]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/d/d-longdouble.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / d / d-longdouble.cc
CommitLineData
b4c522fa 1/* d-longdouble.cc -- Software floating-point emulation for the frontend.
99dee823 2 Copyright (C) 2006-2021 Free Software Foundation, Inc.
b4c522fa
IB
3
4GCC is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation; either version 3, or (at your option)
7any later version.
8
9GCC is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with GCC; see the file COPYING3. If not see
16<http://www.gnu.org/licenses/>. */
17
18#include "config.h"
19#include "system.h"
20#include "coretypes.h"
21
22#include "dmd/mtype.h"
23
24#include "tree.h"
25#include "fold-const.h"
26#include "diagnostic.h"
27#include "stor-layout.h"
28
29#include "d-tree.h"
30#include "longdouble.h"
31
32
33/* Constant real values 0, 1, -1 and 0.5. */
34real_t CTFloat::zero;
35real_t CTFloat::one;
36real_t CTFloat::minusone;
37real_t CTFloat::half;
38
39/* Truncate longdouble to the highest precision supported by target. */
40
41longdouble
42longdouble::normalize (void)
43{
44 const machine_mode mode = TYPE_MODE (long_double_type_node);
45 real_convert (&this->rv (), mode, &this->rv ());
46 return *this;
47}
48
49/* Assign a real_value to a longdouble type. */
50
51void
af3c19f0 52longdouble::set (real_value &d)
b4c522fa
IB
53{
54 real_convert (&this->rv (), TYPE_MODE (long_double_type_node), &d);
55}
56
57/* Conversion routines between longdouble and integer types. */
58
59void
60longdouble::set (int32_t d)
61{
62 real_from_integer (&this->rv (), TYPE_MODE (double_type_node), d, SIGNED);
63}
64
65void
66longdouble::set (int64_t d)
67{
68 real_from_integer (&this->rv (), TYPE_MODE (long_double_type_node), d,
69 SIGNED);
70}
71
72int64_t
73longdouble::to_int (void) const
74{
75 bool overflow;
76 wide_int wi = real_to_integer (&this->rv (), &overflow, 64);
77 return wi.to_shwi ();
78}
79
80/* Unsigned variants of the same conversion routines. */
81
82void
83longdouble::set (uint32_t d)
84{
85 real_from_integer (&this->rv (), TYPE_MODE (double_type_node), d, UNSIGNED);
86}
87
88void
89longdouble::set (uint64_t d)
90{
91 real_from_integer (&this->rv (), TYPE_MODE (long_double_type_node), d,
92 UNSIGNED);
93}
94
95uint64_t
96longdouble::to_uint (void) const
97{
98 bool overflow;
99 wide_int wi = real_to_integer (&this->rv (), &overflow, 64);
100 return wi.to_uhwi ();
101}
102
103/* For conversion between boolean, only need to check if is zero. */
104
105void
106longdouble::set (bool d)
107{
108 this->rv () = (d == false) ? dconst0 : dconst1;
109}
110
111bool
112longdouble::to_bool (void) const
113{
114 return this->rv ().cl != rvc_zero;
115}
116
117/* Overload numeric operators for longdouble types. */
118
119longdouble
af3c19f0 120longdouble::add (const longdouble &r) const
b4c522fa
IB
121{
122 longdouble x;
123 real_arithmetic (&x.rv (), PLUS_EXPR, &this->rv (), &r.rv ());
124 return x.normalize ();
125}
126
127longdouble
af3c19f0 128longdouble::sub (const longdouble &r) const
b4c522fa
IB
129{
130 longdouble x;
131 real_arithmetic (&x.rv (), MINUS_EXPR, &this->rv (), &r.rv ());
132 return x.normalize ();
133}
134
135longdouble
af3c19f0 136longdouble::mul (const longdouble &r) const
b4c522fa
IB
137{
138 longdouble x;
139 real_arithmetic (&x.rv (), MULT_EXPR, &this->rv (), &r.rv ());
140 return x.normalize ();
141}
142
143longdouble
af3c19f0 144longdouble::div (const longdouble &r) const
b4c522fa
IB
145{
146 longdouble x;
147 real_arithmetic (&x.rv (), RDIV_EXPR, &this->rv (), &r.rv ());
148 return x.normalize ();
149}
150
151longdouble
af3c19f0 152longdouble::mod (const longdouble &r) const
b4c522fa
IB
153{
154 longdouble x;
155 real_value q;
156
157 if (r.rv ().cl == rvc_zero || REAL_VALUE_ISINF (this->rv ()))
158 {
159 real_nan (&x.rv (), "", 1, TYPE_MODE (long_double_type_node));
160 return x;
161 }
162
163 if (this->rv ().cl == rvc_zero)
164 return *this;
165
166 if (REAL_VALUE_ISINF (r.rv ()))
167 return *this;
168
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);
174
175 return x.normalize ();
176}
177
178longdouble
179longdouble::neg (void) const
180{
181 longdouble x;
182 real_arithmetic (&x.rv (), NEGATE_EXPR, &this->rv (), NULL);
183 return x.normalize ();
184}
185
186/* Overload equality operators for longdouble types. */
187
188int
af3c19f0 189longdouble::cmp (const longdouble &r) const
b4c522fa
IB
190{
191 if (real_compare (LT_EXPR, &this->rv (), &r.rv ()))
192 return -1;
193
194 if (real_compare (GT_EXPR, &this->rv (), &r.rv ()))
195 return 1;
196
197 return 0;
198}
199
200int
af3c19f0 201longdouble::equals (const longdouble &r) const
b4c522fa
IB
202{
203 return real_compare (EQ_EXPR, &this->rv (), &r.rv ());
204}