/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 1988 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/* IEEE function implementations. */
#include "base_conversion.h"
enum fp_class_type
_class_single(single *x)
{
single_equivalence kluge;
kluge.x = *x;
if (kluge.f.msw.exponent == 0) { /* 0 or sub */
if (kluge.f.msw.significand == 0)
return fp_zero;
else
return fp_subnormal;
} else if (kluge.f.msw.exponent == 0xff) { /* inf or nan */
if (kluge.f.msw.significand == 0)
return fp_infinity;
else if (kluge.f.msw.significand >= 0x400000)
return fp_quiet;
else
return fp_signaling;
} else
return fp_normal;
}
enum fp_class_type
_class_extended(extended *x)
{
extended_equivalence kluge;
kluge.x[0] = (*x)[0];
kluge.x[1] = (*x)[1];
kluge.x[2] = (*x)[2];
if (kluge.f.msw.exponent == 0) { /* 0 or sub */
if ((kluge.f.significand == 0) && (kluge.f.significand2 == 0))
return fp_zero;
else
return fp_subnormal;
} else if (kluge.f.msw.exponent == 0x7fff) { /* inf or nan */
if (((kluge.f.significand & 0x7fffffff) == 0) && (kluge.f.significand2 == 0))
return fp_infinity;
else if ((kluge.f.significand & 0x7fffffff) >= 0x40000000)
return fp_quiet;
else
return fp_signaling;
} else
return fp_normal;
}
void
_unpack_single(unpacked *pu, single *px)
{
single_equivalence x;
int i;
x.x = *px;
(*pu).sign = x.f.msw.sign;
for (i = 1; i < UNPACKED_SIZE; i++)
pu->significand[i] = 0;
if (x.f.msw.exponent == 0) { /* zero or sub */
if (x.f.msw.significand == 0) { /* zero */
pu->fpclass = fp_zero;
return;
} else { /* subnormal */
pu->fpclass = fp_normal;
pu->exponent = -SINGLE_BIAS;
pu->significand[0] = x.f.msw.significand << 9;
_fp_normalize(pu);
return;
}
} else if (x.f.msw.exponent == 0xff) { /* inf or nan */
if (x.f.msw.significand == 0) { /* inf */
pu->fpclass = fp_infinity;
return;
} else { /* nan */
if ((x.f.msw.significand & 0x400000) != 0) { /* quiet */
pu->fpclass = fp_quiet;
} else {/* signaling */
pu->fpclass = fp_quiet;
_fp_set_exception(fp_invalid);
}
pu->significand[0] = 0x40000000 | (x.f.msw.significand << 8);
return;
}
}
(*pu).exponent = x.f.msw.exponent - SINGLE_BIAS;
(*pu).fpclass = fp_normal;
(*pu).significand[0] = 0x80000000 | (x.f.msw.significand << 8);
}
void
_unpack_extended(unpacked *pu, extended *px)
{
extended_equivalence x;
int i;
x.x[0] = (*px)[0];
x.x[1] = (*px)[1];
x.x[2] = (*px)[2];
pu->sign = x.f.msw.sign;
pu->fpclass = fp_normal;
pu->exponent = x.f.msw.exponent - EXTENDED_BIAS;
pu->significand[0] = x.f.significand;
pu->significand[1] = x.f.significand2;
for (i = 2; i < UNPACKED_SIZE; i++)
pu->significand[i] = 0;
if (x.f.msw.exponent == 0x7fff) { /* inf or nan */
if (((x.f.significand & 0x7fffffff) == 0) && (x.f.significand2 == 0)) { /* inf */
pu->fpclass = fp_infinity;
return;
} else { /* nan */
if ((x.f.significand & 0x40000000) != 0) { /* quiet */
pu->fpclass = fp_quiet;
} else {/* signaling */
pu->fpclass = fp_quiet;
_fp_set_exception(fp_invalid);
}
return;
}
}
if (x.f.significand < 0x80000000) { /* zero or unnormal */
if ((x.f.significand == 0) && (x.f.significand2 == 0)) { /* zero */
pu->fpclass = fp_zero;
return;
} else { /* unnormal */
pu->fpclass = fp_normal;
_fp_normalize(pu);
return;
}
}
}
void
_display_unpacked(unpacked *pu)
{
int i, e;
(void) printf(" unpacked ");
if (pu->sign == 1)
(void) printf("-");
else
(void) printf("+");
switch (pu->fpclass) {
case fp_zero:
(void) printf("0");
break;
case fp_infinity:
(void) printf("Infinity");
break;
case fp_quiet:
(void) printf("NaN(quiet)");
break;
case fp_signaling:
(void) printf("NaN(signaling)");
break;
case fp_subnormal:
case fp_normal:
e = 1 + pu->exponent;
for (i = 0; i < UNPACKED_SIZE; i++) {
e -= 32;
(void) printf(" %8X *2**%d + ", pu->significand[i], e);
}
}
(void) printf("\n");
}