1 /* d-longdouble.cc -- Software floating-point emulation for the frontend. 2 Copyright (C) 2006-2019 Free Software Foundation, Inc. 3 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) 7 any later version. 8 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. 13 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/>. */ 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. */ 34 real_t CTFloat::zero; 35 real_t CTFloat::one; 36 real_t CTFloat::minusone; 37 real_t CTFloat::half; 38 39 /* Truncate longdouble to the highest precision supported by target. */ 40 41 longdouble 42 longdouble::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 51 void 52 longdouble::set (real_value& d) 53 { 54 real_convert (&this->rv (), TYPE_MODE (long_double_type_node), &d); 55 } 56 57 /* Conversion routines between longdouble and integer types. */ 58 59 void 60 longdouble::set (int32_t d) 61 { 62 real_from_integer (&this->rv (), TYPE_MODE (double_type_node), d, SIGNED); 63 } 64 65 void 66 longdouble::set (int64_t d) 67 { 68 real_from_integer (&this->rv (), TYPE_MODE (long_double_type_node), d, 69 SIGNED); 70 } 71 72 int64_t 73 longdouble::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 82 void 83 longdouble::set (uint32_t d) 84 { 85 real_from_integer (&this->rv (), TYPE_MODE (double_type_node), d, UNSIGNED); 86 } 87 88 void 89 longdouble::set (uint64_t d) 90 { 91 real_from_integer (&this->rv (), TYPE_MODE (long_double_type_node), d, 92 UNSIGNED); 93 } 94 95 uint64_t 96 longdouble::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 105 void 106 longdouble::set (bool d) 107 { 108 this->rv () = (d == false) ? dconst0 : dconst1; 109 } 110 111 bool 112 longdouble::to_bool (void) const 113 { 114 return this->rv ().cl != rvc_zero; 115 } 116 117 /* Overload numeric operators for longdouble types. */ 118 119 longdouble 120 longdouble::add (const longdouble& r) const 121 { 122 longdouble x; 123 real_arithmetic (&x.rv (), PLUS_EXPR, &this->rv (), &r.rv ()); 124 return x.normalize (); 125 } 126 127 longdouble 128 longdouble::sub (const longdouble& r) const 129 { 130 longdouble x; 131 real_arithmetic (&x.rv (), MINUS_EXPR, &this->rv (), &r.rv ()); 132 return x.normalize (); 133 } 134 135 longdouble 136 longdouble::mul (const longdouble& r) const 137 { 138 longdouble x; 139 real_arithmetic (&x.rv (), MULT_EXPR, &this->rv (), &r.rv ()); 140 return x.normalize (); 141 } 142 143 longdouble 144 longdouble::div (const longdouble& r) const 145 { 146 longdouble x; 147 real_arithmetic (&x.rv (), RDIV_EXPR, &this->rv (), &r.rv ()); 148 return x.normalize (); 149 } 150 151 longdouble 152 longdouble::mod (const longdouble& r) const 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 178 longdouble 179 longdouble::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 188 int 189 longdouble::cmp (const longdouble& r) const 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 200 int 201 longdouble::equals (const longdouble& r) const 202 { 203 return real_compare (EQ_EXPR, &this->rv (), &r.rv ()); 204 } 205