rts-math.c

     
   1  //! @file rts-math.c
   2  //! @author J. Marcel van der Veer
   3  //
   4  //! @section Copyright
   5  //
   6  // This file is part of VIF - vintage FORTRAN compiler.
   7  // Copyright 2020-2024 J. Marcel van der Veer <algol68g@xs4all.nl>.
   8  //
   9  //! @section License
  10  //
  11  // This program is free software; you can redistribute it and/or modify it 
  12  // under the terms of the GNU General Public License as published by the 
  13  // Free Software Foundation; either version 3 of the License, or 
  14  // (at your option) any later version.
  15  //
  16  // This program is distributed in the hope that it will be useful, but 
  17  // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  18  // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
  19  // more details. You should have received a copy of the GNU General Public 
  20  // License along with this program. If not, see <http://www.gnu.org/licenses/>.
  21  
  22  //! @section Synopsis
  23  //!
  24  //! Runtime support for math operations.
  25  
  26  #include <vif.h>
  27  
  28  // INTEGER*4
  29  
  30  int_4 _up_int_4 (int_4 m, int_4 n)
  31  {
  32  // Special cases.
  33    if (m == 2 && n >= 0) {
  34      return 1 << n;
  35    } else if (m == 1) {
  36      return m;
  37    } else if (m == -1) {
  38      return (n % 2 == 0 ? 1 : -1);
  39    } else if (m == 0) {
  40      return (n == 0 ? 1 : 0);
  41    } else if (n < 0) {
  42      return 0;
  43    }
  44  // General case.
  45    unsigned bit = 1;
  46    int_4 M = m, P = 1;
  47    do {
  48      if (n & bit) {
  49        P *= M;
  50      }
  51      bit <<= 1;
  52      if ((int_4) bit <= n) {
  53        M *= M;
  54      }
  55    } while ((int_4) bit <= n);
  56    return P;
  57  }
  58  
  59  // INTEGER*8
  60  
  61  int_8 _up_int_8 (int_8 m, int_4 n)
  62  {
  63  // Special cases.
  64    if (m == 2 && n >= 0) {
  65      int_8 s = 1;
  66      s <<= n;
  67      return s;
  68    } else if (m == 1) {
  69      return m;
  70    } else if (m == -1) {
  71      return (n % 2 == 0 ? 1 : -1);
  72    } else if (m == 0) {
  73      return (n == 0 ? 1 : 0);
  74    } else if (n < 0) {
  75      return 0;
  76    }
  77  // General case.
  78    unsigned bit = 1;
  79    int_8 M = m, P = 1;
  80    do {
  81      if (n & bit) {
  82        P *= M;
  83      }
  84      bit <<= 1;
  85      if ((int_4) bit <= n) {
  86        M *= M;
  87      }
  88    } while ((int_4) bit <= n);
  89    return P;
  90  }
  91  
  92  // REAL*4
  93  
  94  real_4 _aint (real_4 x)
  95  {
  96    return (x >= 0 ? floorf (x) : - floorf (- x));
  97  }
  98  
  99  real_4 _anint (real_4 x)
 100  {
 101    return (x >= 0 ? floorf (0.5 + x) : - floorf (0.5 - x));
 102  }
 103  
 104  real_4 _up_real_4 (real_4 x, int_4 n)
 105  {
 106  // Only positive n.
 107    if (n < 0) {
 108      return 1 / _up_real_4 (x, -n);
 109    }
 110  // Special cases.
 111    if (x == 0 || x == 1) {
 112      return x;
 113    } else if (x == -1) {
 114      return (n % 2 == 0 ? 1 : -1);
 115    }
 116  // General case.
 117    unsigned bit = 1;
 118    real_4 M = x, P = 1;
 119    do {
 120      if (n & bit) {
 121        P *= M;
 122      }
 123      bit <<= 1;
 124      if ((int_4) bit <= n) {
 125        M *= M;
 126      }
 127    } while ((int_4) bit <= n);
 128    return P;
 129  }
 130  
 131  real_4 cotanf (real_4 x)
 132  {
 133    return 1.0 / tanf (x);
 134  }
 135  
 136  // REAL*8
 137  
 138  real_8 _dint (real_8 x)
 139  {
 140    return (x >= 0 ? floor (x) : - floor (- x));
 141  }
 142  
 143  real_8 _dnint (real_8 x)
 144  {
 145    return (x >= 0 ? floor (0.5 + x) : - floor (0.5 - x));
 146  }
 147  
 148  real_8 _up_real_8 (real_8 x, int_4 n)
 149  {
 150  // Only positive n.
 151    if (n < 0) {
 152      return 1 / _up_real_8 (x, -n);
 153    }
 154  // Special cases.
 155    if (x == 0 || x == 1) {
 156      return x;
 157    } else if (x == -1) {
 158      return (n % 2 == 0 ? 1 : -1);
 159    }
 160  // General case.
 161    unsigned bit = 1;
 162    real_8 M = x, P = 1;
 163    do {
 164      if (n & bit) {
 165        P *= M;
 166      }
 167      bit <<= 1;
 168      if ((int_4) bit <= n) {
 169        M *= M;
 170      }
 171    } while ((int_4) bit <= n);
 172    return P;
 173  }
 174  
 175  real_8 cotan (real_8 x)
 176  {
 177    return 1.0 / tan (x);
 178  }
 179  
 180  real_8 _vif_inverfc (real_8 y)
 181  {
 182  #define N_c_inverfc 34
 183  
 184    static const real_8 c_inverfc[N_c_inverfc] = {
 185      0.91646139826896400000,
 186      0.48882664027310800000,
 187      0.23172920032340500000,
 188      0.12461045461371200000,
 189      -0.07288467655856750000,
 190      0.26999930867002900000,
 191      0.15068904736022300000,
 192      0.11606502534161400000,
 193      0.49999930343979000000,
 194      3.97886080735226000000,
 195      0.00112648096188977922,
 196      1.05739299623423047e-4,
 197      0.00351287146129100025,
 198      7.71708358954120939e-4,
 199      0.00685649426074558612,
 200      0.00339721910367775861,
 201      0.01127491693325048700,
 202      0.01185981170477711040,
 203      0.01429619886978980180,
 204      0.03464942077890999220,
 205      0.00220995927012179067,
 206      0.07434243572417848610,
 207      0.10587217794159548800,
 208      0.01472979383314851210,
 209      0.31684763852013594400,
 210      0.71365763586873036400,
 211      1.05375024970847138000,
 212      1.21448730779995237000,
 213      1.16374581931560831000,
 214      0.95646497474479900600,
 215      0.68626594827409781600,
 216      0.43439749233143011500,
 217      0.24404451059319093500,
 218      0.12078223763524522200
 219    };
 220  
 221    if (y < 0 || y > 2) {
 222      errno = ERANGE;
 223      return 0;
 224    }
 225    if (y == 0) {
 226      return DBL_MAX;
 227    } else if (y == 1) {
 228      return 0;
 229    } else if (y == 2) {
 230      return -DBL_MAX;
 231    } else {
 232  // Next is based on code that originally contained following statement:
 233  //   Copyright (c) 1996 Takuya Ooura. You may use, copy, modify this 
 234  //   code for any purpose and without fee.
 235      real_8 s, t, u, v, x, z;
 236      z = (y <= 1 ? y : 2 - y);
 237      v = c_inverfc[0] - ln (z);
 238      u = sqrt (v);
 239      s = (ln (u) + c_inverfc[1]) / v;
 240      t = 1 / (u + c_inverfc[2]);
 241      x = u *(1 - s *(s *c_inverfc[3] + 0.5)) - ((((c_inverfc[4] *t + c_inverfc[5]) *t + c_inverfc[6]) *t + c_inverfc[7]) *t + c_inverfc[8]) *t;
 242      t = c_inverfc[9] / (x + c_inverfc[9]);
 243      u = t - 0.5;
 244      s = (((((((((c_inverfc[10] *u + c_inverfc[11]) *u - c_inverfc[12]) *u - c_inverfc[13]) *u + c_inverfc[14]) *u + c_inverfc[15]) *u - c_inverfc[16]) *u - c_inverfc[17]) *u + c_inverfc[18]) *u + c_inverfc[19]) *u + c_inverfc[20];
 245      s = ((((((((((((s *u - c_inverfc[21]) *u - c_inverfc[22]) *u + c_inverfc[23]) *u + c_inverfc[24]) *u + c_inverfc[25]) *u + c_inverfc[26]) *u + c_inverfc[27]) *u + c_inverfc[28]) *u + c_inverfc[29]) *u + c_inverfc[30]) *u + c_inverfc[31]) *u + c_inverfc[32]) *t - z *exp (x *x - c_inverfc[33]);
 246      x += s *(x *s + 1);
 247      return (y <= 1 ? x : -x);
 248    }
 249  }
 250  
 251  real_8 _vif_inverf (real_8 y)
 252  {
 253    return _vif_inverfc (1 - y);
 254  }
 255  
 256  void _merfi (real_8 *p, real_8 *x, int_4 *err)
 257  {
 258    (*x) = _vif_inverf (*p);
 259    (*err) = errno;
 260  }
 261  
 262  // REAL*16
 263  
 264  real_16 _qint (real_16 x)
 265  {
 266    return (x >= 0 ? floorq (x) : - floorq (- x));
 267  }
 268  
 269  real_16 _qext (real_8 x)
 270  {
 271    RECORD str;
 272    _srecordf (str, "%.*le", DBL_DIG, x);
 273    return _strtoquad (str, NULL);
 274  }
 275  
 276  real_16 _qmod (real_16 x, real_16 y)
 277  {
 278    real_16 q;
 279    if ((q = x / y) >= 0) {
 280      q = floorq (q);
 281    } else {
 282      q = -floorq (-q);
 283    }
 284    return (x - y *q);
 285  }
 286  
 287  real_16 _up_real_16 (real_16 x, int_4 n)
 288  {
 289  // Only positive n.
 290    if (n < 0) {
 291      return 1.0q / _up_real_16 (x, -n);
 292    }
 293  // Special cases.
 294    if (x == 0.0q || x == 1.0q) {
 295      return x;
 296    } else if (x == -1.0q) {
 297      return (n % 2 == 0 ? 1.0q : -1.0q);
 298    }
 299  // General case.
 300    unsigned bit = 1;
 301    real_16 M = x, P = 1.0q;
 302    do {
 303      if (n & bit) {
 304        P *= M;
 305      }
 306      bit <<= 1;
 307      if ((int_4) bit <= n) {
 308        M *= M;
 309      }
 310    } while ((int_4) bit <= n);
 311    return P;
 312  }
 313  
 314  real_16 cotanq (real_16 x)
 315  {
 316    return 1.0q / tanq (x);
 317  }
 318  
 319  // COMPLEX*8
 320  
 321  complex_8 _cmplxd (complex_16 z)
 322  {
 323    return CMPLXF ((real_4) creal (z), (real_4) cimag (z));
 324  }
 325  
 326  complex_8 _up_complex_8 (complex_8 x, int_4 n)
 327  {
 328  // Only positive n.
 329    if (n < 0) {
 330      return 1 / _up_complex (x, -n);
 331    }
 332  // General case.
 333    unsigned bit = 1;
 334    complex_8 M = x, P = 1;
 335    do {
 336      if (n & bit) {
 337        P *= M;
 338      }
 339      bit <<= 1;
 340      if ((int_4) bit <= n) {
 341        M *= M;
 342      }
 343    } while ((int_4) bit <= n);
 344    return P;
 345  }
 346  
 347  // COMPLEX*16
 348  
 349  complex_16 _dcmplxq (complex_32 z)
 350  {
 351    return CMPLX (crealq (z), cimagq (z));
 352  }
 353  
 354  complex_16 _up_complex (complex_16 x, int_4 n)
 355  {
 356  // Only positive n.
 357    if (n < 0) {
 358      return 1 / _up_complex (x, -n);
 359    }
 360  // General case.
 361    unsigned bit = 1;
 362    complex_16 M = x, P = 1;
 363    do {
 364      if (n & bit) {
 365        P *= M;
 366      }
 367      bit <<= 1;
 368      if ((int_4) bit <= n) {
 369        M *= M;
 370      }
 371    } while ((int_4) bit <= n);
 372    return P;
 373  }
 374  
 375  // COMPLEX*32
 376  
 377  complex_32 _qcmplxd (complex_16 z)
 378  {
 379    return CMPLXQ (_qext (creal (z)), _qext (cimag (z)));
 380  }
 381  
 382  complex_32 _up_complex_32 (complex_32 x, int_4 n)
 383  {
 384  // Only positive n.
 385    if (n < 0) {
 386      return 1.0q / _up_complex_32 (x, -n);
 387    }
 388  // General case.
 389    unsigned bit = 1;
 390    complex_32 M = x, P = 1.0q;
 391    do {
 392      if (n & bit) {
 393        P *= M;
 394      }
 395      bit <<= 1;
 396      if ((int_4) bit <= n) {
 397        M *= M;
 398      }
 399    } while ((int_4) bit <= n);
 400    return P;
 401  }
 402  
 403  real_4 _zabs_8 (real_4 re, real_4 im)
 404  {
 405    return cabsf (CMPLXF (re, im));
 406  }
 407  
 408  real_8 _zabs_16 (real_8 re, real_8 im)
 409  {
 410    return cabs (CMPLX (re, im));
 411  }
 412  
 413  real_16 _zabs_32 (real_16 re, real_16 im)
 414  {
 415    return cabsq (CMPLXQ (re, im));
 416  }
 417  
 418  void _qhex (real_16 *u)
 419  {
 420    unt_2 *p = (unt_2 *) u;
 421    fprintf (stdout, "{");
 422    for (int_4 i = 0; i <= FLT128_LEN; i++) {
 423      fprintf (stdout, "0x%04x", *(p++));
 424      if (i < FLT128_LEN) {
 425        fprintf (stdout, ", ");
 426      }
 427    }
 428    fprintf (stdout, "}\n");
 429  }
 430  
 431  void _xhex (real_32 *u)
 432  {
 433    fprintf (stdout, "{");
 434    for (int_4 i = 0; i <= FLT256_LEN; i++) {
 435      fprintf (stdout, "0x%04x", u->value[i]);
 436      if (i < FLT256_LEN) {
 437        fprintf (stdout, ", ");
 438      }
 439    }
 440    fprintf (stdout, "}\n");
 441  }
 442  
 443  int_4 _int4 (char *str)
 444  {
 445    int_4 sum = 0, fact = 1, len = strlen (str);
 446    for (int_4 k = 0; k < 4 && k < len; k++) {
 447      sum += fact * (int_4) str[k];
 448      fact <<= 8;
 449    }
 450    return sum;
 451  }
 452  
 453  //
 454  
 455  void _pi4 (real_4 * x)
 456  {
 457    *x = (real_4) M_PI;
 458  }
 459  
 460  void _pi8 (real_8 * x)
 461  {
 462    *x = M_PI;
 463  }
 464  
 465  void _pi16 (real_16 * x)
 466  {
 467    *x = M_PIq;
 468  }
     


© 2002-2024 J.M. van der Veer (jmvdveer@xs4all.nl)