/* FFT form of Taylor and Fourier series and roots of polynomials 12.06.2023 */ /* global complex */ var canvas, centre = 314, colour, dif = 0, num = 32, opt = 0, twice = centre << 1; function get_colour() { // Get colour from cookie // var ca = document.cookie.split(";"), ch, i, name = "bh_style="; // for (i = 0; i < ca.length; i++) { // ch = ca[i]; // while (ch.charAt(0) === " ") { // ch = ch.substring(1); // } // if (ch.indexOf(name) === 0) { // return (ch.substring(name.length, ch.length) === "bh_inblackandwhite") ? "#000000" : "#FFFFFF"; // } // } return "#000000"; // default colour } function form() { // build and write form var form = '
'; form += '
'; form += ''; form += '
 Beispiele   '; if (opt == 1) form += ''; else form += ''; if (opt == 2) form += ''; else form += ''; if (opt == 3) form += ''; else form += ''; if (opt == 4) form += ''; else form += '
'; form += '.Stufe   '; form += '  -lb(Epsilon)   '; form += '. Ableitung'; form += '. Integral'; form += ' Exponent'; form += ' Zählergrad'; form += ' Nennergrad
'; form += ''; form += '  '; form += '
'; document.writeln(form); canvas = new Raphael("canvas", twice, twice + 1); colour = get_colour(); } function solve_ls(mat) { // solve linear equation of rank d with coefficients in m using Gauss Jordan algorithm // m: array[d][d+1] // returns solution in m[i][d+1] // returns false if no solution found // // usage: // // EQ 1: a * x + b * y = c // EQ 2: e * x + f * y = g // // var m = [ [ a, b, c ], [ e, f, g ] ]; // if (solve_ls(m)) { // x = m[0][2]; // y = m[1][2]; // } else { // no solution // } function find_max(rv) { var ma = d, mi = Decimal(0); for (var c = rv + 1; c < d; c++) { if (mat[c][rv].cabs().re.gt(mi)) { mi = mat[c][rv].cabs().re; ma = c; } } return ma; } function swap_rows(r1, r2) { for (var c = 0; c <= d; c++) { [mat[r1][c], mat[r2][c]] = [mat[r2][c], mat[r1][c]]; } } function norm_row(rp) { // require m[r][r] != 0 mat[r][r] = new Complex(Decimal(1), Decimal(0)); for (var c = r + 1; c <= d; c++) { mat[r][c] = mat[r][c].cmul(rp); } } function pivo_cell(za) { mat[zr][r] = new Complex(Decimal(0), Decimal(0)); for (var c = r + 1; c <= d; c++) { mat[zr][c] = mat[zr][c].cadd(za.cmul(mat[r][c])); } } var d = mat.length, one = new Complex(Decimal(1), Decimal(0)); for (var r = 0; r < d; r++) { if (mat[r][r].re.eq(Decimal(0)) && mat[r][r].im.eq(Decimal(0))) { var nzr = find_max(r); if (nzr == d) return false; swap_rows(r, nzr); } // assert m[r][r] != 0 if (!(mat[r][r].re.eq(Decimal(0)) && mat[r][r].im.eq(Decimal(0)))) norm_row(one.cdiv(mat[r][r])); for (var zr = 0; zr < d; zr++) { if (zr != r && !(mat[zr][r].re.eq(Decimal(0)) && mat[zr][r].im.eq(Decimal(0)))) { pivo_cell(mat[zr][r].cneg()); } } } return true; } function initialise_tft(signal, pbsize, realft, xvalue, method, epsilo) { var s = new Complex(Decimal(1), Decimal(0)), t = new Complex((method == 1) ? Decimal(epsilo) : Decimal(1/16384), Decimal(0)); var u = new Complex(Decimal(0), Decimal.acos(-1).mul(Decimal(2).div(Decimal(pbsize)))).cexp(), x = xvalue.cadd(t); // check input and compute coefficients if (realft.search(/[^\.\(\)\w\-\[\]]/g) == -1) { /* check real function */ realft = realft.replace(/\./g, ".c").replace(/\[E\]/g, "Complex(Decimal(1).exp(),Decimal(0))"); realft = realft.replace(/\[I\]/g, "Complex(Decimal(0),Decimal(1))"); realft = realft.replace(/\[PI\]/g, "Complex(Decimal.acos(-1),Decimal(0))") + ".cadd([0])"; realft = realft.replace(/\[/g, "Complex(Decimal(").replace(/\]/g, "),Decimal(0))"); try { signal[0] = eval(realft); } catch (exception) { alert("Ausdruck ist nicht auswertbar!"); } if (signal[0] !== null) { for (var k = 1; k < pbsize; k++) { s = s.cmul(u); x = xvalue.cadd(t.cmul(s)); signal[k] = eval(realft); } } } else alert("Ausdruck enthält ungültige(s) Zeichen!"); return realft; } function initialise_fft(signal, pbsize, realft) { var z = new Complex(Decimal.acos(-1).neg(), Decimal(0)), j, k, x, y; var u = Decimal.acos(-1).div(Decimal(pbsize)), e = Decimal(1e-17), f = 0; // check input and compute coefficients if (realft.search(/[^\.\(\)\w\-\[\]]/g) == -1) { /* check real function */ realft = realft.replace(/\./g, ".c").replace(/\[E\]/g, "Complex(Decimal(1).exp(),Decimal(0))"); realft = realft.replace(/\[I\]/g, "Complex(Decimal(0),Decimal(1))"); realft = realft.replace(/\[PI\]/g, "Complex(Decimal.acos(-1),Decimal(0))") + ".cadd([0])"; realft = realft.replace(/\[/g, "Complex(Decimal(").replace(/\]/g, "),Decimal(0))"); try { x = z; signal[0] = eval(realft); if (signal[0].re.abs().lt(e) || signal[0].re.isNaN()) signal[0].re = Decimal(0); if (signal[0].im.abs().lt(e) || signal[0].im.isNaN()) signal[0].im = Decimal(0); } catch (exception) { alert("Ausdruck ist nicht auswertbar!"); } if (signal[0] !== null) { for (k = 1; k < 2 * pbsize; k++) { x = z.cadd(Complex(u.mul(Decimal(k)), Decimal(0))); signal[k] = eval(realft); if (signal[k].re.abs().lt(e) || signal[k].re.isNaN()) signal[k].re = Decimal(0); if (signal[k].im.abs().lt(e) || signal[k].im.isNaN()) signal[k].im = Decimal(0); } } } else alert("Ausdruck enthält ungültige(s) Zeichen!"); return f; } function cfft(ins) { var max = ins.length, i, j = 0, k, l = 1, m = max >> 1, n; var one = Decimal(1), two = Decimal(2), c1 = new Complex(one, Decimal(0)), cn = c1.cneg(), t, u; // reverse bits for (i = 0; i < max - 1; i++) { if (i < j) [ins[i], ins[j]] = [ins[j], ins[i]]; k = m; while (k <= j) { j -= k; k >>= 1; } j += k; } // compute FFT for (k = 0; k < Math.log2(max); k++) { u = c1; m = l; l <<= 1; for (j = 0; j < m; j++) { for (i = j; i < max; i += l) { n = i + m; t = u.cmul(ins[n]); ins[n] = ins[i].csub(t); ins[i] = ins[i].cadd(t); } u = u.cmul(cn); } cn.im = one.sub(cn.re).div(two).sqrt().neg(); // do not negate for ifft, but normalise cn.re = one.add(cn.re).div(two).sqrt(); } } function output_pade(result, factor, elldeg, emmdeg, numera, denomi) { var d, s, str = "Auf sechzehn Dezimalstellen gerundete Koeffizienten der Taylorpolynome von Zähler p und Nenner q:\n"; var z = Decimal(0), matrix = [], zer = new Complex(z, z), l = elldeg, m = emmdeg, n = l - m; if (factor > 0) for (var k = 0; k < 32; k++) result[k] = result[k + factor]; // build matrix for (var i = 0; i < m; i++) { matrix[i] = []; matrix[i][m] = result[++n + m].cneg(); for (var j = 0; j < m; j++) matrix[i][j] = (n + j < 0) ? zer : result[n + j]; } // solve linear system and determine coefficients of quotient if (solve_ls(matrix)) { denomi[0] = new Complex(Decimal(1), Decimal(0)); for (var j = 1; j <= m; j++) denomi[j] = matrix[m - j][m]; for (var i = 0; i <= l; i++) { d = result[i]; for (var j = 1; j <= Math.min(i, m); j++) d = d.cadd(denomi[j].cmul(result[i - j])); numera[i] = d; } // output quotient for (var k = 0; k <= l; k++) { s = (k < 10) ? "p[0" : "p["; str = str + s + k + "] = "; s = ((numera[k].re.gte(Decimal(0))) ? "+" : "") + numera[k].re.toExponential(50, 4).replace("e", ")e"); s = s.padEnd(59); str = str + s.substring(0, 17) + "(" + s.substring(17); /* real coefficient */ s = ((numera[k].im.gte(Decimal(0))) ? " +" : " ") + numera[k].im.toExponential(50, 4).replace("e", ")e"); str = str + s.substring(0, 17) + "(" + s.substring(17) + "im\n"; /* complex coefficient */ } for (var k = 0; k <= m; k++) { s = (k < 10) ? "q[0" : "q["; str = str + s + k + "] = "; s = ((denomi[k].re.gte(Decimal(0))) ? "+" : "") + denomi[k].re.toExponential(50, 4).replace("e", ")e"); s = s.padEnd(59); str = str + s.substring(0, 17) + "(" + s.substring(17); /* real coefficient */ s = ((denomi[k].im.gte(Decimal(0))) ? " +" : " ") + denomi[k].im.toExponential(50, 4).replace("e", ")e"); str = str + s.substring(0, 17) + "(" + s.substring(17) + "im\n"; /* complex coefficient */ } } else { str = str + "Das lineare Gleichungssystem ist nicht lösbar: Bitte eventuell andere Vorgabe wählen."; } return str; } function output_taylor(result, factor) { var p = 32, s, str = "Auf sechzehn Dezimalstellen gerundete Koeffizienten der Taylorreihe:\n"; if (factor > 0) p += factor; for (var k = Math.max(0, factor); k < p; k++) { s = (k < factor + 10) ? "a[0" : "a["; str = str + s + (k - factor) + "] = "; s = ((result[k].re.gte(Decimal(0))) ? "+" : "") + result[k].re.toExponential(50, 4).replace("e", ")e"); s = s.padEnd(59); str = str + s.substring(0, 17) + "(" + s.substring(17); /* real coefficient */ s = ((result[k].im.gte(Decimal(0))) ? " +" : " ") + result[k].im.toExponential(50, 4).replace("e", ")e"); str = str + s.substring(0, 17) + "(" + s.substring(17) + "im\n"; /* complex coefficient */ } return str; } function compute_taylor(result, pbsize, factor, epsilo) { var z = Decimal(0), p = 32, c = new Complex((pbsize >= p) ? Decimal(epsilo) : Decimal(1/16384), Decimal(0)); var f = Decimal(1), h = new Complex(Decimal(pbsize), Decimal(0)), one = new Complex(f, z), zer = new Complex(z, z); if (factor < 0) for (var k = 1; k <= -factor; k++) f = f.div(Decimal(k)); else p += factor; result[0] = result[0].cdiv(h); h = h.cmul(c); result[0] = result[0].cmul(Complex(f, z).cmul((factor > 0) ? zer : one)); for (var k = 1; k < p; k++) { result[k] = result[k].cdiv(h); h = h.cmul(c); // differentiate or integrate if (factor < 0) { f = f.mul(Decimal(k)).div(Decimal(k - factor)); } else if (factor > 0) { f = f.mul(Decimal(k)); if (k > factor) f = f.div(Decimal(k - factor)); } result[k] = result[k].cmul(Complex(f, z).cmul((k < factor) ? zer : one)); } } function compute_fourier(result, pbsize, differ, factor) { var f = new Complex(Decimal(differ), Decimal(0)), h = new Complex(Decimal(pbsize), Decimal(0)), n = 16, s; var str = "Auf sechzehn Dezimalstellen gerundete Koeffizienten der Fourierreihe:\n"; // differentiate if necessary if (differ > 0) result[0] = new Complex(Decimal(0), Decimal(0)); for (var j = -n; j < n; j++) { k = (j < 0) ? j + pbsize : j; result[k] = result[k].cdiv(h); if (differ > 0 && k > 0) result[k] = result[k].cmul(Complex(Decimal(0), Decimal(k)).cpow(f)); h = h.cneg(); s = (j < 0) ? "c[" : "c[ "; if (Math.abs(j) < 10) s = s + " "; str = str + s + j + "] = "; s = ((result[k].re.gte(Decimal(0))) ? "+" : "") + result[k].re.toExponential(50, 4).replace("e", ")e"); s = s.padEnd(59); str = str + s.substring(0, 17) + "(" + s.substring(17); /* real coefficient */ s = ((result[k].im.gte(Decimal(0))) ? " +" : " ") + result[k].im.toExponential(50, 4).replace("e", ")e"); str = str + s.substring(0, 17) + "(" + s.substring(17) + "im\n"; /* complex coefficient */ } return str; } function compute_simpson(result, pbsize, xvalue, conver, realft) { var c0 = new Complex(Decimal( 0), Decimal(0)), c1 = new Complex(Decimal(1), Decimal(0 )); var c2 = new Complex(Decimal( 2), Decimal(0)), c3 = new Complex(Decimal(3), Decimal(0 )); var c4 = new Complex(Decimal( 4), Decimal(0)), c5 = new Complex(Decimal(5), Decimal(0 )); var c6 = new Complex(Decimal( 6), Decimal(0)), c7 = new Complex(Decimal(7), Decimal(0 )); var c8 = new Complex(Decimal(16384), Decimal(0)), c9 = new Complex(Decimal(0), Decimal(1e-40)); var fa = [], ga = [], ha = [], height = [], f, g, h, p, v = c0, w, y, z, r = Decimal(1e16 ); var str = "Auf sechzehn Dezimalstellen gerundete Iterationen:\n", e = xvalue, x = xvalue; // determine coefficients by differentiating Taylor series if (conver > 1) { height[0] = new Complex(Decimal(1 / pbsize), Decimal(0)); result[0] = result[0].cmul(height[0]); for (var k = 1; k < pbsize; k++) { height[k] = height[k - 1].cmul(c8); result[k] = result[k].cmul(height[k]); fa[k] = result[k].cmul(Complex(Decimal(k), Decimal(0))); ga[k] = fa[k].cmul(Complex(Decimal(k - 1), Decimal(0))); ha[k] = ga[k].cmul(Complex(Decimal(k - 2), Decimal(0))); } pbsize--; } // determine derivatives by using Horner's scheme for (var m = 1; m < 17; m++) { if (conver > 1) { f = g = h = z = c0; var k = pbsize; do { f = f.cmul(v).cadd( fa[k]); z = z.cmul(v).cadd(result[k]); } while (--k > 0); z = z.cmul(v).cadd(result[0]); } // precise and fast, quadratic, cubic, quartic, quintic, sextic, septic, and octic convergence switch(conver) { case 0: y = x; x = y.cadd(c9); z = eval(realft); x = y.csub(c9); f = eval(realft); x = c1.csub( z.cdiv(f)); x = c2.cdiv(x).csub(c1); v = v.cadd( x.cmul(c9)); break; case 1: y = x; x = y.cadd(c9); z = eval(realft); x = y.csub(c9); f = eval(realft); x = c1.csub( z.cdiv(f)); x = c2.cdiv(x).csub(c1); w = x.cmul(c9); z = z.cadd( f).cdiv(c2); f = z.csub( f).cdiv(c9); // see case 8 x = y.cadd(w); g = eval(realft); y = w.cmul(g); w = z.csub(g.cmul(c2)); x = x.cadd(y.cdiv(w )); h = eval(realft); w = z.csub(g).cdiv( w); y = h.cdiv( g.csub(h)); w = w.cmul(w).cadd( y); y = h.cmul(c4); y = y.cdiv( z.cadd(h)); y = y.cadd( w); y = y.cmul( h.cdiv(f)); y = y.cadd(xvalue); v = x.csub( y); break; case 2: v = v.csub( z.cdiv(f)); break; case 3: k = pbsize; do { g = g.cmul(v).cadd( ga[k]); } while (--k > 1); g = g.cdiv(c2.cmul(f)); g = g.csub( f.cdiv(z)); v = v.cadd(c1.cdiv(g)); break; case 4: k = pbsize; do { g = g.cmul(v).cadd( ga[k]); h = h.cmul(v).cadd( ha[k]); } while (--k > 2); g = g.cmul(v).cadd( ga[2]); g = g.cmul(z); x = f.cmul(f); y = x.csub(g).cmul(c2); g = g.cadd(y); f = f.cmul( y.cdiv(g)); y = z.cdiv(x).cdiv(c6); y = y.cmul(h); y = f.cdiv(z).cadd(y ); v = v.csub(c1.cdiv(y)); break; case 5: x = v.csub( z.cdiv(f)); k = pbsize; do { g = g.cmul(x).cadd(result[k]); h = h.cmul(x).cadd( fa[k]); } while (--k > 0); g = g.cmul(x).cadd(result[0]); h = h.cmul(h ); g = g.cdiv(f ); f = f.cmul(f ); y = f.cmul(c5); y = y.cadd(c3.cmul(h)); z = f.cadd(c7.cmul(h)); y = y.cdiv(z).cmul(g ); v = x.csub(y ); break; case 6: x = v.csub( z.cdiv(f)); k = pbsize; do { g = g.cmul(x).cadd( fa[k]); } while (--k > 0); x = z.cdiv( f.cadd(g)); x = v.csub(c2.cmul(x)); k = pbsize; do { h = h.cmul(x).cadd(result[k]); } while (k-- > 0); y = c3.cmul(g).csub(f); y = f.cadd(g).cdiv(y); y = h.cdiv(f).cmul(y); v = x.csub(y); break; case 7: y = z.cdiv(f); x = v.csub(y); k = pbsize; do { g = g.cmul(x).cadd(result[k]); } while (k-- > 0); y = y.cmul(g); w = z.csub(g.cmul(c2)); x = x.csub(y.cdiv( w)); k = pbsize; do { h = h.cmul(x).cadd(result[k]); } while (k-- > 0); z = z.csub(g).cdiv( w); y = h.cdiv( g.csub(h)); z = z.cmul(z).cadd( y); z = z.cdiv(f).cmul( h); v = x.csub(z); break; case 8: y = z.cdiv(f); x = v.csub(y); k = pbsize; do { g = g.cmul(x).cadd(result[k]); } while (k-- > 0); y = y.cmul(g); w = z.csub(g.cmul(c2)); x = x.csub(y.cdiv(w )); k = pbsize; do { h = h.cmul(x).cadd(result[k]); } while (k-- > 0); w = z.csub(g).cdiv( w); y = h.cdiv( g.csub(h)); w = w.cmul(w).cadd( y); y = h.cmul(c4); y = y.cdiv( z.cadd(h)); y = y.cadd( w); y = y.cmul( h.cdiv(f)); v = x.csub( y); break; default : } // output if interesting p = (m < 10) ? " " + m : m; x = v.cadd(xvalue); if (x.re.isNaN() || x.im.isNaN() || e.csub(x).cabs().re.lt(Decimal(2e-80))) { m = 17; str = str + "Berechnung vorzeitig beendet: Bitte eventuell andere Vorgabe wählen."; } else { s = ((x.re.gte(Decimal(0))) ? "+" : "") + x.re.toExponential(16, 4); str = str + p + ": Re(x) = " + s.padEnd(24) + " (" + ((x.re.gte(Decimal(0))) ? "+" : "") + x.re.toExponential(80, 4) + ")\n"; s = ((x.im.gte(Decimal(0))) ? "+" : "") + x.im.toExponential(16, 4); str = str + "und Im(x) = " + s.padEnd(24) + " (" + ((x.im.gte(Decimal(0))) ? "+" : "") + x.im.toExponential(80, 4) + ")\n"; } e = x; } return str; } function compute_coeffs() { var aft, eps, fac, fct, img, inp = [], inq = [], inr = [], pee = [], quu = [], lev, n = Decimal(0), z = n, index = document.fft.b.selectedIndex, rea, str = "", val, y = Decimal(1); // insert examples if (index > 0) { switch (index) { case 1 : document.fft.pbsize.value = "x.add([1]).log()"; break; case 2 : document.fft.pbsize.value = "x.atan()"; break; case 3 : document.fft.pbsize.value = "[1].div([1].sub(x))"; break; case 4 : document.fft.pbsize.value = "[200e-2].mul([I]).mul(x.exp())"; break; case 5 : document.fft.pbsize.value = "[PI].add([E].mul(x.mul(x).mul(x)))"; break; case 6 : document.fft.pbsize.value = "x.mul([2]).cos()"; break; case 7 : document.fft.pbsize.value = "x.abs()"; break; case 8 : document.fft.pbsize.value = "x.div(x.abs())"; break; case 9 : document.fft.pbsize.value = "x.sin().abs()"; break; case 10 : document.fft.pbsize.value = "[1].div(x).sin()"; break; } } // determine Taylor or Fourier series, or compute Padé approximant and zeros resp. fct = document.fft.pbsize.value.toString(); eps = 1 / Math.pow(2, Number(document.fft.exp.value)); rea = (isNaN(document.fft.real.value)) ? 0 : Number(document.fft.real.value); img = (isNaN(document.fft.imag.value)) ? 0 : Number(document.fft.imag.value); if (Number(document.fft.opt.value) > 0) opt = Number(document.fft.opt.value); if (Number(document.fft.dif.value) >= 0) dif = Number(document.fft.dif.value); if (Number(document.fft.ite.value) >= 0 && dif == 0 && opt != 2) { dif = -Number(document.fft.ite.value); document.fft.dif.value = 0; } else { document.fft.ite.value = 0; } if (Number(document.fft.num.value) > 0) num = Math.pow(2, Number(document.fft.num.value)); // process options switch (opt) { case 1 : val = new Complex(Decimal(rea), Decimal(img)); initialise_tft(inp, num * 2, fct, val, opt, eps); if (inp[0] !== null) { cfft(inp); compute_taylor(inp, num * 2, dif, eps); document.fft.result.value = output_taylor(inp, dif); pee = inp; ell = num; quu[0] = new Complex(Decimal(1), Decimal(0)); emm = 0; } break; case 2 : num /= 2; fac = initialise_fft(inp, num, fct); if (inp[0] !== null) { cfft(inp); document.fft.result.value = compute_fourier(inp, num * 2, dif, fac); } num *= 2; break; case 3 : num /= 2; val = new Complex(Decimal(rea), Decimal(img)); lev = Number(document.fft.lev.value); fct = (lev > 1) ? initialise_tft(inp, num, fct, val, opt, eps) : initialise_tft(inp, 1, fct, val, opt, eps); if (inp[0] !== null) { if (lev > 1) cfft(inp); document.fft.result.value = compute_simpson(inp, num, val, lev, fct); } num *= 2; break; case 4 : val = new Complex(Decimal(rea), Decimal(img)); initialise_tft(inp, num * 2, fct, val, 1, eps); if (inp[0] !== null) { cfft(inp); compute_taylor(inp, num * 2, dif, eps); ell = Number(document.fft.ell.value); emm = Number(document.fft.emm.value); document.fft.result.value = output_pade(inp, dif, ell, emm, pee, quu); } break; } if (inp[0] === null) { document.fft.result.value = str + "Auswertung ist nicht möglich."; } // draw graph show_fft(num, fct, inp, opt, ell, emm, pee, quu, val); } function show_fft(asize, realf, input, optio, eldeg, emdeg, numer, denom, value) { var bnd = 1e5, fra = new Complex(Decimal(Math.PI / num), Decimal(0)), graph = [], padeg = [], den, hlp, inc, len, max = -bnd, min = bnd, k = -twice, r = asize - 0.5, quo = 2 * r / twice, tst; var end_x, end_y, horizontal_axis, vertical_axis, start_x, start_y; realf = realf.replace(/\./g, ".c").replace(/\[E\]/g, "Complex(Decimal(1).exp(),Decimal(0))"); realf = realf.replace(/\[I\]/g, "Complex(Decimal(0),Decimal(1))"); realf = realf.replace(/\[PI\]/g, "Complex(Decimal.acos(-1),Decimal(0))") + ".cadd([0])"; realf = realf.replace(/\[/g, "Complex(Decimal(").replace(/\]/g, "),Decimal(0))"); // compute Taylor series or Padé approximant if requested if (optio == 1 || optio == 4) { var x = new Complex(Decimal(-Math.PI), Decimal(0)).csub(value); for (var n = 0; n < 2 * num; n++) { hlp = numer[eldeg]; for (var l = eldeg - 1; l >= 0; l--) hlp = hlp.cmul(x).cadd(numer[l]); den = denom[emdeg]; for (var m = emdeg - 1; m >= 0; m--) den = den.cmul(x).cadd(denom[m]); padeg[n] = hlp.cdiv(den); x = x.cadd(fra); } } // determine minimum and maximum x = new Complex(Decimal(-Math.PI), Decimal(0)); for (var n = 0; n < 2 * num; n++) { graph[n] = eval(realf); tst = graph[n].re.toNumber(); if (tst > max) max = tst; if (tst < min) min = tst; x = x.cadd(fra); } if (max > bnd) max = bnd; if (min < -bnd) min = -bnd; bnd = Math.round(Math.max(Math.abs(max), Math.abs(min)) + 0.499); len = bnd.toString().length; // draw axes canvas.clear(); start_x = 0; start_y = 0; end_x = twice; end_y = twice; horizontal_axis = canvas.path("M" + start_x + " " + centre + "L" + end_x + " " + centre); horizontal_axis.attr({"stroke": colour, "stroke-width": 1 }); vertical_axis = canvas.path("M" + centre + " " + start_y + "L" + centre + " " + end_y); vertical_axis.attr({ "stroke": colour, "stroke-width": 1 }); // add texts canvas.text(20, 6, "Re(f(x))").attr({fill: colour}); canvas.text(6, centre + 6, "-π").attr({fill: colour}); canvas.text(twice - 6, centre + 6, "π").attr({fill: colour}); canvas.text(centre - 4 * len++, 6, bnd.toString()).attr({fill: colour}); canvas.text(centre - 4 * len, twice - 6, "-" + bnd.toString()).attr({fill: colour}); // draw function inc = quo * k / 2 + r; bnd = centre / bnd; while (++k < twice) { if (k % 2 == 0) { start_y = centre - Math.round(bnd * graph[Math.round(inc)].re.toNumber()); inc += quo; end_y = centre - Math.round(bnd * graph[Math.round(inc)].re.toNumber()); horizontal_axis = canvas.path("M" + (start_x - 1) + " " + start_y + "L" + ++start_x + " " + end_y); horizontal_axis.attr({"stroke": colour, "stroke-width": 1 }); } } // draw Taylor series or Padé approximant if requested if (optio == 1 || optio == 4) { if (optio == 1) canvas.text(20, 18, "--- Taylor").attr({fill: "#FF0000"}); else canvas.text(20, 18, "--- Padé ").attr({fill: "#FF0000"}); start_x = 0; k = -twice; inc = quo * k / 2 + r; while (++k < twice) { if (k % 2 == 0) { start_y = centre - Math.round(bnd * padeg[Math.round(inc)].re.toNumber()); inc += quo; end_y = centre - Math.round(bnd * padeg[Math.round(inc)].re.toNumber()); horizontal_axis = canvas.path("M" + (start_x - 1) + " " + start_y + "L" + ++start_x + " " + end_y); horizontal_axis.attr({"stroke": "#FF0000", "stroke-width": 1 }); } } } } // main programme form(); document.fft.result.value = "Beispiele:\n1) x.add([1]).log() für ln(x+1)\n2) x.atan() für arctan(x)\n3) [1].div([1].sub(x)) für 1/(1-x)\n4) [200e-2].mul([I]).mul(x.exp()) für 2ieˣ \n5) [PI].add([E].mul(x.mul(x).mul(x))) für π+ex³\n6) x.mul([2]).cos() für cos(2x)\n7) x.abs() für |x|\n8) x.div(x.abs()) für x/|x|\n9) x.sin().abs() für |sin(x)|\n10) [1].div(x).sin() für sin(1/x)"; compute_coeffs();