Implement and understand Takum arithmetic - a logarithmic tapered-precision number format using base βe...
Takum is a logarithmic tapered-precision number format that uses base βe instead of base 2. It provides superior dynamic range while maintaining precision guarantees that IEEE 754 floats and posits cannot match.
Activate this skill when:
| Variant | Types | Significand Domain | Best For |
|---|---|---|---|
| Logarithmic (standard) | takum_log8/16/32/64 |
Logarithmic | Multiplication, division, powers |
| Linear | takum8/16/32/64 |
Linear | Addition, subtraction |
Recommendation: Use logarithmic Takums unless your workload is addition-heavy.
Β±(βe^-255, βe^255) β Β±(4.2Γ10^-56, 2.4Γ10^55)
This range is identical for takum16, takum32, and takum64.
βββββββ¬ββββββββββββ¬ββββββββββββββββββ¬βββββββββββββββββββββββββββ
β S β D β RβRβRβ β Characteristic β Mantissa β
β 1b β 1bβ 3b β r bits β remaining bits β
βββββββ΄ββββββββββββ΄ββββββββββββββββββ΄βββββββββββββββββββββββββββ
| Value | Representation |
|---|---|
| Zero | All bits 0: 0b00000000β¦ |
| NaR (Not a Real) | Sign=1, rest zeros: 0b10000000β¦ |
| One | Type-specific positive encoding |
For logarithmic Takum with decoded value l:
value = sign Γ βe^l = sign Γ e^(l/2)
| Direction | Characteristic Range |
|---|---|
| D = 0 | c β {-255, β¦, -1} |
| D = 1 | c β {0, β¦, 254} |
| Regime r | Mantissa bits p | Characteristic bits |
|---|---|---|
| 0 | 11 | 0 |
| 1 | 10 | 1 |
| 2 | 9 | 2 |
| β¦ | β¦ | β¦ |
| 7 | 4 | 7 |
Minimum precision guarantee: At least (n-12) mantissa bits for any value.
takum_neg(t) = -t // Standard two's complement negation
// 1/x is just negating the logarithmic value!
takum_log_inversion(t) = (t ^ 0x7FFF...FF) + 1 // XOR non-sign bits, add 1
// In log domain: multiply = add exponents
l_result = l(a) + l(b)
sign = (a < 0) != (b < 0)
// In log domain: divide = subtract exponents
l_result = l(a) - l(b)
sign = (a < 0) != (b < 0)
Requires Gaussian logarithm computation β convert to linear domain, compute, convert back.
Use signed integers matching the bit width:
typedef int8_t takum_log8;
typedef int16_t takum_log16;
typedef int32_t takum_log32;
typedef int64_t takum_log64;
NaR is the minimum signed value (two's complement minimum):
#define TAKUM_LOG8_NAR INT8_MIN // -128
#define TAKUM_LOG16_NAR INT16_MIN // -32768
#define TAKUM_LOG32_NAR INT32_MIN // -2147483648
#define TAKUM_LOG64_NAR INT64_MIN // -9223372036854775808
// Maps (D|Rβ|Rβ|Rβ) 4-bit index to characteristic bias
static const int16_t c_bias_lut[16] = {
-255, -127, -63, -31, -15, -7, -3, -1, // D=0
0, 1, 3, 7, 15, 31, 63, 127 // D=1
};
// Maps (D|Rβ|Rβ|Rβ) to mantissa bit count for takum16
static const uint8_t p_lut_16[16] = {
11, 10, 9, 8, 7, 6, 5, 4, // D=0 (r=0..7)
11, 10, 9, 8, 7, 6, 5, 4 // D=1 (r=0..7)
};
// Decode takum_log16 to logarithmic value l
double takum_log16_to_l(takum_log16 t) {
if (t == TAKUM_LOG16_NAR) return NAN;
if (t == 0) return -INFINITY; // log(0) = -β
bool sign = t < 0;
uint16_t bits = sign ? -t : t;
uint8_t DR = (bits >> 11) & 0x0F; // Extract D|R
int16_t c = c_bias_lut[DR];
uint8_t p = p_lut_16[DR];
// Extract and add additional characteristic bits
// Extract mantissa
// Combine: l = c + m
return sign ? -l : l;
}
// Encode sign and logarithmic value to takum_log16
takum_log16 takum_log16_from_s_and_l(bool sign, double l) {
if (isnan(l)) return TAKUM_LOG16_NAR;
// Clamp to representable range
l = clamp(l, -254.9375, 254.9375);
// Separate into characteristic and mantissa
int16_t c = (int16_t)floor(fabs(l));
double m = fabs(l) - c;
// Find DR from c using lookup table
// Encode bits: S|D|R|C|M
return sign ? -result : result;
}
takum_log16 from_float64(double f) {
if (isnan(f)) return TAKUM_LOG16_NAR;
if (f == 0.0) return 0;
bool sign = f < 0;
double l = 2.0 * log(fabs(f)); // l = 2Β·ln|f| = ln(|f|Β²)
return takum_log16_from_s_and_l(sign, l);
}
double to_float64(takum_log16 t) {
if (t == TAKUM_LOG16_NAR) return NAN;
if (t == 0) return 0.0;
double l = takum_log16_to_l(t);
bool sign = t < 0;
return (sign ? -1.0 : 1.0) * exp(l / 2.0); // βe^l = e^(l/2)
}
For detailed information, see:
| Property | IEEE 754 | Takum |
|---|---|---|
| Dynamic range consistency | Varies with precision | Constant for nβ₯12 |
| Multiplication closure | ~25% exact | 40%+ exact |
| Inversion closure | Rare | 100% exact (log) |
| Precision guarantee | Variable | n-12 bits minimum |
| Zero representation | +0 and -0 | Single zero |
| Special values | NaN, Β±Inf, subnormals | Only NaR |
bool is_nar(takum_log16 t) {
return t == TAKUM_LOG16_NAR;
}
takum_log16 safe_divide(takum_log16 a, takum_log16 b) {
if (is_nar(a) || is_nar(b) || b == 0) return TAKUM_LOG16_NAR;
return takum_log16_division(a, b);
}
takum_log16 takum_abs(takum_log16 t) {
return (t < 0) * (-t) + (t >= 0) * t;
}
Use float-domain computation for transcendental functions:
takum_log16 takum_sin(takum_log16 t) {
double f = to_float64(t);
double result = sin(f);
return from_float64(result);
}
For sinpi, cospi variants, use exact values at special angles.
Pre-compute constants for each type:
| Constant | takum_log16 value |
|---|---|
| Ο | 0x3C48 |
| 2Ο | 0x4648 |
| β2 | 0x1684 |
| e | 0x2000 |
| ln(2) | 0xC91C |
See constants.json for all types.