@zushah/chalkboard 1.5.0 → 1.6.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.6.0 released 12/25/2023
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.6.0 released 12/25/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\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.plot.CONTEXT).canvas.width / 2;
18
+ y = y || Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2;
19
19
  s = s || 1;
20
- context = context || ctx;
20
+ context = context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT);
21
21
  context.save();
22
22
  context.translate(x, y);
23
23
  context.scale(s, s);
@@ -52,9 +52,45 @@ var Chalkboard = {
52
52
  },
53
53
  numb: {
54
54
  random: function(inf, sup) {
55
- inf = inf || 0;
56
- sup = sup || 1;
57
- return inf + Math.random() * (sup - inf);
55
+ if(inf === undefined) {
56
+ inf = 0;
57
+ }
58
+ if(sup === undefined) {
59
+ sup = 1;
60
+ }
61
+ return inf + (sup - inf) * Math.random();
62
+ },
63
+ exponential: function(l) {
64
+ if(l === undefined) {
65
+ l = 1;
66
+ }
67
+ return l <= 0 ? 0 : -Math.log(Math.random()) / l;
68
+ },
69
+ Gaussian: function(height, mean, deviation) {
70
+ var u1 = Math.random(), u2 = Math.random();
71
+ var random = Chalkboard.real.sqrt(-2 * Chalkboard.real.ln(u1)) * Chalkboard.trig.cos(Chalkboard.PI(2) * u2);
72
+ return random * height * Chalkboard.real.sqrt(deviation) + mean;
73
+ },
74
+ Bernoullian: function(p) {
75
+ if(p === undefined) {
76
+ p = 0.5;
77
+ }
78
+ return Math.random() < p ? 1 : 0;
79
+ },
80
+ Poissonian: function(l) {
81
+ if(l === undefined) {
82
+ l = 1;
83
+ }
84
+ if(l > 0) {
85
+ var L = Chalkboard.E(-l);
86
+ var p = 1, k = 0;
87
+ for(; p > L; ++k) {
88
+ p *= Math.random();
89
+ }
90
+ return k - 1;
91
+ } else {
92
+ return 0;
93
+ }
58
94
  },
59
95
  factorial: function(num) {
60
96
  if(num >= 0) {
@@ -241,18 +277,39 @@ var Chalkboard = {
241
277
  }
242
278
  return sequence[num];
243
279
  },
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;
280
+ Goldbach: function(num) {
281
+ if(num % 2 === 0) {
282
+ if(num !== 4) {
283
+ var a = num / 2, b = num / 2;
284
+ if(a % 2 === 0) {
285
+ a--;
286
+ b++;
287
+ }
288
+ while(a >= 3) {
289
+ if(Chalkboard.numb.isPrime(a) && Chalkboard.numb.isPrime(b)) {
290
+ return [a, b];
291
+ }
292
+ a -= 2;
293
+ b += 2;
294
+ }
295
+ return undefined;
296
+ } else {
297
+ return [2, 2];
298
+ }
299
+ } else {
300
+ return undefined;
301
+ }
302
+ },
303
+ Euler: function(num) {
304
+ if(num > 0) {
305
+ var factors = Chalkboard.numb.factors(num);
306
+ for(var i = 0; i < factors.length; i++) {
307
+ num *= (factors[i] - 1) / factors[i];
252
308
  }
309
+ return num;
310
+ } else {
311
+ return undefined;
253
312
  }
254
- var z = u * Chalkboard.real.sqrt(-2 * Chalkboard.real.ln(s) / s);
255
- return z * height * deviation + mean;
256
313
  }
257
314
  },
258
315
  real: {
@@ -260,7 +317,9 @@ var Chalkboard = {
260
317
  type = type || "expl";
261
318
  if(type === "expl") {
262
319
  return {definition: definition, type: type};
263
- } else if(type === "pola") {
320
+ } else if(type === "inve") {
321
+ return {definition: definition, type: type};
322
+ } else if(type === "pola") {
264
323
  return {definition: definition, type: type};
265
324
  } else if(type === "curv") {
266
325
  return definition.length === 2 ? {definition: [definition[0], definition[1]], type: type} : {definition: [definition[0], definition[1], definition[2]], type: type};
@@ -269,7 +328,7 @@ var Chalkboard = {
269
328
  } else if(type === "mult") {
270
329
  return {definition: definition, type: type};
271
330
  } else {
272
- return "TypeError: Parameter \"type\" must be either \"expl\", \"pola\", \"curv\", \"surf\", or \"mult\".";
331
+ return "TypeError: Parameter \"type\" must be either \"expl\", \"inve\", \"pola\", \"curv\", \"surf\", or \"mult\".";
273
332
  }
274
333
  },
275
334
  parse: function(str, init) {
@@ -280,6 +339,9 @@ var Chalkboard = {
280
339
  if(func.type === "expl") {
281
340
  var f = Chalkboard.real.parse("x => " + func.definition);
282
341
  return f(val);
342
+ } else if(func.type === "inve") {
343
+ var f = Chalkboard.real.parse("y => " + func.definition);
344
+ return f(val);
283
345
  } else if(func.type === "pola") {
284
346
  var r = Chalkboard.real.parse("O => " + func.definition);
285
347
  return r(val);
@@ -315,7 +377,11 @@ var Chalkboard = {
315
377
  }
316
378
  },
317
379
  pow: function(base, num) {
318
- return Math.exp(num * Math.log(base));
380
+ if(base === 0 && num === 0) {
381
+ return 1;
382
+ } else {
383
+ return Math.exp(num * Math.log(base));
384
+ }
319
385
  },
320
386
  log: function(base, num) {
321
387
  return Chalkboard.real.ln(num) / Chalkboard.real.ln(base);
@@ -333,7 +399,8 @@ var Chalkboard = {
333
399
  return undefined;
334
400
  }
335
401
  },
336
- nrt: function(num, index) {
402
+ root: function(num, index) {
403
+ index = index || 3;
337
404
  return Math.exp(Math.log(num) / index);
338
405
  },
339
406
  tetration: function(base, num) {
@@ -534,6 +601,18 @@ var Chalkboard = {
534
601
  sqrt: function(comp) {
535
602
  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
603
  },
604
+ root: function(comp, index) {
605
+ index = index || 3;
606
+ if(Number.isInteger(index) && index > 0) {
607
+ var result = [];
608
+ var r = Chalkboard.comp.mag(comp);
609
+ var t = Chalkboard.comp.arg(comp);
610
+ for(var i = 0; i < index; i++) {
611
+ 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)));
612
+ }
613
+ return result;
614
+ }
615
+ },
537
616
  rotate: function(comp, rad) {
538
617
  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
618
  },
@@ -543,17 +622,6 @@ var Chalkboard = {
543
622
  conjugate: function(comp) {
544
623
  return Chalkboard.comp.new(comp.a, -comp.b);
545
624
  },
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
625
  dist: function(comp_1, comp_2) {
558
626
  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
627
  },
@@ -703,136 +771,158 @@ var Chalkboard = {
703
771
  }
704
772
  },
705
773
  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;
774
+ CONTEXT: "ctx",
775
+ xyplane: function(config) {
776
+ config = config || {};
777
+ config = {
778
+ size: config.size || 1,
779
+ strokeStyle: config.strokeStyle || "black",
780
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
781
+ lineWidth: config.lineWidth || 2,
782
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
783
+ };
784
+ config.size /= 100;
785
+ var cw = Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width;
786
+ config.context.save();
787
+ config.context.translate(config.origin[0], config.origin[1]);
788
+ config.context.strokeStyle = config.strokeStyle;
789
+ config.context.lineWidth = config.lineWidth / 4;
790
+ config.context.beginPath();
791
+ for(var i = Math.floor(-config.origin[0] / config.size); i <= (cw - config.origin[0]) / config.size; i++) {
792
+ config.context.moveTo(i / config.size, -config.origin[1]);
793
+ config.context.lineTo(i / config.size, cw - config.origin[1]);
794
+ }
795
+ config.context.stroke();
796
+ config.context.beginPath();
797
+ for(var i = Math.floor(-config.origin[1] / config.size); i <= (cw - config.origin[1]) / config.size; i++) {
798
+ config.context.moveTo(-config.origin[0], i / config.size);
799
+ config.context.lineTo(cw - config.origin[0], i / config.size);
800
+ }
801
+ config.context.stroke();
802
+ config.context.lineWidth = config.lineWidth;
803
+ config.context.beginPath();
804
+ config.context.moveTo(-config.origin[0], 0);
805
+ config.context.lineTo(cw - config.origin[0], 0);
806
+ config.context.stroke();
807
+ config.context.beginPath();
808
+ config.context.moveTo(0, -config.origin[1]);
809
+ config.context.lineTo(0, cw - config.origin[1]);
810
+ config.context.stroke();
811
+ config.context.restore();
812
+ },
813
+ rOplane: function(config) {
814
+ config = config || {};
815
+ config = {
816
+ size: config.size || 1,
817
+ strokeStyle: config.strokeStyle || "black",
818
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
819
+ lineWidth: config.lineWidth || 2,
820
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
821
+ };
822
+ config.size /= 100;
823
+ var cw = Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width;
824
+ config.context.save();
825
+ config.context.translate(config.origin[0], config.origin[1]);
826
+ config.context.strokeStyle = config.strokeStyle;
827
+ config.context.lineWidth = config.lineWidth / 4;
828
+ config.context.beginPath();
829
+ for(var i = 0; i <= config.size * cw / 2; i++) {
830
+ config.context.ellipse(0, 0, i / config.size, i / config.size, 0, 0, Chalkboard.PI(2));
831
+ }
832
+ config.context.stroke();
833
+ config.context.lineWidth = config.lineWidth;
834
+ config.context.beginPath();
835
+ config.context.moveTo(-config.origin[0], 0);
836
+ config.context.lineTo(cw - config.origin[0], 0);
837
+ config.context.stroke()
838
+ config.context.beginPath();
839
+ config.context.moveTo(0, -config.origin[1]);
840
+ config.context.lineTo(0, cw - config.origin[1]);
841
+ config.context.stroke();
842
+ config.context.restore();
843
+ },
844
+ function: function(func, config) {
845
+ config = config || {};
846
+ config = {
847
+ size: config.size || 1,
848
+ strokeStyle: config.strokeStyle || "black",
849
+ domain: config.domain || (func.type === "comp" ? [[-10, 10], [-10, 10]] : [-10, 10]),
850
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
851
+ lineWidth: config.lineWidth || 2,
852
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
853
+ };
854
+ config.size /= 100;
775
855
  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();
856
+ config.context.save();
857
+ config.context.translate(config.origin[0], config.origin[1]);
858
+ config.context.lineWidth = config.lineWidth;
859
+ config.context.strokeStyle = config.strokeStyle;
860
+ config.context.beginPath();
781
861
  if(func.type === "expl") {
782
862
  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);
863
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i++) {
864
+ config.context.lineTo(i, -f(i * config.size) / config.size);
785
865
  data.push([i, f(i)]);
786
866
  }
867
+ } else if(func.type === "inve") {
868
+ var f = Chalkboard.real.parse("y => " + func.definition);
869
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i++) {
870
+ config.context.lineTo(f(i * config.size) / config.size, -i);
871
+ data.push([f(i), i]);
872
+ }
787
873
  } else if(func.type === "pola") {
788
874
  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));
875
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i++) {
876
+ 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
877
  data.push([i, r(i)]);
792
878
  }
793
879
  } else if(func.type === "curv") {
794
880
  var x = Chalkboard.real.parse("t => " + func.definition[0]),
795
881
  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);
