== Part 1: the Formula page, cas = giac, 77 parameter sets ==
  Normal             [0.0, 1.0, 0.0]            tail 1  badge exact (CAS)   1057 ms  mean ok; e2 ok; var ok
  Uniform            [0.0, 1.0, 0.0]            tail 1  badge exact (CAS)    331 ms  mean ok; e2 ok; var ok
  Exponential        [1.0, 0.0, 0.0]            tail 1  badge exact (CAS)    368 ms  mean ok; e2 ok; var ok; cdf ok
  Weibull            [2.0, 1.0, 0.0]            tail 1  badge exact (CAS)    520 ms  mean ok; e2 ok; var ok; cdf ok
  LogNormal          [0.0, 1.0, 0.0]            tail 1  badge exact (CAS)    293 ms  mean ok; e2 ok; var ok
  Laplace            [0.0, 1.0, 0.0]            tail 1  badge exact (CAS)    871 ms  mean ok; e2 ok; var ok
  Student t          [10.0, 0.0, 0.0]           tail 1  badge exact (CAS)    785 ms  mean ok; e2 ok; var ok
  Chi-square         [10.0, 0.0, 0.0]           tail 1  badge exact (CAS)   1800 ms  mean ok; e2 ok; var ok
  Fisher F           [10.0, 15.0, 0.0]          tail 1  badge exact (CAS)   1005 ms  mean ok; e2 ok; var ok
  Burr XII           [2.0, 2.0, 1.0]            tail 1  badge exact (CAS)    762 ms  mean ok; e2 ok; var ok
  Gumbel (max)       [0.0, 1.0, 0.0]            tail 1  badge decimal        253 ms  mean not shown: left undone; e2 not shown: left undone
  Pareto             [1.0, 3.0, 0.0]            tail 1  badge exact (CAS)    430 ms  mean ok; e2 ok; var ok; cdf ok
  Rayleigh           [1.5, 0.0, 0.0]            tail 1  badge exact (CAS)    459 ms  mean ok; e2 ok; var ok
  Logistic           [0.0, 1.0, 0.0]            tail 1  badge exact (CAS)    266 ms  mean ok; e2 not shown: disagreed with the program (-pi^2/3)
  Binomial           [20.0, 0.5, 0.0]           tail 1  badge exact (CAS)    418 ms  prob ok; pmf ok; mean ok
  Poisson            [5.0, 0.0, 0.0]            tail 1  badge exact (CAS)    200 ms  prob ok; pmf ok
  Geometric          [0.3, 0.0, 0.0]            tail 1  badge exact (CAS)    173 ms  prob ok; pmf ok
  Triangular         [2.0, 5.0, 12.0]           tail 1  badge exact (CAS)    278 ms  mean ok; e2 ok; var ok
  Cauchy             [0.0, 1.0, 0.0]            tail 1  badge exact (CAS)    100 ms  mean infinite; e2 infinite
  Frechet            [3.0, 1.0, 0.0]            tail 1  badge decimal        114 ms  mean not shown: left undone; e2 not shown: left undone
  Gompertz           [0.01, 0.085, 0.0]         tail 1  badge decimal        669 ms  mean not shown: left undone; e2 not shown: left undone
  Maxwell-Boltzmann  [1.0, 0.0, 0.0]            tail 1  badge exact (CAS)    510 ms  mean ok; e2 ok; var ok
  Erlang             [3.0, 1.0, 0.0]            tail 1  badge exact (CAS)    409 ms  mean ok; e2 ok; var ok
  Gamma              [2.5, 2.0, 0.0]            tail 1  badge exact (CAS)   2058 ms  mean ok; e2 ok; var ok
  Beta               [2.0, 5.0, 0.0]            tail 1  badge exact (CAS)   1326 ms  mean ok; e2 ok; var ok
  Negative binomial  [3.0, 0.4, 0.0]            tail 1  badge exact (CAS)    621 ms  prob ok; pmf ok
  Hypergeometric     [50.0, 40.0, 6.0]          tail 1  badge exact (CAS)    280 ms  prob ok; pmf ok; mean ok
  Exponential        [0.5, 0.0, 0.0]            tail 1  badge exact (CAS)    418 ms  mean ok; e2 ok; var ok; cdf ok
  Normal             [100.0, 15.0, 0.0]         tail 1  badge exact (CAS)    288 ms  mean ok; e2 ok; var ok
  Weibull            [2.5, 3.0, 0.0]            tail 1  badge exact (CAS)    484 ms  mean ok; e2 ok; var ok; cdf ok
  LogNormal          [0.5, 0.25, 0.0]           tail 1  badge exact (CAS)    324 ms  mean ok; e2 ok; var ok
  Laplace            [1.0, 2.0, 0.0]            tail 1  badge exact (CAS)    397 ms  mean ok; e2 ok; var ok
  Student t          [1.0, 0.0, 0.0]            tail 1  badge exact (CAS)     91 ms  mean infinite; e2 infinite
  Student t          [2.0, 0.0, 0.0]            tail 1  badge exact (CAS)    171 ms  mean ok; e2 infinite
  Student t          [5.0, 0.0, 0.0]            tail 1  badge exact (CAS)    266 ms  mean ok; e2 ok; var ok
  Chi-square         [3.0, 0.0, 0.0]            tail 1  badge exact (CAS)    388 ms  mean ok; e2 ok; var ok
  Chi-square         [2.5, 0.0, 0.0]            tail 1  badge exact (CAS)    303 ms  mean ok; e2 ok; var ok
  Fisher F           [4.0, 6.0, 0.0]            tail 1  badge exact (CAS)    360 ms  mean ok; e2 ok; var ok
  Fisher F           [4.0, 2.0, 0.0]            tail 1  badge exact (CAS)    174 ms  mean infinite; e2 infinite
  Burr XII           [3.0, 2.5, 2.0]            tail 1  badge decimal        235 ms  mean not shown: left undone; e2 not shown: left undone
  Burr XII           [1.0, 1.0, 1.0]            tail 1  badge exact (CAS)     69 ms  mean infinite; e2 infinite
  Pareto             [5.0, 1.5, 0.0]            tail 1  badge exact (CAS)    315 ms  mean ok; e2 infinite; cdf ok
  Pareto             [1.0, 1.0, 0.0]            tail 1  badge exact (CAS)    452 ms  mean infinite; e2 infinite; cdf ok
  Pareto             [2.0, 2.5, 0.0]            tail 1  badge exact (CAS)    920 ms  mean ok; e2 ok; var ok; cdf ok
  Rayleigh           [2.0, 0.0, 0.0]            tail 1  badge exact (CAS)    324 ms  mean ok; e2 ok; var ok
  Logistic           [1.0, 2.0, 0.0]            tail 1  badge exact (CAS)    190 ms  mean ok; e2 not shown: left undone
  Triangular         [2.0, 2.0, 12.0]           tail 1  badge exact (CAS)    522 ms  mean ok; e2 ok; var ok
  Triangular         [0.0, 10.0, 10.0]          tail 1  badge exact (CAS)    335 ms  mean ok; e2 ok; var ok
  Cauchy             [3.0, 0.5, 0.0]            tail 1  badge exact (CAS)     79 ms  mean infinite; e2 infinite
  Frechet            [1.5, 2.0, 1.0]            tail 1  badge decimal        136 ms  mean not shown: left undone; e2 not shown: left undone
  Maxwell-Boltzmann  [2.0, 0.0, 0.0]            tail 1  badge exact (CAS)    397 ms  mean ok; e2 ok; var ok
  Erlang             [2.0, 0.5, 0.0]            tail 1  badge exact (CAS)    350 ms  mean ok; e2 ok; var ok
  Gamma              [0.5, 1.0, 0.0]            tail 1  badge exact (CAS)    321 ms  mean ok; e2 ok; var ok
  Gamma              [3.0, 2.0, 0.0]            tail 1  badge exact (CAS)    296 ms  mean ok; e2 ok; var ok
  Beta               [0.5, 0.5, 0.0]            tail 1  badge exact (CAS)   1851 ms  mean ok; e2 ok; var ok
  Beta               [0.3, 4.0, 0.0]            tail 1  badge exact (CAS)    284 ms  mean ok; e2 ok; var ok
  Uniform            [-1.5, 4.0, 0.0]           tail 1  badge exact (CAS)    469 ms  mean ok; e2 ok; var ok
  Gumbel (max)       [2.0, 3.0, 0.0]            tail 1  badge decimal       2757 ms  mean not shown: left undone; e2 not shown: left undone
  Exponential        [0.3333, 0.0, 0.0]         tail 1  badge exact (CAS)   1933 ms  mean ok; e2 ok; var ok; cdf ok
  Normal             [2.0, 0.3333, 0.0]         tail 1  badge exact (CAS)    266 ms  mean ok; e2 ok; var ok
  Weibull            [2.0, 0.3333, 0.0]         tail 1  badge exact (CAS)    502 ms  mean ok; e2 ok; var ok; cdf ok
  Pareto             [1.0, 0.3333, 0.0]         tail 1  badge exact (CAS)    685 ms  mean not shown: left undone; e2 not shown: left undone; cdf ok
  Rayleigh           [3.1416, 0.0, 0.0]         tail 1  badge exact (CAS)    512 ms  mean ok; e2 ok; var ok
  Gamma              [2.0, 0.3333, 0.0]         tail 1  badge exact (CAS)   1419 ms  mean ok; e2 ok; var ok
  Binomial           [20.0, 0.5, 0.0]           tail 2  badge exact (CAS)    344 ms  prob ok; pmf ok; mean ok
  Binomial           [20.0, 0.37, 0.0]          tail 3  badge exact (CAS)    256 ms  prob ok; mean ok
  Binomial           [5.0, 0.3333, 0.0]         tail 1  badge exact (CAS)    397 ms  prob ok; pmf ok; mean ok
  Poisson            [5.0, 0.0, 0.0]            tail 2  badge exact (CAS)    206 ms  prob ok; pmf ok
  Poisson            [2.5, 0.0, 0.0]            tail 3  badge exact (CAS)     96 ms  prob ok
  Poisson            [0.3333, 0.0, 0.0]         tail 1  badge exact (CAS)    178 ms  prob ok; pmf ok
  Geometric          [0.3, 0.0, 0.0]            tail 2  badge exact (CAS)    189 ms  prob ok; pmf ok
  Negative binomial  [3.0, 0.4, 0.0]            tail 3  badge exact (CAS)     94 ms  prob ok
  Hypergeometric     [50.0, 40.0, 6.0]          tail 2  badge exact (CAS)    228 ms  prob ok; pmf ok; mean ok
  Hypergeometric     [1000.0, 400.0, 50.0]      tail 1  badge exact (CAS)    315 ms  prob ok; pmf ok; mean ok
  Binomial           [500.0, 0.5, 0.0]          tail 1  badge decimal          0 ms  (no CAS: These numbers are too large for an exact sum)
  Exponential        [0.5, 0.0, 0.0]            tail 3  badge exact (CAS)    325 ms  mean ok; e2 ok; var ok; cdf ok
  Pareto             [1.0, 3.0, 0.0]            tail 2  badge exact (CAS)    293 ms  mean ok; e2 ok; var ok; cdf ok

  [ok] every CAS answer the page shows agrees with SciPy (no wrong formula) -- 197 shown and correct, 16 rejected, 0 wrong
  [ok] exact comparisons (fractions / SymPy integrals) agree -- 98 of 98
  Giac time over all 77 pages: 38.6 s; slowest page 2757 ms (Gumbel (max) [2.0, 3.0, 0.0])

