Implement NA.__array_ufunc__
This gives us consistent comparisons with NumPy scalars.

I have a few implementation questions:

1. I wanted to reuse `maybe_dispatch_ufunc_to_dunder_op`. That was in `core/ops/dispatch.py`, but NA is defend in `_libs/missing.pyx`. For now I just moved it to `_libs/missing.pyx`, is there a better home for it? I don't think `_libs/ops.pyx` is an option, as it imports missing.
2. How should we handle comparisons with ndarrays? I see a few options:

  a. Return an `ndarray[object]`, where each element is NA
  b. Really take over and return our extension arrays. So `np.array([1, 2]) == pd.NA` would return an `IntegerArray([NA, NA])`. Boolean results would return a BooleanArray. And float results would return a ... PandasArray? (so maybe this isn't a good idea. But worth considering)
3. What scalars should we handle (in `__array_ufunc__` and in the regular methods)? Any of date time, Timestamp, time delta, Period, Interval? 


One item 2, I seem to have messed something up, as we return just a scalar `NA` right now. Will want to sort that out.