single.c

     
   1  //! @file single.c
   2  //! @author J. Marcel van der Veer
   3  
   4  //! @section Copyright
   5  //! This file is part of Algol68G - an Algol 68 compiler-interpreter.
   6  //! Copyright 2001-2026 J. Marcel van der Veer [algol68g@xs4all.nl].
   7  //!
   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  //! INT, REAL, COMPLEX and BITS routines.
  25  
  26  #include "a68g.h"
  27  #include "a68g-genie.h"
  28  #include "a68g-prelude.h"
  29  #include "a68g-double.h"
  30  #include "a68g-numbers.h"
  31  #include "a68g-stddef.h"
  32  
  33  // INT operations.
  34  
  35  // OP - = (INT) INT.
  36  
  37  A68G_MONAD (genie_minus_int, A68G_INT, -);
  38  
  39  // OP ABS = (INT) INT
  40  
  41  void genie_abs_int (NODE_T * p)
  42  {
  43    A68G_INT *j;
  44    POP_OPERAND_ADDRESS (p, j, A68G_INT);
  45    VALUE (j) = ABS (VALUE (j));
  46  }
  47  
  48  // OP SIGN = (INT) INT
  49  
  50  void genie_sign_int (NODE_T * p)
  51  {
  52    A68G_INT *j;
  53    POP_OPERAND_ADDRESS (p, j, A68G_INT);
  54    VALUE (j) = SIGN (VALUE (j));
  55  }
  56  
  57  // OP ODD = (INT) BOOL
  58  
  59  void genie_odd_int (NODE_T * p)
  60  {
  61    A68G_INT j;
  62    POP_OBJECT (p, &j, A68G_INT);
  63    PUSH_VALUE (p, (BOOL_T) ((VALUE (&j) >= 0 ? VALUE (&j) : -VALUE (&j)) % 2 == 1), A68G_BOOL);
  64  }
  65  
  66  // OP + = (INT, INT) INT
  67  
  68  void genie_add_int (NODE_T * p)
  69  {
  70    A68G_INT *i, *j;
  71    POP_OPERAND_ADDRESSES (p, i, j, A68G_INT);
  72    errno = 0;
  73    VALUE (i) = a68g_add_int (VALUE (i), VALUE (j));
  74    MATH_RTE (p, errno != 0, M_INT, "M overflow");
  75  }
  76  
  77  // OP - = (INT, INT) INT
  78  
  79  void genie_sub_int (NODE_T * p)
  80  {
  81    A68G_INT *i, *j;
  82    POP_OPERAND_ADDRESSES (p, i, j, A68G_INT);
  83    errno = 0;
  84    VALUE (i) = a68g_sub_int (VALUE (i), VALUE (j));
  85    MATH_RTE (p, errno != 0, M_INT, "M overflow");
  86  }
  87  
  88  // OP * = (INT, INT) INT
  89  
  90  void genie_mul_int (NODE_T * p)
  91  {
  92    A68G_INT *i, *j;
  93    POP_OPERAND_ADDRESSES (p, i, j, A68G_INT);
  94    errno = 0;
  95    VALUE (i) = a68g_mul_int (VALUE (i), VALUE (j));
  96    MATH_RTE (p, errno != 0, M_INT, "M overflow");
  97  }
  98  
  99  // OP OVER = (INT, INT) INT
 100  
 101  void genie_over_int (NODE_T * p)
 102  {
 103    A68G_INT *i, *j;
 104    POP_OPERAND_ADDRESSES (p, i, j, A68G_INT);
 105    errno = 0;
 106    VALUE (i) = a68g_over_int (VALUE (i), VALUE (j));
 107    MATH_RTE (p, errno != 0, M_INT, ERROR_DIVISION_BY_ZERO);
 108  }
 109  
 110  // OP MOD = (INT, INT) INT
 111  
 112  void genie_mod_int (NODE_T * p)
 113  {
 114    A68G_INT *i, *j;
 115    POP_OPERAND_ADDRESSES (p, i, j, A68G_INT);
 116    errno = 0;
 117    VALUE (i) = a68g_mod_int (VALUE (i), VALUE (j));
 118    MATH_RTE (p, errno != 0, M_INT, ERROR_DIVISION_BY_ZERO);
 119  }
 120  
 121  // OP / = (INT, INT) REAL
 122  
 123  void genie_div_int (NODE_T * p)
 124  {
 125    A68G_INT i, j;
 126    POP_OBJECT (p, &j, A68G_INT);
 127    POP_OBJECT (p, &i, A68G_INT);
 128    errno = 0;
 129    PUSH_VALUE (p, a68g_div_int (VALUE (&i), VALUE (&j)), A68G_REAL);
 130    MATH_RTE (p, errno != 0, M_INT, "M division by zero");
 131  }
 132  
 133  // OP ** = (INT, INT) INT
 134  
 135  void genie_pow_int (NODE_T * p)
 136  {
 137    A68G_INT i, j;
 138    POP_OBJECT (p, &j, A68G_INT);
 139    PRELUDE_ERROR (VALUE (&j) < 0, p, ERROR_EXPONENT_INVALID, M_INT);
 140    POP_OBJECT (p, &i, A68G_INT);
 141    errno = 0;
 142    PUSH_VALUE (p, a68g_m_up_n (VALUE (&i), VALUE (&j)), A68G_INT);
 143    MATH_RTE (p, errno != 0, M_INT, "M overflow");
 144  }
 145  
 146  // OP (INT, INT) BOOL.
 147  
 148  #define A68G_CMP_INT(n, OP)\
 149  void n (NODE_T * p) {\
 150    A68G_INT i, j;\
 151    POP_OBJECT (p, &j, A68G_INT);\
 152    POP_OBJECT (p, &i, A68G_INT);\
 153    PUSH_VALUE (p, (BOOL_T) (VALUE (&i) OP VALUE (&j)), A68G_BOOL);\
 154    }
 155  
 156  A68G_CMP_INT (genie_eq_int, ==);
 157  A68G_CMP_INT (genie_ne_int, !=);
 158  A68G_CMP_INT (genie_lt_int, <);
 159  A68G_CMP_INT (genie_gt_int, >);
 160  A68G_CMP_INT (genie_le_int, <=);
 161  A68G_CMP_INT (genie_ge_int, >=);
 162  
 163  // OP +:= = (REF INT, INT) REF INT
 164  
 165  void genie_plusab_int (NODE_T * p)
 166  {
 167    genie_f_and_becomes (p, M_REF_INT, genie_add_int);
 168  }
 169  
 170  // OP -:= = (REF INT, INT) REF INT
 171  
 172  void genie_minusab_int (NODE_T * p)
 173  {
 174    genie_f_and_becomes (p, M_REF_INT, genie_sub_int);
 175  }
 176  
 177  // OP *:= = (REF INT, INT) REF INT
 178  
 179  void genie_timesab_int (NODE_T * p)
 180  {
 181    genie_f_and_becomes (p, M_REF_INT, genie_mul_int);
 182  }
 183  
 184  // OP %:= = (REF INT, INT) REF INT
 185  
 186  void genie_overab_int (NODE_T * p)
 187  {
 188    genie_f_and_becomes (p, M_REF_INT, genie_over_int);
 189  }
 190  
 191  // OP %*:= = (REF INT, INT) REF INT
 192  
 193  void genie_modab_int (NODE_T * p)
 194  {
 195    genie_f_and_becomes (p, M_REF_INT, genie_mod_int);
 196  }
 197  
 198  // REAL operations.
 199  
 200  // OP - = (REAL) REAL.
 201  
 202  A68G_MONAD (genie_minus_real, A68G_REAL, -);
 203  
 204  // OP ABS = (REAL) REAL
 205  
 206  void genie_abs_real (NODE_T * p)
 207  {
 208    A68G_REAL *x;
 209    POP_OPERAND_ADDRESS (p, x, A68G_REAL);
 210    VALUE (x) = ABS (VALUE (x));
 211  }
 212  
 213  // OP ROUND = (REAL) INT
 214  
 215  void genie_round_real (NODE_T * p)
 216  {
 217    A68G_REAL x;
 218    POP_OBJECT (p, &x, A68G_REAL);
 219    PRELUDE_ERROR (VALUE (&x) < -(REAL_T) A68G_MAX_INT || VALUE (&x) > (REAL_T) A68G_MAX_INT, p, ERROR_OUT_OF_BOUNDS, M_INT);
 220    PUSH_VALUE (p, a68g_round (VALUE (&x)), A68G_INT);
 221  }
 222  
 223  // OP ENTIER = (REAL) INT
 224  
 225  void genie_entier_real (NODE_T * p)
 226  {
 227    A68G_REAL x;
 228    POP_OBJECT (p, &x, A68G_REAL);
 229    PRELUDE_ERROR (VALUE (&x) < -(REAL_T) A68G_MAX_INT || VALUE (&x) > (REAL_T) A68G_MAX_INT, p, ERROR_OUT_OF_BOUNDS, M_INT);
 230    PUSH_VALUE (p, (INT_T) floor (VALUE (&x)), A68G_INT);
 231  }
 232  
 233  // OP CEIL = (REAL) INT
 234  
 235  void genie_ceil_real (NODE_T * p)
 236  {
 237    A68G_REAL x;
 238    POP_OBJECT (p, &x, A68G_REAL);
 239    PRELUDE_ERROR (VALUE (&x) < -(REAL_T) A68G_MAX_INT || VALUE (&x) > (REAL_T) A68G_MAX_INT, p, ERROR_OUT_OF_BOUNDS, M_INT);
 240    PUSH_VALUE (p, (INT_T) ceil (VALUE (&x)), A68G_INT);
 241  }
 242  
 243  // OP TRUNC = (REAL) INT
 244  
 245  void genie_trunc_real (NODE_T * p)
 246  {
 247    A68G_REAL x;
 248    POP_OBJECT (p, &x, A68G_REAL);
 249    PRELUDE_ERROR (VALUE (&x) < -(REAL_T) A68G_MAX_INT || VALUE (&x) > (REAL_T) A68G_MAX_INT, p, ERROR_OUT_OF_BOUNDS, M_INT);
 250    PUSH_VALUE (p, (INT_T) VALUE (&x), A68G_INT);
 251  }
 252  
 253  // OP FRAC = (REAL) INT
 254  
 255  void genie_frac_real (NODE_T * p)
 256  {
 257    A68G_REAL x;
 258    POP_OBJECT (p, &x, A68G_REAL);
 259    REAL_T y = VALUE (&x);
 260    PUSH_VALUE (p, y - (INT_T) (y), A68G_REAL);
 261  }
 262  
 263  // OP SIGN = (REAL) INT
 264  
 265  void genie_sign_real (NODE_T * p)
 266  {
 267    A68G_REAL x;
 268    POP_OBJECT (p, &x, A68G_REAL);
 269    PUSH_VALUE (p, SIGN (VALUE (&x)), A68G_INT);
 270  }
 271  
 272  // OP + = (REAL, REAL) REAL
 273  
 274  void genie_add_real (NODE_T * p)
 275  {
 276    A68G_REAL *x, *y;
 277    POP_OPERAND_ADDRESSES (p, x, y, A68G_REAL);
 278    VALUE (x) += VALUE (y);
 279    CHECK_REAL (p, VALUE (x));
 280  }
 281  
 282  // OP - = (REAL, REAL) REAL
 283  
 284  void genie_sub_real (NODE_T * p)
 285  {
 286    A68G_REAL *x, *y;
 287    POP_OPERAND_ADDRESSES (p, x, y, A68G_REAL);
 288    VALUE (x) -= VALUE (y);
 289    CHECK_REAL (p, VALUE (x));
 290  }
 291  
 292  // OP * = (REAL, REAL) REAL
 293  
 294  void genie_mul_real (NODE_T * p)
 295  {
 296    A68G_REAL *x, *y;
 297    POP_OPERAND_ADDRESSES (p, x, y, A68G_REAL);
 298    VALUE (x) *= VALUE (y);
 299    CHECK_REAL (p, VALUE (x));
 300  }
 301  
 302  // OP / = (REAL, REAL) REAL
 303  
 304  void genie_div_real (NODE_T * p)
 305  {
 306    A68G_REAL *x, *y;
 307    POP_OPERAND_ADDRESSES (p, x, y, A68G_REAL);
 308    PRELUDE_ERROR (VALUE (y) == 0.0, p, ERROR_DIVISION_BY_ZERO, M_REAL);
 309    VALUE (x) /= VALUE (y);
 310  }
 311  
 312  // OP ** = (REAL, INT) REAL
 313  
 314  void genie_pow_real_int (NODE_T * p)
 315  {
 316    A68G_INT j;
 317    A68G_REAL x;
 318    POP_OBJECT (p, &j, A68G_INT);
 319    POP_OBJECT (p, &x, A68G_REAL);
 320    REAL_T z = a68g_x_up_n_real (VALUE (&x), VALUE (&j));
 321    CHECK_REAL (p, z);
 322    PUSH_VALUE (p, z, A68G_REAL);
 323  }
 324  
 325  // OP ** = (REAL, REAL) REAL
 326  
 327  void genie_pow_real (NODE_T * p)
 328  {
 329    A68G_REAL x, y;
 330    POP_OBJECT (p, &y, A68G_REAL);
 331    POP_OBJECT (p, &x, A68G_REAL);
 332    errno = 0;
 333    REAL_T z = a68g_x_up_y (VALUE (&x), VALUE (&y));
 334    MATH_RTE (p, errno != 0, M_REAL, NO_TEXT);
 335    PUSH_VALUE (p, z, A68G_REAL);
 336  }
 337  
 338  // OP (REAL, REAL) BOOL.
 339  
 340  #define A68G_CMP_REAL(n, OP)\
 341  void n (NODE_T * p) {\
 342    A68G_REAL i, j;\
 343    POP_OBJECT (p, &j, A68G_REAL);\
 344    POP_OBJECT (p, &i, A68G_REAL);\
 345    PUSH_VALUE (p, (BOOL_T) (VALUE (&i) OP VALUE (&j)), A68G_BOOL);\
 346    }
 347  
 348  A68G_CMP_REAL (genie_eq_real, ==);
 349  A68G_CMP_REAL (genie_ne_real, !=);
 350  A68G_CMP_REAL (genie_lt_real, <);
 351  A68G_CMP_REAL (genie_gt_real, >);
 352  A68G_CMP_REAL (genie_le_real, <=);
 353  A68G_CMP_REAL (genie_ge_real, >=);
 354  
 355  // OP +:= = (REF REAL, REAL) REF REAL
 356  
 357  void genie_plusab_real (NODE_T * p)
 358  {
 359    genie_f_and_becomes (p, M_REF_REAL, genie_add_real);
 360  }
 361  
 362  // OP -:= = (REF REAL, REAL) REF REAL
 363  
 364  void genie_minusab_real (NODE_T * p)
 365  {
 366    genie_f_and_becomes (p, M_REF_REAL, genie_sub_real);
 367  }
 368  
 369  // OP *:= = (REF REAL, REAL) REF REAL
 370  
 371  void genie_timesab_real (NODE_T * p)
 372  {
 373    genie_f_and_becomes (p, M_REF_REAL, genie_mul_real);
 374  }
 375  
 376  // OP /:= = (REF REAL, REAL) REF REAL
 377  
 378  void genie_divab_real (NODE_T * p)
 379  {
 380    genie_f_and_becomes (p, M_REF_REAL, genie_div_real);
 381  }
 382  
 383  // @brief PROC (INT) VOID first random
 384  
 385  void genie_first_random (NODE_T * p)
 386  {
 387    A68G_INT i;
 388    POP_OBJECT (p, &i, A68G_INT);
 389    init_rng ((unt) VALUE (&i));
 390  }
 391  
 392  // @brief PROC REAL next random
 393  
 394  void genie_next_random (NODE_T * p)
 395  {
 396    PUSH_VALUE (p, a68g_unif_rand (), A68G_REAL);
 397  }
 398  
 399  // @brief PROC REAL rnd
 400  
 401  void genie_next_rnd (NODE_T * p)
 402  {
 403    PUSH_VALUE (p, 2 * a68g_unif_rand () - 1, A68G_REAL);
 404  }
 405  
 406  // @brief PROC (REAL) REAL sqrt
 407  
 408  void genie_sqrt_real (NODE_T * p)
 409  {
 410    C_FUNCTION (p, sqrt);
 411  }
 412  
 413  // @brief PROC (REAL) REAL curt
 414  
 415  void genie_curt_real (NODE_T * p)
 416  {
 417    C_FUNCTION (p, cbrt);
 418  }
 419  
 420  // @brief PROC (REAL) REAL exp
 421  
 422  void genie_exp_real (NODE_T * p)
 423  {
 424    A68G_REAL *x;
 425    POP_OPERAND_ADDRESS (p, x, A68G_REAL);
 426    errno = 0;
 427    VALUE (x) = exp (VALUE (x));
 428    MATH_RTE (p, errno != 0, M_REAL, NO_TEXT);
 429  }
 430  
 431  // @brief PROC (REAL) REAL ln
 432  
 433  void genie_ln_real (NODE_T * p)
 434  {
 435    C_FUNCTION (p, a68g_ln_real);
 436  }
 437  
 438  // @brief PROC (REAL) REAL ln1p
 439  
 440  void genie_ln1p_real (NODE_T * p)
 441  {
 442    C_FUNCTION (p, a68g_ln1p_real);
 443  }
 444  
 445  // @brief PROC (REAL) REAL log
 446  
 447  void genie_log_real (NODE_T * p)
 448  {
 449    C_FUNCTION (p, log10);
 450  }
 451  
 452  // @brief PROC (REAL) REAL sin
 453  
 454  void genie_sin_real (NODE_T * p)
 455  {
 456    C_FUNCTION (p, sin);
 457  }
 458  
 459  // @brief PROC (REAL) REAL arcsin
 460  
 461  void genie_asin_real (NODE_T * p)
 462  {
 463    C_FUNCTION (p, asin);
 464  }
 465  
 466  // @brief PROC (REAL) REAL cas
 467  
 468  void genie_cas_real (NODE_T * p)
 469  {
 470    C_FUNCTION (p, a68g_cas_real);
 471  }
 472  
 473  // @brief PROC (REAL) REAL cos
 474  
 475  void genie_cos_real (NODE_T * p)
 476  {
 477    C_FUNCTION (p, cos);
 478  }
 479  
 480  // @brief PROC (REAL) REAL arccos
 481  
 482  void genie_acos_real (NODE_T * p)
 483  {
 484    C_FUNCTION (p, acos);
 485  }
 486  
 487  // @brief PROC (REAL) REAL tan
 488  
 489  void genie_tan_real (NODE_T * p)
 490  {
 491    C_FUNCTION (p, tan);
 492  }
 493  
 494  // @brief PROC (REAL) REAL csc 
 495  
 496  void genie_csc_real (NODE_T * p)
 497  {
 498    C_FUNCTION (p, a68g_csc_real);
 499  }
 500  
 501  // @brief PROC (REAL) REAL acsc
 502  
 503  void genie_acsc_real (NODE_T * p)
 504  {
 505    C_FUNCTION (p, a68g_acsc_real);
 506  }
 507  
 508  // @brief PROC (REAL) REAL sec 
 509  
 510  void genie_sec_real (NODE_T * p)
 511  {
 512    C_FUNCTION (p, a68g_sec_real);
 513  }
 514  
 515  // @brief PROC (REAL) REAL asec
 516  
 517  void genie_asec_real (NODE_T * p)
 518  {
 519    C_FUNCTION (p, a68g_asec_real);
 520  }
 521  
 522  // @brief PROC (REAL) REAL cot 
 523  
 524  void genie_cot_real (NODE_T * p)
 525  {
 526    C_FUNCTION (p, a68g_cot_real);
 527  }
 528  
 529  // @brief PROC (REAL) REAL acot
 530  
 531  void genie_acot_real (NODE_T * p)
 532  {
 533    C_FUNCTION (p, a68g_acot_real);
 534  }
 535  
 536  // @brief PROC (REAL) REAL arctan
 537  
 538  void genie_atan_real (NODE_T * p)
 539  {
 540    C_FUNCTION (p, atan);
 541  }
 542  
 543  // @brief PROC (REAL, REAL) REAL arctan2
 544  
 545  void genie_atan2_real (NODE_T * p)
 546  {
 547    A68G_REAL *x, *y;
 548    POP_OPERAND_ADDRESSES (p, x, y, A68G_REAL);
 549    errno = 0;
 550    PRELUDE_ERROR (VALUE (x) == 0.0 && VALUE (y) == 0.0, p, ERROR_INVALID_ARGUMENT, M_LONG_REAL);
 551    VALUE (x) = a68g_atan2_real (VALUE (y), VALUE (x));
 552    PRELUDE_ERROR (errno != 0, p, ERROR_MATH_EXCEPTION, NO_TEXT);
 553  }
 554  
 555  // @brief PROC (REAL) REAL sindg
 556  
 557  void genie_sindg_real (NODE_T * p)
 558  {
 559    C_FUNCTION (p, a68g_sindg_real);
 560  }
 561  
 562  // @brief PROC (REAL) REAL arcsindg
 563  
 564  void genie_asindg_real (NODE_T * p)
 565  {
 566    C_FUNCTION (p, a68g_asindg_real);
 567  }
 568  
 569  // @brief PROC (REAL) REAL cosdg
 570  
 571  void genie_cosdg_real (NODE_T * p)
 572  {
 573    C_FUNCTION (p, a68g_cosdg_real);
 574  }
 575  
 576  // @brief PROC (REAL) REAL arccosdg
 577  
 578  void genie_acosdg_real (NODE_T * p)
 579  {
 580    C_FUNCTION (p, a68g_acosdg_real);
 581  }
 582  
 583  // @brief PROC (REAL) REAL tandg
 584  
 585  void genie_tandg_real (NODE_T * p)
 586  {
 587    C_FUNCTION (p, a68g_tandg_real);
 588  }
 589  
 590  // @brief PROC (REAL) REAL arctandg
 591  
 592  void genie_atandg_real (NODE_T * p)
 593  {
 594    C_FUNCTION (p, a68g_atandg_real);
 595  }
 596  
 597  // @brief PROC (REAL) REAL cscdg
 598  
 599  void genie_cscdg_real (NODE_T * p)
 600  {
 601    C_FUNCTION (p, a68g_cscdg_real);
 602  }
 603  
 604  // @brief PROC (REAL) REAL acscdg
 605  
 606  void genie_acscdg_real (NODE_T * p)
 607  {
 608    C_FUNCTION (p, a68g_acscdg_real);
 609  }
 610  
 611  // @brief PROC (REAL) REAL secdg 
 612  
 613  void genie_secdg_real (NODE_T * p)
 614  {
 615    C_FUNCTION (p, a68g_secdg_real);
 616  }
 617  
 618  // @brief PROC (REAL) REAL asecdg
 619  
 620  void genie_asecdg_real (NODE_T * p)
 621  {
 622    C_FUNCTION (p, a68g_asecdg_real);
 623  }
 624  
 625  // @brief PROC (REAL) REAL cotdg 
 626  
 627  void genie_cotdg_real (NODE_T * p)
 628  {
 629    C_FUNCTION (p, a68g_cot_realdg_real);
 630  }
 631  
 632  // @brief PROC (REAL) REAL acotdg
 633  
 634  void genie_acotdg_real (NODE_T * p)
 635  {
 636    C_FUNCTION (p, a68g_acotdg_real);
 637  }
 638  
 639  // @brief PROC (REAL, REAL) REAL arctan2dg
 640  
 641  void genie_atan2dg_real (NODE_T * p)
 642  {
 643    A68G_REAL *x, *y;
 644    POP_OPERAND_ADDRESSES (p, x, y, A68G_REAL);
 645    errno = 0;
 646    PRELUDE_ERROR (VALUE (x) == 0.0 && VALUE (y) == 0.0, p, ERROR_INVALID_ARGUMENT, M_LONG_REAL);
 647    VALUE (x) = CONST_180_OVER_PI * a68g_atan2_real (VALUE (y), VALUE (x));
 648    PRELUDE_ERROR (errno != 0, p, ERROR_MATH_EXCEPTION, NO_TEXT);
 649  }
 650  
 651  // @brief PROC (REAL) REAL sinpi
 652  
 653  void genie_sinpi_real (NODE_T * p)
 654  {
 655    C_FUNCTION (p, a68g_sinpi_real);
 656  }
 657  
 658  // @brief PROC (REAL) REAL cospi
 659  
 660  void genie_cospi_real (NODE_T * p)
 661  {
 662    C_FUNCTION (p, a68g_cospi_real);
 663  }
 664  
 665  // @brief PROC (REAL) REAL tanpi
 666  
 667  void genie_tanpi_real (NODE_T * p)
 668  {
 669    C_FUNCTION (p, a68g_tanpi_real);
 670  }
 671  
 672  // @brief PROC (REAL) REAL cotpi 
 673  
 674  void genie_cotpi_real (NODE_T * p)
 675  {
 676    C_FUNCTION (p, a68g_cot_realpi);
 677  }
 678  
 679  // @brief PROC (REAL) REAL sinh
 680  
 681  void genie_sinh_real (NODE_T * p)
 682  {
 683    C_FUNCTION (p, sinh);
 684  }
 685  
 686  // @brief PROC (REAL) REAL cosh
 687  
 688  void genie_cosh_real (NODE_T * p)
 689  {
 690    C_FUNCTION (p, cosh);
 691  }
 692  
 693  // @brief PROC (REAL) REAL tanh
 694  
 695  void genie_tanh_real (NODE_T * p)
 696  {
 697    C_FUNCTION (p, tanh);
 698  }
 699  
 700  // @brief PROC (REAL) REAL asinh
 701  
 702  void genie_asinh_real (NODE_T * p)
 703  {
 704    C_FUNCTION (p, a68g_asinh_real);
 705  }
 706  
 707  // @brief PROC (REAL) REAL acosh
 708  
 709  void genie_acosh_real (NODE_T * p)
 710  {
 711    C_FUNCTION (p, a68g_acosh_real);
 712  }
 713  
 714  // @brief PROC (REAL) REAL atanh
 715  
 716  void genie_atanh_real (NODE_T * p)
 717  {
 718    C_FUNCTION (p, a68g_atanh_real);
 719  }
 720  
 721  // @brief PROC (REAL) REAL erf
 722  
 723  void genie_erf_real (NODE_T * p)
 724  {
 725    C_FUNCTION (p, erf);
 726  }
 727  
 728  // @brief PROC (REAL) REAL inverf
 729  
 730  void genie_inverf_real (NODE_T * p)
 731  {
 732    C_FUNCTION (p, a68g_inverf_real);
 733  }
 734  
 735  // @brief PROC (REAL) REAL erfc
 736  
 737  void genie_erfc_real (NODE_T * p)
 738  {
 739    C_FUNCTION (p, erfc);
 740  }
 741  
 742  // @brief PROC (REAL) REAL inverfc
 743  
 744  void genie_inverfc_real (NODE_T * p)
 745  {
 746    C_FUNCTION (p, a68g_inverfc_real);
 747  }
 748  
 749  // @brief PROC (REAL) REAL gamma
 750  
 751  void genie_gamma_real (NODE_T * p)
 752  {
 753    C_FUNCTION (p, tgamma);
 754  }
 755  
 756  // @brief PROC (REAL) REAL ln gamma
 757  
 758  void genie_ln_gamma_real (NODE_T * p)
 759  {
 760    C_FUNCTION (p, lgamma);
 761  }
 762  
 763  // @brief PROC (REAL, REAL) REAL beta
 764  
 765  void genie_beta_real (NODE_T * p)
 766  {
 767    A68G_REAL *x, *y;
 768    POP_OPERAND_ADDRESSES (p, x, y, A68G_REAL);
 769    errno = 0;
 770    VALUE (x) = a68g_beta_real (VALUE (x), VALUE (y));
 771    PRELUDE_ERROR (errno != 0, p, ERROR_MATH_EXCEPTION, NO_TEXT);
 772  }
 773  
 774  // @brief PROC (REAL, REAL) REAL ln beta
 775  
 776  void genie_ln_beta_real (NODE_T * p)
 777  {
 778    A68G_REAL *x, *y;
 779    POP_OPERAND_ADDRESSES (p, x, y, A68G_REAL);
 780    errno = 0;
 781    VALUE (x) = a68g_ln_beta_real (VALUE (x), VALUE (y));
 782    PRELUDE_ERROR (errno != 0, p, ERROR_MATH_EXCEPTION, NO_TEXT);
 783  }
 784  
 785  // @brief PROC (REAL, REAL, REAL) REAL cf beta inc
 786  
 787  void genie_beta_inc_cf_real (NODE_T * p)
 788  {
 789    A68G_REAL *s, *t, *x;
 790    POP_3_OPERAND_ADDRESSES (p, s, t, x, A68G_REAL);
 791    errno = 0;
 792    VALUE (s) = a68g_beta_inc_real (VALUE (s), VALUE (t), VALUE (x));
 793    PRELUDE_ERROR (errno != 0, p, ERROR_MATH_EXCEPTION, NO_TEXT);
 794  }
 795  
 796  // @brief PROC (REAL, REAL, REAL) REAL lj e 12 6
 797  
 798  void genie_lj_e_12_6 (NODE_T * p)
 799  {
 800    A68G_REAL *e, *s, *r;
 801    POP_3_OPERAND_ADDRESSES (p, e, s, r, A68G_REAL);
 802    PRELUDE_ERROR (VALUE (r) == 0, p, ERROR_MATH_EXCEPTION, NO_TEXT);
 803    REAL_T u = (VALUE (s) / VALUE (r));
 804    REAL_T u2 = u * u;
 805    REAL_T u6 = u2 * u2 * u2;
 806    VALUE (e) = 4.0 * VALUE (e) * u6 * (u6 - 1.0);
 807  }
 808  
 809  // @brief PROC (REAL, REAL, REAL) REAL lj f 12 6
 810  
 811  void genie_lj_f_12_6 (NODE_T * p)
 812  {
 813    A68G_REAL *e, *s, *r;
 814    POP_3_OPERAND_ADDRESSES (p, e, s, r, A68G_REAL);
 815    PRELUDE_ERROR (VALUE (r) == 0, p, ERROR_MATH_EXCEPTION, NO_TEXT);
 816    REAL_T u = (VALUE (s) / VALUE (r));
 817    REAL_T u2 = u * u;
 818    REAL_T u6 = u2 * u2 * u2;
 819    VALUE (e) = 24.0 * VALUE (e) * u * u6 * (1.0 - 2.0 * u6);
 820  }
 821  
 822  // This file also contains Algol68G's standard environ for complex numbers.
 823  // Some of the LONG operations are generic for LONG and LONG LONG.
 824  // 
 825  // Some routines are based on
 826  //   GNU Scientific Library
 827  //   Abramowitz and Stegun.
 828  
 829  // OP +* = (REAL, REAL) COMPLEX
 830  
 831  void genie_i_complex (NODE_T * p)
 832  {
 833  // This function must exist so the code generator recognises it!
 834    (void) p;
 835  }
 836  
 837  // OP +* = (INT, INT) COMPLEX
 838  
 839  void genie_i_int_complex (NODE_T * p)
 840  {
 841    A68G_INT re, im;
 842    POP_OBJECT (p, &im, A68G_INT);
 843    POP_OBJECT (p, &re, A68G_INT);
 844    PUSH_VALUE (p, (REAL_T) VALUE (&re), A68G_REAL);
 845    PUSH_VALUE (p, (REAL_T) VALUE (&im), A68G_REAL);
 846  }
 847  
 848  // OP RE = (COMPLEX) REAL
 849  
 850  void genie_re_complex (NODE_T * p)
 851  {
 852    DECREMENT_STACK_POINTER (p, SIZE (M_REAL));
 853  }
 854  
 855  // OP IM = (COMPLEX) REAL
 856  
 857  void genie_im_complex (NODE_T * p)
 858  {
 859    A68G_REAL im;
 860    POP_OBJECT (p, &im, A68G_REAL);
 861    *(A68G_REAL *) (STACK_OFFSET (-SIZE (M_REAL))) = im;
 862  }
 863  
 864  // OP - = (COMPLEX) COMPLEX
 865  
 866  void genie_minus_complex (NODE_T * p)
 867  {
 868    A68G_REAL *re_x, *im_x;
 869    im_x = (A68G_REAL *) (STACK_OFFSET (-SIZE (M_REAL)));
 870    re_x = (A68G_REAL *) (STACK_OFFSET (-2 * SIZE (M_REAL)));
 871    VALUE (im_x) = -VALUE (im_x);
 872    VALUE (re_x) = -VALUE (re_x);
 873    (void) p;
 874  }
 875  
 876  // ABS = (COMPLEX) REAL
 877  
 878  void genie_abs_complex (NODE_T * p)
 879  {
 880    A68G_REAL re_x, im_x;
 881    POP_COMPLEX (p, &re_x, &im_x);
 882    PUSH_VALUE (p, a68g_hypot_real (VALUE (&re_x), VALUE (&im_x)), A68G_REAL);
 883  }
 884  
 885  // OP ARG = (COMPLEX) REAL
 886  
 887  void genie_arg_complex (NODE_T * p)
 888  {
 889    A68G_REAL re_x, im_x;
 890    POP_COMPLEX (p, &re_x, &im_x);
 891    PRELUDE_ERROR (VALUE (&re_x) == 0.0 && VALUE (&im_x) == 0.0, p, ERROR_INVALID_ARGUMENT, M_COMPLEX);
 892    PUSH_VALUE (p, atan2 (VALUE (&im_x), VALUE (&re_x)), A68G_REAL);
 893  }
 894  
 895  // OP CONJ = (COMPLEX) COMPLEX
 896  
 897  void genie_conj_complex (NODE_T * p)
 898  {
 899    A68G_REAL *im;
 900    POP_OPERAND_ADDRESS (p, im, A68G_REAL);
 901    VALUE (im) = -VALUE (im);
 902  }
 903  
 904  // OP + = (COMPLEX, COMPLEX) COMPLEX
 905  
 906  void genie_add_complex (NODE_T * p)
 907  {
 908    A68G_REAL *re_x, *im_x, re_y, im_y;
 909    POP_COMPLEX (p, &re_y, &im_y);
 910    im_x = (A68G_REAL *) (STACK_OFFSET (-SIZE (M_REAL)));
 911    re_x = (A68G_REAL *) (STACK_OFFSET (-2 * SIZE (M_REAL)));
 912    VALUE (im_x) += VALUE (&im_y);
 913    VALUE (re_x) += VALUE (&re_y);
 914    CHECK_COMPLEX (p, VALUE (re_x), VALUE (im_x));
 915  }
 916  
 917  // OP - = (COMPLEX, COMPLEX) COMPLEX
 918  
 919  void genie_sub_complex (NODE_T * p)
 920  {
 921    A68G_REAL *re_x, *im_x, re_y, im_y;
 922    POP_COMPLEX (p, &re_y, &im_y);
 923    im_x = (A68G_REAL *) (STACK_OFFSET (-SIZE (M_REAL)));
 924    re_x = (A68G_REAL *) (STACK_OFFSET (-2 * SIZE (M_REAL)));
 925    VALUE (im_x) -= VALUE (&im_y);
 926    VALUE (re_x) -= VALUE (&re_y);
 927    CHECK_COMPLEX (p, VALUE (re_x), VALUE (im_x));
 928  }
 929  
 930  // OP * = (COMPLEX, COMPLEX) COMPLEX
 931  
 932  void genie_mul_complex (NODE_T * p)
 933  {
 934    A68G_REAL re_x, im_x, re_y, im_y;
 935    POP_COMPLEX (p, &re_y, &im_y);
 936    POP_COMPLEX (p, &re_x, &im_x);
 937    REAL_T re = VALUE (&re_x) * VALUE (&re_y) - VALUE (&im_x) * VALUE (&im_y);
 938    REAL_T im = VALUE (&im_x) * VALUE (&re_y) + VALUE (&re_x) * VALUE (&im_y);
 939    CHECK_COMPLEX (p, re, im);
 940    PUSH_COMPLEX_VALUE (p, re, im);
 941  }
 942  
 943  // OP / = (COMPLEX, COMPLEX) COMPLEX
 944  
 945  void genie_div_complex (NODE_T * p)
 946  {
 947    A68G_REAL re_x, im_x, re_y, im_y;
 948    REAL_T re = 0.0, im = 0.0;
 949    POP_COMPLEX (p, &re_y, &im_y);
 950    POP_COMPLEX (p, &re_x, &im_x);
 951  #if !defined (HAVE_IEEE_754)
 952    PRELUDE_ERROR (VALUE (&re_y) == 0.0 && VALUE (&im_y) == 0.0, p, ERROR_DIVISION_BY_ZERO, M_COMPLEX);
 953  #endif
 954    if (ABS (VALUE (&re_y)) >= ABS (VALUE (&im_y))) {
 955      REAL_T r = VALUE (&im_y) / VALUE (&re_y), den = VALUE (&re_y) + r * VALUE (&im_y);
 956      re = (VALUE (&re_x) + r * VALUE (&im_x)) / den;
 957      im = (VALUE (&im_x) - r * VALUE (&re_x)) / den;
 958    } else {
 959      REAL_T r = VALUE (&re_y) / VALUE (&im_y), den = VALUE (&im_y) + r * VALUE (&re_y);
 960      re = (VALUE (&re_x) * r + VALUE (&im_x)) / den;
 961      im = (VALUE (&im_x) * r - VALUE (&re_x)) / den;
 962    }
 963    CHECK_COMPLEX (p, re, im);
 964    PUSH_COMPLEX_VALUE (p, re, im);
 965  }
 966  
 967  // OP ** = (COMPLEX, INT) COMPLEX
 968  
 969  void genie_pow_complex_int (NODE_T * p)
 970  {
 971    A68G_INT j;
 972    POP_OBJECT (p, &j, A68G_INT);
 973    A68G_REAL re_x, im_x;
 974    POP_COMPLEX (p, &re_x, &im_x);
 975    REAL_T re_z = 1.0, im_z = 0.0;
 976    REAL_T re_y = VALUE (&re_x), im_y = VALUE (&im_x);
 977    INT_T expo = 1;
 978    BOOL_T neg = (BOOL_T) (VALUE (&j) < 0);
 979    if (neg) {
 980      VALUE (&j) = -VALUE (&j);
 981    }
 982    while ((UNSIGNED_T) expo <= (UNSIGNED_T) (VALUE (&j))) {
 983      REAL_T rea;
 984      if (expo & VALUE (&j)) {
 985        rea = re_z * re_y - im_z * im_y;
 986        im_z = re_z * im_y + im_z * re_y;
 987        re_z = rea;
 988      }
 989      rea = re_y * re_y - im_y * im_y;
 990      im_y = im_y * re_y + re_y * im_y;
 991      re_y = rea;
 992      expo <<= 1;
 993    }
 994    CHECK_COMPLEX (p, re_z, im_z);
 995    if (neg) {
 996      PUSH_VALUE (p, 1.0, A68G_REAL);
 997      PUSH_VALUE (p, 0.0, A68G_REAL);
 998      PUSH_VALUE (p, re_z, A68G_REAL);
 999      PUSH_VALUE (p, im_z, A68G_REAL);
1000      genie_div_complex (p);
1001    } else {
1002      PUSH_VALUE (p, re_z, A68G_REAL);
1003      PUSH_VALUE (p, im_z, A68G_REAL);
1004    }
1005  }
1006  
1007  // OP = = (COMPLEX, COMPLEX) BOOL
1008  
1009  void genie_eq_complex (NODE_T * p)
1010  {
1011    A68G_REAL re_x, im_x, re_y, im_y;
1012    POP_COMPLEX (p, &re_y, &im_y);
1013    POP_COMPLEX (p, &re_x, &im_x);
1014    PUSH_VALUE (p, (BOOL_T) ((VALUE (&re_x) == VALUE (&re_y)) && (VALUE (&im_x) == VALUE (&im_y))), A68G_BOOL);
1015  }
1016  
1017  // OP /= = (COMPLEX, COMPLEX) BOOL
1018  
1019  void genie_ne_complex (NODE_T * p)
1020  {
1021    A68G_REAL re_x, im_x, re_y, im_y;
1022    POP_COMPLEX (p, &re_y, &im_y);
1023    POP_COMPLEX (p, &re_x, &im_x);
1024    PUSH_VALUE (p, (BOOL_T) ! ((VALUE (&re_x) == VALUE (&re_y)) && (VALUE (&im_x) == VALUE (&im_y))), A68G_BOOL);
1025  }
1026  
1027  // OP +:= = (REF COMPLEX, COMPLEX) REF COMPLEX
1028  
1029  void genie_plusab_complex (NODE_T * p)
1030  {
1031    genie_f_and_becomes (p, M_REF_COMPLEX, genie_add_complex);
1032  }
1033  
1034  // OP -:= = (REF COMPLEX, COMPLEX) REF COMPLEX
1035  
1036  void genie_minusab_complex (NODE_T * p)
1037  {
1038    genie_f_and_becomes (p, M_REF_COMPLEX, genie_sub_complex);
1039  }
1040  
1041  // OP *:= = (REF COMPLEX, COMPLEX) REF COMPLEX
1042  
1043  void genie_timesab_complex (NODE_T * p)
1044  {
1045    genie_f_and_becomes (p, M_REF_COMPLEX, genie_mul_complex);
1046  }
1047  
1048  // OP /:= = (REF COMPLEX, COMPLEX) REF COMPLEX
1049  
1050  void genie_divab_complex (NODE_T * p)
1051  {
1052    genie_f_and_becomes (p, M_REF_COMPLEX, genie_div_complex);
1053  }
1054  
1055  #define C_C_FUNCTION(p, f)\
1056    A68G_REAL re, im;\
1057    POP_OBJECT (p, &im, A68G_REAL);\
1058    POP_OBJECT (p, &re, A68G_REAL);\
1059    errno = 0;\
1060    COMPLEX_T z = VALUE (&re) + VALUE (&im) * _Complex_I;\
1061    z = f (z);\
1062    PUSH_VALUE (p, (REAL_T) creal (z), A68G_REAL);\
1063    PUSH_VALUE (p, (REAL_T) cimag (z), A68G_REAL);\
1064    MATH_RTE (p, errno != 0, M_COMPLEX, NO_TEXT);
1065  
1066  // @brief PROC (COMPLEX) COMPLEX csqrt
1067  
1068  void genie_sqrt_complex (NODE_T * p)
1069  {
1070    C_C_FUNCTION (p, csqrt);
1071  }
1072  
1073  // @brief PROC (COMPLEX) COMPLEX cexp
1074  
1075  void genie_exp_complex (NODE_T * p)
1076  {
1077    C_C_FUNCTION (p, cexp);
1078  }
1079  
1080  // @brief PROC (COMPLEX) COMPLEX cln
1081  
1082  void genie_ln_complex (NODE_T * p)
1083  {
1084    C_C_FUNCTION (p, clog);
1085  }
1086  
1087  // @brief PROC (COMPLEX) COMPLEX csin
1088  
1089  void genie_sin_complex (NODE_T * p)
1090  {
1091    C_C_FUNCTION (p, csin);
1092  }
1093  
1094  // @brief PROC (COMPLEX) COMPLEX ccos
1095  
1096  void genie_cos_complex (NODE_T * p)
1097  {
1098    C_C_FUNCTION (p, ccos);
1099  }
1100  
1101  // @brief PROC (COMPLEX) COMPLEX ctan
1102  
1103  void genie_tan_complex (NODE_T * p)
1104  {
1105    C_C_FUNCTION (p, ctan);
1106  }
1107  
1108  // @brief PROC carcsin= (COMPLEX) COMPLEX
1109  
1110  void genie_asin_complex (NODE_T * p)
1111  {
1112    C_C_FUNCTION (p, casin);
1113  }
1114  
1115  // @brief PROC (COMPLEX) COMPLEX carccos
1116  
1117  void genie_acos_complex (NODE_T * p)
1118  {
1119    C_C_FUNCTION (p, cacos);
1120  }
1121  
1122  // @brief PROC (COMPLEX) COMPLEX carctan
1123  
1124  void genie_atan_complex (NODE_T * p)
1125  {
1126    C_C_FUNCTION (p, catan);
1127  }
1128  
1129  // @brief PROC (COMPLEX) COMPLEX csinh
1130  
1131  void genie_sinh_complex (NODE_T * p)
1132  {
1133    C_C_FUNCTION (p, csinh);
1134  }
1135  
1136  // @brief PROC (COMPLEX) COMPLEX ccosh
1137  
1138  void genie_cosh_complex (NODE_T * p)
1139  {
1140    C_C_FUNCTION (p, ccosh);
1141  }
1142  
1143  // @brief PROC (COMPLEX) COMPLEX ctanh
1144  
1145  void genie_tanh_complex (NODE_T * p)
1146  {
1147    C_C_FUNCTION (p, ctanh);
1148  }
1149  
1150  // @brief PROC (COMPLEX) COMPLEX carcsinh
1151  
1152  void genie_asinh_complex (NODE_T * p)
1153  {
1154    C_C_FUNCTION (p, casinh);
1155  }
1156  
1157  // @brief PROC (COMPLEX) COMPLEX carccosh
1158  
1159  void genie_acosh_complex (NODE_T * p)
1160  {
1161    C_C_FUNCTION (p, cacosh);
1162  }
1163  
1164  // @brief PROC (COMPLEX) COMPLEX carctanh
1165  
1166  void genie_atanh_complex (NODE_T * p)
1167  {
1168    C_C_FUNCTION (p, catanh);
1169  }
1170  
1171  #define C_C_INLINE(z, x, f)\
1172    COMPLEX_T u = RE (x) + IM (x) * _Complex_I;\
1173    COMPLEX_T v = f (u);\
1174    STATUS_RE (z) = INIT_MASK;\
1175    STATUS_IM (z) = INIT_MASK;\
1176    RE (z) = creal (v);\
1177    IM (z) = cimag (v);\
1178  
1179  //! @brief PROC (COMPLEX) COMPLEX csqrt
1180  
1181  void a68g_sqrt_complex (A68G_REAL * z, A68G_REAL * x)
1182  {
1183    C_C_INLINE (z, x, csqrt);
1184  }
1185  
1186  //! @brief PROC (COMPLEX) COMPLEX cexp
1187  
1188  void a68g_exp_real_complex (A68G_REAL * z, A68G_REAL * x)
1189  {
1190    C_C_INLINE (z, x, cexp);
1191  }
1192  
1193  //! @brief PROC (COMPLEX) COMPLEX cln
1194  
1195  void a68g_ln_complex (A68G_REAL * z, A68G_REAL * x)
1196  {
1197    C_C_INLINE (z, x, clog);
1198  }
1199  
1200  //! @brief PROC (COMPLEX) COMPLEX csin
1201  
1202  void a68g_sin_complex (A68G_REAL * z, A68G_REAL * x)
1203  {
1204    C_C_INLINE (z, x, csin);
1205  }
1206  
1207  //! @brief PROC (COMPLEX) COMPLEX ccos
1208  
1209  void a68g_cos_complex (A68G_REAL * z, A68G_REAL * x)
1210  {
1211    C_C_INLINE (z, x, ccos);
1212  }
1213  
1214  //! @brief PROC (COMPLEX) COMPLEX ctan
1215  
1216  void a68g_tan_complex (A68G_REAL * z, A68G_REAL * x)
1217  {
1218    C_C_INLINE (z, x, ctan);
1219  }
1220  
1221  //! @brief PROC (COMPLEX) COMPLEX casin
1222  
1223  void a68g_asin_complex (A68G_REAL * z, A68G_REAL * x)
1224  {
1225    C_C_INLINE (z, x, casin);
1226  }
1227  
1228  //! @brief PROC (COMPLEX) COMPLEX cacos
1229  
1230  void a68g_acos_complex (A68G_REAL * z, A68G_REAL * x)
1231  {
1232    C_C_INLINE (z, x, cacos);
1233  }
1234  
1235  //! @brief PROC (COMPLEX) COMPLEX catan
1236  
1237  void a68g_atan_complex (A68G_REAL * z, A68G_REAL * x)
1238  {
1239    C_C_INLINE (z, x, catan);
1240  }
1241  
1242  //! @brief PROC (COMPLEX) COMPLEX csinh
1243  
1244  void a68g_sinh_complex (A68G_REAL * z, A68G_REAL * x)
1245  {
1246    C_C_INLINE (z, x, csinh);
1247  }
1248  
1249  //! @brief PROC (COMPLEX) COMPLEX ccosh
1250  
1251  void a68g_cosh_complex (A68G_REAL * z, A68G_REAL * x)
1252  {
1253    C_C_INLINE (z, x, ccosh);
1254  }
1255  
1256  //! @brief PROC (COMPLEX) COMPLEX ctanh
1257  
1258  void a68g_tanh_complex (A68G_REAL * z, A68G_REAL * x)
1259  {
1260    C_C_INLINE (z, x, ctanh);
1261  }
1262  
1263  //! @brief PROC (COMPLEX) COMPLEX casinh
1264  
1265  void a68g_asinh_real_complex (A68G_REAL * z, A68G_REAL * x)
1266  {
1267    C_C_INLINE (z, x, casinh);
1268  }
1269  
1270  //! @brief PROC (COMPLEX) COMPLEX cacosh
1271  
1272  void a68g_acosh_real_complex (A68G_REAL * z, A68G_REAL * x)
1273  {
1274    C_C_INLINE (z, x, cacosh);
1275  }
1276  
1277  //! @brief PROC (COMPLEX) COMPLEX catanh
1278  
1279  void a68g_atanh_real_complex (A68G_REAL * z, A68G_REAL * x)
1280  {
1281    C_C_INLINE (z, x, catanh);
1282  }
1283  
1284  //! @brief PROC (INT, INT) REAL choose
1285  
1286  void genie_fact_real (NODE_T * p)
1287  {
1288    A68G_INT n;
1289    POP_OBJECT (p, &n, A68G_INT);
1290    errno = 0;
1291    PUSH_VALUE (p, a68g_fact_real (VALUE (&n)), A68G_REAL);
1292    MATH_RTE (p, errno != 0, M_INT, NO_TEXT);
1293  }
1294  
1295  //! @brief PROC (INT, INT) REAL ln fact
1296  
1297  void genie_ln_fact_real (NODE_T * p)
1298  {
1299    A68G_INT n;
1300    POP_OBJECT (p, &n, A68G_INT);
1301    errno = 0;
1302    PUSH_VALUE (p, a68g_ln_fact_real (VALUE (&n)), A68G_REAL);
1303    MATH_RTE (p, errno != 0, M_INT, NO_TEXT);
1304  }
1305  
1306  void genie_choose_real (NODE_T * p)
1307  {
1308    A68G_INT n, m;
1309    POP_OBJECT (p, &m, A68G_INT);
1310    POP_OBJECT (p, &n, A68G_INT);
1311    errno = 0;
1312    PUSH_VALUE (p, a68g_choose_real (VALUE (&n), VALUE (&m)), A68G_REAL);
1313    MATH_RTE (p, errno != 0, M_INT, NO_TEXT);
1314  }
1315  
1316  //! @brief PROC (INT, INT) REAL ln choose
1317  
1318  void genie_ln_choose_real (NODE_T * p)
1319  {
1320    A68G_INT n, m;
1321    POP_OBJECT (p, &m, A68G_INT);
1322    POP_OBJECT (p, &n, A68G_INT);
1323    errno = 0;
1324    PUSH_VALUE (p, a68g_ln_choose_real (VALUE (&n), VALUE (&m)), A68G_REAL);
1325    MATH_RTE (p, errno != 0, M_INT, NO_TEXT);
1326  }
1327  
1328  // OP / = (COMPLEX, COMPLEX) COMPLEX
1329  
1330  void a68g_div_complex (A68G_REAL * z, A68G_REAL * x, A68G_REAL * y)
1331  {
1332    STATUS_RE (z) = INIT_MASK;
1333    STATUS_IM (z) = INIT_MASK;
1334    if (RE (y) == 0 && IM (y) == 0) {
1335      RE (z) = 0.0;
1336      IM (z) = 0.0;
1337      errno = EDOM;
1338    } else if (fabs (RE (y)) >= fabs (IM (y))) {
1339      REAL_T r = IM (y) / RE (y), den = RE (y) + r * IM (y);
1340      RE (z) = (RE (x) + r * IM (x)) / den;
1341      IM (z) = (IM (x) - r * RE (x)) / den;
1342    } else {
1343      REAL_T r = RE (y) / IM (y), den = IM (y) + r * RE (y);
1344      RE (z) = (RE (x) * r + IM (x)) / den;
1345      IM (z) = (IM (x) * r - RE (x)) / den;
1346    }
1347  }
1348  
1349  // BITS max bits
1350  
1351  void genie_max_bits (NODE_T * p)
1352  {
1353    PUSH_VALUE (p, A68G_MAX_BITS, A68G_BITS);
1354  }
1355  
1356  // OP NOT = (BITS) BITS.
1357  A68G_MONAD (genie_not_bits, A68G_BITS, ~);
1358  
1359  // OP AND = (BITS, BITS) BITS
1360  
1361  void genie_and_bits (NODE_T * p)
1362  {
1363    A68G_BITS *i, *j;
1364    POP_OPERAND_ADDRESSES (p, i, j, A68G_BITS);
1365    VALUE (i) = VALUE (i) & VALUE (j);
1366  }
1367  
1368  // OP OR = (BITS, BITS) BITS
1369  
1370  void genie_or_bits (NODE_T * p)
1371  {
1372    A68G_BITS *i, *j;
1373    POP_OPERAND_ADDRESSES (p, i, j, A68G_BITS);
1374    VALUE (i) = VALUE (i) | VALUE (j);
1375  }
1376  
1377  // OP XOR = (BITS, BITS) BITS
1378  
1379  void genie_xor_bits (NODE_T * p)
1380  {
1381    A68G_BITS *i, *j;
1382    POP_OPERAND_ADDRESSES (p, i, j, A68G_BITS);
1383    VALUE (i) = VALUE (i) ^ VALUE (j);
1384  }
1385  
1386  // OP + = (BITS, BITS) BITS
1387  
1388  void genie_add_bits (NODE_T * p)
1389  {
1390    A68G_BITS *i, *j;
1391    POP_OPERAND_ADDRESSES (p, i, j, A68G_BITS);
1392    CHECK_BITS_ADDITION (p, VALUE (i), VALUE (j));
1393    VALUE (i) = VALUE (i) + VALUE (j);
1394  }
1395  
1396  // OP - = (BITS, BITS) BITS
1397  
1398  void genie_sub_bits (NODE_T * p)
1399  {
1400    A68G_BITS *i, *j;
1401    POP_OPERAND_ADDRESSES (p, i, j, A68G_BITS);
1402    CHECK_BITS_SUBTRACTION (p, VALUE (i), VALUE (j));
1403    VALUE (i) = VALUE (i) - VALUE (j);
1404  }
1405  
1406  // OP * = (BITS, BITS) BITS
1407  
1408  void genie_times_bits (NODE_T * p)
1409  {
1410    A68G_BITS *i, *j;
1411    POP_OPERAND_ADDRESSES (p, i, j, A68G_BITS);
1412    CHECK_BITS_MULTIPLICATION (p, VALUE (i), VALUE (j));
1413    VALUE (i) = VALUE (i) * VALUE (j);
1414  }
1415  
1416  // OP OVER = (BITS, BITS) BITS
1417  
1418  void genie_over_bits (NODE_T * p)
1419  {
1420    A68G_BITS *i, *j;
1421    POP_OPERAND_ADDRESSES (p, i, j, A68G_BITS);
1422    PRELUDE_ERROR (VALUE (j) == 0, p, ERROR_DIVISION_BY_ZERO, M_BITS);
1423    VALUE (i) = VALUE (i) / VALUE (j);
1424  }
1425  
1426  // OP MOD = (BITS, BITS) BITS
1427  
1428  void genie_mod_bits (NODE_T * p)
1429  {
1430    A68G_BITS *i, *j;
1431    POP_OPERAND_ADDRESSES (p, i, j, A68G_BITS);
1432    PRELUDE_ERROR (VALUE (j) == 0, p, ERROR_DIVISION_BY_ZERO, M_BITS);
1433    VALUE (i) = VALUE (i) % VALUE (j);
1434  }
1435  
1436  // OP = = (BITS, BITS) BOOL.
1437  
1438  #define A68G_CMP_BITS(n, OP)\
1439  void n (NODE_T * p) {\
1440    A68G_BITS i, j;\
1441    POP_OBJECT (p, &j, A68G_BITS);\
1442    POP_OBJECT (p, &i, A68G_BITS);\
1443    PUSH_VALUE (p, (BOOL_T) ((UNSIGNED_T) VALUE (&i) OP (UNSIGNED_T) VALUE (&j)), A68G_BOOL);\
1444    }
1445  
1446  A68G_CMP_BITS (genie_eq_bits, ==);
1447  A68G_CMP_BITS (genie_ne_bits, !=);
1448  
1449  // OP <= = (BITS, BITS) BOOL
1450  
1451  void genie_le_bits (NODE_T * p)
1452  {
1453    A68G_BITS i, j;
1454    POP_OBJECT (p, &j, A68G_BITS);
1455    POP_OBJECT (p, &i, A68G_BITS);
1456    PUSH_VALUE (p, (BOOL_T) ((VALUE (&i) | VALUE (&j)) == VALUE (&j)), A68G_BOOL);
1457  }
1458  
1459  // OP >= = (BITS, BITS) BOOL
1460  
1461  void genie_ge_bits (NODE_T * p)
1462  {
1463    A68G_BITS i, j;
1464    POP_OBJECT (p, &j, A68G_BITS);
1465    POP_OBJECT (p, &i, A68G_BITS);
1466    PUSH_VALUE (p, (BOOL_T) ((VALUE (&i) | VALUE (&j)) == VALUE (&i)), A68G_BOOL);
1467  }
1468  
1469  #if (A68G_LEVEL >= 3)
1470  
1471  // OP < = (BITS, BITS) BOOL
1472  
1473  void genie_lt_bits (NODE_T * p)
1474  {
1475    A68G_BITS i, j;
1476    POP_OBJECT (p, &j, A68G_BITS);
1477    POP_OBJECT (p, &i, A68G_BITS);
1478    if (VALUE (&i) == VALUE (&j)) {
1479      PUSH_VALUE (p, A68G_FALSE, A68G_BOOL);
1480    } else {
1481      PUSH_VALUE (p, (BOOL_T) ((VALUE (&i) | VALUE (&j)) == VALUE (&j)), A68G_BOOL);
1482    }
1483  }
1484  
1485  // OP >= = (BITS, BITS) BOOL
1486  
1487  void genie_gt_bits (NODE_T * p)
1488  {
1489    A68G_BITS i, j;
1490    POP_OBJECT (p, &j, A68G_BITS);
1491    POP_OBJECT (p, &i, A68G_BITS);
1492    if (VALUE (&i) == VALUE (&j)) {
1493      PUSH_VALUE (p, A68G_FALSE, A68G_BOOL);
1494    } else {
1495      PUSH_VALUE (p, (BOOL_T) ((VALUE (&i) | VALUE (&j)) == VALUE (&i)), A68G_BOOL);
1496    }
1497  }
1498  
1499  #endif
1500  
1501  // OP SHL = (BITS, INT) BITS
1502  
1503  void genie_shl_bits (NODE_T * p)
1504  {
1505    A68G_BITS i; A68G_INT j;
1506    POP_OBJECT (p, &j, A68G_INT);
1507    POP_OBJECT (p, &i, A68G_BITS);
1508    UNSIGNED_T z = VALUE (&i);
1509    int n = VALUE (&j);
1510    if (n >= 0) {
1511      for (int k = 0; k < VALUE (&j); k++) {
1512        PRELUDE_ERROR (!MODULAR_MATH (p) && (z & D_SIGN), p, ERROR_MATH, M_BITS);
1513        z = z << 1;
1514      }
1515      PUSH_VALUE (p, z, A68G_BITS);
1516    } else {
1517      for (int k = 0; k < -n; k++) {
1518  //    PRELUDE_ERROR (!MODULAR_MATH (p) && (z & 0x1), p, ERROR_MATH, M_BITS);
1519        z = z >> 1;
1520      }
1521      PUSH_VALUE (p, z, A68G_BITS);
1522    }
1523  }
1524  
1525  // OP SHR = (BITS, INT) BITS
1526  
1527  void genie_shr_bits (NODE_T * p)
1528  {
1529    A68G_INT *j;
1530    POP_OPERAND_ADDRESS (p, j, A68G_INT);
1531    VALUE (j) = -VALUE (j);
1532    genie_shl_bits (p);           // Conform RR
1533  }
1534  
1535  // OP ROL = (BITS, INT) BITS
1536  
1537  void genie_rol_bits (NODE_T * p)
1538  {
1539    A68G_BITS i; A68G_INT j;
1540    POP_OBJECT (p, &j, A68G_INT);
1541    POP_OBJECT (p, &i, A68G_BITS);
1542    CHECK_INT_SHORTEN (p, VALUE (&j));
1543    UNSIGNED_T w = VALUE (&i);
1544    int n = VALUE (&j);
1545    if (n >= 0) {
1546      for (int k = 0; k < n; k++) {
1547        UNSIGNED_T carry = (w & D_SIGN ? 0x1 : 0x0);
1548        w = (w << 1) | carry;
1549      }
1550    } else {
1551      n = -n;
1552      for (int k = 0; k < n; k++) {
1553        UNSIGNED_T carry = (w & 0x1 ? D_SIGN : 0x0);
1554        w = (w >> 1) | carry;
1555      }
1556    }
1557    PUSH_VALUE (p, w, A68G_BITS);
1558  }
1559  
1560  // OP ROR = (BITS, INT) BITS
1561  
1562  void genie_ror_bits (NODE_T * p)
1563  {
1564    A68G_INT *j;
1565    POP_OPERAND_ADDRESS (p, j, A68G_INT);
1566    VALUE (j) = -VALUE (j);
1567    genie_rol_bits (p);
1568  }
1569  
1570  // OP ELEM = (INT, BITS) BOOL
1571  
1572  void genie_elem_bits (NODE_T * p)
1573  {
1574    A68G_BITS j; A68G_INT i;
1575    UNSIGNED_T mask = 0x1;
1576    POP_OBJECT (p, &j, A68G_BITS);
1577    POP_OBJECT (p, &i, A68G_INT);
1578    PRELUDE_ERROR (VALUE (&i) < 1 || VALUE (&i) > A68G_BITS_WIDTH, p, ERROR_OUT_OF_BOUNDS, M_INT);
1579    for (int n = 0; n < (A68G_BITS_WIDTH - VALUE (&i)); n++) {
1580      mask = mask << 1;
1581    }
1582    PUSH_VALUE (p, (BOOL_T) ((VALUE (&j) & mask) != 0 ? A68G_TRUE : A68G_FALSE), A68G_BOOL);
1583  }
1584  
1585  // OP SET = (INT, BITS) BITS
1586  
1587  void genie_set_bits (NODE_T * p)
1588  {
1589    A68G_BITS j; A68G_INT i;
1590    UNSIGNED_T mask = 0x1;
1591    POP_OBJECT (p, &j, A68G_BITS);
1592    POP_OBJECT (p, &i, A68G_INT);
1593    PRELUDE_ERROR (VALUE (&i) < 1 || VALUE (&i) > A68G_BITS_WIDTH, p, ERROR_OUT_OF_BOUNDS, M_INT);
1594    for (int n = 0; n < (A68G_BITS_WIDTH - VALUE (&i)); n++) {
1595      mask = mask << 1;
1596    }
1597    PUSH_VALUE (p, VALUE (&j) | mask, A68G_BITS);
1598  }
1599  
1600  // OP CLEAR = (INT, BITS) BITS
1601  
1602  void genie_clear_bits (NODE_T * p)
1603  {
1604    A68G_BITS j; A68G_INT i;
1605    UNSIGNED_T mask = 0x1;
1606    POP_OBJECT (p, &j, A68G_BITS);
1607    POP_OBJECT (p, &i, A68G_INT);
1608    PRELUDE_ERROR (VALUE (&i) < 1 || VALUE (&i) > A68G_BITS_WIDTH, p, ERROR_OUT_OF_BOUNDS, M_INT);
1609    for (int n = 0; n < (A68G_BITS_WIDTH - VALUE (&i)); n++) {
1610      mask = mask << 1;
1611    }
1612    PUSH_VALUE (p, VALUE (&j) & ~mask, A68G_BITS);
1613  }
1614  
1615  // OP ABS = (BITS) INT
1616  
1617  void genie_abs_bits (NODE_T * p)
1618  {
1619    A68G_BITS i;
1620    POP_OBJECT (p, &i, A68G_BITS);
1621    PUSH_VALUE (p, (INT_T) (VALUE (&i)), A68G_INT);
1622  }
1623  
1624  // OP BIN = (INT) BITS
1625  
1626  void genie_bin_int (NODE_T * p)
1627  {
1628    A68G_INT i;
1629    POP_OBJECT (p, &i, A68G_INT);
1630    if (!MODULAR_MATH (p) && VALUE (&i) < 0) {
1631  // RR does not convert negative numbers.
1632      errno = EDOM;
1633      diagnostic (A68G_RUNTIME_ERROR, p, ERROR_OUT_OF_BOUNDS, M_BITS);
1634      exit_genie (p, A68G_RUNTIME_ERROR);
1635    }
1636    PUSH_VALUE (p, (UNSIGNED_T) (VALUE (&i)), A68G_BITS);
1637  }
1638  
1639  // @brief PROC ([] BOOL) BITS bits pack
1640  
1641  void genie_bits_pack (NODE_T * p)
1642  {
1643    A68G_ARRAY *arr; A68G_TUPLE *tup;
1644    A68G_REF z;
1645    POP_REF (p, &z);
1646    CHECK_REF (p, z, M_ROW_BOOL);
1647    GET_DESCRIPTOR (arr, tup, &z);
1648    size_t size = ROW_SIZE (tup);
1649    PRELUDE_ERROR (size < 0 || size > A68G_BITS_WIDTH, p, ERROR_OUT_OF_BOUNDS, M_ROW_BOOL);
1650    A68G_BITS b;
1651    VALUE (&b) = 0x0;
1652    if (ROW_SIZE (tup) > 0) {
1653      BYTE_T *base = DEREF (BYTE_T, &ARRAY (arr));
1654      UNSIGNED_T bit = 0x1;
1655      for (int k = UPB (tup); k >= LWB (tup); k--) {
1656        int addr = INDEX_1_DIM (arr, tup, k);
1657        A68G_BOOL *boo = (A68G_BOOL *) & (base[addr]);
1658        CHECK_INIT (p, INITIALISED (boo), M_BOOL);
1659        if (VALUE (boo)) {
1660          VALUE (&b) |= bit;
1661        }
1662        bit <<= 1;
1663      }
1664    }
1665    STATUS (&b) = INIT_MASK;
1666    PUSH_OBJECT (p, b, A68G_BITS);
1667  }
     


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