haliax 1.4.dev407__tar.gz → 1.4.dev409__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. {haliax-1.4.dev407 → haliax-1.4.dev409}/.agents/projects/api_parity.md +18 -18
  2. {haliax-1.4.dev407 → haliax-1.4.dev409}/PKG-INFO +1 -1
  3. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/api.md +18 -0
  4. haliax-1.4.dev409/src/haliax/__about__.py +1 -0
  5. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/__init__.py +143 -0
  6. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/ops.py +38 -0
  7. haliax-1.4.dev409/tests/test_bitwise_ops.py +45 -0
  8. haliax-1.4.dev409/tests/test_nan_reductions.py +59 -0
  9. haliax-1.4.dev407/src/haliax/__about__.py +0 -1
  10. {haliax-1.4.dev407 → haliax-1.4.dev409}/.coveragerc +0 -0
  11. {haliax-1.4.dev407 → haliax-1.4.dev409}/.flake8 +0 -0
  12. {haliax-1.4.dev407 → haliax-1.4.dev409}/.github/workflows/publish_dev.yaml +0 -0
  13. {haliax-1.4.dev407 → haliax-1.4.dev409}/.github/workflows/run_pre_commit.yaml +0 -0
  14. {haliax-1.4.dev407 → haliax-1.4.dev409}/.github/workflows/run_quick_levanter_tests.yaml +0 -0
  15. {haliax-1.4.dev407 → haliax-1.4.dev409}/.github/workflows/run_tests.yaml +0 -0
  16. {haliax-1.4.dev407 → haliax-1.4.dev409}/.gitignore +0 -0
  17. {haliax-1.4.dev407 → haliax-1.4.dev409}/.playbooks/add-types.md +0 -0
  18. {haliax-1.4.dev407 → haliax-1.4.dev409}/.playbooks/wrap-non-named.md +0 -0
  19. {haliax-1.4.dev407 → haliax-1.4.dev409}/.pre-commit-config.yaml +0 -0
  20. {haliax-1.4.dev407 → haliax-1.4.dev409}/.readthedocs.yaml +0 -0
  21. {haliax-1.4.dev407 → haliax-1.4.dev409}/AGENTS.md +0 -0
  22. {haliax-1.4.dev407 → haliax-1.4.dev409}/CONTRIBUTING.md +0 -0
  23. {haliax-1.4.dev407 → haliax-1.4.dev409}/LICENSE +0 -0
  24. {haliax-1.4.dev407 → haliax-1.4.dev409}/README.md +0 -0
  25. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/broadcasting.md +0 -0
  26. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/cheatsheet.md +0 -0
  27. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/css/material.css +0 -0
  28. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/css/mkdocstrings.css +0 -0
  29. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/faq.md +0 -0
  30. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/figures/data_parallel_mesh.png +0 -0
  31. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/figures/data_parallel_mesh_replicated.png +0 -0
  32. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/figures/device_mesh_1d.png +0 -0
  33. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/figures/device_mesh_1d_zero.png +0 -0
  34. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/figures/device_mesh_2d.png +0 -0
  35. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/figures/device_mesh_2d_batch_partitioned.png +0 -0
  36. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/figures/device_mesh_2d_data_replicated.png +0 -0
  37. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/figures/device_mesh_2d_data_replicated_mlp_partitioned.png +0 -0
  38. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/figures/device_mesh_2d_intermediate_fully_partitioned.png +0 -0
  39. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/figures/device_mesh_2d_zero.png +0 -0
  40. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/fp8.md +0 -0
  41. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/index.md +0 -0
  42. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/indexing.md +0 -0
  43. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/matmul.md +0 -0
  44. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/nn.md +0 -0
  45. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/partitioning.md +0 -0
  46. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/primer.md +0 -0
  47. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/rearrange.ipynb +0 -0
  48. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/rearrange.md +0 -0
  49. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/requirements.txt +0 -0
  50. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/scan.md +0 -0
  51. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/state-dict.md +0 -0
  52. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/tutorial.md +0 -0
  53. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/typing.md +0 -0
  54. {haliax-1.4.dev407 → haliax-1.4.dev409}/docs/vmap.md +0 -0
  55. {haliax-1.4.dev407 → haliax-1.4.dev409}/mkdocs.yml +0 -0
  56. {haliax-1.4.dev407 → haliax-1.4.dev409}/pyproject.toml +0 -0
  57. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/_src/__init__.py +0 -0
  58. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/_src/compile_utils.py +0 -0
  59. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/_src/dot.py +0 -0
  60. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/_src/einsum.py +0 -0
  61. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/_src/fp8.py +0 -0
  62. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/_src/parsing.py +0 -0
  63. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/_src/rearrange.py +0 -0
  64. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/_src/scan.py +0 -0
  65. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/_src/state_dict.py +0 -0
  66. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/_src/util.py +0 -0
  67. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/axis.py +0 -0
  68. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/core.py +0 -0
  69. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/debug.py +0 -0
  70. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/field.py +0 -0
  71. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/haxtyping.py +0 -0
  72. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/hof.py +0 -0
  73. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/jax_utils.py +0 -0
  74. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/nn/__init__.py +0 -0
  75. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/nn/activations.py +0 -0
  76. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/nn/attention.py +0 -0
  77. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/nn/conv.py +0 -0
  78. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/nn/dropout.py +0 -0
  79. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/nn/embedding.py +0 -0
  80. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/nn/linear.py +0 -0
  81. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/nn/loss.py +0 -0
  82. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/nn/mlp.py +0 -0
  83. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/nn/normalization.py +0 -0
  84. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/nn/pool.py +0 -0
  85. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/nn/scan.py +0 -0
  86. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/partitioning.py +0 -0
  87. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/quantization.py +0 -0
  88. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/random.py +0 -0
  89. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/specialized_fns.py +0 -0
  90. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/state_dict.py +0 -0
  91. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/tree_util.py +0 -0
  92. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/types.py +0 -0
  93. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/util.py +0 -0
  94. {haliax-1.4.dev407 → haliax-1.4.dev409}/src/haliax/wrap.py +0 -0
  95. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/core_test.py +0 -0
  96. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_attention.py +0 -0
  97. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_axis.py +0 -0
  98. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_conv.py +0 -0
  99. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_debug.py +0 -0
  100. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_dot.py +0 -0
  101. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_dtype_typing.py +0 -0
  102. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_einsum.py +0 -0
  103. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_field.py +0 -0
  104. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_fp8.py +0 -0
  105. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_hof.py +0 -0
  106. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_int8.py +0 -0
  107. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_moe_linear.py +0 -0
  108. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_namedarray_typing.py +0 -0
  109. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_nn.py +0 -0
  110. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_ops.py +0 -0
  111. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_parsing.py +0 -0
  112. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_partitioning.py +0 -0
  113. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_pool.py +0 -0
  114. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_random.py +0 -0
  115. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_rearrange.py +0 -0
  116. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_scan.py +0 -0
  117. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_scatter_gather.py +0 -0
  118. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_specialized_fns.py +0 -0
  119. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_state_dict.py +0 -0
  120. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_tree_util.py +0 -0
  121. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_utils.py +0 -0
  122. {haliax-1.4.dev407 → haliax-1.4.dev409}/tests/test_visualize_sharding.py +0 -0
  123. {haliax-1.4.dev407 → haliax-1.4.dev409}/uv.lock +0 -0