== Part 2: cas = fail, all 27 families at their defaults ==
  [ok] all 27: "decimal" badge, the program's decimals, no runtime error -- []

== Part 3: the touch and key paths ==
  [ok] More, More: page 3 is {Formula, Help, , , Menu, More}
  [ok] page 2 still {Edit, Numbers, CDF, Refit, Menu, More}
  [ok] page 3, Formula: the Formula page opens (1 screens) and asks the CAS
  [ok] page 3, Help: the help pages open (2.7d: the title says v2.7d)
  [ok] page 3, Menu: leaves the plot
  [ok] More three times comes back to page 1 -- ['P<=x', 'P>x', 'a<X<b', 'Zoom−', 'Zoom+', 'More']
  [ok] Enter -> "Plot options" item 2 is "Formula page (CAS)" -- ['Numbers page', 'Formula page (CAS)', 'CDF curve on/off']
  [ok] opened twice from the options: built once (8 CAS calls), shown twice
  [ok] a drag on the plot (6 frames) calls the CAS 0 times
  [ok] new parameters: the page is rebuilt (8 CAS calls), mean 4 shown
  [ok] the plot frame (texts, shapes, soft keys) is identical to v2.6 for 5 distributions
  [ok] st_Cas drops one surrounding pair of quotes: '"1/2"' -> '1/2'; "undef" -> ''; 2.7a: the infinity signs -> '', ''

