#define NUMKONG_CONSTEXPR NUMKONG_MAYBE_UNUSED_ NUMKONG_C_INLINE_ It is constexpr from C++20.
With CMake FetchContent:
include(FetchContent)
FetchContent_Declare(
numkong
GIT_REPOSITORY https://github.com/ashvardanian/NumKong.git
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(numkong)
target_link_libraries(my_target PRIVATE numkong::header) # or numkong::static, numkong::sharedVendored:
add_subdirectory(external/NumKong)
target_link_libraries(my_target PRIVATE numkong::header) # or numkong::static, numkong::sharednumkong::static and numkong::shared exist when NUMKONG_BUILD_SHARED is on, the default only for a top-level build.
An installed NumKong provides the same targets through find_package(numkong CONFIG REQUIRED).
By default the headers declare every public function and the library defines it, each kernel once, in the unit of its capability. numkong::header sets NUMKONG_HEADER_ONLY=1 instead: every kernel compiles into your translation unit, and every dispatch point and finder returns nk_missing_library_k, so a header-only build calls a capability’s kernel, like nk_dot_f32_haswell, directly.
The build enforces C99 for the C layer and C++20 for the C++ layer. CONTRIBUTING.md lists the CMake presets and options, and its cross-compilation section the toolchain files in cmake/ with a recipe for each target.
A translation unit linking numkong::static or numkong::shared sees declarations only, while numkong::header defines NUMKONG_HEADER_ONLY=1 and compiles the kernels inline.
The library compiles every capability whose probe in probes/ compiles, each scoped to its kernels by target pragmas, and dispatches between them by runtime detection.
LASX and POWER9 scope that way only under GCC 15 or newer; Clang’s intrinsics headers stay closed without -mlasx or -mcpu=power9.
Header-only units enable the capabilities their own flags name.
NUMKONG_CONSTEXPRInternal helper that callers can fold at compile time, and that CUDA kernels can call through --expt-relaxed-constexpr.#define NUMKONG_CONSTEXPR NUMKONG_MAYBE_UNUSED_ NUMKONG_C_INLINE_ It is constexpr from C++20.
NUMKONG_APICompiles every kernel into this translation unit and stubs every dispatch point and finder with nk_missing_library_k, instead of linking them from the NumKong library.#define NUMKONG_API Every public function: header-inline in header-only builds, otherwise defined once in the library. Windows DLLs export every symbol through CMake, so no import or export spelling.
NUMKONG_DEBUGDebug builds check the library's invariants with nk_assert_, defaulting from DEBUG or _DEBUG.#define NUMKONG_DEBUG 0 NUMKONG_ALLOW_ISA_REDIRECTAllow SIMD kernels to redirect small inputs to serial implementations.#define NUMKONG_ALLOW_ISA_REDIRECT 1 Enabled by default for production use. Tests and benchmarks may disable this to isolate SIMD path behavior.
NUMKONG_MULTIVERSIONED0 folds each dispatch table to its best kernel; 1, the default, keeps every compiled one.#define NUMKONG_MULTIVERSIONED 1 NUMKONG_NULLNUMKONG_NULL, analogous to NULL, so headers need not pull in <stddef.h>.#define NUMKONG_NULL ((void *)0) __null gives better null-pointer diagnostics where the compiler provides it. The nullptr branch matters for MSVC C++: unlike C, it forbids a void * arm in a typed conditional, so (void *)0 there fails to compile.
NUMKONG_NATIVE_F16Half-precision (16-bit) IEEE 754 float.#define NUMKONG_NATIVE_F16 0 Layout: sign(1) + exponent(5) + mantissa(10), bias=15. Range: ±65 504, epsilon at 1.0 ≈ 9.77×10⁻⁴. 30 722 of 63 488 finite values (48.4%) in [−1, +1].
unsigned short by default, on every compiler and architecture.NUMKONG_NATIVE_F16=1: __fp16 on Arm, _Float16 elsewhere.The type crosses the exported ABI by value — nk_f16_sqrt_best, nk_f16_order_best — and a native half is passed in a different register class than unsigned short. Deriving it from -march, as this once did, let each consumer reach its own answer: Swift's header import sees a native half on Apple silicon while the C sources it links were built unsigned short, and rust/scalar.rs binds u16 outright. Enabling it is a decision for a whole build, never for one translation unit, so the default cannot depend on flags.
NUMKONG_NATIVE_BF16BFloat16 (16-bit) float — truncated IEEE 754 single-precision.#define NUMKONG_NATIVE_BF16 0 Layout: sign(1) + exponent(8) + mantissa(7), bias=127. Same dynamic range as f32, epsilon ≈ 7.81×10⁻³. 32 514 of 65 280 finite values (49.8%) in [−1, +1]. Wider range than f16 but lower precision.
unsigned short by default, on every compiler and architecture.NUMKONG_NATIVE_BF16=1: __bf16 on GCC and Clang. See nk_f16_t for why this is opt-in.The compilers have added __bf16 support in compliance with the x86-64 psABI spec. The motivation for this new special type is summed up as:
"Currently @c __bfloat16 is a typedef of short, which creates a problem where the compiler does not raise any alarms if it is used to add, subtract, multiply or divide, but the result of the calculation is actually meaningless. To solve this problem, a real scalar type @c __Bfloat16 needs to be introduced. It is mainly used for intrinsics, not available for C standard operators. @c __Bfloat16 will also be used for movement like passing parameter, load and store, vector initialization, vector shuffle, and etc. It creates a need for a corresponding psABI."
Apple Clang has hard time with bf16.