Path: blob/main/contrib/arm-optimized-routines/math/test/rtest/semi.c
48375 views
/*1* semi.c: test implementations of mathlib seminumerical functions2*3* Copyright (c) 1999-2019, Arm Limited.4* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception5*/67#include <stdio.h>8#include "semi.h"910static void test_rint(uint32 *in, uint32 *out,11int isfloor, int isceil) {12int sign = in[0] & 0x80000000;13int roundup = (isfloor && sign) || (isceil && !sign);14uint32 xh, xl, roundword;15int ex = (in[0] >> 20) & 0x7FF; /* exponent */16int i;1718if ((ex > 0x3ff + 52 - 1) || /* things this big can't be fractional */19((in[0] & 0x7FFFFFFF) == 0 && in[1] == 0)) { /* zero */20/* NaN, Inf, a large integer, or zero: just return the input */21out[0] = in[0];22out[1] = in[1];23return;24}2526/*27* Special case: ex < 0x3ff, ie our number is in (0,1). Return28* 1 or 0 according to roundup.29*/30if (ex < 0x3ff) {31out[0] = sign | (roundup ? 0x3FF00000 : 0);32out[1] = 0;33return;34}3536/*37* We're not short of time here, so we'll do this the hideously38* inefficient way. Shift bit by bit so that the units place is39* somewhere predictable, round, and shift back again.40*/41xh = in[0];42xl = in[1];43roundword = 0;44for (i = ex; i < 0x3ff + 52; i++) {45if (roundword & 1)46roundword |= 2; /* preserve sticky bit */47roundword = (roundword >> 1) | ((xl & 1) << 31);48xl = (xl >> 1) | ((xh & 1) << 31);49xh = xh >> 1;50}51if (roundword && roundup) {52xl++;53xh += (xl==0);54}55for (i = ex; i < 0x3ff + 52; i++) {56xh = (xh << 1) | ((xl >> 31) & 1);57xl = (xl & 0x7FFFFFFF) << 1;58}59out[0] = xh;60out[1] = xl;61}6263char *test_ceil(uint32 *in, uint32 *out) {64test_rint(in, out, 0, 1);65return NULL;66}6768char *test_floor(uint32 *in, uint32 *out) {69test_rint(in, out, 1, 0);70return NULL;71}7273static void test_rintf(uint32 *in, uint32 *out,74int isfloor, int isceil) {75int sign = *in & 0x80000000;76int roundup = (isfloor && sign) || (isceil && !sign);77uint32 x, roundword;78int ex = (*in >> 23) & 0xFF; /* exponent */79int i;8081if ((ex > 0x7f + 23 - 1) || /* things this big can't be fractional */82(*in & 0x7FFFFFFF) == 0) { /* zero */83/* NaN, Inf, a large integer, or zero: just return the input */84*out = *in;85return;86}8788/*89* Special case: ex < 0x7f, ie our number is in (0,1). Return90* 1 or 0 according to roundup.91*/92if (ex < 0x7f) {93*out = sign | (roundup ? 0x3F800000 : 0);94return;95}9697/*98* We're not short of time here, so we'll do this the hideously99* inefficient way. Shift bit by bit so that the units place is100* somewhere predictable, round, and shift back again.101*/102x = *in;103roundword = 0;104for (i = ex; i < 0x7F + 23; i++) {105if (roundword & 1)106roundword |= 2; /* preserve sticky bit */107roundword = (roundword >> 1) | ((x & 1) << 31);108x = x >> 1;109}110if (roundword && roundup) {111x++;112}113for (i = ex; i < 0x7F + 23; i++) {114x = x << 1;115}116*out = x;117}118119char *test_ceilf(uint32 *in, uint32 *out) {120test_rintf(in, out, 0, 1);121return NULL;122}123124char *test_floorf(uint32 *in, uint32 *out) {125test_rintf(in, out, 1, 0);126return NULL;127}128129char *test_fmod(uint32 *a, uint32 *b, uint32 *out) {130int sign;131int32 aex, bex;132uint32 am[2], bm[2];133134if (((a[0] & 0x7FFFFFFF) << 1) + !!a[1] > 0xFFE00000 ||135((b[0] & 0x7FFFFFFF) << 1) + !!b[1] > 0xFFE00000) {136/* a or b is NaN: return QNaN, optionally with IVO */137uint32 an, bn;138out[0] = 0x7ff80000;139out[1] = 1;140an = ((a[0] & 0x7FFFFFFF) << 1) + !!a[1];141bn = ((b[0] & 0x7FFFFFFF) << 1) + !!b[1];142if ((an > 0xFFE00000 && an < 0xFFF00000) ||143(bn > 0xFFE00000 && bn < 0xFFF00000))144return "i"; /* at least one SNaN: IVO */145else146return NULL; /* no SNaNs, but at least 1 QNaN */147}148if ((b[0] & 0x7FFFFFFF) == 0 && b[1] == 0) { /* b==0: EDOM */149out[0] = 0x7ff80000;150out[1] = 1;151return "EDOM status=i";152}153if ((a[0] & 0x7FF00000) == 0x7FF00000) { /* a==Inf: EDOM */154out[0] = 0x7ff80000;155out[1] = 1;156return "EDOM status=i";157}158if ((b[0] & 0x7FF00000) == 0x7FF00000) { /* b==Inf: return a */159out[0] = a[0];160out[1] = a[1];161return NULL;162}163if ((a[0] & 0x7FFFFFFF) == 0 && a[1] == 0) { /* a==0: return a */164out[0] = a[0];165out[1] = a[1];166return NULL;167}168169/*170* OK. That's the special cases cleared out of the way. Now we171* have finite (though not necessarily normal) a and b.172*/173sign = a[0] & 0x80000000; /* we discard sign of b */174test_frexp(a, am, (uint32 *)&aex);175test_frexp(b, bm, (uint32 *)&bex);176am[0] &= 0xFFFFF, am[0] |= 0x100000;177bm[0] &= 0xFFFFF, bm[0] |= 0x100000;178179while (aex >= bex) {180if (am[0] > bm[0] || (am[0] == bm[0] && am[1] >= bm[1])) {181am[1] -= bm[1];182am[0] = am[0] - bm[0] - (am[1] > ~bm[1]);183}184if (aex > bex) {185am[0] = (am[0] << 1) | ((am[1] & 0x80000000) >> 31);186am[1] <<= 1;187aex--;188} else189break;190}191192/*193* Renormalise final result; this can be cunningly done by194* passing a denormal to ldexp.195*/196aex += 0x3fd;197am[0] |= sign;198test_ldexp(am, (uint32 *)&aex, out);199200return NULL; /* FIXME */201}202203char *test_fmodf(uint32 *a, uint32 *b, uint32 *out) {204int sign;205int32 aex, bex;206uint32 am, bm;207208if ((*a & 0x7FFFFFFF) > 0x7F800000 ||209(*b & 0x7FFFFFFF) > 0x7F800000) {210/* a or b is NaN: return QNaN, optionally with IVO */211uint32 an, bn;212*out = 0x7fc00001;213an = *a & 0x7FFFFFFF;214bn = *b & 0x7FFFFFFF;215if ((an > 0x7f800000 && an < 0x7fc00000) ||216(bn > 0x7f800000 && bn < 0x7fc00000))217return "i"; /* at least one SNaN: IVO */218else219return NULL; /* no SNaNs, but at least 1 QNaN */220}221if ((*b & 0x7FFFFFFF) == 0) { /* b==0: EDOM */222*out = 0x7fc00001;223return "EDOM status=i";224}225if ((*a & 0x7F800000) == 0x7F800000) { /* a==Inf: EDOM */226*out = 0x7fc00001;227return "EDOM status=i";228}229if ((*b & 0x7F800000) == 0x7F800000) { /* b==Inf: return a */230*out = *a;231return NULL;232}233if ((*a & 0x7FFFFFFF) == 0) { /* a==0: return a */234*out = *a;235return NULL;236}237238/*239* OK. That's the special cases cleared out of the way. Now we240* have finite (though not necessarily normal) a and b.241*/242sign = a[0] & 0x80000000; /* we discard sign of b */243test_frexpf(a, &am, (uint32 *)&aex);244test_frexpf(b, &bm, (uint32 *)&bex);245am &= 0x7FFFFF, am |= 0x800000;246bm &= 0x7FFFFF, bm |= 0x800000;247248while (aex >= bex) {249if (am >= bm) {250am -= bm;251}252if (aex > bex) {253am <<= 1;254aex--;255} else256break;257}258259/*260* Renormalise final result; this can be cunningly done by261* passing a denormal to ldexp.262*/263aex += 0x7d;264am |= sign;265test_ldexpf(&am, (uint32 *)&aex, out);266267return NULL; /* FIXME */268}269270char *test_ldexp(uint32 *x, uint32 *np, uint32 *out) {271int n = *np;272int32 n2;273uint32 y[2];274int ex = (x[0] >> 20) & 0x7FF; /* exponent */275int sign = x[0] & 0x80000000;276277if (ex == 0x7FF) { /* inf/NaN; just return x */278out[0] = x[0];279out[1] = x[1];280return NULL;281}282if ((x[0] & 0x7FFFFFFF) == 0 && x[1] == 0) { /* zero: return x */283out[0] = x[0];284out[1] = x[1];285return NULL;286}287288test_frexp(x, y, (uint32 *)&n2);289ex = n + n2;290if (ex > 0x400) { /* overflow */291out[0] = sign | 0x7FF00000;292out[1] = 0;293return "overflow";294}295/*296* Underflow. 2^-1074 is 00000000.00000001; so if ex == -1074297* then we have something [2^-1075,2^-1074). Under round-to-298* nearest-even, this whole interval rounds up to 2^-1074,299* except for the bottom endpoint which rounds to even and is300* an underflow condition.301*302* So, ex < -1074 is definite underflow, and ex == -1074 is303* underflow iff all mantissa bits are zero.304*/305if (ex < -1074 || (ex == -1074 && (y[0] & 0xFFFFF) == 0 && y[1] == 0)) {306out[0] = sign; /* underflow: correctly signed zero */307out[1] = 0;308return "underflow";309}310311/*312* No overflow or underflow; should be nice and simple, unless313* we have to denormalise and round the result.314*/315if (ex < -1021) { /* denormalise and round */316uint32 roundword;317y[0] &= 0x000FFFFF;318y[0] |= 0x00100000; /* set leading bit */319roundword = 0;320while (ex < -1021) {321if (roundword & 1)322roundword |= 2; /* preserve sticky bit */323roundword = (roundword >> 1) | ((y[1] & 1) << 31);324y[1] = (y[1] >> 1) | ((y[0] & 1) << 31);325y[0] = y[0] >> 1;326ex++;327}328if (roundword > 0x80000000 || /* round up */329(roundword == 0x80000000 && (y[1] & 1))) { /* round up to even */330y[1]++;331y[0] += (y[1] == 0);332}333out[0] = sign | y[0];334out[1] = y[1];335/* Proper ERANGE underflow was handled earlier, but we still336* expect an IEEE Underflow exception if this partially337* underflowed result is not exact. */338if (roundword)339return "u";340return NULL; /* underflow was handled earlier */341} else {342out[0] = y[0] + (ex << 20);343out[1] = y[1];344return NULL;345}346}347348char *test_ldexpf(uint32 *x, uint32 *np, uint32 *out) {349int n = *np;350int32 n2;351uint32 y;352int ex = (*x >> 23) & 0xFF; /* exponent */353int sign = *x & 0x80000000;354355if (ex == 0xFF) { /* inf/NaN; just return x */356*out = *x;357return NULL;358}359if ((*x & 0x7FFFFFFF) == 0) { /* zero: return x */360*out = *x;361return NULL;362}363364test_frexpf(x, &y, (uint32 *)&n2);365ex = n + n2;366if (ex > 0x80) { /* overflow */367*out = sign | 0x7F800000;368return "overflow";369}370/*371* Underflow. 2^-149 is 00000001; so if ex == -149 then we have372* something [2^-150,2^-149). Under round-to- nearest-even,373* this whole interval rounds up to 2^-149, except for the374* bottom endpoint which rounds to even and is an underflow375* condition.376*377* So, ex < -149 is definite underflow, and ex == -149 is378* underflow iff all mantissa bits are zero.379*/380if (ex < -149 || (ex == -149 && (y & 0x7FFFFF) == 0)) {381*out = sign; /* underflow: correctly signed zero */382return "underflow";383}384385/*386* No overflow or underflow; should be nice and simple, unless387* we have to denormalise and round the result.388*/389if (ex < -125) { /* denormalise and round */390uint32 roundword;391y &= 0x007FFFFF;392y |= 0x00800000; /* set leading bit */393roundword = 0;394while (ex < -125) {395if (roundword & 1)396roundword |= 2; /* preserve sticky bit */397roundword = (roundword >> 1) | ((y & 1) << 31);398y = y >> 1;399ex++;400}401if (roundword > 0x80000000 || /* round up */402(roundword == 0x80000000 && (y & 1))) { /* round up to even */403y++;404}405*out = sign | y;406/* Proper ERANGE underflow was handled earlier, but we still407* expect an IEEE Underflow exception if this partially408* underflowed result is not exact. */409if (roundword)410return "u";411return NULL; /* underflow was handled earlier */412} else {413*out = y + (ex << 23);414return NULL;415}416}417418char *test_frexp(uint32 *x, uint32 *out, uint32 *nout) {419int ex = (x[0] >> 20) & 0x7FF; /* exponent */420if (ex == 0x7FF) { /* inf/NaN; return x/0 */421out[0] = x[0];422out[1] = x[1];423nout[0] = 0;424return NULL;425}426if (ex == 0) { /* denormals/zeros */427int sign;428uint32 xh, xl;429if ((x[0] & 0x7FFFFFFF) == 0 && x[1] == 0) {430/* zero: return x/0 */431out[0] = x[0];432out[1] = x[1];433nout[0] = 0;434return NULL;435}436sign = x[0] & 0x80000000;437xh = x[0] & 0x7FFFFFFF;438xl = x[1];439ex = 1;440while (!(xh & 0x100000)) {441ex--;442xh = (xh << 1) | ((xl >> 31) & 1);443xl = (xl & 0x7FFFFFFF) << 1;444}445out[0] = sign | 0x3FE00000 | (xh & 0xFFFFF);446out[1] = xl;447nout[0] = ex - 0x3FE;448return NULL;449}450out[0] = 0x3FE00000 | (x[0] & 0x800FFFFF);451out[1] = x[1];452nout[0] = ex - 0x3FE;453return NULL; /* ordinary number; no error */454}455456char *test_frexpf(uint32 *x, uint32 *out, uint32 *nout) {457int ex = (*x >> 23) & 0xFF; /* exponent */458if (ex == 0xFF) { /* inf/NaN; return x/0 */459*out = *x;460nout[0] = 0;461return NULL;462}463if (ex == 0) { /* denormals/zeros */464int sign;465uint32 xv;466if ((*x & 0x7FFFFFFF) == 0) {467/* zero: return x/0 */468*out = *x;469nout[0] = 0;470return NULL;471}472sign = *x & 0x80000000;473xv = *x & 0x7FFFFFFF;474ex = 1;475while (!(xv & 0x800000)) {476ex--;477xv = xv << 1;478}479*out = sign | 0x3F000000 | (xv & 0x7FFFFF);480nout[0] = ex - 0x7E;481return NULL;482}483*out = 0x3F000000 | (*x & 0x807FFFFF);484nout[0] = ex - 0x7E;485return NULL; /* ordinary number; no error */486}487488char *test_modf(uint32 *x, uint32 *fout, uint32 *iout) {489int ex = (x[0] >> 20) & 0x7FF; /* exponent */490int sign = x[0] & 0x80000000;491uint32 fh, fl;492493if (((x[0] & 0x7FFFFFFF) | (!!x[1])) > 0x7FF00000) {494/*495* NaN input: return the same in _both_ outputs.496*/497fout[0] = iout[0] = x[0];498fout[1] = iout[1] = x[1];499return NULL;500}501502test_rint(x, iout, 0, 0);503fh = x[0] - iout[0];504fl = x[1] - iout[1];505if (!fh && !fl) { /* no fraction part */506fout[0] = sign;507fout[1] = 0;508return NULL;509}510if (!(iout[0] & 0x7FFFFFFF) && !iout[1]) { /* no integer part */511fout[0] = x[0];512fout[1] = x[1];513return NULL;514}515while (!(fh & 0x100000)) {516ex--;517fh = (fh << 1) | ((fl >> 31) & 1);518fl = (fl & 0x7FFFFFFF) << 1;519}520fout[0] = sign | (ex << 20) | (fh & 0xFFFFF);521fout[1] = fl;522return NULL;523}524525char *test_modff(uint32 *x, uint32 *fout, uint32 *iout) {526int ex = (*x >> 23) & 0xFF; /* exponent */527int sign = *x & 0x80000000;528uint32 f;529530if ((*x & 0x7FFFFFFF) > 0x7F800000) {531/*532* NaN input: return the same in _both_ outputs.533*/534*fout = *iout = *x;535return NULL;536}537538test_rintf(x, iout, 0, 0);539f = *x - *iout;540if (!f) { /* no fraction part */541*fout = sign;542return NULL;543}544if (!(*iout & 0x7FFFFFFF)) { /* no integer part */545*fout = *x;546return NULL;547}548while (!(f & 0x800000)) {549ex--;550f = f << 1;551}552*fout = sign | (ex << 23) | (f & 0x7FFFFF);553return NULL;554}555556char *test_copysign(uint32 *x, uint32 *y, uint32 *out)557{558int ysign = y[0] & 0x80000000;559int xhigh = x[0] & 0x7fffffff;560561out[0] = ysign | xhigh;562out[1] = x[1];563564/* There can be no error */565return NULL;566}567568char *test_copysignf(uint32 *x, uint32 *y, uint32 *out)569{570int ysign = y[0] & 0x80000000;571int xhigh = x[0] & 0x7fffffff;572573out[0] = ysign | xhigh;574575/* There can be no error */576return NULL;577}578579char *test_isfinite(uint32 *x, uint32 *out)580{581int xhigh = x[0];582/* Being finite means that the exponent is not 0x7ff */583if ((xhigh & 0x7ff00000) == 0x7ff00000) out[0] = 0;584else out[0] = 1;585return NULL;586}587588char *test_isfinitef(uint32 *x, uint32 *out)589{590/* Being finite means that the exponent is not 0xff */591if ((x[0] & 0x7f800000) == 0x7f800000) out[0] = 0;592else out[0] = 1;593return NULL;594}595596char *test_isinff(uint32 *x, uint32 *out)597{598/* Being infinite means that our bottom 30 bits equate to 0x7f800000 */599if ((x[0] & 0x7fffffff) == 0x7f800000) out[0] = 1;600else out[0] = 0;601return NULL;602}603604char *test_isinf(uint32 *x, uint32 *out)605{606int xhigh = x[0];607int xlow = x[1];608/* Being infinite means that our fraction is zero and exponent is 0x7ff */609if (((xhigh & 0x7fffffff) == 0x7ff00000) && (xlow == 0)) out[0] = 1;610else out[0] = 0;611return NULL;612}613614char *test_isnanf(uint32 *x, uint32 *out)615{616/* Being NaN means that our exponent is 0xff and non-0 fraction */617int exponent = x[0] & 0x7f800000;618int fraction = x[0] & 0x007fffff;619if ((exponent == 0x7f800000) && (fraction != 0)) out[0] = 1;620else out[0] = 0;621return NULL;622}623624char *test_isnan(uint32 *x, uint32 *out)625{626/* Being NaN means that our exponent is 0x7ff and non-0 fraction */627int exponent = x[0] & 0x7ff00000;628int fractionhigh = x[0] & 0x000fffff;629if ((exponent == 0x7ff00000) && ((fractionhigh != 0) || x[1] != 0))630out[0] = 1;631else out[0] = 0;632return NULL;633}634635char *test_isnormalf(uint32 *x, uint32 *out)636{637/* Being normal means exponent is not 0 and is not 0xff */638int exponent = x[0] & 0x7f800000;639if (exponent == 0x7f800000) out[0] = 0;640else if (exponent == 0) out[0] = 0;641else out[0] = 1;642return NULL;643}644645char *test_isnormal(uint32 *x, uint32 *out)646{647/* Being normal means exponent is not 0 and is not 0x7ff */648int exponent = x[0] & 0x7ff00000;649if (exponent == 0x7ff00000) out[0] = 0;650else if (exponent == 0) out[0] = 0;651else out[0] = 1;652return NULL;653}654655char *test_signbitf(uint32 *x, uint32 *out)656{657/* Sign bit is bit 31 */658out[0] = (x[0] >> 31) & 1;659return NULL;660}661662char *test_signbit(uint32 *x, uint32 *out)663{664/* Sign bit is bit 31 */665out[0] = (x[0] >> 31) & 1;666return NULL;667}668669char *test_fpclassify(uint32 *x, uint32 *out)670{671int exponent = (x[0] & 0x7ff00000) >> 20;672int fraction = (x[0] & 0x000fffff) | x[1];673674if ((exponent == 0x00) && (fraction == 0)) out[0] = 0;675else if ((exponent == 0x00) && (fraction != 0)) out[0] = 4;676else if ((exponent == 0x7ff) && (fraction == 0)) out[0] = 3;677else if ((exponent == 0x7ff) && (fraction != 0)) out[0] = 7;678else out[0] = 5;679return NULL;680}681682char *test_fpclassifyf(uint32 *x, uint32 *out)683{684int exponent = (x[0] & 0x7f800000) >> 23;685int fraction = x[0] & 0x007fffff;686687if ((exponent == 0x000) && (fraction == 0)) out[0] = 0;688else if ((exponent == 0x000) && (fraction != 0)) out[0] = 4;689else if ((exponent == 0xff) && (fraction == 0)) out[0] = 3;690else if ((exponent == 0xff) && (fraction != 0)) out[0] = 7;691else out[0] = 5;692return NULL;693}694695/*696* Internal function that compares doubles in x & y and returns -3, -2, -1, 0,697* 1 if they compare to be signaling, unordered, less than, equal or greater698* than.699*/700static int fpcmp4(uint32 *x, uint32 *y)701{702int result = 0;703704/*705* Sort out whether results are ordered or not to begin with706* NaNs have exponent 0x7ff, and non-zero fraction. Signaling NaNs take707* higher priority than quiet ones.708*/709if ((x[0] & 0x7fffffff) >= 0x7ff80000) result = -2;710else if ((x[0] & 0x7fffffff) > 0x7ff00000) result = -3;711else if (((x[0] & 0x7fffffff) == 0x7ff00000) && (x[1] != 0)) result = -3;712if ((y[0] & 0x7fffffff) >= 0x7ff80000 && result != -3) result = -2;713else if ((y[0] & 0x7fffffff) > 0x7ff00000) result = -3;714else if (((y[0] & 0x7fffffff) == 0x7ff00000) && (y[1] != 0)) result = -3;715if (result != 0) return result;716717/*718* The two forms of zero are equal719*/720if (((x[0] & 0x7fffffff) == 0) && x[1] == 0 &&721((y[0] & 0x7fffffff) == 0) && y[1] == 0)722return 0;723724/*725* If x and y have different signs we can tell that they're not equal726* If x is +ve we have x > y return 1 - otherwise y is +ve return -1727*/728if ((x[0] >> 31) != (y[0] >> 31))729return ((x[0] >> 31) == 0) - ((y[0] >> 31) == 0);730731/*732* Now we have both signs the same, let's do an initial compare of the733* values.734*735* Whoever designed IEEE754's floating point formats is very clever and736* earns my undying admiration. Once you remove the sign-bit, the737* floating point numbers can be ordered using the standard <, ==, >738* operators will treating the fp-numbers as integers with that bit-739* pattern.740*/741if ((x[0] & 0x7fffffff) < (y[0] & 0x7fffffff)) result = -1;742else if ((x[0] & 0x7fffffff) > (y[0] & 0x7fffffff)) result = 1;743else if (x[1] < y[1]) result = -1;744else if (x[1] > y[1]) result = 1;745else result = 0;746747/*748* Now we return the result - is x is positive (and therefore so is y) we749* return the plain result - otherwise we negate it and return.750*/751if ((x[0] >> 31) == 0) return result;752else return -result;753}754755/*756* Internal function that compares floats in x & y and returns -3, -2, -1, 0,757* 1 if they compare to be signaling, unordered, less than, equal or greater758* than.759*/760static int fpcmp4f(uint32 *x, uint32 *y)761{762int result = 0;763764/*765* Sort out whether results are ordered or not to begin with766* NaNs have exponent 0xff, and non-zero fraction - we have to handle all767* signaling cases over the quiet ones768*/769if ((x[0] & 0x7fffffff) >= 0x7fc00000) result = -2;770else if ((x[0] & 0x7fffffff) > 0x7f800000) result = -3;771if ((y[0] & 0x7fffffff) >= 0x7fc00000 && result != -3) result = -2;772else if ((y[0] & 0x7fffffff) > 0x7f800000) result = -3;773if (result != 0) return result;774775/*776* The two forms of zero are equal777*/778if (((x[0] & 0x7fffffff) == 0) && ((y[0] & 0x7fffffff) == 0))779return 0;780781/*782* If x and y have different signs we can tell that they're not equal783* If x is +ve we have x > y return 1 - otherwise y is +ve return -1784*/785if ((x[0] >> 31) != (y[0] >> 31))786return ((x[0] >> 31) == 0) - ((y[0] >> 31) == 0);787788/*789* Now we have both signs the same, let's do an initial compare of the790* values.791*792* Whoever designed IEEE754's floating point formats is very clever and793* earns my undying admiration. Once you remove the sign-bit, the794* floating point numbers can be ordered using the standard <, ==, >795* operators will treating the fp-numbers as integers with that bit-796* pattern.797*/798if ((x[0] & 0x7fffffff) < (y[0] & 0x7fffffff)) result = -1;799else if ((x[0] & 0x7fffffff) > (y[0] & 0x7fffffff)) result = 1;800else result = 0;801802/*803* Now we return the result - is x is positive (and therefore so is y) we804* return the plain result - otherwise we negate it and return.805*/806if ((x[0] >> 31) == 0) return result;807else return -result;808}809810char *test_isgreater(uint32 *x, uint32 *y, uint32 *out)811{812int result = fpcmp4(x, y);813*out = (result == 1);814return result == -3 ? "i" : NULL;815}816817char *test_isgreaterequal(uint32 *x, uint32 *y, uint32 *out)818{819int result = fpcmp4(x, y);820*out = (result >= 0);821return result == -3 ? "i" : NULL;822}823824char *test_isless(uint32 *x, uint32 *y, uint32 *out)825{826int result = fpcmp4(x, y);827*out = (result == -1);828return result == -3 ? "i" : NULL;829}830831char *test_islessequal(uint32 *x, uint32 *y, uint32 *out)832{833int result = fpcmp4(x, y);834*out = (result == -1) || (result == 0);835return result == -3 ? "i" : NULL;836}837838char *test_islessgreater(uint32 *x, uint32 *y, uint32 *out)839{840int result = fpcmp4(x, y);841*out = (result == -1) || (result == 1);842return result == -3 ? "i" : NULL;843}844845char *test_isunordered(uint32 *x, uint32 *y, uint32 *out)846{847int normal = 0;848int result = fpcmp4(x, y);849850test_isnormal(x, out);851normal |= *out;852test_isnormal(y, out);853normal |= *out;854*out = (result == -2) || (result == -3);855return result == -3 ? "i" : NULL;856}857858char *test_isgreaterf(uint32 *x, uint32 *y, uint32 *out)859{860int result = fpcmp4f(x, y);861*out = (result == 1);862return result == -3 ? "i" : NULL;863}864865char *test_isgreaterequalf(uint32 *x, uint32 *y, uint32 *out)866{867int result = fpcmp4f(x, y);868*out = (result >= 0);869return result == -3 ? "i" : NULL;870}871872char *test_islessf(uint32 *x, uint32 *y, uint32 *out)873{874int result = fpcmp4f(x, y);875*out = (result == -1);876return result == -3 ? "i" : NULL;877}878879char *test_islessequalf(uint32 *x, uint32 *y, uint32 *out)880{881int result = fpcmp4f(x, y);882*out = (result == -1) || (result == 0);883return result == -3 ? "i" : NULL;884}885886char *test_islessgreaterf(uint32 *x, uint32 *y, uint32 *out)887{888int result = fpcmp4f(x, y);889*out = (result == -1) || (result == 1);890return result == -3 ? "i" : NULL;891}892893char *test_isunorderedf(uint32 *x, uint32 *y, uint32 *out)894{895int normal = 0;896int result = fpcmp4f(x, y);897898test_isnormalf(x, out);899normal |= *out;900test_isnormalf(y, out);901normal |= *out;902*out = (result == -2) || (result == -3);903return result == -3 ? "i" : NULL;904}905906907