Introduction

REXX does not have an 'include' facility nor 'arbitrary precision' mathematical functions out of the box. In previous REXX entries it was custom the have all needed routines and procedures copied into the program. Newer entries redirect to
Libraries and Pre processor and Include clause how to use them.

At the end of each entry you'll find several 'include' clauses, showing the libraries that the program needs (cf '#include', 'import', 'uses' or '::requires').
The use of this tool is highly recommended. But you may always copy the source code into your program and do the text changes yourself, i.e. change all '[label]' to 'some_name' etc. if present.

Both Regina and ooRexx are supplied with a mathematical library, a DLL based on the C-library. This supports some basic math functions and a few constants, up to 16 digits precision. For many tasks on RosettaCode this is not sufficient.

This year I started posting on RosettaCode and found the copy-and-paste WoW to get a runnable program annoying. Therefore I'll gather all procedures I have until now and present them here in 6 libraries and several stand alone files. Other REXX entries will link to this page.

Many sources were helpful while creating these libraries. Credits go to:

  • Math functions in REXX: John Brock, Patrick McPhee, several sources
  • Code snippets RosettaCode: Gerard Schildberger, Walter Pachl
  • Wikipedia International
  • Wolfram Mathworld
  • Geeks for Geeks
  • Online Encyclopedia of Integer Sequences
  • Google
  • ChatGPT4
  • Numerical methods at work: Henrik Vestermark
  • Numerical recipes: Press et al
  • Various other books and internet math sources and online calculators
  • And my own research and try-outs

General remarks

For now, all procedures work only with real arguments and deliver real results. No complex arithmetic is supported yet.
Out of the box, REXX can work with arbitrary precision, thus also these procedures, using your current numeric digits setting. However, basic functions such as square root, pi or tangent start having problems at 1000 digits, and the more complex functions as gamma or zeta struggle already with 100 digits.
Basic parameter checks are present. In case of error, a procedure just returns 'X' (= forbidden) and your program will fail elsewhere. No fancy error trapping is present.
All routines are coded with the 'procedure' clause, meaning all variables within are local. They communicate via the parameters. However, sometimes it's handy or needed to use global variables (store multiple results, memorization). For this the stem 'glob.' is used, and every procedure has 'expose glob.' coded to make it available. Some procedures also use extra stems, like prim. or flag.
As you might guess, there are many cross references between the libraries.

Usage

Use the low profile pre processor (include pieces of code in a REXX program): Low profile REXX pre processor
or
Copy and paste (parts) of the libraries in your program

Mind the cross refs: if you copy Numbers, big chance you'll also need Functions and Constants.

Constants

