adept-digital / int-utils
Utilities for emulating WebAssembly 32-bit and 64-bit integer operations in PHP.
Installs: 1
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/adept-digital/int-utils
Requires
- php-64bit: >=8.4
Requires (Dev)
- phpunit/phpunit: ^12
README
Utilities for emulating WebAssembly 32-bit and 64-bit integer operations in PHP. These may be useful for porting an application or library from C, C++, or other languages.
Requirements
This package requires a 64-bit build of PHP 8.4 or later.
There is no dependency on external Composer packages or PHP extensions.
Installation
Install via Composer.
composer require adept-digital/int-utils
Usage
There are two classes with near-identical interfaces:
- \AdeptDigital\IntUtils\Int32
- \AdeptDigital\IntUtils\Int64
The following operations are provided:
- add(int $a, int $b): int: Integer addition.
- sub(int $a, int $b): int: Integer subtraction.
- mul(int $a, int $b): int: Integer multiplication.
- div_s(int $a, int $b): int: Signed integer division. 1
- div_u(int $a, int $b): int: Unsigned integer division.
- rem_s(int $a, int $b): int: Signed integer modulo. 1
- rem_u(int $a, int $b): int: Unsigned integer modulo.
- eq(int $a, int $b): int: Equal comparison. 2
- eqz(int $a): int: Equals zero test. 2
- ne(int $a, int $b): int: Not equal comparison. 2
- lt_s(int $a, int $b): int: Signed less than comparison. 2
- lt_u(int $a, int $b): int: Unsigned less than comparison.
- le_s(int $a, int $b): int: Signed less than or equal comparison. 2
- le_u(int $a, int $b): int: Unsigned less than or equal comparison.
- gt_s(int $a, int $b): int: Signed greater than comparison. 2
- gt_u(int $a, int $b): int: Unsigned greater than comparison.
- ge_s(int $a, int $b): int: Signed greater than or equal comparison. 2
- ge_u(int $a, int $b): int: Unsigned greater than or equal comparison.
- and(int $a, int $b): int: Bitwise AND. 1
- or(int $a, int $b): int: Bitwise OR. 1
- xor(int $a, int $b): int: Bitwise XOR. 1
- shl(int $a, int $b): int: Shift left. 2
- shr_s(int $a, int $b): int: Signed (arithmetic) shift right. 2
- shr_u(int $a, int $b): int: Unsigned (logical) shift right.
- rotl(int $a, int $b): int: Rotate left.
- rotr(int $a, int $b): int: Rotate right.
- clz(int $a): int: Count leading zeros.
- ctz(int $a): int: Count trailing zeros.
- popcnt(int $a): int: Population count.
- extend8_s(int $a): int: Extend the sign of the least significant 8 bits.
- extend16_s(int $a): int: Extend the sign of the least significant 16 bits.
- extend32_s(int $a): int: Extend the sign of the least significant 32 bits. 3
32-bit representation
PHP has no 32-bit integer type, so 32-bit numbers are represented in 64-bit, but are limited to the range of a signed
32-bit integer (-2,147,483,648 to 2,147,483,647). For example, 4,294,967,295 (2**32-1) should be represented as
-1. Using numbers outside this range will cause a RangeException to be thrown, unless assertions are disabled, in
which case the result is undefined.
To correctly format an unsigned 32-bit integer, unset the most significant 32 bits:
use \AdeptDigital\IntUtils\Int32; echo Int32::add(Int32::MAX, 1) & 0xFFFF_FFFF; // output: 2147483648
64-bit representation
PHP has no unsigned integer type, so numbers larger than PHP_INT_MAX will appear to be negative.
To correctly format an unsigned integer, use printf() or sprintf():
use \AdeptDigital\IntUtils\Int64; printf('%u', Int64::add(Int64::MAX, 1)); // output: 9223372036854775808
Contributing
All contributions are welcome. If you would like to work on a new feature, consider creating an issue before starting.
TODO
- Add benchmarks and benchmark on different machines.
- Add alternative implementations (eg: GMP, FFI, custom extension).
- Add feature detection for alternative implementations.
License
Copyright 2025 David Gallagher david@adeptdigital.com.au.
The package is licensed under the GNU Lesser General Public License 3.0 or later.