/* Copyright (c) 2004-2012, 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; } */ })(); }