This site is version 0.0.1. Most of the code on this site is drafted by an agent and needs review. I apologize for the AI-speak, we are working on rewriting it!
viv-lang.org

Python and Viv · Numerics

Simpson's rule

What to notice

Open the Viv in the workbench The atlas of the Viv py2viv refuses this Python (the reason is in its column).
Python simpson.py · 30 lines
Viv simpson.viv · 39 lines
py2viv refuses simpson.py
1 imports
4import math
2PI = 3.141592653589793
py2viv refuses this program:
simpson.py:18:8: not numeric Python: `None` as a value
    prev = None
           ^^^^
  Use a number (for example -1 or nan) to mean 'nothing'.
simpson.py:20:23: not numeric Python: passing a builtin or library function (`math.sin`)
        err = abs(simpson(math.sin, 0.0, 1.0, n) - exact)
                          ^^^^^^^^
  Viv passes defs of the program: wrap it in a def.
simpson.py:21:16: not numeric Python: the text of a value of unknown type (it comes from a construct refused elsewhere)
        ratio = f"{prev / err:6.2f}" if prev else "     -"
                   ^^^^^^^^^^
  Fix the refusal that produced it.
simpson.py:22:34: not numeric Python: printing a value of unknown type (it comes from a construct refused elsewhere)
        print(f"n = {n:2d}  error = {err:.3e}  ratio = {ratio}")
                                     ^^^
  Fix the refusal that produced it.
4 constructs outside the numeric subset (tools/py2viv/SUBSET.md)
2 composite Simpson's rule
7def simpson(f, a, b, n):
8 if n % 2 == 1:
9 n += 1
10 h = (b - a) / n
11 s = f(a) + f(b)
12 for i in range(1, n):
13 s += (4 if i % 2 == 1 else 2) * f(a + i * h)
14 return s * h / 3
5def simpson_rule(f, a, b, n) {
6 if n % 2 == 1 {
7 n += 1
8 }
9 h = (b - a) / n
10 s = f(a) + f(b)
11 for i from 1 to n {
12 s += (4 if i % 2 == 1 else 2) * f(a + i * h)
13 }
14 return s * h / 3
15}
(refused)
3 the error falls as h^4
17exact = 1.0 - math.cos(1.0)
18prev = None
19for n in [4, 8, 16, 32]:
20 err = abs(simpson(math.sin, 0.0, 1.0, n) - exact)
21 ratio = f"{prev / err:6.2f}" if prev else " -"
22 print(f"n = {n:2d} error = {err:.3e} ratio = {ratio}")
23 prev = err
18exact = 1.0 - cos(1.0)
19prev = 0.0
20for n in [4, 8, 16, 32] {
21 err = abs(simpson_rule(fn(x) -> sin(x), 0.0, 1.0, n) - exact)
22 ratio = f"{prev / err:6.2f}" if prev > 0 else " -"
23 print(f"n = {n:2d} error = {err:.3e} ratio = {ratio}")
24 prev = err
25}
(refused)
4 a Gaussian integral
26g = simpson(lambda x: math.exp(-x * x), -6.0, 6.0, 200)
27print(f"integral of exp(-x^2) = {g:.12f}, sqrt(pi) = {math.sqrt(math.pi):.12f}")
28POINTS = 200
29g = simpson_rule(fn(x) -> exp(-x * x), -6.0, 6.0, POINTS)
30print(f"integral of exp(-x^2) = {g:.12f}, sqrt(pi) = {sqrt(PI):.12f}")
(refused)
5 checks
30assert abs(g - math.sqrt(math.pi)) < 1e-10
33test "Gaussian" {
34 assert_near(g, sqrt(PI), 1e-10)
35 assert_near(simpson(fn(x) -> exp(-x * x), -6.0, 6.0, POINTS), g, 1e-12)
36}
(refused)

What they print

identical — the two programs print the same text.

Dimmed lines are left out of the comparison. Each Viv test block prints one PASS line; the Python checks the same facts with assert, which prints nothing.

$ python3 simpson.py

n = 4 error = 1.005e-05 ratio = -
n = 8 error = 6.247e-07 ratio = 16.09
n = 16 error = 3.899e-08 ratio = 16.02
n = 32 error = 2.436e-09 ratio = 16.01
integral of exp(-x^2) = 1.772453850906, sqrt(pi) = 1.772453850906

$ viv run simpson.viv

n = 4 error = 1.005e-05 ratio = -
n = 8 error = 6.247e-07 ratio = 16.09
n = 16 error = 3.899e-08 ratio = 16.02
n = 32 error = 2.436e-09 ratio = 16.01
integral of exp(-x^2) = 1.772453850906, sqrt(pi) = 1.772453850906
PASS Gaussian