Function setFloat [src]

Set a Rational from a floating-point value. The rational will have enough precision to completely represent the provided float.

Prototype

pub fn setFloat(self: *Rational, comptime T: type, f: T) !void

Parameters

self: *RationalT: typef: T

Source

pub fn setFloat(self: *Rational, comptime T: type, f: T) !void { // Translated from golang.go/src/math/big/rat.go. debug.assert(@typeInfo(T) == .float); const UnsignedInt = std.meta.Int(.unsigned, @typeInfo(T).float.bits); const f_bits = @as(UnsignedInt, @bitCast(f)); const exponent_bits = math.floatExponentBits(T); const exponent_bias = (1 << (exponent_bits - 1)) - 1; const mantissa_bits = math.floatMantissaBits(T); const exponent_mask = (1 << exponent_bits) - 1; const mantissa_mask = (1 << mantissa_bits) - 1; var exponent = @as(i16, @intCast((f_bits >> mantissa_bits) & exponent_mask)); var mantissa = f_bits & mantissa_mask; switch (exponent) { exponent_mask => { return error.NonFiniteFloat; }, 0 => { // denormal exponent -= exponent_bias - 1; }, else => { // normal mantissa |= 1 << mantissa_bits; exponent -= exponent_bias; }, } var shift: i16 = mantissa_bits - exponent; // factor out powers of two early from rational while (mantissa & 1 == 0 and shift > 0) { mantissa >>= 1; shift -= 1; } try self.p.set(mantissa); self.p.setSign(f >= 0); try self.q.set(1); if (shift >= 0) { try self.q.shiftLeft(&self.q, @as(usize, @intCast(shift))); } else { try self.p.shiftLeft(&self.p, @as(usize, @intCast(-shift))); } try self.reduce(); }