this repo has no description
at fixPythonPipStalling 145 lines 3.1 kB view raw
1/* 2 * remainderf.c 3 * cLibm 4 * 5 * Written by Jon Okada, started on December 7th, 1992. 6 * Modified by Paul Finlayson (PAF) for MathLib v2. 7 * Modified by A. Sazegari (ali) for MathLib v3. 8 * Modified and ported by Robert A. Murley (ram) for Mac OS X. 9 * Modified for cLibm, fixed a few edge cases, rewrote local_ funcs by Ian Ollmann. 10 * 11 * Copyright 2007 Apple Inc. All rights reserved. 12 * 13 */ 14 15#include <math.h> 16#include <float.h> 17#include <stdint.h> 18 19#ifdef ARMLIBM_SET_FLAGS 20#include "required_arithmetic.h" 21#endif 22 23static inline int local_ilogbf( float x ) __attribute__ ((always_inline)); 24static inline int local_ilogbf( float x ) 25{ 26 union{ float f; uint32_t u;}u = {x}; 27 28 u.u &= 0x7fffffff; 29 int32_t exp = u.u >> 23; 30 31 if( __builtin_expect( (uint32_t) exp - 1U >= 254, 0 ) ) 32 { // +-denorm, other possibilities: +-0, +-inf, NaN are screened out by caller 33 34 u.u |= 0x3f800000U; 35 u.f -= 1.0f; 36 exp = u.u >> 23; 37 38 return exp - (127+126); 39 } 40 41 return exp - 127; 42} 43 44static inline float local_scalbnf( float x, int n ) __attribute__ ((always_inline)); 45static inline float local_scalbnf( float x, int n ) 46{ 47 //create 2**n in double 48 union{ uint64_t u; double d;} u = { ( (int64_t) n + 1023) << 52 }; 49 double d = x; 50 51 //scale by appropriate power of 2 52 d *= u.d; 53 54 //return result 55 return (float) d; 56} 57 58 59 60float remainderf( float x, float y ) 61{ 62 63 // deal with NaN 64 if( x != x || y != y ) 65 return x + y; 66 67 //x = Inf or y = 0, return Invalid per IEEE-754 68 float fabsx = __builtin_fabsf(x); 69 if( fabsx == __builtin_inff() || 0.0f == y ) 70 { 71#ifdef ARMLIBM_SET_FLAGS 72 return required_add_float( __builtin_inff(), -__builtin_inff() ); //set invalid 73#else 74 return __builtin_nanf(""); 75#endif 76 } 77 78 //handle trivial case 79 float fabsy = __builtin_fabsf(y); 80 if( fabsy == __builtin_inff() || 0.0f == x ) 81 { 82#ifdef ARMLIBM_SET_FLAGS 83 required_add_float( fabsx, 0.0f ); //signal underflow (that is, no flag set, but exception occurs if unmasked) if x is denorm 84#endif 85 return x; 86 } 87 88 //we have to work 89 int32_t iquo = 0; 90 int32_t iscx = local_ilogbf(fabsx); 91 int32_t iscy = local_ilogbf(fabsy); 92 int32_t idiff = iscx - iscy; 93 float x1, y1, z; 94 x1 = fabsx; 95 y1 = fabsy; 96 union{ float d[2]; uint32_t u[2];} u = { { x, y } }; 97 int32_t sign = u.u[0] ^ u.u[1]; 98 sign = sign >> 31; 99 100 if( idiff >= 0 ) 101 { 102 int32_t i; 103 104 if( idiff ) 105 { 106 y1 = local_scalbnf( y1, -iscy ); 107 x1 = local_scalbnf( x1, -iscx ); 108 for( i = idiff; i != 0; i-- ) 109 { 110 if( x1 >= y1 ) 111 { 112 x1 -= y1; 113 iquo += 1; 114 } 115 iquo += iquo; 116 x1 += x1; 117 } 118 x1 = local_scalbnf( x1, iscy ); 119 } 120 if( x1 >= fabsy ) 121 { 122 x1 -= fabsy; 123 iquo += 1; 124 } 125 } 126 127 if( x1 < 0x1.0p127f ) 128 { 129 z = x1 + x1; 130 if( (z > fabsy) || ((z == fabsy) && ((iquo & 1) != 0 ))) 131 x1 -= fabsy; 132 } 133 else 134 { // x1 is only this large if y is even bigger, so we can safely divide y by 2 135 float halfy = 0.5f * fabsy; 136 if( (x1 > halfy) || ((x1 == halfy) & ((iquo & 1) != 0 ))) 137 x1 -= fabsy; 138 } 139 140 if( x < -0.0f ) 141 x1 = -x1; 142 143 return x1; 144} 145