/*
Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
Available via Academic Free License >= 2.1 OR the modified BSD license.
see: http://dojotoolkit.org/license for details
*/
if(!dojo._hasResource["dojox.calc.toFrac"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.calc.toFrac"] = true;
dojo.provide("dojox.calc.toFrac");
(function(){
var a = [];
var sqrts = [2,3,5,6,7,10,11,13,14,15,17,19,21,22,23,26,29,
30,31,33,34,35,37,38,39,41,42,43,46,47,51,53,55,57,58,59,
61,62,65,66,67,69,70,71,73,74,77,78,79,82,83,85,86,87,89,91,93,94,95,97];
var _fracHashInitialized = false;
var i = -3;
var d = 2;
var epsilon = 1e-15 / 9;
function _fracHashInit(searchNumber){
// summary
// make a fairly large hash table of some fractions, sqrts, etc
var m, mt;
while(i < sqrts.length){
switch(i){
case -3:
m = 1;
mt = '';
break;
case -2:
m = Math.PI;
mt = 'pi';
break;
case -1:
m = Math.sqrt(Math.PI);
mt = '\u221A(pi)';
break;
default:
m = Math.sqrt(sqrts[i]);
mt = "\u221A(" + sqrts[i] + ")";
}
while(d <= 100){
for(n = 1; n < (m == 1 ? d : 100); n++){
var r = m * n / d;
var f = dojox.calc.approx(r);
if(!(f in a)){
// make sure that it is simplified so that toFrac(pi) doesn't get 2*pi/2
if(n==d){
n=1;
d=1;
}
a[f] = {n:n, d:d, m:m, mt:mt};
if(f == searchNumber){ searchNumber = undefined; } // found number, so return and finish hash in nbackground
}
}
d++;
if(searchNumber == undefined){
setTimeout(function(){ _fracHashInit() }, 1);
return;
}
}
d = 2;
i++;
}
_fracHashInitialized = true;
}
// this 1 is standard and the other is advanced and could be a
// separate dojo.require if the user wants the function (and slow init)
function isInt(n){
return Math.floor(n) == n;
}
// make the hash
_fracHashInit();
// advanced _fracLookup
function _fracLookup(number){
function retryWhenInitialized(){
_fracHashInit(number);
return _fracLookup(number);
}
number = Math.abs(number);
var f = a[dojox.calc.approx(number)];
if(!f && !_fracHashInitialized){
return retryWhenInitialized();
}
if(!f){
var i = Math.floor(number);
if(i == 0) { return _fracHashInitialized ? null : retryWhenInitialized(); }
var n = number % 1;
if(n == 0){
return { m: 1, mt: 1, n: number, d: 1 }
}
f = a[dojox.calc.approx(n)];
if(!f || f.m != 1){
var inv = dojox.calc.approx(1 / n);
return isInt(inv) ? { m: 1, mt: 1, n: 1, d: inv } : (_fracHashInitialized ? null : retryWhenInitialized());
}else{
return { m: 1, mt: 1, n: (i * f.d + f.n), d: f.d };
}
}
return f;
}
// add toFrac to the calculator
dojo.mixin(dojox.calc, {
toFrac: function(number){// get a string fraction for a decimal with a set range of numbers, based on the hash
var f = _fracLookup(number);
return f ? ((number < 0 ? '-' : '') + (f.m == 1 ? '' : (f.n == 1 ? '' : (f.n + '*'))) + (f.m == 1 ? f.n : f.mt) + ((f.d == 1 ? '' : '/' + f.d))) : number;
//return f ? ((number < 0 ? '-' : '') + (f.m == 1 ? '' : (f.n == 1 ? '' : (f.n + '*'))) + (f.m == 1 ? f.n : f.mt) + '/' + f.d) : number;
},
pow: function(base, exponent){// pow benefits from toFrac because it can overcome many of the limitations set before the standard Math.pow
// summary:
// Computes base ^ exponent
// Wrapper to Math.pow(base, exponent) to handle (-27) ^ (1/3)
if(base>0||isInt(exponent)){
return Math.pow(base, exponent);
}else{
var f = _fracLookup(exponent);
if(base >= 0){
return (f && f.m == 1)
? Math.pow(Math.pow(base, 1 / f.d), exponent < 0 ? -f.n : f.n) // 32 ^ (2/5) is much more accurate if done as (32 ^ (1/5)) ^ 2
: Math.pow(base, exponent);
}else{ // e.g. (1/3) root of -27 = -3, 1 / exponent must be an odd integer for a negative base
return (f && f.d & 1) ? Math.pow(Math.pow(-Math.pow(-base, 1 / f.d), exponent < 0 ? -f.n : f.n), f.m) : NaN;
}
}
}
});
/*
function reduceError(number){
var f = _fracLookup(number);
if(!f){ f = _fracLookup(number); }
return f ? ((number < 0 ? -1 : 1) * f.n * f.m / f.d) : number;
}
*/
})();
}