@@ -5,7 +5,7 @@ APIs that don't translate well to named tensors are intentionally omitted here.
5
5
 
6
6
  ## numpy
7
7
  - [x] `allclose`
8
- - [ ] `amin`
8
+ - [x] `amin`
9
9
  - [ ] `append`
10
10
  - [ ] `apply_along_axis`
11
11
  - [ ] `apply_over_axes`
@@ -18,10 +18,10 @@ APIs that don't translate well to named tensors are intentionally omitted here.
18
18
  - [ ] `atan2`
19
19
  - [ ] `average`
20
20
  - [ ] `bartlett`
21
- - [ ] `bitwise_count`
22
- - [ ] `bitwise_invert`
23
- - [ ] `bitwise_left_shift`
24
- - [ ] `bitwise_right_shift`
21
+ - [x] `bitwise_count`
22
+ - [x] `bitwise_invert`
23
+ - [x] `bitwise_left_shift`
24
+ - [x] `bitwise_right_shift`
25
25
  - [ ] `blackman`
26
26
  - [ ] `block`
27
27
  - [ ] `broadcast_shapes`
@@ -93,23 +93,23 @@ APIs that don't translate well to named tensors are intentionally omitted here.
93
93
  - [ ] `modf`
94
94
  - [ ] `moveaxis`
