1*54746Storek /*- 2*54746Storek * Copyright (c) 1992 The Regents of the University of California. 3*54746Storek * All rights reserved. 4*54746Storek * 5*54746Storek * This software was developed by the Computer Systems Engineering group 6*54746Storek * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7*54746Storek * contributed to Berkeley. 8*54746Storek * 9*54746Storek * %sccs.include.redist.c% 10*54746Storek */ 11*54746Storek 12*54746Storek #if defined(LIBC_SCCS) && !defined(lint) 13*54746Storek static char sccsid[] = "@(#)fixunssfdi.c 5.1 (Berkeley) 07/07/92"; 14*54746Storek #endif /* LIBC_SCCS and not lint */ 15*54746Storek 16*54746Storek #include "quad.h" 17*54746Storek 18*54746Storek #define ONE_FOURTH (1 << (LONG_BITS - 2)) 19*54746Storek #define ONE_HALF (ONE_FOURTH * 2.0) 20*54746Storek #define ONE (ONE_FOURTH * 4.0) 21*54746Storek 22*54746Storek /* 23*54746Storek * Convert float to (unsigned) quad. We do most of our work in double, 24*54746Storek * out of sheer paranoia. 25*54746Storek * 26*54746Storek * Not sure what to do with negative numbers---for now, anything out 27*54746Storek * of range becomes UQUAD_MAX. 28*54746Storek * 29*54746Storek * N.B.: must use new ANSI syntax (sorry). 30*54746Storek */ 31*54746Storek u_quad_t 32*54746Storek __fixunssfdi(float f) 33*54746Storek { 34*54746Storek double x, toppart; 35*54746Storek union uu t; 36*54746Storek 37*54746Storek if (f < 0) 38*54746Storek return (UQUAD_MAX); /* ??? should be 0? ERANGE??? */ 39*54746Storek if (f >= UQUAD_MAX) 40*54746Storek return (UQUAD_MAX); 41*54746Storek x = f; 42*54746Storek /* 43*54746Storek * Get the upper part of the result. Note that the divide 44*54746Storek * may round up; we want to avoid this if possible, so we 45*54746Storek * subtract `1/2' first. 46*54746Storek */ 47*54746Storek toppart = (x - ONE_HALF) / ONE; 48*54746Storek /* 49*54746Storek * Now build a u_quad_t out of the top part. The difference 50*54746Storek * between x and this is the bottom part (this may introduce 51*54746Storek * a few fuzzy bits, but what the heck). With any luck this 52*54746Storek * difference will be nonnegative: x should wind up in the 53*54746Storek * range [0..ULONG_MAX]. For paranoia, we assume [LONG_MIN.. 54*54746Storek * 2*ULONG_MAX] instead. 55*54746Storek */ 56*54746Storek t.ul[H] = (unsigned long)toppart; 57*54746Storek t.ul[L] = 0; 58*54746Storek x -= (double)t.uq; 59*54746Storek if (x < 0) { 60*54746Storek t.ul[H]--; 61*54746Storek x += ULONG_MAX; 62*54746Storek } 63*54746Storek if (x > ULONG_MAX) { 64*54746Storek t.ul[H]++; 65*54746Storek x -= ULONG_MAX; 66*54746Storek } 67*54746Storek t.ul[L] = (u_long)x; 68*54746Storek return (t.uq); 69*54746Storek } 70