tinycwrap 0.0.4__tar.gz → 0.0.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tinycwrap-0.0.4 → tinycwrap-0.0.6}/PKG-INFO +1 -1
- {tinycwrap-0.0.4 → tinycwrap-0.0.6}/pyproject.toml +1 -1
- tinycwrap-0.0.4/tests/test_examples.py → tinycwrap-0.0.6/tests/test_kernels.py +3 -3
- {tinycwrap-0.0.4 → tinycwrap-0.0.6}/tests/test_path.py +4 -0
- {tinycwrap-0.0.4 → tinycwrap-0.0.6}/tinycwrap/__init__.py +1 -1
- {tinycwrap-0.0.4 → tinycwrap-0.0.6}/tinycwrap/cmodule.py +81 -42
- {tinycwrap-0.0.4 → tinycwrap-0.0.6}/tinycwrap.egg-info/PKG-INFO +1 -1
- {tinycwrap-0.0.4 → tinycwrap-0.0.6}/tinycwrap.egg-info/SOURCES.txt +1 -1
- {tinycwrap-0.0.4 → tinycwrap-0.0.6}/README.md +0 -0
- {tinycwrap-0.0.4 → tinycwrap-0.0.6}/setup.cfg +0 -0
- {tinycwrap-0.0.4 → tinycwrap-0.0.6}/tests/test_geom.py +0 -0
- {tinycwrap-0.0.4 → tinycwrap-0.0.6}/tinycwrap/parsing.py +0 -0
- {tinycwrap-0.0.4 → tinycwrap-0.0.6}/tinycwrap.egg-info/dependency_links.txt +0 -0
- {tinycwrap-0.0.4 → tinycwrap-0.0.6}/tinycwrap.egg-info/requires.txt +0 -0
- {tinycwrap-0.0.4 → tinycwrap-0.0.6}/tinycwrap.egg-info/top_level.txt +0 -0
|
@@ -14,9 +14,9 @@ def cm():
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def test_dot(cm):
|
|
17
|
-
x = np.
|
|
18
|
-
y = np.
|
|
19
|
-
assert cm.dot(x, y, len_x=len(x)) == np.
|
|
17
|
+
x = np.array([1.0, 2.0, 3.0], dtype=np.float64)
|
|
18
|
+
y = np.array([4.0, 5.0, 6.0], dtype=np.float64)
|
|
19
|
+
assert cm.dot(x, y, len_x=len(x)) == np.dot(x, y)
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def test_scale_auto_output(cm):
|
|
@@ -52,3 +52,7 @@ def test_repr_pointer_array(cp):
|
|
|
52
52
|
repr_str = repr(path)
|
|
53
53
|
assert "segments=<segments* 0x" in repr_str
|
|
54
54
|
assert "len_segments=2" in repr_str
|
|
55
|
+
|
|
56
|
+
def test_post_contract(cp):
|
|
57
|
+
segments, len_segments = cp.geom2d_segments_from_rectellipse(1,2,3,4)
|
|
58
|
+
assert segments.shape == (4,)
|
|
@@ -381,24 +381,22 @@ class CModule:
|
|
|
381
381
|
fspec.doc = doc
|
|
382
382
|
contracts = []
|
|
383
383
|
for line in doc.splitlines():
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
mlen = re.match(r"
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
expr = mlen.group(2).strip()
|
|
401
|
-
contracts.append((target, expr, is_post))
|
|
384
|
+
m_contract = re.search(r"(post-)?contract:\s*(.*)", line, flags=re.IGNORECASE)
|
|
385
|
+
if not m_contract:
|
|
386
|
+
continue
|
|
387
|
+
is_post = m_contract.group(1) is not None
|
|
388
|
+
after = m_contract.group(2)
|
|
389
|
+
for part in after.split(";"):
|
|
390
|
+
part = part.strip()
|
|
391
|
+
if not part:
|
|
392
|
+
continue
|
|
393
|
+
mlen = re.match(r"len\((\w+)\)\s*=\s*(.+)", part)
|
|
394
|
+
if not mlen:
|
|
395
|
+
mlen = re.match(r"(\w+)\s*=\s*(.+)", part)
|
|
396
|
+
if mlen:
|
|
397
|
+
target = mlen.group(1)
|
|
398
|
+
expr = mlen.group(2).strip()
|
|
399
|
+
contracts.append((target, expr, is_post))
|
|
402
400
|
fspec.contracts = contracts or None
|
|
403
401
|
|
|
404
402
|
def _mark_length_params_from_contracts(self):
|
|
@@ -430,13 +428,14 @@ class CModule:
|
|
|
430
428
|
"size_t",
|
|
431
429
|
"ssize_t",
|
|
432
430
|
)
|
|
433
|
-
and (not arg.is_pointer)
|
|
434
431
|
and arg.name in referenced
|
|
435
432
|
):
|
|
436
433
|
arg.is_length_param = True
|
|
437
434
|
for arg in fspec.args:
|
|
438
435
|
if arg.is_length_param:
|
|
439
436
|
arg.is_scalar = False
|
|
437
|
+
arg.is_array_in = False
|
|
438
|
+
arg.is_array_out = False
|
|
440
439
|
elif (
|
|
441
440
|
(not arg.is_pointer)
|
|
442
441
|
and arg.array_len is None
|
|
@@ -496,7 +495,15 @@ class CModule:
|
|
|
496
495
|
target_dtype = _struct_dtypes.get(f.base_type)
|
|
497
496
|
provided = kwargs.get(f.name)
|
|
498
497
|
if provided is not None and target_dtype is not None:
|
|
499
|
-
|
|
498
|
+
try:
|
|
499
|
+
arr = np.ascontiguousarray(provided, dtype=target_dtype)
|
|
500
|
+
except ValueError:
|
|
501
|
+
if hasattr(provided, "_data"):
|
|
502
|
+
arr = np.ascontiguousarray(provided._data, dtype=target_dtype)
|
|
503
|
+
elif isinstance(provided, (list, tuple)) and provided and hasattr(provided[0], "_data"):
|
|
504
|
+
arr = np.ascontiguousarray([p._data for p in provided], dtype=target_dtype)
|
|
505
|
+
else:
|
|
506
|
+
raise
|
|
500
507
|
children[f.name] = arr
|
|
501
508
|
data[f.name] = arr.ctypes.data
|
|
502
509
|
if len_field in dtype.names and len_field not in kwargs:
|
|
@@ -747,6 +754,7 @@ class CModule:
|
|
|
747
754
|
else:
|
|
748
755
|
contract_map[target] = expr
|
|
749
756
|
|
|
757
|
+
length_pointer_names = {a.name for a in fspec.args if a.is_length_param and a.is_pointer}
|
|
750
758
|
pointer_scalar_names = {
|
|
751
759
|
a.name
|
|
752
760
|
for a in fspec.args
|
|
@@ -767,7 +775,7 @@ class CModule:
|
|
|
767
775
|
"ssize_t",
|
|
768
776
|
)
|
|
769
777
|
)
|
|
770
|
-
}
|
|
778
|
+
} | length_pointer_names
|
|
771
779
|
|
|
772
780
|
func_names = set(self._func_specs.keys())
|
|
773
781
|
|
|
@@ -776,6 +784,7 @@ class CModule:
|
|
|
776
784
|
expr = re.sub(r"len\((\w+)\)", r"len(arr_\1)", expr)
|
|
777
785
|
for name in pointer_scalar_names:
|
|
778
786
|
expr = re.sub(rf"\b{name}\b", f"int(arr_{name}.ravel()[0])", expr)
|
|
787
|
+
expr = re.sub(rf"\b{name}\b", f"scalar_{name}", expr)
|
|
779
788
|
if func_names:
|
|
780
789
|
pattern = r"\b(" + "|".join(re.escape(n) for n in func_names) + r")\s*\(([^()]*)\)"
|
|
781
790
|
|
|
@@ -803,6 +812,17 @@ class CModule:
|
|
|
803
812
|
scalar_lines: list[str] = []
|
|
804
813
|
|
|
805
814
|
for a in fspec.args:
|
|
815
|
+
if a.is_length_param and a.is_pointer:
|
|
816
|
+
base_dtype = "np.dtype('int32')"
|
|
817
|
+
out_lines = [
|
|
818
|
+
f" arr_{a.name} = np.zeros((), dtype={base_dtype})",
|
|
819
|
+
f" ptr_{a.name} = _self._ffi.cast('{a.base_type} *', _self._ffi.from_buffer(arr_{a.name}))",
|
|
820
|
+
]
|
|
821
|
+
call_args.append(f"ptr_{a.name}")
|
|
822
|
+
output_vars.append(f"arr_{a.name}")
|
|
823
|
+
output_names.append(a.name)
|
|
824
|
+
pointer_scalar_outputs.append((a.name, f"arr_{a.name}"))
|
|
825
|
+
continue
|
|
806
826
|
if a.is_array_in:
|
|
807
827
|
const_prefix = "const " if a.is_const else ""
|
|
808
828
|
if a.base_type in struct_names:
|
|
@@ -834,21 +854,25 @@ class CModule:
|
|
|
834
854
|
scalar_lines.append(f" {a.name} = {a.name}")
|
|
835
855
|
call_args.append(a.name)
|
|
836
856
|
elif a.is_length_param:
|
|
837
|
-
if a.
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
f" if {a.name} is None:",
|
|
841
|
-
f" {a.name} = int({expr_py})",
|
|
842
|
-
f" else:",
|
|
843
|
-
f" {a.name} = int({a.name})",
|
|
844
|
-
]
|
|
857
|
+
if a.is_pointer:
|
|
858
|
+
# handled in array/pointer branch
|
|
859
|
+
call_args.append(None)
|
|
845
860
|
else:
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
861
|
+
if a.name in contract_map:
|
|
862
|
+
expr_py = _expr_py(contract_map[a.name])
|
|
863
|
+
length_lines += [
|
|
864
|
+
f" if {a.name} is None:",
|
|
865
|
+
f" {a.name} = int({expr_py})",
|
|
866
|
+
f" else:",
|
|
867
|
+
f" {a.name} = int({a.name})",
|
|
868
|
+
]
|
|
869
|
+
else:
|
|
870
|
+
length_lines += [
|
|
871
|
+
f" if {a.name} is None:",
|
|
872
|
+
f" raise ValueError('{fspec.name}: length parameter {a.name} requires an explicit Contract')",
|
|
873
|
+
f" {a.name} = int({a.name})",
|
|
874
|
+
]
|
|
875
|
+
call_args.append(a.name)
|
|
852
876
|
else:
|
|
853
877
|
# defer outputs / pointer handling
|
|
854
878
|
call_args.append(None) # placeholder
|
|
@@ -954,11 +978,6 @@ class CModule:
|
|
|
954
978
|
else:
|
|
955
979
|
lines.append(f" res = {call_expr}")
|
|
956
980
|
|
|
957
|
-
for out_name, out_var in zip(output_names, output_vars):
|
|
958
|
-
if out_name in post_contract_map:
|
|
959
|
-
expr_py = _expr_py(post_contract_map[out_name])
|
|
960
|
-
lines.append(f" {out_var} = {out_var}[:int({expr_py})]")
|
|
961
|
-
|
|
962
981
|
for name, arr_var in pointer_scalar_outputs:
|
|
963
982
|
lines.append(f" scalar_{name} = int(np.asarray({arr_var}).ravel()[0])")
|
|
964
983
|
|
|
@@ -966,11 +985,19 @@ class CModule:
|
|
|
966
985
|
for name, arr_var, cls_expr in struct_scalar_outputs:
|
|
967
986
|
lines.append(f" obj_{name} = {cls_expr}()")
|
|
968
987
|
lines.append(f" object.__setattr__(obj_{name}, '_data', np.array({arr_var}, copy=True))")
|
|
988
|
+
pointer_scalar_map = {arr: (name, f"scalar_{name}") for name, arr in pointer_scalar_outputs}
|
|
989
|
+
pairs = list(zip(output_names, output_vars))
|
|
990
|
+
# place array outputs before scalar pointer lengths
|
|
991
|
+
pairs_sorted = sorted(pairs, key=lambda p: 1 if p[1] in pointer_scalar_map else 0)
|
|
992
|
+
output_names_reordered: list[str] = []
|
|
969
993
|
output_vars_final: list[str] = []
|
|
970
|
-
for ov in
|
|
994
|
+
for name, ov in pairs_sorted:
|
|
995
|
+
output_names_reordered.append(name)
|
|
971
996
|
if ov in struct_scalar_map:
|
|
972
997
|
n, _ = struct_scalar_map[ov]
|
|
973
998
|
output_vars_final.append(f"obj_{n}")
|
|
999
|
+
elif ov in pointer_scalar_map:
|
|
1000
|
+
output_vars_final.append(pointer_scalar_map[ov][1])
|
|
974
1001
|
else:
|
|
975
1002
|
output_vars_final.append(ov)
|
|
976
1003
|
|
|
@@ -985,8 +1012,20 @@ class CModule:
|
|
|
985
1012
|
ret_expr = f"{output_vars_final[0]}, res"
|
|
986
1013
|
else:
|
|
987
1014
|
ret_expr = "(" + ", ".join(output_vars_final) + "), res"
|
|
1015
|
+
# apply post-contract slicing using scalar lengths if available
|
|
1016
|
+
for out_name, out_var in zip(output_names_reordered, output_vars_final):
|
|
1017
|
+
if out_name in post_contract_map:
|
|
1018
|
+
expr_py = _expr_py(post_contract_map[out_name])
|
|
1019
|
+
scalar_names = {n for n, _ in pointer_scalar_outputs}
|
|
1020
|
+
if out_name in scalar_names:
|
|
1021
|
+
expr_py = expr_py.replace(out_name, f"scalar_{out_name}")
|
|
1022
|
+
ret_expr = ret_expr.replace(out_var, f"({out_var})[:int({expr_py})]")
|
|
988
1023
|
if pointer_scalar_outputs:
|
|
989
|
-
scalars = [
|
|
1024
|
+
scalars = [
|
|
1025
|
+
f"scalar_{n}"
|
|
1026
|
+
for n, _ in pointer_scalar_outputs
|
|
1027
|
+
if f"scalar_{n}" not in output_vars_final
|
|
1028
|
+
]
|
|
990
1029
|
if isinstance(ret_expr, str) and ret_expr.startswith("("):
|
|
991
1030
|
ret_expr = (
|
|
992
1031
|
ret_expr[:-1]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|