modfl.c revision 1ec68d336ba97cd53f46053ac10401d16014d075
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi/*
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * CDDL HEADER START
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi *
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * The contents of this file are subject to the terms of the
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * Common Development and Distribution License (the "License").
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * You may not use this file except in compliance with the License.
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi *
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * or http://www.opensolaris.org/os/licensing.
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * See the License for the specific language governing permissions
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * and limitations under the License.
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi *
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * When distributing Covered Code, include this CDDL HEADER in each
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * If applicable, add the following below this CDDL HEADER, with the
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * fields enclosed by brackets "[]" replaced with your own identifying
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * information: Portions Copyright [yyyy] [name of copyright owner]
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi *
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * CDDL HEADER END
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi/*
44ed9dbbfa620821ecf59a131462082f628dd0f3Stephen Hanson * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
aed5247ff899ec457005d93dfbdb4ffd74574695Joshua M. Clulow */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi/*
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * Use is subject to license terms.
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi#pragma weak modfl = __modfl
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi#include "libm.h"
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi#if defined(__sparc)
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindilong double
908f1e1388f616898b4e515d343c0414f2a6472esd__modfl(long double x, long double *iptr) {
184cd04c26b064536977dfbb913a1240eaf6f708cth union {
908f1e1388f616898b4e515d343c0414f2a6472esd unsigned i[4];
14ea4bb737263733ad80a36b4f73f681c30a6b45sd long double q;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi } xx, yy;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi unsigned hx, s;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi xx.q = x;
908f1e1388f616898b4e515d343c0414f2a6472esd hx = xx.i[0] & ~0x80000000;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost if (hx >= 0x406f0000) { /* x is NaN, infinite, or integral */
940d71d237794874e18a0eb72f6564821a823517eschrock *iptr = x;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (hx < 0x7fff0000 || (hx == 0x7fff0000 &&
13faa91230bde46da937bf33010b9accc5bdeb59sd (xx.i[1] | xx.i[2] | xx.i[3]) == 0)) {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi xx.i[0] &= 0x80000000;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi xx.i[1] = xx.i[2] = xx.i[3] = 0;
908f1e1388f616898b4e515d343c0414f2a6472esd }
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi return (xx.q);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj }
ded9341448cd6e2573619c7f6fe98909bdd35ec6Hyon Kim
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj if (hx < 0x3fff0000) { /* |x| < 1 */
fc33347812f84907261f6fd501e2409da108b8d8Tom Pothier xx.i[0] &= 0x80000000;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi xx.i[1] = xx.i[2] = xx.i[3] = 0;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi *iptr = xx.q;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi return (x);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim }
13faa91230bde46da937bf33010b9accc5bdeb59sd
908f1e1388f616898b4e515d343c0414f2a6472esd /* split x at the binary point */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi s = xx.i[0] & 0x80000000;
908f1e1388f616898b4e515d343c0414f2a6472esd if (hx < 0x40100000) {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi yy.i[0] = xx.i[0] & ~((1 << (0x400f - (hx >> 16))) - 1);
14ea4bb737263733ad80a36b4f73f681c30a6b45sd yy.i[1] = yy.i[2] = yy.i[3] = 0;
14ea4bb737263733ad80a36b4f73f681c30a6b45sd } else if (hx < 0x40300000) {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi yy.i[0] = xx.i[0];
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi yy.i[1] = xx.i[1] & ~((1 << (0x402f - (hx >> 16))) - 1);
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi yy.i[2] = yy.i[3] = 0;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi } else if (hx < 0x40500000) {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi yy.i[0] = xx.i[0];
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi yy.i[1] = xx.i[1];
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi yy.i[2] = xx.i[2] & ~((1 << (0x404f - (hx >> 16))) - 1);
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi yy.i[3] = 0;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi } else {
ded9341448cd6e2573619c7f6fe98909bdd35ec6Hyon Kim yy.i[0] = xx.i[0];
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj yy.i[1] = xx.i[1];
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj yy.i[2] = xx.i[2];
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi yy.i[3] = xx.i[3] & ~((1 << (0x406f - (hx >> 16))) - 1);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim }
908f1e1388f616898b4e515d343c0414f2a6472esd *iptr = yy.q;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
908f1e1388f616898b4e515d343c0414f2a6472esd /*
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * we could implement the following more efficiently than by using
940d71d237794874e18a0eb72f6564821a823517eschrock * software emulation of fsubq, but we'll do it this way for now
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * (and hope hardware support becomes commonplace)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
53dbcc5939527e6d5d52d814e51e364b5e8bb532Sundeep Panicker xx.q -= yy.q;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi xx.i[0] = (xx.i[0] & ~0x80000000) | s; /* keep sign of x */
14ea4bb737263733ad80a36b4f73f681c30a6b45sd return (xx.q);
14ea4bb737263733ad80a36b4f73f681c30a6b45sd}
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi#elif defined(__x86)
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindilong double
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi__modfl(long double x, long double *iptr) {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi union {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi unsigned i[3];
9dd0f810214fdc8e1af881a9a5c4b6927629ff9ecindi long double e;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi } xx, yy;
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth unsigned hx, s;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi /*
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth * It might be faster to use one of the x86 fpops instead of
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * the following.
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi xx.e = x;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi hx = xx.i[2] & 0x7fff;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (hx >= 0x403e) { /* x is NaN, infinite, or integral */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi *iptr = x;
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae if (hx < 0x7fff || (hx == 0x7fff &&
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi ((xx.i[1] << 1) | xx.i[0]) == 0)) {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim xx.i[2] &= 0x8000;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim xx.i[1] = xx.i[0] = 0;
aed5247ff899ec457005d93dfbdb4ffd74574695Joshua M. Clulow }
aed5247ff899ec457005d93dfbdb4ffd74574695Joshua M. Clulow return (xx.e);
aed5247ff899ec457005d93dfbdb4ffd74574695Joshua M. Clulow }
aed5247ff899ec457005d93dfbdb4ffd74574695Joshua M. Clulow
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if (hx < 0x3fff) { /* |x| < 1 */
44ed9dbbfa620821ecf59a131462082f628dd0f3Stephen Hanson xx.i[2] &= 0x8000;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim xx.i[1] = xx.i[0] = 0;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim *iptr = xx.e;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (x);
44ed9dbbfa620821ecf59a131462082f628dd0f3Stephen Hanson }
44ed9dbbfa620821ecf59a131462082f628dd0f3Stephen Hanson
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim /* split x at the binary point */
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim s = xx.i[2] & 0x8000;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim yy.i[2] = xx.i[2];
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if (hx < 0x401f) {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim yy.i[1] = xx.i[1] & ~((1 << (0x401e - hx)) - 1);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim yy.i[0] = 0;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim } else {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim yy.i[1] = xx.i[1];
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim yy.i[0] = xx.i[0] & ~((1 << (0x403e - hx)) - 1);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim }
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim *iptr = yy.e;
03f9f63d24f0494b7d47b927090ad9045e396402Tom Pothier xx.e -= yy.e;
e58a33b62cd4c9a6815fd752ce58b5f389289da1Stephen Hanson xx.i[2] = (xx.i[2] & ~0x8000) | s; /* keep sign of x */
e58a33b62cd4c9a6815fd752ce58b5f389289da1Stephen Hanson return (xx.e);
e58a33b62cd4c9a6815fd752ce58b5f389289da1Stephen Hanson}
e58a33b62cd4c9a6815fd752ce58b5f389289da1Stephen Hanson
e58a33b62cd4c9a6815fd752ce58b5f389289da1Stephen Hanson#else
e58a33b62cd4c9a6815fd752ce58b5f389289da1Stephen Hanson#error Unknown architecture
e58a33b62cd4c9a6815fd752ce58b5f389289da1Stephen Hanson#endif
e58a33b62cd4c9a6815fd752ce58b5f389289da1Stephen Hanson