rs_f16_math.c revision f9760483073d9f452e4701fbf367dc518f7e6531
1/* Implementations for copysign, ilogb, and nextafter for float16 based on 2 * corresponding float32 implementations in 3 * bionic/libm/upstream-freebsd/lib/msun/src 4 */ 5 6/* 7 * ==================================================== 8 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 9 * 10 * Developed at SunPro, a Sun Microsystems, Inc. business. 11 * Permission to use, copy, modify, and distribute this 12 * software is freely granted, provided that this notice 13 * is preserved. 14 * ==================================================== 15 */ 16 17#include "rs_core.rsh" 18#include "rs_f16_util.h" 19 20// Based on bionic/libm/upstream-freebsd/lib/msun/src/s_copysignf.c 21extern half __attribute__((overloadable)) copysign(half x, half y) { 22 short hx, hy; 23 GET_HALF_WORD(hx, x); 24 GET_HALF_WORD(hy, y); 25 26 SET_HALF_WORD(hx, (hx & 0x7fff) | (hy & 0x8000)); 27 return x; 28} 29 30// Based on bionic/libm/upstream-freebsd/lib/msun/src/s_ilogbf.c 31extern int __attribute__((overloadable)) ilogb(half x) { 32 const int RS_INT_MAX = 0x7fffffff; 33 const int RS_INT_MIN = 0x80000000; 34 35 short hx, ix; 36 GET_HALF_WORD(hx, x); 37 hx &= 0x7fff; 38 39 if (hx < 0x0400) { // subnormal 40 if (hx == 0) 41 return RS_INT_MIN; // for zero 42 for (hx <<= 5, ix = -14; hx > 0; hx <<= 1) 43 ix -= 1; 44 return ix; 45 } 46 else if (hx < 0x7c00) { 47 return (hx >> 10) - 15; 48 } 49 else { // hx >= 0x7c00 50 return RS_INT_MAX; // for NaN and infinity 51 } 52} 53 54// Based on bionic/libm/upstream-freebsd/lib/msun/src/s_nextafterf.c 55extern half __attribute__((overloadable)) nextafter(half x, half y) { 56 volatile half t; 57 short hx, hy, ix, iy; 58 59 GET_HALF_WORD(hx, x); 60 GET_HALF_WORD(hy, y); 61 ix = hx & 0x7fff; // |x| 62 iy = hy & 0x7fff; // |y| 63 64 if ((ix > 0x7c00) || // x is nan 65 (iy > 0x7c00)) // y is nan 66 return x + y; // return nan 67 68 if (x == y) return y; // x == y. return y 69 if (ix == 0) { 70 SET_HALF_WORD(x, (hy & 0x8000) | 1); 71 return x; 72 } 73 74 if (hx >= 0) { // x >= 0 75 if (hx > hy) 76 hx -= 1; // x > y, x -= 1 ulp 77 else 78 hx += 1; // x < y, x += 1 ulp 79 } 80 else { // x < 0 81 if (hy>= 0 || hx > hy) 82 hx -= 1; // x < y, x -= 1 ulp 83 else 84 hx += 1; 85 } 86 87 SET_HALF_WORD(x, hx); 88 return x; 89} 90