catniff 0.2.11 → 0.2.13

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/README.md CHANGED
@@ -87,6 +87,9 @@ I'm mostly just learning and playing with this currently, so there are no concre
87
87
  * Proper documentation.
88
88
  * GPU acceleration.
89
89
  * Some general neural net APIs.
90
+ * Refactor code.
91
+ * Proper tests.
92
+ * Option to load more backends.
90
93
 
91
94
  ## Copyrights and License
92
95
 
package/dist/core.d.ts CHANGED
@@ -41,6 +41,8 @@ export declare class Tensor {
41
41
  sum(dims?: number[] | number, keepDims?: boolean): Tensor;
42
42
  prod(dims?: number[] | number, keepDims?: boolean): Tensor;
43
43
  mean(dims?: number[] | number, keepDims?: boolean): Tensor;
44
+ max(dims?: number[] | number, keepDims?: boolean): Tensor;
45
+ min(dims?: number[] | number, keepDims?: boolean): Tensor;
44
46
  add(other: TensorValue | Tensor): Tensor;
45
47
  sub(other: TensorValue | Tensor): Tensor;
46
48
  subtract: (other: TensorValue | Tensor) => Tensor;
@@ -137,9 +139,20 @@ export declare class Tensor {
137
139
  mm(other: TensorValue | Tensor): Tensor;
138
140
  mv(other: TensorValue | Tensor): Tensor;
139
141
  matmul(other: TensorValue | Tensor): Tensor;
142
+ static full(shape: number[], num: number, options?: TensorOptions): Tensor;
140
143
  static fullLike(tensor: Tensor, num: number, options?: TensorOptions): Tensor;
144
+ static ones(shape?: number[], options?: TensorOptions): Tensor;
141
145
  static onesLike(tensor: Tensor, options?: TensorOptions): Tensor;
146
+ static zeros(shape?: number[], options?: TensorOptions): Tensor;
142
147
  static zerosLike(tensor: Tensor, options?: TensorOptions): Tensor;
148
+ static rand(shape?: number[], options?: TensorOptions): Tensor;
149
+ static randLike(tensor: Tensor, options?: TensorOptions): Tensor;
150
+ static randn(shape?: number[], options?: TensorOptions): Tensor;
151
+ static randnLike(tensor: Tensor, options?: TensorOptions): Tensor;
152
+ static randint(shape: number[], low: number, high: number, options?: TensorOptions): Tensor;
153
+ static randintLike(tensor: Tensor, low: number, high: number, options?: TensorOptions): Tensor;
154
+ static normal(shape: number[], mean: number, stdDev: number, options?: TensorOptions): Tensor;
155
+ static uniform(shape: number[], low: number, high: number, options?: TensorOptions): Tensor;
143
156
  backward(): void;
144
157
  val(): TensorValue;
145
158
  withGrad(requiresGrad: boolean): Tensor;
package/dist/core.js CHANGED
@@ -252,7 +252,7 @@ class Tensor {
252
252
  // Tensor squeeze
253
253
  squeeze(dims) {
254
254
  if (typeof this.value === "number")
255
- return new Tensor(this.value);
255
+ return this;
256
256
  if (typeof dims === "number") {
257
257
  dims = [dims];
258
258
  }
@@ -300,10 +300,9 @@ class Tensor {
300
300
  }
301
301
  // Tensor unsqueeze - adds dimension of size 1 at specified position
302
302
  unsqueeze(dim) {
303
- if (typeof this.value === "number")
304
- return new Tensor([this.value]);
305
- if (dim < 0 || dim > this.shape.length) {
306
- throw new Error(`Invalid dimension ${dim} for unsqueeze`);
303
+ let thisValue = this.value;
304
+ if (typeof thisValue === "number") {
305
+ thisValue = [thisValue];
307
306
  }
308
307
  // Insert size-1 dimension at specified position
309
308
  const newShape = [...this.shape];
@@ -320,7 +319,7 @@ class Tensor {
320
319
  newDimStride = this.strides[dim] * this.shape[dim];
321
320
  }
322
321
  newStrides.splice(dim, 0, newDimStride);
323
- const out = new Tensor(this.value, { shape: newShape, strides: newStrides });
322
+ const out = new Tensor(thisValue, { shape: newShape, strides: newStrides });
324
323
  // Set up gradient if needed
325
324
  if (this.requiresGrad) {
326
325
  out.requiresGrad = true;
@@ -334,7 +333,7 @@ class Tensor {
334
333
  // Tensor sum reduction
335
334
  sum(dims, keepDims = false) {
336
335
  if (typeof this.value === "number")
337
- return new Tensor(this.value);
336
+ return this;
338
337
  if (typeof dims === "number") {
339
338
  dims = [dims];
340
339
  }
@@ -364,6 +363,7 @@ class Tensor {
364
363
  const outFlatIndex = Tensor.coordsToIndex(outCoords, outputStrides);
365
364
  // Accumulate, outFlatIndex should match multiple realFlatIndexes
366
365
  const realFlatIndex = Tensor.coordsToIndex(coords, this.strides);
366
+ // Add into sum
367
367
  outputValue[outFlatIndex] += this.value[realFlatIndex];
368
368
  // Mark for gradient if needed
369
369
  if (this.requiresGrad) {
@@ -388,7 +388,7 @@ class Tensor {
388
388
  // Tensor product reduction
389
389
  prod(dims, keepDims = false) {
390
390
  if (typeof this.value === "number")
391
- return new Tensor(this.value);
391
+ return this;
392
392
  if (typeof dims === "number") {
393
393
  dims = [dims];
394
394
  }
@@ -401,14 +401,6 @@ class Tensor {
401
401
  const outputSize = Tensor.shapeToSize(outputShape);
402
402
  const outputValue = new Array(outputSize).fill(1);
403
403
  const originalSize = Tensor.shapeToSize(this.shape);
404
- // Gradient data
405
- let gradShape, gradStrides, gradValue = [];
406
- // Allocate gradient data only when needed
407
- if (this.requiresGrad) {
408
- gradShape = this.shape;
409
- gradStrides = this.strides;
410
- gradValue = new Array(originalSize).fill(0);
411
- }
412
404
  // Calculate new value after multiplying
413
405
  for (let index = 0; index < originalSize; index++) {
414
406
  const coords = Tensor.indexToCoords(index, this.strides);
@@ -418,6 +410,7 @@ class Tensor {
418
410
  const outFlatIndex = Tensor.coordsToIndex(outCoords, outputStrides);
419
411
  // Accumulate, outFlatIndex should match multiple realFlatIndexes
420
412
  const realFlatIndex = Tensor.coordsToIndex(coords, this.strides);
413
+ // Multiply into product
421
414
  outputValue[outFlatIndex] *= this.value[realFlatIndex];
422
415
  }
423
416
  const out = new Tensor(outputValue, {
@@ -426,7 +419,7 @@ class Tensor {
426
419
  });
427
420
  // Set up gradient if needed
428
421
  if (this.requiresGrad) {
429
- // Grad is the product of other elements of the same axis, which is product of all els divided by the current value
422
+ const gradShape = this.shape, gradStrides = this.strides, gradValue = new Array(originalSize).fill(0);
430
423
  for (let index = 0; index < originalSize; index++) {
431
424
  const coords = Tensor.indexToCoords(index, this.strides);
432
425
  // Force 0 on reduced axes to collapse into size-1 dims
@@ -435,7 +428,7 @@ class Tensor {
435
428
  const outFlatIndex = Tensor.coordsToIndex(outCoords, outputStrides);
436
429
  // Accumulate, outFlatIndex should match multiple realFlatIndexes
437
430
  const realFlatIndex = Tensor.coordsToIndex(coords, this.strides);
438
- // Calculate gradient at position
431
+ // Grad is the product of other elements of the same axis, which is product of all els divided by the current value
439
432
  gradValue[realFlatIndex] = outputValue[outFlatIndex] / this.value[realFlatIndex];
440
433
  }
441
434
  out.requiresGrad = true;
@@ -450,7 +443,7 @@ class Tensor {
450
443
  // Tensor mean reduction
451
444
  mean(dims, keepDims = false) {
452
445
  if (typeof this.value === "number")
453
- return new Tensor(this.value);
446
+ return this;
454
447
  if (typeof dims === "number") {
455
448
  dims = [dims];
456
449
  }
@@ -464,14 +457,6 @@ class Tensor {
464
457
  const outputValue = new Array(outputSize).fill(0);
465
458
  const outputFeeders = new Array(outputSize).fill(0);
466
459
  const originalSize = Tensor.shapeToSize(this.shape);
467
- // Gradient data
468
- let gradShape, gradStrides, gradValue = [];
469
- // Allocate gradient data only when needed
470
- if (this.requiresGrad) {
471
- gradShape = this.shape;
472
- gradStrides = this.strides;
473
- gradValue = new Array(originalSize).fill(0);
474
- }
475
460
  // Calculate sums and how many elements contribute to specific positions
476
461
  for (let index = 0; index < originalSize; index++) {
477
462
  const coords = Tensor.indexToCoords(index, this.strides);
@@ -481,6 +466,7 @@ class Tensor {
481
466
  const outFlatIndex = Tensor.coordsToIndex(outCoords, outputStrides);
482
467
  // Accumulate, outFlatIndex should match multiple realFlatIndexes
483
468
  const realFlatIndex = Tensor.coordsToIndex(coords, this.strides);
469
+ // Calculate sum and contributors to the sum
484
470
  outputValue[outFlatIndex] += this.value[realFlatIndex];
485
471
  outputFeeders[outFlatIndex]++;
486
472
  }
@@ -494,7 +480,8 @@ class Tensor {
494
480
  });
495
481
  // Set up gradient if needed
496
482
  if (this.requiresGrad) {
497
- // Calculate grad by assiging 1 divide by the number of contributors to the position
483
+ const gradShape = this.shape, gradStrides = this.strides, gradValue = new Array(originalSize).fill(0);
484
+ // Calculate grad by assigning 1 divided by the number of contributors to the position
498
485
  for (let index = 0; index < originalSize; index++) {
499
486
  const coords = Tensor.indexToCoords(index, this.strides);
500
487
  // Force 0 on reduced axes to collapse into size-1 dims
@@ -515,6 +502,120 @@ class Tensor {
515
502
  }
516
503
  return keepDims ? out : out.squeeze(dims);
517
504
  }
505
+ // Tensor maximum reduction
506
+ max(dims, keepDims = false) {
507
+ if (typeof this.value === "number")
508
+ return this;
509
+ if (typeof dims === "number") {
510
+ dims = [dims];
511
+ }
512
+ if (typeof dims === "undefined") {
513
+ dims = Array.from({ length: this.shape.length }, (_, index) => index);
514
+ }
515
+ // Dims that are reduced now have size-1
516
+ const outputShape = this.shape.map((dim, i) => dims.includes(i) ? 1 : dim);
517
+ const outputStrides = Tensor.getStrides(outputShape);
518
+ const outputSize = Tensor.shapeToSize(outputShape);
519
+ const outputValue = new Array(outputSize).fill(-Infinity);
520
+ const originalSize = Tensor.shapeToSize(this.shape);
521
+ // Calculate maximum values of axes
522
+ for (let index = 0; index < originalSize; index++) {
523
+ const coords = Tensor.indexToCoords(index, this.strides);
524
+ // Force 0 on reduced axes to collapse into size-1 dims
525
+ const outCoords = coords.map((val, i) => dims.includes(i) ? 0 : val);
526
+ // Convert output coordinates to flat index
527
+ const outFlatIndex = Tensor.coordsToIndex(outCoords, outputStrides);
528
+ // Accumulate, outFlatIndex should match multiple realFlatIndexes
529
+ const realFlatIndex = Tensor.coordsToIndex(coords, this.strides);
530
+ // Get max over time
531
+ if (this.value[realFlatIndex] > outputValue[outFlatIndex]) {
532
+ outputValue[outFlatIndex] = this.value[realFlatIndex];
533
+ }
534
+ }
535
+ const out = new Tensor(outputValue, {
536
+ shape: outputShape,
537
+ strides: outputStrides
538
+ });
539
+ // Set up gradient if needed
540
+ if (this.requiresGrad) {
541
+ const gradShape = this.shape, gradStrides = this.strides, gradValue = new Array(originalSize).fill(0);
542
+ for (let index = 0; index < originalSize; index++) {
543
+ const coords = Tensor.indexToCoords(index, this.strides);
544
+ // Force 0 on reduced axes to collapse into size-1 dims
545
+ const outCoords = coords.map((val, i) => dims.includes(i) ? 0 : val);
546
+ // Convert output coordinates to flat index
547
+ const outFlatIndex = Tensor.coordsToIndex(outCoords, outputStrides);
548
+ // Accumulate, outFlatIndex should match multiple realFlatIndexes
549
+ const realFlatIndex = Tensor.coordsToIndex(coords, this.strides);
550
+ // Calculate grad by checking if a positon holds a value equal to the max value
551
+ gradValue[realFlatIndex] = outputValue[outFlatIndex] === this.value[realFlatIndex] ? 1 : 0;
552
+ }
553
+ out.requiresGrad = true;
554
+ out.children.push(this);
555
+ out.gradFn = () => {
556
+ const localGrad = new Tensor(gradValue, { shape: gradShape, strides: gradStrides });
557
+ Tensor.addGrad(this, out.grad.withGrad(false).mul(localGrad));
558
+ };
559
+ }
560
+ return keepDims ? out : out.squeeze(dims);
561
+ }
562
+ // Tensor minimum reduction
563
+ min(dims, keepDims = false) {
564
+ if (typeof this.value === "number")
565
+ return this;
566
+ if (typeof dims === "number") {
567
+ dims = [dims];
568
+ }
569
+ if (typeof dims === "undefined") {
570
+ dims = Array.from({ length: this.shape.length }, (_, index) => index);
571
+ }
572
+ // Dims that are reduced now have size-1
573
+ const outputShape = this.shape.map((dim, i) => dims.includes(i) ? 1 : dim);
574
+ const outputStrides = Tensor.getStrides(outputShape);
575
+ const outputSize = Tensor.shapeToSize(outputShape);
576
+ const outputValue = new Array(outputSize).fill(Infinity);
577
+ const originalSize = Tensor.shapeToSize(this.shape);
578
+ // Calculate minimum values of axes
579
+ for (let index = 0; index < originalSize; index++) {
580
+ const coords = Tensor.indexToCoords(index, this.strides);
581
+ // Force 0 on reduced axes to collapse into size-1 dims
582
+ const outCoords = coords.map((val, i) => dims.includes(i) ? 0 : val);
583
+ // Convert output coordinates to flat index
584
+ const outFlatIndex = Tensor.coordsToIndex(outCoords, outputStrides);
585
+ // Accumulate, outFlatIndex should match multiple realFlatIndexes
586
+ const realFlatIndex = Tensor.coordsToIndex(coords, this.strides);
587
+ // Get min over time
588
+ if (this.value[realFlatIndex] < outputValue[outFlatIndex]) {
589
+ outputValue[outFlatIndex] = this.value[realFlatIndex];
590
+ }
591
+ }
592
+ const out = new Tensor(outputValue, {
593
+ shape: outputShape,
594
+ strides: outputStrides
595
+ });
596
+ // Set up gradient if needed
597
+ if (this.requiresGrad) {
598
+ const gradShape = this.shape, gradStrides = this.strides, gradValue = new Array(originalSize).fill(0);
599
+ for (let index = 0; index < originalSize; index++) {
600
+ const coords = Tensor.indexToCoords(index, this.strides);
601
+ // Force 0 on reduced axes to collapse into size-1 dims
602
+ const outCoords = coords.map((val, i) => dims.includes(i) ? 0 : val);
603
+ // Convert output coordinates to flat index
604
+ const outFlatIndex = Tensor.coordsToIndex(outCoords, outputStrides);
605
+ // Accumulate, outFlatIndex should match multiple realFlatIndexes
606
+ const realFlatIndex = Tensor.coordsToIndex(coords, this.strides);
607
+ // Calculate grad by checking if a positon holds a value equal to the min value
608
+ gradValue[realFlatIndex] = outputValue[outFlatIndex] === this.value[realFlatIndex] ? 1 : 0;
609
+ }
610
+ out.requiresGrad = true;
611
+ out.children.push(this);
612
+ out.gradFn = () => {
613
+ const localGrad = new Tensor(gradValue, { shape: gradShape, strides: gradStrides });
614
+ Tensor.addGrad(this, out.grad.withGrad(false).mul(localGrad));
615
+ };
616
+ }
617
+ return keepDims ? out : out.squeeze(dims);
618
+ }
518
619
  // Tensor element-wise addition
519
620
  add(other) {
520
621
  return this.elementWiseABDAG(other, (a, b) => a + b, (self, other, outGrad) => outGrad, (self, other, outGrad) => outGrad);
@@ -1000,24 +1101,139 @@ class Tensor {
1000
1101
  // Too lazy for batched matmul
1001
1102
  throw new Error(`Shapes [${this.shape}] and [${other.shape}] are not supported`);
1002
1103
  }
1104
+ // Utility to create a new tensor filled with a number
1105
+ static full(shape, num, options = {}) {
1106
+ if (shape.length === 0)
1107
+ return new Tensor(num, options);
1108
+ const outputSize = Tensor.shapeToSize(shape);
1109
+ const outputValue = new Array(outputSize).fill(num);
1110
+ return new Tensor(outputValue, { shape, ...options });
1111
+ }
1003
1112
  // Utility to create a new tensor with shape of another tensor, filled with a number
1004
1113
  static fullLike(tensor, num, options = {}) {
1005
1114
  if (typeof tensor.value === "number")
1006
1115
  return new Tensor(num, options);
1007
1116
  return new Tensor(new Array(tensor.value.length).fill(num), { shape: tensor.shape, strides: tensor.strides, ...options });
1008
1117
  }
1118
+ // Utility to create a new tensor filled with 1
1119
+ static ones(shape, options = {}) {
1120
+ if (typeof shape === "undefined" || shape.length === 0)
1121
+ return new Tensor(1, options);
1122
+ const outputSize = Tensor.shapeToSize(shape);
1123
+ const outputValue = new Array(outputSize).fill(1);
1124
+ return new Tensor(outputValue, { shape, ...options });
1125
+ }
1009
1126
  // Utility to create a new tensor with shape of another tensor, filled with 1
1010
1127
  static onesLike(tensor, options = {}) {
1011
1128
  if (typeof tensor.value === "number")
1012
1129
  return new Tensor(1, options);
1013
1130
  return new Tensor(new Array(tensor.value.length).fill(1), { shape: tensor.shape, strides: tensor.strides, ...options });
1014
1131
  }
1132
+ // Utility to create a new tensor filled with 0
1133
+ static zeros(shape, options = {}) {
1134
+ if (typeof shape === "undefined" || shape.length === 0)
1135
+ return new Tensor(0, options);
1136
+ const outputSize = Tensor.shapeToSize(shape);
1137
+ const outputValue = new Array(outputSize).fill(0);
1138
+ return new Tensor(outputValue, { shape, ...options });
1139
+ }
1015
1140
  // Utility to create a new tensor with shape of another tensor, filled with 0
1016
1141
  static zerosLike(tensor, options = {}) {
1017
1142
  if (typeof tensor.value === "number")
1018
1143
  return new Tensor(0, options);
1019
1144
  return new Tensor(new Array(tensor.value.length).fill(0), { shape: tensor.shape, strides: tensor.strides, ...options });
1020
1145
  }
1146
+ // Utility to create a new tensor filled with a random number with uniform distribution from 0 to 1
1147
+ static rand(shape, options = {}) {
1148
+ if (typeof shape === "undefined" || shape.length === 0)
1149
+ return new Tensor((0, utils_1.randUniform)(), options);
1150
+ const outputSize = Tensor.shapeToSize(shape);
1151
+ const outputValue = new Array(outputSize);
1152
+ for (let index = 0; index < outputValue.length; index++) {
1153
+ outputValue[index] = (0, utils_1.randUniform)();
1154
+ }
1155
+ return new Tensor(outputValue, { shape, ...options });
1156
+ }
1157
+ // Utility to create a new tensor with shape of another tensor, filled with a random number with uniform distribution from 0 to 1
1158
+ static randLike(tensor, options = {}) {
1159
+ if (typeof tensor.value === "number")
1160
+ return new Tensor((0, utils_1.randUniform)(), options);
1161
+ const outputValue = new Array(tensor.value.length);
1162
+ for (let index = 0; index < outputValue.length; index++) {
1163
+ outputValue[index] = (0, utils_1.randUniform)();
1164
+ }
1165
+ return new Tensor(outputValue, {
1166
+ shape: tensor.shape, strides: tensor.strides, ...options
1167
+ });
1168
+ }
1169
+ // Utility to create a new tensor filled with a random number with normal distribution of mean=0 and stddev=1
1170
+ static randn(shape, options = {}) {
1171
+ if (typeof shape === "undefined" || shape.length === 0)
1172
+ return new Tensor((0, utils_1.randNormal)(), options);
1173
+ const outputSize = Tensor.shapeToSize(shape);
1174
+ const outputValue = new Array(outputSize);
1175
+ for (let index = 0; index < outputValue.length; index++) {
1176
+ outputValue[index] = (0, utils_1.randNormal)();
1177
+ }
1178
+ return new Tensor(outputValue, { shape, ...options });
1179
+ }
1180
+ // Utility to create a new tensor with shape of another tensor, filled with a random number with normal distribution of mean=0 and stddev=1
1181
+ static randnLike(tensor, options = {}) {
1182
+ if (typeof tensor.value === "number")
1183
+ return new Tensor((0, utils_1.randNormal)(), options);
1184
+ const outputValue = new Array(tensor.value.length);
1185
+ for (let index = 0; index < outputValue.length; index++) {
1186
+ outputValue[index] = (0, utils_1.randNormal)();
1187
+ }
1188
+ return new Tensor(outputValue, {
1189
+ shape: tensor.shape, strides: tensor.strides, ...options
1190
+ });
1191
+ }
1192
+ // Utility to create a new tensor filled with a random integer between low and high
1193
+ static randint(shape, low, high, options = {}) {
1194
+ if (shape.length === 0)
1195
+ return new Tensor((0, utils_1.randInt)(low, high), options);
1196
+ const outputSize = Tensor.shapeToSize(shape);
1197
+ const outputValue = new Array(outputSize);
1198
+ for (let index = 0; index < outputValue.length; index++) {
1199
+ outputValue[index] = (0, utils_1.randInt)(low, high);
1200
+ }
1201
+ return new Tensor(outputValue, { shape, ...options });
1202
+ }
1203
+ // Utility to create a new tensor with shape of another tensor, filled with a random integer between low and high
1204
+ static randintLike(tensor, low, high, options = {}) {
1205
+ if (typeof tensor.value === "number")
1206
+ return new Tensor((0, utils_1.randInt)(low, high), options);
1207
+ const outputValue = new Array(tensor.value.length);
1208
+ for (let index = 0; index < outputValue.length; index++) {
1209
+ outputValue[index] = (0, utils_1.randInt)(low, high);
1210
+ }
1211
+ return new Tensor(outputValue, {
1212
+ shape: tensor.shape, strides: tensor.strides, ...options
1213
+ });
1214
+ }
1215
+ // Utility to create a new tensor filled with a random number with normal distribution of custom mean and stddev
1216
+ static normal(shape, mean, stdDev, options = {}) {
1217
+ if (shape.length === 0)
1218
+ return new Tensor((0, utils_1.randNormal)(mean, stdDev), options);
1219
+ const outputSize = Tensor.shapeToSize(shape);
1220
+ const outputValue = new Array(outputSize);
1221
+ for (let index = 0; index < outputValue.length; index++) {
1222
+ outputValue[index] = (0, utils_1.randNormal)(mean, stdDev);
1223
+ }
1224
+ return new Tensor(outputValue, { shape, ...options });
1225
+ }
1226
+ // Utility to create a new tensor filled with a random number with uniform distribution from low to high
1227
+ static uniform(shape, low, high, options = {}) {
1228
+ if (shape.length === 0)
1229
+ return new Tensor((0, utils_1.randUniform)(low, high), options);
1230
+ const outputSize = Tensor.shapeToSize(shape);
1231
+ const outputValue = new Array(outputSize);
1232
+ for (let index = 0; index < outputValue.length; index++) {
1233
+ outputValue[index] = (0, utils_1.randUniform)(low, high);
1234
+ }
1235
+ return new Tensor(outputValue, { shape, ...options });
1236
+ }
1021
1237
  // Reverse-mode autodiff call
1022
1238
  backward() {
1023
1239
  // Build topological order
package/dist/utils.d.ts CHANGED
@@ -1,3 +1,6 @@
1
1
  export declare function erf(x: number): number;
2
2
  export declare function erfc(x: number): number;
3
3
  export declare function erfinv(x: number): number;
4
+ export declare function randUniform(low?: number, high?: number): number;
5
+ export declare function randNormal(mean?: number, stdDev?: number): number;
6
+ export declare function randInt(low: number, high: number): number;
package/dist/utils.js CHANGED
@@ -3,6 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.erf = erf;
4
4
  exports.erfc = erfc;
5
5
  exports.erfinv = erfinv;
6
+ exports.randUniform = randUniform;
7
+ exports.randNormal = randNormal;
8
+ exports.randInt = randInt;
6
9
  // Error function using Abramowitz and Stegun approximation
7
10
  function erf(x) {
8
11
  const a1 = 0.254829592;
@@ -33,3 +36,15 @@ function erfinv(x) {
33
36
  const sign = x >= 0 ? 1 : -1;
34
37
  return sign * Math.sqrt(-part1 + Math.sqrt(part1 * part1 - part2));
35
38
  }
39
+ function randUniform(low = 0, high = 1) {
40
+ return Math.random() * (high - low) + low;
41
+ }
42
+ function randNormal(mean = 0, stdDev = 1) {
43
+ const u = 1 - Math.random();
44
+ const v = 1 - Math.random();
45
+ const z = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);
46
+ return z * stdDev + mean;
47
+ }
48
+ function randInt(low, high) {
49
+ return Math.floor(Math.random() * (high - low) + low);
50
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "catniff",
3
- "version": "0.2.11",
3
+ "version": "0.2.13",
4
4
  "description": "A cute autograd engine for Javascript",
5
5
  "main": "index.js",
6
6
  "scripts": {