makeGlobalObject(); SnapExtensions.primitives.set( 'big_switch(bool)', loadBlocks ); SnapExtensions.primitives.set( 'big_scheme(fn, num)', function (which, num) { function parseNumber (n) { var fn = SchemeNumber.fn; if (!fn['number?'](n)) { n = '' + n; try { return parseENotation(n) || SchemeNumber(n); } catch (err) { return NaN; } } return n; } function parseENotation (n) { var fn = SchemeNumber.fn; var numbers = n.match(/^(-?\d+\.?\d*|-?\.\d+)e(-?\d+)$/i); if (!numbers) return null; var coefficient = numbers[1]; var exponent = numbers[2]; return fn['*']( coefficient, fn.expt('10', exponent) ); } var fn=SchemeNumber.fn, number=parseNumber(num); switch (which) { case 'number?': case 'complex?': return (fn['number?'](number)); case 'real?': return (fn['real?'](number) || fn['real-valued?'](number)); case 'rational?': return (fn['rational?'](number) || (fn['='](number, fn.rationalize(number, parseNumber('1.0e-5'))))); case 'integer?': return (fn['integer?'](number) || fn['integer-valued?'](number)); case 'exact?': case 'inexact?': case 'finite?': case 'infinite?': case 'nan?': case 'real-part': case 'imag-part': return (fn[which](number)); case 'magnitude': return (fn.magnitude(number)); case 'angle': return (fn.angle(number)); case 'numerator': return (fn.numerator(number)); case 'denominator': return (fn.denominator(number)); case 'exact': return (fn.exact(number)); case 'inexact': return (fn.inexact(number)); } } ); function makeGlobalObject () { window.bigNumbers = { originalEvaluate: InputSlotMorph.prototype.evaluate, originalChangeVar: VariableFrame.prototype.changeVar, originalPrims: { reportBasicSum: Process.prototype.reportBasicSum, reportBasicDifference: Process.prototype.reportBasicDifference, reportBasicProduct: Process.prototype.reportBasicProduct, reportBasicQuotient: Process.prototype.reportBasicQuotient, reportBasicPower: Process.prototype.reportBasicPower, reportBasicModulus: Process.prototype.reportBasicModulus, reportBasicAtan2: Process.prototype.reportBasicAtan2, reportRound: Process.prototype.reportRound, reportBasicMin: Process.prototype.reportBasicMin, reportBasicMax: Process.prototype.reportBasicMax, reportBasicRandom: Process.prototype.reportBasicRandom, reportBasicLessThan: Process.prototype.reportBasicLessThan, reportBasicGreaterThan: Process.prototype.reportBasicGreaterThan, reportEquals: Process.prototype.reportEquals, reportIsIdentical: Process.prototype.reportIsIdentical, reportMonadic: Process.prototype.reportMonadic } }; } function loadBlocks (useBigNums) { var fn = SchemeNumber.fn; var originalPrims = window.bigNumbers.originalPrims; if (useBigNums) { InputSlotMorph.prototype.evaluate = function () { var contents = this.contents(); if (this.selectedBlock) { return this.selectedBlock; } if (this.constant) { return this.constant; } if (this.isNumeric) { return parseNumber(contents.text || '0'); } return contents.text; }; VariableFrame.prototype.changeVar = function (name, delta, sender) { var frame = this.find(name), value, newValue; if (frame) { value = parseNumber(frame.vars[name].value); newValue = Number.isNaN(value) ? delta : fn['+'](value, parseNumber(delta)); if (sender instanceof SpriteMorph && (frame.owner instanceof SpriteMorph) && (sender !== frame.owner)) { sender.shadowVar(name, newValue); } else { frame.vars[name].value = newValue; } } }; Object.assign(Process.prototype, { reportBasicSum: function (a, b) { a = parseNumber(a); b = parseNumber(b); if (Number.isNaN(a) || Number.isNaN(b)) return NaN; return fn['+'](a, b); }, reportBasicDifference: function (a, b) { a = parseNumber(a); b = parseNumber(b); if (Number.isNaN(a) || Number.isNaN(b)) return NaN; return fn['-'](a, b); }, reportBasicProduct: function (a, b) { a = parseNumber(a); b = parseNumber(b); if (Number.isNaN(a) || Number.isNaN(b)) return NaN; return fn['*'](a, b); }, reportBasicQuotient: function (a, b) { a = parseNumber(a); b = parseNumber(b); if (fn['='](b, '0') && !fn['='](a, '0')) { return (fn['<'](a, '0') ? SchemeNumber('-inf.0') : SchemeNumber('+inf.0')) }; if (Number.isNaN(a) || Number.isNaN(b) || fn['='](b, '0')) return NaN; return fn['/'](a, b); }, reportBasicPower: function (a, b) { a = parseNumber(a); b = parseNumber(b); if (Number.isNaN(a) || Number.isNaN(b)) return NaN; return fn['expt'](a, b); }, reportBasicModulus: function (a, b) { a = parseNumber(a); b = parseNumber(b); if (Number.isNaN(a) || Number.isNaN(b)) return NaN; var result = fn.mod(a, b); if (fn['<'](b, '0') && fn['>'](result, '0')) { result = fn['+'](result, b); } return result; }, reportBasicAtan2: function (a, b) { a = parseNumber(a); b = parseNumber(b); if (Number.isNaN(a) || Number.isNaN(b)) return NaN; return degrees(fn.atan2(a, b)); }, reportRound: function (n) { if (this.enableHyperOps) { if (n instanceof List) { return n.map(each => this.reportRound(each)); } } n = parseNumber(n); if (Number.isNaN(n)) return NaN; x = fn.round(n); if (fn["integer?"](x)) return fn["exact"](x); return x; }, reportBasicMin: function (a, b) { x = parseNumber(a); y = parseNumber(b); if (Number.isNaN(x) || Number.isNaN(y)) { return ab ? a : b; } return fn['>'](x, y) ? x : y; }, reportBasicRandom: function (min, max) { var floor = parseNumber(min), ceil = parseNumber(max); if (Number.isNaN(floor) || Number.isNaN(ceil)) return NaN; if (!fn['='](fn.mod(floor, '1'), '0') || !fn['='](fn.mod(ceil, '1'), '0')) { // One of the numbers isn't whole. Include the decimal. return fn['+']( fn['*']( Math.random(), fn['-'](ceil, floor) ), floor ); } var size = Math.ceil(max.toString(10).length/14); const array = new Uint32Array(size); window.crypto.getRandomValues(array); var digits=""; for (i=0;ib; return fn['>'](x, y); }, reportEquals: function (a, b) { x = parseNumber(a); y = parseNumber(b); if (Number.isNaN(x) || Number.isNaN(y)) return snapEquals(a, b); return fn['='](x, y); }, reportIsIdentical: function (a, b) { x = parseNumber(a); y = parseNumber(b); if (Number.isNaN(x) || Number.isNaN(y)) return originalPrims.reportIsIdentical.call(this, a, b); return fn['='](x, y); }, reportMonadic: function (fname, n) { if (this.enableHyperOps) { if (n instanceof List) { return n.map(each => this.reportMonadic(fname, each)); } } n = parseNumber(n); if (Number.isNaN(n)) return NaN; switch (Process.prototype.inputOption(fname)) { case 'abs': return fn.abs(n); case 'neg': return fn['-'](n); case 'sign': if (fn['='](n,SchemeNumber('0'))) return SchemeNumber('0'); return fn['/'](n, fn.abs(n)); case 'ceiling': return fn.ceiling(n); case 'floor': return fn.floor(n); case 'sqrt': return sqrt(n); case 'sin': return fn.sin(radians(n)); case 'cos': return fn.cos(radians(n)); case 'tan': return fn.tan(radians(n)); case 'asin': return degrees(fn.asin(n)); case 'acos': return degrees(fn.acos(n)); case 'atan': return degrees(fn.atan(n)); case 'ln': return fn.log(n); case 'log': return fn.log(n, '10'); case 'lg': return fn.log(n, '2'); case 'e^': return fn.exp(n); case '10^': return fn.expt('10', n); case '2^': return fn.expt('2', n); case 'id': return n; default: return SchemeNumber('0'); } } }); } else { InputSlotMorph.prototype.evaluate = window.bigNumbers.originalEvaluate; VariableFrame.prototype.changeVar = window.bigNumbers.originalChangeVar; Object.assign(Process.prototype, originalPrims); } // +++ done = true; } function parseNumber (n) { var fn = SchemeNumber.fn; if (!fn['number?'](n)) { n = '' + n; try { return parseENotation(n) || SchemeNumber(n); } catch (err) { return NaN; } } return n; } function parseENotation (n) { var fn = SchemeNumber.fn; var numbers = n.match(/^(-?\d+\.?\d*|-?\.\d+)e(-?\d+)$/i); if (!numbers) return null; var coefficient = numbers[1]; var exponent = numbers[2]; return fn['*']( coefficient, fn.expt('10', exponent) ); } function sqrt (n) { var fn = SchemeNumber.fn; if (!fn['exact?'](n) || !fn['rational?'](n) || fn['<'](n,'0')) return fn.sqrt(n); var rootNumerator = fn['exact-integer-sqrt'](fn.numerator(n)); if (!fn['='](rootNumerator[1], '0')) return fn.sqrt(n); var rootDenominator = fn['exact-integer-sqrt'](fn.denominator(n)); if (!fn['='](rootDenominator[1], '0')) return fn.sqrt(n); return fn['/'](rootNumerator[0], rootDenominator[0]); }