extend.rs 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. use float::Float;
  2. use int::{CastInto, Int};
  3. /// Generic conversion from a narrower to a wider IEEE-754 floating-point type
  4. fn extend<F: Float, R: Float>(a: F) -> R
  5. where
  6. F::Int: CastInto<u64>,
  7. u64: CastInto<F::Int>,
  8. u32: CastInto<R::Int>,
  9. R::Int: CastInto<u32>,
  10. R::Int: CastInto<u64>,
  11. u64: CastInto<R::Int>,
  12. F::Int: CastInto<R::Int>,
  13. {
  14. let src_zero = F::Int::ZERO;
  15. let src_one = F::Int::ONE;
  16. let src_bits = F::BITS;
  17. let src_sign_bits = F::SIGNIFICAND_BITS;
  18. let src_exp_bias = F::EXPONENT_BIAS;
  19. let src_min_normal = F::IMPLICIT_BIT;
  20. let src_infinity = F::EXPONENT_MASK;
  21. let src_sign_mask = F::SIGN_MASK as F::Int;
  22. let src_abs_mask = src_sign_mask - src_one;
  23. let src_qnan = F::SIGNIFICAND_MASK;
  24. let src_nan_code = src_qnan - src_one;
  25. let dst_bits = R::BITS;
  26. let dst_sign_bits = R::SIGNIFICAND_BITS;
  27. let dst_inf_exp = R::EXPONENT_MAX;
  28. let dst_exp_bias = R::EXPONENT_BIAS;
  29. let dst_min_normal = R::IMPLICIT_BIT;
  30. let sign_bits_delta = dst_sign_bits - src_sign_bits;
  31. let exp_bias_delta = dst_exp_bias - src_exp_bias;
  32. let a_abs = a.repr() & src_abs_mask;
  33. let mut abs_result = R::Int::ZERO;
  34. if a_abs.wrapping_sub(src_min_normal) < src_infinity.wrapping_sub(src_min_normal) {
  35. // a is a normal number.
  36. // Extend to the destination type by shifting the significand and
  37. // exponent into the proper position and rebiasing the exponent.
  38. let abs_dst: R::Int = a_abs.cast();
  39. let bias_dst: R::Int = exp_bias_delta.cast();
  40. abs_result = abs_dst.wrapping_shl(sign_bits_delta);
  41. abs_result += bias_dst.wrapping_shl(dst_sign_bits);
  42. } else if a_abs >= src_infinity {
  43. // a is NaN or infinity.
  44. // Conjure the result by beginning with infinity, then setting the qNaN
  45. // bit (if needed) and right-aligning the rest of the trailing NaN
  46. // payload field.
  47. let qnan_dst: R::Int = (a_abs & src_qnan).cast();
  48. let nan_code_dst: R::Int = (a_abs & src_nan_code).cast();
  49. let inf_exp_dst: R::Int = dst_inf_exp.cast();
  50. abs_result = inf_exp_dst.wrapping_shl(dst_sign_bits);
  51. abs_result |= qnan_dst.wrapping_shl(sign_bits_delta);
  52. abs_result |= nan_code_dst.wrapping_shl(sign_bits_delta);
  53. } else if a_abs != src_zero {
  54. // a is denormal.
  55. // Renormalize the significand and clear the leading bit, then insert
  56. // the correct adjusted exponent in the destination type.
  57. let scale = a_abs.leading_zeros() - src_min_normal.leading_zeros();
  58. let abs_dst: R::Int = a_abs.cast();
  59. let bias_dst: R::Int = (exp_bias_delta - scale + 1).cast();
  60. abs_result = abs_dst.wrapping_shl(sign_bits_delta + scale);
  61. abs_result = (abs_result ^ dst_min_normal) | (bias_dst.wrapping_shl(dst_sign_bits));
  62. }
  63. let sign_result: R::Int = (a.repr() & src_sign_mask).cast();
  64. R::from_repr(abs_result | (sign_result.wrapping_shl(dst_bits - src_bits)))
  65. }
  66. intrinsics! {
  67. #[aapcs_on_arm]
  68. #[arm_aeabi_alias = __aeabi_f2d]
  69. pub extern "C" fn __extendsfdf2(a: f32) -> f64 {
  70. extend(a)
  71. }
  72. #[cfg(target_arch = "arm")]
  73. pub extern "C" fn __extendsfdf2vfp(a: f32) -> f64 {
  74. a as f64 // LLVM generate 'fcvtds'
  75. }
  76. }