11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* @(#)s_nextafter.c 5.1 93/09/24 */ 21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ==================================================== 41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Developed at SunPro, a Sun Microsystems, Inc. business. 71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Permission to use, copy, modify, and distribute this 81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * software is freely granted, provided that this notice 91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * is preserved. 101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ==================================================== 111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 13a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include <sys/cdefs.h> 14a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes__FBSDID("$FreeBSD$"); 151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * We assume that a long double has a 15-bit exponent. On systems 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * where long double is the same as double, nexttoward() is an alias 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * for nextafter(), so we don't use this routine. 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <float.h> 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "fpmath.h" 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "math.h" 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "math_private.h" 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if LDBL_MAX_EXP != 0x4000 291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#error "Unsupported long double format" 301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdouble 331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectnexttoward(double x, long double y) 341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project union IEEEl2bits uy; 361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project volatile double t; 371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int32_t hx,ix; 381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int32_t lx; 391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project EXTRACT_WORDS(hx,lx,x); 411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ix = hx&0x7fffffff; /* |x| */ 421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project uy.e = y; 431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || 451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (uy.bits.exp == 0x7fff && 461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0)) 471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return x+y; /* x or y is nan */ 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(x==y) return (double)y; /* x=y, return y */ 491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(x==0.0) { 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project INSERT_WORDS(x,uy.bits.sign<<31,1); /* return +-minsubnormal */ 511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project t = x*x; 521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(t==x) return t; else return x; /* raise underflow flag */ 531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(hx>0.0 ^ x < y) { /* x -= ulp */ 551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(lx==0) hx -= 1; 561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project lx -= 1; 571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { /* x += ulp */ 581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project lx += 1; 591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(lx==0) hx += 1; 601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ix = hx&0x7ff00000; 621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(ix>=0x7ff00000) return x+x; /* overflow */ 631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(ix<0x00100000) { /* underflow */ 641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project t = x*x; 651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(t!=x) { /* raise underflow flag */ 66a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes INSERT_WORDS(x,hx,lx); 67a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes return x; 681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project INSERT_WORDS(x,hx,lx); 711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return x; 721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 73