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 131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef lint 141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic char rcsid[] = "$FreeBSD: src/lib/msun/src/s_nexttoward.c,v 1.1 2005/03/07 04:56:46 das Exp $"; 151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * We assume that a long double has a 15-bit exponent. On systems 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * where long double is the same as double, nexttoward() is an alias 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * for nextafter(), so we don't use this routine. 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <float.h> 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "fpmath.h" 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "math.h" 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "math_private.h" 281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if LDBL_MAX_EXP != 0x4000 301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#error "Unsupported long double format" 311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdouble 341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectnexttoward(double x, long double y) 351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project union IEEEl2bits uy; 371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project volatile double t; 381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int32_t hx,ix; 391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int32_t lx; 401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project EXTRACT_WORDS(hx,lx,x); 421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ix = hx&0x7fffffff; /* |x| */ 431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project uy.e = y; 441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || 461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (uy.bits.exp == 0x7fff && 471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0)) 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return x+y; /* x or y is nan */ 491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(x==y) return (double)y; /* x=y, return y */ 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(x==0.0) { 511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project INSERT_WORDS(x,uy.bits.sign<<31,1); /* return +-minsubnormal */ 521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project t = x*x; 531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(t==x) return t; else return x; /* raise underflow flag */ 541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(hx>0.0 ^ x < y) { /* x -= ulp */ 561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(lx==0) hx -= 1; 571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project lx -= 1; 581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { /* x += ulp */ 591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project lx += 1; 601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(lx==0) hx += 1; 611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ix = hx&0x7ff00000; 631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(ix>=0x7ff00000) return x+x; /* overflow */ 641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(ix<0x00100000) { /* underflow */ 651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project t = x*x; 661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(t!=x) { /* raise underflow flag */ 671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project INSERT_WORDS(y,hx,lx); 681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return y; 691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project INSERT_WORDS(x,hx,lx); 721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return x; 731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 74