A whole bunch of mathematical constants: Pi, E, Euler-Mascheroni and a lot more. Up to 100 digits, these constants are predefined and thus given directly. Above 100 digits, under availability of a acceptable fast algorithm, the constant is calculated. All procedures in this library have no parameters. The full list follows:

  • Apery: Apery constant
  • Artin: Artin constant
  • Backhouse: Backhouse constant
  • Bernstein: Bernstein constant
  • Bloch: Bloch constant
  • Bronze: Bronze ratio constant = positive root of x^2-3x-1
  • Brun: Brun constant
  • Cahen: Cahen constant
  • Capacity: Logarithmic capacity of the unit disk constant
  • Catalan1: Catalan constant
  • Chaitin: Chaitin constant
  • Champernowne: Champernowne constant
  • Conway2: Conway constant = real root of x^71-x^69-2x^68...-6x^2+3x-6
  • Copeland: Copeland-Erdos constant
  • Devicci: DeVicci constant = positive root of 4x^8-28x^6-7x^4+16x^2+16
  • Dottie: Dottie constant = root of Cos(x) - x
  • Dubois: Second Dubois-Reymond constant
  • E: Euler number
  • Embree: Embree-Trefethen constant
  • Erdos1: Erdos-Borwein constant
  • Erdos2: Erdos-Tenenbaum-Ford constant
  • Euler: Euler-Mascheroni constant
  • Feigenbaum1: Feigenbaum first constant
  • Feigenbaum2: Feigenbaum second constant
  • Feller: Feller-Tornier constant
  • Foias: Foias constant
  • Fraction: First continued fraction constant
  • Fransen: Fransen-Robertson constant
  • Gauss: Gauss constant
  • Gelfond1: Gelfond constant
  • Gelfond2: Gelfond-Schneider constant
  • Gieseking: Gieseking constant
  • Glaisher: Glaisher-Kinkelin constant
  • Golden: Golden ratio constant = root of x^2-x-1
  • Goldenangle: Golden angle constant
  • Golomb1: Golomb constant
  • Gompertz: Gompertz constant
  • Hafner: Hafner-Sarnak-McCurley constant
  • Heath: Heath-Brown-Moroz constant
  • Hermite: Second Hermite constant
  • Kepler: Kepler-Bouwkamp constant
  • Khinchin: Kinchin constant
  • Komornik: Komornik-Loreti constant
  • Landau1: Landau-Ramanujan constant
  • Landau2: Second Landau constant
  • Laplace: Laplace limit constant
  • Lebesgue2: Lebesgue constant
  • Lemniscate: Lemniscate constant
  • Levy1: Levy-Khinchin constant
  • Levy2: Second Levy constant
  • Lieb: Lieb constant
  • Ln2: Natural log of 2 constant
  • Ln4: Natural log of 4 constant
  • Ln8: Natural log of 8 constant
  • Ln10: Natural log of 10 constant
  • Loch: Loch constant
  • Magicangle: Magic angle constant
  • Meissel: Meissel-Mertens constant
  • Mills: Mills constant
  • Mrb: MRB constant
  • Nielsen: Nielsen-Ramanujan constant
  • Niven: Niven constant
  • Omega: Omega constant
  • Paperfolding: Paperfolding constant
  • Parabolic: Universal parabolic constant
  • Pi: Pi constant
  • Plastic: Plastic ratio constant = real root of x^3-x-1
  • Porter: Porter constant
  • Prouhet: Prouhet-Thue-Morse constant
  • Ramanujan: Ramanujan constant
  • Recifibo: Reciprocal Fibonacci constant
  • Robbins: Robbins constant
  • Salem: Salem constant = largest positive root of x^10+x^9-x^7-x^6-x^5-x^4-x^3+x+1
  • Sierpinski: Sierpinski constant
  • Silver: Silver ratio constant = positive root of x^2-2x-1
  • Soldner: Soldner constant
  • Somos: Somos quadratic recurrence constant
  • Sqrt2: Square root of 2 constant
  • Sqrt3: Square root of 3 constant
  • Sqrt5: Square root of 5 constant
  • Stephens: Stevens constant
  • Supergolden: Super golden ratio constant = real solution of x^3-x^2-1
  • Taniguchi: Taniguchi constant
  • Tau1: Tau constant = 2*pi
  • Tetranacci2: Tetranacci constant = root of x^4-x^3-x^2-x-1
  • Tribonacci2: Tribonacci constant = root of x^3-x^2-x-1
  • Twinprimes: Twin primes constant
  • Vanderpauw: Van der Pauw constant
  • Viswanath: Viswanath constant
  • Wallis: Wallis constant = real root of x^3-2x-5
  • Weierstrass: Weierstrass constant
  • Zscore: Z-score 97.5 percentile constant

Functions

