From 79b304eb5e9f29905cdbe283c386c513958d32bd Mon Sep 17 00:00:00 2001 From: Vanilla Date: Wed, 29 Jan 2025 16:04:11 +0300 Subject: [PATCH] initial commit --- lab1/add.js | 72 ++++++++ lab1/add/10B.js | 143 +++++++++++++++ lab1/add/16B.js | 317 ++++++++++++++++++++++++++++++++++ lab1/add/2B.js | 23 +++ lab1/add/8B.js | 102 +++++++++++ lab1/alloc.js | 106 ++++++++++++ lab1/convert.js | 403 +++++++++++++++++++++++++++++++++++++++++++ lab1/convert.test.js | 34 ++++ lab1/demo.js | 41 +++++ lab1/index.js | 4 + lab1/math.test.js | 27 +++ lab1/neg.js | 102 +++++++++++ lab1/not.js | 137 +++++++++++++++ lab1/num.js | 195 +++++++++++++++++++++ lab1/package.json | 3 + lab1/parse.js | 141 +++++++++++++++ lab1/string.js | 65 +++++++ lab1/string/10B.js | 20 +++ lab1/string/16B.js | 26 +++ lab1/string/2B.js | 12 ++ lab1/string/8B.js | 19 ++ lab1/sub.js | 15 ++ lab1/symbol/S10.js | 10 ++ lab1/symbol/S16.js | 16 ++ lab1/symbol/S2.js | 2 + lab1/symbol/S8.js | 8 + lab1/utils.js | 7 + lab2/index.js | 362 ++++++++++++++++++++++++++++++++++++++ lab2/test.js | 261 ++++++++++++++++++++++++++++ lab2/utilities.js | 9 + 30 files changed, 2682 insertions(+) create mode 100644 lab1/add.js create mode 100644 lab1/add/10B.js create mode 100644 lab1/add/16B.js create mode 100644 lab1/add/2B.js create mode 100644 lab1/add/8B.js create mode 100644 lab1/alloc.js create mode 100644 lab1/convert.js create mode 100644 lab1/convert.test.js create mode 100644 lab1/demo.js create mode 100644 lab1/index.js create mode 100644 lab1/math.test.js create mode 100644 lab1/neg.js create mode 100644 lab1/not.js create mode 100644 lab1/num.js create mode 100644 lab1/package.json create mode 100644 lab1/parse.js create mode 100644 lab1/string.js create mode 100644 lab1/string/10B.js create mode 100644 lab1/string/16B.js create mode 100644 lab1/string/2B.js create mode 100644 lab1/string/8B.js create mode 100644 lab1/sub.js create mode 100644 lab1/symbol/S10.js create mode 100644 lab1/symbol/S16.js create mode 100644 lab1/symbol/S2.js create mode 100644 lab1/symbol/S8.js create mode 100644 lab1/utils.js create mode 100644 lab2/index.js create mode 100644 lab2/test.js create mode 100644 lab2/utilities.js diff --git a/lab1/add.js b/lab1/add.js new file mode 100644 index 0000000..fb31be0 --- /dev/null +++ b/lab1/add.js @@ -0,0 +1,72 @@ +/** + * @import { Num } from "./num.js" + */ +import { kBuffer } from "./num.js"; +import { add16B } from "./add/16B.js" +import { add8B } from "./add/8B.js"; +import { add2B } from "./add/2B.js"; +import { add10B } from "./add/10B.js"; +import { size16, size8, size2, size10 } from "./alloc.js" + +/** + * @param { Num } a + * @param { Num } b + */ +export function add16(a, b) { + let carry = false; + const { [kBuffer]: b1 } = a; + const { [kBuffer]: b2 } = b; + + for (let i = 0; i < size16; i++) ([b1[i], carry] = add16B(b1[i], b2[i], carry)); +} + +/** + * @param { Num } a + * @param { Num } b + */ +export function add8(a, b) { + let carry = false; + const { [kBuffer]: b1 } = a; + const { [kBuffer]: b2 } = b; + + for (let i = 0; i < size8; i++) ([b1[i], carry] = add8B(b1[i], b2[i], carry)); +} + +/** + * @param { Num } a + * @param { Num } b + */ +export function add2(a, b) { + let carry = false; + const { [kBuffer]: b1 } = a; + const { [kBuffer]: b2 } = b; + + for (let i = 0; i < size2; i++) ([b1[i], carry] = add2B(b1[i], b2[i], carry)); +} + +/** + * @param { Num } a + * @param { Num } b + */ +export function add10(a, b) { + let carry = false; + const { [kBuffer]: b1 } = a; + const { [kBuffer]: b2 } = b; + + for (let i = 0; i < size10; i++) ([b1[i], carry] = add10B(b1[i], b2[i], carry)); +} + +/** + * @param { Num } a + * @param { Num } b + */ +export function add(a, b) { + if (a.radix !== b.radix) throw new Error(`numbers must have same radix`); + switch (a.radix) { + case 2: return add2(a, b); + case 8: return add8(a, b); + case 16: return add16(a, b); + case 10: return add10(a, b); + default: throw new Error(`unsupported radix (${a.radix})`); + } +} \ No newline at end of file diff --git a/lab1/add/10B.js b/lab1/add/10B.js new file mode 100644 index 0000000..8bf8c66 --- /dev/null +++ b/lab1/add/10B.js @@ -0,0 +1,143 @@ +import { S10_0, S10_1, S10_2, S10_3, S10_4, S10_5, S10_6, S10_7, S10_8, S10_9 } from "../symbol/S10.js" + +/** + * @param { symbol } a + * @param { symbol } b + * @param { boolean } carry + * @returns { [value: symbol, carry: boolean] } + */ +export function add10B(a, b, carry) { + switch (a) { + case S10_0: switch (b) { + case S10_0: return carry ? [S10_1, false] : [S10_0, false]; + case S10_1: return carry ? [S10_2, false] : [S10_1, false]; + case S10_2: return carry ? [S10_3, false] : [S10_2, false]; + case S10_3: return carry ? [S10_4, false] : [S10_3, false]; + case S10_4: return carry ? [S10_5, false] : [S10_4, false]; + case S10_5: return carry ? [S10_6, false] : [S10_5, false]; + case S10_6: return carry ? [S10_7, false] : [S10_6, false]; + case S10_7: return carry ? [S10_8, false] : [S10_7, false]; + case S10_8: return carry ? [S10_9, false] : [S10_8, false]; + case S10_9: return carry ? [S10_0, true ] : [S10_9, false]; + default: throw new Error("unexpected symbol"); + } + case S10_1: switch (b) { + case S10_0: return carry ? [S10_2, false] : [S10_1, false]; + case S10_1: return carry ? [S10_3, false] : [S10_2, false]; + case S10_2: return carry ? [S10_4, false] : [S10_3, false]; + case S10_3: return carry ? [S10_5, false] : [S10_4, false]; + case S10_4: return carry ? [S10_6, false] : [S10_5, false]; + case S10_5: return carry ? [S10_7, false] : [S10_6, false]; + case S10_6: return carry ? [S10_8, false] : [S10_7, false]; + case S10_7: return carry ? [S10_9, false] : [S10_8, false]; + case S10_8: return carry ? [S10_0, true ] : [S10_9, false]; + case S10_9: return carry ? [S10_1, true ] : [S10_0, true ]; + default: throw new Error("unexpected symbol"); + } + case S10_2: switch (b) { + case S10_0: return carry ? [S10_3, false] : [S10_2, false]; + case S10_1: return carry ? [S10_4, false] : [S10_3, false]; + case S10_2: return carry ? [S10_5, false] : [S10_4, false]; + case S10_3: return carry ? [S10_6, false] : [S10_5, false]; + case S10_4: return carry ? [S10_7, false] : [S10_6, false]; + case S10_5: return carry ? [S10_8, false] : [S10_7, false]; + case S10_6: return carry ? [S10_9, false] : [S10_8, false]; + case S10_7: return carry ? [S10_0, true ] : [S10_9, false]; + case S10_8: return carry ? [S10_1, true ] : [S10_0, true ]; + case S10_9: return carry ? [S10_2, true ] : [S10_1, true ]; + default: throw new Error("unexpected symbol"); + } + case S10_3: switch (b) { + case S10_0: return carry ? [S10_4, false] : [S10_3, false]; + case S10_1: return carry ? [S10_5, false] : [S10_4, false]; + case S10_2: return carry ? [S10_6, false] : [S10_5, false]; + case S10_3: return carry ? [S10_7, false] : [S10_6, false]; + case S10_4: return carry ? [S10_8, false] : [S10_7, false]; + case S10_5: return carry ? [S10_9, false] : [S10_8, false]; + case S10_6: return carry ? [S10_0, true ] : [S10_9, false]; + case S10_7: return carry ? [S10_1, true ] : [S10_0, true ]; + case S10_8: return carry ? [S10_2, true ] : [S10_1, true ]; + case S10_9: return carry ? [S10_3, true ] : [S10_2, true ]; + default: throw new Error("unexpected symbol"); + } + case S10_4: switch (b) { + case S10_0: return carry ? [S10_5, false] : [S10_4, false]; + case S10_1: return carry ? [S10_6, false] : [S10_5, false]; + case S10_2: return carry ? [S10_7, false] : [S10_6, false]; + case S10_3: return carry ? [S10_8, false] : [S10_7, false]; + case S10_4: return carry ? [S10_9, false] : [S10_8, false]; + case S10_5: return carry ? [S10_0, true ] : [S10_9, false]; + case S10_6: return carry ? [S10_1, true ] : [S10_0, true ]; + case S10_7: return carry ? [S10_2, true ] : [S10_1, true ]; + case S10_8: return carry ? [S10_3, true ] : [S10_2, true ]; + case S10_9: return carry ? [S10_4, true ] : [S10_3, true ]; + default: throw new Error("unexpected symbol"); + } + case S10_5: switch (b) { + case S10_0: return carry ? [S10_6, false] : [S10_5, false]; + case S10_1: return carry ? [S10_7, false] : [S10_6, false]; + case S10_2: return carry ? [S10_8, false] : [S10_7, false]; + case S10_3: return carry ? [S10_9, false] : [S10_8, false]; + case S10_4: return carry ? [S10_0, true ] : [S10_9, false]; + case S10_5: return carry ? [S10_1, true ] : [S10_0, true ]; + case S10_6: return carry ? [S10_2, true ] : [S10_1, true ]; + case S10_7: return carry ? [S10_3, true ] : [S10_2, true ]; + case S10_8: return carry ? [S10_4, true ] : [S10_3, true ]; + case S10_9: return carry ? [S10_5, true ] : [S10_4, true ]; + default: throw new Error("unexpected symbol"); + } + case S10_6: switch (b) { + case S10_0: return carry ? [S10_7, false] : [S10_6, false]; + case S10_1: return carry ? [S10_8, false] : [S10_7, false]; + case S10_2: return carry ? [S10_9, false] : [S10_8, false]; + case S10_3: return carry ? [S10_0, true ] : [S10_9, false]; + case S10_4: return carry ? [S10_1, true ] : [S10_0, true ]; + case S10_5: return carry ? [S10_2, true ] : [S10_1, true ]; + case S10_6: return carry ? [S10_3, true ] : [S10_2, true ]; + case S10_7: return carry ? [S10_4, true ] : [S10_3, true ]; + case S10_8: return carry ? [S10_5, true ] : [S10_4, true ]; + case S10_9: return carry ? [S10_6, true ] : [S10_5, true ]; + default: throw new Error("unexpected symbol"); + } + case S10_7: switch (b) { + case S10_0: return carry ? [S10_8, false] : [S10_7, false]; + case S10_1: return carry ? [S10_9, false] : [S10_8, false]; + case S10_2: return carry ? [S10_0, true ] : [S10_9, false]; + case S10_3: return carry ? [S10_1, true ] : [S10_0, true ]; + case S10_4: return carry ? [S10_2, true ] : [S10_1, true ]; + case S10_5: return carry ? [S10_3, true ] : [S10_2, true ]; + case S10_6: return carry ? [S10_4, true ] : [S10_3, true ]; + case S10_7: return carry ? [S10_5, true ] : [S10_4, true ]; + case S10_8: return carry ? [S10_6, true ] : [S10_5, true ]; + case S10_9: return carry ? [S10_7, true ] : [S10_6, true ]; + default: throw new Error("unexpected symbol"); + } + case S10_8: switch (b) { + case S10_0: return carry ? [S10_9, false] : [S10_8, false]; + case S10_1: return carry ? [S10_0, true ] : [S10_9, false]; + case S10_2: return carry ? [S10_1, true ] : [S10_0, true ]; + case S10_3: return carry ? [S10_2, true ] : [S10_1, true ]; + case S10_4: return carry ? [S10_3, true ] : [S10_2, true ]; + case S10_5: return carry ? [S10_4, true ] : [S10_3, true ]; + case S10_6: return carry ? [S10_5, true ] : [S10_4, true ]; + case S10_7: return carry ? [S10_6, true ] : [S10_5, true ]; + case S10_8: return carry ? [S10_7, true ] : [S10_6, true ]; + case S10_9: return carry ? [S10_8, true ] : [S10_7, true ]; + default: throw new Error("unexpected symbol"); + } + case S10_9: switch (b) { + case S10_0: return carry ? [S10_0, true ] : [S10_9, false]; + case S10_1: return carry ? [S10_1, true ] : [S10_0, true ]; + case S10_2: return carry ? [S10_2, true ] : [S10_1, true ]; + case S10_3: return carry ? [S10_3, true ] : [S10_2, true ]; + case S10_4: return carry ? [S10_4, true ] : [S10_3, true ]; + case S10_5: return carry ? [S10_5, true ] : [S10_4, true ]; + case S10_6: return carry ? [S10_6, true ] : [S10_5, true ]; + case S10_7: return carry ? [S10_7, true ] : [S10_6, true ]; + case S10_8: return carry ? [S10_8, true ] : [S10_7, true ]; + case S10_9: return carry ? [S10_9, true ] : [S10_8, true ]; + default: throw new Error("unexpected symbol"); + } + default: throw new Error("unexpected symbol"); + } +} \ No newline at end of file diff --git a/lab1/add/16B.js b/lab1/add/16B.js new file mode 100644 index 0000000..9171a32 --- /dev/null +++ b/lab1/add/16B.js @@ -0,0 +1,317 @@ +import { S16_0, S16_1, S16_2, S16_3, S16_4, S16_5, S16_6, S16_7, S16_8, S16_9, S16_A, S16_B, S16_C, S16_D, S16_E, S16_F } from "../symbol/S16.js" + +/** + * @param { symbol } a + * @param { symbol } b + * @param { boolean } carry + * @returns { [value: symbol, carry: boolean] } + */ +export function add16B(a, b, carry) { + switch (a) { + case S16_0: switch (b) { + case S16_0: return carry ? [S16_1, false] : [S16_0, false]; + case S16_1: return carry ? [S16_2, false] : [S16_1, false]; + case S16_2: return carry ? [S16_3, false] : [S16_2, false]; + case S16_3: return carry ? [S16_4, false] : [S16_3, false]; + case S16_4: return carry ? [S16_5, false] : [S16_4, false]; + case S16_5: return carry ? [S16_6, false] : [S16_5, false]; + case S16_6: return carry ? [S16_7, false] : [S16_6, false]; + case S16_7: return carry ? [S16_8, false] : [S16_7, false]; + case S16_8: return carry ? [S16_9, false] : [S16_8, false]; + case S16_9: return carry ? [S16_A, false] : [S16_9, false]; + case S16_A: return carry ? [S16_B, false] : [S16_A, false]; + case S16_B: return carry ? [S16_C, false] : [S16_B, false]; + case S16_C: return carry ? [S16_D, false] : [S16_C, false]; + case S16_D: return carry ? [S16_E, false] : [S16_D, false]; + case S16_E: return carry ? [S16_F, false] : [S16_E, false]; + case S16_F: return carry ? [S16_0, true ] : [S16_F, false]; + default: throw new Error("unexpected symbol"); + } + case S16_1: switch (b) { + case S16_0: return carry ? [S16_2, false] : [S16_1, false]; + case S16_1: return carry ? [S16_3, false] : [S16_2, false]; + case S16_2: return carry ? [S16_4, false] : [S16_3, false]; + case S16_3: return carry ? [S16_5, false] : [S16_4, false]; + case S16_4: return carry ? [S16_6, false] : [S16_5, false]; + case S16_5: return carry ? [S16_7, false] : [S16_6, false]; + case S16_6: return carry ? [S16_8, false] : [S16_7, false]; + case S16_7: return carry ? [S16_9, false] : [S16_8, false]; + case S16_8: return carry ? [S16_A, false] : [S16_9, false]; + case S16_9: return carry ? [S16_B, false] : [S16_A, false]; + case S16_A: return carry ? [S16_C, false] : [S16_B, false]; + case S16_B: return carry ? [S16_D, false] : [S16_C, false]; + case S16_C: return carry ? [S16_E, false] : [S16_D, false]; + case S16_D: return carry ? [S16_F, false] : [S16_E, false]; + case S16_E: return carry ? [S16_0, true ] : [S16_F, false]; + case S16_F: return carry ? [S16_1, true ] : [S16_0, true ]; + default: throw new Error("unexpected symbol"); + } + case S16_2: switch (b) { + case S16_0: return carry ? [S16_3, false] : [S16_2, false]; + case S16_1: return carry ? [S16_4, false] : [S16_3, false]; + case S16_2: return carry ? [S16_5, false] : [S16_4, false]; + case S16_3: return carry ? [S16_6, false] : [S16_5, false]; + case S16_4: return carry ? [S16_7, false] : [S16_6, false]; + case S16_5: return carry ? [S16_8, false] : [S16_7, false]; + case S16_6: return carry ? [S16_9, false] : [S16_8, false]; + case S16_7: return carry ? [S16_A, false] : [S16_9, false]; + case S16_8: return carry ? [S16_B, false] : [S16_A, false]; + case S16_9: return carry ? [S16_C, false] : [S16_B, false]; + case S16_A: return carry ? [S16_D, false] : [S16_C, false]; + case S16_B: return carry ? [S16_E, false] : [S16_D, false]; + case S16_C: return carry ? [S16_F, false] : [S16_E, false]; + case S16_D: return carry ? [S16_0, true ] : [S16_F, false]; + case S16_E: return carry ? [S16_1, true ] : [S16_0, true ]; + case S16_F: return carry ? [S16_2, true ] : [S16_1, true ]; + default: throw new Error("unexpected symbol"); + } + case S16_3: switch (b) { + case S16_0: return carry ? [S16_4, false] : [S16_3, false]; + case S16_1: return carry ? [S16_5, false] : [S16_4, false]; + case S16_2: return carry ? [S16_6, false] : [S16_5, false]; + case S16_3: return carry ? [S16_7, false] : [S16_6, false]; + case S16_4: return carry ? [S16_8, false] : [S16_7, false]; + case S16_5: return carry ? [S16_9, false] : [S16_8, false]; + case S16_6: return carry ? [S16_A, false] : [S16_9, false]; + case S16_7: return carry ? [S16_B, false] : [S16_A, false]; + case S16_8: return carry ? [S16_C, false] : [S16_B, false]; + case S16_9: return carry ? [S16_D, false] : [S16_C, false]; + case S16_A: return carry ? [S16_E, false] : [S16_D, false]; + case S16_B: return carry ? [S16_F, false] : [S16_E, false]; + case S16_C: return carry ? [S16_0, true ] : [S16_F, false]; + case S16_D: return carry ? [S16_1, true ] : [S16_0, true ]; + case S16_E: return carry ? [S16_2, true ] : [S16_1, true ]; + case S16_F: return carry ? [S16_3, true ] : [S16_2, true ]; + default: throw new Error("unexpected symbol"); + } + case S16_4: switch (b) { + case S16_0: return carry ? [S16_5, false] : [S16_4, false]; + case S16_1: return carry ? [S16_6, false] : [S16_5, false]; + case S16_2: return carry ? [S16_7, false] : [S16_6, false]; + case S16_3: return carry ? [S16_8, false] : [S16_7, false]; + case S16_4: return carry ? [S16_9, false] : [S16_8, false]; + case S16_5: return carry ? [S16_A, false] : [S16_9, false]; + case S16_6: return carry ? [S16_B, false] : [S16_A, false]; + case S16_7: return carry ? [S16_C, false] : [S16_B, false]; + case S16_8: return carry ? [S16_D, false] : [S16_C, false]; + case S16_9: return carry ? [S16_E, false] : [S16_D, false]; + case S16_A: return carry ? [S16_F, false] : [S16_E, false]; + case S16_B: return carry ? [S16_0, true ] : [S16_F, false]; + case S16_C: return carry ? [S16_1, true ] : [S16_0, true ]; + case S16_D: return carry ? [S16_2, true ] : [S16_1, true ]; + case S16_E: return carry ? [S16_3, true ] : [S16_2, true ]; + case S16_F: return carry ? [S16_4, true ] : [S16_3, true ]; + default: throw new Error("unexpected symbol"); + } + case S16_5: switch (b) { + case S16_0: return carry ? [S16_6, false] : [S16_5, false]; + case S16_1: return carry ? [S16_7, false] : [S16_6, false]; + case S16_2: return carry ? [S16_8, false] : [S16_7, false]; + case S16_3: return carry ? [S16_9, false] : [S16_8, false]; + case S16_4: return carry ? [S16_A, false] : [S16_9, false]; + case S16_5: return carry ? [S16_B, false] : [S16_A, false]; + case S16_6: return carry ? [S16_C, false] : [S16_B, false]; + case S16_7: return carry ? [S16_D, false] : [S16_C, false]; + case S16_8: return carry ? [S16_E, false] : [S16_D, false]; + case S16_9: return carry ? [S16_F, false] : [S16_E, false]; + case S16_A: return carry ? [S16_0, true ] : [S16_F, false]; + case S16_B: return carry ? [S16_1, true ] : [S16_0, true ]; + case S16_C: return carry ? [S16_2, true ] : [S16_1, true ]; + case S16_D: return carry ? [S16_3, true ] : [S16_2, true ]; + case S16_E: return carry ? [S16_4, true ] : [S16_3, true ]; + case S16_F: return carry ? [S16_5, true ] : [S16_4, true ]; + default: throw new Error("unexpected symbol"); + } + case S16_6: switch (b) { + case S16_0: return carry ? [S16_7, false] : [S16_6, false]; + case S16_1: return carry ? [S16_8, false] : [S16_7, false]; + case S16_2: return carry ? [S16_9, false] : [S16_8, false]; + case S16_3: return carry ? [S16_A, false] : [S16_9, false]; + case S16_4: return carry ? [S16_B, false] : [S16_A, false]; + case S16_5: return carry ? [S16_C, false] : [S16_B, false]; + case S16_6: return carry ? [S16_D, false] : [S16_C, false]; + case S16_7: return carry ? [S16_E, false] : [S16_D, false]; + case S16_8: return carry ? [S16_F, false] : [S16_E, false]; + case S16_9: return carry ? [S16_0, true ] : [S16_F, false]; + case S16_A: return carry ? [S16_1, true ] : [S16_0, true ]; + case S16_B: return carry ? [S16_2, true ] : [S16_1, true ]; + case S16_C: return carry ? [S16_3, true ] : [S16_2, true ]; + case S16_D: return carry ? [S16_4, true ] : [S16_3, true ]; + case S16_E: return carry ? [S16_5, true ] : [S16_4, true ]; + case S16_F: return carry ? [S16_6, true ] : [S16_5, true ]; + default: throw new Error("unexpected symbol"); + } + case S16_7: switch (b) { + case S16_0: return carry ? [S16_8, false] : [S16_7, false]; + case S16_1: return carry ? [S16_9, false] : [S16_8, false]; + case S16_2: return carry ? [S16_A, false] : [S16_9, false]; + case S16_3: return carry ? [S16_B, false] : [S16_A, false]; + case S16_4: return carry ? [S16_C, false] : [S16_B, false]; + case S16_5: return carry ? [S16_D, false] : [S16_C, false]; + case S16_6: return carry ? [S16_E, false] : [S16_D, false]; + case S16_7: return carry ? [S16_F, false] : [S16_E, false]; + case S16_8: return carry ? [S16_0, true ] : [S16_F, false]; + case S16_9: return carry ? [S16_1, true ] : [S16_0, true ]; + case S16_A: return carry ? [S16_2, true ] : [S16_1, true ]; + case S16_B: return carry ? [S16_3, true ] : [S16_2, true ]; + case S16_C: return carry ? [S16_4, true ] : [S16_3, true ]; + case S16_D: return carry ? [S16_5, true ] : [S16_4, true ]; + case S16_E: return carry ? [S16_6, true ] : [S16_5, true ]; + case S16_F: return carry ? [S16_7, true ] : [S16_6, true ]; + default: throw new Error("unexpected symbol"); + } + case S16_8: switch (b) { + case S16_0: return carry ? [S16_9, false] : [S16_8, false]; + case S16_1: return carry ? [S16_A, false] : [S16_9, false]; + case S16_2: return carry ? [S16_B, false] : [S16_A, false]; + case S16_3: return carry ? [S16_C, false] : [S16_B, false]; + case S16_4: return carry ? [S16_D, false] : [S16_C, false]; + case S16_5: return carry ? [S16_E, false] : [S16_D, false]; + case S16_6: return carry ? [S16_F, false] : [S16_E, false]; + case S16_7: return carry ? [S16_0, true ] : [S16_F, false]; + case S16_8: return carry ? [S16_1, true ] : [S16_0, true ]; + case S16_9: return carry ? [S16_2, true ] : [S16_1, true ]; + case S16_A: return carry ? [S16_3, true ] : [S16_2, true ]; + case S16_B: return carry ? [S16_4, true ] : [S16_3, true ]; + case S16_C: return carry ? [S16_5, true ] : [S16_4, true ]; + case S16_D: return carry ? [S16_6, true ] : [S16_5, true ]; + case S16_E: return carry ? [S16_7, true ] : [S16_6, true ]; + case S16_F: return carry ? [S16_8, true ] : [S16_7, true ]; + default: throw new Error("unexpected symbol"); + } + case S16_9: switch (b) { + case S16_0: return carry ? [S16_A, false] : [S16_9, false]; + case S16_1: return carry ? [S16_B, false] : [S16_A, false]; + case S16_2: return carry ? [S16_C, false] : [S16_B, false]; + case S16_3: return carry ? [S16_D, false] : [S16_C, false]; + case S16_4: return carry ? [S16_E, false] : [S16_D, false]; + case S16_5: return carry ? [S16_F, false] : [S16_E, false]; + case S16_6: return carry ? [S16_0, true ] : [S16_F, false]; + case S16_7: return carry ? [S16_1, true ] : [S16_0, true ]; + case S16_8: return carry ? [S16_2, true ] : [S16_1, true ]; + case S16_9: return carry ? [S16_3, true ] : [S16_2, true ]; + case S16_A: return carry ? [S16_4, true ] : [S16_3, true ]; + case S16_B: return carry ? [S16_5, true ] : [S16_4, true ]; + case S16_C: return carry ? [S16_6, true ] : [S16_5, true ]; + case S16_D: return carry ? [S16_7, true ] : [S16_6, true ]; + case S16_E: return carry ? [S16_8, true ] : [S16_7, true ]; + case S16_F: return carry ? [S16_9, true ] : [S16_8, true ]; + default: throw new Error("unexpected symbol"); + } + case S16_A: switch (b) { + case S16_0: return carry ? [S16_B, false] : [S16_A, false]; + case S16_1: return carry ? [S16_C, false] : [S16_B, false]; + case S16_2: return carry ? [S16_D, false] : [S16_C, false]; + case S16_3: return carry ? [S16_E, false] : [S16_D, false]; + case S16_4: return carry ? [S16_F, false] : [S16_E, false]; + case S16_5: return carry ? [S16_0, true ] : [S16_F, false]; + case S16_6: return carry ? [S16_1, true ] : [S16_0, true ]; + case S16_7: return carry ? [S16_2, true ] : [S16_1, true ]; + case S16_8: return carry ? [S16_3, true ] : [S16_2, true ]; + case S16_9: return carry ? [S16_4, true ] : [S16_3, true ]; + case S16_A: return carry ? [S16_5, true ] : [S16_4, true ]; + case S16_B: return carry ? [S16_6, true ] : [S16_5, true ]; + case S16_C: return carry ? [S16_7, true ] : [S16_6, true ]; + case S16_D: return carry ? [S16_8, true ] : [S16_7, true ]; + case S16_E: return carry ? [S16_9, true ] : [S16_8, true ]; + case S16_F: return carry ? [S16_A, true ] : [S16_9, true ]; + default: throw new Error("unexpected symbol"); + } + case S16_B: switch (b) { + case S16_0: return carry ? [S16_C, false] : [S16_B, false]; + case S16_1: return carry ? [S16_D, false] : [S16_C, false]; + case S16_2: return carry ? [S16_E, false] : [S16_D, false]; + case S16_3: return carry ? [S16_F, false] : [S16_E, false]; + case S16_4: return carry ? [S16_0, true ] : [S16_F, false]; + case S16_5: return carry ? [S16_1, true ] : [S16_0, true ]; + case S16_6: return carry ? [S16_2, true ] : [S16_1, true ]; + case S16_7: return carry ? [S16_3, true ] : [S16_2, true ]; + case S16_8: return carry ? [S16_4, true ] : [S16_3, true ]; + case S16_9: return carry ? [S16_5, true ] : [S16_4, true ]; + case S16_A: return carry ? [S16_6, true ] : [S16_5, true ]; + case S16_B: return carry ? [S16_7, true ] : [S16_6, true ]; + case S16_C: return carry ? [S16_8, true ] : [S16_7, true ]; + case S16_D: return carry ? [S16_9, true ] : [S16_8, true ]; + case S16_E: return carry ? [S16_A, true ] : [S16_9, true ]; + case S16_F: return carry ? [S16_B, true ] : [S16_A, true ]; + default: throw new Error("unexpected symbol"); + } + case S16_C: switch (b) { + case S16_0: return carry ? [S16_D, false] : [S16_C, false]; + case S16_1: return carry ? [S16_E, false] : [S16_D, false]; + case S16_2: return carry ? [S16_F, false] : [S16_E, false]; + case S16_3: return carry ? [S16_0, true ] : [S16_F, false]; + case S16_4: return carry ? [S16_1, true ] : [S16_0, true ]; + case S16_5: return carry ? [S16_2, true ] : [S16_1, true ]; + case S16_6: return carry ? [S16_3, true ] : [S16_2, true ]; + case S16_7: return carry ? [S16_4, true ] : [S16_3, true ]; + case S16_8: return carry ? [S16_5, true ] : [S16_4, true ]; + case S16_9: return carry ? [S16_6, true ] : [S16_5, true ]; + case S16_A: return carry ? [S16_7, true ] : [S16_6, true ]; + case S16_B: return carry ? [S16_8, true ] : [S16_7, true ]; + case S16_C: return carry ? [S16_9, true ] : [S16_8, true ]; + case S16_D: return carry ? [S16_A, true ] : [S16_9, true ]; + case S16_E: return carry ? [S16_B, true ] : [S16_A, true ]; + case S16_F: return carry ? [S16_C, true ] : [S16_B, true ]; + default: throw new Error("unexpected symbol"); + } + case S16_D: switch (b) { + case S16_0: return carry ? [S16_E, false] : [S16_D, false]; + case S16_1: return carry ? [S16_F, false] : [S16_E, false]; + case S16_2: return carry ? [S16_0, true ] : [S16_F, false]; + case S16_3: return carry ? [S16_1, true ] : [S16_0, true ]; + case S16_4: return carry ? [S16_2, true ] : [S16_1, true ]; + case S16_5: return carry ? [S16_3, true ] : [S16_2, true ]; + case S16_6: return carry ? [S16_4, true ] : [S16_3, true ]; + case S16_7: return carry ? [S16_5, true ] : [S16_4, true ]; + case S16_8: return carry ? [S16_6, true ] : [S16_5, true ]; + case S16_9: return carry ? [S16_7, true ] : [S16_6, true ]; + case S16_A: return carry ? [S16_8, true ] : [S16_7, true ]; + case S16_B: return carry ? [S16_9, true ] : [S16_8, true ]; + case S16_C: return carry ? [S16_A, true ] : [S16_9, true ]; + case S16_D: return carry ? [S16_B, true ] : [S16_A, true ]; + case S16_E: return carry ? [S16_C, true ] : [S16_B, true ]; + case S16_F: return carry ? [S16_D, true ] : [S16_C, true ]; + default: throw new Error("unexpected symbol"); + } + case S16_E: switch (b) { + case S16_0: return carry ? [S16_F, false] : [S16_E, false]; + case S16_1: return carry ? [S16_0, true ] : [S16_F, false]; + case S16_2: return carry ? [S16_1, true ] : [S16_0, true ]; + case S16_3: return carry ? [S16_2, true ] : [S16_1, true ]; + case S16_4: return carry ? [S16_3, true ] : [S16_2, true ]; + case S16_5: return carry ? [S16_4, true ] : [S16_3, true ]; + case S16_6: return carry ? [S16_5, true ] : [S16_4, true ]; + case S16_7: return carry ? [S16_6, true ] : [S16_5, true ]; + case S16_8: return carry ? [S16_7, true ] : [S16_6, true ]; + case S16_9: return carry ? [S16_8, true ] : [S16_7, true ]; + case S16_A: return carry ? [S16_9, true ] : [S16_8, true ]; + case S16_B: return carry ? [S16_A, true ] : [S16_9, true ]; + case S16_C: return carry ? [S16_B, true ] : [S16_A, true ]; + case S16_D: return carry ? [S16_C, true ] : [S16_B, true ]; + case S16_E: return carry ? [S16_D, true ] : [S16_C, true ]; + case S16_F: return carry ? [S16_E, true ] : [S16_D, true ]; + default: throw new Error("unexpected symbol"); + } + case S16_F: switch (b) { + case S16_0: return carry ? [S16_0, true ] : [S16_F, false]; + case S16_1: return carry ? [S16_1, true ] : [S16_0, true ]; + case S16_2: return carry ? [S16_2, true ] : [S16_1, true ]; + case S16_3: return carry ? [S16_3, true ] : [S16_2, true ]; + case S16_4: return carry ? [S16_4, true ] : [S16_3, true ]; + case S16_5: return carry ? [S16_5, true ] : [S16_4, true ]; + case S16_6: return carry ? [S16_6, true ] : [S16_5, true ]; + case S16_7: return carry ? [S16_7, true ] : [S16_6, true ]; + case S16_8: return carry ? [S16_8, true ] : [S16_7, true ]; + case S16_9: return carry ? [S16_9, true ] : [S16_8, true ]; + case S16_A: return carry ? [S16_A, true ] : [S16_9, true ]; + case S16_B: return carry ? [S16_B, true ] : [S16_A, true ]; + case S16_C: return carry ? [S16_C, true ] : [S16_B, true ]; + case S16_D: return carry ? [S16_D, true ] : [S16_C, true ]; + case S16_E: return carry ? [S16_E, true ] : [S16_D, true ]; + case S16_F: return carry ? [S16_F, true ] : [S16_E, true ]; + default: throw new Error("unexpected symbol"); + } + default: throw new Error("unexpected symbol"); + } +} \ No newline at end of file diff --git a/lab1/add/2B.js b/lab1/add/2B.js new file mode 100644 index 0000000..4217a1a --- /dev/null +++ b/lab1/add/2B.js @@ -0,0 +1,23 @@ +import { S2_0, S2_1 } from "../symbol/S2.js" + +/** + * @param { symbol } a + * @param { symbol } b + * @param { boolean } carry + * @returns { [value: symbol, carry: boolean] } + */ +export function add2B(a, b, carry) { + switch (a) { + case S2_0: switch (b) { + case S2_0: return carry ? [S2_1, false] : [S2_0, false]; + case S2_1: return carry ? [S2_0, true ] : [S2_1, false]; + default: throw new Error("unexpected symbol"); + } + case S2_1: switch (b) { + case S2_0: return carry ? [S2_0, true] : [S2_1, false]; + case S2_1: return carry ? [S2_1, true] : [S2_0, true ]; + default: throw new Error("unexpected symbol"); + } + default: throw new Error("unexpected symbol"); + } +} \ No newline at end of file diff --git a/lab1/add/8B.js b/lab1/add/8B.js new file mode 100644 index 0000000..d7041c1 --- /dev/null +++ b/lab1/add/8B.js @@ -0,0 +1,102 @@ +import { S8_0, S8_1, S8_2, S8_3, S8_4, S8_5, S8_6, S8_7 } from "../symbol/S8.js" + +/** + * @param { symbol } a + * @param { symbol } b + * @param { boolean } carry + * @returns { [value: symbol, carry: boolean] } + */ +export function add8B(a, b, carry) { + switch (a) { + case S8_0: switch (b) { + case S8_0: return carry ? [S8_1, false] : [S8_0, false]; + case S8_1: return carry ? [S8_2, false] : [S8_1, false]; + case S8_2: return carry ? [S8_3, false] : [S8_2, false]; + case S8_3: return carry ? [S8_4, false] : [S8_3, false]; + case S8_4: return carry ? [S8_5, false] : [S8_4, false]; + case S8_5: return carry ? [S8_6, false] : [S8_5, false]; + case S8_6: return carry ? [S8_7, false] : [S8_6, false]; + case S8_7: return carry ? [S8_0, true ] : [S8_7, false]; + default: throw new Error("unexpected symbol"); + } + case S8_1: switch (b) { + case S8_0: return carry ? [S8_2, false] : [S8_1, false]; + case S8_1: return carry ? [S8_3, false] : [S8_2, false]; + case S8_2: return carry ? [S8_4, false] : [S8_3, false]; + case S8_3: return carry ? [S8_5, false] : [S8_4, false]; + case S8_4: return carry ? [S8_6, false] : [S8_5, false]; + case S8_5: return carry ? [S8_7, false] : [S8_6, false]; + case S8_6: return carry ? [S8_0, true ] : [S8_7, false]; + case S8_7: return carry ? [S8_1, true ] : [S8_0, true ]; + default: throw new Error("unexpected symbol"); + } + case S8_2: switch (b) { + case S8_0: return carry ? [S8_3, false] : [S8_2, false]; + case S8_1: return carry ? [S8_4, false] : [S8_3, false]; + case S8_2: return carry ? [S8_5, false] : [S8_4, false]; + case S8_3: return carry ? [S8_6, false] : [S8_5, false]; + case S8_4: return carry ? [S8_7, false] : [S8_6, false]; + case S8_5: return carry ? [S8_0, true ] : [S8_7, false]; + case S8_6: return carry ? [S8_1, true ] : [S8_0, true ]; + case S8_7: return carry ? [S8_2, true ] : [S8_1, true ]; + default: throw new Error("unexpected symbol"); + } + case S8_3: switch (b) { + case S8_0: return carry ? [S8_4, false] : [S8_3, false]; + case S8_1: return carry ? [S8_5, false] : [S8_4, false]; + case S8_2: return carry ? [S8_6, false] : [S8_5, false]; + case S8_3: return carry ? [S8_7, false] : [S8_6, false]; + case S8_4: return carry ? [S8_0, true ] : [S8_7, false]; + case S8_5: return carry ? [S8_1, true ] : [S8_0, true ]; + case S8_6: return carry ? [S8_2, true ] : [S8_1, true ]; + case S8_7: return carry ? [S8_3, true ] : [S8_2, true ]; + default: throw new Error("unexpected symbol"); + } + case S8_4: switch (b) { + case S8_0: return carry ? [S8_5, false] : [S8_4, false]; + case S8_1: return carry ? [S8_6, false] : [S8_5, false]; + case S8_2: return carry ? [S8_7, false] : [S8_6, false]; + case S8_3: return carry ? [S8_0, true ] : [S8_7, false]; + case S8_4: return carry ? [S8_1, true ] : [S8_0, true ]; + case S8_5: return carry ? [S8_2, true ] : [S8_1, true ]; + case S8_6: return carry ? [S8_3, true ] : [S8_2, true ]; + case S8_7: return carry ? [S8_4, true ] : [S8_3, true ]; + default: throw new Error("unexpected symbol"); + } + case S8_5: switch (b) { + case S8_0: return carry ? [S8_6, false] : [S8_5, false]; + case S8_1: return carry ? [S8_7, false] : [S8_6, false]; + case S8_2: return carry ? [S8_0, true ] : [S8_7, false]; + case S8_3: return carry ? [S8_1, true ] : [S8_0, true ]; + case S8_4: return carry ? [S8_2, true ] : [S8_1, true ]; + case S8_5: return carry ? [S8_3, true ] : [S8_2, true ]; + case S8_6: return carry ? [S8_4, true ] : [S8_3, true ]; + case S8_7: return carry ? [S8_5, true ] : [S8_4, true ]; + default: throw new Error("unexpected symbol"); + } + case S8_6: switch (b) { + case S8_0: return carry ? [S8_7, false] : [S8_6, false]; + case S8_1: return carry ? [S8_0, true ] : [S8_7, false]; + case S8_2: return carry ? [S8_1, true ] : [S8_0, true ]; + case S8_3: return carry ? [S8_2, true ] : [S8_1, true ]; + case S8_4: return carry ? [S8_3, true ] : [S8_2, true ]; + case S8_5: return carry ? [S8_4, true ] : [S8_3, true ]; + case S8_6: return carry ? [S8_5, true ] : [S8_4, true ]; + case S8_7: return carry ? [S8_6, true ] : [S8_5, true ]; + default: throw new Error("unexpected symbol"); + } + case S8_7: switch (b) { + case S8_0: return carry ? [S8_0, true ] : [S8_7, false]; + case S8_1: return carry ? [S8_1, true ] : [S8_0, true ]; + case S8_2: return carry ? [S8_2, true ] : [S8_1, true ]; + case S8_3: return carry ? [S8_3, true ] : [S8_2, true ]; + case S8_4: return carry ? [S8_4, true ] : [S8_3, true ]; + case S8_5: return carry ? [S8_5, true ] : [S8_4, true ]; + case S8_6: return carry ? [S8_6, true ] : [S8_5, true ]; + case S8_7: return carry ? [S8_7, true ] : [S8_6, true ]; + default: throw new Error("unexpected symbol"); + } + default: throw new Error("unexpected symbol"); + + } +} \ No newline at end of file diff --git a/lab1/alloc.js b/lab1/alloc.js new file mode 100644 index 0000000..637852d --- /dev/null +++ b/lab1/alloc.js @@ -0,0 +1,106 @@ +/** + * @import { Radix } from "./num.js" + */ +import { S16_0 } from "./symbol/S16.js" +import { S8_0 } from "./symbol/S8.js" +import { S2_0 } from "./symbol/S2.js" +import { S10_0 } from "./symbol/S10.js" + +function alloc16() { + return [ + S16_0, + S16_0, + S16_0, + S16_0, + S16_0, + S16_0, + S16_0, + S16_0 + ] +} +export const size16 = 8; + +function alloc8() { + return [ + S8_0, + S8_0, + S8_0, + S8_0, + S8_0, + S8_0, + S8_0, + S8_0, + S8_0, + S8_0, + S8_0 + ] +} +export const size8 = 11; + +function alloc2() { + return [ + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0, + S2_0 + ] +} +export const size2 = 32; + +function alloc10() { + return [ + S10_0, + S10_0, + S10_0, + S10_0, + S10_0, + S10_0, + S10_0, + S10_0, + S10_0, + S10_0 + ] +} +export const size10 = 10; +export const last10 = size10 - 1; + +/** + * @param { Radix } radix + */ +export function alloc(radix) { + switch (radix) { + case 2: return alloc2(); + case 8: return alloc8(); + case 16: return alloc16(); + case 10: return alloc10(); + default: throw new Error(`unsupported radix (${radix})`); + } +} \ No newline at end of file diff --git a/lab1/convert.js b/lab1/convert.js new file mode 100644 index 0000000..bc0f93f --- /dev/null +++ b/lab1/convert.js @@ -0,0 +1,403 @@ +import { Num, dec2p0neg, dec2p1neg, dec2p2neg, dec2p3neg, dec2p4neg, dec2p5neg, dec2p6neg, dec2p7neg, dec2p8neg, dec2p9neg, dec2p10neg, dec2p11neg, dec2p12neg, dec2p13neg, dec2p14neg, dec2p15neg, dec2p16neg, dec2p17neg, dec2p18neg, dec2p19neg, dec2p20neg, dec2p21neg, dec2p22neg, dec2p23neg, dec2p24neg, dec2p25neg, dec2p26neg, dec2p27neg, dec2p28neg, dec2p29neg, dec2p30neg, dec2p31neg, dec2p0, dec2p1, dec2p2, dec2p3, dec2p4, dec2p5, dec2p6, dec2p7, dec2p8, dec2p9, dec2p10, dec2p11, dec2p12, dec2p13, dec2p14, dec2p15, dec2p16, dec2p17, dec2p18, dec2p19, dec2p20, dec2p21, dec2p22, dec2p23, dec2p24, dec2p25, dec2p26, dec2p27, dec2p28, dec2p29, dec2p30, dec2p31, kBuffer } from "./num.js"; +import { alloc, size2 } from "./alloc.js" +import { add } from "./add.js"; +import { neg } from "./neg.js"; +import { S2_0, S2_1 } from "./symbol/S2.js"; +import { not } from "./not.js"; +import { S16_0, S16_1, S16_2, S16_3, S16_4, S16_5, S16_6, S16_7, S16_8, S16_9, S16_A, S16_B, S16_C, S16_D, S16_E, S16_F } from "./symbol/S16.js"; +import { S8_0, S8_1, S8_2, S8_3, S8_4, S8_5, S8_6, S8_7 } from "./symbol/S8.js"; + +/** + * @param { number } i + */ +function subtrahend(i) { + switch (i) { + case 0: return dec2p0neg; + case 1: return dec2p1neg; + case 2: return dec2p2neg; + case 3: return dec2p3neg; + case 4: return dec2p4neg; + case 5: return dec2p5neg; + case 6: return dec2p6neg; + case 7: return dec2p7neg; + case 8: return dec2p8neg; + case 9: return dec2p9neg; + case 10: return dec2p10neg; + case 11: return dec2p11neg; + case 12: return dec2p12neg; + case 13: return dec2p13neg; + case 14: return dec2p14neg; + case 15: return dec2p15neg; + case 16: return dec2p16neg; + case 17: return dec2p17neg; + case 18: return dec2p18neg; + case 19: return dec2p19neg; + case 20: return dec2p20neg; + case 21: return dec2p21neg; + case 22: return dec2p22neg; + case 23: return dec2p23neg; + case 24: return dec2p24neg; + case 25: return dec2p25neg; + case 26: return dec2p26neg; + case 27: return dec2p27neg; + case 28: return dec2p28neg; + case 29: return dec2p29neg; + case 30: return dec2p30neg; + case 31: return dec2p31neg; + default: throw new Error(`unexpected index (${i})`) + } +} + +function addend(i) { + switch (i) { + case 0: return dec2p0; + case 1: return dec2p1; + case 2: return dec2p2; + case 3: return dec2p3; + case 4: return dec2p4; + case 5: return dec2p5; + case 6: return dec2p6; + case 7: return dec2p7; + case 8: return dec2p8; + case 9: return dec2p9; + case 10: return dec2p10; + case 11: return dec2p11; + case 12: return dec2p12; + case 13: return dec2p13; + case 14: return dec2p14; + case 15: return dec2p15; + case 16: return dec2p16; + case 17: return dec2p17; + case 18: return dec2p18; + case 19: return dec2p19; + case 20: return dec2p20; + case 21: return dec2p21; + case 22: return dec2p22; + case 23: return dec2p23; + case 24: return dec2p24; + case 25: return dec2p25; + case 26: return dec2p26; + case 27: return dec2p27; + case 28: return dec2p28; + case 29: return dec2p29; + case 30: return dec2p30; + case 31: return dec2p31; + default: throw new Error(`unexpected index (${i})`) + } +} + +/** + * @param { Num } a + */ +function udec2bin(a) { + const buff = alloc(2); + for (let i = size2 - 1; i >= 0; i--) { + let b = a.copy(); + add(b, subtrahend(i)); + if (!neg(b)) { + a = b; + buff[i] = S2_1; + } + } + return new Num(2, buff); +} +/** + * @param { Num } a + */ +export function dec2bin(a) { + const negative = neg(a); + if (negative) { + a = a.copy(); + not(a); + } + const result = udec2bin(a); + if (negative) not(result); + return result; +} + +/** + * @param { Num } a + */ +function ubin2dec(a) { + const result = new Num(10, alloc(10)); + const { [kBuffer]: buff } = a; + for (let i = 0; i < size2; i++) { + if (buff[i] == S2_1) add(result, addend(i)); + } + return result +} +/** + * @param { Num } a + */ +export function bin2dec(a) { + const negative = neg(a); + if (negative) { + a = a.copy(); + not(a); + } + const result = ubin2dec(a); + if (negative) not(result); + return result; +} + +/** + * @param { symbol } a + * @param { symbol } b + * @param { symbol } c + * @param { symbol } d + */ +function ubin2hexB(d, c, b, a) { + switch (a) { + case S2_0: switch (b) { + case S2_0: switch (c) { + case S2_0: switch (d) { + case S2_0: return S16_0; + case S2_1: return S16_1; + default: throw new Error("unexpected symbol"); + } + case S2_1: switch (d) { + case S2_0: return S16_2; + case S2_1: return S16_3; + default: throw new Error("unexpected symbol"); + } + default: throw new Error("unexpected symbol"); + } + case S2_1: switch (c) { + case S2_0: switch (d) { + case S2_0: return S16_4; + case S2_1: return S16_5; + default: throw new Error("unexpected symbol"); + } + case S2_1: switch (d) { + case S2_0: return S16_6; + case S2_1: return S16_7; + default: throw new Error("unexpected symbol"); + } + default: throw new Error("unexpected symbol"); + } + } + case S2_1: switch (b) { + case S2_0: switch (c) { + case S2_0: switch (d) { + case S2_0: return S16_8; + case S2_1: return S16_9; + default: throw new Error("unexpected symbol"); + } + case S2_1: switch (d) { + case S2_0: return S16_A; + case S2_1: return S16_B; + default: throw new Error("unexpected symbol"); + } + default: throw new Error("unexpected symbol"); + } + case S2_1: switch (c) { + case S2_0: switch (d) { + case S2_0: return S16_C; + case S2_1: return S16_D; + default: throw new Error("unexpected symbol"); + } + case S2_1: switch (d) { + case S2_0: return S16_E; + case S2_1: return S16_F; + default: throw new Error("unexpected symbol"); + } + default: throw new Error("unexpected symbol"); + } + } + default: throw new Error("unexpected symbol"); + } +} + +/** + * @param { Num } a + */ +function ubin2hex(a) { + const buff = alloc(16); + const { [kBuffer]: buffer } = a; + for (let i = 0; i < buff.length; i++) { + const a = buffer[(i * 4)] ?? S2_0; + const b = buffer[(i * 4) + 1] ?? S2_0; + const c = buffer[(i * 4) + 2] ?? S2_0; + const d = buffer[(i * 4) + 3] ?? S2_0; + buff[i] = ubin2hexB(a, b, c, d); + } + return new Num(16, buff); +} +/** + * @param { Num } a + */ +export function bin2hex(a) { + const negative = neg(a); + if (negative) { + a = a.copy(); + not(a); + } + const result = ubin2hex(a); + if (negative) not(result); + return result; +} + +/** + * @param { symbol } a + * @returns { [symbol, symbol, symbol, symbol] } + */ +function uhex2binB(a) { + switch (a) { + case S16_0: return [S2_0, S2_0, S2_0, S2_0]; + case S16_1: return [S2_0, S2_0, S2_0, S2_1]; + case S16_2: return [S2_0, S2_0, S2_1, S2_0]; + case S16_3: return [S2_0, S2_0, S2_1, S2_1]; + case S16_4: return [S2_0, S2_1, S2_0, S2_0]; + case S16_5: return [S2_0, S2_1, S2_0, S2_1]; + case S16_6: return [S2_0, S2_1, S2_1, S2_0]; + case S16_7: return [S2_0, S2_1, S2_1, S2_1]; + case S16_8: return [S2_1, S2_0, S2_0, S2_0]; + case S16_9: return [S2_1, S2_0, S2_0, S2_1]; + case S16_A: return [S2_1, S2_0, S2_1, S2_0]; + case S16_B: return [S2_1, S2_0, S2_1, S2_1]; + case S16_C: return [S2_1, S2_1, S2_0, S2_0]; + case S16_D: return [S2_1, S2_1, S2_0, S2_1]; + case S16_E: return [S2_1, S2_1, S2_1, S2_0]; + case S16_F: return [S2_1, S2_1, S2_1, S2_1]; + default: throw new Error("unexpected symbol"); + } +} + +/** + * @param { Num } a + */ +function uhex2bin(a) { + const buff = alloc(2); + const { [kBuffer]: buffer } = a; + for (let i = 0; i < buffer.length; i++) { + const [d, c, b, a] = uhex2binB(buffer[i]); + if ((i * 4) < buff.length) buff[(i * 4)] = a; + if ((i * 4) + 1 < buff.length) buff[(i * 4) + 1] = b; + if ((i * 4) + 2 < buff.length) buff[(i * 4) + 2] = c; + if ((i * 4) + 3< buff.length) buff[(i * 4) + 3] = d; + } + return new Num(2, buff); +} +/** + * @param { Num } a + */ +export function hex2bin(a) { + const negative = neg(a); + if (negative) { + a = a.copy(); + not(a); + } + const result = uhex2bin(a); + if (negative) not(result); + return result; +} + +/** + * @param { symbol } a + * @param { symbol } b + * @param { symbol } c + */ +function ubin2octB(c, b, a) { + switch (a) { + case S2_0: switch (b) { + case S2_0: switch (c) { + case S2_0: return S8_0; + case S2_1: return S8_1; + default: throw new Error("unexpected symbol"); + } + case S2_1: switch (c) { + case S2_0: return S8_2; + case S2_1: return S8_3; + default: throw new Error("unexpected symbol"); + } + default: throw new Error("unexpected symbol"); + } + case S2_1: switch (b) { + case S2_0: switch (c) { + case S2_0: return S8_4; + case S2_1: return S8_5; + default: throw new Error("unexpected symbol"); + } + case S2_1: switch (c) { + case S2_0: return S8_6; + case S2_1: return S8_7; + default: throw new Error("unexpected symbol"); + } + default: throw new Error("unexpected symbol"); + } + default: throw new Error("unexpected symbol"); + } +} + +/** + * @param { Num } a + */ +function ubin2oct(a) { + const buff = alloc(8); + const { [kBuffer]: buffer } = a; + for (let i = 0; i < buff.length; i++) { + const a = buffer[(i * 3)] ?? S2_0; + const b = buffer[(i * 3) + 1] ?? S2_0; + const c = buffer[(i * 3) + 2] ?? S2_0; + buff[i] = ubin2octB(a, b, c); + } + return new Num(8, buff); +} +/** + * @param { Num } a + */ +export function bin2oct(a) { + const negative = neg(a); + if (negative) { + a = a.copy(); + not(a); + } + const result = ubin2oct(a); + if (negative) not(result); + return result; +} + +/** + * @param { symbol } a + * @returns { [symbol, symbol, symbol] } + */ +function uoct2binB(a) { + switch (a) { + case S8_0: return [S2_0, S2_0, S2_0]; + case S8_1: return [S2_0, S2_0, S2_1]; + case S8_2: return [S2_0, S2_1, S2_0]; + case S8_3: return [S2_0, S2_1, S2_1]; + case S8_4: return [S2_1, S2_0, S2_0]; + case S8_5: return [S2_1, S2_0, S2_1]; + case S8_6: return [S2_1, S2_1, S2_0]; + case S8_7: return [S2_1, S2_1, S2_1]; + default: throw new Error("unexpected symbol"); + } +} +/** + * @param { Num } a + */ +function uoct2bin(a) { + const buff = alloc(2); + const { [kBuffer]: buffer } = a; + for (let i = 0; i < buffer.length; i++) { + const [c, b, a] = uoct2binB(buffer[i]); + if ((i * 3) < buff.length) buff[(i * 3)] = a; + if ((i * 3) + 1 < buff.length) buff[(i * 3) + 1] = b; + if ((i * 3) + 2 < buff.length) buff[(i * 3) + 2] = c; + } + return new Num(2, buff); +} +/** + * @param { Num } a + */ +export function oct2bin(a) { + const negative = neg(a); + if (negative) { + a = a.copy(); + not(a); + } + const result = uoct2bin(a); + if (negative) not(result); + return result; +} \ No newline at end of file diff --git a/lab1/convert.test.js b/lab1/convert.test.js new file mode 100644 index 0000000..9187ea1 --- /dev/null +++ b/lab1/convert.test.js @@ -0,0 +1,34 @@ +import { Num } from "./index.js" + +for (let i = 0; i < 0xFFFF; i++) { + const str2 = `0b${i.toString(2).toUpperCase()}`; + const str8 = `0o${i.toString(8).toUpperCase()}`; + const str16 = `0x${i.toString(16).toUpperCase()}`; + const str10 = i.toString(10).toUpperCase(); + + const t2 = Num.parse(str2); + const t8 = Num.parse(str8); + const t16 = Num.parse(str16); + const t10 = Num.parse(str10); + + if (t2.as(2).toString() !== str2) throw new Error(`${str2}:${t2.as(2).toString()}`); + if (t2.as(8).toString() !== str8) throw new Error(`${str2}:${t2.as(8).toString()}`); + if (t2.as(16).toString() !== str16) throw new Error(`${str2}:${t2.as(16).toString()}`); + if (t2.as(10).toString() !== str10) throw new Error(`${str2}:${t2.as(10).toString()}`); + + if (t8.as(2).toString() !== str2) throw new Error(`${str2}:${t8.as(2).toString()}`); + if (t8.as(8).toString() !== str8) throw new Error(`${str2}:${t8.as(8).toString()}`); + if (t8.as(16).toString() !== str16) throw new Error(`${str2}:${t8.as(16).toString()}`); + if (t8.as(10).toString() !== str10) throw new Error(`${str2}:${t8.as(10).toString()}`); + + if (t16.as(2).toString() !== str2) throw new Error(`${str2}:${t16.as(2).toString()}`); + if (t16.as(8).toString() !== str8) throw new Error(`${str2}:${t16.as(8).toString()}`); + if (t16.as(16).toString() !== str16) throw new Error(`${str2}:${t16.as(16).toString()}`); + if (t16.as(10).toString() !== str10) throw new Error(`${str2}:${t16.as(10).toString()}`); + + if (t10.as(2).toString() !== str2) throw new Error(`${str2}:${t10.as(2).toString()}`); + if (t10.as(8).toString() !== str8) throw new Error(`${str2}:${t10.as(8).toString()}`); + if (t10.as(16).toString() !== str16) throw new Error(`${str2}:${t10.as(16).toString()}`); + if (t10.as(10).toString() !== str10) throw new Error(`${str2}:${t10.as(10).toString()}`); + +} \ No newline at end of file diff --git a/lab1/demo.js b/lab1/demo.js new file mode 100644 index 0000000..243ddf2 --- /dev/null +++ b/lab1/demo.js @@ -0,0 +1,41 @@ +import { Num, add, sub } from "./index.js"; + +const A = 123123; +const B = 879; + +const a = Num.parse(A.toString()); +const b = Num.parse(B.toString()); + +/**@type { { expression: string; correct: boolean; }[] } */ +const results = []; + +for (const radix of /**@type { const } */([10, 2, 8, 16])) { + const a1 = a.as(radix); + const b1 = b.as(radix); + // console.log(`a { radix: ${radix} } ${ a1.toString() } (${ Number(a1.toString()) == A })`); + results.push({ + expression: `a { radix: ${radix} } ${ a1.toString() }`, + correct: Number(a1.toString()) == A + }); + // console.log(`b { radix: ${radix} } ${ b1.toString() } (${ Number(b1.toString()) == B })`); + results.push({ + expression: `b { radix: ${radix} } ${ b1.toString() }`, + correct: Number(b1.toString()) == B + }); + const a2 = a1.copy() + const a3 = a1.copy(); + add(a2, b1); + sub(a3, b1); + // console.log(`a + b = ${ a2.toString() } (${ Number(a2.toString()) == (A + B) })`); + results.push({ + expression: `a + b = ${ a2.toString() }`, + correct: Number(a2.toString()) == (A + B) + }); + // console.log(`a - b = ${ a3.toString() } (${ Number(a3.toString()) == (A - B) })`); + results.push({ + expression: `a - b = ${ a3.toString() }`, + correct: Number(a3.toString()) == (A - B) + }); +} + +console.table(results); \ No newline at end of file diff --git a/lab1/index.js b/lab1/index.js new file mode 100644 index 0000000..b843ff4 --- /dev/null +++ b/lab1/index.js @@ -0,0 +1,4 @@ +export { add } from "./add.js" +export { sub } from "./sub.js" +export { not } from "./not.js" +export { Num } from "./num.js" \ No newline at end of file diff --git a/lab1/math.test.js b/lab1/math.test.js new file mode 100644 index 0000000..4ef962f --- /dev/null +++ b/lab1/math.test.js @@ -0,0 +1,27 @@ +/** + * @import { Radix } from "./num.js" + */ +import { Num, add, sub } from "./index.js" + +/** + * @param { number } number + * @param { number } radix + * @param { string } prefix + */ +function stringify(number, radix, prefix) { + return (Math.sign(number) === -1 ? "-" : "") + prefix + Math.abs(number).toString(radix).toUpperCase(); +} + +for (const [radix, prefix] of /**@type { [radix: Radix, prefix: string][]}*/([[2, "0b"], [8, "0o"], [16, "0x"], [10, ""]])) { + for (let i = 0; i < 0xFFF; i++) { + for (let j = 0; j < 0xFFF; j++) { + const a1 = Num.parse(`${prefix}${i.toString(radix)}`); + const a2 = a1.copy(); + const b = Num.parse(`${prefix}${j.toString(radix)}`); + add(a1, b); + sub(a2, b); + console.assert(a1.toString() === stringify(i + j, radix, prefix), i, j, stringify(i + j, radix, prefix), a1.toString()); + console.assert(a2.toString() === stringify(i - j, radix, prefix), i, j, stringify(i - j, radix, prefix), a2.toString()); + } + } +} \ No newline at end of file diff --git a/lab1/neg.js b/lab1/neg.js new file mode 100644 index 0000000..ed41bcc --- /dev/null +++ b/lab1/neg.js @@ -0,0 +1,102 @@ +/** + * @import { Num } from "./num.js" + */ +import { S16_0, S16_1, S16_2, S16_3, S16_4, S16_5, S16_6, S16_7, S16_8, S16_9, S16_A, S16_B, S16_C, S16_D, S16_E, S16_F } from "./symbol/S16.js" +import { S8_0, S8_1, S8_2, S8_3, S8_4, S8_5, S8_6, S8_7 } from "./symbol/S8.js" +import { S2_0, S2_1 } from "./symbol/S2.js" +import { S10_0, S10_1, S10_2, S10_3, S10_4, S10_5, S10_6, S10_7, S10_8, S10_9 } from "./symbol/S10.js" + +import { kBuffer } from "./num.js" + +/** + * @param { Num } a + */ +function neg16(a) { + const { [kBuffer]: buff } = a; + switch (buff[buff.length - 1]) { + case S16_0: return false; + case S16_1: return false; + case S16_2: return false; + case S16_3: return false; + case S16_4: return false; + case S16_5: return false; + case S16_6: return false; + case S16_7: return false; + + case S16_8: return true; + case S16_9: return true; + case S16_A: return true; + case S16_B: return true; + case S16_C: return true; + case S16_D: return true; + case S16_E: return true; + case S16_F: return true; + default: throw new Error("unexpected symbol"); + } +} + +/** + * @param { Num } a + */ +function neg8(a) { + const { [kBuffer]: buff } = a; + switch (buff[buff.length - 1]) { + case S8_0: return false; + case S8_1: return false; + case S8_2: return false; + case S8_3: return false; + + case S8_4: return true; + case S8_5: return true; + case S8_6: return true; + case S8_7: return true; + default: throw new Error("unexpected symbol"); + } +} + +/** + * @param { Num } a + */ +function neg2(a) { + const { [kBuffer]: buff } = a; + switch (buff[buff.length - 1]) { + case S2_0: return false; + + case S2_1: return true; + default: throw new Error("unexpected symbol"); + } +} + +/** + * @param { Num } a + */ +function neg10(a) { + const { [kBuffer]: buff } = a; + switch (buff[buff.length - 1]) { + case S10_0: return false; + case S10_1: return false; + case S10_2: return false; + case S10_3: return false; + case S10_4: return false; + + case S10_5: return true; + case S10_6: return true; + case S10_7: return true; + case S10_8: return true; + case S10_9: return true; + default: throw new Error("unexpected symbol"); + } +} + +/** + * @param { Num } a + */ +export function neg(a) { + switch (a.radix) { + case 2: return neg2(a); + case 8: return neg8(a); + case 16: return neg16(a); + case 10: return neg10(a); + default: throw new Error(`unsupported radix (${a.radix})`); + } +} \ No newline at end of file diff --git a/lab1/not.js b/lab1/not.js new file mode 100644 index 0000000..4e503ca --- /dev/null +++ b/lab1/not.js @@ -0,0 +1,137 @@ +import { S16_0, S16_1, S16_2, S16_3, S16_4, S16_5, S16_6, S16_7, S16_8, S16_9, S16_A, S16_B, S16_C, S16_D, S16_E, S16_F } from "./symbol/S16.js" +import { S8_0, S8_1, S8_2, S8_3, S8_4, S8_5, S8_6, S8_7 } from "./symbol/S8.js" +import { S2_0, S2_1 } from "./symbol/S2.js" +import { S10_0, S10_1, S10_2, S10_3, S10_4, S10_5, S10_6, S10_7, S10_8, S10_9 } from "./symbol/S10.js" +import { kBuffer, Num } from "./num.js" +import { add16, add8, add2, add10 } from "./add.js" +import { size16, size8, size2, size10 } from "./alloc.js" +import { one10, one16, one2, one8 } from "./num.js" + +/** + * @param { symbol } a + */ +function not16B(a) { + switch (a) { + case S16_0: return S16_F; + case S16_1: return S16_E; + case S16_2: return S16_D; + case S16_3: return S16_C; + case S16_4: return S16_B; + case S16_5: return S16_A; + case S16_6: return S16_9; + case S16_7: return S16_8; + case S16_8: return S16_7; + case S16_9: return S16_6; + case S16_A: return S16_5; + case S16_B: return S16_4; + case S16_C: return S16_3; + case S16_D: return S16_2; + case S16_E: return S16_1; + case S16_F: return S16_0; + default: throw new Error("unexpected symbol"); + } +} + +/** + * @param { symbol } a + */ +function not8B(a) { + switch (a) { + case S8_0: return S8_7; + case S8_1: return S8_6; + case S8_2: return S8_5; + case S8_3: return S8_4; + case S8_4: return S8_3; + case S8_5: return S8_2; + case S8_6: return S8_1; + case S8_7: return S8_0; + default: throw new Error("unexpected symbol"); + } +} + +/** + * @param { symbol } a + */ +function not2B(a) { + switch (a) { + case S2_0: return S2_1; + case S2_1: return S2_0; + default: throw new Error("unexpected symbol"); + } +} + +/** + * @param { symbol } a + */ +function not10B(a) { + switch (a) { + case S10_0: return S10_9; + case S10_1: return S10_8; + case S10_2: return S10_7; + case S10_3: return S10_6; + case S10_4: return S10_5; + case S10_5: return S10_4; + case S10_6: return S10_3; + case S10_7: return S10_2; + case S10_8: return S10_1; + case S10_9: return S10_0; + default: throw new Error("unexpected symbol"); + } +} + +/** + * @param { Num } a + */ +export function not16(a) { + const { [kBuffer]: buff } = a; + for (let i = 0; i < size16; i++) { + buff[i] = not16B(buff[i]); + } + add16(a, one16); +} + +/** + * @param { Num } a + */ +export function not8(a) { + const { [kBuffer]: buff } = a; + for (let i = 0; i < size8; i++) { + buff[i] = not8B(buff[i]); + } + add8(a, one8); +} + +/** + * @param { Num } a + */ +export function not2(a) { + const { [kBuffer]: buff } = a; + for (let i = 0; i < size2; i++) { + buff[i] = not2B(buff[i]); + } + add2(a, one2); +} + +/** + * @param { Num } a + */ +export function not10(a) { + const { [kBuffer]: buff } = a; + for (let i = 0; i < size10; i++) { + buff[i] = not10B(buff[i]); + } + add10(a, one10); +} + +/** + * @param { Num } a + */ +export function not(a) { + switch (a.radix) { + case 2: return not2(a); + case 8: return not8(a); + case 16: return not16(a); + case 10: return not10(a); + default: throw new Error(`unsupported radix (${a.radix})`); + } +} \ No newline at end of file diff --git a/lab1/num.js b/lab1/num.js new file mode 100644 index 0000000..2e97de0 --- /dev/null +++ b/lab1/num.js @@ -0,0 +1,195 @@ +import { alloc } from "./alloc.js"; +import { bin2dec, bin2hex, bin2oct, dec2bin, hex2bin, oct2bin } from "./convert.js"; +import { neg } from "./neg.js"; +import { not } from "./not.js"; +import { parse } from "./parse.js"; +import { string } from "./string.js"; +import { __throw } from "./utils.js"; + +export const kBuffer = Symbol("buffer"); + +/** + * @typedef { 2 | 8 | 16 | 10 } Radix + */ + +export class Num { + + /** + * @param { string } value + */ + static parse(value) { + /**@type { Radix } */ + let radix = 10; + if (value.startsWith("0b")) radix = 2; + else if (value.startsWith("0o")) radix = 8; + else if (value.startsWith("0x")) radix = 16; + const buff = alloc(radix); + if (radix !== 10) value = value.substring(2); + if (value === "") throw new Error("unexpected end of seaquence") + + parse(radix, value, buff); + return new Num(radix, buff); + } + + /** + * + * @param { Radix } radix + * @param { symbol[] } buffer + * @returns + */ + constructor(radix, buffer) { + this.radix = radix; + this[kBuffer] = buffer; + } + + /** + * @readonly + * @type { Radix } + */ + radix; + + copy() { + return new Num(this.radix, [...this[kBuffer]]); + } + + toString() { + /**@type { Num } */ + let target = this; + const negative = neg(target); + if (negative) not((target = target.copy())); + return negative ? `-${ string(target) }` : string(target); + } + + /** + * @param { Radix } radix + * @returns { Num } + */ + as(radix) { + if (this.radix == radix) return this.copy(); + if (radix == 2) { + switch (this.radix) { + case 8: return oct2bin(this); + case 16: return hex2bin(this); + case 10: return dec2bin(this); + default: throw new Error(); + } + } else if (this.radix == 2) { + switch (radix) { + case 8: return bin2oct(this); + case 16: return bin2hex(this); + case 10: return bin2dec(this); + default: throw new Error(); + } + } + return this.as(2).as(radix); + } + + /**@see https://github.com/microsoft/TypeScript/issues/60590 */ + // /** + // * @protected + // * @type { symbol[] } + // */ + // [kBuffer]; +} + +export const one16 = Num.parse("0x1"); +export const one8 = Num.parse("0o1"); +export const one2 = Num.parse("0b1"); +export const one10 = Num.parse("1"); + +export const dec2p0 = Num.parse("1"); +export const dec2p0neg = dec2p0.copy(); +not(dec2p0neg); +export const dec2p1 = Num.parse("2"); +export const dec2p1neg = dec2p1.copy(); +not(dec2p1neg); +export const dec2p2 = Num.parse("4"); +export const dec2p2neg = dec2p2.copy(); +not(dec2p2neg); +export const dec2p3 = Num.parse("8"); +export const dec2p3neg = dec2p3.copy(); +not(dec2p3neg); +export const dec2p4 = Num.parse("16"); +export const dec2p4neg = dec2p4.copy(); +not(dec2p4neg); +export const dec2p5 = Num.parse("32"); +export const dec2p5neg = dec2p5.copy(); +not(dec2p5neg); +export const dec2p6 = Num.parse("64"); +export const dec2p6neg = dec2p6.copy(); +not(dec2p6neg); +export const dec2p7 = Num.parse("128"); +export const dec2p7neg = dec2p7.copy(); +not(dec2p7neg); +export const dec2p8 = Num.parse("256"); +export const dec2p8neg = dec2p8.copy(); +not(dec2p8neg); +export const dec2p9 = Num.parse("512"); +export const dec2p9neg = dec2p9.copy(); +not(dec2p9neg); +export const dec2p10 = Num.parse("1024"); +export const dec2p10neg = dec2p10.copy(); +not(dec2p10neg); +export const dec2p11 = Num.parse("2048"); +export const dec2p11neg = dec2p11.copy(); +not(dec2p11neg); +export const dec2p12 = Num.parse("4096"); +export const dec2p12neg = dec2p12.copy(); +not(dec2p12neg); +export const dec2p13 = Num.parse("8192"); +export const dec2p13neg = dec2p13.copy(); +not(dec2p13neg); +export const dec2p14 = Num.parse("16384"); +export const dec2p14neg = dec2p14.copy(); +not(dec2p14neg); +export const dec2p15 = Num.parse("32768"); +export const dec2p15neg = dec2p15.copy(); +not(dec2p15neg); +export const dec2p16 = Num.parse("65536"); +export const dec2p16neg = dec2p16.copy(); +not(dec2p16neg); +export const dec2p17 = Num.parse("131072"); +export const dec2p17neg = dec2p17.copy(); +not(dec2p17neg); +export const dec2p18 = Num.parse("262144"); +export const dec2p18neg = dec2p18.copy(); +not(dec2p18neg); +export const dec2p19 = Num.parse("524288"); +export const dec2p19neg = dec2p19.copy(); +not(dec2p19neg); +export const dec2p20 = Num.parse("1048576"); +export const dec2p20neg = dec2p20.copy(); +not(dec2p20neg); +export const dec2p21 = Num.parse("2097152"); +export const dec2p21neg = dec2p21.copy(); +not(dec2p21neg); +export const dec2p22 = Num.parse("4194304"); +export const dec2p22neg = dec2p22.copy(); +not(dec2p22neg); +export const dec2p23 = Num.parse("8388608"); +export const dec2p23neg = dec2p23.copy(); +not(dec2p23neg); +export const dec2p24 = Num.parse("16777216"); +export const dec2p24neg = dec2p24.copy(); +not(dec2p24neg); +export const dec2p25 = Num.parse("33554432"); +export const dec2p25neg = dec2p25.copy(); +not(dec2p25neg); +export const dec2p26 = Num.parse("67108864"); +export const dec2p26neg = dec2p26.copy(); +not(dec2p26neg); +export const dec2p27 = Num.parse("134217728"); +export const dec2p27neg = dec2p27.copy(); +not(dec2p27neg); +export const dec2p28 = Num.parse("268435456"); +export const dec2p28neg = dec2p28.copy(); +not(dec2p28neg); +export const dec2p29 = Num.parse("536870912"); +export const dec2p29neg = dec2p29.copy(); +not(dec2p29neg); +export const dec2p30 = Num.parse("1073741824"); +export const dec2p30neg = dec2p30.copy(); +not(dec2p30neg); +export const dec2p31 = Num.parse("2147483648"); +export const dec2p31neg = dec2p31.copy(); +not(dec2p31neg); \ No newline at end of file diff --git a/lab1/package.json b/lab1/package.json new file mode 100644 index 0000000..96ae6e5 --- /dev/null +++ b/lab1/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} \ No newline at end of file diff --git a/lab1/parse.js b/lab1/parse.js new file mode 100644 index 0000000..fbd9cab --- /dev/null +++ b/lab1/parse.js @@ -0,0 +1,141 @@ +/** + * @import { Radix } from "./num.js" + */ +import { S16_0, S16_1, S16_2, S16_3, S16_4, S16_5, S16_6, S16_7, S16_8, S16_9, S16_A, S16_B, S16_C, S16_D, S16_E, S16_F } from "./symbol/S16.js" +import { S8_0, S8_1, S8_2, S8_3, S8_4, S8_5, S8_6, S8_7 } from "./symbol/S8.js" +import { S2_0, S2_1 } from "./symbol/S2.js" +import { S10_0, S10_1, S10_2, S10_3, S10_4, S10_5, S10_6, S10_7, S10_8, S10_9 } from "./symbol/S10.js" +import { __throw } from "./utils.js"; + +/** + * @param { string } char + */ +function parse16B(char) { + switch (char) { + case "0": return S16_0; + case "1": return S16_1; + case "2": return S16_2; + case "3": return S16_3; + case "4": return S16_4; + case "5": return S16_5; + case "6": return S16_6; + case "7": return S16_7; + case "8": return S16_8; + case "9": return S16_9; + case "a": return S16_A; + case "A": return S16_A; + case "b": return S16_B; + case "B": return S16_B; + case "c": return S16_C; + case "C": return S16_C; + case "d": return S16_D; + case "D": return S16_D; + case "e": return S16_E; + case "E": return S16_E; + case "f": return S16_F; + case "F": return S16_F; + default: throw new Error(`unexpected symbol (${char})`) + } +} + +/** + * @param { string } char + */ +function parse8B(char) { + switch (char) { + case "0": return S8_0; + case "1": return S8_1; + case "2": return S8_2; + case "3": return S8_3; + case "4": return S8_4; + case "5": return S8_5; + case "6": return S8_6; + case "7": return S8_7; + default: throw new Error(`unexpected symbol (${char})`) + } +} + +/** + * @param { string } char + */ +function parse2B(char) { + switch (char) { + case "0": return S2_0; + case "1": return S2_1; + default: throw new Error(`unexpected symbol (${char})`) + } +} + +/** + * @param { string } char + */ +function parse10B(char) { + switch (char) { + case "0": return S10_0; + case "1": return S10_1; + case "2": return S10_2; + case "3": return S10_3; + case "4": return S10_4; + case "5": return S10_5; + case "6": return S10_6; + case "7": return S10_7; + case "8": return S10_8; + case "9": return S10_9; + default: throw new Error(`unexpected symbol (${char})`) + } +} + +/** + * @param { string } value + * @param { symbol[] } buffer + */ +function parse16(value, buffer) { + for (let i = 0, j = value.length - 1; i < buffer.length && j >= 0; i++, j--) { + buffer[i] = parse16B(value[j]); + } +} + +/** + * @param { string } value + * @param { symbol[] } buffer + */ +function parse8(value, buffer) { + for (let i = 0, j = value.length - 1; i < buffer.length && j >= 0; i++, j--) { + buffer[i] = parse8B(value[j]); + } +} + +/** + * @param { string } value + * @param { symbol[] } buffer + */ +function parse2(value, buffer) { + for (let i = 0, j = value.length - 1; i < buffer.length && j >= 0; i++, j--) { + buffer[i] = parse2B(value[j]); + } +} + +/** + * @param { string } value + * @param { symbol[] } buffer + */ +function parse10(value, buffer) { + for (let i = 0, j = value.length - 1; i < buffer.length && j >= 0; i++, j--) { + buffer[i] = parse10B(value[j]); + } +} + +/** + * @param { Radix } radix + * @param { string } value + * @param { symbol[] } buffer + */ +export function parse(radix, value, buffer) { + switch (radix) { + case 2: return parse2(value, buffer); + case 8: return parse8(value, buffer); + case 16: return parse16(value, buffer); + case 10: return parse10(value, buffer); + default: throw new Error(`unsupported radix (${radix})`); + } +} \ No newline at end of file diff --git a/lab1/string.js b/lab1/string.js new file mode 100644 index 0000000..93e5b93 --- /dev/null +++ b/lab1/string.js @@ -0,0 +1,65 @@ +/** + * @import { Num } from "./num.js" + */ +import { kBuffer } from "./num.js"; +import { string16B } from "./string/16B.js" +import { string8B } from "./string/8B.js" +import { string2B } from "./string/2B.js"; +import { string10B } from "./string/10B.js" +import { S8_0 } from "./symbol/S8.js"; +import { S16_0 } from "./symbol/S16.js"; +import { S2_0 } from "./symbol/S2.js"; +import { S10_0 } from "./symbol/S10.js"; + +/** + * @param { Num } n + */ +export function string16(n) { + const { [kBuffer]: buff } = n; + let str = "" + for (let i = buff.length - 1; i >= 0; i--) if (buff[i] !== S16_0) while (i >= 0) str += string16B(buff[i--]); + return `0x${str.padStart(1, "0")}`; +} + +/** + * @param { Num } n + */ +export function string8(n) { + const { [kBuffer]: buff } = n; + let str = "" + for (let i = buff.length - 1; i >= 0; i--) if (buff[i] !== S8_0) while (i >= 0) str += string8B(buff[i--]); + return `0o${str.padStart(1, "0")}`; +} + +/** + * @param { Num } n + */ +export function string2(n) { + const { [kBuffer]: buff } = n; + let str = "" + for (let i = buff.length - 1; i >= 0; i--) if (buff[i] !== S2_0) while (i >= 0) str += string2B(buff[i--]); + return `0b${str.padStart(1, "0")}`; +} + +/** + * @param { Num } n + */ +export function string10(n) { + const { [kBuffer]: buff } = n; + let str = "" + for (let i = buff.length - 1; i >= 0; i--) if (buff[i] !== S10_0) while (i >= 0) str += string10B(buff[i--]); + return str.padStart(1, "0"); +} + +/** + * @param { Num } n + */ +export function string(n) { + switch (n.radix) { + case 2: return string2(n); + case 8: return string8(n); + case 16: return string16(n); + case 10: return string10(n); + default: throw new Error(`unsupported radix (${n.radix})`); + } +} \ No newline at end of file diff --git a/lab1/string/10B.js b/lab1/string/10B.js new file mode 100644 index 0000000..f64b71f --- /dev/null +++ b/lab1/string/10B.js @@ -0,0 +1,20 @@ +import { S10_0, S10_1, S10_2, S10_3, S10_4, S10_5, S10_6, S10_7, S10_8, S10_9 } from "../symbol/S10.js" + +/** + * @param { symbol } s + */ +export function string10B(s) { + switch (s) { + case S10_0: return "0"; + case S10_1: return "1"; + case S10_2: return "2"; + case S10_3: return "3"; + case S10_4: return "4"; + case S10_5: return "5"; + case S10_6: return "6"; + case S10_7: return "7"; + case S10_8: return "8"; + case S10_9: return "9"; + default: throw new Error("unexpected symbol"); + } +} \ No newline at end of file diff --git a/lab1/string/16B.js b/lab1/string/16B.js new file mode 100644 index 0000000..33ea64e --- /dev/null +++ b/lab1/string/16B.js @@ -0,0 +1,26 @@ +import { S16_0, S16_1, S16_2, S16_3, S16_4, S16_5, S16_6, S16_7, S16_8, S16_9, S16_A, S16_B, S16_C, S16_D, S16_E, S16_F } from "../symbol/S16.js" + +/** + * @param { symbol } s + */ +export function string16B(s) { + switch (s) { + case S16_0: return "0"; + case S16_1: return "1"; + case S16_2: return "2"; + case S16_3: return "3"; + case S16_4: return "4"; + case S16_5: return "5"; + case S16_6: return "6"; + case S16_7: return "7"; + case S16_8: return "8"; + case S16_9: return "9"; + case S16_A: return "A"; + case S16_B: return "B"; + case S16_C: return "C"; + case S16_D: return "D"; + case S16_E: return "E"; + case S16_F: return "F"; + default: throw new Error("unexpected symbol"); + } +} \ No newline at end of file diff --git a/lab1/string/2B.js b/lab1/string/2B.js new file mode 100644 index 0000000..b31533c --- /dev/null +++ b/lab1/string/2B.js @@ -0,0 +1,12 @@ +import { S2_0, S2_1 } from "../symbol/S2.js" + +/** + * @param { symbol } s + */ +export function string2B(s) { + switch (s) { + case S2_0: return "0"; + case S2_1: return "1"; + default: throw new Error("unexpected symbol"); + } +} \ No newline at end of file diff --git a/lab1/string/8B.js b/lab1/string/8B.js new file mode 100644 index 0000000..f3d33f3 --- /dev/null +++ b/lab1/string/8B.js @@ -0,0 +1,19 @@ +import { S8_0, S8_1, S8_2, S8_3, S8_4, S8_5, S8_6, S8_7 } from "../symbol/S8.js" + + +/** + * @param { symbol } s + */ +export function string8B(s) { + switch (s) { + case S8_0: return "0"; + case S8_1: return "1"; + case S8_2: return "2"; + case S8_3: return "3"; + case S8_4: return "4"; + case S8_5: return "5"; + case S8_6: return "6"; + case S8_7: return "7"; + default: throw new Error("unexpected symbol"); + } +} \ No newline at end of file diff --git a/lab1/sub.js b/lab1/sub.js new file mode 100644 index 0000000..bd291fe --- /dev/null +++ b/lab1/sub.js @@ -0,0 +1,15 @@ +/** + * @import { Num } from "./num.js" + */ +import { add } from "./add.js"; +import { not } from "./not.js"; + +/** + * @param { Num } a + * @param { Num } b + */ +export function sub(a, b) { + b = b.copy(); + not(b); + add(a, b); +} \ No newline at end of file diff --git a/lab1/symbol/S10.js b/lab1/symbol/S10.js new file mode 100644 index 0000000..83c36e9 --- /dev/null +++ b/lab1/symbol/S10.js @@ -0,0 +1,10 @@ +export const S10_0 = Symbol("0"); +export const S10_1 = Symbol("1"); +export const S10_2 = Symbol("2"); +export const S10_3 = Symbol("3"); +export const S10_4 = Symbol("4"); +export const S10_5 = Symbol("5"); +export const S10_6 = Symbol("6"); +export const S10_7 = Symbol("7"); +export const S10_8 = Symbol("8"); +export const S10_9 = Symbol("9"); \ No newline at end of file diff --git a/lab1/symbol/S16.js b/lab1/symbol/S16.js new file mode 100644 index 0000000..094843a --- /dev/null +++ b/lab1/symbol/S16.js @@ -0,0 +1,16 @@ +export const S16_0 = Symbol("0"); +export const S16_1 = Symbol("1"); +export const S16_2 = Symbol("2"); +export const S16_3 = Symbol("3"); +export const S16_4 = Symbol("4"); +export const S16_5 = Symbol("5"); +export const S16_6 = Symbol("6"); +export const S16_7 = Symbol("7"); +export const S16_8 = Symbol("8"); +export const S16_9 = Symbol("9"); +export const S16_A = Symbol("A"); +export const S16_B = Symbol("B"); +export const S16_C = Symbol("C"); +export const S16_D = Symbol("D"); +export const S16_E = Symbol("E"); +export const S16_F = Symbol("F"); diff --git a/lab1/symbol/S2.js b/lab1/symbol/S2.js new file mode 100644 index 0000000..5c67deb --- /dev/null +++ b/lab1/symbol/S2.js @@ -0,0 +1,2 @@ +export const S2_0 = Symbol("0"); +export const S2_1 = Symbol("1"); \ No newline at end of file diff --git a/lab1/symbol/S8.js b/lab1/symbol/S8.js new file mode 100644 index 0000000..c211938 --- /dev/null +++ b/lab1/symbol/S8.js @@ -0,0 +1,8 @@ +export const S8_0 = Symbol("0"); +export const S8_1 = Symbol("1"); +export const S8_2 = Symbol("2"); +export const S8_3 = Symbol("3"); +export const S8_4 = Symbol("4"); +export const S8_5 = Symbol("5"); +export const S8_6 = Symbol("6"); +export const S8_7 = Symbol("7"); \ No newline at end of file diff --git a/lab1/utils.js b/lab1/utils.js new file mode 100644 index 0000000..a97869e --- /dev/null +++ b/lab1/utils.js @@ -0,0 +1,7 @@ +/** + * @param { unknown } err + * @returns { never } + */ +export function __throw(err) { + throw err; +} diff --git a/lab2/index.js b/lab2/index.js new file mode 100644 index 0000000..a6a7a73 --- /dev/null +++ b/lab2/index.js @@ -0,0 +1,362 @@ +import { at } from "./utilities.js"; + +const L = 4; +const MAX = 9999; +const LIM = 10000; + +const kBuffer = Symbol("buffer"); + +export class BigInteger { + /** + * @private + */ + static zero = BigInteger.from("0"); + /** + * @private + */ + static one = BigInteger.from("1"); + /** + * @private + */ + static two = BigInteger.from("2"); + + /** + * @param { number[] } buffer + * @param {boolean} [negative] + */ + constructor(buffer, negative = false) { + this[kBuffer] = buffer; + this.negative = negative; + } + + /** + * @param { string } str + */ + static from(str) { + const negative = str[0] === "-"; + if (negative) str = str.substring(1); + /**@type { number[] } */ + const buffer = []; + let i = str.length; + let j = i - L; + while (j > 0) { + buffer.push(Number.parseInt(str.substring(j, i))); + j -= L; + i -= L; + } + buffer.push(Number.parseInt(str.substring(0, i))); + return new BigInteger(buffer, negative); + } + + /** + * @param { BigInteger } a + * @param { BigInteger } b + */ + static ucmp(a, b) { + const l = a[kBuffer].length; + if (l !== b[kBuffer].length) return l > b[kBuffer].length ? 1 : -1; + for (let i = l - 1; i >= 0; i--) { + if (a[kBuffer][i] !== b[kBuffer][i]) return a[kBuffer][i] > b[kBuffer][i] ? 1 : -1; + } + return 0; + } + + /** + * @param { BigInteger } num + */ + static isZero(num) { + return num[kBuffer].length === 1 && num[kBuffer][0] === 0; + } + + /** + * @param { boolean } [negative] + * @returns { BigInteger } + */ + copy(negative = this.negative) { + return new BigInteger(Array.from(this[kBuffer]), negative); + } + + /** + * @returns { BigInteger } + */ + shallowCopy() { + return new BigInteger(this[kBuffer], this.negative); + } + + /** + * @param { BigInteger } num + * @param { boolean } [negative] + * @returns { this } + */ + assign(num, negative = num.negative) { + this[kBuffer] = Array.from(num[kBuffer]); + this.negative = negative; + return this; + } + + /** + * @returns { this } + */ + toggleSign() { + this.negative = !this.negative; + return this; + } + + /** + * @param { boolean } negative + * @returns { this } + */ + setSign(negative) { + this.negative = negative; + return this; + } + + toString() { + const buff = this[kBuffer]; + let accum = this.negative ? "-" : ""; + accum += buff[buff.length - 1].toString(); + for (let i = buff.length - 2; i >= 0; i--) accum += buff[i].toString().padStart(4, "0"); + return accum; + } + + /** + * @param { BigInteger } num + * @param { boolean } [negative] + * @returns { this } + */ + add(num, negative = num.negative) { + if (this.negative !== negative) return this.negative ? this.sub(num, true) : this.sub(num, false); + const buffA = this[kBuffer]; + const buffB = num[kBuffer]; + let carry = 0; + for (let i = 0; i < buffB.length; i++) { + while (buffA.length <= i) buffA.push(0); + buffA[i] += buffB[i] + carry; + carry = Number(buffA[i] > MAX); + if (carry) buffA[i] %= LIM; + } + if (carry) { + let i = buffB.length; + while (buffA.length <= i) buffA.push(0); + while (buffA[i] === MAX) { + buffA[i++] = 0; + while (buffA.length <= i) buffA.push(0); + } + buffA[i] += carry; + } + return this; + } + + // /** + // * @param { BigInteger } num + // * @param { boolean } [negative] + // * @returns { this } + // */ + // add(num, negative = num.negative) { + // if (this.negative !== negative) return this.sub(num, this.negative); + // return this.uadd(num); + // } + + // /** + // * @param { BigInteger } num + // * @returns { this } + // */ + // uadd(num) { + // const buffA = this[kBuffer]; + // const buffB = num[kBuffer]; + // let carry = 0; + // let i = 0; + // while (buffA.length < buffB.length) buffA.push(0); + // for (; i < buffB.length; i++) { + // buffA[i] += buffB[i] + carry; + // carry = Number(buffA[i] > MAX); + // if (carry) buffA[i] %= LIM; + // } + // if (carry === 1) { + // while (at(buffA, i, 0) === MAX) buffA[i++] = 0; + // buffA[i] += carry; + // } + // return this; + // } + + /** + * @param { BigInteger } num + * @param { boolean } [negative] + * @returns { this } + */ + sub(num, negative = num.negative) { + if (this.negative !== negative) return this.negative ? this.add(num, true) : this.add(num, false); + if (BigInteger.ucmp(num, this) == 1) { + const self = this.shallowCopy(); + return this.assign(num, negative).sub(self).toggleSign(); + } + const buffA = this[kBuffer]; + const buffB = num[kBuffer]; + let carry = 0; + for (let i = 0; i < buffB.length; i++) { + buffA[i] -= buffB[i] + carry; + carry = Number(buffA[i] < 0); + if (carry) buffA[i] += LIM; + } + if (carry) { + let i = buffB.length; + while (buffA[i] === 0) buffA[i++] = MAX; + buffA[i] -= carry; + } + while (buffA.length > 1 && buffA[buffA.length - 1] == 0) buffA.pop(); + return this; + } + + // /** + // * @param { BigInteger } num + // * @param { boolean } [negative] + // * @returns { this } + // */ + // sub(num, negative = num.negative) { + // if (this.negative !== negative) return this.add(num, this.negative); + // return this.usub(num); + // } + + // /** + // * @param { BigInteger } num + // * @returns { this } + // */ + // usub(num) { + // if (BigInteger.ucmp(num, this) == 1) { + // const self = this.shallowCopy(); + // return this.assign(num, !this.negative).usub(self) + // } + // const buffA = this[kBuffer]; + // const buffB = num[kBuffer]; + // let carry = 0; + // let i = 0; + // for (; i < buffB.length; i++) { + // buffA[i] -= buffB[i] + carry; + // carry = Number(buffA[i] < 0); + // if (carry) buffA[i] += LIM; + // } + // if (carry == 1) { + // while (buffA[i] === 0) buffA[i++] = MAX; + // buffA[i] -= carry; + // } + // for (let i = buffA.length - 1; i > 0 && buffA[i] === 0; i--) buffA.pop(); + // return this; + // } + + /** + * @param { BigInteger } num + * @returns { this } + */ + mul(num) { + /**@type { number[] } */ + const buff = []; + for (let i = 0; i < this[kBuffer].length; i++) { + const a = this[kBuffer][i]; + for (let j = 0; j < num[kBuffer].length; j++) { + const b = num[kBuffer][j]; + let k = i + j; + while (buff.length <= k) buff.push(0); + buff[k] += a * b; + while (buff[k] > MAX) { + const carry = Math.trunc(buff[k] / LIM) + buff[k++] %= LIM; + while (buff.length <= k) buff.push(0); + buff[k] += carry; + } + } + } + + this[kBuffer] = buff; + this.negative = this.negative !== num.negative; + return this; + } + + // /** + // * @param { BigInteger } num + // * @returns { this } + // */ + // mul(num) { + // return this.umul(num).setSign(this.negative !== num.negative); + // } + + // /** + // * @param { BigInteger } num + // * @returns { this } + // */ + // umul(num) { + // /**@type { number[] } */ + // const buff = []; + // for (let i = 0; i < this[kBuffer].length; i++) { + // const a = this[kBuffer][i]; + // for (let j = 0; j < num[kBuffer].length; j++) { + // const b = num[kBuffer][j]; + // let k = i + j; + // while (buff.length <= k) buff.push(0); + // buff[k] += a * b; + // while (buff[k] > MAX) { + // const carry = Math.trunc(buff[k] / LIM) + // buff[k++] %= LIM; + // while (buff.length <= k) buff.push(0); + // buff[k] += carry; + // } + // } + // } + // this[kBuffer] = buff; + // return this; + // } + + /** + * @param { BigInteger } num + * @returns { this } + */ + div(num) { + const buffB = num[kBuffer]; + const l = buffB.length - 1; + let quick = true; + for (let i = 0; i < l && quick; i++) quick = (buffB[i] == 0); + if (quick) { + const D = buffB[l]; + const N = this[kBuffer].slice(l); + let carry = 0; + for (let i = N.length - 1; i >= 0; i--) { + N[i] += (carry * LIM); + carry = N[i] % D; + N[i] = Math.trunc(N[i] / D); + } + if (N.length < 1) N.push(0); + while (N.length > 1 && N[N.length - 1] == 0) N.pop(); + this[kBuffer] = N; + this.negative = this.negative !== num.negative; + return this; + } + + const A = num.copy(); + for (let i = 0; i < l; i++) A[kBuffer][i] = 0; + const Q = this.copy().div(A); + const R = num.copy().add(BigInteger.one, num.negative); + const TMP = BigInteger.zero.copy(); + while (BigInteger.ucmp(R, num) != -1) { + TMP.assign(Q).mul(num); + R.assign(this).sub(TMP); + TMP.assign(R).div(A).add(Q); + Q.add(TMP).div(BigInteger.two); + } + TMP.assign(Q).mul(num); + R.assign(this).sub(TMP); + if (this.negative !== R.negative && !BigInteger.isZero(R)) { + Q.sub(BigInteger.one, Q.negative); + R.add(num); + } + this[kBuffer] = Q[kBuffer]; + this.negative = Q.negative; + return this; + } + + /** + * @param { BigInteger } num + * @returns { this } + */ + udiv(num) { + throw new Error("Not Implemented"); + } +} \ No newline at end of file diff --git a/lab2/test.js b/lab2/test.js new file mode 100644 index 0000000..3834192 --- /dev/null +++ b/lab2/test.js @@ -0,0 +1,261 @@ +import { BigInteger } from "./index.js" + +console.group("Addition and subtraction") +console.group("by 0 is the identity") + +console.assert(BigInteger.from("1").add(BigInteger.from("0")).toString() === "1"); +console.assert(BigInteger.from("-1").add(BigInteger.from("0")).toString() === "-1"); +console.assert(BigInteger.from("0").add(BigInteger.from("-1")).toString() === "-1"); +console.assert(BigInteger.from("0").add(BigInteger.from("153")).toString() === "153"); +console.assert(BigInteger.from("153").add(BigInteger.from("0")).toString() === "153"); +console.assert(BigInteger.from("0").add(BigInteger.from("-153")).toString() === "-153"); +console.assert(BigInteger.from("-153").add(BigInteger.from("0")).toString() === "-153"); +console.assert(BigInteger.from("0").add(BigInteger.from("9844190321790980841789")).toString() === "9844190321790980841789"); +console.assert(BigInteger.from("9844190321790980841789").add(BigInteger.from("0")).toString() ==="9844190321790980841789"); + +console.assert(BigInteger.from("0").add(BigInteger.from("-9844190321790980841789")).toString() ==="-9844190321790980841789"); +console.assert(BigInteger.from("-9844190321790980841789").add(BigInteger.from("0")).toString() === "-9844190321790980841789"); +console.assert(BigInteger.from("1").sub(BigInteger.from("0")).toString() === "1"); +console.assert(BigInteger.from("-1").sub(BigInteger.from("0")).toString() === "-1"); +console.assert(BigInteger.from("153").sub(BigInteger.from("0")).toString() === "153"); +console.assert(BigInteger.from("-153").sub(BigInteger.from("0")).toString() === "-153"); +console.assert(BigInteger.from("9844190321790980841789").sub(BigInteger.from("0")).toString() === "9844190321790980841789"); +console.assert(BigInteger.from("-9844190321790980841789").sub(BigInteger.from("0")).toString() === "-9844190321790980841789"); + +console.groupEnd(); +console.group("addition by inverse is 0, subtraction by self is 0"); + +console.assert(BigInteger.from("5").sub(BigInteger.from("5")).toString() === "0"); +console.assert(BigInteger.from("5").add(BigInteger.from("-5")).toString() === "0"); +console.assert(BigInteger.from("10000000000000000").sub(BigInteger.from("10000000000000000")).toString() === "0"); +console.assert(BigInteger.from("10000000000000000").add(BigInteger.from("-10000000000000000")).toString() === "0"); + +console.groupEnd(); +console.group("handles signs correctly"); + +console.assert(BigInteger.from("1").add(BigInteger.from("1")).toString() === "2"); +console.assert(BigInteger.from("1").add(BigInteger.from("-5")).toString() === "-4"); +console.assert(BigInteger.from("-1").add(BigInteger.from("5")).toString() === "4"); +console.assert(BigInteger.from("-1").add(BigInteger.from("-5")).toString() === "-6"); +console.assert(BigInteger.from("5").add(BigInteger.from("1")).toString() === "6"); +console.assert(BigInteger.from("5").add(BigInteger.from("-1")).toString() === "4"); +console.assert(BigInteger.from("-5").add(BigInteger.from("1")).toString() === "-4"); +console.assert(BigInteger.from("-5").add(BigInteger.from("-1")).toString() === "-6"); + +console.assert(BigInteger.from("1").sub(BigInteger.from("1")).toString() === "0"); +console.assert(BigInteger.from("1").sub(BigInteger.from("-5")).toString() === "6"); +console.assert(BigInteger.from("-1").sub(BigInteger.from("5")).toString() === "-6"); +console.assert(BigInteger.from("-1").sub(BigInteger.from("-5")).toString() === "4"); +console.assert(BigInteger.from("5").sub(BigInteger.from("1")).toString() === "4"); +console.assert(BigInteger.from("5").sub(BigInteger.from("-1")).toString() === "6"); +console.assert(BigInteger.from("-5").sub(BigInteger.from("1")).toString() === "-6"); +console.assert(BigInteger.from("-5").sub(BigInteger.from("-1")).toString() === "-4"); + +console.assert(BigInteger.from("1234698764971301").add(BigInteger.from("5")).toString() === "1234698764971306"); +console.assert(BigInteger.from("1234698764971301").add(BigInteger.from("-5")).toString() === "1234698764971296"); +console.assert(BigInteger.from("-1234698764971301").add(BigInteger.from("5")).toString() === "-1234698764971296"); +console.assert(BigInteger.from("-1234698764971301").add(BigInteger.from("-5")).toString() === "-1234698764971306"); +console.assert(BigInteger.from("5").add(BigInteger.from("1234698764971301")).toString() === "1234698764971306"); +console.assert(BigInteger.from("5").add(BigInteger.from("-1234698764971301")).toString() === "-1234698764971296"); +console.assert(BigInteger.from("-5").add(BigInteger.from("1234698764971301")).toString() === "1234698764971296"); +console.assert(BigInteger.from("-5").add(BigInteger.from("-1234698764971301")).toString() === "-1234698764971306"); + +console.assert(BigInteger.from("1234698764971301").sub(BigInteger.from("5")).toString() === "1234698764971296"); +console.assert(BigInteger.from("1234698764971301").sub(BigInteger.from("-5")).toString() === "1234698764971306"); +console.assert(BigInteger.from("-1234698764971301").sub(BigInteger.from("5")).toString() === "-1234698764971306"); +console.assert(BigInteger.from("-1234698764971301").sub(BigInteger.from("-5")).toString() === "-1234698764971296"); +console.assert(BigInteger.from("5").sub(BigInteger.from("1234698764971301")).toString() === "-1234698764971296"); +console.assert(BigInteger.from("5").sub(BigInteger.from("-1234698764971301")).toString() === "1234698764971306"); +console.assert(BigInteger.from("-5").sub(BigInteger.from("1234698764971301")).toString() === "-1234698764971306"); +console.assert(BigInteger.from("-5").sub(BigInteger.from("-1234698764971301")).toString() === "1234698764971296"); + +console.assert(BigInteger.from("1234567890987654321").add(BigInteger.from("9876543210123456789")).toString() === "11111111101111111110"); +console.assert(BigInteger.from("1234567890987654321").add(BigInteger.from("-9876543210123456789")).toString() === "-8641975319135802468"); +console.assert(BigInteger.from("-1234567890987654321").add(BigInteger.from("9876543210123456789")).toString() === "8641975319135802468"); +console.assert(BigInteger.from("-1234567890987654321").add(BigInteger.from("-9876543210123456789")).toString() === "-11111111101111111110"); +console.assert(BigInteger.from("9876543210123456789").add(BigInteger.from("1234567890987654321")).toString() === "11111111101111111110"); +console.assert(BigInteger.from("9876543210123456789").add(BigInteger.from("-1234567890987654321")).toString() === "8641975319135802468"); +console.assert(BigInteger.from("-9876543210123456789").add(BigInteger.from("1234567890987654321")).toString() === "-8641975319135802468"); +console.assert(BigInteger.from("-9876543210123456789").add(BigInteger.from("-1234567890987654321")).toString() === "-11111111101111111110"); + +console.assert(BigInteger.from("1234567890987654321").sub(BigInteger.from("9876543210123456789")).toString() === "-8641975319135802468"); +console.assert(BigInteger.from("1234567890987654321").sub(BigInteger.from("-9876543210123456789")).toString() === "11111111101111111110"); +console.assert(BigInteger.from("-1234567890987654321").sub(BigInteger.from("9876543210123456789")).toString() === "-11111111101111111110"); +console.assert(BigInteger.from("-1234567890987654321").sub(BigInteger.from("-9876543210123456789")).toString() === "8641975319135802468"); +console.assert(BigInteger.from("9876543210123456789").sub(BigInteger.from("1234567890987654321")).toString() === "8641975319135802468"); +console.assert(BigInteger.from("9876543210123456789").sub(BigInteger.from("-1234567890987654321")).toString() === "11111111101111111110"); +console.assert(BigInteger.from("-9876543210123456789").sub(BigInteger.from("1234567890987654321")).toString() === "-11111111101111111110"); +console.assert(BigInteger.from("-9876543210123456789").sub(BigInteger.from("-1234567890987654321")).toString() === "-8641975319135802468"); + +console.assert(BigInteger.from("-9007199254740991").add(BigInteger.from("-1")).toString() === "-9007199254740992"); +console.assert(BigInteger.from("-5616421592529327000000000000000").sub(BigInteger.from("987682355516543")).toString() === "-5616421592529327987682355516543") + +console.assert(BigInteger.from("-0").add(BigInteger.from("10000000000000000")).toString() === "10000000000000000"); +console.assert(BigInteger.from("-0").add(BigInteger.from("-1")).toString() ==="-1"); + +console.groupEnd(); +console.group("carries over correctly"); +{ + const fibs = ["1", "1", "2", "3", "5", "8", "13", "21", "34", "55", "89", "144", "233", "377", "610", "987", "1597", "2584", "4181", "6765", "10946", "17711", "28657", "46368", "75025", "121393", "196418", "317811", "514229", "832040", "1346269", "2178309", "3524578", "5702887", "9227465", "14930352", "24157817", "39088169", "63245986", "102334155", "165580141", "267914296", "433494437", "701408733", "1134903170", "1836311903", "2971215073", "4807526976", "7778742049", "12586269025"]; + const number = BigInteger.from("1"); + const last = BigInteger.from("1"); + + for (let i = 2; i < 50; i++) { + number.add(last); + last.assign(number.copy().sub(last)); + + console.assert(number.toString() === fibs[i]); + } +} + +console.assert(BigInteger.from("9007199254740991").add(BigInteger.from("1")).toString() === "9007199254740992"); +console.assert(BigInteger.from("999999999999999999999000000000000000000000").add(BigInteger.from("1000000000000000000000")).toString() === "1000000000000000000000000000000000000000000"); +console.assert(BigInteger.from("100000000000000000000").add(BigInteger.from("9007199254740972")).toString() === "100009007199254740972"); +console.assert(BigInteger.from("-9007199254740983").add(BigInteger.from("-9999999999999998")).toString() === "-19007199254740981"); + +console.assert(BigInteger.from("100000000000000000000000000000000000").sub(BigInteger.from("999999999999999999")).toString() === "99999999999999999000000000000000001"); + +console.assert(BigInteger.from("10000000010000000").sub(BigInteger.from("10000000")).toString() === "10000000000000000"); + +console.groupEnd(); +console.group("work"); + +console.assert(BigInteger.from("10").add(BigInteger.from("10")).toString() === "20"); +console.assert(BigInteger.from("-10000000000000000").add(BigInteger.from("0")).toString() === "-10000000000000000"); +console.assert(BigInteger.from("0").add(BigInteger.from("10000000000000000")).toString() === "10000000000000000"); +console.assert(BigInteger.from("9999999").add(BigInteger.from("1")).toString() === "10000000"); +console.assert(BigInteger.from("10000000").sub(BigInteger.from("1")).toString() === "9999999"); +console.assert(BigInteger.from("-1000000000000000000000000000000000001").add(BigInteger.from("1000000000000000000000000000000000000")).toString() === "-1"); +console.assert(BigInteger.from("100000000000000000002222222222222222222").sub(BigInteger.from("100000000000000000001111111111111111111")).toString() === "1111111111111111111"); +console.assert(BigInteger.from("1").add(BigInteger.from("0")).toString() === "1"); +console.assert(BigInteger.from("10").add(BigInteger.from("10000000000000000")).toString() === "10000000000000010"); +console.assert(BigInteger.from("10000000000000000").add(BigInteger.from("10")).toString() === "10000000000000010"); +console.assert(BigInteger.from("10000000000000000").add(BigInteger.from("10000000000000000")).toString() === "20000000000000000"); + +console.groupEnd(); +console.groupEnd(); + +console.group("Multiplication") +console.group("by 0 equals 0"); + +// console.assert(BigInteger.from("0").mul(BigInteger.from("0")).toString() === "0"); +// console.assert(BigInteger.from("0").mul(BigInteger.from("-0")).toString() === "0"); +// console.assert(BigInteger.from("1").mul(BigInteger.from("0")).toString() === "-0"); +// console.assert(BigInteger.from("-0").mul(BigInteger.from("1")).toString() === "0"); +// console.assert(BigInteger.from("1234567890987654321").mul(BigInteger.from("0")).toString() ==="-0"); +// console.assert(BigInteger.from("-0").mul(BigInteger.from("1234567890987654321")).toString() === "0"); +// console.assert(BigInteger.from("0").mul(BigInteger.from("-1234567890987654321")).toString() === "0"); + +console.groupEnd(); +console.group("by 1 is the identity") + +console.assert(BigInteger.from("1").mul(BigInteger.from("1")).toString() === "1"); +console.assert(BigInteger.from("-1").mul(BigInteger.from("1")).toString() === "-1"); +console.assert(BigInteger.from("1").mul(BigInteger.from("-1")).toString() === "-1"); +console.assert(BigInteger.from("1").mul(BigInteger.from("153")).toString() === "153"); +console.assert(BigInteger.from("153").mul(BigInteger.from("1")).toString() === "153"); +console.assert(BigInteger.from("1").mul(BigInteger.from("-153")).toString() === "-153"); +console.assert(BigInteger.from("-153").mul(BigInteger.from("1")).toString() === "-153"); +console.assert(BigInteger.from("1").mul(BigInteger.from("9844190321790980841789")).toString() === "9844190321790980841789"); +console.assert(BigInteger.from("9844190321790980841789").mul(BigInteger.from("1")).toString() === "9844190321790980841789"); +console.assert(BigInteger.from("1").mul(BigInteger.from("-9844190321790980841789")).toString() === "-9844190321790980841789"); +console.assert(BigInteger.from("-9844190321790980841789").mul(BigInteger.from("1")).toString() === "-9844190321790980841789"); + +console.groupEnd(); +console.group("handles signs correctly"); + +console.assert(BigInteger.from("100").mul(BigInteger.from("100")).toString() === "10000"); +console.assert(BigInteger.from("100").mul(BigInteger.from("-100")).toString() === "-10000"); +console.assert(BigInteger.from("-100").mul(BigInteger.from("100")).toString() === "-10000"); +console.assert(BigInteger.from("-100").mul(BigInteger.from("-100")).toString() === "10000"); + +console.assert(BigInteger.from("13579").mul(BigInteger.from("163500573666152634716420931676158")).toString() === "2220174289812686626814279831230549482"); +console.assert(BigInteger.from("13579").mul(BigInteger.from("-163500573666152634716420931676158")).toString() === "-2220174289812686626814279831230549482"); +console.assert(BigInteger.from("-13579").mul(BigInteger.from("163500573666152634716420931676158")).toString() === "-2220174289812686626814279831230549482"); +console.assert(BigInteger.from("-13579").mul(BigInteger.from("-163500573666152634716420931676158")).toString() === "2220174289812686626814279831230549482"); +console.assert(BigInteger.from("163500573666152634716420931676158").mul(BigInteger.from("13579")).toString() === "2220174289812686626814279831230549482"); +console.assert(BigInteger.from("163500573666152634716420931676158").mul(BigInteger.from("-13579")).toString() === "-2220174289812686626814279831230549482"); +console.assert(BigInteger.from("-163500573666152634716420931676158").mul(BigInteger.from("13579")).toString() === "-2220174289812686626814279831230549482"); +console.assert(BigInteger.from("-163500573666152634716420931676158").mul(BigInteger.from("-13579")).toString() === "2220174289812686626814279831230549482"); +console.assert(BigInteger.from("163500573666152634716420931676158").mul(BigInteger.from("-1")).toString() === "-163500573666152634716420931676158"); + +console.assert(BigInteger.from("1234567890987654321").mul(BigInteger.from("132435465768798")).toString() === "163500573666152634716420931676158"); +console.assert(BigInteger.from("1234567890987654321").mul(BigInteger.from("-132435465768798")).toString() === "-163500573666152634716420931676158"); +console.assert(BigInteger.from("-1234567890987654321").mul(BigInteger.from("132435465768798")).toString() === "-163500573666152634716420931676158"); +console.assert(BigInteger.from("-1234567890987654321").mul(BigInteger.from("-132435465768798")).toString() === "163500573666152634716420931676158"); + +console.groupEnd(); +console.group("carries over correctly"); + +console.assert(BigInteger.from("50000005000000").mul(BigInteger.from("10000001")).toString() === "500000100000005000000"); +console.assert(BigInteger.from("50000005000000").mul(BigInteger.from("10000001")).toString() === "500000100000005000000"); + +console.groupEnd(); +console.groupEnd(); + +console.group("Division") +console.group("by 1 is the identity"); + +console.assert(BigInteger.from("1").div(BigInteger.from("1")).toString() === "1"); +console.assert(BigInteger.from("-1").div(BigInteger.from("1")).toString() === "-1"); +console.assert(BigInteger.from("1").div(BigInteger.from("-1")).toString() === "-1"); +console.assert(BigInteger.from("153").div(BigInteger.from("1")).toString() === "153"); +console.assert(BigInteger.from("-153").div(BigInteger.from("1")).toString() === "-153"); +console.assert(BigInteger.from("9844190321790980841789").div(BigInteger.from("1")).toString() === "9844190321790980841789"); +console.assert(BigInteger.from("-9844190321790980841789").div(BigInteger.from("1")).toString() === "-9844190321790980841789"); + +console.groupEnd(); +console.group("by self is 1"); + +console.assert(BigInteger.from("5").div(BigInteger.from("5")).toString() === "1"); +console.assert(BigInteger.from("-5").div(BigInteger.from("-5")).toString() === "1"); +console.assert(BigInteger.from("20194965098495006574").div(BigInteger.from("20194965098495006574")).toString() === "1"); +console.assert(BigInteger.from("-20194965098495006574").div(BigInteger.from("-20194965098495006574")).toString() === "1"); + +console.groupEnd(); +console.group("of 0 equals 0"); + +console.assert(BigInteger.from("0").div(BigInteger.from("1")).toString() === "0"); +console.assert(BigInteger.from("-0").div(BigInteger.from("1")).toString() === "-0"); +console.assert(BigInteger.from("-0").div(BigInteger.from("1234567890987654321")).toString() === "-0"); +console.assert(BigInteger.from("0").div(BigInteger.from("-1234567890987654321")).toString() === "-0"); + +console.groupEnd(); +console.group("handles signs correctly"); + +console.assert(BigInteger.from("10000").div(BigInteger.from("100")).toString() === "100"); +console.assert(BigInteger.from("10000").div(BigInteger.from("-100")).toString() === "-100"); +console.assert(BigInteger.from("-10000").div(BigInteger.from("100")).toString() === "-100"); +console.assert(BigInteger.from("-10000").div(BigInteger.from("-100")).toString() === "100"); +console.assert(BigInteger.from("100").div(BigInteger.from("-1000")).toString() === "-0"); + +console.assert(BigInteger.from("163500573666152634716420931676158").div(BigInteger.from("13579")).toString() === "12040693251797086288859336598"); +console.assert(BigInteger.from("163500573666152634716420931676158").div(BigInteger.from("-13579")).toString() === "-12040693251797086288859336598"); + +console.assert(BigInteger.from("-163500573666152634716420931676158").div(BigInteger.from("13579")).toString() === "-12040693251797086288859336598"); +console.assert(BigInteger.from("-163500573666152634716420931676158").div(BigInteger.from("-13579")).toString() === "12040693251797086288859336598"); + +console.assert(BigInteger.from("1234567890987654321").div(BigInteger.from("132435465768798")).toString() === "9322"); +console.assert(BigInteger.from("1234567890987654321").div(BigInteger.from("-132435465768798")).toString() === "-9322"); +console.assert(BigInteger.from("-1234567890987654321").div(BigInteger.from("132435465768798")).toString() === "-9322"); +console.assert(BigInteger.from("-1234567890987654321").div(BigInteger.from("-132435465768798")).toString() === "9322"); + +console.assert(BigInteger.from("786456456335437356436").div(BigInteger.from("-5423424653")).toString() === "-145011041298"); +console.assert(BigInteger.from("-93453764643534523").div(BigInteger.from("-2342")).toString() === "39903400787162"); +console.assert(BigInteger.from("10000000000000000").div(BigInteger.from("-10000000000000000")).toString() === "-1"); + +console.assert(BigInteger.from("98789789419609840614360398703968368740365403650364036403645046").div(BigInteger.from("-1")).toString() === "-98789789419609840614360398703968368740365403650364036403645046"); + +console.groupEnd(); +console.group("works"); + +console.assert(BigInteger.from("98109840984098409156481068456541684065964819841065106865710397464513210416435401645030648036034063974065004951094209420942097421970490274195049120974210974209742190274092740492097420929892490974202241981098409840984091564810684565416840659648198410651068657103974645132104164354016450306480360340639740650049510942094209420974219704902741950491209742109742097421902740927404920974209298924909742022419810984098409840915648106845654168406596481984106510686571039746451321041643540164503064803603406397406500495109420942094209742197049027419504912097421097420974219027409274049209742092989249097420224198109840984098409156481068456541684065964819841065106865710397464513210416435401645030648036034063974065004951094209420942097421970490274195049120974210974209742190274092740492097420929892490974202241981098409840984091564810684565416840659648198410651068657103974645132104164354016450306480360340639740650049510942094209420974219704902741950491209742109742097421902740927404920974209298924909742022419810984098409840915648106845654168406596481984106510686571039746451321041643540164503064803603406397406500495109420942094209742197049027419504912097421097420974219027409274049209742092989249097420224198109840984098409156481068456541684065964819841065106865710397464513210416435401645030648036034063974065004951094209420942097421970490274195049120974210974209742190274092740492097420929892490974202241981098409840984091564810684565416840659648198410651068657103974645132104164354016450306480360340639740650049510942094209420974219704902741950491209742109742097421902740927404920974209298924909742022419810984098409840915648106845654168406596481984106510686571039746451321041643540164503064803603406397406500495109420942094209742197049027419504912097421097420974219027409274049209742092989249097420224198109840984098409156481068456541684065964819841065106865710397464513210416435401645030648036034063974065004951094209420942097421970490274195049120974210974209742190274092740492097420929892490974202241").div(BigInteger.from("98109840984098409156481068456541684065964819841065106865710397464513210416435401645030648036034063974065004951094209420942097421970490274195049120974210974209742190274092740492097420929892490974202241")).toString() === "1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"); +console.assert(BigInteger.from("650891045068740450350436540352434350243346254305240433565403624570436542564034355230360437856406345450735366803660233645540323657640436735034636550432635454032364560324366403643455063652403346540263364032643454530236455402336455640363263405423565405623454062354540326564062306456432664546654436564364556406435460643646363545606345066534456065340165344065234064564").div(BigInteger.from("2634565230452364554234565062345452365450236455423654456253445652344565423655423655462534506253450462354056523445062535462534052654350426355023654540625344056203455402635454026435501635446643754664546780646476442344654465764466744566754436556406235454066354570657548036545465")).toString() === "247058238507527885509216194910087226997858456323482112332514020694766925604284002588230023"); +console.assert(BigInteger.from("650891045068740450350436540352434350243346254305240433565403624570436542564034355230360437856406345450735366803660233645540323657640436735034636550432635454032364560324366403643455063652403346540263364032643454530236455402336455640363263405423565405623454062354540326564062306456432664546654436564364556406435460643646363545606345066534456065340165344065234064564000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").div(BigInteger.from("2634565230452364554234565062345452365450236455423654456253445652344565423655423655462534506253450462354056523445062535462534052654350426355023654540625344056203455402635454026435501635446643754664546780646476442344654465764466744566754436556406235454066354570657548036545465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")).toString() === "247058238507527885509216194910087226997858456323482112332514020694766925604284002588230023"); +console.assert(BigInteger.from("9999999999999900000000000000").div(BigInteger.from("999999999999990000001")).toString() === "9999999"); + +console.groupEnd(); +console.groupEnd(); +console.groupEnd(); + +console.log("done"); diff --git a/lab2/utilities.js b/lab2/utilities.js new file mode 100644 index 0000000..aa54ecf --- /dev/null +++ b/lab2/utilities.js @@ -0,0 +1,9 @@ +/** + * @param { number[] } array + * @param { number } index + * @param { number } init + */ +export function at(array, index, init) { + while (array.length <= index) array.push(init); + return array[index]; +} \ No newline at end of file