95
95
  - [ ] `nan_to_num`
96
- - [ ] `nanargmax`
97
- - [ ] `nanargmin`
98
- - [ ] `nancumprod`
99
- - [ ] `nancumsum`
100
- - [ ] `nanmax`
101
- - [ ] `nanmean`
96
+ - [x] `nanargmax`
97
+ - [x] `nanargmin`
98
+ - [x] `nancumprod`
99
+ - [x] `nancumsum`
100
+ - [x] `nanmax`
101
+ - [x] `nanmean`
102
102
  - [ ] `nanmedian`
103
- - [ ] `nanmin`
103
+ - [x] `nanmin`
104
104
  - [ ] `nanpercentile`
105
- - [ ] `nanprod`
105
+ - [x] `nanprod`
106
106
  - [ ] `nanquantile`
107
- - [ ] `nanstd`
108
- - [ ] `nansum`
109
- - [ ] `nanvar`
107
+ - [x] `nanstd`
108
+ - [x] `nansum`
109
+ - [x] `nanvar`
110
110
  - [ ] `nonzero`
111
111
  - [ ] `ogrid`
112
- - [ ] `packbits`
112
+ - [x] `packbits`
113
113
  - [ ] `partition`
114
114
  - [ ] `percentile`
115
115
  - [ ] `permute_dims`
@@ -152,7 +152,7 @@ APIs that don't translate well to named tensors are intentionally omitted here.
152
152
  - [ ] `triu_indices`
153
153
  - [ ] `triu_indices_from`
154
154
  - [ ] `union1d`
155
- - [ ] `unpackbits`
155
+ - [x] `unpackbits`
156
156
  - [ ] `unravel_index`
157
157
  - [ ] `unstack`
158
158
  - [ ] `unwrap`
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: haliax
3
- Version: 1.4.dev407
3
+ Version: 1.4.dev409
4
4
  Summary: Named Tensors for Legible Deep Learning in JAX
5
5
  Project-URL: Homepage, https://github.com/stanford-crfm/haliax
6
6
  Project-URL: Bug Tracker, https://github.com/stanford-crfm/haliax/issues/
@@ -128,12 +128,22 @@ You can convert it to a [jax.numpy.ndarray][] with [haliax.NamedArray.scalar][],
128
128
 
129
129
  ::: haliax.all
130
130
  ::: haliax.amax
131
+ ::: haliax.amin
131
132
  ::: haliax.any
132
133
  ::: haliax.argmax
133
134
  ::: haliax.argmin
134
135
  ::: haliax.max
135
136
  ::: haliax.mean
136
137
  ::: haliax.min
138
+ ::: haliax.nanargmax
139
+ ::: haliax.nanargmin
140
+ ::: haliax.nanmax
141
+ ::: haliax.nanmean
142
+ ::: haliax.nanmin
143
+ ::: haliax.nanprod
144
+ ::: haliax.nanstd
145
+ ::: haliax.nansum
146
+ ::: haliax.nanvar
137
147
  ::: haliax.prod
138
148
  ::: haliax.ptp
139
149
  ::: haliax.std
@@ -146,6 +156,8 @@ don't reduce it.
146
156
 
147
157
  ::: haliax.cumsum
148
158
  ::: haliax.cumprod
159
+ ::: haliax.nancumprod
160
+ ::: haliax.nancumsum
149
161
  ::: haliax.sort
150
162
  ::: haliax.argsort
151
163
 
