/* * Copyright (C) 2005 Josef Cejka * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include /* Arithmetic functions */ float __addsf3(float a, float b) { float32 fa, fb; fa.f = a; fb.f = b; if (fa.parts.sign != fb.parts.sign) { if (fa.parts.sign) { fa.parts.sign = 0; return subFloat32(fb, fa).f; }; fb.parts.sign = 0; return subFloat32(fa, fb).f; } return addFloat32(fa, fb).f; } double __adddf3(double a, double b) { float64 da, db; da.d = a; db.d = b; if (da.parts.sign != db.parts.sign) { if (da.parts.sign) { da.parts.sign = 0; return subFloat64(db, da).d; }; db.parts.sign = 0; return subFloat64(da, db).d; } return addFloat64(da, db).d; } float __subsf3(float a, float b) { float32 fa, fb; fa.f = a; fb.f = b; if (fa.parts.sign != fb.parts.sign) { fb.parts.sign = !fb.parts.sign; return addFloat32(fa, fb).f; } return subFloat32(fa, fb).f; } double __subdf3(double a, double b) { float64 da, db; da.d = a; db.d = b; if (da.parts.sign != db.parts.sign) { db.parts.sign = !db.parts.sign; return addFloat64(da, db).d; } return subFloat64(da, db).d; } float __mulsf3(float a, float b) { float32 fa, fb; fa.f = a; fb.f = b; return mulFloat32(fa, fb).f; } double __muldf3(double a, double b) { float64 da, db; da.d = a; db.d = b; return mulFloat64(da, db).d; } float __divsf3(float a, float b) { float32 fa, fb; fa.f = a; fb.f = b; return divFloat32(fa, fb).f; } float __negsf2(float a) { float32 fa; fa.f = a; fa.parts.sign = !fa.parts.sign; return fa.f; } double __negdf2(double a) { float64 fa; fa.d = a; fa.parts.sign = !fa.parts.sign; return fa.d; } /* Conversion functions */ double __extendsfdf2(float a) { float32 fa; fa.f = a; return convertFloat32ToFloat64(fa).d; } float __truncdfsf2(double a) { float64 da; da.d = a; return convertFloat64ToFloat32(da).f; } /* Comparison functions */ /* ab .. 1 * */ int __cmpsf2(float a, float b) { float32 fa, fb; fa.f = a; fb.f = b; if ( (isFloat32NaN(fa)) || (isFloat32NaN(fb)) ) { return 1; /* no special constant for unordered - maybe signaled? */ }; if (isFloat32eq(fa, fb)) { return 0; }; if (isFloat32lt(fa, fb)) { return -1; }; return 1; } int __unordsf2(float a, float b) { float32 fa, fb; fa.f = a; fb.f = b; return ( (isFloat32NaN(fa)) || (isFloat32NaN(fb)) ); } /** * @return zero, if neither argument is a NaN and are equal * */ int __eqsf2(float a, float b) { float32 fa, fb; fa.f = a; fb.f = b; if ( (isFloat32NaN(fa)) || (isFloat32NaN(fb)) ) { /* TODO: sigNaNs*/ return 1; }; return isFloat32eq(fa, fb) - 1; } /* strange behavior, but it was in gcc documentation */ int __nesf2(float a, float b) { return __eqsf2(a, b); } /* return value >= 0 if a>=b and neither is NaN */ int __gesf2(float a, float b) { float32 fa, fb; fa.f = a; fb.f = b; if ( (isFloat32NaN(fa)) || (isFloat32NaN(fb)) ) { /* TODO: sigNaNs*/ return -1; }; if (isFloat32eq(fa, fb)) { return 0; }; if (isFloat32gt(fa, fb)) { return 1; }; return -1; } /** Return negative value, if ab and neither is NaN*/ int __gtsf2(float a, float b) { float32 fa, fb; fa.f = a; fb.f = b; if ( (isFloat32NaN(fa)) || (isFloat32NaN(fb)) ) { /* TODO: sigNaNs*/ return -1; }; if (isFloat32gt(fa, fb)) { return 1; }; return 0; } /* Other functions */ float __powisf2(float a, int b) { /* TODO: */ } float __mulsc3(float a, float b, float c, float d) { /* TODO: */ } float __divsc3(float a, float b, float c, float d) { /* TODO: */ }