@danielsimonjr/mathts-autograd 0.3.1 → 0.3.3

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.
package/dist/index.d.ts CHANGED
@@ -58,6 +58,14 @@ declare class DualTensor {
58
58
  */
59
59
  divide(other: DualTensor): DualTensor;
60
60
  private _unaryElementwise;
61
+ /**
62
+ * Apply a shared elementary rule from core's `DUAL_UNARY_RULES` element-wise.
63
+ * Sourcing `primal`/`deriv` from the canonical table (rather than inline
64
+ * `Math.*`) keeps this AD path and the scalar `Dual` in lock-step and lets a
65
+ * future accelerated `primal` in the standard layer propagate here for free —
66
+ * the loop still calls plain scalar functions, so it stays allocation-free.
67
+ */
68
+ private _rule;
61
69
  /** Exponential. f'(x) = eˣ = y. */
62
70
  exp(): DualTensor;
63
71
  /** Natural logarithm. f'(x) = 1/x. */
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  // src/dual-tensor.ts
2
2
  import { Tensor } from "@danielsimonjr/mathts-tensor";
3
+ import { DUAL_UNARY_RULES } from "@danielsimonjr/mathts-core";
3
4
  var DualTensor = class _DualTensor {
4
5
  shape;
5
6
  primal;
@@ -138,47 +139,51 @@ var DualTensor = class _DualTensor {
138
139
  }
139
140
  return new _DualTensor(this.shape, p, t);
140
141
  }
142
+ /**
143
+ * Apply a shared elementary rule from core's `DUAL_UNARY_RULES` element-wise.
144
+ * Sourcing `primal`/`deriv` from the canonical table (rather than inline
145
+ * `Math.*`) keeps this AD path and the scalar `Dual` in lock-step and lets a
146
+ * future accelerated `primal` in the standard layer propagate here for free —
147
+ * the loop still calls plain scalar functions, so it stays allocation-free.
148
+ */
149
+ _rule(rule) {
150
+ return this._unaryElementwise(rule.primal, rule.deriv);
151
+ }
141
152
  /** Exponential. f'(x) = eˣ = y. */
142
153
  exp() {
143
- return this._unaryElementwise(Math.exp, (_x, y) => y);
154
+ return this._rule(DUAL_UNARY_RULES.exp);
144
155
  }
145
156
  /** Natural logarithm. f'(x) = 1/x. */
146
157
  log() {
147
- return this._unaryElementwise(Math.log, (x) => 1 / x);
158
+ return this._rule(DUAL_UNARY_RULES.log);
148
159
  }
149
160
  /** Sine. f'(x) = cos(x). */
150
161
  sin() {
151
- return this._unaryElementwise(Math.sin, (x) => Math.cos(x));
162
+ return this._rule(DUAL_UNARY_RULES.sin);
152
163
  }
153
164
  /** Cosine. f'(x) = −sin(x). */
154
165
  cos() {
155
- return this._unaryElementwise(Math.cos, (x) => -Math.sin(x));
166
+ return this._rule(DUAL_UNARY_RULES.cos);
156
167
  }
157
168
  /** Tangent. f'(x) = 1/cos²(x). */
158
169
  tan() {
159
- return this._unaryElementwise(Math.tan, (x) => 1 / (Math.cos(x) * Math.cos(x)));
170
+ return this._rule(DUAL_UNARY_RULES.tan);
160
171
  }
161
172
  /** Square root. f'(x) = 1/(2·y) where y = √x. */
162
173
  sqrt() {
163
- return this._unaryElementwise(Math.sqrt, (_x, y) => 1 / (2 * y));
174
+ return this._rule(DUAL_UNARY_RULES.sqrt);
164
175
  }
165
176
  /** Square (x²). f'(x) = 2x. */
166
177
  square() {
167
- return this._unaryElementwise(
168
- (x) => x * x,
169
- (x) => 2 * x
170
- );
178
+ return this._rule(DUAL_UNARY_RULES.square);
171
179
  }
172
180
  /** Reciprocal (1/x). f'(x) = −1/x². */
173
181
  reciprocal() {
174
- return this._unaryElementwise(
175
- (x) => 1 / x,
176
- (x) => -1 / (x * x)
177
- );
182
+ return this._rule(DUAL_UNARY_RULES.reciprocal);
178
183
  }
179
184
  /** Absolute value. f'(x) = sign(x) (subgradient 0 at exact zero). */
180
185
  abs() {
181
- return this._unaryElementwise(Math.abs, (x) => Math.sign(x));
186
+ return this._rule(DUAL_UNARY_RULES.abs);
182
187
  }
183
188
  /** Fixed-exponent power x^k. f'(x) = k·x^(k−1). */
184
189
  pow(k) {
@@ -189,63 +194,63 @@ var DualTensor = class _DualTensor {
189
194
  }
190
195
  /** Hyperbolic sine. f'(x) = cosh(x). */
191
196
  sinh() {
192
- return this._unaryElementwise(Math.sinh, (x) => Math.cosh(x));
197
+ return this._rule(DUAL_UNARY_RULES.sinh);
193
198
  }
194
199
  /** Hyperbolic cosine. f'(x) = sinh(x). */
195
200
  cosh() {
196
- return this._unaryElementwise(Math.cosh, (x) => Math.sinh(x));
201
+ return this._rule(DUAL_UNARY_RULES.cosh);
197
202
  }
198
203
  /** Hyperbolic tangent. f'(x) = 1 − tanh²(x) = 1 − y². */
199
204
  tanh() {
200
- return this._unaryElementwise(Math.tanh, (_x, y) => 1 - y * y);
205
+ return this._rule(DUAL_UNARY_RULES.tanh);
201
206
  }
202
207
  /** Arcsine. f'(x) = 1/√(1 − x²). */
203
208
  asin() {
204
- return this._unaryElementwise(Math.asin, (x) => 1 / Math.sqrt(1 - x * x));
209
+ return this._rule(DUAL_UNARY_RULES.asin);
205
210
  }
206
211
  /** Arccosine. f'(x) = −1/√(1 − x²). */
207
212
  acos() {
208
- return this._unaryElementwise(Math.acos, (x) => -1 / Math.sqrt(1 - x * x));
213
+ return this._rule(DUAL_UNARY_RULES.acos);
209
214
  }
210
215
  /** Arctangent. f'(x) = 1/(1 + x²). */
211
216
  atan() {
212
- return this._unaryElementwise(Math.atan, (x) => 1 / (1 + x * x));
217
+ return this._rule(DUAL_UNARY_RULES.atan);
213
218
  }
214
219
  /** Inverse hyperbolic sine. f'(x) = 1/√(x² + 1). */
215
220
  asinh() {
216
- return this._unaryElementwise(Math.asinh, (x) => 1 / Math.sqrt(x * x + 1));
221
+ return this._rule(DUAL_UNARY_RULES.asinh);
217
222
  }
218
223
  /** Inverse hyperbolic cosine (x ≥ 1). f'(x) = 1/√(x² − 1). */
219
224
  acosh() {
220
- return this._unaryElementwise(Math.acosh, (x) => 1 / Math.sqrt(x * x - 1));
225
+ return this._rule(DUAL_UNARY_RULES.acosh);
221
226
  }
222
227
  /** Inverse hyperbolic tangent (|x| < 1). f'(x) = 1/(1 − x²). */
223
228
  atanh() {
224
- return this._unaryElementwise(Math.atanh, (x) => 1 / (1 - x * x));
229
+ return this._rule(DUAL_UNARY_RULES.atanh);
225
230
  }
226
231
  /** Base-2 logarithm. f'(x) = 1/(x·ln2). */
227
232
  log2() {
228
- return this._unaryElementwise(Math.log2, (x) => 1 / (x * Math.LN2));
233
+ return this._rule(DUAL_UNARY_RULES.log2);
229
234
  }
230
235
  /** Base-10 logarithm. f'(x) = 1/(x·ln10). */
231
236
  log10() {
232
- return this._unaryElementwise(Math.log10, (x) => 1 / (x * Math.LN10));
237
+ return this._rule(DUAL_UNARY_RULES.log10);
233
238
  }
234
239
  /** log(1 + x). f'(x) = 1/(1 + x). */
235
240
  log1p() {
236
- return this._unaryElementwise(Math.log1p, (x) => 1 / (1 + x));
241
+ return this._rule(DUAL_UNARY_RULES.log1p);
237
242
  }
238
243
  /** exp(x) − 1. f'(x) = eˣ = y + 1. */
239
244
  expm1() {
240
- return this._unaryElementwise(Math.expm1, (_x, y) => y + 1);
245
+ return this._rule(DUAL_UNARY_RULES.expm1);
241
246
  }
242
247
  /** Cube root. f'(x) = 1/(3·y²) where y = x^(1/3) (→∞ at x = 0). */
243
248
  cbrt() {
244
- return this._unaryElementwise(Math.cbrt, (_x, y) => 1 / (3 * y * y));
249
+ return this._rule(DUAL_UNARY_RULES.cbrt);
245
250
  }
246
251
  /** Sign (−1/0/+1). f'(x) = 0 almost everywhere. */
247
252
  sign() {
248
- return this._unaryElementwise(Math.sign, () => 0);
253
+ return this._rule(DUAL_UNARY_RULES.sign);
249
254
  }
250
255
  /**
251
256
  * Two-argument arctangent: atan2(this, other), this = y, other = x.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danielsimonjr/mathts-autograd",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Forward + reverse-mode automatic differentiation for MathTS rank-N Tensor",
5
5
  "author": "Daniel Simon Jr.",
6
6
  "license": "MIT",
@@ -31,8 +31,8 @@
31
31
  "build:prod": "tsup src/index.ts --format esm --dts --clean --minify --treeshake"
32
32
  },
33
33
  "dependencies": {
34
- "@danielsimonjr/mathts-core": "^0.2.0",
35
- "@danielsimonjr/mathts-tensor": "^0.2.1"
34
+ "@danielsimonjr/mathts-core": "^0.4.0",
35
+ "@danielsimonjr/mathts-tensor": "^0.2.4"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/node": "^25.5.2",