blob: 27fcf9c849fbdeda7fb10297af156595efbfaaa8 [file] [log] [blame]
/**
* 80-bit floating point value implementation if the C/D compiler does not support them natively.
* Copyright (C) 2021-2022 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
{
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;
}