1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1988 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984 AT&T */ 28 /* All Rights Reserved */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" /* from S5R2 2.7 */ 31 32 /*LINTLIBRARY*/ 33 /* 34 * double ldexp (value, exp) 35 * double value; 36 * int exp; 37 * 38 * Ldexp returns value * 2**exp, if that result is in range. 39 * If underflow occurs, it returns zero. If overflow occurs, 40 * it returns a value of appropriate sign and largest single- 41 * precision magnitude. In case of underflow or overflow, 42 * the external int "errno" is set to ERANGE. Note that errno is 43 * not modified if no error occurs, so if you intend to test it 44 * after you use ldexp, you had better set it to something 45 * other than ERANGE first (zero is a reasonable value to use). 46 */ 47 48 #include <values.h> 49 #include <errno.h> 50 /* Largest signed long int power of 2 */ 51 #define MAXSHIFT (BITSPERBYTE * sizeof(long) - 2) 52 53 extern double frexp(); 54 55 double 56 ldexp(value, exp) 57 register double value; 58 register int exp; 59 { 60 int old_exp; 61 62 if (exp == 0 || value == 0.0) /* nothing to do for zero */ 63 return (value); 64 #if !(pdp11 || u3b5) /* pdp11 "cc" can't handle cast of 65 double to void on pdp11 or 3b5 */ 66 (void) 67 #endif 68 frexp(value, &old_exp); 69 if (exp > 0) { 70 if (exp + old_exp > MAXBEXP) { /* overflow */ 71 errno = ERANGE; 72 return ((double)(value < 0 ? MINDOUBLE : MAXDOUBLE)); 73 /* 74 return ((double)(value < 0 ? -1.0e999 : 1.0e999)); 75 */ 76 } 77 for ( ; exp > MAXSHIFT; exp -= MAXSHIFT) 78 value *= (1L << MAXSHIFT); 79 return (value * (1L << exp)); 80 } 81 if (exp + old_exp < MINBEXP) { /* underflow */ 82 errno = ERANGE; 83 return (0.0); 84 } 85 for ( ; exp < -MAXSHIFT; exp += MAXSHIFT) 86 value *= 1.0/(1L << MAXSHIFT); /* mult faster than div */ 87 return (value / (1L << -exp)); 88 } 89