Commit 3811960
committed
fix(asanyarray,where): pure-float object[] promotion + hot-path short-circuits
Second-round code review caught one real bug and several minor efficiency issues.
1. Fix: FindCommonNumericType promoted pure-float object[] to double
np.asanyarray(new object[]{1.5f, 2.5f}) returned Double instead of Single.
Root cause: the early-exit `if (hasDouble || hasFloat) return typeof(double)`
fired before the `uniqueCount == 1` check that preserves the original dtype.
Removing the hasFloat arm lets the general path handle it:
- Pure float32 -> uniqueCount == 1 -> returns firstType (Single) -- matches NumPy
- int + float32 -> _FindCommonType_Scalar -> returns Double -- matches NumPy NEP50
- Pure float64 -> unchanged (still Double)
- decimal-wins-everything early exit preserved.
Two regression tests added:
- ObjectArray_AllFloat_PreservesSingle
- ObjectArray_MixedIntAndFloat32_PromotesToDouble
2. Perf: skip type promotion in np.where when x.dtype == y.dtype
Previously _FindCommonType(x, y) always ran, even when both operands shared a
dtype. Short-circuit to x.GetTypeCode in that case, saving one dict lookup +
two astype traversals per call. The NEP50 lookup still runs when dtypes
differ, preserving scalar+array promotion semantics.
3. Perf: skip broadcast_arrays when all three shapes already match
broadcast_arrays allocates three fresh NDArrays plus helper Shape[]. For the
common case of np.where(mask, arr, other_arr) where all three arrays share a
shape, this is wasted. Skip it when condition.Shape == x.Shape == y.Shape
(Shape == compares by dimensions).
4. Perf: cache Vector256/Vector128 generic MethodInfo
EmitWhereV256BodyWithOffset and EmitWhereV128BodyWithOffset did
Array.Find(typeof(Vector*).GetMethods(), ...) three times per call, each
scanning ~100 methods. Per kernel generation (4-way unrolled + 1 remainder
call = 5 calls), that was 15 reflection scans per T, or ~180 on first use
across all 12 dtypes. Cached as six static readonly fields; only
MakeGenericMethod(typeof(T)) runs per call.
5. Polish: doc + error message
- where(NDArray) xmldoc was copy-pasted from the 3-arg overload ("Return
elements chosen from x or y"); rewritten to describe nonzero semantics.
- object[] NotSupportedException now names the actual problem ("element type
is not a supported NumSharp dtype") instead of just reporting the length.
Verified: 180 np.where + np.asanyarray tests pass on net8.0 + net10.0.1 parent f0473d2 commit 3811960
4 files changed
Lines changed: 72 additions & 41 deletions
File tree
- src/NumSharp.Core
- APIs
- Backends/Kernels
- Creation
- test/NumSharp.UnitTest/Creation
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
10 | | - | |
| 10 | + | |
| 11 | + | |
11 | 12 | | |
12 | | - | |
13 | | - | |
| 13 | + | |
| 14 | + | |
14 | 15 | | |
15 | 16 | | |
16 | 17 | | |
| |||
62 | 63 | | |
63 | 64 | | |
64 | 65 | | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
70 | 82 | | |
71 | | - | |
72 | | - | |
73 | | - | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
74 | 88 | | |
75 | | - | |
76 | 89 | | |
77 | 90 | | |
78 | 91 | | |
| |||
Lines changed: 22 additions & 20 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
251 | 251 | | |
252 | 252 | | |
253 | 253 | | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
254 | 270 | | |
255 | 271 | | |
256 | | - | |
257 | | - | |
258 | | - | |
259 | | - | |
260 | | - | |
261 | | - | |
262 | | - | |
263 | | - | |
264 | | - | |
265 | | - | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
266 | 275 | | |
267 | 276 | | |
268 | 277 | | |
| |||
327 | 336 | | |
328 | 337 | | |
329 | 338 | | |
330 | | - | |
331 | | - | |
332 | | - | |
333 | | - | |
334 | | - | |
335 | | - | |
336 | | - | |
337 | | - | |
338 | | - | |
339 | | - | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
340 | 342 | | |
341 | 343 | | |
342 | 344 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
35 | | - | |
| 35 | + | |
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| |||
206 | 206 | | |
207 | 207 | | |
208 | 208 | | |
209 | | - | |
210 | | - | |
211 | 209 | | |
212 | 210 | | |
213 | 211 | | |
| |||
221 | 219 | | |
222 | 220 | | |
223 | 221 | | |
| 222 | + | |
224 | 223 | | |
225 | 224 | | |
226 | 225 | | |
227 | | - | |
228 | | - | |
229 | | - | |
230 | 226 | | |
231 | 227 | | |
232 | 228 | | |
| |||
236 | 232 | | |
237 | 233 | | |
238 | 234 | | |
239 | | - | |
240 | | - | |
241 | | - | |
242 | 235 | | |
243 | 236 | | |
244 | 237 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
791 | 791 | | |
792 | 792 | | |
793 | 793 | | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
| 816 | + | |
794 | 817 | | |
795 | 818 | | |
796 | 819 | | |
0 commit comments