# ridiculousfish/libdivide for Faster Integer Division

> ridiculousfish/libdivide is a header-only C and C++ library that replaces integer division with shift, add and multiply operations. It is aimed at code paths where a divisor is known at runtime, reused in a loop, or processed in a vector, with separate APIs for branchfull, branchfree, constant-divisor and SIMD division.

**ridiculousfish/libdivide** — Official git repository for libdivide: optimized integer division

- Repository: https://github.com/ridiculousfish/libdivide
- Website: http://libdivide.com
- Stars: 1,364 · Forks: 103
- Language: C++
- License: NOASSERTION
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/ridiculousfish-libdivide

## When libdivide Replaces C Integer Division

ridiculousfish/libdivide targets a specific cost rather than general arithmetic acceleration. The README states that integer division is among the slowest instructions on many CPUs, giving an example where a 64-bit division can take up to 90 clock cycles while multiplication takes about 3. The library generates an alternative calculation made from shift, add and multiply instructions. That is most useful when the program performs many divisions with the same divisor, especially when the divisor is not known until runtime and the result is reused across a loop.

The intended users are C and C++ developers working on integer-heavy loops, low-cost microcontrollers without hardware dividers, and code compiled for SSE2, AVX2, AVX512, NEON or SVE. The repository includes a single header, libdivide.h, so the central library can be incorporated without linking a separate runtime library. It also provides constant_fast_div.h and constant_fast_div.hpp for division by 16-bit constants, a case the README identifies as unoptimized by avr-gcc on 8-bit systems.

The library does not promise that every division becomes faster. A single division outside a hot path may not benefit enough to justify changing the code. The README is more precise about the cases where libdivide is likely to help, so the project should be treated as an implementation choice for a known workload rather than a compiler-wide replacement for `/`.

## The C++ Divider Object and Reused Divisor

The C++ API creates a divider object once and reuses it for each value. In the README example, the function accepts a vector of int64_t values and a runtime int64_t divisor. The usual implementation divides every element directly by divisor. The libdivide version constructs libdivide::divider<int64_t> before entering the loop, then divides each element through that object. The object holds the generated parameters needed to perform the operation without repeating the setup work for every element.

This design matches the library's central performance condition. A generated divider is useful when the same divisor appears repeatedly, because the expensive hardware division instruction is replaced by a short arithmetic sequence whose setup has already been completed. The ordinary C++ operator `/` remains the familiar interface at the call site, which makes the change small in a function that has a clear hot loop.

The documented C API follows the same separation of generation and use. A program calls libdivide_s64_gen(divisor) to create a struct libdivide_s64_t, then passes each value and a pointer to that struct to libdivide_s64_do. The API has corresponding generation and execution functions for s32, u32, s64 and u64 types. This makes libdivide usable from C code as well as C++ code, without requiring a C++ wrapper.

## Branchfull, Branchfree and Constant-Divisor Choices

The default divider is branchfull. The README says that it uses branches while computing division, although a CPU can often predict those branches correctly when the same divider remains active in a hot loop. A compiler may also apply loop-invariant code motion and move the branches outside the loop. This behavior makes the default divider a reasonable starting point for repeated division by one unchanged value.

libdivide also provides branchfree_divider<T>. It removes branch instructions from the calculation, which can help when the program iterates over an array of different dividers. If the branch pattern changes frequently, a CPU may predict the default divider's branches poorly. The branchfree type trades those branches for more instructions, and the README says it is generally faster for unsigned types than for signed types. It also states that the unsigned branchfree divider cannot be 1. That restriction must be checked before selecting this type.

For constant divisors, the repository includes macro and template based invariant division APIs. The README specifically calls out 16-bit constants because avr-gcc does not optimize that case on 8-bit systems. These headers are separate from the general runtime divider API. Choosing the constant API can therefore be more appropriate when the divisor is fixed in source code, while libdivide::divider is intended for runtime divisors.

## SIMD Support and Platform-Specific Configuration

The README documents vector division for SSE2, AVX2, AVX512, NEON, SVE and SVE2. The vector example uses std::vector<__m512i>, constructs libdivide::divider<uint32_t> from a uint32_t divisor, and divides each packed value with the operator `/`. Vector support covers 16-bit, 32-bit and 64-bit elements for signed and unsigned integers, according to the README.

Vector support is not enabled by default. A build must define one of these macros: LIBDIVIDE_SSE2, LIBDIVIDE_AVX2, LIBDIVIDE_AVX512, LIBDIVIDE_NEON, LIBDIVIDE_SVE or LIBDIVIDE_SVE2. The repository also contains a benchmark program, which the README identifies as a way to measure the possible speedup on a particular CPU. Since the library is header-only, the user is responsible for defining the correct feature macro before including the relevant API path in the compilation environment.

