12
dictionary property funcName;
19
* input precision - for any number entered with smaller precision,
20
* we'll increase the precision to this value
24
/* guard digits added to input precision */
27
/* number of fractional digits to display for each value */
30
/* maximum number of digits to display for each value */
33
/* display in scientific notation */
39
* Custom tokenizer for arithmetic expressions
41
CalcTokenizer: Tokenizer
45
['[ \t]+', nil, &tokCvtSkip, nil],
48
['(%.[0-9]+|[0-9]+(%.[0-9]*)?)([eE][+-]?[0-9]+)?',
52
['[(+*-/)!^?]', tokOp, nil, nil],
55
['[a-zA-Z]+', tokWord, &tokCvtLower, nil]
59
grammar command: expression->expr_ : object
60
eval() { return expr_.eval(); }
63
class commandWithIntegerOp: object
64
op_ = nil // this is the grammar element for the operand
65
desc_ = "desc" // this is the command name
66
opDesc_ = "operator desc" // description of operator's purpose
71
local val = toInteger(op_.eval());
76
"Invalid argument to '<<desc_>>' - please specify
82
grammar command: 'sci' number->op_ : commandWithIntegerOp
84
opDesc_ = "the number of digits to display after the decimal point"
87
/* set scientific notation */
88
calcGlobals.dispSci = true;
90
/* note the number of digits after the decimal */
91
calcGlobals.dispFracDigits = val;
93
/* set the maximum digits */
94
calcGlobals.dispMaxDigits = (val > 32 ? val + 5 : 32);
96
/* explain the change */
97
"Scientific notation, <<val>> digits after the decimal\n";
101
grammar command: [badness 1] 'sci' *: object
104
"Please enter in the format 'sci N', where N is the number of
105
digits to display after the decimal point.\n";
109
grammar command: 'fix' number->op_ : commandWithIntegerOp
111
opDesc_ = "the number of digits to display after the decimal point"
114
/* set non-scientific notation */
115
calcGlobals.dispSci = nil;
117
/* note the number of digits after the decimal */
118
calcGlobals.dispFracDigits = val;
120
/* set the maximum digits */
121
calcGlobals.dispMaxDigits = (val > 32 ? val + 12 : 32);
123
/* explain the change */
124
"Fixed notation, <<val>> digits after the decimal\n";
128
grammar command: [badness 1] 'fix' *: object
131
"Please enter in the format 'fix N', where N is the number of
132
digits to display after the decimal point.\n";
136
grammar command: 'prec' number->op_ : commandWithIntegerOp
138
opDesc_ = "the default input precision"
141
/* note the new input precision */
142
calcGlobals.inputPrecision = val;
144
/* explain the change */
145
"Input precision is now <<val>> digits\n";
149
grammar command: [badness 1] 'prec' *: object
152
"Please enter in the format 'prec N', where N is the number of
153
digits to use for the default input precision.\n";
157
grammar expression: term->val_: object
158
eval() { return val_.eval(); }
161
grammar term: term->val1_ '+' factor->val2_: object
162
eval() { return val1_.eval() + val2_.eval(); }
165
grammar term: term->val1_ '-' factor->val2_: object
166
eval() { return val1_.eval() - val2_.eval(); }
169
grammar term: factor->val_: object
170
eval() { return val_.eval(); }
173
grammar factor: factor->val1_ '*' power->val2_: object
174
eval() { return val1_.eval() * val2_.eval(); }
177
grammar factor: factor->val1_ '/' power->val2_: object
178
eval() { return val1_.eval() / val2_.eval(); }
181
grammar factor: power->val_: object
182
eval() { return val_.eval(); }
185
grammar power: power->val1_ '^' prefix->val2_: object
186
eval() { return val1_.eval().raiseToPower(val2_.eval()); }
189
grammar power: prefix->val_: object
190
eval() { return val_.eval(); }
193
grammar prefix: funcName->func_ '(' expression->expr_ ')': object
194
eval() { return gDict.findWord(func_, &funcName)[1].eval(expr_); }
197
grammar prefix: funcName->func_ prefix->expr_ : object
198
eval() { return gDict.findWord(func_, &funcName)[1].eval(expr_); }
201
#define DefFunc(nm, func) \
202
object funcName = #@nm eval(expr) { return expr.eval().func(); }
208
DefFunc(cos, cosine);
209
DefFunc(tan, tangent);
210
DefFunc(asin, arcsine);
211
DefFunc(acos, arccosine);
212
DefFunc(atan, arctangent);
221
return expr.eval().logE();
229
return expr.eval().log10();
237
return expr.eval().expE();
245
return expr.eval().sine();
253
return expr.eval().cosine();
261
return expr.eval().tangent();
269
return expr.eval().arcsine();
277
return expr.eval().arccosine();
285
return expr.eval().arctangent();
293
return expr.eval().sqrt();
301
return expr.eval().sqrt();
306
grammar prefix: '-' postfix->val_ : object
307
eval() { return -val_.eval(); }
310
grammar prefix: '+' postfix->val_: object
311
eval() { return val_.eval(); }
314
grammar prefix: postfix->val_ : object
315
eval() { return val_.eval(); }
318
grammar postfix: atomic->val_ '!': object
319
eval() { return factorial(val_.eval()); }
322
grammar postfix: atomic->val_ : object
323
eval() { return val_.eval(); }
331
* do this iteratively rather than recursively, to allow for really
332
* big inputs without fear of blowing out the stack
334
for (prod = 1.0 ; x > 1 ; --x)
337
/* return the product */
341
grammar atomic: '(' expression->val_ ')': object
342
eval() { return val_.eval(); }
345
grammar atomic: number->num_ : object
346
eval() { return num_.eval(); }
349
grammar number: tokFloat->num_ : object
354
/* parse the number */
355
val = new BigNumber(num_);
357
/* if the precision is smaller than the input minimum, increase it */
358
if (val.getPrecision()
359
< calcGlobals.inputPrecision + calcGlobals.guardPrecision)
360
val = val.setPrecision(calcGlobals.inputPrecision
361
+ calcGlobals.guardPrecision);
363
/* return the value */
368
grammar atomic: 'e' : object
371
return BigNumber.getE(calcGlobals.inputPrecision
372
+ calcGlobals.guardPrecision);
376
grammar atomic: 'pi': object
379
return BigNumber.getPi(calcGlobals.inputPrecision
380
+ calcGlobals.guardPrecision);
386
"T3 Scientific Calculator\n
387
Type ?\ for help, type Q or QUIT to quit.\n";
398
/* tokenize the string */
401
toks = CalcTokenizer.tokenize(str);
403
catch (TokErrorNoMatch err)
405
"Invalid character '<<err.remainingStr_.substr(1, 1)>>'\n";
409
/* if it's 'quit' or 'q', stop */
410
if (toks.length() == 1
411
&& (getTokVal(toks[1]) is in ('q', 'quit')))
414
/* if it's '?', show help */
415
if (toks.length() == 1
416
&& (getTokVal(toks[1]) == '?'))
423
match = command.parseTokens(toks, gDict);
425
/* if we didn't get anything, say so */
426
if (match.length() == 0)
428
"Invalid expression\n";
437
/* evaluate the expression */
438
val = match[1].eval();
440
/* if we got a valid, display it */
443
/* clear the display flags */
446
/* display in scientific or normal notation as desired */
447
if (calcGlobals.dispSci)
450
/* display the value */
451
"<<val.formatString(calcGlobals.dispMaxDigits, flags,
452
-1, calcGlobals.dispFracDigits)>>\n";
455
catch (Exception exc)
457
"Evaluation error: <<exc.displayException()>>\n";
465
"Enter numbers in decimal or scientific notation:\b
468
Operators, in order of precedence:\b
469
\ta ^ b\t\traise a to the power of b\n
470
\ta * b\t\tmultiply\n
473
\ta - b\t\tsubtract\n
474
\t( a )\t\toverride operator precedence\n
477
\tsin(x)\t\ttrigonometric sine\n
478
\tcos(x)\t\ttrigonometric cosine\n
479
\ttan(x)\t\ttrigonometric tangent\n
480
\tasin(x)\t\tarcsine\n
481
\tacos(x)\t\tarccosine\n
482
\tatan(x)\t\tarctangent\n
483
\tln(x)\t\tnatural logarithm\n
484
\tlog(x)\t\tcommon (base-10) logarithm\n
485
\texp(x)\t\traise e (the base of the natural logarithm) to power\n
486
\tsqr(x)\t\tsquare root (sqrt(x) is equivalent)\n
493
\tquit\t\tturn off the calculator\n
494
\tsci N\t\tdisplay scientific notation with N digits after the decimal\n
495
\tfix N\t\tdisplay fixed notation with N digits after the decimal\n
496
\tprec N\t\tset default input precision to N digits\n