mlx-bun 0.0.10 → 0.0.12

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 (216) hide show
  1. package/README.md +107 -32
  2. package/THIRD_PARTY_LICENSES.md +10 -0
  3. package/docs/archive/mlx-bun-lab-report.html +275 -0
  4. package/docs/archive/wwdc-mlx-bun.html +848 -0
  5. package/docs/design/audio-input-plan.md +356 -0
  6. package/docs/design/batching-perf-path.md +58 -35
  7. package/docs/design/batching-v2-plan.md +23 -9
  8. package/docs/design/bucketing-stage.md +2 -1
  9. package/docs/design/colibri-glm52-port.md +1479 -0
  10. package/docs/design/compat-cli-surface-design.md +4 -3
  11. package/docs/design/decode-speed-program.md +172 -0
  12. package/docs/design/docs-reorg-plan.md +1 -1
  13. package/docs/design/dspark-serving-program.md +371 -0
  14. package/docs/design/dspark-speculative-decoding.md +167 -5
  15. package/docs/design/faithful-l1-consolidation.md +310 -0
  16. package/docs/design/generic-model-support.md +8 -5
  17. package/docs/design/grammar-spec-batching-integration.md +301 -0
  18. package/docs/design/minicpm5-decode-megakernel.md +16 -11
  19. package/docs/design/mlx-lm-tool-parity-plan.md +11 -1
  20. package/docs/design/omlx-adoption-map.md +14 -6
  21. package/docs/design/orpo-training.md +34 -30
  22. package/docs/design/paged-kv-cache.md +214 -0
  23. package/docs/design/parallel-slots.md +82 -49
  24. package/docs/design/parity-tier-dag.md +43 -33
  25. package/docs/design/pre-colibri-stabilization.md +329 -0
  26. package/docs/design/repo-cleanup-plan.md +189 -0
  27. package/docs/design/runtime-isolation.md +19 -3
  28. package/docs/design/segmented-backward-training.md +3 -2
  29. package/docs/design/ssd-kv-cold-tier.md +130 -0
  30. package/docs/design/structured-output.md +484 -0
  31. package/docs/design/the-dreaming-master-plan.md +2 -3
  32. package/docs/design/turboquant-kv.md +235 -0
  33. package/docs/design/unified-engine-frontier-plan.md +774 -0
  34. package/docs/design/web-chat-beat-matrix.md +315 -0
  35. package/docs/design/web-chat-redesign.md +1112 -0
  36. package/docs/investigations/colibri-oracle-pin.md +1284 -0
  37. package/docs/investigations/dspark-handoff.md +182 -16
  38. package/docs/investigations/indexshare-performance-spike.md +357 -0
  39. package/docs/investigations/lab-build-journal.md +2 -2
  40. package/docs/investigations/openwiki-evaluation.md +249 -0
  41. package/docs/planning/IDEAS.md +14 -0
  42. package/docs/planning/PRODUCT_ROADMAP.md +2 -3
  43. package/docs/planning/chat-ui-vision-memory-first.md +199 -0
  44. package/docs/planning/chat-ui-vision.md +50 -0
  45. package/docs/planning/memory-docs-and-dag-plan.md +15 -6
  46. package/docs/planning/release-notes-v0.0.11.md +239 -0
  47. package/docs/planning/release-notes-v0.0.12.md +80 -0
  48. package/docs/reference/cli.md +63 -18
  49. package/docs/reference/distribution.md +37 -6
  50. package/docs/reference/embedding.md +40 -16
  51. package/docs/reference/features-matrix.md +99 -0
  52. package/docs/reference/library-api.md +69 -20
  53. package/docs/reference/memory.md +26 -6
  54. package/docs/reference/models.md +60 -3
  55. package/docs/reference/orpo-quickstart.md +3 -4
  56. package/docs/reference/server-api.md +717 -24
  57. package/docs/reference/server-config.md +265 -129
  58. package/docs/reference/training.md +24 -16
  59. package/package.json +5 -3
  60. package/src/anthropic.ts +67 -44
  61. package/src/audio/conformer.ts +647 -0
  62. package/src/audio/decode.ts +133 -0
  63. package/src/audio/features.ts +202 -0
  64. package/src/audio/transcode.ts +67 -0
  65. package/src/chat-template.ts +155 -10
  66. package/src/cli.ts +483 -113
  67. package/src/config.ts +116 -24
  68. package/src/diffusion/diffusion-generate.ts +14 -8
  69. package/src/download.ts +143 -12
  70. package/src/eval/README.md +7 -6
  71. package/src/eval/ifeval.ts +63 -120
  72. package/src/eval/kl.ts +59 -3
  73. package/src/eval/quality-db.ts +2 -2
  74. package/src/eval/runner.ts +17 -8
  75. package/src/eval/tasks/ifeval.ts +167 -31
  76. package/src/expert-io.ts +391 -0
  77. package/src/expert-offload.ts +15 -2
  78. package/src/expert-residency.ts +1134 -0
  79. package/src/expert-usage.ts +415 -0
  80. package/src/flags.ts +13 -0
  81. package/src/generate.ts +438 -35
  82. package/src/grammar.ts +585 -0
  83. package/src/hf-push.ts +1 -1
  84. package/src/hub-rest.ts +242 -0
  85. package/src/index.ts +14 -2
  86. package/src/jobs/runner.ts +37 -18
  87. package/src/kv-store.ts +586 -93
  88. package/src/lora.ts +85 -14
  89. package/src/md-modules.d.ts +42 -0
  90. package/src/media-fetch.ts +426 -0
  91. package/src/memory/rest.ts +245 -0
  92. package/src/memory/vault.ts +74 -0
  93. package/src/mlx/array.ts +149 -19
  94. package/src/mlx/autograd.ts +53 -16
  95. package/src/mlx/checkpoint.ts +46 -13
  96. package/src/mlx/custom-vjp.ts +83 -35
  97. package/src/mlx/ffi.ts +27 -3
  98. package/src/mlx/metal-kernel.ts +7 -4
  99. package/src/mlx/ops.ts +153 -23
  100. package/src/mlx/turboquant-ops.ts +831 -0
  101. package/src/mlx/turboquant-tables.ts +237 -0
  102. package/src/model/batched-mask.ts +62 -1
  103. package/src/model/batched-quant.ts +206 -0
  104. package/src/model/batched-rotating-quant.ts +346 -0
  105. package/src/model/batched-rotating.ts +46 -1
  106. package/src/model/compiled-decode.ts +4 -15
  107. package/src/model/factory.ts +103 -6
  108. package/src/model/gemma4-base.ts +395 -39
  109. package/src/model/gemma4.ts +122 -33
  110. package/src/model/generated/gemma4-12b.ts +9 -13
  111. package/src/model/generated/gemma4-26b.ts +10 -5
  112. package/src/model/generated/gemma4-e4b.ts +14 -9
  113. package/src/model/glm52-atlas.ts +511 -0
  114. package/src/model/glm52-cache.ts +706 -0
  115. package/src/model/glm52-config.ts +262 -0
  116. package/src/model/glm52-container.ts +305 -0
  117. package/src/model/glm52-coupling.ts +388 -0
  118. package/src/model/glm52-dsa.ts +602 -0
  119. package/src/model/glm52-expert-layout.ts +253 -0
  120. package/src/model/glm52-layout.ts +152 -0
  121. package/src/model/glm52-memory.ts +473 -0
  122. package/src/model/glm52-mla.ts +786 -0
  123. package/src/model/glm52-moe.ts +223 -0
  124. package/src/model/glm52-pilot.ts +537 -0
  125. package/src/model/glm52-reference.ts +445 -0
  126. package/src/model/glm52-residency.ts +557 -0
  127. package/src/model/glm52-resident-weights.ts +135 -0
  128. package/src/model/glm52-streamed-experts.ts +453 -0
  129. package/src/model/glm52-streamed-metal.ts +610 -0
  130. package/src/model/glm52-weights.ts +503 -0
  131. package/src/model/glm52.ts +1153 -0
  132. package/src/model/minicpm5.ts +58 -102
  133. package/src/model/paged-kv.ts +253 -0
  134. package/src/model/qwen3-delta.ts +76 -15
  135. package/src/model/qwen3-moe.ts +404 -0
  136. package/src/model/qwen3.ts +9 -8
  137. package/src/model/qwen3_5.ts +88 -23
  138. package/src/model/support.ts +19 -1
  139. package/src/model/universal/dense.ts +40 -5
  140. package/src/model/universal/rope.ts +36 -21
  141. package/src/native/expert_io.c +523 -0
  142. package/src/native-pack.ts +6 -4
  143. package/src/pi-web.ts +1299 -82
  144. package/src/preflight.ts +27 -8
  145. package/src/prompt-cache.ts +293 -33
  146. package/src/quantize/quantizer.ts +16 -1
  147. package/src/registry.ts +57 -2
  148. package/src/responses.ts +62 -49
  149. package/src/serve/batch-scheduler.ts +1050 -78
  150. package/src/serve/generation-gateway.ts +252 -24
  151. package/src/serve/isolate.ts +417 -0
  152. package/src/serve/lane-registry.ts +44 -0
  153. package/src/serve/session-search.ts +326 -0
  154. package/src/server.ts +1701 -175
  155. package/src/spec/assistant-source.ts +150 -0
  156. package/src/spec/deepspec-source.ts +143 -0
  157. package/src/spec/dflash-source.ts +124 -0
  158. package/src/spec/dspark/ab-stats.ts +136 -0
  159. package/src/spec/dspark/calibration.ts +112 -0
  160. package/src/spec/dspark/deepspec-module.ts +801 -0
  161. package/src/spec/dspark/generate-dflash.ts +72 -20
  162. package/src/spec/dspark/loader.ts +23 -0
  163. package/src/spec/dspark/module-dflash.ts +278 -36
  164. package/src/spec/dspark/quantize-drafter.ts +91 -0
  165. package/src/spec/generate.ts +59 -25
  166. package/src/spec/glm52-mtp-source.ts +392 -0
  167. package/src/spec/ngram-source.ts +132 -0
  168. package/src/spec/serve-loop.ts +617 -0
  169. package/src/spec/source.ts +118 -0
  170. package/src/spec/two-model.ts +171 -0
  171. package/src/ssd-cache.ts +111 -35
  172. package/src/tokenizer.ts +288 -2
  173. package/src/tool-approvals.ts +131 -0
  174. package/src/tool-call.ts +438 -22
  175. package/src/train/flash-cce.ts +2 -2
  176. package/src/train/job.ts +0 -12
  177. package/src/train/lora-params.ts +17 -6
  178. package/src/train/trainer.ts +60 -30
  179. package/src/vision/prompt.ts +217 -48
  180. package/src/web/app.html +1197 -1791
  181. package/src/web/app.js +5694 -0
  182. package/src/web/icon.svg +13 -0
  183. package/src/web/manifest.webmanifest +24 -0
  184. package/src/web/src/adapters-panel.ts +288 -0
  185. package/src/web/src/api.ts +57 -0
  186. package/src/web/src/assistant.ts +485 -0
  187. package/src/web/src/chat.ts +1050 -0
  188. package/src/web/src/composer.ts +959 -0
  189. package/src/web/src/dataset.ts +132 -0
  190. package/src/web/src/finetune.ts +267 -0
  191. package/src/web/src/hub.ts +428 -0
  192. package/src/web/src/main.ts +98 -0
  193. package/src/web/src/markdown.ts +0 -0
  194. package/src/web/src/memory-panel.ts +572 -0
  195. package/src/web/src/model-picker.ts +159 -0
  196. package/src/web/src/palette.ts +346 -0
  197. package/src/web/src/protocol.ts +62 -0
  198. package/src/web/src/quantize.ts +167 -0
  199. package/src/web/src/rag.ts +274 -0
  200. package/src/web/src/sessions.ts +469 -0
  201. package/src/web/src/shell.ts +804 -0
  202. package/src/web/src/status.ts +300 -0
  203. package/src/web/src/ui-catalog.ts +92 -0
  204. package/src/web/sw.js +71 -0
  205. package/src/web/vendor/README.md +61 -0
  206. package/src/web/vendor/hljs-LICENSE +29 -0
  207. package/src/web/vendor/hljs-theme.css +59 -0
  208. package/src/web/vendor/hljs.js +26 -0
  209. package/src/web-tools.ts +54 -2
  210. package/src/weights.ts +82 -19
  211. package/src/model/fused-decode-kernel.ts +0 -312
  212. package/src/model/fused-geglu-kernel.ts +0 -198
  213. package/src/model/fused-mlp-kernel.ts +0 -169
  214. package/src/model/fused-swiglu-kernel.ts +0 -240
  215. package/src/model/steel-linear-kernel.ts +0 -96
  216. package/src/status-page.html +0 -497