Here we have the well known set of trigonometric, hyperbolic, exponential and logarithmic functions and their inverses. And of course functions like Square/Cubic/Quartic/Nth root. Some 'higher' functions are also included: Beta, Gamma, Zeta and a few more. Arguments for the trig functions is always in radians, maybe you like to use Deg or Rad to convert values. Several functions regarding number theory are present: Factorials, Combinations, Totient and more. The full list:

  • Ackerman: Ackerman's function
  • Acos: Arc cosine
  • Acosh: Arc cosine hyperbolic
  • Acot: Arc cotangent
  • Acoth: Arc cotangent hyperbolic
  • Acsc: Arc cosecant
  • Acsch: Arc cosecant hyperbolic
  • Agmean: Arithmetic geometric mean
  • Aliquot: Aliquot function = Sum of all divisors of x including 1
  • Alog: Antilog = 10^x
  • Amean: Arithmetic mean
  • Asec: Arc secant
  • Asech: Arc secant hyperbolic
  • Asin: Arc sine
  • Asinh: Arc sine hyperbolic
  • Atan: Arc tangent
  • Atanh: Arc tangent hyperbolic
  • Atan2: Arc tangent correct quadrant
  • Beta: Beta
  • Cbrt: Cubic root = x^(1/3)
  • Ceil: Ceiling
  • Comb: Combinations = binomial coefficients
  • Cos: Cosine
  • Cosh: Cosine hyperbolic
  • Cot: Cotangent
  • Coth: Cotangent hyperbolic
  • Csc: Cosecant
  • Csch: Cosecant hyperbolic
  • Deg: Radians->degrees
  • Dfact: Double factorial = n!!
  • Digamma: Digamma
  • Digitproduct: Digitproduct = product(digits)
  • Digitroot: Digital root
  • Digitsum: Digitsum = sum(digits)
  • Divisor: Divisor = sum(Divisors(x)^y)
  • Dxgamma: First derivative of Gamma
  • Dxzeta: First derivative of Zeta
  • Erf: Error
  • Erfc: Error complementary
  • Even: Is a number even?
  • Exp: Exponential = e^x
  • Fact: Factorial = n!
  • Factorial: Factorial = x!
  • Ffact: Falling factorial
  • Floor: Floor
  • Frac: Fractional part
  • Gamma: Gamma
  • Gcd: Greatest common divisor
  • Gmean: Geometric mean
  • Half: Is a number half integer?
  • Isqrt: Integer square root = Floor(x^(1/2))
  • Lambda1: Dirichlet lambda
  • Lambda2: Carmichael's lambda function = reduced totient function
  • Lambertw0: Lambert W0
  • Lambertwm1: Lambert W-1
  • Lcm: Least common multiple function
  • Ln: Natural logarithm
  • Log: Briggs logarithm
  • Logxy: Logarithm x base y
  • Mant: Mantissa
  • Nroot: Nth root = x^(1/n)
  • Odd: Is a number odd?
  • Perm: Permutations
  • Power: Power = x^y
  • Powermod: Power modulus = x^(y mod z)
  • Prim: Primorial = n#
  • Qtrt: Quartic root = x^(1/4)
  • Rad: Degrees->radians
  • Radical: Radical = product of unique prime factors
  • Rand: Random number between x and y max 12 digits precision
  • Repunit: Repeated 1's
  • Rfact: Rising factorial
  • Round: Round to nearest integer
  • Sec: Secant
  • Sech: Secant hyperbolic
  • Sigma: Sigma = Sum of all divisors of x including 1 and x
  • Sin: Sine
  • Sinh: Sine hyperbolic
  • Sqrt: Square root = x^(1/2)
  • Tan: Tangent
  • Tanh: Tangent hyperbolic
  • Tau2: Ramanujan Tau
  • Totient: Euler's totient function = Phi
  • Trigamma: Trigamma
  • Xpon: Exponent
  • Whole: Is a number integer?
  • Zeta: Zeta

Numbers

These are procedures belonging to the field 'number theory or sequences': all kinds of numbers, permutations, combinations, factors, divisors, sequences and more. Some of these procedures come in pairs: i.e. Prime(number) checks if number is prime and Primes(threshold) gives the number of primes <= threshold and stores all these primes in prim. Most procedures expect a number as parameter, some two numbers. Many of these procedures become quite slow as the numbers grow. The full list:

  • Abundant: Is a number abundant?
  • Abundants: Abundant numbers
  • Additiveprime: Is a number additive prime?
  • Additiveprimes: Additive prime numbers
  • Almostprime: Is a number almost k-prime?
  • Alcuin: Alcuin numbers
  • Amicables: Amicable number pairs
  • Arithmetic: Is a number arithmetic?
  • Arithmetics: Arithmetic numbers
  • Bell: Bell numbers
  • Beraha: Beraha numbers
  • Bernoulli: Bernoulli numbers
  • Cake: Cake numbers
  • Carmichaels: Carmichael 3 strong prime numbers
  • Catalan2: Catalan numbers
  • Caterer: Lazy caterer's numbers
  • Central: Central binomial coefficient numbers
  • Chowla: Chowla numbers
  • Composite: Is a number composite?
  • Composites: Composite numbers = not prime
  • Conway1: Conway look-and-say numbers
  • Coprime: Are 2 numbers coprime?
  • Cullen: Cullen numbers
  • Deficient: Is a number deficient?
  • Deficients: Deficient numbers
  • Derangement: Derangement numbers
  • Divisors: Divisors of an integer
  • Efactors: Prime factors with exponent
  • Euclids: Euclid-Mullin numbers
  • Factors: Prime factors of an integer
  • Fareys: Farey fraction numbers
  • Favard: Favard numbers
  • Fermat: Fermat numbers
  • Fibonacci: Fibonacci numbers
  • Giugas: Giuga numbers
  • Golomb2: Golomb-Silverman numbers
  • Gould: Gould numbers
  • Gregory1: Gregory numbers 1
  • Gregory2: Gregory numbers 2
  • Harmonic: Harmonic numbers
  • Highcomposite: Is a number highly composite?
  • Highcomposites: Highly composite numbers
  • Jacobsthal: Jacobsthal numbers
  • Kaprekar: Is a number Kaprekar?
  • Kaprekars: Kaprekar numbers
  • Lah: Lah numbers
  • Lebesgue1: Lebesgue numbers
  • Leonardo: Leonardo numbers
  • Lucas: Lucas numbers
  • Magic: Magic numbers
  • Metallic: Metallic ratio numbers
  • Moebius: Moebius numbers
  • Motzkin: Motzkin numbers
  • Narayana: Narayana cows numbers
  • Padovan: Padovan numbers
  • Partition: Partition numbers
  • Pell1: Pell numbers
  • Pell2: Pell-Lucas companion numbers
  • Perfect: Is a number perfect?
  • Perfects: Perfect numbers
  • Perrin: Perrin numbers
  • Persistence: Additive persistence
  • Practical: Is a number practical?
  • Practicals: Practical numbers
  • Prime: Is a number prime?
  • Primes: Prime numbers
  • Pronic: Pronic numbers
  • Recaman: Recaman numbers
  • Semiprime: Is a number semi prime?
  • Sorting: Sorting numbers
  • Stirling1: Stirling first kind numbers
  • Stirling2: Stirling second kind numbers
  • Sylvester: Sylvester numbers
  • Tetranacci1: Tetranacci numbers
  • Thue: Thue-Morse numbers
  • Totients: Euler's totient series = Phi
  • Tribonacci1: Tribonacci numbers
  • Ufactors: Unique prime factors of an integer
  • Ulam: Ulam numbers
  • Wedderburn: Wedderburn numbers
  • Woodall: Woodall numbers
  • Zigzag: Zigzag or alternating permutations numbers

