/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 1988 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984 AT&T */ /* All Rights Reserved */ #pragma ident "%Z%%M% %I% %E% SMI" /* from S5R2 2.7 */ /*LINTLIBRARY*/ /* * double ldexp (value, exp) * double value; * int exp; * * Ldexp returns value * 2**exp, if that result is in range. * If underflow occurs, it returns zero. If overflow occurs, * it returns a value of appropriate sign and largest single- * precision magnitude. In case of underflow or overflow, * the external int "errno" is set to ERANGE. Note that errno is * not modified if no error occurs, so if you intend to test it * after you use ldexp, you had better set it to something * other than ERANGE first (zero is a reasonable value to use). */ #include #include /* Largest signed long int power of 2 */ #define MAXSHIFT (BITSPERBYTE * sizeof(long) - 2) extern double frexp(); double ldexp(value, exp) register double value; register int exp; { int old_exp; if (exp == 0 || value == 0.0) /* nothing to do for zero */ return (value); #if !(pdp11 || u3b5) /* pdp11 "cc" can't handle cast of double to void on pdp11 or 3b5 */ (void) #endif frexp(value, &old_exp); if (exp > 0) { if (exp + old_exp > MAXBEXP) { /* overflow */ errno = ERANGE; return ((double)(value < 0 ? MINDOUBLE : MAXDOUBLE)); /* return ((double)(value < 0 ? -1.0e999 : 1.0e999)); */ } for ( ; exp > MAXSHIFT; exp -= MAXSHIFT) value *= (1L << MAXSHIFT); return (value * (1L << exp)); } if (exp + old_exp < MINBEXP) { /* underflow */ errno = ERANGE; return (0.0); } for ( ; exp < -MAXSHIFT; exp += MAXSHIFT) value *= 1.0/(1L << MAXSHIFT); /* mult faster than div */ return (value / (1L << -exp)); }