Summary
When constructing a SimpleArray from a NumPy array, the current F-contiguous stride check is overly strict and incorrectly rejects arrays that NumPy itself considers both C and F contiguous — especially those with singleton dimensions such as (1, n) or (n, 1).
How to reproduce the error
Code:
import numpy as np
import modmesh as mm
# Test case 1: 1x2 array - fails with Fortran contiguous check
try:
array1 = np.array([[1.0, 0.1]])
print(f"Test 1: shape={array1.shape}, strides={array1.strides}")
print(f" C_CONTIGUOUS={array1.flags.c_contiguous}, F_CONTIGUOUS={array1.flags.f_contiguous}")
error1 = mm.SimpleArrayFloat64(array=array1)
print(" ✓ Success")
except Exception as e:
print(f" ✗ Failed: {e}")
# Test case 2: 2x1 array - fails with Fortran contiguous check
try:
array2 = np.array([[1.0], [0.0]])
print(f"\nTest 2: shape={array2.shape}, strides={array2.strides}")
print(f" C_CONTIGUOUS={array2.flags.c_contiguous}, F_CONTIGUOUS={array2.flags.f_contiguous}")
error2 = mm.SimpleArrayFloat64(array=array2)
print(" ✓ Success")
except Exception as e:
print(f" ✗ Failed: {e}")
# Working solution: 2 * 2 array
try:
array_2d = np.array([[1.0, 0.1], [0.0, 1.0]])
print(f"\nWorking solution: 1D array shape={array_2d.shape}, strides={array_2d.strides}")
success = mm.SimpleArrayFloat64(array=array_2d)
print(" ✓ 2D array works")
except Exception as e:
print(f" ✗ 2D array failed: {e}")
Console:
Test 1: shape=(1, 2), strides=(16, 8)
C_CONTIGUOUS=True, F_CONTIGUOUS=True
✗ Failed: SimpleArray: Fortran contiguous stride must start with 1
Test 2: shape=(2, 1), strides=(8, 8)
C_CONTIGUOUS=True, F_CONTIGUOUS=True
✗ Failed: SimpleArray: Fortran contiguous stride must match shape
Working solution: 1D array shape=(2, 2), strides=(16, 8)
✓ 2D array works
Root Cause
NumPy defines contiguity more flexibly:
The problematic code is located in SimpleArray.hpp, within the check_f_contiguous() function:
void check_f_contiguous(small_vector<size_t> const & shape,
small_vector<size_t> const & stride) const
{
if (stride[0] != 1)
{
throw std::runtime_error("SimpleArray: Fortran contiguous stride must start with 1");
}
for (size_t it = 0; it < shape.size() - 1; ++it)
{
if (stride[it + 1] != shape[it] * stride[it])
{
throw std::runtime_error("SimpleArray: Fortran contiguous stride must match shape");
}
}
}
This logic assumes that:
- The first dimension’s stride must always be 1 (in element units).
- Each following stride must strictly equal the product of the previous stride and shape.
- That assumption fails for singleton dimensions, where NumPy explicitly allows strides to take any value while the array remains contiguous.
Summary
When constructing a SimpleArray from a NumPy array, the current F-contiguous stride check is overly strict and incorrectly rejects arrays that NumPy itself considers both C and F contiguous — especially those with singleton dimensions such as (1, n) or (n, 1).
How to reproduce the error
Code:
Console:
Root Cause
NumPy defines contiguity more flexibly:
The problematic code is located in SimpleArray.hpp, within the
check_f_contiguous()function:This logic assumes that: