mirror of
https://github.com/ziglang/zig.git
synced 2024-11-28 08:02:32 +00:00
c99c085d70
The purpose of this branch is to switch to using an object file for each independent function, in order to make linking simpler - instead of relying on `-ffunction-sections` and `--gc-sections`, which involves the linker doing the work of linking everything and then undoing work via garbage collection, this will allow the linker to only include the compilation units that are depended on in the first place. This commit makes progress towards that goal.
56 lines
2.0 KiB
Zig
56 lines
2.0 KiB
Zig
const Int = @import("std").meta.Int;
|
|
const math = @import("std").math;
|
|
const Log2Int = math.Log2Int;
|
|
|
|
pub inline fn floatToInt(comptime I: type, a: anytype) I {
|
|
const F = @TypeOf(a);
|
|
const float_bits = @typeInfo(F).Float.bits;
|
|
const int_bits = @typeInfo(I).Int.bits;
|
|
const rep_t = Int(.unsigned, float_bits);
|
|
const sig_bits = math.floatMantissaBits(F);
|
|
const exp_bits = math.floatExponentBits(F);
|
|
const fractional_bits = math.floatFractionalBits(F);
|
|
|
|
const implicit_bit = if (F != f80) (@as(rep_t, 1) << sig_bits) else 0;
|
|
const max_exp = (1 << (exp_bits - 1));
|
|
const exp_bias = max_exp - 1;
|
|
const sig_mask = (@as(rep_t, 1) << sig_bits) - 1;
|
|
|
|
// Break a into sign, exponent, significand
|
|
const a_rep: rep_t = @bitCast(rep_t, a);
|
|
const negative = (a_rep >> (float_bits - 1)) != 0;
|
|
const exponent = @intCast(i32, (a_rep << 1) >> (sig_bits + 1)) - exp_bias;
|
|
const significand: rep_t = (a_rep & sig_mask) | implicit_bit;
|
|
|
|
// If the exponent is negative, the result rounds to zero.
|
|
if (exponent < 0) return 0;
|
|
|
|
// If the value is too large for the integer type, saturate.
|
|
switch (@typeInfo(I).Int.signedness) {
|
|
.unsigned => {
|
|
if (negative) return 0;
|
|
if (@intCast(c_uint, exponent) >= @minimum(int_bits, max_exp)) return math.maxInt(I);
|
|
},
|
|
.signed => if (@intCast(c_uint, exponent) >= @minimum(int_bits - 1, max_exp)) {
|
|
return if (negative) math.minInt(I) else math.maxInt(I);
|
|
},
|
|
}
|
|
|
|
// If 0 <= exponent < sig_bits, right shift to get the result.
|
|
// Otherwise, shift left.
|
|
var result: I = undefined;
|
|
if (exponent < fractional_bits) {
|
|
result = @intCast(I, significand >> @intCast(Log2Int(rep_t), fractional_bits - exponent));
|
|
} else {
|
|
result = @intCast(I, significand) << @intCast(Log2Int(I), exponent - fractional_bits);
|
|
}
|
|
|
|
if ((@typeInfo(I).Int.signedness == .signed) and negative)
|
|
return ~result +% 1;
|
|
return result;
|
|
}
|
|
|
|
test {
|
|
_ = @import("float_to_int_test.zig");
|
|
}
|