package/src/mlx/ops.ts CHANGED
@@ -43,10 +43,39 @@ export function sigmoid(a: MlxArray, s: S = gpuStream): MlxArray {
43
43
  return new MlxArray(outArray("sigmoid", (o) => C.mlx_sigmoid(o, a.handle, s)));
44
44
  }
45
45
 
46
- /** Scalar constant with the same dtype as `like` (python weak-scalar semantics). */
46
+ /** f32 → bf16 truncation with round-to-nearest-even, returning the 2
47
+ * little-endian bytes of the bf16 value. Matches mlx's
48
+ * `static_cast<bfloat16_t>(float)` bit-for-bit so a host-built bf16 scalar is
49
+ * numerically identical to `f32_scalar.astype(bf16)` — just without the GPU
50
+ * Copy (astype) kernel. */
51
+ function bf16Bytes(value: number): Uint8Array {
52
+ const fb = new Float32Array([value]);
53
+ const bits = new Uint32Array(fb.buffer)[0]!;
54
+ let hi16: number;
55
+ if (((bits >>> 23) & 0xff) === 0xff) {
56
+ // inf / nan: keep the high 16 bits, and keep a NaN a (quiet) NaN.
57
+ hi16 = (bits >>> 16) & 0xffff;
58
+ if ((bits & 0x7fffff) !== 0) hi16 |= 0x40;
59
+ } else {
60
+ const roundingBias = 0x7fff + ((bits >>> 16) & 1); // round to nearest even
61
+ hi16 = ((bits + roundingBias) >>> 16) & 0xffff;
62
+ }
63
+ return new Uint8Array([hi16 & 0xff, (hi16 >>> 8) & 0xff]);
64
+ }
65
+
66
+ /** Scalar constant with the same dtype as `like` (python weak-scalar semantics).
67
+ * Built HOST-SIDE at the target dtype — mlx's own scalar→array path constructs
68
+ * a bf16/f32 constant directly, so `scalar * bf16_array` is a single multiply.
69
+ * Going through an f32 leaf + GPU `.astype(bf16)` (the old path) emits a
70
+ * separate Copy kernel (`v_copy…`) that the reference never dispatches. */
47
71
  export function scalarLike(value: number, like: MlxArray): MlxArray {
72
+ if (like.dtype === Dtype.float32)
73
+ return MlxArray.fromFloat32(new Float32Array([value]), []);
74
+ if (like.dtype === Dtype.bfloat16)
75
+ return MlxArray.fromBytesCopy(bf16Bytes(value), [], Dtype.bfloat16);
76
+ // f16 / other float dtypes: keep the astype path (rare here; no bit-exact JS
77
+ // converter written for them yet).
48
78
  const f = MlxArray.fromFloat32(new Float32Array([value]), []);
49
- if (like.dtype === Dtype.float32) return f;
50
79
  const cast = f.astype(like.dtype);
51
80
  f.dispose();
52
81
  return cast;
@@ -147,6 +176,25 @@ export function ropeDynamic(
147
176
  );
148
177
  }
