s_nextafterl.c revision 1.1
11.1Schristos/* $NetBSD: s_nextafterl.c,v 1.1 2010/09/15 16:12:05 christos Exp $ */ 21.1Schristos 31.1Schristos/* @(#)s_nextafter.c 5.1 93/09/24 */ 41.1Schristos/* 51.1Schristos * ==================================================== 61.1Schristos * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 71.1Schristos * 81.1Schristos * Developed at SunPro, a Sun Microsystems, Inc. business. 91.1Schristos * Permission to use, copy, modify, and distribute this 101.1Schristos * software is freely granted, provided that this notice 111.1Schristos * is preserved. 121.1Schristos * ==================================================== 131.1Schristos */ 141.1Schristos 151.1Schristos#include <sys/cdefs.h> 161.1Schristos__RCSID("$NetBSD: s_nextafterl.c,v 1.1 2010/09/15 16:12:05 christos Exp $"); 171.1Schristos 181.1Schristos#include <float.h> 191.1Schristos#include <math.h> 201.1Schristos#include <machine/ieee.h> 211.1Schristos 221.1Schristos#if LDBL_MAX_EXP != 0x4000 231.1Schristos#error "Unsupported long double format" 241.1Schristos#endif 251.1Schristos 261.1Schristos/* 271.1Schristos * IEEE functions 281.1Schristos * nextafterl(x,y) 291.1Schristos * return the next machine floating-point number of x in the 301.1Schristos * direction toward y. 311.1Schristos * Special cases: 321.1Schristos * If x == y, y shall be returned 331.1Schristos * If x or y is NaN, a NaN shall be returned 341.1Schristos */ 351.1Schristoslong double 361.1Schristosnextafterl(long double x, long double y) 371.1Schristos{ 381.1Schristos volatile long double t; 391.1Schristos union ieee_ext_u ux, uy; 401.1Schristos 411.1Schristos ux.extu_ld = x; 421.1Schristos uy.extu_ld = y; 431.1Schristos 441.1Schristos if ((ux.extu_exp == EXT_EXP_NAN && 451.1Schristos ((ux.extu_frach &~ LDBL_NBIT)|ux.extu_fracl) != 0) || 461.1Schristos (uy.extu_exp == EXT_EXP_NAN && 471.1Schristos ((uy.extu_frach &~ LDBL_NBIT)|uy.extu_fracl) != 0)) 481.1Schristos return x+y; /* x or y is nan */ 491.1Schristos 501.1Schristos if (x == y) return y; /* x=y, return y */ 511.1Schristos 521.1Schristos if (x == 0.0) { 531.1Schristos ux.extu_frach = 0; /* return +-minsubnormal */ 541.1Schristos ux.extu_fracl = 1; 551.1Schristos ux.extu_sign = uy.extu_sign; 561.1Schristos t = ux.extu_ld * ux.extu_ld; 571.1Schristos if (t == ux.extu_ld) 581.1Schristos return t; 591.1Schristos else 601.1Schristos return ux.extu_ld; /* raise underflow flag */ 611.1Schristos } 621.1Schristos 631.1Schristos if ((x>0.0) ^ (x<y)) { /* x -= ulp */ 641.1Schristos if (ux.extu_fracl == 0) { 651.1Schristos if ((ux.extu_frach & ~LDBL_NBIT) == 0) 661.1Schristos ux.extu_exp -= 1; 671.1Schristos ux.extu_frach = (ux.extu_frach - 1) | 681.1Schristos (ux.extu_frach & LDBL_NBIT); 691.1Schristos } 701.1Schristos ux.extu_fracl -= 1; 711.1Schristos } else { /* x += ulp */ 721.1Schristos ux.extu_fracl += 1; 731.1Schristos if (ux.extu_fracl == 0) { 741.1Schristos ux.extu_frach = (ux.extu_frach + 1) | 751.1Schristos (ux.extu_frach & LDBL_NBIT); 761.1Schristos if ((ux.extu_frach & ~LDBL_NBIT) == 0) 771.1Schristos ux.extu_exp += 1; 781.1Schristos } 791.1Schristos } 801.1Schristos 811.1Schristos if (ux.extu_exp == EXT_EXP_INF) 821.1Schristos return x+x; /* overflow */ 831.1Schristos 841.1Schristos if (ux.extu_exp == 0) { /* underflow */ 851.1Schristos mask_nbit_l(ux); 861.1Schristos t = ux.extu_ld * ux.extu_ld; 871.1Schristos if (t != ux.extu_ld) /* raise underflow flag */ 881.1Schristos return ux.extu_ld; 891.1Schristos } 901.1Schristos 911.1Schristos return ux.extu_ld; 921.1Schristos} 93