882
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i++) {
883
+ config.context.lineTo(x(i * config.size) / config.size, -y(i * config.size) / config.size);
798
884
  data.push([x(i), y(i)]);
799
885
  }
800
886
  } else if(func.type === "comp") {
801
887
  var u = Chalkboard.comp.parse("(a, b) => " + func.definition[0]),
802
888
  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);
889
+ for(var i = config.domain[0][0] / config.size; i <= config.domain[0][1] / config.size; i += 5) {
890
+ for(var j = config.domain[1][0] / config.size; j <= config.domain[1][1] / config.size; j += 5) {
891
+ var z = Chalkboard.comp.new(u(i * config.size, j * config.size) / config.size, v(i * config.size, j * config.size) / config.size);
806
892
  if(z.a === 0 && z.b === 0) {
807
- context.fillStyle = "rgb(0, 0, 0)";
893
+ config.context.fillStyle = "rgb(0, 0, 0)";
808
894
  } else if(z.a === Infinity && z.b === Infinity) {
809
- context.fillStyle = "rgb(255, 255, 255)";
895
+ config.context.fillStyle = "rgb(255, 255, 255)";
810
896
  } 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 + "%)";
897
+ 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
898
  }
813
- context.fillRect(i, j, 5, 5);
899
+ config.context.fillRect(i, j, 5, 5);
814
900
  data.push([u(i, j), v(i, j)]);
815
901
  }
816
902
  }
817
903
  } else {
818
- return "TypeError: Property \"type\" of parameter \"func\" must be either \"expl\", \"pola\", \"curv\", or \"comp\".";
904
+ return "TypeError: Property \"type\" of parameter \"func\" must be either \"expl\", \"inve\", \"pola\", \"curv\", or \"comp\".";
819
905
  }
820
- context.stroke();
821
- context.restore();
906
+ config.context.stroke();
907
+ config.context.restore();
822
908
  return data;
