From e87001f07be069a07185837896d9e73ca08f3574 Mon Sep 17 00:00:00 2001 From: David Ellis Date: Fri, 20 Sep 2024 17:11:57 -0500 Subject: [PATCH] Implement the js u16 arithmetic and bitwise operations (#905) --- alan_std.js | 140 +++++++++++++++++++++++++++++++++++++++++++++++ alan_std.test.js | 26 +++++++++ 2 files changed, 166 insertions(+) diff --git a/alan_std.js b/alan_std.js index 571a0f00..7010afb9 100644 --- a/alan_std.js +++ b/alan_std.js @@ -636,6 +636,17 @@ export function wrappingPowU8(a, b) { return v; } +export function notU8(a) { + let v = ~a; + while (v > 255) { + v -= 256; + } + while (v < 0) { + v += 256; + } + return v; +} + export function wrappingShlU8(a, b) { let v = a << b; while (v > 255) { @@ -687,3 +698,132 @@ export function rotateRightU8(a, b) { let p2 = a & rhs; return wrappingShrU8(p1, 8 - c) + wrappingShlU8(p2, c); } + +export function wrappingAddU16(a, b) { + let v = a + b; + while (v > 65_535) { + v -= 65_536; + } + while (v < 0) { + v += 65_536; + } + return v; +} + +export function wrappingSubU16(a, b) { + let v = a - b; + while (v > 65_535) { + v -= 65_536; + } + while (v < 0) { + v += 65_536; + } + return v; +} + +export function wrappingMulU16(a, b) { + let v = a * b; + while (v > 65_535) { + v -= 65_536; + } + while (v < 0) { + v += 65_536; + } + return v; +} + +export function wrappingDivU16(a, b) { + let v = Math.floor(a / b); + while (v > 65_535) { + v -= 65_536; + } + while (v < 0) { + v += 65_536; + } + return v; +} + +export function wrappingModU16(a, b) { + let v = a % b; + while (v > 65_535) { + v -= 65_536; + } + while (v < 0) { + v += 65_536; + } + return v; +} + +export function wrappingPowU16(a, b) { + let v = Math.floor(a ** b); + while (v > 65_535) { + v -= 65_536; + } + while (v < 0) { + v += 65_536; + } + return v; +} + +export function notU16(a) { + let v = ~a; + while (v > 65_535) { + v -= 65_536; + } + while (v < 0) { + v += 65_536; + } + return v; +} + +export function wrappingShlU16(a, b) { + let v = a << b; + while (v > 65_535) { + v -= 65_536; + } + while (v < 0) { + v += 65_536; + } + return v; +} + +export function wrappingShrU16(a, b) { + let v = a >> b; + while (v > 65_535) { + v -= 65_536; + } + while (v < 0) { + v += 65_536; + } + return v; +} + +export function rotateLeftU16(a, b) { + let c = b; + while (c > 15) { + c -= 16; + } + if (c == 0) { + return a; + } + let lhs = clampU16(65_535 << c); + let rhs = clampU16(65_535 ^ lhs); + let p1 = a & lhs; + let p2 = a & rhs; + return wrappingShrU16(p1, 16 - c) + wrappingShlU16(p2, c); +} + +export function rotateRightU16(a, b) { + let c = b; + while (c > 15) { + c -= 16; + } + if (c == 0) { + return a; + } + let rhs = clampU16(65_535 << c); + let lhs = clampU16(65_535 ^ rhs); + let p1 = a & lhs; + let p2 = a & rhs; + return wrappingShrU16(p1, 16 - c) + wrappingShlU16(p2, c); +} diff --git a/alan_std.test.js b/alan_std.test.js index 62c269f4..6893c267 100644 --- a/alan_std.test.js +++ b/alan_std.test.js @@ -151,6 +151,8 @@ assert(alanStd.wrappingModU8(5, 2) == 1, "wrappingModU8 5 % 2 = 1"); assert(alanStd.wrappingPowU8(2, 8) == 0, "wrappingPowU8 2 ^ 8 = 0"); +assert(alanStd.notU8(0) == 255, "notU8 0 = 255"); + assert(alanStd.wrappingShlU8(128, 1) == 0, "wrappingShlU8 128 << 1 = 0"); assert(alanStd.wrappingShrU8(128, 1) == 64, "wrappingShrU8 128 >> 1 = 64"); @@ -158,3 +160,27 @@ assert(alanStd.wrappingShrU8(128, 1) == 64, "wrappingShrU8 128 >> 1 = 64"); assert(alanStd.rotateLeftU8(128, 1) == 1, "rotateLeftU8 128 <<< 1 = 1"); assert(alanStd.rotateRightU8(64, 1) == 128, "rotateRightU8 64 >>> 1 = 128"); + +assert(alanStd.wrappingAddU16(1, 2) === 3, "wrappingAddU16 1 + 2 = 3"); +assert(alanStd.wrappingAddU16(65_535, 1) === 0, "wrappingAddU16 65_535 + 1 = 0"); + +assert(alanStd.wrappingSubU16(1, 2) === 65_535, "wrappingSubU16 1 - 2 = 65_535"); +assert(alanStd.wrappingSubU16(65_535, 1) === 65_534, "wrappingSubU16 65_535 - 1 = 65_534"); + +assert(alanStd.wrappingMulU16(256, 256) === 0, "wrappingMulU16 256 * 256 = 0"); + +assert(alanStd.wrappingDivU16(128, 2) == 64, "wrappingDivU16 128 / 2 = 64"); + +assert(alanStd.wrappingModU16(5, 2) == 1, "wrappingModU16 5 % 2 = 1"); + +assert(alanStd.wrappingPowU16(2, 16) == 0, "wrappingPowU16 2 ^ 8 = 0"); + +assert(alanStd.notU16(0) == 65_535, "notU16 0 = 65_535"); + +assert(alanStd.wrappingShlU16(32_768, 1) == 0, "wrappingShlU16 32_768 << 1 = 0"); + +assert(alanStd.wrappingShrU16(128, 1) == 64, "wrappingShrU16 128 >> 1 = 64"); + +assert(alanStd.rotateLeftU16(32_768, 1) == 1, "rotateLeftU16 128 <<< 1 = 1"); + +assert(alanStd.rotateRightU16(64, 1) == 128, "rotateRightU16 64 >>> 1 = 128");