Skip to content

Commit 275ca0d

Browse files
committed
refactor: migrate Shape and ArraySlice indexing from int32 to int64
Enables support for large arrays exceeding 2 billion elements, aligning with NumPy's int64-based shape architecture. Core changes: - Shape: dimensions, strides, size, offset, bufferSize all changed to long - IArraySlice interface: all index parameters changed to long - ArraySlice implementations: updated for long indexing - Default.Broadcasting: broadcast shape computation uses long - Reduction operations: iterator indices use long - NDIterator: index tracking uses long - ILKernelGenerator.Clip: updated for long-based shape access Also marks ATan2 as fixed in KERNEL_API_AUDIT.md (now uses IL kernels with proper stride/offset/broadcast handling).
1 parent dc100fd commit 275ca0d

35 files changed

Lines changed: 512 additions & 397 deletions

docs/KERNEL_API_AUDIT.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,15 @@ Every np.* function and DefaultEngine operation MUST:
5959
| BitwiseXor ||| ⚠️ int only || 🔲 |
6060
| LeftShift ||| ⚠️ int only | ⚠️ ||
6161
| RightShift ||| ⚠️ int only | ⚠️ ||
62-
| ATan2 || **BUG** | ⚠️ float only |||
62+
| ATan2 || | ⚠️ float only |||
6363

6464
Legend: ✅ Complete | ⚠️ Partial | 🔲 Not verified | ❌ Missing/Bug
6565

