mlx-bun 0.0.9 → 0.0.11

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 (179) hide show
  1. package/README.md +66 -21
  2. package/THIRD_PARTY_LICENSES.md +1 -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 +255 -0
  7. package/docs/design/batching-v2-plan.md +23 -9
  8. package/docs/design/bucketing-stage.md +2 -1
  9. package/docs/design/compat-cli-surface-design.md +4 -3
  10. package/docs/design/decode-speed-program.md +172 -0
  11. package/docs/design/docs-reorg-plan.md +1 -1
  12. package/docs/design/dspark-serving-program.md +371 -0
  13. package/docs/design/dspark-speculative-decoding.md +167 -5
  14. package/docs/design/faithful-l1-consolidation.md +310 -0
  15. package/docs/design/generic-model-support.md +8 -5
  16. package/docs/design/grammar-spec-batching-integration.md +301 -0
  17. package/docs/design/minicpm5-decode-megakernel.md +16 -11
  18. package/docs/design/mlx-lm-tool-parity-plan.md +11 -1
  19. package/docs/design/omlx-adoption-map.md +98 -0
  20. package/docs/design/orpo-training.md +34 -30
  21. package/docs/design/paged-kv-cache.md +214 -0
  22. package/docs/design/parallel-slots.md +82 -49
  23. package/docs/design/parity-tier-dag.md +43 -33
  24. package/docs/design/repo-cleanup-plan.md +189 -0
  25. package/docs/design/runtime-isolation.md +19 -3
  26. package/docs/design/segmented-backward-training.md +18 -2
  27. package/docs/design/ssd-kv-cold-tier.md +288 -0
  28. package/docs/design/structured-output.md +484 -0
  29. package/docs/design/the-dreaming-master-plan.md +2 -3
  30. package/docs/design/turboquant-kv.md +235 -0
  31. package/docs/design/unified-engine-frontier-plan.md +774 -0
  32. package/docs/design/web-chat-beat-matrix.md +315 -0
  33. package/docs/design/web-chat-redesign.md +1112 -0
  34. package/docs/investigations/decode-roofline-lookagain.md +92 -6
  35. package/docs/investigations/dspark-handoff.md +182 -16
  36. package/docs/investigations/kernel-perf-review-2026-07.md +105 -26
  37. package/docs/investigations/lab-build-journal.md +2 -2
  38. package/docs/investigations/openwiki-evaluation.md +249 -0
  39. package/docs/planning/IDEAS.md +14 -0
  40. package/docs/planning/PRODUCT_ROADMAP.md +2 -3
  41. package/docs/planning/chat-ui-vision-memory-first.md +199 -0
  42. package/docs/planning/chat-ui-vision.md +50 -0
  43. package/docs/planning/memory-docs-and-dag-plan.md +15 -6
  44. package/docs/planning/release-notes-v0.0.10.md +57 -0
  45. package/docs/planning/release-notes-v0.0.11.md +239 -0
  46. package/docs/reference/cli.md +35 -16
  47. package/docs/reference/distribution.md +13 -6
  48. package/docs/reference/embedding.md +35 -14
  49. package/docs/reference/features-matrix.md +97 -0
  50. package/docs/reference/library-api.md +30 -9
  51. package/docs/reference/memory.md +26 -6
  52. package/docs/reference/models.md +11 -1
  53. package/docs/reference/orpo-quickstart.md +3 -4
  54. package/docs/reference/server-api.md +634 -22
  55. package/docs/reference/server-config.md +251 -119
  56. package/docs/reference/training.md +20 -16
  57. package/package.json +5 -3
  58. package/src/anthropic.ts +13 -0
  59. package/src/audio/conformer.ts +647 -0
  60. package/src/audio/decode.ts +133 -0
  61. package/src/audio/features.ts +202 -0
  62. package/src/audio/transcode.ts +67 -0
  63. package/src/cli.ts +402 -107
  64. package/src/config.ts +49 -2
  65. package/src/download.ts +40 -0
  66. package/src/eval/README.md +7 -6
  67. package/src/eval/kl.ts +59 -3
  68. package/src/eval/quality-db.ts +2 -2
  69. package/src/eval/runner.ts +3 -3
  70. package/src/expert-offload.ts +15 -2
  71. package/src/flags.ts +13 -0
  72. package/src/generate.ts +330 -16
  73. package/src/grammar.ts +585 -0
  74. package/src/hub-rest.ts +242 -0
  75. package/src/kv-store.ts +618 -122
  76. package/src/lora.ts +8 -0
  77. package/src/md-modules.d.ts +42 -0
  78. package/src/media-fetch.ts +284 -0
  79. package/src/memory/rest.ts +245 -0
  80. package/src/memory/vault.ts +74 -0
  81. package/src/mlx/array.ts +127 -19
  82. package/src/mlx/autograd.ts +2 -2
  83. package/src/mlx/ffi.ts +27 -3
  84. package/src/mlx/metal-kernel.ts +7 -4
  85. package/src/mlx/ops.ts +179 -23
  86. package/src/mlx/turboquant-ops.ts +831 -0
  87. package/src/mlx/turboquant-tables.ts +237 -0
  88. package/src/model/batched-mask.ts +62 -1
  89. package/src/model/batched-quant.ts +206 -0
  90. package/src/model/batched-rotating-quant.ts +346 -0
  91. package/src/model/batched-rotating.ts +46 -1
  92. package/src/model/compiled-decode.ts +4 -15
  93. package/src/model/factory.ts +10 -4
  94. package/src/model/gemma4-base.ts +391 -34
  95. package/src/model/gemma4.ts +122 -33
  96. package/src/model/generated/gemma4-12b.ts +9 -13
  97. package/src/model/generated/gemma4-26b.ts +10 -5
  98. package/src/model/generated/gemma4-e4b.ts +14 -9
  99. package/src/model/minicpm5.ts +58 -102
  100. package/src/model/paged-kv.ts +253 -0
  101. package/src/model/qwen3-delta.ts +123 -15
  102. package/src/model/qwen3-moe.ts +404 -0
  103. package/src/model/qwen3.ts +9 -8
  104. package/src/model/qwen3_5.ts +99 -25
  105. package/src/model/support.ts +12 -1
  106. package/src/model/universal/dense.ts +40 -5
  107. package/src/model/universal/rope.ts +36 -21
  108. package/src/pi-web.ts +1299 -82
  109. package/src/preflight.ts +27 -8
  110. package/src/prompt-cache.ts +338 -32
  111. package/src/quantize/quantizer.ts +16 -1
  112. package/src/registry.ts +61 -3
  113. package/src/serve/batch-scheduler.ts +1001 -76
  114. package/src/serve/generation-gateway.ts +292 -30
  115. package/src/serve/isolate.ts +417 -0
  116. package/src/serve/lane-registry.ts +44 -0
  117. package/src/serve/session-search.ts +326 -0
  118. package/src/server.ts +1460 -105
  119. package/src/spec/assistant-source.ts +150 -0
  120. package/src/spec/deepspec-source.ts +143 -0
  121. package/src/spec/dflash-source.ts +124 -0
  122. package/src/spec/dspark/ab-stats.ts +136 -0
  123. package/src/spec/dspark/calibration.ts +112 -0
  124. package/src/spec/dspark/deepspec-module.ts +801 -0
  125. package/src/spec/dspark/generate-dflash.ts +72 -20
  126. package/src/spec/dspark/loader.ts +23 -0
  127. package/src/spec/dspark/module-dflash.ts +278 -36
  128. package/src/spec/dspark/quantize-drafter.ts +91 -0
  129. package/src/spec/generate.ts +59 -25
  130. package/src/spec/ngram-source.ts +132 -0
  131. package/src/spec/serve-loop.ts +536 -0
  132. package/src/spec/source.ts +93 -0
  133. package/src/spec/two-model.ts +171 -0
  134. package/src/ssd-cache.ts +285 -0
  135. package/src/tokenizer.ts +288 -2
  136. package/src/tool-approvals.ts +131 -0
  137. package/src/tool-call.ts +408 -20
  138. package/src/train/flash-cce.ts +29 -26
  139. package/src/train/job.ts +0 -2
  140. package/src/train/loss.ts +53 -11
  141. package/src/train/prefix-shared.ts +30 -7
  142. package/src/train/segmented.ts +150 -46
  143. package/src/train/trainer.ts +22 -15
  144. package/src/vision/prompt.ts +217 -48
  145. package/src/web/app.html +1184 -1789
  146. package/src/web/app.js +5667 -0
  147. package/src/web/icon.svg +13 -0
  148. package/src/web/manifest.webmanifest +24 -0
  149. package/src/web/src/adapters-panel.ts +288 -0
  150. package/src/web/src/api.ts +57 -0
  151. package/src/web/src/assistant.ts +485 -0
  152. package/src/web/src/chat.ts +1050 -0
  153. package/src/web/src/composer.ts +959 -0
  154. package/src/web/src/dataset.ts +132 -0
  155. package/src/web/src/finetune.ts +267 -0
  156. package/src/web/src/hub.ts +428 -0
  157. package/src/web/src/main.ts +98 -0
  158. package/src/web/src/markdown.ts +0 -0
  159. package/src/web/src/memory-panel.ts +572 -0
  160. package/src/web/src/model-picker.ts +159 -0
  161. package/src/web/src/palette.ts +346 -0
  162. package/src/web/src/protocol.ts +62 -0
  163. package/src/web/src/quantize.ts +167 -0
  164. package/src/web/src/rag.ts +274 -0
  165. package/src/web/src/sessions.ts +469 -0
  166. package/src/web/src/shell.ts +804 -0
  167. package/src/web/src/status.ts +252 -0
  168. package/src/web/src/ui-catalog.ts +92 -0
  169. package/src/web/sw.js +71 -0
  170. package/src/web/vendor/README.md +61 -0
  171. package/src/web/vendor/hljs-LICENSE +29 -0
  172. package/src/web/vendor/hljs-theme.css +59 -0
  173. package/src/web/vendor/hljs.js +26 -0
  174. package/src/model/fused-decode-kernel.ts +0 -312
  175. package/src/model/fused-geglu-kernel.ts +0 -198
  176. package/src/model/fused-mlp-kernel.ts +0 -169
  177. package/src/model/fused-swiglu-kernel.ts +0 -240
  178. package/src/model/steel-linear-kernel.ts +0 -96
  179. 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,
