| /** |
| * 80-bit floating point value implementation if the C/D compiler does not support them natively. |
| * Copyright (C) 2021-2023 Free Software Foundation, Inc. |
| * |
| * GCC is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 3, or (at your option) |
| * any later version. |
| * |
| * GCC is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with GCC; see the file COPYING3. If not see |
| * <http://www.gnu.org/licenses/>. |
| */ |
| |
| module dmd.root.longdouble; |
| |
| import core.stdc.config; |
| import core.stdc.stdint; |
| |
| extern(C++): |
| nothrow: |
| @nogc: |
| |
| // Type used by the front-end for compile-time reals |
| struct longdouble |
| { |
| nothrow: |
| @nogc: |
| extern (D) this(T)(T r) |
| { |
| this.set(cast(SetType!T)r); |
| } |
| |
| // No constructor to be able to use this class in a union. |
| extern (D) longdouble opAssign(T)(T r) |
| if (is (T : longdouble)) |
| { |
| this.realvalue = r.realvalue; |
| return this; |
| } |
| |
| extern (D) longdouble opAssign(T)(T r) |
| if (!is (T : longdouble)) |
| { |
| this.set(cast(SetType!T)r); |
| return this; |
| } |
| |
| // Arithmetic operators. |
| extern (D) longdouble opBinary(string op, T)(T r) const |
| if ((op == "+" || op == "-" || op == "*" || op == "/" || op == "%") |
| && is (T : longdouble)) |
| { |
| static if (op == "+") |
| return this.add(r); |
| else static if (op == "-") |
| return this.sub(r); |
| else static if (op == "*") |
| return this.mul(r); |
| else static if (op == "/") |
| return this.div(r); |
| else static if (op == "%") |
| return this.mod(r); |
| } |
| |
| extern (D) longdouble opUnary(string op)() const |
| if (op == "-") |
| { |
| return this.neg(); |
| } |
| |
| extern (D) int opCmp(longdouble r) const |
| { |
| return this.cmp(r); |
| } |
| |
| extern (D) int opEquals(longdouble r) const |
| { |
| return this.equals(r); |
| } |
| |
| extern (D) bool opCast(T : bool)() const |
| { |
| return this.to_bool(); |
| } |
| |
| extern (D) T opCast(T)() const |
| { |
| static if (__traits(isUnsigned, T)) |
| return cast (T) this.to_uint(); |
| else |
| return cast(T) this.to_int(); |
| } |
| |
| void set(int8_t d); |
| void set(int16_t d); |
| void set(int32_t d); |
| void set(int64_t d); |
| void set(uint8_t d); |
| void set(uint16_t d); |
| void set(uint32_t d); |
| void set(uint64_t d); |
| void set(bool d); |
| |
| int64_t to_int() const; |
| uint64_t to_uint() const; |
| bool to_bool() const; |
| |
| longdouble add(const ref longdouble r) const; |
| longdouble sub(const ref longdouble r) const; |
| longdouble mul(const ref longdouble r) const; |
| longdouble div(const ref longdouble r) const; |
| longdouble mod(const ref longdouble r) const; |
| longdouble neg() const; |
| int cmp(const ref longdouble t) const; |
| int equals(const ref longdouble t) const; |
| |
| private: |
| // Statically allocate enough space for REAL_VALUE_TYPE. |
| enum REALVALUE_SIZE = (2 + (16 + c_long.sizeof) / c_long.sizeof); |
| c_long [REALVALUE_SIZE] realvalue; |
| } |
| |
| // Pick the corresponding (u)int64_t type for T, as int64_t may be |
| // a special enum that requires casting to explicitly. |
| private template SetType(T) |
| { |
| static if (__traits(isIntegral, T) && T.sizeof == 8) |
| { |
| static if (__traits(isUnsigned, T)) |
| alias SetType = uint64_t; |
| else |
| alias SetType = int64_t; |
| } |
| else |
| alias SetType = T; |
| } |