@zushah/chalkboard 1.5.0 → 1.7.0

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/src/Chalkboard.js CHANGED
@@ -1,23 +1,23 @@
1
1
  /*
2
2
  The Chalkboard Library
3
- Version 1.5.0 released 12/18/2023
3
+ Version 1.7.0 Descartes released 01/01/2024
4
4
  Authored by Zushah ===> https://www.github.com/Zushah
5
5
  Available under the MIT License ===> https://www.opensource.org/license/mit/
6
6
 
7
7
  The Chalkboard library is a JavaScript namespace that provides a plethora of both practical and abstract mathematical functionalities for its user.
8
8
 
9
- Latest release ===> https://www.github.com/Zushah/Chalkboard/releases/tag/v1.5.0
10
- Documentation ===> https://zushah.github.io/Chalkboard/documentation.html/
9
+ Repository ===> https://www.github.com/Zushah/Chalkboard
10
+ Website ===> https://zushah.github.io/Chalkboard/home.html
11
11
  */
12
12
  var Chalkboard = {
13
13
  README: function() {
14
- console.log("The Chalkboard Library\nVersion 1.5.0 released 12/18/2023\nAuthored by Zushah ===> https://www.github.com/Zushah\nAvailable under the MIT License ===> https://www.opensource.org/license/mit/\n\nThe Chalkboard library is a JavaScript namespace that provides a plethora of both practical and abstract mathematical functionalities for its user.\n\nLatest release ===> https://www.github.com/Zushah/Chalkboard/releases/tag/v1.5.0\nDocumentation ===> https://zushah.github.io/Chalkboard/documentation.html/");
14
+ console.log("The Chalkboard Library\nVersion 1.7.0 Descartes released 01/01/2024\nAuthored by Zushah ===> https://www.github.com/Zushah\nAvailable under the MIT License ===> https://www.opensource.org/license/mit/\n\nThe Chalkboard library is a JavaScript namespace that provides a plethora of both practical and abstract mathematical functionalities for its user.\n\nRepository ===> https://www.github.com/Zushah/Chalkboard\nWebsite ===> https://zushah.github.io/Chalkboard/home.html");
15
15
  },
16
16
  LOGO: function(x, y, s, context) {
17
- x = x || canvas.width / 2;
18
- y = y || canvas.height / 2;
17
+ x = x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2;
18
+ y = y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2;
19
19
  s = s || 1;
20
- context = context || ctx;
20
+ context = context || Chalkboard.real.parse(Chalkboard.CONTEXT);
21
21
  context.save();
22
22
  context.translate(x, y);
23
23
  context.scale(s, s);
@@ -50,11 +50,49 @@ var Chalkboard = {
50
50
  exponent = exponent || 1;
51
51
  return Math.pow(Math.pow(10, 1 / Math.log(10)), exponent);
52
52
  },
53
+ CONTEXT: "ctx",
54
+ PARSEPREFIX: "",
53
55
  numb: {
54
56
  random: function(inf, sup) {
55
- inf = inf || 0;
56
- sup = sup || 1;
57
- return inf + Math.random() * (sup - inf);
57
+ if(inf === undefined) {
58
+ inf = 0;
59
+ }
60
+ if(sup === undefined) {
61
+ sup = 1;
62
+ }
63
+ return inf + (sup - inf) * Math.random();
64
+ },
65
+ exponential: function(l) {
66
+ if(l === undefined) {
67
+ l = 1;
68
+ }
69
+ return l <= 0 ? 0 : -Math.log(Math.random()) / l;
70
+ },
71
+ Gaussian: function(height, mean, deviation) {
72
+ var u1 = Math.random(), u2 = Math.random();
73
+ var random = Chalkboard.real.sqrt(-2 * Chalkboard.real.ln(u1)) * Chalkboard.trig.cos(Chalkboard.PI(2) * u2);
74
+ return random * height * Chalkboard.real.sqrt(deviation) + mean;
75
+ },
76
+ Bernoullian: function(p) {
77
+ if(p === undefined) {
78
+ p = 0.5;
79
+ }
80
+ return Math.random() < p ? 1 : 0;
81
+ },
82
+ Poissonian: function(l) {
83
+ if(l === undefined) {
84
+ l = 1;
85
+ }
86
+ if(l > 0) {
87
+ var L = Chalkboard.E(-l);
88
+ var p = 1, k = 0;
89
+ for(; p > L; ++k) {
90
+ p *= Math.random();
91
+ }
92
+ return k - 1;
93
+ } else {
94
+ return 0;
95
+ }
58
96
  },
59
97
  factorial: function(num) {
60
98
  if(num >= 0) {
@@ -228,11 +266,23 @@ var Chalkboard = {
228
266
  }
229
267
  },
230
268
  binomial: function(n, k) {
269
+ if(k < 0 || k > n) {
270
+ return 0;
271
+ }
231
272
  if(k === 0 || k === n) {
232
273
  return 1;
233
- } else {
234
- return Chalkboard.numb.binomial(n - 1, k - 1) + Chalkboard.numb.binomial(n - 1, k);
235
274
  }
275
+ if(k === 1 || k === n - 1) {
276
+ return n;
277
+ }
278
+ if(n - k < k) {
279
+ k = n - k;
280
+ }
281
+ var result = n;
282
+ for(var i = 2; i <= k; i++) {
283
+ result *= (n - i + 1) / i;
284
+ }
285
+ return Math.round(result);
236
286
  },
237
287
  Fibonacci: function(num) {
238
288
  var sequence = [0, 1];
@@ -241,18 +291,39 @@ var Chalkboard = {
241
291
  }
242
292
  return sequence[num];
243
293
  },
244
- Gaussian: function(height, mean, deviation) {
245
- var u, v, s;
246
- for(;;) {
247
- u = Chalkboard.numb.random(-1, 1);
248
- v = Chalkboard.numb.random(-1, 1);
249
- s = u * u + v * v;
250
- if(s < 1 && s !== 0) {
251
- break;
294
+ Goldbach: function(num) {
295
+ if(num % 2 === 0) {
296
+ if(num !== 4) {
297
+ var a = num / 2, b = num / 2;
298
+ if(a % 2 === 0) {
299
+ a--;
300
+ b++;
301
+ }
302
+ while(a >= 3) {
303
+ if(Chalkboard.numb.isPrime(a) && Chalkboard.numb.isPrime(b)) {
304
+ return [a, b];
305
+ }
306
+ a -= 2;
307
+ b += 2;
308
+ }
309
+ return undefined;
310
+ } else {
311
+ return [2, 2];
252
312
  }
313
+ } else {
314
+ return undefined;
315
+ }
316
+ },
317
+ Euler: function(num) {
318
+ if(num > 0) {
319
+ var factors = Chalkboard.numb.factors(num);
320
+ for(var i = 0; i < factors.length; i++) {
321
+ num *= (factors[i] - 1) / factors[i];
322
+ }
323
+ return num;
324
+ } else {
325
+ return undefined;
253
326
  }
254
- var z = u * Chalkboard.real.sqrt(-2 * Chalkboard.real.ln(s) / s);
255
- return z * height * deviation + mean;
256
327
  }
257
328
  },
258
329
  real: {
@@ -260,7 +331,9 @@ var Chalkboard = {
260
331
  type = type || "expl";
261
332
  if(type === "expl") {
262
333
  return {definition: definition, type: type};
263
- } else if(type === "pola") {
334
+ } else if(type === "inve") {
335
+ return {definition: definition, type: type};
336
+ } else if(type === "pola") {
264
337
  return {definition: definition, type: type};
265
338
  } else if(type === "curv") {
266
339
  return definition.length === 2 ? {definition: [definition[0], definition[1]], type: type} : {definition: [definition[0], definition[1], definition[2]], type: type};
@@ -269,17 +342,19 @@ var Chalkboard = {
269
342
  } else if(type === "mult") {
270
343
  return {definition: definition, type: type};
271
344
  } else {
272
- return "TypeError: Parameter \"type\" must be either \"expl\", \"pola\", \"curv\", \"surf\", or \"mult\".";
345
+ return "TypeError: Parameter \"type\" must be either \"expl\", \"inve\", \"pola\", \"curv\", \"surf\", or \"mult\".";
273
346
  }
274
347
  },
275
- parse: function(str, init) {
276
- init = init || '';
277
- return Function('"use strict"; ' + init + ' return (' + str + ')')();
348
+ parse: function(str) {
349
+ return Function('"use strict"; ' + Chalkboard.PARSEPREFIX + ' return (' + str + ')')();
278
350
  },
279
351
  val: function(func, val) {
280
352
  if(func.type === "expl") {
281
353
  var f = Chalkboard.real.parse("x => " + func.definition);
282
354
  return f(val);
355
+ } else if(func.type === "inve") {
356
+ var f = Chalkboard.real.parse("y => " + func.definition);
357
+ return f(val);
283
358
  } else if(func.type === "pola") {
284
359
  var r = Chalkboard.real.parse("O => " + func.definition);
285
360
  return r(val);
@@ -315,7 +390,11 @@ var Chalkboard = {
315
390
  }
316
391
  },
317
392
  pow: function(base, num) {
318
- return Math.exp(num * Math.log(base));
393
+ if(base === 0 && num === 0) {
394
+ return 1;
395
+ } else {
396
+ return Math.exp(num * Math.log(base));
397
+ }
319
398
  },
320
399
  log: function(base, num) {
321
400
  return Chalkboard.real.ln(num) / Chalkboard.real.ln(base);
@@ -333,7 +412,8 @@ var Chalkboard = {
333
412
  return undefined;
334
413
  }
335
414
  },
336
- nrt: function(num, index) {
415
+ root: function(num, index) {
416
+ index = index || 3;
337
417
  return Math.exp(Math.log(num) / index);
338
418
  },
339
419
  tetration: function(base, num) {
@@ -448,14 +528,20 @@ var Chalkboard = {
448
528
  },
449
529
  comp: {
450
530
  new: function(a, b) {
451
- return {a: a, b: b, type: "comp"};
531
+ if(b === undefined) {
532
+ return {a: a, b: 0, type: "comp"};
533
+ } else {
534
+ return {a: a, b: b, type: "comp"};
535
+ }
536
+ },
537
+ copy: function(comp) {
538
+ return Object.create(Object.getPrototypeOf(comp), Object.getOwnPropertyDescriptors(comp));
452
539
  },
453
540
  function: function(realDefinition, imagDefinition) {
454
541
  return {definition: [realDefinition, imagDefinition], type: "comp"};
455
542
  },
456
- parse: function(str, init) {
457
- init = init || '';
458
- return Function('"use strict"; ' + init + ' return (' + str + ')')();
543
+ parse: function(str) {
544
+ return Function('"use strict"; ' + Chalkboard.PARSEPREFIX + ' return (' + str + ')')();
459
545
  },
460
546
  val: function(func, comp) {
461
547
  if(func.type === "comp") {
@@ -534,6 +620,18 @@ var Chalkboard = {
534
620
  sqrt: function(comp) {
535
621
  return Chalkboard.comp.new(Chalkboard.real.sqrt((comp.a + Chalkboard.real.sqrt((comp.a * comp.a) + (comp.b * comp.b))) / 2), Chalkboard.numb.sgn(comp.b) * Chalkboard.real.sqrt((-comp.a + Chalkboard.real.sqrt((comp.a * comp.a) + (comp.b * comp.b))) / 2));
536
622
  },
623
+ root: function(comp, index) {
624
+ index = index || 3;
625
+ if(Number.isInteger(index) && index > 0) {
626
+ var result = [];
627
+ var r = Chalkboard.comp.mag(comp);
628
+ var t = Chalkboard.comp.arg(comp);
629
+ for(var i = 0; i < index; i++) {
630
+ result.push(Chalkboard.comp.new(Chalkboard.real.root(r, index) * Chalkboard.trig.cos((t + Chalkboard.PI(2 * i)) / index), Chalkboard.real.root(r, index) * Chalkboard.trig.sin((t + Chalkboard.PI(2 * i)) / index)));
631
+ }
632
+ return result;
633
+ }
634
+ },
537
635
  rotate: function(comp, rad) {
538
636
  return Chalkboard.comp.new(Chalkboard.comp.mag(comp) * Chalkboard.trig.cos(Chalkboard.comp.arg(comp) + rad), Chalkboard.comp.mag(comp) * Chalkboard.trig.sin(Chalkboard.comp.arg(comp) + rad));
539
637
  },
@@ -543,21 +641,22 @@ var Chalkboard = {
543
641
  conjugate: function(comp) {
544
642
  return Chalkboard.comp.new(comp.a, -comp.b);
545
643
  },
546
- root: function(comp, n) {
547
- if(Number.isInteger(n) && n > 0) {
548
- var result = [];
549
- var r = Chalkboard.comp.mag(comp);
550
- var t = Chalkboard.comp.arg(comp);
551
- for(var i = 0; i < n; i++) {
552
- result.push(Chalkboard.comp.new(Chalkboard.real.nrt(r, n) * Chalkboard.trig.cos((t + Chalkboard.PI(2 * i)) / n), Chalkboard.real.nrt(r, n) * Chalkboard.trig.sin((t + Chalkboard.PI(2 * i)) / n)));
553
- }
554
- return result;
555
- }
556
- },
557
644
  dist: function(comp_1, comp_2) {
645
+ if(typeof comp_1 === "number") {
646
+ comp_1 = Chalkboard.comp.new(comp_1, 0);
647
+ }
648
+ if(typeof comp_2 === "number") {
649
+ comp_2 = Chalkboard.comp.new(comp_2, 0);
650
+ }
558
651
  return Chalkboard.real.sqrt(((comp_2.a - comp_1.a) * (comp_2.a - comp_1.a)) + ((comp_2.b - comp_1.b) * (comp_2.b - comp_1.b)));
559
652
  },
560
653
  distsq: function(comp_1, comp_2) {
654
+ if(typeof comp_1 === "number") {
655
+ comp_1 = Chalkboard.comp.new(comp_1, 0);
656
+ }
657
+ if(typeof comp_2 === "number") {
658
+ comp_2 = Chalkboard.comp.new(comp_2, 0);
659
+ }
561
660
  return ((comp_2.a - comp_1.a) * (comp_2.a - comp_1.a)) + ((comp_2.b - comp_1.b) * (comp_2.b - comp_1.b));
562
661
  },
563
662
  scl: function(comp, num) {
@@ -567,15 +666,39 @@ var Chalkboard = {
567
666
  return Chalkboard.comp.new(Chalkboard.numb.constrain(comp.a, range), Chalkboard.numb.constrain(comp.b, range));
568
667
  },
569
668
  add: function(comp_1, comp_2) {
669
+ if(typeof comp_1 === "number") {
670
+ comp_1 = Chalkboard.comp.new(comp_1, 0);
671
+ }
672
+ if(typeof comp_2 === "number") {
673
+ comp_2 = Chalkboard.comp.new(comp_2, 0);
674
+ }
570
675
  return Chalkboard.comp.new(comp_1.a + comp_2.a, comp_1.b + comp_2.b);
571
676
  },
572
677
  sub: function(comp_1, comp_2) {
678
+ if(typeof comp_1 === "number") {
679
+ comp_1 = Chalkboard.comp.new(comp_1, 0);
680
+ }
681
+ if(typeof comp_2 === "number") {
682
+ comp_2 = Chalkboard.comp.new(comp_2, 0);
683
+ }
573
684
  return Chalkboard.comp.new(comp_1.a - comp_2.a, comp_1.b - comp_2.b);
574
685
  },
575
686
  mul: function(comp_1, comp_2) {
687
+ if(typeof comp_1 === "number") {
688
+ comp_1 = Chalkboard.comp.new(comp_1, 0);
689
+ }
690
+ if(typeof comp_2 === "number") {
691
+ comp_2 = Chalkboard.comp.new(comp_2, 0);
692
+ }
576
693
  return Chalkboard.comp.new((comp_1.a * comp_2.a) - (comp_1.b * comp_2.b), (comp_1.a * comp_2.b) + (comp_1.b * comp_2.a));
577
694
  },
578
695
  div: function(comp_1, comp_2) {
696
+ if(typeof comp_1 === "number") {
697
+ comp_1 = Chalkboard.comp.new(comp_1, 0);
698
+ }
699
+ if(typeof comp_2 === "number") {
700
+ comp_2 = Chalkboard.comp.new(comp_2, 0);
701
+ }
579
702
  return Chalkboard.comp.new(((comp_1.a * comp_2.a) - (comp_1.b * comp_2.b)) / Chalkboard.comp.magsq(comp_2), ((comp_1.a * comp_2.b) + (comp_1.b * comp_2.a)) / Chalkboard.comp.magsq(comp_2));
580
703
  },
581
704
  toVector: function(comp) {
@@ -597,7 +720,14 @@ var Chalkboard = {
597
720
  },
598
721
  quat: {
599
722
  new: function(a, b, c, d) {
600
- return {a: a, b: b, c: c, d: d, type: "quat"};
723
+ if(b === undefined && c === undefined && d === undefined) {
724
+ return {a: a, b: 0, c: 0, d: 0, type: "quat"};
725
+ } else {
726
+ return {a: a, b: b, c: c, d: d, type: "quat"};
727
+ }
728
+ },
729
+ copy: function(quat) {
730
+ return Object.create(Object.getPrototypeOf(quat), Object.getOwnPropertyDescriptors(quat));
601
731
  },
602
732
  random: function(inf, sup) {
603
733
  return Chalkboard.quat.new(Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup));
@@ -639,9 +769,21 @@ var Chalkboard = {
639
769
  return Chalkboard.quat.new(quat.a, -quat.b, -quat.c, -quat.d);
640
770
  },
641
771
  dist: function(quat_1, quat_2) {
772
+ if(typeof quat_1 === "number") {
773
+ quat_1 = Chalkboard.quat.new(quat_1, 0, 0, 0);
774
+ }
775
+ if(typeof quat_2 === "number") {
776
+ quat_2 = Chalkboard.quat.new(quat_2, 0, 0, 0);
777
+ }
642
778
  return Chalkboard.real.sqrt(((quat_2.a - quat_1.a) * (quat_2.a - quat_1.a)) + ((quat_2.b - quat_1.b) * (quat_2.b - quat_1.b)) + ((quat_2.c - quat_1.c) * (quat_2.c - quat_1.c)) + ((quat_2.d - quat_1.d) * (quat_2.d - quat_1.d)));
643
779
  },
644
780
  distsq: function(quat_1, quat_2) {
781
+ if(typeof quat_1 === "number") {
782
+ quat_1 = Chalkboard.quat.new(quat_1, 0, 0, 0);
783
+ }
784
+ if(typeof quat_2 === "number") {
785
+ quat_2 = Chalkboard.quat.new(quat_2, 0, 0, 0);
786
+ }
645
787
  return ((quat_2.a - quat_1.a) * (quat_2.a - quat_1.a)) + ((quat_2.b - quat_1.b) * (quat_2.b - quat_1.b)) + ((quat_2.c - quat_1.c) * (quat_2.c - quat_1.c)) + ((quat_2.d - quat_1.d) * (quat_2.d - quat_1.d));
646
788
  },
647
789
  scl: function(quat, num) {
@@ -651,14 +793,41 @@ var Chalkboard = {
651
793
  return Chalkboard.quat.new(Chalkboard.numb.constrain(quat.a, range), Chalkboard.numb.constrain(quat.b, range), Chalkboard.numb.constrain(quat.c, range), Chalkboard.numb.constrain(quat.d, range));
652
794
  },
653
795
  add: function(quat_1, quat_2) {
796
+ if(typeof quat_1 === "number") {
797
+ quat_1 = Chalkboard.quat.new(quat_1, 0, 0, 0);
798
+ }
799
+ if(typeof quat_2 === "number") {
800
+ quat_2 = Chalkboard.quat.new(quat_2, 0, 0, 0);
801
+ }
654
802
  return Chalkboard.quat.new(quat_1.a + quat_2.a, quat_1.b + quat_2.b, quat_1.c + quat_2.c, quat_1.d + quat_2.d);
655
803
  },
656
804
  sub: function(quat_1, quat_2) {
805
+ if(typeof quat_1 === "number") {
806
+ quat_1 = Chalkboard.quat.new(quat_1, 0, 0, 0);
807
+ }
808
+ if(typeof quat_2 === "number") {
809
+ quat_2 = Chalkboard.quat.new(quat_2, 0, 0, 0);
810
+ }
657
811
  return Chalkboard.quat.new(quat_1.a - quat_2.a, quat_1.b - quat_2.b, quat_1.c - quat_2.c, quat_1.d - quat_2.d);
658
812
  },
659
813
  mul: function(quat_1, quat_2) {
814
+ if(typeof quat_1 === "number") {
815
+ quat_1 = Chalkboard.quat.new(quat_1, 0, 0, 0);
816
+ }
817
+ if(typeof quat_2 === "number") {
818
+ quat_2 = Chalkboard.quat.new(quat_2, 0, 0, 0);
819
+ }
660
820
  return Chalkboard.quat.new((quat_1.a * quat_2.a) - (quat_1.b * quat_2.b) - (quat_1.c * quat_2.c) - (quat_1.d * quat_2.d), (quat_1.a * quat_2.b) + (quat_1.b * quat_2.a) + (quat_1.c * quat_2.d) - (quat_1.d * quat_2.c), (quat_1.a * quat_2.c) - (quat_1.b * quat_2.d) + (quat_1.c * quat_2.a) + (quat_1.d * quat_2.b), (quat_1.a * quat_2.d) + (quat_1.b * quat_2.c) - (quat_1.c * quat_2.b) + (quat_1.d * quat_2.a));
661
821
  },
822
+ div: function(quat_1, quat_2) {
823
+ if(typeof quat_1 === "number") {
824
+ quat_1 = Chalkboard.quat.new(quat_1, 0, 0, 0);
825
+ }
826
+ if(typeof quat_2 === "number") {
827
+ quat_2 = Chalkboard.quat.new(quat_2, 0, 0, 0);
828
+ }
829
+ return Chalkboard.quat.new((quat_1.a * quat_2.a + quat_1.b * quat_2.b + quat_1.c * quat_2.c + quat_1.d * quat_2.d) / Chalkboard.quat.magsq(quat_2), (quat_1.b * quat_2.a - quat_1.a * quat_2.b - quat_1.d * quat_2.c + quat_1.c * quat_2.d) / Chalkboard.quat.magsq(quat_2), (quat_1.c * quat_2.a + quat_1.d * quat_2.b - quat_1.a * quat_2.c - quat_1.b * quat_2.d) / Chalkboard.quat.magsq(quat_2), (quat_1.d * quat_2.a - quat_1.c * quat_2.b + quat_1.b * quat_2.c - quat_1.a * quat_2.d) / Chalkboard.quat.magsq(quat_2));
830
+ },
662
831
  fromAxis: function(vec3, rad) {
663
832
  return Chalkboard.quat.new(Chalkboard.trig.cos(rad / 2), vec3.x * Chalkboard.trig.sin(rad / 2), vec3.y * Chalkboard.trig.sin(rad / 2), vec3.z * Chalkboard.trig.sin(rad / 2));
664
833
  },
@@ -703,136 +872,153 @@ var Chalkboard = {
703
872
  }
704
873
  },
705
874
  plot: {
706
- xyplane: function(scl, rgba, origin, weight, context) {
707
- scl = scl || 1;
708
- scl /= 100;
709
- rgba = rgba || [0, 0, 0];
710
- origin = origin || [canvas.width / 2, canvas.height / 2];
711
- weight = weight || 2;
712
- context = context || ctx;
713
- context.save();
714
- context.translate(origin[0], origin[1]);
715
- context.strokeStyle = rgba.length === 3 ? "rgb(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ")" : "rgba(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ", " + rgba[3].toString() + ")";
716
- context.lineWidth = weight / 4;
717
- context.beginPath();
718
- for(var i = Math.floor(-origin[0] / scl); i <= (canvas.width - origin[0]) / scl; i++) {
719
- context.moveTo(i / scl, -origin[1]);
720
- context.lineTo(i / scl, canvas.width - origin[1]);
721
- }
722
- context.stroke();
723
- context.beginPath();
724
- for(var i = Math.floor(-origin[1] / scl); i <= (canvas.width - origin[1]) / scl; i++) {
725
- context.moveTo(-origin[0], i / scl);
726
- context.lineTo(canvas.width - origin[0], i / scl);
727
- }
728
- context.stroke();
729
- context.lineWidth = weight;
730
- context.beginPath();
731
- context.moveTo(-origin[0], 0);
732
- context.lineTo(canvas.width - origin[0], 0);
733
- context.stroke();
734
- context.beginPath();
735
- context.moveTo(0, -origin[1]);
736
- context.lineTo(0, canvas.width - origin[1]);
737
- context.stroke();
738
- context.restore();
739
- },
740
- rOplane: function(scl, rgba, origin, weight, context) {
741
- scl = scl || 1;
742
- scl /= 100;
743
- rgba = rgba || [0, 0, 0];
744
- origin = origin || [canvas.width / 2, canvas.height / 2];
745
- weight = weight || 2;
746
- context = context || ctx;
747
- context.save();
748
- context.translate(origin[0], origin[1]);
749
- context.strokeStyle = rgba.length === 3 ? "rgb(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ")" : "rgba(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ", " + rgba[3].toString() + ")";
750
- context.lineWidth = weight / 4;
751
- context.beginPath();
752
- for(var i = 0; i <= scl * canvas.width / 2; i++) {
753
- context.ellipse(0, 0, i / scl, i / scl, 0, 0, Chalkboard.PI(2));
754
- }
755
- context.stroke();
756
- context.lineWidth = weight;
757
- context.beginPath();
758
- context.moveTo(-origin[0], 0);
759
- context.lineTo(canvas.width - origin[0], 0);
760
- context.stroke()
761
- context.beginPath();
762
- context.moveTo(0, -origin[1]);
763
- context.lineTo(0, canvas.width - origin[1]);
764
- context.stroke();
765
- context.restore();
766
- },
767
- function: function(func, scl, rgba, domain, origin, weight, context) {
768
- scl = scl || 1;
769
- scl /= 100;
770
- rgba = rgba || [0, 0, 0];
771
- domain = domain || func.type === "comp" ? [[-10, 10], [-10, 10]] : [-10, 10];
772
- origin = origin || [canvas.width / 2, canvas.height / 2];
773
- weight = weight || 2;
774
- context = context || ctx;
875
+ xyplane: function(config) {
876
+ (config = {
877
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
878
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
879
+ size: config.size || 1,
880
+ strokeStyle: config.strokeStyle || "black",
881
+ lineWidth: config.lineWidth || 2,
882
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
883
+ }).size /= 100;
884
+ var cw = Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width;
885
+ config.context.save();
886
+ config.context.translate(config.x, config.y);
887
+ config.context.strokeStyle = config.strokeStyle;
888
+ config.context.lineWidth = config.lineWidth / 4;
889
+ config.context.beginPath();
890
+ for(var i = Math.floor(-config.x / config.size); i <= (cw - config.x) / config.size; i++) {
891
+ config.context.moveTo(i / config.size, -config.y);
892
+ config.context.lineTo(i / config.size, cw - config.y);
893
+ }
894
+ config.context.stroke();
895
+ config.context.beginPath();
896
+ for(var i = Math.floor(-config.y / config.size); i <= (cw - config.y) / config.size; i++) {
897
+ config.context.moveTo(-config.x, i / config.size);
898
+ config.context.lineTo(cw - config.x, i / config.size);
899
+ }
900
+ config.context.stroke();
901
+ config.context.lineWidth = config.lineWidth;
902
+ config.context.beginPath();
903
+ config.context.moveTo(-config.x, 0);
904
+ config.context.lineTo(cw - config.x, 0);
905
+ config.context.stroke();
906
+ config.context.beginPath();
907
+ config.context.moveTo(0, -config.y);
908
+ config.context.lineTo(0, cw - config.y);
909
+ config.context.stroke();
910
+ config.context.restore();
911
+ },
912
+ rOplane: function(config) {
913
+ (config = {
914
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
915
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
916
+ size: config.size || 1,
917
+ strokeStyle: config.strokeStyle || "black",
918
+ lineWidth: config.lineWidth || 2,
919
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
920
+ }).size /= 100;
921
+ var cw = Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width;
922
+ config.context.save();
923
+ config.context.translate(config.x, config.y);
924
+ config.context.strokeStyle = config.strokeStyle;
925
+ config.context.lineWidth = config.lineWidth / 4;
926
+ config.context.beginPath();
927
+ for(var i = 0; i <= config.size * cw / 2; i++) {
928
+ config.context.ellipse(0, 0, i / config.size, i / config.size, 0, 0, Chalkboard.PI(2));
929
+ }
930
+ config.context.stroke();
931
+ config.context.lineWidth = config.lineWidth;
932
+ config.context.beginPath();
933
+ config.context.moveTo(-config.x, 0);
934
+ config.context.lineTo(cw - config.x, 0);
935
+ config.context.stroke()
936
+ config.context.beginPath();
937
+ config.context.moveTo(0, -config.y);
938
+ config.context.lineTo(0, cw - config.y);
939
+ config.context.stroke();
940
+ config.context.restore();
941
+ },
942
+ function: function(func, config) {
943
+ (config = {
944
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
945
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
946
+ size: config.size || 1,
947
+ strokeStyle: config.strokeStyle || "black",
948
+ lineWidth: config.lineWidth || 2,
949
+ domain: config.domain || (func.type === "comp" ? [[-10, 10], [-10, 10]] : [-10, 10]),
950
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
951
+ }).size /= 100;
775
952
  var data = [];
776
- context.save();
777
- context.translate(origin[0], origin[1]);
778
- context.lineWidth = weight;
779
- context.strokeStyle = rgba.length === 3 ? "rgb(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ")" : "rgba(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ", " + rgba[3].toString() + ")";
780
- context.beginPath();
953
+ config.context.save();
954
+ config.context.translate(config.x, config.y);
955
+ config.context.lineWidth = config.lineWidth;
956
+ config.context.strokeStyle = config.strokeStyle;
957
+ config.context.beginPath();
781
958
  if(func.type === "expl") {
782
959
  var f = Chalkboard.real.parse("x => " + func.definition);
783
- for(var i = domain[0] / scl; i <= domain[1] / scl; i++) {
784
- context.lineTo(i, -f(i * scl) / scl);
960
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i++) {
961
+ config.context.lineTo(i, -f(i * config.size) / config.size);
785
962
  data.push([i, f(i)]);
786
963
  }
964
+ } else if(func.type === "inve") {
965
+ var f = Chalkboard.real.parse("y => " + func.definition);
966
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i++) {
967
+ config.context.lineTo(f(i * config.size) / config.size, -i);
968
+ data.push([f(i), i]);
969
+ }
787
970
  } else if(func.type === "pola") {
788
971
  var r = Chalkboard.real.parse("O => " + func.definition);
789
- for(var i = domain[0] / scl; i <= domain[1] / scl; i++) {
790
- context.lineTo(r(i * scl) / scl * Chalkboard.trig.cos(i * scl), -r(i * scl) / scl * Chalkboard.trig.sin(i * scl));
972
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i++) {
973
+ config.context.lineTo(r(i * config.size) / config.size * Chalkboard.trig.cos(i * config.size), -r(i * config.size) / config.size * Chalkboard.trig.sin(i * config.size));
791
974
  data.push([i, r(i)]);
792
975
  }
793
976
  } else if(func.type === "curv") {
794
977
  var x = Chalkboard.real.parse("t => " + func.definition[0]),
795
978
  y = Chalkboard.real.parse("t => " + func.definition[1]);
796
- for(var i = domain[0] / scl; i <= domain[1] / scl; i++) {
797
- context.lineTo(x(i * scl) / scl, -y(i * scl) / scl);
979
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i++) {
980
+ config.context.lineTo(x(i * config.size) / config.size, -y(i * config.size) / config.size);
798
981
  data.push([x(i), y(i)]);
799
982
  }
800
983
  } else if(func.type === "comp") {
801
984
  var u = Chalkboard.comp.parse("(a, b) => " + func.definition[0]),
802
985
  v = Chalkboard.comp.parse("(a, b) => " + func.definition[1]);
803
- for(var i = domain[0][0] / scl; i <= domain[0][1] / scl; i += 5) {
804
- for(var j = domain[1][0] / scl; j <= domain[1][1] / scl; j += 5) {
805
- var z = Chalkboard.comp.new(u(i * scl, j * scl) / scl, v(i * scl, j * scl) / scl);
986
+ for(var i = config.domain[0][0] / config.size; i <= config.domain[0][1] / config.size; i += 5) {
987
+ for(var j = config.domain[1][0] / config.size; j <= config.domain[1][1] / config.size; j += 5) {
988
+ var z = Chalkboard.comp.new(u(i * config.size, j * config.size) / config.size, v(i * config.size, j * config.size) / config.size);
806
989
  if(z.a === 0 && z.b === 0) {
807
- context.fillStyle = "rgb(0, 0, 0)";
990
+ config.context.fillStyle = "rgb(0, 0, 0)";
808
991
  } else if(z.a === Infinity && z.b === Infinity) {
809
- context.fillStyle = "rgb(255, 255, 255)";
992
+ config.context.fillStyle = "rgb(255, 255, 255)";
810
993
  } else {
811
- context.fillStyle = "hsl(" + Chalkboard.trig.toDeg(Chalkboard.comp.arg(z)) + ", 100%, " + (Chalkboard.trig.tanh(Chalkboard.comp.mag(z) / Chalkboard.real.pow(10, 20)) + 0.5) * 100 + "%)";
994
+ config.context.fillStyle = "hsl(" + Chalkboard.trig.toDeg(Chalkboard.comp.arg(z)) + ", 100%, " + (Chalkboard.trig.tanh(Chalkboard.comp.mag(z) / Chalkboard.real.pow(10, 20)) + 0.5) * 100 + "%)";
812
995
  }
813
- context.fillRect(i, j, 5, 5);
996
+ config.context.fillRect(i, j, 5, 5);
814
997
  data.push([u(i, j), v(i, j)]);
815
998
  }
816
999
  }
817
1000
  } else {
818
- return "TypeError: Property \"type\" of parameter \"func\" must be either \"expl\", \"pola\", \"curv\", or \"comp\".";
1001
+ return "TypeError: Property \"type\" of parameter \"func\" must be either \"expl\", \"inve\", \"pola\", \"curv\", or \"comp\".";
819
1002
  }
820
- context.stroke();
821
- context.restore();
1003
+ config.context.stroke();
1004
+ config.context.restore();
822
1005
  return data;
823
1006
  },
824
- barplot: function(arr, bins, scl, rgba, origin, weight, context) {
825
- scl = scl || 1;
826
- scl /= 100;
827
- rgba = rgba || [[0, 0, 0], [255, 255, 255]];
828
- origin = origin || [canvas.width / 2, canvas.height / 2];
829
- weight = weight || 2;
830
- context = context || ctx;
831
- context.save();
832
- context.translate(origin[0], origin[1]);
833
- context.lineWidth = weight;
834
- context.strokeStyle = rgba[0].length === 3 ? "rgb(" + rgba[0][0].toString() + ", " + rgba[0][1].toString() + ", " + rgba[0][2].toString() + ")" : "rgba(" + rgba[0][0].toString() + ", " + rgba[0][1].toString() + ", " + rgba[0][2].toString() + ", " + rgba[0][3].toString() + ")";
835
- context.fillStyle = rgba[1].length === 3 ? "rgb(" + rgba[1][0].toString() + ", " + rgba[1][1].toString() + ", " + rgba[1][2].toString() + ")" : "rgba(" + rgba[1][0].toString() + ", " + rgba[1][1].toString() + ", " + rgba[1][2].toString() + ", " + rgba[1][3].toString() + ")";
1007
+ barplot: function(arr, bins, config) {
1008
+ (config = {
1009
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
1010
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
1011
+ size: config.size || 1,
1012
+ fillStyle: config.fillStyle || "white",
1013
+ strokeStyle: config.strokeStyle || "black",
1014
+ lineWidth: config.lineWidth || 2,
1015
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
1016
+ }).size /= 100;
1017
+ config.context.save();
1018
+ config.context.translate(config.x, config.y);
1019
+ config.context.lineWidth = config.lineWidth;
1020
+ config.context.strokeStyle = config.strokeStyle;
1021
+ config.context.fillStyle = config.fillStyle;
836
1022
  var bars = [];
837
1023
  for(var i = 0; i < bins.length; i++) {
838
1024
  if(i === 0) {
@@ -847,26 +1033,28 @@ var Chalkboard = {
847
1033
  for(var i = 0; i < bars.length; i++) {
848
1034
  counts.push(bars[i].length);
849
1035
  }
850
- var x = 0, width = counts.length / (2 * scl);
1036
+ var x = 0, width = counts.length / (2 * config.size);
851
1037
  for(var i = 0; i < counts.length; i++) {
852
- context.fillRect(x - width, 0, 1 / scl, -counts[i] / scl);
853
- context.strokeRect(x - width, 0, 1 / scl, -counts[i] / scl);
854
- x += 1 / scl;
1038
+ config.context.fillRect(x - width, 0, 1 / config.size, -counts[i] / config.size);
1039
+ config.context.strokeRect(x - width, 0, 1 / config.size, -counts[i] / config.size);
1040
+ x += 1 / config.size;
855
1041
  }
856
- context.restore();
1042
+ config.context.restore();
857
1043
  return bars;
858
1044
  },
859
- lineplot: function(arr, bins, scl, rgba, origin, weight, context) {
860
- scl = scl || 1;
861
- scl /= 100;
862
- rgba = rgba || [0, 0, 0];
863
- origin = origin || [canvas.width / 2, canvas.height / 2];
864
- weight = weight || 2;
865
- context = context || ctx;
866
- context.save();
867
- context.translate(origin[0], origin[1]);
868
- context.lineWidth = weight;
869
- context.strokeStyle = rgba.length === 3 ? "rgb(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ")" : "rgba(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ", " + rgba[3].toString() + ")";
1045
+ lineplot: function(arr, bins, config) {
1046
+ (config = {
1047
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
1048
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
1049
+ size: config.size || 1,
1050
+ strokeStyle: config.strokeStyle || "black",
1051
+ lineWidth: config.lineWidth || 2,
1052
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
1053
+ }).size /= 100;
1054
+ config.context.save();
1055
+ config.context.translate(config.x, config.y);
1056
+ config.context.lineWidth = config.lineWidth;
1057
+ config.context.strokeStyle = config.strokeStyle;
870
1058
  var verts = [];
871
1059
  for(var i = 0; i < bins.length; i++) {
872
1060
  if(i === 0) {
@@ -881,353 +1069,392 @@ var Chalkboard = {
881
1069
  for(var i = 0; i < verts.length; i++) {
882
1070
  counts.push(verts[i].length);
883
1071
  }
884
- context.beginPath();
1072
+ config.context.beginPath();
885
1073
  for(var i = 0; i < counts.length; i++) {
886
- context.lineTo(i / scl, -counts[i] / scl);
1074
+ config.context.lineTo(i / config.size, -counts[i] / config.size);
887
1075
  }
888
- context.stroke();
889
- context.restore();
1076
+ config.context.stroke();
1077
+ config.context.restore();
890
1078
  return verts;
891
1079
  },
892
- scatterplot: function(arr1, arr2, scl, rgba, origin, weight, context) {
893
- scl = scl || 1;
894
- scl /= 100;
895
- rgba = rgba || [0, 0, 0];
896
- origin = origin || [canvas.width / 2, canvas.height / 2];
897
- weight = weight || 5;
898
- context = context || ctx;
1080
+ scatterplot: function(arr1, arr2, config) {
1081
+ (config = {
1082
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
1083
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
1084
+ size: config.size || 1,
1085
+ fillStyle: config.fillStyle || "black",
1086
+ lineWidth: config.lineWidth || 5,
1087
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
1088
+ }).size /= 100;
899
1089
  var data = [];
900
- context.save();
901
- context.translate(origin[0], origin[1]);
902
- context.fillStyle = rgba.length === 3 ? "rgb(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ")" : "rgba(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ", " + rgba[3].toString() + ")";
1090
+ config.context.save();
1091
+ config.context.translate(config.x, config.y);
1092
+ config.context.fillStyle = config.fillStyle;
903
1093
  if(arr1.length === arr2.length) {
904
1094
  for(var i = 0; i < arr1.length; i++) {
905
- context.beginPath();
906
- context.ellipse(arr1[i] / scl - arr1.length / (2 * scl), -arr2[i] / scl + arr1.length / (2 * scl), weight, weight, 0, 0, Chalkboard.PI(2));
907
- context.fill();
1095
+ config.context.beginPath();
1096
+ config.context.ellipse(arr1[i] / config.size - arr1.length / (2 * config.size), -arr2[i] / config.size + arr1.length / (2 * config.size), config.lineWidth, config.lineWidth, 0, 0, Chalkboard.PI(2));
1097
+ config.context.fill();
908
1098
  data.push([arr1[i], arr2[i]]);
909
1099
  }
910
1100
  }
911
- context.restore();
1101
+ config.context.restore();
912
1102
  return data;
913
1103
  },
914
- comp: function(comp, scl, rgba, origin, weight, context) {
915
- scl = scl || 1;
916
- scl /= 100;
917
- rgba = rgba || [0, 0, 0];
918
- origin = origin || [canvas.width / 2, canvas.height / 2];
919
- weight = weight || 5;
920
- context = context || ctx;
921
- context.fillStyle = rgba.length === 3 ? "rgb(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ")" : "rgba(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ", " + rgba[3].toString() + ")";
922
- context.save();
923
- context.translate(origin[0], origin[1]);
924
- context.beginPath();
925
- context.ellipse(comp.a / scl, -comp.b / scl, weight, weight, 0, 0, Chalkboard.PI(2));
926
- context.fill();
927
- context.restore();
1104
+ comp: function(comp, config) {
1105
+ (config = {
1106
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
1107
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
1108
+ size: config.size || 1,
1109
+ fillStyle: config.fillStyle || "black",
1110
+ lineWidth: config.lineWidth || 5,
1111
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
1112
+ }).size /= 100;
1113
+ config.context.fillStyle = config.fillStyle;
1114
+ config.context.save();
1115
+ config.context.translate(config.x, config.y);
1116
+ config.context.beginPath();
1117
+ config.context.ellipse(comp.a / config.size, -comp.b / config.size, config.lineWidth, config.lineWidth, 0, 0, Chalkboard.PI(2));
1118
+ config.context.fill();
1119
+ config.context.restore();
928
1120
  return [[comp.a], [comp.b]];
929
1121
  },
930
- vec2: function(vec2, scl, rgba, origin, weight, context) {
931
- scl = scl || 1;
932
- scl /= 100;
933
- rgba = rgba || [0, 0, 0];
934
- origin = origin || [canvas.width / 2, canvas.height / 2];
935
- weight = weight || 5;
936
- context = context || ctx;
937
- context.strokeStyle = rgba.length === 3 ? "rgb(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ")" : "rgba(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ", " + rgba[3].toString() + ")";
938
- context.lineWidth = weight;
939
- context.save();
940
- context.translate(origin[0], origin[1]);
941
- context.beginPath();
942
- context.moveTo(0, 0);
943
- context.lineTo(vec2.x / scl, -vec2.y / scl);
944
- context.stroke();
945
- context.restore();
1122
+ vec2: function(vec2, config) {
1123
+ (config = {
1124
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
1125
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
1126
+ size: config.size || 1,
1127
+ strokeStyle: config.strokeStyle || "black",
1128
+ lineWidth: config.lineWidth || 5,
1129
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
1130
+ }).size /= 100;
1131
+ config.context.strokeStyle = config.strokeStyle;
1132
+ config.context.lineWidth = config.lineWidth;
1133
+ config.context.save();
1134
+ config.context.translate(config.x, config.y);
1135
+ config.context.beginPath();
1136
+ config.context.moveTo(0, 0);
1137
+ config.context.lineTo(vec2.x / config.size, -vec2.y / config.size);
1138
+ config.context.stroke();
1139
+ config.context.restore();
946
1140
  return [[vec2.x], [vec2.y]];
947
1141
  },
948
- field: function(vec2field, scl, rgba, domain, origin, weight, res, context) {
949
- scl = scl || 1;
950
- scl /= 100;
951
- rgba = rgba || [0, 0, 0];
952
- domain = domain || [[-10, 10], [-10, 10]];
953
- origin = origin || [canvas.width / 2, canvas.height / 2];
954
- weight = weight || 5;
955
- res = res || 25;
956
- context = context || ctx;
1142
+ field: function(vec2field, config) {
1143
+ (config = {
1144
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
1145
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
1146
+ size: config.size || 1,
1147
+ strokeStyle: config.strokeStyle || "black",
1148
+ lineWidth: config.lineWidth || 2,
1149
+ domain: config.domain || [[-10, 10], [10, 10]],
1150
+ res: config.res || 25,
1151
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
1152
+ }).size /= 100;
957
1153
  var data = [];
958
- context.strokeStyle = rgba.length === 3 ? "rgb(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ")" : "rgba(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ", " + rgba[3].toString() + ")";
959
- context.lineWidth = weight;
960
- context.save();
961
- context.translate(origin[0], origin[1]);
962
- for(var i = domain[0][0] / scl; i <= domain[0][1] / scl; i += res) {
963
- for(var j = domain[1][0] / scl; j <= domain[1][1] / scl; j += res) {
1154
+ config.context.strokeStyle = config.strokeStyle;
1155
+ config.context.lineWidth = config.lineWidth;
1156
+ config.context.save();
1157
+ config.context.translate(config.x, config.y);
1158
+ for(var i = config.domain[0][0] / config.size; i <= config.domain[0][1] / config.size; i += config.res) {
1159
+ for(var j = config.domain[1][0] / config.size; j <= config.domain[1][1] / config.size; j += config.res) {
964
1160
  var v = Chalkboard.vec2.fromField(vec2field, Chalkboard.vec2.new(i, j));
965
- context.beginPath();
966
- context.moveTo(i, j);
967
- context.lineTo(i + v.x, j + v.y);
968
- context.stroke();
1161
+ config.context.beginPath();
1162
+ config.context.moveTo(i, j);
1163
+ config.context.lineTo(i + v.x, j + v.y);
1164
+ config.context.stroke();
969
1165
  data.push([i + v.x, j + v.y]);
970
1166
  }
971
1167
  }
972
- context.restore();
1168
+ config.context.restore();
973
1169
  return data;
974
1170
  },
975
- vec3: function(vec3, scl, rgba, origin, weight, context) {
976
- scl = scl || 1;
977
- scl /= 100;
978
- rgba = rgba || [0, 0, 0];
979
- origin = origin || [canvas.width / 2, canvas.height / 2];
980
- weight = weight || 5;
981
- context = context || ctx;
982
- context.strokeStyle = rgba.length === 3 ? "rgb(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ")" : "rgba(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ", " + rgba[3].toString() + ")";
983
- context.lineWidth = weight;
984
- context.save();
985
- context.translate(origin[0], origin[1]);
986
- context.beginPath();
987
- context.moveTo(0, 0);
988
- context.lineTo((vec3.x / scl) / (vec3.z * 0.25 + 1), (-vec3.y / scl) / (vec3.z * 0.25 + 1));
989
- context.stroke();
990
- context.restore();
1171
+ vec3: function(vec3, config) {
1172
+ (config = {
1173
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
1174
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
1175
+ size: config.size || 1,
1176
+ strokeStyle: config.strokeStyle || "black",
1177
+ lineWidth: config.lineWidth || 5,
1178
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
1179
+ }).size /= 100;
1180
+ config.context.strokeStyle = config.strokeStyle;
1181
+ config.context.lineWidth = config.lineWidth;
1182
+ config.context.save();
1183
+ config.context.translate(config.x, config.y);
1184
+ config.context.beginPath();
1185
+ config.context.moveTo(0, 0);
1186
+ config.context.lineTo((vec3.x / config.size) / (vec3.z * 0.25 + 1), (-vec3.y / config.size) / (vec3.z * 0.25 + 1));
1187
+ config.context.stroke();
1188
+ config.context.restore();
991
1189
  return [[vec3.x], [vec3.y], [vec3.z]];
992
1190
  },
993
- matr: function(matr, scl, rgba, origin, weight, context) {
994
- scl = scl || 1;
995
- scl /= 100;
996
- rgba = rgba || [0, 0, 0];
997
- origin = origin || [canvas.width / 2, canvas.height / 2];
998
- weight = weight || 2;
999
- var plotposx = Chalkboard.vec2.new(matr[0][0], matr[1][0]);
1000
- var plotnegx = Chalkboard.vec2.new(-matr[0][0], -matr[1][0]);
1001
- var plotposy = Chalkboard.vec2.new(matr[0][1], matr[1][1]);
1002
- var plotnegy = Chalkboard.vec2.new(-matr[0][1], -matr[1][1]);
1003
- for(var i = -10; i <= 10; i++) {
1004
- Chalkboard.vec2.plot(plotposx, scl, rgba, [origin[0], origin[1] + (i / scl) * matr[1][1]], weight / 4, context);
1005
- Chalkboard.vec2.plot(plotnegx, scl, rgba, [origin[0], origin[1] + (i / scl) * matr[1][1]], weight / 4, context);
1006
- Chalkboard.vec2.plot(plotposy, scl, rgba, [origin[0] + (i / scl) * matr[0][0], origin[1]], weight / 4, context);
1007
- Chalkboard.vec2.plot(plotnegy, scl, rgba, [origin[0] + (i / scl) * matr[0][0], origin[1]], weight / 4, context);
1008
- }
1009
- var plotposaxisx = Chalkboard.vec2.new(matr[0][0], matr[1][0]);
1010
- var plotnegaxisx = Chalkboard.vec2.new(-matr[0][0], -matr[1][0]);
1011
- var plotposaxisy = Chalkboard.vec2.new(matr[0][1], matr[1][1]);
1012
- var plotnegaxisy = Chalkboard.vec2.new(-matr[0][1], -matr[1][1]);
1013
- Chalkboard.vec2.plot(plotposaxisx, scl, rgba, origin, weight, context);
1014
- Chalkboard.vec2.plot(plotnegaxisx, scl, rgba, origin, weight, context);
1015
- Chalkboard.vec2.plot(plotposaxisy, scl, rgba, origin, weight, context);
1016
- Chalkboard.vec2.plot(plotnegaxisy, scl, rgba, origin, weight, context);
1191
+ matr: function(matr, config) {
1192
+ (config = {
1193
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
1194
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
1195
+ size: config.size || 1,
1196
+ strokeStyle: config.strokeStyle || "black",
1197
+ lineWidth: config.lineWidth || 2,
1198
+ domain: config.domain || [-10, 10],
1199
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
1200
+ }).size /= 100;
1201
+ for(var i = config.domain[0]; i <= config.domain[1]; i++) {
1202
+ Chalkboard.plot.vec2(Chalkboard.vec2.new(matr[0][0], matr[1][0]), {x: config.x, y: config.y + (i / config.size) * matr[1][1], size: config.size, strokeStyle: config.strokeStyle, lineWidth: config.lineWidth / 4, context: config.context});
1203
+ Chalkboard.plot.vec2(Chalkboard.vec2.new(-matr[0][0], -matr[1][0]), {x: config.x, y: config.y + (i / config.size) * matr[1][1], size: config.size, strokeStyle: config.strokeStyle, lineWidth: config.lineWidth / 4, context: config.context});
1204
+ Chalkboard.plot.vec2(Chalkboard.vec2.new(matr[0][1], matr[1][1]), {x: config.x + (i / config.size) * matr[0][0], y: config.y, size: config.size, strokeStyle: config.strokeStyle, lineWidth: config.lineWidth / 4, context: config.context});
1205
+ Chalkboard.plot.vec2(Chalkboard.vec2.new(-matr[0][1], -matr[1][1]), {x: config.x + (i / config.size) * matr[0][0], y: config.y, size: config.size, strokeStyle: config.strokeStyle, lineWidth: config.lineWidth / 4, context: config.context});
1206
+ }
1207
+ Chalkboard.plot.vec2(Chalkboard.vec2.new(matr[0][0], matr[1][0]), config);
1208
+ Chalkboard.plot.vec2(Chalkboard.vec2.new(-matr[0][0], -matr[1][0]), config);
1209
+ Chalkboard.plot.vec2(Chalkboard.vec2.new(matr[0][1], matr[1][1]), config);
1210
+ Chalkboard.plot.vec2(Chalkboard.vec2.new(-matr[0][1], -matr[1][1]), config);
1017
1211
  return matr;
1018
1212
  },
1019
- dfdx: function(func, scl, rgba, domain, origin, weight, res, context) {
1020
- scl = scl || 1;
1021
- scl /= 100;
1022
- rgba = rgba || [0, 0, 0];
1023
- domain = domain || [-10, 10];
1024
- origin = origin || [canvas.width / 2, canvas.height / 2];
1025
- weight = weight || 2;
1026
- res = res || 25;
1027
- context = context || ctx;
1213
+ dfdx: function(func, config) {
1214
+ (config = {
1215
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
1216
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
1217
+ size: config.size || 1,
1218
+ strokeStyle: config.strokeStyle || "black",
1219
+ lineWidth: config.lineWidth || 2,
1220
+ domain: config.domain || [-10, 10],
1221
+ res: config.res || 25,
1222
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
1223
+ }).size /= 100;
1028
1224
  var data = [];
1029
- context.save();
1030
- context.translate(origin[0], origin[1]);
1031
- context.lineWidth = weight;
1032
- context.strokeStyle = rgba.length === 3 ? "rgb(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ")" : "rgba(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ", " + rgba[3].toString() + ")";
1033
- context.beginPath();
1034
- for(var i = domain[0] / scl; i <= domain[1] / scl; i += res) {
1035
- context.lineTo(i, -Chalkboard.calc.dfdx(func, i * scl) / scl);
1036
- data.push([i, Chalkboard.calc.dfdx(func, i)]);
1225
+ config.context.save();
1226
+ config.context.translate(config.x, config.y);
1227
+ config.context.lineWidth = config.lineWidth;
1228
+ config.context.strokeStyle = config.strokeStyle;
1229
+ config.context.beginPath();
1230
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i += config.res) {
1231
+ if(func.type === "expl") {
1232
+ config.context.lineTo(i, -Chalkboard.calc.dfdx(func, i * config.size) / config.size);
1233
+ data.push([i, Chalkboard.calc.dfdx(func, i)]);
1234
+ } else if(func.type === "inve") {
1235
+ config.context.lineTo(Chalkboard.calc.dfdx(func, i * config.size) / config.size, -i);
1236
+ data.push([Chalkboard.calc.dfdx(func, i), i]);
1237
+ }
1037
1238
  }
1038
- context.stroke();
1039
- context.restore();
1239
+ config.context.stroke();
1240
+ config.context.restore();
1040
1241
  return data;
1041
1242
  },
1042
- d2fdx2: function(func, scl, rgba, domain, origin, weight, res, context) {
1043
- scl = scl || 1;
1044
- scl /= 100;
1045
- rgba = rgba || [0, 0, 0];
1046
- domain = domain || [-10, 10];
1047
- origin = origin || [canvas.width / 2, canvas.height / 2];
1048
- weight = weight || 2;
1049
- res = res || 25;
1050
- context = context || ctx;
1243
+ d2fdx2: function(func, config) {
1244
+ (config = {
1245
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
1246
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
1247
+ size: config.size || 1,
1248
+ strokeStyle: config.strokeStyle || "black",
1249
+ lineWidth: config.lineWidth || 2,
1250
+ domain: config.domain || [-10, 10],
1251
+ res: config.res || 25,
1252
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
1253
+ }).size /= 100;
1051
1254
  var data = [];
1052
- context.save();
1053
- context.translate(origin[0], origin[1]);
1054
- context.lineWidth = weight;
1055
- context.strokeStyle = rgba.length === 3 ? "rgb(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ")" : "rgba(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ", " + rgba[3].toString() + ")";
1056
- context.beginPath();
1057
- for(var i = domain[0] / scl; i <= domain[1] / scl; i += res) {
1058
- context.lineTo(i, -Chalkboard.calc.d2fdx2(func, i * scl) / scl);
1059
- data.push([i, Chalkboard.calc.d2fdx2(func, i)]);
1255
+ config.context.save();
1256
+ config.context.translate(config.x, config.y);
1257
+ config.context.lineWidth = config.lineWidth;
1258
+ config.context.strokeStyle = config.strokeStyle;
1259
+ config.context.beginPath();
1260
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i += config.res) {
1261
+ if(func.type === "expl") {
1262
+ config.context.lineTo(i, -Chalkboard.calc.d2fdx2(func, i * config.size) / config.size);
1263
+ data.push([i, Chalkboard.calc.d2fdx2(func, i)]);
1264
+ } else if(func.type === "inve") {
1265
+ config.context.lineTo(Chalkboard.calc.d2fdx2(func, i * config.size) / config.size, -i);
1266
+ data.push([Chalkboard.calc.d2fdx2(func, i), i]);
1267
+ }
1060
1268
  }
1061
- context.stroke();
1062
- context.restore();
1269
+ config.context.stroke();
1270
+ config.context.restore();
1063
1271
  return data;
1064
1272
  },
1065
- fxdx: function(func, scl, rgba, domain, origin, weight, res, context) {
1066
- scl = scl || 1;
1067
- scl /= 100;
1068
- rgba = rgba || [0, 0, 0];
1069
- domain = domain || [-10, 10];
1070
- origin = origin || [canvas.width / 2, canvas.height / 2];
1071
- weight = weight || 2;
1072
- res = res || 25;
1073
- context = context || ctx;
1273
+ fxdx: function(func, config) {
1274
+ (config = {
1275
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
1276
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
1277
+ size: config.size || 1,
1278
+ strokeStyle: config.strokeStyle || "black",
1279
+ lineWidth: config.lineWidth || 2,
1280
+ domain: config.domain || [-10, 10],
1281
+ res: config.res || 25,
1282
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
1283
+ }).size /= 100;
1074
1284
  var data = [];
1075
- context.save();
1076
- context.translate(origin[0], origin[1]);
1077
- context.lineWidth = weight;
1078
- context.strokeStyle = rgba.length === 3 ? "rgb(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ")" : "rgba(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ", " + rgba[3].toString() + ")";
1079
- context.beginPath();
1080
- for(var i = domain[0] / scl; i <= domain[1] / scl; i += res) {
1081
- context.lineTo(i, -Chalkboard.calc.fxdx(func, 0, i * scl) / scl);
1082
- data.push([i, Chalkboard.calc.fxdx(func, 0, i)]);
1285
+ config.context.save();
1286
+ config.context.translate(config.x, config.y);
1287
+ config.context.lineWidth = config.lineWidth;
1288
+ config.context.strokeStyle = config.strokeStyle;
1289
+ config.context.beginPath();
1290
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i += config.res) {
1291
+ if(func.type === "expl") {
1292
+ config.context.lineTo(i, -Chalkboard.calc.fxdx(func, 0, i * config.size) / config.size);
1293
+ data.push([i, Chalkboard.calc.fxdx(func, 0, i)]);
1294
+ } else if(func.type === "inve") {
1295
+ config.context.lineTo(Chalkboard.calc.fxdx(func, 0, i * config.size) / config.size, -i);
1296
+ data.push([Chalkboard.calc.fxdx(func, 0, i), i]);
1297
+ }
1083
1298
  }
1084
- context.stroke();
1085
- context.restore();
1299
+ config.context.stroke();
1300
+ config.context.restore();
1086
1301
  return data;
1087
1302
  },
1088
- convolution: function(func_1, func_2, scl, rgba, domain, origin, weight, res, context) {
1089
- scl = scl || 1;
1090
- scl /= 100;
1091
- rgba = rgba || [0, 0, 0];
1092
- domain = domain || [-10, 10];
1093
- origin = origin || [canvas.width / 2, canvas.height / 2];
1094
- weight = weight || 2;
1095
- res = res || 25;
1096
- context = context || ctx;
1303
+ convolution: function(func_1, func_2, config) {
1304
+ (config = {
1305
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
1306
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
1307
+ size: config.size || 1,
1308
+ strokeStyle: config.strokeStyle || "black",
1309
+ lineWidth: config.lineWidth || 2,
1310
+ domain: config.domain || [-10, 10],
1311
+ res: config.res || 25,
1312
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
1313
+ }).size /= 100;
1097
1314
  var data = [];
1098
- context.save();
1099
- context.translate(origin[0], origin[1]);
1100
- context.lineWidth = weight;
1101
- context.strokeStyle = rgba.length === 3 ? "rgb(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ")" : "rgba(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ", " + rgba[3].toString() + ")";
1102
- context.beginPath();
1103
- for(var i = domain[0] / scl; i <= domain[1] / scl; i += res) {
1104
- context.lineTo(i, -Chalkboard.calc.convolution(func_1, func_2, i * scl) / scl);
1315
+ config.context.save();
1316
+ config.context.translate(config.x, config.y);
1317
+ config.context.lineWidth = config.lineWidth;
1318
+ config.context.strokeStyle = config.strokeStyle;
1319
+ config.context.beginPath();
1320
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i += config.res) {
1321
+ config.context.lineTo(i, -Chalkboard.calc.convolution(func_1, func_2, i * config.size) / config.size);
1105
1322
  data.push([i, Chalkboard.calc.convolution(func_1, func_2, i)]);
1106
1323
  }
1107
- context.stroke();
1108
- context.restore();
1324
+ config.context.stroke();
1325
+ config.context.restore();
1109
1326
  return data;
1110
1327
  },
1111
- correlation: function(func_1, func_2, scl, rgba, domain, origin, weight, res, context) {
1112
- scl = scl || 1;
1113
- scl /= 100;
1114
- rgba = rgba || [0, 0, 0];
1115
- domain = domain || [-10, 10];
1116
- origin = origin || [canvas.width / 2, canvas.height / 2];
1117
- weight = weight || 2;
1118
- res = res || 25;
1119
- context = context || ctx;
1328
+ correlation: function(func_1, func_2, config) {
1329
+ (config = {
1330
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
1331
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
1332
+ size: config.size || 1,
1333
+ strokeStyle: config.strokeStyle || "black",
1334
+ lineWidth: config.lineWidth || 2,
1335
+ domain: config.domain || [-10, 10],
1336
+ res: config.res || 25,
1337
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
1338
+ }).size /= 100;
1120
1339
  var data = [];
1121
- context.save();
1122
- context.translate(origin[0], origin[1]);
1123
- context.lineWidth = weight;
1124
- context.strokeStyle = rgba.length === 3 ? "rgb(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ")" : "rgba(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ", " + rgba[3].toString() + ")";
1125
- context.beginPath();
1126
- for(var i = domain[0] / scl; i <= domain[1] / scl; i += res) {
1127
- context.lineTo(i, -Chalkboard.calc.correlation(func_1, func_2, i * scl) / scl);
1340
+ config.context.save();
1341
+ config.context.translate(config.x, config.y);
1342
+ config.context.lineWidth = config.lineWidth;
1343
+ config.context.strokeStyle = config.strokeStyle;
1344
+ config.context.beginPath();
1345
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i += config.res) {
1346
+ config.context.lineTo(i, -Chalkboard.calc.correlation(func_1, func_2, i * config.size) / config.size);
1128
1347
  data.push([i, Chalkboard.calc.correlation(func_1, func_2, i)]);
1129
1348
  }
1130
- context.stroke();
1131
- context.restore();
1349
+ config.context.stroke();
1350
+ config.context.restore();
1132
1351
  return data;
1133
1352
  },
1134
- autocorrelation: function(func, scl, rgba, domain, origin, weight, res, context) {
1135
- scl = scl || 1;
1136
- scl /= 100;
1137
- rgba = rgba || [0, 0, 0];
1138
- domain = domain || [-10, 10];
1139
- origin = origin || [canvas.width / 2, canvas.height / 2];
1140
- weight = weight || 2;
1141
- res = res || 25;
1142
- context = context || ctx;
1353
+ autocorrelation: function(func, config) {
1354
+ (config = {
1355
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
1356
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
1357
+ size: config.size || 1,
1358
+ strokeStyle: config.strokeStyle || "black",
1359
+ lineWidth: config.lineWidth || 2,
1360
+ domain: config.domain || [-10, 10],
1361
+ res: config.res || 25,
1362
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
1363
+ }).size /= 100;
1143
1364
  var data = [];
1144
- context.save();
1145
- context.translate(origin[0], origin[1]);
1146
- context.lineWidth = weight;
1147
- context.strokeStyle = rgba.length === 3 ? "rgb(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ")" : "rgba(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ", " + rgba[3].toString() + ")";
1148
- context.beginPath();
1149
- for(var i = domain[0] / scl; i <= domain[1] / scl; i += res) {
1150
- context.lineTo(i, -Chalkboard.calc.autocorrelation(func, i * scl) / scl);
1365
+ config.context.save();
1366
+ config.context.translate(config.x, config.y);
1367
+ config.context.lineWidth = config.lineWidth;
1368
+ config.context.strokeStyle = config.strokeStyle;
1369
+ config.context.beginPath();
1370
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i += config.res) {
1371
+ config.context.lineTo(i, -Chalkboard.calc.autocorrelation(func, i * config.size) / config.size);
1151
1372
  data.push([i, Chalkboard.calc.autocorrelation(func, i)]);
1152
1373
  }
1153
- context.stroke();
1154
- context.restore();
1374
+ config.context.stroke();
1375
+ config.context.restore();
1155
1376
  return data;
1156
1377
  },
1157
- Taylor: function(func, n, a, scl, rgba, domain, origin, weight, res, context) {
1158
- scl = scl || 1;
1159
- scl /= 100;
1160
- rgba = rgba || [0, 0, 0];
1161
- domain = domain || [-10, 10];
1162
- origin = origin || [canvas.width / 2, canvas.height / 2];
1163
- weight = weight || 2;
1164
- res = res || 25;
1165
- context = context || ctx;
1378
+ Taylor: function(func, n, a, config) {
1379
+ (config = {
1380
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
1381
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
1382
+ size: config.size || 1,
1383
+ strokeStyle: config.strokeStyle || "black",
1384
+ lineWidth: config.lineWidth || 2,
1385
+ domain: config.domain || [-10, 10],
1386
+ res: config.res || 25,
1387
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
1388
+ }).size /= 100;
1166
1389
  var data = [];
1167
- context.save();
1168
- context.translate(origin[0], origin[1]);
1169
- context.lineWidth = weight;
1170
- context.strokeStyle = rgba.length === 3 ? "rgb(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ")" : "rgba(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ", " + rgba[3].toString() + ")";
1171
- context.beginPath();
1172
- for(var i = domain[0] / scl; i <= domain[1] / scl; i += res) {
1173
- context.lineTo(i, -Chalkboard.calc.Taylor(func, i * scl, n, a) / scl);
1390
+ config.context.save();
1391
+ config.context.translate(config.x, config.y);
1392
+ config.context.lineWidth = config.lineWidth;
1393
+ config.context.strokeStyle = config.strokeStyle;
1394
+ config.context.beginPath();
1395
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i += config.res) {
1396
+ config.context.lineTo(i, -Chalkboard.calc.Taylor(func, i * config.size, n, a) / config.size);
1174
1397
  data.push([i, Chalkboard.calc.Taylor(func, i, n, a)]);
1175
1398
  }
1176
- context.stroke();
1177
- context.restore();
1399
+ config.context.stroke();
1400
+ config.context.restore();
1178
1401
  return data;
1179
1402
  },
1180
- Laplace: function(func, scl, rgba, domain, origin, weight, res, context) {
1181
- scl = scl || 1;
1182
- scl /= 100;
1183
- rgba = rgba || [0, 0, 0];
1184
- domain = domain || [-10, 10];
1185
- origin = origin || [canvas.width / 2, canvas.height / 2];
1186
- weight = weight || 2;
1187
- res = res || 25;
1188
- context = context || ctx;
1403
+ Laplace: function(func, config) {
1404
+ (config = {
1405
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
1406
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
1407
+ size: config.size || 1,
1408
+ strokeStyle: config.strokeStyle || "black",
1409
+ lineWidth: config.lineWidth || 2,
1410
+ domain: config.domain || [-10, 10],
1411
+ res: config.res || 25,
1412
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
1413
+ }).size /= 100;
1189
1414
  var data = [];
1190
- context.save();
1191
- context.translate(origin[0], origin[1]);
1192
- context.lineWidth = weight;
1193
- context.strokeStyle = rgba.length === 3 ? "rgb(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ")" : "rgba(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ", " + rgba[3].toString() + ")";
1194
- context.beginPath();
1195
- if(domain[0] >= 0) {
1196
- for(var i = domain[0] / scl; i <= domain[1] / scl; i += res) {
1197
- context.lineTo(i, -Chalkboard.calc.Laplace(func, i * scl) / scl);
1415
+ config.context.save();
1416
+ config.context.translate(config.x, config.y);
1417
+ config.context.lineWidth = config.lineWidth;
1418
+ config.context.strokeStyle = config.strokeStyle;
1419
+ config.context.beginPath();
1420
+ if( config.domain[0] >= 0) {
1421
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i += config.res) {
1422
+ config.context.lineTo(i, -Chalkboard.calc.Laplace(func, i * config.size) / config.size);
1198
1423
  data.push([i, Chalkboard.calc.Laplace(func, i)]);
1199
1424
  }
1200
1425
  } else {
1201
- for(var i = 0; i <= domain[1] / scl; i += res) {
1202
- context.lineTo(i, -Chalkboard.calc.Laplace(func, i * scl) / scl);
1426
+ for(var i = 0; i <= config.domain[1] / config.size; i += config.res) {
1427
+ config.context.lineTo(i, -Chalkboard.calc.Laplace(func, i * config.size) / config.size);
1203
1428
  data.push([i, Chalkboard.calc.Laplace(func, i)]);
1204
1429
  }
1205
1430
  }
1206
- context.stroke();
1207
- context.restore();
1431
+ config.context.stroke();
1432
+ config.context.restore();
1208
1433
  return data;
1209
1434
  },
1210
- Fourier: function(func, scl, rgba, domain, origin, weight, res, context) {
1211
- scl = scl || 1;
1212
- scl /= 100;
1213
- rgba = rgba || [0, 0, 0];
1214
- domain = domain || [-10, 10];
1215
- origin = origin || [canvas.width / 2, canvas.height / 2];
1216
- weight = weight || 2;
1217
- res = res || 25;
1218
- context = context || ctx;
1435
+ Fourier: function(func, config) {
1436
+ (config = {
1437
+ x: (config = config || {}).x || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.width / 2,
1438
+ y: config.y || Chalkboard.real.parse(Chalkboard.CONTEXT).canvas.height / 2,
1439
+ size: config.size || 1,
1440
+ strokeStyle: config.strokeStyle || "black",
1441
+ lineWidth: config.lineWidth || 2,
1442
+ domain: config.domain || [-10, 10],
1443
+ res: config.res || 25,
1444
+ context: config.context || Chalkboard.real.parse(Chalkboard.CONTEXT)
1445
+ }).size /= 100;
1219
1446
  var data = [];
1220
- context.save();
1221
- context.translate(origin[0], origin[1]);
1222
- context.lineWidth = weight;
1223
- context.strokeStyle = rgba.length === 3 ? "rgb(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ")" : "rgba(" + rgba[0].toString() + ", " + rgba[1].toString() + ", " + rgba[2].toString() + ", " + rgba[3].toString() + ")";
1224
- context.beginPath();
1225
- for(var i = domain[0] / scl; i <= domain[1] / scl; i += res) {
1226
- context.lineTo(i, -Chalkboard.calc.Fourier(func, i * scl) / scl);
1447
+ config.context.save();
1448
+ config.context.translate(config.x, config.y);
1449
+ config.context.lineWidth = config.lineWidth;
1450
+ config.context.strokeStyle = config.strokeStyle;
1451
+ config.context.beginPath();
1452
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i += config.res) {
1453
+ config.context.lineTo(i, -Chalkboard.calc.Fourier(func, i * config.size) / config.size);
1227
1454
  data.push([i, Chalkboard.calc.Fourier(func, i)]);
1228
1455
  }
1229
- context.stroke();
1230
- context.restore();
1456
+ config.context.stroke();
1457
+ config.context.restore();
1231
1458
  return data;
1232
1459
  }
1233
1460
  },
@@ -1375,7 +1602,7 @@ var Chalkboard = {
1375
1602
  return h * (Chalkboard.real.sqrt(-(a * a * a * a) + 2 * (a * b) * (a * b) + 2 * (a * c) * (a * c) - (b * b * b * b) + 2 * (b * c) * (b * c) - (c * c * c * c))) / 4;
1376
1603
  },
1377
1604
  line3D: function(x1, y1, z1, x2, y2, z2, context) {
1378
- context = context || ctx;
1605
+ context = context || Chalkboard.real.parse(Chalkboard.CONTEXT);
1379
1606
  context.beginPath();
1380
1607
  context.moveTo(x1 / (z1 * 0.0025 + 1), y1 / (z1 * 0.0025 + 1));
1381
1608
  context.lineTo(x2 / (z2 * 0.0025 + 1), y2 / (z2 * 0.0025 + 1));
@@ -1559,6 +1786,16 @@ var Chalkboard = {
1559
1786
  }
1560
1787
  return result;
1561
1788
  },
1789
+ shuffle: function(arr) {
1790
+ var index, temp, rindex;
1791
+ for(index = arr.length - 1; index > 0; index--) {
1792
+ rindex = Math.floor(Chalkboard.numb.random(0, index + 1));
1793
+ temp = arr[index];
1794
+ arr[index] = arr[rindex];
1795
+ arr[rindex] = temp;
1796
+ }
1797
+ return arr;
1798
+ },
1562
1799
  norm: function(arr, type) {
1563
1800
  type = type || "L2";
1564
1801
  var result = 0;
@@ -1632,7 +1869,7 @@ var Chalkboard = {
1632
1869
  },
1633
1870
  eq: function(arr, arrORnum) {
1634
1871
  var result = [];
1635
- if(arrORnum.constructor === Array) {
1872
+ if(Array.isArray(arrORnum)) {
1636
1873
  if(arr.length === arrORnum.length) {
1637
1874
  for(var i = 0; i < arr.length; i++) {
1638
1875
  if(arr[i] === arrORnum[i]) {
@@ -1653,7 +1890,7 @@ var Chalkboard = {
1653
1890
  includeInf = includeInf || false;
1654
1891
  includeSup = includeSup || false;
1655
1892
  var result = [];
1656
- if(inf.constructor === Array && sup.constructor === Array) {
1893
+ if(Array.isArray(inf) && Array.isArray(sup)) {
1657
1894
  if(arr.length === inf.length && arr.length === sup.length) {
1658
1895
  for(var i = 0; i < arr.length; i++) {
1659
1896
  if(includeInf) {
@@ -1709,7 +1946,7 @@ var Chalkboard = {
1709
1946
  lt: function(arr, arrORnum, includeEnd) {
1710
1947
  includeEnd = includeEnd || false;
1711
1948
  var result = [];
1712
- if(arrORnum.constructor === Array) {
1949
+ if(Array.isArray(arrORnum)) {
1713
1950
  if(arr.length === arrORnum.length) {
1714
1951
  for(var i = 0; i < arr.length; i++) {
1715
1952
  if(includeEnd) {
@@ -1741,7 +1978,7 @@ var Chalkboard = {
1741
1978
  gt: function(arr, arrORnum, includeEnd) {
1742
1979
  includeEnd = includeEnd || false;
1743
1980
  var result = [];
1744
- if(arrORnum.constructor === Array) {
1981
+ if(Array.isArray(arrORnum)) {
1745
1982
  if(arr.length === arrORnum.length) {
1746
1983
  for(var i = 0; i < arr.length; i++) {
1747
1984
  if(includeEnd) {
@@ -1770,6 +2007,23 @@ var Chalkboard = {
1770
2007
  }
1771
2008
  return result;
1772
2009
  },
2010
+ subsets: function(arr) {
2011
+ var result = [[]];
2012
+ arr.sort();
2013
+ for(var i = 0; i < arr.length; i++) {
2014
+ if(i === 0 || arr[i] !== arr[i - 1]) {
2015
+ var curr = arr[i];
2016
+ var subsetsWithCurr = [];
2017
+ for(var j = 0; j < result.length; j++) {
2018
+ var subset = result[j].slice();
2019
+ subset.push(curr);
2020
+ subsetsWithCurr.push(subset);
2021
+ }
2022
+ result = result.concat(subsetsWithCurr);
2023
+ }
2024
+ }
2025
+ return result;
2026
+ },
1773
2027
  max: function(arr) {
1774
2028
  var max = arr[0];
1775
2029
  for(var i = 0; i < arr.length; i++) {
@@ -1803,7 +2057,7 @@ var Chalkboard = {
1803
2057
  for(var i = 0; i < arr.length; i++) {
1804
2058
  result *= arr[i];
1805
2059
  }
1806
- return Chalkboard.real.nrt(Math.abs(result), arr.length);
2060
+ return Chalkboard.real.root(Math.abs(result), arr.length);
1807
2061
  } else if(type === "harmonic") {
1808
2062
  for(var i = 0; i < arr.length; i++) {
1809
2063
  result += 1 / arr[i];
@@ -1968,13 +2222,93 @@ var Chalkboard = {
1968
2222
  Gaussian: function(height, mean, deviation) {
1969
2223
  return Chalkboard.real.function(height.toString() + " * Math.exp(-((x - " + mean.toString() + ") * (x - " + mean.toString() + ")) / (2 * " + deviation.toString() + " * " + deviation.toString() + "))");
1970
2224
  },
1971
- toVector: function(arr, type) {
2225
+ regression: function(data, type, degree) {
2226
+ type = type || "linear";
2227
+ degree = degree || 2;
2228
+ if(type === "linear") {
2229
+ var x = 0, y = 0;
2230
+ var xx = 0, xy = 0;
2231
+ for(var i = 0; i < data.length; i++) {
2232
+ x += data[i][0];
2233
+ y += data[i][1];
2234
+ xx += data[i][0] * data[i][0];
2235
+ xy += data[i][0] * data[i][1];
2236
+ }
2237
+ var a = (data.length * xy - x * y) / (data.length * xx - x * x),
2238
+ b = (y / data.length) - (a * x) / data.length;
2239
+ return Chalkboard.real.function(a + " * x + " + b);
2240
+ } else if(type === "polynomial") {
2241
+ var A = Chalkboard.matr.new();
2242
+ for(var i = 0; i < data.length; i++) {
2243
+ A.push([]);
2244
+ for(var j = 0; j <= degree; j++) {
2245
+ A[i].push(Chalkboard.real.pow(data[i][0], j));
2246
+ }
2247
+ }
2248
+ var AT = Chalkboard.matr.transpose(A);
2249
+ var B = Chalkboard.matr.new();
2250
+ for(var i = 0; i < data.length; i++) {
2251
+ B.push([data[i][1]]);
2252
+ }
2253
+ var ATA = Chalkboard.matr.mul(AT, A);
2254
+ var ATAI = Chalkboard.matr.invert(ATA);
2255
+ var x = Chalkboard.matr.mul(Chalkboard.matr.mul(ATAI, AT), B);
2256
+ var coeff = [];
2257
+ for(var i = 0; i < x.length; i++) {
2258
+ coeff.push(x[i][0]);
2259
+ }
2260
+ var f = coeff[0].toString() + " + " + coeff[1].toString() + " * x";
2261
+ for(var i = 2; i <= degree; i++) {
2262
+ f += " + " + coeff[i].toString() + " * Math.pow(x, " + i + ")";
2263
+ }
2264
+ return Chalkboard.real.function(f);
2265
+ } else if(type === "power") {
2266
+ var arr = [0, 0, 0, 0];
2267
+ for(var i = 0; i < data.length; i++) {
2268
+ arr[0] += Chalkboard.real.ln(data[i][0]);
2269
+ arr[1] += data[i][1] * Chalkboard.real.ln(data[i][0]);
2270
+ arr[2] += data[i][1];
2271
+ arr[3] += Chalkboard.real.ln(data[i][0]) * Chalkboard.real.ln(data[i][0]);
2272
+ }
2273
+ var a = Chalkboard.E((arr[2] - ((data.length * arr[1] - arr[2] * arr[0]) / (data.length * arr[3] - arr[0] * arr[0])) * arr[0]) / data.length),
2274
+ b = (data.length * arr[1] - arr[2] * arr[0]) / (data.length * arr[3] - arr[0] * arr[0]);
2275
+ return Chalkboard.real.function(a + " * Math.pow(x, " + b + ")");
2276
+ } else if(type === "exponential") {
2277
+ var arr = [0, 0, 0, 0, 0, 0];
2278
+ for(var i = 0; i < data.length; i++) {
2279
+ arr[0] += data[i][0];
2280
+ arr[1] += data[i][1];
2281
+ arr[2] += data[i][0] * data[i][0] * data[i][1];
2282
+ arr[3] += data[i][1] * Chalkboard.real.ln(data[i][1]);
2283
+ arr[4] += data[i][0] & data[i][1] * Chalkboard.real.ln(data[i][1]);
2284
+ arr[5] += data[i][0] * data[i][1];
2285
+ }
2286
+ var a = Chalkboard.E((arr[2] * arr[3] - arr[5] * arr[4]) / (arr[1] * arr[2] - arr[5] * arr[5])),
2287
+ b = (arr[1] * arr[4] - arr[5] * arr[3]) / (arr[1] * arr[2] - arr[5] * arr[5]);
2288
+ return Chalkboard.real.function(a + "* Math.exp(" + b + " * x)");
2289
+ } else if(type === "logarithmic") {
2290
+ var arr = [0, 0, 0, 0];
2291
+ for(var i = 0; i < data.length; i++) {
2292
+ arr[0] += Chalkboard.real.ln(data[i][0]);
2293
+ arr[1] += data[i][1] * Chalkboard.real.ln(data[i][0]);
2294
+ arr[2] += data[i][1];
2295
+ arr[3] += Chalkboard.real.ln(data[i][0]) * Chalkboard.real.ln(data[i][0]);
2296
+ }
2297
+ var a = (arr[2] - ((data.length * arr[1] - arr[2] * arr[0]) / (data.length * arr[3] - arr[0] * arr[0])) * arr[0]) / data.length,
2298
+ b = (data.length * arr[1] - arr[2] * arr[0]) / (data.length * arr[3] - arr[0] * arr[0]);
2299
+ return Chalkboard.real.function(a + " + " + b + " * Math.log(x)");
2300
+ } else {
2301
+ return "TypeError: Parameter \"type\" must be either \"linear\", \"polynomial\", \"power\", \"exponential\", or \"logarithmic\".";
2302
+ }
2303
+ },
2304
+ toVector: function(arr, type, index) {
2305
+ if(index === undefined) { index = 0; }
1972
2306
  if(type === "vec2") {
1973
- return Chalkboard.vec2.new(arr[0], arr[1]);
2307
+ return Chalkboard.vec2.new(arr[index], arr[index + 1]);
1974
2308
  } else if(type === "vec3") {
1975
- return Chalkboard.vec3.new(arr[0], arr[1], arr[2]);
2309
+ return Chalkboard.vec3.new(arr[index], arr[index + 1], arr[index + 2]);
1976
2310
  } else if(type === "vec4") {
1977
- return Chalkboard.vec4.new(arr[0], arr[1], arr[2], arr[3]);
2311
+ return Chalkboard.vec4.new(arr[index], arr[index + 1], arr[index + 2], arr[index + 3]);
1978
2312
  } else {
1979
2313
  return "TypeError: Parameter \"type\" should be \"vec2\", \"vec3\", or \"vec4\".";
1980
2314
  }
@@ -1995,6 +2329,12 @@ var Chalkboard = {
1995
2329
  }
1996
2330
  return result;
1997
2331
  },
2332
+ toTensor: function(arr, size) {
2333
+ if(!Array.isArray(size)) {
2334
+ size = Array.from(arguments).slice(1);
2335
+ }
2336
+ return Chalkboard.tens.resize(arr, size);
2337
+ },
1998
2338
  toObject: function(arr) {
1999
2339
  var result = {};
2000
2340
  for(var i = 0; i < arr.length; i++) {
@@ -2017,6 +2357,9 @@ var Chalkboard = {
2017
2357
  return {x: x, y: y, type: "vec2"};
2018
2358
  }
2019
2359
  },
2360
+ copy: function(vec2) {
2361
+ return Object.create(Object.getPrototypeOf(vec2), Object.getOwnPropertyDescriptors(vec2));
2362
+ },
2020
2363
  random: function(inf, sup) {
2021
2364
  return Chalkboard.vec2.new(Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup));
2022
2365
  },
@@ -2161,6 +2504,9 @@ var Chalkboard = {
2161
2504
  return {x: x, y: y, z: z, type: "vec3"};
2162
2505
  }
2163
2506
  },
2507
+ copy: function(vec3) {
2508
+ return Object.create(Object.getPrototypeOf(vec3), Object.getOwnPropertyDescriptors(vec3));
2509
+ },
2164
2510
  random: function(inf, sup) {
2165
2511
  return Chalkboard.vec3.new(Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup));
2166
2512
  },
@@ -2312,6 +2658,9 @@ var Chalkboard = {
2312
2658
  return {x: x, y: y, z: z, w: w, type: "vec4"};
2313
2659
  }
2314
2660
  },
2661
+ copy: function(vec4) {
2662
+ return Object.create(Object.getPrototypeOf(vec4), Object.getOwnPropertyDescriptors(vec4));
2663
+ },
2315
2664
  random: function(inf, sup) {
2316
2665
  return Chalkboard.vec4.new(Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup));
2317
2666
  },
@@ -2446,7 +2795,23 @@ var Chalkboard = {
2446
2795
  },
2447
2796
  matr: {
2448
2797
  new: function(matrix) {
2449
- return Array.from(arguments);
2798
+ if(arguments.length === 0) {
2799
+ return [];
2800
+ } else if(Array.isArray(matrix) && Array.isArray(matrix[0])) {
2801
+ return matrix;
2802
+ } else {
2803
+ return Array.from(arguments);
2804
+ }
2805
+ },
2806
+ copy: function(matr) {
2807
+ var result = Chalkboard.matr.new();
2808
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2809
+ result.push([]);
2810
+ for(var j = 0; j < Chalkboard.matr.cols(matr); j++) {
2811
+ result[i].push(matr[i][j]);
2812
+ }
2813
+ }
2814
+ return result;
2450
2815
  },
2451
2816
  rows: function(matr) {
2452
2817
  return matr.length;
@@ -2454,12 +2819,75 @@ var Chalkboard = {
2454
2819
  cols: function(matr) {
2455
2820
  return matr[0].length;
2456
2821
  },
2457
- empty: function(dimension) {
2458
- if(Number.isInteger(dimension) && dimension > 0) {
2822
+ resize: function(matr, rows, cols) {
2823
+ if(cols === undefined) {
2824
+ cols = rows;
2825
+ }
2826
+ var result = Chalkboard.matr.new();
2827
+ var flat = Chalkboard.matr.toArray(matr);
2828
+ var index = 0;
2829
+ for(var i = 0; i < rows; i++) {
2830
+ result.push([]);
2831
+ for(var j = 0; j < cols; j++) {
2832
+ result[i].push(index < flat.length ? flat[index++] : 0);
2833
+ }
2834
+ }
2835
+ return result;
2836
+ },
2837
+ push: function(matr, type, rowORcol, elements) {
2838
+ rowORcol -= 1;
2839
+ if(type === "row") {
2840
+ matr.splice(rowORcol, 0, elements);
2841
+ return matr;
2842
+ } else if(type === "col") {
2843
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2844
+ matr[i].splice(rowORcol, 0, elements[i]);
2845
+ }
2846
+ return matr;
2847
+ } else {
2848
+ return "TypeError: Parameter \"type\" must be either \"row\" or \"col\".";
2849
+ }
2850
+ },
2851
+ pull: function(matr, type, rowORcol) {
2852
+ rowORcol -= 1;
2853
+ if(type === "row") {
2854
+ matr.splice(rowORcol, 1);
2855
+ return matr;
2856
+ } else if(type === "col") {
2857
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2858
+ matr[i].splice(rowORcol, 1);
2859
+ }
2860
+ return matr;
2861
+ } else {
2862
+ return "TypeError: Parameter \"type\" must be either \"row\" or \"col\".";
2863
+ }
2864
+ },
2865
+ fill: function(element, rows, cols) {
2866
+ if(cols === undefined) {
2867
+ cols = rows;
2868
+ }
2869
+ if(Number.isInteger(rows) && Number.isInteger(cols) && rows > 0 && cols > 0) {
2870
+ var result = Chalkboard.matr.new();
2871
+ for(var i = 0; i < rows; i++) {
2872
+ result.push([]);
2873
+ for(var j = 0; j < cols; j++) {
2874
+ result[i].push(element);
2875
+ }
2876
+ }
2877
+ return result;
2878
+ } else {
2879
+ return undefined;
2880
+ }
2881
+ },
2882
+ empty: function(rows, cols) {
2883
+ if(cols === undefined) {
2884
+ cols = rows;
2885
+ }
2886
+ if(Number.isInteger(rows) && Number.isInteger(cols) && rows > 0 && cols > 0) {
2459
2887
  var result = Chalkboard.matr.new();
2460
- for(var i = 0; i < dimension; i++) {
2888
+ for(var i = 0; i < rows; i++) {
2461
2889
  result.push([]);
2462
- for(var j = 0; j < dimension; j++) {
2890
+ for(var j = 0; j < cols; j++) {
2463
2891
  result[i].push(null);
2464
2892
  }
2465
2893
  }
@@ -2468,11 +2896,11 @@ var Chalkboard = {
2468
2896
  return undefined;
2469
2897
  }
2470
2898
  },
2471
- identity: function(dimension) {
2472
- if(Number.isInteger(dimension) && dimension > 0) {
2899
+ identity: function(size) {
2900
+ if(Number.isInteger(size) && size > 0) {
2473
2901
  var result = Chalkboard.matr.new();
2474
- for(var i = 0; i < dimension; i++) {
2475
- result.push(Array(dimension).fill(0));
2902
+ for(var i = 0; i < size; i++) {
2903
+ result.push(Array(size).fill(0));
2476
2904
  result[i][i] = 1;
2477
2905
  }
2478
2906
  return result;
@@ -2480,14 +2908,30 @@ var Chalkboard = {
2480
2908
  return undefined;
2481
2909
  }
2482
2910
  },
2483
- random: function(dimension, inf, sup) {
2484
- if(Number.isInteger(dimension) && dimension > 0) {
2485
- inf = inf || 0;
2486
- sup = sup || 1;
2911
+ exchange: function(size) {
2912
+ if(Number.isInteger(size) && size > 0) {
2913
+ var result = Chalkboard.matr.fill(0, size, size);
2914
+ for(var i = 0; i < size; i++) {
2915
+ for(var j = 0; j < size; j++) {
2916
+ if(i + j === size - 1) {
2917
+ result[i][j] = 1;
2918
+ }
2919
+ }
2920
+ }
2921
+ return result;
2922
+ } else {
2923
+ return undefined;
2924
+ }
2925
+ },
2926
+ random: function(inf, sup, rows, cols) {
2927
+ if(cols === undefined) {
2928
+ cols = rows;
2929
+ }
2930
+ if(Number.isInteger(rows) && Number.isInteger(cols) && rows > 0 && cols > 0) {
2487
2931
  var result = Chalkboard.matr.new();
2488
- for(var i = 0; i < dimension; i++) {
2932
+ for(var i = 0; i < rows; i++) {
2489
2933
  result.push([]);
2490
- for(var j = 0; j < dimension; j++) {
2934
+ for(var j = 0; j < cols; j++) {
2491
2935
  result[i].push(Chalkboard.numb.random(inf, sup));
2492
2936
  }
2493
2937
  }
@@ -2496,8 +2940,75 @@ var Chalkboard = {
2496
2940
  return undefined;
2497
2941
  }
2498
2942
  },
2943
+ shift: function(size, shiftAmount) {
2944
+ shiftAmount = shiftAmount || 1;
2945
+ if(Number.isInteger(size) && size > 0) {
2946
+ var result = Chalkboard.matr.fill(0, size, size);
2947
+ for(var i = 0; i < size; i++) {
2948
+ for(var j = 0; j < size; j++) {
2949
+ result[i][j] = Chalkboard.numb.Kronecker(i + shiftAmount, j);
2950
+ }
2951
+ }
2952
+ return result;
2953
+ } else {
2954
+ return undefined;
2955
+ }
2956
+ },
2957
+ binomial: function(size, type) {
2958
+ type = type || "lower";
2959
+ if(Number.isInteger(size) && size > 0) {
2960
+ var result = Chalkboard.matr.new();
2961
+ for(var i = 0; i < size; i++) {
2962
+ result.push([]);
2963
+ for(var j = 0; j < size; j++) {
2964
+ if(type === "lower") {
2965
+ result[i].push(Chalkboard.numb.binomial(i, j));
2966
+ } else if(type === "upper") {
2967
+ result[i].push(Chalkboard.numb.binomial(j, i));
2968
+ }
2969
+ }
2970
+ }
2971
+ if(type === "symmetric") {
2972
+ return Chalkboard.matr.mul(Chalkboard.matr.binomial(size, "lower"), Chalkboard.matr.binomial(size, "upper"));
2973
+ } else if(type !== "lower" && type !== "upper") {
2974
+ return "TypeError: Parameter \"type\" must be either \"lower\", \"upper\", or \"symmetric\".";
2975
+ } else {
2976
+ return result;
2977
+ }
2978
+ } else {
2979
+ return undefined;
2980
+ }
2981
+ },
2982
+ Hilbert: function(size) {
2983
+ if(Number.isInteger(size) && size > 0) {
2984
+ var result = Chalkboard.matr.new();
2985
+ for(var i = 0; i < size; i++) {
2986
+ result.push([]);
2987
+ for(var j = 0; j < size; j++) {
2988
+ result[i].push(1 / (i + j + 1));
2989
+ }
2990
+ }
2991
+ return result;
2992
+ } else {
2993
+ return undefined;
2994
+ }
2995
+ },
2996
+ Lehmer: function(size) {
2997
+ if(Number.isInteger(size) && size > 0) {
2998
+ var result = Chalkboard.matr.new();
2999
+ for(var i = 0; i < size; i++) {
3000
+ result.push([]);
3001
+ for(var j = 0; j < size; j++) {
3002
+ result[i].push(Math.min(i + 1, j + 1) / Math.max(i + 1, j + 1));
3003
+ }
3004
+ }
3005
+ return result;
3006
+ } else {
3007
+ return undefined;
3008
+ }
3009
+ },
2499
3010
  cofactor: function(matr, row, col) {
2500
- return matr.slice(0, row - 1).concat(matr.slice(row)).map(function (row) {
3011
+ return matr.slice(0, row - 1).concat(matr.slice(row)).map(function(row) {
2501
3012
  return row.slice(0, col - 1).concat(row.slice(col));
2502
3013
  });
2503
3014
  },
@@ -2534,15 +3045,15 @@ var Chalkboard = {
2534
3045
  }
2535
3046
  },
2536
3047
  rank: function(matr) {
2537
- return Chalkboard.matr.reduce(matr).filter(function (row) {
2538
- return row.some(function (element) {
3048
+ return Chalkboard.matr.reduce(matr).filter(function(row) {
3049
+ return row.some(function(element) {
2539
3050
  return element !== 0;
2540
3051
  });
2541
3052
  }).length;
2542
3053
  },
2543
3054
  rowspace: function(matr) {
2544
- return Chalkboard.matr.reduce(matr).filter(function (row) {
2545
- return row.some(function (element) {
3055
+ return Chalkboard.matr.reduce(matr).filter(function(row) {
3056
+ return row.some(function(element) {
2546
3057
  return element !== 0;
2547
3058
  });
2548
3059
  });
@@ -2551,15 +3062,15 @@ var Chalkboard = {
2551
3062
  return Chalkboard.matr.transpose(Chalkboard.matr.rowspace(Chalkboard.matr.transpose(matr)));
2552
3063
  },
2553
3064
  nullspace: function(matr) {
2554
- var augmented = matr.map(function (row) {
3065
+ var augmented = matr.map(function(row) {
2555
3066
  return row.slice().concat(Array(Chalkboard.matr.rows(matr)).fill(0));
2556
3067
  });
2557
3068
  var reduced = Chalkboard.matr.reduce(augmented);
2558
- return reduced.filter(function (row) {
2559
- return row.slice(0, Chalkboard.matr.rows(matr)).every(function (element) {
3069
+ return reduced.filter(function(row) {
3070
+ return row.slice(0, Chalkboard.matr.rows(matr)).every(function(element) {
2560
3071
  return element === 0;
2561
3072
  });
2562
- }).map(function (row) {
3073
+ }).map(function(row) {
2563
3074
  return row.slice(Chalkboard.matr.rows(matr));
2564
3075
  });
2565
3076
  },
@@ -2615,6 +3126,78 @@ var Chalkboard = {
2615
3126
  return undefined;
2616
3127
  }
2617
3128
  },
3129
+ LUdecomp: function(matr) {
3130
+ if(Chalkboard.matr.rows(matr) === Chalkboard.matr.cols(matr)) {
3131
+ var L = Chalkboard.matr.identity(Chalkboard.matr.rows(matr)),
3132
+ U = Chalkboard.matr.fill(0, Chalkboard.matr.rows(matr));
3133
+ for(var j = 0; j < Chalkboard.matr.cols(matr); j++) {
3134
+ for(var i = 0; i <= j; i++) {
3135
+ var sum = 0;
3136
+ for(var k = 0; k < i; k++) {
3137
+ sum += L[i][k] * U[k][j];
3138
+ }
3139
+ U[i][j] = matr[i][j] - sum;
3140
+ }
3141
+ for(var i = j + 1; i < Chalkboard.matr.rows(matr); i++) {
3142
+ var sum = 0;
3143
+ for(var k = 0; k < j; k++) {
3144
+ sum += L[i][k] * U[k][j];
3145
+ }
3146
+ L[i][j] = (matr[i][j] - sum) / U[j][j];
3147
+ }
3148
+ }
3149
+ return {L: L, U: U};
3150
+ } else {
3151
+ return undefined;
3152
+ }
3153
+ },
3154
+ QRdecomp: function(matr) {
3155
+ var Q = Chalkboard.matr.identity(Chalkboard.matr.rows(matr)),
3156
+ R = Chalkboard.matr.copy(matr);
3157
+ for(var j = 0; j < Math.min(Chalkboard.matr.rows(matr), Chalkboard.matr.cols(matr)) - (Chalkboard.matr.rows(matr) > Chalkboard.matr.cols(matr) ? 0 : 1); j++) {
3158
+ var norm = 0;
3159
+ for(var i = j; i < Chalkboard.matr.rows(matr); i++) {
3160
+ norm += R[i][j] * R[i][j];
3161
+ }
3162
+ norm = Chalkboard.real.sqrt(norm);
3163
+ var v = [];
3164
+ v[0] = norm - R[j][j];
3165
+ var normalizer = v[0] * v[0];
3166
+ for(var i = 1; i < Chalkboard.matr.rows(matr) - j; i++) {
3167
+ v[i] = -R[i + j][j];
3168
+ normalizer += v[i] * v[i];
3169
+ }
3170
+ normalizer = 1 / Chalkboard.real.sqrt(normalizer);
3171
+ for(var i = 0; i < v.length; i++) {
3172
+ v[i] *= normalizer;
3173
+ }
3174
+ R[j][j] = norm;
3175
+ for(var i = j + 1; i < Chalkboard.matr.rows(R); i++) {
3176
+ R[i][j] = 0;
3177
+ }
3178
+ for(var k = j + 1; k < Chalkboard.matr.cols(R); k++) {
3179
+ var dot = 0;
3180
+ for(var i = 0; i < v.length; i++) {
3181
+ dot += v[i] * R[i + j][k];
3182
+ }
3183
+ dot *= 2;
3184
+ for(var i = 0; i < v.length; i++) {
3185
+ R[i + j][k] -= dot * v[i];
3186
+ }
3187
+ }
3188
+ for(var k = 0; k < Chalkboard.matr.cols(Q); k++) {
3189
+ var dot = 0;
3190
+ for(var i = 0; i < v.length; i++) {
3191
+ dot += v[i] * Q[k][i + j];
3192
+ }
3193
+ dot *= 2;
3194
+ for(var i = 0; i < v.length; i++) {
3195
+ Q[k][i + j] -= dot * v[i];
3196
+ }
3197
+ }
3198
+ }
3199
+ return {Q: Q, R: R};
3200
+ },
2618
3201
  zero: function(matr) {
2619
3202
  var result = Chalkboard.matr.new();
2620
3203
  for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
@@ -2715,6 +3298,28 @@ var Chalkboard = {
2715
3298
  }
2716
3299
  return result;
2717
3300
  },
3301
+ concat: function(matr_1, matr_2, type) {
3302
+ type = type || "row";
3303
+ if(type === "row") {
3304
+ if(Chalkboard.matr.rows(matr_1) === Chalkboard.matr.rows(matr_2)) {
3305
+ return Chalkboard.matr.new(matr_1.concat(matr_2));
3306
+ } else {
3307
+ return undefined;
3308
+ }
3309
+ } else if(type === "col") {
3310
+ if(Chalkboard.matr.cols(matr_1) === Chalkboard.matr.cols(matr_2)) {
3311
+ var result = Chalkboard.matr.new();
3312
+ for(var i = 0; i < Chalkboard.matr.rows(matr_1); i++) {
3313
+ result.push(matr_1[i].concat(matr_2[i]));
3314
+ }
3315
+ return result;
3316
+ } else {
3317
+ return undefined;
3318
+ }
3319
+ } else {
3320
+ return "TypeError: Parameter \"type\" should be either \"row\" or \"col\".";
3321
+ }
3322
+ },
2718
3323
  add: function(matr_1, matr_2) {
2719
3324
  if(Chalkboard.matr.rows(matr_1) === Chalkboard.matr.rows(matr_2) && Chalkboard.matr.cols(matr_1) === Chalkboard.matr.cols(matr_2)) {
2720
3325
  var result = Chalkboard.matr.new();
@@ -2760,6 +3365,29 @@ var Chalkboard = {
2760
3365
  return undefined;
2761
3366
  }
2762
3367
  },
3368
+ mulvec: function(matr, vec) {
3369
+ if(vec.type === "vec2") {
3370
+ if(Chalkboard.matr.rows(matr) === 2) {
3371
+ return Chalkboard.matr.toVector(Chalkboard.matr.mul(matr, Chalkboard.vec2.toMatrix(vec)), "vec2");
3372
+ } else {
3373
+ return Chalkboard.matr.mul(matr, Chalkboard.vec2.toMatrix(vec));
3374
+ }
3375
+ } else if(vec.type === "vec3") {
3376
+ if(Chalkboard.matr.rows(matr) === 3) {
3377
+ return Chalkboard.matr.toVector(Chalkboard.matr.mul(matr, Chalkboard.vec3.toMatrix(vec)), "vec3");
3378
+ } else {
3379
+ return Chalkboard.matr.mul(matr, Chalkboard.vec2.toMatrix(vec));
3380
+ }
3381
+ } else if(vec.type === "vec4") {
3382
+ if(Chalkboard.matr.rows(matr) === 4) {
3383
+ return Chalkboard.matr.toVector(Chalkboard.matr.mul(matr, Chalkboard.vec4.toMatrix(vec)), "vec4");
3384
+ } else {
3385
+ return Chalkboard.matr.mul(matr, Chalkboard.vec2.toMatrix(vec));
3386
+ }
3387
+ } else {
3388
+ return "TypeError: Parameter \"vec\" should be \"vec2\", \"vec3\", or \"vec4\".";
3389
+ }
3390
+ },
2763
3391
  pow: function(matr, num) {
2764
3392
  if(Chalkboard.matr.rows(matr) === Chalkboard.matr.cols(matr)) {
2765
3393
  if(Number.isInteger(num) && num >= 0) {
@@ -2779,6 +3407,29 @@ var Chalkboard = {
2779
3407
  return undefined;
2780
3408
  }
2781
3409
  },
3410
+ addKronecker: function(matr_1, matr_2) {
3411
+ if(Chalkboard.matr.rows(matr_1) === Chalkboard.matr.cols(matr_1) && Chalkboard.matr.rows(matr_2) === Chalkboard.matr.cols(matr_2)) {
3412
+ return Chalkboard.matr.add(Chalkboard.matr.mulKronecker(matr_1, Chalkboard.matr.identity(Chalkboard.matr.rows(matr_1))), Chalkboard.matr.mulKronecker(Chalkboard.matr.identity(Chalkboard.matr.rows(matr_2)), matr_2));
3413
+ } else {
3414
+ return undefined;
3415
+ }
3416
+ },
3417
+ mulKronecker: function(matr_1, matr_2) {
3418
+ var result = Chalkboard.matr.new();
3419
+ for(var i = 0; i < Chalkboard.matr.rows(matr_1); i++) {
3420
+ for(var j = 0; j < Chalkboard.matr.cols(matr_1); j++) {
3421
+ for(var k = 0; k < Chalkboard.matr.rows(matr_2); k++) {
3422
+ for(var l = 0; l < Chalkboard.matr.cols(matr_2); l++) {
3423
+ if(!result[i * Chalkboard.matr.rows(matr_2) + k]) {
3424
+ result[i * Chalkboard.matr.rows(matr_2) + k] = [];
3425
+ }
3426
+ result[i * Chalkboard.matr.rows(matr_2) + k][j * Chalkboard.matr.cols(matr_2) + l] = matr_1[i][j] * matr_2[k][l];
3427
+ }
3428
+ }
3429
+ }
3430
+ }
3431
+ return result;
3432
+ },
2782
3433
  reduce: function(matr) {
2783
3434
  var lead = 0;
2784
3435
  for(var row = 0; row < Chalkboard.matr.rows(matr); row++) {
@@ -2862,6 +3513,12 @@ var Chalkboard = {
2862
3513
  return "TypeError: Parameter \"vec\" should be \"vec2\", \"vec3\", or \"vec4\".";
2863
3514
  }
2864
3515
  },
3516
+ toTensor: function(matr, size) {
3517
+ if(!Array.isArray(size)) {
3518
+ size = Array.from(arguments).slice(1);
3519
+ }
3520
+ return Chalkboard.tens.resize(matr, size);
3521
+ },
2865
3522
  toArray: function(matr) {
2866
3523
  var result = [];
2867
3524
  for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
@@ -2871,6 +3528,16 @@ var Chalkboard = {
2871
3528
  }
2872
3529
  return result;
2873
3530
  },
3531
+ toObject: function(matr) {
3532
+ var result = {};
3533
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
3534
+ result["i" + (i + 1)] = {};
3535
+ for(var j = 0; j < Chalkboard.matr.cols(matr); j++) {
3536
+ result["i" + (i + 1)]["j" + (j + 1)] = matr[i][j];
3537
+ }
3538
+ }
3539
+ return result;
3540
+ },
2874
3541
  toString: function(matr) {
2875
3542
  var result = "";
2876
3543
  for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
@@ -2882,18 +3549,369 @@ var Chalkboard = {
2882
3549
  }
2883
3550
  return result;
2884
3551
  },
2885
- toObject: function(matr) {
2886
- var result = {};
2887
- for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2888
- result["i" + (i + 1)] = {};
2889
- for(var j = 0; j < Chalkboard.matr.cols(matr); j++) {
2890
- result["i" + (i + 1)]["j" + (j + 1)] = matr[i][j];
3552
+ print: function(matr) {
3553
+ console.log(Chalkboard.matr.toString(matr));
3554
+ }
3555
+ },
3556
+ tens: {
3557
+ new: function(tensor) {
3558
+ if(arguments.length === 0) {
3559
+ return [];
3560
+ } else if(arguments.length === 1 && Array.isArray(arguments[0])) {
3561
+ tensor = arguments[0];
3562
+ } else {
3563
+ tensor = Array.from(arguments);
3564
+ }
3565
+ var newNDArray = function(arr) {
3566
+ return arr.map(function(subarr) {
3567
+ if(Array.isArray(subarr)) {
3568
+ return newNDArray(subarr);
3569
+ } else {
3570
+ return subarr;
3571
+ }
3572
+ });
3573
+ };
3574
+ return newNDArray(tensor);
3575
+ },
3576
+ copy: function(tens) {
3577
+ if(Array.isArray(tens)) {
3578
+ var result = Chalkboard.tens.new();
3579
+ for(var i = 0; i < tens.length; i++) {
3580
+ result[i] = Chalkboard.tens.copy(tens[i]);
2891
3581
  }
3582
+ return result;
3583
+ } else {
3584
+ return tens;
2892
3585
  }
3586
+ },
3587
+ rank: function(tens) {
3588
+ if(Array.isArray(tens)) {
3589
+ var result = 0;
3590
+ for(var i = 0; i < tens.length; i++) {
3591
+ result = Math.max(result, Chalkboard.tens.rank(tens[i]));
3592
+ }
3593
+ return result + 1;
3594
+ } else {
3595
+ return 0;
3596
+ }
3597
+ },
3598
+ size: function(tens) {
3599
+ if(Array.isArray(tens)) {
3600
+ var result = [tens.length];
3601
+ if(Array.isArray(tens[0])) {
3602
+ result = result.concat(Chalkboard.tens.size(tens[0]));
3603
+ }
3604
+ return result;
3605
+ } else {
3606
+ return [];
3607
+ }
3608
+ },
3609
+ resize: function(tens, size) {
3610
+ if(!Array.isArray(size)) {
3611
+ size = Array.from(arguments).slice(1);
3612
+ }
3613
+ var result = Chalkboard.tens.fill(0, size);
3614
+ var refill = function(arr1, arr2) {
3615
+ for(var i = 0; i < arr2.length; i++) {
3616
+ if(Array.isArray(arr2[i])) {
3617
+ refill(arr1, arr2[i]);
3618
+ } else {
3619
+ arr2[i] = arr1.length > 0 ? arr1.shift() : 0;
3620
+ }
3621
+ }
3622
+ };
3623
+ refill(Chalkboard.tens.toArray(tens), result);
2893
3624
  return result;
2894
3625
  },
2895
- print: function(matr) {
2896
- console.log(Chalkboard.matr.toString(matr));
3626
+ push: function(tens, rank, index, elements) {
3627
+ if(rank === 0) {
3628
+ tens.splice(index, 0, elements);
3629
+ return tens;
3630
+ } else {
3631
+ for(var i = 0; i < tens.length; i++) {
3632
+ Chalkboard.tens.push(tens[i], rank - 1, index, elements[i]);
3633
+ }
3634
+ return tens;
3635
+ }
3636
+ },
3637
+ pull: function(tens, rank, index) {
3638
+ if(rank === 0) {
3639
+ tens.splice(index, 1);
3640
+ return tens;
3641
+ } else {
3642
+ for(var i = 0; i < tens.length; i++) {
3643
+ Chalkboard.tens.pull(tens[i], rank - 1, index);
3644
+ }
3645
+ return tens;
3646
+ }
3647
+ },
3648
+ fill: function(element, size) {
3649
+ if(!Array.isArray(size)) {
3650
+ size = Array.from(arguments).slice(1);
3651
+ }
3652
+ var newNDArray = function(size) {
3653
+ if(size.length === 0) {
3654
+ return element;
3655
+ }
3656
+ var curr = size[0];
3657
+ var rest = size.slice(1);
3658
+ var result = [];
3659
+ for(var i = 0; i < curr; i++) {
3660
+ result[i] = newNDArray(rest);
3661
+ }
3662
+ return result;
3663
+ }
3664
+ return newNDArray(size);
3665
+ },
3666
+ empty: function(size) {
3667
+ if(!Array.isArray(size)) {
3668
+ size = Array.from(arguments);
3669
+ }
3670
+ var newNDArray = function(size) {
3671
+ if(size.length === 0) {
3672
+ return null;
3673
+ }
3674
+ var curr = size[0];
3675
+ var rest = size.slice(1);
3676
+ var result = [];
3677
+ for(var i = 0; i < curr; i++) {
3678
+ result[i] = newNDArray(rest);
3679
+ }
3680
+ return result;
3681
+ }
3682
+ return newNDArray(size);
3683
+ },
3684
+ random: function(inf, sup, size) {
3685
+ if(!Array.isArray(size)) {
3686
+ size = Array.from(arguments).slice(2);
3687
+ }
3688
+ var newNDArray = function(size) {
3689
+ if(size.length === 0) {
3690
+ return Chalkboard.numb.random(inf, sup);
3691
+ }
3692
+ var curr = size[0];
3693
+ var rest = size.slice(1);
3694
+ var result = [];
3695
+ for(var i = 0; i < curr; i++) {
3696
+ result[i] = newNDArray(rest);
3697
+ }
3698
+ return result;
3699
+ }
3700
+ return newNDArray(size);
3701
+ },
3702
+ contract: function(tens) {
3703
+ if(Chalkboard.tens.rank(tens) > 2) {
3704
+ return Chalkboard.tens.resize(tens, Chalkboard.tens.size(tens)[0], Chalkboard.tens.size(tens).slice(1).reduce(function(a, b) { return a * b; }) / Chalkboard.tens.size(tens)[0]);
3705
+ } else if(Chalkboard.tens.rank(tens) === 2) {
3706
+ return Chalkboard.matr.trace(tens);
3707
+ }
3708
+ },
3709
+ transpose: function(tens) {
3710
+ return Chalkboard.tens.resize(tens, Chalkboard.tens.size(tens).reverse());
3711
+ },
3712
+ zero: function(tens) {
3713
+ var result = Chalkboard.tens.new();
3714
+ if(Array.isArray(tens)) {
3715
+ for(var i = 0; i < tens.length; i++) {
3716
+ result[i] = Chalkboard.tens.zero(tens[i]);
3717
+ }
3718
+ return result;
3719
+ } else {
3720
+ return 0;
3721
+ }
3722
+ },
3723
+ negate: function(tens) {
3724
+ var result = Chalkboard.tens.new();
3725
+ if(Array.isArray(tens)) {
3726
+ for(var i = 0; i < tens.length; i++) {
3727
+ result[i] = Chalkboard.tens.negate(tens[i]);
3728
+ }
3729
+ return result;
3730
+ } else {
3731
+ return -tens;
3732
+ }
3733
+ },
3734
+ reciprocate: function(tens) {
3735
+ var result = Chalkboard.tens.new();
3736
+ if(Array.isArray(tens)) {
3737
+ for(var i = 0; i < tens.length; i++) {
3738
+ result[i] = Chalkboard.tens.reciprocate(tens[i]);
3739
+ }
3740
+ return result;
3741
+ } else {
3742
+ return 1 / tens;
3743
+ }
3744
+ },
3745
+ absolute: function(tens) {
3746
+ var result = Chalkboard.tens.new();
3747
+ if(Array.isArray(tens)) {
3748
+ for(var i = 0; i < tens.length; i++) {
3749
+ result[i] = Chalkboard.tens.absolute(tens[i]);
3750
+ }
3751
+ return result;
3752
+ } else {
3753
+ return Math.abs(tens);
3754
+ }
3755
+ },
3756
+ round: function(tens) {
3757
+ var result = Chalkboard.tens.new();
3758
+ if(Array.isArray(tens)) {
3759
+ for(var i = 0; i < tens.length; i++) {
3760
+ result[i] = Chalkboard.tens.round(tens[i]);
3761
+ }
3762
+ return result;
3763
+ } else {
3764
+ return Math.round(tens);
3765
+ }
3766
+ },
3767
+ scl: function(tens, num) {
3768
+ var result = Chalkboard.tens.new();
3769
+ if(Array.isArray(tens)) {
3770
+ for(var i = 0; i < tens.length; i++) {
3771
+ result[i] = Chalkboard.tens.scl(tens[i], num);
3772
+ }
3773
+ return result;
3774
+ } else {
3775
+ return tens * num;
3776
+ }
3777
+ },
3778
+ constrain: function(tens, range) {
3779
+ var result = Chalkboard.tens.new();
3780
+ if(Array.isArray(tens)) {
3781
+ for(var i = 0; i < tens.length; i++) {
3782
+ result[i] = Chalkboard.tens.constrain(tens[i], range);
3783
+ }
3784
+ return result;
3785
+ } else {
3786
+ return Chalkboard.numb.constrain(tens, range);
3787
+ }
3788
+ },
3789
+ concat: function(tens_1, tens_2, rank) {
3790
+ rank = rank || 1;
3791
+ var concatAtRank = function(arr1, arr2, currentRank) {
3792
+ if(currentRank === rank) {
3793
+ return Chalkboard.tens.new(arr1.concat(arr2));
3794
+ }
3795
+ return arr1.map(function(element, index) {
3796
+ return concatAtRank(element, arr2[index], currentRank);
3797
+ });
3798
+ }
3799
+ return concatAtRank(tens_1, tens_2, 1);
3800
+ },
3801
+ add: function(tens_1, tens_2) {
3802
+ var result = Chalkboard.tens.new();
3803
+ if(Array.isArray(tens_1) && Array.isArray(tens_2)) {
3804
+ for(var i = 0; i < Math.max(tens_1.length, tens_2.length); i++) {
3805
+ result[i] = Chalkboard.tens.add(tens_1[i] !== undefined ? tens_1[i] : 0, tens_2[i] !== undefined ? tens_2[i] : 0);
3806
+ }
3807
+ return result;
3808
+ } else {
3809
+ return tens_1 + tens_2;
3810
+ }
3811
+ },
3812
+ sub: function(tens_1, tens_2) {
3813
+ var result = Chalkboard.tens.new();
3814
+ if(Array.isArray(tens_1) && Array.isArray(tens_2)) {
3815
+ for(var i = 0; i < Math.max(tens_1.length, tens_2.length); i++) {
3816
+ result[i] = Chalkboard.tens.sub(tens_1[i] !== undefined ? tens_1[i] : 0, tens_2[i] !== undefined ? tens_2[i] : 0);
3817
+ }
3818
+ return result;
3819
+ } else {
3820
+ return tens_1 - tens_2;
3821
+ }
3822
+ },
3823
+ mul: function(tens_1, tens_2) {
3824
+ var result = Chalkboard.tens.new();
3825
+ if(Array.isArray(tens_1) && Array.isArray(tens_2)) {
3826
+ for(var i = 0; i < tens_1.length; i++) {
3827
+ var subarr = Chalkboard.tens.new();
3828
+ for(var j = 0; j < tens_2.length; j++) {
3829
+ subarr[j] = Chalkboard.tens.mul(tens_1[i], tens_2[j]);
3830
+ }
3831
+ result.push(subarr);
3832
+ }
3833
+ return result;
3834
+ } else {
3835
+ return tens_1 * tens_2;
3836
+ }
3837
+ },
3838
+ toVector: function(tens, type, index) {
3839
+ if(index === undefined) { index = 0; }
3840
+ var arr = Chalkboard.tens.toArray(tens);
3841
+ if(type === "vec2") {
3842
+ return Chalkboard.vec2.new(arr[index], arr[index + 1]);
3843
+ } else if(type === "vec3") {
3844
+ return Chalkboard.vec3.new(arr[index], arr[index + 1], arr[index + 2]);
3845
+ } else if(type === "vec4") {
3846
+ return Chalkboard.vec4.new(arr[index], arr[index + 1], arr[index + 2], arr[index + 3]);
3847
+ } else {
3848
+ return "TypeError: Parameter \"type\" should be \"vec2\", \"vec3\", or \"vec4\".";
3849
+ }
3850
+ },
3851
+ toMatrix: function(tens) {
3852
+ var result = Chalkboard.matr.new();
3853
+ var flatten = function(tens, result) {
3854
+ for(var i = 0; i < tens.length; i++) {
3855
+ if(Array.isArray(tens[i])) {
3856
+ flatten(tens[i], result);
3857
+ } else {
3858
+ result.push(tens[i]);
3859
+ }
3860
+ }
3861
+ }
3862
+ var matr = Chalkboard.matr.new();
3863
+ flatten(tens, matr);
3864
+ var rows = tens.length || 1;
3865
+ for(var j = 0; j < rows; j++) {
3866
+ result.push(matr.slice(j * matr.length / rows, (j + 1) * matr.length / rows));
3867
+ }
3868
+ return result;
3869
+ },
3870
+ toArray: function(tens) {
3871
+ var result = [];
3872
+ var flatten = function(tens) {
3873
+ for(var i = 0; i < tens.length; i++) {
3874
+ if(Array.isArray(tens[i])) {
3875
+ flatten(tens[i]);
3876
+ } else {
3877
+ result.push(tens[i]);
3878
+ }
3879
+ }
3880
+ }
3881
+ flatten(tens);
3882
+ return result;
3883
+ },
3884
+ toObject: function(tens) {
3885
+ if(Array.isArray(tens)) {
3886
+ var result = {};
3887
+ for(var i = 0; i < tens.length; i++) {
3888
+ result["_" + (i + 1)] = Chalkboard.tens.toObject(tens[i]);
3889
+ }
3890
+ return result;
3891
+ } else {
3892
+ return tens;
3893
+ }
3894
+ },
3895
+ toString: function(tens, indentation) {
3896
+ if(indentation === undefined) { indentation = 0; }
3897
+ if(Array.isArray(tens[0])) {
3898
+ var result = "\t".repeat(indentation) + "[\n";
3899
+ for(var i = 0; i < tens.length; i++) {
3900
+ result += Chalkboard.tens.toString(tens[i], indentation + 1);
3901
+ }
3902
+ result += "\t".repeat(indentation) + "]\n";
3903
+ return result;
3904
+ } else {
3905
+ var result = "\t".repeat(indentation) + "[ ";
3906
+ for(var i = 0; i < tens.length; i++) {
3907
+ result += tens[i].toString() + " ";
3908
+ }
3909
+ result += "]\n";
3910
+ return result;
3911
+ }
3912
+ },
3913
+ print: function(tens) {
3914
+ return console.log(Chalkboard.tens.toString(tens));
2897
3915
  }
2898
3916
  },
2899
3917
  calc: {
@@ -2931,6 +3949,9 @@ var Chalkboard = {
2931
3949
  if(func.type === "expl") {
2932
3950
  var f = Chalkboard.real.parse("x => " + func.definition);
2933
3951
  return (f(val + h) - f(val)) / h;
3952
+ } else if(func.type === "inve") {
3953
+ var f = Chalkboard.real.parse("y => " + func.definition);
3954
+ return (f(val + h) - f(val)) / h;
2934
3955
  } else if(func.type === "pola") {
2935
3956
  var r = Chalkboard.real.parse("O => " + func.definition);
2936
3957
  return (r(val + h) - r(val)) / h;
@@ -2946,7 +3967,7 @@ var Chalkboard = {
2946
3967
  return Chalkboard.vec3.new((x(val + h) - x(val)) / h, (y(val + h) - y(val)) / h, (z(val + h) - z(val)) / h);
2947
3968
  }
2948
3969
  } else {
2949
- return "TypeError: Parameter \"func\" must be of type \"expl\", \"pola\", or \"curv\".";
3970
+ return "TypeError: Parameter \"func\" must be of type \"expl\", \"inve\", \"pola\", or \"curv\".";
2950
3971
  }
2951
3972
  },
2952
3973
  d2fdx2: function(func, val) {
@@ -2954,6 +3975,9 @@ var Chalkboard = {
2954
3975
  if(func.type === "expl") {
2955
3976
  var f = Chalkboard.real.parse("x => " + func.definition);
2956
3977
  return (f(val + h) - 2 * f(val) + f(val - h)) / (h * h);
3978
+ } else if(func.type === "inve") {
3979
+ var f = Chalkboard.real.parse("y => " + func.definition);
3980
+ return (f(val + h) - 2 * f(val) + f(val - h)) / (h * h);
2957
3981
  } else if(func.type === "pola") {
2958
3982
  var r = Chalkboard.real.parse("O => " + func.definition);
2959
3983
  return (r(val + h) - 2 * r(val) + r(val - h)) / (h * h);
@@ -2969,7 +3993,7 @@ var Chalkboard = {
2969
3993
  return Chalkboard.vec3.new((x(val + h) - 2 * x(val) + x(val - h)) / (h * h), (y(val + h) - 2 * y(val) + y(val - h)) / (h * h), (z(val + h) - 2 * z(val) + z(val - h)) / (h * h));
2970
3994
  }
2971
3995
  } else {
2972
- return "TypeError: Parameter \"func\" must be of type \"expl\", \"pola\", or \"curv\".";
3996
+ return "TypeError: Parameter \"func\" must be of type \"expl\", \"inve\", \"pola\", or \"curv\".";
2973
3997
  }
2974
3998
  },
2975
3999
  tangent: function(func, val) {
@@ -3224,7 +4248,7 @@ var Chalkboard = {
3224
4248
  return "TypeError: Parameter \"func\" must be of type \"comp\".";
3225
4249
  }
3226
4250
  },
3227
- df2dz2: function(func, comp) {
4251
+ d2fdz2: function(func, comp) {
3228
4252
  var h = 0.00001;
3229
4253
  if(func.type === "comp") {
3230
4254
  var u = Chalkboard.comp.parse("(a, b) => " + func.definition[0]),
@@ -3238,59 +4262,61 @@ var Chalkboard = {
3238
4262
  return "TypeError: Parameter \"func\" must be of type \"comp\".";
3239
4263
  }
3240
4264
  },
3241
- fxdx: function(func, a, b) {
3242
- if(func.type === "expl" || func.type === "pola") {
4265
+ fxdx: function(func, inf, sup) {
4266
+ if(func.type === "expl" || func.type === "inve" || func.type === "pola") {
3243
4267
  var f;
3244
4268
  if(func.type === "expl") {
3245
4269
  f = Chalkboard.real.parse("x => " + func.definition);
4270
+ } else if(func.type === "inve") {
4271
+ f = Chalkboard.real.parse("y => " + func.definition);
3246
4272
  } else if(func.type === "pola") {
3247
4273
  f = Chalkboard.real.parse("O => " + "((" + func.definition + ") * (" + func.definition + ")) / 2");
3248
4274
  }
3249
- var fx = f(a) + f(b);
3250
- var dx = (b - a) / 1000000;
4275
+ var fx = f(inf) + f(sup);
4276
+ var dx = (sup - inf) / 1000000;
3251
4277
  for(var i = 1; i < 1000000; i++) {
3252
- fx += i % 2 === 0 ? 2 * f(a + i * dx) : 4 * f(a + i * dx);
4278
+ fx += i % 2 === 0 ? 2 * f(inf + i * dx) : 4 * f(inf + i * dx);
3253
4279
  }
3254
4280
  return (fx * dx) / 3;
3255
4281
  } else if(func.type === "curv") {
3256
4282
  if(func.definition.length === 2) {
3257
4283
  var x = Chalkboard.real.parse("t => " + func.definition[0]),
3258
4284
  y = Chalkboard.real.parse("t => " + func.definition[1]);
3259
- var xt = x(a) + x(b),
3260
- yt = y(a) + y(b);
3261
- var dt = (b - a) / 1000000;
4285
+ var xt = x(inf) + x(sup),
4286
+ yt = y(inf) + y(sup);
4287
+ var dt = (sup - inf) / 1000000;
3262
4288
  for(var i = 1; i < 1000000; i++) {
3263
- xt += i % 2 === 0 ? 2 * x(a + i * dt) : 4 * x(a + i * dt);
3264
- yt += i % 2 === 0 ? 2 * y(a + i * dt) : 4 * y(a + i * dt);
4289
+ xt += i % 2 === 0 ? 2 * x(inf + i * dt) : 4 * x(inf + i * dt);
4290
+ yt += i % 2 === 0 ? 2 * y(sup + i * dt) : 4 * y(sup + i * dt);
3265
4291
  }
3266
4292
  return Chalkboard.vec2.new((xt * dt) / 3, (yt * dt) / 3);
3267
4293
  } else if(func.definition.length === 3) {
3268
4294
  var x = Chalkboard.real.parse("t => " + func.definition[0]),
3269
4295
  y = Chalkboard.real.parse("t => " + func.definition[1]),
3270
4296
  z = Chalkboard.real.parse("t => " + func.definition[2]);
3271
- var xt = x(a) + x(b),
3272
- yt = y(a) + y(b),
3273
- zt = z(a) + z(b);
3274
- var dt = (b - a) / 1000000;
4297
+ var xt = x(inf) + x(sup),
4298
+ yt = y(inf) + y(sup),
4299
+ zt = z(inf) + z(sup);
4300
+ var dt = (sup - inf) / 1000000;
3275
4301
  for(var i = 1; i < 1000000; i++) {
3276
- xt += i % 2 === 0 ? 2 * x(a + i * dt) : 4 * x(a + i * dt);
3277
- yt += i % 2 === 0 ? 2 * y(a + i * dt) : 4 * y(a + i * dt);
3278
- zt += i % 2 === 0 ? 2 * z(a + i * dt) : 4 * z(a + i * dt);
4302
+ xt += i % 2 === 0 ? 2 * x(inf + i * dt) : 4 * x(inf + i * dt);
4303
+ yt += i % 2 === 0 ? 2 * y(inf + i * dt) : 4 * y(inf + i * dt);
4304
+ zt += i % 2 === 0 ? 2 * z(inf + i * dt) : 4 * z(inf + i * dt);
3279
4305
  }
3280
4306
  return Chalkboard.vec3.new((xt * dt) / 3, (yt * dt) / 3, (zt * dt) / 3);
3281
4307
  }
3282
4308
  } else {
3283
- return "TypeError: Parameter \"func\" must be of type \"expl\", \"pola\", or \"curv\".";
4309
+ return "TypeError: Parameter \"func\" must be of type \"expl\", \"inve\", \"pola\", or \"curv\".";
3284
4310
  }
3285
4311
  },
3286
- fxydxdy: function(func, a, b, c, d) {
4312
+ fxydxdy: function(func, xinf, xsup, yinf, ysup) {
3287
4313
  if(func.type === "mult") {
3288
4314
  var f = Chalkboard.real.parse("(x, y) => " + func.definition);
3289
4315
  var result = 0;
3290
- var dx = (b - a) / 10000,
3291
- dy = (d - c) / 10000;
3292
- for(var x = a; x <= b; x += dx) {
3293
- for(var y = c; y <= d; y += dy) {
4316
+ var dx = (xsup - xinf) / 10000,
4317
+ dy = (ysup - yinf) / 10000;
4318
+ for(var x = xinf; x <= xsup; x += dx) {
4319
+ for(var y = yinf; y <= ysup; y += dy) {
3294
4320
  result += f(x, y);
3295
4321
  }
3296
4322
  }
@@ -3299,29 +4325,29 @@ var Chalkboard = {
3299
4325
  return "TypeError: Parameter \"func\" must be of type \"mult\".";
3300
4326
  }
3301
4327
  },
3302
- fds: function(func, a, b, c, d) {
4328
+ fds: function(func, tinf, tsup, sinf, ssup) {
3303
4329
  var result = 0;
3304
4330
  var drdt, drds;
3305
4331
  if(func.type === "curv") {
3306
- var dt = (b - a) / 10000;
4332
+ var dt = (tsup - tinf) / 10000;
3307
4333
  if(func.definition.length === 2) {
3308
- for(var t = a; t <= b; t += dt) {
4334
+ for(var t = tinf; t <= tsup; t += dt) {
3309
4335
  drdt = Chalkboard.calc.dfdx(func, t);
3310
4336
  result += Chalkboard.vec2.mag(drdt);
3311
4337
  }
3312
4338
  return result * dt;
3313
4339
  } else if(func.definition.length === 3) {
3314
- for(var t = a; t <= b; t += dt) {
4340
+ for(var t = tinf; t <= tsup; t += dt) {
3315
4341
  drdt = Chalkboard.calc.dfdx(func, t);
3316
4342
  result += Chalkboard.vec3.mag(drdt);
3317
4343
  }
3318
4344
  return result * dt;
3319
4345
  }
3320
4346
  } else if(func.type === "surf") {
3321
- var dt = (b - a) / 100,
3322
- ds = (d - c) / 100;
3323
- for(var s = c; s <= d; s += ds) {
3324
- for(var t = a; t <= b; t += dt) {
4347
+ var dt = (tsup - tinf) / 100,
4348
+ ds = (ssup - sinf) / 100;
4349
+ for(var s = sinf; s <= ssup; s += ds) {
4350
+ for(var t = tinf; t <= tsup; t += dt) {
3325
4351
  drds = Chalkboard.matr.toVector(Chalkboard.calc.grad(func, Chalkboard.vec2.new(s, t)), "vec3", "col", 1);
3326
4352
  drdt = Chalkboard.matr.toVector(Chalkboard.calc.grad(func, Chalkboard.vec2.new(s, t)), "vec3", "col", 2);
3327
4353
  result += Chalkboard.vec3.mag(Chalkboard.vec3.cross(drds, drdt));
@@ -3332,22 +4358,22 @@ var Chalkboard = {
3332
4358
  return "TypeError: Parameter \"func\" must be of type \"curv\" or \"surf\".";
3333
4359
  }
3334
4360
  },
3335
- frds: function(funcORvecfield, func, a, b) {
4361
+ frds: function(funcORvecfield, func, inf, sup) {
3336
4362
  if(func.type === "curv") {
3337
4363
  var result = 0;
3338
- var dt = (b - a) / 10000;
4364
+ var dt = (sup - inf) / 10000;
3339
4365
  if(funcORvecfield.type === "mult") {
3340
- for(var t = a; t <= b; t += dt) {
3341
- result += Chalkboard.real.val(funcORvecfield, Chalkboard.vec2.toArray(Chalkboard.real.val(func, t))) * Chalkboard.vec2.mag(Chalkboard.calc.dfdx(func, t));
4366
+ for(var t = inf; t <= sup; t += dt) {
4367
+ result += Chalkboard.real.val(funcORvecfield, Chalkboard.real.val(func, t)) * Chalkboard.vec2.mag(Chalkboard.calc.dfdx(func, t));
3342
4368
  }
3343
4369
  return result * dt;
3344
4370
  } else if(funcORvecfield.type === "vec2field") {
3345
- for(var t = a; t <= b; t += dt) {
4371
+ for(var t = inf; t <= sup; t += dt) {
3346
4372
  result += Chalkboard.vec2.dot(Chalkboard.vec2.fromField(funcORvecfield, Chalkboard.real.val(func, t)), Chalkboard.calc.dfdx(func, t));
3347
4373
  }
3348
4374
  return result * dt;
3349
4375
  } else if(funcORvecfield.type === "vec3field") {
3350
- for(var t = a; t <= b; t += dt) {
4376
+ for(var t = inf; t <= sup; t += dt) {
3351
4377
  result += Chalkboard.vec3.dot(Chalkboard.vec3.fromField(funcORvecfield, Chalkboard.real.val(func, t)), Chalkboard.calc.dfdx(func, t));
3352
4378
  }
3353
4379
  return result * dt;
@@ -3358,29 +4384,29 @@ var Chalkboard = {
3358
4384
  return "TypeError: Parameter \"func\" must be of type \"curv\".";
3359
4385
  }
3360
4386
  },
3361
- fnds: function(vecfield, func, a, b, c, d) {
4387
+ fnds: function(vecfield, func, tinf, tsup, sinf, ssup) {
3362
4388
  var result = 0;
3363
4389
  var drdt, drds;
3364
4390
  if(func.type === "curv") {
3365
- var dt = (b - a) / 10000;
4391
+ var dt = (tsup - tinf) / 10000;
3366
4392
  if(func.definition.length === 2) {
3367
- for(var t = a; t <= b; t += dt) {
4393
+ for(var t = tinf; t <= tsup; t += dt) {
3368
4394
  drdt = Chalkboard.calc.dfdx(func, t);
3369
4395
  result += Chalkboard.vec2.dot(Chalkboard.vec2.fromField(vecfield, Chalkboard.real.val(func, t)), Chalkboard.vec2.new(-drdt.y, drdt.x)) * Chalkboard.vec2.mag(drdt);
3370
4396
  }
3371
4397
  return result * dt;
3372
4398
  } else if(func.definition.length === 3) {
3373
- for(var t = a; t <= b; t += dt) {
4399
+ for(var t = tinf; t <= tsup; t += dt) {
3374
4400
  drdt = Chalkboard.calc.dfdx(func, t);
3375
4401
  result += Chalkboard.vec3.dot(Chalkboard.vec3.fromField(vecfield, Chalkboard.real.val(func, t)), Chalkboard.calc.normal(func, t)) * Chalkboard.vec3.mag(drdt);
3376
4402
  }
3377
4403
  return result * dt;
3378
4404
  }
3379
4405
  } else if(func.type === "surf") {
3380
- var dt = (b - a) / 100,
3381
- ds = (d - c) / 100;
3382
- for(var s = c; s <= d; s += ds) {
3383
- for(var t = a; t <= b; t += dt) {
4406
+ var dt = (tsup - tinf) / 100,
4407
+ ds = (ssup - sinf) / 100;
4408
+ for(var s = sinf; s <= ssup; s += ds) {
4409
+ for(var t = tinf; t <= tsup; t += dt) {
3384
4410
  drds = Chalkboard.matr.toVector(Chalkboard.calc.grad(func, Chalkboard.vec2.new(s, t)), "vec3", "col", 1);
3385
4411
  drdt = Chalkboard.matr.toVector(Chalkboard.calc.grad(func, Chalkboard.vec2.new(s, t)), "vec3", "col", 2);
3386
4412
  result += Chalkboard.vec3.scalarTriple(Chalkboard.vec3.fromField(vecfield, Chalkboard.real.val(func, Chalkboard.vec2.new(s, t))), drds, drdt);
@@ -3391,12 +4417,12 @@ var Chalkboard = {
3391
4417
  return "TypeError: Parameter \"func\" must be of type \"curv\" or \"surf\".";
3392
4418
  }
3393
4419
  },
3394
- fzdz: function(func_1, func_2, a, b) {
4420
+ fzdz: function(func_1, func_2, inf, sup) {
3395
4421
  if(func_1.type === "comp") {
3396
4422
  if(func_2.type === "curv") {
3397
4423
  var result = Chalkboard.comp.new(0, 0);
3398
- var dt = (b - a) / 10000;
3399
- for(var t = a; t <= b; t += dt) {
4424
+ var dt = (sup - inf) / 10000;
4425
+ for(var t = inf; t <= sup; t += dt) {
3400
4426
  var fz = Chalkboard.comp.val(func_1, Chalkboard.vec2.toComplex(Chalkboard.real.val(func_2, t)));
3401
4427
  var rt = Chalkboard.calc.dfdx(func_2, t);
3402
4428
  result = Chalkboard.comp.add(result, Chalkboard.comp.new((fz.a * rt.x) - (fz.b * rt.y), (fz.b * rt.x) + (fz.a * rt.y)));
@@ -3478,4 +4504,8 @@ var Chalkboard = {
3478
4504
  }
3479
4505
  }
3480
4506
  };
3481
- module.exports = Chalkboard;
4507
+ if(typeof window === "undefined") {
4508
+ module.exports = Chalkboard;
4509
+ } else {
4510
+ window.Chalkboard = Chalkboard;
4511
+ }