source: mainline/uspace/lib/softfloat/generic/comparison.c@ 88d5c1e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 88d5c1e was 88d5c1e, checked in by Martin Decky <martin@…>, 13 years ago

softfloat redesign

  • avoid hardwired type sizes, actual sizes are determined at compile-time
  • add basic support for x87 extended-precision data types (stored as 96bit long double)
  • a lot of coding style changes (removal of CamelCase, etc.)
  • Property mode set to 100644
File size: 11.9 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
[750636a]36#include <sftypes.h>
37#include <comparison.h>
[c67aff2]38#include <common.h>
[b5440cf]39
[c67aff2]40/**
41 * Determines whether the given float represents NaN (either signalling NaN or
42 * quiet NaN).
43 *
44 * @param f Single-precision float.
45 * @return 1 if float is NaN, 0 otherwise.
46 */
[88d5c1e]47int is_float32_nan(float32 f)
[750636a]48{
[c67aff2]49 /* NaN : exp = 0xff and nonzero fraction */
[750636a]50 return ((f.parts.exp == 0xFF) && (f.parts.fraction));
[e591928]51}
[b5440cf]52
[c67aff2]53/**
54 * Determines whether the given float represents NaN (either signalling NaN or
55 * quiet NaN).
56 *
57 * @param d Double-precision float.
58 * @return 1 if float is NaN, 0 otherwise.
59 */
[88d5c1e]60int is_float64_nan(float64 d)
[750636a]61{
[c67aff2]62 /* NaN : exp = 0x7ff and nonzero fraction */
[750636a]63 return ((d.parts.exp == 0x7FF) && (d.parts.fraction));
[e591928]64}
[feef1cd]65
[c67aff2]66/**
67 * Determines whether the given float represents NaN (either signalling NaN or
68 * quiet NaN).
69 *
70 * @param ld Quadruple-precision float.
71 * @return 1 if float is NaN, 0 otherwise.
72 */
[88d5c1e]73int is_float128_nan(float128 ld)
[c67aff2]74{
75 /* NaN : exp = 0x7fff and nonzero fraction */
76 return ((ld.parts.exp == 0x7FF) &&
77 !eq128(ld.parts.frac_hi, ld.parts.frac_lo, 0x0ll, 0x0ll));
78}
79
80/**
81 * Determines whether the given float represents signalling NaN.
82 *
83 * @param f Single-precision float.
84 * @return 1 if float is signalling NaN, 0 otherwise.
85 */
[88d5c1e]86int is_float32_signan(float32 f)
[750636a]87{
[c67aff2]88 /* SigNaN : exp = 0xff and fraction = 0xxxxx..x (binary),
89 * where at least one x is nonzero */
90 return ((f.parts.exp == 0xFF) &&
91 (f.parts.fraction < 0x400000) && (f.parts.fraction));
[e591928]92}
[b5440cf]93
[c67aff2]94/**
95 * Determines whether the given float represents signalling NaN.
96 *
97 * @param d Double-precision float.
98 * @return 1 if float is signalling NaN, 0 otherwise.
99 */
[88d5c1e]100int is_float64_signan(float64 d)
[750636a]101{
[c67aff2]102 /* SigNaN : exp = 0x7ff and fraction = 0xxxxx..x (binary),
103 * where at least one x is nonzero */
104 return ((d.parts.exp == 0x7FF) &&
105 (d.parts.fraction) && (d.parts.fraction < 0x8000000000000ll));
[e591928]106}
[feef1cd]107
[c67aff2]108/**
109 * Determines whether the given float represents signalling NaN.
110 *
111 * @param ld Quadruple-precision float.
112 * @return 1 if float is signalling NaN, 0 otherwise.
113 */
[88d5c1e]114int is_float128_signan(float128 ld)
[c67aff2]115{
116 /* SigNaN : exp = 0x7fff and fraction = 0xxxxx..x (binary),
117 * where at least one x is nonzero */
118 return ((ld.parts.exp == 0x7FFF) &&
119 (ld.parts.frac_hi || ld.parts.frac_lo) &&
120 lt128(ld.parts.frac_hi, ld.parts.frac_lo, 0x800000000000ll, 0x0ll));
121
122}
123
124/**
125 * Determines whether the given float represents positive or negative infinity.
126 *
127 * @param f Single-precision float.
128 * @return 1 if float is infinite, 0 otherwise.
129 */
[88d5c1e]130int is_float32_infinity(float32 f)
[7e557805]131{
[c67aff2]132 /* NaN : exp = 0x7ff and zero fraction */
[750636a]133 return ((f.parts.exp == 0xFF) && (f.parts.fraction == 0x0));
[e591928]134}
[7e557805]135
[c67aff2]136/**
137 * Determines whether the given float represents positive or negative infinity.
138 *
139 * @param d Double-precision float.
140 * @return 1 if float is infinite, 0 otherwise.
141 */
[88d5c1e]142int is_float64_infinity(float64 d)
[feef1cd]143{
[c67aff2]144 /* NaN : exp = 0x7ff and zero fraction */
[750636a]145 return ((d.parts.exp == 0x7FF) && (d.parts.fraction == 0x0));
[e591928]146}
[feef1cd]147
[c67aff2]148/**
149 * Determines whether the given float represents positive or negative infinity.
150 *
151 * @param ld Quadruple-precision float.
152 * @return 1 if float is infinite, 0 otherwise.
153 */
[88d5c1e]154int is_float128_infinity(float128 ld)
[c67aff2]155{
156 /* NaN : exp = 0x7fff and zero fraction */
157 return ((ld.parts.exp == 0x7FFF) &&
158 eq128(ld.parts.frac_hi, ld.parts.frac_lo, 0x0ll, 0x0ll));
159}
160
161/**
162 * Determines whether the given float represents positive or negative zero.
163 *
164 * @param f Single-precision float.
165 * @return 1 if float is zero, 0 otherwise.
166 */
[88d5c1e]167int is_float32_zero(float32 f)
[3af72dc]168{
[88d5c1e]169 return (((f.bin) & 0x7FFFFFFF) == 0);
[3af72dc]170}
171
[c67aff2]172/**
173 * Determines whether the given float represents positive or negative zero.
174 *
175 * @param d Double-precision float.
176 * @return 1 if float is zero, 0 otherwise.
177 */
[88d5c1e]178int is_float64_zero(float64 d)
[feef1cd]179{
[88d5c1e]180 return (((d.bin) & 0x7FFFFFFFFFFFFFFFll) == 0);
[feef1cd]181}
182
[7e557805]183/**
[c67aff2]184 * Determines whether the given float represents positive or negative zero.
185 *
186 * @param ld Quadruple-precision float.
187 * @return 1 if float is zero, 0 otherwise.
188 */
[88d5c1e]189int is_float128_zero(float128 ld)
[c67aff2]190{
191 uint64_t tmp_hi;
192 uint64_t tmp_lo;
[88d5c1e]193
194 and128(ld.bin.hi, ld.bin.lo,
[c67aff2]195 0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
[88d5c1e]196
[c67aff2]197 return eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll);
198}
199
200/**
201 * Determine whether two floats are equal. NaNs are not recognized.
202 *
203 * @a First single-precision operand.
204 * @b Second single-precision operand.
205 * @return 1 if both floats are equal, 0 otherwise.
[7e557805]206 */
[88d5c1e]207int is_float32_eq(float32 a, float32 b)
[7e557805]208{
[750636a]209 /* a equals to b or both are zeros (with any sign) */
[88d5c1e]210 return ((a.bin == b.bin) ||
211 (((a.bin | b.bin) & 0x7FFFFFFF) == 0));
[c67aff2]212}
213
214/**
215 * Determine whether two floats are equal. NaNs are not recognized.
216 *
217 * @a First double-precision operand.
218 * @b Second double-precision operand.
219 * @return 1 if both floats are equal, 0 otherwise.
220 */
[88d5c1e]221int is_float64_eq(float64 a, float64 b)
[c67aff2]222{
223 /* a equals to b or both are zeros (with any sign) */
[88d5c1e]224 return ((a.bin == b.bin) ||
225 (((a.bin | b.bin) & 0x7FFFFFFFFFFFFFFFll) == 0));
[c67aff2]226}
227
228/**
229 * Determine whether two floats are equal. NaNs are not recognized.
230 *
231 * @a First quadruple-precision operand.
232 * @b Second quadruple-precision operand.
233 * @return 1 if both floats are equal, 0 otherwise.
234 */
[88d5c1e]235int is_float128_eq(float128 a, float128 b)
[c67aff2]236{
237 uint64_t tmp_hi;
238 uint64_t tmp_lo;
[88d5c1e]239
[c67aff2]240 /* both are zeros (with any sign) */
[88d5c1e]241 or128(a.bin.hi, a.bin.lo,
242 b.bin.hi, b.bin.lo, &tmp_hi, &tmp_lo);
[c67aff2]243 and128(tmp_hi, tmp_lo,
244 0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
245 int both_zero = eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll);
246
247 /* a equals to b */
[88d5c1e]248 int are_equal = eq128(a.bin.hi, a.bin.lo, b.bin.hi, b.bin.lo);
249
[c67aff2]250 return are_equal || both_zero;
[7e557805]251}
252
253/**
[c67aff2]254 * Lower-than comparison between two floats. NaNs are not recognized.
255 *
256 * @a First single-precision operand.
257 * @b Second single-precision operand.
258 * @return 1 if a is lower than b, 0 otherwise.
[7e557805]259 */
[88d5c1e]260int is_float32_lt(float32 a, float32 b)
[7e557805]261{
[88d5c1e]262 if (((a.bin | b.bin) & 0x7FFFFFFF) == 0) {
263 /* +- zeroes */
264 return 0;
[c67aff2]265 }
[cf4a823]266
[c67aff2]267 if ((a.parts.sign) && (b.parts.sign)) {
[750636a]268 /* if both are negative, smaller is that with greater binary value */
[88d5c1e]269 return (a.bin > b.bin);
[c67aff2]270 }
[cf4a823]271
[88d5c1e]272 /*
273 * lets negate signs - now will be positive numbers always
274 * bigger than negative (first bit will be set for unsigned
275 * integer comparison)
276 */
[750636a]277 a.parts.sign = !a.parts.sign;
278 b.parts.sign = !b.parts.sign;
[88d5c1e]279 return (a.bin < b.bin);
[7e557805]280}
281
[e649dfa]282/**
[c67aff2]283 * Lower-than comparison between two floats. NaNs are not recognized.
284 *
285 * @a First double-precision operand.
286 * @b Second double-precision operand.
287 * @return 1 if a is lower than b, 0 otherwise.
288 */
[88d5c1e]289int is_float64_lt(float64 a, float64 b)
[c67aff2]290{
[88d5c1e]291 if (((a.bin | b.bin) & 0x7FFFFFFFFFFFFFFFll) == 0) {
292 /* +- zeroes */
293 return 0;
[c67aff2]294 }
[88d5c1e]295
[c67aff2]296 if ((a.parts.sign) && (b.parts.sign)) {
297 /* if both are negative, smaller is that with greater binary value */
[88d5c1e]298 return (a.bin > b.bin);
[c67aff2]299 }
[88d5c1e]300
301 /*
302 * lets negate signs - now will be positive numbers always
303 * bigger than negative (first bit will be set for unsigned
304 * integer comparison)
305 */
[c67aff2]306 a.parts.sign = !a.parts.sign;
307 b.parts.sign = !b.parts.sign;
[88d5c1e]308 return (a.bin < b.bin);
[c67aff2]309}
310
311/**
312 * Lower-than comparison between two floats. NaNs are not recognized.
313 *
314 * @a First quadruple-precision operand.
315 * @b Second quadruple-precision operand.
316 * @return 1 if a is lower than b, 0 otherwise.
317 */
[88d5c1e]318int is_float128_lt(float128 a, float128 b)
[c67aff2]319{
320 uint64_t tmp_hi;
321 uint64_t tmp_lo;
[88d5c1e]322
323 or128(a.bin.hi, a.bin.lo,
324 b.bin.hi, b.bin.lo, &tmp_hi, &tmp_lo);
[c67aff2]325 and128(tmp_hi, tmp_lo,
326 0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
327 if (eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll)) {
[88d5c1e]328 /* +- zeroes */
329 return 0;
[c67aff2]330 }
[88d5c1e]331
[c67aff2]332 if ((a.parts.sign) && (b.parts.sign)) {
333 /* if both are negative, smaller is that with greater binary value */
[88d5c1e]334 return lt128(b.bin.hi, b.bin.lo, a.bin.hi, a.bin.lo);
[c67aff2]335 }
[88d5c1e]336
337 /*
338 * lets negate signs - now will be positive numbers always
339 * bigger than negative (first bit will be set for unsigned
340 * integer comparison)
341 */
[c67aff2]342 a.parts.sign = !a.parts.sign;
343 b.parts.sign = !b.parts.sign;
[88d5c1e]344 return lt128(a.bin.hi, a.bin.lo, b.bin.hi, b.bin.lo);
[c67aff2]345}
346
347/**
348 * Greater-than comparison between two floats. NaNs are not recognized.
349 *
350 * @a First single-precision operand.
351 * @b Second single-precision operand.
352 * @return 1 if a is greater than b, 0 otherwise.
[e649dfa]353 */
[88d5c1e]354int is_float32_gt(float32 a, float32 b)
[e649dfa]355{
[88d5c1e]356 if (((a.bin | b.bin) & 0x7FFFFFFF) == 0) {
357 /* zeroes are equal with any sign */
358 return 0;
[c67aff2]359 }
[cf4a823]360
[c67aff2]361 if ((a.parts.sign) && (b.parts.sign)) {
[750636a]362 /* if both are negative, greater is that with smaller binary value */
[88d5c1e]363 return (a.bin < b.bin);
[c67aff2]364 }
[cf4a823]365
[88d5c1e]366 /*
367 * lets negate signs - now will be positive numbers always
368 * bigger than negative (first bit will be set for unsigned
369 * integer comparison)
370 */
[750636a]371 a.parts.sign = !a.parts.sign;
372 b.parts.sign = !b.parts.sign;
[88d5c1e]373 return (a.bin > b.bin);
[e649dfa]374}
375
[c67aff2]376/**
377 * Greater-than comparison between two floats. NaNs are not recognized.
378 *
379 * @a First double-precision operand.
380 * @b Second double-precision operand.
381 * @return 1 if a is greater than b, 0 otherwise.
382 */
[88d5c1e]383int is_float64_gt(float64 a, float64 b)
[c67aff2]384{
[88d5c1e]385 if (((a.bin | b.bin) & 0x7FFFFFFFFFFFFFFFll) == 0) {
386 /* zeroes are equal with any sign */
387 return 0;
[c67aff2]388 }
[88d5c1e]389
[c67aff2]390 if ((a.parts.sign) && (b.parts.sign)) {
391 /* if both are negative, greater is that with smaller binary value */
[88d5c1e]392 return (a.bin < b.bin);
[c67aff2]393 }
[88d5c1e]394
395 /*
396 * lets negate signs - now will be positive numbers always
397 * bigger than negative (first bit will be set for unsigned
398 * integer comparison)
399 */
[c67aff2]400 a.parts.sign = !a.parts.sign;
401 b.parts.sign = !b.parts.sign;
[88d5c1e]402 return (a.bin > b.bin);
[c67aff2]403}
404
405/**
406 * Greater-than comparison between two floats. NaNs are not recognized.
407 *
408 * @a First quadruple-precision operand.
409 * @b Second quadruple-precision operand.
410 * @return 1 if a is greater than b, 0 otherwise.
411 */
[88d5c1e]412int is_float128_gt(float128 a, float128 b)
[c67aff2]413{
414 uint64_t tmp_hi;
415 uint64_t tmp_lo;
[88d5c1e]416
417 or128(a.bin.hi, a.bin.lo,
418 b.bin.hi, b.bin.lo, &tmp_hi, &tmp_lo);
[c67aff2]419 and128(tmp_hi, tmp_lo,
420 0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
421 if (eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll)) {
[88d5c1e]422 /* zeroes are equal with any sign */
423 return 0;
[c67aff2]424 }
[88d5c1e]425
[c67aff2]426 if ((a.parts.sign) && (b.parts.sign)) {
427 /* if both are negative, greater is that with smaller binary value */
[88d5c1e]428 return lt128(a.bin.hi, a.bin.lo, b.bin.hi, b.bin.lo);
[c67aff2]429 }
[88d5c1e]430
431 /*
432 * lets negate signs - now will be positive numbers always
433 * bigger than negative (first bit will be set for unsigned
434 * integer comparison)
435 */
[c67aff2]436 a.parts.sign = !a.parts.sign;
437 b.parts.sign = !b.parts.sign;
[88d5c1e]438 return lt128(b.bin.hi, b.bin.lo, a.bin.hi, a.bin.lo);
[c67aff2]439}
440
[231a60a]441/** @}
[846848a6]442 */
Note: See TracBrowser for help on using the repository browser.