From ab4a6c7d897bef66eb8c4b65acabaf2e60ebf9bb Mon Sep 17 00:00:00 2001 From: Iason Krommydas Date: Sat, 10 Oct 2026 02:28:21 +0200 Subject: [PATCH 01/19] feat: add long double kernels for reducers, sorting and unique --- .../awkward_NumpyArray_subrange_equal.cpp | 1 + .../src/cpu-kernels/awkward_argsort.cpp | 4 + .../src/cpu-kernels/awkward_reduce_argmax.cpp | 1 + .../awkward_reduce_argmax_complex.cpp | 1 + .../src/cpu-kernels/awkward_reduce_argmin.cpp | 1 + .../awkward_reduce_argmin_complex.cpp | 1 + .../awkward_reduce_countnonzero.cpp | 1 + .../awkward_reduce_countnonzero_complex.cpp | 1 + .../src/cpu-kernels/awkward_reduce_max.cpp | 1 + .../awkward_reduce_max_complex.cpp | 1 + .../src/cpu-kernels/awkward_reduce_min.cpp | 1 + .../awkward_reduce_min_complex.cpp | 1 + .../src/cpu-kernels/awkward_reduce_prod.cpp | 1 + .../cpu-kernels/awkward_reduce_prod_bool.cpp | 1 + .../awkward_reduce_prod_bool_complex.cpp | 1 + .../awkward_reduce_prod_complex.cpp | 1 + .../src/cpu-kernels/awkward_reduce_sum.cpp | 1 + .../cpu-kernels/awkward_reduce_sum_bool.cpp | 1 + .../awkward_reduce_sum_bool_complex.cpp | 1 + .../awkward_reduce_sum_complex.cpp | 1 + awkward-cpp/src/cpu-kernels/awkward_sort.cpp | 1 + .../src/cpu-kernels/awkward_unique_ranges.cpp | 1 + dev/generate-kernel-signatures.py | 6 +- dev/generate-tests.py | 3 +- kernel-specification.yml | 172 ++++++++++++++++++ src/awkward/_nplikes/numpy_like.py | 2 + src/awkward/_reducers.py | 21 ++- 27 files changed, 218 insertions(+), 11 deletions(-) diff --git a/awkward-cpp/src/cpu-kernels/awkward_NumpyArray_subrange_equal.cpp b/awkward-cpp/src/cpu-kernels/awkward_NumpyArray_subrange_equal.cpp index ed695dc907..81c1014564 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_NumpyArray_subrange_equal.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_NumpyArray_subrange_equal.cpp @@ -52,3 +52,4 @@ WRAPPER(awkward_NumpyArray_subrange_equal_int64, int64_t) WRAPPER(awkward_NumpyArray_subrange_equal_uint64, uint64_t) WRAPPER(awkward_NumpyArray_subrange_equal_float32, float) WRAPPER(awkward_NumpyArray_subrange_equal_float64, double) +WRAPPER(awkward_NumpyArray_subrange_equal_float128, long double) diff --git a/awkward-cpp/src/cpu-kernels/awkward_argsort.cpp b/awkward-cpp/src/cpu-kernels/awkward_argsort.cpp index a651465613..c61c27e811 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_argsort.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_argsort.cpp @@ -172,3 +172,7 @@ ARGSORT_OFF(awkward_argsort_float64_int32, double, int32_t) ARGSORT_OFF(awkward_argsort_float64_uint32, double, uint32_t) ARGSORT_OFF(awkward_argsort_float64_uint64, double, uint64_t) ARGSORT_OFF(awkward_argsort_float64_int64, double, int64_t) +ARGSORT_OFF(awkward_argsort_float128_int32, long double, int32_t) +ARGSORT_OFF(awkward_argsort_float128_uint32, long double, uint32_t) +ARGSORT_OFF(awkward_argsort_float128_uint64, long double, uint64_t) +ARGSORT_OFF(awkward_argsort_float128_int64, long double, int64_t) diff --git a/awkward-cpp/src/cpu-kernels/awkward_reduce_argmax.cpp b/awkward-cpp/src/cpu-kernels/awkward_reduce_argmax.cpp index a9cab3cece..c458b4e5e0 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_reduce_argmax.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_reduce_argmax.cpp @@ -50,3 +50,4 @@ REDUCE_ARGMAX(awkward_reduce_argmax_int64_64, int64_t) REDUCE_ARGMAX(awkward_reduce_argmax_uint64_64, uint64_t) REDUCE_ARGMAX(awkward_reduce_argmax_float32_64, float) REDUCE_ARGMAX(awkward_reduce_argmax_float64_64, double) +REDUCE_ARGMAX(awkward_reduce_argmax_float128_64, long double) diff --git a/awkward-cpp/src/cpu-kernels/awkward_reduce_argmax_complex.cpp b/awkward-cpp/src/cpu-kernels/awkward_reduce_argmax_complex.cpp index 356be66a83..a2c36e793f 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_reduce_argmax_complex.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_reduce_argmax_complex.cpp @@ -37,3 +37,4 @@ ERROR awkward_reduce_argmax_complex( WRAPPER(awkward_reduce_argmax_complex64_64, int64_t, float) WRAPPER(awkward_reduce_argmax_complex128_64, int64_t, double) +WRAPPER(awkward_reduce_argmax_complex256_64, int64_t, long double) diff --git a/awkward-cpp/src/cpu-kernels/awkward_reduce_argmin.cpp b/awkward-cpp/src/cpu-kernels/awkward_reduce_argmin.cpp index 9882dc088d..9515dae708 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_reduce_argmin.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_reduce_argmin.cpp @@ -66,3 +66,4 @@ REDUCE_ARGMIN(awkward_reduce_argmin_int64_64, int64_t) REDUCE_ARGMIN(awkward_reduce_argmin_uint64_64, uint64_t) REDUCE_ARGMIN(awkward_reduce_argmin_float32_64, float) REDUCE_ARGMIN(awkward_reduce_argmin_float64_64, double) +REDUCE_ARGMIN(awkward_reduce_argmin_float128_64, long double) diff --git a/awkward-cpp/src/cpu-kernels/awkward_reduce_argmin_complex.cpp b/awkward-cpp/src/cpu-kernels/awkward_reduce_argmin_complex.cpp index 8a9220d797..4897a0a519 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_reduce_argmin_complex.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_reduce_argmin_complex.cpp @@ -37,3 +37,4 @@ ERROR awkward_reduce_argmin_complex( WRAPPER(awkward_reduce_argmin_complex64_64, int64_t, float) WRAPPER(awkward_reduce_argmin_complex128_64, int64_t, double) +WRAPPER(awkward_reduce_argmin_complex256_64, int64_t, long double) diff --git a/awkward-cpp/src/cpu-kernels/awkward_reduce_countnonzero.cpp b/awkward-cpp/src/cpu-kernels/awkward_reduce_countnonzero.cpp index 6a6a49d280..30f76d77d4 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_reduce_countnonzero.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_reduce_countnonzero.cpp @@ -54,3 +54,4 @@ REDUCE_COUNTNONZERO(awkward_reduce_countnonzero_int64_64, int64_t) REDUCE_COUNTNONZERO(awkward_reduce_countnonzero_uint64_64, uint64_t) REDUCE_COUNTNONZERO(awkward_reduce_countnonzero_float32_64, float) REDUCE_COUNTNONZERO(awkward_reduce_countnonzero_float64_64, double) +REDUCE_COUNTNONZERO(awkward_reduce_countnonzero_float128_64, long double) diff --git a/awkward-cpp/src/cpu-kernels/awkward_reduce_countnonzero_complex.cpp b/awkward-cpp/src/cpu-kernels/awkward_reduce_countnonzero_complex.cpp index 607c3fef79..75cd68cb11 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_reduce_countnonzero_complex.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_reduce_countnonzero_complex.cpp @@ -27,3 +27,4 @@ ERROR awkward_reduce_countnonzero_complex( WRAPPER(awkward_reduce_countnonzero_complex64_64, float) WRAPPER(awkward_reduce_countnonzero_complex128_64, double) +WRAPPER(awkward_reduce_countnonzero_complex256_64, long double) diff --git a/awkward-cpp/src/cpu-kernels/awkward_reduce_max.cpp b/awkward-cpp/src/cpu-kernels/awkward_reduce_max.cpp index e816e02d12..e0fe796eb3 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_reduce_max.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_reduce_max.cpp @@ -42,3 +42,4 @@ REDUCE_MAX(awkward_reduce_max_int64_int64_64, int64_t) REDUCE_MAX(awkward_reduce_max_uint64_uint64_64, uint64_t) REDUCE_MAX(awkward_reduce_max_float32_float32_64, float) REDUCE_MAX(awkward_reduce_max_float64_float64_64, double) +REDUCE_MAX(awkward_reduce_max_float128_float128_64, long double) diff --git a/awkward-cpp/src/cpu-kernels/awkward_reduce_max_complex.cpp b/awkward-cpp/src/cpu-kernels/awkward_reduce_max_complex.cpp index 8d254cb7ee..002e81f088 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_reduce_max_complex.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_reduce_max_complex.cpp @@ -37,3 +37,4 @@ ERROR awkward_reduce_max_complex( WRAPPER(awkward_reduce_max_complex64_complex64_64, float, float) WRAPPER(awkward_reduce_max_complex128_complex128_64, double, double) +WRAPPER(awkward_reduce_max_complex256_complex256_64, long double, long double) diff --git a/awkward-cpp/src/cpu-kernels/awkward_reduce_min.cpp b/awkward-cpp/src/cpu-kernels/awkward_reduce_min.cpp index 5319c6dee2..9b987d8ef1 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_reduce_min.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_reduce_min.cpp @@ -59,3 +59,4 @@ REDUCE_MIN(awkward_reduce_min_int64_int64_64, int64_t) REDUCE_MIN(awkward_reduce_min_uint64_uint64_64, uint64_t) REDUCE_MIN(awkward_reduce_min_float32_float32_64, float) REDUCE_MIN(awkward_reduce_min_float64_float64_64, double) +REDUCE_MIN(awkward_reduce_min_float128_float128_64, long double) diff --git a/awkward-cpp/src/cpu-kernels/awkward_reduce_min_complex.cpp b/awkward-cpp/src/cpu-kernels/awkward_reduce_min_complex.cpp index 75e3dc5c90..c0d7eafb3d 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_reduce_min_complex.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_reduce_min_complex.cpp @@ -37,3 +37,4 @@ ERROR awkward_reduce_min_complex( WRAPPER(awkward_reduce_min_complex64_complex64_64, float, float) WRAPPER(awkward_reduce_min_complex128_complex128_64, double, double) +WRAPPER(awkward_reduce_min_complex256_complex256_64, long double, long double) diff --git a/awkward-cpp/src/cpu-kernels/awkward_reduce_prod.cpp b/awkward-cpp/src/cpu-kernels/awkward_reduce_prod.cpp index b1c38fa909..e0de00c0e4 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_reduce_prod.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_reduce_prod.cpp @@ -41,6 +41,7 @@ REDUCE_PROD(awkward_reduce_prod_int64_int64_64, int64_t, int64_t) REDUCE_PROD(awkward_reduce_prod_uint64_uint64_64, uint64_t, uint64_t) REDUCE_PROD(awkward_reduce_prod_float32_float32_64, float, float) REDUCE_PROD(awkward_reduce_prod_float64_float64_64, double, double) +REDUCE_PROD(awkward_reduce_prod_float128_float128_64, long double, long double) REDUCE_PROD(awkward_reduce_prod_int32_int8_64, int32_t, int8_t) REDUCE_PROD(awkward_reduce_prod_uint32_uint8_64, uint32_t, uint8_t) REDUCE_PROD(awkward_reduce_prod_int32_int16_64, int32_t, int16_t) diff --git a/awkward-cpp/src/cpu-kernels/awkward_reduce_prod_bool.cpp b/awkward-cpp/src/cpu-kernels/awkward_reduce_prod_bool.cpp index a0049051b2..09ff8d12f8 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_reduce_prod_bool.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_reduce_prod_bool.cpp @@ -42,3 +42,4 @@ REDUCE_PROD_BOOL(awkward_reduce_prod_bool_int64_64, int64_t) REDUCE_PROD_BOOL(awkward_reduce_prod_bool_uint64_64, uint64_t) REDUCE_PROD_BOOL(awkward_reduce_prod_bool_float32_64, float) REDUCE_PROD_BOOL(awkward_reduce_prod_bool_float64_64, double) +REDUCE_PROD_BOOL(awkward_reduce_prod_bool_float128_64, long double) diff --git a/awkward-cpp/src/cpu-kernels/awkward_reduce_prod_bool_complex.cpp b/awkward-cpp/src/cpu-kernels/awkward_reduce_prod_bool_complex.cpp index a74b46c5e5..16572a7644 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_reduce_prod_bool_complex.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_reduce_prod_bool_complex.cpp @@ -27,3 +27,4 @@ ERROR awkward_reduce_prod_bool_complex( WRAPPER(awkward_reduce_prod_bool_complex64_64, float) WRAPPER(awkward_reduce_prod_bool_complex128_64, double) +WRAPPER(awkward_reduce_prod_bool_complex256_64, long double) diff --git a/awkward-cpp/src/cpu-kernels/awkward_reduce_prod_complex.cpp b/awkward-cpp/src/cpu-kernels/awkward_reduce_prod_complex.cpp index 184c09f342..fe463b41c0 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_reduce_prod_complex.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_reduce_prod_complex.cpp @@ -36,3 +36,4 @@ ERROR awkward_reduce_prod_complex( WRAPPER(awkward_reduce_prod_complex64_complex64_64, float, float) WRAPPER(awkward_reduce_prod_complex128_complex128_64, double, double) +WRAPPER(awkward_reduce_prod_complex256_complex256_64, long double, long double) diff --git a/awkward-cpp/src/cpu-kernels/awkward_reduce_sum.cpp b/awkward-cpp/src/cpu-kernels/awkward_reduce_sum.cpp index 5ce5f9b415..51ed942e63 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_reduce_sum.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_reduce_sum.cpp @@ -41,6 +41,7 @@ REDUCE_SUM(awkward_reduce_sum_int64_int64_64, int64_t, int64_t) REDUCE_SUM(awkward_reduce_sum_uint64_uint64_64, uint64_t, uint64_t) REDUCE_SUM(awkward_reduce_sum_float32_float32_64, float, float) REDUCE_SUM(awkward_reduce_sum_float64_float64_64, double, double) +REDUCE_SUM(awkward_reduce_sum_float128_float128_64, long double, long double) REDUCE_SUM(awkward_reduce_sum_int32_int8_64, int32_t, int8_t) REDUCE_SUM(awkward_reduce_sum_uint32_uint8_64, uint32_t, uint8_t) REDUCE_SUM(awkward_reduce_sum_int32_int16_64, int32_t, int16_t) diff --git a/awkward-cpp/src/cpu-kernels/awkward_reduce_sum_bool.cpp b/awkward-cpp/src/cpu-kernels/awkward_reduce_sum_bool.cpp index 7a5d015d7b..ab54ade46b 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_reduce_sum_bool.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_reduce_sum_bool.cpp @@ -50,3 +50,4 @@ REDUCE_SUM_BOOL(awkward_reduce_sum_bool_int64_64, int64_t) REDUCE_SUM_BOOL(awkward_reduce_sum_bool_uint64_64, uint64_t) REDUCE_SUM_BOOL(awkward_reduce_sum_bool_float32_64, float) REDUCE_SUM_BOOL(awkward_reduce_sum_bool_float64_64, double) +REDUCE_SUM_BOOL(awkward_reduce_sum_bool_float128_64, long double) diff --git a/awkward-cpp/src/cpu-kernels/awkward_reduce_sum_bool_complex.cpp b/awkward-cpp/src/cpu-kernels/awkward_reduce_sum_bool_complex.cpp index 366df853ed..e3cef02c49 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_reduce_sum_bool_complex.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_reduce_sum_bool_complex.cpp @@ -27,3 +27,4 @@ ERROR awkward_reduce_sum_bool_complex( WRAPPER(awkward_reduce_sum_bool_complex64_64, float) WRAPPER(awkward_reduce_sum_bool_complex128_64, double) +WRAPPER(awkward_reduce_sum_bool_complex256_64, long double) diff --git a/awkward-cpp/src/cpu-kernels/awkward_reduce_sum_complex.cpp b/awkward-cpp/src/cpu-kernels/awkward_reduce_sum_complex.cpp index 194d31ad37..fbbc60438d 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_reduce_sum_complex.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_reduce_sum_complex.cpp @@ -30,3 +30,4 @@ ERROR awkward_reduce_sum_complex( WRAPPER(awkward_reduce_sum_complex64_complex64_64, float, float) WRAPPER(awkward_reduce_sum_complex128_complex128_64, double, double) +WRAPPER(awkward_reduce_sum_complex256_complex256_64, long double, long double) diff --git a/awkward-cpp/src/cpu-kernels/awkward_sort.cpp b/awkward-cpp/src/cpu-kernels/awkward_sort.cpp index a9bf3bec94..c825c4ef16 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_sort.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_sort.cpp @@ -137,3 +137,4 @@ SORT(awkward_sort_int64, int64_t) SORT(awkward_sort_uint64, uint64_t) SORT(awkward_sort_float32, float) SORT(awkward_sort_float64, double) +SORT(awkward_sort_float128, long double) diff --git a/awkward-cpp/src/cpu-kernels/awkward_unique_ranges.cpp b/awkward-cpp/src/cpu-kernels/awkward_unique_ranges.cpp index e8ba374ecf..91e25d559f 100644 --- a/awkward-cpp/src/cpu-kernels/awkward_unique_ranges.cpp +++ b/awkward-cpp/src/cpu-kernels/awkward_unique_ranges.cpp @@ -40,3 +40,4 @@ WRAPPER(awkward_unique_ranges_int64, int64_t) WRAPPER(awkward_unique_ranges_uint64, uint64_t) WRAPPER(awkward_unique_ranges_float32, float) WRAPPER(awkward_unique_ranges_float64, double) +WRAPPER(awkward_unique_ranges_float128, long double) diff --git a/dev/generate-kernel-signatures.py b/dev/generate-kernel-signatures.py index 305a0c88ac..aeba91ddb2 100644 --- a/dev/generate-kernel-signatures.py +++ b/dev/generate-kernel-signatures.py @@ -123,6 +123,7 @@ def include_kernels_h(specification): "uint64": "uint64", "float": "float32", "double": "float64", + "long double": "longdouble", } @@ -137,7 +138,8 @@ def type_to_pytype(typename, special): typename = typename[:-2] if count != 0: special.append(type_to_dtype[typename]) - return ("POINTER(" * count) + ("c_" + typename) + (")" * count) + # "long double" is `c_longdouble` in ctypes + return ("POINTER(" * count) + ("c_" + typename.replace(" ", "")) + (")" * count) def kernel_signatures_py(specification): @@ -179,6 +181,7 @@ def kernel_signatures_py(specification): c_uint64, c_float, c_double, + c_longdouble, c_char_p, ) @@ -196,6 +199,7 @@ def kernel_signatures_py(specification): uint64, float32, float64, + longdouble, ) class ERROR(Structure): diff --git a/dev/generate-tests.py b/dev/generate-tests.py index 00beed9e0d..a61236a99c 100644 --- a/dev/generate-tests.py +++ b/dev/generate-tests.py @@ -294,7 +294,8 @@ def gettypename(spectype): typename = spectype.replace("List", "").replace("[", "").replace("]", "") if typename.endswith("_t"): typename = typename[:-2] - return typename + # "long double" is `longdouble` in both ctypes and NumPy + return typename.replace(" ", "") def genpykernels(): diff --git a/kernel-specification.yml b/kernel-specification.yml index 36d3bc7d2f..6243f44efb 100644 --- a/kernel-specification.yml +++ b/kernel-specification.yml @@ -2842,6 +2842,13 @@ kernels: - {name: fromstops, type: "Const[List[int64_t]]", dir: in, role: ListArray-stops} - {name: length, type: "int64_t", dir: in, role: default} - {name: toequal, type: "List[bool]", dir: out} + - name: awkward_NumpyArray_subrange_equal_float128 + args: + - {name: tmpptr, type: "List[long double]", dir: in, role: IndexedArray-index} + - {name: fromstarts, type: "Const[List[int64_t]]", dir: in, role: ListArray-starts} + - {name: fromstops, type: "Const[List[int64_t]]", dir: in, role: ListArray-stops} + - {name: length, type: "int64_t", dir: in, role: default} + - {name: toequal, type: "List[bool]", dir: out} description: null definition: | def awkward_NumpyArray_subrange_equal( @@ -4097,6 +4104,42 @@ kernels: - {name: offsetslength, type: "int64_t", dir: in, role: default} - {name: ascending, type: "bool", dir: in, role: ListArray-replacement} - {name: stable, type: "bool", dir: in, role: ListArray-replacement} + - name: awkward_argsort_float128_int32 + args: + - {name: toptr, type: "List[int64_t]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: IndexedArray-index} + - {name: length, type: "int64_t", dir: in, role: default} + - {name: offsets, type: "Const[List[int32_t]]", dir: in, role: ListOffsetArray-offsets} + - {name: offsetslength, type: "int64_t", dir: in, role: default} + - {name: ascending, type: "bool", dir: in, role: ListArray-replacement} + - {name: stable, type: "bool", dir: in, role: ListArray-replacement} + - name: awkward_argsort_float128_uint32 + args: + - {name: toptr, type: "List[int64_t]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: IndexedArray-index} + - {name: length, type: "int64_t", dir: in, role: default} + - {name: offsets, type: "Const[List[uint32_t]]", dir: in, role: ListOffsetArray-offsets} + - {name: offsetslength, type: "int64_t", dir: in, role: default} + - {name: ascending, type: "bool", dir: in, role: ListArray-replacement} + - {name: stable, type: "bool", dir: in, role: ListArray-replacement} + - name: awkward_argsort_float128_uint64 + args: + - {name: toptr, type: "List[int64_t]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: IndexedArray-index} + - {name: length, type: "int64_t", dir: in, role: default} + - {name: offsets, type: "Const[List[uint64_t]]", dir: in, role: ListOffsetArray-offsets} + - {name: offsetslength, type: "int64_t", dir: in, role: default} + - {name: ascending, type: "bool", dir: in, role: ListArray-replacement} + - {name: stable, type: "bool", dir: in, role: ListArray-replacement} + - name: awkward_argsort_float128_int64 + args: + - {name: toptr, type: "List[int64_t]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: IndexedArray-index} + - {name: length, type: "int64_t", dir: in, role: default} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: ListOffsetArray-offsets} + - {name: offsetslength, type: "int64_t", dir: in, role: default} + - {name: ascending, type: "bool", dir: in, role: ListArray-replacement} + - {name: stable, type: "bool", dir: in, role: ListArray-replacement} description: null definition: | def awkward_argsort( @@ -4274,6 +4317,13 @@ kernels: - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} - {name: starts, type: "Const[List[int64_t]]", dir: in, role: reducer-starts} - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} + - name: awkward_reduce_argmax_float128_64 + args: + - {name: toptr, type: "List[int64_t]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: reducer-fromptr} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} + - {name: starts, type: "Const[List[int64_t]]", dir: in, role: reducer-starts} + - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} description: null definition: | def awkward_reduce_argmax(toptr, fromptr, offsets, starts, outlength): @@ -4298,6 +4348,12 @@ kernels: - {name: fromptr, type: "Const[List[double]]", dir: in, role: reducer-fromptr} - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} + - name: awkward_reduce_argmax_complex256_64 + args: + - {name: toptr, type: "List[int64_t]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: reducer-fromptr} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} + - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} description: null definition: | def awkward_reduce_argmax_complex(toptr, fromptr, offsets, outlength): @@ -4385,6 +4441,13 @@ kernels: - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} - {name: starts, type: "Const[List[int64_t]]", dir: in, role: reducer-starts} - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} + - name: awkward_reduce_argmin_float128_64 + args: + - {name: toptr, type: "List[int64_t]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: reducer-fromptr} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} + - {name: starts, type: "Const[List[int64_t]]", dir: in, role: reducer-starts} + - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} description: null definition: | def awkward_reduce_argmin(toptr, fromptr, offsets, starts, outlength): @@ -4409,6 +4472,12 @@ kernels: - {name: fromptr, type: "Const[List[double]]", dir: in, role: reducer-fromptr} - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} + - name: awkward_reduce_argmin_complex256_64 + args: + - {name: toptr, type: "List[int64_t]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: reducer-fromptr} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} + - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} description: null definition: | def awkward_reduce_argmin_complex(toptr, fromptr, offsets, outlength): @@ -4505,6 +4574,12 @@ kernels: - {name: fromptr, type: "Const[List[double]]", dir: in, role: reducer-fromptr} - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} + - name: awkward_reduce_countnonzero_float128_64 + args: + - {name: toptr, type: "List[int64_t]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: reducer-fromptr} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} + - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} description: null definition: | def awkward_reduce_countnonzero(toptr, fromptr, offsets, outlength): @@ -4529,6 +4604,12 @@ kernels: - {name: fromptr, type: "Const[List[double]]", dir: in, role: reducer-fromptr} - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} + - name: awkward_reduce_countnonzero_complex256_64 + args: + - {name: toptr, type: "List[int64_t]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: reducer-fromptr} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} + - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} description: null definition: | def awkward_reduce_countnonzero_complex(toptr, fromptr, offsets, outlength): @@ -4611,6 +4692,13 @@ kernels: - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} - {name: identity, type: "double", dir: in, role: reducer-identity} + - name: awkward_reduce_max_float128_float128_64 + args: + - {name: toptr, type: "List[long double]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: reducer-fromptr} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} + - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} + - {name: identity, type: "long double", dir: in, role: reducer-identity} description: null definition: | def awkward_reduce_max(toptr, fromptr, offsets, outlength, identity): @@ -4638,6 +4726,13 @@ kernels: - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} - {name: identity, type: "double", dir: in, role: reducer-identity} + - name: awkward_reduce_max_complex256_complex256_64 + args: + - {name: toptr, type: "List[long double]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: reducer-fromptr} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} + - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} + - {name: identity, type: "long double", dir: in, role: reducer-identity} description: null definition: | def awkward_reduce_max_complex(toptr, fromptr, offsets, outlength, identity): @@ -4727,6 +4822,13 @@ kernels: - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} - {name: identity, type: "double", dir: in, role: reducer-identity} + - name: awkward_reduce_min_float128_float128_64 + args: + - {name: toptr, type: "List[long double]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: reducer-fromptr} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} + - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} + - {name: identity, type: "long double", dir: in, role: reducer-identity} description: null definition: | def awkward_reduce_min(toptr, fromptr, offsets, outlength, identity): @@ -4754,6 +4856,13 @@ kernels: - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} - {name: identity, type: "double", dir: in, role: reducer-identity} + - name: awkward_reduce_min_complex256_complex256_64 + args: + - {name: toptr, type: "List[long double]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: reducer-fromptr} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} + - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} + - {name: identity, type: "long double", dir: in, role: reducer-identity} description: null definition: | def awkward_reduce_min_complex(toptr, fromptr, offsets, outlength, identity): @@ -4833,6 +4942,12 @@ kernels: - {name: fromptr, type: "Const[List[double]]", dir: in, role: reducer-fromptr} - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} + - name: awkward_reduce_prod_float128_float128_64 + args: + - {name: toptr, type: "List[long double]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: reducer-fromptr} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} + - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} - name: awkward_reduce_prod_int32_int8_64 args: - {name: toptr, type: "List[int32_t]", dir: out} @@ -4892,6 +5007,12 @@ kernels: - {name: fromptr, type: "Const[List[double]]", dir: in, role: reducer-fromptr} - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} + - name: awkward_reduce_prod_complex256_complex256_64 + args: + - {name: toptr, type: "List[long double]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: reducer-fromptr} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} + - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} description: null definition: | def awkward_reduce_prod_complex(toptr, fromptr, offsets, outlength): @@ -4976,6 +5097,12 @@ kernels: - {name: fromptr, type: "Const[List[double]]", dir: in, role: reducer-fromptr} - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} + - name: awkward_reduce_prod_bool_float128_64 + args: + - {name: toptr, type: "List[bool]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: reducer-fromptr} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} + - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} description: null definition: | def awkward_reduce_prod_bool(toptr, fromptr, offsets, outlength): @@ -5001,6 +5128,12 @@ kernels: - {name: fromptr, type: "Const[List[double]]", dir: in, role: reducer-fromptr} - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} + - name: awkward_reduce_prod_bool_complex256_64 + args: + - {name: toptr, type: "List[bool]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: reducer-fromptr} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} + - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} description: null definition: | def awkward_reduce_prod_bool_complex(toptr, fromptr, offsets, outlength): @@ -5074,6 +5207,12 @@ kernels: - {name: fromptr, type: "Const[List[double]]", dir: in, role: reducer-fromptr} - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} + - name: awkward_reduce_sum_float128_float128_64 + args: + - {name: toptr, type: "List[long double]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: reducer-fromptr} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} + - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} - name: awkward_reduce_sum_int32_int8_64 args: - {name: toptr, type: "List[int32_t]", dir: out} @@ -5133,6 +5272,12 @@ kernels: - {name: fromptr, type: "Const[List[double]]", dir: in, role: reducer-fromptr} - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} + - name: awkward_reduce_sum_complex256_complex256_64 + args: + - {name: toptr, type: "List[long double]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: reducer-fromptr} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} + - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} description: null definition: | def awkward_reduce_sum_complex(toptr, fromptr, offsets, outlength): @@ -5213,6 +5358,12 @@ kernels: - {name: fromptr, type: "Const[List[double]]", dir: in, role: reducer-fromptr} - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} + - name: awkward_reduce_sum_bool_float128_64 + args: + - {name: toptr, type: "List[bool]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: reducer-fromptr} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} + - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} description: null definition: | def awkward_reduce_sum_bool(toptr, fromptr, offsets, outlength): @@ -5238,6 +5389,12 @@ kernels: - {name: fromptr, type: "Const[List[double]]", dir: in, role: reducer-fromptr} - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} + - name: awkward_reduce_sum_bool_complex256_64 + args: + - {name: toptr, type: "List[bool]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: reducer-fromptr} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: reducer-offsets} + - {name: outlength, type: "int64_t", dir: in, role: reducer-outlength} description: null definition: | def awkward_reduce_sum_bool_complex(toptr, fromptr, offsets, outlength): @@ -5386,6 +5543,15 @@ kernels: - {name: offsetslength, type: "int64_t", dir: in, role: default} - {name: ascending, type: "bool", dir: in, role: ListArray-replacement} - {name: stable, type: "bool", dir: in, role: ListArray-replacement} + - name: awkward_sort_float128 + args: + - {name: toptr, type: "List[long double]", dir: out} + - {name: fromptr, type: "Const[List[long double]]", dir: in, role: IndexedArray-index} + - {name: length, type: "int64_t", dir: in, role: default} + - {name: offsets, type: "Const[List[int64_t]]", dir: in, role: ListOffsetArray-offsets} + - {name: offsetslength, type: "int64_t", dir: in, role: default} + - {name: ascending, type: "bool", dir: in, role: ListArray-replacement} + - {name: stable, type: "bool", dir: in, role: ListArray-replacement} description: null definition: | def awkward_sort( @@ -5535,6 +5701,12 @@ kernels: - {name: fromoffsets, type: "Const[List[int64_t]]", dir: in, role: default} - {name: offsetslength, type: "int64_t", dir: in, role: default} - {name: tooffsets, type: "List[int64_t]", dir: out, role: default} + - name: awkward_unique_ranges_float128 + args: + - {name: toptr, type: "List[long double]", dir: out} + - {name: fromoffsets, type: "Const[List[int64_t]]", dir: in, role: default} + - {name: offsetslength, type: "int64_t", dir: in, role: default} + - {name: tooffsets, type: "List[int64_t]", dir: out, role: default} description: null definition: | def awkward_unique_ranges( diff --git a/src/awkward/_nplikes/numpy_like.py b/src/awkward/_nplikes/numpy_like.py index 99a1751a2e..1b3208fbe5 100644 --- a/src/awkward/_nplikes/numpy_like.py +++ b/src/awkward/_nplikes/numpy_like.py @@ -54,6 +54,8 @@ class NumpyMetadata(PublicSingleton): float64 = numpy.float64 complex64 = numpy.complex64 complex128 = numpy.complex128 + longdouble = numpy.longdouble + clongdouble = numpy.clongdouble str_ = numpy.str_ bytes_ = numpy.bytes_ diff --git a/src/awkward/_reducers.py b/src/awkward/_reducers.py index 36be33f52d..1e93b80bab 100644 --- a/src/awkward/_reducers.py +++ b/src/awkward/_reducers.py @@ -52,7 +52,7 @@ class KernelReducer(Reducer): @classmethod def _length_for_kernel(cls, type: DTypeLike, length: ShapeItem) -> ShapeItem: # Complex types are implemented as double-wide arrays - return 2 * length if type in (np.complex128, np.complex64) else length + return 2 * length if np.dtype(type).kind == "c" else length @classmethod def _dtype_for_kernel(cls, dtype: DTypeLike) -> DTypeLike: @@ -63,6 +63,9 @@ def _dtype_for_kernel(cls, dtype: DTypeLike) -> DTypeLike: return np.dtype(np.float64) elif dtype == np.complex64: return np.dtype(np.float32) + elif dtype.kind == "c": + # long double complex numbers are pairs of long doubles + return np.dtype(np.longdouble) else: return dtype @@ -151,7 +154,7 @@ def apply( assert isinstance(array, ak.contents.NumpyArray) kernel_array_data = array.data.view(self._dtype_for_kernel(array.dtype)) result = array.backend.nplike.empty(outlength, dtype=np.int64) - if array.dtype.type in (np.complex128, np.complex64): + if array.dtype.kind == "c": assert offsets.nplike is array.backend.nplike array.backend.maybe_kernel_error( array.backend[ @@ -212,7 +215,7 @@ def apply( assert isinstance(array, ak.contents.NumpyArray) kernel_array_data = array.data.view(self._dtype_for_kernel(array.dtype)) result = array.backend.nplike.empty(outlength, dtype=np.int64) - if array.dtype.type in (np.complex128, np.complex64): + if array.dtype.kind == "c": assert offsets.nplike is array.backend.nplike array.backend.maybe_kernel_error( array.backend[ @@ -391,7 +394,7 @@ def apply( self._length_for_kernel(array.dtype.type, outlength), dtype=self._promote_integer_rank(kernel_array_data.dtype), ) - if array.dtype.type in (np.complex128, np.complex64): + if array.dtype.kind == "c": assert offsets.nplike is array.backend.nplike array.backend.maybe_kernel_error( array.backend[ @@ -497,7 +500,7 @@ def apply( self._length_for_kernel(array.dtype.type, outlength), dtype=self._promote_integer_rank(kernel_array_data.dtype), ) - if array.dtype.type in (np.complex128, np.complex64): + if array.dtype.kind == "c": assert offsets.nplike is array.backend.nplike array.backend.maybe_kernel_error( array.backend[ @@ -551,7 +554,7 @@ def apply( kernel_array_data = array.data.view(self._dtype_for_kernel(array.dtype)) result = array.backend.nplike.empty(outlength, dtype=np.bool_) - if array.dtype.type in (np.complex128, np.complex64): + if array.dtype.kind == "c": assert offsets.nplike is array.backend.nplike array.backend.maybe_kernel_error( array.backend[ @@ -601,7 +604,7 @@ def apply( kernel_array_data = array.data.view(self._dtype_for_kernel(array.dtype)) result = array.backend.nplike.empty(outlength, dtype=np.bool_) - if array.dtype.type in (np.complex128, np.complex64): + if array.dtype.kind == "c": assert offsets.nplike is array.backend.nplike array.backend.maybe_kernel_error( array.backend[ @@ -704,7 +707,7 @@ def apply( self._length_for_kernel(array.dtype.type, outlength), dtype=kernel_array_data.dtype, ) - if array.dtype.type in (np.complex128, np.complex64): + if array.dtype.kind == "c": assert offsets.nplike is array.backend.nplike array.backend.maybe_kernel_error( array.backend[ @@ -849,7 +852,7 @@ def apply( self._length_for_kernel(array.dtype.type, outlength), dtype=kernel_array_data.dtype, ) - if array.dtype.type in (np.complex128, np.complex64): + if array.dtype.kind == "c": assert offsets.nplike is array.backend.nplike array.backend.maybe_kernel_error( array.backend[ From f67d23e7c39e675a350b62ecad90926b62eed90b Mon Sep 17 00:00:00 2001 From: Iason Krommydas Date: Sat, 10 Oct 2026 02:28:33 +0200 Subject: [PATCH 02/19] feat: run float16 reducers, sorting and unique through the float32 kernels and name the type in errors for complex sorting --- src/awkward/contents/numpyarray.py | 43 +++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/awkward/contents/numpyarray.py b/src/awkward/contents/numpyarray.py index 43a243e372..2febb94251 100644 --- a/src/awkward/contents/numpyarray.py +++ b/src/awkward/contents/numpyarray.py @@ -609,9 +609,18 @@ def to_contiguous(self) -> Self: def is_contiguous(self) -> bool: return self._backend.nplike.is_c_contiguous(self._data) + def _float16_as_float32(self): + # The kernels have no half-precision versions. float32 holds every + # float16 value, so they are given float32 data. + return self._numbers_to_type("float32", False) + def _subranges_equal(self, starts, stops, length, sorted=True): if not self.is_contiguous: return self.to_contiguous()._subranges_equal(starts, stops, length, sorted) + elif self.dtype == np.float16: + return self._float16_as_float32()._subranges_equal( + starts, stops, length, sorted + ) is_equal = self._backend.nplike.zeros(1, dtype=np.bool_) @@ -755,6 +764,17 @@ def _unique(self, negaxis, starts, offsets, outlength): elif len(self.shape) == 0: return self + elif self.dtype == np.float16: + out = self._float16_as_float32()._unique( + negaxis, starts, offsets, outlength + ) + return out._numbers_to_type("float16", False) + + elif self.dtype.kind == "c" or ( + negaxis is not None and self.dtype.kind.upper() == "M" + ): + raise ValueError(f"cannot find the unique values of {self.dtype!r}") + elif negaxis is None: contiguous_self = self.to_contiguous() @@ -911,6 +931,12 @@ def _argsort_next( return self.to_contiguous()._argsort_next( negaxis, starts, shifts, offsets, outlength, ascending, stable ) + elif self.dtype == np.float16: + return self._float16_as_float32()._argsort_next( + negaxis, starts, shifts, offsets, outlength, ascending, stable + ) + elif self.dtype.kind == "c": + raise ValueError(f"cannot sort (ak.argsort) values of {self.dtype!r}") else: offsets_length = offsets.length @@ -998,6 +1024,13 @@ def _sort_next(self, negaxis, starts, offsets, outlength, ascending, stable): return self.to_contiguous()._sort_next( negaxis, starts, offsets, outlength, ascending, stable ) + elif self.dtype == np.float16: + out = self._float16_as_float32()._sort_next( + negaxis, starts, offsets, outlength, ascending, stable + ) + return out._numbers_to_type("float16", False) + elif self.dtype.kind == "c": + raise ValueError(f"cannot sort (ak.sort) values of {self.dtype!r}") else: offsets_length = offsets.length @@ -1086,7 +1119,15 @@ def _reduce_next( # No more `parents_to_offsets_aligned` round-trip — `offsets` is the # bin descriptor we receive directly. - out = reducer.apply(self, offsets, starts, shifts, outlength) + if self.dtype == np.float16: + out = reducer.apply( + self._float16_as_float32(), offsets, starts, shifts, outlength + ) + # a reducer that returns the type of its input returns float16 + if out.dtype == np.float32: + out = out._numbers_to_type("float16", False) + else: + out = reducer.apply(self, offsets, starts, shifts, outlength) if mask: outmask = ak.index.Index8.empty(outlength, self._backend.nplike) From 86705776604272ea0750dd0f3c932a369b4452ab Mon Sep 17 00:00:00 2001 From: Iason Krommydas Date: Sat, 10 Oct 2026 02:28:35 +0200 Subject: [PATCH 03/19] feat: parse float16, float128 and complex256 in type strings --- src/awkward/types/_awkward_datashape_parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/awkward/types/_awkward_datashape_parser.py b/src/awkward/types/_awkward_datashape_parser.py index b9f9b14541..fb947e1664 100644 --- a/src/awkward/types/_awkward_datashape_parser.py +++ b/src/awkward/types/_awkward_datashape_parser.py @@ -2897,7 +2897,7 @@ def always_accept(self): {'parser': {'lexer_conf': {'terminals': [{'@': 0}, {'@': 1}, {'@': 2}, {'@': 3}, {'@': 4}, {'@': 5}, {'@': 6}, {'@': 7}, {'@': 8}, {'@': 9}, {'@': 10}, {'@': 11}, {'@': 12}, {'@': 13}, {'@': 14}, {'@': 15}, {'@': 16}, {'@': 17}, {'@': 18}, {'@': 19}, {'@': 20}, {'@': 21}, {'@': 22}, {'@': 23}, {'@': 24}, {'@': 25}, {'@': 26}, {'@': 27}, {'@': 28}, {'@': 29}, {'@': 30}, {'@': 31}, {'@': 32}, {'@': 33}, {'@': 34}], 'ignore': ['WS'], 'g_regex_flags': 0, 'use_bytes': False, 'lexer_type': 'contextual', '__type__': 'LexerConf'}, 'parser_conf': {'rules': [{'@': 35}, {'@': 36}, {'@': 37}, {'@': 38}, {'@': 39}, {'@': 40}, {'@': 41}, {'@': 42}, {'@': 43}, {'@': 44}, {'@': 45}, {'@': 46}, {'@': 47}, {'@': 48}, {'@': 49}, {'@': 50}, {'@': 51}, {'@': 52}, {'@': 53}, {'@': 54}, {'@': 55}, {'@': 56}, {'@': 57}, {'@': 58}, {'@': 59}, {'@': 60}, {'@': 61}, {'@': 62}, {'@': 63}, {'@': 64}, {'@': 65}, {'@': 66}, {'@': 67}, {'@': 68}, {'@': 69}, {'@': 70}, {'@': 71}, {'@': 72}, {'@': 73}, {'@': 74}, {'@': 75}, {'@': 76}, {'@': 77}, {'@': 78}, {'@': 79}, {'@': 80}, {'@': 81}, {'@': 82}, {'@': 83}, {'@': 84}, {'@': 85}, {'@': 86}, {'@': 87}, {'@': 88}, {'@': 89}, {'@': 90}, {'@': 91}, {'@': 92}, {'@': 93}, {'@': 94}, {'@': 95}, {'@': 96}, {'@': 97}, {'@': 98}, {'@': 99}, {'@': 100}, {'@': 101}, {'@': 102}, {'@': 103}, {'@': 104}, {'@': 105}, {'@': 106}, {'@': 107}, {'@': 108}, {'@': 109}, {'@': 110}, {'@': 111}, {'@': 112}, {'@': 113}, {'@': 114}, {'@': 115}, {'@': 116}, {'@': 117}, {'@': 118}, {'@': 119}, {'@': 120}, {'@': 121}, {'@': 122}, {'@': 123}, {'@': 124}, {'@': 125}, {'@': 126}, {'@': 127}, {'@': 128}, {'@': 129}, {'@': 130}], 'start': ['start'], 'parser_type': 'lalr', '__type__': 'ParserConf'}, 'parser': {'tokens': {0: 'RSQB', 1: 'LSQB', 2: 'COMMA', 3: 'RBRACE', 4: '$END', 5: 'RPAR', 6: 'INT', 7: 'key', 8: 'ESCAPED_STRING', 9: 'CNAME', 10: 'pair', 11: 'LBRACE', 12: 'json_object', 13: 'EQUAL', 14: 'PARAMETERS', 15: 'OPTION', 16: 'tuple', 17: 'numpytype_name', 18: 'type', 19: 'tuple_parameters', 20: 'TUPLE', 21: 'named_pair', 22: 'list_parameters', 23: 'option1', 24: 'BYTE', 25: 'union', 26: 'regulartype', 27: 'unknowntype', 28: 'option2', 29: 'named_pairs', 30: 'varlen_string', 31: 'UNION', 32: 'char', 33: 'VAR', 34: 'record_parameters', 35: 'STRING', 36: 'CATEGORICAL', 37: 'record', 38: 'DTYPE', 39: 'STRUCT', 40: 'categorical', 41: 'UNKNOWN', 42: 'named0', 43: 'named', 44: 'numpytype', 45: 'named_key', 46: 'CHAR', 47: 'LPAR', 48: 'TIMEDELTA64', 49: 'named_types', 50: 'byte', 51: 'listtype', 52: 'DATETIME64', 53: 'BYTES', 54: 'fixedlen_string', 55: 'QMARK', 56: 'types', 57: 'pairs', 58: '__pairs_star_1', 59: 'json', 60: 'json_array', 61: 'FALSE', 62: 'TRUE', 63: 'NULL', 64: 'SIGNED_NUMBER', 65: 'COLON', 66: '__types_star_0', 67: 'json_pair', 68: 'STAR', 69: '__json_object_star_3', 70: '__json_array_star_2', 71: 'start', 72: 'TYPE'}, 'states': {0: {0: (1, {'@': 57}), 1: (1, {'@': 57}), 2: (1, {'@': 57}), 3: (1, {'@': 57}), 4: (1, {'@': 57}), 5: (1, {'@': 57})}, 1: {0: (1, {'@': 106}), 2: (1, {'@': 106}), 3: (1, {'@': 106}), 4: (1, {'@': 106}), 5: (1, {'@': 106})}, 2: {0: (0, 165)}, 3: {1: (0, 160)}, 4: {6: (0, 72)}, 5: {7: (0, 52), 8: (0, 46), 9: (0, 47), 10: (0, 42)}, 6: {0: (0, 91)}, 7: {11: (0, 189), 12: (0, 63)}, 8: {11: (0, 189), 12: (0, 59)}, 9: {0: (1, {'@': 119}), 2: (1, {'@': 119}), 3: (1, {'@': 119})}, 10: {11: (0, 189), 12: (0, 65)}, 11: {3: (0, 9), 2: (0, 89)}, 12: {0: (1, {'@': 44}), 2: (1, {'@': 44}), 3: (1, {'@': 44}), 4: (1, {'@': 44}), 5: (1, {'@': 44})}, 13: {13: (0, 138)}, 14: {1: (0, 69), 0: (1, {'@': 61}), 2: (1, {'@': 61}), 3: (1, {'@': 61}), 4: (1, {'@': 61}), 5: (1, {'@': 61})}, 15: {13: (0, 119)}, 16: {1: (0, 164), 14: (0, 182), 15: (0, 140), 16: (0, 147), 17: (0, 197), 18: (0, 177), 19: (0, 174), 20: (0, 3), 21: (0, 201), 0: (0, 114), 22: (0, 22), 23: (0, 12), 9: (0, 123), 24: (0, 145), 25: (0, 116), 26: (0, 96), 27: (0, 200), 28: (0, 137), 29: (0, 112), 30: (0, 153), 31: (0, 120), 32: (0, 146), 11: (0, 32), 33: (0, 64), 34: (0, 186), 35: (0, 51), 36: (0, 143), 37: (0, 166), 38: (0, 0), 39: (0, 45), 40: (0, 40), 6: (0, 75), 41: (0, 14), 42: (0, 55), 43: (0, 128), 44: (0, 131), 45: (0, 98), 46: (0, 107), 47: (0, 181), 48: (0, 159), 49: (0, 104), 50: (0, 133), 51: (0, 198), 8: (0, 126), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191)}, 17: {21: (0, 201), 14: (0, 15), 8: (0, 126), 45: (0, 98), 29: (0, 31), 9: (0, 93)}, 18: {3: (1, {'@': 122}), 2: (1, {'@': 122})}, 19: {1: (0, 164), 15: (0, 140), 36: (0, 143), 18: (0, 60), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 56: (0, 155), 33: (0, 64), 40: (0, 40), 0: (0, 130), 6: (0, 75), 9: (0, 29), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 25: (0, 116), 26: (0, 96), 44: (0, 131), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 34: (0, 186)}, 20: {0: (1, {'@': 112}), 2: (1, {'@': 112}), 3: (1, {'@': 112})}, 21: {0: (1, {'@': 90}), 2: (1, {'@': 90}), 3: (1, {'@': 90}), 4: (1, {'@': 90}), 5: (1, {'@': 90})}, 22: {0: (1, {'@': 53}), 2: (1, {'@': 53}), 3: (1, {'@': 53}), 4: (1, {'@': 53}), 5: (1, {'@': 53})}, 23: {0: (1, {'@': 74}), 2: (1, {'@': 74}), 3: (1, {'@': 74}), 4: (1, {'@': 74}), 5: (1, {'@': 74})}, 24: {14: (0, 179)}, 25: {0: (1, {'@': 109}), 2: (1, {'@': 109}), 3: (1, {'@': 109})}, 26: {0: (1, {'@': 118}), 2: (1, {'@': 118}), 3: (1, {'@': 118})}, 27: {0: (1, {'@': 111}), 2: (1, {'@': 111}), 3: (1, {'@': 111})}, 28: {0: (1, {'@': 128}), 2: (1, {'@': 128})}, 29: {1: (0, 16)}, 30: {3: (0, 170), 7: (0, 52), 57: (0, 193), 10: (0, 33), 8: (0, 46), 9: (0, 47)}, 31: {0: (1, {'@': 99})}, 32: {7: (0, 52), 10: (0, 33), 8: (0, 46), 9: (0, 47), 3: (0, 58), 57: (0, 76)}, 33: {58: (0, 157), 2: (0, 149), 3: (1, {'@': 84})}, 34: {0: (1, {'@': 96})}, 35: {59: (0, 80), 12: (0, 44), 60: (0, 199), 1: (0, 35), 11: (0, 189), 0: (0, 26), 61: (0, 20), 62: (0, 27), 8: (0, 25), 63: (0, 136), 64: (0, 127)}, 36: {0: (0, 152)}, 37: {0: (0, 122)}, 38: {0: (0, 50), 2: (0, 77)}, 39: {0: (1, {'@': 77}), 2: (1, {'@': 77}), 3: (1, {'@': 77}), 4: (1, {'@': 77}), 5: (1, {'@': 77})}, 40: {0: (1, {'@': 54}), 2: (1, {'@': 54}), 3: (1, {'@': 54}), 4: (1, {'@': 54}), 5: (1, {'@': 54})}, 41: {0: (1, {'@': 102}), 2: (1, {'@': 102})}, 42: {3: (1, {'@': 126}), 2: (1, {'@': 126})}, 43: {61: (0, 20), 11: (0, 189), 62: (0, 27), 8: (0, 25), 12: (0, 44), 1: (0, 35), 60: (0, 199), 63: (0, 136), 64: (0, 127), 59: (0, 90)}, 44: {0: (1, {'@': 115}), 2: (1, {'@': 115}), 3: (1, {'@': 115})}, 45: {1: (0, 113)}, 46: {65: (1, {'@': 86})}, 47: {65: (1, {'@': 87})}, 48: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 18: (0, 6), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 49: {0: (1, {'@': 120}), 2: (1, {'@': 120}), 3: (1, {'@': 120})}, 50: {0: (1, {'@': 116}), 2: (1, {'@': 116}), 3: (1, {'@': 116})}, 51: {1: (0, 129), 0: (1, {'@': 64}), 2: (1, {'@': 64}), 3: (1, {'@': 64}), 4: (1, {'@': 64}), 5: (1, {'@': 64})}, 52: {65: (0, 74)}, 53: {13: (0, 121)}, 54: {0: (0, 97)}, 55: {0: (1, {'@': 50}), 2: (1, {'@': 50}), 3: (1, {'@': 50}), 4: (1, {'@': 50}), 5: (1, {'@': 50})}, 56: {11: (0, 189), 12: (0, 139)}, 57: {0: (0, 190), 2: (0, 168)}, 58: {0: (1, {'@': 82}), 2: (1, {'@': 82}), 3: (1, {'@': 82}), 4: (1, {'@': 82}), 5: (1, {'@': 82})}, 59: {0: (0, 21)}, 60: {66: (0, 106), 2: (0, 108), 0: (1, {'@': 76}), 5: (1, {'@': 76})}, 61: {0: (1, {'@': 95}), 2: (1, {'@': 95}), 3: (1, {'@': 95}), 4: (1, {'@': 95}), 5: (1, {'@': 95})}, 62: {8: (0, 163), 67: (0, 71)}, 63: {0: (0, 135)}, 64: {68: (0, 148)}, 65: {0: (0, 82)}, 66: {0: (1, {'@': 100})}, 67: {0: (1, {'@': 88}), 2: (1, {'@': 88}), 3: (1, {'@': 88}), 4: (1, {'@': 88}), 5: (1, {'@': 88})}, 68: {0: (0, 1), 1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 18: (0, 177), 19: (0, 174), 20: (0, 3), 39: (0, 45), 49: (0, 54), 40: (0, 40), 6: (0, 75), 9: (0, 29), 38: (0, 0), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 69: {14: (0, 87)}, 70: {0: (1, {'@': 72}), 2: (1, {'@': 72}), 3: (1, {'@': 72}), 4: (1, {'@': 72}), 5: (1, {'@': 72})}, 71: {3: (1, {'@': 129}), 2: (1, {'@': 129})}, 72: {0: (0, 103)}, 73: {0: (1, {'@': 97})}, 74: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 18: (0, 102), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 75: {68: (0, 175)}, 76: {3: (0, 132)}, 77: {61: (0, 20), 11: (0, 189), 62: (0, 27), 8: (0, 25), 59: (0, 28), 12: (0, 44), 1: (0, 35), 60: (0, 199), 63: (0, 136), 64: (0, 127)}, 78: {0: (1, {'@': 117}), 2: (1, {'@': 117}), 3: (1, {'@': 117})}, 79: {69: (0, 11), 3: (0, 49), 2: (0, 62)}, 80: {70: (0, 38), 0: (0, 78), 2: (0, 43)}, 81: {0: (1, {'@': 55}), 2: (1, {'@': 55}), 3: (1, {'@': 55}), 4: (1, {'@': 55}), 5: (1, {'@': 55})}, 82: {0: (1, {'@': 71}), 2: (1, {'@': 71}), 3: (1, {'@': 71}), 4: (1, {'@': 71}), 5: (1, {'@': 71})}, 83: {0: (0, 67)}, 84: {0: (0, 70), 2: (0, 24)}, 85: {0: (0, 171)}, 86: {0: (0, 39)}, 87: {13: (0, 173)}, 88: {0: (1, {'@': 91}), 2: (1, {'@': 91}), 3: (1, {'@': 91}), 4: (1, {'@': 91}), 5: (1, {'@': 91})}, 89: {8: (0, 163), 67: (0, 162)}, 90: {0: (1, {'@': 127}), 2: (1, {'@': 127})}, 91: {0: (1, {'@': 108}), 2: (1, {'@': 108}), 3: (1, {'@': 108}), 4: (1, {'@': 108}), 5: (1, {'@': 108})}, 92: {13: (0, 183)}, 93: {65: (1, {'@': 104})}, 94: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 18: (0, 177), 19: (0, 174), 20: (0, 3), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 38: (0, 0), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 49: (0, 34), 48: (0, 159), 50: (0, 133), 14: (0, 53), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 95: {14: (0, 184)}, 96: {0: (1, {'@': 38}), 2: (1, {'@': 38}), 3: (1, {'@': 38}), 4: (1, {'@': 38}), 5: (1, {'@': 38})}, 97: {0: (1, {'@': 105}), 2: (1, {'@': 105}), 3: (1, {'@': 105}), 4: (1, {'@': 105}), 5: (1, {'@': 105})}, 98: {65: (0, 150)}, 99: {0: (1, {'@': 121}), 2: (1, {'@': 121}), 3: (1, {'@': 121})}, 100: {71: (0, 169), 1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 33: (0, 64), 6: (0, 75), 9: (0, 29), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 18: (0, 101), 31: (0, 120), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 34: (0, 186)}, 101: {4: (1, {'@': 35})}, 102: {3: (1, {'@': 85}), 2: (1, {'@': 85})}, 103: {0: (1, {'@': 67}), 2: (1, {'@': 67}), 3: (1, {'@': 67}), 4: (1, {'@': 67}), 5: (1, {'@': 67})}, 104: {0: (0, 178)}, 105: {14: (0, 194)}, 106: {2: (0, 115), 0: (1, {'@': 75}), 5: (1, {'@': 75})}, 107: {0: (1, {'@': 68}), 2: (1, {'@': 68}), 3: (1, {'@': 68}), 4: (1, {'@': 68}), 5: (1, {'@': 68})}, 108: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 18: (0, 187), 31: (0, 120), 34: (0, 186), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 109: {3: (1, {'@': 125}), 2: (1, {'@': 125})}, 110: {2: (0, 172)}, 111: {5: (0, 117)}, 112: {0: (0, 61)}, 113: {11: (0, 30)}, 114: {0: (1, {'@': 93}), 2: (1, {'@': 93}), 3: (1, {'@': 93}), 4: (1, {'@': 93}), 5: (1, {'@': 93})}, 115: {1: (0, 164), 15: (0, 140), 36: (0, 143), 18: (0, 134), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 116: {0: (1, {'@': 52}), 2: (1, {'@': 52}), 3: (1, {'@': 52}), 4: (1, {'@': 52}), 5: (1, {'@': 52})}, 117: {0: (1, {'@': 73}), 2: (1, {'@': 73}), 3: (1, {'@': 73}), 4: (1, {'@': 73}), 5: (1, {'@': 73})}, 118: {2: (0, 158), 0: (0, 142)}, 119: {12: (0, 66), 11: (0, 189)}, 120: {1: (0, 68)}, 121: {11: (0, 189), 12: (0, 73)}, 122: {0: (1, {'@': 107}), 2: (1, {'@': 107}), 3: (1, {'@': 107}), 4: (1, {'@': 107}), 5: (1, {'@': 107})}, 123: {1: (0, 16), 65: (1, {'@': 104})}, 124: {13: (0, 156)}, 125: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 33: (0, 64), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 25: (0, 116), 26: (0, 96), 44: (0, 131), 18: (0, 84), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 34: (0, 186)}, 126: {65: (1, {'@': 103})}, 127: {0: (1, {'@': 110}), 2: (1, {'@': 110}), 3: (1, {'@': 110})}, 128: {0: (1, {'@': 51}), 2: (1, {'@': 51}), 3: (1, {'@': 51}), 4: (1, {'@': 51}), 5: (1, {'@': 51})}, 129: {6: (0, 85)}, 130: {0: (0, 196), 2: (0, 105)}, 131: {0: (1, {'@': 36}), 2: (1, {'@': 36}), 3: (1, {'@': 36}), 4: (1, {'@': 36}), 5: (1, {'@': 36})}, 132: {0: (1, {'@': 81}), 2: (1, {'@': 81}), 3: (1, {'@': 81}), 4: (1, {'@': 81}), 5: (1, {'@': 81})}, 133: {0: (1, {'@': 43}), 2: (1, {'@': 43}), 3: (1, {'@': 43}), 4: (1, {'@': 43}), 5: (1, {'@': 43})}, 134: {0: (1, {'@': 124}), 5: (1, {'@': 124}), 2: (1, {'@': 124})}, 135: {0: (1, {'@': 79}), 2: (1, {'@': 79}), 3: (1, {'@': 79}), 4: (1, {'@': 79}), 5: (1, {'@': 79})}, 136: {0: (1, {'@': 113}), 2: (1, {'@': 113}), 3: (1, {'@': 113})}, 137: {0: (1, {'@': 45}), 2: (1, {'@': 45}), 3: (1, {'@': 45}), 4: (1, {'@': 45}), 5: (1, {'@': 45})}, 138: {11: (0, 189), 12: (0, 83)}, 139: {0: (0, 81)}, 140: {1: (0, 125)}, 141: {0: (1, {'@': 58}), 1: (1, {'@': 58}), 2: (1, {'@': 58}), 3: (1, {'@': 58}), 4: (1, {'@': 58}), 5: (1, {'@': 58})}, 142: {0: (1, {'@': 78}), 2: (1, {'@': 78}), 3: (1, {'@': 78}), 4: (1, {'@': 78}), 5: (1, {'@': 78})}, 143: {1: (0, 192)}, 144: {13: (0, 56)}, 145: {0: (1, {'@': 69}), 2: (1, {'@': 69}), 3: (1, {'@': 69}), 4: (1, {'@': 69}), 5: (1, {'@': 69})}, 146: {0: (1, {'@': 42}), 2: (1, {'@': 42}), 3: (1, {'@': 42}), 4: (1, {'@': 42}), 5: (1, {'@': 42})}, 147: {0: (1, {'@': 46}), 2: (1, {'@': 46}), 3: (1, {'@': 46}), 4: (1, {'@': 46}), 5: (1, {'@': 46})}, 148: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 18: (0, 161), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 149: {10: (0, 109), 8: (0, 46), 7: (0, 52), 9: (0, 47)}, 150: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 18: (0, 41), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 151: {13: (0, 48)}, 152: {0: (1, {'@': 92}), 2: (1, {'@': 92}), 3: (1, {'@': 92}), 4: (1, {'@': 92}), 5: (1, {'@': 92})}, 153: {0: (1, {'@': 40}), 2: (1, {'@': 40}), 3: (1, {'@': 40}), 4: (1, {'@': 40}), 5: (1, {'@': 40})}, 154: {11: (0, 189), 12: (0, 36)}, 155: {0: (0, 118)}, 156: {11: (0, 189), 12: (0, 86)}, 157: {2: (0, 5), 3: (1, {'@': 83})}, 158: {14: (0, 124)}, 159: {0: (1, {'@': 59}), 1: (1, {'@': 59}), 2: (1, {'@': 59}), 3: (1, {'@': 59}), 4: (1, {'@': 59}), 5: (1, {'@': 59})}, 160: {1: (0, 19)}, 161: {0: (1, {'@': 63}), 2: (1, {'@': 63}), 3: (1, {'@': 63}), 4: (1, {'@': 63}), 5: (1, {'@': 63})}, 162: {3: (1, {'@': 130}), 2: (1, {'@': 130})}, 163: {65: (0, 176)}, 164: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 18: (0, 110), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 165: {0: (1, {'@': 60}), 2: (1, {'@': 60}), 3: (1, {'@': 60}), 4: (1, {'@': 60}), 5: (1, {'@': 60})}, 166: {0: (1, {'@': 48}), 2: (1, {'@': 48}), 3: (1, {'@': 48}), 4: (1, {'@': 48}), 5: (1, {'@': 48})}, 167: {0: (1, {'@': 41}), 2: (1, {'@': 41}), 3: (1, {'@': 41}), 4: (1, {'@': 41}), 5: (1, {'@': 41})}, 168: {14: (0, 13)}, 169: {}, 170: {2: (0, 95), 0: (0, 88)}, 171: {0: (1, {'@': 66}), 2: (1, {'@': 66}), 3: (1, {'@': 66}), 4: (1, {'@': 66}), 5: (1, {'@': 66})}, 172: {14: (0, 92)}, 173: {12: (0, 2), 11: (0, 189)}, 174: {0: (1, {'@': 47}), 2: (1, {'@': 47}), 3: (1, {'@': 47}), 4: (1, {'@': 47}), 5: (1, {'@': 47})}, 175: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 18: (0, 185), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 176: {59: (0, 18), 61: (0, 20), 11: (0, 189), 62: (0, 27), 8: (0, 25), 12: (0, 44), 1: (0, 35), 60: (0, 199), 63: (0, 136), 64: (0, 127)}, 177: {2: (0, 94), 0: (1, {'@': 98})}, 178: {0: (1, {'@': 94}), 2: (1, {'@': 94}), 3: (1, {'@': 94}), 4: (1, {'@': 94}), 5: (1, {'@': 94})}, 179: {13: (0, 10)}, 180: {1: (0, 4), 0: (1, {'@': 65}), 2: (1, {'@': 65}), 3: (1, {'@': 65}), 4: (1, {'@': 65}), 5: (1, {'@': 65})}, 181: {1: (0, 164), 15: (0, 140), 36: (0, 143), 18: (0, 60), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 5: (0, 23), 38: (0, 0), 39: (0, 45), 40: (0, 40), 6: (0, 75), 9: (0, 29), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 56: (0, 111), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 182: {13: (0, 154)}, 183: {11: (0, 189), 12: (0, 37)}, 184: {13: (0, 8)}, 185: {0: (1, {'@': 62}), 2: (1, {'@': 62}), 3: (1, {'@': 62}), 4: (1, {'@': 62}), 5: (1, {'@': 62})}, 186: {0: (1, {'@': 49}), 2: (1, {'@': 49}), 3: (1, {'@': 49}), 4: (1, {'@': 49}), 5: (1, {'@': 49})}, 187: {0: (1, {'@': 123}), 5: (1, {'@': 123}), 2: (1, {'@': 123})}, 188: {0: (1, {'@': 70}), 2: (1, {'@': 70}), 3: (1, {'@': 70}), 4: (1, {'@': 70}), 5: (1, {'@': 70})}, 189: {67: (0, 79), 3: (0, 99), 8: (0, 163)}, 190: {0: (1, {'@': 89}), 2: (1, {'@': 89}), 3: (1, {'@': 89}), 4: (1, {'@': 89}), 5: (1, {'@': 89})}, 191: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 18: (0, 188), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 192: {72: (0, 151)}, 193: {3: (0, 57)}, 194: {13: (0, 7)}, 195: {14: (0, 144)}, 196: {0: (1, {'@': 80}), 2: (1, {'@': 80}), 3: (1, {'@': 80}), 4: (1, {'@': 80}), 5: (1, {'@': 80})}, 197: {1: (0, 195), 0: (1, {'@': 56}), 2: (1, {'@': 56}), 3: (1, {'@': 56}), 4: (1, {'@': 56}), 5: (1, {'@': 56})}, 198: {0: (1, {'@': 39}), 2: (1, {'@': 39}), 3: (1, {'@': 39}), 4: (1, {'@': 39}), 5: (1, {'@': 39})}, 199: {0: (1, {'@': 114}), 2: (1, {'@': 114}), 3: (1, {'@': 114})}, 200: {0: (1, {'@': 37}), 2: (1, {'@': 37}), 3: (1, {'@': 37}), 4: (1, {'@': 37}), 5: (1, {'@': 37})}, 201: {2: (0, 17), 0: (1, {'@': 101})}}, 'start_states': {'start': 100}, 'end_states': {'start': 169}}, 'options': {'debug': False, 'keep_all_tokens': False, 'tree_class': None, 'cache': False, 'postlex': None, 'parser': 'lalr', 'lexer': 'contextual', 'transformer': None, 'start': ['start'], 'priority': 'normal', 'ambiguity': 'auto', 'regex': False, 'propagate_positions': False, 'lexer_callbacks': {}, 'maybe_placeholders': False, 'edit_terminals': None, 'g_regex_flags': 0, 'use_bytes': False, 'import_paths': [], 'source_path': None}, '__type__': 'ParsingFrontend'}, 'rules': [{'@': 35}, {'@': 36}, {'@': 37}, {'@': 38}, {'@': 39}, {'@': 40}, {'@': 41}, {'@': 42}, {'@': 43}, {'@': 44}, {'@': 45}, {'@': 46}, {'@': 47}, {'@': 48}, {'@': 49}, {'@': 50}, {'@': 51}, {'@': 52}, {'@': 53}, {'@': 54}, {'@': 55}, {'@': 56}, {'@': 57}, {'@': 58}, {'@': 59}, {'@': 60}, {'@': 61}, {'@': 62}, {'@': 63}, {'@': 64}, {'@': 65}, {'@': 66}, {'@': 67}, {'@': 68}, {'@': 69}, {'@': 70}, {'@': 71}, {'@': 72}, {'@': 73}, {'@': 74}, {'@': 75}, {'@': 76}, {'@': 77}, {'@': 78}, {'@': 79}, {'@': 80}, {'@': 81}, {'@': 82}, {'@': 83}, {'@': 84}, {'@': 85}, {'@': 86}, {'@': 87}, {'@': 88}, {'@': 89}, {'@': 90}, {'@': 91}, {'@': 92}, {'@': 93}, {'@': 94}, {'@': 95}, {'@': 96}, {'@': 97}, {'@': 98}, {'@': 99}, {'@': 100}, {'@': 101}, {'@': 102}, {'@': 103}, {'@': 104}, {'@': 105}, {'@': 106}, {'@': 107}, {'@': 108}, {'@': 109}, {'@': 110}, {'@': 111}, {'@': 112}, {'@': 113}, {'@': 114}, {'@': 115}, {'@': 116}, {'@': 117}, {'@': 118}, {'@': 119}, {'@': 120}, {'@': 121}, {'@': 122}, {'@': 123}, {'@': 124}, {'@': 125}, {'@': 126}, {'@': 127}, {'@': 128}, {'@': 129}, {'@': 130}], 'options': {'debug': False, 'keep_all_tokens': False, 'tree_class': None, 'cache': False, 'postlex': None, 'parser': 'lalr', 'lexer': 'contextual', 'transformer': None, 'start': ['start'], 'priority': 'normal', 'ambiguity': 'auto', 'regex': False, 'propagate_positions': False, 'lexer_callbacks': {}, 'maybe_placeholders': False, 'edit_terminals': None, 'g_regex_flags': 0, 'use_bytes': False, 'import_paths': [], 'source_path': None}, '__type__': 'Lark'} ) MEMO = ( -{0: {'name': 'INT', 'pattern': {'value': '(?:[0-9])+', 'flags': [], '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 1, '__type__': 'TerminalDef'}, 1: {'name': 'SIGNED_NUMBER', 'pattern': {'value': '(?:(?:\\+|\\-))?(?:(?:(?:[0-9])+(?:e|E)(?:(?:\\+|\\-))?(?:[0-9])+|(?:(?:[0-9])+\\.(?:(?:[0-9])+)?|\\.(?:[0-9])+)(?:(?:e|E)(?:(?:\\+|\\-))?(?:[0-9])+)?)|(?:[0-9])+)', 'flags': [], '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 1, '__type__': 'TerminalDef'}, 2: {'name': 'ESCAPED_STRING', 'pattern': {'value': '".*?(? Date: Sat, 10 Oct 2026 02:28:37 +0200 Subject: [PATCH 04/19] fix: stop ArrayBuilder from crashing on long double complex scalars and from rounding long double scalars --- awkward-cpp/src/python/content.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/awkward-cpp/src/python/content.cpp b/awkward-cpp/src/python/content.cpp index 102231d97a..837571147b 100644 --- a/awkward-cpp/src/python/content.cpp +++ b/awkward-cpp/src/python/content.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "awkward/python/content.h" #include "awkward/python/util.h" @@ -19,6 +20,25 @@ builder_fromiter_iscomplex(const py::handle& obj) { return PyComplex_Check(obj.ptr()); } +// The builder holds real numbers as double and complex numbers as pairs of +// doubles. Where long double is wider than double, a long double value would +// lose digits in it. +void +builder_fromiter_notlongdouble(const py::handle& obj) { + if (std::numeric_limits::digits > std::numeric_limits::digits && + (py::isinstance(obj, py::module::import("numpy").attr("longdouble")) || + py::isinstance(obj, py::module::import("numpy").attr("clongdouble")))) { + throw std::invalid_argument( + std::string("cannot convert ") + + obj.attr("__repr__")().cast() + std::string(" (type ") + + obj.attr("__class__").attr("__name__").cast() + + std::string(") to an array element because an ArrayBuilder holds " + "float64 and complex128 numbers, which have fewer digits. " + "Convert the value with float or complex first, or make " + "the array from a NumPy array") + FILENAME(__LINE__)); + } +} + void builder_datetime(ak::ArrayBuilder& self, const py::handle& obj) { if (py::isinstance(obj)) { @@ -170,8 +190,13 @@ builder_fromiter(ak::ArrayBuilder& self, const py::handle& obj) { self.integer(obj.cast()); } else if (py::isinstance(obj, py::module::import("numpy").attr("floating"))) { + builder_fromiter_notlongdouble(obj); self.real(obj.cast()); } + else if (py::isinstance(obj, py::module::import("numpy").attr("complexfloating"))) { + builder_fromiter_notlongdouble(obj); + self.complex(obj.cast>()); + } else if (py::hasattr(obj, "to_list")) { builder_fromiter(self, obj.attr("to_list")()); } From 7f6c0743b9ae3a74708fba1d0eeb8cc9b28d288a Mon Sep 17 00:00:00 2001 From: Iason Krommydas Date: Sat, 10 Oct 2026 02:28:38 +0200 Subject: [PATCH 05/19] fix: keep long double in ak.covar and ak.corr --- src/awkward/_do.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/awkward/_do.py b/src/awkward/_do.py index a480a20779..c2c20f08a1 100644 --- a/src/awkward/_do.py +++ b/src/awkward/_do.py @@ -240,9 +240,13 @@ def real_numbers_to_float64(layout: Content) -> Content: Data that are not real numbers (complex numbers, date-times, and time differences) are returned as they are, because a cast to float64 would - discard the imaginary part or the units. + discard the imaginary part or the units. So are long double data where + they are wider than float64, because the cast would discard digits. """ - if all(dtype.kind in "biuf" for dtype in _number_dtypes(layout)): + if all( + dtype.kind in "biu" or (dtype.kind == "f" and dtype.itemsize <= 8) + for dtype in _number_dtypes(layout) + ): return layout._numbers_to_type("float64", False) else: return layout From 23b17127a1c8b27bbb1195abc155ad17e6271792 Mon Sep 17 00:00:00 2001 From: Iason Krommydas Date: Sat, 10 Oct 2026 02:28:40 +0200 Subject: [PATCH 06/19] fix: apply float formatters to float16 everywhere and to long double where NumPy has no float128 --- src/awkward/prettyprint.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/awkward/prettyprint.py b/src/awkward/prettyprint.py index df9a29c05a..06193237c2 100644 --- a/src/awkward/prettyprint.py +++ b/src/awkward/prettyprint.py @@ -313,12 +313,12 @@ def _find_formatter_impl(self, cls: type) -> FormatterType: return self._formatters["int"] except KeyError: return self._formatters.get("int_kind", str) - elif issubclass(cls, (np.float64, np.float32)): + elif issubclass(cls, (np.float64, np.float32, np.float16)): try: return self._formatters["float"] except KeyError: return self._formatters.get("float_kind", self._format_real) - elif hasattr(np, "float128") and issubclass(cls, np.float128): + elif issubclass(cls, np.longdouble): try: return self._formatters["longfloat"] except KeyError: @@ -328,7 +328,7 @@ def _find_formatter_impl(self, cls: type) -> FormatterType: return self._formatters["complexfloat"] except KeyError: return self._formatters.get("complex_kind", self._format_complex) - elif hasattr(np, "complex256") and issubclass(cls, np.complex256): + elif issubclass(cls, np.clongdouble): try: return self._formatters["longcomplexfloat"] except KeyError: From ebeb841dfe6468b08344e070bef43a63d4a79d45 Mon Sep 17 00:00:00 2001 From: Iason Krommydas Date: Sat, 10 Oct 2026 02:28:42 +0200 Subject: [PATCH 07/19] fix: raise a TypeError for long double forms in Awkward 1 pickles where NumPy has no float128 --- src/awkward/forms/numpyform.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/awkward/forms/numpyform.py b/src/awkward/forms/numpyform.py index 0a3b59968f..fea9e9f819 100644 --- a/src/awkward/forms/numpyform.py +++ b/src/awkward/forms/numpyform.py @@ -212,13 +212,13 @@ def __setstate__(self, state): elif format == "d": dtype = np.dtype(np.float64) elif format == "g": - dtype = np.dtype(np.float128) + dtype = ak.types.numpytype.primitive_to_dtype("float128") elif format == "Zf": dtype = np.dtype(np.complex64) elif format == "Zd": dtype = np.dtype(np.complex128) elif format == "Zg": - dtype = np.dtype(np.complex256) + dtype = ak.types.numpytype.primitive_to_dtype("complex256") else: dtype = np.dtype(format) # datetime or timedelta with units From 166f7e77b106501f7e11b429f1046de19af63e32 Mon Sep 17 00:00:00 2001 From: Iason Krommydas Date: Sat, 10 Oct 2026 02:28:44 +0200 Subject: [PATCH 08/19] feat: raise clear errors for float16 values and long double arrays in Numba --- src/awkward/_connect/numba/layout.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/awkward/_connect/numba/layout.py b/src/awkward/_connect/numba/layout.py index 09c321641d..3d87693762 100644 --- a/src/awkward/_connect/numba/layout.py +++ b/src/awkward/_connect/numba/layout.py @@ -550,10 +550,20 @@ def regularize_atval(context, builder, viewproxy, attype, atval, wrapneg, checkb return castint(context, builder, atval.type, numba.intp, atval) +def numba_type_of_primitive(primitive): + if primitive in ("float128", "complex256"): + raise TypeError( + f"Numba has no long double type, so arrays of {primitive} cannot be " + "passed to Numba-compiled functions. Convert them with " + "ak.values_astype first" + ) + return numba.from_dtype(ak.types.numpytype.primitive_to_dtype(primitive)) + + class NumpyArrayType(ContentType, ak._lookup.NumpyLookup): @classmethod def from_form(cls, form): - t = numba.from_dtype(ak.types.numpytype.primitive_to_dtype(form.primitive)) + t = numba_type_of_primitive(form.primitive) arraytype = numba.types.Array(t, 1, "C") return NumpyArrayType(arraytype, form.parameters) @@ -568,6 +578,13 @@ def has_field(self, key): return False def getitem_at(self, viewtype): + if self.arraytype.dtype == numba.types.float16: + # such arrays can be passed through and sliced, but not read + raise TypeError( + "Numba cannot read float16 values. Convert them with " + "ak.values_astype(array, np.float32) before calling the " + "Numba-compiled function" + ) return self.arraytype.dtype def lower_getitem_at( @@ -1703,7 +1720,7 @@ def inner_dtype_of_form(form): return None elif isinstance(form, ak.forms.NumpyForm): - return numba.from_dtype(ak.types.numpytype.primitive_to_dtype(form.primitive)) + return numba_type_of_primitive(form.primitive) elif isinstance(form, ak.forms.EmptyForm): return numba.types.float64 From 5cc4f2aa2e7022c3dafa3831c560a83cd91b00e5 Mon Sep 17 00:00:00 2001 From: Iason Krommydas Date: Sat, 10 Oct 2026 02:28:45 +0200 Subject: [PATCH 09/19] feat: pass long double to and from C++ and raise a clear error for float16 --- header-only/layout-builder/awkward/utils.h | 7 ++ header-only/tests/CMakeLists.txt | 4 + .../test_4259-layout-builder-long-double.cpp | 82 +++++++++++++++++++ src/awkward/_connect/cling.py | 8 ++ .../_connect/rdataframe/from_rdataframe.py | 2 + 5 files changed, 103 insertions(+) create mode 100644 header-only/tests/test_4259-layout-builder-long-double.cpp diff --git a/header-only/layout-builder/awkward/utils.h b/header-only/layout-builder/awkward/utils.h index dd122960db..1f3ce1f3e8 100644 --- a/header-only/layout-builder/awkward/utils.h +++ b/header-only/layout-builder/awkward/utils.h @@ -64,6 +64,13 @@ namespace awkward { else if (std::is_same_v>) { return "complex128"; } + else if (std::is_same_v) { + // NumPy names long double by its size, which depends on the platform. + return "float" + std::to_string(8 * sizeof(T)); + } + else if (std::is_same_v>) { + return "complex" + std::to_string(8 * sizeof(T)); + } // std::is_integral_v and sizeof(T) not in (1, 2, 4, 8) can get here. // Don't connect this line with the above as an 'else' clause. diff --git a/header-only/tests/CMakeLists.txt b/header-only/tests/CMakeLists.txt index a29a1e091e..af9d6a3532 100644 --- a/header-only/tests/CMakeLists.txt +++ b/header-only/tests/CMakeLists.txt @@ -20,6 +20,8 @@ addtest_nolibs(test_4087-bitmasked-growablebuffer test_4087-bitmasked-growablebuffer.cpp) addtest_nolibs(test_4088-layoutbuilder-form-fixes test_4088-layoutbuilder-form-fixes.cpp) +addtest_nolibs(test_4259-layout-builder-long-double + test_4259-layout-builder-long-double.cpp) target_link_libraries(test_1494-layout-builder PRIVATE awkward::layout-builder) target_link_libraries(test_1542-growable-buffer @@ -32,3 +34,5 @@ target_link_libraries(test_4087-bitmasked-growablebuffer PRIVATE awkward::layout-builder) target_link_libraries(test_4088-layoutbuilder-form-fixes PRIVATE awkward::layout-builder) +target_link_libraries(test_4259-layout-builder-long-double + PRIVATE awkward::layout-builder) diff --git a/header-only/tests/test_4259-layout-builder-long-double.cpp b/header-only/tests/test_4259-layout-builder-long-double.cpp new file mode 100644 index 0000000000..58a1c1344f --- /dev/null +++ b/header-only/tests/test_4259-layout-builder-long-double.cpp @@ -0,0 +1,82 @@ +// BSD 3-Clause License; see https://github.com/scikit-hep/awkward/blob/main/LICENSE + +// The form of a builder of long double values names the primitive as NumPy +// does, by its size. The size depends on the platform. + +#include "awkward/LayoutBuilder.h" + +#include +#include +#include +#include +#include + +template +using NumpyBuilder = awkward::LayoutBuilder::Numpy; + +void +test_type_to_name() { + assert(awkward::type_to_name() == + "float" + std::to_string(8 * sizeof(long double))); + assert(awkward::type_to_name>() == + "complex" + std::to_string(16 * sizeof(long double))); + + // the other names do not change + assert(awkward::type_to_name() == "float32"); + assert(awkward::type_to_name() == "float64"); + assert(awkward::type_to_name>() == "complex128"); +} + +void +test_Numpy_long_double() { + NumpyBuilder builder; + builder.append(1.1L); + builder.append(2.2L); + assert(builder.length() == 2); + + std::string error; + assert(builder.is_valid(error) == true); + + assert(builder.form() == + "{ " + "\"class\": \"NumpyArray\", " + "\"primitive\": \"" + awkward::type_to_name() + "\", " + "\"form_key\": \"node0\" " + "}"); + + std::map names_nbytes = {}; + builder.buffer_nbytes(names_nbytes); + assert(names_nbytes["node0-data"] == 2 * sizeof(long double)); + + std::map buffers = {}; + buffers["node0-data"] = malloc(names_nbytes["node0-data"]); + builder.to_buffers(buffers); + + long double* data = (long double*)buffers["node0-data"]; + assert(data[0] == 1.1L); + assert(data[1] == 2.2L); + + free(buffers["node0-data"]); +} + +void +test_Numpy_complex_long_double() { + NumpyBuilder> builder; + builder.append({1.1L, 0.1L}); + assert(builder.length() == 1); + + assert(builder.form() == + "{ " + "\"class\": \"NumpyArray\", " + "\"primitive\": \"" + awkward::type_to_name>() + "\", " + "\"form_key\": \"node0\" " + "}"); +} + +int +main(int /* argc */, char** /* argv */) { + test_type_to_name(); + test_Numpy_long_double(); + test_Numpy_complex_long_double(); + return 0; +} diff --git a/src/awkward/_connect/cling.py b/src/awkward/_connect/cling.py index 0783e1c4b9..06b12fee3a 100644 --- a/src/awkward/_connect/cling.py +++ b/src/awkward/_connect/cling.py @@ -592,6 +592,12 @@ def class_type(self): return f"NumpyArray_{self.primitive}_{self.class_type_suffix((self, self.flatlist_as_rvec))}" def value_type(self): + if self.primitive == "float16": + raise TypeError( + "C++ has no half precision type, so arrays of float16 cannot be " + "used from C++. Convert them with ak.values_astype(array, " + "np.float32) first" + ) return { "bool": "bool", "int8": "int8_t", @@ -604,8 +610,10 @@ def value_type(self): "uint64": "uint64_t", "float32": "float", "float64": "double", + "float128": "long double", "complex64": "std::complex", "complex128": "std::complex", + "complex256": "std::complex", "datetime64": "std::time_point", "timedelta64": "std::duration", }[self.primitive] diff --git a/src/awkward/_connect/rdataframe/from_rdataframe.py b/src/awkward/_connect/rdataframe/from_rdataframe.py index 03aedc514b..13bd08a27a 100644 --- a/src/awkward/_connect/rdataframe/from_rdataframe.py +++ b/src/awkward/_connect/rdataframe/from_rdataframe.py @@ -29,8 +29,10 @@ "uint64": "uint64_t", "float32": "float", "float64": "double", + "float128": "long double", "complex64": "std::complex", "complex128": "std::complex", + "complex256": "std::complex", "datetime64": "std::time_t", "timedelta64": "std::difftime", } From c18ec9ec63ee597aa5f7dd803354d313083e2790 Mon Sep 17 00:00:00 2001 From: Iason Krommydas Date: Sat, 10 Oct 2026 02:28:47 +0200 Subject: [PATCH 10/19] feat: raise clear errors when Arrow or JSON cannot hold a type and convert long double where it is double --- src/awkward/contents/numpyarray.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/awkward/contents/numpyarray.py b/src/awkward/contents/numpyarray.py index 2febb94251..a261583749 100644 --- a/src/awkward/contents/numpyarray.py +++ b/src/awkward/contents/numpyarray.py @@ -1198,6 +1198,10 @@ def _to_arrow( ) (nparray,) = maybe_materialize(self._raw(numpy)) + if nparray.dtype.type is np.longdouble and nparray.dtype == np.float64: + # long double is the same as double on this platform + nparray = nparray.view(np.float64) + if ( np.issubdtype(nparray.dtype, np.datetime64) and nparray.dtype.name == "datetime64[D]" @@ -1205,7 +1209,14 @@ def _to_arrow( nparray = nparray.astype("timedelta64[D]").astype(np.int32) storage_type = pyarrow.date32() else: - storage_type = pyarrow.from_numpy_dtype(nparray.dtype) + try: + storage_type = pyarrow.from_numpy_dtype(nparray.dtype) + except pyarrow.ArrowNotImplementedError: + raise TypeError( + f"Arrow has no type for {nparray.dtype.name} values. Convert " + "them with ak.values_astype before converting the array to " + "Arrow" + ) from None if issubclass(nparray.dtype.type, (bool, np.bool_)): nparray = numpy.packbits(nparray, bitorder="little") @@ -1337,7 +1348,19 @@ def _to_list(self, behavior, json_conversions): backend=self._backend, )._to_list(behavior, json_conversions) - out = self._data.tolist() + data = self._data + if json_conversions is not None and data.dtype.type is np.longdouble: + # JSON numbers are written from Python floats, which are doubles + if data.dtype != np.float64: + raise TypeError( + f"{data.dtype.name} values cannot be written as JSON without " + "losing digits. Convert them with ak.values_astype(array, " + "np.float64) first" + ) + # long double is the same as double on this platform + (data,) = maybe_materialize(data) + data = data.view(np.float64) + out = data.tolist() if json_conversions is not None: nan_string = json_conversions["nan_string"] From 9317d3f8405aeca868022096a013c6dc37eb368c Mon Sep 17 00:00:00 2001 From: Iason Krommydas Date: Sat, 10 Oct 2026 02:28:49 +0200 Subject: [PATCH 11/19] test: cover float16 and long double across reducers, sorting, type strings, builders, printing and conversions --- tests/test_4259_float16_and_longdouble.py | 371 ++++++++++++++++++++++ 1 file changed, 371 insertions(+) create mode 100644 tests/test_4259_float16_and_longdouble.py diff --git a/tests/test_4259_float16_and_longdouble.py b/tests/test_4259_float16_and_longdouble.py new file mode 100644 index 0000000000..cbdd506078 --- /dev/null +++ b/tests/test_4259_float16_and_longdouble.py @@ -0,0 +1,371 @@ +# BSD 3-Clause License; see https://github.com/scikit-hep/awkward/blob/main/LICENSE + +from __future__ import annotations + +import io +import json + +import numpy as np +import pytest + +import awkward as ak + +# long double has 80 or 128 bits on Linux and is the same as double on +# macOS arm64 and Windows +LONGDOUBLE_IS_WIDER = np.finfo(np.longdouble).nmant > np.finfo(np.float64).nmant + +REDUCERS = [ + (ak.sum, np.sum), + (ak.prod, np.prod), + (ak.min, np.min), + (ak.max, np.max), + (ak.argmin, np.argmin), + (ak.argmax, np.argmax), + (ak.any, np.any), + (ak.all, np.all), + (ak.count_nonzero, np.count_nonzero), +] + + +def values(dtype): + rng = np.random.default_rng(4259) + out = rng.integers(1, 5, size=(50, 6)) + rng.normal(size=(50, 6)) + if np.dtype(dtype).kind == "c": + out = out + 1j * rng.integers(0, 3, size=(50, 6)) + return out.astype(dtype) + + +@pytest.mark.parametrize("dtype", [np.float16, np.longdouble, np.clongdouble]) +@pytest.mark.parametrize("ak_reducer, np_reducer", REDUCERS) +def test_reducers(dtype, ak_reducer, np_reducer): + data = values(dtype) + array = ak.from_regular(ak.Array(data)) + + result = ak.to_numpy(ak_reducer(array, axis=1)) + expected = np_reducer(data, axis=1) + assert result.dtype == expected.dtype + if ak_reducer in (ak.sum, ak.prod): + # the kernels and NumPy do not add and multiply in the same order + assert np.allclose( + result, expected, rtol=1e-2 if dtype is np.float16 else 1e-12 + ) + else: + assert np.array_equal(result, expected) + + +@pytest.mark.parametrize("dtype", [np.float16, np.longdouble]) +def test_sort_and_argsort(dtype): + data = values(dtype) + array = ak.from_regular(ak.Array(data)) + + result = ak.to_numpy(ak.sort(array, axis=1)) + assert result.dtype == np.dtype(dtype) + assert np.array_equal(result, np.sort(data, axis=1)) + + result = ak.to_numpy(ak.sort(array, axis=1, ascending=False)) + assert np.array_equal(result, np.sort(data, axis=1)[:, ::-1]) + + result = ak.to_numpy(ak.argsort(array, axis=1, stable=True)) + assert np.array_equal(result, np.argsort(data, axis=1, kind="stable")) + + +def test_float16_with_missing_values(): + array = ak.Array(np.array([[3, 1, 2], [5, 4, 6]], dtype=np.float16)) + array = ak.mask(ak.from_regular(array), [[True, False, True], [True, True, True]]) + + assert ak.sum(array, axis=1).to_list() == [5, 15] + assert ak.sort(array, axis=1).to_list() == [[2, 3, None], [4, 5, 6]] + assert ak.argmax(array, axis=1).to_list() == [0, 2] + assert str(ak.sort(array, axis=1).type) == "2 * var * ?float16" + + +def test_float16_axis_none(): + data = values(np.float16)[:2] + array = ak.Array(data) + + for ak_reducer, np_reducer in REDUCERS: + result = ak_reducer(array, axis=None) + expected = np_reducer(data) + assert np.asarray(result).dtype == np.asarray(expected).dtype + assert result == pytest.approx(expected, rel=1e-2) + + +def test_float16_typetracer(): + array = ak.from_regular(ak.Array(values(np.float16))) + tracer = ak.to_backend(array, "typetracer") + + for function in (ak.sum, ak.min, ak.argmax, ak.any, ak.sort, ak.argsort): + assert function(tracer, axis=1).type == function(array, axis=1).type + + +def test_float16_totals_are_rounded_once_as_in_numpy(): + # 60000 + 60000 does not fit in float16, the total does + data = np.array([[60000, 60000, -60000]], dtype=np.float16) + array = ak.from_regular(ak.Array(data)) + assert ak.to_numpy(ak.sum(array, axis=1))[0] == np.sum(data) == 60000 + + # the same for 300 * 300 + data = np.array([[300, 300, 0.001]], dtype=np.float16) + array = ak.from_regular(ak.Array(data)) + assert ak.to_numpy(ak.prod(array, axis=1))[0] == np.prod(data) + assert np.isfinite(np.prod(data)) + + +@pytest.mark.skipif( + not LONGDOUBLE_IS_WIDER, + reason="long double is not wider than double on this platform", +) +def test_longdouble_keeps_its_precision(): + # these values are all equal to 1 when they are rounded to float64 + one = np.longdouble(1) + eps = np.finfo(np.longdouble).eps + data = np.array([[one + 2 * eps, one, one + eps, one + 3 * eps]]) + assert len(set(data.astype(np.float64).ravel().tolist())) == 1 + array = ak.from_regular(ak.Array(data)) + + assert ak.to_numpy(ak.min(array, axis=1))[0] == one + assert ak.to_numpy(ak.max(array, axis=1))[0] == one + 3 * eps + assert ak.to_numpy(ak.argmin(array, axis=1))[0] == 1 + assert ak.to_numpy(ak.argmax(array, axis=1))[0] == 3 + assert np.array_equal(ak.to_numpy(ak.sort(array, axis=1)), np.sort(data, axis=1)) + assert ak.to_numpy(ak.argsort(array, axis=1)).tolist() == [[1, 2, 0, 3]] + assert ak.to_numpy(ak.sum(array, axis=1))[0] == np.sum(data) + + as_complex = ak.from_regular(ak.Array(data.astype(np.clongdouble))) + assert ak.to_numpy(ak.max(as_complex, axis=1))[0] == one + 3 * eps + assert ak.to_numpy(ak.sum(as_complex, axis=1))[0] == np.sum(data) + + +@pytest.mark.parametrize("dtype", [np.complex64, np.complex128, np.clongdouble]) +def test_complex_numbers_cannot_be_sorted(dtype): + array = ak.from_regular(ak.Array(values(dtype))) + + with pytest.raises(ValueError, match=r"cannot sort \(ak\.sort\) values of"): + ak.sort(array, axis=1) + with pytest.raises(ValueError, match=r"cannot sort \(ak\.argsort\) values of"): + ak.argsort(array, axis=1) + with pytest.raises(ValueError, match="cannot find the unique values of"): + ak._do.unique(array.layout, axis=-1) + + +@pytest.mark.parametrize("dtype", [np.float16, np.longdouble, np.clongdouble]) +def test_type_strings_can_be_parsed(dtype): + array = ak.from_regular(ak.Array(values(dtype))) + + assert ak.types.from_datashape(str(array.type), highlevel=True) == array.type + + name = np.dtype(dtype).name + as_option = ak.enforce_type(array, f"var * ?{name}") + assert str(as_option.type) == f"50 * var * ?{name}" + assert ak.to_numpy(ak.flatten(as_option)).dtype == np.dtype(dtype) + + +def test_enforce_type_to_float16(): + array = ak.Array(np.array([1.5, 2.5], dtype=np.float32)) + + result = ak.enforce_type(array, "float16") + assert str(result.type) == "2 * float16" + assert result.to_list() == [1.5, 2.5] + + +def test_covar_and_corr_keep_long_double(): + x = ak.Array(np.array([[1, 2, 4, 8]], dtype=np.longdouble)) + y = ak.Array(np.array([[1, 3, 2, 9]], dtype=np.longdouble)) + expected = np.cov(np.asarray(x[0]), np.asarray(y[0]), bias=True) + + result = ak.to_numpy(ak.covar(x, y, axis=1)) + assert result.dtype == expected.dtype == np.dtype(np.longdouble) + assert result[0] == pytest.approx(expected[0, 1]) + assert ak.to_numpy(ak.corr(x, y, axis=1)).dtype == np.dtype(np.longdouble) + + # NumPy makes float64 out of the narrower types + x, y = ak.values_astype(x, np.float16), ak.values_astype(y, np.float16) + assert ak.to_numpy(ak.covar(x, y, axis=1)).dtype == np.dtype(np.float64) + + +def test_from_iter_with_numpy_scalars(): + array = ak.from_iter([np.float16(1.5), np.float32(2.5)]) + assert str(array.type) == "2 * float64" + assert array.to_list() == [1.5, 2.5] + + array = ak.from_iter([np.complex64(1 + 2j), np.float16(1.5)]) + assert str(array.type) == "2 * complex128" + assert array.to_list() == [1 + 2j, 1.5 + 0j] + + +@pytest.mark.parametrize("scalar", [np.longdouble(1.5), np.clongdouble(1.5 + 2j)]) +def test_builder_with_long_double_scalars(scalar): + builder = ak.ArrayBuilder() + + if LONGDOUBLE_IS_WIDER: + message = "ArrayBuilder holds float64 and complex128 numbers" + with pytest.raises(ValueError, match=message): + ak.from_iter([scalar]) + with pytest.raises(ValueError, match=message): + builder.append(scalar) + else: + builder.append(scalar) + for array in (ak.from_iter([scalar]), builder.snapshot()): + assert array.to_list() == [scalar] + assert array.layout.dtype.type in (np.float64, np.complex128) + + +@pytest.mark.parametrize( + "dtype, key", + [ + (np.float16, "float"), + (np.float16, "float_kind"), + (np.longdouble, "longfloat"), + (np.longdouble, "float_kind"), + (np.clongdouble, "longcomplexfloat"), + (np.clongdouble, "complex_kind"), + ], +) +def test_show_with_a_formatter(dtype, key): + array = ak.Array(np.array([1.5, 2.5], dtype=dtype)) + + stream = io.StringIO() + array.show(formatter={key: lambda x: ""}, stream=stream) + assert stream.getvalue() == "[,\n ]\n" + + +@pytest.mark.parametrize("dtype", [np.float16, np.longdouble]) +def test_show_with_a_precision(dtype): + array = ak.Array(np.array([1 / 3], dtype=dtype)) + + stream = io.StringIO() + array.show(precision=2, stream=stream) + assert stream.getvalue() == "[0.33]\n" + + +def test_json(): + half = ak.from_regular(ak.Array(values(np.float16))) + assert json.loads(ak.to_json(half)) == half.to_list() + + array = ak.from_regular(ak.Array(values(np.longdouble))) + if LONGDOUBLE_IS_WIDER: + with pytest.raises(TypeError, match="written as JSON without losing"): + ak.to_json(array) + else: + assert json.loads(ak.to_json(array)) == array.to_list() + + array = ak.from_regular(ak.Array(values(np.clongdouble))) + if LONGDOUBLE_IS_WIDER: + with pytest.raises(TypeError, match="written as JSON without losing"): + ak.to_json(array, complex_record_fields=("real", "imag")) + else: + written = json.loads(ak.to_json(array, complex_record_fields=("real", "imag"))) + assert written[0][0] == {"real": array[0, 0].real, "imag": array[0, 0].imag} + + +def test_arrow(): + pytest.importorskip("pyarrow") + + half = ak.from_regular(ak.Array(values(np.float16))) + back = ak.from_arrow(ak.to_arrow(half)) + assert back.type == half.type + assert back.to_list() == half.to_list() + + array = ak.from_regular(ak.Array(values(np.longdouble))) + if LONGDOUBLE_IS_WIDER: + with pytest.raises(TypeError, match="Arrow has no type for float128"): + ak.to_arrow(array) + else: + back = ak.from_arrow(ak.to_arrow(array)) + assert str(back.type) == "50 * var * float64" + assert back.to_list() == array.to_list() + + array = ak.from_regular(ak.Array(values(np.clongdouble))) + with pytest.raises(TypeError, match="Arrow has no type for complex"): + ak.to_arrow(array) + + +def test_numba(): + numba = pytest.importorskip("numba") + pytest.importorskip("awkward.numba").register_and_check() + + @numba.njit + def first(array): + return array[0][0] + + @numba.njit + def without_first(array): + return array[1:] + + # float16 arrays can go through a compiled function, but not be read + half = ak.from_regular(ak.Array(values(np.float16))) + result = without_first(half) + assert result.type == half[1:].type + assert result.to_list() == half[1:].to_list() + with pytest.raises(TypeError, match="Numba cannot read float16 values"): + first(half) + + array = ak.from_regular(ak.Array(values(np.longdouble))) + if LONGDOUBLE_IS_WIDER: + with pytest.raises(TypeError, match="Numba has no long double type"): + without_first(array) + else: + assert first(array) == array[0][0] + + +def test_cpp_value_types(): + cling = pytest.importorskip("awkward._connect.cling") + + def value_type(dtype): + form = ak.Array(np.zeros(3, dtype=dtype)).layout.form + return cling.togenerator(form, flatlist_as_rvec=False).value_type() + + if LONGDOUBLE_IS_WIDER: + assert value_type(np.longdouble) == "long double" + assert value_type(np.clongdouble) == "std::complex" + else: + assert value_type(np.longdouble) == "double" + assert value_type(np.clongdouble) == "std::complex" + + with pytest.raises(TypeError, match=r"C\+\+ has no half precision type"): + value_type(np.float16) + + +@pytest.mark.parametrize("dtype", [np.longdouble, np.clongdouble]) +def test_rdataframe(dtype): + pytest.importorskip("ROOT") + + array = ak.from_regular(ak.Array(values(dtype))) + data_frame = ak.to_rdataframe({"x": array}) + if LONGDOUBLE_IS_WIDER: + assert "long double" in str(data_frame.GetColumnType("x")) + + back = ak.from_rdataframe(data_frame, columns=("x",))["x"] + assert back.type == array.type + assert ak.all(back == array, axis=None) + + +def test_rdataframe_long_double_column(): + ROOT = pytest.importorskip("ROOT") + + data_frame = ROOT.RDataFrame(3).Define("x", "1.0L / 3.0L + rdfentry_") + assert str(data_frame.GetColumnType("x")) == "long double" + + result = ak.to_numpy(ak.from_rdataframe(data_frame, columns=("x",))["x"]) + assert result.dtype == np.dtype(np.longdouble) + assert result[0] == np.longdouble(1) / np.longdouble(3) + + +def test_rdataframe_float16(): + pytest.importorskip("ROOT") + + array = ak.from_regular(ak.Array(values(np.float16))) + with pytest.raises(TypeError, match=r"C\+\+ has no half precision type"): + ak.to_rdataframe({"x": array}) + + +def test_long_double_form_from_an_awkward1_pickle(): + form = ak.forms.NumpyForm.__new__(ak.forms.NumpyForm) + state = (False, None, None, (), np.dtype(np.longdouble).itemsize, "g") + + if hasattr(np, "float128"): + form.__setstate__(state) + assert form.primitive == "float128" + else: + with pytest.raises(TypeError, match="unrecognized primitive: 'float128'"): + form.__setstate__(state) From 4f0a9fbba9714fdbba823483bd784362387fee1e Mon Sep 17 00:00:00 2001 From: Iason Krommydas Date: Sat, 10 Oct 2026 02:44:25 +0200 Subject: [PATCH 12/19] feat: find the unique values of complex numbers without an axis through NumPy --- src/awkward/contents/numpyarray.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/awkward/contents/numpyarray.py b/src/awkward/contents/numpyarray.py index a261583749..d9e3ce7dc8 100644 --- a/src/awkward/contents/numpyarray.py +++ b/src/awkward/contents/numpyarray.py @@ -770,10 +770,20 @@ def _unique(self, negaxis, starts, offsets, outlength): ) return out._numbers_to_type("float16", False) + elif self.dtype.kind == "c" and negaxis is None: + # the kernels cannot sort complex numbers, NumPy can + return ak.contents.NumpyArray( + self._backend.nplike.unique_values(self.to_contiguous()._data), + parameters=None, + backend=self._backend, + ) + elif self.dtype.kind == "c" or ( negaxis is not None and self.dtype.kind.upper() == "M" ): - raise ValueError(f"cannot find the unique values of {self.dtype!r}") + raise ValueError( + f"cannot find the unique values of {self.dtype!r} along an axis" + ) elif negaxis is None: contiguous_self = self.to_contiguous() From 28137730b99a1b2aa7e7cb86402195c2822724bc Mon Sep 17 00:00:00 2001 From: Iason Krommydas Date: Sat, 10 Oct 2026 02:44:28 +0200 Subject: [PATCH 13/19] fix: convert long double to the nearest double in ArrayBuilder and JSON instead of raising --- awkward-cpp/src/python/content.cpp | 22 ---------------------- src/awkward/contents/numpyarray.py | 12 +++--------- 2 files changed, 3 insertions(+), 31 deletions(-) diff --git a/awkward-cpp/src/python/content.cpp b/awkward-cpp/src/python/content.cpp index 837571147b..515a1c1877 100644 --- a/awkward-cpp/src/python/content.cpp +++ b/awkward-cpp/src/python/content.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include "awkward/python/content.h" #include "awkward/python/util.h" @@ -20,25 +19,6 @@ builder_fromiter_iscomplex(const py::handle& obj) { return PyComplex_Check(obj.ptr()); } -// The builder holds real numbers as double and complex numbers as pairs of -// doubles. Where long double is wider than double, a long double value would -// lose digits in it. -void -builder_fromiter_notlongdouble(const py::handle& obj) { - if (std::numeric_limits::digits > std::numeric_limits::digits && - (py::isinstance(obj, py::module::import("numpy").attr("longdouble")) || - py::isinstance(obj, py::module::import("numpy").attr("clongdouble")))) { - throw std::invalid_argument( - std::string("cannot convert ") - + obj.attr("__repr__")().cast() + std::string(" (type ") - + obj.attr("__class__").attr("__name__").cast() - + std::string(") to an array element because an ArrayBuilder holds " - "float64 and complex128 numbers, which have fewer digits. " - "Convert the value with float or complex first, or make " - "the array from a NumPy array") + FILENAME(__LINE__)); - } -} - void builder_datetime(ak::ArrayBuilder& self, const py::handle& obj) { if (py::isinstance(obj)) { @@ -190,11 +170,9 @@ builder_fromiter(ak::ArrayBuilder& self, const py::handle& obj) { self.integer(obj.cast()); } else if (py::isinstance(obj, py::module::import("numpy").attr("floating"))) { - builder_fromiter_notlongdouble(obj); self.real(obj.cast()); } else if (py::isinstance(obj, py::module::import("numpy").attr("complexfloating"))) { - builder_fromiter_notlongdouble(obj); self.complex(obj.cast>()); } else if (py::hasattr(obj, "to_list")) { diff --git a/src/awkward/contents/numpyarray.py b/src/awkward/contents/numpyarray.py index d9e3ce7dc8..e59e1d5467 100644 --- a/src/awkward/contents/numpyarray.py +++ b/src/awkward/contents/numpyarray.py @@ -1360,16 +1360,10 @@ def _to_list(self, behavior, json_conversions): data = self._data if json_conversions is not None and data.dtype.type is np.longdouble: - # JSON numbers are written from Python floats, which are doubles - if data.dtype != np.float64: - raise TypeError( - f"{data.dtype.name} values cannot be written as JSON without " - "losing digits. Convert them with ak.values_astype(array, " - "np.float64) first" - ) - # long double is the same as double on this platform + # The json module writes Python floats, which are doubles. A long + # double is written as the nearest double. (data,) = maybe_materialize(data) - data = data.view(np.float64) + data = data.astype(np.float64) out = data.tolist() if json_conversions is not None: From 4d6cd0a9893eee0d7068def389d62e4008e63eed Mon Sep 17 00:00:00 2001 From: Iason Krommydas Date: Sat, 10 Oct 2026 02:44:31 +0200 Subject: [PATCH 14/19] test: expect int64 counts and indexes on 32-bit platforms and cover complex unique, JSON and builder conversions --- tests/test_4259_float16_and_longdouble.py | 70 +++++++++++++++-------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/tests/test_4259_float16_and_longdouble.py b/tests/test_4259_float16_and_longdouble.py index cbdd506078..72bca9dc46 100644 --- a/tests/test_4259_float16_and_longdouble.py +++ b/tests/test_4259_float16_and_longdouble.py @@ -35,6 +35,11 @@ def values(dtype): return out.astype(dtype) +def result_dtype(expected): + # NumPy counts and indexes with intp, which is int32 on 32-bit platforms + return np.dtype(np.int64) if expected.dtype.kind == "i" else expected.dtype + + @pytest.mark.parametrize("dtype", [np.float16, np.longdouble, np.clongdouble]) @pytest.mark.parametrize("ak_reducer, np_reducer", REDUCERS) def test_reducers(dtype, ak_reducer, np_reducer): @@ -43,7 +48,7 @@ def test_reducers(dtype, ak_reducer, np_reducer): result = ak.to_numpy(ak_reducer(array, axis=1)) expected = np_reducer(data, axis=1) - assert result.dtype == expected.dtype + assert result.dtype == result_dtype(expected) if ak_reducer in (ak.sum, ak.prod): # the kernels and NumPy do not add and multiply in the same order assert np.allclose( @@ -86,7 +91,7 @@ def test_float16_axis_none(): for ak_reducer, np_reducer in REDUCERS: result = ak_reducer(array, axis=None) expected = np_reducer(data) - assert np.asarray(result).dtype == np.asarray(expected).dtype + assert np.asarray(result).dtype == result_dtype(np.asarray(expected)) assert result == pytest.approx(expected, rel=1e-2) @@ -148,6 +153,30 @@ def test_complex_numbers_cannot_be_sorted(dtype): ak._do.unique(array.layout, axis=-1) +@pytest.mark.parametrize("dtype", [np.complex64, np.complex128, np.clongdouble]) +def test_unique_complex_numbers_without_an_axis(dtype): + data = np.array([2 + 1j, 1 + 2j, 2 + 1j, 1 - 1j, 1 + 2j], dtype=dtype) + + for array in (ak.Array(data), ak.unflatten(ak.Array(data), [2, 0, 3])): + result = ak.to_numpy(ak._do.unique(array.layout, axis=None)) + assert result.dtype == np.dtype(dtype) + assert np.array_equal(result, np.unique(data)) + assert not ak._do.is_unique(array.layout) + + assert ak._do.is_unique(ak.Array(data[2:]).layout) + + +def test_unique_date_times(): + data = np.array(["2020-01-02", "2020-01-01", "2020-01-02"], "datetime64[s]") + array = ak.Array(data) + + result = ak.to_numpy(ak._do.unique(array.layout, axis=None)) + assert np.array_equal(result, np.unique(data)) + + with pytest.raises(ValueError, match="cannot find the unique values of"): + ak._do.unique(ak.unflatten(array, [2, 1]).layout, axis=-1) + + @pytest.mark.parametrize("dtype", [np.float16, np.longdouble, np.clongdouble]) def test_type_strings_can_be_parsed(dtype): array = ak.from_regular(ak.Array(values(dtype))) @@ -195,19 +224,14 @@ def test_from_iter_with_numpy_scalars(): @pytest.mark.parametrize("scalar", [np.longdouble(1.5), np.clongdouble(1.5 + 2j)]) def test_builder_with_long_double_scalars(scalar): + # the builder holds float64 and complex128 numbers, whatever the type + # of the NumPy scalar builder = ak.ArrayBuilder() + builder.append(scalar) - if LONGDOUBLE_IS_WIDER: - message = "ArrayBuilder holds float64 and complex128 numbers" - with pytest.raises(ValueError, match=message): - ak.from_iter([scalar]) - with pytest.raises(ValueError, match=message): - builder.append(scalar) - else: - builder.append(scalar) - for array in (ak.from_iter([scalar]), builder.snapshot()): - assert array.to_list() == [scalar] - assert array.layout.dtype.type in (np.float64, np.complex128) + for array in (ak.from_iter([scalar]), builder.snapshot()): + assert array.to_list() == [scalar] + assert array.layout.dtype.type in (np.float64, np.complex128) @pytest.mark.parametrize( @@ -243,19 +267,15 @@ def test_json(): assert json.loads(ak.to_json(half)) == half.to_list() array = ak.from_regular(ak.Array(values(np.longdouble))) - if LONGDOUBLE_IS_WIDER: - with pytest.raises(TypeError, match="written as JSON without losing"): - ak.to_json(array) - else: - assert json.loads(ak.to_json(array)) == array.to_list() + assert json.loads(ak.to_json(array)) == array.to_list() - array = ak.from_regular(ak.Array(values(np.clongdouble))) - if LONGDOUBLE_IS_WIDER: - with pytest.raises(TypeError, match="written as JSON without losing"): - ak.to_json(array, complex_record_fields=("real", "imag")) - else: - written = json.loads(ak.to_json(array, complex_record_fields=("real", "imag"))) - assert written[0][0] == {"real": array[0, 0].real, "imag": array[0, 0].imag} + # JSON is written from Python floats, so it has the nearest double + third = np.longdouble(1) / np.longdouble(3) + assert json.loads(ak.to_json(ak.Array(np.array([third])))) == [float(third)] + + array = ak.Array(np.array([third + 2j * third], dtype=np.clongdouble)) + written = ak.to_json(array, complex_record_fields=("real", "imag")) + assert json.loads(written) == [{"real": float(third), "imag": 2 * float(third)}] def test_arrow(): From 19f0e2f6cb2d87602556ded70a6a487bbc8d53f0 Mon Sep 17 00:00:00 2001 From: Iason Krommydas Date: Sat, 10 Oct 2026 04:12:19 +0200 Subject: [PATCH 15/19] fix: choose the JSON replacement strings from the converted long double values and update the license line of the new test files --- .../tests/test_4259-layout-builder-long-double.cpp | 2 +- src/awkward/contents/numpyarray.py | 13 +++++++------ tests/test_4259_float16_and_longdouble.py | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/header-only/tests/test_4259-layout-builder-long-double.cpp b/header-only/tests/test_4259-layout-builder-long-double.cpp index 58a1c1344f..990688152a 100644 --- a/header-only/tests/test_4259-layout-builder-long-double.cpp +++ b/header-only/tests/test_4259-layout-builder-long-double.cpp @@ -1,4 +1,4 @@ -// BSD 3-Clause License; see https://github.com/scikit-hep/awkward/blob/main/LICENSE +// BSD 3-Clause License; see https://github.com/CoffeaTeam/awkward-lite/blob/main/LICENSE // The form of a builder of long double values names the primitive as NumPy // does, by its size. The size depends on the platform. diff --git a/src/awkward/contents/numpyarray.py b/src/awkward/contents/numpyarray.py index 1f7a60ef8f..b97587c6a6 100644 --- a/src/awkward/contents/numpyarray.py +++ b/src/awkward/contents/numpyarray.py @@ -1361,7 +1361,9 @@ def _to_list(self, behavior, json_conversions): data = self._data if json_conversions is not None and data.dtype.type is np.longdouble: # The json module writes Python floats, which are doubles. A long - # double is written as the nearest double. + # double is written as the nearest double, which is infinite for a + # value beyond the range of double. The strings below are chosen + # from the converted values for that reason. (data,) = maybe_materialize(data) data = data.astype(np.float64) out = data.tolist() @@ -1369,19 +1371,18 @@ def _to_list(self, behavior, json_conversions): if json_conversions is not None: nan_string = json_conversions["nan_string"] if nan_string is not None: - for i in self._backend.nplike.nonzero( - self._backend.nplike.isnan(self._data) - )[0]: + is_nan = self._backend.nplike.isnan(data) + for i in self._backend.nplike.nonzero(is_nan)[0]: out[i] = nan_string posinf_string = json_conversions["posinf_string"] if posinf_string is not None: - for i in self._backend.nplike.nonzero(self._data == np.inf)[0]: + for i in self._backend.nplike.nonzero(data == np.inf)[0]: out[i] = posinf_string neginf_string = json_conversions["neginf_string"] if neginf_string is not None: - for i in self._backend.nplike.nonzero(self._data == -np.inf)[0]: + for i in self._backend.nplike.nonzero(data == -np.inf)[0]: out[i] = neginf_string return out diff --git a/tests/test_4259_float16_and_longdouble.py b/tests/test_4259_float16_and_longdouble.py index 72bca9dc46..de88b6c3f3 100644 --- a/tests/test_4259_float16_and_longdouble.py +++ b/tests/test_4259_float16_and_longdouble.py @@ -1,4 +1,4 @@ -# BSD 3-Clause License; see https://github.com/scikit-hep/awkward/blob/main/LICENSE +# BSD 3-Clause License; see https://github.com/CoffeaTeam/awkward-lite/blob/main/LICENSE from __future__ import annotations From 3614ff479f32aac1d41e6d9be2263629075578e0 Mon Sep 17 00:00:00 2001 From: Iason Krommydas Date: Sat, 10 Oct 2026 04:12:22 +0200 Subject: [PATCH 16/19] fix: pass a long double initial to the min and max kernels without rounding it to double --- src/awkward/_kernels.py | 20 +++++++++++++++ tests/test_4259_float16_and_longdouble.py | 31 +++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/awkward/_kernels.py b/src/awkward/_kernels.py index 19ea9c9107..3c491c0f63 100644 --- a/src/awkward/_kernels.py +++ b/src/awkward/_kernels.py @@ -79,6 +79,26 @@ def __init__(self, impl: Callable[..., Any], key: KernelKeyType): ), )(ctypes.cast(impl, ctypes.c_void_p).value) + # ctypes makes a long double argument from a Python float, which is a + # double. Where long double is wider, a kernel that takes one (the + # identity of a reducer) is given the bytes of the value instead. + if ctypes.sizeof(ctypes.c_longdouble) > ctypes.sizeof(ctypes.c_double): + positions = tuple( + i for i, t in enumerate(argtypes) if t is ctypes.c_longdouble + ) + if positions: + call = self._call + + def call_with_long_doubles(*args): + args = list(args) + for i in positions: + args[i] = ctypes.c_longdouble.from_buffer_copy( + metadata.longdouble(args[i]).tobytes() + ) + return call(*args) + + self._call = call_with_long_doubles + def _pointer_of(self, x): """The address of ``x``'s buffer, rejecting anything this backend cannot pass.""" raise NotImplementedError diff --git a/tests/test_4259_float16_and_longdouble.py b/tests/test_4259_float16_and_longdouble.py index de88b6c3f3..0c8d8e42a9 100644 --- a/tests/test_4259_float16_and_longdouble.py +++ b/tests/test_4259_float16_and_longdouble.py @@ -141,6 +141,37 @@ def test_longdouble_keeps_its_precision(): assert ak.to_numpy(ak.sum(as_complex, axis=1))[0] == np.sum(data) +def test_longdouble_min_and_max_with_initial(): + data = values(np.longdouble) + array = ak.from_regular(ak.Array(data)) + + result = ak.to_numpy(ak.min(array, axis=1, initial=1.5)) + assert np.array_equal(result, np.min(data, axis=1, initial=1.5)) + result = ak.to_numpy(ak.max(array, axis=1, initial=3.5)) + assert np.array_equal(result, np.max(data, axis=1, initial=3.5)) + + if LONGDOUBLE_IS_WIDER: + # these values and the initial are all equal to 1 as float64 + one = np.longdouble(1) + eps = np.finfo(np.longdouble).eps + data = np.array( + [[one + 2 * eps, one + 3 * eps], [one + 5 * eps, one + 6 * eps]] + ) + array = ak.from_regular(ak.Array(data)) + + low, high = one + eps, one + 4 * eps + result = ak.to_numpy(ak.min(array, axis=1, initial=low)) + assert np.array_equal(result, np.min(data, axis=1, initial=low)) + result = ak.to_numpy(ak.max(array, axis=1, initial=high)) + assert np.array_equal(result, np.max(data, axis=1, initial=high)) + + # for complex numbers the initial is the result of an empty list + data = np.array([1 + 1j], dtype=np.clongdouble) + array = ak.unflatten(ak.Array(data), [1, 0]) + result = ak.to_numpy(ak.min(array, axis=1, initial=low, mask_identity=False)) + assert result[1] == low + + @pytest.mark.parametrize("dtype", [np.complex64, np.complex128, np.clongdouble]) def test_complex_numbers_cannot_be_sorted(dtype): array = ak.from_regular(ak.Array(values(dtype))) From 10bcab858b421ea3031cbb971bc2dfdb3152d745 Mon Sep 17 00:00:00 2001 From: Iason Krommydas Date: Sat, 17 Oct 2026 22:29:37 +0200 Subject: [PATCH 17/19] fix: parse record and field names that start with or equal a dtype name (#4390) --- .../types/_awkward_datashape_parser.py | 4 +- src/awkward/types/recordtype.py | 2 + tests/test_4390_all_numpy_numeric_dtypes.py | 127 ++++++++++++++++++ 3 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 tests/test_4390_all_numpy_numeric_dtypes.py diff --git a/src/awkward/types/_awkward_datashape_parser.py b/src/awkward/types/_awkward_datashape_parser.py index fb947e1664..dc5474dd62 100644 --- a/src/awkward/types/_awkward_datashape_parser.py +++ b/src/awkward/types/_awkward_datashape_parser.py @@ -2894,10 +2894,10 @@ def always_accept(self): import zlib DATA = ( -{'parser': {'lexer_conf': {'terminals': [{'@': 0}, {'@': 1}, {'@': 2}, {'@': 3}, {'@': 4}, {'@': 5}, {'@': 6}, {'@': 7}, {'@': 8}, {'@': 9}, {'@': 10}, {'@': 11}, {'@': 12}, {'@': 13}, {'@': 14}, {'@': 15}, {'@': 16}, {'@': 17}, {'@': 18}, {'@': 19}, {'@': 20}, {'@': 21}, {'@': 22}, {'@': 23}, {'@': 24}, {'@': 25}, {'@': 26}, {'@': 27}, {'@': 28}, {'@': 29}, {'@': 30}, {'@': 31}, {'@': 32}, {'@': 33}, {'@': 34}], 'ignore': ['WS'], 'g_regex_flags': 0, 'use_bytes': False, 'lexer_type': 'contextual', '__type__': 'LexerConf'}, 'parser_conf': {'rules': [{'@': 35}, {'@': 36}, {'@': 37}, {'@': 38}, {'@': 39}, {'@': 40}, {'@': 41}, {'@': 42}, {'@': 43}, {'@': 44}, {'@': 45}, {'@': 46}, {'@': 47}, {'@': 48}, {'@': 49}, {'@': 50}, {'@': 51}, {'@': 52}, {'@': 53}, {'@': 54}, {'@': 55}, {'@': 56}, {'@': 57}, {'@': 58}, {'@': 59}, {'@': 60}, {'@': 61}, {'@': 62}, {'@': 63}, {'@': 64}, {'@': 65}, {'@': 66}, {'@': 67}, {'@': 68}, {'@': 69}, {'@': 70}, {'@': 71}, {'@': 72}, {'@': 73}, {'@': 74}, {'@': 75}, {'@': 76}, {'@': 77}, {'@': 78}, {'@': 79}, {'@': 80}, {'@': 81}, {'@': 82}, {'@': 83}, {'@': 84}, {'@': 85}, {'@': 86}, {'@': 87}, {'@': 88}, {'@': 89}, {'@': 90}, {'@': 91}, {'@': 92}, {'@': 93}, {'@': 94}, {'@': 95}, {'@': 96}, {'@': 97}, {'@': 98}, {'@': 99}, {'@': 100}, {'@': 101}, {'@': 102}, {'@': 103}, {'@': 104}, {'@': 105}, {'@': 106}, {'@': 107}, {'@': 108}, {'@': 109}, {'@': 110}, {'@': 111}, {'@': 112}, {'@': 113}, {'@': 114}, {'@': 115}, {'@': 116}, {'@': 117}, {'@': 118}, {'@': 119}, {'@': 120}, {'@': 121}, {'@': 122}, {'@': 123}, {'@': 124}, {'@': 125}, {'@': 126}, {'@': 127}, {'@': 128}, {'@': 129}, {'@': 130}], 'start': ['start'], 'parser_type': 'lalr', '__type__': 'ParserConf'}, 'parser': {'tokens': {0: 'RSQB', 1: 'LSQB', 2: 'COMMA', 3: 'RBRACE', 4: '$END', 5: 'RPAR', 6: 'INT', 7: 'key', 8: 'ESCAPED_STRING', 9: 'CNAME', 10: 'pair', 11: 'LBRACE', 12: 'json_object', 13: 'EQUAL', 14: 'PARAMETERS', 15: 'OPTION', 16: 'tuple', 17: 'numpytype_name', 18: 'type', 19: 'tuple_parameters', 20: 'TUPLE', 21: 'named_pair', 22: 'list_parameters', 23: 'option1', 24: 'BYTE', 25: 'union', 26: 'regulartype', 27: 'unknowntype', 28: 'option2', 29: 'named_pairs', 30: 'varlen_string', 31: 'UNION', 32: 'char', 33: 'VAR', 34: 'record_parameters', 35: 'STRING', 36: 'CATEGORICAL', 37: 'record', 38: 'DTYPE', 39: 'STRUCT', 40: 'categorical', 41: 'UNKNOWN', 42: 'named0', 43: 'named', 44: 'numpytype', 45: 'named_key', 46: 'CHAR', 47: 'LPAR', 48: 'TIMEDELTA64', 49: 'named_types', 50: 'byte', 51: 'listtype', 52: 'DATETIME64', 53: 'BYTES', 54: 'fixedlen_string', 55: 'QMARK', 56: 'types', 57: 'pairs', 58: '__pairs_star_1', 59: 'json', 60: 'json_array', 61: 'FALSE', 62: 'TRUE', 63: 'NULL', 64: 'SIGNED_NUMBER', 65: 'COLON', 66: '__types_star_0', 67: 'json_pair', 68: 'STAR', 69: '__json_object_star_3', 70: '__json_array_star_2', 71: 'start', 72: 'TYPE'}, 'states': {0: {0: (1, {'@': 57}), 1: (1, {'@': 57}), 2: (1, {'@': 57}), 3: (1, {'@': 57}), 4: (1, {'@': 57}), 5: (1, {'@': 57})}, 1: {0: (1, {'@': 106}), 2: (1, {'@': 106}), 3: (1, {'@': 106}), 4: (1, {'@': 106}), 5: (1, {'@': 106})}, 2: {0: (0, 165)}, 3: {1: (0, 160)}, 4: {6: (0, 72)}, 5: {7: (0, 52), 8: (0, 46), 9: (0, 47), 10: (0, 42)}, 6: {0: (0, 91)}, 7: {11: (0, 189), 12: (0, 63)}, 8: {11: (0, 189), 12: (0, 59)}, 9: {0: (1, {'@': 119}), 2: (1, {'@': 119}), 3: (1, {'@': 119})}, 10: {11: (0, 189), 12: (0, 65)}, 11: {3: (0, 9), 2: (0, 89)}, 12: {0: (1, {'@': 44}), 2: (1, {'@': 44}), 3: (1, {'@': 44}), 4: (1, {'@': 44}), 5: (1, {'@': 44})}, 13: {13: (0, 138)}, 14: {1: (0, 69), 0: (1, {'@': 61}), 2: (1, {'@': 61}), 3: (1, {'@': 61}), 4: (1, {'@': 61}), 5: (1, {'@': 61})}, 15: {13: (0, 119)}, 16: {1: (0, 164), 14: (0, 182), 15: (0, 140), 16: (0, 147), 17: (0, 197), 18: (0, 177), 19: (0, 174), 20: (0, 3), 21: (0, 201), 0: (0, 114), 22: (0, 22), 23: (0, 12), 9: (0, 123), 24: (0, 145), 25: (0, 116), 26: (0, 96), 27: (0, 200), 28: (0, 137), 29: (0, 112), 30: (0, 153), 31: (0, 120), 32: (0, 146), 11: (0, 32), 33: (0, 64), 34: (0, 186), 35: (0, 51), 36: (0, 143), 37: (0, 166), 38: (0, 0), 39: (0, 45), 40: (0, 40), 6: (0, 75), 41: (0, 14), 42: (0, 55), 43: (0, 128), 44: (0, 131), 45: (0, 98), 46: (0, 107), 47: (0, 181), 48: (0, 159), 49: (0, 104), 50: (0, 133), 51: (0, 198), 8: (0, 126), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191)}, 17: {21: (0, 201), 14: (0, 15), 8: (0, 126), 45: (0, 98), 29: (0, 31), 9: (0, 93)}, 18: {3: (1, {'@': 122}), 2: (1, {'@': 122})}, 19: {1: (0, 164), 15: (0, 140), 36: (0, 143), 18: (0, 60), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 56: (0, 155), 33: (0, 64), 40: (0, 40), 0: (0, 130), 6: (0, 75), 9: (0, 29), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 25: (0, 116), 26: (0, 96), 44: (0, 131), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 34: (0, 186)}, 20: {0: (1, {'@': 112}), 2: (1, {'@': 112}), 3: (1, {'@': 112})}, 21: {0: (1, {'@': 90}), 2: (1, {'@': 90}), 3: (1, {'@': 90}), 4: (1, {'@': 90}), 5: (1, {'@': 90})}, 22: {0: (1, {'@': 53}), 2: (1, {'@': 53}), 3: (1, {'@': 53}), 4: (1, {'@': 53}), 5: (1, {'@': 53})}, 23: {0: (1, {'@': 74}), 2: (1, {'@': 74}), 3: (1, {'@': 74}), 4: (1, {'@': 74}), 5: (1, {'@': 74})}, 24: {14: (0, 179)}, 25: {0: (1, {'@': 109}), 2: (1, {'@': 109}), 3: (1, {'@': 109})}, 26: {0: (1, {'@': 118}), 2: (1, {'@': 118}), 3: (1, {'@': 118})}, 27: {0: (1, {'@': 111}), 2: (1, {'@': 111}), 3: (1, {'@': 111})}, 28: {0: (1, {'@': 128}), 2: (1, {'@': 128})}, 29: {1: (0, 16)}, 30: {3: (0, 170), 7: (0, 52), 57: (0, 193), 10: (0, 33), 8: (0, 46), 9: (0, 47)}, 31: {0: (1, {'@': 99})}, 32: {7: (0, 52), 10: (0, 33), 8: (0, 46), 9: (0, 47), 3: (0, 58), 57: (0, 76)}, 33: {58: (0, 157), 2: (0, 149), 3: (1, {'@': 84})}, 34: {0: (1, {'@': 96})}, 35: {59: (0, 80), 12: (0, 44), 60: (0, 199), 1: (0, 35), 11: (0, 189), 0: (0, 26), 61: (0, 20), 62: (0, 27), 8: (0, 25), 63: (0, 136), 64: (0, 127)}, 36: {0: (0, 152)}, 37: {0: (0, 122)}, 38: {0: (0, 50), 2: (0, 77)}, 39: {0: (1, {'@': 77}), 2: (1, {'@': 77}), 3: (1, {'@': 77}), 4: (1, {'@': 77}), 5: (1, {'@': 77})}, 40: {0: (1, {'@': 54}), 2: (1, {'@': 54}), 3: (1, {'@': 54}), 4: (1, {'@': 54}), 5: (1, {'@': 54})}, 41: {0: (1, {'@': 102}), 2: (1, {'@': 102})}, 42: {3: (1, {'@': 126}), 2: (1, {'@': 126})}, 43: {61: (0, 20), 11: (0, 189), 62: (0, 27), 8: (0, 25), 12: (0, 44), 1: (0, 35), 60: (0, 199), 63: (0, 136), 64: (0, 127), 59: (0, 90)}, 44: {0: (1, {'@': 115}), 2: (1, {'@': 115}), 3: (1, {'@': 115})}, 45: {1: (0, 113)}, 46: {65: (1, {'@': 86})}, 47: {65: (1, {'@': 87})}, 48: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 18: (0, 6), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 49: {0: (1, {'@': 120}), 2: (1, {'@': 120}), 3: (1, {'@': 120})}, 50: {0: (1, {'@': 116}), 2: (1, {'@': 116}), 3: (1, {'@': 116})}, 51: {1: (0, 129), 0: (1, {'@': 64}), 2: (1, {'@': 64}), 3: (1, {'@': 64}), 4: (1, {'@': 64}), 5: (1, {'@': 64})}, 52: {65: (0, 74)}, 53: {13: (0, 121)}, 54: {0: (0, 97)}, 55: {0: (1, {'@': 50}), 2: (1, {'@': 50}), 3: (1, {'@': 50}), 4: (1, {'@': 50}), 5: (1, {'@': 50})}, 56: {11: (0, 189), 12: (0, 139)}, 57: {0: (0, 190), 2: (0, 168)}, 58: {0: (1, {'@': 82}), 2: (1, {'@': 82}), 3: (1, {'@': 82}), 4: (1, {'@': 82}), 5: (1, {'@': 82})}, 59: {0: (0, 21)}, 60: {66: (0, 106), 2: (0, 108), 0: (1, {'@': 76}), 5: (1, {'@': 76})}, 61: {0: (1, {'@': 95}), 2: (1, {'@': 95}), 3: (1, {'@': 95}), 4: (1, {'@': 95}), 5: (1, {'@': 95})}, 62: {8: (0, 163), 67: (0, 71)}, 63: {0: (0, 135)}, 64: {68: (0, 148)}, 65: {0: (0, 82)}, 66: {0: (1, {'@': 100})}, 67: {0: (1, {'@': 88}), 2: (1, {'@': 88}), 3: (1, {'@': 88}), 4: (1, {'@': 88}), 5: (1, {'@': 88})}, 68: {0: (0, 1), 1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 18: (0, 177), 19: (0, 174), 20: (0, 3), 39: (0, 45), 49: (0, 54), 40: (0, 40), 6: (0, 75), 9: (0, 29), 38: (0, 0), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 69: {14: (0, 87)}, 70: {0: (1, {'@': 72}), 2: (1, {'@': 72}), 3: (1, {'@': 72}), 4: (1, {'@': 72}), 5: (1, {'@': 72})}, 71: {3: (1, {'@': 129}), 2: (1, {'@': 129})}, 72: {0: (0, 103)}, 73: {0: (1, {'@': 97})}, 74: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 18: (0, 102), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 75: {68: (0, 175)}, 76: {3: (0, 132)}, 77: {61: (0, 20), 11: (0, 189), 62: (0, 27), 8: (0, 25), 59: (0, 28), 12: (0, 44), 1: (0, 35), 60: (0, 199), 63: (0, 136), 64: (0, 127)}, 78: {0: (1, {'@': 117}), 2: (1, {'@': 117}), 3: (1, {'@': 117})}, 79: {69: (0, 11), 3: (0, 49), 2: (0, 62)}, 80: {70: (0, 38), 0: (0, 78), 2: (0, 43)}, 81: {0: (1, {'@': 55}), 2: (1, {'@': 55}), 3: (1, {'@': 55}), 4: (1, {'@': 55}), 5: (1, {'@': 55})}, 82: {0: (1, {'@': 71}), 2: (1, {'@': 71}), 3: (1, {'@': 71}), 4: (1, {'@': 71}), 5: (1, {'@': 71})}, 83: {0: (0, 67)}, 84: {0: (0, 70), 2: (0, 24)}, 85: {0: (0, 171)}, 86: {0: (0, 39)}, 87: {13: (0, 173)}, 88: {0: (1, {'@': 91}), 2: (1, {'@': 91}), 3: (1, {'@': 91}), 4: (1, {'@': 91}), 5: (1, {'@': 91})}, 89: {8: (0, 163), 67: (0, 162)}, 90: {0: (1, {'@': 127}), 2: (1, {'@': 127})}, 91: {0: (1, {'@': 108}), 2: (1, {'@': 108}), 3: (1, {'@': 108}), 4: (1, {'@': 108}), 5: (1, {'@': 108})}, 92: {13: (0, 183)}, 93: {65: (1, {'@': 104})}, 94: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 18: (0, 177), 19: (0, 174), 20: (0, 3), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 38: (0, 0), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 49: (0, 34), 48: (0, 159), 50: (0, 133), 14: (0, 53), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 95: {14: (0, 184)}, 96: {0: (1, {'@': 38}), 2: (1, {'@': 38}), 3: (1, {'@': 38}), 4: (1, {'@': 38}), 5: (1, {'@': 38})}, 97: {0: (1, {'@': 105}), 2: (1, {'@': 105}), 3: (1, {'@': 105}), 4: (1, {'@': 105}), 5: (1, {'@': 105})}, 98: {65: (0, 150)}, 99: {0: (1, {'@': 121}), 2: (1, {'@': 121}), 3: (1, {'@': 121})}, 100: {71: (0, 169), 1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 33: (0, 64), 6: (0, 75), 9: (0, 29), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 18: (0, 101), 31: (0, 120), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 34: (0, 186)}, 101: {4: (1, {'@': 35})}, 102: {3: (1, {'@': 85}), 2: (1, {'@': 85})}, 103: {0: (1, {'@': 67}), 2: (1, {'@': 67}), 3: (1, {'@': 67}), 4: (1, {'@': 67}), 5: (1, {'@': 67})}, 104: {0: (0, 178)}, 105: {14: (0, 194)}, 106: {2: (0, 115), 0: (1, {'@': 75}), 5: (1, {'@': 75})}, 107: {0: (1, {'@': 68}), 2: (1, {'@': 68}), 3: (1, {'@': 68}), 4: (1, {'@': 68}), 5: (1, {'@': 68})}, 108: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 18: (0, 187), 31: (0, 120), 34: (0, 186), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 109: {3: (1, {'@': 125}), 2: (1, {'@': 125})}, 110: {2: (0, 172)}, 111: {5: (0, 117)}, 112: {0: (0, 61)}, 113: {11: (0, 30)}, 114: {0: (1, {'@': 93}), 2: (1, {'@': 93}), 3: (1, {'@': 93}), 4: (1, {'@': 93}), 5: (1, {'@': 93})}, 115: {1: (0, 164), 15: (0, 140), 36: (0, 143), 18: (0, 134), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 116: {0: (1, {'@': 52}), 2: (1, {'@': 52}), 3: (1, {'@': 52}), 4: (1, {'@': 52}), 5: (1, {'@': 52})}, 117: {0: (1, {'@': 73}), 2: (1, {'@': 73}), 3: (1, {'@': 73}), 4: (1, {'@': 73}), 5: (1, {'@': 73})}, 118: {2: (0, 158), 0: (0, 142)}, 119: {12: (0, 66), 11: (0, 189)}, 120: {1: (0, 68)}, 121: {11: (0, 189), 12: (0, 73)}, 122: {0: (1, {'@': 107}), 2: (1, {'@': 107}), 3: (1, {'@': 107}), 4: (1, {'@': 107}), 5: (1, {'@': 107})}, 123: {1: (0, 16), 65: (1, {'@': 104})}, 124: {13: (0, 156)}, 125: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 33: (0, 64), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 25: (0, 116), 26: (0, 96), 44: (0, 131), 18: (0, 84), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 34: (0, 186)}, 126: {65: (1, {'@': 103})}, 127: {0: (1, {'@': 110}), 2: (1, {'@': 110}), 3: (1, {'@': 110})}, 128: {0: (1, {'@': 51}), 2: (1, {'@': 51}), 3: (1, {'@': 51}), 4: (1, {'@': 51}), 5: (1, {'@': 51})}, 129: {6: (0, 85)}, 130: {0: (0, 196), 2: (0, 105)}, 131: {0: (1, {'@': 36}), 2: (1, {'@': 36}), 3: (1, {'@': 36}), 4: (1, {'@': 36}), 5: (1, {'@': 36})}, 132: {0: (1, {'@': 81}), 2: (1, {'@': 81}), 3: (1, {'@': 81}), 4: (1, {'@': 81}), 5: (1, {'@': 81})}, 133: {0: (1, {'@': 43}), 2: (1, {'@': 43}), 3: (1, {'@': 43}), 4: (1, {'@': 43}), 5: (1, {'@': 43})}, 134: {0: (1, {'@': 124}), 5: (1, {'@': 124}), 2: (1, {'@': 124})}, 135: {0: (1, {'@': 79}), 2: (1, {'@': 79}), 3: (1, {'@': 79}), 4: (1, {'@': 79}), 5: (1, {'@': 79})}, 136: {0: (1, {'@': 113}), 2: (1, {'@': 113}), 3: (1, {'@': 113})}, 137: {0: (1, {'@': 45}), 2: (1, {'@': 45}), 3: (1, {'@': 45}), 4: (1, {'@': 45}), 5: (1, {'@': 45})}, 138: {11: (0, 189), 12: (0, 83)}, 139: {0: (0, 81)}, 140: {1: (0, 125)}, 141: {0: (1, {'@': 58}), 1: (1, {'@': 58}), 2: (1, {'@': 58}), 3: (1, {'@': 58}), 4: (1, {'@': 58}), 5: (1, {'@': 58})}, 142: {0: (1, {'@': 78}), 2: (1, {'@': 78}), 3: (1, {'@': 78}), 4: (1, {'@': 78}), 5: (1, {'@': 78})}, 143: {1: (0, 192)}, 144: {13: (0, 56)}, 145: {0: (1, {'@': 69}), 2: (1, {'@': 69}), 3: (1, {'@': 69}), 4: (1, {'@': 69}), 5: (1, {'@': 69})}, 146: {0: (1, {'@': 42}), 2: (1, {'@': 42}), 3: (1, {'@': 42}), 4: (1, {'@': 42}), 5: (1, {'@': 42})}, 147: {0: (1, {'@': 46}), 2: (1, {'@': 46}), 3: (1, {'@': 46}), 4: (1, {'@': 46}), 5: (1, {'@': 46})}, 148: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 18: (0, 161), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 149: {10: (0, 109), 8: (0, 46), 7: (0, 52), 9: (0, 47)}, 150: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 18: (0, 41), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 151: {13: (0, 48)}, 152: {0: (1, {'@': 92}), 2: (1, {'@': 92}), 3: (1, {'@': 92}), 4: (1, {'@': 92}), 5: (1, {'@': 92})}, 153: {0: (1, {'@': 40}), 2: (1, {'@': 40}), 3: (1, {'@': 40}), 4: (1, {'@': 40}), 5: (1, {'@': 40})}, 154: {11: (0, 189), 12: (0, 36)}, 155: {0: (0, 118)}, 156: {11: (0, 189), 12: (0, 86)}, 157: {2: (0, 5), 3: (1, {'@': 83})}, 158: {14: (0, 124)}, 159: {0: (1, {'@': 59}), 1: (1, {'@': 59}), 2: (1, {'@': 59}), 3: (1, {'@': 59}), 4: (1, {'@': 59}), 5: (1, {'@': 59})}, 160: {1: (0, 19)}, 161: {0: (1, {'@': 63}), 2: (1, {'@': 63}), 3: (1, {'@': 63}), 4: (1, {'@': 63}), 5: (1, {'@': 63})}, 162: {3: (1, {'@': 130}), 2: (1, {'@': 130})}, 163: {65: (0, 176)}, 164: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 18: (0, 110), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 165: {0: (1, {'@': 60}), 2: (1, {'@': 60}), 3: (1, {'@': 60}), 4: (1, {'@': 60}), 5: (1, {'@': 60})}, 166: {0: (1, {'@': 48}), 2: (1, {'@': 48}), 3: (1, {'@': 48}), 4: (1, {'@': 48}), 5: (1, {'@': 48})}, 167: {0: (1, {'@': 41}), 2: (1, {'@': 41}), 3: (1, {'@': 41}), 4: (1, {'@': 41}), 5: (1, {'@': 41})}, 168: {14: (0, 13)}, 169: {}, 170: {2: (0, 95), 0: (0, 88)}, 171: {0: (1, {'@': 66}), 2: (1, {'@': 66}), 3: (1, {'@': 66}), 4: (1, {'@': 66}), 5: (1, {'@': 66})}, 172: {14: (0, 92)}, 173: {12: (0, 2), 11: (0, 189)}, 174: {0: (1, {'@': 47}), 2: (1, {'@': 47}), 3: (1, {'@': 47}), 4: (1, {'@': 47}), 5: (1, {'@': 47})}, 175: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 18: (0, 185), 50: (0, 133), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 176: {59: (0, 18), 61: (0, 20), 11: (0, 189), 62: (0, 27), 8: (0, 25), 12: (0, 44), 1: (0, 35), 60: (0, 199), 63: (0, 136), 64: (0, 127)}, 177: {2: (0, 94), 0: (1, {'@': 98})}, 178: {0: (1, {'@': 94}), 2: (1, {'@': 94}), 3: (1, {'@': 94}), 4: (1, {'@': 94}), 5: (1, {'@': 94})}, 179: {13: (0, 10)}, 180: {1: (0, 4), 0: (1, {'@': 65}), 2: (1, {'@': 65}), 3: (1, {'@': 65}), 4: (1, {'@': 65}), 5: (1, {'@': 65})}, 181: {1: (0, 164), 15: (0, 140), 36: (0, 143), 18: (0, 60), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 5: (0, 23), 38: (0, 0), 39: (0, 45), 40: (0, 40), 6: (0, 75), 9: (0, 29), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 56: (0, 111), 51: (0, 198), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 182: {13: (0, 154)}, 183: {11: (0, 189), 12: (0, 37)}, 184: {13: (0, 8)}, 185: {0: (1, {'@': 62}), 2: (1, {'@': 62}), 3: (1, {'@': 62}), 4: (1, {'@': 62}), 5: (1, {'@': 62})}, 186: {0: (1, {'@': 49}), 2: (1, {'@': 49}), 3: (1, {'@': 49}), 4: (1, {'@': 49}), 5: (1, {'@': 49})}, 187: {0: (1, {'@': 123}), 5: (1, {'@': 123}), 2: (1, {'@': 123})}, 188: {0: (1, {'@': 70}), 2: (1, {'@': 70}), 3: (1, {'@': 70}), 4: (1, {'@': 70}), 5: (1, {'@': 70})}, 189: {67: (0, 79), 3: (0, 99), 8: (0, 163)}, 190: {0: (1, {'@': 89}), 2: (1, {'@': 89}), 3: (1, {'@': 89}), 4: (1, {'@': 89}), 5: (1, {'@': 89})}, 191: {1: (0, 164), 15: (0, 140), 36: (0, 143), 16: (0, 147), 17: (0, 197), 37: (0, 166), 19: (0, 174), 20: (0, 3), 38: (0, 0), 39: (0, 45), 40: (0, 40), 9: (0, 29), 6: (0, 75), 35: (0, 51), 22: (0, 22), 23: (0, 12), 41: (0, 14), 11: (0, 32), 42: (0, 55), 24: (0, 145), 43: (0, 128), 44: (0, 131), 26: (0, 96), 25: (0, 116), 46: (0, 107), 27: (0, 200), 47: (0, 181), 48: (0, 159), 50: (0, 133), 51: (0, 198), 18: (0, 188), 28: (0, 137), 30: (0, 153), 31: (0, 120), 34: (0, 186), 32: (0, 146), 52: (0, 141), 53: (0, 180), 54: (0, 167), 55: (0, 191), 33: (0, 64)}, 192: {72: (0, 151)}, 193: {3: (0, 57)}, 194: {13: (0, 7)}, 195: {14: (0, 144)}, 196: {0: (1, {'@': 80}), 2: (1, {'@': 80}), 3: (1, {'@': 80}), 4: (1, {'@': 80}), 5: (1, {'@': 80})}, 197: {1: (0, 195), 0: (1, {'@': 56}), 2: (1, {'@': 56}), 3: (1, {'@': 56}), 4: (1, {'@': 56}), 5: (1, {'@': 56})}, 198: {0: (1, {'@': 39}), 2: (1, {'@': 39}), 3: (1, {'@': 39}), 4: (1, {'@': 39}), 5: (1, {'@': 39})}, 199: {0: (1, {'@': 114}), 2: (1, {'@': 114}), 3: (1, {'@': 114})}, 200: {0: (1, {'@': 37}), 2: (1, {'@': 37}), 3: (1, {'@': 37}), 4: (1, {'@': 37}), 5: (1, {'@': 37})}, 201: {2: (0, 17), 0: (1, {'@': 101})}}, 'start_states': {'start': 100}, 'end_states': {'start': 169}}, 'options': {'debug': False, 'keep_all_tokens': False, 'tree_class': None, 'cache': False, 'postlex': None, 'parser': 'lalr', 'lexer': 'contextual', 'transformer': None, 'start': ['start'], 'priority': 'normal', 'ambiguity': 'auto', 'regex': False, 'propagate_positions': False, 'lexer_callbacks': {}, 'maybe_placeholders': False, 'edit_terminals': None, 'g_regex_flags': 0, 'use_bytes': False, 'import_paths': [], 'source_path': None}, '__type__': 'ParsingFrontend'}, 'rules': [{'@': 35}, {'@': 36}, {'@': 37}, {'@': 38}, {'@': 39}, {'@': 40}, {'@': 41}, {'@': 42}, {'@': 43}, {'@': 44}, {'@': 45}, {'@': 46}, {'@': 47}, {'@': 48}, {'@': 49}, {'@': 50}, {'@': 51}, {'@': 52}, {'@': 53}, {'@': 54}, {'@': 55}, {'@': 56}, {'@': 57}, {'@': 58}, {'@': 59}, {'@': 60}, {'@': 61}, {'@': 62}, {'@': 63}, {'@': 64}, {'@': 65}, {'@': 66}, {'@': 67}, {'@': 68}, {'@': 69}, {'@': 70}, {'@': 71}, {'@': 72}, {'@': 73}, {'@': 74}, {'@': 75}, {'@': 76}, {'@': 77}, {'@': 78}, {'@': 79}, {'@': 80}, {'@': 81}, {'@': 82}, {'@': 83}, {'@': 84}, {'@': 85}, {'@': 86}, {'@': 87}, {'@': 88}, {'@': 89}, {'@': 90}, {'@': 91}, {'@': 92}, {'@': 93}, {'@': 94}, {'@': 95}, {'@': 96}, {'@': 97}, {'@': 98}, {'@': 99}, {'@': 100}, {'@': 101}, {'@': 102}, {'@': 103}, {'@': 104}, {'@': 105}, {'@': 106}, {'@': 107}, {'@': 108}, {'@': 109}, {'@': 110}, {'@': 111}, {'@': 112}, {'@': 113}, {'@': 114}, {'@': 115}, {'@': 116}, {'@': 117}, {'@': 118}, {'@': 119}, {'@': 120}, {'@': 121}, {'@': 122}, {'@': 123}, {'@': 124}, {'@': 125}, {'@': 126}, {'@': 127}, {'@': 128}, {'@': 129}, {'@': 130}], 'options': {'debug': False, 'keep_all_tokens': False, 'tree_class': None, 'cache': False, 'postlex': None, 'parser': 'lalr', 'lexer': 'contextual', 'transformer': None, 'start': ['start'], 'priority': 'normal', 'ambiguity': 'auto', 'regex': False, 'propagate_positions': False, 'lexer_callbacks': {}, 'maybe_placeholders': False, 'edit_terminals': None, 'g_regex_flags': 0, 'use_bytes': False, 'import_paths': [], 'source_path': None}, '__type__': 'Lark'} +{'parser': {'lexer_conf': {'terminals': [{'@': 0}, {'@': 1}, {'@': 2}, {'@': 3}, {'@': 4}, {'@': 5}, {'@': 6}, {'@': 7}, {'@': 8}, {'@': 9}, {'@': 10}, {'@': 11}, {'@': 12}, {'@': 13}, {'@': 14}, {'@': 15}, {'@': 16}, {'@': 17}, {'@': 18}, {'@': 19}, {'@': 20}, {'@': 21}, {'@': 22}, {'@': 23}, {'@': 24}, {'@': 25}, {'@': 26}, {'@': 27}, {'@': 28}, {'@': 29}, {'@': 30}, {'@': 31}, {'@': 32}, {'@': 33}, {'@': 34}], 'ignore': ['WS'], 'g_regex_flags': 0, 'use_bytes': False, 'lexer_type': 'contextual', '__type__': 'LexerConf'}, 'parser_conf': {'rules': [{'@': 35}, {'@': 36}, {'@': 37}, {'@': 38}, {'@': 39}, {'@': 40}, {'@': 41}, {'@': 42}, {'@': 43}, {'@': 44}, {'@': 45}, {'@': 46}, {'@': 47}, {'@': 48}, {'@': 49}, {'@': 50}, {'@': 51}, {'@': 52}, {'@': 53}, {'@': 54}, {'@': 55}, {'@': 56}, {'@': 57}, {'@': 58}, {'@': 59}, {'@': 60}, {'@': 61}, {'@': 62}, {'@': 63}, {'@': 64}, {'@': 65}, {'@': 66}, {'@': 67}, {'@': 68}, {'@': 69}, {'@': 70}, {'@': 71}, {'@': 72}, {'@': 73}, {'@': 74}, {'@': 75}, {'@': 76}, {'@': 77}, {'@': 78}, {'@': 79}, {'@': 80}, {'@': 81}, {'@': 82}, {'@': 83}, {'@': 84}, {'@': 85}, {'@': 86}, {'@': 87}, {'@': 88}, {'@': 89}, {'@': 90}, {'@': 91}, {'@': 92}, {'@': 93}, {'@': 94}, {'@': 95}, {'@': 96}, {'@': 97}, {'@': 98}, {'@': 99}, {'@': 100}, {'@': 101}, {'@': 102}, {'@': 103}, {'@': 104}, {'@': 105}, {'@': 106}, {'@': 107}, {'@': 108}, {'@': 109}, {'@': 110}, {'@': 111}, {'@': 112}, {'@': 113}, {'@': 114}, {'@': 115}, {'@': 116}, {'@': 117}, {'@': 118}, {'@': 119}, {'@': 120}, {'@': 121}, {'@': 122}, {'@': 123}, {'@': 124}, {'@': 125}, {'@': 126}, {'@': 127}, {'@': 128}, {'@': 129}, {'@': 130}, {'@': 131}, {'@': 132}, {'@': 133}], 'start': ['start'], 'parser_type': 'lalr', '__type__': 'ParserConf'}, 'parser': {'tokens': {0: 'STAR', 1: 'COMMA', 2: 'RPAR', 3: 'RSQB', 4: 'TIMEDELTA64', 5: 'ESCAPED_STRING', 6: 'named_pairs', 7: 'named_key', 8: 'DATETIME64', 9: 'CNAME', 10: 'PARAMETERS', 11: 'DTYPE', 12: 'named_pair', 13: 'COLON', 14: 'LSQB', 15: '$END', 16: 'RBRACE', 17: 'SIGNED_NUMBER', 18: 'json_array', 19: 'json', 20: 'LBRACE', 21: 'json_object', 22: 'NULL', 23: 'FALSE', 24: 'TRUE', 25: 'listtype', 26: 'TUPLE', 27: 'UNION', 28: 'record', 29: 'union', 30: 'STRING', 31: 'record_parameters', 32: 'tuple', 33: 'unknowntype', 34: 'option1', 35: 'tuple_parameters', 36: 'UNKNOWN', 37: 'INT', 38: 'fixedlen_string', 39: 'numpytype_name', 40: 'list_parameters', 41: 'VAR', 42: 'OPTION', 43: 'BYTES', 44: 'byte', 45: 'LPAR', 46: 'varlen_string', 47: 'STRUCT', 48: 'char', 49: 'BYTE', 50: 'CHAR', 51: 'regulartype', 52: 'type', 53: 'numpytype', 54: 'option2', 55: 'named', 56: 'categorical', 57: 'named0', 58: 'QMARK', 59: 'CATEGORICAL', 60: 'EQUAL', 61: 'types', 62: 'start', 63: 'named_types', 64: 'json_pair', 65: '__json_object_star_3', 66: '__pairs_star_1', 67: 'pairs', 68: 'key', 69: 'pair', 70: 'TYPE', 71: '__types_star_0', 72: '__json_array_star_2'}, 'states': {0: {0: (0, 116)}, 1: {1: (0, 193), 2: (1, {'@': 75}), 3: (1, {'@': 75})}, 2: {4: (0, 105), 5: (0, 147), 6: (0, 138), 7: (0, 111), 8: (0, 95), 9: (0, 157), 10: (0, 33), 11: (0, 44), 12: (0, 63)}, 3: {13: (0, 136)}, 4: {13: (1, {'@': 106}), 1: (1, {'@': 58}), 3: (1, {'@': 58}), 14: (1, {'@': 58})}, 5: {2: (1, {'@': 55}), 1: (1, {'@': 55}), 15: (1, {'@': 55}), 16: (1, {'@': 55}), 3: (1, {'@': 55})}, 6: {1: (1, {'@': 123}), 3: (1, {'@': 123}), 16: (1, {'@': 123})}, 7: {17: (0, 31), 18: (0, 36), 14: (0, 156), 19: (0, 70), 20: (0, 148), 21: (0, 187), 22: (0, 151), 23: (0, 166), 24: (0, 24), 5: (0, 11)}, 8: {1: (0, 120), 3: (1, {'@': 98})}, 9: {21: (0, 46), 20: (0, 148)}, 10: {2: (1, {'@': 67}), 1: (1, {'@': 67}), 15: (1, {'@': 67}), 16: (1, {'@': 67}), 3: (1, {'@': 67})}, 11: {1: (1, {'@': 112}), 3: (1, {'@': 112}), 16: (1, {'@': 112})}, 12: {3: (0, 90)}, 13: {25: (0, 104), 26: (0, 106), 27: (0, 122), 28: (0, 160), 29: (0, 159), 30: (0, 39), 31: (0, 127), 32: (0, 92), 20: (0, 163), 33: (0, 102), 9: (0, 146), 34: (0, 144), 35: (0, 60), 36: (0, 58), 37: (0, 198), 38: (0, 50), 39: (0, 188), 40: (0, 51), 41: (0, 0), 42: (0, 203), 4: (0, 101), 43: (0, 154), 44: (0, 207), 45: (0, 16), 46: (0, 61), 47: (0, 40), 48: (0, 184), 49: (0, 202), 50: (0, 195), 51: (0, 167), 52: (0, 17), 53: (0, 152), 54: (0, 145), 11: (0, 129), 8: (0, 109), 55: (0, 117), 14: (0, 91), 56: (0, 77), 57: (0, 74), 58: (0, 22), 59: (0, 180)}, 14: {20: (0, 148), 21: (0, 83)}, 15: {60: (0, 30)}, 16: {25: (0, 104), 26: (0, 106), 27: (0, 122), 28: (0, 160), 61: (0, 98), 29: (0, 159), 30: (0, 39), 31: (0, 127), 32: (0, 92), 20: (0, 163), 33: (0, 102), 9: (0, 146), 34: (0, 144), 35: (0, 60), 36: (0, 58), 37: (0, 198), 38: (0, 50), 39: (0, 188), 40: (0, 51), 2: (0, 21), 41: (0, 0), 42: (0, 203), 4: (0, 101), 43: (0, 154), 52: (0, 134), 44: (0, 207), 45: (0, 16), 46: (0, 61), 47: (0, 40), 48: (0, 184), 49: (0, 202), 50: (0, 195), 51: (0, 167), 53: (0, 152), 54: (0, 145), 11: (0, 129), 8: (0, 109), 55: (0, 117), 14: (0, 91), 56: (0, 77), 57: (0, 74), 58: (0, 22), 59: (0, 180)}, 17: {2: (1, {'@': 62}), 1: (1, {'@': 62}), 15: (1, {'@': 62}), 16: (1, {'@': 62}), 3: (1, {'@': 62})}, 18: {26: (0, 106), 25: (0, 104), 27: (0, 122), 28: (0, 160), 29: (0, 159), 31: (0, 127), 20: (0, 163), 32: (0, 92), 30: (0, 39), 9: (0, 146), 33: (0, 102), 34: (0, 144), 35: (0, 60), 36: (0, 58), 37: (0, 198), 38: (0, 50), 39: (0, 188), 40: (0, 51), 41: (0, 0), 42: (0, 203), 4: (0, 101), 43: (0, 154), 44: (0, 207), 45: (0, 16), 46: (0, 61), 47: (0, 40), 48: (0, 184), 49: (0, 202), 50: (0, 195), 51: (0, 167), 53: (0, 152), 54: (0, 145), 11: (0, 129), 52: (0, 81), 8: (0, 109), 55: (0, 117), 59: (0, 180), 14: (0, 91), 56: (0, 77), 57: (0, 74), 58: (0, 22)}, 19: {14: (0, 76), 13: (1, {'@': 104})}, 20: {1: (1, {'@': 119}), 3: (1, {'@': 119}), 16: (1, {'@': 119})}, 21: {2: (1, {'@': 74}), 1: (1, {'@': 74}), 15: (1, {'@': 74}), 16: (1, {'@': 74}), 3: (1, {'@': 74})}, 22: {25: (0, 104), 26: (0, 106), 27: (0, 122), 28: (0, 160), 29: (0, 159), 30: (0, 39), 31: (0, 127), 32: (0, 92), 20: (0, 163), 33: (0, 102), 9: (0, 146), 34: (0, 144), 35: (0, 60), 36: (0, 58), 37: (0, 198), 38: (0, 50), 39: (0, 188), 40: (0, 51), 41: (0, 0), 42: (0, 203), 4: (0, 101), 43: (0, 154), 44: (0, 207), 45: (0, 16), 46: (0, 61), 47: (0, 40), 48: (0, 184), 49: (0, 202), 52: (0, 125), 50: (0, 195), 51: (0, 167), 53: (0, 152), 54: (0, 145), 11: (0, 129), 8: (0, 109), 55: (0, 117), 14: (0, 91), 56: (0, 77), 57: (0, 74), 58: (0, 22), 59: (0, 180)}, 23: {13: (1, {'@': 107}), 1: (1, {'@': 59}), 3: (1, {'@': 59}), 14: (1, {'@': 59})}, 24: {1: (1, {'@': 114}), 3: (1, {'@': 114}), 16: (1, {'@': 114})}, 25: {25: (0, 104), 26: (0, 106), 27: (0, 122), 28: (0, 160), 29: (0, 159), 31: (0, 127), 32: (0, 92), 30: (0, 39), 20: (0, 163), 33: (0, 102), 9: (0, 146), 34: (0, 144), 35: (0, 60), 36: (0, 58), 37: (0, 198), 38: (0, 50), 39: (0, 188), 40: (0, 51), 41: (0, 0), 42: (0, 203), 4: (0, 101), 43: (0, 154), 44: (0, 207), 45: (0, 16), 46: (0, 61), 47: (0, 40), 48: (0, 184), 49: (0, 202), 50: (0, 195), 51: (0, 167), 53: (0, 152), 54: (0, 145), 11: (0, 129), 59: (0, 180), 55: (0, 117), 8: (0, 109), 14: (0, 91), 56: (0, 77), 57: (0, 74), 62: (0, 73), 58: (0, 22), 52: (0, 67)}, 26: {17: (0, 31), 19: (0, 201), 18: (0, 36), 14: (0, 156), 20: (0, 148), 21: (0, 187), 22: (0, 151), 23: (0, 166), 24: (0, 24), 5: (0, 11)}, 27: {2: (1, {'@': 109}), 1: (1, {'@': 109}), 15: (1, {'@': 109}), 16: (1, {'@': 109}), 3: (1, {'@': 109})}, 28: {2: (1, {'@': 72}), 1: (1, {'@': 72}), 15: (1, {'@': 72}), 16: (1, {'@': 72}), 3: (1, {'@': 72})}, 29: {60: (0, 196)}, 30: {20: (0, 148), 21: (0, 64)}, 31: {1: (1, {'@': 113}), 3: (1, {'@': 113}), 16: (1, {'@': 113})}, 32: {2: (1, {'@': 78}), 1: (1, {'@': 78}), 15: (1, {'@': 78}), 16: (1, {'@': 78}), 3: (1, {'@': 78})}, 33: {60: (0, 43)}, 34: {1: (1, {'@': 124}), 3: (1, {'@': 124}), 16: (1, {'@': 124})}, 35: {2: (1, {'@': 93}), 1: (1, {'@': 93}), 15: (1, {'@': 93}), 16: (1, {'@': 93}), 3: (1, {'@': 93})}, 36: {1: (1, {'@': 117}), 3: (1, {'@': 117}), 16: (1, {'@': 117})}, 37: {2: (1, {'@': 111}), 1: (1, {'@': 111}), 15: (1, {'@': 111}), 16: (1, {'@': 111}), 3: (1, {'@': 111})}, 38: {3: (0, 10)}, 39: {14: (0, 175), 2: (1, {'@': 64}), 1: (1, {'@': 64}), 15: (1, {'@': 64}), 16: (1, {'@': 64}), 3: (1, {'@': 64})}, 40: {14: (0, 107)}, 41: {20: (0, 148), 21: (0, 194)}, 42: {1: (0, 112), 16: (1, {'@': 83})}, 43: {20: (0, 148), 21: (0, 72)}, 44: {13: (1, {'@': 105})}, 45: {10: (0, 75)}, 46: {3: (0, 131)}, 47: {16: (0, 158)}, 48: {60: (0, 9)}, 49: {20: (0, 148), 21: (0, 54)}, 50: {2: (1, {'@': 41}), 1: (1, {'@': 41}), 15: (1, {'@': 41}), 16: (1, {'@': 41}), 3: (1, {'@': 41})}, 51: {2: (1, {'@': 53}), 1: (1, {'@': 53}), 15: (1, {'@': 53}), 16: (1, {'@': 53}), 3: (1, {'@': 53})}, 52: {3: (0, 37)}, 53: {16: (0, 143), 1: (0, 177)}, 54: {3: (0, 173)}, 55: {60: (0, 62)}, 56: {2: (1, {'@': 60}), 1: (1, {'@': 60}), 15: (1, {'@': 60}), 16: (1, {'@': 60}), 3: (1, {'@': 60})}, 57: {60: (0, 49)}, 58: {14: (0, 94), 2: (1, {'@': 61}), 1: (1, {'@': 61}), 15: (1, {'@': 61}), 16: (1, {'@': 61}), 3: (1, {'@': 61})}, 59: {60: (0, 97)}, 60: {2: (1, {'@': 47}), 1: (1, {'@': 47}), 15: (1, {'@': 47}), 16: (1, {'@': 47}), 3: (1, {'@': 47})}, 61: {2: (1, {'@': 40}), 1: (1, {'@': 40}), 15: (1, {'@': 40}), 16: (1, {'@': 40}), 3: (1, {'@': 40})}, 62: {20: (0, 148), 21: (0, 124)}, 63: {1: (0, 2), 3: (1, {'@': 101})}, 64: {3: (0, 65)}, 65: {2: (1, {'@': 110}), 1: (1, {'@': 110}), 15: (1, {'@': 110}), 16: (1, {'@': 110}), 3: (1, {'@': 110})}, 66: {2: (1, {'@': 81}), 1: (1, {'@': 81}), 15: (1, {'@': 81}), 16: (1, {'@': 81}), 3: (1, {'@': 81})}, 67: {15: (1, {'@': 35})}, 68: {2: (1, {'@': 82}), 1: (1, {'@': 82}), 15: (1, {'@': 82}), 16: (1, {'@': 82}), 3: (1, {'@': 82})}, 69: {1: (0, 26), 3: (0, 20)}, 70: {1: (1, {'@': 130}), 3: (1, {'@': 130})}, 71: {20: (0, 148), 21: (0, 12)}, 72: {3: (1, {'@': 100})}, 73: {}, 74: {2: (1, {'@': 50}), 1: (1, {'@': 50}), 15: (1, {'@': 50}), 16: (1, {'@': 50}), 3: (1, {'@': 50})}, 75: {60: (0, 71)}, 76: {26: (0, 106), 3: (0, 35), 28: (0, 160), 29: (0, 159), 31: (0, 127), 20: (0, 163), 9: (0, 19), 12: (0, 63), 4: (0, 23), 5: (0, 147), 36: (0, 58), 37: (0, 198), 8: (0, 4), 38: (0, 50), 40: (0, 51), 44: (0, 207), 42: (0, 203), 46: (0, 61), 47: (0, 40), 27: (0, 122), 10: (0, 29), 7: (0, 111), 52: (0, 8), 6: (0, 93), 53: (0, 152), 54: (0, 145), 11: (0, 103), 63: (0, 84), 14: (0, 91), 57: (0, 74), 58: (0, 22), 30: (0, 39), 25: (0, 104), 32: (0, 92), 33: (0, 102), 34: (0, 144), 35: (0, 60), 39: (0, 188), 41: (0, 0), 43: (0, 154), 45: (0, 16), 48: (0, 184), 49: (0, 202), 50: (0, 195), 51: (0, 167), 55: (0, 117), 56: (0, 77), 59: (0, 180)}, 77: {2: (1, {'@': 54}), 1: (1, {'@': 54}), 15: (1, {'@': 54}), 16: (1, {'@': 54}), 3: (1, {'@': 54})}, 78: {64: (0, 200), 5: (0, 3)}, 79: {2: (1, {'@': 79}), 1: (1, {'@': 79}), 15: (1, {'@': 79}), 16: (1, {'@': 79}), 3: (1, {'@': 79})}, 80: {2: (1, {'@': 126}), 1: (1, {'@': 126}), 3: (1, {'@': 126})}, 81: {3: (0, 28), 1: (0, 45)}, 82: {3: (0, 164)}, 83: {3: (0, 79)}, 84: {3: (0, 174)}, 85: {1: (0, 78), 65: (0, 53), 16: (0, 6)}, 86: {1: (0, 155), 66: (0, 42), 16: (1, {'@': 84})}, 87: {67: (0, 47), 16: (0, 99), 68: (0, 191), 69: (0, 86), 9: (0, 115), 5: (0, 132)}, 88: {2: (1, {'@': 80}), 1: (1, {'@': 80}), 15: (1, {'@': 80}), 16: (1, {'@': 80}), 3: (1, {'@': 80})}, 89: {3: (0, 32), 1: (0, 130)}, 90: {2: (1, {'@': 71}), 1: (1, {'@': 71}), 15: (1, {'@': 71}), 16: (1, {'@': 71}), 3: (1, {'@': 71})}, 91: {25: (0, 104), 26: (0, 106), 27: (0, 122), 28: (0, 160), 29: (0, 159), 30: (0, 39), 31: (0, 127), 32: (0, 92), 20: (0, 163), 33: (0, 102), 9: (0, 146), 34: (0, 144), 35: (0, 60), 36: (0, 58), 37: (0, 198), 38: (0, 50), 39: (0, 188), 40: (0, 51), 41: (0, 0), 42: (0, 203), 4: (0, 101), 43: (0, 154), 44: (0, 207), 45: (0, 16), 46: (0, 61), 47: (0, 40), 48: (0, 184), 52: (0, 110), 49: (0, 202), 50: (0, 195), 51: (0, 167), 53: (0, 152), 54: (0, 145), 11: (0, 129), 8: (0, 109), 55: (0, 117), 14: (0, 91), 56: (0, 77), 57: (0, 74), 58: (0, 22), 59: (0, 180)}, 92: {2: (1, {'@': 46}), 1: (1, {'@': 46}), 15: (1, {'@': 46}), 16: (1, {'@': 46}), 3: (1, {'@': 46})}, 93: {3: (0, 204)}, 94: {10: (0, 161)}, 95: {13: (1, {'@': 106})}, 96: {2: (1, {'@': 63}), 1: (1, {'@': 63}), 15: (1, {'@': 63}), 16: (1, {'@': 63}), 3: (1, {'@': 63})}, 97: {25: (0, 104), 26: (0, 106), 27: (0, 122), 28: (0, 160), 29: (0, 159), 30: (0, 39), 31: (0, 127), 32: (0, 92), 20: (0, 163), 33: (0, 102), 9: (0, 146), 34: (0, 144), 35: (0, 60), 36: (0, 58), 37: (0, 198), 38: (0, 50), 39: (0, 188), 40: (0, 51), 41: (0, 0), 42: (0, 203), 4: (0, 101), 43: (0, 154), 44: (0, 207), 45: (0, 16), 46: (0, 61), 47: (0, 40), 48: (0, 184), 49: (0, 202), 50: (0, 195), 51: (0, 167), 52: (0, 52), 53: (0, 152), 54: (0, 145), 11: (0, 129), 8: (0, 109), 55: (0, 117), 14: (0, 91), 56: (0, 77), 57: (0, 74), 58: (0, 22), 59: (0, 180)}, 98: {2: (0, 169)}, 99: {3: (0, 108), 1: (0, 162)}, 100: {2: (1, {'@': 88}), 1: (1, {'@': 88}), 15: (1, {'@': 88}), 16: (1, {'@': 88}), 3: (1, {'@': 88})}, 101: {2: (1, {'@': 59}), 15: (1, {'@': 59}), 1: (1, {'@': 59}), 14: (1, {'@': 59}), 16: (1, {'@': 59}), 3: (1, {'@': 59})}, 102: {2: (1, {'@': 37}), 1: (1, {'@': 37}), 15: (1, {'@': 37}), 16: (1, {'@': 37}), 3: (1, {'@': 37})}, 103: {13: (1, {'@': 105}), 1: (1, {'@': 57}), 3: (1, {'@': 57}), 14: (1, {'@': 57})}, 104: {2: (1, {'@': 39}), 1: (1, {'@': 39}), 15: (1, {'@': 39}), 16: (1, {'@': 39}), 3: (1, {'@': 39})}, 105: {13: (1, {'@': 107})}, 106: {14: (0, 168)}, 107: {20: (0, 87)}, 108: {2: (1, {'@': 91}), 1: (1, {'@': 91}), 15: (1, {'@': 91}), 16: (1, {'@': 91}), 3: (1, {'@': 91})}, 109: {2: (1, {'@': 58}), 15: (1, {'@': 58}), 1: (1, {'@': 58}), 14: (1, {'@': 58}), 16: (1, {'@': 58}), 3: (1, {'@': 58})}, 110: {1: (0, 149)}, 111: {13: (0, 178)}, 112: {69: (0, 170), 68: (0, 191), 5: (0, 132), 9: (0, 115)}, 113: {10: (0, 199)}, 114: {16: (1, {'@': 125}), 1: (1, {'@': 125})}, 115: {13: (1, {'@': 87})}, 116: {25: (0, 104), 26: (0, 106), 27: (0, 122), 28: (0, 160), 29: (0, 159), 30: (0, 39), 31: (0, 127), 32: (0, 92), 20: (0, 163), 33: (0, 102), 9: (0, 146), 34: (0, 144), 35: (0, 60), 36: (0, 58), 37: (0, 198), 38: (0, 50), 39: (0, 188), 40: (0, 51), 41: (0, 0), 42: (0, 203), 4: (0, 101), 43: (0, 154), 44: (0, 207), 45: (0, 16), 46: (0, 61), 47: (0, 40), 48: (0, 184), 49: (0, 202), 50: (0, 195), 51: (0, 167), 53: (0, 152), 54: (0, 145), 52: (0, 96), 11: (0, 129), 8: (0, 109), 55: (0, 117), 14: (0, 91), 56: (0, 77), 57: (0, 74), 58: (0, 22), 59: (0, 180)}, 117: {2: (1, {'@': 51}), 1: (1, {'@': 51}), 15: (1, {'@': 51}), 16: (1, {'@': 51}), 3: (1, {'@': 51})}, 118: {16: (1, {'@': 133}), 1: (1, {'@': 133})}, 119: {70: (0, 59)}, 120: {25: (0, 104), 52: (0, 8), 26: (0, 106), 27: (0, 122), 28: (0, 160), 29: (0, 159), 30: (0, 39), 31: (0, 127), 32: (0, 92), 20: (0, 163), 33: (0, 102), 9: (0, 146), 34: (0, 144), 35: (0, 60), 36: (0, 58), 37: (0, 198), 38: (0, 50), 39: (0, 188), 40: (0, 51), 41: (0, 0), 63: (0, 142), 42: (0, 203), 4: (0, 101), 43: (0, 154), 44: (0, 207), 45: (0, 16), 46: (0, 61), 47: (0, 40), 48: (0, 184), 49: (0, 202), 50: (0, 195), 51: (0, 167), 53: (0, 152), 54: (0, 145), 11: (0, 129), 59: (0, 180), 55: (0, 117), 8: (0, 109), 14: (0, 91), 56: (0, 77), 57: (0, 74), 58: (0, 22), 10: (0, 121)}, 121: {60: (0, 41)}, 122: {14: (0, 181)}, 123: {16: (1, {'@': 128}), 1: (1, {'@': 128})}, 124: {3: (0, 5)}, 125: {2: (1, {'@': 70}), 1: (1, {'@': 70}), 15: (1, {'@': 70}), 16: (1, {'@': 70}), 3: (1, {'@': 70})}, 126: {2: (1, {'@': 89}), 1: (1, {'@': 89}), 15: (1, {'@': 89}), 16: (1, {'@': 89}), 3: (1, {'@': 89})}, 127: {2: (1, {'@': 49}), 1: (1, {'@': 49}), 15: (1, {'@': 49}), 16: (1, {'@': 49}), 3: (1, {'@': 49})}, 128: {26: (0, 106), 25: (0, 104), 3: (0, 205), 27: (0, 122), 28: (0, 160), 29: (0, 159), 31: (0, 127), 20: (0, 163), 32: (0, 92), 30: (0, 39), 9: (0, 146), 33: (0, 102), 34: (0, 144), 61: (0, 135), 35: (0, 60), 36: (0, 58), 37: (0, 198), 38: (0, 50), 39: (0, 188), 40: (0, 51), 41: (0, 0), 42: (0, 203), 4: (0, 101), 43: (0, 154), 44: (0, 207), 52: (0, 134), 45: (0, 16), 46: (0, 61), 47: (0, 40), 48: (0, 184), 49: (0, 202), 50: (0, 195), 51: (0, 167), 53: (0, 152), 54: (0, 145), 11: (0, 129), 8: (0, 109), 55: (0, 117), 59: (0, 180), 14: (0, 91), 56: (0, 77), 57: (0, 74), 58: (0, 22)}, 129: {2: (1, {'@': 57}), 15: (1, {'@': 57}), 1: (1, {'@': 57}), 14: (1, {'@': 57}), 16: (1, {'@': 57}), 3: (1, {'@': 57})}, 130: {10: (0, 57)}, 131: {2: (1, {'@': 90}), 1: (1, {'@': 90}), 15: (1, {'@': 90}), 16: (1, {'@': 90}), 3: (1, {'@': 90})}, 132: {13: (1, {'@': 86})}, 133: {2: (1, {'@': 108}), 1: (1, {'@': 108}), 15: (1, {'@': 108}), 16: (1, {'@': 108}), 3: (1, {'@': 108})}, 134: {71: (0, 1), 1: (0, 183), 2: (1, {'@': 76}), 3: (1, {'@': 76})}, 135: {3: (0, 89)}, 136: {17: (0, 31), 18: (0, 36), 14: (0, 156), 19: (0, 114), 20: (0, 148), 21: (0, 187), 22: (0, 151), 23: (0, 166), 24: (0, 24), 5: (0, 11)}, 137: {37: (0, 38)}, 138: {3: (1, {'@': 99})}, 139: {25: (0, 104), 26: (0, 106), 27: (0, 122), 28: (0, 160), 29: (0, 159), 30: (0, 39), 31: (0, 127), 32: (0, 92), 20: (0, 163), 33: (0, 102), 9: (0, 146), 34: (0, 144), 35: (0, 60), 36: (0, 58), 37: (0, 198), 38: (0, 50), 39: (0, 188), 40: (0, 51), 41: (0, 0), 42: (0, 203), 4: (0, 101), 43: (0, 154), 44: (0, 207), 45: (0, 16), 46: (0, 61), 47: (0, 40), 48: (0, 184), 49: (0, 202), 50: (0, 195), 51: (0, 167), 53: (0, 152), 54: (0, 145), 11: (0, 129), 8: (0, 109), 55: (0, 117), 14: (0, 91), 56: (0, 77), 52: (0, 185), 57: (0, 74), 58: (0, 22), 59: (0, 180)}, 140: {10: (0, 55)}, 141: {16: (0, 66)}, 142: {3: (1, {'@': 96})}, 143: {1: (1, {'@': 122}), 3: (1, {'@': 122}), 16: (1, {'@': 122})}, 144: {2: (1, {'@': 44}), 1: (1, {'@': 44}), 15: (1, {'@': 44}), 16: (1, {'@': 44}), 3: (1, {'@': 44})}, 145: {2: (1, {'@': 45}), 1: (1, {'@': 45}), 15: (1, {'@': 45}), 16: (1, {'@': 45}), 3: (1, {'@': 45})}, 146: {14: (0, 76)}, 147: {13: (1, {'@': 103})}, 148: {64: (0, 85), 16: (0, 34), 5: (0, 3)}, 149: {10: (0, 15)}, 150: {60: (0, 189)}, 151: {1: (1, {'@': 116}), 3: (1, {'@': 116}), 16: (1, {'@': 116})}, 152: {2: (1, {'@': 36}), 1: (1, {'@': 36}), 15: (1, {'@': 36}), 16: (1, {'@': 36}), 3: (1, {'@': 36})}, 153: {2: (1, {'@': 66}), 1: (1, {'@': 66}), 15: (1, {'@': 66}), 16: (1, {'@': 66}), 3: (1, {'@': 66})}, 154: {14: (0, 137), 2: (1, {'@': 65}), 1: (1, {'@': 65}), 15: (1, {'@': 65}), 16: (1, {'@': 65}), 3: (1, {'@': 65})}, 155: {5: (0, 132), 9: (0, 115), 68: (0, 191), 69: (0, 123)}, 156: {17: (0, 31), 18: (0, 36), 19: (0, 182), 20: (0, 148), 21: (0, 187), 5: (0, 11), 14: (0, 156), 22: (0, 151), 23: (0, 166), 24: (0, 24), 3: (0, 172)}, 157: {13: (1, {'@': 104})}, 158: {3: (0, 126), 1: (0, 186)}, 159: {2: (1, {'@': 52}), 1: (1, {'@': 52}), 15: (1, {'@': 52}), 16: (1, {'@': 52}), 3: (1, {'@': 52})}, 160: {2: (1, {'@': 48}), 1: (1, {'@': 48}), 15: (1, {'@': 48}), 16: (1, {'@': 48}), 3: (1, {'@': 48})}, 161: {60: (0, 171)}, 162: {10: (0, 48)}, 163: {68: (0, 191), 5: (0, 132), 16: (0, 68), 69: (0, 86), 67: (0, 141), 9: (0, 115)}, 164: {2: (1, {'@': 92}), 1: (1, {'@': 92}), 15: (1, {'@': 92}), 16: (1, {'@': 92}), 3: (1, {'@': 92})}, 165: {3: (0, 133)}, 166: {1: (1, {'@': 115}), 3: (1, {'@': 115}), 16: (1, {'@': 115})}, 167: {2: (1, {'@': 38}), 1: (1, {'@': 38}), 15: (1, {'@': 38}), 16: (1, {'@': 38}), 3: (1, {'@': 38})}, 168: {14: (0, 128)}, 169: {2: (1, {'@': 73}), 1: (1, {'@': 73}), 15: (1, {'@': 73}), 16: (1, {'@': 73}), 3: (1, {'@': 73})}, 170: {16: (1, {'@': 129}), 1: (1, {'@': 129})}, 171: {20: (0, 148), 21: (0, 179)}, 172: {1: (1, {'@': 121}), 3: (1, {'@': 121}), 16: (1, {'@': 121})}, 173: {2: (1, {'@': 77}), 1: (1, {'@': 77}), 15: (1, {'@': 77}), 16: (1, {'@': 77}), 3: (1, {'@': 77})}, 174: {2: (1, {'@': 94}), 1: (1, {'@': 94}), 15: (1, {'@': 94}), 16: (1, {'@': 94}), 3: (1, {'@': 94})}, 175: {37: (0, 192)}, 176: {2: (1, {'@': 127}), 1: (1, {'@': 127}), 3: (1, {'@': 127})}, 177: {64: (0, 118), 5: (0, 3)}, 178: {25: (0, 104), 26: (0, 106), 27: (0, 122), 28: (0, 160), 29: (0, 159), 30: (0, 39), 31: (0, 127), 32: (0, 92), 20: (0, 163), 33: (0, 102), 9: (0, 146), 34: (0, 144), 35: (0, 60), 36: (0, 58), 37: (0, 198), 38: (0, 50), 39: (0, 188), 40: (0, 51), 41: (0, 0), 42: (0, 203), 4: (0, 101), 43: (0, 154), 44: (0, 207), 45: (0, 16), 46: (0, 61), 47: (0, 40), 48: (0, 184), 49: (0, 202), 50: (0, 195), 51: (0, 167), 53: (0, 152), 54: (0, 145), 11: (0, 129), 8: (0, 109), 55: (0, 117), 14: (0, 91), 56: (0, 77), 57: (0, 74), 58: (0, 22), 52: (0, 190), 59: (0, 180)}, 179: {3: (0, 56)}, 180: {14: (0, 119)}, 181: {25: (0, 104), 52: (0, 8), 26: (0, 106), 27: (0, 122), 28: (0, 160), 29: (0, 159), 30: (0, 39), 31: (0, 127), 32: (0, 92), 20: (0, 163), 33: (0, 102), 9: (0, 146), 34: (0, 144), 35: (0, 60), 36: (0, 58), 37: (0, 198), 38: (0, 50), 39: (0, 188), 40: (0, 51), 41: (0, 0), 42: (0, 203), 4: (0, 101), 43: (0, 154), 63: (0, 165), 44: (0, 207), 45: (0, 16), 46: (0, 61), 47: (0, 40), 48: (0, 184), 49: (0, 202), 50: (0, 195), 51: (0, 167), 53: (0, 152), 54: (0, 145), 11: (0, 129), 8: (0, 109), 55: (0, 117), 14: (0, 91), 56: (0, 77), 3: (0, 27), 57: (0, 74), 58: (0, 22), 59: (0, 180)}, 182: {3: (0, 206), 1: (0, 7), 72: (0, 69)}, 183: {25: (0, 104), 26: (0, 106), 27: (0, 122), 28: (0, 160), 29: (0, 159), 30: (0, 39), 31: (0, 127), 32: (0, 92), 20: (0, 163), 33: (0, 102), 9: (0, 146), 52: (0, 80), 34: (0, 144), 35: (0, 60), 36: (0, 58), 37: (0, 198), 38: (0, 50), 39: (0, 188), 40: (0, 51), 41: (0, 0), 42: (0, 203), 4: (0, 101), 43: (0, 154), 44: (0, 207), 45: (0, 16), 46: (0, 61), 47: (0, 40), 48: (0, 184), 49: (0, 202), 50: (0, 195), 51: (0, 167), 53: (0, 152), 54: (0, 145), 11: (0, 129), 8: (0, 109), 55: (0, 117), 14: (0, 91), 56: (0, 77), 57: (0, 74), 58: (0, 22), 59: (0, 180)}, 184: {2: (1, {'@': 42}), 1: (1, {'@': 42}), 15: (1, {'@': 42}), 16: (1, {'@': 42}), 3: (1, {'@': 42})}, 185: {16: (1, {'@': 85}), 1: (1, {'@': 85})}, 186: {10: (0, 150)}, 187: {1: (1, {'@': 118}), 3: (1, {'@': 118}), 16: (1, {'@': 118})}, 188: {14: (0, 140), 2: (1, {'@': 56}), 1: (1, {'@': 56}), 15: (1, {'@': 56}), 16: (1, {'@': 56}), 3: (1, {'@': 56})}, 189: {21: (0, 197), 20: (0, 148)}, 190: {1: (1, {'@': 102}), 3: (1, {'@': 102})}, 191: {13: (0, 139)}, 192: {3: (0, 153)}, 193: {25: (0, 104), 26: (0, 106), 27: (0, 122), 28: (0, 160), 29: (0, 159), 30: (0, 39), 52: (0, 176), 31: (0, 127), 32: (0, 92), 20: (0, 163), 33: (0, 102), 9: (0, 146), 34: (0, 144), 35: (0, 60), 36: (0, 58), 37: (0, 198), 38: (0, 50), 39: (0, 188), 40: (0, 51), 41: (0, 0), 42: (0, 203), 4: (0, 101), 43: (0, 154), 44: (0, 207), 45: (0, 16), 46: (0, 61), 47: (0, 40), 48: (0, 184), 49: (0, 202), 50: (0, 195), 51: (0, 167), 53: (0, 152), 54: (0, 145), 11: (0, 129), 8: (0, 109), 55: (0, 117), 14: (0, 91), 56: (0, 77), 57: (0, 74), 58: (0, 22), 59: (0, 180)}, 194: {3: (1, {'@': 97})}, 195: {2: (1, {'@': 68}), 1: (1, {'@': 68}), 15: (1, {'@': 68}), 16: (1, {'@': 68}), 3: (1, {'@': 68})}, 196: {21: (0, 82), 20: (0, 148)}, 197: {3: (0, 100)}, 198: {0: (0, 13)}, 199: {60: (0, 14)}, 200: {16: (1, {'@': 132}), 1: (1, {'@': 132})}, 201: {1: (1, {'@': 131}), 3: (1, {'@': 131})}, 202: {2: (1, {'@': 69}), 1: (1, {'@': 69}), 15: (1, {'@': 69}), 16: (1, {'@': 69}), 3: (1, {'@': 69})}, 203: {14: (0, 18)}, 204: {2: (1, {'@': 95}), 1: (1, {'@': 95}), 15: (1, {'@': 95}), 16: (1, {'@': 95}), 3: (1, {'@': 95})}, 205: {1: (0, 113), 3: (0, 88)}, 206: {1: (1, {'@': 120}), 3: (1, {'@': 120}), 16: (1, {'@': 120})}, 207: {2: (1, {'@': 43}), 1: (1, {'@': 43}), 15: (1, {'@': 43}), 16: (1, {'@': 43}), 3: (1, {'@': 43})}}, 'start_states': {'start': 25}, 'end_states': {'start': 73}}, 'options': {'debug': False, 'keep_all_tokens': False, 'tree_class': None, 'cache': False, 'postlex': None, 'parser': 'lalr', 'lexer': 'contextual', 'transformer': None, 'start': ['start'], 'priority': 'normal', 'ambiguity': 'auto', 'regex': False, 'propagate_positions': False, 'lexer_callbacks': {}, 'maybe_placeholders': False, 'edit_terminals': None, 'g_regex_flags': 0, 'use_bytes': False, 'import_paths': [], 'source_path': None}, '__type__': 'ParsingFrontend'}, 'rules': [{'@': 35}, {'@': 36}, {'@': 37}, {'@': 38}, {'@': 39}, {'@': 40}, {'@': 41}, {'@': 42}, {'@': 43}, {'@': 44}, {'@': 45}, {'@': 46}, {'@': 47}, {'@': 48}, {'@': 49}, {'@': 50}, {'@': 51}, {'@': 52}, {'@': 53}, {'@': 54}, {'@': 55}, {'@': 56}, {'@': 57}, {'@': 58}, {'@': 59}, {'@': 60}, {'@': 61}, {'@': 62}, {'@': 63}, {'@': 64}, {'@': 65}, {'@': 66}, {'@': 67}, {'@': 68}, {'@': 69}, {'@': 70}, {'@': 71}, {'@': 72}, {'@': 73}, {'@': 74}, {'@': 75}, {'@': 76}, {'@': 77}, {'@': 78}, {'@': 79}, {'@': 80}, {'@': 81}, {'@': 82}, {'@': 83}, {'@': 84}, {'@': 85}, {'@': 86}, {'@': 87}, {'@': 88}, {'@': 89}, {'@': 90}, {'@': 91}, {'@': 92}, {'@': 93}, {'@': 94}, {'@': 95}, {'@': 96}, {'@': 97}, {'@': 98}, {'@': 99}, {'@': 100}, {'@': 101}, {'@': 102}, {'@': 103}, {'@': 104}, {'@': 105}, {'@': 106}, {'@': 107}, {'@': 108}, {'@': 109}, {'@': 110}, {'@': 111}, {'@': 112}, {'@': 113}, {'@': 114}, {'@': 115}, {'@': 116}, {'@': 117}, {'@': 118}, {'@': 119}, {'@': 120}, {'@': 121}, {'@': 122}, {'@': 123}, {'@': 124}, {'@': 125}, {'@': 126}, {'@': 127}, {'@': 128}, {'@': 129}, {'@': 130}, {'@': 131}, {'@': 132}, {'@': 133}], 'options': {'debug': False, 'keep_all_tokens': False, 'tree_class': None, 'cache': False, 'postlex': None, 'parser': 'lalr', 'lexer': 'contextual', 'transformer': None, 'start': ['start'], 'priority': 'normal', 'ambiguity': 'auto', 'regex': False, 'propagate_positions': False, 'lexer_callbacks': {}, 'maybe_placeholders': False, 'edit_terminals': None, 'g_regex_flags': 0, 'use_bytes': False, 'import_paths': [], 'source_path': None}, '__type__': 'Lark'} ) MEMO = ( -{0: {'name': 'INT', 'pattern': {'value': '(?:[0-9])+', 'flags': [], '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 1, '__type__': 'TerminalDef'}, 1: {'name': 'SIGNED_NUMBER', 'pattern': {'value': '(?:(?:\\+|\\-))?(?:(?:(?:[0-9])+(?:e|E)(?:(?:\\+|\\-))?(?:[0-9])+|(?:(?:[0-9])+\\.(?:(?:[0-9])+)?|\\.(?:[0-9])+)(?:(?:e|E)(?:(?:\\+|\\-))?(?:[0-9])+)?)|(?:[0-9])+)', 'flags': [], '_width': [1, 4294967295], '__type__': 'PatternRE'}, 'priority': 1, '__type__': 'TerminalDef'}, 2: {'name': 'ESCAPED_STRING', 'pattern': {'value': '".*?(? list[str "categorical", ) or name in ak.types.numpytype._primitive_to_dtype_dict + # the grammar reserves these on every platform + or name in ("float128", "complex256") ): if params is None: params = 'parameters={"__record__": ' + json.dumps(name) + "}" diff --git a/tests/test_4390_all_numpy_numeric_dtypes.py b/tests/test_4390_all_numpy_numeric_dtypes.py new file mode 100644 index 0000000000..d927a59f44 --- /dev/null +++ b/tests/test_4390_all_numpy_numeric_dtypes.py @@ -0,0 +1,127 @@ +# BSD 3-Clause License; see https://github.com/CoffeaTeam/awkward-lite/blob/main/LICENSE + +from __future__ import annotations + +import numpy as np +import pytest + +import awkward as ak +from awkward.types import ( + ArrayType, + ListType, + NumpyType, + OptionType, + RecordType, + RegularType, + ScalarType, + UnionType, +) +from awkward.types.numpytype import _primitive_to_dtype_dict + +PRIMITIVES = list(_primitive_to_dtype_dict) + +CONTEXTS = [ + ("{}", lambda t: t), + ("var * {}", ListType), + ("3 * {}", lambda t: RegularType(t, 3)), + ("?{}", OptionType), + ("option[var * {}]", lambda t: OptionType(ListType(t))), + ("{{x: {}}}", lambda t: RecordType([t], ["x"])), + ("({}, int64)", lambda t: RecordType([t, NumpyType("int64")], None)), + ( + "union[{}, var * int64]", + lambda t: UnionType([t, ListType(NumpyType("int64"))]), + ), + ( + "Name[x: {}]", + lambda t: RecordType([t], ["x"], parameters={"__record__": "Name"}), + ), +] + + +# the grammar knows every platform's dtype names, not just this platform's +GRAMMAR_PRIMITIVES = PRIMITIVES + sorted({"float128", "complex256"} - set(PRIMITIVES)) + + +@pytest.mark.parametrize("primitive", GRAMMAR_PRIMITIVES) +@pytest.mark.parametrize("suffix", ["", "x", "_1", "9"]) +@pytest.mark.parametrize( + "build", + [ + lambda n: RecordType([NumpyType("int64")], ["x"], parameters={"__record__": n}), + lambda n: RecordType([NumpyType("int64")], None, parameters={"__record__": n}), + lambda n: RecordType([NumpyType("int64")], [n], parameters={"__record__": "R"}), + ], + ids=["record-name", "tuple-name", "named-record-field"], +) +def test_record_and_field_names_with_primitive_prefix(primitive, suffix, build): + expected = build(primitive + suffix) + assert ak.types.from_datashape(str(expected), highlevel=False) == expected + + +@pytest.mark.parametrize("primitive", PRIMITIVES) +@pytest.mark.parametrize(("template", "build"), CONTEXTS) +def test_type_string_roundtrip(primitive, template, build): + datashape = template.format(primitive) + expected = build(NumpyType(primitive)) + assert str(expected) == datashape + assert ak.types.from_datashape(datashape, highlevel=False) == expected + + +@pytest.mark.parametrize("primitive", PRIMITIVES) +def test_parameters_roundtrip(primitive): + expected = NumpyType(primitive, parameters={"a": 1}) + assert ak.types.from_datashape(str(expected), highlevel=False) == expected + + +@pytest.mark.parametrize("primitive", PRIMITIVES) +def test_highlevel(primitive): + content = NumpyType(primitive) + assert ak.types.from_datashape(f"5 * var * {primitive}") == ArrayType( + ListType(content), 5 + ) + assert ak.types.from_datashape(f"{{x: {primitive}}}") == ScalarType( + RecordType([content], ["x"]) + ) + + +@pytest.mark.parametrize("primitive", PRIMITIVES) +def test_from_numpy_type_reparses(primitive): + array = ak.from_numpy(np.zeros((2, 3), dtype=_primitive_to_dtype_dict[primitive])) + assert ak.types.from_datashape(str(array.type), highlevel=True) == array.type + + +@pytest.mark.parametrize("primitive", PRIMITIVES) +def test_enforce_type_string(primitive): + array = ak.Array([[0, 1], []]) + out = ak.enforce_type(array, f"var * {primitive}") + assert out.type == ArrayType(ListType(NumpyType(primitive)), 2) + + +@pytest.mark.parametrize("primitive", ["float128", "complex256"]) +def test_platform_dependent_primitive_is_lexed(primitive): + if primitive in _primitive_to_dtype_dict: + assert ak.types.from_datashape( + f"var * {primitive}", highlevel=False + ) == ListType(NumpyType(primitive)) + else: + with pytest.raises(TypeError, match="unrecognized primitive"): + ak.types.from_datashape(f"var * {primitive}", highlevel=False) + + +@pytest.mark.parametrize( + ("dtype", "key", "text"), + [ + (np.float16, "float", "1.2"), + (np.float32, "float", "1.2"), + (np.float64, "float", "1.2"), + (np.longdouble, "longfloat", "1.2"), + (np.complex64, "complexfloat", "1.2+0j"), + (np.complex128, "complexfloat", "1.2+0j"), + (np.clongdouble, "longcomplexfloat", "1.2+0j"), + ], +) +def test_show_formats_floating(dtype, key, text): + array = ak.Array(np.array([1.23456], dtype=dtype)) + assert array.show(precision=2, stream=None) == f"[{text}]" + assert array.show(formatter={key: lambda x: "F"}, stream=None) == "[F]" From c86b6910bdf6376a3e3ea621f5e0f4f32f3e0057 Mon Sep 17 00:00:00 2001 From: Iason Krommydas Date: Thu, 22 Oct 2026 22:39:15 +0200 Subject: [PATCH 18/19] test: sort float16 references in float32 to avoid a NumPy bug on 32-bit Windows --- tests/test_4259_float16_and_longdouble.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/test_4259_float16_and_longdouble.py b/tests/test_4259_float16_and_longdouble.py index 0c8d8e42a9..53425c136c 100644 --- a/tests/test_4259_float16_and_longdouble.py +++ b/tests/test_4259_float16_and_longdouble.py @@ -63,15 +63,20 @@ def test_sort_and_argsort(dtype): data = values(dtype) array = ak.from_regular(ak.Array(data)) + # NumPy's float16 sort is wrong on 32-bit Windows with AVX-512 + # (numpy/numpy#29808), so sort in float32, which holds every float16 value + reference = data.astype(np.float32) if dtype is np.float16 else data + expected = np.sort(reference, axis=1).astype(dtype) + result = ak.to_numpy(ak.sort(array, axis=1)) assert result.dtype == np.dtype(dtype) - assert np.array_equal(result, np.sort(data, axis=1)) + assert np.array_equal(result, expected) result = ak.to_numpy(ak.sort(array, axis=1, ascending=False)) - assert np.array_equal(result, np.sort(data, axis=1)[:, ::-1]) + assert np.array_equal(result, expected[:, ::-1]) result = ak.to_numpy(ak.argsort(array, axis=1, stable=True)) - assert np.array_equal(result, np.argsort(data, axis=1, kind="stable")) + assert np.array_equal(result, np.argsort(reference, axis=1, kind="stable")) def test_float16_with_missing_values(): From 6c58813eed02c062f31c657f58939e630cb9bf94 Mon Sep 17 00:00:00 2001 From: Iason Krommydas Date: Thu, 22 Oct 2026 23:27:22 +0200 Subject: [PATCH 19/19] test: compare float16 sorts with NumPy's again now that 32-bit Windows runs Python 3.11 --- tests/test_4259_float16_and_longdouble.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/tests/test_4259_float16_and_longdouble.py b/tests/test_4259_float16_and_longdouble.py index 53425c136c..0c8d8e42a9 100644 --- a/tests/test_4259_float16_and_longdouble.py +++ b/tests/test_4259_float16_and_longdouble.py @@ -63,20 +63,15 @@ def test_sort_and_argsort(dtype): data = values(dtype) array = ak.from_regular(ak.Array(data)) - # NumPy's float16 sort is wrong on 32-bit Windows with AVX-512 - # (numpy/numpy#29808), so sort in float32, which holds every float16 value - reference = data.astype(np.float32) if dtype is np.float16 else data - expected = np.sort(reference, axis=1).astype(dtype) - result = ak.to_numpy(ak.sort(array, axis=1)) assert result.dtype == np.dtype(dtype) - assert np.array_equal(result, expected) + assert np.array_equal(result, np.sort(data, axis=1)) result = ak.to_numpy(ak.sort(array, axis=1, ascending=False)) - assert np.array_equal(result, expected[:, ::-1]) + assert np.array_equal(result, np.sort(data, axis=1)[:, ::-1]) result = ak.to_numpy(ak.argsort(array, axis=1, stable=True)) - assert np.array_equal(result, np.argsort(reference, axis=1, kind="stable")) + assert np.array_equal(result, np.argsort(data, axis=1, kind="stable")) def test_float16_with_missing_values():