== Part 4 (2.7a): v2.7 in harness v3d; the infinity probe; the glyph refusals ==
  [ok] 2.7a: v2.7 in v3b shows no closed form (badge ['decimal']) -- the emulator's finding
  [ok] 2.7a: Exponential(0.5): exact page, every CAS text asks for string(...), every answer quoted, no CAS variable assigned, no CAS call of a variable
  [ok] 2.7a: Cauchy [0.0, 1.0, 0.0]: the probe exp(-(...)) answered ['0', '0']; "NO mean" 1 (want 1), "NO variance" 1 (want 1)
  [ok] 2.7a: Student t [1.0, 0.0, 0.0]: the probe exp(-(...)) answered ['0', '0']; "NO mean" 1 (want 1), "NO variance" 1 (want 1)
  [ok] 2.7a: Student t [2.0, 0.0, 0.0]: the probe exp(-(...)) answered ['0']; "NO mean" 0 (want 0), "NO variance" 1 (want 1)
  [ok] 2.7a: Fisher F [4.0, 2.0, 0.0]: the probe exp(-(...)) answered ['0', '0']; "NO mean" 1 (want 1), "NO variance" 1 (want 1)
  [ok] 2.7a: Burr XII [1.0, 1.0, 1.0]: the probe exp(-(...)) answered ['0', '0']; "NO mean" 1 (want 1), "NO variance" 1 (want 1)
  [ok] 2.7a: Pareto [1.0, 1.0, 0.0]: the probe exp(-(...)) answered ['0', '0']; "NO mean" 1 (want 1), "NO variance" 1 (want 1)
  [ok] 2.7a: Pareto [5.0, 1.5, 0.0]: the probe exp(-(...)) answered ['0']; "NO mean" 0 (want 0), "NO variance" 1 (want 1)
  [ok] 2.7a: Cauchy [3.0, 0.5, 0.0]: the probe exp(-(...)) answered ['0', '0']; "NO mean" 1 (want 1), "NO variance" 1 (want 1)
  [ok] 2.7a: exp(-(simplify(int(stqx*exp(-stqx),stqx,0,inf)))) = 1/e^(1) -> 0.0
  [ok] 2.7a: exp(-(simplify(int(-stqx/(pi*(1+stqx^2)),stqx,0,in)) = ∞ -> refused by st_Cas
  [ok] 2.7a: exp(-(simplify(int(stqx/(pi*(1+stqx^2)),stqx,0,inf)) = 0 -> 1.0
  [ok] 2.7a: exp(-(simplify(int(stqx/(pi*(1+stqx^2)),stqx,0,1)))) = e^(-ln(2)/(2*pi)) -> 0.0
  [ok] 2.7a: st_FmGood refuses '∫(stqx^2,stqx,0,1)'
  [ok] 2.7a: st_FmGood refuses '∑(stqk,stqk,0,5)'
  [ok] 2.7a: st_FmGood refuses 'Σ(stqk,stqk,0,5)'
  [ok] 2.7a: st_FmGood still takes an ordinary closed form

== Part 5 (2.7b): a fractional df for the chi-square and F; the INPUT labels ==
  [ok] 5a v2.7a in v3d: ChiSquare df 2.5 stops with "Invalid input" (the emulator's finding) -- CHISQUARE_CDF: Invalid input (df = 2.5 is not a whole number; the calculator's chi-square and F CDF and ICDF take whole-
  [ok] 5a v2.7b: ChiSquare df 2.5, P(X <= 5) = 0.876911 (SciPy 0.876911), no error -- StatDist: P(X <= 5) = 0.876911 None
  [ok] 5a v2.7b: the plot is drawn (the shaded tail and the P readout) -- 1
  [ok] 5a v2.7b: ChiSquare df 2.5, P(X > 5) = 0.123089 -- StatDist: P(X > 5) = 0.123089 None
  [ok] 5a v2.7a in v3d: F(2.5, 7.5) stops with "Invalid input" too -- FISHER_CDF: Invalid input (df = 2.5 is not a whole number; the calculator's chi-square and F CDF and ICDF take whole-num
  [ok] 5a v2.7b: F(2.5, 7.5), P(X <= 2) = 0.800427 (SciPy; the emulator table: 0.80043) -- StatDist: P(X <= 2) = 0.800427 None
  [ok] 5a v2.7b: F(4, 2.5) Between at its default bounds (one df whole, one not) = SciPy: StatDist: P(0.5 < X < 2) = 0.421381 -- None
  [ok] 5a v2.7b: a whole df still uses CHISQUARE_CDF (the emulator's Chi-square(4): 0.712703) -- StatDist: P(X <= 5) = 0.712703 ['CHISQUARE', 'CHISQUARE_CDF', 'CHISQUARE_ICDF']
  [ok] 5b chi-square, 7 fractional df x 8 x: CDF = SciPy chi2.cdf within 1E-9 (3.1e-12)
  [ok] 5b chi-square, fractional df: the density (the built-in, which takes any df) = SciPy (rel 0.0e+00)
  [ok] 5b chi-square, fractional df: the quantile (bisection on the new CDF; it fits the window) = chi2.ppf, |error| / (1 + x) 1.0e-10
  [ok] 5b F, 7 df pairs (one or both fractional) x 7 x: CDF = SciPy f.cdf within 1E-9 (1.1e-11)
  [ok] 5b F, fractional df: the density by the formula = SciPy f.pdf, rel 2.1e-11
  [ok] 5b F, fractional df: the quantile (bisection, as before) = f.ppf, |error| / (1 + x) 3.9e-11
  worst: chi cdf 3.1e-12, F cdf 1.1e-11, F pdf 2.1e-11, chi q 1.0e-10, F q 3.9e-11, chi pdf 0.0e+00
  [ok] 5c no CHISQUARE_CDF/_ICDF, FISHER_CDF/_ICDF or FISHER density call with a fractional df (56 calls checked) -- []
  [ok] 5c no warning about an unmeasured fractional-df F density
  [ok] 5c the plot (fit, cache, all three tails) for 5 fractional-df cases: no error -- []
  [ok] 5c Erlang(3, 1.5): CHISQUARE_CDF(6, ...) = SciPy erlang.cdf (0.576810)
  [ok] 5c Poisson(4) Between 0 and 5: 0.785130 = SciPy, no POISSON_CDF(4, -1) (v3c would raise)
  [ok] 5d no INPUT label is longer than 14 characters (133 labels; the longest: "k (successes):", 14)
  [ok] 5d "Degrees of freedom:", "Denominator df:", "K (positives in N):" are gone
  [ok] 5d the chi-square form reads "df:" and "X value:" -- ['df:', 'X value:']
  [ok] 5d the F form reads "df1:", "df2:" with "Numerator df > 0", "Denominator df > 0" under them -- ['df1:', 'df2:', 'X value:']
  [ok] 5e routines that differ from v2.7a: ['st_ask_cauchy', 'st_ask_chisquare', 'st_ask_fisher', 'st_ask_hypergeom', 'st_ask_student', 'st_cdf', 'st_pdf', 'st_show_help'] -- want ['st_ask_cauchy', 'st_ask_chisquare', 'st_ask_fisher', 'st_ask_hypergeom', 'st_ask_student', 'st_cdf', 'st_pdf', 'st_show_help']
  [ok] 5e outside those routines only comments differ
  [ok] 5e the #PYTHON blocks (if any) are unchanged
  [ok] 5e st_Cas (the CAS call form) is byte-identical to v2.7a

== Part 6 (2.7c): the round-2 string rules, v2.7c against v2.7b, both in harness v3d ==
  [ok] 6a st_Cas (cas=giac): 1/2+1/3 -> '5/6'; 1/0, 0/0 and a syntax error -> ['', '', '']
  [ok] 6a st_Cas with the CAS failing returns "" and no error -- '' None
  [ok] 6a v2.7b's st_Cas with the CAS failing stops: INSTRING: Invalid input (the first argument is an empty stri
  [ok] 6b Pareto [1, 1, 0], CAS failing: v2.7c shows the Formula page with "decimal" and "no closed form shown", no error -- None ['decimal']
  [ok] 6b Pareto [1, 1, 0], CAS failing: v2.7b stops: INSTRING: Invalid input (the first argument is an empty string -- emulator, 17 Oct 2026) [
  [ok] 6b Exponential [0.5, 0, 0], CAS failing: v2.7c shows the Formula page with "decimal" and "no closed form shown", no error -- None ['decimal']
  [ok] 6b Exponential [0.5, 0, 0], CAS failing: v2.7b stops: INSTRING: Invalid input (the first argument is an empty string -- emulator, 17 Oct 2026) [
  [ok] 6b Binomial [20, 0.5, 0], CAS failing: v2.7c shows the Formula page with "decimal" and "no closed form shown", no error -- None ['decimal']
  [ok] 6b Binomial [20, 0.5, 0], CAS failing: v2.7b stops: INSTRING: Invalid input (the first argument is an empty string -- emulator, 17 Oct 2026) [
  [ok] 6c Pareto(1, 1), CAS answering: the CDF comes back as ['"(stqx-1)/stqx"'] (it ends in stqx); v2.7c shows "  F(x) = (x-1)/x" with "exact (CAS)", no error -- None ['CDF: F(x) = integral of f(t) dt, t = 1 to x:', '  F(x) = (x-1)/x']
  [ok] 6c the same page in v2.7b stops in st_Repl: INSTRING: Invalid input (the first argument is an empty string -- emulator, 17 Oct 2026) [st_Plot > 
  [ok] 6c every CAS answer of Part 1 (251) through st_FmShow: v2.7c reads them all; the 5 that END in a name it replaces stopped v2.7b, the others read as in v2.7b -- []
  [ok] 6d st_Repl, at the end: ('(stqx-1)/stqx', 'stqx', 'x') -> '(x-1)/x' (v2.7b: stops: INSTRING: Invalid input (the first argum)
  [ok] 6d st_Repl, at the start: ('stqx^2+1', 'stqx', 'x') -> 'x^2+1' (v2.7b: 'x^2+1')
  [ok] 6d st_Repl, the whole text: ('stqa', 'stqa', 'a') -> 'a' (v2.7b: stops: INSTRING: Invalid input (the first argum)
  [ok] 6d st_Repl, an empty pattern: ('abc', '', 'z') -> 'abc' (v2.7b: (not run: v2.7b loops for ever))
  [ok] 6d st_Repl, an empty text: ('', 'stqx', 'x') -> '' (v2.7b: stops: INSTRING: Invalid input (the first argum)
  [ok] 6d st_Repl, no match: ('abc', 'z', 'y') -> 'abc' (v2.7b: 'abc')
  [ok] 6d st_Repl, two in a row: ('**', '*', '×') -> '××' (v2.7b: stops: INSTRING: Invalid input (the first argum)
  [ok] 6d st_Repl, the pattern in the new text: ('a*b', '*', '**') -> 'a**b' (v2.7b: 'a**b')
  [ok] 6e st_fmtx(1e-17) = '0' (v2.7b: '1ᴇ-17')
  [ok] 6e st_fmtx(-1e-17) = '0' (v2.7b: '-1ᴇ-17')
  [ok] 6e st_fmtx(1e-11) = '0' (v2.7b: '1ᴇ-11')
  [ok] 6e st_fmtx(2.0) = '2' (v2.7b: '2')
  [ok] 6e st_fmtx(1.96) = '1.96' (v2.7b: '1.96')
  [ok] 6e st_fmtx(0.3333333333333333) = '0.3333' (v2.7b: '0.3333')
  [ok] 6e st_fmtx(0.0004) = '0.0004' (v2.7b: '0.0004')
  [ok] 6e st_fmtx(-2.5) = '-2.5' (v2.7b: '-2.5')
  [ok] 6e st_fmtx(123.0) = '123' (v2.7b: '123')
  [ok] 6e st_fmtx(0.3) = '0.3' (v2.7b: '0.3')
  [ok] 6e v2.7b printed 1E-17 as '1ᴇ-17', scientific
  16 STRING(x, 2, d) calls in v2.7c:
    st_Draw      100*stCut(1)     d = 1    the "% beyond" note: drawn only when the cut is 0.15 % or more
    st_Draw      100*stCut(2)     d = 1    the "% beyond" note: drawn only when the cut is 0.15 % or more
    st_Draw      dwV              d = dwD  an axis label: a multiple of a 1-2-5 step, d = -FLOOR(LOG(step)), -0 set to 0
    st_FmBuild   stPar(fbI)       d = 12   12 decimals: only a parameter below 1E-12 (the one form that can show it)
    st_Int       IP(rdV)          d = 0    a whole number (IP)
    st_Numbers   stAv             d = 0    k, a or b of a discrete family: whole
    st_Numbers   stAv - 1         d = 0    k, a or b of a discrete family: whole
    st_Numbers   stBv             d = 0    k, a or b of a discrete family: whole
    st_Numbers   stXv             d = 0    k, a or b of a discrete family: whole
    st_Numbers   stXv + 1         d = 0    k, a or b of a discrete family: whole
    st_fmtp      pv               d = dg   st_fmtp: a value below 10^-dg has already become "< 0.000001"
    st_fmtp      thr              d = dg   st_fmtp: thr = 10^-dg itself
    st_fmtx      fxR              d = fxD  st_fmtx: rounded to fxD decimals first (2.7c)
  [ok] 6f every STRING(x, 2, d) is rounded first or cannot print scientific (16 calls; unlisted none, stale none)
  INSTRING in v2.7c (code lines):
      832 st_Cas         IF INSTRING(cR, "undef") > 0 OR INSTRING(cR, "rror") > 0 OR INSTRING(cR, CHAR(8734)) > 0 THEN cR
      847 st_IVal        ivD := INSTRING("0123456789", ivC);
      877 st_Repl        rpP := 0; IF DIM(rpT) > 0 THEN rpP := INSTRING(rpT, rpO); END;
      886 st_Repl        rpP := 0; IF DIM(rpT) > 0 THEN rpP := INSTRING(rpT, rpO); END;
      975 st_Digits      IF INSTRING("0123456789", MID(dgS, dgI, 1)) > 0 THEN dgN := dgN + 1; END;
     3513 st_FmGood      IF INSTRING(fgT, "integrate") > 0 OR INSTRING(fgT, "int(") > 0 OR INSTRING(fgT, "sum(") > 0 THEN
     3514 st_FmGood      IF INSTRING(fgT, "seq(") > 0 OR INSTRING(fgT, "limit") > 0 OR INSTRING(fgT, "?") > 0 THEN RETURN
     3515 st_FmGood      IF INSTRING(fgT, "when") > 0 OR INSTRING(fgT, "piecewise") > 0 OR INSTRING(fgT, "infinity") > 0 
     3516 st_FmGood      IF INSTRING(fgT, CHAR(8734)) > 0 THEN RETURN 0; END;
     3520 st_FmGood      IF INSTRING(fgT, CHAR(8747)) > 0 OR INSTRING(fgT, CHAR(8721)) > 0 OR INSTRING(fgT, CHAR(931)) > 
     3533 st_FmSub       IF INSTRING(fsS, "stqx") > 0 THEN fsS := "subst(" + fsS + ",stqx," + stFmXR + ")"; END;
     3629 st_FmRes       IF INSTRING("0123456789/-", MID(frS, frI, 1)) == 0 THEN frF := 0; END;
  [ok] 6f INSTRING's first argument is a fixed digit string, or a text tested non-empty just before it: ['"0123456789"', '"0123456789/-"', 'cR', 'fgT', 'fsS', 'rpT']
  [ok] 6f st_Repl looks only while text is left (2 lines), st_Cas only inside IF DIM(cR) > 0
  LEFT / MID / RIGHT in v2.7c: st_Eq LEFT(eqS, 1); st_Eq LEFT(eqS, 1); st_Page LEFT(pgS, 2); st_Cas LEFT(cR, 1); st_Cas MID(cR, DIM(cR), 1); st_Cas MID(cR, 2, DIM(cR) - 2); st_IVal MID(ivS, ivI, 1); st_Repl LEFT(rpT, rpP - 1); st_Repl MID(rpT, rpP + rpLn, DIM(rpT) - rpP - rpLn + 1); st_Wrap MID(wrR, wrI, 1); st_Wrap LEFT(wrR, wrB); st_Wrap MID(wrR, wrB + 1, DIM(wrR) - wrB); st_Digits MID(dgS, dgI, 1); st_FmRes MID(frS, frI, 1)
  [ok] 6f no RIGHT; every LEFT count is 1, 2 or guarded (rpP - 1 under IF rpP > 1; wrB >= 1); every MID start is 1 or more
  [ok] 6g routines that differ from v2.7b: ['st_Cas', 'st_Repl', 'st_fmtx', 'st_show_help']
  [ok] 6g outside those routines only comments differ
  [ok] 6g st_Cas keeps the IFERR line and the quote strip byte-identical
  [ok] 6g the version reads v2.7c in the banner and the help title; no code line says v2.7b
  v2.7c: 30 harness runs in this script, 0 scientific STRING results: none
  v2.7b (part 6, for comparison): 8 runs, scientific in [('st_fmtx', '-1ᴇ-17'), ('st_fmtx', '1ᴇ-11'), ('st_fmtx', '1ᴇ-17')]
  [ok] 6h no scientific STRING result in any of the 30 harness runs of v2.7c

== Part 7 (2.7d): no "=" before a relation; the normal approximation's right tail ==
  Normal(0, 1), left tail at -6
    v2.7c panel ['f(x) = < 0.0001: a density, not a probability', 'P(X <= -6) = < 0.000001'] numbers ['  PDF: < 0.000001 (a density)', '  CDF: < 0.000001', 'P(X <= -6.0000) = < 0.000001']
    v2.7d panel ['f(x) < 0.0001: a density, not a probability', 'P(X <= -6) < 0.000001'] numbers ['  PDF: < 0.000001 (a density)', '  CDF: < 0.000001', 'P(X <= -6.0000) < 0.000001']
  [ok] 7a Normal(0, 1), left tail at -6: the panel and the Numbers page read f(x) < 0.0001: a density, not a probability; P(X <= -6) < 0.000001; P(X <= -6.0000) < 0.000001
  [ok] 7a Normal(0, 1), left tail at -6: the summary returned to Home (stLast) reads "P(X <= -6) < 0.000001"
  Normal(0, 1), right tail at 6
    v2.7c panel ['f(x) = < 0.0001: a density, not a probability', 'P(X > 6) = < 0.000001'] numbers ['  PDF: < 0.000001 (a density)', 'P(X > 6.0000) = < 0.000001']
    v2.7d panel ['f(x) < 0.0001: a density, not a probability', 'P(X > 6) < 0.000001'] numbers ['  PDF: < 0.000001 (a density)', 'P(X > 6.0000) < 0.000001']
  [ok] 7a Normal(0, 1), right tail at 6: the panel and the Numbers page read P(X > 6) < 0.000001; P(X > 6.0000) < 0.000001
  Normal(0, 1), between -7 and -6
    v2.7c panel ['f(a) = < 0.0001, f(b) = < 0.0001: densities', 'P(-7 < X < -6) = < 0.000001'] numbers ['CDF(b) = < 0.000001 at b = -6.0000', 'CDF(a) = < 0.000001 at a = -7.0000', 'P(-7.0000 < X < -6.0000) = < 0.000001']
    v2.7d panel ['f(a) < 0.0001, f(b) < 0.0001: densities', 'P(-7 < X < -6) < 0.000001'] numbers ['CDF(b) < 0.000001 at b = -6.0000', 'CDF(a) < 0.000001 at a = -7.0000', 'P(-7.0000 < X < -6.0000) < 0.000001']
  [ok] 7a Normal(0, 1), between -7 and -6: the panel and the Numbers page read f(a) < 0.0001, f(b) < 0.0001: densities; P(-7 < X < -6) < 0.000001; CDF(b) < 0.000001 at b = -6.0000; CDF(a) < 0.000001 at a = -7.0000; P(-7.0000 < X < -6.0000) < 0.000001
  Normal(0, 0.001)
    v2.7c panel [] numbers ['variance = < 0.0001']
    v2.7d panel [] numbers ['variance < 0.0001']
  [ok] 7a Normal(0, 0.001): the panel and the Numbers page read variance < 0.0001
  Normal(0.00002, 0.00005)
    v2.7c panel ['μ = < 0.0001, σ = < 0.0001', 'mean = < 0.0001, sd = < 0.0001'] numbers ['μ = < 0.0001, σ = < 0.0001', 'mean = < 0.0001,  sd = < 0.0001', 'variance = < 0.0001']
    v2.7d panel ['μ < 0.0001, σ < 0.0001', 'mean < 0.0001, sd < 0.0001'] numbers ['μ < 0.0001, σ < 0.0001', 'mean < 0.0001,  sd < 0.0001', 'variance < 0.0001']
  [ok] 7a Normal(0.00002, 0.00005): the panel and the Numbers page read μ < 0.0001, σ < 0.0001; mean < 0.0001, sd < 0.0001; μ < 0.0001, σ < 0.0001; mean < 0.0001,  sd < 0.0001
  Binomial(100, 0.5), right tail at 95, normal approx. on
    v2.7c panel ['P(X = 95) = < 0.000001: the red bar', 'P(X > 95) = P(X >= 96) = < 0.000001'] numbers ['  PMF: < 0.000001', 'P(X > 95) = P(X >= 96) = < 0.000001']
    v2.7d panel ['P(X = 95) < 0.000001: the red bar', 'P(X > 95) = P(X >= 96) < 0.000001', 'normal approx. < 0.0001 (continuity corr.)'] numbers ['  PMF: < 0.000001', 'P(X > 95) = P(X >= 96) < 0.000001']
  [ok] 7a Binomial(100, 0.5), right tail at 95, normal approx. on: the panel and the Numbers page read P(X = 95) < 0.000001: the red bar; P(X > 95) = P(X >= 96) < 0.000001; normal approx. < 0.0001 (continuity corr.); P(X > 95) = P(X >= 96) < 0.000001
  Binomial(100, 0.5), left tail at 3, normal approx. on
    v2.7c panel ['P(X = 3) = < 0.000001: the red bar', 'P(X <= 3) = < 0.000001', 'normal approx. = < 0.0001 (continuity corr.)'] numbers ['  PMF: < 0.000001', '  CDF: < 0.000001', 'P(X <= 3) = < 0.000001']
    v2.7d panel ['P(X = 3) < 0.000001: the red bar', 'P(X <= 3) < 0.000001', 'normal approx. < 0.0001 (continuity corr.)'] numbers ['  PMF: < 0.000001', '  CDF: < 0.000001', 'P(X <= 3) < 0.000001']
  [ok] 7a Binomial(100, 0.5), left tail at 3, normal approx. on: the panel and the Numbers page read P(X <= 3) < 0.000001; normal approx. < 0.0001 (continuity corr.); P(X <= 3) < 0.000001
  Binomial(100, 0.5), between 0 and 3
    v2.7c panel ['P(X = 0) = < 0.0001, P(X = 3) = < 0.0001', 'P(0 <= X <= 3) = < 0.000001'] numbers ['CDF(b) = P(X <= 3) = < 0.000001', 'P(0 <= X <= 3) = < 0.000001']
    v2.7d panel ['P(X = 0) < 0.0001, P(X = 3) < 0.0001', 'P(0 <= X <= 3) < 0.000001'] numbers ['CDF(b) = P(X <= 3) < 0.000001', 'P(0 <= X <= 3) < 0.000001']
  [ok] 7a Binomial(100, 0.5), between 0 and 3: the panel and the Numbers page read P(X = 0) < 0.0001, P(X = 3) < 0.0001; P(0 <= X <= 3) < 0.000001; CDF(b) = P(X <= 3) < 0.000001; P(0 <= X <= 3) < 0.000001
  Poisson(4), right tail at 30
    v2.7c panel ['P(X = 30) = < 0.000001: the red bar', 'P(X > 30) = P(X >= 31) = < 0.000001'] numbers ['  PMF: < 0.000001', 'P(X > 30) = P(X >= 31) = < 0.000001']
    v2.7d panel ['P(X = 30) < 0.000001: the red bar', 'P(X > 30) = P(X >= 31) < 0.000001'] numbers ['  PMF: < 0.000001', 'P(X > 30) = P(X >= 31) < 0.000001']
  [ok] 7a Poisson(4), right tail at 30: the panel and the Numbers page read P(X > 30) = P(X >= 31) < 0.000001; P(X > 30) = P(X >= 31) < 0.000001
  Normal(0, 1), x = 0.00005
    v2.7c panel ['P(X <= < 0.0001) = 0.500020'] numbers ['At x = < 0.0001:', 'P(X <= < 0.0001) = 0.500020']
    v2.7d panel ['P(X <= < 0.0001) = 0.500020'] numbers ['At x < 0.0001:', 'P(X <= < 0.0001) = 0.500020']
  [ok] 7a Normal(0, 1), x = 0.00005: the panel and the Numbers page read At x < 0.0001:
  doubles:
    Bin(100, 0.5), x 80: SciPy 5.3e-10;  v2.7c ['normal approx. = < 0.0001 (continuity corr.)'];  v2.7d ['normal approx. < 0.0001 (continuity corr.)']
    Bin(100, 0.5), x 85: SciPy 6.24e-13;  v2.7c ['normal approx. = < 0.0001 (continuity corr.)'];  v2.7d ['normal approx. < 0.0001 (continuity corr.)']
    Bin(100, 0.5), x 95: SciPy 4.52e-20;  v2.7c ['normal approx. = 0.0000 (continuity corr.)'];  v2.7d ['normal approx. < 0.0001 (continuity corr.)']
    Bin(400, 0.3), x 200: SciPy 7.94e-19;  v2.7c ['normal approx. = 0.0000 (continuity corr.)'];  v2.7d ['normal approx. < 0.0001 (continuity corr.)']
    Bin(50, 0.4), x 45: SciPy 9.11e-14;  v2.7c ['normal approx. = < 0.0001 (continuity corr.)'];  v2.7d ['normal approx. < 0.0001 (continuity corr.)']
  [ok] 7b (doubles) the right tail is never shown as 0: v2.7d prints the floor exactly where SciPy's tail is below 0.0001 -- []
    v2.7c printed "= 0.0000" for 2 of the 5
  [ok] 7b (doubles) v2.7c read "normal approx. = 0.0000" (1 - CDF exactly 0) at Bin(100, 0.5) x 95 and Bin(400, 0.3) x 200; v2.7d "< 0.0001" there
  the Prime's 12 digits:
    Bin(100, 0.5), x 80: SciPy 5.3e-10;  v2.7c ['normal approx. = < 0.0001 (continuity corr.)'];  v2.7d ['normal approx. < 0.0001 (continuity corr.)']
    Bin(100, 0.5), x 85: SciPy 6.24e-13;  v2.7c ['normal approx. = < 0.0001 (continuity corr.)'];  v2.7d ['normal approx. < 0.0001 (continuity corr.)']
    Bin(100, 0.5), x 95: SciPy 4.52e-20;  v2.7c ['normal approx. = 0.0000 (continuity corr.)'];  v2.7d ['normal approx. < 0.0001 (continuity corr.)']
    Bin(400, 0.3), x 200: SciPy 7.94e-19;  v2.7c ['normal approx. = 0.0000 (continuity corr.)'];  v2.7d ['normal approx. < 0.0001 (continuity corr.)']
    Bin(50, 0.4), x 45: SciPy 9.11e-14;  v2.7c ['normal approx. = 0.0000 (continuity corr.)'];  v2.7d ['normal approx. < 0.0001 (continuity corr.)']
  [ok] 7b (12 digits) the right tail is never shown as 0: v2.7d prints the floor exactly where SciPy's tail is below 0.0001 -- []
    v2.7c printed "= 0.0000" for 3 of the 5
  [ok] 7b (12 digits) v2.7c read "normal approx. = 0.0000" (1 - CDF exactly 0) at Bin(100, 0.5) x 95, Bin(400, 0.3) x 200 and Bin(50, 0.4) x 45; v2.7d "< 0.0001" there
  [ok] 7b NORMALD_CDF(m, s, 2m - x) is the upper tail P(Z > x) (4 cases, against SciPy)
  27 families x 3 tails x 3 settings: 194 identical, 49 differ only by the rewrite, 0 otherwise
    "P(X <= -50) = < 0.000001"  ->  "P(X <= -50) < 0.000001"
    "P(X <= -50.0000) = < 0.000001"  ->  "P(X <= -50.0000) < 0.000001"
    "P(X <= 0) = < 0.000001"  ->  "P(X <= 0) < 0.000001"
    "P(X = 0) = < 0.000001: the red bar"  ->  "P(X = 0) < 0.000001: the red bar"
    "P(X = 0) = < 0.0001, P(X = 4) = 0.2588"  ->  "P(X = 0) < 0.0001, P(X = 4) = 0.2588"
    "P(X = 20) = < 0.000001: the red bar"  ->  "P(X = 20) < 0.000001: the red bar"
    "P(X = 63) = < 0.000001: the red bar"  ->  "P(X = 63) < 0.000001: the red bar"
    "P(X = 64) = < 0.000001: the red bar"  ->  "P(X = 64) < 0.000001: the red bar"
    "P(X > 60) = < 0.000001"  ->  "P(X > 60) < 0.000001"
    "P(X > 60.0000) = < 0.000001"  ->  "P(X > 60.0000) < 0.000001"
    (19 distinct rewritten lines)
  [ok] 7c every family and tail (243 states): v2.7d's panel and Numbers page are v2.7c's with "= <" written "<", and nothing else -- []
  [ok] 7c every rewritten line differs only by "= <" -> "<" or "= >" -> ">", and none in v2.7d reads "= <"
  [ok] 7c st_ParStr, 27 families, defaults and tiny parameters: v2.7c's text written without "= <" -- []
  [ok] 7d st_Eq("0.158655") = " = 0.158655"
  [ok] 7d st_Eq("< 0.000001") = " < 0.000001"
  [ok] 7d st_Eq("> -0.000001") = " > -0.000001"
  [ok] 7d st_Eq("") = " = "
  [ok] 7d st_Eq("-1.5") = " = -1.5"
  [ok] 7d st_Eq("undef (no mean)") = " = undef (no mean)"
  7e Normal(0, 0.0005), variance 2.5E-7: v2.7d ["  < 0.000001, the program's value: agree"]
       v2.7c ["  = < 0.000001, the program's value: agree"]
  [ok] 7e Normal(0, 0.0005), variance 2.5E-7: the Formula page reads "< 0.000001, the program's value: agree", and is v2.7c's written without "= <"
  7e Exponential(1), x = 0.00005: v2.7d ["  at x < 0.0001: 0.000050, the program's: agree"]
       v2.7c ["  = 1.000000, the program's value: agree", "  = 2.000000, the program's value: agree"]
  [ok] 7e Exponential(1), x = 0.00005: the Formula page reads "at x < 0.0001:", and is v2.7c's written without "= <"
  7e Normal(0, 1): v2.7d ["  = 1.000000, the program's value: agree", "  = 1.000000, the program's value: agree"]
       v2.7c ["  = 0.000000, the program's value: agree", "  = 1.000000, the program's value: agree"]
  [ok] 7e Normal(0, 1): the Formula page reads "= 1.000000, the program's value: agree", and is v2.7c's written without "= <"
  [ok] 7f the code lines removed (55) and added (62) are exactly the sites above, through st_Eq, the lower tail, the help title, and st_Eq itself -- []
  [ok] 7f the new names st_Eq and eqS are not built-ins (ignoring case); st_Eq carries the st_ tag and is defined once, after st_fmtp and before its first use
  [ok] 7f the version reads v2.7d in the banner and the help title, a "WHAT CHANGED in v2.7d" paragraph is there, and no code line says v2.7c
  [ok] 7f no // comment inside an open bracket -- []
  [ok] 7f INSTRING appears in as many code lines as in v2.7c; every LOCAL line holds at most 6 names
  7g seen, not changed: Normal(0, 1), P(X > 10): v2.7c ['P(X > 10) = 0.000000'], v2.7d ['P(X > 10) = 0.000000'] (1 - CDF, st_Prob; SciPy 7.6e-24)
  7g seen, not changed: a typed x of 0.00005 reads ['P(X <= < 0.0001) = 0.500020'] (no "=" before the relation)
  [ok] 7h no scientific STRING result in any of the 607 harness runs of v2.7d in this script -- []

RESULT: ALL PASS