823
909
  },
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() + ")";
910
+ barplot: function(arr, bins, config) {
911
+ config = config || {};
912
+ config = {
913
+ size: config.size || 1,
914
+ strokeStyle: config.strokeStyle || "black",
915
+ fillStyle: config.fillStyle || "white",
916
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
917
+ lineWidth: config.lineWidth || 2,
918
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
919
+ };
920
+ config.size /= 100;
921
+ config.context.save();
922
+ config.context.translate(config.origin[0], config.origin[1]);
923
+ config.context.lineWidth = config.lineWidth;
924
+ config.context.strokeStyle = config.strokeStyle;
925
+ config.context.fillStyle = config.fillStyle;
836
926
  var bars = [];
837
927
  for(var i = 0; i < bins.length; i++) {
838
928
  if(i === 0) {
@@ -847,26 +937,29 @@ var Chalkboard = {
847
937
  for(var i = 0; i < bars.length; i++) {
848
938
  counts.push(bars[i].length);
849
939
  }
850
- var x = 0, width = counts.length / (2 * scl);
940
+ var x = 0, width = counts.length / (2 * config.size);
851
941
  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;
942
+ config.context.fillRect(x - width, 0, 1 / config.size, -counts[i] / config.size);
943
+ config.context.strokeRect(x - width, 0, 1 / config.size, -counts[i] / config.size);
944
+ x += 1 / config.size;
855
945
  }
856
- context.restore();
946
+ config.context.restore();
857
947
  return bars;
858
948
  },
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() + ")";
949
+ lineplot: function(arr, bins, config) {
950
+ config = config || {};
951
+ config = {
952
+ size: config.size || 1,
953
+ strokeStyle: config.strokeStyle || "black",
954
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
955
+ lineWidth: config.lineWidth || 2,
956
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
957
+ };
958
+ config.size /= 100;
959
+ config.context.save();
960
+ config.context.translate(config.origin[0], config.origin[1]);
961
+ config.context.lineWidth = config.lineWidth;
962
+ config.context.strokeStyle = config.strokeStyle;
870
963
  var verts = [];
871
964
  for(var i = 0; i < bins.length; i++) {
872
965
  if(i === 0) {
@@ -881,353 +974,414 @@ var Chalkboard = {
881
974
  for(var i = 0; i < verts.length; i++) {
882
975
  counts.push(verts[i].length);
883
976
  }
884
- context.beginPath();
977
+ config.context.beginPath();
885
978
  for(var i = 0; i < counts.length; i++) {
886
- context.lineTo(i / scl, -counts[i] / scl);
979
+ config.context.lineTo(i / config.size, -counts[i] / config.size);
887
980
  }
888
- context.stroke();
889
- context.restore();
981
+ config.context.stroke();
982
+ config.context.restore();
890
983
  return verts;
891
984
  },
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;
985
+ scatterplot: function(arr1, arr2, config) {
986
+ config = config || {};
987
+ config = {
988
+ size: config.size || 1,
989
+ fillStyle: config.fillStyle || "black",
990
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
991
+ lineWidth: config.lineWidth || 5,
992
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
993
+ };
994
+ config.size /= 100;
899
995
  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() + ")";
996
+ config.context.save();
997
+ config.context.translate(config.origin[0], config.origin[1]);
998
+ config.context.fillStyle = config.fillStyle;
903
999
  if(arr1.length === arr2.length) {
904
1000
  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();
1001
+ config.context.beginPath();
1002
+ 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));
1003
+ config.context.fill();
908
1004
  data.push([arr1[i], arr2[i]]);
909
1005
  }
910
1006
  }
911
- context.restore();
1007
+ config.context.restore();
912
1008
  return data;
913
1009
  },
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();
1010
+ comp: function(comp, config) {
1011
+ config = config || {};
1012
+ config = {
1013
+ size: config.size || 1,
1014
+ fillStyle: config.fillStyle || "black",
1015
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
1016
+ lineWidth: config.lineWidth || 5,
1017
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
1018
+ };
1019
+ config.size /= 100;
1020
+ config.context.fillStyle = config.fillStyle;
1021
+ config.context.save();
1022
+ config.context.translate(config.origin[0], config.origin[1]);
1023
+ config.context.beginPath();
1024
+ config.context.ellipse(comp.a / config.size, -comp.b / config.size, config.lineWidth, config.lineWidth, 0, 0, Chalkboard.PI(2));
1025
+ config.context.fill();
1026
+ config.context.restore();
928
1027
  return [[comp.a], [comp.b]];
929
1028
  },
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();
1029
+ vec2: function(vec2, config) {
1030
+ config = config || {};
1031
+ config = {
1032
+ size: config.size || 1,
1033
+ strokeStyle: config.strokeStyle || "black",
1034
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
1035
+ lineWidth: config.lineWidth || 5,
1036
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
1037
+ };
1038
+ config.size /= 100;
1039
+ config.context.strokeStyle = config.strokeStyle;
1040
+ config.context.lineWidth = config.lineWidth;
1041
+ config.context.save();
1042
+ config.context.translate(config.origin[0], config.origin[1]);
1043
+ config.context.beginPath();
1044
+ config.context.moveTo(0, 0);
1045
+ config.context.lineTo(vec2.x / config.size, -vec2.y / config.size);
1046
+ config.context.stroke();
1047
+ config.context.restore();
946
1048
  return [[vec2.x], [vec2.y]];
947
1049
  },
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;
1050
+ field: function(vec2field, config) {
1051
+ config = config || {};
1052
+ config = {
1053
+ size: config.size || 1,
1054
+ strokeStyle: config.strokeStyle || "black",
1055
+ domain: config.domain || [[-10, 10], [-10, 10]],
1056
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
1057
+ lineWidth: config.lineWidth || 5,
1058
+ res: config.res || 25,
1059
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
1060
+ };
1061
+ config.size /= 100;
957
1062
  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) {
1063
+ config.context.strokeStyle = config.strokeStyle;
1064
+ config.context.lineWidth = config.lineWidth;
1065
+ config.context.save();
1066
+ config.context.translate(config.origin[0], config.origin[1]);
1067
+ for(var i = config.domain[0][0] / config.size; i <= config.domain[0][1] / config.size; i += config.res) {
1068
+ for(var j = config.domain[1][0] / config.size; j <= config.domain[1][1] / config.size; j += config.res) {
964
1069
  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();
1070
+ config.context.beginPath();
1071
+ config.context.moveTo(i, j);
1072
+ config.context.lineTo(i + v.x, j + v.y);
1073
+ config.context.stroke();
969
1074
  data.push([i + v.x, j + v.y]);
970
1075
  }
971
1076
  }
972
- context.restore();
1077
+ config.context.restore();
973
1078
  return data;
974
1079
  },
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();
1080
+ vec3: function(vec3, config) {
1081
+ config = config || {};
1082
+ config = {
1083
+ size: config.size || 1,
1084
+ strokeStyle: config.strokeStyle || "black",
1085
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
1086
+ lineWidth: config.lineWidth || 5,
1087
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
1088
+ };
1089
+ config.size /= 100;
1090
+ config.context.strokeStyle = config.strokeStyle;
1091
+ config.context.lineWidth = config.lineWidth;
1092
+ config.context.save();
1093
+ config.context.translate(config.origin[0], config.origin[1]);
1094
+ config.context.beginPath();
1095
+ config.context.moveTo(0, 0);
1096
+ config.context.lineTo((vec3.x / config.size) / (vec3.z * 0.25 + 1), (-vec3.y / config.size) / (vec3.z * 0.25 + 1));
1097
+ config.context.stroke();
1098
+ config.context.restore();
991
1099
  return [[vec3.x], [vec3.y], [vec3.z]];
992
1100
  },
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;
1101
+ matr: function(matr, config) {
1102
+ config = config || {};
1103
+ config = {
1104
+ size: config.size || 1,
1105
+ strokeStyle: config.strokeStyle || "black",
1106
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
1107
+ lineWidth: config.lineWidth || 2,
1108
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
1109
+ };
1110
+ config.size /= 100;
999
1111
  var plotposx = Chalkboard.vec2.new(matr[0][0], matr[1][0]);
1000
1112
  var plotnegx = Chalkboard.vec2.new(-matr[0][0], -matr[1][0]);
1001
1113
  var plotposy = Chalkboard.vec2.new(matr[0][1], matr[1][1]);
1002
1114
  var plotnegy = Chalkboard.vec2.new(-matr[0][1], -matr[1][1]);
1003
1115
  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);
1116
+ Chalkboard.vec2.plot(plotposx, {origin: [config.origin[0], config.origin[1] + (i / config.size) * matr[1][1]], lineWidth: config.lineWidth / 4});
1117
+ Chalkboard.vec2.plot(plotnegx, {origin: [config.origin[0], config.origin[1] + (i / config.size) * matr[1][1]], lineWidth: config.lineWidth / 4});
1118
+ Chalkboard.vec2.plot(plotposy, {origin: [config.origin[0] + (i / config.size) * matr[0][0], config.origin[1]], lineWidth: config.lineWidth / 4});
1119
+ Chalkboard.vec2.plot(plotnegy, {origin: [config.origin[0] + (i / config.size) * matr[0][0], config.origin[1]], lineWidth: config.lineWidth / 4});
1008
1120
  }
1009
1121
  var plotposaxisx = Chalkboard.vec2.new(matr[0][0], matr[1][0]);
1010
1122
  var plotnegaxisx = Chalkboard.vec2.new(-matr[0][0], -matr[1][0]);
1011
1123
  var plotposaxisy = Chalkboard.vec2.new(matr[0][1], matr[1][1]);
1012
1124
  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);
