this repo has no description
at fixPythonPipStalling 156 lines 3.3 kB view raw
1/* 2 * remquof.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 remquof( float x, float y, int *quo ) 61{ 62 63 *quo = 0; // Init quotient result 64 65 // deal with NaN 66 if( x != x || y != y ) 67 return x + y; 68 69 //x = Inf or y = 0, return Invalid per IEEE-754 70 float fabsx = __builtin_fabsf(x); 71 if( fabsx == __builtin_inff() || 0.0f == y ) 72 { 73#ifdef ARMLIBM_SET_FLAGS 74 return required_add_float( __builtin_inff(), -__builtin_inff() ); //set invalid 75#else 76 return __builtin_nanf(""); 77#endif 78 } 79 80 //handle trivial case 81 float fabsy = __builtin_fabsf(y); 82 if( fabsy == __builtin_inff() || 0.0f == x ) 83 { 84#ifdef ARMLIBM_SET_FLAGS 85 required_add_float( fabsx, 0.0f ); //signal underflow (that is, no flag set, but exception occurs if unmasked) if x is denorm 86#endif 87 return x; 88 } 89 90 //we have to work 91 int32_t iquo = 0; 92 int32_t iscx = local_ilogbf(fabsx); 93 int32_t iscy = local_ilogbf(fabsy); 94 int32_t idiff = iscx - iscy; 95 float x1, y1, z; 96 x1 = fabsx; 97 y1 = fabsy; 98 union{ float d[2]; uint32_t u[2];} u = { { x, y } }; 99 int32_t sign = u.u[0] ^ u.u[1]; 100 sign = sign >> 31; 101 102 if( idiff >= 0 ) 103 { 104 int32_t i; 105 106 if( idiff ) 107 { 108 y1 = local_scalbnf( y1, -iscy ); 109 x1 = local_scalbnf( x1, -iscx ); 110 for( i = idiff; i != 0; i-- ) 111 { 112 if( x1 >= y1 ) 113 { 114 x1 -= y1; 115 iquo += 1; 116 } 117 iquo += iquo; 118 x1 += x1; 119 } 120 x1 = local_scalbnf( x1, iscy ); 121 } 122 if( x1 >= fabsy ) 123 { 124 x1 -= fabsy; 125 iquo += 1; 126 } 127 } 128 129 if( x1 < 0x1.0p127f ) 130 { 131 z = x1 + x1; 132 if( (z > fabsy) || ((z == fabsy) && ((iquo & 1) != 0 ))) 133 { 134 x1 -= fabsy; 135 iquo += 1; 136 } 137 } 138 else 139 { // x1 is only this large if y is even bigger, so we can safely divide y by 2 140 float halfy = 0.5f * fabsy; 141 if( (x1 > halfy) || ((x1 == halfy) & ((iquo & 1) != 0 ))) 142 { 143 x1 -= fabsy; 144 iquo += 1; 145 } 146 } 147 148 if( x < -0.0f ) 149 x1 = -x1; 150 iquo &= 0x7f; 151 152 *quo = (iquo ^ sign) - sign; 153 154 return x1; 155} 156