MCPcopy Index your code
hub / github.com/RustPython/RustPython / dd_ln

Method dd_ln

crates/jit/src/instructions.rs:1004–1083  ·  view source on GitHub ↗

Computes the natural logarithm ln(x) in double–double arithmetic. It first checks for domain errors (x ≤ 0 or NaN), then extracts the exponent and mantissa from the bit-level representation of x. It computes ln(mantissa) using the ln(1+f) series and adds k*ln2 to obtain ln(x).

(&mut self, x: Value)

Source from the content-addressed store, hash-verified

1002 /// and mantissa from the bit-level representation of x. It computes ln(mantissa) using
1003 /// the ln(1+f) series and adds k*ln2 to obtain ln(x).
1004 fn dd_ln(&mut self, x: Value) -> DDValue {
1005 // (A) Prepare a DDValue representing NaN.
1006 let dd_nan = self.dd_from_f64(f64::NAN);
1007
1008 // Build a zero constant for comparisons.
1009 let zero_f64 = self.builder.ins().f64const(0.0);
1010
1011 // Check if x is less than or equal to 0 or is NaN.
1012 let cmp_le = self
1013 .builder
1014 .ins()
1015 .fcmp(FloatCC::LessThanOrEqual, x, zero_f64);
1016 let cmp_nan = self.builder.ins().fcmp(FloatCC::Unordered, x, x);
1017 let need_nan = self.builder.ins().bor(cmp_le, cmp_nan);
1018
1019 // (B) Reinterpret the bits of x as an integer.
1020 let bits = self.builder.ins().bitcast(types::I64, MemFlags::new(), x);
1021
1022 // (C) Extract the exponent (top 11 bits) from the bit representation.
1023 let shift_52 = self.builder.ins().ushr_imm(bits, 52);
1024 let exponent_mask = self.builder.ins().iconst(types::I64, 0x7FF);
1025 let exponent = self.builder.ins().band(shift_52, exponent_mask);
1026
1027 // k = exponent - 1023 (unbias the exponent).
1028 let bias = self.builder.ins().iconst(types::I64, 1023);
1029 let k_i64 = self.builder.ins().isub(exponent, bias);
1030
1031 // (D) Extract the fraction (mantissa) from the lower 52 bits.
1032 let fraction_mask = self.builder.ins().iconst(types::I64, 0x000F_FFFF_FFFF_FFFF);
1033 let fraction_part = self.builder.ins().band(bits, fraction_mask);
1034
1035 // (E) For normal numbers (exponent ≠ 0), add the implicit leading 1.
1036 let implicit_one = self.builder.ins().iconst(types::I64, 1 << 52);
1037 let zero_exp = self.builder.ins().icmp_imm(IntCC::Equal, exponent, 0);
1038 let frac_one_bor = self.builder.ins().bor(fraction_part, implicit_one);
1039 let fraction_with_leading_one = self.builder.ins().select(
1040 zero_exp,
1041 fraction_part, // For subnormals, do not add the implicit 1.
1042 frac_one_bor,
1043 );
1044
1045 // (F) Force the exponent bits to 1023, yielding a mantissa m in [1, 2).
1046 let new_exp = self.builder.ins().iconst(types::I64, 0x3FF0_0000_0000_0000);
1047 let fraction_bits = self.builder.ins().bor(fraction_with_leading_one, new_exp);
1048 let m = self
1049 .builder
1050 .ins()
1051 .bitcast(types::F64, MemFlags::new(), fraction_bits);
1052
1053 // (G) Compute ln(m) using the series ln(1+f) with f = m - 1.
1054 let one_f64 = self.builder.ins().f64const(1.0);
1055 let f_val = self.builder.ins().fsub(m, one_f64);
1056 let dd_ln_m = self.dd_ln_1p_series(f_val);
1057
1058 // (H) Compute k*ln2 in double–double arithmetic.
1059 let ln2_dd = self.dd_from_parts(
1060 f64::from_bits(0x3fe62e42fefa39ef),
1061 f64::from_bits(0x3c7abc9e3b39803f),

Callers 1

compile_fpowMethod · 0.80

Calls 8

newFunction · 0.85
dd_from_f64Method · 0.80
insMethod · 0.80
dd_ln_1p_seriesMethod · 0.80
dd_from_partsMethod · 0.80
dd_mul_f64Method · 0.80
dd_addMethod · 0.80
selectMethod · 0.45

Tested by

no test coverage detected