1125
+ Chalkboard.vec2.plot(plotposaxisx, config);
1126
+ Chalkboard.vec2.plot(plotnegaxisx, config);
1127
+ Chalkboard.vec2.plot(plotposaxisy, config);
1128
+ Chalkboard.vec2.plot(plotnegaxisy, config);
1017
1129
  return matr;
1018
1130
  },
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;
1131
+ dfdx: function(func, config) {
1132
+ config = config || {};
1133
+ config = {
1134
+ size: config.size || 1,
1135
+ strokeStyle: config.strokeStyle || "black",
1136
+ domain: config.domain || [-10, 10],
1137
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
1138
+ lineWidth: config.lineWidth || 2,
1139
+ res: config.res || 25,
1140
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
1141
+ };
1142
+ config.size /= 100;
1028
1143
  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)]);
1144
+ config.context.save();
1145
+ config.context.translate(config.origin[0], config.origin[1]);
1146
+ config.context.lineWidth = config.lineWidth;
1147
+ config.context.strokeStyle = config.strokeStyle;
1148
+ config.context.beginPath();
1149
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i += config.res) {
1150
+ if(func.type === "expl") {
1151
+ config.context.lineTo(i, -Chalkboard.calc.dfdx(func, i * config.size) / config.size);
1152
+ data.push([i, Chalkboard.calc.dfdx(func, i)]);
1153
+ } else if(func.type === "inve") {
1154
+ config.context.lineTo(Chalkboard.calc.dfdx(func, i * config.size) / config.size, -i);
1155
+ data.push([Chalkboard.calc.dfdx(func, i), i]);
1156
+ }
1037
1157
  }
1038
- context.stroke();
1039
- context.restore();
1158
+ config.context.stroke();
1159
+ config.context.restore();
1040
1160
  return data;
1041
1161
  },
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;
1162
+ d2fdx2: function(func, config) {
1163
+ config = config || {};
1164
+ config = {
1165
+ size: config.size || 1,
1166
+ strokeStyle: config.strokeStyle || "black",
1167
+ domain: config.domain || [-10, 10],
1168
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
1169
+ lineWidth: config.lineWidth || 2,
1170
+ res: config.res || 25,
1171
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
1172
+ };
1173
+ config.size /= 100;
1051
1174
  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)]);
1175
+ config.context.save();
1176
+ config.context.translate(config.origin[0], config.origin[1]);
1177
+ config.context.lineWidth = config.lineWidth;
1178
+ config.context.strokeStyle = config.strokeStyle;
1179
+ config.context.beginPath();
1180
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i += config.res) {
1181
+ if(func.type === "expl") {
1182
+ config.context.lineTo(i, -Chalkboard.calc.d2fdx2(func, i * config.size) / config.size);
1183
+ data.push([i, Chalkboard.calc.d2fdx2(func, i)]);
1184
+ } else if(func.type === "inve") {
1185
+ config.context.lineTo(Chalkboard.calc.d2fdx2(func, i * config.size) / config.size, -i);
1186
+ data.push([Chalkboard.calc.d2fdx2(func, i), i]);
1187
+ }
1060
1188
  }
1061
- context.stroke();
1062
- context.restore();
1189
+ config.context.stroke();
1190
+ config.context.restore();
1063
1191
  return data;
1064
1192
  },
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;
1193
+ fxdx: function(func, config) {
1194
+ config = config || {};
1195
+ config = {
1196
+ size: config.size || 1,
1197
+ strokeStyle: config.strokeStyle || "black",
1198
+ domain: config.domain || [-10, 10],
1199
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
1200
+ lineWidth: config.lineWidth || 2,
1201
+ res: config.res || 25,
1202
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
1203
+ };
1204
+ config.size /= 100;
1074
1205
  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)]);
1206
+ config.context.save();
1207
+ config.context.translate(config.origin[0], config.origin[1]);
1208
+ config.context.lineWidth = config.lineWidth;
1209
+ config.context.strokeStyle = config.strokeStyle;
1210
+ config.context.beginPath();
1211
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i += config.res) {
1212
+ if(func.type === "expl") {
1213
+ config.context.lineTo(i, -Chalkboard.calc.fxdx(func, 0, i * config.size) / config.size);
1214
+ data.push([i, Chalkboard.calc.fxdx(func, 0, i)]);
1215
+ } else if(func.type === "inve") {
1216
+ config.context.lineTo(Chalkboard.calc.fxdx(func, 0, i * config.size) / config.size, -i);
1217
+ data.push([Chalkboard.calc.fxdx(func, 0, i), i]);
1218
+ }
1083
1219
  }
1084
- context.stroke();
1085
- context.restore();
1220
+ config.context.stroke();
1221
+ config.context.restore();
1086
1222
  return data;
1087
1223
  },
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;
1224
+ convolution: function(func_1, func_2, config) {
1225
+ config = config || {};
1226
+ config = {
1227
+ size: config.size || 1,
1228
+ strokeStyle: config.strokeStyle || "black",
1229
+ domain: config.domain || [-10, 10],
1230
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
1231
+ lineWidth: config.lineWidth || 2,
1232
+ res: config.res || 25,
1233
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
1234
+ };
1235
+ config.size /= 100;
1097
1236
  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);
1237
+ config.context.save();
1238
+ config.context.translate(config.origin[0], config.origin[1]);
1239
+ config.context.lineWidth = config.lineWidth;
1240
+ config.context.strokeStyle = config.strokeStyle;
1241
+ config.context.beginPath();
1242
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i += config.res) {
1243
+ config.context.lineTo(i, -Chalkboard.calc.convolution(func_1, func_2, i * config.size) / config.size);
1105
1244
  data.push([i, Chalkboard.calc.convolution(func_1, func_2, i)]);
1106
1245
  }
1107
- context.stroke();
1108
- context.restore();
1246
+ config.context.stroke();
1247
+ config.context.restore();
1109
1248
  return data;
1110
1249
  },
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;
1250
+ correlation: function(func_1, func_2, config) {
1251
+ config = config || {};
1252
+ config = {
1253
+ size: config.size || 1,
1254
+ strokeStyle: config.strokeStyle || "black",
1255
+ domain: config.domain || [-10, 10],
1256
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
1257
+ lineWidth: config.lineWidth || 2,
1258
+ res: config.res || 25,
1259
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
1260
+ };
1261
+ config.size /= 100;
1120
1262
  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);
