/usr/share/yacas/constants.rep/code.ys is in yacas 1.3.3-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | /* Definition of constants. */
/* TODO:
* There is a problem with defining I this way: if I is used, but the
* file "complex" has not been loaded, the interpreter can not deal
* with "Complex".
*/
SetGlobalLazyVariable(I,Complex(0,1));
//////////////////////////////////////////////////
/// Cached constants support and definition of Pi
//////////////////////////////////////////////////
//TODO: here we wrap the entire file in LocalSymbols, this is inefficient in that it slows loading of this file. Needs optimization.
LocalSymbols(CacheOfConstantsN) [
/// declare a new cached constant C'atom and its associated function C'atom().
/// C'atom() will call C'func() at current precision to evaluate C'atom if it has not yet been cached at that precision. (note: any arguments to C'func() must be included)
RuleBase("CachedConstant", {C'cache, C'atom, C'func});
UnFence("CachedConstant", 3); // not sure if this is useful
HoldArg("CachedConstant", C'func);
HoldArg("CachedConstant", C'cache); // name of the cache
// check syntax: must be called on an atom and a function
Rule("CachedConstant", 3, 10, And(IsAtom(C'atom), IsFunction(C'func)))
[
Local(C'name,C'functionName);
Set(C'name, String(C'atom)); // this is for later conveniences
Set(C'functionName,ConcatStrings("Internal'",C'name));
If( // create the cache it if it does not already exist
IsAtom(Eval(C'cache)),
MacroSet(Eval(C'cache), {})
);
// Write({"debug step 0: ", C'cache, Eval(C'cache), C'atom, C'func, C'name});
// check that the constant is not already defined
If(
Equals(Builtin'Assoc(C'name, Eval(C'cache)), Empty), // the constant is not already defined, so need to define "C'atom" and the corresponding function "C'atom"()
[ // e.g. C'atom evaluates to Pi, C'cache to a name e.g. CacheOfConstantsN, which is bound to a hash
MacroClear(C'atom);
// Write({"debug step 1: ", Cache'name, C'cache, Eval(C'cache)});
// add the new constant to the cache
// MacroSet(Cache'name, Insert(Eval(C'cache), 1, {C'name, 0, 0}));
DestructiveInsert(Eval(C'cache), 1, {C'name, 0, 0});
// Write({"debug step 2: ", Cache'name, C'cache, Eval(C'cache)});
// define the new function "C'atom"()
// note: this should not use N() because it may be called from inside N() itself
MacroRuleBase(C'functionName, {});
`( Rule(@C'functionName, 0, 1024, True)
[
Local(new'prec, new'C, cached'C);
Set(new'prec, Builtin'Precision'Get());
// fetch the cache entry for this constant
// note that this procedure will store the name of the cache here in this statement as Eval(C'cache)
Set(cached'C, Builtin'Assoc(@C'name, @C'cache));
If(
LessThan(MathNth(cached'C, 2), new'prec),
[ // need to recalculate at current precision
If(Equals(InVerboseMode(),True), Echo("CachedConstant: Info: constant ", @C'name, " is being recalculated at precision ", new'prec));
Set(new'C, Eval(@C'func));
DestructiveReplace(cached'C, 2, new'prec);
DestructiveReplace(cached'C, 3, new'C);
new'C;
],
// return cached value of C'atom
MathNth(cached'C, 3)
);
]);
// calculate C'atom at current precision for the first time
// Eval(UnList({C'atom})); // "C'name"();
// we do not need this until the constant is used; it will just slow us down
],
// the constant is defined
Echo("CachedConstant: Warning: constant ", C'atom, " already defined")
);
];
Rule("CachedConstant", 3, 20, True)
Echo("CachedConstant: Error: ", C'atom, " must be an atom and ", C'func, " must be a function.");
/// assign numerical values to all cached constants: using fixed cache "CacheOfConstantsN"
// this is called from N()
Function("AssignCachedConstantsN", {})
[
Local(var,fname);
ForEach(var, AssocIndices(CacheOfConstantsN))
[
MacroClear(Atom(var));
Set(fname,ConcatStrings("Internal'",var));
Set(var,Atom(var));
// this way the routine Internal'Pi() will be actually called only when the variable 'Pi' is used, etcetera.
`SetGlobalLazyVariable((@var), UnList({Atom(fname)}));
];
];
UnFence("AssignCachedConstantsN", 0);
/// clear values from all cached constants: using fixed cache "CacheOfConstantsN"
// this is called from N()
Function("ClearCachedConstantsN", {})
[
Local(c'entry);
ForEach(c'entry, CacheOfConstantsN)
MacroClear(Atom(c'entry[1]));
];
UnFence("ClearCachedConstantsN", 0);
/// declare some constants now
CachedConstant(CacheOfConstantsN, Pi,
[// it seems necessary to precompute Pi to a few more digits
// so that Cos(0.5*Pi)=0 at precision 10
// FIXME: find a better solution
Local(result,old'prec);
Set(old'prec,Builtin'Precision'Get());
If(Equals(InVerboseMode(),True), Echo("Recalculating Pi at precision ",old'prec+5));
Builtin'Precision'Set(Builtin'Precision'Get()+5);
result := MathPi();
If(Equals(InVerboseMode(),True),Echo("Switching back to precision ",old'prec));
Builtin'Precision'Set(old'prec);
result;
]
);
CachedConstant(CacheOfConstantsN, gamma, GammaConstNum());
CachedConstant(CacheOfConstantsN, GoldenRatio, N( (1+Sqrt(5))/2 ) );
CachedConstant(CacheOfConstantsN, Catalan, CatalanConstNum() );
]; // LocalSymbols(CacheOfConstantsN)
|