| 126 | // TODO(sfeuz): Replace by absl::SafeCast once available. |
| 127 | template <class IntOut, class FloatIn> |
| 128 | IntOut SafeCast(FloatIn x) { |
| 129 | static_assert(!std::numeric_limits<FloatIn>::is_integer, |
| 130 | "FloatIn is integer"); |
| 131 | static_assert(std::numeric_limits<IntOut>::is_integer, |
| 132 | "IntOut is not integer"); |
| 133 | static_assert(std::numeric_limits<IntOut>::radix == 2, "IntOut is base 2"); |
| 134 | |
| 135 | // Special case NaN, for which the logic below doesn't work. |
| 136 | if (std::isnan(x)) { |
| 137 | return 0; |
| 138 | } |
| 139 | |
| 140 | // Negative values all clip to zero for unsigned results. |
| 141 | if (!std::numeric_limits<IntOut>::is_signed && x < 0) { |
| 142 | return 0; |
| 143 | } |
| 144 | |
| 145 | // Handle infinities. |
| 146 | if (std::isinf(x)) { |
| 147 | return x < 0 ? std::numeric_limits<IntOut>::min() |
| 148 | : std::numeric_limits<IntOut>::max(); |
| 149 | } |
| 150 | |
| 151 | // Set exp such that x == f * 2^exp for some f with |f| in [0.5, 1.0), |
| 152 | // unless x is zero in which case exp == 0. Note that this implies that the |
| 153 | // magnitude of x is strictly less than 2^exp. |
| 154 | int exp = 0; |
| 155 | std::frexp(x, &exp); |
| 156 | |
| 157 | // Let N be the number of non-sign bits in the representation of IntOut. If |
| 158 | // the magnitude of x is strictly less than 2^N, the truncated version of x |
| 159 | // is representable as IntOut. The only representable integer for which this |
| 160 | // is not the case is kMin for signed types (i.e. -2^N), but that is covered |
| 161 | // by the fall-through below. |
| 162 | if (exp <= std::numeric_limits<IntOut>::digits) { |
| 163 | return x; |
| 164 | } |
| 165 | |
| 166 | // Handle numbers with magnitude >= 2^N. |
| 167 | return x < 0 ? std::numeric_limits<IntOut>::min() |
| 168 | : std::numeric_limits<IntOut>::max(); |
| 169 | } |
| 170 | |
| 171 | // Decompose a double multiplier into a Q0.31 int32 representation of its |
| 172 | // significand, and shift representation of NEGATIVE its exponent --- |