DoxigAlpha

setFloat

Sets the Mutable to a float value rounded according to round. Returns whether the conversion was exact (round had no effect on the result).

Function parameters

Parameters

#
self:*Mutable
value:anytype

Used to indicate either limit of a 2s-complement integer.

Types

#
TwosCompIntLimit
Used to indicate either limit of a 2s-complement integer.
Mutable
A arbitrary-precision big integer, with a fixed set of mutable limbs.
Const
A arbitrary-precision big integer, with a fixed set of immutable limbs.
Managed
An arbitrary-precision big integer along with an allocator which manages the memory.

Returns the number of limbs needed to store `scalar`, which must be a

Functions

#
calcLimbLen
Returns the number of limbs needed to store `scalar`, which must be a
calcSetStringLimbCount
Assumes `string_len` doesn't account for minus signs if the number is negative.
calcNonZeroTwosCompLimbCount
Compute the number of limbs required to store a 2s-complement number of `bit_count` bits.
calcTwosCompLimbCount
Compute the number of limbs required to store a 2s-complement number of `bit_count` bits.
addMulLimbWithCarry
a + b * c + *carry, sets carry to the overflow bits
llcmp
Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively for limbs.

Source

Implementation

#
pub fn setFloat(self: *Mutable, value: anytype, round: Round) Exactness {
    const Float = @TypeOf(value);
    if (Float == comptime_float) return self.setFloat(@as(f128, value), round);
    const abs_value = @abs(value);
    if (abs_value < 1.0) {
        if (abs_value == 0.0) {
            self.set(0);
            return .exact;
        }
        self.set(@as(i2, round: switch (round) {
            .nearest_even => if (abs_value <= 0.5) 0 else continue :round .away,
            .away => if (value < 0.0) -1 else 1,
            .trunc => 0,
            .floor => -@as(i2, @intFromBool(value < 0.0)),
            .ceil => @intFromBool(value > 0.0),
        }));
        return .inexact;
    }
    const Repr = std.math.FloatRepr(Float);
    const repr: Repr = @bitCast(value);
    const exponent = repr.exponent.unbias();
    assert(exponent >= 0);
    const int_bit: Repr.Mantissa = 1 << (@bitSizeOf(Repr.Mantissa) - 1);
    const mantissa = int_bit | repr.mantissa;
    if (exponent >= @bitSizeOf(Repr.Normalized.Fraction)) {
        self.set(mantissa);
        self.shiftLeft(self.toConst(), @intCast(exponent - @bitSizeOf(Repr.Normalized.Fraction)));
        self.positive = repr.sign == .positive;
        return .exact;
    }
    self.set(mantissa >> @intCast(@bitSizeOf(Repr.Normalized.Fraction) - exponent));
    const round_bits: Repr.Normalized.Fraction = @truncate(mantissa << @intCast(exponent));
    if (round_bits == 0) {
        self.positive = repr.sign == .positive;
        return .exact;
    }
    round: switch (round) {
        .nearest_even => {
            const half: Repr.Normalized.Fraction = 1 << (@bitSizeOf(Repr.Normalized.Fraction) - 1);
            if (round_bits >= half) self.addScalar(self.toConst(), 1);
            if (round_bits == half) self.limbs[0] &= ~@as(Limb, 1);
        },
        .away => self.addScalar(self.toConst(), 1),
        .trunc => {},
        .floor => switch (repr.sign) {
            .positive => {},
            .negative => continue :round .away,
        },
        .ceil => switch (repr.sign) {
            .positive => continue :round .away,
            .negative => {},
        },
    }
    self.positive = repr.sign == .positive;
    return .inexact;
}