]>
git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/d/d-longdouble.cc
1 /* d-longdouble.cc -- Software floating-point emulation for the frontend.
2 Copyright (C) 2006-2019 Free Software Foundation, Inc.
4 GCC is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
9 GCC is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with GCC; see the file COPYING3. If not see
16 <http://www.gnu.org/licenses/>. */
20 #include "coretypes.h"
22 #include "dmd/mtype.h"
25 #include "fold-const.h"
26 #include "diagnostic.h"
27 #include "stor-layout.h"
30 #include "longdouble.h"
33 /* Constant real values 0, 1, -1 and 0.5. */
36 real_t
CTFloat::minusone
;
39 /* Truncate longdouble to the highest precision supported by target. */
42 longdouble::normalize (void)
44 const machine_mode mode
= TYPE_MODE (long_double_type_node
);
45 real_convert (&this->rv (), mode
, &this->rv ());
49 /* Assign a real_value to a longdouble type. */
52 longdouble::set (real_value
& d
)
54 real_convert (&this->rv (), TYPE_MODE (long_double_type_node
), &d
);
57 /* Conversion routines between longdouble and integer types. */
60 longdouble::set (int32_t d
)
62 real_from_integer (&this->rv (), TYPE_MODE (double_type_node
), d
, SIGNED
);
66 longdouble::set (int64_t d
)
68 real_from_integer (&this->rv (), TYPE_MODE (long_double_type_node
), d
,
73 longdouble::to_int (void) const
76 wide_int wi
= real_to_integer (&this->rv (), &overflow
, 64);
80 /* Unsigned variants of the same conversion routines. */
83 longdouble::set (uint32_t d
)
85 real_from_integer (&this->rv (), TYPE_MODE (double_type_node
), d
, UNSIGNED
);
89 longdouble::set (uint64_t d
)
91 real_from_integer (&this->rv (), TYPE_MODE (long_double_type_node
), d
,
96 longdouble::to_uint (void) const
99 wide_int wi
= real_to_integer (&this->rv (), &overflow
, 64);
100 return wi
.to_uhwi ();
103 /* For conversion between boolean, only need to check if is zero. */
106 longdouble::set (bool d
)
108 this->rv () = (d
== false) ? dconst0
: dconst1
;
112 longdouble::to_bool (void) const
114 return this->rv ().cl
!= rvc_zero
;
117 /* Overload numeric operators for longdouble types. */
120 longdouble::add (const longdouble
& r
) const
123 real_arithmetic (&x
.rv (), PLUS_EXPR
, &this->rv (), &r
.rv ());
124 return x
.normalize ();
128 longdouble::sub (const longdouble
& r
) const
131 real_arithmetic (&x
.rv (), MINUS_EXPR
, &this->rv (), &r
.rv ());
132 return x
.normalize ();
136 longdouble::mul (const longdouble
& r
) const
139 real_arithmetic (&x
.rv (), MULT_EXPR
, &this->rv (), &r
.rv ());
140 return x
.normalize ();
144 longdouble::div (const longdouble
& r
) const
147 real_arithmetic (&x
.rv (), RDIV_EXPR
, &this->rv (), &r
.rv ());
148 return x
.normalize ();
152 longdouble::mod (const longdouble
& r
) const
157 if (r
.rv ().cl
== rvc_zero
|| REAL_VALUE_ISINF (this->rv ()))
159 real_nan (&x
.rv (), "", 1, TYPE_MODE (long_double_type_node
));
163 if (this->rv ().cl
== rvc_zero
)
166 if (REAL_VALUE_ISINF (r
.rv ()))
169 /* Need to check for NaN? */
170 real_arithmetic (&q
, RDIV_EXPR
, &this->rv (), &r
.rv ());
171 real_arithmetic (&q
, FIX_TRUNC_EXPR
, &q
, NULL
);
172 real_arithmetic (&q
, MULT_EXPR
, &q
, &r
.rv ());
173 real_arithmetic (&x
.rv (), MINUS_EXPR
, &this->rv (), &q
);
175 return x
.normalize ();
179 longdouble::neg (void) const
182 real_arithmetic (&x
.rv (), NEGATE_EXPR
, &this->rv (), NULL
);
183 return x
.normalize ();
186 /* Overload equality operators for longdouble types. */
189 longdouble::cmp (const longdouble
& r
) const
191 if (real_compare (LT_EXPR
, &this->rv (), &r
.rv ()))
194 if (real_compare (GT_EXPR
, &this->rv (), &r
.rv ()))
201 longdouble::equals (const longdouble
& r
) const
203 return real_compare (EQ_EXPR
, &this->rv (), &r
.rv ());