@@ -164,6 +176,8 @@ These are all more or less directly from JAX's NumPy API.
164
176
  ::: haliax.arctan
165
177
  ::: haliax.arctanh
166
178
  ::: haliax.around
179
+ ::: haliax.bitwise_count
180
+ ::: haliax.bitwise_invert
167
181
  ::: haliax.bitwise_not
168
182
  ::: haliax.cbrt
169
183
  ::: haliax.ceil
@@ -221,7 +235,9 @@ These are all more or less directly from JAX's NumPy API.
221
235
  ::: haliax.add
222
236
  ::: haliax.arctan2
223
237
  ::: haliax.bitwise_and
238
+ ::: haliax.bitwise_left_shift
224
239
  ::: haliax.bitwise_or
240
+ ::: haliax.bitwise_right_shift
225
241
  ::: haliax.bitwise_xor
226
242
  ::: haliax.divide
227
243
  ::: haliax.divmod
@@ -258,6 +274,8 @@ These are all more or less directly from JAX's NumPy API.
258
274
 
259
275
  ::: haliax.bincount
260
276
  ::: haliax.clip
277
+ ::: haliax.packbits
278
+ ::: haliax.unpackbits
261
279
  ::: haliax.isclose
262
280
  ::: haliax.allclose
263
281
  ::: haliax.array_equal
