123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- /*
- 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;
- }
- */
- })();
- }
|