1/*	$NetBSD: sfcmp.c,v 1.3 2005/12/11 12:17:40 christos Exp $	*/
2
3/*	$OpenBSD: sfcmp.c,v 1.4 2001/03/29 03:58:19 mickey Exp $	*/
4
5/*
6 * Copyright 1996 1995 by Open Software Foundation, Inc.
7 *              All Rights Reserved
8 *
9 * Permission to use, copy, modify, and distribute this software and
10 * its documentation for any purpose and without fee is hereby granted,
11 * provided that the above copyright notice appears in all copies and
12 * that both the copyright notice and this permission notice appear in
13 * supporting documentation.
14 *
15 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
17 * FOR A PARTICULAR PURPOSE.
18 *
19 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
22 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
23 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 *
25 */
26/*
27 * pmk1.1
28 */
29/*
30 * (c) Copyright 1986 HEWLETT-PACKARD COMPANY
31 *
32 * To anyone who acknowledges that this file is provided "AS IS"
33 * without any express or implied warranty:
34 *     permission to use, copy, modify, and distribute this file
35 * for any purpose is hereby granted without fee, provided that
36 * the above copyright notice and this notice appears in all
37 * copies, and that the name of Hewlett-Packard Company not be
38 * used in advertising or publicity pertaining to distribution
39 * of the software without specific, written prior permission.
40 * Hewlett-Packard Company makes no representations about the
41 * suitability of this software for any purpose.
42 */
43
44#include <sys/cdefs.h>
45__KERNEL_RCSID(0, "$NetBSD: sfcmp.c,v 1.3 2005/12/11 12:17:40 christos Exp $");
46
47#include "../spmath/float.h"
48#include "../spmath/sgl_float.h"
49
50/*
51 * sgl_cmp: compare two values
52 */
53int
54sgl_fcmp(sgl_floating_point *leftptr, sgl_floating_point *rightptr,
55    unsigned int cond, unsigned int *status)
56{
57    register unsigned int left, right;
58    register int xorresult;
59
60    /* Create local copies of the numbers */
61    left = *leftptr;
62    right = *rightptr;
63    /*
64     * Test for NaN
65     */
66    if(    (Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
67	|| (Sgl_exponent(right) == SGL_INFINITY_EXPONENT) )
68	{
69	/* Check if a NaN is involved.  Signal an invalid exception when
70	 * comparing a signaling NaN or when comparing quiet NaNs and the
71	 * low bit of the condition is set */
72	if( (  (Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
73	    && Sgl_isnotzero_mantissa(left)
74	    && (Exception(cond) || Sgl_isone_signaling(left)))
75	   ||
76	    (  (Sgl_exponent(right) == SGL_INFINITY_EXPONENT)
77	    && Sgl_isnotzero_mantissa(right)
78	    && (Exception(cond) || Sgl_isone_signaling(right)) ) )
79	    {
80	    if( Is_invalidtrap_enabled() ) {
81		Set_status_cbit(Unordered(cond));
82		return(INVALIDEXCEPTION);
83	    }
84	    else Set_invalidflag();
85	    Set_status_cbit(Unordered(cond));
86	    return(NOEXCEPTION);
87	    }
88	/* All the exceptional conditions are handled, now special case
89	   NaN compares */
90	else if( ((Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
91	    && Sgl_isnotzero_mantissa(left))
92	   ||
93	    ((Sgl_exponent(right) == SGL_INFINITY_EXPONENT)
94	    && Sgl_isnotzero_mantissa(right)) )
95	    {
96	    /* NaNs always compare unordered. */
97	    Set_status_cbit(Unordered(cond));
98	    return(NOEXCEPTION);
99	    }
100	/* infinities will drop down to the normal compare mechanisms */
101	}
102    /* First compare for unequal signs => less or greater or
103     * special equal case */
104    Sgl_xortointp1(left,right,xorresult);
105    if( xorresult < 0 )
106	{
107	/* left negative => less, left positive => greater.
108	 * equal is possible if both operands are zeros. */
109	if( Sgl_iszero_exponentmantissa(left)
110	  && Sgl_iszero_exponentmantissa(right) )
111	    {
112	    Set_status_cbit(Equal(cond));
113	    }
114	else if( Sgl_isone_sign(left) )
115	    {
116	    Set_status_cbit(Lessthan(cond));
117	    }
118	else
119	    {
120	    Set_status_cbit(Greaterthan(cond));
121	    }
122	}
123    /* Signs are the same.  Treat negative numbers separately
124     * from the positives because of the reversed sense.  */
125    else if( Sgl_all(left) == Sgl_all(right) )
126	{
127	Set_status_cbit(Equal(cond));
128	}
129    else if( Sgl_iszero_sign(left) )
130	{
131	/* Positive compare */
132	if( Sgl_all(left) < Sgl_all(right) )
133	    {
134	    Set_status_cbit(Lessthan(cond));
135	    }
136	else
137	    {
138	    Set_status_cbit(Greaterthan(cond));
139	    }
140	}
141    else
142	{
143	/* Negative compare.  Signed or unsigned compares
144	 * both work the same.  That distinction is only
145	 * important when the sign bits differ. */
146	if( Sgl_all(left) > Sgl_all(right) )
147	    {
148	    Set_status_cbit(Lessthan(cond));
149	    }
150	else
151	    {
152	    Set_status_cbit(Greaterthan(cond));
153	    }
154	}
155	return(NOEXCEPTION);
156    }
157