Polynomial

Two procedures, used elsewhere, deal with the first derivative or value of a polynomial. They both have a string with coefficients as parameter, highest power first, zero entries included:2x^3+x+3 = '2 0 1 3'. Pdiff returns as string in this format, which than may be evaluated using Peval. The list:

  • Pdiff: Polynomial differentiation function
  • Peval: Polynomial evaluation function

Rational

One of the tasks on RosettaCode is 'rational arithmetic'. The most important procedures from this field are included here. Besides the second parameter of Rpower, all arguments in and out have the form 'numerator/denominator'. The list:

  • Rabs: Rational absolute value function
  • Radd: Rational add function
  • Rdivide: Rational divide function
  • Rinvert: Rational invert function
  • Rmultiply: Rational multiply function
  • Rnegate: Rational negate function
  • Rpower: Rational power function
  • Rrational: Integer->Rational function
  • Rsimplify: Rational simplify function
  • Rsubtract: Rational subtract function

Roots

For equations of the second to fourth degree solutions in closed form (formulas) are possible. Procedures for these equations are present here. The input follows the convention as described in Polynomial: so solving x^2-3x+2=0 is represented by parameter '1 -3 2'. The list:

  • Cbeq: Cubic roots of ax^3+bx^2+cx+d = 0
  • Qteq: Quartic roots of ax^4+bx^3+cx^2+dx+e = 0
  • Sqeq: Square roots of ax^2+bx+c = 0

Generic Quicksort

If you are willing to adopt a specific structure of your stems, this procedure is able to sort a 'composite stem', on 1 or more key tails, syncing 0 or more data tails. Any number of keys or data is allowed. Sorting may be ascending or descending, string or numeric. The procedure is highly optimized to handle both small and large stems.

The mentioned structure goes as follows. Let's use a 'database' approach. A (classic relational) database has tables, each table has columns. Some of these columns may be key columns, other may be data columns. Represent this in REXX with stems:

  • table. (a stem for each table)
  • table.0 = n (number of rows)
  • table.col1.x (first column with row number)
  • table.col2.x (second column with row number)
  • table.col3.x (third column with row number)
  • etc

Of course put your own names for 'table', 'col1' etc. This naming convention closely mimics the fully qualified names for tables and columns in SQL, and shows clearly the relation between the tails as belonging to the head 'table.'. Exposing only 'table.' to a procedure makes the number of rows and all columns available.

A call to this generic quicksort might look like

table = 'table.'; keys = 'key1. key2.' ; data = 'data1.'
call <your name> table,keys,data
...
include Quicksort [label]=<your name>

