1 /*
  2     Copyright 2008-2022
  3         Matthias Ehmann,
  4         Michael Gerhaeuser,
  5         Carsten Miller,
  6         Bianca Valentin,
  7         Alfred Wassermann,
  8         Peter Wilfahrt
  9 
 10     This file is part of JSXGraph.
 11 
 12     JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
 13 
 14     You can redistribute it and/or modify it under the terms of the
 15 
 16       * GNU Lesser General Public License as published by
 17         the Free Software Foundation, either version 3 of the License, or
 18         (at your option) any later version
 19       OR
 20       * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
 21 
 22     JSXGraph is distributed in the hope that it will be useful,
 23     but WITHOUT ANY WARRANTY; without even the implied warranty of
 24     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 25     GNU Lesser General Public License for more details.
 26 
 27     You should have received a copy of the GNU Lesser General Public License and
 28     the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
 29     and <http://opensource.org/licenses/MIT/>.
 30  */
 31 
 32 
 33 /*global JXG: true, define: true, Float32Array: true */
 34 /*jslint nomen: true, plusplus: true, bitwise: true*/
 35 
 36 /* depends:
 37  jxg
 38  */
 39 
 40 /**
 41  * @fileoverview In this file the namespace JXG.Math is defined, which is the base namespace
 42  * for namespaces like Math.Numerics, Math.Algebra, Math.Statistics etc.
 43  */
 44 
 45 define(['jxg', 'utils/type'], function (JXG, Type) {
 46 
 47     "use strict";
 48 
 49     var undef,
 50 
 51         /*
 52          * Dynamic programming approach for recursive functions.
 53          * From "Speed up your JavaScript, Part 3" by Nicholas C. Zakas.
 54          * @see JXG.Math.factorial
 55          * @see JXG.Math.binomial
 56          * http://blog.thejit.org/2008/09/05/memoization-in-javascript/
 57          *
 58          * This method is hidden, because it is only used in JXG.Math. If someone wants
 59          * to use it in JSXGraph outside of JXG.Math, it should be moved to jsxgraph.js
 60          */
 61         memoizer = function (f) {
 62             var cache, join;
 63 
 64             if (f.memo) {
 65                 return f.memo;
 66             }
 67 
 68             cache = {};
 69             join = Array.prototype.join;
 70 
 71             f.memo = function () {
 72                 var key = join.call(arguments);
 73 
 74                 // Seems to be a bit faster than "if (a in b)"
 75                 return (cache[key] !== undef) ?
 76                         cache[key] :
 77                         cache[key] = f.apply(this, arguments);
 78             };
 79 
 80             return f.memo;
 81         };
 82 
 83     /**
 84      * Math namespace.
 85      * @namespace
 86      */
 87     JXG.Math = {
 88         /**
 89          * eps defines the closeness to zero. If the absolute value of a given number is smaller
 90          * than eps, it is considered to be equal to zero.
 91          * @type Number
 92          */
 93         eps: 0.000001,
 94 
 95         /**
 96          * Determine the relative difference between two numbers.
 97          * @param  {Number} a First number
 98          * @param  {Number} b Second number
 99          * @returns {Number}  Relative difference between a and b: |a-b| / max(|a|, |b|)
100          */
101         relDif: function(a, b) {
102             var c = Math.abs(a),
103                 d = Math.abs(b);
104 
105             d = Math.max(c, d);
106 
107             return (d === 0.0) ? 0.0 : Math.abs(a - b) / d;
108         },
109 
110         /**
111          * The JavaScript implementation of the % operator returns the symmetric modulo.
112          * mod and "%" are both identical if a >= 0 and m >= 0 but the results differ if a or m < 0.
113          * @param {Number} a
114          * @param {Number} m
115          * @returns {Number} Mathematical modulo <tt>a mod m</tt>
116          */
117         mod: function (a, m) {
118             return a - Math.floor(a / m) * m;
119         },
120 
121         /**
122          * Initializes a vector as an array with the coefficients set to the given value resp. zero.
123          * @param {Number} n Length of the vector
124          * @param {Number} [init=0] Initial value for each coefficient
125          * @returns {Array} A <tt>n</tt> times <tt>m</tt>-matrix represented by a
126          * two-dimensional array. The inner arrays hold the columns, the outer array holds the rows.
127          */
128         vector: function (n, init) {
129             var r, i;
130 
131             init = init || 0;
132             r = [];
133 
134             for (i = 0; i < n; i++) {
135                 r[i] = init;
136             }
137 
138             return r;
139         },
140 
141         /**
142          * Initializes a matrix as an array of rows with the given value.
143          * @param {Number} n Number of rows
144          * @param {Number} [m=n] Number of columns
145          * @param {Number} [init=0] Initial value for each coefficient
146          * @returns {Array} A <tt>n</tt> times <tt>m</tt>-matrix represented by a
147          * two-dimensional array. The inner arrays hold the columns, the outer array holds the rows.
148          */
149         matrix: function (n, m, init) {
150             var r, i, j;
151 
152             init = init || 0;
153             m = m || n;
154             r = [];
155 
156             for (i = 0; i < n; i++) {
157                 r[i] = [];
158 
159                 for (j = 0; j < m; j++) {
160                     r[i][j] = init;
161                 }
162             }
163 
164             return r;
165         },
166 
167         /**
168          * Generates an identity matrix. If n is a number and m is undefined or not a number, a square matrix is generated,
169          * if n and m are both numbers, an nxm matrix is generated.
170          * @param {Number} n Number of rows
171          * @param {Number} [m=n] Number of columns
172          * @returns {Array} A square matrix of length <tt>n</tt> with all coefficients equal to 0 except a_(i,i), i out of (1, ..., n), if <tt>m</tt> is undefined or not a number
173          * or a <tt>n</tt> times <tt>m</tt>-matrix with a_(i,j) = 0 and a_(i,i) = 1 if m is a number.
174          */
175         identity: function (n, m) {
176             var r, i;
177 
178             if ((m === undef) && (typeof m !== 'number')) {
179                 m = n;
180             }
181 
182             r = this.matrix(n, m);
183 
184             for (i = 0; i < Math.min(n, m); i++) {
185                 r[i][i] = 1;
186             }
187 
188             return r;
189         },
190 
191         /**
192          * Generates a 4x4 matrix for 3D to 2D projections.
193          * @param {Number} l Left
194          * @param {Number} r Right
195          * @param {Number} t Top
196          * @param {Number} b Bottom
197          * @param {Number} n Near
198          * @param {Number} f Far
199          * @returns {Array} 4x4 Matrix
200          */
201         frustum: function (l, r, b, t, n, f) {
202             var ret = this.matrix(4, 4);
203 
204             ret[0][0] = (n * 2) / (r - l);
205             ret[0][1] = 0;
206             ret[0][2] = (r + l) / (r - l);
207             ret[0][3] = 0;
208 
209             ret[1][0] = 0;
210             ret[1][1] = (n * 2) / (t - b);
211             ret[1][2] = (t + b) / (t - b);
212             ret[1][3] = 0;
213 
214             ret[2][0] = 0;
215             ret[2][1] = 0;
216             ret[2][2] = -(f + n) / (f - n);
217             ret[2][3] = -(f * n * 2) / (f - n);
218 
219             ret[3][0] = 0;
220             ret[3][1] = 0;
221             ret[3][2] = -1;
222             ret[3][3] = 0;
223 
224             return ret;
225         },
226 
227         /**
228          * Generates a 4x4 matrix for 3D to 2D projections.
229          * @param {Number} fov Field of view in vertical direction, given in rad.
230          * @param {Number} ratio Aspect ratio of the projection plane.
231          * @param {Number} n Near
232          * @param {Number} f Far
233          * @returns {Array} 4x4 Projection Matrix
234          */
235         projection: function (fov, ratio, n, f) {
236             var t = n * Math.tan(fov / 2),
237                 r = t * ratio;
238 
239             return this.frustum(-r, r, -t, t, n, f);
240         },
241 
242         /**
243          * Multiplies a vector vec to a matrix mat: mat * vec. The matrix is interpreted by this function as an array of rows. Please note: This
244          * function does not check if the dimensions match.
245          * @param {Array} mat Two dimensional array of numbers. The inner arrays describe the columns, the outer ones the matrix' rows.
246          * @param {Array} vec Array of numbers
247          * @returns {Array} Array of numbers containing the result
248          * @example
249          * var A = [[2, 1],
250          *          [1, 3]],
251          *     b = [4, 5],
252          *     c;
253          * c = JXG.Math.matVecMult(A, b)
254          * // c === [13, 19];
255          */
256         matVecMult: function (mat, vec) {
257             var i, s, k,
258                 m = mat.length,
259                 n = vec.length,
260                 res = [];
261 
262             if (n === 3) {
263                 for (i = 0; i < m; i++) {
264                     res[i] = mat[i][0] * vec[0] + mat[i][1] * vec[1] + mat[i][2] * vec[2];
265                 }
266             } else {
267                 for (i = 0; i < m; i++) {
268                     s = 0;
269                     for (k = 0; k < n; k++) {
270                         s += mat[i][k] * vec[k];
271                     }
272                     res[i] = s;
273                 }
274             }
275             return res;
276         },
277 
278         /**
279          * Computes the product of the two matrices mat1*mat2.
280          * @param {Array} mat1 Two dimensional array of numbers
281          * @param {Array} mat2 Two dimensional array of numbers
282          * @returns {Array} Two dimensional Array of numbers containing result
283          */
284         matMatMult: function (mat1, mat2) {
285             var i, j, s, k,
286                 m = mat1.length,
287                 n = m > 0 ? mat2[0].length : 0,
288                 m2 = mat2.length,
289                 res = this.matrix(m, n);
290 
291             for (i = 0; i < m; i++) {
292                 for (j = 0; j < n; j++) {
293                     s = 0;
294                     for (k = 0; k < m2; k++) {
295                         s += mat1[i][k] * mat2[k][j];
296                     }
297                     res[i][j] = s;
298                 }
299             }
300             return res;
301         },
302 
303         /**
304          * Transposes a matrix given as a two dimensional array.
305          * @param {Array} M The matrix to be transposed
306          * @returns {Array} The transpose of M
307          */
308         transpose: function (M) {
309             var MT, i, j,
310                 m, n;
311 
312             // number of rows of M
313             m = M.length;
314             // number of columns of M
315             n = M.length > 0 ? M[0].length : 0;
316             MT = this.matrix(n, m);
317 
318             for (i = 0; i < n; i++) {
319                 for (j = 0; j < m; j++) {
320                     MT[i][j] = M[j][i];
321                 }
322             }
323 
324             return MT;
325         },
326 
327         /**
328          * Compute the inverse of an nxn matrix with Gauss elimination.
329          * @param {Array} Ain
330          * @returns {Array} Inverse matrix of Ain
331          */
332         inverse: function (Ain) {
333             var i, j, k, s, ma, r, swp,
334                 n = Ain.length,
335                 A = [],
336                 p = [],
337                 hv = [];
338 
339             for (i = 0; i < n; i++) {
340                 A[i] = [];
341                 for (j = 0; j < n; j++) {
342                     A[i][j] = Ain[i][j];
343                 }
344                 p[i] = i;
345             }
346 
347             for (j = 0; j < n; j++) {
348                 // pivot search:
349                 ma = Math.abs(A[j][j]);
350                 r = j;
351 
352                 for (i = j + 1; i < n; i++) {
353                     if (Math.abs(A[i][j]) > ma) {
354                         ma = Math.abs(A[i][j]);
355                         r = i;
356                     }
357                 }
358 
359                 // Singular matrix
360                 if (ma <= this.eps) {
361                     return [];
362                 }
363 
364                 // swap rows:
365                 if (r > j) {
366                     for (k = 0; k < n; k++) {
367                         swp = A[j][k];
368                         A[j][k] = A[r][k];
369                         A[r][k] = swp;
370                     }
371 
372                     swp = p[j];
373                     p[j] = p[r];
374                     p[r] = swp;
375                 }
376 
377                 // transformation:
378                 s = 1.0 / A[j][j];
379                 for (i = 0; i < n; i++) {
380                     A[i][j] *= s;
381                 }
382                 A[j][j] = s;
383 
384                 for (k = 0; k < n; k++) {
385                     if (k !== j) {
386                         for (i = 0; i < n; i++) {
387                             if (i !== j) {
388                                 A[i][k] -= A[i][j] * A[j][k];
389                             }
390                         }
391                         A[j][k] = -s * A[j][k];
392                     }
393                 }
394             }
395 
396             // swap columns:
397             for (i = 0; i < n; i++) {
398                 for (k = 0; k < n; k++) {
399                     hv[p[k]] = A[i][k];
400                 }
401                 for (k = 0; k < n; k++) {
402                     A[i][k] = hv[k];
403                 }
404             }
405 
406             return A;
407         },
408 
409         /**
410          * Inner product of two vectors a and b. n is the length of the vectors.
411          * @param {Array} a Vector
412          * @param {Array} b Vector
413          * @param {Number} [n] Length of the Vectors. If not given the length of the first vector is taken.
414          * @returns {Number} The inner product of a and b.
415          */
416         innerProduct: function (a, b, n) {
417             var i,
418                 s = 0;
419 
420             if (n === undef || !Type.isNumber(n)) {
421                 n = a.length;
422             }
423 
424             for (i = 0; i < n; i++) {
425                 s += a[i] * b[i];
426             }
427 
428             return s;
429         },
430 
431         /**
432          * Calculates the cross product of two vectors both of length three.
433          * In case of homogeneous coordinates this is either
434          * <ul>
435          * <li>the intersection of two lines</li>
436          * <li>the line through two points</li>
437          * </ul>
438          * @param {Array} c1 Homogeneous coordinates of line or point 1
439          * @param {Array} c2 Homogeneous coordinates of line or point 2
440          * @returns {Array} vector of length 3: homogeneous coordinates of the resulting point / line.
441          */
442         crossProduct: function (c1, c2) {
443             return [c1[1] * c2[2] - c1[2] * c2[1],
444                 c1[2] * c2[0] - c1[0] * c2[2],
445                 c1[0] * c2[1] - c1[1] * c2[0]];
446         },
447 
448         /**
449          * Euclidean norm of a vector.
450          *
451          * @param {Array} a Array containing a vector.
452          * @param {Number} n (Optional) length of the array.
453          * @returns {Number} Euclidean norm of the vector.
454          */
455         norm: function(a, n) {
456             var i, sum = 0.0;
457 
458             if (n === undef || !Type.isNumber(n)) {
459                 n = a.length;
460             }
461 
462             for (i = 0; i < n; i++) {
463                 sum += a[i] * a[i];
464             }
465 
466             return Math.sqrt(sum);
467         },
468 
469         axpy: function (a, x, y) {
470             var i, le = x.length,
471                 p = [];
472             for (i = 0; i < le; i++) {
473                 p[i] = a * x[i] + y[i];
474             }
475             return p;
476         },
477 
478         /**
479          * Compute the factorial of a positive integer. If a non-integer value
480          * is given, the fraction will be ignored.
481          * @function
482          * @param {Number} n
483          * @returns {Number} n! = n*(n-1)*...*2*1
484          */
485         factorial: memoizer(function (n) {
486             if (n < 0) {
487                 return NaN;
488             }
489 
490             n = Math.floor(n);
491 
492             if (n === 0 || n === 1) {
493                 return 1;
494             }
495 
496             return n * this.factorial(n - 1);
497         }),
498 
499         /**
500          * Computes the binomial coefficient n over k.
501          * @function
502          * @param {Number} n Fraction will be ignored
503          * @param {Number} k Fraction will be ignored
504          * @returns {Number} The binomial coefficient n over k
505          */
506         binomial: memoizer(function (n, k) {
507             var b, i;
508 
509             if (k > n || k < 0) {
510                 return NaN;
511             }
512 
513             k = Math.round(k);
514             n = Math.round(n);
515 
516             if (k === 0 || k === n) {
517                 return 1;
518             }
519 
520             b = 1;
521 
522             for (i = 0; i < k; i++) {
523                 b *= (n - i);
524                 b /= (i + 1);
525             }
526 
527             return b;
528         }),
529 
530         /**
531          * Calculates the cosine hyperbolicus of x.
532          * @function
533          * @param {Number} x The number the cosine hyperbolicus will be calculated of.
534          * @returns {Number} Cosine hyperbolicus of the given value.
535          */
536         cosh: Math.cosh || function (x) {
537             return (Math.exp(x) + Math.exp(-x)) * 0.5;
538         },
539 
540         /**
541          * Sine hyperbolicus of x.
542          * @function
543          * @param {Number} x The number the sine hyperbolicus will be calculated of.
544          * @returns {Number} Sine hyperbolicus of the given value.
545          */
546         sinh: Math.sinh || function (x) {
547             return (Math.exp(x) - Math.exp(-x)) * 0.5;
548         },
549 
550         /**
551          * Hyperbolic arc-cosine of a number.
552          *
553          * @param {Number} x
554          * @returns {Number}
555          */
556         acosh: Math.acosh || function(x) {
557             return Math.log(x + Math.sqrt(x * x - 1));
558         },
559 
560         /**
561          * Hyperbolic arcsine of a number
562          * @param {Number} x
563          * @returns {Number}
564          */
565         asinh: Math.asinh || function(x) {
566             if (x === -Infinity) {
567                 return x;
568             }
569             return Math.log(x + Math.sqrt(x * x + 1));
570         },
571 
572         /**
573          * Computes the cotangent of x.
574          * @function
575          * @param {Number} x The number the cotangent will be calculated of.
576          * @returns {Number} Cotangent of the given value.
577          */
578         cot: function (x) {
579             return 1 / Math.tan(x);
580         },
581 
582         /**
583          * Computes the inverse cotangent of x.
584          * @param {Number} x The number the inverse cotangent will be calculated of.
585          * @returns {Number} Inverse cotangent of the given value.
586          */
587         acot: function (x) {
588             return ((x >= 0) ? (0.5) : (-0.5)) * Math.PI - Math.atan(x);
589         },
590 
591         /**
592          * Compute n-th real root of a real number. n must be strictly positive integer.
593          * If n is odd, the real n-th root exists and is negative.
594          * For n even, for negative valuees of x NaN is returned
595          * @param  {Number} x radicand. Must be non-negative, if n even.
596          * @param  {Number} n index of the root. must be strictly positive integer.
597          * @returns {Number} returns real root or NaN
598          *
599          * @example
600          * nthroot(16, 4): 2
601          * nthroot(-27, 3): -3
602          * nthroot(-4, 2): NaN
603          */
604         nthroot: function(x, n) {
605             var inv = 1 / n;
606 
607             if (n <= 0 || Math.floor(n) !== n) {
608                 return NaN;
609             }
610 
611             if (x === 0.0) {
612                 return 0.0;
613             }
614 
615             if (x > 0) {
616                 return Math.exp(inv * Math.log(x));
617             }
618 
619             // From here on, x is negative
620             if (n % 2 === 1) {
621                 return -Math.exp(inv * Math.log(-x));
622             }
623 
624             // x negative, even root
625             return NaN;
626         },
627 
628         /**
629          * Computes cube root of real number
630          * Polyfill for Math.cbrt().
631          *
632          * @function
633          * @param  {Number} x Radicand
634          * @returns {Number} Cube root of x.
635          */
636         cbrt: Math.cbrt || function(x) {
637             return this.nthroot(x, 3);
638         },
639 
640         /**
641          * Compute base to the power of exponent.
642          * @param {Number} base
643          * @param {Number} exponent
644          * @returns {Number} base to the power of exponent.
645          */
646         pow: function (base, exponent) {
647             if (base === 0) {
648                 if (exponent === 0) {
649                     return 1;
650                 }
651                 return 0;
652             }
653 
654             // exponent is an integer
655             if (Math.floor(exponent) === exponent) {
656                 return Math.pow(base, exponent);
657             }
658 
659             // exponent is not an integer
660             if (base > 0) {
661                 return Math.exp(exponent * Math.log(base));
662             }
663 
664             return NaN;
665         },
666 
667         /**
668          * Compute base to the power of the rational exponent m / n.
669          * This function first reduces the fraction m/n and then computes
670          * JXG.Math.pow(base, m/n).
671          *
672          * This function is necessary to have the same results for e.g.
673          * (-8)^(1/3) = (-8)^(2/6) = -2
674          * @param {Number} base
675          * @param {Number} m numerator of exponent
676          * @param {Number} n denominator of exponent
677          * @returns {Number} base to the power of exponent.
678          */
679         ratpow: function(base, m, n) {
680             var g;
681             if (m === 0) {
682                 return 1;
683             }
684             if (n === 0) {
685                 return NaN;
686             }
687 
688             g = this.gcd(m, n);
689             return this.nthroot(this.pow(base, m / g), n / g);
690         },
691 
692         /**
693          * Logarithm to base 10.
694          * @param {Number} x
695          * @returns {Number} log10(x) Logarithm of x to base 10.
696          */
697         log10: function (x) {
698             return Math.log(x) / Math.log(10.0);
699         },
700 
701         /**
702          * Logarithm to base 2.
703          * @param {Number} x
704          * @returns {Number} log2(x) Logarithm of x to base 2.
705          */
706         log2: function (x) {
707             return Math.log(x) / Math.log(2.0);
708         },
709 
710         /**
711          * Logarithm to arbitrary base b. If b is not given, natural log is taken, i.e. b = e.
712          * @param {Number} x
713          * @param {Number} b base
714          * @returns {Number} log(x, b) Logarithm of x to base b, that is log(x)/log(b).
715          */
716         log: function (x, b) {
717             if (b !== undefined && Type.isNumber(b)) {
718                 return Math.log(x) / Math.log(b);
719             }
720 
721             return Math.log(x);
722         },
723 
724         /**
725          * The sign() function returns the sign of a number, indicating whether the number is positive, negative or zero.
726          *
727          * @function
728          * @param  {Number} x A Number
729          * @returns {[type]}  This function has 5 kinds of return values,
730          *    1, -1, 0, -0, NaN, which represent "positive number", "negative number", "positive zero", "negative zero"
731          *    and NaN respectively.
732          */
733         sign: Math.sign || function(x) {
734             x = +x; // convert to a number
735             if (x === 0 || isNaN(x)) {
736                 return x;
737             }
738             return x > 0 ? 1 : -1;
739         },
740 
741         /**
742          * A square & multiply algorithm to compute base to the power of exponent.
743          * Implementated by Wolfgang Riedl.
744          *
745          * @param {Number} base
746          * @param {Number} exponent
747          * @returns {Number} Base to the power of exponent
748          */
749         squampow: function (base, exponent) {
750             var result;
751 
752             if (Math.floor(exponent) === exponent) {
753                 // exponent is integer (could be zero)
754                 result = 1;
755 
756                 if (exponent < 0) {
757                     // invert: base
758                     base = 1.0 / base;
759                     exponent *= -1;
760                 }
761 
762                 while (exponent !== 0) {
763                     if (exponent & 1) {
764                         result *= base;
765                     }
766 
767                     exponent >>= 1;
768                     base *= base;
769                 }
770                 return result;
771             }
772 
773             return this.pow(base, exponent);
774         },
775 
776         /**
777          * Greatest common divisor (gcd) of two numbers.
778          * @see <a href="http://rosettacode.org/wiki/Greatest_common_divisor#JavaScript">rosettacode.org</a>
779          *
780          * @param  {Number} a First number
781          * @param  {Number} b Second number
782          * @returns {Number}   gcd(a, b) if a and b are numbers, NaN else.
783          */
784         gcd: function (a, b) {
785             a = Math.abs(a);
786             b = Math.abs(b);
787 
788             if (!(Type.isNumber(a) && Type.isNumber(b))) {
789                 return NaN;
790             }
791             if (b > a) {
792                 var temp = a;
793                 a = b;
794                 b = temp;
795             }
796 
797             while (true) {
798                 a %= b;
799                 if (a === 0) { return b; }
800                 b %= a;
801                 if (b === 0) { return a; }
802             }
803         },
804 
805         /**
806          * Least common multiple (lcm) of two numbers.
807          *
808          * @param  {Number} a First number
809          * @param  {Number} b Second number
810          * @returns {Number}   lcm(a, b) if a and b are numbers, NaN else.
811          */
812         lcm: function (a, b) {
813             var ret;
814 
815             if (!(Type.isNumber(a) && Type.isNumber(b))) {
816                 return NaN;
817             }
818 
819             ret = a * b;
820             if (ret !== 0) {
821                 return ret / this.gcd(a, b);
822             }
823 
824             return 0;
825         },
826 
827         /**
828          *  Error function, see {@link https://en.wikipedia.org/wiki/Error_function}.
829          *
830          * @see JXG.Math.PropFunc.erf
831          * @param  {Number} x
832          * @returns {Number}
833          */
834         erf: function(x) {
835             return this.ProbFuncs.erf(x);
836         },
837 
838         /**
839          * Complementary error function, i.e. 1 - erf(x).
840          *
841          * @see JXG.Math.erf
842          * @see JXG.Math.PropFunc.erfc
843          * @param  {Number} x
844          * @returns {Number}
845          */
846          erfc: function(x) {
847             return this.ProbFuncs.erfc(x);
848         },
849 
850         /**
851          * Inverse of error function
852          *
853          * @see JXG.Math.erf
854          * @see JXG.Math.PropFunc.erfi
855          * @param  {Number} x
856          * @returns {Number}
857          */
858          erfi: function(x) {
859             return this.ProbFuncs.erfi(x);
860         },
861 
862         /**
863          * Normal distribution function
864          *
865          * @see JXG.Math.PropFunc.ndtr
866          * @param  {Number} x
867          * @returns {Number}
868          */
869          ndtr: function(x) {
870             return this.ProbFuncs.ndtr(x);
871         },
872 
873         /**
874          * Inverse of normal distribution function
875          *
876          * @see JXG.Math.ndtr
877          * @see JXG.Math.PropFunc.ndtri
878          * @param  {Number} x
879          * @returns {Number}
880          */
881          ndtri: function(x) {
882             return this.ProbFuncs.ndtri(x);
883         },
884 
885         /* ********************  Comparisons and logical operators ************** */
886 
887         /**
888          * Logical test: a < b?
889          *
890          * @param {Number} a
891          * @param {Number} b
892          * @returns {Boolean}
893          */
894         lt: function(a, b) {
895             return a < b;
896         },
897 
898         /**
899          * Logical test: a <= b?
900          *
901          * @param {Number} a
902          * @param {Number} b
903          * @returns {Boolean}
904          */
905         leq: function(a, b) {
906             return a <= b;
907         },
908 
909         /**
910          * Logical test: a > b?
911          *
912          * @param {Number} a
913          * @param {Number} b
914          * @returns {Boolean}
915          */
916         gt: function(a, b) {
917             return a > b;
918         },
919 
920         /**
921          * Logical test: a >= b?
922          *
923          * @param {Number} a
924          * @param {Number} b
925          * @returns {Boolean}
926          */
927         geq: function(a, b) {
928             return a >= b;
929         },
930 
931         /**
932          * Logical test: a === b?
933          *
934          * @param {Number} a
935          * @param {Number} b
936          * @returns {Boolean}
937          */
938         eq: function(a, b) {
939             return a === b;
940         },
941 
942         /**
943          * Logical test: a !== b?
944          *
945          * @param {Number} a
946          * @param {Number} b
947          * @returns {Boolean}
948          */
949         neq: function(a, b) {
950             return a !== b;
951         },
952 
953         /**
954          * Logical operator: a && b?
955          *
956          * @param {Boolean} a
957          * @param {Boolean} b
958          * @returns {Boolean}
959          */
960         and: function(a, b) {
961             return a && b;
962         },
963 
964         /**
965          * Logical operator: !a?
966          *
967          * @param {Boolean} a
968          * @returns {Boolean}
969          */
970         not: function(a) {
971             return !a;
972         },
973 
974         /**
975          * Logical operator: a || b?
976          *
977          * @param {Boolean} a
978          * @param {Boolean} b
979          * @returns {Boolean}
980          */
981         or: function(a, b) {
982             return a || b;
983         },
984 
985         /**
986          * Logical operator: either a or b?
987          *
988          * @param {Boolean} a
989          * @param {Boolean} b
990          * @returns {Boolean}
991          */
992         xor: function(a, b) {
993             return (a || b) && !(a && b);
994         },
995 
996         /* *************************** Normalize *************************** */
997 
998         /**
999          * Normalize the standard form [c, b0, b1, a, k, r, q0, q1].
1000          * @private
1001          * @param {Array} stdform The standard form to be normalized.
1002          * @returns {Array} The normalized standard form.
1003          */
1004         normalize: function (stdform) {
1005             var n, signr,
1006                 a2 = 2 * stdform[3],
1007                 r = stdform[4] / a2;
1008 
1009             stdform[5] = r;
1010             stdform[6] = -stdform[1] / a2;
1011             stdform[7] = -stdform[2] / a2;
1012 
1013             if (!isFinite(r)) {
1014                 n = Math.sqrt(stdform[1] * stdform[1] + stdform[2] * stdform[2]);
1015 
1016                 stdform[0] /= n;
1017                 stdform[1] /= n;
1018                 stdform[2] /= n;
1019                 stdform[3] = 0;
1020                 stdform[4] = 1;
1021             } else if (Math.abs(r) >= 1) {
1022                 stdform[0] = (stdform[6] * stdform[6] + stdform[7] * stdform[7] - r * r) / (2 * r);
1023                 stdform[1] = -stdform[6] / r;
1024                 stdform[2] = -stdform[7] / r;
1025                 stdform[3] = 1 / (2 * r);
1026                 stdform[4] = 1;
1027             } else {
1028                 signr = (r <= 0 ? -1 : 1);
1029                 stdform[0] = signr * (stdform[6] * stdform[6] + stdform[7] * stdform[7] - r * r) * 0.5;
1030                 stdform[1] = -signr * stdform[6];
1031                 stdform[2] = -signr * stdform[7];
1032                 stdform[3] = signr / 2;
1033                 stdform[4] = signr * r;
1034             }
1035 
1036             return stdform;
1037         },
1038 
1039         /**
1040          * Converts a two dimensional array to a one dimensional Float32Array that can be processed by WebGL.
1041          * @param {Array} m A matrix in a two dimensional array.
1042          * @returns {Float32Array} A one dimensional array containing the matrix in column wise notation. Provides a fall
1043          * back to the default JavaScript Array if Float32Array is not available.
1044          */
1045         toGL: function (m) {
1046             var v, i, j;
1047 
1048             if (typeof Float32Array === 'function') {
1049                 v = new Float32Array(16);
1050             } else {
1051                 v = new Array(16);
1052             }
1053 
1054             if (m.length !== 4 && m[0].length !== 4) {
1055                 return v;
1056             }
1057 
1058             for (i = 0; i < 4; i++) {
1059                 for (j = 0; j < 4; j++) {
1060                     v[i + 4 * j] = m[i][j];
1061                 }
1062             }
1063 
1064             return v;
1065         },
1066 
1067         /**
1068          * Theorem of Vieta: Given a set of simple zeroes x_0, ..., x_n
1069          * of a polynomial f, compute the coefficients s_k, (k=0,...,n-1)
1070          * of the polynomial of the form. See {@link https://de.wikipedia.org/wiki/Elementarsymmetrisches_Polynom}.
1071          * <p>
1072          *  f(x) = (x-x_0)*...*(x-x_n) =
1073          *  x^n + sum_{k=1}^{n} (-1)^(k) s_{k-1} x^(n-k)
1074          * </p>
1075          * @param {Array} x Simple zeroes of the polynomial.
1076          * @returns {Array} Coefficients of the polynomial.
1077          *
1078          */
1079         Vieta: function(x) {
1080             var n = x.length,
1081                 s = [],
1082                 m, k, y;
1083 
1084             s = x.slice();
1085             for (m = 1; m < n; ++m) {
1086                 y = s[m];
1087                 s[m] *= s[m - 1];
1088                 for (k = m - 1; k >= 1; --k) {
1089                     s[k] += s[k - 1] * y;
1090                 }
1091                 s[0] += y;
1092             }
1093             return s;
1094         }
1095     };
1096 
1097     return JXG.Math;
1098 });
1099