PHP
Rotate Functions
64-bit Conversion
Programming
Software Development

Converting Complex PHP Rotate Functions to Work in 64-bit

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Bit-rotation code that behaves correctly on 32-bit PHP can break on a 64-bit runtime because PHP integers are signed and platform-dependent. The usual goal is not "use 64-bit arithmetic everywhere," but "preserve the original fixed-width bit behavior." For cryptographic or hashing code, that means you must control masking and right-shift semantics explicitly instead of trusting native integer behavior.

Why rotate code breaks on 64-bit PHP

Most rotation helpers were written with a fixed word size in mind, often 32 bits. On a 64-bit build of PHP:

  • Integers are wider
  • Right shift is arithmetic, not logical
  • Sign extension can pollute the high bits
  • Intermediate results can exceed the intended word width

So this naïve helper is unsafe:

php
1function rotl_bad(int $value, int $shift): int
2{
3    return ($value << $shift) | ($value >> (32 - $shift));
4}

It does not force 32-bit behavior, and the right shift can keep the sign bit instead of acting like an unsigned logical shift.

Build a safe 32-bit logical right shift

The first step is creating a helper that behaves like an unsigned 32-bit right shift.

php
1function urshift32(int $value, int $shift): int
2{
3    $value &= 0xFFFFFFFF;
4    $shift &= 31;
5
6    if ($shift === 0) {
7        return $value;
8    }
9
10    return ($value >> $shift) & ~(1 << (31 - $shift + 1));
11}

A more readable and reliable version avoids edge-case confusion by building the mask directly:

php
1function urshift32(int $value, int $shift): int
2{
3    $value &= 0xFFFFFFFF;
4    $shift &= 31;
5
6    if ($shift === 0) {
7        return $value;
8    }
9
10    $shifted = $value >> $shift;
11    $mask = (1 << (32 - $shift)) - 1;
12
13    return $shifted & $mask;
14}

The key idea is that the result must be trimmed back to the intended 32-bit unsigned range.

Implement fixed-width rotate helpers

Once logical right shift is under control, the rotate functions become predictable.

php
1function rotl32(int $value, int $shift): int
2{
3    $value &= 0xFFFFFFFF;
4    $shift &= 31;
5
6    if ($shift === 0) {
7        return $value;
8    }
9
10    return (($value << $shift) | urshift32($value, 32 - $shift)) & 0xFFFFFFFF;
11}
12
13function rotr32(int $value, int $shift): int
14{
15    $value &= 0xFFFFFFFF;
16    $shift &= 31;
17
18    if ($shift === 0) {
19        return $value;
20    }
21
22    return (urshift32($value, $shift) | (($value << (32 - $shift)) & 0xFFFFFFFF)) & 0xFFFFFFFF;
23}
24
25printf("%08X\n", rotl32(0x12345678, 8));
26printf("%08X\n", rotr32(0x12345678, 8));

Those helpers preserve 32-bit word behavior even when PHP itself is running with 64-bit signed integers.

Be clear about whether you need 32-bit or true 64-bit words

Many algorithms executed on 64-bit PHP still require 32-bit operations because the algorithm definition itself is 32-bit. In that case, the solution is explicit masking, not wider integers.

If you truly need unsigned 64-bit rotation semantics, native PHP integers become much harder to use correctly because signed overflow and right-shift rules are not designed for low-level unsigned arithmetic. For true 64-bit bit-twiddling, many developers switch to:

  • GMP or another big-integer extension
  • A C extension
  • A representation based on two 32-bit halves

That is often safer than trying to force native signed integers into an unsigned 64-bit role.

Common Pitfalls

The biggest mistake is assuming >> is a logical right shift in PHP. It is not. It preserves the sign bit, which is exactly what bit-rotation code usually does not want.

Another issue is forgetting to mask intermediate results. Even if the final line masks the output, wrong high bits may already have influenced the expression.

Developers also confuse "running on a 64-bit machine" with "the algorithm should now use 64-bit words." Those are different questions. The algorithm's word size should come from its specification, not from the CPU architecture.

Finally, do not trust rotate helpers without tests. For low-level code, print known hex vectors and compare them with reference outputs.

Summary

  • Rotate code often breaks on 64-bit PHP because PHP integers are signed and platform-dependent.
  • Preserve the algorithm's intended word size with explicit masks.
  • Implement a logical unsigned right shift before writing rotate helpers.
  • For 32-bit algorithms, keep 32-bit semantics even on 64-bit PHP.
  • For true unsigned 64-bit arithmetic, consider GMP, extensions, or split-word representations.

Course illustration
Course illustration

All Rights Reserved.