134122Sbostic /* 234122Sbostic * Copyright (c) 1985 Regents of the University of California. 334401Sbostic * All rights reserved. 434401Sbostic * 5*42657Sbostic * %sccs.include.redist.c% 634401Sbostic * 734401Sbostic * All recipients should regard themselves as participants in an ongoing 834401Sbostic * research project and hence should feel obligated to report their 934401Sbostic * experiences (good or bad) with these elementary function codes, using 1034401Sbostic * the sendbug(8) program, to the authors. 1134122Sbostic */ 1224596Szliu 1334122Sbostic #ifndef lint 14*42657Sbostic static char sccsid[] = "@(#)floor.c 5.6 (Berkeley) 06/01/90"; 1534122Sbostic #endif /* not lint */ 1634122Sbostic 1735679Sbostic #include "mathimpl.h" 1834401Sbostic 1935679Sbostic vc(L, 4503599627370496.0E0 ,0000,5c00,0000,0000, 55, 1.0) /* 2**55 */ 2035679Sbostic 2135679Sbostic ic(L, 4503599627370496.0E0, 52, 1.0) /* 2**52 */ 2235679Sbostic 2335679Sbostic #ifdef vccast 2435679Sbostic #define L vccast(L) 2535679Sbostic #endif 2635679Sbostic 2735679Sbostic 2835679Sbostic double ceil(); 2935679Sbostic double floor(); 3035679Sbostic 3124596Szliu /* 3234401Sbostic * floor(x) := the largest integer no larger than x; 3334401Sbostic * ceil(x) := -floor(-x), for all real x. 3434401Sbostic * 3534401Sbostic * Note: Inexact will be signaled if x is not an integer, as is 3634401Sbostic * customary for IEEE 754. No other signal can be emitted. 3724596Szliu */ 3824596Szliu double 3934401Sbostic floor(x) 4034401Sbostic double x; 4124596Szliu { 4235679Sbostic double y; 4324596Szliu 4434401Sbostic if ( 4534401Sbostic #if !defined(vax)&&!defined(tahoe) 4634401Sbostic x != x || /* NaN */ 4734401Sbostic #endif /* !defined(vax)&&!defined(tahoe) */ 4834401Sbostic x >= L) /* already an even integer */ 4934401Sbostic return x; 5034401Sbostic else if (x < (double)0) 5134401Sbostic return -ceil(-x); 5234401Sbostic else { /* now 0 <= x < L */ 5334401Sbostic y = L+x; /* destructive store must be forced */ 5434401Sbostic y -= L; /* an integer, and |x-y| < 1 */ 5534401Sbostic return x < y ? y-(double)1 : y; 5634401Sbostic } 5724596Szliu } 5824596Szliu 5924596Szliu double 6034401Sbostic ceil(x) 6134401Sbostic double x; 6224596Szliu { 6335679Sbostic double y; 6434401Sbostic 6534401Sbostic if ( 6634401Sbostic #if !defined(vax)&&!defined(tahoe) 6734401Sbostic x != x || /* NaN */ 6834401Sbostic #endif /* !defined(vax)&&!defined(tahoe) */ 6934401Sbostic x >= L) /* already an even integer */ 7034401Sbostic return x; 7134401Sbostic else if (x < (double)0) 7234401Sbostic return -floor(-x); 7334401Sbostic else { /* now 0 <= x < L */ 7434401Sbostic y = L+x; /* destructive store must be forced */ 7534401Sbostic y -= L; /* an integer, and |x-y| < 1 */ 7634401Sbostic return x > y ? y+(double)1 : y; 7734401Sbostic } 7824596Szliu } 7924596Szliu 8031853Szliu #ifndef national /* rint() is in ./NATIONAL/support.s */ 8124596Szliu /* 8224596Szliu * algorithm for rint(x) in pseudo-pascal form ... 8324596Szliu * 8424596Szliu * real rint(x): real x; 8524596Szliu * ... delivers integer nearest x in direction of prevailing rounding 8624596Szliu * ... mode 8724596Szliu * const L = (last consecutive integer)/2 8824596Szliu * = 2**55; for VAX D 8924596Szliu * = 2**52; for IEEE 754 Double 9024596Szliu * real s,t; 9124596Szliu * begin 9224596Szliu * if x != x then return x; ... NaN 9324596Szliu * if |x| >= L then return x; ... already an integer 9424596Szliu * s := copysign(L,x); 9524596Szliu * t := x + s; ... = (x+s) rounded to integer 9624596Szliu * return t - s 9724596Szliu * end; 9824596Szliu * 9924596Szliu * Note: Inexact will be signaled if x is not an integer, as is 10024596Szliu * customary for IEEE 754. No other signal can be emitted. 10124596Szliu */ 10224596Szliu double 10324596Szliu rint(x) 10424596Szliu double x; 10524596Szliu { 10635679Sbostic double s,t; 10735679Sbostic const double one = 1.0; 10835679Sbostic 10931853Szliu #if !defined(vax)&&!defined(tahoe) 11024596Szliu if (x != x) /* NaN */ 11124596Szliu return (x); 11231853Szliu #endif /* !defined(vax)&&!defined(tahoe) */ 11324596Szliu if (copysign(x,one) >= L) /* already an integer */ 11424596Szliu return (x); 11524596Szliu s = copysign(L,x); 11624596Szliu t = x + s; /* x+s rounded to integer */ 11724596Szliu return (t - s); 11824596Szliu } 11931853Szliu #endif /* not national */ 120