Print this page
11210 libm should be cstyle(1ONBLD) clean


   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  24  */

  25 /*
  26  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  27  * Use is subject to license terms.
  28  */
  29 
  30 #pragma weak __remquo = remquo
  31 
  32 /* INDENT OFF */
  33 /*
  34  * double remquo(double x, double y, int *quo) return remainder(x,y) and an
  35  * integer pointer quo such that *quo = N mod {2**31}, where N is the
  36  * exact integral part of x/y rounded to nearest even.
  37  *
  38  * remquo call internal fmodquo
  39  */
  40 /* INDENT ON */
  41 
  42 #include "libm.h"
  43 #include "libm_protos.h"
  44 #include <math.h>         /* fabs() */
  45 #include <sys/isa_defs.h>
  46 
  47 #if defined(_BIG_ENDIAN)
  48 #define HIWORD  0
  49 #define LOWORD  1
  50 #else
  51 #define HIWORD  1
  52 #define LOWORD  0
  53 #endif
  54 #define __HI(x) ((int *) &x)[HIWORD]
  55 #define __LO(x) ((int *) &x)[LOWORD]
  56 
  57 static const double one = 1.0, Zero[] = {0.0, -0.0};
  58 

  59 static double
  60 fmodquo(double x, double y, int *quo) {

  61         int n, hx, hy, hz, ix, iy, sx, sq, i, m;
  62         unsigned lx, ly, lz;
  63 
  64         hx = __HI(x);           /* high word of x */
  65         lx = __LO(x);           /* low  word of x */
  66         hy = __HI(y);           /* high word of y */
  67         ly = __LO(y);           /* low  word of y */
  68         sx = hx & 0x80000000;       /* sign of x */
  69         sq = (hx ^ hy) & 0x80000000;        /* sign of x/y */
  70         hx ^= sx;               /* |x| */
  71         hy &= 0x7fffffff;   /* |y| */
  72 
  73         /* purge off exception values */
  74         *quo = 0;

  75         if ((hy | ly) == 0 || hx >= 0x7ff00000 ||    /* y=0, or x !finite */
  76             (hy | ((ly | -ly) >> 31)) > 0x7ff00000)    /* or y is NaN */
  77                 return ((x * y) / (x * y));

  78         if (hx <= hy) {
  79                 if (hx < hy || lx < ly)
  80                         return (x);     /* |x|<|y| return x */

  81                 if (lx == ly) {
  82                         *quo = 1 + (sq >> 30);
  83                         /* |x|=|y| return x*0 */
  84                         return (Zero[(unsigned) sx >> 31]);
  85                 }
  86         }
  87 
  88         /* determine ix = ilogb(x) */
  89         if (hx < 0x00100000) {       /* subnormal x */
  90                 if (hx == 0) {
  91                         for (ix = -1043, i = lx; i > 0; i <<= 1)
  92                                 ix -= 1;
  93                 } else {
  94                         for (ix = -1022, i = (hx << 11); i > 0; i <<= 1)
  95                                 ix -= 1;
  96                 }
  97         } else
  98                 ix = (hx >> 20) - 1023;

  99 
 100         /* determine iy = ilogb(y) */
 101         if (hy < 0x00100000) {       /* subnormal y */
 102                 if (hy == 0) {
 103                         for (iy = -1043, i = ly; i > 0; i <<= 1)
 104                                 iy -= 1;
 105                 } else {
 106                         for (iy = -1022, i = (hy << 11); i > 0; i <<= 1)
 107                                 iy -= 1;
 108                 }
 109         } else
 110                 iy = (hy >> 20) - 1023;

 111 
 112         /* set up {hx,lx}, {hy,ly} and align y to x */
 113         if (ix >= -1022)
 114                 hx = 0x00100000 | (0x000fffff & hx);
 115         else {                  /* subnormal x, shift x to normal */
 116                 n = -1022 - ix;

 117                 if (n <= 31) {
 118                         hx = (hx << n) | (lx >> (32 - n));
 119                         lx <<= n;
 120                 } else {
 121                         hx = lx << (n - 32);
 122                         lx = 0;
 123                 }
 124         }
 125         if (iy >= -1022)

 126                 hy = 0x00100000 | (0x000fffff & hy);
 127         else {                  /* subnormal y, shift y to normal */
 128                 n = -1022 - iy;

 129                 if (n <= 31) {
 130                         hy = (hy << n) | (ly >> (32 - n));
 131                         ly <<= n;
 132                 } else {
 133                         hy = ly << (n - 32);
 134                         ly = 0;
 135                 }
 136         }
 137 
 138         /* fix point fmod */
 139         n = ix - iy;
 140         m = 0;

 141         while (n--) {
 142                 hz = hx - hy;
 143                 lz = lx - ly;

 144                 if (lx < ly)
 145                         hz -= 1;

 146                 if (hz < 0) {
 147                         hx = hx + hx + (lx >> 31);
 148                         lx = lx + lx;
 149                 } else {
 150                         m += 1;

 151                         if ((hz | lz) == 0) {   /* return sign(x)*0 */
 152                                 if (n < 31)
 153                                         m <<= 1 + n;
 154                                 else
 155                                         m = 0;

 156                                 m &= 0x7fffffff;
 157                                 *quo = sq >= 0 ? m : -m;
 158                                 return (Zero[(unsigned) sx >> 31]);
 159                         }

 160                         hx = hz + hz + (lz >> 31);
 161                         lx = lz + lz;
 162                 }

 163                 m += m;
 164         }

 165         hz = hx - hy;
 166         lz = lx - ly;

 167         if (lx < ly)
 168                 hz -= 1;

 169         if (hz >= 0) {
 170                 hx = hz;
 171                 lx = lz;
 172                 m += 1;
 173         }

 174         m &= 0x7fffffff;
 175         *quo = sq >= 0 ? m : -m;
 176 
 177         /* convert back to floating value and restore the sign */
 178         if ((hx | lx) == 0) {   /* return sign(x)*0 */
 179                 return (Zero[(unsigned) sx >> 31]);
 180         }
 181         while (hx < 0x00100000) {    /* normalize x */
 182                 hx = hx + hx + (lx >> 31);
 183                 lx = lx + lx;
 184                 iy -= 1;
 185         }

 186         if (iy >= -1022) {   /* normalize output */
 187                 hx = (hx - 0x00100000) | ((iy + 1023) << 20);
 188                 __HI(x) = hx | sx;
 189                 __LO(x) = lx;
 190         } else {                        /* subnormal output */
 191                 n = -1022 - iy;

 192                 if (n <= 20) {
 193                         lx = (lx >> n) | ((unsigned) hx << (32 - n));
 194                         hx >>= n;
 195                 } else if (n <= 31) {
 196                         lx = (hx << (32 - n)) | (lx >> n);
 197                         hx = sx;
 198                 } else {
 199                         lx = hx >> (n - 32);
 200                         hx = sx;
 201                 }

 202                 __HI(x) = hx | sx;
 203                 __LO(x) = lx;
 204                 x *= one;       /* create necessary signal */
 205         }

 206         return (x);             /* exact output */
 207 }
 208 
 209 #define zero    Zero[0]
 210 
 211 double
 212 remquo(double x, double y, int *quo) {

 213         int hx, hy, sx, sq;
 214         double v;
 215         unsigned ly;
 216 
 217         hx = __HI(x);           /* high word of x */
 218         hy = __HI(y);           /* high word of y */
 219         ly = __LO(y);           /* low  word of y */
 220         sx = hx & 0x80000000;       /* sign of x */
 221         sq = (hx ^ hy) & 0x80000000;        /* sign of x/y */
 222         hx ^= sx;               /* |x| */
 223         hy &= 0x7fffffff;   /* |y| */
 224 
 225         /* purge off exception values */
 226         *quo = 0;

 227         if ((hy | ly) == 0 || hx >= 0x7ff00000 ||    /* y=0, or x !finite */
 228             (hy | ((ly | -ly) >> 31)) > 0x7ff00000)    /* or y is NaN */
 229                 return ((x * y) / (x * y));
 230 
 231         y = fabs(y);
 232         x = fabs(x);

 233         if (hy <= 0x7fdfffff) {
 234                 x = fmodquo(x, y + y, quo);
 235                 *quo = ((*quo) & 0x3fffffff) << 1;
 236         }

 237         if (hy < 0x00200000) {
 238                 if (x + x > y) {
 239                         *quo += 1;

 240                         if (x == y)
 241                                 x = zero;
 242                         else
 243                                 x -= y;

 244                         if (x + x >= y) {
 245                                 x -= y;
 246                                 *quo += 1;
 247                         }
 248                 }
 249         } else {
 250                 v = 0.5 * y;

 251                 if (x > v) {
 252                         *quo += 1;

 253                         if (x == y)
 254                                 x = zero;
 255                         else
 256                                 x -= y;

 257                         if (x >= v) {
 258                                 x -= y;
 259                                 *quo += 1;
 260                         }
 261                 }
 262         }

 263         if (sq != 0)
 264                 *quo = -(*quo);

 265         return (sx == 0 ? x : -x);
 266 }


   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  28  * Use is subject to license terms.
  29  */
  30 
  31 #pragma weak __remquo = remquo
  32 
  33 
  34 /*
  35  * double remquo(double x, double y, int *quo) return remainder(x,y) and an
  36  * integer pointer quo such that *quo = N mod {2**31}, where N is the
  37  * exact integral part of x/y rounded to nearest even.
  38  *
  39  * remquo call internal fmodquo
  40  */

  41 
  42 #include "libm.h"
  43 #include "libm_protos.h"
  44 #include <math.h>                 /* fabs() */
  45 #include <sys/isa_defs.h>
  46 
  47 #if defined(_BIG_ENDIAN)
  48 #define HIWORD          0
  49 #define LOWORD          1
  50 #else
  51 #define HIWORD          1
  52 #define LOWORD          0
  53 #endif
  54 #define __HI(x)         ((int *)&x)[HIWORD]
  55 #define __LO(x)         ((int *)&x)[LOWORD]


  56 
  57 static const double one = 1.0, Zero[] = { 0.0, -0.0 };
  58 static double
  59 fmodquo(double x, double y, int *quo)
  60 {
  61         int n, hx, hy, hz, ix, iy, sx, sq, i, m;
  62         unsigned lx, ly, lz;
  63 
  64         hx = __HI(x);                   /* high word of x */
  65         lx = __LO(x);                   /* low  word of x */
  66         hy = __HI(y);                   /* high word of y */
  67         ly = __LO(y);                   /* low  word of y */
  68         sx = hx & 0x80000000;               /* sign of x */
  69         sq = (hx ^ hy) & 0x80000000;        /* sign of x/y */
  70         hx ^= sx;                       /* |x| */
  71         hy &= 0x7fffffff;           /* |y| */
  72 
  73         /* purge off exception values */
  74         *quo = 0;
  75 
  76         if ((hy | ly) == 0 || hx >= 0x7ff00000 ||    /* y=0, or x !finite */
  77             (hy | ((ly | -ly) >> 31)) > 0x7ff00000)    /* or y is NaN */
  78                 return ((x * y) / (x * y));
  79 
  80         if (hx <= hy) {
  81                 if (hx < hy || lx < ly)
  82                         return (x);     /* |x|<|y| return x */
  83 
  84                 if (lx == ly) {
  85                         *quo = 1 + (sq >> 30);
  86                         /* |x|=|y| return x*0 */
  87                         return (Zero[(unsigned)sx >> 31]);
  88                 }
  89         }
  90 
  91         /* determine ix = ilogb(x) */
  92         if (hx < 0x00100000) {               /* subnormal x */
  93                 if (hx == 0) {
  94                         for (ix = -1043, i = lx; i > 0; i <<= 1)
  95                                 ix -= 1;
  96                 } else {
  97                         for (ix = -1022, i = (hx << 11); i > 0; i <<= 1)
  98                                 ix -= 1;
  99                 }
 100         } else {
 101                 ix = (hx >> 20) - 1023;
 102         }
 103 
 104         /* determine iy = ilogb(y) */
 105         if (hy < 0x00100000) {               /* subnormal y */
 106                 if (hy == 0) {
 107                         for (iy = -1043, i = ly; i > 0; i <<= 1)
 108                                 iy -= 1;
 109                 } else {
 110                         for (iy = -1022, i = (hy << 11); i > 0; i <<= 1)
 111                                 iy -= 1;
 112                 }
 113         } else {
 114                 iy = (hy >> 20) - 1023;
 115         }
 116 
 117         /* set up {hx,lx}, {hy,ly} and align y to x */
 118         if (ix >= -1022) {
 119                 hx = 0x00100000 | (0x000fffff & hx);
 120         } else {                        /* subnormal x, shift x to normal */
 121                 n = -1022 - ix;
 122 
 123                 if (n <= 31) {
 124                         hx = (hx << n) | (lx >> (32 - n));
 125                         lx <<= n;
 126                 } else {
 127                         hx = lx << (n - 32);
 128                         lx = 0;
 129                 }
 130         }
 131 
 132         if (iy >= -1022) {
 133                 hy = 0x00100000 | (0x000fffff & hy);
 134         } else {                        /* subnormal y, shift y to normal */
 135                 n = -1022 - iy;
 136 
 137                 if (n <= 31) {
 138                         hy = (hy << n) | (ly >> (32 - n));
 139                         ly <<= n;
 140                 } else {
 141                         hy = ly << (n - 32);
 142                         ly = 0;
 143                 }
 144         }
 145 
 146         /* fix point fmod */
 147         n = ix - iy;
 148         m = 0;
 149 
 150         while (n--) {
 151                 hz = hx - hy;
 152                 lz = lx - ly;
 153 
 154                 if (lx < ly)
 155                         hz -= 1;
 156 
 157                 if (hz < 0) {
 158                         hx = hx + hx + (lx >> 31);
 159                         lx = lx + lx;
 160                 } else {
 161                         m += 1;
 162 
 163                         if ((hz | lz) == 0) {   /* return sign(x)*0 */
 164                                 if (n < 31)
 165                                         m <<= 1 + n;
 166                                 else
 167                                         m = 0;
 168 
 169                                 m &= 0x7fffffff;
 170                                 *quo = sq >= 0 ? m : -m;
 171                                 return (Zero[(unsigned)sx >> 31]);
 172                         }
 173 
 174                         hx = hz + hz + (lz >> 31);
 175                         lx = lz + lz;
 176                 }
 177 
 178                 m += m;
 179         }
 180 
 181         hz = hx - hy;
 182         lz = lx - ly;
 183 
 184         if (lx < ly)
 185                 hz -= 1;
 186 
 187         if (hz >= 0) {
 188                 hx = hz;
 189                 lx = lz;
 190                 m += 1;
 191         }
 192 
 193         m &= 0x7fffffff;
 194         *quo = sq >= 0 ? m : -m;
 195 
 196         /* convert back to floating value and restore the sign */
 197         if ((hx | lx) == 0)             /* return sign(x)*0 */
 198                 return (Zero[(unsigned)sx >> 31]);
 199 
 200         while (hx < 0x00100000) {    /* normalize x */
 201                 hx = hx + hx + (lx >> 31);
 202                 lx = lx + lx;
 203                 iy -= 1;
 204         }
 205 
 206         if (iy >= -1022) {           /* normalize output */
 207                 hx = (hx - 0x00100000) | ((iy + 1023) << 20);
 208                 __HI(x) = hx | sx;
 209                 __LO(x) = lx;
 210         } else {                        /* subnormal output */
 211                 n = -1022 - iy;
 212 
 213                 if (n <= 20) {
 214                         lx = (lx >> n) | ((unsigned)hx << (32 - n));
 215                         hx >>= n;
 216                 } else if (n <= 31) {
 217                         lx = (hx << (32 - n)) | (lx >> n);
 218                         hx = sx;
 219                 } else {
 220                         lx = hx >> (n - 32);
 221                         hx = sx;
 222                 }
 223 
 224                 __HI(x) = hx | sx;
 225                 __LO(x) = lx;
 226                 x *= one;               /* create necessary signal */
 227         }
 228 
 229         return (x);                     /* exact output */
 230 }
 231 
 232 #define zero    Zero[0]
 233 
 234 double
 235 remquo(double x, double y, int *quo)
 236 {
 237         int hx, hy, sx, sq;
 238         double v;
 239         unsigned ly;
 240 
 241         hx = __HI(x);                   /* high word of x */
 242         hy = __HI(y);                   /* high word of y */
 243         ly = __LO(y);                   /* low  word of y */
 244         sx = hx & 0x80000000;               /* sign of x */
 245         sq = (hx ^ hy) & 0x80000000;        /* sign of x/y */
 246         hx ^= sx;                       /* |x| */
 247         hy &= 0x7fffffff;           /* |y| */
 248 
 249         /* purge off exception values */
 250         *quo = 0;
 251 
 252         if ((hy | ly) == 0 || hx >= 0x7ff00000 ||    /* y=0, or x !finite */
 253             (hy | ((ly | -ly) >> 31)) > 0x7ff00000)    /* or y is NaN */
 254                 return ((x * y) / (x * y));
 255 
 256         y = fabs(y);
 257         x = fabs(x);
 258 
 259         if (hy <= 0x7fdfffff) {
 260                 x = fmodquo(x, y + y, quo);
 261                 *quo = ((*quo) & 0x3fffffff) << 1;
 262         }
 263 
 264         if (hy < 0x00200000) {
 265                 if (x + x > y) {
 266                         *quo += 1;
 267 
 268                         if (x == y)
 269                                 x = zero;
 270                         else
 271                                 x -= y;
 272 
 273                         if (x + x >= y) {
 274                                 x -= y;
 275                                 *quo += 1;
 276                         }
 277                 }
 278         } else {
 279                 v = 0.5 * y;
 280 
 281                 if (x > v) {
 282                         *quo += 1;
 283 
 284                         if (x == y)
 285                                 x = zero;
 286                         else
 287                                 x -= y;
 288 
 289                         if (x >= v) {
 290                                 x -= y;
 291                                 *quo += 1;
 292                         }
 293                 }
 294         }
 295 
 296         if (sq != 0)
 297                 *quo = -(*quo);
 298 
 299         return (sx == 0 ? x : -x);
 300 }