Keys and data specify your key and data columns, separated by a space. The table and at least 1 key must be given, but data may be empty. Always include the period in your names.
Default the sort is numeric ascending. By specifying special values with your include of this routine you may create copies that behave different:

  • [lt]=> [gt]=< for a descending sort
  • [lt]=<< [eq]=== [gt]=>> for a ascending string sort
  • [lt]=>> [eq]=== [gt]=<< for a descending string sort

For a real world example see [states, cities and population] (Realistic example, Version 3).

Customized Quicksorts

Above procedure is beautiful and generic, but also slow compared to customized sorts (by about a factor 4). Therefore I include here predefined procedures for various numbers of keys and columns. If you have big stems (say 100,000 items or more), you may want to use these faster sorts. There are 12 templates for 1-3 key columns and 0-3 data columns, named Quicksortkd (k = number of key columns, d = number of data columns), i.e. Quicksort21 will sort on 2 keys, while syncing 1 data. For each combination keys/data you'll have a separate procedure generated. A call to such a customized routine might look like

call <your name>
...
include Quicksort21 [label=<your name> [table]=<your stem.> [key1]=<first key.> [key2]=<second key.> [data1]=<data to sync.>

Always include the period in your names. Defaults for and control of ascending/descending/numeric/string is the same as for the generic sort.
For a real world example see [states, cities and population] (Realistic example, Version 2).

Abnormal end handler

This is a standard handler of the REXX conditions causing a program to stop, such as SYNTAX, NOVALUE, NOTREADY and HALT. There are 2 parts: a code snippet Settings to set the conditions and a library Abend to handle them. Include Settings always at the beginning of your program or main procedure if present. And include Abend at the end.

Consider below program. Name it Abend.rex if want to try it.

Main:
include Settings
say version; say 'Abnormal program end handler'; say
call TriggerSyntax
call TriggerNovalue
call TriggerNotready
call TriggerHalt
exit

TriggerSyntax:
procedure
say 'Trigger syntax...'
a = 1; b = 2; c = 3
say a+b b-c c/0
return

TriggerNovalue:
procedure
say 'Trigger no value...'
a = 1; b = 2; c = 3; d = absent; e = 1/d
return

TriggerNotready:
procedure
say 'Trigger not ready...'
file = 'absent'
call Stream file,'c','open read'
return

TriggerHalt:
procedure
say 'Trigger halt...'
do forever
   a = 1; b = 2; c = 3
end
return

include Abend

Using 'rexx|regina run Abend' will generate Runner.rex:

/* Program : abend */
/* Build   : 15 Sep 2024 04:10:27 */
/* Run     : 15 Sep 2024 04:26:10 */

Main:
/* Include : Settings */
/* Build   : 14 Sep 2024 14:17:10 */
/* Global settings snippet - Build 14 Sep 2024 */
/* (C) Paul van den Eertwegh 2024 */

parse arg parms; parse version version
call Time('r'); call Lines 'Dummy'; glob. = ''
signal on halt name Abend
signal on notready name Abend
signal on novalue name Abend
signal on syntax name Abend
/* End     : Settings */

say version; say 'Abnormal program end handler'; say
call TriggerSyntax
call TriggerNovalue
call TriggerNotready
call TriggerHalt
exit

TriggerSyntax:
procedure
say 'Trigger syntax...'
a = 1; b = 2; c = 3
say a+b b-c c/0
return

TriggerNovalue:
procedure
say 'Trigger no value...'
a = 1; b = 2; c = 3; d = absent; e = 1/d
return

TriggerNotready:
procedure
say 'Trigger not ready...'
file = 'absent'
call Stream file,'c','open read'
return

TriggerHalt:
procedure
say 'Trigger halt...'
do forever
   a = 1; b = 2; c = 3
end
return

/* Include : Abend */
/* Build   : 7 Sep 2024 17:54:35 */
/* Abnormal end condition handler library - Build 7 Sep 2024 */
/* (C) Paul van den Eertwegh 2024 */

Abend:
trace off
signal off halt
signal off notready
signal off novalue
signal off syntax
ss = Strip(SourceLine(sigl))
vv. = 0
say
say 'Proces  : Runner'
say 'Line    :' sigl ss
ss = Translate(ss,"                ","+-*|<>,;=/\%()'")
do xx = 1 to Words(ss)
   ww = Word(ss,xx)
   if Symbol(ww) = 'VAR' then do
      call Variable
      if Pos('.',ww) > 0 then do
         tt = Translate(ww," ",".")
         do yy = 2 to Words(tt)
            ww = Word(tt,yy)
            call Variable
         end
      end
   end
end
cc = condition('c'); dd = condition('d')
do xx = 1 to vv.0
   vv = vv.xx
   if Symbol(vv) = 'VAR' then
      if dd = 'DUMMY' then
         interpret 'say' "'Arg     :'" 'vv' "'='" vv
      else
         interpret 'say' "'Var     :'" 'vv' "'='" vv
end
select
   when dd = 'DUMMY' then
      cc = 'Argument outside domain or invalid'
   when cc = 'HALT' then
      cc = 'Program interrupted'
   when cc = 'NOTREADY' then
      cc = 'File does not exist or is in use'
   when cc = 'NOVALUE' then
      cc = 'Variable has no value'
   when cc = 'SYNTAX' then
      cc = 'Runtime error'
   otherwise
      cc = ''
end
if cc <> '' then
   say 'Signal  :' cc
if dd <> 'DUMMY' then do
   if DataType(rc) = 'NUM' then
      if rc >= 0 then
         say 'Error   :' rc ErrorText(rc)
      else
         say 'Error   :' rc
   if dd <> '' then
      if dd <> 'SIGINT' then
         say 'Reason  :' dd
end
exit

Variable:
do zz = 1 to vv.0
   if ww = vv.zz then
      leave
end
if zz > vv.0 then do
   vv.zz = ww; vv.0 = zz
end
return
/* End     : Abend */

/* abend.rex 38 lines */
/* \Rex\General\Settings.inc 9 lines */
/* \Rex\General\Abend.inc 74 lines */

/* Total 121 lines */
/* Took 5 milliseconds */

If I comment out the trap condition settings in this program and Run.rex and run successively the 4 calls in Main:, then I get the standard error handling.

REXX-Regina_3.9.6(MT) 5.00 29 Apr 2024
Abnormal program end handler

Trigger syntax...
    20 +++    say a+b b-c c/0
    10 +++ call TriggerSyntax
Error 42 running "C:\Rex\Rosetta\Runner.rex", line 20: Arithmetic overflow/underflow
Error 42.3: Arithmetic overflow; divisor must not be zero
   126 *-* 'regina' runner parms
       +++ RC=-1073741782 +++

Trigger no value...
    26 +++    e = 1/d
    11 +++ call TriggerNovalue
Error 41 running "C:\Rex\Rosetta\Runner.rex", line 26: Bad arithmetic conversion
Error 41.2: Non-numeric value ("ABSENT") to right of arithmetic operation "/"
   126 *-* 'regina' runner parms
       +++ RC=-1073741783 +++

Trigger not ready...

Trigger halt...
    39 +++       do forever
    13 +++    call TriggerHalt
Error 4 running "C:\Rex\Rosetta\Runner.rex", line 39: Program interrupted
   126 *-* 'regina' runner parms
       +++ RC=-1073741820 +++
   126 +++ 'regina' runner parms
Error 4 running "C:\Rex\Rosetta\run.rex", line 126: Program interrupted

The 'NOVALUE' condition is standard not triggered. Very likely your program will fail somewhere else. The 'NOTREADY' condition is standard also not triggered. Your program might fail elsewhere or produce no output. An advantage of this standard approach is the showing of the 'call stack', i.e. runner -> abend -> call Trigger... -> clause in error. This helps very much while debugging.

Now, the same action with all condition traps enabled, produces following output.

REXX-Regina_3.9.6(MT) 5.00 29 Apr 2024
Abnormal program end handler

Trigger syntax...

Proces  : Runner
Line    : 33 say a+b b-c c/0
Var     : a = 1
Var     : b = 2
Var     : c = 3
Signal  : Runtime error
Error   : 42 Arithmetic overflow/underflow
Reason  : Error 42.3: Arithmetic overflow; divisor must not be zero

Trigger no value...

Proces  : Runner
Line    : 39 a = 1; b = 2; c = 3; d = absent; e = 1/d
Var     : a = 1
Var     : b = 2
Var     : c = 3
Signal  : Variable has no value
Reason  : ABSENT

Trigger not ready...

Proces  : Runner
Line    : 46 call Stream file,'c','open read'
Var     : file = absent
Signal  : File does not exist or is in use
Reason  : absent

Trigger halt...

Proces  : Runner
Line    : 53 a = 1; b = 2; c = 3
Var     : a = 1
Var     : b = 2
Var     : c = 3
Signal  : Program interrupted

Proces  : Run
Program : abend
Signal  : Program interrupted
Error   : 0

Nice layout... and it shows the values of all recognized variables for the line in error.

It's up to you which method you prefer. You may easily switch between them by disabling/enabling 'Include Settings'.