Repository: navjotk/pyzfp (language: python)

Issue:
Feature Request: Support for Fortran-style contiguous arrays
Hi, we are processing 3-dimensional numpy arrays that use Fortran style memory layout and ideally they should not have to be converted / copied to become C contiguous.

I was wondering if this is something you would be willing to support? Will create a PR in a bit.


Discussion / hints:

Fix patch:
diff --git a/pyzfp.pyx b/pyzfp.pyx
index f521073..5118630 100644
--- a/pyzfp.pyx
+++ b/pyzfp.pyx
@@ -136,14 +136,14 @@ cdef extern from "zfp.h":
 
 cdef void* raw_pointer_double(arr) except NULL:
     assert(arr.dtype==np.float64)
-    assert(arr.flags.c_contiguous) # if this isn't true, ravel will make a copy
-    cdef double[::1] mview = arr.ravel()
+    assert(arr.flags.forc) # if this isn't true, ravel will make a copy
+    cdef double[::1] mview = arr.ravel(order='A')
     return <void*>&mview[0]
 
 cdef void* raw_pointer_float(arr) except NULL:
-    assert(arr.flags.c_contiguous) # if this isn't true, ravel will make a copy
+    assert(arr.flags.forc) # if this isn't true, ravel will make a copy
     assert(arr.dtype == np.float32)
-    cdef float[::1] mview = arr.ravel()
+    cdef float[::1] mview = arr.ravel(order='A')
     return <void*>&mview[0]
 
 cdef void* raw_pointer(arr):
@@ -204,12 +204,13 @@ def compress(indata, tolerance=None, precision=None, rate=None, parallel=True):
 
 
 def decompress(const unsigned char[::1] compressed, shape, dtype, tolerance=None, precision=None,
-               rate=None, parallel=True):
+               rate=None, parallel=True, order='C'):
     assert(tolerance or precision or rate)
     assert(not(tolerance is not None and precision is not None))
     assert(not(tolerance is not None and rate is not None))
     assert(not(rate is not None and precision is not None))
-    outdata = np.zeros(shape, dtype=dtype)
+    assert(order.upper() in ('C', 'F'))
+    outdata = np.zeros(shape, dtype=dtype, order=order)
     data_type = zfp_types[dtype]
     shape = list(reversed(shape))
     field = init_field(outdata)


Test patch:
diff --git a/test.py b/test.py
index dfe36ca..d7333d0 100644
--- a/test.py
+++ b/test.py
@@ -1,24 +1,31 @@
+import pytest
 import numpy as np
 from pyzfp import compress, decompress
 
 
-def test_compress_decompress():
-    a = np.linspace(0, 100, num=1000000).reshape((100, 100, 100))
+@pytest.mark.parametrize("order", ["C", "F"])
+def test_compress_decompress(order):
+    a = np.linspace(0, 100, num=1000000).reshape((100, 100, 100), order=order)
     tolerance = 0.0000001
     compressed = compress(a, tolerance=tolerance)
-    recovered = decompress(compressed, a.shape, a.dtype, tolerance=tolerance)
+    recovered = decompress(compressed, a.shape, a.dtype,
+                           tolerance=tolerance, order=order)
+    a.flags == recovered.flags
     assert(a.shape == recovered.shape)
     assert(np.allclose(a, recovered))
 
 
-def test_dim_order():
-    a = np.arange(32, dtype=np.float32).reshape((8, 4))
+@pytest.mark.parametrize("order", ["C", "F"])
+def test_dim_order(order):
+    a = np.arange(32, dtype=np.float32).reshape((8, 4), order=order)
     compressed = compress(a, rate=8)
     recovered = decompress(compressed[0:16], (4, 4), np.dtype('float32'),
-                           rate=8)
-    b = np.arange(16, dtype=np.float32).reshape((4, 4))
+                           rate=8, order=order)
+    b = np.arange(16, dtype=np.float32).reshape((4, 4), order=order)
     assert(np.allclose(recovered, b))
 
 
-test_compress_decompress()
-test_dim_order()
+test_compress_decompress('C')
+test_compress_decompress('F')
+test_dim_order('C')
+test_dim_order('F')