Skip to content

Migrating to 0.7.0

This guide covers upgrading from 0.6.0 to 0.7.0. See the release overview.

The former full-library CMake alias and forwarding header paths are removed. Version 0.7.0 introduces the stable float32 core API v1, reusing the existing quantization algorithms and code interpretation. Persisted index formats remain compatible with 0.6.0. Index count semantics are unified as described below. Rebuild C++ consumers against 0.7.0; no cross-version C++ binary ABI is promised.

Choose a component explicitly

find_package(rabitqlib CONFIG REQUIRED COMPONENTS index)
target_link_libraries(my_app PRIVATE rabitqlib::index)

Replace rabitqlib::rabitqlib with the smallest component needed:

Target Contains Dependency
rabitqlib::core Encoding, single-vector estimation, rotation and packing Numerical helpers and essential SIMD
rabitqlib::fastscan Batch layouts, packing/encoding adapters and FastScan/HACC scoring core
rabitqlib::index IVF-RaBitQ, HNSW-RaBitQ, SymphonyQG and clustering fastscan and core
rabitqlib::python Existing Python ANN extension; build-tree alias only index

The old implementation target rabitq_headers is also removed. C++ libraries remain static. Python still uses import rabitqlib; it is not an exported C++ package component.

For a numerical library without ANN or OpenMP:

cmake -S . -B build-core -DCMAKE_BUILD_TYPE=Release \
  -DRABITQ_BUILD_INDEX=OFF -DRABITQ_BUILD_FASTSCAN=OFF \
  -DRABITQ_USE_OPENMP=OFF -DRABITQ_BUILD_SAMPLES=OFF \
  -DRABITQ_ENABLE_NATIVE_OPTIMIZATION=OFF \
  -DCMAKE_INSTALL_PREFIX="<new-empty-prefix>"
cmake --build build-core --parallel
cmake --install build-core

Enable FastScan separately if needed. ANN/Python still require OpenMP. A core-only installation contains core and its header dependencies, including bundled Eigen; it does not install FastScan, index, clustering or vendored hnswlib headers. Source-tree presence of disabled modules does not make them part of the installed component.

Use a fresh install prefix during migration. CMake installation does not remove files left by an older package, and stale headers can conceal a missing migration. Point each consumer to the intended prefix and rebuild its CMake cache/objects accordingly.

Replace old includes

Paths below are relative to rabitqlib/. Include the modules actually used instead of relying on transitive declarations from a former umbrella header.

Removed header Replacement
quantization/rabitq.hpp core/encoder.hpp for per-vector encoding; fastscan/encoder.hpp for batch encoding; fastscan/fastscan.hpp for accumulation/LUT functions
quantization/data_layout.hpp core/data_layout.hpp for per-vector maps; fastscan/data_layout.hpp for BatchDataMap, QGBatchDataMap and their const variants
quantization/pack_excode.hpp core/pack_excode.hpp
utils/rotator.hpp core/rotator.hpp
index/query.hpp core/query.hpp for single vectors; fastscan/query.hpp for batches
index/estimator.hpp core/estimator.hpp for single vectors; fastscan/estimator.hpp for batches
index/lut.hpp Use the batch-query interfaces in fastscan/query.hpp
defines.hpp Include core/metric.hpp, core/types.hpp or index/types.hpp according to the types used; internal Eigen aliases live in core/detail/eigen.hpp
core/pack_codes.hpp fastscan/pack_codes.hpp for 32-vector batch packing/unpacking

New integrations should prefer core/api.hpp and its versioned, storage-neutral interface. Migrating an existing low-level caller to canonical headers does not require changing its code bytes or factors. Batch scoring requires linking FastScan; advanced core headers do not import that component for convenience.

Public and implementation interfaces

Encoding and shared types

The advanced two-factor batch adapter has also moved: include fastscan/data_layout.hpp for QGBatchDataMap / ConstQGBatchDataMap, and fastscan/encoder.hpp for quant::quantize_qg_batch. It is shared by FastScan, clustering and SymphonyQG, so it does not belong exclusively to the index module. Its code packing, factor order and record sizes are unchanged. The three-factor BatchDataMap / ConstBatchDataMap also belong to fastscan/data_layout.hpp. Include fastscan/encoder.hpp for quantize_one_batch and quantize_split_batch, and link rabitqlib::fastscan when using this format. The fixed batch size, permutation and pack_codes/unpack_codes are all in fastscan/pack_codes.hpp; no FastScan declarations remain in core.

Core retains single-vector BinDataMap, ExDataMap and BaseDataMap, per-vector packing and generic encoding loops that do not impose a 32-vector format. Shared unaligned value/array access resides in utils/packed.hpp. The v1 SplitPacked layout is a per-vector sign/extra representation and remains part of core.

