x68/_dtos18.c


DEFINITIONS

This source file includes following functions.
  1. _cmpd
  2. _dtos18


   1  /*
   2   * PROJECT C Library, X68000 PROGRAMMING INTERFACE DEFINITION
   3   * --------------------------------------------------------------------
   4   * This file is written by the Project C Library Group,  and completely
   5   * in public domain. You can freely use, copy, modify, and redistribute
   6   * the whole contents, without this notice.
   7   * --------------------------------------------------------------------
   8   * $Id: _dtos18.c,v 1.1.1.2 1999/01/20 04:59:39 matz Exp $
   9   */
  10  
  11  /* System headers */
  12  #include <stdlib.h>
  13  #include <sys/xstdlib.h>
  14  
  15  /*
  16  ** 本関数は浮動小数点を倍精度整数に変換してから文字列にするため、精度的には
  17  ** 倍精度整数に格納できる桁数までしか扱うことができない。したがって最高精度
  18  ** は18桁である。
  19  */
  20  
  21  /* File scope variables */
  22  static double _pos1[32] = {
  23      1.0e+17,                                    /* + 0 */
  24      1.0e+18,                                    /* + 1 */
  25      1.0e+19,                                    /* + 2 */
  26      1.0e+20,                                    /* + 3 */
  27      1.0e+21,                                    /* + 4 */
  28      1.0e+22,                                    /* + 5 */
  29      1.0e+23,                                    /* + 6 */
  30      1.0e+24,                                    /* + 7 */
  31      1.0e+25,                                    /* + 8 */
  32      1.0e+26,                                    /* + 9 */
  33      1.0e+27,                                    /* +10 */
  34      1.0e+28,                                    /* +11 */
  35      1.0e+29,                                    /* +12 */
  36      1.0e+30,                                    /* +13 */
  37      1.0e+31,                                    /* +14 */
  38      1.0e+32,                                    /* +15 */
  39      1.0e+33,                                    /* +16 */
  40      1.0e+34,                                    /* +17 */
  41      1.0e+35,                                    /* +18 */
  42      1.0e+36,                                    /* +19 */
  43      1.0e+37,                                    /* +20 */
  44      1.0e+38,                                    /* +21 */
  45      1.0e+39,                                    /* +22 */
  46      1.0e+40,                                    /* +23 */
  47      1.0e+41,                                    /* +24 */
  48      1.0e+42,                                    /* +25 */
  49      1.0e+43,                                    /* +26 */
  50      1.0e+44,                                    /* +27 */
  51      1.0e+45,                                    /* +28 */
  52      1.0e+46,                                    /* +29 */
  53      1.0e+47,                                    /* +30 */
  54      1.0e+48,                                    /* +31 */
  55  };
  56  
  57  /* File scope variables */
  58  static double _neg1[32] = {
  59      1.0e+17,                                    /* - 0 */
  60      1.0e+16,                                    /* - 1 */
  61      1.0e+15,                                    /* - 2 */
  62      1.0e+14,                                    /* - 3 */
  63      1.0e+13,                                    /* - 4 */
  64      1.0e+12,                                    /* - 5 */
  65      1.0e+11,                                    /* - 6 */
  66      1.0e+10,                                    /* - 7 */
  67      1.0e+9,                                     /* - 8 */
  68      1.0e+8,                                     /* - 9 */
  69      1.0e+7,                                     /* -10 */
  70      1.0e+6,                                     /* -11 */
  71      1.0e+5,                                     /* -12 */
  72      1.0e+4,                                     /* -13 */
  73      1.0e+3,                                     /* -14 */
  74      1.0e+2,                                     /* -15 */
  75      1.0e+1,                                     /* -16 */
  76      1.0e+0,                                     /* -17 */
  77      1.0e-1,                                     /* -18 */
  78      1.0e-2,                                     /* -19 */
  79      1.0e-3,                                     /* -20 */
  80      1.0e-4,                                     /* -21 */
  81      1.0e-5,                                     /* -22 */
  82      1.0e-6,                                     /* -23 */
  83      1.0e-7,                                     /* -24 */
  84      1.0e-8,                                     /* -25 */
  85      1.0e-9,                                     /* -26 */
  86      1.0e-10,                                    /* -27 */
  87      1.0e-11,                                    /* -28 */
  88      1.0e-12,                                    /* -29 */
  89      1.0e-13,                                    /* -30 */
  90      1.0e-14,                                    /* -31 */
  91  };
  92  
  93  /* File scope variables */
  94  static double _pos2[10] = {
  95      1.0e+0,                                     /* 000 */
  96      1.0e+32,                                    /* 001 */
  97      1.0e+64,                                    /* 010 */
  98      1.0e+96,                                    /* 011 */
  99      1.0e+128,                                   /* 100 */
 100      1.0e+160,                                   /* 101 */
 101      1.0e+192,                                   /* 110 */
 102      1.0e+224,                                   /* 111 */
 103      1.0e+256,                                   /* 1000 */
 104      1.0e+288,                                   /* 1001 */
 105  };
 106  
 107  /* File scope variables */
 108  static double _neg2[10] = {
 109      1.0e-0,                                     /* 000 */
 110      1.0e-32,                                    /* 001 */
 111      1.0e-64,                                    /* 010 */
 112      1.0e-96,                                    /* 011 */
 113      1.0e-128,                                   /* 100 */
 114      1.0e-160,                                   /* 101 */
 115      1.0e-192,                                   /* 110 */
 116      1.0e-224,                                   /* 111 */
 117      1.0e-256,                                   /* 1000 */
 118      1.0e-288,                                   /* 1001 */
 119  };
 120  
 121  /* File scope functions */
 122  static int _cmpd (double x, double y)
 123  {
 124      unsigned long vx, vy, rc;
 125      unsigned long *x_ptr = (unsigned long *) &x;
 126      unsigned long *y_ptr = (unsigned long *) &y;
 127  
 128      /* xの指数ビットを取り出す */
 129      vx = x_ptr[0] & 0x7FF00000;
 130  
 131      /* yの指数ビットを取り出す */
 132      vy = y_ptr[0] & 0x7FF00000;
 133  
 134      /* 指数ビットだけで判断する */
 135      if ((rc = vy - vx) != 0)
 136          return rc;
 137  
 138      /* xの有効数字の上位ビットを取り出す */
 139      vx = x_ptr[0] & 0x000FFFFF;
 140  
 141      /* yの有効数字の上位ビットを取り出す */
 142      vy = y_ptr[0] & 0x000FFFFF;
 143  
 144      /* 上位ビットだけで判断する */
 145      if ((rc = vy - vx) != 0)
 146          return rc;
 147  
 148      /* xの有効数字の下位ビットを取り出す */
 149      vx = x_ptr[1];
 150  
 151      /* yの有効数字の下位ビットを取り出す */
 152      vy = y_ptr[1];
 153  
 154      /* 最終判断 */
 155      return vy - vx;
 156  }
 157  
 158  /* Functions */
 159  void _dtos18 (double x, int *decpt, int *sign, char *buffer)
 160  {
 161      short e2;
 162      int e, n;
 163  
 164      /* 基数2の指数を求める(バイアスなしの状態) */
 165      e2 = (((unsigned short *) &x)[0] & 0x7FF0U) >> 4;
 166  
 167      /* 指数が0の場合は±0.0チェック */
 168      if (e2 == 0) {
 169  
 170          unsigned long hi = ((unsigned long *) &x)[0] & 0xFFFFF;
 171          unsigned long lo = ((unsigned long *) &x)[1];
 172  
 173          /* 有効数字が全部0かどうか */
 174          if (hi == 0 && lo == 0) {
 175  
 176              /* 文字列を設定 */
 177              buffer[0] = '0';
 178  
 179              /* NULを設定 */
 180              buffer[1] = '\0';
 181  
 182              /* 小数点位置を計算 */
 183              *decpt = 1;
 184  
 185              /* 符号を計算 */
 186              /* *sign = hi & 0x80000000UL; */
 187              *sign = 0;
 188  
 189              /* 確定 */
 190              return;
 191  
 192          }
 193  
 194      }
 195  
 196      /* 2の指数にバイアスをかけてから10の指数を概算 (approx. log10(2)) */
 197      e = ((int) ((e2 - 1023) * 77)) >> 8;
 198  
 199      /* 指数が正の場合 */
 200      if (e >= 0) {
 201  
 202          /* 指数が32より小さい場合はテーブル1から */
 203          if (e < 32)
 204              x *= _neg1[e];
 205  
 206          /* 指数が32より大きい場合はテーブル1,2から */
 207          else
 208              x *= _neg1[e & 31] * _neg2[e >> 5];
 209  
 210      }
 211  
 212      /* 指数が負の場合 */
 213      else {
 214  
 215          /* 絶対値を計算 */
 216          n = -e;
 217  
 218          /* 絶対値が32より小さい場合はテーブル1から */
 219          if (n < 32)
 220              x *= _pos1[n];
 221  
 222          /* 絶対値が32より大きい場合はテーブル1,2から */
 223          else {
 224              x *= _pos1[n & 31];
 225              x *= _pos2[n >> 5];
 226          }
 227  
 228      }
 229  
 230      /* スケーリングしすぎた場合は戻す */
 231      if (_cmpd (1.0e+18, x) >= 0) {
 232          e++;
 233          x *= 1.0e-1;
 234      }
 235  
 236      /* スケーリングし足りない場合は追加 */
 237      else if (_cmpd (1.0e+17, x) < 0) {
 238          e--;
 239          x *= 1.0e+1;
 240      }
 241  
 242      /* 小数点位置を計算 */
 243      *decpt = e + 1;
 244  
 245      /* 符号を計算 */
 246      *sign = ((unsigned char *) &x)[0] & 0x80U;
 247  
 248      /* 文字列に変換 */
 249      _ulltoa ((unsigned long long) x, buffer);
 250  }