| module imports.aXXXXX; |
| |
| auto min(A, B)(A a, B b) { return a < b ? a : b; } |
| alias TypeTuple(T...) = T; |
| |
| private template CustomFloatParams(uint bits) |
| { |
| static if (bits == 8) alias CustomFloatParams!( 4, 3) CustomFloatParams; |
| static if (bits == 16) alias CustomFloatParams!(10, 5) CustomFloatParams; |
| static if (bits == 32) alias CustomFloatParams!(23, 8) CustomFloatParams; |
| static if (bits == 64) alias CustomFloatParams!(52, 11) CustomFloatParams; |
| static if (bits == 80) alias CustomFloatParams!(64, 15) CustomFloatParams; |
| } |
| private template CustomFloatParams(uint precision, uint exponentWidth) |
| { |
| alias TypeTuple!( |
| precision, |
| exponentWidth, |
| ) CustomFloatParams; |
| } |
| |
| private union ToBinary(F) |
| if (is(typeof(CustomFloatParams!(F.sizeof*8))) || is(F == real)) |
| { |
| F set; |
| |
| // If on Linux or Mac, where 80-bit reals are padded, ignore the |
| // padding. |
| CustomFloat!(CustomFloatParams!(min(F.sizeof*8, 80))) get; |
| |
| // Convert F to the correct binary type. |
| static typeof(get) opCall(F value) |
| { |
| ToBinary r; |
| r.set = value; |
| return r.get; |
| } |
| alias get this; |
| } |
| |
| struct CustomFloat(uint precision, uint exponentWidth) |
| if ((1 + precision + exponentWidth) % 8 == 0 && precision + exponentWidth > 0) |
| { |
| public: |
| @property bool sign() { return 1; } |
| @property void sign(bool) {} |
| |
| this(F)(F input) |
| if (__traits(compiles, cast(real)input)) |
| { |
| this = input; |
| } |
| |
| void opAssign(F)(F input) |
| if (__traits(compiles, cast(real)input)) |
| { |
| static if (is(F == float) || is(F == double) || is(F == real)) |
| auto value = ToBinary!(F)(input); |
| else auto value = ToBinary!(real)(input); |
| |
| sign = value.sign; |
| } |
| |
| @property F get(F)() |
| if (is(F == float) || is(F == double) || is(F == real)) |
| { |
| ToBinary result; |
| return F.init; |
| } |
| |
| T opCast(T)() |
| if (__traits(compiles, get!T)) |
| { |
| return get!T; |
| } |
| } |