xref: /netbsd-src/external/gpl3/gcc/dist/gcc/d/dmd/root/longdouble.d (revision b1e838363e3c6fc78a55519254d99869742dd33c)
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)131 private 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