@@ -0,0 +1 @@
1
+ __version__ = "1.4.dev409"
@@ -83,6 +83,8 @@ from .ops import (
83
83
  unique_counts,
84
84
  unique_inverse,
85
85
  unique_all,
86
+ packbits,
87
+ unpackbits,
86
88
  searchsorted,
87
89
  bincount,
88
90
  where,
@@ -337,6 +339,14 @@ def around(a: A) -> A:
337
339
  return wrap_elemwise_unary(jnp.around, a)
338
340
 
339
341
 
342
+ def bitwise_count(a: A) -> A:
343
+ return wrap_elemwise_unary(jnp.bitwise_count, a)
344
+
345
+
346
+ def bitwise_invert(a: A) -> A:
347
+ return wrap_elemwise_unary(jnp.bitwise_invert, a)
348
+
349
+
340
350
  def bitwise_not(a: A) -> A:
341
351
  return wrap_elemwise_unary(jnp.bitwise_not, a)
342
352
 
@@ -560,6 +570,13 @@ def amax(array: NamedArray, axis: Optional[AxisSelection] = None, *, where: Opti
560
570
  return wrap_reduction_call(jnp.amax, array, axis, where, single_axis_only=False, supports_where=True)
561
571
 
562
572
 
573
+ def amin(array: NamedArray, axis: Optional[AxisSelection] = None, *, where: Optional[NamedArray] = None) -> NamedArray:
574
+ """
575
+ Aliax for min. See min for details.
576
+ """
577
+ return wrap_reduction_call(jnp.amin, array, axis, where, single_axis_only=False, supports_where=True)
578
+
579
+
563
580
  def any(array: NamedArray, axis: Optional[AxisSelection] = None, *, where: Optional[NamedArray] = None) -> NamedArray:
564
581
  """True if any elements along a given axis or axes are True. If axis is None, any elements are True."""
565
582
  return wrap_reduction_call(jnp.any, array, axis, where, single_axis_only=False, supports_where=True)
@@ -656,6 +673,84 @@ def var(
656
673
  )
657
674
 
658
675
 
676
+ def nanargmax(array: NamedArray, axis: Optional[AxisSelector] = None) -> NamedArray:
677
+ return wrap_reduction_call(jnp.nanargmax, array, axis, None, single_axis_only=True, supports_where=False)
678
+
679
+
680
+ def nanargmin(array: NamedArray, axis: Optional[AxisSelector] = None) -> NamedArray:
681
+ return wrap_reduction_call(jnp.nanargmin, array, axis, None, single_axis_only=True, supports_where=False)
682
+
683
+
684
+ def nanmax(
685
+ array: NamedArray,
686
+ axis: Optional[AxisSelection] = None,
687
+ *,
688
+ where: Optional[NamedArray] = None,
689
+ ) -> NamedArray:
690
+ return wrap_reduction_call(jnp.nanmax, array, axis, where, single_axis_only=False, supports_where=True)
691
+
692
+
693
+ def nanmean(
694
+ array: NamedArray,
695
+ axis: Optional[AxisSelection] = None,
696
+ *,
697
+ where: Optional[NamedArray] = None,
698
+ dtype: Optional[DTypeLike] = None,
699
+ ) -> NamedArray:
700
+ return wrap_reduction_call(jnp.nanmean, array, axis, where, single_axis_only=False, supports_where=True, dtype=dtype)
701
+
702
+
703
+ def nanmin(
704
+ array: NamedArray,
705
+ axis: Optional[AxisSelection] = None,
706
+ *,
707
+ where: Optional[NamedArray] = None,
708
+ ) -> NamedArray:
709
+ return wrap_reduction_call(jnp.nanmin, array, axis, where, single_axis_only=False, supports_where=True)
710
+
711
+
712
+ def nanprod(
713
+ array: NamedArray,
714
+ axis: Optional[AxisSelection] = None,
715
+ *,
716
+ where: Optional[NamedArray] = None,
717
+ dtype: Optional[DTypeLike] = None,
718
+ ) -> NamedArray:
719
+ return wrap_reduction_call(jnp.nanprod, array, axis, where, single_axis_only=False, supports_where=True, dtype=dtype)
720
+
721
+
722
+ def nanstd(
723
+ array: NamedArray,
724
+ axis: Optional[AxisSelection] = None,
725
+ *,
726
+ where: Optional[NamedArray] = None,
727
+ ddof: int = 0,
728
+ dtype: Optional[DTypeLike] = None,
729
+ ) -> NamedArray:
730
+ return wrap_reduction_call(jnp.nanstd, array, axis, where, single_axis_only=False, supports_where=True, dtype=dtype, ddof=ddof)
731
+
732
+
733
+ def nansum(
734
+ array: NamedArray,
735
+ axis: Optional[AxisSelection] = None,
736
+ *,
737
+ where: Optional[NamedArray] = None,
738
+ dtype: Optional[DTypeLike] = None,
739
+ ) -> NamedArray:
740
+ return wrap_reduction_call(jnp.nansum, array, axis, where, single_axis_only=False, supports_where=True, dtype=dtype)
741
+
742
+
743
+ def nanvar(
744
+ array: NamedArray,
745
+ axis: Optional[AxisSelection] = None,
746
+ *,
747
+ where: Optional[NamedArray] = None,
748
+ ddof: int = 0,
749
+ dtype: Optional[DTypeLike] = None,
750
+ ) -> NamedArray:
751
+ return wrap_reduction_call(jnp.nanvar, array, axis, where, single_axis_only=False, supports_where=True, dtype=dtype, ddof=ddof)
752
+
753
+
659
754
  # "Normalization" functions that use an axis but don't change the shape
660
755
 
661
756
 
@@ -673,6 +768,20 @@ def cumprod(a: NamedArray, axis: AxisSelector, dtype: Optional[DTypeLike] = None
673
768
  return wrap_axiswise_call(jnp.cumprod, a, axis, dtype=dtype, single_axis_only=True)
674
769
 
675
770
 
771
+ def nancumsum(a: NamedArray, axis: AxisSelector, *, dtype: Optional[DTypeLike] = None) -> NamedArray:
772
+ """
773
+ Named version of [jax.numpy.nancumsum](https://jax.readthedocs.io/en/latest/_autosummary/jax.numpy.nancumsum.html)
774
+ """
775
+ return wrap_axiswise_call(jnp.nancumsum, a, axis, dtype=dtype, single_axis_only=True)
776
+
777
+
778
+ def nancumprod(a: NamedArray, axis: AxisSelector, dtype: Optional[DTypeLike] = None) -> NamedArray:
779
+ """
780
+ Named version of [jax.numpy.nancumprod](https://jax.readthedocs.io/en/latest/_autosummary/jax.numpy.nancumprod.html)
781
+ """
782
+ return wrap_axiswise_call(jnp.nancumprod, a, axis, dtype=dtype, single_axis_only=True)
783
+
784
+
676
785
  def sort(a: NamedArray, axis: AxisSelector) -> NamedArray:
677
786
  """
678
787
  Named version of [jax.numpy.sort](https://jax.readthedocs.io/en/latest/_autosummary/jax.numpy.sort.html)
@@ -717,6 +826,14 @@ def bitwise_and(x1: NamedOrNumeric, x2: NamedOrNumeric, /) -> NamedOrNumeric:
717
826
  return jnp.bitwise_and(x1, x2) # type: ignore
718
827
 
719
828
 
829
+ @wrap_elemwise_binary
830
+ def bitwise_left_shift(x1: NamedOrNumeric, x2: NamedOrNumeric, /) -> NamedOrNumeric:
831
+ """
832
+ Named version of [jax.numpy.bitwise_left_shift](https://jax.readthedocs.io/en/latest/_autosummary/jax.numpy.bitwise_left_shift.html)
833
+ """
834
+ return jnp.bitwise_left_shift(x1, x2) # type: ignore
835
+
836
+
720
837
  @wrap_elemwise_binary
721
838
  def bitwise_or(x1: NamedOrNumeric, x2: NamedOrNumeric, /) -> NamedOrNumeric:
722
839
  """
@@ -725,6 +842,14 @@ def bitwise_or(x1: NamedOrNumeric, x2: NamedOrNumeric, /) -> NamedOrNumeric:
725
842
  return jnp.bitwise_or(x1, x2) # type: ignore
726
843
 
727
844
 
845
+ @wrap_elemwise_binary
846
+ def bitwise_right_shift(x1: NamedOrNumeric, x2: NamedOrNumeric, /) -> NamedOrNumeric:
847
+ """
848
+ Named version of [jax.numpy.bitwise_right_shift](https://jax.readthedocs.io/en/latest/_autosummary/jax.numpy.bitwise_right_shift.html)
849
+ """
850
+ return jnp.bitwise_right_shift(x1, x2) # type: ignore
851
+
852
+
728
853
  @wrap_elemwise_binary
729
854
  def bitwise_xor(x1: NamedOrNumeric, x2: NamedOrNumeric, /) -> NamedOrNumeric:
730
855
  """
@@ -981,6 +1106,8 @@ __all__ = [
981
1106
  "arctan",
982
1107
  "arctanh",
983
1108
  "around",
1109
+ "bitwise_count",
1110
+ "bitwise_invert",
984
1111
  "bitwise_not",
985
1112
  "cbrt",
986
1113
  "ceil",
@@ -1034,12 +1161,22 @@ __all__ = [
1034
1161
  "trunc",
1035
1162
  "all",
1036
1163
  "amax",
1164
+ "amin",
1037
1165
  "any",
1038
1166
  "argmax",
1039
1167
  "argmin",
1040
1168
  "max",
1041
1169
  "mean",
1042
1170
  "min",
1171
+ "nanargmax",
1172
+ "nanargmin",
1173
+ "nanmax",
1174
+ "nanmean",
1175
+ "nanmin",
1176
+ "nanprod",
1177
+ "nanstd",
1178
+ "nansum",
1179
+ "nanvar",
1043
1180
  "prod",
1044
1181
  "product",
1045
1182
  "ptp",
@@ -1048,6 +1185,8 @@ __all__ = [
1048
1185
  "var",
1049
1186
  "cumsum",
1050
1187
  "cumprod",
1188
+ "nancumprod",
1189
+ "nancumsum",
1051
1190
  "sort",
1052
1191
  "scan",
1053
1192
  "fold",
@@ -1060,6 +1199,8 @@ __all__ = [
1060
1199
  "unique_counts",
1061
1200
  "unique_inverse",
1062
1201
  "unique_all",
1202
+ "packbits",
1203
+ "unpackbits",
1063
1204
  "searchsorted",
1064
1205
  "bincount",
1065
1206
  "clip",
@@ -1068,7 +1209,9 @@ __all__ = [
1068
1209
  "add",
1069
1210
  "arctan2",
1070
1211
  "bitwise_and",
1212
+ "bitwise_left_shift",
1071
1213
  "bitwise_or",
1214
+ "bitwise_right_shift",
1072
1215
  "bitwise_xor",
1073
1216
  "divide",
1074
1217
  "divmod",
@@ -508,6 +508,42 @@ def bincount(
508
508
  return NamedArray(result, (Counts,))
509
509
 
510
510
 
511
+ def packbits(a: NamedArray, axis: AxisSelector, *, bitorder: str = "big") -> NamedArray:
512
+ """Named version of `jax.numpy.packbits`."""
513
+
514
+ axis_index = a.axis_indices(axis)
515
+ if not isinstance(axis_index, int):
516
+ raise ValueError("packbits only supports a single existing axis")
517
+
518
+ result = jnp.packbits(a.array, axis=axis_index, bitorder=bitorder)
519
+ old_axis = a.axes[axis_index]
520
+ new_size = (old_axis.size + 7) // 8
521
+ new_axis = old_axis.resize(new_size)
522
+ new_axes = a.axes[:axis_index] + (new_axis,) + a.axes[axis_index + 1 :]
523
+ return NamedArray(result, new_axes)
524
+
525
+
526
+ def unpackbits(
527
+ a: NamedArray,
528
+ axis: AxisSelector,
529
+ *,
530
+ count: int | None = None,
531
+ bitorder: str = "big",
532
+ ) -> NamedArray:
533
+ """Named version of `jax.numpy.unpackbits`."""
534
+
535
+ axis_index = a.axis_indices(axis)
536
+ if not isinstance(axis_index, int):
537
+ raise ValueError("unpackbits only supports a single existing axis")
538
+
539
+ result = jnp.unpackbits(a.array, axis=axis_index, count=count, bitorder=bitorder)
540
+ old_axis = a.axes[axis_index]
541
+ new_size = count if count is not None else old_axis.size * 8
542
+ new_axis = old_axis.resize(new_size)
543
+ new_axes = a.axes[:axis_index] + (new_axis,) + a.axes[axis_index + 1 :]
544
+ return NamedArray(result, new_axes)
545
+
546
+
511
547
  __all__ = [
512
548
  "trace",
513
549
  "where",
@@ -517,6 +553,8 @@ __all__ = [
517
553
  "pad_left",
518
554
  "pad",
519
555
  "clip",
556
+ "packbits",
557
+ "unpackbits",
520
558
  "unique",
521
559
  "unique_values",
522
560
  "unique_counts",
@@ -0,0 +1,45 @@
1
+ import jax.numpy as jnp
2
+ import haliax as hax
3
+ from haliax import Axis
4
+
5
+
6
+ def test_bitwise_count_invert():
7
+ A = Axis("A", 4)
8
+ x = hax.named(jnp.array([0, 1, 2, 3], dtype=jnp.uint8), (A,))
9
+
10
+ inv = hax.bitwise_invert(x)
11
+ assert jnp.all(inv.array == jnp.bitwise_invert(x.array))
12
+
13
+ cnt = hax.bitwise_count(x)
14
+ assert jnp.all(cnt.array == jnp.bitwise_count(x.array))
15
+
16
+
17
+ def test_bitwise_shift():
18
+ A = Axis("A", 4)
19
+ x = hax.named(jnp.array([1, 2, 3, 4], dtype=jnp.int32), (A,))
20
+ shift = hax.named(jnp.array([1, 1, 1, 1], dtype=jnp.int32), (A,))
21
+
22
+ left = hax.bitwise_left_shift(x, shift)
23
+ assert jnp.all(left.array == jnp.bitwise_left_shift(x.array, shift.array))
24
+
25
+ right = hax.bitwise_right_shift(left, shift)
26
+ assert jnp.all(right.array == jnp.bitwise_right_shift(left.array, shift.array))
27
+
28
+ right_scalar = hax.bitwise_right_shift(x, 1)
29
+ assert jnp.all(right_scalar.array == jnp.bitwise_right_shift(x.array, 1))
30
+
31
+
32
+ def test_packbits_unpackbits():
33
+ B = Axis("B", 10)
34
+ data = hax.named(jnp.array([0, 1, 1, 0, 1, 0, 0, 1, 1, 0], dtype=jnp.uint8), (B,))
35
+
36
+ packed = hax.packbits(data, B)
37
+ expected_packed = jnp.packbits(data.array, axis=0)
38
+ assert jnp.all(packed.array == expected_packed)
39
+ assert packed.axes[0].name == B.name
40
+ assert packed.axes[0].size == 2
41
+
42
+ unpacked = hax.unpackbits(packed, "B", count=B.size)
43
+ expected_unpacked = jnp.unpackbits(packed.array, axis=0, count=B.size)
44
+ assert jnp.all(unpacked.array == expected_unpacked)
45
+ assert unpacked.axes[0].size == B.size
@@ -0,0 +1,59 @@
1
+ from typing import Any, Callable
2
+
3
+ import jax.numpy as jnp
4
+ import haliax as hax
5
+
6
+
7
+ def _sample_array():
8
+ Height, Width = hax.make_axes(Height=2, Width=3)
9
+ data = jnp.array([[1.0, jnp.nan, 3.0], [jnp.nan, 5.0, 6.0]])
10
+ arr = hax.named(data, (Height, Width))
11
+ return Height, Width, data, arr
12
+
13
+
14
+ def test_amin_alias():
15
+ Height, Width = hax.make_axes(Height=2, Width=3)
16
+ data = jnp.arange(6.0).reshape(2, 3)
17
+ arr = hax.named(data, (Height, Width))
18
+ assert jnp.array_equal(hax.amin(arr).array, jnp.amin(data))
19
+ assert jnp.array_equal(hax.amin(arr, axis=Height).array, jnp.amin(data, axis=0))
20
+ assert hax.amin(arr, axis=Height).axes == (Width,)
21
+
22
+
23
+ def test_nan_reductions():
24
+ Height, Width, data, arr = _sample_array()
25
+
26
+ funcs: list[tuple[Callable[..., Any], Callable[..., Any]]] = [
27
+ (hax.nanmin, jnp.nanmin),
28
+ (hax.nanmax, jnp.nanmax),
29
+ (hax.nanmean, jnp.nanmean),
30
+ (hax.nansum, jnp.nansum),
31
+ (hax.nanprod, jnp.nanprod),
32
+ (hax.nanstd, jnp.nanstd),
33
+ (hax.nanvar, jnp.nanvar),
34
+ ]
35
+
36
+ for hfunc, jfunc in funcs:
37
+ assert jnp.allclose(hfunc(arr).array, jfunc(data), equal_nan=True)
38
+ assert jnp.allclose(hfunc(arr, axis=Height).array, jfunc(data, axis=0), equal_nan=True)
39
+ assert hfunc(arr, axis=Height).axes == (Width,)
40
+
41
+ arg_funcs: list[tuple[Callable[..., Any], Callable[..., Any]]] = [
42
+ (hax.nanargmax, jnp.nanargmax),
43
+ (hax.nanargmin, jnp.nanargmin),
44
+ ]
45
+
46
+ for hfunc, jfunc in arg_funcs:
47
+ out = hfunc(arr, axis=Height)
48
+ assert jnp.array_equal(out.array, jfunc(data, axis=0))
49
+ assert out.axes == (Width,)
50
+
51
+ axiswise_funcs: list[tuple[Callable[..., Any], Callable[..., Any]]] = [
52
+ (hax.nancumsum, jnp.nancumsum),
53
+ (hax.nancumprod, jnp.nancumprod),
54
+ ]
55
+
56
+ for hfunc, jfunc in axiswise_funcs:
57
+ out = hfunc(arr, axis=Height)
58
+ assert jnp.allclose(out.array, jfunc(data, axis=0), equal_nan=True)
59
+ assert out.axes == (Height, Width)
@@ -1 +0,0 @@
1
- __version__ = "1.4.dev407"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes