UNPKG

mathjslab

Version:

MathJSLab - An interpreter with language syntax like MATLAB®/Octave, ISBN 978-65-00-82338-7.

171 lines (164 loc) 8.32 kB
import { CharString } from './CharString'; import { ComplexDecimal } from './ComplexDecimal'; import type { Rounding, Modulo } from './ComplexDecimal'; import { CoreFunctions } from './CoreFunctions'; import { ElementType, MultiArray } from './MultiArray'; /** * MathJSLab configuration. */ abstract class Configuration { /** * User functions */ public static functions: Record<string, Function> = { configure: Configuration.configure, getconfig: Configuration.getconfig, }; private static roundingStrings = ['up', 'down', 'ceil', 'floor', 'half_up', 'half_down', 'half_even', 'half_ceil', 'half_floor']; private static moduloStrings = ['up', 'down', undefined, 'floor', undefined, undefined, 'half_even', undefined, undefined, 'euclid']; /** * Configuration parameters table. */ private static configuration: Record< string, { set: (config: any) => void; setDefault: () => void; get: () => any; } > = { precision: { set: (precision: ComplexDecimal) => ComplexDecimal.set({ precision: precision.re.toNumber() }), setDefault: () => ComplexDecimal.set({ precision: ComplexDecimal.defaultConfiguration.precision }), get: () => new ComplexDecimal(ComplexDecimal.settings.precision), }, precisionCompare: { set: (precisionCompare: ComplexDecimal) => ComplexDecimal.set({ precisionCompare: precisionCompare.re.toNumber() }), setDefault: () => ComplexDecimal.set({ precisionCompare: ComplexDecimal.defaultConfiguration.precisionCompare }), get: () => new ComplexDecimal(ComplexDecimal.settings.precisionCompare), }, rounding: { set: (rounding: CharString) => { const roundingMode = Configuration.roundingStrings.indexOf(rounding.str); if (roundingMode > 0) { ComplexDecimal.set({ rounding: roundingMode as Rounding }); } else { throw new Error(`configure: invalid rounding mode: ${rounding.str}`); } }, setDefault: () => ComplexDecimal.set({ rounding: ComplexDecimal.defaultConfiguration.rounding }), get: () => new CharString(Configuration.roundingStrings[ComplexDecimal.settings.rounding as number]), }, toExpPos: { set: (toExpPos: ComplexDecimal) => ComplexDecimal.set({ toExpPos: toExpPos.re.toNumber() }), setDefault: () => ComplexDecimal.set({ toExpPos: ComplexDecimal.defaultConfiguration.toExpPos }), get: () => new ComplexDecimal(ComplexDecimal.settings.toExpPos), }, toExpNeg: { set: (toExpNeg: ComplexDecimal) => ComplexDecimal.set({ toExpPos: toExpNeg.re.toNumber() }), setDefault: () => ComplexDecimal.set({ toExpNeg: ComplexDecimal.defaultConfiguration.toExpNeg }), get: () => new ComplexDecimal(ComplexDecimal.settings.toExpNeg), }, minE: { set: (minE: ComplexDecimal) => ComplexDecimal.set({ minE: minE.re.toNumber() }), setDefault: () => ComplexDecimal.set({ minE: ComplexDecimal.defaultConfiguration.minE }), get: () => new ComplexDecimal(ComplexDecimal.settings.minE), }, maxE: { set: (maxE: ComplexDecimal) => ComplexDecimal.set({ maxE: maxE.re.toNumber() }), setDefault: () => ComplexDecimal.set({ maxE: ComplexDecimal.defaultConfiguration.maxE }), get: () => new ComplexDecimal(ComplexDecimal.settings.maxE), }, modulo: { set: (modulo: CharString) => { const moduloMode = Configuration.moduloStrings.indexOf(modulo.str); if (moduloMode > 0) { ComplexDecimal.set({ modulo: moduloMode as Modulo }); } else { throw new Error(`configure: invalid modulo mode: ${modulo.str}`); } }, setDefault: () => ComplexDecimal.set({ modulo: ComplexDecimal.defaultConfiguration.modulo }), get: () => new CharString(Configuration.moduloStrings[ComplexDecimal.settings.modulo as number] as string), }, crypto: { set: (crypto: ComplexDecimal) => ComplexDecimal.set({ crypto: Boolean(crypto.re.toNumber()) }), setDefault: () => ComplexDecimal.set({ crypto: ComplexDecimal.defaultConfiguration.crypto }), get: () => new ComplexDecimal(Number(ComplexDecimal.settings.crypto), 0, ComplexDecimal.LOGICAL), }, }; public static configure(): CharString; public static configure(config: CharString, value: ElementType): CharString; public static configure(CONFIG: MultiArray): CharString; public static configure(...args: any[]): CharString | undefined { const setConfig = (config: [CharString, any]): void => { if (config[0] instanceof CharString) { if (config[0].str in Configuration.configuration) { Configuration.configuration[config[0].str].set(config[1]); } else { throw new ReferenceError(`configure: invalid configuration: '${config[0].str}'.`); } } else { CoreFunctions.throwInvalidCallError('configure'); } }; if (args.length === 0) { // Set default configuration. for (const config in Configuration.configuration) { Configuration.configuration[config].setDefault(); } return new CharString('All configuration set to default values.'); } else if (args.length === 1 && args[0] instanceof MultiArray) { // Array of configuration key and value. if (args[0].dimension[1] === 2) { (args[0].array as [CharString, any][]).forEach((config: [CharString, any]) => { setConfig(config); }); return new CharString(`${args[0].array.length} configuration values set.`); } else { CoreFunctions.throwInvalidCallError('configure'); } } else if (args.length === 2 && args[0] instanceof CharString) { // Configuration key and value. setConfig(args as [CharString, any]); return new CharString(`Configuration parameter '${args[0].str}' set to ${Configuration.configuration[args[0].str].get().unparse()}`); } else { CoreFunctions.throwInvalidCallError('configure'); } } public static getconfig(): MultiArray; public static getconfig(config: CharString): MultiArray; public static getconfig(CONFIG: MultiArray): MultiArray; public static getconfig(...args: ElementType[]): MultiArray | undefined { let result: MultiArray; const keys = Object.keys(Configuration.configuration); const loadResult = (list: string[]): void => { list.forEach((config, i) => { const conf = Configuration.configuration[config].get(); result.array[i] = [new CharString(config), conf]; }); }; if (args.length === 0) { // Get all configurations. result = new MultiArray([keys.length, 2], null, true); loadResult(keys); return result; } else if (args.length === 1) { // Get selected configurations. const C = MultiArray.linearize(MultiArray.scalarToMultiArray(args[0])).map((c) => { if (c instanceof CharString && c.str in Configuration.configuration) { return c.str; } else { throw new Error('getconfig: invalid configuration parameter.'); } }); result = new MultiArray([C.length, 2], null, true); loadResult(C); return result; } else { CoreFunctions.throwInvalidCallError('getconfig'); } } } export { Configuration }; export default Configuration;