fixunssfdi.c revision 1573
189948Simp/*-
289948Simp * Copyright (c) 1992, 1993
389948Simp *	The Regents of the University of California.  All rights reserved.
489948Simp *
589948Simp * This software was developed by the Computer Systems Engineering group
689948Simp * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
789948Simp * contributed to Berkeley.
889948Simp *
989948Simp * Redistribution and use in source and binary forms, with or without
1089948Simp * modification, are permitted provided that the following conditions
1189948Simp * are met:
1289948Simp * 1. Redistributions of source code must retain the above copyright
1389948Simp *    notice, this list of conditions and the following disclaimer.
1489948Simp * 2. Redistributions in binary form must reproduce the above copyright
1589948Simp *    notice, this list of conditions and the following disclaimer in the
1689948Simp *    documentation and/or other materials provided with the distribution.
1789948Simp * 3. All advertising materials mentioning features or use of this software
1889948Simp *    must display the following acknowledgement:
1989948Simp *	This product includes software developed by the University of
2089948Simp *	California, Berkeley and its contributors.
2189948Simp * 4. Neither the name of the University nor the names of its contributors
2289948Simp *    may be used to endorse or promote products derived from this software
2389948Simp *    without specific prior written permission.
2489948Simp *
2589948Simp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2689948Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2789948Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2889948Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2989948Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3089948Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3189948Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3289948Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3389948Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3489948Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3589948Simp * SUCH DAMAGE.
3689948Simp */
3789948Simp
3889948Simp#if defined(LIBC_SCCS) && !defined(lint)
3989948Simpstatic char sccsid[] = "@(#)fixunssfdi.c	8.1 (Berkeley) 6/4/93";
4089948Simp#endif /* LIBC_SCCS and not lint */
4189948Simp
4289948Simp#include "quad.h"
4389948Simp
4489948Simp#define	ONE_FOURTH	(1 << (LONG_BITS - 2))
4589948Simp#define	ONE_HALF	(ONE_FOURTH * 2.0)
4689948Simp#define	ONE		(ONE_FOURTH * 4.0)
4789948Simp
4889948Simp/*
4989948Simp * Convert float to (unsigned) quad.  We do most of our work in double,
5089948Simp * out of sheer paranoia.
5189948Simp *
5289948Simp * Not sure what to do with negative numbers---for now, anything out
5389948Simp * of range becomes UQUAD_MAX.
5489948Simp *
5589948Simp * N.B.: must use new ANSI syntax (sorry).
5689948Simp */
5789948Simpu_quad_t
58100703Simp__fixunssfdi(float f)
59100703Simp{
60100703Simp	double x, toppart;
6189948Simp	union uu t;
6289948Simp
6389948Simp	if (f < 0)
6489948Simp		return (UQUAD_MAX);	/* ??? should be 0?  ERANGE??? */
6589948Simp#ifdef notdef				/* this falls afoul of a GCC bug */
6689948Simp	if (f >= UQUAD_MAX)
6789948Simp		return (UQUAD_MAX);
6889948Simp#else					/* so we wire in 2^64-1 instead */
6989948Simp	if (f >= 18446744073709551615.0)
7089948Simp		return (UQUAD_MAX);
7189948Simp#endif
7289948Simp	x = f;
7389948Simp	/*
7489948Simp	 * Get the upper part of the result.  Note that the divide
7589948Simp	 * may round up; we want to avoid this if possible, so we
7689948Simp	 * subtract `1/2' first.
7789948Simp	 */
7889948Simp	toppart = (x - ONE_HALF) / ONE;
7989948Simp	/*
8089948Simp	 * Now build a u_quad_t out of the top part.  The difference
8189948Simp	 * between x and this is the bottom part (this may introduce
8289948Simp	 * a few fuzzy bits, but what the heck).  With any luck this
8389948Simp	 * difference will be nonnegative: x should wind up in the
8489948Simp	 * range [0..ULONG_MAX].  For paranoia, we assume [LONG_MIN..
8589948Simp	 * 2*ULONG_MAX] instead.
8689948Simp	 */
8789948Simp	t.ul[H] = (unsigned long)toppart;
8889948Simp	t.ul[L] = 0;
8989948Simp	x -= (double)t.uq;
9089948Simp	if (x < 0) {
9189948Simp		t.ul[H]--;
9289948Simp		x += ULONG_MAX;
9389948Simp	}
9489948Simp	if (x > ULONG_MAX) {
9589948Simp		t.ul[H]++;
9689948Simp		x -= ULONG_MAX;
9789948Simp	}
9889948Simp	t.ul[L] = (u_long)x;
9989948Simp	return (t.uq);
10089948Simp}
10189948Simp