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)
| 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), |
no test coverage detected