1570af302Sopenharmony_ci#include <math.h> 2570af302Sopenharmony_ci#include <stdint.h> 3570af302Sopenharmony_ci 4570af302Sopenharmony_cifloat remquof(float x, float y, int *quo) 5570af302Sopenharmony_ci{ 6570af302Sopenharmony_ci union {float f; uint32_t i;} ux = {x}, uy = {y}; 7570af302Sopenharmony_ci int ex = ux.i>>23 & 0xff; 8570af302Sopenharmony_ci int ey = uy.i>>23 & 0xff; 9570af302Sopenharmony_ci int sx = ux.i>>31; 10570af302Sopenharmony_ci int sy = uy.i>>31; 11570af302Sopenharmony_ci uint32_t q; 12570af302Sopenharmony_ci uint32_t i; 13570af302Sopenharmony_ci uint32_t uxi = ux.i; 14570af302Sopenharmony_ci 15570af302Sopenharmony_ci *quo = 0; 16570af302Sopenharmony_ci if (uy.i<<1 == 0 || isnan(y) || ex == 0xff) 17570af302Sopenharmony_ci return (x*y)/(x*y); 18570af302Sopenharmony_ci if (ux.i<<1 == 0) 19570af302Sopenharmony_ci return x; 20570af302Sopenharmony_ci 21570af302Sopenharmony_ci /* normalize x and y */ 22570af302Sopenharmony_ci if (!ex) { 23570af302Sopenharmony_ci for (i = uxi<<9; i>>31 == 0; ex--, i <<= 1); 24570af302Sopenharmony_ci uxi <<= -ex + 1; 25570af302Sopenharmony_ci } else { 26570af302Sopenharmony_ci uxi &= -1U >> 9; 27570af302Sopenharmony_ci uxi |= 1U << 23; 28570af302Sopenharmony_ci } 29570af302Sopenharmony_ci if (!ey) { 30570af302Sopenharmony_ci for (i = uy.i<<9; i>>31 == 0; ey--, i <<= 1); 31570af302Sopenharmony_ci uy.i <<= -ey + 1; 32570af302Sopenharmony_ci } else { 33570af302Sopenharmony_ci uy.i &= -1U >> 9; 34570af302Sopenharmony_ci uy.i |= 1U << 23; 35570af302Sopenharmony_ci } 36570af302Sopenharmony_ci 37570af302Sopenharmony_ci q = 0; 38570af302Sopenharmony_ci if (ex < ey) { 39570af302Sopenharmony_ci if (ex+1 == ey) 40570af302Sopenharmony_ci goto end; 41570af302Sopenharmony_ci return x; 42570af302Sopenharmony_ci } 43570af302Sopenharmony_ci 44570af302Sopenharmony_ci /* x mod y */ 45570af302Sopenharmony_ci for (; ex > ey; ex--) { 46570af302Sopenharmony_ci i = uxi - uy.i; 47570af302Sopenharmony_ci if (i >> 31 == 0) { 48570af302Sopenharmony_ci uxi = i; 49570af302Sopenharmony_ci q++; 50570af302Sopenharmony_ci } 51570af302Sopenharmony_ci uxi <<= 1; 52570af302Sopenharmony_ci q <<= 1; 53570af302Sopenharmony_ci } 54570af302Sopenharmony_ci i = uxi - uy.i; 55570af302Sopenharmony_ci if (i >> 31 == 0) { 56570af302Sopenharmony_ci uxi = i; 57570af302Sopenharmony_ci q++; 58570af302Sopenharmony_ci } 59570af302Sopenharmony_ci if (uxi == 0) 60570af302Sopenharmony_ci ex = -30; 61570af302Sopenharmony_ci else 62570af302Sopenharmony_ci for (; uxi>>23 == 0; uxi <<= 1, ex--); 63570af302Sopenharmony_ciend: 64570af302Sopenharmony_ci /* scale result and decide between |x| and |x|-|y| */ 65570af302Sopenharmony_ci if (ex > 0) { 66570af302Sopenharmony_ci uxi -= 1U << 23; 67570af302Sopenharmony_ci uxi |= (uint32_t)ex << 23; 68570af302Sopenharmony_ci } else { 69570af302Sopenharmony_ci uxi >>= -ex + 1; 70570af302Sopenharmony_ci } 71570af302Sopenharmony_ci ux.i = uxi; 72570af302Sopenharmony_ci x = ux.f; 73570af302Sopenharmony_ci if (sy) 74570af302Sopenharmony_ci y = -y; 75570af302Sopenharmony_ci if (ex == ey || (ex+1 == ey && (2*x > y || (2*x == y && q%2)))) { 76570af302Sopenharmony_ci x -= y; 77570af302Sopenharmony_ci q++; 78570af302Sopenharmony_ci } 79570af302Sopenharmony_ci q &= 0x7fffffff; 80570af302Sopenharmony_ci *quo = sx^sy ? -(int)q : (int)q; 81570af302Sopenharmony_ci return sx ? -x : x; 82570af302Sopenharmony_ci} 83