nx_array_ops.nx
buildroot/runtime/nx_array_ops.nx
about
nx_array_ops.nx -- language-level higher-order array primitives.
User cardinal 2026-05-15: "I want the language to be as powerful as
possible on the prerequisites... that's where Javascript and Python
are doing good work."
What every program needs over arrays: map, filter, reduce, find,
sort, percentile, argmax/argmin, mean, variance, unique, contains.
Python has these in stdlib (operator + itertools + statistics);
JS has them as Array methods (.map / .filter / .reduce / .find).
Both shaped programming for the last 20 years. NishiLang absorbs
them here at the substrate-prerequisite layer.
NO-CLOSURE-NEEDED DESIGN: NishiLang doesn't have first-class function
values yet. Instead of forcing callers to write hand-loops, this
primitive ships SEALED-ENUM OP KINDS that the substrate dispatches
internally. Coverage: ~80% of real-world array operations.
The remaining 20% (truly custom predicates) callers write a while
loop, same as today. When function-pointer / closure support
lands (queued nxc2 work), nx_array_map_fn / _filter_fn / _reduce_fn
variants extend this primitive additively.
OPERATES ON: arrays of nx_int (the substrate-wide arithmetic type
from nx_tier.nx). Same primitive over indices, counts, Q10
fractions, IDs, anything that fits in nx_int.
genealogy_id: numpy_oliphant_2006 + apl_iverson_1962 +
python_pep_3132_unpacking + js_es5_array_methods_2009
lineage_id: array_ops_language_prerequisite
dependencies 2 imports · 3 importers
imports: nx_syscalls.nxnx_tier.nx
imported by: nx_array_ops_test.nxnx_iterator.nxnx_iterator_test.nx
structs
| none |
consts
| 40 | const NX_AOP_Q: nx_int = 1024 |
| 44 | const NX_REDUCE_SUM: nx_int = 0 |
| 45 | const NX_REDUCE_PRODUCT: nx_int = 1 |
| 46 | const NX_REDUCE_MIN: nx_int = 2 |
| 47 | const NX_REDUCE_MAX: nx_int = 3 |
| 48 | const NX_REDUCE_COUNT: nx_int = 4 |
| 49 | const NX_REDUCE_AND: nx_int = 5 // bitwise AND |
| 50 | const NX_REDUCE_OR: nx_int = 6 // bitwise OR |
| 51 | const NX_REDUCE_XOR: nx_int = 7 // bitwise XOR |
| 52 | const NX_REDUCE_N_OPS: nx_int = 8 |
| 56 | const NX_FILTER_GT_ZERO: nx_int = 0 |
| 57 | const NX_FILTER_LT_ZERO: nx_int = 1 |
| 58 | const NX_FILTER_GTE_ZERO: nx_int = 2 |
| 59 | const NX_FILTER_LTE_ZERO: nx_int = 3 |
| 60 | const NX_FILTER_NON_ZERO: nx_int = 4 |
| 61 | const NX_FILTER_ZERO: nx_int = 5 |
| 62 | const NX_FILTER_EVEN: nx_int = 6 |
| 63 | const NX_FILTER_ODD: nx_int = 7 |
| 64 | const NX_FILTER_GT_PARAM: nx_int = 8 // uses param |
| 65 | const NX_FILTER_LT_PARAM: nx_int = 9 |
| 66 | const NX_FILTER_EQ_PARAM: nx_int = 10 |
| 67 | const NX_FILTER_N_PREDS: nx_int = 11 |
| 71 | const NX_MAP_ABS: nx_int = 0 |
| 72 | const NX_MAP_NEGATE: nx_int = 1 |
| 73 | const NX_MAP_SQUARE: nx_int = 2 |
| 74 | const NX_MAP_DOUBLE: nx_int = 3 |
| 75 | const NX_MAP_HALVE: nx_int = 4 |
| 76 | const NX_MAP_ADD_PARAM: nx_int = 5 // out[i] = arr[i] + param |
| 77 | const NX_MAP_SUB_PARAM: nx_int = 6 |
| 78 | const NX_MAP_MUL_PARAM: nx_int = 7 |
| 79 | const NX_MAP_DIV_PARAM: nx_int = 8 |
| 80 | const NX_MAP_CLAMP_Q10: nx_int = 9 // clamp to [0, Q] |
| 81 | const NX_MAP_CLAMP_SIGNED_Q10: nx_int = 10 // clamp to [-Q, +Q] |
| 82 | const NX_MAP_SIGN: nx_int = 11 // -1 / 0 / +1 |
| 83 | const NX_MAP_N_OPS: nx_int = 12 |
functions
| 87 | func _aop_abs(x: nx_int) -> nx_int called by 1: _aop_map_one |
| 92 | func _aop_sign(x: nx_int) -> nx_int called by 1: _aop_map_one |
| 103 | func nx_array_reduce(arr: *nx_int, n: nx_int, op: nx_int) -> nx_int |
| 134 | func nx_array_sum(arr: *nx_int, n: nx_int) -> nx_int |
| 138 | func nx_array_product(arr: *nx_int, n: nx_int) -> nx_int calls 1: nx_array_reduce |
| 142 | func nx_array_min(arr: *nx_int, n: nx_int) -> nx_int |
| 146 | func nx_array_max(arr: *nx_int, n: nx_int) -> nx_int |
| 151 | func nx_array_mean(arr: *nx_int, n: nx_int) -> nx_int |
| 157 | func nx_array_range(arr: *nx_int, n: nx_int) -> nx_int |
| 165 | func nx_array_variance_pop(arr: *nx_int, n: nx_int) -> nx_int |
| 184 | func _aop_filter_match(v: nx_int, pred: nx_int, param: nx_int) -> nx_int |
| 205 | func nx_array_filter(arr: *nx_int, n: nx_int, pred: nx_int, param: nx_int, |
| 223 | func nx_array_count_matching(arr: *nx_int, n: nx_int, pred: nx_int, param: nx_int) -> nx_int |
| 238 | func _aop_map_one(v: nx_int, op: nx_int, param: nx_int) -> nx_int |
| 265 | func nx_array_map(arr: *nx_int, n: nx_int, op: nx_int, param: nx_int, |
| 278 | func nx_array_find(arr: *nx_int, n: nx_int, value: nx_int) -> nx_int |
| 288 | func nx_array_contains(arr: *nx_int, n: nx_int, value: nx_int) -> nx_int |
| 294 | func nx_array_argmin(arr: *nx_int, n: nx_int) -> nx_int called by 1: main |
| 310 | func nx_array_argmax(arr: *nx_int, n: nx_int) -> nx_int called by 1: main |
| 327 | func nx_array_all(arr: *nx_int, n: nx_int, pred: nx_int, param: nx_int) -> nx_int |
| 336 | func nx_array_any(arr: *nx_int, n: nx_int, pred: nx_int, param: nx_int) -> nx_int |
| 347 | func nx_array_reverse(arr: *nx_int, n: nx_int) -> nx_int |
| 364 | func nx_array_sort_asc(arr: *nx_int, n: nx_int) -> nx_int |
| 388 | func nx_array_sort_desc(arr: *nx_int, n: nx_int) -> nx_int |
| 399 | func nx_array_median(arr: *nx_int, n: nx_int, scratch: *nx_int) -> nx_int |
| 411 | func nx_array_percentile(arr: *nx_int, n: nx_int, p_q10: nx_int, |
| 432 | func nx_array_unique_count(arr: *nx_int, n: nx_int) -> nx_int called by 1: main |
| 454 | func nx_array_reduce_op_is_valid(op: nx_int) -> nx_int called by 1: main |
| 460 | func nx_array_filter_pred_is_valid(p: nx_int) -> nx_int called by 1: main |
| 466 | func nx_array_map_op_is_valid(op: nx_int) -> nx_int called by 1: main |