comparison gcc/sreal.c @ 16:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents f6334be47118
children 84e7813d76e9
comparison
equal deleted inserted replaced
15:561a7518be6b 16:04ced10e8804
1 /* Simple data type for positive real numbers for the GNU compiler. 1 /* Simple data type for real numbers for the GNU compiler.
2 Copyright (C) 2002, 2003, 2004, 2007, 2010 Free Software Foundation, Inc. 2 Copyright (C) 2002-2017 Free Software Foundation, Inc.
3 3
4 This file is part of GCC. 4 This file is part of GCC.
5 5
6 GCC is free software; you can redistribute it and/or modify it under 6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free 7 the terms of the GNU General Public License as published by the Free
15 15
16 You should have received a copy of the GNU General Public License 16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see 17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */ 18 <http://www.gnu.org/licenses/>. */
19 19
20 /* This library supports positive real numbers and 0; 20 /* This library supports real numbers;
21 inf and nan are NOT supported. 21 inf and nan are NOT supported.
22 It is written to be simple and fast. 22 It is written to be simple and fast.
23 23
24 Value of sreal is 24 Value of sreal is
25 x = sig * 2 ^ exp 25 x = sig * 2 ^ exp
26 where 26 where
27 sig = significant 27 sig = significant
28 (for < 64-bit machines sig = sig_lo + sig_hi * 2 ^ SREAL_PART_BITS) 28 (for < 64-bit machines sig = sig_lo + sig_hi * 2 ^ SREAL_PART_BITS)
29 exp = exponent 29 exp = exponent
30 30
31 One HOST_WIDE_INT is used for the significant on 64-bit (and more than 31 One uint64_t is used for the significant.
32 64-bit) machines,
33 otherwise two HOST_WIDE_INTs are used for the significant.
34 Only a half of significant bits is used (in normalized sreals) so that we do 32 Only a half of significant bits is used (in normalized sreals) so that we do
35 not have problems with overflow, for example when c->sig = a->sig * b->sig. 33 not have problems with overflow, for example when c->sig = a->sig * b->sig.
36 So the precision for 64-bit and 32-bit machines is 32-bit. 34 So the precision is 32-bit.
37 35
38 Invariant: The numbers are normalized before and after each call of sreal_*. 36 Invariant: The numbers are normalized before and after each call of sreal_*.
39 37
40 Normalized sreals: 38 Normalized sreals:
41 All numbers (except zero) meet following conditions: 39 All numbers (except zero) meet following conditions:
49 sig == 0 && exp == -SREAL_MAX_EXP 47 sig == 0 && exp == -SREAL_MAX_EXP
50 */ 48 */
51 49
52 #include "config.h" 50 #include "config.h"
53 #include "system.h" 51 #include "system.h"
52 #include <math.h>
54 #include "coretypes.h" 53 #include "coretypes.h"
55 #include "sreal.h" 54 #include "sreal.h"
56 55 #include "selftest.h"
57 static inline void copy (sreal *, sreal *); 56 #include "backend.h"
58 static inline void shift_right (sreal *, int); 57 #include "tree.h"
59 static void normalize (sreal *); 58 #include "gimple.h"
59 #include "cgraph.h"
60 #include "data-streamer.h"
60 61
61 /* Print the content of struct sreal. */ 62 /* Print the content of struct sreal. */
62 63
63 void 64 void
64 dump_sreal (FILE *file, sreal *x) 65 sreal::dump (FILE *file) const
65 { 66 {
66 #if SREAL_PART_BITS < 32 67 fprintf (file, "(%" PRIi64 " * 2^%d)", m_sig, m_exp);
67 fprintf (file, "((" HOST_WIDE_INT_PRINT_UNSIGNED " * 2^16 + " 68 }
68 HOST_WIDE_INT_PRINT_UNSIGNED ") * 2^%d)", 69
69 x->sig_hi, x->sig_lo, x->exp); 70 DEBUG_FUNCTION void
70 #else 71 debug (const sreal &ref)
71 fprintf (file, "(" HOST_WIDE_INT_PRINT_UNSIGNED " * 2^%d)", x->sig, x->exp); 72 {
72 #endif 73 ref.dump (stderr);
73 } 74 }
74 75
75 /* Copy the sreal number. */ 76 DEBUG_FUNCTION void
76 77 debug (const sreal *ptr)
77 static inline void 78 {
78 copy (sreal *r, sreal *a) 79 if (ptr)
79 { 80 debug (*ptr);
80 #if SREAL_PART_BITS < 32 81 else
81 r->sig_lo = a->sig_lo; 82 fprintf (stderr, "<nil>\n");
82 r->sig_hi = a->sig_hi; 83 }
83 #else 84
84 r->sig = a->sig; 85 /* Shift this right by S bits. Needed: 0 < S <= SREAL_BITS.
85 #endif 86 When the most significant bit shifted out is 1, add 1 to this (rounding).
86 r->exp = a->exp; 87 */
87 } 88
88 89 void
89 /* Shift X right by S bits. Needed: 0 < S <= SREAL_BITS. 90 sreal::shift_right (int s)
90 When the most significant bit shifted out is 1, add 1 to X (rounding). */ 91 {
91 92 gcc_checking_assert (s > 0);
92 static inline void 93 gcc_checking_assert (s <= SREAL_BITS);
93 shift_right (sreal *x, int s)
94 {
95 gcc_assert (s > 0);
96 gcc_assert (s <= SREAL_BITS);
97 /* Exponent should never be so large because shift_right is used only by 94 /* Exponent should never be so large because shift_right is used only by
98 sreal_add and sreal_sub ant thus the number cannot be shifted out from 95 sreal_add and sreal_sub ant thus the number cannot be shifted out from
99 exponent range. */ 96 exponent range. */
100 gcc_assert (x->exp + s <= SREAL_MAX_EXP); 97 gcc_checking_assert (m_exp + s <= SREAL_MAX_EXP);
101 98
102 x->exp += s; 99 m_exp += s;
103 100
104 #if SREAL_PART_BITS < 32 101 m_sig += (int64_t) 1 << (s - 1);
105 if (s > SREAL_PART_BITS) 102 m_sig >>= s;
106 { 103 }
107 s -= SREAL_PART_BITS; 104
108 x->sig_hi += (uhwi) 1 << (s - 1); 105 /* Return integer value of *this. */
109 x->sig_lo = x->sig_hi >> s; 106
110 x->sig_hi = 0; 107 int64_t
111 } 108 sreal::to_int () const
109 {
110 int64_t sign = SREAL_SIGN (m_sig);
111
112 if (m_exp <= -SREAL_BITS)
113 return 0;
114 if (m_exp >= SREAL_PART_BITS)
115 return sign * INTTYPE_MAXIMUM (int64_t);
116 if (m_exp > 0)
117 return sign * (SREAL_ABS (m_sig) << m_exp);
118 if (m_exp < 0)
119 return m_sig >> -m_exp;
120 return m_sig;
121 }
122
123 /* Return value of *this as double.
124 This should be used for debug output only. */
125
126 double
127 sreal::to_double () const
128 {
129 double val = m_sig;
130 if (m_exp)
131 val = ldexp (val, m_exp);
132 return val;
133 }
134
135 /* Return *this + other. */
136
137 sreal
138 sreal::operator+ (const sreal &other) const
139 {
140 int dexp;
141 sreal tmp, r;
142
143 const sreal *a_p = this, *b_p = &other, *bb;
144
145 if (a_p->m_exp < b_p->m_exp)
146 std::swap (a_p, b_p);
147
148 dexp = a_p->m_exp - b_p->m_exp;
149 r.m_exp = a_p->m_exp;
150 if (dexp > SREAL_BITS)
151 {
152 r.m_sig = a_p->m_sig;
153 return r;
154 }
155
156 if (dexp == 0)
157 bb = b_p;
112 else 158 else
113 { 159 {
114 x->sig_lo += (uhwi) 1 << (s - 1); 160 tmp = *b_p;
115 if (x->sig_lo & ((uhwi) 1 << SREAL_PART_BITS)) 161 tmp.shift_right (dexp);
116 { 162 bb = &tmp;
117 x->sig_hi++; 163 }
118 x->sig_lo -= (uhwi) 1 << SREAL_PART_BITS; 164
119 } 165 r.m_sig = a_p->m_sig + bb->m_sig;
120 x->sig_lo >>= s; 166 r.normalize ();
121 x->sig_lo |= (x->sig_hi & (((uhwi) 1 << s) - 1)) << (SREAL_PART_BITS - s);
122 x->sig_hi >>= s;
123 }
124 #else
125 x->sig += (uhwi) 1 << (s - 1);
126 x->sig >>= s;
127 #endif
128 }
129
130 /* Normalize *X. */
131
132 static void
133 normalize (sreal *x)
134 {
135 #if SREAL_PART_BITS < 32
136 int shift;
137 HOST_WIDE_INT mask;
138
139 if (x->sig_lo == 0 && x->sig_hi == 0)
140 {
141 x->exp = -SREAL_MAX_EXP;
142 }
143 else if (x->sig_hi < SREAL_MIN_SIG)
144 {
145 if (x->sig_hi == 0)
146 {
147 /* Move lower part of significant to higher part. */
148 x->sig_hi = x->sig_lo;
149 x->sig_lo = 0;
150 x->exp -= SREAL_PART_BITS;
151 }
152 shift = 0;
153 while (x->sig_hi < SREAL_MIN_SIG)
154 {
155 x->sig_hi <<= 1;
156 x->exp--;
157 shift++;
158 }
159 /* Check underflow. */
160 if (x->exp < -SREAL_MAX_EXP)
161 {
162 x->exp = -SREAL_MAX_EXP;
163 x->sig_hi = 0;
164 x->sig_lo = 0;
165 }
166 else if (shift)
167 {
168 mask = (1 << SREAL_PART_BITS) - (1 << (SREAL_PART_BITS - shift));
169 x->sig_hi |= (x->sig_lo & mask) >> (SREAL_PART_BITS - shift);
170 x->sig_lo = (x->sig_lo << shift) & (((uhwi) 1 << SREAL_PART_BITS) - 1);
171 }
172 }
173 else if (x->sig_hi > SREAL_MAX_SIG)
174 {
175 unsigned HOST_WIDE_INT tmp = x->sig_hi;
176
177 /* Find out how many bits will be shifted. */
178 shift = 0;
179 do
180 {
181 tmp >>= 1;
182 shift++;
183 }
184 while (tmp > SREAL_MAX_SIG);
185
186 /* Round the number. */
187 x->sig_lo += (uhwi) 1 << (shift - 1);
188
189 x->sig_lo >>= shift;
190 x->sig_lo += ((x->sig_hi & (((uhwi) 1 << shift) - 1))
191 << (SREAL_PART_BITS - shift));
192 x->sig_hi >>= shift;
193 x->exp += shift;
194 if (x->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
195 {
196 x->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
197 x->sig_hi++;
198 if (x->sig_hi > SREAL_MAX_SIG)
199 {
200 /* x->sig_hi was SREAL_MAX_SIG before increment
201 so now last bit is zero. */
202 x->sig_hi >>= 1;
203 x->sig_lo >>= 1;
204 x->exp++;
205 }
206 }
207
208 /* Check overflow. */
209 if (x->exp > SREAL_MAX_EXP)
210 {
211 x->exp = SREAL_MAX_EXP;
212 x->sig_hi = SREAL_MAX_SIG;
213 x->sig_lo = SREAL_MAX_SIG;
214 }
215 }
216 #else
217 if (x->sig == 0)
218 {
219 x->exp = -SREAL_MAX_EXP;
220 }
221 else if (x->sig < SREAL_MIN_SIG)
222 {
223 do
224 {
225 x->sig <<= 1;
226 x->exp--;
227 }
228 while (x->sig < SREAL_MIN_SIG);
229
230 /* Check underflow. */
231 if (x->exp < -SREAL_MAX_EXP)
232 {
233 x->exp = -SREAL_MAX_EXP;
234 x->sig = 0;
235 }
236 }
237 else if (x->sig > SREAL_MAX_SIG)
238 {
239 int last_bit;
240 do
241 {
242 last_bit = x->sig & 1;
243 x->sig >>= 1;
244 x->exp++;
245 }
246 while (x->sig > SREAL_MAX_SIG);
247
248 /* Round the number. */
249 x->sig += last_bit;
250 if (x->sig > SREAL_MAX_SIG)
251 {
252 x->sig >>= 1;
253 x->exp++;
254 }
255
256 /* Check overflow. */
257 if (x->exp > SREAL_MAX_EXP)
258 {
259 x->exp = SREAL_MAX_EXP;
260 x->sig = SREAL_MAX_SIG;
261 }
262 }
263 #endif
264 }
265
266 /* Set *R to SIG * 2 ^ EXP. Return R. */
267
268 sreal *
269 sreal_init (sreal *r, unsigned HOST_WIDE_INT sig, signed int exp)
270 {
271 #if SREAL_PART_BITS < 32
272 r->sig_lo = 0;
273 r->sig_hi = sig;
274 r->exp = exp - 16;
275 #else
276 r->sig = sig;
277 r->exp = exp;
278 #endif
279 normalize (r);
280 return r; 167 return r;
281 } 168 }
282 169
283 /* Return integer value of *R. */ 170
284 171 /* Return *this - other. */
285 HOST_WIDE_INT 172
286 sreal_to_int (sreal *r) 173 sreal
287 { 174 sreal::operator- (const sreal &other) const
288 #if SREAL_PART_BITS < 32
289 if (r->exp <= -SREAL_BITS)
290 return 0;
291 if (r->exp >= 0)
292 return MAX_HOST_WIDE_INT;
293 return ((r->sig_hi << SREAL_PART_BITS) + r->sig_lo) >> -r->exp;
294 #else
295 if (r->exp <= -SREAL_BITS)
296 return 0;
297 if (r->exp >= SREAL_PART_BITS)
298 return MAX_HOST_WIDE_INT;
299 if (r->exp > 0)
300 return r->sig << r->exp;
301 if (r->exp < 0)
302 return r->sig >> -r->exp;
303 return r->sig;
304 #endif
305 }
306
307 /* Compare *A and *B. Return -1 if *A < *B, 1 if *A > *B and 0 if *A == *B. */
308
309 int
310 sreal_compare (sreal *a, sreal *b)
311 {
312 if (a->exp > b->exp)
313 return 1;
314 if (a->exp < b->exp)
315 return -1;
316 #if SREAL_PART_BITS < 32
317 if (a->sig_hi > b->sig_hi)
318 return 1;
319 if (a->sig_hi < b->sig_hi)
320 return -1;
321 if (a->sig_lo > b->sig_lo)
322 return 1;
323 if (a->sig_lo < b->sig_lo)
324 return -1;
325 #else
326 if (a->sig > b->sig)
327 return 1;
328 if (a->sig < b->sig)
329 return -1;
330 #endif
331 return 0;
332 }
333
334 /* *R = *A + *B. Return R. */
335
336 sreal *
337 sreal_add (sreal *r, sreal *a, sreal *b)
338 { 175 {
339 int dexp; 176 int dexp;
340 sreal tmp; 177 sreal tmp, r;
341 sreal *bb; 178 const sreal *bb;
342 179 const sreal *a_p = this, *b_p = &other;
343 if (sreal_compare (a, b) < 0) 180
344 { 181 int64_t sign = 1;
345 sreal *swap; 182 if (a_p->m_exp < b_p->m_exp)
346 swap = a; 183 {
347 a = b; 184 sign = -1;
348 b = swap; 185 std::swap (a_p, b_p);
349 } 186 }
350 187
351 dexp = a->exp - b->exp; 188 dexp = a_p->m_exp - b_p->m_exp;
352 r->exp = a->exp; 189 r.m_exp = a_p->m_exp;
353 if (dexp > SREAL_BITS) 190 if (dexp > SREAL_BITS)
354 { 191 {
355 #if SREAL_PART_BITS < 32 192 r.m_sig = sign * a_p->m_sig;
356 r->sig_hi = a->sig_hi;
357 r->sig_lo = a->sig_lo;
358 #else
359 r->sig = a->sig;
360 #endif
361 return r; 193 return r;
362 } 194 }
363
364 if (dexp == 0) 195 if (dexp == 0)
365 bb = b; 196 bb = b_p;
366 else 197 else
367 { 198 {
368 copy (&tmp, b); 199 tmp = *b_p;
369 shift_right (&tmp, dexp); 200 tmp.shift_right (dexp);
370 bb = &tmp; 201 bb = &tmp;
371 } 202 }
372 203
373 #if SREAL_PART_BITS < 32 204 r.m_sig = sign * (a_p->m_sig - bb->m_sig);
374 r->sig_hi = a->sig_hi + bb->sig_hi; 205 r.normalize ();
375 r->sig_lo = a->sig_lo + bb->sig_lo;
376 if (r->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
377 {
378 r->sig_hi++;
379 r->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
380 }
381 #else
382 r->sig = a->sig + bb->sig;
383 #endif
384 normalize (r);
385 return r; 206 return r;
386 } 207 }
387 208
388 /* *R = *A - *B. Return R. */ 209 /* Return *this * other. */
389 210
390 sreal * 211 sreal
391 sreal_sub (sreal *r, sreal *a, sreal *b) 212 sreal::operator* (const sreal &other) const
392 { 213 {
393 int dexp; 214 sreal r;
394 sreal tmp; 215 if (absu_hwi (m_sig) < SREAL_MIN_SIG || absu_hwi (other.m_sig) < SREAL_MIN_SIG)
395 sreal *bb; 216 {
396 217 r.m_sig = 0;
397 gcc_assert (sreal_compare (a, b) >= 0); 218 r.m_exp = -SREAL_MAX_EXP;
398 219 }
399 dexp = a->exp - b->exp;
400 r->exp = a->exp;
401 if (dexp > SREAL_BITS)
402 {
403 #if SREAL_PART_BITS < 32
404 r->sig_hi = a->sig_hi;
405 r->sig_lo = a->sig_lo;
406 #else
407 r->sig = a->sig;
408 #endif
409 return r;
410 }
411 if (dexp == 0)
412 bb = b;
413 else 220 else
414 { 221 {
415 copy (&tmp, b); 222 r.m_sig = m_sig * other.m_sig;
416 shift_right (&tmp, dexp); 223 r.m_exp = m_exp + other.m_exp;
417 bb = &tmp; 224 r.normalize ();
418 } 225 }
419 226
420 #if SREAL_PART_BITS < 32
421 if (a->sig_lo < bb->sig_lo)
422 {
423 r->sig_hi = a->sig_hi - bb->sig_hi - 1;
424 r->sig_lo = a->sig_lo + ((uhwi) 1 << SREAL_PART_BITS) - bb->sig_lo;
425 }
426 else
427 {
428 r->sig_hi = a->sig_hi - bb->sig_hi;
429 r->sig_lo = a->sig_lo - bb->sig_lo;
430 }
431 #else
432 r->sig = a->sig - bb->sig;
433 #endif
434 normalize (r);
435 return r; 227 return r;
436 } 228 }
437 229
438 /* *R = *A * *B. Return R. */ 230 /* Return *this / other. */
439 231
440 sreal * 232 sreal
441 sreal_mul (sreal *r, sreal *a, sreal *b) 233 sreal::operator/ (const sreal &other) const
442 { 234 {
443 #if SREAL_PART_BITS < 32 235 gcc_checking_assert (other.m_sig != 0);
444 if (a->sig_hi < SREAL_MIN_SIG || b->sig_hi < SREAL_MIN_SIG) 236 sreal r;
445 { 237 r.m_sig
446 r->sig_lo = 0; 238 = SREAL_SIGN (m_sig) * (SREAL_ABS (m_sig) << SREAL_PART_BITS) / other.m_sig;
447 r->sig_hi = 0; 239 r.m_exp = m_exp - other.m_exp - SREAL_PART_BITS;
448 r->exp = -SREAL_MAX_EXP; 240 r.normalize ();
449 }
450 else
451 {
452 unsigned HOST_WIDE_INT tmp1, tmp2, tmp3;
453 if (sreal_compare (a, b) < 0)
454 {
455 sreal *swap;
456 swap = a;
457 a = b;
458 b = swap;
459 }
460
461 r->exp = a->exp + b->exp + SREAL_PART_BITS;
462
463 tmp1 = a->sig_lo * b->sig_lo;
464 tmp2 = a->sig_lo * b->sig_hi;
465 tmp3 = a->sig_hi * b->sig_lo + (tmp1 >> SREAL_PART_BITS);
466
467 r->sig_hi = a->sig_hi * b->sig_hi;
468 r->sig_hi += (tmp2 >> SREAL_PART_BITS) + (tmp3 >> SREAL_PART_BITS);
469 tmp2 &= ((uhwi) 1 << SREAL_PART_BITS) - 1;
470 tmp3 &= ((uhwi) 1 << SREAL_PART_BITS) - 1;
471 tmp1 = tmp2 + tmp3;
472
473 r->sig_lo = tmp1 & (((uhwi) 1 << SREAL_PART_BITS) - 1);
474 r->sig_hi += tmp1 >> SREAL_PART_BITS;
475
476 normalize (r);
477 }
478 #else
479 if (a->sig < SREAL_MIN_SIG || b->sig < SREAL_MIN_SIG)
480 {
481 r->sig = 0;
482 r->exp = -SREAL_MAX_EXP;
483 }
484 else
485 {
486 r->sig = a->sig * b->sig;
487 r->exp = a->exp + b->exp;
488 normalize (r);
489 }
490 #endif
491 return r; 241 return r;
492 } 242 }
493 243
494 /* *R = *A / *B. Return R. */ 244 /* Stream sreal value to OB. */
495 245
496 sreal * 246 void
497 sreal_div (sreal *r, sreal *a, sreal *b) 247 sreal::stream_out (struct output_block *ob)
498 { 248 {
499 #if SREAL_PART_BITS < 32 249 streamer_write_hwi (ob, m_sig);
500 unsigned HOST_WIDE_INT tmp, tmp1, tmp2; 250 streamer_write_hwi (ob, m_exp);
501 251 }
502 gcc_assert (b->sig_hi >= SREAL_MIN_SIG); 252
503 if (a->sig_hi < SREAL_MIN_SIG) 253 /* Read sreal value from IB. */
504 { 254
505 r->sig_hi = 0; 255 sreal
506 r->sig_lo = 0; 256 sreal::stream_in (struct lto_input_block *ib)
507 r->exp = -SREAL_MAX_EXP; 257 {
508 } 258 sreal val;
509 else 259 val.m_sig = streamer_read_hwi (ib);
510 { 260 val.m_exp = streamer_read_hwi (ib);
511 /* Since division by the whole number is pretty ugly to write 261 return val;
512 we are dividing by first 3/4 of bits of number. */ 262 }
513 263
514 tmp1 = (a->sig_hi << SREAL_PART_BITS) + a->sig_lo; 264 #if CHECKING_P
515 tmp2 = ((b->sig_hi << (SREAL_PART_BITS / 2)) 265
516 + (b->sig_lo >> (SREAL_PART_BITS / 2))); 266 namespace selftest {
517 if (b->sig_lo & ((uhwi) 1 << ((SREAL_PART_BITS / 2) - 1))) 267
518 tmp2++; 268 /* Selftests for sreals. */
519 269
520 r->sig_lo = 0; 270 /* Verify basic sreal operations. */
521 tmp = tmp1 / tmp2; 271
522 tmp1 = (tmp1 % tmp2) << (SREAL_PART_BITS / 2); 272 static void
523 r->sig_hi = tmp << SREAL_PART_BITS; 273 sreal_verify_basics (void)
524 274 {
525 tmp = tmp1 / tmp2; 275 sreal minimum = INT_MIN;
526 tmp1 = (tmp1 % tmp2) << (SREAL_PART_BITS / 2); 276 sreal maximum = INT_MAX;
527 r->sig_hi += tmp << (SREAL_PART_BITS / 2); 277
528 278 sreal seven = 7;
529 tmp = tmp1 / tmp2; 279 sreal minus_two = -2;
530 r->sig_hi += tmp; 280 sreal minus_nine = -9;
531 281
532 r->exp = a->exp - b->exp - SREAL_BITS - SREAL_PART_BITS / 2; 282 ASSERT_EQ (INT_MIN, minimum.to_int ());
533 normalize (r); 283 ASSERT_EQ (INT_MAX, maximum.to_int ());
534 } 284
535 #else 285 ASSERT_FALSE (minus_two < minus_two);
536 gcc_assert (b->sig != 0); 286 ASSERT_FALSE (seven < seven);
537 r->sig = (a->sig << SREAL_PART_BITS) / b->sig; 287 ASSERT_TRUE (seven > minus_two);
538 r->exp = a->exp - b->exp - SREAL_PART_BITS; 288 ASSERT_TRUE (minus_two < seven);
539 normalize (r); 289 ASSERT_TRUE (minus_two != seven);
540 #endif 290 ASSERT_EQ (minus_two, -2);
541 return r; 291 ASSERT_EQ (seven, 7);
542 } 292 ASSERT_EQ ((seven << 10) >> 10, 7);
293 ASSERT_EQ (seven + minus_nine, -2);
294 }
295
296 /* Helper function that performs basic arithmetics and comparison
297 of given arguments A and B. */
298
299 static void
300 verify_aritmetics (int64_t a, int64_t b)
301 {
302 ASSERT_EQ (a, -(-(sreal (a))).to_int ());
303 ASSERT_EQ (a < b, sreal (a) < sreal (b));
304 ASSERT_EQ (a <= b, sreal (a) <= sreal (b));
305 ASSERT_EQ (a == b, sreal (a) == sreal (b));
306 ASSERT_EQ (a != b, sreal (a) != sreal (b));
307 ASSERT_EQ (a > b, sreal (a) > sreal (b));
308 ASSERT_EQ (a >= b, sreal (a) >= sreal (b));
309 ASSERT_EQ (a + b, (sreal (a) + sreal (b)).to_int ());
310 ASSERT_EQ (a - b, (sreal (a) - sreal (b)).to_int ());
311 ASSERT_EQ (b + a, (sreal (b) + sreal (a)).to_int ());
312 ASSERT_EQ (b - a, (sreal (b) - sreal (a)).to_int ());
313 }
314
315 /* Verify arithmetics for interesting numbers. */
316
317 static void
318 sreal_verify_arithmetics (void)
319 {
320 int values[] = {-14123413, -7777, -17, -10, -2, 0, 17, 139, 1234123};
321 unsigned c = sizeof (values) / sizeof (int);
322
323 for (unsigned i = 0; i < c; i++)
324 for (unsigned j = 0; j < c; j++)
325 {
326 int a = values[i];
327 int b = values[j];
328
329 verify_aritmetics (a, b);
330 }
331 }
332
333 /* Helper function that performs various shifting test of a given
334 argument A. */
335
336 static void
337 verify_shifting (int64_t a)
338 {
339 sreal v = a;
340
341 for (unsigned i = 0; i < 16; i++)
342 ASSERT_EQ (a << i, (v << i).to_int());
343
344 a = a << 16;
345 v = v << 16;
346
347 for (unsigned i = 0; i < 16; i++)
348 ASSERT_EQ (a >> i, (v >> i).to_int());
349 }
350
351 /* Verify shifting for interesting numbers. */
352
353 static void
354 sreal_verify_shifting (void)
355 {
356 int values[] = {0, 17, 32, 139, 1024, 55555, 1234123};
357 unsigned c = sizeof (values) / sizeof (int);
358
359 for (unsigned i = 0; i < c; i++)
360 verify_shifting (values[i]);
361 }
362
363 /* Verify division by (of) a negative value. */
364
365 static void
366 sreal_verify_negative_division (void)
367 {
368 ASSERT_EQ (sreal (1) / sreal (1), sreal (1));
369 ASSERT_EQ (sreal (-1) / sreal (-1), sreal (1));
370 ASSERT_EQ (sreal (-1234567) / sreal (-1234567), sreal (1));
371 ASSERT_EQ (sreal (-1234567) / sreal (1234567), sreal (-1));
372 ASSERT_EQ (sreal (1234567) / sreal (-1234567), sreal (-1));
373 }
374
375 /* Run all of the selftests within this file. */
376
377 void sreal_c_tests ()
378 {
379 sreal_verify_basics ();
380 sreal_verify_arithmetics ();
381 sreal_verify_shifting ();
382 sreal_verify_negative_division ();
383 }
384
385 } // namespace selftest
386 #endif /* CHECKING_P */