1 /* 2 Copyright 2008-2024 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 <https://www.gnu.org/licenses/> 29 and <https://opensource.org/licenses/MIT/>. 30 */ 31 32 /*global JXG: true, define: true*/ 33 /*jslint nomen: true, plusplus: true*/ 34 35 /** 36 * @fileoverview In this file the namespace Math.Poly is defined, which holds algorithms to create and 37 * manipulate polynomials. 38 */ 39 40 import JXG from "../jxg.js"; 41 import Mat from "./math.js"; 42 import Type from "../utils/type.js"; 43 44 /** 45 * The JXG.Math.Poly namespace holds algorithms to create and manipulate polynomials. 46 * @name JXG.Math.Poly 47 * @exports Mat.Poly as JXG.Math.Poly 48 * @namespace 49 */ 50 Mat.Poly = {}; 51 52 /** 53 * Define a polynomial ring over R. 54 * @class 55 * @name JXG.Math.Poly.Ring 56 * @param {Array} variables List of indeterminates. 57 */ 58 Mat.Poly.Ring = function (variables) { 59 /** 60 * A list of variables in this polynomial ring. 61 * @type Array 62 */ 63 this.vars = variables; 64 }; 65 66 JXG.extend( 67 Mat.Poly.Ring.prototype, 68 /** @lends JXG.Math.Poly.Ring.prototype */ { 69 // nothing yet. 70 } 71 ); 72 73 /** 74 * Define a monomial over the polynomial ring <tt>ring</tt>. 75 * @class 76 * @name JXG.Math.Poly.Monomial 77 * @param {JXG.Math.Poly.Ring} ring 78 * @param {Number} coefficient 79 * @param {Array} exponents An array of exponents, corresponding to ring 80 */ 81 Mat.Poly.Monomial = function (ring, coefficient, exponents) { 82 var i; 83 84 if (!Type.exists(ring)) { 85 throw new Error("JSXGraph error: In JXG.Math.Poly.monomial missing parameter 'ring'."); 86 } 87 88 if (!Type.isArray(exponents)) { 89 exponents = []; 90 } 91 92 exponents = exponents.slice(0, ring.vars.length); 93 94 for (i = exponents.length; i < ring.vars.length; i++) { 95 exponents.push(0); 96 } 97 98 /** 99 * A polynomial ring. 100 * @type JXG.Math.Poly.Ring 101 */ 102 this.ring = ring; 103 104 /** 105 * The monomial's coefficient 106 * @type Number 107 */ 108 this.coefficient = coefficient || 0; 109 110 /** 111 * Exponent vector, the order depends on the order of the variables 112 * in the ring definition. 113 * @type Array 114 */ 115 this.exponents = Type.deepCopy(exponents); 116 }; 117 118 JXG.extend( 119 Mat.Poly.Monomial.prototype, 120 /** @lends JXG.Math.Poly.Monomial.prototype */ { 121 /** 122 * Creates a deep copy of the monomial. 123 * 124 * @returns {JXG.Math.Poly.Monomial} 125 * 126 * @memberof JXG.Math.Poly.Monomial 127 */ 128 copy: function () { 129 return new Mat.Poly.Monomial(this.ring, this.coefficient, this.exponents); 130 }, 131 132 /** 133 * Print the monomial. 134 * @returns {String} String representation of the monomial 135 136 * @memberof JXG.Math.Poly.Monomial 137 */ 138 print: function () { 139 var s = [], 140 i; 141 142 for (i = 0; i < this.ring.vars.length; i++) { 143 s.push(this.ring.vars[i] + "^" + this.exponents[i]); 144 } 145 146 return this.coefficient + "*" + s.join("*"); 147 } 148 } 149 ); 150 151 /** 152 * A polynomial is a sum of monomials. 153 * @class 154 * @name JXG.Math.Poly.Polynomial 155 * @param {JXG.Math.Poly.Ring} ring A polynomial ring. 156 * @param {String} str TODO String representation of the polynomial, will be parsed. 157 */ 158 Mat.Poly.Polynomial = function (ring, str) { 159 var parse = function () {}, 160 mons; 161 162 if (!Type.exists(ring)) { 163 throw new Error( 164 "JSXGraph error: In JXG.Math.Poly.polynomial missing parameter 'ring'." 165 ); 166 } 167 168 if (Type.exists(str) && Type.isString(str)) { 169 mons = parse(str); 170 } else { 171 mons = []; 172 } 173 174 /** 175 * A polynomial ring. 176 * @type JXG.Math.Poly.Ring 177 */ 178 this.ring = ring; 179 180 /** 181 * List of monomials. 182 * @type Array 183 */ 184 this.monomials = mons; 185 }; 186 187 JXG.extend( 188 Mat.Poly.Polynomial.prototype, 189 /** @lends JXG.Math.Poly.Polynomial.prototype */ { 190 /** 191 * Find a monomial with the given signature, i.e. exponent vector. 192 * @param {Array} sig An array of numbers 193 * @returns {Number} The index of the first monomial with the given signature, or -1 194 * if no monomial could be found. 195 * @memberof JXG.Math.Poly.Polynomial 196 */ 197 findSignature: function (sig) { 198 var i; 199 200 for (i = 0; i < this.monomials.length; i++) { 201 if (Type.cmpArrays(this.monomials[i].exponents, sig)) { 202 return i; 203 } 204 } 205 206 return -1; 207 }, 208 209 /** 210 * Adds a monomial to the polynomial. Checks the existing monomials for the added 211 * monomial's signature and just adds the coefficient if one is found. 212 * @param {JXG.Math.Poly.Monomial} m 213 * @param {Number} factor Either <tt>1</tt> or <tt>-1</tt>. 214 * @memberof JXG.Math.Poly.Polynomial 215 */ 216 addSubMonomial: function (m, factor) { 217 var i; 218 219 i = this.findSignature(m.exponents); 220 if (i > -1) { 221 this.monomials[i].coefficient += factor * m.coefficient; 222 } else { 223 m.coefficient *= factor; 224 this.monomials.push(m); 225 } 226 }, 227 228 /** 229 * Adds another polynomial or monomial to this one and merges them by checking for the 230 * signature of each new monomial in the existing monomials. 231 * @param {JXG.Math.Poly.Polynomial|JXG.Math.Poly.Monomial} mp 232 * @memberof JXG.Math.Poly.Polynomial 233 */ 234 add: function (mp) { 235 var i; 236 237 if (Type.exists(mp) && mp.ring === this.ring) { 238 if (Type.isArray(mp.exponents)) { 239 // mp is a monomial 240 this.addSubMonomial(mp, 1); 241 } else { 242 // mp is a polynomial 243 for (i = 0; i < mp.monomials.length; i++) { 244 this.addSubMonomial(mp.monomials[i], 1); 245 } 246 } 247 } else { 248 throw new Error( 249 "JSXGraph error: In JXG.Math.Poly.polynomial.add either summand is undefined or rings don't match." 250 ); 251 } 252 }, 253 254 /** 255 * Subtracts another polynomial or monomial from this one and merges them by checking for the 256 * signature of each new monomial in the existing monomials. 257 * @param {JXG.Math.Poly.Polynomial|JXG.Math.Poly.Monomial} mp 258 * @memberof JXG.Math.Poly.Polynomial 259 */ 260 sub: function (mp) { 261 var i; 262 263 if (Type.exists(mp) && mp.ring === this.ring) { 264 if (Type.isArray(mp.exponents)) { 265 // mp is a monomial 266 this.addSubMonomial(mp, -1); 267 } else { 268 // mp is a polynomial 269 for (i = 0; i < mp.monomials.length; i++) { 270 this.addSubMonomial(mp.monomials[i], -1); 271 } 272 } 273 } else { 274 throw new Error( 275 "JSXGraph error: In JXG.Math.Poly.polynomial.sub either summand is undefined or rings don't match." 276 ); 277 } 278 }, 279 280 /** 281 * Creates a deep copy of the polynomial. 282 * @returns {JXG.Math.Poly.Polynomial} 283 * @memberof JXG.Math.Poly.Polynomial 284 */ 285 copy: function () { 286 var i, p; 287 288 p = new Mat.Poly.Polynomial(this.ring); 289 290 for (i = 0; i < this.monomials.length; i++) { 291 p.monomials.push(this.monomials[i].copy()); 292 } 293 return p; 294 }, 295 296 /** 297 * Prints the polynomial. 298 * @returns {String} A string representation of the polynomial. 299 * @memberof JXG.Math.Poly.Polynomial 300 */ 301 print: function () { 302 var s = [], 303 i; 304 305 for (i = 0; i < this.monomials.length; i++) { 306 s.push("(" + this.monomials[i].print() + ")"); 307 } 308 309 return s.join("+"); 310 } 311 } 312 ); 313 314 export default Mat.Poly; 315