Implementation:ClickHouse ClickHouse Musl Log Data
| Knowledge Sources | |
|---|---|
| Domains | Mathematics, Portability |
| Last Updated | 2026-02-08 00:00 GMT |
Overview
Precomputed lookup tables and polynomial coefficients for fast and accurate logarithm computation.
Description
This data structure provides lookup tables and polynomial coefficients used by the `log` function implementation from ARM's optimized math library. It contains 128 table entries for subinterval decomposition, polynomial coefficients for different accuracy requirements, and optional high-precision correction tables for non-FMA architectures. The tables enable fast range reduction by splitting the input into `2^k * z` where z is looked up in the table, allowing the log computation to use fast polynomial approximations on small values.
Usage
This data is used internally by optimized logarithm implementations to achieve sub-ULP accuracy with minimal computational overhead, particularly in hot paths where logarithm performance is critical.
Code Reference
Source Location
- Repository: ClickHouse
- File: base/glibc-compatibility/musl/log_data.c
- Lines: 1-328
Signature
// Data structure definition (from log_data.h)
struct log_data {
double ln2hi;
double ln2lo;
double poly[N_POLY]; // Polynomial for small range
double poly1[N_POLY1]; // Higher-accuracy polynomial
struct {
double invc; // 1/c for subinterval
double logc; // log(c) for subinterval
} tab[N_TABLE];
struct {
double chi; // High part of c
double clo; // Low part of c for extra precision
} tab2[N_TABLE]; // Only for non-FMA
};
extern const struct log_data __log_data;
Import
#include "log_data.h"
// Access via: __log_data
I/O Contract
| Data Component | Purpose | Precision | Table Size |
|---|---|---|---|
| ln2hi, ln2lo | High and low parts of ln(2) | Split for extra precision | 2 doubles |
| poly[5] | Polynomial coefficients | 0x1.c04d76cp-63 relative error | 5 coefficients |
| poly1[11] | Extended polynomial | log(1+x)| > 2^-4 | 11 coefficients |
| tab[128] | Inverse and log values | Each entry: {1/c, log(c)} | 128 × 2 doubles |
| tab2[128] | High-precision c values | {c_high, c_low} for non-FMA | 128 × 2 doubles (optional) |
Usage Examples
// Fast log implementation using the tables
double fast_log(double x) {
uint64_t ix = asuint64(x);
// Extract exponent and mantissa
uint32_t tmp = (ix - OFF) >> (52 - LOG_TABLE_BITS);
int k = (int64_t)tmp >> LOG_TABLE_BITS; // exponent
int i = tmp % N; // table index
// Range reduction: x = 2^k * z
double z = asdouble(ix - (tmp & 0xfffULL << 52));
// Table lookup
double invc = __log_data.tab[i].invc;
double logc = __log_data.tab[i].logc;
// Compute r = z/c - 1
double r = z * invc - 1.0;
// Polynomial evaluation
double r2 = r * r;
double y = __log_data.poly[0] * r + __log_data.poly[1];
y = y * r2 + __log_data.poly[2];
// ... continue polynomial evaluation
// Combine: k*ln2 + log(c) + poly(r)
double ln2 = __log_data.ln2hi + __log_data.ln2lo;
return k * ln2 + logc + r + r2 * y;
}
// Access constants for other computations
double get_ln2_high_precision() {
// Get ln(2) with extra precision
return __log_data.ln2hi + __log_data.ln2lo;
}
// Use in logarithm-based functions
double log1p_fast(double x) {
// For small x, use polynomial directly
if (fabs(x) < 0x1p-4) {
double x2 = x * x;
double y = __log_data.poly[0];
for (int i = 1; i < 5; i++) {
y = y * x + __log_data.poly[i];
}
return x + x * x2 * y;
}
return fast_log(1.0 + x);
}
// Extract table entry for specific range
void get_log_table_entry(int index, double *invc, double *logc) {
if (index >= 0 && index < 128) {
*invc = __log_data.tab[index].invc;
*logc = __log_data.tab[index].logc;
}
}