The platform choice affects the cost model. On x86, the README states that 32-bit vector division is much faster than 64-bit vector division because efficient 64-bit by 64-bit to 128-bit multiplication instructions are not available in the same form. It also advises trying both divider types and compiling with an appropriate native target option when evaluating whether branchfree division is more likely to be auto-vectorized. These are hardware and compiler decisions, not settings that libdivide can discover automatically.

## Building libdivide and Running Its Included Checks

The repository contains a top-level CMakeLists.txt, one test program and two benchmark programs. The README's build section does not include a complete install or build command, and it does not document a package-manager installation procedure. The project should therefore be obtained from its official repository or homepage rather than from an invented package command.

The first real use does not require a separate build step for the core library. Include libdivide.h in a C or C++ translation unit, generate or construct a divider for the exact signedness and width of the values, and place it outside the repeated division loop. The README's C++ example is the shortest path:

```cpp
#include "libdivide.h"

void divide(std::vector<int64_t>& vect, int64_t divisor)
{
    libdivide::divider<int64_t> fast_d(divisor);

    for (auto& n : vect)
        n /= fast_d;
}
```

The function should be called with a nonzero divisor and should preserve the signed division behavior required by the program. The README does not document a universal validation command for this function, so a caller should compare its results with the original integer division operation in the target test suite. For C code, the equivalent documented pattern is:

```c
#include "libdivide.h"

void divide(int64_t *array, size_t size, int64_t divisor)
{
    struct libdivide_s64_t fast_d = libdivide_s64_gen(divisor);

    for (size_t i = 0; i < size; i++)
        array[i] = libdivide_s64_do(array[i], &fast_d);
}
```

This C example requires a compatible signed 64-bit path and a divisor valid for that type. The README does not document zero-divisor behavior for libdivide, so the function should not be used with zero unless the surrounding program defines its own policy.

## Measured Claims, Licensing and Upgrade Scope

The README states that libdivide can produce speedups of up to 10x for 64-bit integer division and up to 5x for 32-bit integer division on current CPUs, and says vector division can provide even larger gains. It also provides a benchmark program for checking the result on a specific CPU. Those are documented project claims, not a guarantee for every workload. Division frequency, signedness, branch predictability, instruction set and compiler output all affect the result.

The project uses a custom license identified in the repository metadata as “Other,” with the authoritative text in LICENSE.txt. The README does not reproduce the license terms, so it does not establish whether the code can be used in proprietary products, how attribution must be presented or whether redistribution has additional conditions. Anyone integrating libdivide should read LICENSE.txt directly before shipping the header. This article does not infer permissions that the license text does not state.

The repository is not archived. Its last push was on 2026-10-04, and the listed releases include v5.4.0 on 2026-09-06, v5.3.0 on 2026-02-16 and v5.2.0 on 2025-01-25. The upgrade cost is primarily the header and API review because the core is header-only. The relevant upgrade check is whether the selected divider types, feature macros, signedness rules and benchmark workflow remain compatible with the application.

## Conclusion

Adopt ridiculousfish/libdivide when integer division is repeated, especially with unsigned values, a reused runtime divisor or a supported vector instruction set. Do not adopt it as a universal replacement for ordinary division: the README identifies signed division as slower than unsigned division, the unsigned branchfree divider cannot use 1, and vector support depends on the selected macro. Verify first whether your divisor and data types match the available divider type, then compile with the appropriate vector option and compare the generated behavior against division in the target workload. The last push was on 2026-10-04, and the latest listed release is v5.4.0 from 2026-09-06.

## FAQ

### How do I install ridiculousfish/libdivide?

The README identifies libdivide as a header-only C/C++ library, and the repository contains a top-level CMakeLists.txt. Include libdivide.h from the project and follow the repository's build files for tests and benchmarks because the README does not provide a complete installation command.

### When should I use the branchfree divider in ridiculousfish/libdivide?

The README describes branchfree division as useful when an array contains different divisors and branch prediction would be poor. It generally uses more instructions, is faster for unsigned types than signed types, and the unsigned branchfree divider cannot be 1.

### Does ridiculousfish/libdivide support vector integer division?

The README lists SSE2, AVX2, AVX512, NEON, SVE and SVE2 support, with 16-bit, 32-bit and 64-bit signed and unsigned vector division. One of the corresponding LIBDIVIDE_* macros must be defined to enable vector division.

## Sources

- [Issues](https://github.com/ridiculousfish/libdivide/issues)
- [Project website](http://libdivide.com)
- [README](https://github.com/ridiculousfish/libdivide/blob/master/README.md)
- [Releases](https://github.com/ridiculousfish/libdivide/releases)
- [ridiculousfish/libdivide on GitHub](https://github.com/ridiculousfish/libdivide)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ridiculousfish-libdivide
