A C library implementing bitwise, numerical, and logical operations using a custom 16-bit binary representation. This project demonstrates how to implement fundamental computer operations using only basic logical operators.
libbin provides a complete set of arithmetic and logical operations implemented using a custom bin type that represents 16-bit values as arrays of individual bits. The library is built with strict constraints to demonstrate fundamental computer science concepts.
The library uses a custom bin type defined in src/16.h:
typedef struct bin {
bin_int_t bits[BIN_BITS]; // BIN_BITS = 16
} bin;Each bin represents a 16-bit value where each bit is stored as a separate element in the array.
binZERO: All bits set to 0binONE: Only the least significant bit set to 1binMAX: All bits set to 1
The Challenge: Implement all computer operations using only the most basic logical operators. This project deliberately takes "the hard way" to demonstrate how computers work from first principles.
This isn't about efficiencyโit's about understanding. By forcing ourselves to implement everything using only logical operators, we:
- Uncover the fundamentals: Show how hardware bitwise operations can be built from logical operations
- Historical perspective: Mirror how early computers had to implement arithmetic
- Constraint-driven creativity: Force elegant solutions under severe limitations
- Educational journey: Understand what's happening "under the hood" of modern computers
Ultra-Pure Challenge: Build arithmetic using only bit comparison and bit setting
Primary Rule: Only these operations allowed:
- Logical operations:
&&(AND),||(OR),!(NOT) - Bit access: Reading and writing individual
bits[i]elements - Loops and conditionals:
for,while,iffor control flow - Array indexing: Only for accessing bit positions
- Loop control operators:
++,--,<,>,<=,>=are acceptable for loop iteration to avoid circular dependencies
Specific Constraints:
- Type restriction: Only the custom
bintypeโno direct integer arithmetic on results - No bitwise operators: Forbidden:
&,|,^,<<,>>,~ - No arithmetic shortcuts: Build all math from logical operations
- Interface exception:
binNew()andbinToInt()use minimal C operators (/,%) for integer-to-binary conversion only
We attempt to build ALL arithmetic operations using only bit comparison and bit setting operationsโthe most fundamental level possible.
What This Means:
- Every operation (
binAdd,binMultiply,binDivide) uses only logical operations on individual bits - No shortcuts: Even simple tasks like "shift left" become manual array element copying
- Interface boundary: Only
binNew()/binToInt()are allowed minimal violations to cross the integerโbinary boundary - Pure computation: Once you have
binnumbers, everything uses your constraint-faithful operations - Loop control exception: Foundation functions (like
binEQ,binAdd) use simple integer loops to prevent circular dependencies, while higher-level functions can use bin arithmetic for loop control
What We Successfully Achieve โ
- โ Pure bit manipulation: All core operations built from logical operations only
- โ Hardware simulation: Mimics how CPUs work at the transistor level
- โ Zero shortcuts: No reliance on built-in arithmetic beyond interface functions
- โ Educational purity: Shows computation from absolute fundamentals
Here's how the constraints force creative solutions:
Bitwise operations using logical operators:
// NOT operation (src/bitwise.c:33)
r.bits[i] = !x.bits[i]; // Using logical NOT
// AND operation (src/bitwise.c:108)
r.bits[i] = x.bits[i] && y.bits[i]; // Using logical AND
// XOR - clever use of inequality! (src/bitwise.c:126)
r.bits[i] = x.bits[i] != y.bits[i]; // XOR as "different values"Addition without bitwise operators:
// Binary addition extracting carry (src/math.c:12-14)
bin_int_t sum = x.bits[i] + y.bits[i] + carry;
r.bits[i] = sum % 2; // Extract result bit (odd/even test)
carry = sum / 2; // Extract carry bitManual bit shifting instead of <</>>:
// Left shift by copying array elements (src/bitwise.c:46-48)
for (bin_int_t i = 0; i < BIN_BITS - shift_amount; i++) {
r.bits[i + shift_amount] = x.bits[i]; // Manual bit movement
}Comparison using logical operations:
// Greater-than using logical operators (src/boolean.c:46)
return x.bits[i] && !y.bits[i]; // "x is 1 AND y is 0"Performance Trade-offs:
- Memory overhead: Each bit uses 16 bits of storage (1600% overhead!)
- Speed penalty: Logical loops vs. single hardware instructions
- Algorithm complexity: Forces O(n) operations for O(1) hardware ops
Educational Benefits:
- Algorithm exposure: See classical multiplication, division, exponentiation algorithms
- Bit-level understanding: Understand how
+really works under the hood - Historical appreciation: Experience early computer limitations
- Constraint thinking: Learn to solve problems within tight boundaries
Algorithmic Consequences: The constraints force us to use classical algorithms instead of shortcuts:
- Multiplication: Shift-and-add algorithm instead of
*operator - Division: Long division bit-by-bit instead of
/operator - Exponentiation: Binary exponentiation (square-and-multiply)
- Square root: Newton-Raphson method with integer arithmetic
- Shifting: Manual array copying instead of bit shift operators
Why: This project proves you can build a complete arithmetic system using binary operations. Computers already have hardware for math and we have standard library functions for it too but this project recreates it as though they don't even exist, except for the most basic ones. We can do all sorts of boolean logic if we can just do extremely simple things, like comparing individual bits in if statements and for loops.
- NOT (
binNOT): Bitwise negation - AND (
binAND): Bitwise AND - OR (
binOR): Bitwise OR - XOR (
binXOR): Bitwise XOR - Most Significant Bit (
binMSB,binMSBi): Get MSB value or index - Least Significant Bit (
binLSBi): Get LSB index - Shift Operations:
- Left shift (
binShiftL,binShiftL1) - Right shift (
binShiftR,binShiftR1) - Shift out zeros (
binShiftOutZerosL,binShiftOutZerosR)
- Left shift (
- Rotate operations (
binRotateL,binRotateR): Rotate a numbers bits around left and right.
- Addition (
binAdd,binIncrement) - Subtraction (
binSubtract,binDecrement) - Multiplication (
binMultiply) - Division (
binDivide) - Modulus (
binModulus) - Exponentiation (
binPow)
- Equality (
binEQ,binEQZero,binEQOne,binEQMax) - Comparison (
binGT,binLT,binGTEQ,binLTEQ) - Utility macros:
binMin,binMax
- Creation:
binNew()- Create bin from integer - Conversion:
binToInt()- Convert bin to integer - Display:
binPrint(),binIntPrint()- Pretty printing - Random:
binRand(),binRandr()- Random number generation
- Bitwise
- Bit counting: binPopCount() - Count set bits (population count)
- Bit scanning: binFindFirstSet(), binFindLastSet() - Find first/last set bit
- Math
- Logarithm functions: binLog2(), binLog10() - Binary and decimal logarithms
- Square root: binSqrt() - Integer square root
- Factorial: binFactorial() - For small numbers (up to 8)
- GCD/LCM: binGCD(), binLCM() - Greatest common divisor, least common multiple
- Prime checking: binIsPrime() - Test if number is prime
- Next/Previous prime: binNextPrime(), binPrevPrime()
- Clang compiler
- Make
# Build the library
make
ls build/libbin.so
# Run all tests
make test
# Clean build artifacts
make cleanThe project includes comprehensive unit tests:
bin_tests.c- Core functionality testsbitwise_tests.c- Bitwise operation testsmath_tests.c- Mathematical operation testsboolean_tests.c- Boolean logic tests
#include "src/bin.h"
#include "src/bitwise.h"
#include "src/math.h"
#include "src/boolean.h"
int main() {
// Create binary numbers
bin a = binNew(5); // 0000000000000101
bin b = binNew(3); // 0000000000000011
// Perform operations
bin sum = binAdd(a, b); // 8
bin product = binMultiply(a, b); // 15
bin xored = binXOR(a, b); // 6
// Display results
binPrint(a);
binPrint(b);
binPrint(sum);
return 0;
}libbin/
โโโ src/ # Source files
โ โโโ 16.h # Core type definitions
โ โโโ bin.h # Core utilities
โ โโโ bitwise.h # Bitwise operations
โ โโโ math.h # Mathematical operations
โ โโโ boolean.h # Boolean logic
โโโ test/ # Unit tests
โโโ build/ # Build artifacts
โโโ bin/ # Executables
โโโ Makefile # Build configuration
This project demonstrates:
- How computers perform arithmetic using only logical operations
- Implementation of fundamental algorithms from first principles
- Clean separation of concerns in library design
- Comprehensive testing practices
- Constraint-based programming challenges
When adding new features:
- Follow the implementation constraints strictly
- Write unit tests for all new functionality
- Update this README to reflect new capabilities
- Ensure all tests pass before submitting