_Executor.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. define("dojox/calc/_Executor", [
  2. "dojo/_base/kernel",
  3. "dojo/_base/declare",
  4. "dojo/_base/lang",
  5. "dojo/number",
  6. "dijit/_base/manager",
  7. "dijit/_WidgetBase",
  8. "dijit/_TemplatedMixin",
  9. "dojox/math/_base"
  10. ], function(kernel, declare, lang, number, dijit, WidgetBase, TemplatedMixin, math){
  11. kernel.experimental("dojox.calc");
  12. var calcEnv, calc; // private
  13. var magicBigInt = (1 << 30) - 35; // 2^30 - 35 is a prime that ensures approx(n/(2^k)) != n/(2^k) for k >= 1 and n < 2^k
  14. /*=====
  15. WidgetBase = dijit._WidgetBase;
  16. TemplatedMixin = dijit._TemplatedMixin;
  17. =====*/
  18. var Executor = declare(
  19. "dojox.calc._Executor",
  20. [WidgetBase, TemplatedMixin],
  21. {
  22. // summary:
  23. // A graphing, scientific calculator
  24. //
  25. templateString: '<iframe src="' + require.toUrl("dojox/calc/_ExecutorIframe.html") +
  26. '" style="display:none;" onload="if(arguments[0] && arguments[0].Function)'+dijit._scopeName+'.byNode(this)._onLoad(arguments[0])"></iframe>',
  27. _onLoad: function(env){
  28. // summary
  29. // prepare for communications between the user and the calculator by saving the calculator environment, storing the prompt function locally, and making dojox.math available
  30. //
  31. calcEnv = env;
  32. env.outerPrompt = window.prompt; // for IE who can't execute the iframe's prompt method without notifying the user first
  33. // let the user call dojo math functions
  34. env.dojox = {math: {}};
  35. for(var f in math){ env.dojox.math[f] = lang.hitch(math, f); }
  36. if("toFrac" in calc){
  37. env.toFracCall = lang.hitch(calc, 'toFrac');
  38. this.Function('toFrac', 'x', "return toFracCall(x)");
  39. }
  40. env.isJavaScriptLanguage = number.format(1.5, {pattern:'#.#'}) == "1.5";
  41. env.Ans = 0;
  42. env.pi = Math.PI;
  43. env.eps = Math.E;
  44. env.powCall = lang.hitch(calc, 'pow');
  45. // TODO add Degrees support to trig functions
  46. //this.normalizedFunction('toString', 'number, radix', "return number.toString(radix)");
  47. this.normalizedFunction('sqrt', 'x', "return Math.sqrt(x)");
  48. this.normalizedFunction('sin', 'x', "return Math.sin(x)");
  49. this.normalizedFunction('cos', 'x', "return Math.cos(x)");
  50. this.normalizedFunction('tan', 'x', "return Math.tan(x)");
  51. this.normalizedFunction('asin', 'x', "return Math.asin(x)");
  52. this.normalizedFunction('acos', 'x', "return Math.acos(x)");
  53. this.normalizedFunction('atan', 'x', "return Math.atan(x)");
  54. this.normalizedFunction('atan2', 'y, x', "return Math.atan2(y, x)");
  55. this.normalizedFunction('Round', 'x', "return Math.round(x)");
  56. this.normalizedFunction('Int', 'x', "return Math.floor(x)");
  57. this.normalizedFunction('Ceil', 'x', "return Math.ceil(x)");
  58. this.normalizedFunction('ln', 'x', "return Math.log(x)");
  59. this.normalizedFunction('log', 'x', "return Math.log(x)/Math.log(10)");
  60. this.normalizedFunction('pow', 'x, y', "return powCall(x,y)");
  61. this.normalizedFunction('permutations', 'n, r', "return dojox.math.permutations(n, r);");
  62. this.normalizedFunction('P', 'n, r', "return dojox.math.permutations(n, r);");
  63. this.normalizedFunction('combinations', 'n, r', "return dojox.math.combinations(n, r);");
  64. this.normalizedFunction('C', 'n, r', "return dojox.math.combinations(n, r)");
  65. this.normalizedFunction('toRadix', 'number, baseOut', "if(!baseOut){ baseOut = 10; } if(typeof number == 'string'){ number = parseFloat(number); }return number.toString(baseOut);");
  66. this.normalizedFunction('toBin', 'number', "return toRadix(number, 2)");
  67. this.normalizedFunction('toOct', 'number', "return toRadix(number, 8)");
  68. this.normalizedFunction('toHex', 'number', "return toRadix(number, 16)");
  69. this.onLoad();
  70. },
  71. onLoad: function(){
  72. // summary:
  73. // this should be overwritten and become a great place for making user predefined functions
  74. //
  75. },
  76. Function: function(name, args, body){
  77. // summary
  78. // create an anonymous function to run the code the parser generates from the user input.
  79. // params
  80. // name: this argument is simply a String that represents the name of the function being evaluated. It can be undefined, but in that case the function is a one time use.
  81. // args: the function arguments (a String)
  82. // body: the function body, also a String
  83. //
  84. return lang.hitch(calcEnv, calcEnv.Function.apply(calcEnv, arguments));
  85. },
  86. normalizedFunction: function(name, args, body){
  87. return lang.hitch(calcEnv, calcEnv.normalizedFunction.apply(calcEnv, arguments));
  88. },
  89. deleteFunction: function(name){
  90. calcEnv[name] = undefined;
  91. delete calcEnv[name];
  92. },
  93. eval: function(text){
  94. // summary
  95. // create an anonymous function to run the code the parser generates from the user input.
  96. // params
  97. // text, type String, is the user input that needs to be parsed
  98. //
  99. return calcEnv.eval.apply(calcEnv, arguments);
  100. },
  101. destroy: function(){
  102. this.inherited(arguments);
  103. calcEnv = null; // assist garbage collection
  104. }
  105. });
  106. return calc = {
  107. pow: function(/*Number*/ base, /*Number*/ exponent){
  108. // summary:
  109. // Computes base ^ exponent
  110. // Wrapper to Math.pow(base, exponent) to handle (-27) ^ (1/3)
  111. function isInt(n){
  112. return Math.floor(n) == n;
  113. }
  114. if(base >= 0 || isInt(exponent)){
  115. return Math.pow(base, exponent);
  116. }else{ // e.g. (1/3) root of -27 = -3
  117. var inv = 1 / exponent;
  118. // e.g. 1 / (1/3) must be an odd integer
  119. return (isInt(inv) && (inv & 1)) ? -Math.pow(-base, exponent) : NaN;
  120. }
  121. },
  122. approx: function(/*Number*/ r){
  123. // summary:
  124. // Return a less exact approximation of r such that approx(r * (1 +- eps)) == approx(r)
  125. if(typeof r == "number"){
  126. return Math.round(r * magicBigInt) / magicBigInt;
  127. }
  128. return r;
  129. },
  130. _Executor: Executor
  131. };
  132. });