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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c67aff2 was c67aff2, checked in by Petr Koupy <petr.koupy@…>, 14 years ago

Quadruple-precision softfloat, coding style improvements. Details below…

Highlights:

  • completed double-precision support
  • added quadruple-precision support
  • added SPARC quadruple-precision wrappers
  • added doxygen comments
  • corrected and unified coding style

Current state of the softfloat library:

Support for single, double and quadruple precision is currently almost complete (apart from power, square root, complex multiplication and complex division) and provides the same set of features (i.e. the support for all three precisions is now aligned). In order to extend softfloat library consistently, addition of quadruple precision was done in the same spirit as already existing single and double precision written by Josef Cejka in 2006 - that is relaxed standard-compliance for corner cases while mission-critical code sections heavily inspired by the widely used softfloat library written by John R. Hauser (although I personally think it would be more appropriate for HelenOS to use something less optimized, shorter and more readable).

Most of the quadruple-precision code is just an adapted double-precision code to work on 128-bit variables. That means if there is TODO, FIXME or some defect in single or double-precision code, it is most likely also in the quadruple-precision code. Please note that quadruple-precision functions are currently not tested - it is challenging task for itself, especially when the ports that use them are either not finished (mips64) or badly supported by simulators (sparc64). To test whole softfloat library, one would probably have to either write very non-trivial native tester, or use some existing one (e.g. TestFloat from J. R. Hauser) and port it to HelenOS (or rip the softfloat library out of HelenOS and test it on a host system). At the time of writing this, the code dependent on quadruple-precision functions (on mips64 and sparc64) is just a libposix strtold() function (and its callers, most notably scanf backend).

  • Property mode set to 100644