index/types.hpp supplies PID, kPidMax and AnnCandidate without importing Eigen. Identifier width, candidate layout and marker semantics are unchanged. The advanced exact_nn helper now requires index/detail/exact_nn.hpp instead of utils/space.hpp. Metric definitions move to core/metric.hpp; ScalarQuantizerType now resides in core/types.hpp. The unused BIT_ID macro and internal LOWBIT macro are removed. The new core/api.hpp exposes the stable v1 interface; it was not present in 0.6.0.

Only core/api.hpp's documented v1 surface has the new source-stability guarantee. Other core/fastscan/index module interfaces remain available as advanced interfaces; they are not implicitly frozen by that promise.

Query metric arguments use MetricType. SplitSingleQuery no longer accepts integer arguments; pass METRIC_L2 or METRIC_IP.

Index headers

IVF-RaBitQ, HNSW-RaBitQ and SymphonyQG operations now compile into rabitqlib::index. Their main headers no longer import numerical implementations, search scratch, Eigen or hnswlib. This implementation move preserves method signatures and file formats.

Include the types you use explicitly:

Types Header
RotatorType, quant::RabitqConfig, scalar quantizer choices core/types.hpp
ivf::InitializerType index/ivf/types.hpp
SymphonyQG query and buffer helpers fastscan/query.hpp, index/detail/buffer.hpp, index/detail/visited_set.hpp
Internal SearchScratch index/symqg/detail/search_scratch.hpp

Explicit includes of core/rotator.hpp, core/encoder.hpp and index/ivf/initializer.hpp still expose their associated types. HNSW-RaBitQ backend search templates are private in src/index/hnsw_search_impl.hpp.

Removed HNSW-RaBitQ members

HNSW-RaBitQ no longer exposes HierarchicalNSW::rawDataPtr_, ResultRecord, Candidate, or BoundedKNN as public interfaces. The construction pointer and search helpers are private implementation details. This is a C++ source compatibility break: code that accessed those members must stop doing so. Pass construction input through construct() and consume the distance/label pairs returned by search(); there are no public replacements for the internal candidate types. Construction borrows its input buffers only until the synchronous call returns or throws. This visibility change does not alter persisted indexes or the Python API.

Internal headers

Internal headers have explicit ownership:

Implementation Location
Exact encoder scratch and quantization implementation core/detail/
Eigen aliases used by numerical implementations core/detail/eigen.hpp
Core SIMD declarations core/detail/simd/
FastScan SIMD declarations and LUT implementation fastscan/detail/
FastScan batch-encoder adapter fastscan/detail/encoder.hpp
HNSW-RaBitQ dispatch, search buffers, visited sets and shared scheduling index/detail/
Non-template dispatcher implementation and private resolver src/simd/, src/fastscan/ and src/index/

The old simd/* public paths, fastscan/{simd,estimator_dispatch,lut}.hpp, quantization/rabitq_impl.hpp and index-specific utils/{buffer,hashset,visited_*}.hpp paths are removed. Callers using these internals should migrate to supported module operations; direct use of detail/ binds a caller to that implementation revision. Some detail headers must be installed because public templates include them. Installation does not turn them into a stable extension API.

HNSW-RaBitQ and IVF-RaBitQ share index/detail/parallel_for.hpp. Callers relying on HNSW-RaBitQ to import the IVF-RaBitQ initializer must include it explicitly. Scheduling behavior is unchanged; custom thread-pool and SIMD registration remain unsupported.

Unified index counts

All three indexes now share the count contract in C++ and Python.

Compared with the 0.6.0 Python API, IVF-RaBitQ adds num_points and num_stored_points, HNSW-RaBitQ adds num_stored_points, and SymphonyQG adds max_elements and num_stored_points.

HNSW-RaBitQ num_points now excludes removed records. Use num_stored_points for ID bounds, append offsets, and minimum resize capacity. Use num_points for a live count, without subtracting a separate deletion counter.

The IVF-RaBitQ constructor keyword max_elements still specifies the required initial build size. SymphonyQG's C++ num_vertices() still returns the configured graph size for builders. Existing index files need no conversion: loading recovers counts from their removal markers.

Downstream rollout

Pin 0.7.0 in downstream migration PRs and validate the affected integration entry points with their maintainers. Projects that have not migrated can continue pinning their supported old release.

The conformance suite preserves the frozen v1 source consumer and historical index fixtures. It also verifies component link closure, absent retired targets/headers, standalone installed headers, and independent add_subdirectory/FetchContent/package consumers. Historical release notes and the v0.5.2 fixture generator deliberately retain their old target names: those documents/tools describe or build the historical release.