diff options
author | David Timber <dxdt@dev.snart.me> | 2025-04-02 23:58:14 +0200 |
---|---|---|
committer | David Timber <dxdt@dev.snart.me> | 2025-04-02 23:58:14 +0200 |
commit | a3cb688be29ca9d5be4a4cd2959c41d69077c8ad (patch) | |
tree | a9a98fe3e8976950f31d1f88691fa341b28cddf1 /linux-casual/mp-int/index.js | |
parent | adece75b051d22bc13054978e66f9f30b3e9f8d6 (diff) |
Move some files ...
- Moved the ripple carry adder animations impl to subdir
Diffstat (limited to 'linux-casual/mp-int/index.js')
-rw-r--r-- | linux-casual/mp-int/index.js | 483 |
1 files changed, 0 insertions, 483 deletions
diff --git a/linux-casual/mp-int/index.js b/linux-casual/mp-int/index.js deleted file mode 100644 index 5d25e8e..0000000 --- a/linux-casual/mp-int/index.js +++ /dev/null @@ -1,483 +0,0 @@ -const BITS = 8; -const INTMAX = (() => { - let ret = 0; - - for (let i = 0; i < BITS; i += 1) { - ret = (ret << 1) | 1 - } - - return ret; -})(); -const STATE_DELAY_DEFAULT = 250; -const ANIMATIONS_DEFAULT = 'state-change 0.5s ease-in 0s 1'; -let state_delay, animations; - -function myParseInt (str) { - let v, radix; - - if (str.startsWith("0b")) { - v = str.substring(2); - radix = 2; - } - else if (str.startsWith("0x")) { - v = str.substring(2); - radix = 16; - } - else if (str.startsWith("0")) { - v = str.substring(1); - radix = 1; - } - else { - v = str; - radix = 10; - } - - if (v === '') { - return 0; - } - - return parseInt(v, radix); -} - -function onOperandChange (val, span) { - if (val.trim() === '') { - span.style.opacity = 0; - } - else { - const n = myParseInt(val); - - if (!(n <= INTMAX)) { // NaN is also handled with this single conditional - span.style.opacity = 1; - } - else { - span.style.opacity = 0; - } - } -} - -function restartClassAnimation (element) { - const evtOpts = { "once": true }; - - // I fucking hate modern web development - - element.querySelectorAll('.state').forEach((element) => { - element.style.animation = ''; - }); - element.querySelectorAll('.state-op tspan').forEach((element) => { - element.style.animation = ''; - }); - element.querySelectorAll('.state').forEach((element) => { - element.style.animation = animations; - element.addEventListener('animationend', () => { - element.style.animation = ''; - }, evtOpts); - element.addEventListener('animationcancel', () => { - element.style.animation = ''; - }, evtOpts); - }); - element.querySelectorAll('.state-op tspan').forEach((element) => { - element.style.animation = animations; - element.addEventListener('animationend', () => { - element.style.animation = ''; - }, evtOpts); - element.addEventListener('animationcancel', () => { - element.style.animation = ''; - }, evtOpts); - }); -} - -class Renderer { - reset () {} - start (opr_a, opr_b, carry) {} -} -class MathRenderer extends Renderer {} -class AdderRenderer extends Renderer {} - -class State { - timer; - outputList = []; - - addOutput (output_f) { - this.outputList.push(output_f); - } - - clearTimer () { - if (this.timer) { - clearTimeout(this.timer); - } - } - - startTimer (v, ms) { - this.clearTimer(); - this.timer = setTimeout(() => { - this.outputList.forEach((output_f) => { - output_f(v) - }); - }, ms); - } - - detach () { - this.clearTimer(); - this.outputList = null; - } -} - -class Register extends State { - #elements; - #txts = []; - #bit = false; - #onclick = null; - - constructor (elements, clickable = true) { - super(); - const self = this; - - this.#elements = elements; - - this.#elements.forEach((e) => { - const t = e.querySelector('text tspan'); - - this.#txts.push(t); - t.innerHTML = '0'; - }); - - - if (clickable) { - this.#onclick = () => { - self.value = !self.value; - }; - - this.#elements.forEach((e) => { - e.style.cursor = 'pointer'; - e.addEventListener('click', this.#onclick); - }); - } - } - - get value () { - return this.#bit; - } - - set value (v_in) { - const v = !!v_in; - - if (this.#bit == v) { - return; - } - this.#bit = v; - - this.#elements.forEach((e) => { - restartClassAnimation(e); - }); - this.#txts.forEach((e) => { - if (v) { - e.innerHTML = '1'; - } - else { - e.innerHTML = '0'; - } - }); - - this.startTimer(v, state_delay); - } - - detach () { - super.detach(); - - if (this.#onclick) { - this.#elements.forEach((e) => { - e.removeEventListener('click', this.#onclick); - }); - - this.#onclick = null; - } - - this.#elements = null; - this.#txts = null; - } -} - -class Adder extends State { - #a = false; - #b = false; - #c = false; - - #update () { - this.startTimer(this.value, state_delay); - } - - set a (v_in) { - this.#a = !!v_in; - this.#update(); - } - - set b (v_in) { - this.#b = !!v_in; - this.#update(); - } - - set c (v_in) { - this.#c = !!v_in; - this.#update(); - } - - get value () { - let sum = 0; - - if (this.#a) { - sum += 1; - } - if (this.#b) { - sum += 1; - } - if (this.#c) { - sum += 1; - } - - return { - "a": this.#a, - "b": this.#b, - "ci": this.#c, - "co": (sum & 2) > 0, - "s": (sum & 1) > 0 - }; - } -} - -function forEachBit (n, nb_bits, f) { - let bit; - - for (let i = 0; i < nb_bits; i += 1) { - bit = n & 1; - f(bit > 0); - - n = n >> 1; - } -} - -function getLocalstorageData () { - const item = localStorage.getItem('animations'); - - if (item) { - return JSON.parse(item); - } - else { - return { - "state-delay": STATE_DELAY_DEFAULT, - "animations": ANIMATIONS_DEFAULT - }; - } -} - -function setLocalstorageData (obj) { - localStorage.setItem('animations', JSON.stringify(obj)); -} - -function clearLocalstorageData () { - localStorage.removeItem('animations'); -} - -function uploadLocalstorageData (elements) { - state_delay = elements["state-delay"].value; - animations = elements["animations"].value; - setLocalstorageData({ - "state-delay": elements["state-delay"].value, - "animations": elements["animations"].value - }); -} - -function downloadLocalstorageData (elements) { - const obj = getLocalstorageData(); - - state_delay = elements["state-delay"].value = obj["state-delay"]; - animations = elements["animations"].value = obj["animations"]; -} - -window.addEventListener('load', async () => { - const svg_math = document.getElementById("svg_the-math"); - const svg_adder = document.getElementById("svg_adder"); - const span_operand_a = document.getElementById("span_operand-a"); - const span_operand_b = document.getElementById("span_operand-b"); - const css_anim = await (await fetch('./anim.css')).text(); - - // inject animation - svg_math.contentDocument.getElementById('style1').innerHTML = css_anim; - svg_adder.contentDocument.getElementById('style1').innerHTML = css_anim; - - let stateList = []; - let adders; - let registerCarry; - let registerA; - let registerB; - let registerS; - let carryState; - - function doReset () { - stateList.forEach((s) => { - s.detach(); - }); - stateList = []; - adders = []; - registerCarry = []; - registerA = []; - registerB = []; - registerS = []; - carryState = null; - carry0 = null; - - // carryState - (() => { - const eMath = svg_math.contentDocument.getElementById('carry-ovf'); - const eAdder = svg_adder.contentDocument.getElementById('ovf'); - - carryState = new Register([ eMath, eAdder ]); - stateList.push(carryState); - })(); - - // registerS - for (let i = 0; i < BITS; i += 1) { - const eMath = svg_math.contentDocument.getElementById('result-' + i); - const eAdder = svg_adder.contentDocument.getElementById('8-bit-register-c-' + i); - const r = new Register([ eMath, eAdder ], false); - - stateList.push(r); - registerS.push(r); - } - - // registerCarry - for (let i = 1; i <= BITS - 1; i += 1) { - const eMath = svg_math.contentDocument.getElementById('carry-' + i); - const eAdder = svg_adder.contentDocument.getElementById('carry-' + (i - 1)); - const r = new Register([ eMath, eAdder ], false); - - stateList.push(r); - registerCarry.push(r); - } - registerCarry.push(carryState); - - // carry0 - const carry0element = svg_math.contentDocument.getElementById('carry-0'); - carry0 = new Register([ carry0element ]); - carry0.addOutput((v) => { - adders[0].c = v; - }); - stateList.push(carry0); - - // adders - for (let i = 0; i < BITS; i += 1) { - const a = new Adder(); - - a.addOutput((v) => { - registerS[i].value = v['s']; - registerCarry[i].value = v['co']; - }); - adders.push(a); - stateList.push(a); - } - for (let i = 1; i < BITS; i += 1) { - adders[i - 1].addOutput((v) => { - adders[i].c = v['co']; - }); - } - - // registerA - for (let i = 0; i < BITS; i += 1) { - const eMath = svg_math.contentDocument.getElementById('operand-a-' + i); - const eAdder = svg_adder.contentDocument.getElementById('8-bit-register-a-' + i); - const r = new Register([ eMath, eAdder ]); - - r.addOutput((v) => { - adders[i].a = v; - }); - stateList.push(r); - registerA.push(r); - } - - // registerB - for (let i = 0; i < BITS; i += 1) { - const eMath = svg_math.contentDocument.getElementById('operand-b-' + i); - const eAdder = svg_adder.contentDocument.getElementById('8-bit-register-b-' + i); - const r = new Register([ eMath, eAdder ]); - - r.addOutput((v) => { - adders[i].b = v; - }); - stateList.push(r); - registerB.push(r); - } - } - - doReset(); - - const txt_operand_a = document.getElementById("txt_operand-a"); - const txt_operand_b = document.getElementById("txt_operand-b"); - const radio_op_add = document.getElementById("radio_op-add"); - const radio_op_adc = document.getElementById("radio_op-adc"); - const txt_state_animations = document.getElementById("txt_state-animations"); - const txt_state_change_delay = document.getElementById("txt_state-change-delay"); - const btn_animation_defaults = document.getElementById("btn_animation-defaults"); - - document.getElementById("btn_exec").addEventListener('click', () => { - const a = myParseInt(txt_operand_a.value); - const b = myParseInt(txt_operand_b.value); - let c; - - if (isNaN(a) || isNaN(b)) { - return; - } - let i; - - function setRegisters () { - i = 0; - forEachBit(a, BITS, (v) => { - registerA[i].value = v; - i += 1; - }); - i = 0; - forEachBit(b, BITS, (v) => { - registerB[i].value = v; - i += 1; - }); - } - - if (radio_op_add.checked) { - setRegisters(); - c = (a + b) & INTMAX; - } - else if (radio_op_adc.checked) { - carry0.value = carryState.value; - setRegisters(); - c = (a + b + (carryState.value ? 1 : 0)) & INTMAX; - } - - txt_operand_a.value = c; - }); - - document.getElementById("btn_reset").addEventListener('click', () => { - doReset(); - }); - - txt_operand_a.addEventListener('change', (evt) => { - onOperandChange(evt.target.value, span_operand_a); - }); - txt_operand_b.addEventListener('change', (evt) => { - onOperandChange(evt.target.value, span_operand_b); - }); - - const animations_conf_elements = { - "animations": txt_state_animations, - "state-delay": txt_state_change_delay - }; - downloadLocalstorageData(animations_conf_elements); - - txt_state_animations.addEventListener('change', () => { - uploadLocalstorageData(animations_conf_elements); - }); - txt_state_change_delay.addEventListener('change', () => { - uploadLocalstorageData(animations_conf_elements); - }); - btn_animation_defaults.addEventListener('click', () => { - clearLocalstorageData(); - downloadLocalstorageData(animations_conf_elements); - }); -}); |