UpsilonNumworks / Upsilon

Upsilon, an OS forked from Omega for your Numworks calculator
https://getupsilon.web.app/
Other
209 stars 61 forks source link

Logic Toolbox #308

Open joecrop opened 1 year ago

joecrop commented 1 year ago

Binary Logic Toolbox

Numworks is about to release some basic binary functions in Epsilon. I tried them out, and they are honestly pretty useless, with inputs of just 'True' and 'False' and just AND/OR/NOT functions. Here's my take on a toolbox with much more powerful logic functions to be used on both unsigned and signed integers. I have also extended the '...' (Additional Results) display to show the 2's complement binary/hex of negative numbers.

logic_toolbox

Additional Results

Negative integers can now be displayed in binary/hex. Simply navigate to the ellipsis ('...') on the right of a negative integer result to see a 2's complement representation of the number:

negative_binary_results

Functions Implemented

Basic Logic Operations

AND

// x = a & b
and(a, b); // and of 2 integers

// Examples
and(0b11,0b01) = 1;
and(0b100110,0b1011) = 2;

OR

// x = a | b
or(a, b); // or of 2 integers

// Examples
or(0b11,0b01) = 3 = 0b11;
or(0b100110,0b1011) = 47 = 0b101111;

XOR - Exclusive OR

// x = a ^ b
xor(a, b); // xor of 2 integers

// Examples
xor(0b11,0b01) = 1;
xor(0b100110,0b1011) = 45 = 0b101101;

NOT

// x = ~a
not(a); // logical inversion of 32-bit unsigend integer

// Examples
not(0b11) = 4294967292 = 0xFFFFFFFC;
not(0xFFFF0000) = 65535 = 0xFFFF;

Bit Shifts

Shift Logical Left

// x = a << s
sll(a, s) // shift 'a' left by 's' bit positions

// Examples
sll(0b11,2) = 12 = 0b1100;

Shift Logical Right

// x = a >> s
srl(a, s) // shift 'a' right by 's' bit positions

// Examples
srl(0b11,2) = 0;
srl(0b1100,1) = 6 = 0b110;

Arithmetic Shift Right

// x = a >>> s
sra(a, s) // shift 'a' right by 's' bit positions, perserving the MSB sign bit, where 'a' is presumed to a 32 bits

// Examples
sra(0b11,2) = 0;
sra(0b1100,1) = 6 = 0b110;
sra(0xFFFF0000,8) = 4294967040 = 0xFFFFFF00;

Rotate Left

// x = (a << r) | (a & 1)
rol(a, r) // rotate 'a' by 'r' bit positions, the MSB is warpped around to the LSB, where 'a' is presumed to a 32 bits

// Examples
rol(0b101,1) = 10 = 0b1010;
rol(0xFFFF0000,4) = 4293918735 = 0xFFF000F;

Rotate Right

// x = (a >> r) | ((a & 1) << 32)
ror(a, r) // rotate 'a' by 'r' bit positions, the LSB is warpped around to the MSB, where 'a' is presumed to a 32 bits

// Examples
ror(0b1010,1) = 5 = 0b101;
ror(0b101,1) = 1073741825 = 0x40000001;
ror(0xFFFF0000,4) = 268431360 = 0x0FFFF000;

Setting And Clearing Bits

Get Bit

// (a >> n) & 1
bit(a, n) // return the n-th bit of 'a'

// Examples
bit(0b1010,1) = 0;
bit(0b1010,2) = 1;

Set Bit

// x = a | (1 << n)
bset(a, n) // set the n-th bit of 'a'

// Examples
bset(0b1010,1) = 11 = 0b1011;
bset(0b1010,2) = 10 = 0b1010;

Clear Bit

// x = a & ~(1 << n)
bclr(a, n) // clear the n-th bit of 'a'

// Examples
bclr(0b1010,1) = 10 = 0b1010;
bclr(0b1010,2) = 8 = 0b1000;

Flip Bit

// x = a ^ (1 << n)
bflp(a, n) // flip the n-th bit of 'a'

// Examples
bflp(0b1010,1) = 11 = 0b1011;
bflp(0b1010,2) = 8 = 0b1000;

Clear 'a' With 'b'

// x = (a & ~b)
bic(a, b) // clear 'a' with 'b'

// Examples
bic(0b1010,1) = 10 = 0b1010;
bic(0b1010,0b10) = 8 = 0b1000;
bic(0b1010,0b1010) = 0;

Logic Operations (With Explicit Number of Bits)

Some logic operations (like NOT) end up generating large 32-bit numbers as the default precision is 32 bits. This adds frustration when 32 bits of precision is undesired. So some of the functions have overridden methods that have an extra argument that allows the user to control the number of output bits.

not(a,n);
sra(a,s,n);
rol(a,r,n);
ror(a,r,n);
bic(a,b,n);

// Examples
not(0b11) = 4294967292 = 0xFFFFFFFC;
not(0b11,8) = 252 = 0b11111100;
not(0b00,2) = 3 = 0b11;
not(0b10,1) = 1 = 0b1;
not(0b0,1) = 1 = 0b1;
not(0b1,1) = 0 = 0b0;

2'S Compliment Conversions/Helpers

2's Compliment Equivalent

// Converts an unsigned binary number to it's two-compliment equivalent Integer.
// Simply useful to decode binary numbers that are negative

// Examples:
// If argument 1 is positive, the output will be converted to two-s comp (i.e. look at sign bit in MSB)
tc(0xFF, 8) = -1;
tc(0x0F, 8) = 15;

// if argument 1 is negative, it is always converted to unsigned
tc(-1, 8) = 255;

Ceiling Log2

// Returns the numver of bits required to represent a number in binary.
clog2(255) = 8;
clog2(3) = 2;

//NOTE: this is not the same as ceil(log(x,2)), as negative inputs to this function will instead be treated as 2's compliment numbers it report the number of bits needed to represent a signed 2's compliment number.
clog2(-3) = 2; // -3 in binary 2's compliment is 0b100
// If you want to konw the number of bits of an unsigend number in 2'c compliment number, just add 1 to the result for a sign bit.

Other Information

github-actions[bot] commented 1 year ago
.text .rodata .bss .data Total (RAM) Total (ROM)
Base 821684 bytes 478173 bytes 226384 bytes 1816 bytes 228200 bytes 1301673 bytes
Head 834324 bytes 486889 bytes 226376 bytes 1816 bytes 228192 bytes 1323029 bytes
+12640 bytes +8716 bytes -8 bytes +0 bytes -8 bytes +21356 bytes
+1.5 % +1.8 % -0.0 % +0.0 % -0.0 % +1.6 %
github-actions[bot] commented 1 year ago
.text .rodata .bss .data Total (RAM) Total (ROM)
Base 821684 bytes 478173 bytes 226384 bytes 1816 bytes 228200 bytes 1301673 bytes
Head 834324 bytes 486881 bytes 226376 bytes 1816 bytes 228192 bytes 1323021 bytes
+12640 bytes +8708 bytes -8 bytes +0 bytes -8 bytes +21348 bytes
+1.5 % +1.8 % -0.0 % +0.0 % -0.0 % +1.6 %