source: mainline/uspace/lib/softfloat/comparison.c@ 516e780

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 516e780 was 516e780, checked in by GitHub <noreply@…>, 7 years ago

Strip down libmath. (#45)

libmath is mostly unused (except for trunc(), sin() and cos()), and most functions in it are either very imprecise or downright broken. Additionally, it is implemented in manner that conflicts with C standard. Instead of trying to fix all the shortcomings while maintaining unused functionality, I'm opting to simply remove most of it and only keep the parts that are currently necessary.

Later readdition of the removed functions is possible, but there needs to be a reliable way to evaluate their quality first.

  • Property mode set to 100644
File size: 23.0 KB
RevLine 
[b5440cf]1/*
[df4ed85]2 * Copyright (c) 2005 Josef Cejka
[c67aff2]3 * Copyright (c) 2011 Petr Koupy
[b5440cf]4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
[750636a]30/** @addtogroup softfloat
[846848a6]31 * @{
32 */
[c67aff2]33/** @file Comparison functions.
[846848a6]34 */
35
[2416085]36#include "comparison.h"
37#include "common.h"
[b5440cf]38
[c67aff2]39/**
40 * Determines whether the given float represents NaN (either signalling NaN or
41 * quiet NaN).
42 *
43 * @param f Single-precision float.
44 * @return 1 if float is NaN, 0 otherwise.
45 */
[88d5c1e]46int is_float32_nan(float32 f)
[750636a]47{
[c67aff2]48 /* NaN : exp = 0xff and nonzero fraction */
[750636a]49 return ((f.parts.exp == 0xFF) && (f.parts.fraction));
[e591928]50}
[b5440cf]51
[c67aff2]52/**
53 * Determines whether the given float represents NaN (either signalling NaN or
54 * quiet NaN).
55 *
56 * @param d Double-precision float.
57 * @return 1 if float is NaN, 0 otherwise.
58 */
[88d5c1e]59int is_float64_nan(float64 d)
[750636a]60{
[c67aff2]61 /* NaN : exp = 0x7ff and nonzero fraction */
[750636a]62 return ((d.parts.exp == 0x7FF) && (d.parts.fraction));
[e591928]63}
[feef1cd]64
[c67aff2]65/**
66 * Determines whether the given float represents NaN (either signalling NaN or
67 * quiet NaN).
68 *
69 * @param ld Quadruple-precision float.
70 * @return 1 if float is NaN, 0 otherwise.
71 */
[88d5c1e]72int is_float128_nan(float128 ld)
[c67aff2]73{
74 /* NaN : exp = 0x7fff and nonzero fraction */
75 return ((ld.parts.exp == 0x7FF) &&
76 !eq128(ld.parts.frac_hi, ld.parts.frac_lo, 0x0ll, 0x0ll));
77}
78
79/**
80 * Determines whether the given float represents signalling NaN.
81 *
82 * @param f Single-precision float.
83 * @return 1 if float is signalling NaN, 0 otherwise.
84 */
[88d5c1e]85int is_float32_signan(float32 f)
[750636a]86{
[7c3fb9b]87 /*
88 * SigNaN : exp = 0xff and fraction = 0xxxxx..x (binary),
89 * where at least one x is nonzero
90 */
[c67aff2]91 return ((f.parts.exp == 0xFF) &&
92 (f.parts.fraction < 0x400000) && (f.parts.fraction));
[e591928]93}
[b5440cf]94
[c67aff2]95/**
96 * Determines whether the given float represents signalling NaN.
97 *
98 * @param d Double-precision float.
99 * @return 1 if float is signalling NaN, 0 otherwise.
100 */
[88d5c1e]101int is_float64_signan(float64 d)
[750636a]102{
[7c3fb9b]103 /*
104 * SigNaN : exp = 0x7ff and fraction = 0xxxxx..x (binary),
105 * where at least one x is nonzero
106 */
[c67aff2]107 return ((d.parts.exp == 0x7FF) &&
108 (d.parts.fraction) && (d.parts.fraction < 0x8000000000000ll));
[e591928]109}
[feef1cd]110
[c67aff2]111/**
112 * Determines whether the given float represents signalling NaN.
113 *
114 * @param ld Quadruple-precision float.
115 * @return 1 if float is signalling NaN, 0 otherwise.
116 */
[88d5c1e]117int is_float128_signan(float128 ld)
[c67aff2]118{
[7c3fb9b]119 /*
120 * SigNaN : exp = 0x7fff and fraction = 0xxxxx..x (binary),
121 * where at least one x is nonzero
122 */
[c67aff2]123 return ((ld.parts.exp == 0x7FFF) &&
124 (ld.parts.frac_hi || ld.parts.frac_lo) &&
125 lt128(ld.parts.frac_hi, ld.parts.frac_lo, 0x800000000000ll, 0x0ll));
126
127}
128
129/**
130 * Determines whether the given float represents positive or negative infinity.
131 *
132 * @param f Single-precision float.
133 * @return 1 if float is infinite, 0 otherwise.
134 */
[88d5c1e]135int is_float32_infinity(float32 f)
[7e557805]136{
[c67aff2]137 /* NaN : exp = 0x7ff and zero fraction */
[750636a]138 return ((f.parts.exp == 0xFF) && (f.parts.fraction == 0x0));
[e591928]139}
[7e557805]140
[c67aff2]141/**
142 * Determines whether the given float represents positive or negative infinity.
143 *
144 * @param d Double-precision float.
145 * @return 1 if float is infinite, 0 otherwise.
146 */
[88d5c1e]147int is_float64_infinity(float64 d)
[feef1cd]148{
[c67aff2]149 /* NaN : exp = 0x7ff and zero fraction */
[750636a]150 return ((d.parts.exp == 0x7FF) && (d.parts.fraction == 0x0));
[e591928]151}
[feef1cd]152
[c67aff2]153/**
154 * Determines whether the given float represents positive or negative infinity.
155 *
156 * @param ld Quadruple-precision float.
157 * @return 1 if float is infinite, 0 otherwise.
158 */
[88d5c1e]159int is_float128_infinity(float128 ld)
[c67aff2]160{
161 /* NaN : exp = 0x7fff and zero fraction */
162 return ((ld.parts.exp == 0x7FFF) &&
163 eq128(ld.parts.frac_hi, ld.parts.frac_lo, 0x0ll, 0x0ll));
164}
165
166/**
167 * Determines whether the given float represents positive or negative zero.
168 *
169 * @param f Single-precision float.
170 * @return 1 if float is zero, 0 otherwise.
171 */
[88d5c1e]172int is_float32_zero(float32 f)
[3af72dc]173{
[88d5c1e]174 return (((f.bin) & 0x7FFFFFFF) == 0);
[3af72dc]175}
176
[c67aff2]177/**
178 * Determines whether the given float represents positive or negative zero.
179 *
180 * @param d Double-precision float.
181 * @return 1 if float is zero, 0 otherwise.
182 */
[88d5c1e]183int is_float64_zero(float64 d)
[feef1cd]184{
[88d5c1e]185 return (((d.bin) & 0x7FFFFFFFFFFFFFFFll) == 0);
[feef1cd]186}
187
[7e557805]188/**
[c67aff2]189 * Determines whether the given float represents positive or negative zero.
190 *
191 * @param ld Quadruple-precision float.
192 * @return 1 if float is zero, 0 otherwise.
193 */
[88d5c1e]194int is_float128_zero(float128 ld)
[c67aff2]195{
196 uint64_t tmp_hi;
197 uint64_t tmp_lo;
[a35b458]198
[88d5c1e]199 and128(ld.bin.hi, ld.bin.lo,
[c67aff2]200 0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
[a35b458]201
[c67aff2]202 return eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll);
203}
204
205/**
206 * Determine whether two floats are equal. NaNs are not recognized.
207 *
208 * @a First single-precision operand.
209 * @b Second single-precision operand.
210 * @return 1 if both floats are equal, 0 otherwise.
[7e557805]211 */
[88d5c1e]212int is_float32_eq(float32 a, float32 b)
[7e557805]213{
[750636a]214 /* a equals to b or both are zeros (with any sign) */
[88d5c1e]215 return ((a.bin == b.bin) ||
216 (((a.bin | b.bin) & 0x7FFFFFFF) == 0));
[c67aff2]217}
218
219/**
220 * Determine whether two floats are equal. NaNs are not recognized.
221 *
222 * @a First double-precision operand.
223 * @b Second double-precision operand.
224 * @return 1 if both floats are equal, 0 otherwise.
225 */
[88d5c1e]226int is_float64_eq(float64 a, float64 b)
[c67aff2]227{
228 /* a equals to b or both are zeros (with any sign) */
[88d5c1e]229 return ((a.bin == b.bin) ||
230 (((a.bin | b.bin) & 0x7FFFFFFFFFFFFFFFll) == 0));
[c67aff2]231}
232
233/**
234 * Determine whether two floats are equal. NaNs are not recognized.
235 *
236 * @a First quadruple-precision operand.
237 * @b Second quadruple-precision operand.
238 * @return 1 if both floats are equal, 0 otherwise.
239 */
[88d5c1e]240int is_float128_eq(float128 a, float128 b)
[c67aff2]241{
242 uint64_t tmp_hi;
243 uint64_t tmp_lo;
[a35b458]244
[c67aff2]245 /* both are zeros (with any sign) */
[88d5c1e]246 or128(a.bin.hi, a.bin.lo,
247 b.bin.hi, b.bin.lo, &tmp_hi, &tmp_lo);
[c67aff2]248 and128(tmp_hi, tmp_lo,
249 0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
250 int both_zero = eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll);
[a35b458]251
[c67aff2]252 /* a equals to b */
[88d5c1e]253 int are_equal = eq128(a.bin.hi, a.bin.lo, b.bin.hi, b.bin.lo);
[a35b458]254
[c67aff2]255 return are_equal || both_zero;
[7e557805]256}
257
258/**
[c67aff2]259 * Lower-than comparison between two floats. NaNs are not recognized.
260 *
261 * @a First single-precision operand.
262 * @b Second single-precision operand.
263 * @return 1 if a is lower than b, 0 otherwise.
[7e557805]264 */
[1b20da0]265int is_float32_lt(float32 a, float32 b)
[7e557805]266{
[88d5c1e]267 if (((a.bin | b.bin) & 0x7FFFFFFF) == 0) {
268 /* +- zeroes */
269 return 0;
[c67aff2]270 }
[a35b458]271
[c67aff2]272 if ((a.parts.sign) && (b.parts.sign)) {
[750636a]273 /* if both are negative, smaller is that with greater binary value */
[88d5c1e]274 return (a.bin > b.bin);
[c67aff2]275 }
[a35b458]276
[88d5c1e]277 /*
278 * lets negate signs - now will be positive numbers always
279 * bigger than negative (first bit will be set for unsigned
280 * integer comparison)
281 */
[750636a]282 a.parts.sign = !a.parts.sign;
283 b.parts.sign = !b.parts.sign;
[88d5c1e]284 return (a.bin < b.bin);
[7e557805]285}
286
[e649dfa]287/**
[c67aff2]288 * Lower-than comparison between two floats. NaNs are not recognized.
289 *
290 * @a First double-precision operand.
291 * @b Second double-precision operand.
292 * @return 1 if a is lower than b, 0 otherwise.
293 */
[88d5c1e]294int is_float64_lt(float64 a, float64 b)
[c67aff2]295{
[88d5c1e]296 if (((a.bin | b.bin) & 0x7FFFFFFFFFFFFFFFll) == 0) {
297 /* +- zeroes */
298 return 0;
[c67aff2]299 }
[a35b458]300
[c67aff2]301 if ((a.parts.sign) && (b.parts.sign)) {
302 /* if both are negative, smaller is that with greater binary value */
[88d5c1e]303 return (a.bin > b.bin);
[c67aff2]304 }
[a35b458]305
[88d5c1e]306 /*
307 * lets negate signs - now will be positive numbers always
308 * bigger than negative (first bit will be set for unsigned
309 * integer comparison)
310 */
[c67aff2]311 a.parts.sign = !a.parts.sign;
312 b.parts.sign = !b.parts.sign;
[88d5c1e]313 return (a.bin < b.bin);
[c67aff2]314}
315
316/**
317 * Lower-than comparison between two floats. NaNs are not recognized.
318 *
319 * @a First quadruple-precision operand.
320 * @b Second quadruple-precision operand.
321 * @return 1 if a is lower than b, 0 otherwise.
322 */
[88d5c1e]323int is_float128_lt(float128 a, float128 b)
[c67aff2]324{
325 uint64_t tmp_hi;
326 uint64_t tmp_lo;
[a35b458]327
[88d5c1e]328 or128(a.bin.hi, a.bin.lo,
329 b.bin.hi, b.bin.lo, &tmp_hi, &tmp_lo);
[c67aff2]330 and128(tmp_hi, tmp_lo,
331 0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
332 if (eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll)) {
[88d5c1e]333 /* +- zeroes */
334 return 0;
[c67aff2]335 }
[a35b458]336
[c67aff2]337 if ((a.parts.sign) && (b.parts.sign)) {
338 /* if both are negative, smaller is that with greater binary value */
[88d5c1e]339 return lt128(b.bin.hi, b.bin.lo, a.bin.hi, a.bin.lo);
[c67aff2]340 }
[a35b458]341
[88d5c1e]342 /*
343 * lets negate signs - now will be positive numbers always
344 * bigger than negative (first bit will be set for unsigned
345 * integer comparison)
346 */
[c67aff2]347 a.parts.sign = !a.parts.sign;
348 b.parts.sign = !b.parts.sign;
[88d5c1e]349 return lt128(a.bin.hi, a.bin.lo, b.bin.hi, b.bin.lo);
[c67aff2]350}
351
352/**
353 * Greater-than comparison between two floats. NaNs are not recognized.
354 *
355 * @a First single-precision operand.
356 * @b Second single-precision operand.
357 * @return 1 if a is greater than b, 0 otherwise.
[e649dfa]358 */
[1b20da0]359int is_float32_gt(float32 a, float32 b)
[e649dfa]360{
[88d5c1e]361 if (((a.bin | b.bin) & 0x7FFFFFFF) == 0) {
362 /* zeroes are equal with any sign */
363 return 0;
[c67aff2]364 }
[a35b458]365
[c67aff2]366 if ((a.parts.sign) && (b.parts.sign)) {
[750636a]367 /* if both are negative, greater is that with smaller binary value */
[88d5c1e]368 return (a.bin < b.bin);
[c67aff2]369 }
[a35b458]370
[88d5c1e]371 /*
372 * lets negate signs - now will be positive numbers always
373 * bigger than negative (first bit will be set for unsigned
374 * integer comparison)
375 */
[750636a]376 a.parts.sign = !a.parts.sign;
377 b.parts.sign = !b.parts.sign;
[88d5c1e]378 return (a.bin > b.bin);
[e649dfa]379}
380
[c67aff2]381/**
382 * Greater-than comparison between two floats. NaNs are not recognized.
383 *
384 * @a First double-precision operand.
385 * @b Second double-precision operand.
386 * @return 1 if a is greater than b, 0 otherwise.
387 */
[88d5c1e]388int is_float64_gt(float64 a, float64 b)
[c67aff2]389{
[88d5c1e]390 if (((a.bin | b.bin) & 0x7FFFFFFFFFFFFFFFll) == 0) {
391 /* zeroes are equal with any sign */
392 return 0;
[c67aff2]393 }
[a35b458]394
[c67aff2]395 if ((a.parts.sign) && (b.parts.sign)) {
396 /* if both are negative, greater is that with smaller binary value */
[88d5c1e]397 return (a.bin < b.bin);
[c67aff2]398 }
[a35b458]399
[88d5c1e]400 /*
401 * lets negate signs - now will be positive numbers always
402 * bigger than negative (first bit will be set for unsigned
403 * integer comparison)
404 */
[c67aff2]405 a.parts.sign = !a.parts.sign;
406 b.parts.sign = !b.parts.sign;
[88d5c1e]407 return (a.bin > b.bin);
[c67aff2]408}
409
410/**
411 * Greater-than comparison between two floats. NaNs are not recognized.
412 *
413 * @a First quadruple-precision operand.
414 * @b Second quadruple-precision operand.
415 * @return 1 if a is greater than b, 0 otherwise.
416 */
[88d5c1e]417int is_float128_gt(float128 a, float128 b)
[c67aff2]418{
419 uint64_t tmp_hi;
420 uint64_t tmp_lo;
[a35b458]421
[88d5c1e]422 or128(a.bin.hi, a.bin.lo,
423 b.bin.hi, b.bin.lo, &tmp_hi, &tmp_lo);
[c67aff2]424 and128(tmp_hi, tmp_lo,
425 0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
426 if (eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll)) {
[88d5c1e]427 /* zeroes are equal with any sign */
428 return 0;
[c67aff2]429 }
[a35b458]430
[c67aff2]431 if ((a.parts.sign) && (b.parts.sign)) {
432 /* if both are negative, greater is that with smaller binary value */
[88d5c1e]433 return lt128(a.bin.hi, a.bin.lo, b.bin.hi, b.bin.lo);
[c67aff2]434 }
[a35b458]435
[88d5c1e]436 /*
437 * lets negate signs - now will be positive numbers always
438 * bigger than negative (first bit will be set for unsigned
439 * integer comparison)
440 */
[c67aff2]441 a.parts.sign = !a.parts.sign;
442 b.parts.sign = !b.parts.sign;
[88d5c1e]443 return lt128(b.bin.hi, b.bin.lo, a.bin.hi, a.bin.lo);
[c67aff2]444}
445
[c0c38c7c]446#ifdef float32_t
447
448int __gtsf2(float32_t a, float32_t b)
449{
450 float32_u ua;
451 ua.val = a;
[a35b458]452
[c0c38c7c]453 float32_u ub;
454 ub.val = b;
[a35b458]455
[c0c38c7c]456 if ((is_float32_nan(ua.data)) || (is_float32_nan(ub.data))) {
457 // TODO: sigNaNs
458 return -1;
459 }
[a35b458]460
[c0c38c7c]461 if (is_float32_gt(ua.data, ub.data))
462 return 1;
[a35b458]463
[c0c38c7c]464 return 0;
465}
466
467int __gesf2(float32_t a, float32_t b)
468{
469 float32_u ua;
470 ua.val = a;
[a35b458]471
[c0c38c7c]472 float32_u ub;
473 ub.val = b;
[a35b458]474
[c0c38c7c]475 if ((is_float32_nan(ua.data)) || (is_float32_nan(ub.data))) {
476 // TODO: sigNaNs
477 return -1;
478 }
[a35b458]479
[c0c38c7c]480 if (is_float32_eq(ua.data, ub.data))
481 return 0;
[a35b458]482
[c0c38c7c]483 if (is_float32_gt(ua.data, ub.data))
484 return 1;
[a35b458]485
[c0c38c7c]486 return -1;
487}
488
489int __ltsf2(float32_t a, float32_t b)
490{
491 float32_u ua;
492 ua.val = a;
[a35b458]493
[c0c38c7c]494 float32_u ub;
495 ub.val = b;
[a35b458]496
[c0c38c7c]497 if ((is_float32_nan(ua.data)) || (is_float32_nan(ub.data))) {
498 // TODO: sigNaNs
499 return 1;
500 }
[a35b458]501
[c0c38c7c]502 if (is_float32_lt(ua.data, ub.data))
503 return -1;
[a35b458]504
[c0c38c7c]505 return 0;
506}
507
508int __lesf2(float32_t a, float32_t b)
509{
510 float32_u ua;
511 ua.val = a;
[a35b458]512
[c0c38c7c]513 float32_u ub;
514 ub.val = b;
[a35b458]515
[c0c38c7c]516 if ((is_float32_nan(ua.data)) || (is_float32_nan(ub.data))) {
517 // TODO: sigNaNs
518 return 1;
519 }
[a35b458]520
[c0c38c7c]521 if (is_float32_eq(ua.data, ub.data))
522 return 0;
[a35b458]523
[c0c38c7c]524 if (is_float32_lt(ua.data, ub.data))
525 return -1;
[a35b458]526
[c0c38c7c]527 return 1;
528}
529
530int __eqsf2(float32_t a, float32_t b)
531{
532 float32_u ua;
533 ua.val = a;
[a35b458]534
[c0c38c7c]535 float32_u ub;
536 ub.val = b;
[a35b458]537
[c0c38c7c]538 if ((is_float32_nan(ua.data)) || (is_float32_nan(ub.data))) {
539 // TODO: sigNaNs
540 return 1;
541 }
[a35b458]542
[c0c38c7c]543 return is_float32_eq(ua.data, ub.data) - 1;
544}
545
546int __nesf2(float32_t a, float32_t b)
547{
548 /* Strange, but according to GCC documentation */
549 return __eqsf2(a, b);
550}
551
552int __cmpsf2(float32_t a, float32_t b)
553{
554 float32_u ua;
555 ua.val = a;
[a35b458]556
[c0c38c7c]557 float32_u ub;
558 ub.val = b;
[a35b458]559
[c0c38c7c]560 if ((is_float32_nan(ua.data)) || (is_float32_nan(ub.data))) {
561 /* No special constant for unordered - maybe signaled? */
562 return 1;
563 }
[a35b458]564
[c0c38c7c]565 if (is_float32_eq(ua.data, ub.data))
566 return 0;
[a35b458]567
[c0c38c7c]568 if (is_float32_lt(ua.data, ub.data))
569 return -1;
[a35b458]570
[c0c38c7c]571 return 1;
572}
573
574int __unordsf2(float32_t a, float32_t b)
575{
576 float32_u ua;
577 ua.val = a;
[a35b458]578
[c0c38c7c]579 float32_u ub;
580 ub.val = b;
[a35b458]581
[c0c38c7c]582 return ((is_float32_nan(ua.data)) || (is_float32_nan(ub.data)));
583}
584
585int __aeabi_fcmpgt(float32_t a, float32_t b)
586{
587 float32_u ua;
588 ua.val = a;
[a35b458]589
[c0c38c7c]590 float32_u ub;
591 ub.val = b;
[a35b458]592
[c0c38c7c]593 if ((is_float32_nan(ua.data)) || (is_float32_nan(ub.data))) {
594 // TODO: sigNaNs
[565aaff]595 return 0;
[c0c38c7c]596 }
[a35b458]597
[c0c38c7c]598 if (is_float32_gt(ua.data, ub.data))
599 return 1;
[a35b458]600
[c0c38c7c]601 return 0;
602}
603
604int __aeabi_fcmplt(float32_t a, float32_t b)
605{
606 float32_u ua;
607 ua.val = a;
[a35b458]608
[c0c38c7c]609 float32_u ub;
610 ub.val = b;
[a35b458]611
[c0c38c7c]612 if ((is_float32_nan(ua.data)) || (is_float32_nan(ub.data))) {
613 // TODO: sigNaNs
[565aaff]614 return 0;
[c0c38c7c]615 }
[a35b458]616
[c0c38c7c]617 if (is_float32_lt(ua.data, ub.data))
[565aaff]618 return 1;
[a35b458]619
[c0c38c7c]620 return 0;
621}
622
623int __aeabi_fcmpge(float32_t a, float32_t b)
624{
625 float32_u ua;
626 ua.val = a;
[a35b458]627
[c0c38c7c]628 float32_u ub;
629 ub.val = b;
[a35b458]630
[c0c38c7c]631 if ((is_float32_nan(ua.data)) || (is_float32_nan(ub.data))) {
632 // TODO: sigNaNs
[565aaff]633 return 0;
[c0c38c7c]634 }
[a35b458]635
[c0c38c7c]636 if (is_float32_eq(ua.data, ub.data))
[565aaff]637 return 1;
[a35b458]638
[c0c38c7c]639 if (is_float32_gt(ua.data, ub.data))
640 return 1;
[a35b458]641
[565aaff]642 return 0;
[c0c38c7c]643}
644
[3212921]645int __aeabi_fcmple(float32_t a, float32_t b)
646{
647 float32_u ua;
648 ua.val = a;
649
650 float32_u ub;
651 ub.val = b;
652
653 if ((is_float32_nan(ua.data)) || (is_float32_nan(ub.data))) {
654 // TODO: sigNaNs
655 return 0;
656 }
657
658 if (is_float32_eq(ua.data, ub.data))
659 return 1;
660
661 if (is_float32_lt(ua.data, ub.data))
662 return 1;
663
664 return 0;
665}
666
[c0c38c7c]667int __aeabi_fcmpeq(float32_t a, float32_t b)
668{
669 float32_u ua;
670 ua.val = a;
[a35b458]671
[c0c38c7c]672 float32_u ub;
673 ub.val = b;
[a35b458]674
[c0c38c7c]675 if ((is_float32_nan(ua.data)) || (is_float32_nan(ub.data))) {
676 // TODO: sigNaNs
[565aaff]677 return 0;
[c0c38c7c]678 }
[a35b458]679
[565aaff]680 return is_float32_eq(ua.data, ub.data);
[c0c38c7c]681}
682
[516e780]683int __aeabi_fcmpun(float32_t a, float32_t b)
684{
685 float32_u ua;
686 ua.val = a;
687
688 float32_u ub;
689 ub.val = b;
690
691 // TODO: sigNaNs
692 return is_float32_nan(ua.data) || is_float32_nan(ub.data);
693}
694
[c0c38c7c]695#endif
696
697#ifdef float64_t
698
699int __gtdf2(float64_t a, float64_t b)
700{
701 float64_u ua;
702 ua.val = a;
[a35b458]703
[c0c38c7c]704 float64_u ub;
705 ub.val = b;
[a35b458]706
[c0c38c7c]707 if ((is_float64_nan(ua.data)) || (is_float64_nan(ub.data))) {
708 // TODO: sigNaNs
709 return -1;
710 }
[a35b458]711
[c0c38c7c]712 if (is_float64_gt(ua.data, ub.data))
713 return 1;
[a35b458]714
[c0c38c7c]715 return 0;
716}
717
718int __gedf2(float64_t a, float64_t b)
719{
720 float64_u ua;
721 ua.val = a;
[a35b458]722
[c0c38c7c]723 float64_u ub;
724 ub.val = b;
[a35b458]725
[c0c38c7c]726 if ((is_float64_nan(ua.data)) || (is_float64_nan(ub.data))) {
727 // TODO: sigNaNs
728 return -1;
729 }
[a35b458]730
[c0c38c7c]731 if (is_float64_eq(ua.data, ub.data))
732 return 0;
[a35b458]733
[c0c38c7c]734 if (is_float64_gt(ua.data, ub.data))
735 return 1;
[a35b458]736
[c0c38c7c]737 return -1;
738}
739
740int __ltdf2(float64_t a, float64_t b)
741{
742 float64_u ua;
743 ua.val = a;
[a35b458]744
[c0c38c7c]745 float64_u ub;
746 ub.val = b;
[a35b458]747
[c0c38c7c]748 if ((is_float64_nan(ua.data)) || (is_float64_nan(ub.data))) {
749 // TODO: sigNaNs
750 return 1;
751 }
[a35b458]752
[c0c38c7c]753 if (is_float64_lt(ua.data, ub.data))
754 return -1;
[a35b458]755
[c0c38c7c]756 return 0;
757}
758
759int __ledf2(float64_t a, float64_t b)
760{
761 float64_u ua;
762 ua.val = a;
[a35b458]763
[c0c38c7c]764 float64_u ub;
765 ub.val = b;
[a35b458]766
[c0c38c7c]767 if ((is_float64_nan(ua.data)) || (is_float64_nan(ub.data))) {
768 // TODO: sigNaNs
769 return 1;
770 }
[a35b458]771
[c0c38c7c]772 if (is_float64_eq(ua.data, ub.data))
773 return 0;
[a35b458]774
[c0c38c7c]775 if (is_float64_lt(ua.data, ub.data))
776 return -1;
[a35b458]777
[c0c38c7c]778 return 1;
779}
780
781int __eqdf2(float64_t a, float64_t b)
782{
783 float64_u ua;
784 ua.val = a;
[a35b458]785
[c0c38c7c]786 float64_u ub;
787 ub.val = b;
[a35b458]788
[c0c38c7c]789 if ((is_float64_nan(ua.data)) || (is_float64_nan(ub.data))) {
790 // TODO: sigNaNs
791 return 1;
792 }
[a35b458]793
[c0c38c7c]794 return is_float64_eq(ua.data, ub.data) - 1;
795}
796
797int __nedf2(float64_t a, float64_t b)
798{
799 /* Strange, but according to GCC documentation */
800 return __eqdf2(a, b);
801}
802
803int __cmpdf2(float64_t a, float64_t b)
804{
805 float64_u ua;
806 ua.val = a;
[a35b458]807
[c0c38c7c]808 float64_u ub;
809 ub.val = b;
[a35b458]810
[c0c38c7c]811 if ((is_float64_nan(ua.data)) || (is_float64_nan(ub.data))) {
812 /* No special constant for unordered - maybe signaled? */
813 return 1;
814 }
[a35b458]815
[c0c38c7c]816 if (is_float64_eq(ua.data, ub.data))
817 return 0;
[a35b458]818
[c0c38c7c]819 if (is_float64_lt(ua.data, ub.data))
820 return -1;
[a35b458]821
[c0c38c7c]822 return 1;
823}
824
825int __unorddf2(float64_t a, float64_t b)
826{
827 float64_u ua;
828 ua.val = a;
[a35b458]829
[c0c38c7c]830 float64_u ub;
831 ub.val = b;
[a35b458]832
[c0c38c7c]833 return ((is_float64_nan(ua.data)) || (is_float64_nan(ub.data)));
834}
835
836int __aeabi_dcmplt(float64_t a, float64_t b)
837{
838 float64_u ua;
839 ua.val = a;
[a35b458]840
[c0c38c7c]841 float64_u ub;
842 ub.val = b;
[a35b458]843
[c0c38c7c]844 if ((is_float64_nan(ua.data)) || (is_float64_nan(ub.data))) {
845 // TODO: sigNaNs
[565aaff]846 return 0;
[c0c38c7c]847 }
[a35b458]848
[c0c38c7c]849 if (is_float64_lt(ua.data, ub.data))
[565aaff]850 return 1;
[a35b458]851
[c0c38c7c]852 return 0;
853}
854
855int __aeabi_dcmpeq(float64_t a, float64_t b)
856{
857 float64_u ua;
858 ua.val = a;
[a35b458]859
[c0c38c7c]860 float64_u ub;
861 ub.val = b;
[a35b458]862
[c0c38c7c]863 if ((is_float64_nan(ua.data)) || (is_float64_nan(ub.data))) {
864 // TODO: sigNaNs
[565aaff]865 return 0;
[c0c38c7c]866 }
[a35b458]867
[565aaff]868 return is_float64_eq(ua.data, ub.data);
[c0c38c7c]869}
870
871int __aeabi_dcmpgt(float64_t a, float64_t b)
872{
873 float64_u ua;
874 ua.val = a;
[a35b458]875
[c0c38c7c]876 float64_u ub;
877 ub.val = b;
[a35b458]878
[c0c38c7c]879 if ((is_float64_nan(ua.data)) || (is_float64_nan(ub.data))) {
880 // TODO: sigNaNs
[565aaff]881 return 0;
[c0c38c7c]882 }
[a35b458]883
[c0c38c7c]884 if (is_float64_gt(ua.data, ub.data))
885 return 1;
[a35b458]886
[c0c38c7c]887 return 0;
888}
889
890int __aeabi_dcmpge(float64_t a, float64_t b)
891{
892 float64_u ua;
893 ua.val = a;
[a35b458]894
[c0c38c7c]895 float64_u ub;
896 ub.val = b;
[a35b458]897
[c0c38c7c]898 if ((is_float64_nan(ua.data)) || (is_float64_nan(ub.data))) {
899 // TODO: sigNaNs
[565aaff]900 return 0;
[c0c38c7c]901 }
[a35b458]902
[c0c38c7c]903 if (is_float64_eq(ua.data, ub.data))
[565aaff]904 return 1;
[a35b458]905
[c0c38c7c]906 if (is_float64_gt(ua.data, ub.data))
907 return 1;
[a35b458]908
[565aaff]909 return 0;
[c0c38c7c]910}
911
912int __aeabi_dcmple(float64_t a, float64_t b)
913{
914 float64_u ua;
915 ua.val = a;
[a35b458]916
[c0c38c7c]917 float64_u ub;
918 ub.val = b;
[a35b458]919
[c0c38c7c]920 if ((is_float64_nan(ua.data)) || (is_float64_nan(ub.data))) {
921 // TODO: sigNaNs
[565aaff]922 return 0;
[c0c38c7c]923 }
[a35b458]924
[c0c38c7c]925 if (is_float64_eq(ua.data, ub.data))
[565aaff]926 return 1;
[a35b458]927
[c0c38c7c]928 if (is_float64_lt(ua.data, ub.data))
[565aaff]929 return 1;
[a35b458]930
[565aaff]931 return 0;
[c0c38c7c]932}
933
[516e780]934int __aeabi_dcmpun(float64_t a, float64_t b)
935{
936 float64_u ua;
937 ua.val = a;
938
939 float64_u ub;
940 ub.val = b;
941
942 // TODO: sigNaNs
943 return is_float64_nan(ua.data) || is_float64_nan(ub.data);
944}
945
[c0c38c7c]946#endif
947
948#ifdef float128_t
949
950int __gttf2(float128_t a, float128_t b)
951{
952 float128_u ua;
953 ua.val = a;
[a35b458]954
[c0c38c7c]955 float128_u ub;
956 ub.val = b;
[a35b458]957
[c0c38c7c]958 if ((is_float128_nan(ua.data)) || (is_float128_nan(ub.data))) {
959 // TODO: sigNaNs
960 return -1;
961 }
[a35b458]962
[c0c38c7c]963 if (is_float128_gt(ua.data, ub.data))
964 return 1;
[a35b458]965
[c0c38c7c]966 return 0;
967}
968
969int __getf2(float128_t a, float128_t b)
970{
971 float128_u ua;
972 ua.val = a;
[a35b458]973
[c0c38c7c]974 float128_u ub;
975 ub.val = b;
[a35b458]976
[c0c38c7c]977 if ((is_float128_nan(ua.data)) || (is_float128_nan(ub.data))) {
978 // TODO: sigNaNs
979 return -1;
980 }
[a35b458]981
[c0c38c7c]982 if (is_float128_eq(ua.data, ub.data))
983 return 0;
[a35b458]984
[c0c38c7c]985 if (is_float128_gt(ua.data, ub.data))
986 return 1;
[a35b458]987
[c0c38c7c]988 return -1;
989}
990
991int __lttf2(float128_t a, float128_t b)
992{
993 float128_u ua;
994 ua.val = a;
[a35b458]995
[c0c38c7c]996 float128_u ub;
997 ub.val = b;
[a35b458]998
[c0c38c7c]999 if ((is_float128_nan(ua.data)) || (is_float128_nan(ub.data))) {
1000 // TODO: sigNaNs
1001 return 1;
1002 }
[a35b458]1003
[c0c38c7c]1004 if (is_float128_lt(ua.data, ub.data))
1005 return -1;
[a35b458]1006
[c0c38c7c]1007 return 0;
1008}
1009
1010int __letf2(float128_t a, float128_t b)
1011{
1012 float128_u ua;
1013 ua.val = a;
[a35b458]1014
[c0c38c7c]1015 float128_u ub;
1016 ub.val = b;
[a35b458]1017
[c0c38c7c]1018 if ((is_float128_nan(ua.data)) || (is_float128_nan(ub.data))) {
1019 // TODO: sigNaNs
1020 return 1;
1021 }
[a35b458]1022
[c0c38c7c]1023 if (is_float128_eq(ua.data, ub.data))
1024 return 0;
[a35b458]1025
[c0c38c7c]1026 if (is_float128_lt(ua.data, ub.data))
1027 return -1;
[a35b458]1028
[c0c38c7c]1029 return 1;
1030}
1031
1032int __eqtf2(float128_t a, float128_t b)
1033{
1034 float128_u ua;
1035 ua.val = a;
[a35b458]1036
[c0c38c7c]1037 float128_u ub;
1038 ub.val = b;
[a35b458]1039
[c0c38c7c]1040 if ((is_float128_nan(ua.data)) || (is_float128_nan(ub.data))) {
1041 // TODO: sigNaNs
1042 return 1;
1043 }
[a35b458]1044
[c0c38c7c]1045 return is_float128_eq(ua.data, ub.data) - 1;
1046}
1047
1048int __netf2(float128_t a, float128_t b)
1049{
1050 /* Strange, but according to GCC documentation */
1051 return __eqtf2(a, b);
1052}
1053
1054int __cmptf2(float128_t a, float128_t b)
1055{
1056 float128_u ua;
1057 ua.val = a;
[a35b458]1058
[c0c38c7c]1059 float128_u ub;
1060 ub.val = b;
[a35b458]1061
[c0c38c7c]1062 if ((is_float128_nan(ua.data)) || (is_float128_nan(ub.data))) {
1063 /* No special constant for unordered - maybe signaled? */
1064 return 1;
1065 }
[a35b458]1066
[c0c38c7c]1067 if (is_float128_eq(ua.data, ub.data))
1068 return 0;
[a35b458]1069
[c0c38c7c]1070 if (is_float128_lt(ua.data, ub.data))
1071 return -1;
[a35b458]1072
[c0c38c7c]1073 return 1;
1074}
1075
1076int __unordtf2(float128_t a, float128_t b)
1077{
1078 float128_u ua;
1079 ua.val = a;
[a35b458]1080
[c0c38c7c]1081 float128_u ub;
1082 ub.val = b;
[a35b458]1083
[c0c38c7c]1084 return ((is_float128_nan(ua.data)) || (is_float128_nan(ub.data)));
1085}
1086
1087int _Qp_cmp(float128_t *a, float128_t *b)
1088{
1089 float128_u ua;
1090 ua.val = *a;
[a35b458]1091
[c0c38c7c]1092 float128_u ub;
1093 ub.val = *b;
[a35b458]1094
[c0c38c7c]1095 if ((is_float128_nan(ua.data)) || (is_float128_nan(ub.data)))
1096 return 3;
[a35b458]1097
[c0c38c7c]1098 if (is_float128_eq(ua.data, ub.data))
1099 return 0;
[a35b458]1100
[c0c38c7c]1101 if (is_float128_lt(ua.data, ub.data))
1102 return 1;
[a35b458]1103
[c0c38c7c]1104 return 2;
1105}
1106
1107int _Qp_cmpe(float128_t *a, float128_t *b)
1108{
1109 /* Strange, but according to SPARC Compliance Definition */
1110 return _Qp_cmp(a, b);
1111}
1112
1113int _Qp_fgt(float128_t *a, float128_t *b)
1114{
1115 float128_u ua;
1116 ua.val = *a;
[a35b458]1117
[c0c38c7c]1118 float128_u ub;
1119 ub.val = *b;
[a35b458]1120
[c0c38c7c]1121 if ((is_float128_nan(ua.data)) || (is_float128_nan(ub.data)))
1122 return 0;
[a35b458]1123
[c0c38c7c]1124 return is_float128_gt(ua.data, ub.data);
1125}
1126
1127int _Qp_fge(float128_t *a, float128_t *b)
1128{
1129 float128_u ua;
1130 ua.val = *a;
[a35b458]1131
[c0c38c7c]1132 float128_u ub;
1133 ub.val = *b;
[a35b458]1134
[c0c38c7c]1135 if ((is_float128_nan(ua.data)) || (is_float128_nan(ub.data)))
1136 return 0;
[a35b458]1137
[c0c38c7c]1138 return is_float128_eq(ua.data, ub.data) ||
1139 is_float128_gt(ua.data, ub.data);
1140}
1141
1142int _Qp_flt(float128_t *a, float128_t *b)
1143{
1144 float128_u ua;
1145 ua.val = *a;
[a35b458]1146
[c0c38c7c]1147 float128_u ub;
1148 ub.val = *b;
[a35b458]1149
[c0c38c7c]1150 if ((is_float128_nan(ua.data)) || (is_float128_nan(ub.data)))
1151 return 0;
[a35b458]1152
[c0c38c7c]1153 return is_float128_lt(ua.data, ub.data);
1154}
1155
1156int _Qp_fle(float128_t *a, float128_t *b)
1157{
1158 float128_u ua;
1159 ua.val = *a;
[a35b458]1160
[c0c38c7c]1161 float128_u ub;
1162 ub.val = *b;
[a35b458]1163
[c0c38c7c]1164 if ((is_float128_nan(ua.data)) || (is_float128_nan(ub.data)))
1165 return 0;
[a35b458]1166
[c0c38c7c]1167 return is_float128_eq(ua.data, ub.data) ||
1168 is_float128_lt(ua.data, ub.data);
1169}
1170
1171int _Qp_feq(float128_t *a, float128_t *b)
1172{
1173 float128_u ua;
1174 ua.val = *a;
[a35b458]1175
[c0c38c7c]1176 float128_u ub;
1177 ub.val = *b;
[a35b458]1178
[c0c38c7c]1179 if ((is_float128_nan(ua.data)) || (is_float128_nan(ub.data)))
1180 return 0;
[a35b458]1181
[c0c38c7c]1182 return is_float128_eq(ua.data, ub.data);
1183}
1184
1185int _Qp_fne(float128_t *a, float128_t *b)
1186{
1187 float128_u ua;
1188 ua.val = *a;
[a35b458]1189
[c0c38c7c]1190 float128_u ub;
1191 ub.val = *b;
[a35b458]1192
[c0c38c7c]1193 if ((is_float128_nan(ua.data)) || (is_float128_nan(ub.data)))
1194 return 0;
[a35b458]1195
[c0c38c7c]1196 return !is_float128_eq(ua.data, ub.data);
1197}
1198
1199#endif
1200
[231a60a]1201/** @}
[846848a6]1202 */
Note: See TracBrowser for help on using the repository browser.