xref: /original-bsd/lib/libc/quad/fixunsdfdi.c (revision 8a7e0fcd)
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