1*25c28e83SPiotr Jasiukajtis /* 2*25c28e83SPiotr Jasiukajtis * CDDL HEADER START 3*25c28e83SPiotr Jasiukajtis * 4*25c28e83SPiotr Jasiukajtis * The contents of this file are subject to the terms of the 5*25c28e83SPiotr Jasiukajtis * Common Development and Distribution License (the "License"). 6*25c28e83SPiotr Jasiukajtis * You may not use this file except in compliance with the License. 7*25c28e83SPiotr Jasiukajtis * 8*25c28e83SPiotr Jasiukajtis * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*25c28e83SPiotr Jasiukajtis * or http://www.opensolaris.org/os/licensing. 10*25c28e83SPiotr Jasiukajtis * See the License for the specific language governing permissions 11*25c28e83SPiotr Jasiukajtis * and limitations under the License. 12*25c28e83SPiotr Jasiukajtis * 13*25c28e83SPiotr Jasiukajtis * When distributing Covered Code, include this CDDL HEADER in each 14*25c28e83SPiotr Jasiukajtis * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*25c28e83SPiotr Jasiukajtis * If applicable, add the following below this CDDL HEADER, with the 16*25c28e83SPiotr Jasiukajtis * fields enclosed by brackets "[]" replaced with your own identifying 17*25c28e83SPiotr Jasiukajtis * information: Portions Copyright [yyyy] [name of copyright owner] 18*25c28e83SPiotr Jasiukajtis * 19*25c28e83SPiotr Jasiukajtis * CDDL HEADER END 20*25c28e83SPiotr Jasiukajtis */ 21*25c28e83SPiotr Jasiukajtis 22*25c28e83SPiotr Jasiukajtis /* 23*25c28e83SPiotr Jasiukajtis * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 24*25c28e83SPiotr Jasiukajtis */ 25*25c28e83SPiotr Jasiukajtis /* 26*25c28e83SPiotr Jasiukajtis * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 27*25c28e83SPiotr Jasiukajtis * Use is subject to license terms. 28*25c28e83SPiotr Jasiukajtis */ 29*25c28e83SPiotr Jasiukajtis 30*25c28e83SPiotr Jasiukajtis #pragma weak modfl = __modfl 31*25c28e83SPiotr Jasiukajtis 32*25c28e83SPiotr Jasiukajtis #include "libm.h" 33*25c28e83SPiotr Jasiukajtis 34*25c28e83SPiotr Jasiukajtis #if defined(__sparc) 35*25c28e83SPiotr Jasiukajtis 36*25c28e83SPiotr Jasiukajtis long double 37*25c28e83SPiotr Jasiukajtis __modfl(long double x, long double *iptr) { 38*25c28e83SPiotr Jasiukajtis union { 39*25c28e83SPiotr Jasiukajtis unsigned i[4]; 40*25c28e83SPiotr Jasiukajtis long double q; 41*25c28e83SPiotr Jasiukajtis } xx, yy; 42*25c28e83SPiotr Jasiukajtis unsigned hx, s; 43*25c28e83SPiotr Jasiukajtis 44*25c28e83SPiotr Jasiukajtis xx.q = x; 45*25c28e83SPiotr Jasiukajtis hx = xx.i[0] & ~0x80000000; 46*25c28e83SPiotr Jasiukajtis 47*25c28e83SPiotr Jasiukajtis if (hx >= 0x406f0000) { /* x is NaN, infinite, or integral */ 48*25c28e83SPiotr Jasiukajtis *iptr = x; 49*25c28e83SPiotr Jasiukajtis if (hx < 0x7fff0000 || (hx == 0x7fff0000 && 50*25c28e83SPiotr Jasiukajtis (xx.i[1] | xx.i[2] | xx.i[3]) == 0)) { 51*25c28e83SPiotr Jasiukajtis xx.i[0] &= 0x80000000; 52*25c28e83SPiotr Jasiukajtis xx.i[1] = xx.i[2] = xx.i[3] = 0; 53*25c28e83SPiotr Jasiukajtis } 54*25c28e83SPiotr Jasiukajtis return (xx.q); 55*25c28e83SPiotr Jasiukajtis } 56*25c28e83SPiotr Jasiukajtis 57*25c28e83SPiotr Jasiukajtis if (hx < 0x3fff0000) { /* |x| < 1 */ 58*25c28e83SPiotr Jasiukajtis xx.i[0] &= 0x80000000; 59*25c28e83SPiotr Jasiukajtis xx.i[1] = xx.i[2] = xx.i[3] = 0; 60*25c28e83SPiotr Jasiukajtis *iptr = xx.q; 61*25c28e83SPiotr Jasiukajtis return (x); 62*25c28e83SPiotr Jasiukajtis } 63*25c28e83SPiotr Jasiukajtis 64*25c28e83SPiotr Jasiukajtis /* split x at the binary point */ 65*25c28e83SPiotr Jasiukajtis s = xx.i[0] & 0x80000000; 66*25c28e83SPiotr Jasiukajtis if (hx < 0x40100000) { 67*25c28e83SPiotr Jasiukajtis yy.i[0] = xx.i[0] & ~((1 << (0x400f - (hx >> 16))) - 1); 68*25c28e83SPiotr Jasiukajtis yy.i[1] = yy.i[2] = yy.i[3] = 0; 69*25c28e83SPiotr Jasiukajtis } else if (hx < 0x40300000) { 70*25c28e83SPiotr Jasiukajtis yy.i[0] = xx.i[0]; 71*25c28e83SPiotr Jasiukajtis yy.i[1] = xx.i[1] & ~((1 << (0x402f - (hx >> 16))) - 1); 72*25c28e83SPiotr Jasiukajtis yy.i[2] = yy.i[3] = 0; 73*25c28e83SPiotr Jasiukajtis } else if (hx < 0x40500000) { 74*25c28e83SPiotr Jasiukajtis yy.i[0] = xx.i[0]; 75*25c28e83SPiotr Jasiukajtis yy.i[1] = xx.i[1]; 76*25c28e83SPiotr Jasiukajtis yy.i[2] = xx.i[2] & ~((1 << (0x404f - (hx >> 16))) - 1); 77*25c28e83SPiotr Jasiukajtis yy.i[3] = 0; 78*25c28e83SPiotr Jasiukajtis } else { 79*25c28e83SPiotr Jasiukajtis yy.i[0] = xx.i[0]; 80*25c28e83SPiotr Jasiukajtis yy.i[1] = xx.i[1]; 81*25c28e83SPiotr Jasiukajtis yy.i[2] = xx.i[2]; 82*25c28e83SPiotr Jasiukajtis yy.i[3] = xx.i[3] & ~((1 << (0x406f - (hx >> 16))) - 1); 83*25c28e83SPiotr Jasiukajtis } 84*25c28e83SPiotr Jasiukajtis *iptr = yy.q; 85*25c28e83SPiotr Jasiukajtis 86*25c28e83SPiotr Jasiukajtis /* 87*25c28e83SPiotr Jasiukajtis * we could implement the following more efficiently than by using 88*25c28e83SPiotr Jasiukajtis * software emulation of fsubq, but we'll do it this way for now 89*25c28e83SPiotr Jasiukajtis * (and hope hardware support becomes commonplace) 90*25c28e83SPiotr Jasiukajtis */ 91*25c28e83SPiotr Jasiukajtis xx.q -= yy.q; 92*25c28e83SPiotr Jasiukajtis xx.i[0] = (xx.i[0] & ~0x80000000) | s; /* keep sign of x */ 93*25c28e83SPiotr Jasiukajtis return (xx.q); 94*25c28e83SPiotr Jasiukajtis } 95*25c28e83SPiotr Jasiukajtis 96*25c28e83SPiotr Jasiukajtis #elif defined(__x86) 97*25c28e83SPiotr Jasiukajtis 98*25c28e83SPiotr Jasiukajtis long double 99*25c28e83SPiotr Jasiukajtis __modfl(long double x, long double *iptr) { 100*25c28e83SPiotr Jasiukajtis union { 101*25c28e83SPiotr Jasiukajtis unsigned i[3]; 102*25c28e83SPiotr Jasiukajtis long double e; 103*25c28e83SPiotr Jasiukajtis } xx, yy; 104*25c28e83SPiotr Jasiukajtis unsigned hx, s; 105*25c28e83SPiotr Jasiukajtis 106*25c28e83SPiotr Jasiukajtis /* 107*25c28e83SPiotr Jasiukajtis * It might be faster to use one of the x86 fpops instead of 108*25c28e83SPiotr Jasiukajtis * the following. 109*25c28e83SPiotr Jasiukajtis */ 110*25c28e83SPiotr Jasiukajtis xx.e = x; 111*25c28e83SPiotr Jasiukajtis hx = xx.i[2] & 0x7fff; 112*25c28e83SPiotr Jasiukajtis 113*25c28e83SPiotr Jasiukajtis if (hx >= 0x403e) { /* x is NaN, infinite, or integral */ 114*25c28e83SPiotr Jasiukajtis *iptr = x; 115*25c28e83SPiotr Jasiukajtis if (hx < 0x7fff || (hx == 0x7fff && 116*25c28e83SPiotr Jasiukajtis ((xx.i[1] << 1) | xx.i[0]) == 0)) { 117*25c28e83SPiotr Jasiukajtis xx.i[2] &= 0x8000; 118*25c28e83SPiotr Jasiukajtis xx.i[1] = xx.i[0] = 0; 119*25c28e83SPiotr Jasiukajtis } 120*25c28e83SPiotr Jasiukajtis return (xx.e); 121*25c28e83SPiotr Jasiukajtis } 122*25c28e83SPiotr Jasiukajtis 123*25c28e83SPiotr Jasiukajtis if (hx < 0x3fff) { /* |x| < 1 */ 124*25c28e83SPiotr Jasiukajtis xx.i[2] &= 0x8000; 125*25c28e83SPiotr Jasiukajtis xx.i[1] = xx.i[0] = 0; 126*25c28e83SPiotr Jasiukajtis *iptr = xx.e; 127*25c28e83SPiotr Jasiukajtis return (x); 128*25c28e83SPiotr Jasiukajtis } 129*25c28e83SPiotr Jasiukajtis 130*25c28e83SPiotr Jasiukajtis /* split x at the binary point */ 131*25c28e83SPiotr Jasiukajtis s = xx.i[2] & 0x8000; 132*25c28e83SPiotr Jasiukajtis yy.i[2] = xx.i[2]; 133*25c28e83SPiotr Jasiukajtis if (hx < 0x401f) { 134*25c28e83SPiotr Jasiukajtis yy.i[1] = xx.i[1] & ~((1 << (0x401e - hx)) - 1); 135*25c28e83SPiotr Jasiukajtis yy.i[0] = 0; 136*25c28e83SPiotr Jasiukajtis } else { 137*25c28e83SPiotr Jasiukajtis yy.i[1] = xx.i[1]; 138*25c28e83SPiotr Jasiukajtis yy.i[0] = xx.i[0] & ~((1 << (0x403e - hx)) - 1); 139*25c28e83SPiotr Jasiukajtis } 140*25c28e83SPiotr Jasiukajtis *iptr = yy.e; 141*25c28e83SPiotr Jasiukajtis xx.e -= yy.e; 142*25c28e83SPiotr Jasiukajtis xx.i[2] = (xx.i[2] & ~0x8000) | s; /* keep sign of x */ 143*25c28e83SPiotr Jasiukajtis return (xx.e); 144*25c28e83SPiotr Jasiukajtis } 145*25c28e83SPiotr Jasiukajtis 146*25c28e83SPiotr Jasiukajtis #else 147*25c28e83SPiotr Jasiukajtis #error Unknown architecture 148*25c28e83SPiotr Jasiukajtis #endif 149