File size: 12.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
[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 */
[750636a]47int isFloat32NaN(float32 f)
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 */
[750636a]60int isFloat64NaN(float64 d)
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 */
73int isFloat128NaN(float128 ld)
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 */
[750636a]86int isFloat32SigNaN(float32 f)
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 */
[750636a]100int isFloat64SigNaN(float64 d)
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 */
114int isFloat128SigNaN(float128 ld)
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 */
[750636a]130int isFloat32Infinity(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 */
[750636a]142int isFloat64Infinity(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 */
154int isFloat128Infinity(float128 ld)
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 */
[750636a]167int isFloat32Zero(float32 f)
[3af72dc]168{
169 return (((f.binary) & 0x7FFFFFFF) == 0);
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 */
[750636a]178int isFloat64Zero(float64 d)
[feef1cd]179{
180 return (((d.binary) & 0x7FFFFFFFFFFFFFFFll) == 0);
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 */
189int isFloat128Zero(float128 ld)
190{
191 uint64_t tmp_hi;
192 uint64_t tmp_lo;
193
194 and128(ld.binary.hi, ld.binary.lo,
195 0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
196
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 */
[750636a]207int isFloat32eq(float32 a, float32 b)
[7e557805]208{
[750636a]209 /* a equals to b or both are zeros (with any sign) */
[c67aff2]210 return ((a.binary == b.binary) ||
211 (((a.binary | b.binary) & 0x7FFFFFFF) == 0));
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 */
221int isFloat64eq(float64 a, float64 b)
222{
223 /* a equals to b or both are zeros (with any sign) */
224 return ((a.binary == b.binary) ||
225 (((a.binary | b.binary) & 0x7FFFFFFFFFFFFFFFll) == 0));
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 */
235int isFloat128eq(float128 a, float128 b)
236{
237 uint64_t tmp_hi;
238 uint64_t tmp_lo;
239
240 /* both are zeros (with any sign) */
241 or128(a.binary.hi, a.binary.lo,
242 b.binary.hi, b.binary.lo, &tmp_hi, &tmp_lo);
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 */
248 int are_equal = eq128(a.binary.hi, a.binary.lo, b.binary.hi, b.binary.lo);
249
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 */
[750636a]260int isFloat32lt(float32 a, float32 b)
[7e557805]261{
[c67aff2]262 if (((a.binary | b.binary) & 0x7FFFFFFF) == 0) {
[cf4a823]263 return 0; /* +- zeroes */
[c67aff2]264 }
[cf4a823]265
[c67aff2]266 if ((a.parts.sign) && (b.parts.sign)) {
[750636a]267 /* if both are negative, smaller is that with greater binary value */
268 return (a.binary > b.binary);
[c67aff2]269 }
[cf4a823]270
[c67aff2]271 /* lets negate signs - now will be positive numbers allways bigger than
272 * negative (first bit will be set for unsigned integer comparison) */
[750636a]273 a.parts.sign = !a.parts.sign;
274 b.parts.sign = !b.parts.sign;
275 return (a.binary < b.binary);
[7e557805]276}
277
[e649dfa]278/**
[c67aff2]279 * Lower-than comparison between two floats. NaNs are not recognized.
280 *
281 * @a First double-precision operand.
282 * @b Second double-precision operand.
283 * @return 1 if a is lower than b, 0 otherwise.
284 */
285int isFloat64lt(float64 a, float64 b)
286{
287 if (((a.binary | b.binary) & 0x7FFFFFFFFFFFFFFFll) == 0) {
288 return 0; /* +- zeroes */
289 }
290
291 if ((a.parts.sign) && (b.parts.sign)) {
292 /* if both are negative, smaller is that with greater binary value */
293 return (a.binary > b.binary);
294 }
295
296 /* lets negate signs - now will be positive numbers allways bigger than
297 * negative (first bit will be set for unsigned integer comparison) */
298 a.parts.sign = !a.parts.sign;
299 b.parts.sign = !b.parts.sign;
300 return (a.binary < b.binary);
301}
302
303/**
304 * Lower-than comparison between two floats. NaNs are not recognized.
305 *
306 * @a First quadruple-precision operand.
307 * @b Second quadruple-precision operand.
308 * @return 1 if a is lower than b, 0 otherwise.
309 */
310int isFloat128lt(float128 a, float128 b)
311{
312 uint64_t tmp_hi;
313 uint64_t tmp_lo;
314
315 or128(a.binary.hi, a.binary.lo,
316 b.binary.hi, b.binary.lo, &tmp_hi, &tmp_lo);
317 and128(tmp_hi, tmp_lo,
318 0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
319 if (eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll)) {
320 return 0; /* +- zeroes */
321 }
322
323 if ((a.parts.sign) && (b.parts.sign)) {
324 /* if both are negative, smaller is that with greater binary value */
325 return lt128(b.binary.hi, b.binary.lo, a.binary.hi, a.binary.lo);
326 }
327
328 /* lets negate signs - now will be positive numbers allways bigger than
329 * negative (first bit will be set for unsigned integer comparison) */
330 a.parts.sign = !a.parts.sign;
331 b.parts.sign = !b.parts.sign;
332 return lt128(a.binary.hi, a.binary.lo, b.binary.hi, b.binary.lo);
333}
334
335/**
336 * Greater-than comparison between two floats. NaNs are not recognized.
337 *
338 * @a First single-precision operand.
339 * @b Second single-precision operand.
340 * @return 1 if a is greater than b, 0 otherwise.
[e649dfa]341 */
[750636a]342int isFloat32gt(float32 a, float32 b)
[e649dfa]343{
[c67aff2]344 if (((a.binary | b.binary) & 0x7FFFFFFF) == 0) {
[cf4a823]345 return 0; /* zeroes are equal with any sign */
[c67aff2]346 }
[cf4a823]347
[c67aff2]348 if ((a.parts.sign) && (b.parts.sign)) {
[750636a]349 /* if both are negative, greater is that with smaller binary value */
350 return (a.binary < b.binary);
[c67aff2]351 }
[cf4a823]352
[c67aff2]353 /* lets negate signs - now will be positive numbers allways bigger than
354 * negative (first bit will be set for unsigned integer comparison) */
[750636a]355 a.parts.sign = !a.parts.sign;
356 b.parts.sign = !b.parts.sign;
357 return (a.binary > b.binary);
[e649dfa]358}
359
[c67aff2]360/**
361 * Greater-than comparison between two floats. NaNs are not recognized.
362 *
363 * @a First double-precision operand.
364 * @b Second double-precision operand.
365 * @return 1 if a is greater than b, 0 otherwise.
366 */
367int isFloat64gt(float64 a, float64 b)
368{
369 if (((a.binary | b.binary) & 0x7FFFFFFFFFFFFFFFll) == 0) {
370 return 0; /* zeroes are equal with any sign */
371 }
372
373 if ((a.parts.sign) && (b.parts.sign)) {
374 /* if both are negative, greater is that with smaller binary value */
375 return (a.binary < b.binary);
376 }
377
378 /* lets negate signs - now will be positive numbers allways bigger than
379 * negative (first bit will be set for unsigned integer comparison) */
380 a.parts.sign = !a.parts.sign;
381 b.parts.sign = !b.parts.sign;
382 return (a.binary > b.binary);
383}
384
385/**
386 * Greater-than comparison between two floats. NaNs are not recognized.
387 *
388 * @a First quadruple-precision operand.
389 * @b Second quadruple-precision operand.
390 * @return 1 if a is greater than b, 0 otherwise.
391 */
392int isFloat128gt(float128 a, float128 b)
393{
394 uint64_t tmp_hi;
395 uint64_t tmp_lo;
396
397 or128(a.binary.hi, a.binary.lo,
398 b.binary.hi, b.binary.lo, &tmp_hi, &tmp_lo);
399 and128(tmp_hi, tmp_lo,
400 0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
401 if (eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll)) {
402 return 0; /* zeroes are equal with any sign */
403 }
404
405 if ((a.parts.sign) && (b.parts.sign)) {
406 /* if both are negative, greater is that with smaller binary value */
407 return lt128(a.binary.hi, a.binary.lo, b.binary.hi, b.binary.lo);
408 }
409
410 /* lets negate signs - now will be positive numbers allways bigger than
411 * negative (first bit will be set for unsigned integer comparison) */
412 a.parts.sign = !a.parts.sign;
413 b.parts.sign = !b.parts.sign;
414 return lt128(b.binary.hi, b.binary.lo, a.binary.hi, a.binary.lo);
415}
416
[231a60a]417/** @}
[846848a6]418 */
Note: See TracBrowser for help on using the repository browser.