[PR #308] [MERGED] Logic Toolbox #359

Closed
opened 2026-05-06 13:17:00 +02:00 by BreizhHardware · 0 comments

📋 Pull Request Information

Original PR: https://github.com/UpsilonNumworks/Upsilon/pull/308
Author: @joecrop
Created: 12/27/2022
Status: Merged
Merged: 11/5/2025
Merged by: @Yaya-Cout

Base: upsilon-devHead: logic-toolbox


📝 Commits (6)

  • 42d8fea logic toolbox with logic functions
  • fc95028 - Added clog2 function
  • 81dc1bd moved logic toolbox to the bottom of the list
  • d7f54ad removed shift functions with explicit number of bits
  • 8041c7a Updated french translations after feedback
  • c1f5b4a Merge branch 'upsilon-dev' into logic-toolbox

📊 Changes

25 files changed (+1887 additions, -9 deletions)

View changed files

📝 apps/calculation/additional_outputs/integer_list_controller.cpp (+26 -4)
📝 apps/calculation/calculation.h (+1 -1)
📝 apps/math_toolbox.cpp (+30 -2)
📝 apps/shared.universal.i18n (+25 -0)
📝 apps/toolbox.de.i18n (+14 -0)
📝 apps/toolbox.en.i18n (+14 -0)
📝 apps/toolbox.es.i18n (+14 -0)
📝 apps/toolbox.fr.i18n (+14 -0)
📝 apps/toolbox.hu.i18n (+14 -0)
📝 apps/toolbox.it.i18n (+14 -0)
📝 apps/toolbox.nl.i18n (+14 -0)
📝 apps/toolbox.pt.i18n (+14 -0)
📝 poincare/Makefile (+2 -0)
poincare/include/poincare/binary_operation.h (+218 -0)
📝 poincare/include/poincare/expression.h (+24 -0)
📝 poincare/include/poincare/expression_node.h (+21 -0)
📝 poincare/include/poincare/integer.h (+16 -0)
📝 poincare/include/poincare_nodes.h (+1 -0)
poincare/src/binary_operation.cpp (+543 -0)
📝 poincare/src/expression.cpp (+1 -1)

...and 5 more files

📄 Description

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


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/UpsilonNumworks/Upsilon/pull/308 **Author:** [@joecrop](https://github.com/joecrop) **Created:** 12/27/2022 **Status:** ✅ Merged **Merged:** 11/5/2025 **Merged by:** [@Yaya-Cout](https://github.com/Yaya-Cout) **Base:** `upsilon-dev` ← **Head:** `logic-toolbox` --- ### 📝 Commits (6) - [`42d8fea`](https://github.com/UpsilonNumworks/Upsilon/commit/42d8fea8c6d8ada5b827ec9a5f057b6f6032dc08) logic toolbox with logic functions - [`fc95028`](https://github.com/UpsilonNumworks/Upsilon/commit/fc95028b57ade8fa823ac451e8732798a8904ab8) - Added clog2 function - [`81dc1bd`](https://github.com/UpsilonNumworks/Upsilon/commit/81dc1bd806c6625515d9d22379636c0d3ea557df) moved logic toolbox to the bottom of the list - [`d7f54ad`](https://github.com/UpsilonNumworks/Upsilon/commit/d7f54ad6443746da47a63e7e8b50984073c50921) removed shift functions with explicit number of bits - [`8041c7a`](https://github.com/UpsilonNumworks/Upsilon/commit/8041c7a9d0d20824713f40dc10732e4dceb00c3c) Updated french translations after feedback - [`c1f5b4a`](https://github.com/UpsilonNumworks/Upsilon/commit/c1f5b4afacae1e83e25d391b1824329a01478b9c) Merge branch 'upsilon-dev' into logic-toolbox ### 📊 Changes **25 files changed** (+1887 additions, -9 deletions) <details> <summary>View changed files</summary> 📝 `apps/calculation/additional_outputs/integer_list_controller.cpp` (+26 -4) 📝 `apps/calculation/calculation.h` (+1 -1) 📝 `apps/math_toolbox.cpp` (+30 -2) 📝 `apps/shared.universal.i18n` (+25 -0) 📝 `apps/toolbox.de.i18n` (+14 -0) 📝 `apps/toolbox.en.i18n` (+14 -0) 📝 `apps/toolbox.es.i18n` (+14 -0) 📝 `apps/toolbox.fr.i18n` (+14 -0) 📝 `apps/toolbox.hu.i18n` (+14 -0) 📝 `apps/toolbox.it.i18n` (+14 -0) 📝 `apps/toolbox.nl.i18n` (+14 -0) 📝 `apps/toolbox.pt.i18n` (+14 -0) 📝 `poincare/Makefile` (+2 -0) ➕ `poincare/include/poincare/binary_operation.h` (+218 -0) 📝 `poincare/include/poincare/expression.h` (+24 -0) 📝 `poincare/include/poincare/expression_node.h` (+21 -0) 📝 `poincare/include/poincare/integer.h` (+16 -0) 📝 `poincare/include/poincare_nodes.h` (+1 -0) ➕ `poincare/src/binary_operation.cpp` (+543 -0) 📝 `poincare/src/expression.cpp` (+1 -1) _...and 5 more files_ </details> ### 📄 Description # 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](https://user-images.githubusercontent.com/3010369/209618483-5747ea8f-d34b-4c63-a04b-6e6d5f4ee578.gif) ## 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: <img width="327" alt="negative_binary_results" src="https://user-images.githubusercontent.com/3010369/209618780-0c957b19-4ff6-4c91-b0a9-543d9d9972b3.png"> ## Functions Implemented ### Basic Logic Operations #### AND ```c // x = a & b and(a, b); // and of 2 integers // Examples and(0b11,0b01) = 1; and(0b100110,0b1011) = 2; ``` #### OR ```c // x = a | b or(a, b); // or of 2 integers // Examples or(0b11,0b01) = 3 = 0b11; or(0b100110,0b1011) = 47 = 0b101111; ``` #### XOR - Exclusive OR ```c // x = a ^ b xor(a, b); // xor of 2 integers // Examples xor(0b11,0b01) = 1; xor(0b100110,0b1011) = 45 = 0b101101; ``` #### NOT ```c // 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 ```c // x = a << s sll(a, s) // shift 'a' left by 's' bit positions // Examples sll(0b11,2) = 12 = 0b1100; ``` #### Shift Logical Right ```c // 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 ```c // 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 ```c // 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 ```c // 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 ```c // (a >> n) & 1 bit(a, n) // return the n-th bit of 'a' // Examples bit(0b1010,1) = 0; bit(0b1010,2) = 1; ``` #### Set Bit ```c // 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 ```c // 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 ```c // 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' ```c // 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. ```c 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 - Please find a lengthy discussion and planing here: https://github.com/numworks/epsilon/issues/146 - Contributors: @debrouxl, @bmuessig --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-06 13:17:00 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/Upsilon#359
No description provided.