Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Math.cos = function(a)
- {
- // Bring a into the 0 to +pi range without expensive branching.
- // Uses the symmetry that cos is even.
- a = (a + Math.PI) % (2*Math.PI);
- a = Math.abs((2*Math.PI + a) % (2*Math.PI) - Math.PI);
- // make b = 0 if a < pi/2 and b=1 if a > pi/2
- var b = (a-Math.PI/2) + Math.abs(a-Math.PI/2);
- b = b/(b+1e-30); // normalize b to one while avoiding divide by zero errors.
- // if a > pi/2 send a to pi-a, otherwise just send a to -a which has no effect
- // Using the symmetry cos(x) = -cos(pi-x) to bring a to the 0 to pi/2 range.
- a = b*Math.PI - a;
- var c = 1 - 2*b; // sign of the output
- // Taylor expansion about 0 with a correction term in the quadratic to make cos(pi/2)=0
- return c * (1 - a*a*(0.5000000025619951 - a*a*(1/24 - a*a*(1/720 - a*a*(1/40320 - a*a*(1/3628800 - a*a/479001600))))));
- };
- Math.sin = function(a)
- {
- return Math.cos(a - Math.PI/2);
- };
- // Returns angle from -pi/2 to pi/2
- Math.atan = function(a)
- {
- var tanPiBy6 = 0.5773502691896257;
- var tanPiBy12 = 0.2679491924311227;
- var sign = 1;
- var inverted = false;
- var tanPiBy6Shift = 0;
- if (a < 0){
- // tan(x) = -tan(-x) so remove sign now and put it back at the end
- sign = -1;
- a *= -1;
- }
- if (a > 1)
- {
- // tan(pi/2 - x) = 1/tan(x)
- inverted = true;
- a = 1/a;
- }
- if (a > tanPiBy12)
- {
- // tan(x-pi/6) = (tan(x) - tan(pi/6)) / (1 + tan(pi/6)tan(x))
- tanPiBy6Shift = Math.PI/6;
- a = (a - tanPiBy6) / (1 + tanPiBy6*a);
- }
- // Now a will be in the range [-tan(pi/12), tan(pi/12)]
- // Use the taylor expansion around 0 with a correction to the linear term to match the pi/12 boundary
- // atan(x) = x - x^3/3 + x^5/5 - ...
- var r = a*(1.0000000000390272 - a*a*(1/3 - a*a*(1/5 - a*a*(1/7 - a*a*(1/9 - a*a*(1/11 - a*a*(1/13 - a*a/15)))))));
- // shift the result back where necessary
- r += tanPiBy6Shift;
- if (inverted)
- r = Math.PI/2 - r;
- return sign * r;
- };
- Math.atan2 = function(y,x)
- {
- // get unsigned x,y for ease of calculation, this means all angles are in the range [0, pi/2]
- var ux = Math.abs(x);
- var uy = Math.abs(y);
- // holds the result in the upper right quadrant
- var r;
- // Handle all edges cases to match the spec
- if (uy === 0)
- {
- r = 0;
- }
- else
- {
- if (ux === 0)
- {
- r = Math.PI / 2;
- }
- if (uy === Infinity)
- {
- if (ux === Infinity)
- r = Math.PI / 4;
- else
- r = Math.PI / 2;
- }
- else
- {
- if (ux === Infinity)
- r = 0;
- else
- r = Math.atan(uy/ux);
- }
- }
- // puts the result into the correct quadrant
- // 1/(-0) is the only way to determine the sign for a 0 value
- if (x < 0 || 1/x === -Infinity)
- {
- if (y < 0 || 1/y === -Infinity)
- return -Math.PI + r;
- else
- return Math.PI - r;
- }
- else
- {
- if (y < 0 || 1/y === -Infinity)
- return -r;
- else
- return r;
- }
- };
- Math.acos = function()
- {
- error("Math.acos() does not have a synchronization safe implementation");
- };
- Math.asin = function()
- {
- error("Math.asin() does not have a synchronization safe implementation");
- };
- Math.tan = function()
- {
- error("Math.tan() does not have a synchronization safe implementation");
- };
- Math.pow = function(base, e)
- {
- if (Math.round(e) == e)
- {
- if (e >= 0)
- {
- var a = Math.intPow(base, e);
- }
- else
- {
- var a = 1 / Math.intPow(base, -e);
- }
- }
- else
- {
- var a = Math.exp(e*Math.ln(base));
- }
- warn(base+" ^ "+e+" = "+a);
- return a;
- }
- Math.exp = function(x)
- {
- if (x < 0)
- {
- var iPart = 1/Math.intPow(Math.E, -Math.floor(x));
- }
- else
- {
- var iPart = Math.intPow(Math.E, Math.floor(x));
- }
- x = x - Math.floor(x);
- // x \in [0,1)
- if (x == 0)
- // no need to loop if we know the answer
- return iPart;
- // taylor series around 0
- var fPart =1+x*(1+x*(1+x*(1+x*(1+x*(1+x*(1+x*(1+x*(1+x*(1+x/10)/9)/8)/7)/6)/5)/4)/3)/2);
- return iPart*fPart;
- }
- Math.ln = function(x)
- {
- // the binary logarithm of e
- var lb_e = 1.442695040888963407359924681001892137426645954152985934135449;
- return Math.lb(x) / lb_e;
- }
- /**
- * binary log implementation
- *
- * based on http://en.wikipedia.org/wiki/Binary_logarithm#Real_number
- */
- Math.lb = function(x)
- {
- if (x <= 0)
- {
- return -Infinity;
- }
- // calculate to 20 fractional bits
- var precisionBits = 20;
- // calculate integer log, rounded down
- // when implemented in C, just count the number of bits before the fraction
- // without leading zeros. This may be negative.
- var log = 0;
- if (x >= 1)
- {
- for (var i = 1; i <= x; i *= 2)
- {
- log++;
- }
- log--;
- i /= 2;
- }
- else
- {
- for (var i = 1; i > x; i /= 2)
- {
- log--;
- }
- }
- // now lb(x) = log + lb(y) with y = x/i. So y \in [1,2)
- var y = x/i;
- if (y <= 1)
- // we're done, or there's a minimal rounding error, and we should be done
- return log;
- var m = 0;
- var add = 1;
- while (true)
- {
- while (m <= precisionBits && y < 4)
- {
- m++;
- y *= y;
- add /= 2;
- }
- if (m > precisionBits)
- break;
- log += add;
- y /= 2;
- }
- return log;
- }
- /**
- * calculate the power for positive integer exponents
- */
- Math.intPow = function(base, exp)
- {
- var powers = [base];
- var binary = [1];
- var i = 0;
- for (var e = 2; e <= exp; e *= 2)
- {
- // calculate base^i, using base^(i/2)
- powers.push(powers[i]*powers[i]);
- binary.push(e);
- i++;
- }
- var result = 1;
- var i = binary.length;
- while (exp > 0)
- {
- if (binary[--i] <= exp)
- {
- result *= powers[i];
- exp -= binary[i];
- }
- }
- return result;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement