Shared Rust kernels
ported/excel_numeric/x87
All modules · quoted at commit 9e1884369a67 of DnaCalc/DnaCalc. Comments are the source's own.
atan · 26 lines · calc-func/src/ported/excel_numeric/x87.rs on GitHub/// Public ISA FPATAN operation, selected by W111 black-box complex-argument
/// witnesses. No binary provenance inference is needed for this arithmetic graph.
pub(super) fn atan(x: f64) -> f64 {
let mut result = 0.0_f64;
let cw_core = CW_CORE;
let mut cw_save = 0_u16;
// SAFETY: the two pushes and FPATAN/store pops balance the x87 stack. All
// pointers refer to live locals and the caller's control word is restored.
unsafe {
asm!(
"fnstcw word ptr [{save}]",
"fldcw word ptr [{core}]",
"fld qword ptr [{x}]",
"fld1",
"fpatan",
"fstp qword ptr [{res}]",
"fldcw word ptr [{save}]",
x = in(reg) &x,
res = in(reg) &mut result,
core = in(reg) &cw_core,
save = in(reg) &mut cw_save,
options(nostack, preserves_flags),
);
}
result
}
Used by 5 functions.
atan_reduced · 26 lines · calc-func/src/ported/excel_numeric/x87.rs on GitHub/// W111 ATAN magnitude reduction selected by independent black-box counterexamples.
/// For |x| > 1, keep atan(1/|x|) and pi/2 extended until the final subtraction.
/// FPATAN takes the two operands directly, so no rounded reciprocal is introduced.
pub(super) fn atan_reduced(x: f64) -> f64 {
let magnitude = x.abs();
if magnitude <= 1.0 { return atan(x); }
let mut result = 0.0_f64;
let mut cw_save = 0_u16;
let cw_core = CW_CORE;
let two = 2.0_f64;
// SAFETY: all operands are live locals; the two FPATAN operands reduce to
// one angle, FLDPI adds one value, and subtraction/store empty the stack.
// The caller's control word is restored before returning.
unsafe {
asm!(
"fnstcw word ptr [{save}]", "fldcw word ptr [{core}]",
"fld1", "fld qword ptr [{x}]", "fpatan",
"fldpi", "fdiv qword ptr [{two}]", "fsubrp st(1), st(0)",
"fstp qword ptr [{res}]", "fldcw word ptr [{save}]",
x = in(reg) &magnitude, two = in(reg) &two, res = in(reg) &mut result,
core = in(reg) &cw_core, save = in(reg) &mut cw_save,
options(nostack, preserves_flags),
);
}
result.copysign(x)
}
Used by 4 functions.
mul · 27 lines · calc-func/src/ported/excel_numeric/x87.rs on GitHub/// `RN53(RN64(a * b))` — one x87 `FMUL` at PC=64 then a `binary64` store: the
/// **double-rounded** product. Excel forms `POWER`'s `|y|·ln x` this way; a plain
/// SSE multiply is single-rounded and differs on double-rounding-window inputs.
pub(super) fn mul(a: f64, b: f64) -> f64 {
let mut result: f64 = 0.0;
let cw_core: u16 = CW_CORE;
let mut cw_save: u16 = 0;
// SAFETY: balanced x87 stack (2 push; `fmulp` and `fstp` pop both), pointer
// I/O only, control word saved and restored.
unsafe {
asm!(
"fnstcw word ptr [{save}]",
"fldcw word ptr [{core}]",
"fld qword ptr [{a}]", // st0 = a
"fld qword ptr [{b}]", // st0 = b, st1 = a
"fmulp st(1), st", // st0 = RN64(a*b)
"fstp qword ptr [{res}]", // RN53 store
"fldcw word ptr [{save}]",
a = in(reg) &a,
b = in(reg) &b,
res = in(reg) &mut result,
core = in(reg) &cw_core,
save = in(reg) &mut cw_save,
);
}
result
}
Used by 127 functions.
add · 27 lines · calc-func/src/ported/excel_numeric/x87.rs on GitHub/// `RN53(RN64(a + b))` — one x87 `FADD` at PC=64 then a `binary64` store: the
/// double-rounded sum. Excel's legacy x87-compiled function bodies produce
/// this for every `t = a + b;` with `t` spilled to memory (W109: XNPV's
/// `1 + rate` and its running `total += term` accumulate this way).
pub(super) fn add(a: f64, b: f64) -> f64 {
let mut result: f64 = 0.0;
let cw_core: u16 = CW_CORE;
let mut cw_save: u16 = 0;
// SAFETY: balanced x87 stack (one push; `fadd` folds in memory operand,
// `fstp` pops), pointer I/O only, control word saved and restored.
unsafe {
asm!(
"fnstcw word ptr [{save}]",
"fldcw word ptr [{core}]",
"fld qword ptr [{a}]", // st0 = a
"fadd qword ptr [{b}]", // st0 = RN64(a+b)
"fstp qword ptr [{res}]", // RN53 store
"fldcw word ptr [{save}]",
a = in(reg) &a,
b = in(reg) &b,
res = in(reg) &mut result,
core = in(reg) &cw_core,
save = in(reg) &mut cw_save,
);
}
result
}
Used by 80 functions.
sub · 25 lines · calc-func/src/ported/excel_numeric/x87.rs on GitHub/// `RN53(RN64(a - b))` — one x87 `FSUB` at PC=64 then a `binary64` store: the
/// double-rounded difference (W109: NPER's `tf·pmt - fv·rate`).
pub(super) fn sub(a: f64, b: f64) -> f64 {
let mut result: f64 = 0.0;
let cw_core: u16 = CW_CORE;
let mut cw_save: u16 = 0;
// SAFETY: balanced x87 stack (one push; `fsub` folds in memory operand,
// `fstp` pops), pointer I/O only, control word saved and restored.
unsafe {
asm!(
"fnstcw word ptr [{save}]",
"fldcw word ptr [{core}]",
"fld qword ptr [{a}]", // st0 = a
"fsub qword ptr [{b}]", // st0 = RN64(a-b)
"fstp qword ptr [{res}]", // RN53 store
"fldcw word ptr [{save}]",
a = in(reg) &a,
b = in(reg) &b,
res = in(reg) &mut result,
core = in(reg) &cw_core,
save = in(reg) &mut cw_save,
);
}
result
}
Used by 72 functions.
div · 25 lines · calc-func/src/ported/excel_numeric/x87.rs on GitHub/// `RN53(RN64(a / b))` — one x87 `FDIV` at PC=64 then a `binary64` store: the
/// double-rounded quotient (W109: XNPV's per-term `value / pow`).
pub(super) fn div(a: f64, b: f64) -> f64 {
let mut result: f64 = 0.0;
let cw_core: u16 = CW_CORE;
let mut cw_save: u16 = 0;
// SAFETY: balanced x87 stack (one push; `fdiv` folds in memory operand,
// `fstp` pops), pointer I/O only, control word saved and restored.
unsafe {
asm!(
"fnstcw word ptr [{save}]",
"fldcw word ptr [{core}]",
"fld qword ptr [{a}]", // st0 = a
"fdiv qword ptr [{b}]", // st0 = RN64(a/b)
"fstp qword ptr [{res}]", // RN53 store
"fldcw word ptr [{save}]",
a = in(reg) &a,
b = in(reg) &b,
res = in(reg) &mut result,
core = in(reg) &cw_core,
save = in(reg) &mut cw_save,
);
}
result
}
Used by 82 functions.
recip · 24 lines · calc-func/src/ported/excel_numeric/x87.rs on GitHub/// `RN53(RN64(1.0 / x))` — one x87 `FDIV` at PC=64 then a `binary64` store: the
/// double-rounded reciprocal Excel uses to stage `POWER(x, y)` for `y < 0`
/// (compute the positive power, store it, then reciprocate).
pub(super) fn recip(x: f64) -> f64 {
let mut result: f64 = 0.0;
let cw_core: u16 = CW_CORE;
let mut cw_save: u16 = 0;
// SAFETY: balanced x87 stack (`fld1` pushes, `fstp` pops), pointer I/O only.
unsafe {
asm!(
"fnstcw word ptr [{save}]",
"fldcw word ptr [{core}]",
"fld1", // st0 = 1
"fdiv qword ptr [{x}]", // st0 = RN64(1/x)
"fstp qword ptr [{res}]", // RN53 store
"fldcw word ptr [{save}]",
x = in(reg) &x,
res = in(reg) &mut result,
core = in(reg) &cw_core,
save = in(reg) &mut cw_save,
);
}
result
}
Used by 23 functions.