Allow returning something of type void in a function that returns void
[delight/core.git] / d-gcc-real.cc
blob8938e52977eac2011cf3b1c3176f0c884062fc63
1 /* GDC -- D front-end for GCC
2 Copyright (C) 2004 David Friedman
4 This program 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 2 of the License, or
7 (at your option) any later version.
9 This program 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 this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "d-gcc-includes.h"
20 #include <assert.h>
22 // d-real_t.cc
24 #include "mars.h"
25 #include "lexer.h"
26 #include "mtype.h"
27 #include "d-gcc-real.h"
29 #include "d-lang.h"
30 #include "d-codegen.h"
32 static enum machine_mode
33 max_float_mode()
35 return TYPE_MODE(long_double_type_node);
38 static enum machine_mode
39 myMode_to_machineMode(real_t::MyMode mode)
41 switch (mode) {
43 case real_t::Float: return SFmode;
44 case real_t::Double: return DFmode;
45 case real_t::LongDouble: return max_float_mode();
47 case real_t::Float: return TYPE_MODE(float_type_node);
48 case real_t::Double: return TYPE_MODE(double_type_node);
49 case real_t::LongDouble: return TYPE_MODE(long_double_type_node);
51 default:
52 abort();
53 return VOIDmode;
57 real_t_Properties real_t_properties[real_t::NumModes];
59 #define M_LOG10_2 0.30102999566398119521
61 void
62 real_t::init()
64 assert(sizeof(real_t) >= sizeof(REAL_VALUE_TYPE));
65 for (int i = (int) Float; i < (int) NumModes; i++) {
66 real_t_Properties & p = real_t_properties[i];
68 enum machine_mode mode = myMode_to_machineMode((MyMode) i);
69 const struct real_format & rf = * REAL_MODE_FORMAT(mode);
71 real_maxval(& p.maxval.rv(), 0, mode);
72 real_ldexp(& p.minval.rv(), & dconst1, rf.emin - 1); // %% correct for non-ieee754?
73 real_ldexp(& p.epsilonval.rv(), & dconst1, 1 - rf.p); // %% correct for non-ieee754?
75 real_nan(& p.nanval.rv(), "", 1, mode);
76 real_inf(& p.infval.rv());
78 p.dig = (int)(rf.p * M_LOG10_2); // %% not always the same as header values..
79 p.mant_dig = rf.p;
80 p.max_10_exp = (int)(rf.emax * M_LOG10_2);
81 p.min_10_exp = (int)(rf.emin * M_LOG10_2);
82 p.max_exp = rf.emax;
83 p.min_exp = rf.emin;
87 real_t
88 real_t::parse(const char * str, MyMode mode)
90 real_t r;
91 r.rv() = REAL_VALUE_ATOF(str, myMode_to_machineMode(mode));
92 return r;
95 real_t
96 real_t::getnan(MyMode mode)
98 real_t r;
99 real_nan(& r.rv(), "", 1, myMode_to_machineMode(mode));
100 return r;
103 real_t
104 real_t::getinfinity()
106 real_t r;
107 real_inf(& r.rv());
108 return r;
112 real_t::real_t()
114 REAL_VALUE_FROM_INT(rv(), 0, 0, max_float_mode());
118 real_t::real_t(const real_t & r)
120 rv() = r.rv();
123 real_t::real_t(const struct real_value & rv)
125 this->rv() = rv;
128 // HOST_WIDE_INT is probably == d_uns64 this is probably zero, so this is probably zero...
129 real_t::real_t(int v)
131 *this = v;
134 real_t::real_t(d_uns64 v)
136 # if HOST_BITS_PER_WIDE_INT == 32
137 REAL_VALUE_FROM_UNSIGNED_INT(rv(),
138 v & 0xffffffff, (v >> 32) & 0xffffffff,
139 max_float_mode());
140 # elif HOST_BITS_PER_WIDE_INT == 64
141 REAL_VALUE_FROM_UNSIGNED_INT(rv(), v, 0,
142 max_float_mode());
143 # else
144 # error Fix This
145 # endif
149 real_t::real_t(d_int64 v)
151 # if HOST_BITS_PER_WIDE_INT == 32
152 REAL_VALUE_FROM_INT(rv(), v & 0xffffffff,
153 (v >> 32) & 0xffffffff, max_float_mode());
154 # elif HOST_BITS_PER_WIDE_INT == 64
155 REAL_VALUE_FROM_INT(rv(), v,
156 (v & 0x8000000000000000ULL) ? ~(unsigned HOST_WIDE_INT) 0 : 0,
157 max_float_mode());
158 # else
159 # error Fix This
160 # endif
163 real_t & real_t::operator=(const real_t & r)
165 rv() = r.rv();
166 return *this;
169 real_t & real_t::operator=(int v)
171 REAL_VALUE_FROM_UNSIGNED_INT(rv(), v, 0, max_float_mode());
172 return *this;
175 real_t real_t::operator+ (const real_t & r)
177 real_t x;
178 REAL_ARITHMETIC(x.rv(), PLUS_EXPR, rv(), r.rv());
179 return x;
182 real_t real_t::operator- (const real_t & r)
184 real_t x;
185 REAL_ARITHMETIC(x.rv(), MINUS_EXPR, rv(), r.rv());
186 return x;
189 real_t real_t::operator- ()
191 real_t x;
192 x.rv() = REAL_VALUE_NEGATE(rv());
193 return x;
196 real_t real_t::operator* (const real_t & r)
198 real_t x;
199 REAL_ARITHMETIC(x.rv(), MULT_EXPR, rv(), r.rv());
200 return x;
203 real_t real_t::operator/ (const real_t & r)
205 real_t x;
206 REAL_ARITHMETIC(x.rv(), RDIV_EXPR, rv(), r.rv());
207 return x;
210 // Using darwin fmodl man page for special cases
211 real_t real_t::operator% (const real_t & r)
213 REAL_VALUE_TYPE quot, tmp, x;
214 // %% inf cases..
216 // %% signal error?
217 if (r.rv().cl == rvc_zero || REAL_VALUE_ISINF(rv())) {
218 REAL_VALUE_TYPE rvt;
219 real_nan(& rvt, "", 1, max_float_mode());
220 return real_t(rvt);
223 if ( rv().cl == rvc_zero ) {
224 return *this;
227 if ( REAL_VALUE_ISINF(r.rv()) ) {
228 return *this;
231 // %% need to check for NaN?
232 REAL_ARITHMETIC(quot, RDIV_EXPR, rv(), r.rv());
233 quot = real_arithmetic2(FIX_TRUNC_EXPR, & quot, NULL);
234 REAL_ARITHMETIC(tmp, MULT_EXPR, quot, r.rv());
235 REAL_ARITHMETIC(x, MINUS_EXPR, rv(), tmp);
237 return real_t(x);
240 bool real_t::operator< (const real_t & r)
242 return real_compare(LT_EXPR, & rv(), & r.rv());
245 bool real_t::operator> (const real_t & r)
247 return real_compare(GT_EXPR, & rv(), & r.rv());
250 bool real_t::operator<= (const real_t & r)
252 return real_compare(LE_EXPR, & rv(), & r.rv());
255 bool real_t::operator>= (const real_t & r)
257 return real_compare(GE_EXPR, & rv(), & r.rv());
260 bool real_t::operator== (const real_t & r)
262 return real_compare(EQ_EXPR, & rv(), & r.rv());
265 bool real_t::operator!= (const real_t & r)
267 return real_compare(NE_EXPR, & rv(), & r.rv());
271 real_t::operator d_uns64()
273 // this may not be the same as native real->int
274 // %% host_wide_int
275 return real_to_integer(& rv());
279 d_uns64
280 real_t::toInt() const
282 HOST_WIDE_INT low, high;
283 real_to_integer2(& low, & high, & rv());
284 return gen.hwi2toli(low, high);
287 d_uns64
288 real_t::toInt(Type * real_type, Type * int_type) const
290 tree t = fold( build1(FIX_TRUNC_EXPR, int_type->toCtype(),
291 gen.floatConstant(rv(), real_type->toBasetype()->isTypeBasic())) );
292 // can't use tree_low_cst as it asserts !TREE_OVERFLOW
293 return gen.hwi2toli(TREE_INT_CST_LOW(t), TREE_INT_CST_HIGH(t));
296 real_t
297 real_t::convert(MyMode to_mode) const
299 real_t result;
300 real_convert(& result.rv(), myMode_to_machineMode(to_mode), & rv());
301 return result;
304 bool
305 real_t::isZero()
307 return rv().cl == rvc_zero;
310 bool
311 real_t::isNegative()
313 return REAL_VALUE_NEGATIVE(rv());
316 bool
317 real_t::floatCompare(int op, const real_t & r)
319 enum tree_code out;
321 switch ( (enum TOK) op ) {
322 case TOKleg: out = ORDERED_EXPR; break; //n = r1 <>= r2; break;
323 case TOKlg:
324 return *this < r || * this > r;
325 // n = r1 <> r2; break;
326 case TOKunord: out = UNORDERED_EXPR; break; // n = r1 !<>= r2; break;
327 case TOKue: out = UNEQ_EXPR; break; // n = r1 !<> r2; break;
328 case TOKug: out = UNGT_EXPR; break; // n = r1 !<= r2; break;
329 case TOKuge: out = UNGE_EXPR; break; // n = r1 !< r2; break;
330 case TOKul: out = UNLT_EXPR; break; // n = r1 !>= r2; break;
331 case TOKule: out = UNLE_EXPR; break; // n = r1 !> r2; break;
332 default:
333 abort();
335 return real_compare(out, & rv(), & r.rv());
338 bool
339 real_t::isIdenticalTo(const real_t & r) const
341 return REAL_VALUES_IDENTICAL(rv(), r.rv());
344 void
345 real_t::format(char * buf, unsigned buf_size) const
347 real_to_decimal(buf, & rv(), buf_size, 0, 1);
350 void
351 real_t::formatHex(char * buf, unsigned buf_size) const
353 real_to_hexadecimal(buf, & rv(), buf_size, 0, 1);
356 bool
357 real_t::isInf()
359 return REAL_VALUE_ISINF(rv());
362 bool
363 real_t::isNan()
365 return REAL_VALUE_ISNAN(rv());
368 bool
369 real_t::isConversionExact(MyMode to_mode) const
371 return exact_real_truncate(myMode_to_machineMode(to_mode), & rv());
374 void
375 real_t::toBytes(unsigned char * buf, unsigned buf_size)
377 // See assemble_real in varasm.c
378 // This code assumes we are storing into 8-bit host bytes.
379 unsigned ld_size = int_size_in_bytes(long_double_type_node);
380 unsigned count = ld_size;
381 long data[4];
382 long *src = data;
383 unsigned char *dest = buf;
385 // assert(ld_size == REALSIZE);
386 // assert(buf_size >= REALSIZE);
387 assert( ld_size <= 16 );
389 real_to_target (data, & rv(), TYPE_MODE(long_double_type_node));
390 while (count) {
391 long l = *src++;
392 for (int i = 4; i && count; i--) {
393 *dest++ = l & 0xff;
394 l >>= 8;
395 count--;
401 void
402 real_t::dump()
404 char buf[128];
405 format(buf, sizeof(buf));
406 fprintf(stderr, "%s\n", buf);