trunc.rs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. use float::Float;
  2. use int::{CastInto, Int};
  3. fn trunc<F: Float, R: Float>(a: F) -> R
  4. where
  5. F::Int: CastInto<u64>,
  6. F::Int: CastInto<u32>,
  7. u64: CastInto<F::Int>,
  8. u32: CastInto<F::Int>,
  9. R::Int: CastInto<u32>,
  10. u32: CastInto<R::Int>,
  11. F::Int: CastInto<R::Int>,
  12. {
  13. let src_zero = F::Int::ZERO;
  14. let src_one = F::Int::ONE;
  15. let src_bits = F::BITS;
  16. let src_exp_bias = F::EXPONENT_BIAS;
  17. let src_min_normal = F::IMPLICIT_BIT;
  18. let src_significand_mask = F::SIGNIFICAND_MASK;
  19. let src_infinity = F::EXPONENT_MASK;
  20. let src_sign_mask = F::SIGN_MASK;
  21. let src_abs_mask = src_sign_mask - src_one;
  22. let round_mask = (src_one << (F::SIGNIFICAND_BITS - R::SIGNIFICAND_BITS)) - src_one;
  23. let halfway = src_one << (F::SIGNIFICAND_BITS - R::SIGNIFICAND_BITS - 1);
  24. let src_qnan = src_one << (F::SIGNIFICAND_BITS - 1);
  25. let src_nan_code = src_qnan - src_one;
  26. let dst_zero = R::Int::ZERO;
  27. let dst_one = R::Int::ONE;
  28. let dst_bits = R::BITS;
  29. let dst_inf_exp = R::EXPONENT_MAX;
  30. let dst_exp_bias = R::EXPONENT_BIAS;
  31. let underflow_exponent: F::Int = (src_exp_bias + 1 - dst_exp_bias).cast();
  32. let overflow_exponent: F::Int = (src_exp_bias + dst_inf_exp - dst_exp_bias).cast();
  33. let underflow: F::Int = underflow_exponent << F::SIGNIFICAND_BITS;
  34. let overflow: F::Int = overflow_exponent << F::SIGNIFICAND_BITS;
  35. let dst_qnan = R::Int::ONE << (R::SIGNIFICAND_BITS - 1);
  36. let dst_nan_code = dst_qnan - dst_one;
  37. let sign_bits_delta = F::SIGNIFICAND_BITS - R::SIGNIFICAND_BITS;
  38. // Break a into a sign and representation of the absolute value.
  39. let a_abs = a.repr() & src_abs_mask;
  40. let sign = a.repr() & src_sign_mask;
  41. let mut abs_result: R::Int;
  42. if a_abs.wrapping_sub(underflow) < a_abs.wrapping_sub(overflow) {
  43. // The exponent of a is within the range of normal numbers in the
  44. // destination format. We can convert by simply right-shifting with
  45. // rounding and adjusting the exponent.
  46. abs_result = (a_abs >> sign_bits_delta).cast();
  47. let tmp = src_exp_bias.wrapping_sub(dst_exp_bias) << R::SIGNIFICAND_BITS;
  48. abs_result = abs_result.wrapping_sub(tmp.cast());
  49. let round_bits = a_abs & round_mask;
  50. if round_bits > halfway {
  51. // Round to nearest.
  52. abs_result += dst_one;
  53. } else if round_bits == halfway {
  54. // Tie to even.
  55. abs_result += abs_result & dst_one;
  56. };
  57. } else if a_abs > src_infinity {
  58. // a is NaN.
  59. // Conjure the result by beginning with infinity, setting the qNaN
  60. // bit and inserting the (truncated) trailing NaN field.
  61. abs_result = (dst_inf_exp << R::SIGNIFICAND_BITS).cast();
  62. abs_result |= dst_qnan;
  63. abs_result |= dst_nan_code
  64. & ((a_abs & src_nan_code) >> (F::SIGNIFICAND_BITS - R::SIGNIFICAND_BITS)).cast();
  65. } else if a_abs >= overflow {
  66. // a overflows to infinity.
  67. abs_result = (dst_inf_exp << R::SIGNIFICAND_BITS).cast();
  68. } else {
  69. // a underflows on conversion to the destination type or is an exact
  70. // zero. The result may be a denormal or zero. Extract the exponent
  71. // to get the shift amount for the denormalization.
  72. let a_exp: u32 = (a_abs >> F::SIGNIFICAND_BITS).cast();
  73. let shift = src_exp_bias - dst_exp_bias - a_exp + 1;
  74. let significand = (a.repr() & src_significand_mask) | src_min_normal;
  75. // Right shift by the denormalization amount with sticky.
  76. if shift > F::SIGNIFICAND_BITS {
  77. abs_result = dst_zero;
  78. } else {
  79. let sticky = if (significand << (src_bits - shift)) != src_zero {
  80. src_one
  81. } else {
  82. src_zero
  83. };
  84. let denormalized_significand: F::Int = significand >> shift | sticky;
  85. abs_result =
  86. (denormalized_significand >> (F::SIGNIFICAND_BITS - R::SIGNIFICAND_BITS)).cast();
  87. let round_bits = denormalized_significand & round_mask;
  88. // Round to nearest
  89. if round_bits > halfway {
  90. abs_result += dst_one;
  91. }
  92. // Ties to even
  93. else if round_bits == halfway {
  94. abs_result += abs_result & dst_one;
  95. };
  96. }
  97. }
  98. // Apply the signbit to the absolute value.
  99. R::from_repr(abs_result | sign.wrapping_shr(src_bits - dst_bits).cast())
  100. }
  101. intrinsics! {
  102. pub extern "C" fn __truncdfsf2(a: f64) -> f32 {
  103. trunc(a)
  104. }
  105. }