1 /** 2 * 80-bit floating point value implementation if the C/D compiler does not support them natively. 3 * Copyright (C) 2021-2022 Free Software Foundation, Inc. 4 * 5 * GCC is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 3, or (at your option) 8 * any later version. 9 * 10 * GCC is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with GCC; see the file COPYING3. If not see 17 * <http://www.gnu.org/licenses/>. 18 */ 19 20 module dmd.root.longdouble; 21 22 import core.stdc.config; 23 import core.stdc.stdint; 24 25 extern(C++): 26 nothrow: 27 @nogc: 28 29 // Type used by the front-end for compile-time reals 30 struct longdouble 31 { 32 nothrow: 33 @nogc: thislongdouble34 extern (D) this(T)(T r) 35 { 36 this.set(cast(SetType!T)r); 37 } 38 39 // No constructor to be able to use this class in a union. 40 extern (D) longdouble opAssign(T)(T r) 41 if (is (T : longdouble)) 42 { 43 this.realvalue = r.realvalue; 44 return this; 45 } 46 47 extern (D) longdouble opAssign(T)(T r) 48 if (!is (T : longdouble)) 49 { 50 this.set(cast(SetType!T)r); 51 return this; 52 } 53 54 // Arithmetic operators. 55 extern (D) longdouble opBinary(string op, T)(T r) const 56 if ((op == "+" || op == "-" || op == "*" || op == "/" || op == "%") 57 && is (T : longdouble)) 58 { 59 static if (op == "+") 60 return this.add(r); 61 else static if (op == "-") 62 return this.sub(r); 63 else static if (op == "*") 64 return this.mul(r); 65 else static if (op == "/") 66 return this.div(r); 67 else static if (op == "%") 68 return this.mod(r); 69 } 70 71 extern (D) longdouble opUnary(string op)() const 72 if (op == "-") 73 { 74 return this.neg(); 75 } 76 opCmplongdouble77 extern (D) int opCmp(longdouble r) const 78 { 79 return this.cmp(r); 80 } 81 opEqualslongdouble82 extern (D) int opEquals(longdouble r) const 83 { 84 return this.equals(r); 85 } 86 87 extern (D) bool opCast(T : bool)() const 88 { 89 return this.to_bool(); 90 } 91 opCastlongdouble92 extern (D) T opCast(T)() const 93 { 94 static if (__traits(isUnsigned, T)) 95 return cast (T) this.to_uint(); 96 else 97 return cast(T) this.to_int(); 98 } 99 100 void set(int8_t d); 101 void set(int16_t d); 102 void set(int32_t d); 103 void set(int64_t d); 104 void set(uint8_t d); 105 void set(uint16_t d); 106 void set(uint32_t d); 107 void set(uint64_t d); 108 void set(bool d); 109 110 int64_t to_int() const; 111 uint64_t to_uint() const; 112 bool to_bool() const; 113 114 longdouble add(const ref longdouble r) const; 115 longdouble sub(const ref longdouble r) const; 116 longdouble mul(const ref longdouble r) const; 117 longdouble div(const ref longdouble r) const; 118 longdouble mod(const ref longdouble r) const; 119 longdouble neg() const; 120 int cmp(const ref longdouble t) const; 121 int equals(const ref longdouble t) const; 122 123 private: 124 // Statically allocate enough space for REAL_VALUE_TYPE. 125 enum REALVALUE_SIZE = (2 + (16 + c_long.sizeof) / c_long.sizeof); 126 c_long [REALVALUE_SIZE] realvalue; 127 } 128 129 // Pick the corresponding (u)int64_t type for T, as int64_t may be 130 // a special enum that requires casting to explicitly. SetType(T)131private template SetType(T) 132 { 133 static if (__traits(isIntegral, T) && T.sizeof == 8) 134 { 135 static if (__traits(isUnsigned, T)) 136 alias SetType = uint64_t; 137 else 138 alias SetType = int64_t; 139 } 140 else 141 alias SetType = T; 142 } 143