@zushah/chalkboard 1.5.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.
@@ -0,0 +1,3437 @@
1
+ /*
2
+ The Chalkboard Library
3
+ Version 1.5.0 released 12/18/2023
4
+ Authored by Zushah ===> https://www.github.com/Zushah
5
+ Available under the MIT License ===> https://www.opensource.org/license/mit/
6
+
7
+ The Chalkboard library is a JavaScript namespace that provides a plethora of both practical and abstract mathematical functionalities for its user.
8
+
9
+ Latest release ===> https://www.github.com/Zushah/Chalkboard/releases/tag/v1.5.0
10
+ Documentation ===> https://zushah.github.io/Chalkboard/documentation.html/
11
+ */
12
+ var Chalkboard = {
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/");
15
+ },
16
+ LOGO: function(x, y, s) {
17
+ x = x || width / 2;
18
+ y = y || height / 2;
19
+ s = s || 1;
20
+ pushMatrix();
21
+ translate(x, y);
22
+ scale(s);
23
+ noStroke();
24
+ fill(25, 25, 25);
25
+ rect(-50, -50, 100, 100);
26
+ fill(50, 125, 200);
27
+ textAlign(CENTER, CENTER);
28
+ textSize(75);
29
+ textFont(createFont("Times New Roman"));
30
+ text("C", -25, 0);
31
+ text("B", 25, 0);
32
+ stroke(50, 125, 200);
33
+ strokeWeight(6);
34
+ strokeCap(SQUARE);
35
+ line(-30, 25, -30, -22.5);
36
+ line(22, 25, 22, -22.5);
37
+ textAlign(TOP, LEFT);
38
+ popMatrix();
39
+ },
40
+ PI: function(coefficient) {
41
+ coefficient = coefficient || 1;
42
+ return coefficient * 4 * (4 * Math.atan(1/5) - Math.atan(1/239));
43
+ },
44
+ E: function(exponent) {
45
+ exponent = exponent || 1;
46
+ return Math.pow(Math.pow(10, 1 / Math.log(10)), exponent);
47
+ },
48
+ numb: {
49
+ random: function(inf, sup) {
50
+ inf = inf || 0;
51
+ sup = sup || 0;
52
+ return inf + Math.random() * (sup - inf);
53
+ },
54
+ factorial: function(num) {
55
+ if(num >= 0) {
56
+ var n = 1;
57
+ for(var i = 1; i <= num; i++) {
58
+ n *= i;
59
+ }
60
+ i--;
61
+ return n;
62
+ } else if(num < 0) {
63
+ return undefined;
64
+ }
65
+ },
66
+ gcd: function(a, b) {
67
+ if(b === 0) {
68
+ return a;
69
+ }
70
+ return Chalkboard.numb.gcd(b, a % b);
71
+ },
72
+ lcm: function(a, b) {
73
+ return a * (b / Chalkboard.numb.gcd(a, b));
74
+ },
75
+ sum: function(formula, inf, sup) {
76
+ var result = 0;
77
+ var f = Chalkboard.real.parse("n => " + formula);
78
+ for(var i = inf; i <= sup; i++) {
79
+ result += f(i);
80
+ }
81
+ return result;
82
+ },
83
+ mul: function(formula, inf, sup) {
84
+ var result = 1;
85
+ var f = Chalkboard.real.parse("n => " + formula);
86
+ for(var i = inf; i <= sup; i++) {
87
+ result *= f(i);
88
+ }
89
+ return result;
90
+ },
91
+ combination: function(n, r) {
92
+ return Chalkboard.numb.factorial(n) / (Chalkboard.numb.factorial(n - r) * Chalkboard.numb.factorial(r));
93
+ },
94
+ permutation: function(n, r) {
95
+ return Chalkboard.numb.factorial(n) / Chalkboard.numb.factorial(n - r);
96
+ },
97
+ prime: function(num) {
98
+ if(num === 2) {
99
+ return 2;
100
+ }
101
+ var n = 1;
102
+ var prime = 3;
103
+ while(n < num) {
104
+ if(Chalkboard.numb.isPrime(prime)) {
105
+ n++;
106
+ }
107
+ if(n < num) {
108
+ prime += 2;
109
+ }
110
+ }
111
+ return prime;
112
+ },
113
+ isPrime: function(num) {
114
+ for(var i = 2; i <= Chalkboard.real.sqrt(num); i++) {
115
+ if(num % i === 0) {
116
+ return false;
117
+ }
118
+ }
119
+ return num > 1;
120
+ },
121
+ nextPrime: function(num) {
122
+ var result = num + 1;
123
+ while(!Chalkboard.numb.isPrime(result)) {
124
+ result++;
125
+ }
126
+ return result;
127
+ },
128
+ primeGap: function(inf, sup) {
129
+ var prime = null;
130
+ var gap = 0;
131
+ for(var i = inf; i <= sup; i++) {
132
+ if(Chalkboard.numb.isPrime(i)) {
133
+ if(prime !== null) {
134
+ var temp = i - prime;
135
+ if(temp > gap) {
136
+ gap = temp;
137
+ }
138
+ }
139
+ prime = i;
140
+ }
141
+ }
142
+ return gap;
143
+ },
144
+ primeArr: function(inf, sup) {
145
+ var result = [];
146
+ for(var i = inf; i <= sup; i++) {
147
+ if(Chalkboard.numb.isPrime(i)) {
148
+ result.push(i);
149
+ }
150
+ }
151
+ return result;
152
+ },
153
+ primeCount: function(inf, sup) {
154
+ return Chalkboard.numb.primeArr(inf, sup).length;
155
+ },
156
+ compositeArr: function(inf, sup) {
157
+ var result = [];
158
+ for(var i = inf; i <= sup; i++) {
159
+ if(!Chalkboard.numb.isPrime(i)) {
160
+ result.push(i);
161
+ }
162
+ }
163
+ return result;
164
+ },
165
+ compositeCount: function(inf, sup) {
166
+ return Chalkboard.numb.compositeArr(inf, sup).length;
167
+ },
168
+ factors: function(num) {
169
+ var result = [];
170
+ while(num % 2 === 0) {
171
+ result.push(2);
172
+ num /= 2;
173
+ }
174
+ for(var i = 3; i <= Chalkboard.real.sqrt(num); i += 2) {
175
+ while(num % i === 0) {
176
+ result.push(i);
177
+ num /= i;
178
+ }
179
+ }
180
+ if(num > 2) {
181
+ result.push(num);
182
+ }
183
+ return result;
184
+ },
185
+ divisors: function(num) {
186
+ var result = [];
187
+ for(var i = 1; i <= num; i++) {
188
+ if(num % i === 0) {
189
+ result.push(i);
190
+ }
191
+ }
192
+ return result;
193
+ },
194
+ sgn: function(num) {
195
+ if(num < 0) {
196
+ return -1;
197
+ } else if(num === 0) {
198
+ return 0;
199
+ } else if(num > 0) {
200
+ return 1;
201
+ }
202
+ },
203
+ Kronecker: function(a, b) {
204
+ if(a === b) {
205
+ return 1;
206
+ } else if(a !== b) {
207
+ return 0;
208
+ } else {
209
+ return undefined;
210
+ }
211
+ },
212
+ change: function(initial, final) {
213
+ return (final - initial) / initial;
214
+ },
215
+ map: function(num, range1, range2) {
216
+ return range2[0] + (range2[1] - range2[0]) * ((num - range1[0]) / (range1[1] - range1[0]));
217
+ },
218
+ constrain: function(num, range) {
219
+ if(range === undefined) {
220
+ return Math.max(Math.min(num, 1), 0);
221
+ } else {
222
+ return Math.max(Math.min(num, range[1]), range[0]);
223
+ }
224
+ },
225
+ binomial: function(n, k) {
226
+ if(k === 0 || k === n) {
227
+ return 1;
228
+ } else {
229
+ return Chalkboard.numb.binomial(n - 1, k - 1) + Chalkboard.numb.binomial(n - 1, k);
230
+ }
231
+ },
232
+ Fibonacci: function(num) {
233
+ var sequence = [0, 1];
234
+ if(sequence[num] === undefined) {
235
+ sequence.push(Chalkboard.numb.Fibonacci(num - 1) + sequence[num - 2]);
236
+ }
237
+ return sequence[num];
238
+ },
239
+ Gaussian: function(height, mean, deviation) {
240
+ var u, v, s;
241
+ for(;;) {
242
+ u = Chalkboard.numb.random(-1, 1);
243
+ v = Chalkboard.numb.random(-1, 1);
244
+ s = u * u + v * v;
245
+ if(s < 1 && s !== 0) {
246
+ break;
247
+ }
248
+ }
249
+ var z = u * Chalkboard.real.sqrt(-2 * Chalkboard.real.ln(s) / s);
250
+ return z * height * deviation + mean;
251
+ }
252
+ },
253
+ real: {
254
+ function: function(definition, type) {
255
+ type = type || "expl";
256
+ if(type === "expl") {
257
+ return {definition: definition, type: type};
258
+ } else if(type === "pola") {
259
+ return {definition: definition, type: type};
260
+ } else if(type === "curv") {
261
+ return definition.length === 2 ? {definition: [definition[0], definition[1]], type: type} : {definition: [definition[0], definition[1], definition[2]], type: type};
262
+ } else if(type === "surf") {
263
+ return {definition: [definition[0], definition[1], definition[2]], type: type};
264
+ } else if(type === "mult") {
265
+ return {definition: definition, type: type};
266
+ } else {
267
+ return "TypeError: Parameter \"type\" must be either \"expl\", \"pola\", \"curv\", \"surf\", or \"mult\".";
268
+ }
269
+ },
270
+ parse: function(str, init) {
271
+ init = init || '';
272
+ return Function('"use strict"; ' + init + ' return (' + str + ')')();
273
+ },
274
+ val: function(func, val) {
275
+ if(func.type === "expl") {
276
+ var f = Chalkboard.real.parse("x => " + func.definition);
277
+ return f(val);
278
+ } else if(func.type === "pola") {
279
+ var r = Chalkboard.real.parse("O => " + func.definition);
280
+ return r(val);
281
+ } else if(func.type === "curv") {
282
+ if(func.definition.length === 2) {
283
+ var x = Chalkboard.real.parse("t => " + func.definition[0]),
284
+ y = Chalkboard.real.parse("t => " + func.definition[1]);
285
+ return Chalkboard.vec2.new(x(val), y(val));
286
+ } else if(func.definition.length === 3) {
287
+ var x = Chalkboard.real.parse("t => " + func.definition[0]),
288
+ y = Chalkboard.real.parse("t => " + func.definition[1]),
289
+ z = Chalkboard.real.parse("t => " + func.definition[2]);
290
+ return Chalkboard.vec3.new(x(val), y(val), z(val));
291
+ }
292
+ } else if(func.type === "surf") {
293
+ var x = Chalkboard.real.parse("(s, t) => " + func.definition[0]),
294
+ y = Chalkboard.real.parse("(s, t) => " + func.definition[1]),
295
+ z = Chalkboard.real.parse("(s, t) => " + func.definition[2]);
296
+ if(val.type === "vec2") {
297
+ return Chalkboard.vec3.new(x(val.x, val.y), y(val.x, val.y), z(val.x, val.y));
298
+ } else {
299
+ return "TypeError: Parameter \"val\" must be of type \"vec2\".";
300
+ }
301
+ } else if(func.type === "mult") {
302
+ if(val.type === "vec2") {
303
+ var f = Chalkboard.real.parse("(x, y) => " + func.definition);
304
+ return f(val.x, val.y);
305
+ } else {
306
+ return "TypeError: Parameter \"val\" must be of type \"vec2\".";
307
+ }
308
+ } else {
309
+ return "TypeError: Parameter \"func\" must be of type \"expl\", \"pola\", \"curv\", \"surf\", or \"mult\".";
310
+ }
311
+ },
312
+ pow: function(base, num) {
313
+ return Math.exp(num * Math.log(base));
314
+ },
315
+ log: function(base, num) {
316
+ return Chalkboard.real.ln(num) / Chalkboard.real.ln(base);
317
+ },
318
+ ln: function(num) {
319
+ return Chalkboard.calc.fxdx(Chalkboard.real.function("1 / x"), 1, num);
320
+ },
321
+ log10: function(num) {
322
+ return Chalkboard.real.log(10, num);
323
+ },
324
+ sqrt: function(num) {
325
+ if(num >= 0) {
326
+ return Math.exp(Math.log(num) / 2);
327
+ } else if(num < 0) {
328
+ return undefined;
329
+ }
330
+ },
331
+ nrt: function(num, index) {
332
+ return Math.exp(Math.log(num) / index);
333
+ },
334
+ tetration: function(base, num) {
335
+ if(num === 0) {
336
+ return 1;
337
+ } else if(num > 0) {
338
+ return Math.pow(base, Chalkboard.real.tetration(base, num - 1));
339
+ } else {
340
+ return undefined;
341
+ }
342
+ },
343
+ Heaviside: function(num, edge, scl) {
344
+ edge = edge || 0;
345
+ scl = scl || 1;
346
+ if(num >= edge) {
347
+ return scl;
348
+ } else if(num < edge) {
349
+ return 0;
350
+ }
351
+ },
352
+ Dirac: function(num, edge, scl) {
353
+ edge = edge || 0;
354
+ scl = scl || 1;
355
+ if(num === edge) {
356
+ return scl;
357
+ } else if(num !== edge) {
358
+ return 0;
359
+ }
360
+ },
361
+ ramp: function(num, edge, scl) {
362
+ edge = edge || 0;
363
+ scl = scl || 1;
364
+ if(num >= edge) {
365
+ return num * scl;
366
+ } else if(num < edge) {
367
+ return 0;
368
+ }
369
+ },
370
+ rect: function(num, center, width, scl) {
371
+ center = center || 0;
372
+ width = width || 2;
373
+ scl = scl || 1;
374
+ if(num > (center + width / 2) || num < (center - width / 2)) {
375
+ return 0;
376
+ } else if(num <= (center + width / 2) || num >= (center - width / 2)) {
377
+ return scl;
378
+ }
379
+ },
380
+ pingpong: function(num, edge, scl) {
381
+ edge = edge || 0;
382
+ scl = scl || 1;
383
+ if((num + edge) % (2 * scl) < scl) {
384
+ return (num + edge) % scl;
385
+ } else {
386
+ return scl - (num + edge) % scl;
387
+ }
388
+ },
389
+ slope: function(x1, y1, x2, y2) {
390
+ return (y2 - y1) / (x2 - x1);
391
+ },
392
+ linear: function(x1, y1, x2, y2) {
393
+ return Chalkboard.real.function(Chalkboard.real.slope(x1, y1, x2, y2).toString() + " * (x - " + x2.toString() + ") + " + y2.toString());
394
+ },
395
+ linearFormula: function(a, b, c, d) {
396
+ if(c === undefined && d === undefined) {
397
+ return -b / a;
398
+ } else if(d === undefined) {
399
+ return c / a;
400
+ } else {
401
+ return -b / Chalkboard.real.slope(a, b, c, d) + a;
402
+ }
403
+ },
404
+ lerp: function(p, t) {
405
+ return (p[1] - p[0]) * t + p[0];
406
+ },
407
+ quadratic: function(a, b, c, form) {
408
+ form = form || "stan";
409
+ if(form === "stan") {
410
+ return Chalkboard.real.function(a.toString() + "* x * x + " + b.toString() + " * x +" + c.toString());
411
+ } else if(form === "vert") {
412
+ return Chalkboard.real.function(a.toString() + " * ((x - " + b.toString() + ") * (x - " + b.toString() + ")) +" + c.toString());
413
+ } else {
414
+ return "TypeError: Parameter \"form\" must be \"stan\" or \"vert\".";
415
+ }
416
+ },
417
+ discriminant: function(a, b, c, form) {
418
+ form = form || "stan";
419
+ if(form === "stan") {
420
+ return b * b - 4 * a * c;
421
+ } else if(form === "vert") {
422
+ return (2 * a * b) * (2 * a * b) - 4 * a * c;
423
+ } else {
424
+ return "TypeError: Parameter \"form\" must be \"stan\" or \"vert\".";
425
+ }
426
+ },
427
+ quadraticFormula: function(a, b, c, form) {
428
+ form = form || "stan";
429
+ if(form === "stan") {
430
+ return [(-b + Chalkboard.real.sqrt(Chalkboard.real.discriminant(a, b, c, "stan"))) / (2 * a), (-b - Math.sqrt(Chalkboard.real.discriminant(a, b, c, "stan"))) / (2 * a)];
431
+ } else if(form === "vert") {
432
+ return [b + Chalkboard.real.sqrt(-c / a), b - Chalkboard.real.sqrt(-c / a)];
433
+ } else {
434
+ return "TypeError: Parameter \"form\" must be \"stan\" or \"vert\".";
435
+ }
436
+ },
437
+ qerp: function(p1, p2, p3, t) {
438
+ var a = p1[1] / ((p1[0] - p2[0]) * (p1[0] - p3[0])) + p2[1] / ((p2[0] - p1[0]) * (p2[0] - p3[0])) + p3[1] / ((p3[0] - p1[0]) * (p3[0] - p2[0]));
439
+ var b = -p1[1] * (p2[0] + p3[0]) / ((p1[0] - p2[0]) * (p1[0] - p3[0])) - p2[1] * (p1[0] + p3[0]) / ((p2[0] - p1[0]) * (p2[0] - p3[0])) - p3[1] * (p1[0] + p2[0]) / ((p3[0] - p1[0]) * (p3[0] - p2[0]));
440
+ var c = p1[1] * p2[0] * p3[0] / ((p1[0] - p2[0]) * (p1[0] - p3[0])) + p2[1] * p1[0] * p3[0] / ((p2[0] - p1[0]) * (p2[0] - p3[0])) + p3[1] * p1[0] * p2[0] / ((p3[0] - p1[0]) * (p3[0] - p2[0]));
441
+ return a * t * t + b * t + c;
442
+ }
443
+ },
444
+ comp: {
445
+ new: function(a, b) {
446
+ return {a: a, b: b, type: "comp"};
447
+ },
448
+ function: function(realDefinition, imagDefinition) {
449
+ return {definition: [realDefinition, imagDefinition], type: "comp"};
450
+ },
451
+ parse: function(str, init) {
452
+ init = init || '';
453
+ return Function('"use strict"; ' + init + ' return (' + str + ')')();
454
+ },
455
+ val: function(func, comp) {
456
+ if(func.type === "comp") {
457
+ var u = Chalkboard.comp.parse("(a, b) => " + func.definition[0]),
458
+ v = Chalkboard.comp.parse("(a, b) => " + func.definition[1]);
459
+ return Chalkboard.comp.new(u(comp.a, comp.b), v(comp.a, comp.b));
460
+ } else {
461
+ return "TypeError: Parameter \"func\" must be of type \"comp\".";
462
+ }
463
+ },
464
+ Re: function(funcORcomp) {
465
+ if(funcORcomp.definition !== undefined && funcORcomp.type === "comp") {
466
+ return funcORcomp.definition[0];
467
+ } else if(funcORcomp.a !== undefined && funcORcomp.type === "comp") {
468
+ return funcORcomp.a;
469
+ }
470
+ },
471
+ Im: function(funcORcomp) {
472
+ if(funcORcomp.definition !== undefined && funcORcomp.type === "comp") {
473
+ return funcORcomp.definition[1];
474
+ } else if(funcORcomp.b !== undefined && funcORcomp.type === "comp") {
475
+ return funcORcomp.b;
476
+ }
477
+ },
478
+ random: function(inf, sup) {
479
+ return Chalkboard.comp.new(Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup));
480
+ },
481
+ mag: function(comp) {
482
+ return Chalkboard.real.sqrt((comp.a * comp.a) + (comp.b * comp.b));
483
+ },
484
+ magsq: function(comp) {
485
+ return (comp.a * comp.a) + (comp.b * comp.b);
486
+ },
487
+ magset: function(comp, num) {
488
+ return Chalkboard.comp.scl(Chalkboard.comp.normalize(comp), num);
489
+ },
490
+ arg: function(comp) {
491
+ return Chalkboard.trig.arctan2(comp.b, comp.a);
492
+ },
493
+ slope: function(comp) {
494
+ return comp.b / comp.a;
495
+ },
496
+ average: function(comp) {
497
+ return (comp.a + comp.b) / 2;
498
+ },
499
+ normalize: function(comp) {
500
+ return Chalkboard.comp.new(comp.a / Chalkboard.comp.mag(comp), comp.b / Chalkboard.comp.mag(comp));
501
+ },
502
+ zero: function(comp) {
503
+ return Chalkboard.comp.new(comp.a * 0, comp.b * 0);
504
+ },
505
+ negate: function(comp) {
506
+ return Chalkboard.comp.new(-comp.a, -comp.b);
507
+ },
508
+ reciprocate: function(comp) {
509
+ return Chalkboard.comp.new(1 / comp.a, 1 / comp.b);
510
+ },
511
+ absolute: function(comp) {
512
+ return Chalkboard.comp.new(Math.abs(comp.a), Math.abs(comp.b));
513
+ },
514
+ round: function(comp) {
515
+ return Chalkboard.comp.new(Math.round(comp.a), Math.round(comp.b));
516
+ },
517
+ Euler: function(rad) {
518
+ return Chalkboard.comp.new(Chalkboard.trig.cos(rad), Chalkboard.trig.sin(rad));
519
+ },
520
+ pow: function(comp, num) {
521
+ return Chalkboard.comp.new(Chalkboard.real.pow(Chalkboard.comp.mag(comp), num) * Chalkboard.trig.cos(num * Chalkboard.comp.arg(comp)), Chalkboard.real.pow(Chalkboard.comp.mag(comp), num) * Chalkboard.trig.sin(num * Chalkboard.comp.arg(comp)));
522
+ },
523
+ ln: function(comp) {
524
+ return Chalkboard.comp.new(Chalkboard.real.ln(Chalkboard.comp.mag(comp)), Chalkboard.trig.arctan2(comp.b, comp.a));
525
+ },
526
+ sq: function(comp) {
527
+ return Chalkboard.comp.new((comp.a * comp.a) - (comp.b * comp.b), 2 * comp.a * comp.b);
528
+ },
529
+ sqrt: function(comp) {
530
+ 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));
531
+ },
532
+ rotate: function(comp, rad) {
533
+ 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));
534
+ },
535
+ invert: function(comp) {
536
+ return Chalkboard.comp.new(comp.a / Chalkboard.comp.magsq(comp), -comp.b / Chalkboard.comp.magsq(comp));
537
+ },
538
+ conjugate: function(comp) {
539
+ return Chalkboard.comp.new(comp.a, -comp.b);
540
+ },
541
+ root: function(comp, n) {
542
+ if(Number.isInteger(n) && n > 0) {
543
+ var result = [];
544
+ var r = Chalkboard.comp.mag(comp);
545
+ var t = Chalkboard.comp.arg(comp);
546
+ for(var i = 0; i < n; i++) {
547
+ 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)));
548
+ }
549
+ return result;
550
+ }
551
+ },
552
+ dist: function(comp_1, comp_2) {
553
+ 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)));
554
+ },
555
+ distsq: function(comp_1, comp_2) {
556
+ 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));
557
+ },
558
+ scl: function(comp, num) {
559
+ return Chalkboard.comp.new(comp.a * num, comp.b * num);
560
+ },
561
+ constrain: function(comp, range) {
562
+ return Chalkboard.comp.new(Chalkboard.numb.constrain(comp.a, range), Chalkboard.numb.constrain(comp.b, range));
563
+ },
564
+ add: function(comp_1, comp_2) {
565
+ return Chalkboard.comp.new(comp_1.a + comp_2.a, comp_1.b + comp_2.b);
566
+ },
567
+ sub: function(comp_1, comp_2) {
568
+ return Chalkboard.comp.new(comp_1.a - comp_2.a, comp_1.b - comp_2.b);
569
+ },
570
+ mul: function(comp_1, comp_2) {
571
+ 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));
572
+ },
573
+ div: function(comp_1, comp_2) {
574
+ 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));
575
+ },
576
+ toVector: function(comp) {
577
+ return Chalkboard.vec2.new(comp.a, comp.b);
578
+ },
579
+ toArray: function(comp) {
580
+ return [comp.a, comp.b];
581
+ },
582
+ toString: function(comp) {
583
+ if(comp.b >= 0) {
584
+ return comp.a.toString() + " + " + comp.b.toString() + "i";
585
+ } else if(comp.b < 0) {
586
+ return comp.a.toString() + " - " + Math.abs(comp.b).toString() + "i";
587
+ }
588
+ },
589
+ print: function(comp) {
590
+ console.log(Chalkboard.comp.toString(comp));
591
+ }
592
+ },
593
+ quat: {
594
+ new: function(a, b, c, d) {
595
+ return {a: a, b: b, c: c, d: d, type: "quat"};
596
+ },
597
+ random: function(inf, sup) {
598
+ return Chalkboard.quat.new(Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup));
599
+ },
600
+ mag: function(quat) {
601
+ return Chalkboard.real.sqrt((quat.a * quat.a) + (quat.b * quat.b) + (quat.c * quat.c) + (quat.d * quat.d));
602
+ },
603
+ magsq: function(quat) {
604
+ return (quat.a * quat.a) + (quat.b * quat.b) + (quat.c * quat.c) + (quat.d * quat.d);
605
+ },
606
+ magset: function(quat, num) {
607
+ return Chalkboard.quat.scl(Chalkboard.quat.normalize(quat), num);
608
+ },
609
+ average: function(quat) {
610
+ return (quat.a + quat.b + quat.c + quat.d) / 4;
611
+ },
612
+ normalize: function(quat) {
613
+ return Chalkboard.quat.new(quat.a / Chalkboard.quat.mag(quat), quat.b / Chalkboard.quat.mag(quat), quat.c / Chalkboard.quat.mag(quat), quat.d / Chalkboard.quat.mag(quat));
614
+ },
615
+ zero: function(quat) {
616
+ return Chalkboard.quat.new(quat.a * 0, quat.b * 0, quat.c * 0, quat.d * 0);
617
+ },
618
+ negate: function(quat) {
619
+ return Chalkboard.quat.new(-quat.a, -quat.b, -quat.c, -quat.d);
620
+ },
621
+ reciprocate: function(quat) {
622
+ return Chalkboard.quat.new(1 / quat.a, 1 / quat.b, 1 / quat.c, 1 / quat.d);
623
+ },
624
+ absolute: function(quat) {
625
+ return Chalkboard.quat.new(Math.abs(quat.a), Math.abs(quat.b), Math.abs(quat.c), Math.abs(quat.d));
626
+ },
627
+ round: function(quat) {
628
+ return Chalkboard.quat.new(Math.round(quat.a), Math.round(quat.b), Math.round(quat.c), Math.round(quat.d));
629
+ },
630
+ invert: function(quat) {
631
+ return Chalkboard.quat.new(quat.a / Chalkboard.quat.magsq(quat), -quat.b / Chalkboard.quat.magsq(quat), -quat.c / Chalkboard.quat.magsq(quat), -quat.d / Chalkboard.quat.magsq(quat));
632
+ },
633
+ conjugate: function(quat) {
634
+ return Chalkboard.quat.new(quat.a, -quat.b, -quat.c, -quat.d);
635
+ },
636
+ dist: function(quat_1, quat_2) {
637
+ 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)));
638
+ },
639
+ distsq: function(quat_1, quat_2) {
640
+ 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));
641
+ },
642
+ scl: function(quat, num) {
643
+ return Chalkboard.quat.new(quat.a * num, quat.b * num, quat.c * num, quat.d * num);
644
+ },
645
+ constrain: function(quat, range) {
646
+ 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));
647
+ },
648
+ add: function(quat_1, quat_2) {
649
+ 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);
650
+ },
651
+ sub: function(quat_1, quat_2) {
652
+ 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);
653
+ },
654
+ mul: function(quat_1, quat_2) {
655
+ 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));
656
+ },
657
+ fromAxis: function(vec3, rad) {
658
+ 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));
659
+ },
660
+ fromVector: function(vec3) {
661
+ return Chalkboard.quat.new(0, vec3.x, vec3.y, vec3.z);
662
+ },
663
+ toRotation: function(quat, vec3) {
664
+ var vector = Chalkboard.quat.fromVector(vec3);
665
+ var inverse = Chalkboard.quat.invert(quat);
666
+ var quat_vector_inverse = Chalkboard.quat.mul(quat, Chalkboard.quat.mul(vector, inverse));
667
+ return Chalkboard.vec3.new(quat_vector_inverse.b, quat_vector_inverse.c, quat_vector_inverse.d);
668
+ },
669
+ toVector: function(quat) {
670
+ return Chalkboard.vec4.new(quat.a, quat.b, quat.c, quat.d);
671
+ },
672
+ toArray: function(quat) {
673
+ return [quat.a, quat.b, quat.c, quat.d];
674
+ },
675
+ toString: function(quat) {
676
+ var quat_b = "";
677
+ var quat_c = "";
678
+ var quat_d = "";
679
+ if(quat.b >= 0) {
680
+ quat_b = " + " + quat.b.toString() + "i ";
681
+ } else if(quat.b < 0) {
682
+ quat_b = " - " + Math.abs(quat.b.toString()) + "i ";
683
+ }
684
+ if(quat.c >= 0) {
685
+ quat_c = "+ " + quat.c.toString() + "j ";
686
+ } else if(quat.c < 0) {
687
+ quat_c = "- " + Math.abs(quat.c.toString()) + "j ";
688
+ }
689
+ if(quat.d >= 0) {
690
+ quat_d = "+ " + quat.d.toString() + "k ";
691
+ } else if(quat.d < 0) {
692
+ quat_d = "- " + Math.abs(quat.d.toString()) + "k ";
693
+ }
694
+ return quat.a.toString() + quat_b + quat_c + quat_d;
695
+ },
696
+ print: function(quat) {
697
+ console.log(Chalkboard.quat.toString(quat));
698
+ }
699
+ },
700
+ plot: {
701
+ xyplane: function(scl, rgba, origin, weight) {
702
+ scl = scl || 1;
703
+ scl /= 100;
704
+ rgba = rgba || [0, 0, 0];
705
+ origin = origin || [width / 2, height / 2];
706
+ weight = weight || 2;
707
+ pushMatrix();
708
+ translate(origin[0], origin[1]);
709
+ stroke(rgba.length === 3 ? color(rgba[0], rgba[1], rgba[2]) : color(rgba[0], rgba[1], rgba[2], rgba[3]));
710
+ strokeWeight(weight / 4);
711
+ for(var i = Math.floor(-origin[0] / scl); i <= (width - origin[0]) / scl; i++) {
712
+ line(i / scl, -origin[1], i / scl, width - origin[1]);
713
+ }
714
+ for(var i = Math.floor(-origin[1] / scl); i <= (width - origin[1]) / scl; i++) {
715
+ line(-origin[0], i / scl, width - origin[0], i / scl);
716
+ }
717
+ strokeWeight(weight);
718
+ line(-origin[0], 0, width - origin[0], 0);
719
+ line(0, -origin[1], 0, width - origin[1]);
720
+ popMatrix();
721
+ },
722
+ rOplane: function(scl, rgba, origin, weight) {
723
+ scl = scl || 1;
724
+ scl /= 100;
725
+ rgba = rgba || [0, 0, 0];
726
+ origin = origin || [width / 2, height / 2];
727
+ weight = weight || 2;
728
+ pushMatrix();
729
+ translate(origin[0], origin[1]);
730
+ noFill();
731
+ stroke(rgba.length === 3 ? color(rgba[0], rgba[1], rgba[2]) : color(rgba[0], rgba[1], rgba[2], rgba[3]));
732
+ strokeWeight(weight / 4);
733
+ for(var i = 0; i <= scl * width / 2; i++) {
734
+ ellipse(0, 0, 2 * i / scl, 2 * i / scl);
735
+ }
736
+ strokeWeight(weight);
737
+ line(-origin[0], 0, width - origin[0], 0);
738
+ line(0, -origin[1], 0, width - origin[1]);
739
+ popMatrix();
740
+ },
741
+ function: function(func, scl, rgba, domain, origin, weight) {
742
+ scl = scl || 1;
743
+ scl /= 100;
744
+ rgba = rgba || [0, 0, 0];
745
+ domain = domain || func.type === "comp" ? [[-10, 10], [-10, 10]] : [-10, 10];
746
+ origin = origin || [width / 2, height / 2];
747
+ weight = weight || 2;
748
+ var data = [];
749
+ pushMatrix();
750
+ translate(origin[0], origin[1]);
751
+ noFill();
752
+ strokeWeight(weight);
753
+ stroke(rgba.length === 3 ? color(rgba[0], rgba[1], rgba[2]) : color(rgba[0], rgba[1], rgba[2], rgba[3]));
754
+ beginShape();
755
+ if(func.type === "expl") {
756
+ var f = Chalkboard.real.parse("x => " + func.definition);
757
+ for(var i = domain[0] / scl; i <= domain[1] / scl; i++) {
758
+ vertex(i, -f(i * scl) / scl);
759
+ data.push([i, f(i)]);
760
+ }
761
+ } else if(func.type === "pola") {
762
+ var r = Chalkboard.real.parse("O => " + func.definition);
763
+ for(var i = domain[0] / scl; i < domain[1] / scl; i++) {
764
+ vertex(r(i * scl) / scl * Chalkboard.trig.cos(i * scl), -r(i * scl) / scl * Chalkboard.trig.sin(i * scl));
765
+ data.push([i, r(i)]);
766
+ }
767
+ } else if(func.type === "curv") {
768
+ var x = Chalkboard.real.parse("t => " + func.definition[0]),
769
+ y = Chalkboard.real.parse("t => " + func.definition[1]);
770
+ for(var i = domain[0] / scl; i < domain[1] / scl; i++) {
771
+ vertex(x(i * scl) / scl, -y(i * scl) / scl);
772
+ data.push([x(i), y(i)]);
773
+ }
774
+ } else if(func.type === "comp") {
775
+ var u = Chalkboard.comp.parse("(a, b) => " + func.definition[0]),
776
+ v = Chalkboard.comp.parse("(a, b) => " + func.definition[1]);
777
+ for(var i = domain[0][0] / scl; i <= domain[0][1] / scl; i += 5) {
778
+ for(var j = domain[1][0] / scl; j <= domain[1][1] / scl; j += 5) {
779
+ var z = Chalkboard.comp.new(u(i * scl, j * scl) / scl, v(i * scl, j * scl) / scl);
780
+ noStroke();
781
+ if(z.a === 0 && z.b === 0) {
782
+ fill(0, 0, 0);
783
+ } else if(z.a === Infinity && z.b === Infinity) {
784
+ fill(255, 255, 255);
785
+ } else {
786
+ colorMode(HSB);
787
+ fill(Chalkboard.numb.map(Chalkboard.trig.toDeg(Chalkboard.comp.arg(z)), [0, 360], [0, 255]), 255, Chalkboard.numb.map((Chalkboard.trig.tanh(Chalkboard.comp.mag(z) / Chalkboard.real.pow(10, 20)) + 0.5) * 100, [0, 100], [0, 255]));
788
+ colorMode(RGB);
789
+ }
790
+ rect(i, j, 5, 5);
791
+ data.push([u(i, j), v(i, j)]);
792
+ }
793
+ }
794
+ } else {
795
+ return "TypeError: Property \"type\" of parameter \"func\" must be either \"expl\", \"pola\", \"curv\", or \"comp\".";
796
+ }
797
+ endShape();
798
+ popMatrix();
799
+ return data;
800
+ },
801
+ barplot: function(arr, bins, scl, rgba, origin, weight) {
802
+ scl = scl || 1;
803
+ scl /= 100;
804
+ rgba = rgba || [[0, 0, 0], [255, 255, 255]];
805
+ origin = origin || [width / 2, height / 2];
806
+ weight = weight || 2;
807
+ pushMatrix();
808
+ translate(origin[0], origin[1]);
809
+ strokeWeight(weight);
810
+ stroke(rgba.length === 3 ? color(rgba[0][0], rgba[0][1], rgba[0][2]) : color(rgba[0][0], rgba[0][1], rgba[0][2], rgba[0][3]));
811
+ fill(rgba.length === 3 ? color(rgba[1][0], rgba[1][1], rgba[1][2]) : color(rgba[1][0], rgba[1][1], rgba[1][2], rgba[1][3]));
812
+ var bars = [];
813
+ for(var i = 0; i < bins.length; i++) {
814
+ if(i === 0) {
815
+ bars.push(Chalkboard.stat.lt(arr, bins[0], true));
816
+ } else if(i === bins.length) {
817
+ bars.push(Chalkboard.stat.gt(arr, bins[bins.length - 1], true));
818
+ } else {
819
+ bars.push(Chalkboard.stat.ineq(arr, bins[i - 1], bins[i], false, true));
820
+ }
821
+ }
822
+ var counts = [];
823
+ for(var i = 0; i < bars.length; i++) {
824
+ counts.push(bars[i].length);
825
+ }
826
+ var x = 0, width = counts.length / (2 * scl);
827
+ for(var i = 0; i < counts.length; i++) {
828
+ rect(x - width, 0, 1 / scl, -counts[i] / scl);
829
+ x += 1 / scl;
830
+ }
831
+ popMatrix();
832
+ return bars;
833
+ },
834
+ lineplot: function(arr, bins, scl, rgba, origin, weight) {
835
+ scl = scl || 1;
836
+ scl /= 100;
837
+ rgba = rgba || [0, 0, 0];
838
+ origin = origin || [width / 2, height / 2];
839
+ weight = weight || 2;
840
+ pushMatrix();
841
+ translate(origin[0], origin[1]);
842
+ noFill();
843
+ strokeWeight(weight);
844
+ stroke(rgba.length === 3 ? color(rgba[0], rgba[1], rgba[2]) : color(rgba[0], rgba[1], rgba[2], rgba[3]));
845
+ var verts = [];
846
+ for(var i = 0; i < bins.length; i++) {
847
+ if(i === 0) {
848
+ verts.push(Chalkboard.stat.lt(arr, bins[0], true));
849
+ } else if(i === bins.length) {
850
+ verts.push(Chalkboard.stat.gt(arr, bins[bins.length - 1], true));
851
+ } else {
852
+ verts.push(Chalkboard.stat.ineq(arr, bins[i - 1], bins[i], false, true));
853
+ }
854
+ }
855
+ var counts = [];
856
+ for(var i = 0; i < verts.length; i++) {
857
+ counts.push(verts[i].length);
858
+ }
859
+ beginShape();
860
+ for(var i = 0; i < counts.length; i++) {
861
+ vertex(i / scl, -counts[i] / scl);
862
+ }
863
+ endShape();
864
+ popMatrix();
865
+ return verts;
866
+ },
867
+ scatterplot: function(arr1, arr2, scl, rgba, origin, weight) {
868
+ scl = scl || 1;
869
+ scl /= 100;
870
+ rgba = rgba || [0, 0, 0];
871
+ origin = origin || [width / 2, height / 2];
872
+ weight = weight || 5;
873
+ var data = [];
874
+ pushMatrix();
875
+ translate(origin[0], origin[1]);
876
+ strokeWeight(weight * 5);
877
+ stroke(rgba.length === 3 ? color(rgba[0], rgba[1], rgba[2]) : color(rgba[0], rgba[1], rgba[2], rgba[3]));
878
+ if(arr1.length === arr2.length) {
879
+ for(var i = 0; i < arr1.length; i++) {
880
+ point(arr1[i] / scl - arr1.length / (2 * scl), -arr2[i] / scl + arr1.length / (2 * scl));
881
+ data.push([arr1[i], arr2[i]]);
882
+ }
883
+ }
884
+ popMatrix();
885
+ return data;
886
+ },
887
+ comp: function(comp, scl, origin, weight, rgba) {
888
+ scl = scl || 1;
889
+ origin = origin || [width / 2, height / 2];
890
+ weight = weight || 5;
891
+ rgba = rgba || [0, 0, 0];
892
+ scl /= 100;
893
+ stroke(rgba.length === 3 ? color(rgba[0], rgba[1], rgba[2]) : color(rgba[0], rgba[1], rgba[2], rgba[3]));
894
+ strokeWeight(weight * 5);
895
+ pushMatrix();
896
+ translate(origin[0], origin[1]);
897
+ point(comp.a / scl, -comp.b / scl);
898
+ popMatrix();
899
+ noStroke();
900
+ noFill();
901
+ return [[comp.a], [comp.b]];
902
+ },
903
+ vec2: function(vec2, scl, rgba, origin, weight) {
904
+ scl = scl || 1;
905
+ scl /= 100;
906
+ rgba = rgba || [0, 0, 0];
907
+ origin = origin || [width / 2, height / 2];
908
+ weight = weight || 5;
909
+ stroke(rgba.length === 3 ? color(rgba[0], rgba[1], rgba[2]) : color(rgba[0], rgba[1], rgba[2], rgba[3]));
910
+ strokeWeight(weight);
911
+ pushMatrix();
912
+ translate(origin[0], origin[1]);
913
+ line(0, 0, vec2.x / scl, -vec2.y / scl);
914
+ popMatrix();
915
+ return [[vec2.x], [vec2.y]];
916
+ },
917
+ field: function(vec2field, scl, rgba, domain, origin, weight, res) {
918
+ scl = scl || 1;
919
+ scl /= 100;
920
+ rgba = rgba || [0, 0, 0];
921
+ domain = domain || [[-10, 10], [-10, 10]];
922
+ origin = origin || [width / 2, height / 2];
923
+ weight = weight || 5;
924
+ res = res || 25;
925
+ var data = [];
926
+ stroke(rgba.length === 3 ? color(rgba[0], rgba[1], rgba[2]) : color(rgba[0], rgba[1], rgba[2], rgba[3]));
927
+ strokeWeight(weight);
928
+ pushMatrix();
929
+ translate(origin[0], origin[1]);
930
+ for(var i = domain[0][0] / scl; i <= domain[0][1] / scl; i += res) {
931
+ for(var j = domain[1][0] / scl; j <= domain[1][1] / scl; j += res) {
932
+ var v = Chalkboard.vec2.fromField(vec2field, Chalkboard.vec2.new(i, j));
933
+ line(i, j, i + v.x, j + v.y);
934
+ data.push([i + v.x, j + v.y]);
935
+ }
936
+ }
937
+ popMatrix();
938
+ return data;
939
+ },
940
+ vec3: function(vec3, scl, rgba, origin, weight) {
941
+ scl = scl || 1;
942
+ scl /= 100;
943
+ rgba = rgba || [0, 0, 0];
944
+ origin = origin || [width / 2, height / 2];
945
+ weight = weight || 5;
946
+ stroke(rgba.length === 3 ? color(rgba[0], rgba[1], rgba[2]) : color(rgba[0], rgba[1], rgba[2], rgba[3]));
947
+ strokeWeight(weight);
948
+ pushMatrix();
949
+ translate(origin[0], origin[1]);
950
+ line(0, 0, (vec3.x / scl) / (vec3.z * 0.25 + 1), (-vec3.y / scl) / (vec3.z * 0.25 + 1));
951
+ popMatrix();
952
+ return [[vec3.x], [vec3.y], [vec3.z]];
953
+ },
954
+ matr: function(matr, scl, rgba, origin, weight) {
955
+ scl = scl || 1;
956
+ scl /= 100;
957
+ rgba = rgba || [0, 0, 0];
958
+ origin = origin || [width / 2, height / 2];
959
+ weight = weight || 2;
960
+ var plotposx = Chalkboard.vec2.new(matr[0][0], matr[1][0]);
961
+ var plotnegx = Chalkboard.vec2.new(-matr[0][0], -matr[1][0]);
962
+ var plotposy = Chalkboard.vec2.new(matr[0][1], matr[1][1]);
963
+ var plotnegy = Chalkboard.vec2.new(-matr[0][1], -matr[1][1]);
964
+ for(var i = -10; i <= 10; i++) {
965
+ Chalkboard.vec2.plot(plotposx, scl, rgba, [origin[0], origin[1] + (i / scl) * matr[1][1]], weight / 4);
966
+ Chalkboard.vec2.plot(plotnegx, scl, rgba, [origin[0], origin[1] + (i / scl) * matr[1][1]], weight / 4);
967
+ Chalkboard.vec2.plot(plotposy, scl, rgba, [origin[0] + (i / scl) * matr[0][0], origin[1]], weight / 4);
968
+ Chalkboard.vec2.plot(plotnegy, scl, rgba, [origin[0] + (i / scl) * matr[0][0], origin[1]], weight / 4);
969
+ }
970
+ var plotposaxisx = Chalkboard.vec2.new(matr[0][0], matr[1][0]);
971
+ var plotnegaxisx = Chalkboard.vec2.new(-matr[0][0], -matr[1][0]);
972
+ var plotposaxisy = Chalkboard.vec2.new(matr[0][1], matr[1][1]);
973
+ var plotnegaxisy = Chalkboard.vec2.new(-matr[0][1], -matr[1][1]);
974
+ Chalkboard.vec2.plot(plotposaxisx, scl, rgba, origin, weight);
975
+ Chalkboard.vec2.plot(plotnegaxisx, scl, rgba, origin, weight);
976
+ Chalkboard.vec2.plot(plotposaxisy, scl, rgba, origin, weight);
977
+ Chalkboard.vec2.plot(plotnegaxisy, scl, rgba, origin, weight);
978
+ return matr;
979
+ },
980
+ dfdx: function(func, scl, rgba, domain, origin, weight, res) {
981
+ scl = scl || 1;
982
+ scl /= 100;
983
+ rgba = rgba || [0, 0, 0];
984
+ domain = domain || [-10, 10];
985
+ origin = origin || [width / 2, height / 2];
986
+ weight = weight || 2;
987
+ res = res || 25;
988
+ var data = [];
989
+ pushMatrix();
990
+ translate(origin[0], origin[1]);
991
+ noFill();
992
+ strokeWeight(weight);
993
+ stroke(rgba.length === 3 ? color(rgba[0], rgba[1], rgba[2]) : color(rgba[0], rgba[1], rgba[2], rgba[3]));
994
+ beginShape();
995
+ for(var i = domain[0] / scl; i <= domain[1] / scl; i += res) {
996
+ vertex(i, -Chalkboard.calc.dfdx(func, i * scl) / scl);
997
+ data.push([i, Chalkboard.calc.dfdx(func, i)]);
998
+ }
999
+ endShape();
1000
+ popMatrix();
1001
+ return data;
1002
+ },
1003
+ d2fdx2: function(func, scl, rgba, domain, origin, weight, res) {
1004
+ scl = scl || 1;
1005
+ scl /= 100;
1006
+ rgba = rgba || [0, 0, 0];
1007
+ domain = domain || [-10, 10];
1008
+ origin = origin || [width / 2, height / 2];
1009
+ weight = weight || 2;
1010
+ res = res || 25;
1011
+ var data = [];
1012
+ pushMatrix();
1013
+ translate(origin[0], origin[1]);
1014
+ noFill();
1015
+ strokeWeight(weight);
1016
+ stroke(rgba.length === 3 ? color(rgba[0], rgba[1], rgba[2]) : color(rgba[0], rgba[1], rgba[2], rgba[3]));
1017
+ beginShape();
1018
+ for(var i = domain[0] / scl; i <= domain[1] / scl; i += res) {
1019
+ vertex(i, -Chalkboard.calc.d2fdx2(func, i * scl) / scl);
1020
+ data.push([i, Chalkboard.calc.d2fdx2(func, i)]);
1021
+ }
1022
+ endShape();
1023
+ popMatrix();
1024
+ return data;
1025
+ },
1026
+ fxdx: function(func, scl, rgba, domain, origin, weight, res) {
1027
+ scl = scl || 1;
1028
+ scl /= 100;
1029
+ rgba = rgba || [0, 0, 0];
1030
+ domain = domain || [-10, 10];
1031
+ origin = origin || [width / 2, height / 2];
1032
+ weight = weight || 2;
1033
+ res = res || 25;
1034
+ var data = [];
1035
+ pushMatrix();
1036
+ translate(origin[0], origin[1]);
1037
+ noFill();
1038
+ strokeWeight(weight);
1039
+ stroke(rgba.length === 3 ? color(rgba[0], rgba[1], rgba[2]) : color(rgba[0], rgba[1], rgba[2], rgba[3]));
1040
+ beginShape();
1041
+ for(var i = domain[0] / scl; i <= domain[1] / scl; i += res) {
1042
+ vertex(i, -Chalkboard.calc.fxdx(func, 0, i * scl) / scl);
1043
+ data.push([i, Chalkboard.calc.fxdx(func, 0, i)]);
1044
+ }
1045
+ endShape();
1046
+ popMatrix();
1047
+ return data;
1048
+ },
1049
+ convolution: function(func_1, func_2, scl, rgba, domain, origin, weight, res) {
1050
+ scl = scl || 1;
1051
+ scl /= 100;
1052
+ rgba = rgba || [0, 0, 0];
1053
+ domain = domain || [-10, 10];
1054
+ origin = origin || [width / 2, height / 2];
1055
+ weight = weight || 2;
1056
+ res = res || 25;
1057
+ var data = [];
1058
+ pushMatrix();
1059
+ translate(origin[0], origin[1]);
1060
+ noFill();
1061
+ strokeWeight(weight);
1062
+ stroke(rgba.length === 3 ? color(rgba[0], rgba[1], rgba[2]) : color(rgba[0], rgba[1], rgba[2], rgba[3]));
1063
+ beginShape();
1064
+ for(var i = domain[0] / scl; i <= domain[1] / scl; i += res) {
1065
+ vertex(i, -Chalkboard.calc.convolution(func_1, func_2, i * scl) / scl);
1066
+ data.push([i, Chalkboard.calc.convolution(func_1, func_2, i)]);
1067
+ }
1068
+ endShape();
1069
+ popMatrix();
1070
+ return data;
1071
+ },
1072
+ correlation: function(func_1, func_2, scl, rgba, domain, origin, weight, res) {
1073
+ scl = scl || 1;
1074
+ scl /= 100;
1075
+ rgba = rgba || [0, 0, 0];
1076
+ domain = domain || [-10, 10];
1077
+ origin = origin || [width / 2, height / 2];
1078
+ weight = weight || 2;
1079
+ res = res || 25;
1080
+ var data = [];
1081
+ pushMatrix();
1082
+ translate(origin[0], origin[1]);
1083
+ noFill();
1084
+ strokeWeight(weight);
1085
+ stroke(rgba.length === 3 ? color(rgba[0], rgba[1], rgba[2]) : color(rgba[0], rgba[1], rgba[2], rgba[3]));
1086
+ beginShape();
1087
+ for(var i = domain[0] / scl; i <= domain[1] / scl; i += res) {
1088
+ vertex(i, -Chalkboard.calc.correlation(func_1, func_2, i * scl) / scl);
1089
+ data.push([i, Chalkboard.calc.correlation(func_1, func_2, i)]);
1090
+ }
1091
+ endShape();
1092
+ popMatrix();
1093
+ return data;
1094
+ },
1095
+ autocorrelation: function(func, scl, rgba, domain, origin, weight, res) {
1096
+ scl = scl || 1;
1097
+ scl /= 100;
1098
+ rgba = rgba || [0, 0, 0];
1099
+ domain = domain || [-10, 10];
1100
+ origin = origin || [width / 2, height / 2];
1101
+ weight = weight || 2;
1102
+ res = res || 25;
1103
+ var data = [];
1104
+ pushMatrix();
1105
+ translate(origin[0], origin[1]);
1106
+ noFill();
1107
+ strokeWeight(weight);
1108
+ stroke(rgba.length === 3 ? color(rgba[0], rgba[1], rgba[2]) : color(rgba[0], rgba[1], rgba[2], rgba[3]));
1109
+ beginShape();
1110
+ for(var i = domain[0] / scl; i <= domain[1] / scl; i += res) {
1111
+ vertex(i, -Chalkboard.calc.autocorrelation(func, i * scl) / scl);
1112
+ data.push([i, Chalkboard.calc.autocorrelation(func, i)]);
1113
+ }
1114
+ endShape();
1115
+ popMatrix();
1116
+ return data;
1117
+ },
1118
+ Taylor: function(func, n, a, scl, rgba, domain, origin, weight, res) {
1119
+ scl = scl || 1;
1120
+ scl /= 100;
1121
+ rgba = rgba || [0, 0, 0];
1122
+ domain = domain || [-10, 10];
1123
+ origin = origin || [width / 2, height / 2];
1124
+ weight = weight || 2;
1125
+ res = res || 25;
1126
+ var data = [];
1127
+ pushMatrix();
1128
+ translate(origin[0], origin[1]);
1129
+ noFill();
1130
+ strokeWeight(weight);
1131
+ stroke(rgba.length === 3 ? color(rgba[0], rgba[1], rgba[2]) : color(rgba[0], rgba[1], rgba[2], rgba[3]));
1132
+ beginShape();
1133
+ for(var i = domain[0] / scl; i <= domain[1] / scl; i += res) {
1134
+ vertex(i, -Chalkboard.calc.Taylor(func, i * scl, n, a) / scl);
1135
+ data.push([i, Chalkboard.calc.Taylor(func, i, n, a)]);
1136
+ }
1137
+ endShape();
1138
+ popMatrix();
1139
+ return data;
1140
+ },
1141
+ Laplace: function(func, scl, rgba, domain, origin, weight, res) {
1142
+ scl = scl || 1;
1143
+ scl /= 100;
1144
+ rgba = rgba || [0, 0, 0];
1145
+ domain = domain || [-10, 10];
1146
+ origin = origin || [width / 2, height / 2];
1147
+ weight = weight || 2;
1148
+ res = res || 25;
1149
+ var data = [];
1150
+ pushMatrix();
1151
+ translate(origin[0], origin[1]);
1152
+ noFill();
1153
+ strokeWeight(weight);
1154
+ stroke(rgba.length === 3 ? color(rgba[0], rgba[1], rgba[2]) : color(rgba[0], rgba[1], rgba[2], rgba[3]));
1155
+ beginShape();
1156
+ if(domain[0] >= 0) {
1157
+ for(var i = domain[0] / scl; i <= domain[1] / scl; i += res) {
1158
+ vertex(i, -Chalkboard.calc.Laplace(func, i * scl) / scl);
1159
+ data.push([i, Chalkboard.calc.Laplace(func, i)]);
1160
+ }
1161
+ } else {
1162
+ for(var i = 0; i <= domain[1] / scl; i += res) {
1163
+ vertex(i, -Chalkboard.calc.Laplace(func, i * scl) / scl);
1164
+ data.push([i, Chalkboard.calc.Laplace(func, i)]);
1165
+ }
1166
+ }
1167
+ endShape();
1168
+ popMatrix();
1169
+ return data;
1170
+ },
1171
+ Fourier: function(func, scl, rgba, domain, origin, weight, res) {
1172
+ scl = scl || 1;
1173
+ scl /= 100;
1174
+ rgba = rgba || [0, 0, 0];
1175
+ domain = domain || [-10, 10];
1176
+ origin = origin || [width / 2, height / 2];
1177
+ weight = weight || 2;
1178
+ res = res || 25;
1179
+ var data = [];
1180
+ pushMatrix();
1181
+ translate(origin[0], origin[1]);
1182
+ noFill();
1183
+ strokeWeight(weight);
1184
+ stroke(rgba.length === 3 ? color(rgba[0], rgba[1], rgba[2]) : color(rgba[0], rgba[1], rgba[2], rgba[3]));
1185
+ beginShape();
1186
+ for(var i = domain[0] / scl; i <= domain[1] / scl; i += res) {
1187
+ vertex(i, -Chalkboard.calc.Fourier(func, i * scl) / scl);
1188
+ data.push([i, Chalkboard.calc.Fourier(func, i)]);
1189
+ }
1190
+ endShape();
1191
+ popMatrix();
1192
+ return data;
1193
+ }
1194
+ },
1195
+ geom: {
1196
+ EulerCharacteristic: function(v, e, f) {
1197
+ return v - e + f;
1198
+ },
1199
+ Pythagorean: function(a, b, type) {
1200
+ type = type || "hyp";
1201
+ if(type === "hyp") {
1202
+ return Math.sqrt((a * a) + (b * b));
1203
+ } else if(type === "leg") {
1204
+ return Math.sqrt((b * b) - (a * a));
1205
+ } else {
1206
+ return undefined;
1207
+ }
1208
+ },
1209
+ PythagoreanTriple: function(inf, sup) {
1210
+ var a = 2 * Math.round(Chalkboard.numb.random(inf, sup)) - 1,
1211
+ b = ((a * a) / 2) - 0.5,
1212
+ c = ((a * a) / 2) + 0.5;
1213
+ return a + ", " + b + ", " + c;
1214
+ },
1215
+ dist: function(p1, p2) {
1216
+ if(p1.length === p2.length) {
1217
+ var result = 0;
1218
+ for(var i = 0; i < p1.length; i++) {
1219
+ result += (p1[i] - p2[i]) * (p1[i] - p2[i]);
1220
+ }
1221
+ return Chalkboard.real.sqrt(result);
1222
+ } else {
1223
+ return undefined;
1224
+ }
1225
+ },
1226
+ distsq: function(p1, p2) {
1227
+ if(p1.length === p2.length) {
1228
+ var result = 0;
1229
+ for(var i = 0; i < p1.length; i++) {
1230
+ result += (p1[i] - p2[i]) * (p1[i] - p2[i]);
1231
+ }
1232
+ return result;
1233
+ } else {
1234
+ return undefined;
1235
+ }
1236
+ },
1237
+ mid: function(p1, p2) {
1238
+ if(p1.length === p2.length) {
1239
+ var result = [];
1240
+ for(var i = 0; i < p1.length; i++) {
1241
+ result[i] = (p1[i] + p2[i]) / 2;
1242
+ }
1243
+ return result;
1244
+ } else {
1245
+ return undefined;
1246
+ }
1247
+ },
1248
+ circleP: function(r) {
1249
+ return 2 * Chalkboard.PI() * r;
1250
+ },
1251
+ circleA: function(r) {
1252
+ return Chalkboard.PI() * r * r;
1253
+ },
1254
+ sectorP: function(r, rad) {
1255
+ return r * rad;
1256
+ },
1257
+ sectorA: function(r, rad) {
1258
+ return (r * r * rad) / 2;
1259
+ },
1260
+ ellipseP: function(a, b) {
1261
+ var h = ((a - b) * (a - b)) / ((a + b) * (a + b));
1262
+ return Chalkboard.PI() * (a + b) * (1 + (3 * h) / (10 + Math.sqrt(4 - 3 * h)));
1263
+ },
1264
+ ellipseA: function(a, b) {
1265
+ return Chalkboard.PI() * a * b;
1266
+ },
1267
+ squareP: function(s) {
1268
+ return 4 * s;
1269
+ },
1270
+ squareA: function(s) {
1271
+ return s * s;
1272
+ },
1273
+ parallelogramP: function(l, w) {
1274
+ return 2 * (l + w);
1275
+ },
1276
+ parallelogramA: function(l, w) {
1277
+ return l * w;
1278
+ },
1279
+ triangleP: function(a, b, c) {
1280
+ return a + b + c;
1281
+ },
1282
+ triangleA: function(b, h) {
1283
+ return (b * h) / 2;
1284
+ },
1285
+ trianglesidesA: function(a, b, c) {
1286
+ var s = (a + b + c) / 2;
1287
+ return Chalkboard.real.sqrt(s * ((s - a) * (s - b) * (s - c)));
1288
+ },
1289
+ trapezoidP: function(a, b, c, d) {
1290
+ return a + b + c + d;
1291
+ },
1292
+ trapezoidA: function(b1, b2, h) {
1293
+ return ((b1 + b2) / 2) * h;
1294
+ },
1295
+ polygonP: function(n, s) {
1296
+ return n * s;
1297
+ },
1298
+ polygonA: function(n, s, a) {
1299
+ return (n * s * a) / 2;
1300
+ },
1301
+ sphereA: function(r) {
1302
+ return 4 * Chalkboard.PI() * r * r;
1303
+ },
1304
+ sphereV: function(r) {
1305
+ return (4 * Chalkboard.PI() * r * r * r) / 3;
1306
+ },
1307
+ cylinderA: function(r, h) {
1308
+ return 2 * Chalkboard.PI() * r * r + 2 * Math.PI * r * h;
1309
+ },
1310
+ cylinderV: function(r, h) {
1311
+ return Chalkboard.PI() * r * r * h;
1312
+ },
1313
+ coneA: function(r, h) {
1314
+ return Chalkboard.PI() * r * (r + Math.sqrt(h * h + r * r));
1315
+ },
1316
+ coneV: function(r, h) {
1317
+ return (Chalkboard.PI() * r * r * h) / 3;
1318
+ },
1319
+ cubeA: function(s) {
1320
+ return 6 * s * s;
1321
+ },
1322
+ cubeV: function(s) {
1323
+ return s * s * s;
1324
+ },
1325
+ rectangularprismA: function(l, w, h) {
1326
+ return 2 * (l * h + l * h + w * h);
1327
+ },
1328
+ rectangularprismV: function(l, w, h) {
1329
+ return l * w * h;
1330
+ },
1331
+ triangularprismA: function(a, b, c, h) {
1332
+ var s = (a + b + c) / 2;
1333
+ return 2 * Chalkboard.real.sqrt(s * ((s - a) * (s - b) * (s - c))) + h * (a + b + c);
1334
+ },
1335
+ triangularprismV: function(a, b, c, h) {
1336
+ 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;
1337
+ },
1338
+ line3D: function(x1, y1, z1, x2, y2, z2) {
1339
+ line(x1 / (z1 * 0.0025 + 1), y1 / (z1 * 0.0025 + 1), x2 / (z2 * 0.0025 + 1), y2 / (z2 * 0.0025 + 1));
1340
+ }
1341
+ },
1342
+ trig: {
1343
+ toRad: function(deg) {
1344
+ return deg * (Chalkboard.PI() / 180);
1345
+ },
1346
+ toDeg: function(rad) {
1347
+ return rad * (180 / Chalkboard.PI());
1348
+ },
1349
+ coterminal: function(rad) {
1350
+ return rad % (2 * Chalkboard.PI());
1351
+ },
1352
+ sin: function(rad) {
1353
+ rad = Chalkboard.trig.coterminal(rad);
1354
+ return ((rad) - (Math.pow(rad, 3) / Chalkboard.numb.factorial(3)) + (Math.pow(rad, 5) / Chalkboard.numb.factorial(5)) - (Math.pow(rad, 7) / Chalkboard.numb.factorial(7)) + (Math.pow(rad, 9) / Chalkboard.numb.factorial(9)) - (Math.pow(rad, 11) / Chalkboard.numb.factorial(11)) + (Math.pow(rad, 13) / Chalkboard.numb.factorial(13)) - (Math.pow(rad, 15) / Chalkboard.numb.factorial(15)) + (Math.pow(rad, 17) / Chalkboard.numb.factorial(17)) - (Math.pow(rad, 19) / Chalkboard.numb.factorial(19)) + (Math.pow(rad, 21) / Chalkboard.numb.factorial(21)) - (Math.pow(rad, 23) / Chalkboard.numb.factorial(23)) + (Math.pow(rad, 25) / Chalkboard.numb.factorial(25)) - (Math.pow(rad, 27) / Chalkboard.numb.factorial(27)) + (Math.pow(rad, 29) / Chalkboard.numb.factorial(29)));
1355
+ },
1356
+ cos: function(rad) {
1357
+ rad = Chalkboard.trig.coterminal(rad);
1358
+ return ((1) - (Math.pow(rad, 2) / Chalkboard.numb.factorial(2)) + (Math.pow(rad, 4) / Chalkboard.numb.factorial(4)) - (Math.pow(rad, 6) / Chalkboard.numb.factorial(6)) + (Math.pow(rad, 8) / Chalkboard.numb.factorial(8)) - (Math.pow(rad, 10) / Chalkboard.numb.factorial(10)) + (Math.pow(rad, 12) / Chalkboard.numb.factorial(12)) - (Math.pow(rad, 14) / Chalkboard.numb.factorial(14)) + (Math.pow(rad, 16) / Chalkboard.numb.factorial(16)) - (Math.pow(rad, 18) / Chalkboard.numb.factorial(18)) + (Math.pow(rad, 20) / Chalkboard.numb.factorial(20)) - (Math.pow(rad, 22) / Chalkboard.numb.factorial(22)) + (Math.pow(rad, 24) / Chalkboard.numb.factorial(24)) - (Math.pow(rad, 26) / Chalkboard.numb.factorial(26)) + (Math.pow(rad, 28) / Chalkboard.numb.factorial(28)));
1359
+ },
1360
+ tan: function(rad) {
1361
+ return Chalkboard.trig.sin(rad) / Chalkboard.trig.cos(rad);
1362
+ },
1363
+ csc: function(rad) {
1364
+ return 1 / Chalkboard.trig.sin(rad);
1365
+ },
1366
+ sec: function(rad) {
1367
+ return 1 / Chalkboard.trig.cos(rad);
1368
+ },
1369
+ cot: function(rad) {
1370
+ return 1 / Chalkboard.trig.tan(rad);
1371
+ },
1372
+ sinh: function(rad) {
1373
+ return (Math.pow(Chalkboard.E(), rad) - Math.pow(Chalkboard.E(), -rad)) / 2;
1374
+ },
1375
+ cosh: function(rad) {
1376
+ return (Math.pow(Chalkboard.E(), rad) + Math.pow(Chalkboard.E(), -rad)) / 2;
1377
+ },
1378
+ tanh: function(rad) {
1379
+ return Chalkboard.trig.sinh(rad) / Chalkboard.trig.cosh(rad);
1380
+ },
1381
+ csch: function(rad) {
1382
+ return 1 / Chalkboard.trig.sinh(rad);
1383
+ },
1384
+ sech: function(rad) {
1385
+ return 1 / Chalkboard.trig.cosh(rad);
1386
+ },
1387
+ coth: function(rad) {
1388
+ return 1 / Chalkboard.trig.tanh(rad);
1389
+ },
1390
+ arcsin: function(rad) {
1391
+ if(rad > -1 && rad < 1) {
1392
+ return Chalkboard.calc.fxdx(Chalkboard.real.function("1 / (Math.sqrt(1 - x * x))"), 0, rad);
1393
+ } else if(rad === 1) {
1394
+ return Chalkboard.PI() / 2;
1395
+ } else if(rad === -1) {
1396
+ return -Chalkboard.PI() / 2;
1397
+ } else {
1398
+ return undefined;
1399
+ }
1400
+ },
1401
+ arccos: function(rad) {
1402
+ if(rad > -1 && rad < 1) {
1403
+ return Chalkboard.calc.fxdx(Chalkboard.real.function("1 / (Math.sqrt(1 - x * x))"), rad, 1);
1404
+ } else if(rad === 1) {
1405
+ return 0;
1406
+ } else if(rad === -1) {
1407
+ return Chalkboard.PI();
1408
+ } else {
1409
+ return undefined;
1410
+ }
1411
+ },
1412
+ arctan: function(rad) {
1413
+ return Chalkboard.calc.fxdx(Chalkboard.real.function("1 / (1 + x * x)"), 0, rad);
1414
+ },
1415
+ arctan2: function(y, x) {
1416
+ if(x === 0) {
1417
+ if(y > 0) {
1418
+ return Math.PI / 2;
1419
+ } else if(y < 0) {
1420
+ return -Math.PI / 2;
1421
+ } else {
1422
+ return 0;
1423
+ }
1424
+ } else {
1425
+ if(x > 0 && y >= 0) {
1426
+ return Math.atan(Math.abs(y / x));
1427
+ } else if(x < 0 && y >= 0) {
1428
+ return Math.PI - Math.atan(Math.abs(y / x));
1429
+ } else if(x < 0 && y < 0) {
1430
+ return -Math.PI + Math.atan(Math.abs(y / x));
1431
+ } else {
1432
+ return -Math.atan(Math.abs(y / x));
1433
+ }
1434
+ }
1435
+ },
1436
+ arccsc: function(rad) {
1437
+ if(rad > 1) {
1438
+ return Chalkboard.calc.fxdx(Chalkboard.real.function("1 / (x * Math.sqrt(x * x - 1))"), rad, 1000);
1439
+ } else if(rad === 1) {
1440
+ return Chalkboard.PI() / 2;
1441
+ } else if(rad === -1) {
1442
+ return -Chalkboard.PI() / 2;
1443
+ } else if(rad < 1) {
1444
+ return -Chalkboard.calc.fxdx(Chalkboard.real.function("1 / (x * Math.sqrt(x * x - 1))"), Math.abs(rad), 1000);
1445
+ } else {
1446
+ return undefined;
1447
+ }
1448
+ },
1449
+ arcsec: function(rad) {
1450
+ if(rad > 1) {
1451
+ return Chalkboard.calc.fxdx(Chalkboard.real.function("1 / (x * Math.sqrt(x * x - 1))"), 1.000001, rad);
1452
+ } else if(rad === 1) {
1453
+ return 0;
1454
+ } else if(rad === -1) {
1455
+ return Chalkboard.PI();
1456
+ } else {
1457
+ return undefined;
1458
+ }
1459
+ },
1460
+ arccot: function(rad) {
1461
+ return Chalkboard.calc.fxdx(Chalkboard.real.function("1 / (1 + x * x)"), rad, 1000);
1462
+ },
1463
+ arcsinh: function(rad) {
1464
+ return Math.log(rad + Math.sqrt(rad * rad + 1));
1465
+ },
1466
+ arccosh: function(rad) {
1467
+ if(rad >= 1) {
1468
+ return Math.log(rad + Math.sqrt(rad * rad - 1));
1469
+ } else {
1470
+ return undefined;
1471
+ }
1472
+ },
1473
+ arctanh: function(rad) {
1474
+ if(rad > -1 && rad < 1) {
1475
+ return (Math.log((1 + rad) / (1 - rad))) / 2;
1476
+ } else {
1477
+ return undefined;
1478
+ }
1479
+ },
1480
+ arccsch: function(rad) {
1481
+ if(rad !== 0) {
1482
+ return Math.log((1 / rad) + Math.sqrt((1 / (rad * rad)) + 1));
1483
+ } else {
1484
+ return undefined;
1485
+ }
1486
+ },
1487
+ arcsech: function(rad) {
1488
+ if(rad > 0 && rad <= 1) {
1489
+ return Math.log((1 / rad) + Math.sqrt((1 / (rad * rad)) - 1));
1490
+ } else {
1491
+ return undefined;
1492
+ }
1493
+ },
1494
+ arccoth: function(rad) {
1495
+ if(rad < -1 || rad > 1) {
1496
+ return (Math.log((rad + 1) / (rad - 1))) / 2;
1497
+ } else {
1498
+ return undefined;
1499
+ }
1500
+ }
1501
+ },
1502
+ stat: {
1503
+ array: function(inf, sup, length) {
1504
+ length = length || sup - inf + 1;
1505
+ var result = [];
1506
+ var step = (sup - inf) / (length - 1);
1507
+ for(var i = 0; i < length; i++) {
1508
+ result.push(inf + (step * i));
1509
+ }
1510
+ return result;
1511
+ },
1512
+ random: function(inf, sup, length) {
1513
+ var result = [];
1514
+ for(var i = 0; i < length; i++) {
1515
+ result.push(Chalkboard.numb.random(inf, sup));
1516
+ }
1517
+ return result;
1518
+ },
1519
+ norm: function(arr, type) {
1520
+ type = type || "L2";
1521
+ var result = 0;
1522
+ if(type === "L0") {
1523
+ for(var i = 0; i < arr.length; i++) {
1524
+ if(arr[i] !== 0) {
1525
+ result += 1;
1526
+ }
1527
+ }
1528
+ return result;
1529
+ } else if(type === "L1") {
1530
+ for(var i = 0; i < arr.length; i++) {
1531
+ result += Math.abs(arr[i]);
1532
+ }
1533
+ return result;
1534
+ } else if(type === "L2") {
1535
+ for(var i = 0; i < arr.length; i++) {
1536
+ result += arr[i] * arr[i];
1537
+ }
1538
+ return Chalkboard.real.sqrt(result);
1539
+ } else if(type === "LInfinity") {
1540
+ return Math.abs(Chalkboard.stat.max(arr));
1541
+ } else {
1542
+ return "TypeError: Parameter \"type\" must be \"L0\", \"L1\", \"L2\", or \"LInfinity\".";
1543
+ }
1544
+ },
1545
+ normsq: function(arr, type) {
1546
+ type = type || "L2";
1547
+ var result = 0;
1548
+ if(type === "L0") {
1549
+ for(var i = 0; i < arr.length; i++) {
1550
+ if(arr[i] !== 0) {
1551
+ result += 1;
1552
+ }
1553
+ }
1554
+ return result * result;
1555
+ } else if(type === "L1") {
1556
+ for(var i = 0; i < arr.length; i++) {
1557
+ result += Math.abs(arr[i]);
1558
+ }
1559
+ return result * result;
1560
+ } else if(type === "L2") {
1561
+ for(var i = 0; i < arr.length; i++) {
1562
+ result += arr[i] * arr[i];
1563
+ }
1564
+ return result;
1565
+ } else if(type === "LInfinity") {
1566
+ return Math.abs(Chalkboard.stat.max(arr)) * Math.abs(Chalkboard.stat.max(arr));
1567
+ } else {
1568
+ return "TypeError: Parameter \"type\" must be \"L0\", \"L1\", \"L2\", or \"LInfinity\".";
1569
+ }
1570
+ },
1571
+ normalize: function(arr, type) {
1572
+ if(type === "L0" || type === "L1" || type === "L2" || type === "LInfinity") {
1573
+ var result = [];
1574
+ var norm = Chalkboard.stat.norm(arr, type);
1575
+ for(var i = 0; i < arr.length; i++) {
1576
+ result.push(arr[i] / norm);
1577
+ }
1578
+ return result;
1579
+ } else {
1580
+ return "TypeError: Parameter \"type\" must be \"L0\", \"L1\", \"L2\", or \"LInfinity\".";
1581
+ }
1582
+ },
1583
+ constrain: function(arr, range) {
1584
+ var result = [];
1585
+ for(var i = 0; i < arr.length; i++) {
1586
+ result.push(Chalkboard.numb.constrain(arr[i], range));
1587
+ }
1588
+ return result;
1589
+ },
1590
+ eq: function(arr, arrORnum) {
1591
+ var result = [];
1592
+ if(arrORnum.constructor === Array) {
1593
+ if(arr.length === arrORnum.length) {
1594
+ for(var i = 0; i < arr.length; i++) {
1595
+ if(arr[i] === arrORnum[i]) {
1596
+ result.push(arr[i]);
1597
+ }
1598
+ }
1599
+ }
1600
+ } else {
1601
+ for(var i = 0; i < arr.length; i++) {
1602
+ if(arr[i] === arrORnum) {
1603
+ result.push(arr[i]);
1604
+ }
1605
+ }
1606
+ }
1607
+ return result;
1608
+ },
1609
+ ineq: function(arr, inf, sup, includeInf, includeSup) {
1610
+ includeInf = includeInf || false;
1611
+ includeSup = includeSup || false;
1612
+ var result = [];
1613
+ if(inf.constructor === Array && sup.constructor === Array) {
1614
+ if(arr.length === inf.length && arr.length === sup.length) {
1615
+ for(var i = 0; i < arr.length; i++) {
1616
+ if(includeInf) {
1617
+ if(includeSup) {
1618
+ if(arr[i] >= inf[i] && arr[i] <= sup[i]) {
1619
+ result.push(arr[i]);
1620
+ }
1621
+ } else {
1622
+ if(arr[i] >= inf[i] && arr[i] < sup[i]) {
1623
+ result.push(arr[i]);
1624
+ }
1625
+ }
1626
+ } else {
1627
+ if(includeSup) {
1628
+ if(arr[i] > inf[i] && arr[i] <= sup[i]) {
1629
+ result.push(arr[i]);
1630
+ }
1631
+ } else {
1632
+ if(arr[i] > inf[i] && arr[i] < sup[i]) {
1633
+ result.push(arr[i]);
1634
+ }
1635
+ }
1636
+ }
1637
+ }
1638
+ }
1639
+ } else {
1640
+ for(var i = 0; i < arr.length; i++) {
1641
+ if(includeInf) {
1642
+ if(includeSup) {
1643
+ if(arr[i] >= inf && arr[i] <= sup) {
1644
+ result.push(arr[i]);
1645
+ }
1646
+ } else {
1647
+ if(arr[i] >= inf && arr[i] < sup) {
1648
+ result.push(arr[i]);
1649
+ }
1650
+ }
1651
+ } else {
1652
+ if(includeSup) {
1653
+ if(arr[i] > inf && arr[i] <= sup) {
1654
+ result.push(arr[i]);
1655
+ }
1656
+ } else {
1657
+ if(arr[i] > inf && arr[i] < sup) {
1658
+ result.push(arr[i]);
1659
+ }
1660
+ }
1661
+ }
1662
+ }
1663
+ }
1664
+ return result;
1665
+ },
1666
+ lt: function(arr, arrORnum, includeEnd) {
1667
+ includeEnd = includeEnd || false;
1668
+ var result = [];
1669
+ if(arrORnum.constructor === Array) {
1670
+ if(arr.length === arrORnum.length) {
1671
+ for(var i = 0; i < arr.length; i++) {
1672
+ if(includeEnd) {
1673
+ if(arr[i] <= arrORnum[i]) {
1674
+ result.push(arr[i]);
1675
+ }
1676
+ } else {
1677
+ if(arr[i] < arrORnum[i]) {
1678
+ result.push(arr[i]);
1679
+ }
1680
+ }
1681
+ }
1682
+ }
1683
+ } else {
1684
+ for(var i = 0; i < arr.length; i++) {
1685
+ if(includeEnd) {
1686
+ if(arr[i] <= arrORnum) {
1687
+ result.push(arr[i]);
1688
+ }
1689
+ } else {
1690
+ if(arr[i] < arrORnum) {
1691
+ result.push(arr[i]);
1692
+ }
1693
+ }
1694
+ }
1695
+ }
1696
+ return result;
1697
+ },
1698
+ gt: function(arr, arrORnum, includeEnd) {
1699
+ includeEnd = includeEnd || false;
1700
+ var result = [];
1701
+ if(arrORnum.constructor === Array) {
1702
+ if(arr.length === arrORnum.length) {
1703
+ for(var i = 0; i < arr.length; i++) {
1704
+ if(includeEnd) {
1705
+ if(arr[i] >= arrORnum[i]) {
1706
+ result.push(arr[i]);
1707
+ }
1708
+ } else {
1709
+ if(arr[i] > arrORnum[i]) {
1710
+ result.push(arr[i]);
1711
+ }
1712
+ }
1713
+ }
1714
+ }
1715
+ } else {
1716
+ for(var i = 0; i < arr.length; i++) {
1717
+ if(includeEnd) {
1718
+ if(arr[i] >= arrORnum) {
1719
+ result.push(arr[i]);
1720
+ }
1721
+ } else {
1722
+ if(arr[i] > arrORnum) {
1723
+ result.push(arr[i]);
1724
+ }
1725
+ }
1726
+ }
1727
+ }
1728
+ return result;
1729
+ },
1730
+ max: function(arr) {
1731
+ var max = arr[0];
1732
+ for(var i = 0; i < arr.length; i++) {
1733
+ if(arr[i] > max) {
1734
+ max = arr[i];
1735
+ }
1736
+ }
1737
+ return max;
1738
+ },
1739
+ min: function(arr) {
1740
+ var min = arr[0];
1741
+ for(var i = 0; i < arr.length; i++) {
1742
+ if(arr[i] < min) {
1743
+ min = arr[i];
1744
+ }
1745
+ }
1746
+ return min;
1747
+ },
1748
+ range: function(arr) {
1749
+ return Chalkboard.stat.max(arr) - Chalkboard.stat.min(arr);
1750
+ },
1751
+ mean: function(arr, type) {
1752
+ type = type || "arithmetic";
1753
+ var result = 0;
1754
+ if(type === "arithmetic") {
1755
+ for(var i = 0; i < arr.length; i++) {
1756
+ result += arr[i];
1757
+ }
1758
+ return result / arr.length;
1759
+ } else if(type === "geometric") {
1760
+ for(var i = 0; i < arr.length; i++) {
1761
+ result *= arr[i];
1762
+ }
1763
+ return Chalkboard.real.nrt(Math.abs(result), arr.length);
1764
+ } else if(type === "harmonic") {
1765
+ for(var i = 0; i < arr.length; i++) {
1766
+ result += 1 / arr[i];
1767
+ }
1768
+ return arr.length / result;
1769
+ } else {
1770
+ return "TypeError: Parameter \"type\" must be \"arithmetic\", \"geometric\", or \"harmonic\".";
1771
+ }
1772
+ },
1773
+ median: function(arr) {
1774
+ var temp = arr.slice().sort(function(a, b) {
1775
+ return a - b;
1776
+ });
1777
+ if(temp.length % 2 === 1) {
1778
+ return temp[Math.floor(temp.length / 2)];
1779
+ } else {
1780
+ return (temp[temp.length / 2] + temp[(temp.length / 2) - 1]) / 2;
1781
+ }
1782
+ },
1783
+ mode: function(arr) {
1784
+ var temp = arr.slice().sort(function(a, b) {
1785
+ return a - b;
1786
+ });
1787
+ var bestStr = 1;
1788
+ var currStr = 1;
1789
+ var bestElm = temp[0];
1790
+ var currElm = temp[0];
1791
+ for(var i = 1; i < temp.length; i++) {
1792
+ if(temp[i - 1] !== temp[i]) {
1793
+ if(currStr > bestStr) {
1794
+ bestStr = currStr;
1795
+ bestElm = currElm;
1796
+ }
1797
+ currStr = 0;
1798
+ currElm = temp[i];
1799
+ }
1800
+ currStr++;
1801
+ }
1802
+ if(currStr > bestStr) {
1803
+ return currElm;
1804
+ } else {
1805
+ return bestElm;
1806
+ }
1807
+ },
1808
+ deviation: function(arr) {
1809
+ var result = 0;
1810
+ for(var i = 0; i < arr.length; i++) {
1811
+ result += (arr[i] - Chalkboard.stat.mean(arr)) * (arr[i] - Chalkboard.stat.mean(arr));
1812
+ }
1813
+ return Chalkboard.real.sqrt(result / arr.length);
1814
+ },
1815
+ variance: function(arr) {
1816
+ var result = 0;
1817
+ for(var i = 0; i < arr.length; i++) {
1818
+ result += (arr[i] - Chalkboard.stat.mean(arr)) * (arr[i] - Chalkboard.stat.mean(arr));
1819
+ }
1820
+ return result / arr.length;
1821
+ },
1822
+ mad: function(arr) {
1823
+ var result = 0;
1824
+ for(var i = 0; i < arr.length; i++) {
1825
+ result += Math.abs(arr[i] - Chalkboard.stat.mean(arr));
1826
+ }
1827
+ return result / arr.length;
1828
+ },
1829
+ error: function(arr) {
1830
+ return Chalkboard.stat.deviation(arr) / Chalkboard.real.sqrt(arr.length);
1831
+ },
1832
+ skewness: function(arr) {
1833
+ var result = 0;
1834
+ var mean = Chalkboard.stat.mean(arr);
1835
+ var deviation = Chalkboard.stat.deviation(arr);
1836
+ for(var i = 0; i < arr.length; i++) {
1837
+ result += (arr[i] - mean) * (arr[i] - mean) * (arr[i] - mean);
1838
+ }
1839
+ return result / ((arr.length - 1) * (deviation * deviation * deviation));
1840
+ },
1841
+ kurtosis: function(arr) {
1842
+ var result = 0;
1843
+ var mean = Chalkboard.stat.mean(arr);
1844
+ var deviation = Chalkboard.stat.deviation(arr);
1845
+ for(var i = 0; i < arr.length; i++) {
1846
+ result += (arr[i] - mean) * (arr[i] - mean) * (arr[i] - mean) * (arr[i] - mean);
1847
+ }
1848
+ return result / (deviation * deviation * deviation * deviation) - 3;
1849
+ },
1850
+ confidenceInterval: function(arr) {
1851
+ return [Chalkboard.stat.mean(arr) - 1.96 * (Chalkboard.stat.deviation(arr) / Chalkboard.real.sqrt(arr.length)), Chalkboard.stat.mean(arr) + 1.96 * (Chalkboard.stat.deviation(arr) / Chalkboard.real.sqrt(arr.length))];
1852
+ },
1853
+ percentile: function(arr, num) {
1854
+ var result = 0;
1855
+ for(var i = 0; i < arr.length; i++) {
1856
+ if(num >= arr[i]) {
1857
+ result++;
1858
+ }
1859
+ }
1860
+ return (result / arr.length) * 100;
1861
+ },
1862
+ quartile: function(arr, type) {
1863
+ var temp = arr.slice().sort(function(a, b) {
1864
+ return a - b;
1865
+ });
1866
+ var lo = temp.slice(0, Math.floor(temp.length / 2));
1867
+ var hi = temp.slice(Math.ceil(temp.length / 2));
1868
+ if(type === "Q1") {
1869
+ return Chalkboard.stat.median(lo);
1870
+ } else if(type === "Q2") {
1871
+ return Chalkboard.stat.median(arr);
1872
+ } else if(type === "Q3") {
1873
+ return Chalkboard.stat.median(hi);
1874
+ } else {
1875
+ return "TypeError: Parameter \"type\" must be either \"Q1\", \"Q2\", or \"Q3\".";
1876
+ }
1877
+ },
1878
+ convolution: function(arr1, arr2) {
1879
+ var result = [];
1880
+ for(var i = 0; i < arr1.length + arr2.length - 1; i++) {
1881
+ var sum = 0;
1882
+ for(var j = Math.max(0, i - arr2.length + 1); j < Math.min(arr1.length, i + 1); j++) {
1883
+ sum += arr1[j] * arr2[i - j];
1884
+ }
1885
+ result.push(sum);
1886
+ }
1887
+ return result;
1888
+ },
1889
+ correlation: function(arr1, arr2) {
1890
+ var result = [];
1891
+ for(var i = 0; i < arr1.length + arr2.length - 1; i++) {
1892
+ var sum = 0;
1893
+ for(var j = Math.max(0, i - arr2.length + 1); j < Math.min(arr1.length, i + 1); j++) {
1894
+ sum += arr1[j] * arr2[arr2.length - 1 - i + j];
1895
+ }
1896
+ result.push(sum);
1897
+ }
1898
+ return result;
1899
+ },
1900
+ autocorrelation: function(arr) {
1901
+ return Chalkboard.stat.correlation(arr, arr);
1902
+ },
1903
+ change: function(initialArr, finalArr) {
1904
+ var result = [];
1905
+ if(initialArr.length === finalArr.length) {
1906
+ for(var i = 0; i < initialArr.length; i++) {
1907
+ result.push(Chalkboard.numb.change(initialArr[i], finalArr[i]));
1908
+ }
1909
+ return result;
1910
+ } else {
1911
+ return undefined;
1912
+ }
1913
+ },
1914
+ chiSquared: function(observedArr, expectedArr) {
1915
+ var result = [];
1916
+ if(observedArr.length === expectedArr.length) {
1917
+ for(var i = 0; i < observedArr.length; i++) {
1918
+ result.push(((observedArr[i] - expectedArr[i]) * (observedArr[i] - expectedArr[i])) / expectedArr[i]);
1919
+ }
1920
+ return result;
1921
+ } else {
1922
+ return undefined;
1923
+ }
1924
+ },
1925
+ Gaussian: function(height, mean, deviation) {
1926
+ return Chalkboard.real.function(height.toString() + " * Math.exp(-((x - " + mean.toString() + ") * (x - " + mean.toString() + ")) / (2 * " + deviation.toString() + " * " + deviation.toString() + "))");
1927
+ },
1928
+ toVector: function(arr, type) {
1929
+ if(type === "vec2") {
1930
+ return Chalkboard.vec2.new(arr[0], arr[1]);
1931
+ } else if(type === "vec3") {
1932
+ return Chalkboard.vec3.new(arr[0], arr[1], arr[2]);
1933
+ } else if(type === "vec4") {
1934
+ return Chalkboard.vec4.new(arr[0], arr[1], arr[2], arr[3]);
1935
+ } else {
1936
+ return "TypeError: Parameter \"type\" should be \"vec2\", \"vec3\", or \"vec4\".";
1937
+ }
1938
+ },
1939
+ toMatrix: function(arr, rows, cols) {
1940
+ var result = Chalkboard.matr.new();
1941
+ var index = 0;
1942
+ for(var i = 0; i < rows; i++) {
1943
+ result[i] = [];
1944
+ for(var j = 0; j < cols; j++) {
1945
+ if(index < arr.length) {
1946
+ result[i].push(arr[index]);
1947
+ } else {
1948
+ result[i].push(0);
1949
+ }
1950
+ index++;
1951
+ }
1952
+ }
1953
+ return result;
1954
+ },
1955
+ toObject: function(arr) {
1956
+ var result = {};
1957
+ for(var i = 0; i < arr.length; i++) {
1958
+ result["_" + i] = arr[i];
1959
+ }
1960
+ return result;
1961
+ },
1962
+ toString: function(arr) {
1963
+ return "[" + arr.join(", ") + "]";
1964
+ },
1965
+ print: function(arr) {
1966
+ console.log(Chalkboard.stat.toString(arr));
1967
+ }
1968
+ },
1969
+ vec2: {
1970
+ new: function(x, y) {
1971
+ if(y === undefined) {
1972
+ return {x: x, y: x, type: "vec2"};
1973
+ } else {
1974
+ return {x: x, y: y, type: "vec2"};
1975
+ }
1976
+ },
1977
+ random: function(inf, sup) {
1978
+ return Chalkboard.vec2.new(Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup));
1979
+ },
1980
+ mag: function(vec2) {
1981
+ return Chalkboard.real.sqrt((vec2.x * vec2.x) + (vec2.y * vec2.y));
1982
+ },
1983
+ magsq: function(vec2) {
1984
+ return (vec2.x * vec2.x) + (vec2.y * vec2.y);
1985
+ },
1986
+ magset: function(vec2, num) {
1987
+ return Chalkboard.vec2.scl(Chalkboard.vec2.normalize(vec2), num);
1988
+ },
1989
+ ang: function(vec2) {
1990
+ return Chalkboard.trig.arctan2(vec2.y, vec2.x);
1991
+ },
1992
+ slope: function(vec2) {
1993
+ return vec2.y / vec2.x;
1994
+ },
1995
+ azimuth: function(vec2) {
1996
+ return Chalkboard.trig.arctan(vec2.x / vec2.y);
1997
+ },
1998
+ average: function(vec2) {
1999
+ return (vec2.x + vec2.y) / 2;
2000
+ },
2001
+ normalize: function(vec2) {
2002
+ return Chalkboard.vec2.new(vec2.x / Chalkboard.vec2.mag(vec2), vec2.y / Chalkboard.vec2.mag(vec2));
2003
+ },
2004
+ zero: function(vec2) {
2005
+ return Chalkboard.vec2.new(vec2.x * 0, vec2.y * 0);
2006
+ },
2007
+ negate: function(vec2) {
2008
+ return Chalkboard.vec2.new(-vec2.x, -vec2.y);
2009
+ },
2010
+ reciprocate: function(vec2) {
2011
+ return Chalkboard.vec2.new(1 / vec2.x, 1 / vec2.y);
2012
+ },
2013
+ absolute: function(vec2) {
2014
+ return Chalkboard.vec2.new(Math.abs(vec2.x), Math.abs(vec2.y));
2015
+ },
2016
+ round: function(vec2) {
2017
+ return Chalkboard.vec2.new(Math.round(vec2.x), Math.round(vec2.y));
2018
+ },
2019
+ dist: function(vec2_1, vec2_2) {
2020
+ return Chalkboard.real.sqrt(((vec2_2.x - vec2_1.x) * (vec2_2.x - vec2_1.x)) + ((vec2_2.y - vec2_1.y) * (vec2_2.y - vec2_1.y)));
2021
+ },
2022
+ distsq: function(vec2_1, vec2_2) {
2023
+ return ((vec2_2.x - vec2_1.x) * (vec2_2.x - vec2_1.x)) + ((vec2_2.y - vec2_1.y) * (vec2_2.y - vec2_1.y));
2024
+ },
2025
+ angBtwn: function(vec2_1, vec2_2) {
2026
+ return Math.acos((Chalkboard.vec2.dot(vec2_1, vec2_2)) / (Chalkboard.vec2.mag(vec2_1) * Chalkboard.vec2.mag(vec2_2)));
2027
+ },
2028
+ scl: function(vec2, num) {
2029
+ return Chalkboard.vec2.new(vec2.x * num, vec2.y * num);
2030
+ },
2031
+ constrain: function(vec2, range) {
2032
+ return Chalkboard.vec2.new(Chalkboard.numb.constrain(vec2.x, range), Chalkboard.numb.constrain(vec2.y, range));
2033
+ },
2034
+ add: function(vec2_1, vec2_2) {
2035
+ return Chalkboard.vec2.new(vec2_1.x + vec2_2.x, vec2_1.y + vec2_2.y);
2036
+ },
2037
+ sub: function(vec2_1, vec2_2) {
2038
+ return Chalkboard.vec2.new(vec2_1.x - vec2_2.x, vec2_1.y - vec2_2.y);
2039
+ },
2040
+ mid: function(vec2_1, vec2_2) {
2041
+ return Chalkboard.vec2.new((vec2_1.x + vec2_2.x) / 2, (vec2_1.y + vec2_2.y) / 2);
2042
+ },
2043
+ dot: function(vec2_1, vec2_2) {
2044
+ return (vec2_1.x * vec2_2.x) + (vec2_1.y * vec2_2.y);
2045
+ },
2046
+ cross: function(vec2_1, vec2_2) {
2047
+ return Chalkboard.vec3.new(0, 0, (vec2_1.x * vec2_2.y) - (vec2_1.y * vec2_2.x));
2048
+ },
2049
+ proj: function(vec2_1, vec2_2) {
2050
+ return Chalkboard.vec2.scl(vec2_2, Chalkboard.vec2.dot(vec2_1, vec2_2) / Chalkboard.vec2.dot(vec2_2, vec2_2));
2051
+ },
2052
+ oproj: function(vec2_1, vec2_2) {
2053
+ return Chalkboard.vec2.sub(vec2_1, Chalkboard.vec2.proj(vec2_1, vec2_2));
2054
+ },
2055
+ reflect: function(vec2_1, vec2_2) {
2056
+ return Chalkboard.vec2.sub(vec2_1, Chalkboard.vec2.scl(vec2_2, 2 * Chalkboard.vec2.dot(vec2_1, vec2_2)));
2057
+ },
2058
+ refract: function(vec2_1, vec2_2, refractiveIndex) {
2059
+ if(refractiveIndex > 0) {
2060
+ var perp = Chalkboard.vec2.scl(Chalkboard.vec2.sub(vec2_1, Chalkboard.vec2.scl(vec2_2, Chalkboard.vec2.dot(vec2_1, vec2_2))), refractiveIndex);
2061
+ var parr = Chalkboard.vec2.scl(vec2_2, -Chalkboard.real.sqrt(1 - (refractiveIndex * refractiveIndex) * (1 - (Chalkboard.vec2.dot(vec2_1, vec2_2) * Chalkboard.vec2.dot(vec2_1, vec2_2)))));
2062
+ return Chalkboard.vec2.add(perp, parr);
2063
+ } else {
2064
+ return undefined;
2065
+ }
2066
+ },
2067
+ fromAngle: function(rad) {
2068
+ return Chalkboard.vec2.new(Chalkboard.trig.cos(rad), Chalkboard.trig.sin(rad));
2069
+ },
2070
+ fromPolar: function(vec2) {
2071
+ return Chalkboard.vec2.new(vec2.x * Chalkboard.trig.cos(vec2.y), vec2.x * Chalkboard.trig.sin(vec2.y));
2072
+ },
2073
+ fromBipolar: function(vec2) {
2074
+ return Chalkboard.vec2.new((vec2.x * vec2.x - vec2.y * vec2.y) / 4, Chalkboard.real.sqrt(16 * vec2.x * vec2.x - (vec2.x * vec2.x - vec2.y * vec2.y + 4) * (vec2.x * vec2.x - vec2.y * vec2.y + 4)));
2075
+ },
2076
+ toPolar: function(vec2) {
2077
+ return Chalkboard.vec2.new(Chalkboard.vec2.mag(vec2), Chalkboard.vec2.ang(vec2));
2078
+ },
2079
+ toBipolar: function(vec2) {
2080
+ return Chalkboard.vec2.new((vec2.x + 1) * (vec2.x + 1) + (vec2.y * vec2.y), (vec2.x - 1) * (vec2.x - 1) + (vec2.y * vec2.y));
2081
+ },
2082
+ toMatrix: function(vec2, type) {
2083
+ type = type || "col";
2084
+ if(type === "col") {
2085
+ return Chalkboard.matr.new([vec2.x], [vec2.y]);
2086
+ } else if(type === "row") {
2087
+ return Chalkboard.matr.new([vec2.x, vec2.y]);
2088
+ } else {
2089
+ return "TypeError: Parameter \"type\" should be \"row\" or \"col\".";
2090
+ }
2091
+ },
2092
+ toComplex: function(vec2) {
2093
+ return Chalkboard.comp.new(vec2.x, vec2.y);
2094
+ },
2095
+ toArray: function(vec2) {
2096
+ return [vec2.x, vec2.y];
2097
+ },
2098
+ toString: function(vec2) {
2099
+ return "(" + vec2.x.toString() + ", " + vec2.y.toString() + ")";
2100
+ },
2101
+ field: function(p, q) {
2102
+ return {p: p, q: q, type: "vec2field"};
2103
+ },
2104
+ fromField: function(vec2field, vec2) {
2105
+ var p = Chalkboard.real.parse("(x, y) => " + vec2field.p),
2106
+ q = Chalkboard.real.parse("(x, y) => " + vec2field.q);
2107
+ return Chalkboard.vec2.new(p(vec2.x, vec2.y), q(vec2.x, vec2.y));
2108
+ },
2109
+ print: function(vec2) {
2110
+ console.log(Chalkboard.vec2.toString(vec2));
2111
+ }
2112
+ },
2113
+ vec3: {
2114
+ new: function(x, y, z) {
2115
+ if(y === undefined && z === undefined) {
2116
+ return {x: x, y: x, z: x, type: "vec3"};
2117
+ } else {
2118
+ return {x: x, y: y, z: z, type: "vec3"};
2119
+ }
2120
+ },
2121
+ random: function(inf, sup) {
2122
+ return Chalkboard.vec3.new(Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup));
2123
+ },
2124
+ mag: function(vec3) {
2125
+ return Chalkboard.real.sqrt((vec3.x * vec3.x) + (vec3.y * vec3.y) + (vec3.z * vec3.z));
2126
+ },
2127
+ magsq: function(vec3) {
2128
+ return (vec3.x * vec3.x) + (vec3.y * vec3.y) + (vec3.z * vec3.z);
2129
+ },
2130
+ magset: function(vec3, num) {
2131
+ return Chalkboard.vec3.scl(Chalkboard.vec3.normalize(vec3), num);
2132
+ },
2133
+ ang: function(vec3) {
2134
+ return [Math.acos(vec3.x / Chalkboard.vec3.mag(vec3)), Math.acos(vec3.y / Chalkboard.vec3.mag(vec3)), Math.acos(vec3.z / Chalkboard.vec3.mag(vec3))];
2135
+ },
2136
+ slope: function(vec3) {
2137
+ return vec3.z / Chalkboard.real.sqrt((vec3.x * vec3.x) + (vec3.y * vec3.y));
2138
+ },
2139
+ azimuth: function(vec3) {
2140
+ return Chalkboard.trig.arctan(vec3.x / vec3.y);
2141
+ },
2142
+ average: function(vec3) {
2143
+ return (vec3.x + vec3.y + vec3.z) / 3;
2144
+ },
2145
+ normalize: function(vec3) {
2146
+ return Chalkboard.vec3.new(vec3.x / Chalkboard.vec3.mag(vec3), vec3.y / Chalkboard.vec3.mag(vec3), vec3.z / Chalkboard.vec3.mag(vec3));
2147
+ },
2148
+ zero: function(vec3) {
2149
+ return Chalkboard.vec3.new(vec3.x * 0, vec3.y * 0, vec3.z * 0);
2150
+ },
2151
+ negate: function(vec3) {
2152
+ return Chalkboard.vec3.new(-vec3.x, -vec3.y, -vec3.z);
2153
+ },
2154
+ reciprocate: function(vec3) {
2155
+ return Chalkboard.vec3.new(1 / vec3.x, 1 / vec3.y, 1 / vec3.z);
2156
+ },
2157
+ absolute: function(vec3) {
2158
+ return Chalkboard.vec3.new(Math.abs(vec3.x), Math.abs(vec3.y), Math.abs(vec3.z));
2159
+ },
2160
+ round: function(vec3) {
2161
+ return Chalkboard.vec3.new(Math.round(vec3.x), Math.round(vec3.y), Math.round(vec3.z));
2162
+ },
2163
+ dist: function(vec3_1, vec3_2) {
2164
+ return Chalkboard.real.sqrt(((vec3_2.x - vec3_1.x) * (vec3_2.x - vec3_1.x)) + ((vec3_2.y - vec3_1.y) * (vec3_2.y - vec3_1.y)) + ((vec3_2.z - vec3_1.z) * (vec3_2.z - vec3_1.z)));
2165
+ },
2166
+ distsq: function(vec3_1, vec3_2) {
2167
+ return ((vec3_2.x - vec3_1.x) * (vec3_2.x - vec3_1.x)) + ((vec3_2.y - vec3_1.y) * (vec3_2.y - vec3_1.y)) + ((vec3_2.z - vec3_1.z) * (vec3_2.z - vec3_1.z));
2168
+ },
2169
+ angBtwn: function(vec3_1, vec3_2) {
2170
+ return Math.acos((Chalkboard.vec3.dot(vec3_1, vec3_2)) / (Chalkboard.vec3.mag(vec3_1) * Chalkboard.vec3.mag(vec3_2)));
2171
+ },
2172
+ scl: function(vec3, num) {
2173
+ return Chalkboard.vec3.new(vec3.x * num, vec3.y * num, vec3.z * num);
2174
+ },
2175
+ constrain: function(vec3, range) {
2176
+ return Chalkboard.vec3.new(Chalkboard.numb.constrain(vec3.x, range), Chalkboard.numb.constrain(vec3.y, range), Chalkboard.numb.constrain(vec3.z, range));
2177
+ },
2178
+ add: function(vec3_1, vec3_2) {
2179
+ return Chalkboard.vec3.new(vec3_1.x + vec3_2.x, vec3_1.y + vec3_2.y, vec3_1.z + vec3_2.z);
2180
+ },
2181
+ sub: function(vec3_1, vec3_2) {
2182
+ return Chalkboard.vec3.new(vec3_1.x - vec3_2.x, vec3_1.y - vec3_2.y, vec3_1.z - vec3_2.z);
2183
+ },
2184
+ mid: function(vec3_1, vec3_2) {
2185
+ return Chalkboard.vec3.new((vec3_1.x + vec3_2.x) / 2, (vec3_1.y + vec3_2.y) / 2, (vec3_1.z + vec3_2.z) / 2);
2186
+ },
2187
+ dot: function(vec3_1, vec3_2) {
2188
+ return (vec3_1.x * vec3_2.x) + (vec3_1.y * vec3_2.y) + (vec3_1.z * vec3_2.z);
2189
+ },
2190
+ cross: function(vec3_1, vec3_2) {
2191
+ return Chalkboard.vec3.new((vec3_1.y * vec3_2.z) - (vec3_1.z * vec3_2.y), (vec3_1.z * vec3_2.x) - (vec3_1.x * vec3_2.z), (vec3_1.x * vec3_2.y) - (vec3_1.y * vec3_2.x));
2192
+ },
2193
+ scalarTriple: function(vec3_1, vec3_2, vec3_3) {
2194
+ return Chalkboard.vec3.dot(vec3_1, Chalkboard.vec3.cross(vec3_2, vec3_3));
2195
+ },
2196
+ vectorTriple: function(vec3_1, vec3_2, vec3_3) {
2197
+ return Chalkboard.vec3.cross(vec3_1, Chalkboard.vec3.cross(vec3_2, vec3_3));
2198
+ },
2199
+ proj: function(vec3_1, vec3_2) {
2200
+ return Chalkboard.vec3.scl(vec3_2, Chalkboard.vec3.dot(vec3_1, vec3_2) / Chalkboard.vec3.dot(vec3_2, vec3_2));
2201
+ },
2202
+ oproj: function(vec3_1, vec3_2) {
2203
+ return Chalkboard.vec3.sub(vec3_1, Chalkboard.vec3.proj(vec3_1, vec3_2));
2204
+ },
2205
+ reflect: function(vec3_1, vec3_2) {
2206
+ return Chalkboard.vec3.sub(vec3_1, Chalkboard.vec3.scl(vec3_2, 2 * Chalkboard.vec3.dot(vec3_1, vec3_2)));
2207
+ },
2208
+ refract: function(vec3_1, vec3_2, refractiveIndex) {
2209
+ if(refractiveIndex > 0) {
2210
+ var perp = Chalkboard.vec3.scl(Chalkboard.vec3.sub(vec3_1, Chalkboard.vec3.scl(vec3_2, Chalkboard.vec3.dot(vec3_1, vec3_2))), refractiveIndex);
2211
+ var parr = Chalkboard.vec3.scl(vec3_2, -Chalkboard.real.sqrt(1 - (refractiveIndex * refractiveIndex) * (1 - (Chalkboard.vec3.dot(vec3_1, vec3_2) * Chalkboard.vec3.dot(vec3_1, vec3_2)))));
2212
+ return Chalkboard.vec3.add(perp, parr);
2213
+ } else {
2214
+ return undefined;
2215
+ }
2216
+ },
2217
+ fromAngles: function(rad1, rad2) {
2218
+ return Chalkboard.vec3.new(Chalkboard.trig.cos(rad1) * Chalkboard.trig.cos(rad2), Chalkboard.trig.sin(rad1) * Chalkboard.trig.cos(rad2), Chalkboard.trig.sin(rad2));
2219
+ },
2220
+ fromVector: function(vec2) {
2221
+ return Chalkboard.vec3.new(vec2.x, vec2.y, 0);
2222
+ },
2223
+ fromCylindrical: function(vec3) {
2224
+ return Chalkboard.vec3.new(vec3.x * Chalkboard.trig.cos(vec3.y), vec3.x * Chalkboard.trig.sin(vec3.y), vec3.z);
2225
+ },
2226
+ fromSpherical: function(vec3) {
2227
+ return Chalkboard.vec3.new(vec3.x * Chalkboard.trig.sin(vec3.z) * Chalkboard.trig.cos(vec3.y), vec3.x * Chalkboard.trig.sin(vec3.z) * Chalkboard.trig.sin(vec3.y), vec3.x * Chalkboard.trig.cos(vec3.z));
2228
+ },
2229
+ toCylindrical: function(vec3) {
2230
+ return Chalkboard.vec3.new(Chalkboard.vec2.mag(vec3), Chalkboard.vec2.ang(vec3), vec3.z);
2231
+ },
2232
+ toSpherical: function(vec3) {
2233
+ return Chalkboard.vec3.new(Chalkboard.vec3.mag(vec3), Chalkboard.vec2.ang(vec3), Chalkboard.vec3.ang(vec3)[2]);
2234
+ },
2235
+ toMatrix: function(vec3, type) {
2236
+ type = type || "col";
2237
+ if(type === "col") {
2238
+ return Chalkboard.matr.new([vec3.x], [vec3.y], [vec3.z]);
2239
+ } else if(type === "row") {
2240
+ return Chalkboard.matr.new([vec3.x, vec3.y, vec3.z]);
2241
+ } else {
2242
+ return "TypeError: Parameter \"type\" should be \"row\" or \"col\".";
2243
+ }
2244
+ },
2245
+ toArray: function(vec3) {
2246
+ return [vec3.x, vec3.y, vec3.z];
2247
+ },
2248
+ toString: function(vec3) {
2249
+ return "(" + vec3.x.toString() + ", " + vec3.y.toString() + ", " + vec3.z.toString() + ")";
2250
+ },
2251
+ field: function(p, q, r) {
2252
+ return {p: p, q: q, r: r, type: "vec3field"};
2253
+ },
2254
+ fromField: function(vec3field, vec3) {
2255
+ var p = Chalkboard.real.parse("(x, y, z) => " + vec3field.p),
2256
+ q = Chalkboard.real.parse("(x, y, z) => " + vec3field.q),
2257
+ r = Chalkboard.real.parse("(x, y, z) => " + vec3field.r);
2258
+ return Chalkboard.vec3.new(p(vec3.x, vec3.y, vec3.z), q(vec3.x, vec3.y, vec3.z), r(vec3.x, vec3.y, vec3.z));
2259
+ },
2260
+ print: function(vec3) {
2261
+ console.log(Chalkboard.vec3.toString(vec3));
2262
+ }
2263
+ },
2264
+ vec4: {
2265
+ new: function(x, y, z, w) {
2266
+ if(y === undefined && z === undefined && w === undefined) {
2267
+ return {x: x, y: x, z: x, w: x, type: "vec4"};
2268
+ } else {
2269
+ return {x: x, y: y, z: z, w: w, type: "vec4"};
2270
+ }
2271
+ },
2272
+ random: function(inf, sup) {
2273
+ return Chalkboard.vec4.new(Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup), Chalkboard.numb.random(inf, sup));
2274
+ },
2275
+ mag: function(vec4) {
2276
+ return Chalkboard.real.sqrt((vec4.x * vec4.x) + (vec4.y * vec4.y) + (vec4.z * vec4.z) + (vec4.w * vec4.w));
2277
+ },
2278
+ magsq: function(vec4) {
2279
+ return (vec4.x * vec4.x) + (vec4.y * vec4.y) + (vec4.z * vec4.z) + (vec4.w * vec4.w);
2280
+ },
2281
+ magset: function(vec4, num) {
2282
+ return Chalkboard.vec4.scl(Chalkboard.vec4.normalize(vec4), num);
2283
+ },
2284
+ ang: function(vec4) {
2285
+ return [Math.acos(vec4.x / Chalkboard.vec4.mag(vec4)), Math.acos(vec4.y / Chalkboard.vec4.mag(vec4)), Math.acos(vec4.z / Chalkboard.vec4.mag(vec4)), Math.acos(vec4.w / Chalkboard.vec4.mag(vec4))];
2286
+ },
2287
+ slope: function(vec4) {
2288
+ return vec4.w / Chalkboard.real.sqrt((vec4.x * vec4.x) + (vec4.y * vec4.y) + (vec4.z * vec4.z));
2289
+ },
2290
+ average: function(vec4) {
2291
+ return (vec4.x + vec4.y + vec4.z + vec4.w) / 4;
2292
+ },
2293
+ normalize: function(vec4) {
2294
+ return Chalkboard.vec4.new(vec4.x / Chalkboard.vec4.mag(vec4), vec4.y / Chalkboard.vec4.mag(vec4), vec4.z / Chalkboard.vec4.mag(vec4), vec4.w / Chalkboard.vec4.mag(vec4));
2295
+ },
2296
+ zero: function(vec4) {
2297
+ return Chalkboard.vec4.new(vec4.x * 0, vec4.y * 0, vec4.z * 0, vec4.w * 0);
2298
+ },
2299
+ negate: function(vec4) {
2300
+ return Chalkboard.vec4.new(-vec4.x, -vec4.y, -vec4.z, -vec4.w);
2301
+ },
2302
+ reciprocate: function(vec4) {
2303
+ return Chalkboard.vec4.new(1 / vec4.x, 1 / vec4.y, 1 / vec4.z, 1 / vec4.w);
2304
+ },
2305
+ absolute: function(vec4) {
2306
+ return Chalkboard.vec4.new(Math.abs(vec4.x), Math.abs(vec4.y), Math.abs(vec4.z), Math.abs(vec4.w));
2307
+ },
2308
+ round: function(vec4) {
2309
+ return Chalkboard.vec4.new(Math.round(vec4.x), Math.round(vec4.y), Math.round(vec4.z), Math.round(vec4.w));
2310
+ },
2311
+ dist: function(vec4_1, vec4_2) {
2312
+ return Chalkboard.real.sqrt(((vec4_2.x - vec4_1.x) * (vec4_2.x - vec4_1.x)) + ((vec4_2.y - vec4_1.y) * (vec4_2.y - vec4_1.y)) + ((vec4_2.z - vec4_1.z) * (vec4_2.z - vec4_1.z)) + ((vec4_2.w - vec4_1.w) * (vec4_2.w - vec4_1.w)));
2313
+ },
2314
+ distsq: function(vec4_1, vec4_2) {
2315
+ return ((vec4_2.x - vec4_1.x) * (vec4_2.x - vec4_1.x)) + ((vec4_2.y - vec4_1.y) * (vec4_2.y - vec4_1.y)) + ((vec4_2.z - vec4_1.z) * (vec4_2.z - vec4_1.z)) + ((vec4_2.w - vec4_1.w) * (vec4_2.w - vec4_1.w));
2316
+ },
2317
+ angBtwn: function(vec4_1, vec4_2) {
2318
+ return Math.acos((Chalkboard.vec4.dot(vec4_1, vec4_2)) / (Chalkboard.vec4.mag(vec4_1) * Chalkboard.vec4.mag(vec4_2)));
2319
+ },
2320
+ scl: function(vec4, num) {
2321
+ return Chalkboard.vec4.new(vec4.x * num, vec4.y * num, vec4.z * num, vec4.w * num);
2322
+ },
2323
+ constrain: function(vec4, range) {
2324
+ return Chalkboard.vec4.new(Chalkboard.numb.constrain(vec4.x, range), Chalkboard.numb.constrain(vec4.y, range), Chalkboard.numb.constrain(vec4.z, range), Chalkboard.numb.constrain(vec4.w, range));
2325
+ },
2326
+ add: function(vec4_1, vec4_2) {
2327
+ return Chalkboard.vec4.new(vec4_1.x + vec4_2.x, vec4_1.y + vec4_2.y, vec4_1.z + vec4_2.z, vec4_1.w + vec4_2.w);
2328
+ },
2329
+ sub: function(vec4_1, vec4_2) {
2330
+ return Chalkboard.vec4.new(vec4_1.x - vec4_2.x, vec4_1.y - vec4_2.y, vec4_1.z - vec4_2.z, vec4_1.w - vec4_2.w);
2331
+ },
2332
+ mid: function(vec4_1, vec4_2) {
2333
+ return Chalkboard.vec4.new((vec4_1.x + vec4_2.x) / 2, (vec4_1.y + vec4_2.y) / 2, (vec4_1.z + vec4_2.z) / 2, (vec4_1.w + vec4_2.w) / 2);
2334
+ },
2335
+ dot: function(vec4_1, vec4_2) {
2336
+ return (vec4_1.x * vec4_2.x) + (vec4_1.y * vec4_2.y) + (vec4_1.z * vec4_2.z) + (vec4_1.w * vec4_2.w);
2337
+ },
2338
+ proj: function(vec4_1, vec4_2) {
2339
+ return Chalkboard.vec4.scl(vec4_2, Chalkboard.vec4.dot(vec4_1, vec4_2) / Chalkboard.vec4.dot(vec4_2, vec4_2));
2340
+ },
2341
+ oproj: function(vec4_1, vec4_2) {
2342
+ return Chalkboard.vec4.sub(vec4_1, Chalkboard.vec4.proj(vec4_1, vec4_2));
2343
+ },
2344
+ reflect: function(vec4_1, vec4_2) {
2345
+ return Chalkboard.vec4.sub(vec4_1, Chalkboard.vec4.scl(vec4_2, 2 * Chalkboard.vec4.dot(vec4_1, vec4_2)));
2346
+ },
2347
+ refract: function(vec4_1, vec4_2, refractiveIndex) {
2348
+ if(refractiveIndex > 0) {
2349
+ var perp = Chalkboard.vec4.scl(Chalkboard.vec4.sub(vec4_1, Chalkboard.vec4.scl(vec4_2, Chalkboard.vec4.dot(vec4_1, vec4_2))), refractiveIndex);
2350
+ var parr = Chalkboard.vec4.scl(vec4_2, -Chalkboard.real.sqrt(1 - (refractiveIndex * refractiveIndex) * (1 - (Chalkboard.vec4.dot(vec4_1, vec4_2) * Chalkboard.vec4.dot(vec4_1, vec4_2)))));
2351
+ return Chalkboard.vec4.add(perp, parr);
2352
+ } else {
2353
+ return undefined;
2354
+ }
2355
+ },
2356
+ fromVector: function(vec3) {
2357
+ return Chalkboard.vec4.new(vec3.x, vec3.y, vec3.z, 0);
2358
+ },
2359
+ fromHypercylindrical: function(vec4) {
2360
+ return Chalkboard.vec4.new(vec4.x * Chalkboard.trig.cos(vec4.y) * Chalkboard.trig.cos(vec4.z), vec4.x * Chalkboard.trig.cos(vec4.y) * Chalkboard.trig.sin(vec4.z), vec4.x * Chalkboard.trig.sin(vec4.y), vec4.w);
2361
+ },
2362
+ fromHyperspherical: function(vec4) {
2363
+ return Chalkboard.vec4.new(vec4.x * Chalkboard.trig.cos(vec4.y) * Chalkboard.trig.cos(vec4.z) * Chalkboard.trig.cos(vec4.w), vec4.x * Chalkboard.trig.cos(vec4.y) * Chalkboard.trig.sin(vec4.z) * Chalkboard.trig.cos(vec4.w), vec4.x * Chalkboard.trig.sin(vec4.y) * Chalkboard.trig.cos(vec4.w), vec4.x * Chalkboard.trig.sin(vec4.w));
2364
+ },
2365
+ toHypercylindrical: function(vec4) {
2366
+ return Chalkboard.vec4.new(Chalkboard.vec3.mag(vec4), Chalkboard.vec2.ang(vec4), Chalkboard.vec3.ang(vec4)[2], vec4.w);
2367
+ },
2368
+ toHyperspherical: function(vec4) {
2369
+ return Chalkboard.vec4.new(Chalkboard.vec4.mag(vec4), Chalkboard.vec2.ang(vec4), Chalkboard.vec3.ang(vec4)[2], Chalkboard.vec4.ang(vec4)[3]);
2370
+ },
2371
+ toMatrix: function(vec4, type) {
2372
+ type = type || "col";
2373
+ if(type === "col") {
2374
+ return Chalkboard.matr.new([vec4.x], [vec4.y], [vec4.z], [vec4.w]);
2375
+ } else if(type === "row") {
2376
+ return Chalkboard.matr.new([vec4.x, vec4.y, vec4.z, vec4.w]);
2377
+ } else {
2378
+ return "TypeError: Parameter \"type\" should be \"row\" or \"col\".";
2379
+ }
2380
+ },
2381
+ toQuaternion: function(vec4) {
2382
+ return Chalkboard.quat.new(vec4.x, vec4.y, vec4.z, vec4.w);
2383
+ },
2384
+ toArray: function(vec4) {
2385
+ return [vec4.x, vec4.y, vec4.z, vec4.w];
2386
+ },
2387
+ toString: function(vec4) {
2388
+ return "(" + vec4.x.toString() + ", " + vec4.y.toString() + ", " + vec4.z.toString() + ", " + vec4.w.toString() + ")";
2389
+ },
2390
+ field: function(p, q, r, s) {
2391
+ return {p: p, q: q, r: r, s: s, type: "vec4field"};
2392
+ },
2393
+ fromField: function(vec4field, vec4) {
2394
+ var p = Chalkboard.real.parse("(x, y, z, w) => " + vec4field.p),
2395
+ q = Chalkboard.real.parse("(x, y, z, w) => " + vec4field.q),
2396
+ r = Chalkboard.real.parse("(x, y, z, w) => " + vec4field.r),
2397
+ s = Chalkboard.real.parse("(x, y, z, w) => " + vec4field.s);
2398
+ return Chalkboard.vec4.new(p(vec4.x, vec4.y, vec4.z, vec4.w), q(vec4.x, vec4.y, vec4.z, vec4.w), r(vec4.x, vec4.y, vec4.z, vec4.w), s(vec4.x, vec4.y, vec4.z, vec4.w));
2399
+ },
2400
+ print: function(vec4) {
2401
+ console.log(Chalkboard.vec4.toString(vec4));
2402
+ }
2403
+ },
2404
+ matr: {
2405
+ new: function(matrix) {
2406
+ return Array.from(arguments);
2407
+ },
2408
+ rows: function(matr) {
2409
+ return matr.length;
2410
+ },
2411
+ cols: function(matr) {
2412
+ return matr[0].length;
2413
+ },
2414
+ empty: function(dimension) {
2415
+ if(Number.isInteger(dimension) && dimension > 0) {
2416
+ var result = Chalkboard.matr.new();
2417
+ for(var i = 0; i < dimension; i++) {
2418
+ result.push([]);
2419
+ for(var j = 0; j < dimension; j++) {
2420
+ result[i].push(null);
2421
+ }
2422
+ }
2423
+ return result;
2424
+ } else {
2425
+ return undefined;
2426
+ }
2427
+ },
2428
+ identity: function(dimension) {
2429
+ if(Number.isInteger(dimension) && dimension > 0) {
2430
+ var result = Chalkboard.matr.new();
2431
+ for(var i = 0; i < dimension; i++) {
2432
+ result.push(Array(dimension).fill(0));
2433
+ result[i][i] = 1;
2434
+ }
2435
+ return result;
2436
+ } else {
2437
+ return undefined;
2438
+ }
2439
+ },
2440
+ random: function(dimension, inf, sup) {
2441
+ if(Number.isInteger(dimension) && dimension > 0) {
2442
+ inf = inf || 0;
2443
+ sup = sup || 1;
2444
+ var result = Chalkboard.matr.new();
2445
+ for(var i = 0; i < dimension; i++) {
2446
+ result.push([]);
2447
+ for(var j = 0; j < dimension; j++) {
2448
+ result[i].push(Chalkboard.numb.random(inf, sup));
2449
+ }
2450
+ }
2451
+ return result;
2452
+ } else {
2453
+ return undefined;
2454
+ }
2455
+ },
2456
+ cofactor: function(matr, row, col) {
2457
+ return matr.slice(0, row - 1).concat(matr.slice(row)).map(function (row) {
2458
+ return row.slice(0, col - 1).concat(row.slice(col));
2459
+ });
2460
+ },
2461
+ adjugate: function(matr, row, col) {
2462
+ return Chalkboard.matr.transpose(Chalkboard.matr.cofactor(matr, row, col));
2463
+ },
2464
+ det: function(matr) {
2465
+ if(Chalkboard.matr.rows(matr) === Chalkboard.matr.cols(matr)) {
2466
+ var result = 0;
2467
+ if(Chalkboard.matr.rows(matr) === 1) {
2468
+ return matr[0][0];
2469
+ } else if(Chalkboard.matr.rows(matr) === 2) {
2470
+ return (matr[0][0] * matr[1][1]) - (matr[0][1] * matr[1][0]);
2471
+ } else {
2472
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2473
+ var cofactor = matr[0][i] * Chalkboard.matr.det(Chalkboard.matr.cofactor(matr, 1, i + 1));
2474
+ result += i % 2 === 0 ? cofactor : -cofactor;
2475
+ }
2476
+ return result;
2477
+ }
2478
+ } else {
2479
+ return undefined;
2480
+ }
2481
+ },
2482
+ trace: function(matr) {
2483
+ if(Chalkboard.matr.rows(matr) === Chalkboard.matr.cols(matr)) {
2484
+ var result = 0;
2485
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2486
+ result += matr[i][i];
2487
+ }
2488
+ return result;
2489
+ } else {
2490
+ return undefined;
2491
+ }
2492
+ },
2493
+ rank: function(matr) {
2494
+ return Chalkboard.matr.reduce(matr).filter(function (row) {
2495
+ return row.some(function (element) {
2496
+ return element !== 0;
2497
+ });
2498
+ }).length;
2499
+ },
2500
+ rowspace: function(matr) {
2501
+ return Chalkboard.matr.reduce(matr).filter(function (row) {
2502
+ return row.some(function (element) {
2503
+ return element !== 0;
2504
+ });
2505
+ });
2506
+ },
2507
+ colspace: function(matr) {
2508
+ return Chalkboard.matr.transpose(Chalkboard.matr.rowspace(Chalkboard.matr.transpose(matr)));
2509
+ },
2510
+ nullspace: function(matr) {
2511
+ var augmented = matr.map(function (row) {
2512
+ return row.slice().concat(Array(Chalkboard.matr.rows(matr)).fill(0));
2513
+ });
2514
+ var reduced = Chalkboard.matr.reduce(augmented);
2515
+ return reduced.filter(function (row) {
2516
+ return row.slice(0, Chalkboard.matr.rows(matr)).every(function (element) {
2517
+ return element === 0;
2518
+ });
2519
+ }).map(function (row) {
2520
+ return row.slice(Chalkboard.matr.rows(matr));
2521
+ });
2522
+ },
2523
+ transpose: function(matr) {
2524
+ var result = Chalkboard.matr.new();
2525
+ for(var i = 0; i < Chalkboard.matr.cols(matr); i++) {
2526
+ result[i] = [];
2527
+ for(var j = 0; j < Chalkboard.matr.rows(matr); j++) {
2528
+ result[i][j] = matr[j][i];
2529
+ }
2530
+ }
2531
+ return result;
2532
+ },
2533
+ invert: function(matr) {
2534
+ if(Chalkboard.matr.rows(matr) === Chalkboard.matr.cols(matr)) {
2535
+ var result = Chalkboard.matr.new();
2536
+ var augmented = Chalkboard.matr.new();
2537
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2538
+ augmented.push(matr[i].concat(Array(Chalkboard.matr.rows(matr)).fill(0)));
2539
+ augmented[i][Chalkboard.matr.cols(matr) + i] = 1;
2540
+ }
2541
+ for(var row = 0; row < Chalkboard.matr.rows(matr); row++) {
2542
+ var diagonal = augmented[row][row];
2543
+ if(diagonal === 0) {
2544
+ var max = row;
2545
+ for(var i = row + 1; i < Chalkboard.matr.rows(matr); i++) {
2546
+ if(Math.abs(augmented[i][row]) > Math.abs(augmented[max][row])) {
2547
+ max = i;
2548
+ }
2549
+ }
2550
+ var temp = augmented[row];
2551
+ augmented[row] = augmented[max];
2552
+ augmented[max] = temp;
2553
+ diagonal = augmented[row][row];
2554
+ }
2555
+ for(var col = 0; col < 2 * Chalkboard.matr.cols(matr); col++) {
2556
+ augmented[row][col] /= diagonal;
2557
+ }
2558
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2559
+ if(i !== row) {
2560
+ var coeff = augmented[i][row];
2561
+ for(var j = 0; j < 2 * Chalkboard.matr.cols(matr); j++) {
2562
+ augmented[i][j] -= coeff * augmented[row][j];
2563
+ }
2564
+ }
2565
+ }
2566
+ }
2567
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2568
+ result.push(augmented[i].slice(Chalkboard.matr.cols(matr), 2 * Chalkboard.matr.cols(matr)));
2569
+ }
2570
+ return result;
2571
+ } else {
2572
+ return undefined;
2573
+ }
2574
+ },
2575
+ zero: function(matr) {
2576
+ var result = Chalkboard.matr.new();
2577
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2578
+ result[i] = [];
2579
+ for(var j = 0; j < Chalkboard.matr.cols(matr); j++) {
2580
+ result[i][j] = 0;
2581
+ }
2582
+ }
2583
+ return result;
2584
+ },
2585
+ negate: function(matr) {
2586
+ var result = Chalkboard.matr.new();
2587
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2588
+ result[i] = [];
2589
+ for(var j = 0; j < Chalkboard.matr.cols(matr); j++) {
2590
+ result[i][j] = -matr[i][j];
2591
+ }
2592
+ }
2593
+ return result;
2594
+ },
2595
+ reciprocate: function(matr) {
2596
+ var result = Chalkboard.matr.new();
2597
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2598
+ result[i] = [];
2599
+ for(var j = 0; j < Chalkboard.matr.cols(matr); j++) {
2600
+ result[i][j] = 1 / matr[i][j];
2601
+ }
2602
+ }
2603
+ return result;
2604
+ },
2605
+ absolute: function(matr) {
2606
+ var result = Chalkboard.matr.new();
2607
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2608
+ result[i] = [];
2609
+ for(var j = 0; j < Chalkboard.matr.cols(matr); j++) {
2610
+ result[i][j] = Math.abs(matr[i][j]);
2611
+ }
2612
+ }
2613
+ return result;
2614
+ },
2615
+ round: function(matr) {
2616
+ var result = Chalkboard.matr.new();
2617
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2618
+ result[i] = [];
2619
+ for(var j = 0; j < Chalkboard.matr.cols(matr); j++) {
2620
+ result[i][j] = Math.round(matr[i][j]);
2621
+ }
2622
+ }
2623
+ return result;
2624
+ },
2625
+ scaler: function(vec) {
2626
+ if(vec.type === "vec2") {
2627
+ return Chalkboard.matr.new([vec.x, 0], [0, vec.y]);
2628
+ } else if(vec.type === "vec3") {
2629
+ return Chalkboard.matr.new([vec.x, 0, 0], [0, vec.y, 0], [0, 0, vec.z]);
2630
+ } else if(vec.type === "vec4") {
2631
+ return Chalkboard.matr.new([vec.x, 0, 0, 0], [0, vec.y, 0, 0], [0, 0, vec.z, 0], [0, 0, 0, vec.w]);
2632
+ }
2633
+ },
2634
+ translator: function(vec) {
2635
+ if(vec.type === "vec2") {
2636
+ return Chalkboard.matr.new([1, 0, vec.x], [0, 1, vec.y], [0, 0, 1]);
2637
+ } else if(vec.type === "vec3") {
2638
+ return Chalkboard.matr.new([1, 0, 0, vec.x], [0, 1, 0, vec.y], [0, 0, 1, vec.z], [0, 0, 0, 1]);
2639
+ } else if(vec.type === "vec4") {
2640
+ return Chalkboard.matr.new([1, 0, 0, 0, vec.x], [0, 1, 0, 0, vec.y], [0, 0, 1, 0, vec.z], [0, 0, 0, 1, vec.w], [0, 0, 0, 0, 1]);
2641
+ } else {
2642
+ return "TypeError: Parameter \"vec\" should be \"vec2\", \"vec3\", or \"vec4\".";
2643
+ }
2644
+ },
2645
+ rotator: function(radx, rady, radz) {
2646
+ if(rady === undefined && radz === undefined) {
2647
+ return Chalkboard.matr.new([Chalkboard.trig.cos(radx), -Chalkboard.trig.sin(radx)], [Chalkboard.trig.sin(radx), Chalkboard.trig.cos(radx)]);
2648
+ } else {
2649
+ var matr_x = Chalkboard.matr.new([1, 0, 0], [0, Chalkboard.trig.cos(radx), -Chalkboard.trig.sin(radx)], [0, Chalkboard.trig.sin(radx), Chalkboard.trig.cos(radx)]),
2650
+ matr_y = Chalkboard.matr.new([Chalkboard.trig.cos(rady), 0, Chalkboard.trig.sin(rady)], [0, 1, 0], [-Chalkboard.trig.sin(rady), 0, Chalkboard.trig.cos(rady)]),
2651
+ matr_z = Chalkboard.matr.new([Chalkboard.trig.cos(radz), -Chalkboard.trig.sin(radz), 0], [Chalkboard.trig.sin(radz), Chalkboard.trig.cos(radz), 0], [0, 0, 1]);
2652
+ return Chalkboard.matr.mul(matr_x, Chalkboard.matr.mul(matr_y, matr_z));
2653
+ }
2654
+ },
2655
+ scl: function(matr, num) {
2656
+ var result = Chalkboard.matr.new();
2657
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2658
+ result[i] = [];
2659
+ for(var j = 0; j < Chalkboard.matr.cols(matr); j++) {
2660
+ result[i][j] = matr[i][j] * num;
2661
+ }
2662
+ }
2663
+ return result;
2664
+ },
2665
+ constrain: function(matr, range) {
2666
+ var result = Chalkboard.matr.new();
2667
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2668
+ result[i] = [];
2669
+ for(var j = 0; j < Chalkboard.matr.cols(matr); j++) {
2670
+ result[i][j] = Chalkboard.numb.constrain(matr[i][j], range);
2671
+ }
2672
+ }
2673
+ return result;
2674
+ },
2675
+ add: function(matr_1, matr_2) {
2676
+ if(Chalkboard.matr.rows(matr_1) === Chalkboard.matr.rows(matr_2) && Chalkboard.matr.cols(matr_1) === Chalkboard.matr.cols(matr_2)) {
2677
+ var result = Chalkboard.matr.new();
2678
+ for(var i = 0; i < Chalkboard.matr.rows(matr_1); i++) {
2679
+ result[i] = [];
2680
+ for(var j = 0; j < Chalkboard.matr.cols(matr_1); j++) {
2681
+ result[i][j] = matr_1[i][j] + matr_2[i][j];
2682
+ }
2683
+ }
2684
+ return result;
2685
+ } else {
2686
+ return undefined;
2687
+ }
2688
+ },
2689
+ sub: function(matr_1, matr_2) {
2690
+ if(Chalkboard.matr.rows(matr_1) === Chalkboard.matr.rows(matr_2) && Chalkboard.matr.cols(matr_1) === Chalkboard.matr.cols(matr_2)) {
2691
+ var result = Chalkboard.matr.new();
2692
+ for(var i = 0; i < Chalkboard.matr.rows(matr_1); i++) {
2693
+ result[i] = [];
2694
+ for(var j = 0; j < Chalkboard.matr.cols(matr_1); j++) {
2695
+ result[i][j] = matr_1[i][j] - matr_2[i][j];
2696
+ }
2697
+ }
2698
+ return result;
2699
+ } else {
2700
+ return undefined;
2701
+ }
2702
+ },
2703
+ mul: function(matr_1, matr_2) {
2704
+ if(Chalkboard.matr.cols(matr_1) === Chalkboard.matr.rows(matr_2)) {
2705
+ var result = Chalkboard.matr.new();
2706
+ for(var i = 0; i < Chalkboard.matr.rows(matr_1); i++) {
2707
+ result[i] = [];
2708
+ for(var j = 0; j < Chalkboard.matr.cols(matr_2); j++) {
2709
+ result[i][j] = 0;
2710
+ for(var k = 0; k < Chalkboard.matr.cols(matr_1); k++) {
2711
+ result[i][j] += matr_1[i][k] * matr_2[k][j];
2712
+ }
2713
+ }
2714
+ }
2715
+ return result;
2716
+ } else {
2717
+ return undefined;
2718
+ }
2719
+ },
2720
+ pow: function(matr, num) {
2721
+ if(Chalkboard.matr.rows(matr) === Chalkboard.matr.cols(matr)) {
2722
+ if(Number.isInteger(num) && num >= 0) {
2723
+ if(num === 0) {
2724
+ return Chalkboard.matr.identity(Chalkboard.matr.rows(matr));
2725
+ } else {
2726
+ var result = matr;
2727
+ for(var i = 1; i < num; i++) {
2728
+ result = Chalkboard.matr.mul(matr, result);
2729
+ }
2730
+ return result;
2731
+ }
2732
+ } else {
2733
+ return undefined;
2734
+ }
2735
+ } else {
2736
+ return undefined;
2737
+ }
2738
+ },
2739
+ reduce: function(matr) {
2740
+ var lead = 0;
2741
+ for(var row = 0; row < Chalkboard.matr.rows(matr); row++) {
2742
+ if(lead >= Chalkboard.matr.cols(matr)) {
2743
+ break;
2744
+ }
2745
+ var i = row;
2746
+ while(matr[i][lead] === 0) {
2747
+ i++;
2748
+ if(i === Chalkboard.matr.rows(matr)) {
2749
+ i = row;
2750
+ lead++;
2751
+ if(Chalkboard.matr.cols(matr) === lead) {
2752
+ return matr;
2753
+ }
2754
+ }
2755
+ }
2756
+ var temp = matr[i];
2757
+ matr[i] = matr[row];
2758
+ matr[row] = temp;
2759
+ var scl = matr[row][lead];
2760
+ for(var j = 0; j < Chalkboard.matr.cols(matr); j++) {
2761
+ matr[row][j] /= scl;
2762
+ }
2763
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2764
+ if(i !== row) {
2765
+ var coeff = matr[i][lead];
2766
+ for(var j = 0; j < Chalkboard.matr.cols(matr); j++) {
2767
+ matr[i][j] -= coeff * matr[row][j];
2768
+ }
2769
+ }
2770
+ }
2771
+ lead++;
2772
+ }
2773
+ return matr;
2774
+ },
2775
+ solve: function(matr_A, matr_B) {
2776
+ if(Chalkboard.matr.rows(matr_A) === Chalkboard.matr.cols(matr_A)) {
2777
+ if(Chalkboard.matr.rows(matr_A) === Chalkboard.matr.rows(matr_B)) {
2778
+ if(Chalkboard.matr.det(matr_A) !== 0) {
2779
+ return Chalkboard.matr.mul(Chalkboard.matr.invert(matr_A), matr_B);
2780
+ } else {
2781
+ return undefined;
2782
+ }
2783
+ } else {
2784
+ return undefined;
2785
+ }
2786
+ } else {
2787
+ return undefined;
2788
+ }
2789
+ },
2790
+ toVector: function(matr, vec, type, rowORcol) {
2791
+ type = type || "col";
2792
+ rowORcol = rowORcol || 1;
2793
+ rowORcol -= 1;
2794
+ if(vec === "vec2") {
2795
+ if(type === "col") {
2796
+ return Chalkboard.vec2.new(matr[0][rowORcol], matr[1][rowORcol]);
2797
+ } else if(type === "row") {
2798
+ return Chalkboard.vec2.new(matr[rowORcol][0], matr[rowORcol][1]);
2799
+ } else {
2800
+ return "TypeError: Parameter \"type\" should be \"row\" or \"col\".";
2801
+ }
2802
+ } else if(vec === "vec3") {
2803
+ if(type === "col") {
2804
+ return Chalkboard.vec3.new(matr[0][rowORcol], matr[1][rowORcol], matr[2][rowORcol]);
2805
+ } else if(type === "row") {
2806
+ return Chalkboard.vec3.new(matr[rowORcol][0], matr[rowORcol][1], matr[rowORcol][2]);
2807
+ } else {
2808
+ return "TypeError: Parameter \"type\" should be \"row\" or \"col\".";
2809
+ }
2810
+ } else if(vec === "vec4") {
2811
+ if(type === "col") {
2812
+ return Chalkboard.vec4.new(matr[0][rowORcol], matr[1][rowORcol], matr[2][rowORcol], matr[3][rowORcol]);
2813
+ } else if(type === "row") {
2814
+ return Chalkboard.vec4.new(matr[rowORcol][0], matr[rowORcol][1], matr[rowORcol][2], matr[rowORcol][3]);
2815
+ } else {
2816
+ return "TypeError: Parameter \"type\" should be \"row\" or \"col\".";
2817
+ }
2818
+ } else {
2819
+ return "TypeError: Parameter \"vec\" should be \"vec2\", \"vec3\", or \"vec4\".";
2820
+ }
2821
+ },
2822
+ toArray: function(matr) {
2823
+ var result = [];
2824
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2825
+ for(var j = 0; j < Chalkboard.matr.cols(matr); j++) {
2826
+ result.push(matr[i][j]);
2827
+ }
2828
+ }
2829
+ return result;
2830
+ },
2831
+ toString: function(matr) {
2832
+ var result = "";
2833
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2834
+ result += "[ ";
2835
+ for(var j = 0; j < Chalkboard.matr.cols(matr); j++) {
2836
+ result += matr[i][j].toString() + " ";
2837
+ }
2838
+ result = result.trimEnd() + " ]\n";
2839
+ }
2840
+ return result;
2841
+ },
2842
+ toObject: function(matr) {
2843
+ var result = {};
2844
+ for(var i = 0; i < Chalkboard.matr.rows(matr); i++) {
2845
+ result["i" + (i + 1)] = {};
2846
+ for(var j = 0; j < Chalkboard.matr.cols(matr); j++) {
2847
+ result["i" + (i + 1)]["j" + (j + 1)] = matr[i][j];
2848
+ }
2849
+ }
2850
+ return result;
2851
+ },
2852
+ print: function(matr) {
2853
+ console.log(Chalkboard.matr.toString(matr));
2854
+ }
2855
+ },
2856
+ calc: {
2857
+ lim: function(func, val) {
2858
+ if(func.type === "expl") {
2859
+ if(val === Infinity) {
2860
+ if(Chalkboard.real.val(func, 101) > Chalkboard.real.val(func, 100)) {
2861
+ return Infinity;
2862
+ } else if(Chalkboard.real.val(func, 101) < Chalkboard.real.val(func, 100)) {
2863
+ return -Infinity;
2864
+ }
2865
+ } else if(val === -Infinity) {
2866
+ if(Chalkboard.real.val(func, -101) > Chalkboard.real.val(func, -100)) {
2867
+ return Infinity;
2868
+ } else if(Chalkboard.real.val(func, -101) < Chalkboard.real.val(func, -100)) {
2869
+ return -Infinity;
2870
+ }
2871
+ } else {
2872
+ if(Chalkboard.real.val(func, val - 0.000001).toFixed(4) === Chalkboard.real.val(func, val + 0.000001).toFixed(4)) {
2873
+ if(Chalkboard.real.val(func, val) !== Infinity || Chalkboard.real.val(func, val) !== -Infinity) {
2874
+ return Chalkboard.real.val(func, val);
2875
+ } else {
2876
+ return undefined;
2877
+ }
2878
+ } else {
2879
+ return undefined;
2880
+ }
2881
+ }
2882
+ } else {
2883
+ return "TypeError: Parameter \"func\" must be of type \"expl\".";
2884
+ }
2885
+ },
2886
+ dfdx: function(func, val) {
2887
+ var h = 0.000000001;
2888
+ if(func.type === "expl") {
2889
+ var f = Chalkboard.real.parse("x => " + func.definition);
2890
+ return (f(val + h) - f(val)) / h;
2891
+ } else if(func.type === "pola") {
2892
+ var r = Chalkboard.real.parse("O => " + func.definition);
2893
+ return (r(val + h) - r(val)) / h;
2894
+ } else if(func.type === "curv") {
2895
+ if(func.definition.length === 2) {
2896
+ var x = Chalkboard.real.parse("t => " + func.definition[0]),
2897
+ y = Chalkboard.real.parse("t => " + func.definition[1]);
2898
+ return Chalkboard.vec2.new((x(val + h) - x(val)) / h, (y(val + h) - y(val)) / h);
2899
+ } else if(func.definition.length === 3) {
2900
+ var x = Chalkboard.real.parse("t => " + func.definition[0]),
2901
+ y = Chalkboard.real.parse("t => " + func.definition[1]),
2902
+ z = Chalkboard.real.parse("t => " + func.definition[2]);
2903
+ return Chalkboard.vec3.new((x(val + h) - x(val)) / h, (y(val + h) - y(val)) / h, (z(val + h) - z(val)) / h);
2904
+ }
2905
+ } else {
2906
+ return "TypeError: Parameter \"func\" must be of type \"expl\", \"pola\", or \"curv\".";
2907
+ }
2908
+ },
2909
+ d2fdx2: function(func, val) {
2910
+ var h = 0.00001;
2911
+ if(func.type === "expl") {
2912
+ var f = Chalkboard.real.parse("x => " + func.definition);
2913
+ return (f(val + h) - 2 * f(val) + f(val - h)) / (h * h);
2914
+ } else if(func.type === "pola") {
2915
+ var r = Chalkboard.real.parse("O => " + func.definition);
2916
+ return (r(val + h) - 2 * r(val) + r(val - h)) / (h * h);
2917
+ } else if(func.type === "curv") {
2918
+ if(func.definition.length === 2) {
2919
+ var x = Chalkboard.real.parse("t => " + func.definition[0]),
2920
+ y = Chalkboard.real.parse("t => " + func.definition[1]);
2921
+ return Chalkboard.vec2.new((x(val + h) - 2 * x(val) + x(val - h)) / (h * h), (y(val + h) - 2 * y(val) + y(val - h)) / (h * h));
2922
+ } else if(func.definition.length === 3) {
2923
+ var x = Chalkboard.real.parse("t => " + func.definition[0]),
2924
+ y = Chalkboard.real.parse("t => " + func.definition[1]),
2925
+ z = Chalkboard.real.parse("t => " + func.definition[2]);
2926
+ 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));
2927
+ }
2928
+ } else {
2929
+ return "TypeError: Parameter \"func\" must be of type \"expl\", \"pola\", or \"curv\".";
2930
+ }
2931
+ },
2932
+ tangent: function(func, val) {
2933
+ if(func.type === "curv") {
2934
+ if(func.definition.length === 2) {
2935
+ return Chalkboard.vec2.normalize(Chalkboard.calc.dfdx(func, val));
2936
+ } else if(func.definition.length === 3) {
2937
+ return Chalkboard.vec3.normalize(Chalkboard.calc.dfdx(func, val));
2938
+ }
2939
+ } else {
2940
+ return "TypeError: Parameter \"func\" must be of type \"curv\".";
2941
+ }
2942
+ },
2943
+ normal: function(func, val) {
2944
+ if(func.type === "curv") {
2945
+ if(func.definition.length === 2) {
2946
+ return Chalkboard.vec2.normalize(Chalkboard.calc.d2fdx2(func, val));
2947
+ } else if(func.definition.length === 3) {
2948
+ return Chalkboard.vec3.normalize(Chalkboard.calc.d2fdx2(func, val));
2949
+ }
2950
+ } else {
2951
+ return "TypeError: Parameter \"func\" must be of type \"curv\".";
2952
+ }
2953
+ },
2954
+ binormal: function(func, val) {
2955
+ if(func.type === "curv") {
2956
+ if(func.definition.length === 2) {
2957
+ return Chalkboard.vec2.cross(Chalkboard.calc.tangent(func, val), Chalkboard.calc.normal(func, val));
2958
+ } else if(func.definition.length === 3) {
2959
+ return Chalkboard.vec3.cross(Chalkboard.calc.tangent(func, val), Chalkboard.calc.normal(func, val));
2960
+ }
2961
+ } else {
2962
+ return "TypeError: Parameter \"func\" must be of type \"curv\".";
2963
+ }
2964
+ },
2965
+ dfdv: function(func, vec2_pos, vec2_dir) {
2966
+ if(func.type === "mult") {
2967
+ return Chalkboard.vec2.dot(Chalkboard.calc.grad(func, vec2_pos), Chalkboard.vec2.normalize(vec2_dir));
2968
+ } else {
2969
+ return "TypeError: Parameter \"func\" must be of type \"mult\".";
2970
+ }
2971
+ },
2972
+ dfrdt: function(func_1, func_2, val) {
2973
+ if(func_1.type === "mult") {
2974
+ if(func_2.type === "curv") {
2975
+ if(func_2.definition.length === 2) {
2976
+ var dfdx = Chalkboard.calc.grad(func_1, Chalkboard.real.val(func_2, val)).x,
2977
+ dfdy = Chalkboard.calc.grad(func_1, Chalkboard.real.val(func_2, val)).y,
2978
+ dxdt = Chalkboard.calc.dfdx(func_2, val).x,
2979
+ dydt = Chalkboard.calc.dfdx(func_2, val).y;
2980
+ return dfdx * dxdt + dfdy * dydt;
2981
+ }
2982
+ } else {
2983
+ return "TypeError: Parameter \"func_2\" must be of type \"curv\".";
2984
+ }
2985
+ } else {
2986
+ return "TypeError: Parameter \"func_1\" must be of type \"mult\".";
2987
+ }
2988
+ },
2989
+ grad: function(funcORvecfield, vec) {
2990
+ var h = 0.000000001;
2991
+ if(funcORvecfield.type === "surf") {
2992
+ var x = Chalkboard.real.parse("(s, t) => " + funcORvecfield.definition[0]),
2993
+ y = Chalkboard.real.parse("(s, t) => " + funcORvecfield.definition[1]),
2994
+ z = Chalkboard.real.parse("(s, t) => " + funcORvecfield.definition[2]);
2995
+ var dxds = (x(vec.x + h, vec.y) - x(vec.x, vec.y)) / h,
2996
+ dxdt = (x(vec.x, vec.y + h) - x(vec.x, vec.y)) / h,
2997
+ dyds = (y(vec.x + h, vec.y) - y(vec.x, vec.y)) / h,
2998
+ dydt = (y(vec.x, vec.y + h) - y(vec.x, vec.y)) / h,
2999
+ dzds = (z(vec.x + h, vec.y) - z(vec.x, vec.y)) / h,
3000
+ dzdt = (z(vec.x, vec.y + h) - z(vec.x, vec.y)) / h;
3001
+ return Chalkboard.matr.new([dxds, dxdt],
3002
+ [dyds, dydt],
3003
+ [dzds, dzdt]);
3004
+ } else if(funcORvecfield.type === "mult") {
3005
+ var f = Chalkboard.real.parse("(x, y) => " + funcORvecfield.definition);
3006
+ var dfdx = (f(vec.x + h, vec.y) - f(vec.x, vec.y)) / h,
3007
+ dfdy = (f(vec.x, vec.y + h) - f(vec.x, vec.y)) / h;
3008
+ return Chalkboard.vec2.new(dfdx, dfdy);
3009
+ } else if(funcORvecfield.type === "vec2field") {
3010
+ var p = Chalkboard.real.parse("(x, y) => " + funcORvecfield.p),
3011
+ q = Chalkboard.real.parse("(x, y) => " + funcORvecfield.q);
3012
+ var dpdx = (p(vec.x + h, vec.y) - p(vec.x, vec.y)) / h,
3013
+ dpdy = (p(vec.x, vec.y + h) - p(vec.x, vec.y)) / h,
3014
+ dqdx = (q(vec.x + h, vec.y) - q(vec.x, vec.y)) / h,
3015
+ dqdy = (q(vec.x, vec.y + h) - q(vec.x, vec.y)) / h;
3016
+ return Chalkboard.matr.new([dpdx, dpdy],
3017
+ [dqdx, dqdy]);
3018
+ } else if(funcORvecfield.type === "vec3field") {
3019
+ var p = Chalkboard.real.parse("(x, y, z) => " + funcORvecfield.p),
3020
+ q = Chalkboard.real.parse("(x, y, z) => " + funcORvecfield.q),
3021
+ r = Chalkboard.real.parse("(x, y, z) => " + funcORvecfield.r);
3022
+ var dpdx = (p(vec.x + h, vec.y, vec.z) - p(vec.x, vec.y, vec.z)) / h,
3023
+ dpdy = (p(vec.x, vec.y + h, vec.z) - p(vec.x, vec.y, vec.z)) / h,
3024
+ dpdz = (p(vec.x, vec.y, vec.z + h) - p(vec.x, vec.y, vec.z)) / h,
3025
+ dqdx = (q(vec.x + h, vec.y, vec.z) - q(vec.x, vec.y, vec.z)) / h,
3026
+ dqdy = (q(vec.x, vec.y + h, vec.z) - q(vec.x, vec.y, vec.z)) / h,
3027
+ dqdz = (q(vec.x, vec.y, vec.z + h) - q(vec.x, vec.y, vec.z)) / h,
3028
+ drdx = (r(vec.x + h, vec.y, vec.z) - r(vec.x, vec.y, vec.z)) / h,
3029
+ drdy = (r(vec.x, vec.y + h, vec.z) - r(vec.x, vec.y, vec.z)) / h,
3030
+ drdz = (r(vec.x, vec.y, vec.z + h) - r(vec.x, vec.y, vec.z)) / h;
3031
+ return Chalkboard.matr.new([dpdx, dpdy, dpdz],
3032
+ [dqdx, dqdy, dqdz],
3033
+ [drdx, drdy, drdz]);
3034
+ } else if(funcORvecfield.type === "vec4field") {
3035
+ var p = Chalkboard.real.parse("(x, y, z, w) => " + funcORvecfield.p),
3036
+ q = Chalkboard.real.parse("(x, y, z, w) => " + funcORvecfield.q),
3037
+ r = Chalkboard.real.parse("(x, y, z, w) => " + funcORvecfield.r),
3038
+ s = Chalkboard.real.parse("(x, y, z, w) => " + funcORvecfield.s);
3039
+ var dpdx = (p(vec.x + h, vec.y, vec.z, vec.w) - p(vec.x, vec.y, vec.z, vec.w)) / h,
3040
+ dpdy = (p(vec.x, vec.y + h, vec.z, vec.w) - p(vec.x, vec.y, vec.z, vec.w)) / h,
3041
+ dpdz = (p(vec.x, vec.y, vec.z + h, vec.w) - p(vec.x, vec.y, vec.z, vec.w)) / h,
3042
+ dpdw = (p(vec.x, vec.y, vec.z, vec.w + h) - p(vec.x, vec.y, vec.z, vec.w)) / h,
3043
+ dqdx = (q(vec.x + h, vec.y, vec.z, vec.w) - q(vec.x, vec.y, vec.z, vec.w)) / h,
3044
+ dqdy = (q(vec.x, vec.y + h, vec.z, vec.w) - q(vec.x, vec.y, vec.z, vec.w)) / h,
3045
+ dqdz = (q(vec.x, vec.y, vec.z + h, vec.w) - q(vec.x, vec.y, vec.z, vec.w)) / h,
3046
+ dqdw = (q(vec.x, vec.y, vec.z, vec.w + h) - q(vec.x, vec.y, vec.z, vec.w)) / h,
3047
+ drdx = (r(vec.x + h, vec.y, vec.z, vec.w) - r(vec.x, vec.y, vec.z, vec.w)) / h,
3048
+ drdy = (r(vec.x, vec.y + h, vec.z, vec.w) - r(vec.x, vec.y, vec.z, vec.w)) / h,
3049
+ drdz = (r(vec.x, vec.y, vec.z + h, vec.w) - r(vec.x, vec.y, vec.z, vec.w)) / h,
3050
+ drdw = (r(vec.x, vec.y, vec.z, vec.w + h) - r(vec.x, vec.y, vec.z, vec.w)) / h,
3051
+ dsdx = (s(vec.x + h, vec.y, vec.z, vec.w) - s(vec.x, vec.y, vec.z, vec.w)) / h,
3052
+ dsdy = (s(vec.x, vec.y + h, vec.z, vec.w) - s(vec.x, vec.y, vec.z, vec.w)) / h,
3053
+ dsdz = (s(vec.x, vec.y, vec.z + h, vec.w) - s(vec.x, vec.y, vec.z, vec.w)) / h,
3054
+ dsdw = (s(vec.x, vec.y, vec.z, vec.w + h) - s(vec.x, vec.y, vec.z, vec.w)) / h;
3055
+ return Chalkboard.matr.new([dpdx, dpdy, dpdz, dpdw],
3056
+ [dqdx, dqdy, dqdz, dqdw],
3057
+ [drdx, drdy, drdz, drdw],
3058
+ [dsdx, dsdy, dsdz, dsdw]);
3059
+ } else {
3060
+ return "TypeError: Parameter \"funcORvecfield\" must be of type \"surf\", \"mult\", \"vec2field\", \"vec3field\", or \"vec4field\".";
3061
+ }
3062
+ },
3063
+ grad2: function(funcORvecfield, vec) {
3064
+ var h = 0.00001;
3065
+ if(funcORvecfield.type === "surf") {
3066
+ var x = Chalkboard.real.parse("(s, t) => " + funcORvecfield.definition[0]),
3067
+ y = Chalkboard.real.parse("(s, t) => " + funcORvecfield.definition[1]),
3068
+ z = Chalkboard.real.parse("(s, t) => " + funcORvecfield.definition[2]);
3069
+ var d2xds2 = (x(vec.x + h, vec.y) - 2 * x(vec.x, vec.y) + x(vec.x - h, vec.y)) / (h * h),
3070
+ d2xdt2 = (x(vec.x, vec.y + h) - 2 * x(vec.x, vec.y) + x(vec.x, vec.y - h)) / (h * h),
3071
+ d2yds2 = (y(vec.x + h, vec.y) - 2 * y(vec.x, vec.y) + y(vec.x - h, vec.y)) / (h * h),
3072
+ d2ydt2 = (y(vec.x, vec.y + h) - 2 * y(vec.x, vec.y) + y(vec.x, vec.y - h)) / (h * h),
3073
+ d2zds2 = (z(vec.x + h, vec.y) - 2 * z(vec.x, vec.y) + z(vec.x - h, vec.y)) / (h * h),
3074
+ d2zdt2 = (z(vec.x, vec.y + h) - 2 * z(vec.x, vec.y) + z(vec.x, vec.y - h)) / (h * h);
3075
+ return Chalkboard.matr.new([d2xds2, d2xdt2],
3076
+ [d2yds2, d2ydt2],
3077
+ [d2zds2, d2zdt2]);
3078
+ } else if(funcORvecfield.type === "mult") {
3079
+ var f = Chalkboard.real.parse("(x, y) => " + funcORvecfield.definition);
3080
+ var d2fdx2 = (f(vec.x + h, vec.y) - 2 * f(vec.x, vec.y) + f(vec.x - h, vec.y)) / (h * h),
3081
+ d2fdy2 = (f(vec.x, vec.y + h) - 2 * f(vec.x, vec.y) + f(vec.x, vec.y - h)) / (h * h),
3082
+ d2fdxdy = (f(vec.x + h, vec.y + h) - f(vec.x + h, vec.y) - f(vec.x, vec.y + h) + f(vec.x, vec.y)) / (h * h),
3083
+ d2fdydx = (f(vec.x + h, vec.y + h) - f(vec.x, vec.y + h) - f(vec.x + h, vec.y) + f(vec.x, vec.y)) / (h * h);
3084
+ return Chalkboard.matr.new([d2fdx2, d2fdxdy],
3085
+ [d2fdydx, d2fdy2]);
3086
+ } else if(funcORvecfield.type === "vec2field") {
3087
+ var p = Chalkboard.real.parse("(x, y) => " + funcORvecfield.p),
3088
+ q = Chalkboard.real.parse("(x, y) => " + funcORvecfield.q);
3089
+ var d2pdx2 = (p(vec.x + h, vec.y) - 2 * p(vec.x, vec.y) + p(vec.x - h, vec.y)) / (h * h),
3090
+ d2pdy2 = (p(vec.x, vec.y + h) - 2 * p(vec.x, vec.y) + p(vec.x, vec.y - h)) / (h * h),
3091
+ d2qdx2 = (q(vec.x + h, vec.y) - 2 * q(vec.x, vec.y) + q(vec.x - h, vec.y)) / (h * h),
3092
+ d2qdy2 = (q(vec.x, vec.y + h) - 2 * q(vec.x, vec.y) + q(vec.x, vec.y - h)) / (h * h);
3093
+ return Chalkboard.matr.new([d2pdx2, d2pdy2],
3094
+ [d2qdx2, d2qdy2]);
3095
+ } else if(funcORvecfield.type === "vec3field") {
3096
+ var p = Chalkboard.real.parse("(x, y, z) => " + funcORvecfield.p),
3097
+ q = Chalkboard.real.parse("(x, y, z) => " + funcORvecfield.q),
3098
+ r = Chalkboard.real.parse("(x, y, z) => " + funcORvecfield.r);
3099
+ var d2pdx2 = (p(vec.x + h, vec.y, vec.z) - 2 * p(vec.x, vec.y, vec.z) + p(vec.x - h, vec.y, vec.z)) / (h * h),
3100
+ d2pdy2 = (p(vec.x, vec.y + h, vec.z) - 2 * p(vec.x, vec.y, vec.z) + p(vec.x, vec.y - h, vec.z)) / (h * h),
3101
+ d2pdz2 = (p(vec.x, vec.y, vec.z + h) - 2 * p(vec.x, vec.y, vec.z) + p(vec.x, vec.y, vec.z - h)) / (h * h),
3102
+ d2qdx2 = (q(vec.x + h, vec.y, vec.z) - 2 * q(vec.x, vec.y, vec.z) + q(vec.x - h, vec.y, vec.z)) / (h * h),
3103
+ d2qdy2 = (q(vec.x, vec.y + h, vec.z) - 2 * q(vec.x, vec.y, vec.z) + q(vec.x, vec.y - h, vec.z)) / (h * h),
3104
+ d2qdz2 = (q(vec.x, vec.y, vec.z + h) - 2 * q(vec.x, vec.y, vec.z) + q(vec.x, vec.y, vec.z - h)) / (h * h),
3105
+ d2rdx2 = (r(vec.x + h, vec.y, vec.z) - 2 * r(vec.x, vec.y, vec.z) + r(vec.x - h, vec.y, vec.z)) / (h * h),
3106
+ d2rdy2 = (r(vec.x, vec.y + h, vec.z) - 2 * r(vec.x, vec.y, vec.z) + r(vec.x, vec.y - h, vec.z)) / (h * h),
3107
+ d2rdz2 = (r(vec.x, vec.y, vec.z + h) - 2 * r(vec.x, vec.y, vec.z) + r(vec.x, vec.y, vec.z - h)) / (h * h);
3108
+ return Chalkboard.matr.new([d2pdx2, d2pdy2, d2pdz2],
3109
+ [d2qdx2, d2qdy2, d2qdz2],
3110
+ [d2rdx2, d2rdy2, d2rdz2]);
3111
+ } else if(funcORvecfield.type === "vec4field") {
3112
+ var p = Chalkboard.real.parse("(x, y, z, w) => " + funcORvecfield.p),
3113
+ q = Chalkboard.real.parse("(x, y, z, w) => " + funcORvecfield.q),
3114
+ r = Chalkboard.real.parse("(x, y, z, w) => " + funcORvecfield.r),
3115
+ s = Chalkboard.real.parse("(x, y, z, w) => " + funcORvecfield.s);
3116
+ var d2pdx2 = (p(vec.x + h, vec.y, vec.z, vec.w) - 2 * p(vec.x, vec.y, vec.z, vec.w) + p(vec.x - h, vec.y, vec.z, vec.w)) / (h * h),
3117
+ d2pdy2 = (p(vec.x, vec.y + h, vec.z, vec.w) - 2 * p(vec.x, vec.y, vec.z, vec.w) + p(vec.x, vec.y - h, vec.z, vec.w)) / (h * h),
3118
+ d2pdz2 = (p(vec.x, vec.y, vec.z + h, vec.w) - 2 * p(vec.x, vec.y, vec.z, vec.w) + p(vec.x, vec.y, vec.z - h, vec.w)) / (h * h),
3119
+ d2pdw2 = (p(vec.x, vec.y, vec.z, vec.w + h) - 2 * p(vec.x, vec.y, vec.z, vec.w) + p(vec.x, vec.y, vec.z, vec.w - h)) / (h * h),
3120
+ d2qdx2 = (q(vec.x + h, vec.y, vec.z, vec.w) - 2 * q(vec.x, vec.y, vec.z, vec.w) + q(vec.x - h, vec.y, vec.z, vec.w)) / (h * h),
3121
+ d2qdy2 = (q(vec.x, vec.y + h, vec.z, vec.w) - 2 * q(vec.x, vec.y, vec.z, vec.w) + q(vec.x, vec.y - h, vec.z, vec.w)) / (h * h),
3122
+ d2qdz2 = (q(vec.x, vec.y, vec.z + h, vec.w) - 2 * q(vec.x, vec.y, vec.z, vec.w) + q(vec.x, vec.y, vec.z - h, vec.w)) / (h * h),
3123
+ d2qdw2 = (q(vec.x, vec.y, vec.z, vec.w + h) - 2 * q(vec.x, vec.y, vec.z, vec.w) + q(vec.x, vec.y, vec.z, vec.w - h)) / (h * h),
3124
+ d2rdx2 = (r(vec.x + h, vec.y, vec.z, vec.w) - 2 * r(vec.x, vec.y, vec.z, vec.w) + r(vec.x - h, vec.y, vec.z, vec.w)) / (h * h),
3125
+ d2rdy2 = (r(vec.x, vec.y + h, vec.z, vec.w) - 2 * r(vec.x, vec.y, vec.z, vec.w) + r(vec.x, vec.y - h, vec.z, vec.w)) / (h * h),
3126
+ d2rdz2 = (r(vec.x, vec.y, vec.z + h, vec.w) - 2 * r(vec.x, vec.y, vec.z, vec.w) + r(vec.x, vec.y, vec.z - h, vec.w)) / (h * h),
3127
+ d2rdw2 = (r(vec.x, vec.y, vec.z, vec.w + h) - 2 * r(vec.x, vec.y, vec.z, vec.w) + r(vec.x, vec.y, vec.z, vec.w - h)) / (h * h),
3128
+ d2sdx2 = (s(vec.x + h, vec.y, vec.z, vec.w) - 2 * s(vec.x, vec.y, vec.z, vec.w) + s(vec.x - h, vec.y, vec.z, vec.w)) / (h * h),
3129
+ d2sdy2 = (s(vec.x, vec.y + h, vec.z, vec.w) - 2 * s(vec.x, vec.y, vec.z, vec.w) + s(vec.x, vec.y - h, vec.z, vec.w)) / (h * h),
3130
+ d2sdz2 = (s(vec.x, vec.y, vec.z + h, vec.w) - 2 * s(vec.x, vec.y, vec.z, vec.w) + s(vec.x, vec.y, vec.z - h, vec.w)) / (h * h),
3131
+ d2sdw2 = (s(vec.x, vec.y, vec.z, vec.w + h) - 2 * s(vec.x, vec.y, vec.z, vec.w) + s(vec.x, vec.y, vec.z, vec.w - h)) / (h * h);
3132
+ return Chalkboard.matr.new([d2pdx2, d2pdy2, d2pdz2, d2pdw2],
3133
+ [d2qdx2, d2qdy2, d2qdz2, d2qdw2],
3134
+ [d2rdx2, d2rdy2, d2rdz2, d2rdw2],
3135
+ [d2sdx2, d2sdy2, d2sdz2, d2sdw2]);
3136
+ } else {
3137
+ return "TypeError: Parameter \"funcORvecfield\" must be of type \"surf\", \"mult\", \"vec2field\", \"vec3field\", or \"vec4field\".";
3138
+ }
3139
+ },
3140
+ div: function(vecfield, vec) {
3141
+ if(vecfield.type === "vec2field" || vecfield.type === "vec3field" || vecfield.type === "vec4field") {
3142
+ return Chalkboard.matr.trace(Chalkboard.calc.grad(vecfield, vec));
3143
+ } else {
3144
+ return "TypeError: Parameter \"vecfield\" must be of type \"vec2field\", \"vec3field\", or \"vec4field\".";
3145
+ }
3146
+ },
3147
+ curl: function(vecfield, vec) {
3148
+ var h = 0.000000001;
3149
+ if(vecfield.type === "vec2field") {
3150
+ var p = Chalkboard.real.parse("(x, y) => " + vecfield.p),
3151
+ q = Chalkboard.real.parse("(x, y) => " + vecfield.q);
3152
+ var dpdy = (p(vec.x, vec.y + h) - p(vec.x, vec.y)) / h,
3153
+ dqdx = (q(vec.x + h, vec.y) - q(vec.x, vec.y)) / h;
3154
+ return Chalkboard.vec3.new(0, 0, dqdx - dpdy);
3155
+ } else if(vecfield.type === "vec3field") {
3156
+ var p = Chalkboard.real.parse("(x, y, z) => " + vecfield.p),
3157
+ q = Chalkboard.real.parse("(x, y, z) => " + vecfield.q),
3158
+ r = Chalkboard.real.parse("(x, y, z) => " + vecfield.r);
3159
+ var dpdy = (p(vec.x, vec.y + h, vec.z) - p(vec.x, vec.y, vec.z)) / h,
3160
+ dpdz = (p(vec.x, vec.y, vec.z + h) - p(vec.x, vec.y, vec.z)) / h,
3161
+ dqdx = (q(vec.x + h, vec.y, vec.z) - q(vec.x, vec.y, vec.z)) / h,
3162
+ dqdz = (q(vec.x, vec.y, vec.z + h) - q(vec.x, vec.y, vec.z)) / h,
3163
+ drdx = (r(vec.x + h, vec.y, vec.z) - r(vec.x, vec.y, vec.z)) / h,
3164
+ drdy = (r(vec.x, vec.y + h, vec.z) - r(vec.x, vec.y, vec.z)) / h;
3165
+ return Chalkboard.vec3.new(drdy - dqdz, dpdz - drdx, dqdx - dpdy);
3166
+ } else {
3167
+ return "TypeError: Parameter \"vecfield\" must be of type \"vec2field\" or \"vec3field\".";
3168
+ }
3169
+ },
3170
+ dfdz: function(func, comp) {
3171
+ var h = 0.000000001;
3172
+ if(func.type === "comp") {
3173
+ var u = Chalkboard.comp.parse("(a, b) => " + func.definition[0]),
3174
+ v = Chalkboard.comp.parse("(a, b) => " + func.definition[1]);
3175
+ var duda = (u(comp.a + h, comp.b) - u(comp.a, comp.b)) / h,
3176
+ dudb = (u(comp.a, comp.b + h) - u(comp.a, comp.b)) / h,
3177
+ dvda = (v(comp.a + h, comp.b) - v(comp.a, comp.b)) / h,
3178
+ dvdb = (v(comp.a, comp.b + h) - v(comp.a, comp.b)) / h;
3179
+ return {a: Chalkboard.comp.new(duda, dvda), b: Chalkboard.comp.new(dudb, dvdb)};
3180
+ } else {
3181
+ return "TypeError: Parameter \"func\" must be of type \"comp\".";
3182
+ }
3183
+ },
3184
+ df2dz2: function(func, comp) {
3185
+ var h = 0.00001;
3186
+ if(func.type === "comp") {
3187
+ var u = Chalkboard.comp.parse("(a, b) => " + func.definition[0]),
3188
+ v = Chalkboard.comp.parse("(a, b) => " + func.definition[1]);
3189
+ var d2uda2 = (u(comp.a + h, comp.b) - 2 * u(comp.a, comp.b) + u(comp.a - h, comp.b)) / (h * h),
3190
+ d2udb2 = (u(comp.a, comp.b + h) - 2 * u(comp.a, comp.b) + u(comp.a, comp.b - h)) / (h * h),
3191
+ d2vda2 = (v(comp.a + h, comp.b) - 2 * v(comp.a, comp.b) + v(comp.a - h, comp.b)) / (h * h),
3192
+ d2vdb2 = (v(comp.a, comp.b + h) - 2 * v(comp.a, comp.b) + v(comp.a, comp.b - h)) / (h * h);
3193
+ return {a: Chalkboard.comp.new(d2uda2, d2vda2), b: Chalkboard.comp.new(d2udb2, d2vdb2)};
3194
+ } else {
3195
+ return "TypeError: Parameter \"func\" must be of type \"comp\".";
3196
+ }
3197
+ },
3198
+ fxdx: function(func, a, b) {
3199
+ if(func.type === "expl" || func.type === "pola") {
3200
+ var f;
3201
+ if(func.type === "expl") {
3202
+ f = Chalkboard.real.parse("x => " + func.definition);
3203
+ } else if(func.type === "pola") {
3204
+ f = Chalkboard.real.parse("O => " + "((" + func.definition + ") * (" + func.definition + ")) / 2");
3205
+ }
3206
+ var fx = f(a) + f(b);
3207
+ var dx = (b - a) / 1000000;
3208
+ for(var i = 1; i < 1000000; i++) {
3209
+ fx += i % 2 === 0 ? 2 * f(a + i * dx) : 4 * f(a + i * dx);
3210
+ }
3211
+ return (fx * dx) / 3;
3212
+ } else if(func.type === "curv") {
3213
+ if(func.definition.length === 2) {
3214
+ var x = Chalkboard.real.parse("t => " + func.definition[0]),
3215
+ y = Chalkboard.real.parse("t => " + func.definition[1]);
3216
+ var xt = x(a) + x(b),
3217
+ yt = y(a) + y(b);
3218
+ var dt = (b - a) / 1000000;
3219
+ for(var i = 1; i < 1000000; i++) {
3220
+ xt += i % 2 === 0 ? 2 * x(a + i * dt) : 4 * x(a + i * dt);
3221
+ yt += i % 2 === 0 ? 2 * y(a + i * dt) : 4 * y(a + i * dt);
3222
+ }
3223
+ return Chalkboard.vec2.new((xt * dt) / 3, (yt * dt) / 3);
3224
+ } else if(func.definition.length === 3) {
3225
+ var x = Chalkboard.real.parse("t => " + func.definition[0]),
3226
+ y = Chalkboard.real.parse("t => " + func.definition[1]),
3227
+ z = Chalkboard.real.parse("t => " + func.definition[2]);
3228
+ var xt = x(a) + x(b),
3229
+ yt = y(a) + y(b),
3230
+ zt = z(a) + z(b);
3231
+ var dt = (b - a) / 1000000;
3232
+ for(var i = 1; i < 1000000; i++) {
3233
+ xt += i % 2 === 0 ? 2 * x(a + i * dt) : 4 * x(a + i * dt);
3234
+ yt += i % 2 === 0 ? 2 * y(a + i * dt) : 4 * y(a + i * dt);
3235
+ zt += i % 2 === 0 ? 2 * z(a + i * dt) : 4 * z(a + i * dt);
3236
+ }
3237
+ return Chalkboard.vec3.new((xt * dt) / 3, (yt * dt) / 3, (zt * dt) / 3);
3238
+ }
3239
+ } else {
3240
+ return "TypeError: Parameter \"func\" must be of type \"expl\", \"pola\", or \"curv\".";
3241
+ }
3242
+ },
3243
+ fxydxdy: function(func, a, b, c, d) {
3244
+ if(func.type === "mult") {
3245
+ var f = Chalkboard.real.parse("(x, y) => " + func.definition);
3246
+ var result = 0;
3247
+ var dx = (b - a) / 10000,
3248
+ dy = (d - c) / 10000;
3249
+ for(var x = a; x <= b; x += dx) {
3250
+ for(var y = c; y <= d; y += dy) {
3251
+ result += f(x, y);
3252
+ }
3253
+ }
3254
+ return result * dx * dy;
3255
+ } else {
3256
+ return "TypeError: Parameter \"func\" must be of type \"mult\".";
3257
+ }
3258
+ },
3259
+ fds: function(func, a, b, c, d) {
3260
+ var result = 0;
3261
+ var drdt, drds;
3262
+ if(func.type === "curv") {
3263
+ var dt = (b - a) / 10000;
3264
+ if(func.definition.length === 2) {
3265
+ for(var t = a; t <= b; t += dt) {
3266
+ drdt = Chalkboard.calc.dfdx(func, t);
3267
+ result += Chalkboard.vec2.mag(drdt);
3268
+ }
3269
+ return result * dt;
3270
+ } else if(func.definition.length === 3) {
3271
+ for(var t = a; t <= b; t += dt) {
3272
+ drdt = Chalkboard.calc.dfdx(func, t);
3273
+ result += Chalkboard.vec3.mag(drdt);
3274
+ }
3275
+ return result * dt;
3276
+ }
3277
+ } else if(func.type === "surf") {
3278
+ var dt = (b - a) / 100,
3279
+ ds = (d - c) / 100;
3280
+ for(var s = c; s <= d; s += ds) {
3281
+ for(var t = a; t <= b; t += dt) {
3282
+ drds = Chalkboard.matr.toVector(Chalkboard.calc.grad(func, Chalkboard.vec2.new(s, t)), "vec3", "col", 1);
3283
+ drdt = Chalkboard.matr.toVector(Chalkboard.calc.grad(func, Chalkboard.vec2.new(s, t)), "vec3", "col", 2);
3284
+ result += Chalkboard.vec3.mag(Chalkboard.vec3.cross(drds, drdt));
3285
+ }
3286
+ }
3287
+ return result * ds * dt;
3288
+ } else {
3289
+ return "TypeError: Parameter \"func\" must be of type \"curv\" or \"surf\".";
3290
+ }
3291
+ },
3292
+ frds: function(funcORvecfield, func, a, b) {
3293
+ if(func.type === "curv") {
3294
+ var result = 0;
3295
+ var dt = (b - a) / 10000;
3296
+ if(funcORvecfield.type === "mult") {
3297
+ for(var t = a; t <= b; t += dt) {
3298
+ result += Chalkboard.real.val(funcORvecfield, Chalkboard.vec2.toArray(Chalkboard.real.val(func, t))) * Chalkboard.vec2.mag(Chalkboard.calc.dfdx(func, t));
3299
+ }
3300
+ return result * dt;
3301
+ } else if(funcORvecfield.type === "vec2field") {
3302
+ for(var t = a; t <= b; t += dt) {
3303
+ result += Chalkboard.vec2.dot(Chalkboard.vec2.fromField(funcORvecfield, Chalkboard.real.val(func, t)), Chalkboard.calc.dfdx(func, t));
3304
+ }
3305
+ return result * dt;
3306
+ } else if(funcORvecfield.type === "vec3field") {
3307
+ for(var t = a; t <= b; t += dt) {
3308
+ result += Chalkboard.vec3.dot(Chalkboard.vec3.fromField(funcORvecfield, Chalkboard.real.val(func, t)), Chalkboard.calc.dfdx(func, t));
3309
+ }
3310
+ return result * dt;
3311
+ } else {
3312
+ return "TypeError: Parameter \"funcORvecfield\" must be of type \"mult\", \"vec2field\", or \"vec3field\".";
3313
+ }
3314
+ } else {
3315
+ return "TypeError: Parameter \"func\" must be of type \"curv\".";
3316
+ }
3317
+ },
3318
+ fnds: function(vecfield, func, a, b, c, d) {
3319
+ var result = 0;
3320
+ var drdt, drds;
3321
+ if(func.type === "curv") {
3322
+ var dt = (b - a) / 10000;
3323
+ if(func.definition.length === 2) {
3324
+ for(var t = a; t <= b; t += dt) {
3325
+ drdt = Chalkboard.calc.dfdx(func, t);
3326
+ result += Chalkboard.vec2.dot(Chalkboard.vec2.fromField(vecfield, Chalkboard.real.val(func, t)), Chalkboard.vec2.new(-drdt.y, drdt.x)) * Chalkboard.vec2.mag(drdt);
3327
+ }
3328
+ return result * dt;
3329
+ } else if(func.definition.length === 3) {
3330
+ for(var t = a; t <= b; t += dt) {
3331
+ drdt = Chalkboard.calc.dfdx(func, t);
3332
+ result += Chalkboard.vec3.dot(Chalkboard.vec3.fromField(vecfield, Chalkboard.real.val(func, t)), Chalkboard.calc.normal(func, t)) * Chalkboard.vec3.mag(drdt);
3333
+ }
3334
+ return result * dt;
3335
+ }
3336
+ } else if(func.type === "surf") {
3337
+ var dt = (b - a) / 100,
3338
+ ds = (d - c) / 100;
3339
+ for(var s = c; s <= d; s += ds) {
3340
+ for(var t = a; t <= b; t += dt) {
3341
+ drds = Chalkboard.matr.toVector(Chalkboard.calc.grad(func, Chalkboard.vec2.new(s, t)), "vec3", "col", 1);
3342
+ drdt = Chalkboard.matr.toVector(Chalkboard.calc.grad(func, Chalkboard.vec2.new(s, t)), "vec3", "col", 2);
3343
+ result += Chalkboard.vec3.scalarTriple(Chalkboard.vec3.fromField(vecfield, Chalkboard.real.val(func, Chalkboard.vec2.new(s, t))), drds, drdt);
3344
+ }
3345
+ }
3346
+ return result * ds * dt;
3347
+ } else {
3348
+ return "TypeError: Parameter \"func\" must be of type \"curv\" or \"surf\".";
3349
+ }
3350
+ },
3351
+ fzdz: function(func_1, func_2, a, b) {
3352
+ if(func_1.type === "comp") {
3353
+ if(func_2.type === "curv") {
3354
+ var result = Chalkboard.comp.new(0, 0);
3355
+ var dt = (b - a) / 10000;
3356
+ for(var t = a; t <= b; t += dt) {
3357
+ var fz = Chalkboard.comp.val(func_1, Chalkboard.vec2.toComplex(Chalkboard.real.val(func_2, t)));
3358
+ var rt = Chalkboard.calc.dfdx(func_2, t);
3359
+ result = Chalkboard.comp.add(result, Chalkboard.comp.new((fz.a * rt.x) - (fz.b * rt.y), (fz.b * rt.x) + (fz.a * rt.y)));
3360
+ }
3361
+ return Chalkboard.comp.scl(result, dt);
3362
+ } else {
3363
+ return "TypeError: Parameter \"func_2\" must be of type \"curv\".";
3364
+ }
3365
+ } else {
3366
+ return "TypeError: Parameter \"func_1\" must be of type \"comp\".";
3367
+ }
3368
+ },
3369
+ extrema: function(func, domain) {
3370
+ var result = [];
3371
+ for(var i = domain[0]; i <= domain[1]; i++) {
3372
+ if(Math.round(Chalkboard.calc.dfdx(func, i)) === 0) {
3373
+ result.push(i);
3374
+ }
3375
+ }
3376
+ return result;
3377
+ },
3378
+ mean: function(func, a, b) {
3379
+ return (Chalkboard.calc.fxdx(func, a, b)) / (b - a);
3380
+ },
3381
+ curvature: function(func, val) {
3382
+ if(func.type === "curv") {
3383
+ if(func.definition.length === 2) {
3384
+ var dxdt = Chalkboard.calc.dfdx(func, val).x,
3385
+ dydt = Chalkboard.calc.dfdx(func, val).y,
3386
+ d2xdt2 = Chalkboard.calc.d2fdx2(func, val).x,
3387
+ d2ydt2 = Chalkboard.calc.d2fdx2(func, val).y;
3388
+ return Math.abs(dxdt * d2ydt2 - dydt * d2xdt2) / Math.sqrt((dxdt * dxdt + dydt * dydt) * (dxdt * dxdt + dydt * dydt) * (dxdt * dxdt + dydt * dydt));
3389
+ } else if(func.definition.length === 3) {
3390
+ return Chalkboard.vec3.mag(Chalkboard.calc.normal(func, val)) / Chalkboard.vec3.mag(Chalkboard.calc.dfdx(func, val));
3391
+ }
3392
+ } else {
3393
+ return "TypeError: Parameter \"func\" must be of type \"curv\".";
3394
+ }
3395
+ },
3396
+ convolution: function(func_1, func_2, val) {
3397
+ return Chalkboard.calc.fxdx(Chalkboard.real.function("(" + func_1.definition + ") * (" + func_2.definition.replace(/x/g, "(" + val + " - x)") + ")"), -100, 100);
3398
+ },
3399
+ correlation: function(func_1, func_2, val) {
3400
+ return Chalkboard.calc.fxdx(Chalkboard.real.function("(" + func_1.definition + ") * (" + func_2.definition.replace(/x/g, "(" + val + " + x)") + ")"), -100, 100);
3401
+ },
3402
+ autocorrelation: function(func, val) {
3403
+ return Chalkboard.calc.correlation(func, func, val);
3404
+ },
3405
+ Taylor: function(func, val, n, a) {
3406
+ if(func.type === "expl") {
3407
+ if(n === 0) {
3408
+ return Chalkboard.real.val(func, a);
3409
+ } else if(n === 1) {
3410
+ return Chalkboard.real.val(func, a) + Chalkboard.calc.dfdx(func, a) * (val - a);
3411
+ } else if(n === 2) {
3412
+ return Chalkboard.real.val(func, a) + Chalkboard.calc.dfdx(func, a) * (val - a) + (Chalkboard.calc.d2fdx2(func, a) * (val - a) * (val - a)) / 2;
3413
+ }
3414
+ } else {
3415
+ return "TypeError: Parameter \"func\" must be of type \"expl\".";
3416
+ }
3417
+ },
3418
+ Laplace: function(func, val) {
3419
+ if(val > 0) {
3420
+ return Chalkboard.calc.fxdx(Chalkboard.real.function("(" + func.definition + ") * Math.exp(-" + val + " * x)"), 0, 10);
3421
+ } else {
3422
+ return undefined;
3423
+ }
3424
+ },
3425
+ Fourier: function(func, val) {
3426
+ return (2 * Chalkboard.calc.fxdx(Chalkboard.real.function("(" + func.definition + ") * Math.cos(" + val + " * x)"), 0, 10)) / Chalkboard.PI();
3427
+ },
3428
+ Newton: function(func, domain) {
3429
+ domain = domain || [-1, 1];
3430
+ var x = Chalkboard.numb.random(domain[0], domain[1]);
3431
+ for(var i = 0; i < 10; i++) {
3432
+ x = x - Chalkboard.real.val(func, x) / Chalkboard.calc.dfdx(func, x);
3433
+ }
3434
+ return x;
3435
+ }
3436
+ }
3437
+ };