149
178
 
179
+ /** Array-offset fast::rope with every knob exposed (traditional + scale) —
180
+ * the dynamic twin of `ropeScaled`, for the universal rope factory's
181
+ * batched-decode path (per-row [B] offsets under left-padding). Same
182
+ * kernel as `ropeDynamic`; static/dynamic bit-exactness is asserted in
183
+ * tests/compile.test.ts. */
184
+ export function ropeScaledDynamic(
185
+ x: MlxArray, dims: number, traditional: boolean, base: number | null,
186
+ scale: number, offset: MlxArray, freqs: MlxArray | null, s: S = gpuStream,
187
+ ): MlxArray {
188
+ return new MlxArray(
189
+ outArray("fast_rope_dynamic", (o) =>
190
+ C.mlx_fast_rope_dynamic(
191
+ o, x.handle, dims, traditional, optFloat(base), scale, offset.handle,
192
+ freqs?.handle ?? 0n, s,
193
+ ),
194
+ ),
195
+ );
196
+ }
197
+
150
198
  export function sdpa(
151
199
  q: MlxArray, k: MlxArray, v: MlxArray, scale: number,
152
200
  maskMode: "" | "causal" | "array", maskArr: MlxArray | null = null,
@@ -292,21 +340,35 @@ export function pow(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
292
340
  return new MlxArray(outArray("power", (o) => C.mlx_power(o, a.handle, b.handle, s)));
293
341
  }
294
342
 
295
- /** nn.gelu_approx: 0.5 x (1 + tanh(√(2/π) (x + 0.044715 x³))) — composed
296
- * exactly as mlx's python source: x**3 is mx.power (NOT x·x·x — they
297
- * round differently in bf16), scalars promote weakly to x's dtype. */
343
+ /** nn.gelu_approx: 0.5 * x * (1 + tanh(√(2/π) * (x + 0.044715 * x³))) — composed
344
+ * exactly as mlx's python source, INCLUDING operand order: x**3 is mx.power
345
+ * (NOT x·x·x — they round differently in bf16), and every scalar·array product
346
+ * puts the SCALAR FIRST (`0.5 * x`, not `x * 0.5`). Multiply is commutative so
347
+ * this is bit-identical, but it makes the compiled geglu graph's operand string
348
+ * (`Multiply(C, V)`) match the oracle's fused kernel exactly. Scalars promote
349
+ * weakly to x's dtype. */
298
350
  export function geluApprox(x: MlxArray, s: S = gpuStream): MlxArray {
299
- const three = scalarLike(3, x);
300
- const x3 = pow(x, three, s);
301
- const cx3 = mulScalar(x3, 0.044715, s);
302
- const inner = add(x, cx3, s);
303
- const scaled = mulScalar(inner, Math.sqrt(2 / Math.PI), s);
351
+ // EXACT copy of mlx's graph for
352
+ // 0.5 * x * (1 + tanh(√(2/π) * (x + 0.044715 * x**3)))
353
+ // as dumped via mx.export_to_dot. mlx's `__rmul__`/`__radd__` canonicalize
354
+ // every `scalar OP array` to `array OP scalar`, so every commutative product/
355
+ // sum below is ARRAY-FIRST, constant-second (NOT scalar-first). Build order
356
+ // follows Python left-to-right (`0.5 * x` first). Same libmlx compiles this to
357
+ // the identical fused kernel.
358
+ const cHalf = scalarLike(0.5, x);
359
+ const halfx = mul(x, cHalf, s); // Multiply(x, 0.5)
360
+ const cThree = scalarLike(3, x);
361
+ const x3 = pow(x, cThree, s); // Power(x, 3)
362
+ const cCoef = scalarLike(0.044715, x);
363
+ const cx3 = mul(x3, cCoef, s); // Multiply(x**3, 0.044715)
364
+ const inner = add(x, cx3, s); // Add(x, cx3)
365
+ const cSqrt = scalarLike(Math.sqrt(2 / Math.PI), x);
366
+ const scaled = mul(inner, cSqrt, s); // Multiply(inner, √(2/π))
304
367
  const t = tanh(scaled, s);
305
- const one = scalarLike(1, x);
306
- const t1 = add(one, t, s);
307
- const halfx = mulScalar(x, 0.5, s);
308
- const out = mul(halfx, t1, s);
309
- for (const a of [three, x3, cx3, inner, scaled, t, one, t1, halfx]) a.dispose();
368
+ const cOne = scalarLike(1, x);
369
+ const t1 = add(t, cOne, s); // Add(tanh, 1)
370
+ const out = mul(halfx, t1, s); // Multiply(halfx, 1+tanh)
371
+ for (const a of [cHalf, halfx, cThree, x3, cCoef, cx3, inner, cSqrt, scaled, t, cOne, t1]) a.dispose();
310
372
  return out;
311
373
  }
312
374
 
@@ -402,7 +464,7 @@ export function where(cond: MlxArray, x: MlxArray, y: MlxArray, s: S = gpuStream
402
464
 
403
465
  // arange is built host-side and uploaded. The original mlx_arange binding
404
466
  // broke once the calling path got JIT-optimized; a standalone repro
405
- // (repro/bun-ffi-f64/) traced the root cause to a Bun bug: after DFG
467
+ // (lab/repro/bun-ffi-f64/) traced the root cause to a Bun bug: after DFG
406
468
  // tier-up, typed-array reads following a bun:ffi call return stale values
407
469
  // (the JIT eliminates the load across the native call). Not f64 marshaling
408
470
  // — args reach C intact. See PLAN.md Phase 4 findings. Large constant
@@ -418,13 +480,18 @@ export function arange(start: number, stop: number, step: number, dtype: Dtype,
418
480
  const cached = arangeCache.get(key);
419
481
  if (cached) return cached.slice([0], [n], s);
420
482
 
421
- const data = new Int32Array(n);
422
- for (let i = 0; i < n; i++) data[i] = start + i * step;
423
- let arr = MlxArray.fromInt32(data, [n]);
424
- if (dtype !== Dtype.int32) {
425
- const cast = arr.astype(dtype, s);
426
- arr.dispose();
427
- arr = cast;
483
+ let arr: MlxArray;
484
+ if (dtype === Dtype.int32) {
485
+ // host-built int32 leaf (the Bun-f64-FFI-safe path — see note above).
486
+ const data = new Int32Array(n);
487
+ for (let i = 0; i < n; i++) data[i] = start + i * step;
488
+ arr = MlxArray.fromInt32(data, [n]);
489
+ } else {
490
+ // Native mlx Arange in the target dtype — matches mlx's `Arange` op exactly.
491
+ // The old `fromInt32 → .astype(dtype)` emitted a phantom int32→float Copy
492
+ // (an AsType the oracle never dispatches — e.g. the proportional-RoPE freq
493
+ // exponents). Integer start/step passed as doubles are exact.
494
+ arr = new MlxArray(outArray("arange", (o) => C.mlx_arange(o, start, stop, step, dtype, s)));
428
495
  }
429
496
  if (n >= ARANGE_CACHE_MIN) {
430
497
  arangeCache.set(key, arr);
@@ -811,6 +878,26 @@ export function conv1d(
811
878
  );
812
879
  }
813
880
 
881
+ /** nn.Conv2d: input [B, H, W, C_in] (NHWC), weight [C_out, kH, kW, C_in/groups]
882
+ * → [B, H', W', C_out]. mlx weight layout — the oracle transposes PyTorch's
883
+ * [C_out, C_in, kH, kW] at load. For the gemma-4 audio SSCP subsampler.
884
+ * dilation_1 and groups ride in one packed u64 — see the mlx_conv2d hazard
885
+ * note in ffi.ts (bun:ffi stack-arg ABI bug). */
886
+ export function conv2d(
887
+ input: MlxArray, weight: MlxArray, stride: [number, number] = [1, 1],
888
+ padding: [number, number] = [0, 0], dilation: [number, number] = [1, 1],
889
+ groups = 1, s: S = gpuStream,
890
+ ): MlxArray {
891
+ const dilation1AndGroups =
892
+ (BigInt(dilation[1] >>> 0) & 0xffffffffn) | (BigInt(groups >>> 0) << 32n);
893
+ return new MlxArray(
894
+ outArray("conv2d", (o) =>
895
+ C.mlx_conv2d(o, input.handle, weight.handle, stride[0], stride[1],
896
+ padding[0], padding[1], dilation[0], dilation1AndGroups, s),
897
+ ),
898
+ );
899
+ }
900
+
814
901
  /** mx.split(a, indices, axis): split at the given boundary offsets along `axis`
815
902
  * into N+1 contiguous slices (mirrors numpy/mlx split-by-indices). */
816
903
  export function split(a: MlxArray, indices: number[], axis: number): MlxArray[] {
@@ -844,3 +931,46 @@ export function silu(a: MlxArray, s: S = gpuStream): MlxArray {
844
931
  sig.dispose();
845
932
  return r;
846
933
  }
934
+
935
+ /** fast::hadamard_transform over the last axis. `scale` defaults to
936
+ * 1/sqrt(dim) (mlx's own default when unset) — pass it explicitly to
937
+ * match a reference that always states its normalization, per
938
+ * turboquant-ops.ts's fwht(). */
939
+ export function hadamardTransform(x: MlxArray, scale: number | null = null, s: S = gpuStream): MlxArray {
940
+ return new MlxArray(
941
+ outArray("hadamard_transform", (o) =>
942
+ C.mlx_hadamard_transform(o, x.handle, optFloat(scale), s),
943
+ ),
944
+ );
945
+ }
946
+
947
+ export function minAxis(a: MlxArray, axis: number, keepdims: boolean, s: S = gpuStream): MlxArray {
948
+ return new MlxArray(
949
+ outArray("min_axis", (o) => C.mlx_min_axis(o, a.handle, axis, keepdims, s)),
950
+ );
951
+ }
952
+
953
+ /** mx.round(x, decimals=0) — round-half-to-even at the ULP grid mlx uses. */
954
+ export function round(a: MlxArray, s: S = gpuStream): MlxArray {
955
+ return new MlxArray(outArray("round", (o) => C.mlx_round(o, a.handle, 0, s)));
956
+ }
957
+
958
+ export function greater(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
959
+ return new MlxArray(outArray("greater", (o) => C.mlx_greater(o, a.handle, b.handle, s)));
960
+ }
961
+
962
+ export function bitwiseAnd(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
963
+ return new MlxArray(outArray("bitwise_and", (o) => C.mlx_bitwise_and(o, a.handle, b.handle, s)));
964
+ }
965
+
966
+ export function bitwiseOr(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
967
+ return new MlxArray(outArray("bitwise_or", (o) => C.mlx_bitwise_or(o, a.handle, b.handle, s)));
968
+ }
969
+
970
+ export function leftShift(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
971
+ return new MlxArray(outArray("left_shift", (o) => C.mlx_left_shift(o, a.handle, b.handle, s)));
972
+ }
973
+
974
+ export function rightShift(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
975
+ return new MlxArray(outArray("right_shift", (o) => C.mlx_right_shift(o, a.handle, b.handle, s)));
976
+ }