1276789Sdim//===-- lib/comparesf2.c - Single-precision comparisons -----------*- C -*-===// 2276789Sdim// 3276789Sdim// The LLVM Compiler Infrastructure 4276789Sdim// 5276789Sdim// This file is dual licensed under the MIT and the University of Illinois Open 6276789Sdim// Source Licenses. See LICENSE.TXT for details. 7276789Sdim// 8276789Sdim//===----------------------------------------------------------------------===// 9276789Sdim// 10276789Sdim// This file implements the following soft-fp_t comparison routines: 11276789Sdim// 12276789Sdim// __eqsf2 __gesf2 __unordsf2 13276789Sdim// __lesf2 __gtsf2 14276789Sdim// __ltsf2 15276789Sdim// __nesf2 16276789Sdim// 17276789Sdim// The semantics of the routines grouped in each column are identical, so there 18276789Sdim// is a single implementation for each, and wrappers to provide the other names. 19276789Sdim// 20276789Sdim// The main routines behave as follows: 21276789Sdim// 22276789Sdim// __lesf2(a,b) returns -1 if a < b 23276789Sdim// 0 if a == b 24276789Sdim// 1 if a > b 25276789Sdim// 1 if either a or b is NaN 26276789Sdim// 27276789Sdim// __gesf2(a,b) returns -1 if a < b 28276789Sdim// 0 if a == b 29276789Sdim// 1 if a > b 30276789Sdim// -1 if either a or b is NaN 31276789Sdim// 32276789Sdim// __unordsf2(a,b) returns 0 if both a and b are numbers 33276789Sdim// 1 if either a or b is NaN 34276789Sdim// 35276789Sdim// Note that __lesf2( ) and __gesf2( ) are identical except in their handling of 36276789Sdim// NaN values. 37276789Sdim// 38276789Sdim//===----------------------------------------------------------------------===// 39276789Sdim 40276789Sdim#define SINGLE_PRECISION 41276789Sdim#include "fp_lib.h" 42276789Sdim 43276789Sdimenum LE_RESULT { 44276789Sdim LE_LESS = -1, 45276789Sdim LE_EQUAL = 0, 46276789Sdim LE_GREATER = 1, 47276789Sdim LE_UNORDERED = 1 48276789Sdim}; 49276789Sdim 50276789SdimCOMPILER_RT_ABI enum LE_RESULT 51276789Sdim__lesf2(fp_t a, fp_t b) { 52276789Sdim 53276789Sdim const srep_t aInt = toRep(a); 54276789Sdim const srep_t bInt = toRep(b); 55276789Sdim const rep_t aAbs = aInt & absMask; 56276789Sdim const rep_t bAbs = bInt & absMask; 57276789Sdim 58276789Sdim // If either a or b is NaN, they are unordered. 59276789Sdim if (aAbs > infRep || bAbs > infRep) return LE_UNORDERED; 60276789Sdim 61276789Sdim // If a and b are both zeros, they are equal. 62276789Sdim if ((aAbs | bAbs) == 0) return LE_EQUAL; 63276789Sdim 64276789Sdim // If at least one of a and b is positive, we get the same result comparing 65276789Sdim // a and b as signed integers as we would with a fp_ting-point compare. 66276789Sdim if ((aInt & bInt) >= 0) { 67276789Sdim if (aInt < bInt) return LE_LESS; 68276789Sdim else if (aInt == bInt) return LE_EQUAL; 69276789Sdim else return LE_GREATER; 70276789Sdim } 71276789Sdim 72276789Sdim // Otherwise, both are negative, so we need to flip the sense of the 73276789Sdim // comparison to get the correct result. (This assumes a twos- or ones- 74276789Sdim // complement integer representation; if integers are represented in a 75276789Sdim // sign-magnitude representation, then this flip is incorrect). 76276789Sdim else { 77276789Sdim if (aInt > bInt) return LE_LESS; 78276789Sdim else if (aInt == bInt) return LE_EQUAL; 79276789Sdim else return LE_GREATER; 80276789Sdim } 81276789Sdim} 82276789Sdim 83296417Sdim#if defined(__ELF__) 84296417Sdim// Alias for libgcc compatibility 85296417SdimFNALIAS(__cmpsf2, __lesf2); 86296417Sdim#endif 87296417Sdim 88276789Sdimenum GE_RESULT { 89276789Sdim GE_LESS = -1, 90276789Sdim GE_EQUAL = 0, 91276789Sdim GE_GREATER = 1, 92276789Sdim GE_UNORDERED = -1 // Note: different from LE_UNORDERED 93276789Sdim}; 94276789Sdim 95276789SdimCOMPILER_RT_ABI enum GE_RESULT 96276789Sdim__gesf2(fp_t a, fp_t b) { 97276789Sdim 98276789Sdim const srep_t aInt = toRep(a); 99276789Sdim const srep_t bInt = toRep(b); 100276789Sdim const rep_t aAbs = aInt & absMask; 101276789Sdim const rep_t bAbs = bInt & absMask; 102276789Sdim 103276789Sdim if (aAbs > infRep || bAbs > infRep) return GE_UNORDERED; 104276789Sdim if ((aAbs | bAbs) == 0) return GE_EQUAL; 105276789Sdim if ((aInt & bInt) >= 0) { 106276789Sdim if (aInt < bInt) return GE_LESS; 107276789Sdim else if (aInt == bInt) return GE_EQUAL; 108276789Sdim else return GE_GREATER; 109276789Sdim } else { 110276789Sdim if (aInt > bInt) return GE_LESS; 111276789Sdim else if (aInt == bInt) return GE_EQUAL; 112276789Sdim else return GE_GREATER; 113276789Sdim } 114276789Sdim} 115276789Sdim 116276789SdimARM_EABI_FNALIAS(fcmpun, unordsf2) 117276789Sdim 118276789SdimCOMPILER_RT_ABI int 119276789Sdim__unordsf2(fp_t a, fp_t b) { 120276789Sdim const rep_t aAbs = toRep(a) & absMask; 121276789Sdim const rep_t bAbs = toRep(b) & absMask; 122276789Sdim return aAbs > infRep || bAbs > infRep; 123276789Sdim} 124276789Sdim 125276789Sdim// The following are alternative names for the preceding routines. 126276789Sdim 127276789SdimCOMPILER_RT_ABI enum LE_RESULT 128276789Sdim__eqsf2(fp_t a, fp_t b) { 129276789Sdim return __lesf2(a, b); 130276789Sdim} 131276789Sdim 132276789SdimCOMPILER_RT_ABI enum LE_RESULT 133276789Sdim__ltsf2(fp_t a, fp_t b) { 134276789Sdim return __lesf2(a, b); 135276789Sdim} 136276789Sdim 137276789SdimCOMPILER_RT_ABI enum LE_RESULT 138276789Sdim__nesf2(fp_t a, fp_t b) { 139276789Sdim return __lesf2(a, b); 140276789Sdim} 141276789Sdim 142276789SdimCOMPILER_RT_ABI enum GE_RESULT 143276789Sdim__gtsf2(fp_t a, fp_t b) { 144276789Sdim return __gesf2(a, b); 145276789Sdim} 146