ENH: recognize Decimal("NaN") in pd.isna
State: closed

- [x] closes #23530
- [x] tests added / passed
- [x] Ensure all linting tests pass, see [here](https://pandas.pydata.org/pandas-docs/dev/development/contributing.html#code-standards) for how to run them
- [x] whatsnew entry

Discussion in #23530 seems ambivalent on whether this is desirable, and I don't have a strong opinion on it in general.  BUT tm.assert_foo_equal is incorrect with Decimal("NaN") ATM and id like to see that fixed.

xref #32206

Labels:
name: Missing-data
description: np.nan, pd.NaT, pd.NA, dropna, isnull, interpolate

Comments:
```
In [4]: %timeit pd.isna(2)
323 ns ± 15.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)  # <-- master
319 ns ± 5.37 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)  # <-- PR

In [5]: %timeit pd.isna(np.nan)
329 ns ± 3.86 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)  # <-- master
330 ns ± 9.32 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)  # <-- PR

In [6]: arr = np.arange(1000).astype(object)
In [7]: arr[500] = Decimal("NAN")

In [8]: %timeit pd.isna(arr)
42.1 µs ± 254 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)  # master
45.3 µs ± 213 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)  # <-- PR
```
ok looks fine, can you add a whatsnew note (also prob need to update the docs where we mention missing values e.g. isna & user docs). can do as a followon is ok.

cc @jorisvandenbossche 
What's the rationale for supporting decimals? (we don't have special support for it elsewhere, I think)
 
So that something like `pd.Series([decimal.Decimal("NaN"), decimal.Decimal("2.2")]).isna()` works correctly? (now it returns [False, False])

We don't really have such custom support for anything else in `object` dtype, so while I certainly understand the use case, I am not sure why would we should do it for decimal and not for something else? (although maybe decimal is the only relevant case) 
Also, assume we would have proper decimal support in the future (eg arrow-backed), then the question is also if we want to keep supporting it like this in object dtype (arrow eg also doesn't support "NaN" for decimal).
> we don't have special support for it elsewhere, I think

we recognize it in lib.is_scalar and infer_dtype

> So that something like pd.Series([decimal.Decimal("NaN"), decimal.Decimal("2.2")]).isna() works correctly? (now it returns [False, False])

correct

> we recognize it in infer_dtype

Wondering: is the fact that `infer_dtype` recognizes it actually used somewhere? (I only see it used in the tests)

The fact that `is_scalar` recognizes it is a good point, but in principle any Python class that follows the number protocol (eg implements `__int__` or `__float__`) will be recognized as scalar.

I am personally still hesitant about the "is this the future behaviour we want?"
@jorisvandenbossche are you -1 here? I think this is ok behavior. its rn a special case, so this seems like a nice cleanup.
I don't have a strong opinion about it, but we don't support decimals as a first class citizen (only in object dtype as any other Python class), so I don't really see the value in adding a special case for it in our C code. 

(but so, if others want to see this behaviour, I won't block it)
thanks @jorisvandenbossche yeah to me this improves the UX a bit and doesn't hurt perf so ok with it.
whatsnew added + green
the only reason i can think of to treat Decimal special is bc it is from the stdlib
merging, this makes the logic a bit simpler and agree its a built in type, so why not