@@ -172,6 +220,32 @@ export function quantizedMatmul(
172
220
  x: MlxArray, w: MlxArray, scales: MlxArray, biases: MlxArray | null,
173
221
  spec: QuantSpec, transpose = true, s: S = gpuStream,
174
222
  ): MlxArray {
223
+ // UPSTREAM MLX BUG WORKAROUND (found 2026-07-02, reproduced on stock mlx
224
+ // 0.31.2): quantized_matmul with transpose=false returns WRONG VALUES when
225
+ // the row count is 2 or 3 (relnorm ~0.3-1.1 vs the dequantized matmul);
226
+ // M=1 and M>=4 are correct, transpose=true is correct at every M. Pad the
227
+ // row axis to 4 with zeros and slice the result back. NOTE this wrapper
228
+ // cannot protect mlx's INTERNAL vjp of a transpose=true qmm (C++ calls the
229
+ // primitive directly) — training heads pad the span through the head
230
+ // instead (loss.ts logitsFromHiddenPadM).
231
+ const rowAxis = x.shape.length - 2;
232
+ const rows = x.shape[rowAxis]!;
233
+ if (!transpose && (rows === 2 || rows === 3)) {
234
+ const padShape = [...x.shape];
235
+ padShape[rowAxis] = 4 - rows;
236
+ const pad = zeros(padShape, x.dtype, s);
237
+ const xPad = concatAxis([x, pad], rowAxis, s);
238
+ pad.dispose();
239
+ const yPad = quantizedMatmul(xPad, w, scales, biases, spec, transpose, s);
240
+ xPad.dispose();
241
+ const start = MlxArray.fromInt32(new Int32Array([0]), [1]);
242
+ const outShape = [...yPad.shape];
243
+ outShape[rowAxis] = rows;
244
+ const y = sliceDynamic(yPad, start, [rowAxis], outShape, s);
245
+ start.dispose();
246
+ yPad.dispose();
247
+ return y;
248
+ }
175
249
  return new MlxArray(
176
250
  outArray("quantized_matmul", (o) =>
177
251
  C.mlx_quantized_matmul(
@@ -266,21 +340,35 @@ export function pow(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
266
340
  return new MlxArray(outArray("power", (o) => C.mlx_power(o, a.handle, b.handle, s)));
267
341
  }
268
342
 
269
- /** nn.gelu_approx: 0.5 x (1 + tanh(√(2/π) (x + 0.044715 x³))) — composed
270
- * exactly as mlx's python source: x**3 is mx.power (NOT x·x·x — they
271
- * 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. */
272
350
  export function geluApprox(x: MlxArray, s: S = gpuStream): MlxArray {
273
- const three = scalarLike(3, x);
274
- const x3 = pow(x, three, s);
275
- const cx3 = mulScalar(x3, 0.044715, s);
276
- const inner = add(x, cx3, s);
277
- 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/π))
278
367
  const t = tanh(scaled, s);
279
- const one = scalarLike(1, x);
280
- const t1 = add(one, t, s);
281
- const halfx = mulScalar(x, 0.5, s);
282
- const out = mul(halfx, t1, s);
283
- 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();
284
372
  return out;
285
373
  }
286
374
 
@@ -376,7 +464,7 @@ export function where(cond: MlxArray, x: MlxArray, y: MlxArray, s: S = gpuStream
376
464
 
377
465
  // arange is built host-side and uploaded. The original mlx_arange binding
378
466
  // broke once the calling path got JIT-optimized; a standalone repro
379
- // (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
380
468
  // tier-up, typed-array reads following a bun:ffi call return stale values
381
469
  // (the JIT eliminates the load across the native call). Not f64 marshaling
382
470
  // — args reach C intact. See PLAN.md Phase 4 findings. Large constant
@@ -392,13 +480,18 @@ export function arange(start: number, stop: number, step: number, dtype: Dtype,
392
480
  const cached = arangeCache.get(key);
393
481
  if (cached) return cached.slice([0], [n], s);
394
482
 
395
- const data = new Int32Array(n);
396
- for (let i = 0; i < n; i++) data[i] = start + i * step;
397
- let arr = MlxArray.fromInt32(data, [n]);
398
- if (dtype !== Dtype.int32) {
399
- const cast = arr.astype(dtype, s);
400
- arr.dispose();
401
- 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)));
402
495
  }
403
496
  if (n >= ARANGE_CACHE_MIN) {
404
497
  arangeCache.set(key, arr);
@@ -785,6 +878,26 @@ export function conv1d(
785
878
  );
786
879
  }
787
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
+
788
901
  /** mx.split(a, indices, axis): split at the given boundary offsets along `axis`
789
902
  * into N+1 contiguous slices (mirrors numpy/mlx split-by-indices). */
790
903
  export function split(a: MlxArray, indices: number[], axis: number): MlxArray[] {
@@ -818,3 +931,46 @@ export function silu(a: MlxArray, s: S = gpuStream): MlxArray {
818
931
  sig.dispose();
819
932
  return r;
820
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
+ }