1263
+ config.context.save();
1264
+ config.context.translate(config.origin[0], config.origin[1]);
1265
+ config.context.lineWidth = config.lineWidth;
1266
+ config.context.strokeStyle = config.strokeStyle;
1267
+ config.context.beginPath();
1268
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i += config.res) {
1269
+ config.context.lineTo(i, -Chalkboard.calc.correlation(func_1, func_2, i * config.size) / config.size);
1128
1270
  data.push([i, Chalkboard.calc.correlation(func_1, func_2, i)]);
1129
1271
  }
1130
- context.stroke();
1131
- context.restore();
1272
+ config.context.stroke();
1273
+ config.context.restore();
1132
1274
  return data;
1133
1275
  },
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;
1276
+ autocorrelation: function(func, config) {
1277
+ config = config || {};
1278
+ config = {
1279
+ size: config.size || 1,
1280
+ strokeStyle: config.strokeStyle || "black",
1281
+ domain: config.domain || [-10, 10],
1282
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
1283
+ lineWidth: config.lineWidth || 2,
1284
+ res: config.res || 25,
1285
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
1286
+ };
1287
+ config.size /= 100;
1143
1288
  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);
1289
+ config.context.save();
1290
+ config.context.translate(config.origin[0], config.origin[1]);
1291
+ config.context.lineWidth = config.lineWidth;
1292
+ config.context.strokeStyle = config.strokeStyle;
1293
+ config.context.beginPath();
1294
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i += config.res) {
1295
+ config.context.lineTo(i, -Chalkboard.calc.autocorrelation(func, i * config.size) / config.size);
1151
1296
  data.push([i, Chalkboard.calc.autocorrelation(func, i)]);
1152
1297
  }
1153
- context.stroke();
1154
- context.restore();
1298
+ config.context.stroke();
1299
+ config.context.restore();
1155
1300
  return data;
1156
1301
  },
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;
1302
+ Taylor: function(func, n, a, config) {
1303
+ config = config || {};
1304
+ config = {
1305
+ size: config.size || 1,
1306
+ strokeStyle: config.strokeStyle || "black",
1307
+ domain: config.domain || [-10, 10],
1308
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
1309
+ lineWidth: config.lineWidth || 2,
1310
+ res: config.res || 25,
1311
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
1312
+ };
1313
+ config.size /= 100;
1166
1314
  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);
1315
+ config.context.save();
1316
+ config.context.translate(config.origin[0], config.origin[1]);
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.Taylor(func, i * config.size, n, a) / config.size);
1174
1322
  data.push([i, Chalkboard.calc.Taylor(func, i, n, a)]);
1175
1323
  }
1176
- context.stroke();
1177
- context.restore();
1324
+ config.context.stroke();
1325
+ config.context.restore();
1178
1326
  return data;
1179
1327
  },
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;
1328
+ Laplace: function(func, config) {
1329
+ config = config || {};
1330
+ config = {
1331
+ size: config.size || 1,
1332
+ strokeStyle: config.strokeStyle || "black",
1333
+ domain: config.domain || [-10, 10],
1334
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
1335
+ lineWidth: config.lineWidth || 2,
1336
+ res: config.res || 25,
1337
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
1338
+ };
1339
+ config.size /= 100;
1189
1340
  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);
1341
+ config.context.save();
1342
+ config.context.translate(config.origin[0], config.origin[1]);
1343
+ config.context.lineWidth = config.lineWidth;
1344
+ config.context.strokeStyle = config.strokeStyle;
1345
+ config.context.beginPath();
1346
+ if( config.domain[0] >= 0) {
1347
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i += config.res) {
1348
+ config.context.lineTo(i, -Chalkboard.calc.Laplace(func, i * config.size) / config.size);
1198
1349
  data.push([i, Chalkboard.calc.Laplace(func, i)]);
1199
1350
  }
1200
1351
  } else {
1201
- for(var i = 0; i <= domain[1] / scl; i += res) {
1202
- context.lineTo(i, -Chalkboard.calc.Laplace(func, i * scl) / scl);
1352
+ for(var i = 0; i <= config.domain[1] / config.size; i += config.res) {
1353
+ config.context.lineTo(i, -Chalkboard.calc.Laplace(func, i * config.size) / config.size);
1203
1354
  data.push([i, Chalkboard.calc.Laplace(func, i)]);
1204
1355
  }
1205
1356
  }
1206
- context.stroke();
1207
- context.restore();
1357
+ config.context.stroke();
1358
+ config.context.restore();
1208
1359
  return data;
1209
1360
  },
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;
1361
+ Fourier: function(func, config) {
1362
+ config = config || {};
1363
+ config = {
1364
+ size: config.size || 1,
1365
+ strokeStyle: config.strokeStyle || "black",
1366
+ domain: config.domain || [-10, 10],
1367
+ origin: config.origin || [Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.width / 2, Chalkboard.real.parse(Chalkboard.plot.CONTEXT).canvas.height / 2],
1368
+ lineWidth: config.lineWidth || 2,
1369
+ res: config.res || 25,
1370
+ context: config.context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT)
1371
+ };
1372
+ config.size /= 100;
1219
1373
  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);
1374
+ config.context.save();
1375
+ config.context.translate(config.origin[0], config.origin[1]);
1376
+ config.context.lineWidth = config.lineWidth;
1377
+ config.context.strokeStyle = config.strokeStyle;
1378
+ config.context.beginPath();
1379
+ for(var i = config.domain[0] / config.size; i <= config.domain[1] / config.size; i += config.res) {
1380
+ config.context.lineTo(i, -Chalkboard.calc.Fourier(func, i * config.size) / config.size);
1227
1381
  data.push([i, Chalkboard.calc.Fourier(func, i)]);
1228
1382
  }
1229
- context.stroke();
1230
- context.restore();
1383
+ config.context.stroke();
1384
+ config.context.restore();
1231
1385
  return data;
1232
1386
  }
1233
1387
  },
@@ -1375,7 +1529,7 @@ var Chalkboard = {
1375
1529
  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
1530
  },
1377
1531
  line3D: function(x1, y1, z1, x2, y2, z2, context) {
1378
- context = context || ctx;
1532
+ context = context || Chalkboard.real.parse(Chalkboard.plot.CONTEXT);
1379
1533
  context.beginPath();
1380
1534
  context.moveTo(x1 / (z1 * 0.0025 + 1), y1 / (z1 * 0.0025 + 1));
1381
1535
  context.lineTo(x2 / (z2 * 0.0025 + 1), y2 / (z2 * 0.0025 + 1));
@@ -1559,6 +1713,16 @@ var Chalkboard = {
1559
1713
  }
1560
1714
  return result;
1561
1715
  },
1716
+ shuffle: function(arr) {
1717
+ var index, temp, rindex;
1718
+ for(index = arr.length - 1; index > 0; index--) {
1719
+ rindex = Math.floor(Chalkboard.numb.random(0, index + 1));
1720
+ temp = arr[index];
1721
+ arr[index] = arr[rindex];
1722
+ arr[rindex] = temp;
1723
+ }
1724
+ return arr;
1725
+ },
1562
1726
  norm: function(arr, type) {
1563
1727
  type = type || "L2";
1564
1728
  var result = 0;
@@ -1770,6 +1934,23 @@ var Chalkboard = {
1770
1934
  }
1771
1935
  return result;
1772
1936
  },
