13809401dSbostic /*- 2*8a7e0fcdSbostic * Copyright (c) 1992, 1993 3*8a7e0fcdSbostic * The Regents of the University of California. All rights reserved. 43809401dSbostic * 50dc3174aSbostic * This software was developed by the Computer Systems Engineering group 60dc3174aSbostic * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 70dc3174aSbostic * contributed to Berkeley. 80dc3174aSbostic * 93809401dSbostic * %sccs.include.redist.c% 103809401dSbostic */ 113809401dSbostic 123809401dSbostic #if defined(LIBC_SCCS) && !defined(lint) 13*8a7e0fcdSbostic static char sccsid[] = "@(#)fixunsdfdi.c 8.1 (Berkeley) 06/04/93"; 143809401dSbostic #endif /* LIBC_SCCS and not lint */ 153809401dSbostic 160dc3174aSbostic #include "quad.h" 17ed2c7cf4Sbostic 180dc3174aSbostic #define ONE_FOURTH (1 << (LONG_BITS - 2)) 190dc3174aSbostic #define ONE_HALF (ONE_FOURTH * 2.0) 200dc3174aSbostic #define ONE (ONE_FOURTH * 4.0) 21ed2c7cf4Sbostic 220dc3174aSbostic /* 230dc3174aSbostic * Convert double to (unsigned) quad. 240dc3174aSbostic * Not sure what to do with negative numbers---for now, anything out 250dc3174aSbostic * of range becomes UQUAD_MAX. 260dc3174aSbostic */ 272a65f65aSbostic u_quad_t __fixunsdfdi(x)282a65f65aSbostic__fixunsdfdi(x) 292a65f65aSbostic double x; 303809401dSbostic { 310dc3174aSbostic double toppart; 320dc3174aSbostic union uu t; 333809401dSbostic 340dc3174aSbostic if (x < 0) 350dc3174aSbostic return (UQUAD_MAX); /* ??? should be 0? ERANGE??? */ 36ffcb3004Storek #ifdef notdef /* this falls afoul of a GCC bug */ 370dc3174aSbostic if (x >= UQUAD_MAX) 380dc3174aSbostic return (UQUAD_MAX); 39ffcb3004Storek #else /* so we wire in 2^64-1 instead */ 40ffcb3004Storek if (x >= 18446744073709551615.0) 41ffcb3004Storek return (UQUAD_MAX); 42ffcb3004Storek #endif 430dc3174aSbostic /* 440dc3174aSbostic * Get the upper part of the result. Note that the divide 450dc3174aSbostic * may round up; we want to avoid this if possible, so we 460dc3174aSbostic * subtract `1/2' first. 470dc3174aSbostic */ 480dc3174aSbostic toppart = (x - ONE_HALF) / ONE; 490dc3174aSbostic /* 502a65f65aSbostic * Now build a u_quad_t out of the top part. The difference 510dc3174aSbostic * between x and this is the bottom part (this may introduce 520dc3174aSbostic * a few fuzzy bits, but what the heck). With any luck this 530dc3174aSbostic * difference will be nonnegative: x should wind up in the 540dc3174aSbostic * range [0..ULONG_MAX]. For paranoia, we assume [LONG_MIN.. 550dc3174aSbostic * 2*ULONG_MAX] instead. 560dc3174aSbostic */ 570dc3174aSbostic t.ul[H] = (unsigned long)toppart; 580dc3174aSbostic t.ul[L] = 0; 590dc3174aSbostic x -= (double)t.uq; 600dc3174aSbostic if (x < 0) { 610dc3174aSbostic t.ul[H]--; 620dc3174aSbostic x += ULONG_MAX; 630dc3174aSbostic } 640dc3174aSbostic if (x > ULONG_MAX) { 650dc3174aSbostic t.ul[H]++; 660dc3174aSbostic x -= ULONG_MAX; 670dc3174aSbostic } 680dc3174aSbostic t.ul[L] = (u_long)x; 690dc3174aSbostic return (t.uq); 703809401dSbostic } 71