6666
**Audit Notes (2026-03-08):**
6767
- Add/Sub/Mul/Div/Mod/Power/FloorDivide: Use ILKernelGenerator with proper path classification
6868
- BitwiseAnd/Or/Xor: Integer types only (correct behavior)
6969
- LeftShift/RightShift: Use `.copy()` pattern to materialize non-contiguous before processing
70-
- **ATan2 BUG**: Uses flat indexing, ignores strides/offset/broadcast (Task #73)
70+
- ATan2: FIXED - Now uses IL kernels with proper stride/offset/broadcast handling
7171

7272
### Unary Operations (ILKernelGenerator.Unary.cs)
7373

src/NumSharp.Core/Backends/Default/ArrayManipulation/Default.Broadcasting.cs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ public static Shape ResolveReturnShape(Shape leftShape, Shape rightShape)
2020

2121
//PyArrayMultiIterObject *mit
2222
int i, nd, k;
23-
int tmp;
23+
long tmp;
2424

2525
nd = Math.Max(leftShape.NDim, rightShape.NDim);
2626

2727
//this is the shared shape aka the target broadcast
28-
var mit = new int[nd];
28+
var mit = new long[nd];
2929

3030
/* Discover the broadcast shape in each dimension */
3131
for (i = 0; i < nd; i++)
@@ -88,7 +88,8 @@ public static Shape ResolveReturnShape(params Shape[] shapes)
8888
return shapes[0].Clean();
8989

9090
Shape mit;
91-
int i, nd, k, tmp;
91+
int i, nd, k;
92+
long tmp;
9293

9394
int len = shapes.Length;
9495

@@ -144,7 +145,8 @@ public static Shape ResolveReturnShape(params NDArray[] shapes)
144145
return shapes[0].Shape.Clean();
145146

146147
Shape mit;
147-
int i, nd, k, tmp;
148+
int i, nd, k;
149+
long tmp;
148150

149151
int len = shapes.Length;
150152

@@ -212,7 +214,7 @@ public static Shape[] Broadcast(params Shape[] shapes)
212214
nd = Math.Max(nd, shapes[i].NDim);
213215

214216
// Use temporary array for broadcast dimensions (not Shape.Empty)
215-
var mitDims = new int[nd];
217+
var mitDims = new long[nd];
216218

217219
// Discover the broadcast shape in each dimension
218220
for (i = 0; i < nd; i++)
@@ -243,7 +245,7 @@ public static Shape[] Broadcast(params Shape[] shapes)
243245
int ogNd = ogiter.NDim;
244246

245247
// Compute broadcast strides
246-
var broadcastStrides = new int[nd];
248+
var broadcastStrides = new long[nd];
247249
for (j = 0; j < nd; j++)
248250
{
249251
k = j + ogNd - nd;
@@ -309,7 +311,7 @@ public static (Shape LeftShape, Shape RightShape) Broadcast(Shape leftShape, Sha
309311
nd = Math.Max(rightShape.NDim, leftShape.NDim);
310312

311313
// Compute broadcast dimensions into temporary array
312-
var mitDims = new int[nd];
314+
var mitDims = new long[nd];
313315
for (i = 0; i < nd; i++)
314316
{
315317
mitDims[i] = 1;
@@ -342,7 +344,7 @@ public static (Shape LeftShape, Shape RightShape) Broadcast(Shape leftShape, Sha
342344
}
343345

344346
// Compute left broadcast strides
345-
var leftStrides = new int[nd];
347+
var leftStrides = new long[nd];
346348
for (j = 0; j < nd; j++)
347349
{
348350
k = j + leftShape.NDim - nd;
@@ -353,7 +355,7 @@ public static (Shape LeftShape, Shape RightShape) Broadcast(Shape leftShape, Sha
353355
}
354356

355357
// Compute right broadcast strides
356-
var rightStrides = new int[nd];
358+
var rightStrides = new long[nd];
357359
for (j = 0; j < nd; j++)
358360
{
359361
k = j + rightShape.NDim - nd;

src/NumSharp.Core/Backends/Default/Math/Reduction/Default.Reduction.AMax.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public override NDArray ReduceAMax(NDArray arr, int? axis_, bool keepdims = fals
2323
{
2424
var result = max_elementwise_il(arr, typeCode);
2525
var r = NDArray.Scalar(result);
26-
if (keepdims) { var ks = new int[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
26+
if (keepdims) { var ks = new long[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
2727
else if (!r.Shape.IsScalar && r.Shape.size == 1 && r.ndim == 1) r.Storage.Reshape(Shape.Scalar);
2828
return r;
2929
}

src/NumSharp.Core/Backends/Default/Math/Reduction/Default.Reduction.AMin.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public override NDArray ReduceAMin(NDArray arr, int? axis_, bool keepdims = fals
2323
{
2424
var result = min_elementwise_il(arr, typeCode);
2525
var r = NDArray.Scalar(result);
26-
if (keepdims) { var ks = new int[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
26+
if (keepdims) { var ks = new long[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
2727
else if (!r.Shape.IsScalar && r.Shape.size == 1 && r.ndim == 1) r.Storage.Reshape(Shape.Scalar);
2828
return r;
2929
}

src/NumSharp.Core/Backends/Default/Math/Reduction/Default.Reduction.Add.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ private NDArray HandleElementWiseSum(in NDArray arr, bool keepdims, NPTypeCode?
4040
var result = sum_elementwise_il(arr, typeCode);
4141
if (@out != null) { @out.SetAtIndex(result, 0); return @out; }
4242
var r = NDArray.Scalar(result);
43-
if (keepdims) { var ks = new int[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
43+
if (keepdims) { var ks = new long[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
4444
else if (!r.Shape.IsScalar && r.Shape.size == 1 && r.ndim == 1) r.Storage.Reshape(Shape.Scalar);
4545
return r;
4646
}
@@ -75,7 +75,7 @@ private unsafe NDArray ExecuteAxisReduction(in NDArray arr, int axis, bool keepd
7575

7676
if (keepdims)
7777
{
78-
var ks = new int[arr.ndim];
78+
var ks = new long[arr.ndim];
7979
for (int d = 0, sd = 0; d < arr.ndim; d++) ks[d] = (d == axis) ? 1 : result.shape[sd++];
8080
result.Storage.Reshape(new Shape(ks));
8181
}
@@ -112,7 +112,7 @@ private NDArray HandleEmptyArrayMinMaxReduction(in NDArray arr, int? axis_, bool
112112

113113
if (keepdims)
114114
{
115-
var ks = new int[arr.ndim];
115+
var ks = new long[arr.ndim];
116116
for (int d = 0, sd = 0; d < arr.ndim; d++)
117117
ks[d] = (d == axis) ? 1 : resultShape[sd++];
118118
result.Storage.Reshape(new Shape(ks));
@@ -128,7 +128,7 @@ private NDArray HandleEmptyArrayReduction(in NDArray arr, int? axis_, bool keepd
128128
var defaultVal = (typeCode ?? arr.typecode).GetDefaultValue();
129129
if (@out != null) { @out.SetAtIndex(defaultVal, 0); return @out; }
130130
var r = NDArray.Scalar(defaultVal);
131-
if (keepdims) { var ks = new int[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
131+
if (keepdims) { var ks = new long[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
132132
return r;
133133
}
134134
var axis = NormalizeAxis(axis_.Value, arr.ndim);
@@ -137,7 +137,7 @@ private NDArray HandleEmptyArrayReduction(in NDArray arr, int? axis_, bool keepd
137137
var result = np.zeros(new Shape(resultShape), outputType);
138138
if (keepdims)
139139
{
140-
var ks = new int[arr.ndim];
140+
var ks = new long[arr.ndim];
141141
for (int d = 0, sd = 0; d < arr.ndim; d++) ks[d] = (d == axis) ? 1 : resultShape[sd++];
142142
result.Storage.Reshape(new Shape(ks));
143143
}
@@ -149,7 +149,7 @@ private NDArray HandleScalarReduction(in NDArray arr, bool keepdims, NPTypeCode?
149149
{
150150
var r = typeCode.HasValue ? Cast(arr, typeCode.Value, true) : arr.Clone();
151151
if (@out != null) { @out.SetAtIndex(r.GetAtIndex(0), 0); return @out; }
152-
if (keepdims) { var ks = new int[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
152+
if (keepdims) { var ks = new long[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
153153
else if (!r.Shape.IsScalar && r.Shape.size == 1 && r.ndim == 1) r.Storage.Reshape(Shape.Scalar);
154154
return r;
155155
}

src/NumSharp.Core/Backends/Default/Math/Reduction/Default.Reduction.ArgMax.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public override NDArray ReduceArgMax(NDArray arr, int? axis_, bool keepdims = fa
4747

4848
if (keepdims)
4949
{
50-
var keepdimsShape = new int[arr.ndim];
50+
var keepdimsShape = new long[arr.ndim];
5151
for (int d = 0, sd = 0; d < arr.ndim; d++)
5252
{
5353
if (d == emptyAxis)
@@ -66,7 +66,7 @@ public override NDArray ReduceArgMax(NDArray arr, int? axis_, bool keepdims = fa
6666
var r = NDArray.Scalar(0L); // Int64 for NumPy 2.x alignment
6767
if (keepdims)
6868
{
69-
var keepdimsShape = new int[arr.ndim];
69+
var keepdimsShape = new long[arr.ndim];
7070
for (int i = 0; i < arr.ndim; i++)
7171
keepdimsShape[i] = 1;
7272
r.Storage.Reshape(new Shape(keepdimsShape));
@@ -81,7 +81,7 @@ public override NDArray ReduceArgMax(NDArray arr, int? axis_, bool keepdims = fa
8181
if (keepdims)
8282
{
8383
// NumPy: keepdims preserves the number of dimensions, all set to 1
84-
var keepdimsShape = new int[arr.ndim];
84+
var keepdimsShape = new long[arr.ndim];
8585
for (int i = 0; i < arr.ndim; i++)
8686
keepdimsShape[i] = 1;
8787
r.Storage.Reshape(new Shape(keepdimsShape));
@@ -113,7 +113,7 @@ public override NDArray ReduceArgMax(NDArray arr, int? axis_, bool keepdims = fa
113113
if (keepdims)
114114
{
115115
// Insert a 1 at the axis position
116-
var keepdimsShapeDims = new int[arr.ndim];
116+
var keepdimsShapeDims = new long[arr.ndim];
117117
int srcIdx = 0;
118118
for (int i = 0; i < arr.ndim; i++)
119119
{

src/NumSharp.Core/Backends/Default/Math/Reduction/Default.Reduction.ArgMin.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public override NDArray ReduceArgMin(NDArray arr, int? axis_, bool keepdims = fa
4747

4848
if (keepdims)
4949
{
50-
var keepdimsShape = new int[arr.ndim];
50+
var keepdimsShape = new long[arr.ndim];
5151
for (int d = 0, sd = 0; d < arr.ndim; d++)
5252
{
5353
if (d == emptyAxis)
@@ -66,7 +66,7 @@ public override NDArray ReduceArgMin(NDArray arr, int? axis_, bool keepdims = fa
6666
var r = NDArray.Scalar(0L); // Int64 for NumPy 2.x alignment
6767
if (keepdims)
6868
{
69-
var keepdimsShape = new int[arr.ndim];
69+
var keepdimsShape = new long[arr.ndim];
7070
for (int i = 0; i < arr.ndim; i++)
7171
keepdimsShape[i] = 1;
7272
r.Storage.Reshape(new Shape(keepdimsShape));
@@ -81,7 +81,7 @@ public override NDArray ReduceArgMin(NDArray arr, int? axis_, bool keepdims = fa
8181
if (keepdims)
8282
{
8383
// NumPy: keepdims preserves the number of dimensions, all set to 1
84-
var keepdimsShape = new int[arr.ndim];
84+
var keepdimsShape = new long[arr.ndim];
8585
for (int i = 0; i < arr.ndim; i++)
8686
keepdimsShape[i] = 1;
8787
r.Storage.Reshape(new Shape(keepdimsShape));
@@ -112,7 +112,7 @@ public override NDArray ReduceArgMin(NDArray arr, int? axis_, bool keepdims = fa
112112
if (keepdims)
113113
{
114114
// Insert a 1 at the axis position
115-
var keepdimsShapeDims = new int[arr.ndim];
115+
var keepdimsShapeDims = new long[arr.ndim];
116116
int srcIdx = 0;
117117
for (int i = 0; i < arr.ndim; i++)
118118
{

src/NumSharp.Core/Backends/Default/Math/Reduction/Default.Reduction.Mean.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public override NDArray ReduceMean(in NDArray arr, int? axis_, bool keepdims = f
1818
if (axis_ == null)
1919
{
2020
var r = NDArray.Scalar(double.NaN);
21-
if (keepdims) { var ks = new int[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
21+
if (keepdims) { var ks = new long[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
2222
return r;
2323
}
2424
var axis = NormalizeAxis(axis_.Value, arr.ndim);
@@ -33,7 +33,7 @@ public override NDArray ReduceMean(in NDArray arr, int? axis_, bool keepdims = f
3333
else result = np.empty(new Shape(resultShape), outputType);
3434
if (keepdims)
3535
{
36-
var ks = new int[arr.ndim];
36+
var ks = new long[arr.ndim];
3737
for (int d = 0, sd = 0; d < arr.ndim; d++) ks[d] = (d == axis) ? 1 : resultShape[sd++];
3838
result.Storage.Reshape(new Shape(ks));
3939
}
@@ -45,15 +45,15 @@ public override NDArray ReduceMean(in NDArray arr, int? axis_, bool keepdims = f
4545
var val = arr.GetAtIndex(0);
4646
var outputType = typeCode ?? NPTypeCode.Double;
4747
var r = NDArray.Scalar(Converts.ChangeType(val, outputType));
48-
if (keepdims) { var ks = new int[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
48+
if (keepdims) { var ks = new long[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
4949
return r;
5050
}
5151

5252
if (axis_ == null)
5353
{
5454
var result = mean_elementwise_il(arr, typeCode);
5555
var r = NDArray.Scalar(result);
56-
if (keepdims) { var ks = new int[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
56+
if (keepdims) { var ks = new long[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
5757
else if (!r.Shape.IsScalar && r.Shape.size == 1 && r.ndim == 1) r.Storage.Reshape(Shape.Scalar);
5858
return r;
5959
}

src/NumSharp.Core/Backends/Default/Math/Reduction/Default.Reduction.Product.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ public override NDArray ReduceProduct(NDArray arr, int? axis_, bool keepdims = f
1818
if (axis_ == null)
1919
{
2020
var r = NDArray.Scalar((typeCode ?? arr.typecode).GetOneValue());
21-
if (keepdims) { var ks = new int[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
21+
if (keepdims) { var ks = new long[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
2222
return r;
2323
}
2424
var axis = NormalizeAxis(axis_.Value, arr.ndim);
2525
var resultShape = Shape.GetAxis(shape, axis);
2626
var result = np.ones(new Shape(resultShape), typeCode ?? arr.GetTypeCode.GetAccumulatingType());
2727
if (keepdims)
2828
{
29-
var ks = new int[arr.ndim];
29+
var ks = new long[arr.ndim];
3030
for (int d = 0, sd = 0; d < arr.ndim; d++) ks[d] = (d == axis) ? 1 : resultShape[sd++];
3131
result.Storage.Reshape(new Shape(ks));
3232
}
@@ -40,7 +40,7 @@ public override NDArray ReduceProduct(NDArray arr, int? axis_, bool keepdims = f
4040
{
4141
var result = prod_elementwise_il(arr, typeCode);
4242
var r = NDArray.Scalar(result);
43-
if (keepdims) { var ks = new int[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
43+
if (keepdims) { var ks = new long[arr.ndim]; for (int i = 0; i < arr.ndim; i++) ks[i] = 1; r.Storage.Reshape(new Shape(ks)); }
4444
else if (!r.Shape.IsScalar && r.Shape.size == 1 && r.ndim == 1) r.Storage.Reshape(Shape.Scalar);
4545
return r;
4646
}

src/NumSharp.Core/Backends/Default/Math/Reduction/Default.Reduction.Std.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public override NDArray ReduceStd(NDArray arr, int? axis_, bool keepdims = false
2424
var r = NDArray.Scalar(double.NaN);
2525
if (keepdims)
2626
{
27-
var keepdimsShape = new int[arr.ndim];
27+
var keepdimsShape = new long[arr.ndim];
2828
for (int i = 0; i < arr.ndim; i++)
2929
keepdimsShape[i] = 1;
3030
r.Storage.Reshape(new Shape(keepdimsShape));
@@ -58,7 +58,7 @@ public override NDArray ReduceStd(NDArray arr, int? axis_, bool keepdims = false
5858

5959
if (keepdims)
6060
{
61-
var keepdimsShape = new int[arr.ndim];
61+
var keepdimsShape = new long[arr.ndim];
6262
for (int d = 0, sd = 0; d < arr.ndim; d++)
6363
{
6464
if (d == emptyAxis)
@@ -82,7 +82,7 @@ public override NDArray ReduceStd(NDArray arr, int? axis_, bool keepdims = false
8282
if (keepdims)
8383
{
8484
// NumPy: keepdims preserves the number of dimensions, all set to 1
85-
var keepdimsShape = new int[arr.ndim];
85+
var keepdimsShape = new long[arr.ndim];
8686
for (int i = 0; i < arr.ndim; i++)
8787
keepdimsShape[i] = 1;
8888
r.Storage.Reshape(new Shape(keepdimsShape));
@@ -98,7 +98,7 @@ public override NDArray ReduceStd(NDArray arr, int? axis_, bool keepdims = false
9898
if (keepdims)
9999
{
100100
// NumPy: keepdims preserves the number of dimensions, all set to 1
101-
var keepdimsShape = new int[arr.ndim];
101+
var keepdimsShape = new long[arr.ndim];
102102
for (int i = 0; i < arr.ndim; i++)
103103
keepdimsShape[i] = 1;
104104
r.Storage.Reshape(new Shape(keepdimsShape));
@@ -120,7 +120,7 @@ public override NDArray ReduceStd(NDArray arr, int? axis_, bool keepdims = false
120120
//Return zeros with the appropriate shape (NumPy behavior)
121121
if (keepdims)
122122
{
123-
var keepdimsShapeDims = new int[arr.ndim];
123+
var keepdimsShapeDims = new long[arr.ndim];
124124
for (int i = 0; i < arr.ndim; i++)
125125
keepdimsShapeDims[i] = (i == axis) ? 1 : shape[i];
126126
return np.zeros(keepdimsShapeDims, typeCode ?? arr.GetTypeCode.GetComputingType());
@@ -348,7 +348,7 @@ private unsafe NDArray ExecuteAxisStdReductionIL(in NDArray arr, int axis, bool
348348

349349
if (keepdims)
350350
{
351-
var ks = new int[arr.ndim];
351+
var ks = new long[arr.ndim];
352352
for (int d = 0, sd = 0; d < arr.ndim; d++)
353353
ks[d] = (d == axis) ? 1 : (sd < outputDims.Length ? outputDims[sd++] : 1);
354354
result.Storage.Reshape(new Shape(ks));

0 commit comments

Comments
 (0)