1937
+ subsets: function(arr) {
1938
+ var result = [[]];
1939
+ arr.sort();
1940
+ for(var i = 0; i < arr.length; i++) {
1941
+ if(i === 0 || arr[i] !== arr[i - 1]) {
1942
+ var curr = arr[i];
1943
+ var subsetsWithCurr = [];
1944
+ for(var j = 0; j < result.length; j++) {
1945
+ var subset = result[j].slice();
1946
+ subset.push(curr);
1947
+ subsetsWithCurr.push(subset);
1948
+ }
1949
+ result = result.concat(subsetsWithCurr);
1950
+ }
1951
+ }
1952
+ return result;
1953
+ },
1773
1954
  max: function(arr) {
1774
1955
  var max = arr[0];
1775
1956
  for(var i = 0; i < arr.length; i++) {
@@ -1803,7 +1984,7 @@ var Chalkboard = {
1803
1984
  for(var i = 0; i < arr.length; i++) {
1804
1985
  result *= arr[i];
1805
1986
  }
1806
- return Chalkboard.real.nrt(Math.abs(result), arr.length);
1987
+ return Chalkboard.real.root(Math.abs(result), arr.length);
1807
1988
  } else if(type === "harmonic") {
1808
1989
  for(var i = 0; i < arr.length; i++) {
1809
1990
  result += 1 / arr[i];
@@ -1968,6 +2149,85 @@ var Chalkboard = {
1968
2149
  Gaussian: function(height, mean, deviation) {
1969
2150
  return Chalkboard.real.function(height.toString() + " * Math.exp(-((x - " + mean.toString() + ") * (x - " + mean.toString() + ")) / (2 * " + deviation.toString() + " * " + deviation.toString() + "))");
1970
2151
  },
2152
+ regression: function(data, type, degree) {
2153
+ type = type || "linear";
2154
+ degree = degree || 2;
2155
+ if(type === "linear") {
2156
+ var x = 0, y = 0;
2157
+ var xx = 0, xy = 0;
2158
+ for(var i = 0; i < data.length; i++) {
2159
+ x += data[i][0];
2160
+ y += data[i][1];
2161
+ xx += data[i][0] * data[i][0];
2162
+ xy += data[i][0] * data[i][1];
2163
+ }
2164
+ var a = (data.length * xy - x * y) / (data.length * xx - x * x),
2165
+ b = (y / data.length) - (a * x) / data.length;
2166
+ return Chalkboard.real.function(a + " * x + " + b);
2167
+ } else if(type === "polynomial") {
2168
+ var A = Chalkboard.matr.new();
2169
+ for(var i = 0; i < data.length; i++) {
2170
+ A.push([]);
2171
+ for(var j = 0; j <= degree; j++) {
2172
+ A[i].push(Chalkboard.real.pow(data[i][0], j));
2173
+ }
2174
+ }
2175
+ var AT = Chalkboard.matr.transpose(A);
2176
+ var B = Chalkboard.matr.new();
2177
+ for(var i = 0; i < data.length; i++) {
2178
+ B.push([data[i][1]]);
2179
+ }
2180
+ var ATA = Chalkboard.matr.mul(AT, A);
2181
+ var ATAI = Chalkboard.matr.invert(ATA);
2182
+ var x = Chalkboard.matr.mul(Chalkboard.matr.mul(ATAI, AT), B);
2183
+ var coeff = [];
2184
+ for(var i = 0; i < x.length; i++) {
2185
+ coeff.push(x[i][0]);
2186
+ }
2187
+ var f = coeff[0].toString() + " + " + coeff[1].toString() + " * x";
2188
+ for(var i = 2; i <= degree; i++) {
2189
+ f += " + " + coeff[i].toString() + " * Math.pow(x, " + i + ")";
2190
+ }
2191
+ return Chalkboard.real.function(f);
2192
+ } else if(type === "power") {
2193
+ var arr = [0, 0, 0, 0];
2194
+ for(var i = 0; i < data.length; i++) {
2195
+ arr[0] += Chalkboard.real.ln(data[i][0]);
2196
+ arr[1] += data[i][1] * Chalkboard.real.ln(data[i][0]);
2197
+ arr[2] += data[i][1];
2198
+ arr[3] += Chalkboard.real.ln(data[i][0]) * Chalkboard.real.ln(data[i][0]);
2199
+ }
2200
+ 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),
2201
+ b = (data.length * arr[1] - arr[2] * arr[0]) / (data.length * arr[3] - arr[0] * arr[0]);
2202
+ return Chalkboard.real.function(a + " * Math.pow(x, " + b + ")");
2203
+ } else if(type === "exponential") {
2204
+ var arr = [0, 0, 0, 0, 0, 0];
2205
+ for(var i = 0; i < data.length; i++) {
2206
+ arr[0] += data[i][0];
2207
+ arr[1] += data[i][1];
2208
+ arr[2] += data[i][0] * data[i][0] * data[i][1];
2209
+ arr[3] += data[i][1] * Chalkboard.real.ln(data[i][1]);
2210
+ arr[4] += data[i][0] & data[i][1] * Chalkboard.real.ln(data[i][1]);
2211
+ arr[5] += data[i][0] * data[i][1];
2212
+ }
2213
+ var a = Chalkboard.E((arr[2] * arr[3] - arr[5] * arr[4]) / (arr[1] * arr[2] - arr[5] * arr[5])),
2214
+ b = (arr[1] * arr[4] - arr[5] * arr[3]) / (arr[1] * arr[2] - arr[5] * arr[5]);
2215
+ return Chalkboard.real.function(a + "* Math.exp(" + b + " * x)");
2216
+ } else if(type === "logarithmic") {
2217
+ var arr = [0, 0, 0, 0];
2218
+ for(var i = 0; i < data.length; i++) {
2219
+ arr[0] += Chalkboard.real.ln(data[i][0]);
2220
+ arr[1] += data[i][1] * Chalkboard.real.ln(data[i][0]);
2221
+ arr[2] += data[i][1];
2222
+ arr[3] += Chalkboard.real.ln(data[i][0]) * Chalkboard.real.ln(data[i][0]);
2223
+ }
2224
+ var a = (arr[2] - ((data.length * arr[1] - arr[2] * arr[0]) / (data.length * arr[3] - arr[0] * arr[0])) * arr[0]) / data.length,
2225
+ b = (data.length * arr[1] - arr[2] * arr[0]) / (data.length * arr[3] - arr[0] * arr[0]);
2226
+ return Chalkboard.real.function(a + " + " + b + " * Math.log(x)");
2227
+ } else {
2228
+ return "TypeError: Parameter \"type\" must be either \"linear\", \"polynomial\", \"power\", \"exponential\", or \"logarithmic\".";
2229
+ }
2230
+ },
1971
2231
  toVector: function(arr, type) {
1972
2232
  if(type === "vec2") {
1973
2233
  return Chalkboard.vec2.new(arr[0], arr[1]);
@@ -2446,7 +2706,8 @@ var Chalkboard = {
2446
2706
  },
2447
2707
  matr: {
2448
2708
  new: function(matrix) {
2449
- return Array.from(arguments);
2709
+ matrix = Array.from(arguments);
2710
+ return matrix;
2450
2711
  },
2451
2712
  rows: function(matr) {
2452
2713
  return matr.length;
@@ -2454,12 +2715,54 @@ var Chalkboard = {
2454
2715
  cols: function(matr) {
2455
2716
  return matr[0].length;
2456
2717
  },
2457
- empty: function(dimension) {
2458
- if(Number.isInteger(dimension) && dimension > 0) {
2718
+ push: function(matr, type, rowORcol, elements) {
2719
+ rowORcol -= 1;
2720
+ if(type === "row") {
2721
+ matr.splice(rowORcol, 0, elements);
2722
+ return matr;
2723
+ } else if(type === "col") {
2724
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2725
+ matr[i].splice(rowORcol, 0, elements[i]);
2726
+ }
2727
+ return matr;
2728
+ } else {
2729
+ return "TypeError: Parameter \"type\" must be either \"row\" or \"col\".";
2730
+ }
2731
+ },
2732
+ pull: function(matr, type, rowORcol) {
2733
+ rowORcol -= 1;
2734
+ if(type === "row") {
2735
+ matr.splice(rowORcol, 1);
2736
+ return matr;
2737
+ } else if(type === "col") {
2738
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2739
+ matr[i].splice(rowORcol, 1);
2740
+ }
2741
+ return matr;
2742
+ } else {
2743
+ return "TypeError: Parameter \"type\" must be either \"row\" or \"col\".";
2744
+ }
2745
+ },
2746
+ fill: function(element, rows, cols) {
2747
+ if(Number.isInteger(rows) && Number.isInteger(cols) && rows > 0 && cols > 0) {
2459
2748
  var result = Chalkboard.matr.new();
2460
- for(var i = 0; i < dimension; i++) {
2749
+ for(var i = 0; i < rows; i++) {
2461
2750
  result.push([]);
2462
- for(var j = 0; j < dimension; j++) {
2751
+ for(var j = 0; j < cols; j++) {
2752
+ result[i].push(element);
2753
+ }
2754
+ }
2755
+ return result;
2756
+ } else {
2757
+ return undefined;
2758
+ }
2759
+ },
2760
+ empty: function(rows, cols) {
2761
+ if(Number.isInteger(rows) && Number.isInteger(cols) && rows > 0 && cols > 0) {
2762
+ var result = Chalkboard.matr.new();
2763
+ for(var i = 0; i < rows; i++) {
2764
+ result.push([]);
2765
+ for(var j = 0; j < cols; j++) {
2463
2766
  result[i].push(null);
2464
2767
  }
2465
2768
  }
@@ -2468,11 +2771,11 @@ var Chalkboard = {
2468
2771
  return undefined;
2469
2772
  }
2470
2773
  },
2471
- identity: function(dimension) {
2472
- if(Number.isInteger(dimension) && dimension > 0) {
2774
+ identity: function(size) {
2775
+ if(Number.isInteger(size) && size > 0) {
2473
2776
  var result = Chalkboard.matr.new();
2474
- for(var i = 0; i < dimension; i++) {
2475
- result.push(Array(dimension).fill(0));
2777
+ for(var i = 0; i < size; i++) {
2778
+ result.push(Array(size).fill(0));
2476
2779
  result[i][i] = 1;
2477
2780
  }
2478
2781
  return result;
@@ -2480,14 +2783,12 @@ var Chalkboard = {
2480
2783
  return undefined;
2481
2784
  }
2482
2785
  },
2483
- random: function(dimension, inf, sup) {
2484
- if(Number.isInteger(dimension) && dimension > 0) {
2485
- inf = inf || 0;
2486
- sup = sup || 1;
2786
+ random: function(rows, cols, inf, sup) {
2787
+ if(Number.isInteger(rows) && Number.isInteger(cols) && rows > 0 && cols > 0) {
2487
2788
  var result = Chalkboard.matr.new();
2488
- for(var i = 0; i < dimension; i++) {
2789
+ for(var i = 0; i < rows; i++) {
2489
2790
  result.push([]);
2490
- for(var j = 0; j < dimension; j++) {
2791
+ for(var j = 0; j < cols; j++) {
2491
2792
  result[i].push(Chalkboard.numb.random(inf, sup));
2492
2793
  }
2493
2794
  }
@@ -2497,7 +2798,7 @@ var Chalkboard = {
2497
2798
  }
2498
2799
  },
2499
2800
  cofactor: function(matr, row, col) {
2500
- return matr.slice(0, row - 1).concat(matr.slice(row)).map(function (row) {
2801
+ return matr.slice(0, row - 1).concat(matr.slice(row)).map(function(row) {
2501
2802
  return row.slice(0, col - 1).concat(row.slice(col));
2502
2803
  });
2503
2804
  },
@@ -2534,15 +2835,15 @@ var Chalkboard = {
2534
2835
  }
2535
2836
  },
2536
2837
  rank: function(matr) {
2537
- return Chalkboard.matr.reduce(matr).filter(function (row) {
2538
- return row.some(function (element) {
2838
+ return Chalkboard.matr.reduce(matr).filter(function(row) {
2839
+ return row.some(function(element) {
2539
2840
  return element !== 0;
2540
2841
  });
2541
2842
  }).length;
2542
2843
  },
2543
2844
  rowspace: function(matr) {
2544
- return Chalkboard.matr.reduce(matr).filter(function (row) {
2545
- return row.some(function (element) {
2845
+ return Chalkboard.matr.reduce(matr).filter(function(row) {
2846
+ return row.some(function(element) {
2546
2847
  return element !== 0;
2547
2848
  });
2548
2849
  });
@@ -2551,15 +2852,15 @@ var Chalkboard = {
2551
2852
  return Chalkboard.matr.transpose(Chalkboard.matr.rowspace(Chalkboard.matr.transpose(matr)));
2552
2853
  },
2553
2854
  nullspace: function(matr) {
2554
- var augmented = matr.map(function (row) {
2855
+ var augmented = matr.map(function(row) {
2555
2856
  return row.slice().concat(Array(Chalkboard.matr.rows(matr)).fill(0));
2556
2857
  });
2557
2858
  var reduced = Chalkboard.matr.reduce(augmented);
2558
- return reduced.filter(function (row) {
2559
- return row.slice(0, Chalkboard.matr.rows(matr)).every(function (element) {
2859
+ return reduced.filter(function(row) {
2860
+ return row.slice(0, Chalkboard.matr.rows(matr)).every(function(element) {
2560
2861
  return element === 0;
2561
2862
  });
2562
- }).map(function (row) {
2863
+ }).map(function(row) {
2563
2864
  return row.slice(Chalkboard.matr.rows(matr));
2564
2865
  });
2565
2866
  },
@@ -2615,6 +2916,78 @@ var Chalkboard = {
2615
2916
  return undefined;
2616
2917
  }
2617
2918
  },
2919
+ LUdecomp: function(matr) {
2920
+ if(Chalkboard.matr.rows(matr) === Chalkboard.matr.cols(matr)) {
2921
+ var L = Chalkboard.matr.identity(Chalkboard.matr.rows(matr)),
2922
+ U = Chalkboard.matr.zero(Chalkboard.matr.empty(Chalkboard.matr.rows(matr)));
2923
+ for(var j = 0; j < Chalkboard.matr.cols(matr); j++) {
2924
+ for(var i = 0; i <= j; i++) {
2925
+ var sum = 0;
2926
+ for(var k = 0; k < i; k++) {
2927
+ sum += L[i][k] * U[k][j];
2928
+ }
2929
+ U[i][j] = matr[i][j] - sum;
2930
+ }
2931
+ for(var i = j + 1; i < Chalkboard.matr.rows(matr); i++) {
2932
+ var sum = 0;
2933
+ for(var k = 0; k < j; k++) {
2934
+ sum += L[i][k] * U[k][j];
2935
+ }
2936
+ L[i][j] = (matr[i][j] - sum) / U[j][j];
2937
+ }
2938
+ }
2939
+ return {L: L, U: U};
2940
+ } else {
2941
+ return undefined;
2942
+ }
2943
+ },
2944
+ QRdecomp: function(matr) {
2945
+ if(Chalkboard.matr.rows(matr) === Chalkboard.matr.cols(matr)) {
2946
+ var Q = Chalkboard.matr.zero(Chalkboard.matr.empty(Chalkboard.matr.rows(matr))),
2947
+ R = Chalkboard.matr.zero(Chalkboard.matr.empty(Chalkboard.matr.rows(matr)));
2948
+ var dot = function(v1, v2) {
2949
+ var result = 0;
2950
+ for(var i = 0; i < v1.length; i++) {
2951
+ result += v1[i] * v2[i];
2952
+ }
2953
+ return result;
2954
+ }
2955
+ var mag = function(v) {
2956
+ var result = 0;
2957
+ for(var i = 0; i < v.length; i++) {
2958
+ result += v[i] * v[i];
2959
+ }
2960
+ return Math.sqrt(result);
2961
+ }
2962
+ for(var j = 0; j < Chalkboard.matr.rows(matr); j++) {
2963
+ var v = matr.map(function(row) {
2964
+ return row[j];
2965
+ });
2966
+ for(var i = 0; i < j; i++) {
2967
+ var q = Q.map(function(row) {
2968
+ return row[i];
2969
+ });
2970
+ var coeff = dot(v, q) / (mag(q) * mag(q));
2971
+ v = v.map(function(e, index) {
2972
+ return e - coeff * q[index];
2973
+ });
2974
+ }
2975
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2976
+ Q[i][j] = v[i] / mag(v);
2977
+ }
2978
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2979
+ R[j][i] = i < j ? 0 : matr.map(function(row) {
2980
+ return row[i];
2981
+ }).reduce(function(a, v, index) {
2982
+ return a + v * Q[index][j];
2983
+ }, 0);
2984
+ }
2985
+ }
2986
+ return {Q: Q, R: R};
2987
+ } else {
2988
+ return undefined;
2989
+ }
2990
+ },
2618
2991
  zero: function(matr) {
2619
2992
  var result = Chalkboard.matr.new();
2620
2993
  for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
@@ -2931,6 +3304,9 @@ var Chalkboard = {
2931
3304
  if(func.type === "expl") {
2932
3305
  var f = Chalkboard.real.parse("x => " + func.definition);
2933
3306
  return (f(val + h) - f(val)) / h;
3307
+ } else if(func.type === "inve") {
3308
+ var f = Chalkboard.real.parse("y => " + func.definition);
3309
+ return (f(val + h) - f(val)) / h;
2934
3310
  } else if(func.type === "pola") {
2935
3311
  var r = Chalkboard.real.parse("O => " + func.definition);
2936
3312
  return (r(val + h) - r(val)) / h;
@@ -2946,7 +3322,7 @@ var Chalkboard = {
2946
3322
  return Chalkboard.vec3.new((x(val + h) - x(val)) / h, (y(val + h) - y(val)) / h, (z(val + h) - z(val)) / h);
2947
3323
  }
2948
3324
  } else {
2949
- return "TypeError: Parameter \"func\" must be of type \"expl\", \"pola\", or \"curv\".";
3325
+ return "TypeError: Parameter \"func\" must be of type \"expl\", \"inve\", \"pola\", or \"curv\".";
2950
3326
  }
2951
3327
  },
2952
3328
  d2fdx2: function(func, val) {
@@ -2954,6 +3330,9 @@ var Chalkboard = {
2954
3330
  if(func.type === "expl") {
2955
3331
  var f = Chalkboard.real.parse("x => " + func.definition);
2956
3332
  return (f(val + h) - 2 * f(val) + f(val - h)) / (h * h);
3333
+ } else if(func.type === "inve") {
3334
+ var f = Chalkboard.real.parse("y => " + func.definition);
3335
+ return (f(val + h) - 2 * f(val) + f(val - h)) / (h * h);
2957
3336
  } else if(func.type === "pola") {
2958
3337
  var r = Chalkboard.real.parse("O => " + func.definition);
2959
3338
  return (r(val + h) - 2 * r(val) + r(val - h)) / (h * h);
@@ -2969,7 +3348,7 @@ var Chalkboard = {
2969
3348
  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
3349
  }
2971
3350
  } else {
2972
- return "TypeError: Parameter \"func\" must be of type \"expl\", \"pola\", or \"curv\".";
3351
+ return "TypeError: Parameter \"func\" must be of type \"expl\", \"inve\", \"pola\", or \"curv\".";
2973
3352
  }
2974
3353
  },
2975
3354
  tangent: function(func, val) {
@@ -3224,7 +3603,7 @@ var Chalkboard = {
3224
3603
  return "TypeError: Parameter \"func\" must be of type \"comp\".";
3225
3604
  }
3226
3605
  },
3227
- df2dz2: function(func, comp) {
3606
+ d2fdz2: function(func, comp) {
3228
3607
  var h = 0.00001;
3229
3608
  if(func.type === "comp") {
3230
3609
  var u = Chalkboard.comp.parse("(a, b) => " + func.definition[0]),
@@ -3239,10 +3618,12 @@ var Chalkboard = {
3239
3618
  }
3240
3619
  },
3241
3620
  fxdx: function(func, a, b) {
3242
- if(func.type === "expl" || func.type === "pola") {
3621
+ if(func.type === "expl" || func.type === "inve" || func.type === "pola") {
3243
3622
  var f;
3244
3623
  if(func.type === "expl") {
3245
3624
  f = Chalkboard.real.parse("x => " + func.definition);
3625
+ } else if(func.type === "inve") {
3626
+ f = Chalkboard.real.parse("y => " + func.definition);
3246
3627
  } else if(func.type === "pola") {
3247
3628
  f = Chalkboard.real.parse("O => " + "((" + func.definition + ") * (" + func.definition + ")) / 2");
3248
3629
  }
@@ -3280,7 +3661,7 @@ var Chalkboard = {
3280
3661
  return Chalkboard.vec3.new((xt * dt) / 3, (yt * dt) / 3, (zt * dt) / 3);
3281
3662
  }
3282
3663
  } else {
3283
- return "TypeError: Parameter \"func\" must be of type \"expl\", \"pola\", or \"curv\".";
3664
+ return "TypeError: Parameter \"func\" must be of type \"expl\", \"inve\", \"pola\", or \"curv\".";
3284
3665
  }
3285
3666
  },
3286
3667
  fxydxdy: function(func, a, b, c, d) {
@@ -3478,4 +3859,8 @@ var Chalkboard = {
3478
3859
  }
3479
3860
  }
3480
3861
  };
3481
- module.exports = Chalkboard;
3862
+ if(typeof window === "undefined") {
3863
+ module.exports = Chalkboard;
3864
+ } else {
3865
+ window.Chalkboard = Chalkboard;
3866
+ }