# Bernstein basis polynomials

Bernstein basis polynomials
You are encouraged to solve this task according to the task description, using any language you may know.

The ${\displaystyle n + 1}$ Bernstein basis polynomials of degree ${\displaystyle n}$ are defined as

${\displaystyle b_{k,n}(t) = \binom{n}{k} t^{k} \left( 1 - t \right)^{n - k},\quad k = 0,\ldots,n}$

Any real polynomial can written as a linear combination of such Bernstein basis polynomials. Let us call the coefficients in such linear combinations Bernstein coefficients.

The goal of this task is to write subprograms for working with degree-2 and degree-3 Bernstein coefficients. A programmer is likely to have to deal with such representations. For example, OpenType fonts store glyph outline data as as either degree-2 or degree-3 Bernstein coefficients.

1. Write a subprogram (which we will call Subprogram (1)) to transform the ordinary monomial coefficients of a real polynomial, of degree 2 or less, to Bernstein coefficients for the degree-2 basis.
2. Write Subprogram (2) to evaluate, at a given point, a real polynomial written in degree-2 Bernstein coefficients. For this use de Casteljau's algorithm.
3. Write Subprogram (3) to transform the monomial coefficients of a real polynomial, of degree 3 or less, to Bernstein coefficients for degree 3.
4. Write Subprogram (4) to evaluate, at a given point, a real polynomial written in degree-3 Bernstein coefficients. Use de Casteljau's algorithm.
5. Write Subprogram (5) to transform Bernstein coefficients for degree 2 to Bernstein coefficients for degree 3.
6. For the following polynomials, use Subprogram (1) to find Bernstein coefficients for the degree-2 basis: ${\displaystyle p(x) = 1}$, ${\displaystyle q(x) = 1 + 2x + 3x^2}$. Display the results.
7. Use Subprogram (2) to evaluate ${\displaystyle p(x)}$ and ${\displaystyle q(x)}$ at ${\displaystyle x = 0.25}$ and at ${\displaystyle x = 7.50}$. Display the results. Optionally also evaluate the polynomials in the monomial basis and display the results. (For the monomial basis it is best to use a Horner scheme.)
8. Use Subprogram (3) to find degree-3 Bernstein coefficients for ${\displaystyle p(x)}$ and ${\displaystyle q(x)}$, and additionally also for ${\displaystyle r(x) = 1 + 2x + 3x^2 + 4x^3}$. Display the results.
9. Use Subprogram (4) to evaluate ${\displaystyle p(x)}$, ${\displaystyle q(x)}$, and ${\displaystyle r(x)}$ at ${\displaystyle x = 0.25}$ and ${\displaystyle x = 7.50}$. Display the results. Optionally also evaluate them in the monomial basis and display the results. (You may have done that already for ${\displaystyle p(x)}$ and ${\displaystyle q(x)}$.)
10. Use Subprogram (5) to get degree-3 Bernstein coefficients for ${\displaystyle p(x)}$ and ${\displaystyle q(x)}$ from their degree-2 Bernstein coefficients. Display the results.

ALGOL 60 and Python implementations are provided as initial examples. The latter does the optional monomial-basis evaluations.

You can use the following algorithms. They are written in unambiguous Algol 60 reference language instead of a made up pseudo-language. The ALGOL 60 example was necessary to check my work, but these reference versions are in the actual standard language designed for the printing of algorithms.

procedure tobern2 (a0, a1, a2, b0, b1, b2);
value a0, a1, a2; comment pass by value;
real a0, a1, a2;
real b0, b1, b2;
comment Subprogram (1): transform monomial coefficients a0, a1, a2 to Bernstein coefficients b0, b1, b2;
begin
b0 := a0;
b1 := a0 + ((1/2) × a1);
b2 := a0 + a1 + a2
end tobern2;

real procedure evalbern2 (b0, b1, b2, t);
value b0, b1, b2, t;
real b0, b1, b2, t;
comment Subprogram (2): evaluate, at t, the polynomial with Bernstein coefficients b0, b1, b2. Use de Casteljau’s algorithm;
begin
real s, b01, b12, b012;
s := 1 - t;
b01 := (s × b0) + (t × b1);
b12 := (s × b1) + (t × b2);
b012 := (s × b01) + (t × b12);
evalbern2 := b012
end evalbern2;

procedure tobern3 (a0, a1, a2, a3, b0, b1, b2, b3);
value a0, a1, a2, a3;
real a0, a1, a2, a3;
real b0, b1, b2, b3;
comment Subprogram (3): transform monomial coefficients a0, a1, a2, a3 to Bernstein coefficients b0, b1, b2, b3;
begin
b0 := a0;
b1 := a0 + ((1/3) × a1);
b2 := a0 + ((2/3) × a1) + ((1/3) × a2);
b3 := a0 + a1 + a2 + a3
end tobern3;

real procedure evalbern3 (b0, b1, b2, b3, t);
value b0, b1, b2, b3, t;
real b0, b1, b2, b3, t;
comment Subprogram (4): evaluate, at t, the polynomial with Bernstein coefficients b0, b1, b2, b3. Use de Casteljau's algorithm;
begin
real s, b01, b12, b23, b012, b123, b0123;
s := 1 - t;
b01 := (s × b0) + (t × b1);
b12 := (s × b1) + (t × b2);
b23 := (s × b2) + (t × b3);
b012 := (s × b01) + (t × b12);
b123 := (s × b12) + (t × b23);
b0123 := (s × b012) + (t × b123);
evalbern3 := b0123
end evalbern3;

procedure bern2to3 (q0, q1, q2, c0, c1, c2, c3);
value q0, q1, q2;
real q0, q1, q2;
real c0, c1, c2, c3;
comment Subprogram (5): transform the quadratic Bernstein coefficients q0, q1, q2 to the cubic Bernstein coefficients c0, c1, c2, c3;
begin
c0 := q0;
c1 := ((1/3) × q0) + ((2/3) × q1);
c2 := ((2/3) × q1) + ((1/3) × q2);
c3 := q2
end bern2to3;


## ALGOL 60

Works with: GNU MARST version 2.7
procedure tobern2 (a0, a1, a2, b0, b1, b2);
value a0, a1, a2; comment pass by value;
real a0, a1, a2;
real b0, b1, b2;
comment Subprogram (1): transform monomial coefficients
a0, a1, a2 to Bernstein coefficients b0, b1, b2;
begin
b0 := a0;
b1 := a0 + ((1/2) * a1);
b2 := a0 + a1 + a2
end tobern2;

real procedure evalbern2 (b0, b1, b2, t);
value b0, b1, b2, t;
real b0, b1, b2, t;
comment Subprogram (2): evaluate, at t, the polynomial with
Bernstein coefficients b0, b1, b2. Use de Casteljau's
algorithm;
begin
real s, b01, b12, b012;
s := 1 - t;
b01 := (s * b0) + (t * b1);
b12 := (s * b1) + (t * b2);
b012 := (s * b01) + (t * b12);
evalbern2 := b012
end evalbern2;

procedure tobern3 (a0, a1, a2, a3, b0, b1, b2, b3);
value a0, a1, a2, a3;
real a0, a1, a2, a3;
real b0, b1, b2, b3;
comment Subprogram (3): transform monomial coefficients
a0, a1, a2, a3 to Bernstein coefficients b0, b1,
b2, b3;
begin
b0 := a0;
b1 := a0 + ((1/3) * a1);
b2 := a0 + ((2/3) * a1) + ((1/3) * a2);
b3 := a0 + a1 + a2 + a3
end tobern3;

real procedure evalbern3 (b0, b1, b2, b3, t);
value b0, b1, b2, b3, t;
real b0, b1, b2, b3, t;
comment Subprogram (4): evaluate, at t, the polynomial
with Bernstein coefficients b0, b1, b2, b3. Use
de Casteljau's algorithm;
begin
real s, b01, b12, b23, b012, b123, b0123;
s := 1 - t;
b01 := (s * b0) + (t * b1);
b12 := (s * b1) + (t * b2);
b23 := (s * b2) + (t * b3);
b012 := (s * b01) + (t * b12);
b123 := (s * b12) + (t * b23);
b0123 := (s * b012) + (t * b123);
evalbern3 := b0123
end evalbern3;

procedure bern2to3 (q0, q1, q2, c0, c1, c2, c3);
value q0, q1, q2;
real q0, q1, q2;
real c0, c1, c2, c3;
comment Subprogram (5): transform the quadratic Bernstein
coefficients q0, q1, q2 to the cubic Bernstein
coefficients c0, c1, c2, c3;
begin
c0 := q0;
c1 := ((1/3) * q0) + ((2/3) * q1);
c2 := ((2/3) * q1) + ((1/3) * q2);
c3 := q2
end bern2to3;

begin
real p0m, p1m, p2m;
real q0m, q1m, q2m;
real r0m, r1m, r2m, r3m;

real p0b2, p1b2, p2b2;
real q0b2, q1b2, q2b2;

real p0b3, p1b3, p2b3, p3b3;
real q0b3, q1b3, q2b3, q3b3;
real r0b3, r1b3, r2b3, r3b3;

real pc0, pc1, pc2, pc3;
real qc0, qc1, qc2, qc3;

real x, y;

p0m := 1; p1m := 0; p2m := 0;
q0m := 1; q1m := 2; q2m := 3;
r0m := 1; r1m := 2; r2m := 3; r3m := 4;

tobern2 (p0m, p1m, p2m, p0b2, p1b2, p2b2);
tobern2 (q0m, q1m, q2m, q0b2, q1b2, q2b2);
outstring (1, "Subprogram (1) examples:\n");
outstring (1, "  mono ( ");
outreal (1, p0m); outstring (1, ", ");
outreal (1, p1m); outstring (1, ", ");
outreal (1, p2m); outstring (1, ") --> bern ( ");
outreal (1, p0b2); outstring (1, ", ");
outreal (1, p1b2); outstring (1, ", ");
outreal (1, p2b2); outstring (1, ")\n");
outstring (1, "  mono ( ");
outreal (1, q0m); outstring (1, ", ");
outreal (1, q1m); outstring (1, ", ");
outreal (1, q2m); outstring (1, ") --> bern ( ");
outreal (1, q0b2); outstring (1, ", ");
outreal (1, q1b2); outstring (1, ", ");
outreal (1, q2b2); outstring (1, ")\n");

outstring (1, "Subprogram (2) examples:\n");
x := 0.25;
y := evalbern2 (p0b2, p1b2, p2b2, x);
outstring (1, "  p ( "); outreal (1, x);
outstring (1, ") = "); outreal (1, y);
outstring (1, "\n");
x := 7.50;
y := evalbern2 (p0b2, p1b2, p2b2, x);
outstring (1, "  p ( "); outreal (1, x);
outstring (1, ") = "); outreal (1, y);
outstring (1, "\n");
x := 0.25;
y := evalbern2 (q0b2, q1b2, q2b2, x);
outstring (1, "  q ( "); outreal (1, x);
outstring (1, ") = "); outreal (1, y);
outstring (1, "\n");
x := 7.50;
y := evalbern2 (q0b2, q1b2, q2b2, x);
outstring (1, "  q ( "); outreal (1, x);
outstring (1, ") = "); outreal (1, y);
outstring (1, "\n");

tobern3 (p0m, p1m, p2m, 0, p0b3, p1b3, p2b3, p3b3);
tobern3 (q0m, q1m, q2m, 0, q0b3, q1b3, q2b3, q3b3);
tobern3 (r0m, r1m, r2m, r3m, r0b3, r1b3, r2b3, r3b3);
outstring (1, "Subprogram (3) examples:\n");
outstring (1, "  mono ( ");
outreal (1, p0m); outstring (1, ", ");
outreal (1, p1m); outstring (1, ", ");
outreal (1, p2m); outstring (1, ", ");
outreal (1, 0); outstring (1, ") --> bern ( ");
outreal (1, p0b3); outstring (1, ", ");
outreal (1, p1b3); outstring (1, ", ");
outreal (1, p2b3); outstring (1, ", ");
outreal (1, p3b3); outstring (1, ")\n");
outstring (1, "  mono ( ");
outreal (1, q0m); outstring (1, ", ");
outreal (1, q1m); outstring (1, ", ");
outreal (1, q2m); outstring (1, ", ");
outreal (1, 0); outstring (1, ") --> bern ( ");
outreal (1, q0b3); outstring (1, ", ");
outreal (1, q1b3); outstring (1, ", ");
outreal (1, q2b3); outstring (1, ", ");
outreal (1, q3b3); outstring (1, ")\n");
outstring (1, "  mono ( ");
outreal (1, r0m); outstring (1, ", ");
outreal (1, r1m); outstring (1, ", ");
outreal (1, r2m); outstring (1, ", ");
outreal (1, r3m); outstring (1, ") --> bern ( ");
outreal (1, r0b3); outstring (1, ", ");
outreal (1, r1b3); outstring (1, ", ");
outreal (1, r2b3); outstring (1, ", ");
outreal (1, r3b3); outstring (1, ")\n");

outstring (1, "Subprogram (4) examples:\n");
x := 0.25;
y := evalbern3 (p0b3, p1b3, p2b3, p3b3, x);
outstring (1, "  p ( "); outreal (1, x);
outstring (1, ") = "); outreal (1, y);
outstring (1, "\n");
x := 7.50;
y := evalbern3 (p0b3, p1b3, p2b3, p3b3, x);
outstring (1, "  p ( "); outreal (1, x);
outstring (1, ") = "); outreal (1, y);
outstring (1, "\n");
x := 0.25;
y := evalbern3 (q0b3, q1b3, q2b3, q3b3, x);
outstring (1, "  q ( "); outreal (1, x);
outstring (1, ") = "); outreal (1, y);
outstring (1, "\n");
x := 7.50;
y := evalbern3 (q0b3, q1b3, q2b3, q3b3, x);
outstring (1, "  q ( "); outreal (1, x);
outstring (1, ") = "); outreal (1, y);
outstring (1, "\n");
x := 0.25;
y := evalbern3 (r0b3, r1b3, r2b3, r3b3, x);
outstring (1, "  r ( "); outreal (1, x);
outstring (1, ") = "); outreal (1, y);
outstring (1, "\n");
x := 7.50;
y := evalbern3 (r0b3, r1b3, r2b3, r3b3, x);
outstring (1, "  r ( "); outreal (1, x);
outstring (1, ") = "); outreal (1, y);
outstring (1, "\n");

bern2to3 (p0b2, p1b2, p2b2, pc0, pc1, pc2, pc3);
bern2to3 (q0b2, q1b2, q2b2, qc0, qc1, qc2, qc3);
outstring (1, "Subprogram (5) examples:\n");
outstring (1, "  bern ( ");
outreal (1, p0b2); outstring (1, ", ");
outreal (1, p1b2); outstring (1, ", ");
outreal (1, p2b2); outstring (1, ") --> bern ( ");
outreal (1, pc0); outstring (1, ", ");
outreal (1, pc1); outstring (1, ", ");
outreal (1, pc2); outstring (1, ", ");
outreal (1, pc3); outstring (1, ")\n");
outstring (1, "  bern ( ");
outreal (1, q0b2); outstring (1, ", ");
outreal (1, q1b2); outstring (1, ", ");
outreal (1, q2b2); outstring (1, ") --> bern ( ");
outreal (1, qc0); outstring (1, ", ");
outreal (1, qc1); outstring (1, ", ");
outreal (1, qc2); outstring (1, ", ");
outreal (1, qc3); outstring (1, ")\n")
end
Output:
Subprogram (1) examples:
mono ( 1 , 0 , 0 ) --> bern ( 1 , 1 , 1 )
mono ( 1 , 2 , 3 ) --> bern ( 1 , 2 , 6 )
Subprogram (2) examples:
p ( 0.25 ) = 1
p ( 7.5 ) = 1
q ( 0.25 ) = 1.6875
q ( 7.5 ) = 184.75
Subprogram (3) examples:
mono ( 1 , 0 , 0 , 0 ) --> bern ( 1 , 1 , 1 , 1 )
mono ( 1 , 2 , 3 , 0 ) --> bern ( 1 , 1.66666666667 , 3.33333333333 , 6 )
mono ( 1 , 2 , 3 , 4 ) --> bern ( 1 , 1.66666666667 , 3.33333333333 , 10 )
Subprogram (4) examples:
p ( 0.25 ) = 1
p ( 7.5 ) = 1
q ( 0.25 ) = 1.6875
q ( 7.5 ) = 184.75
r ( 0.25 ) = 1.75
r ( 7.5 ) = 1872.25
Subprogram (5) examples:
bern ( 1 , 1 , 1 ) --> bern ( 1 , 1 , 1 , 1 )
bern ( 1 , 2 , 6 ) --> bern ( 1 , 1.66666666667 , 3.33333333333 , 6 )

## ALGOL 68

BEGIN # Bernstein Basis Polynomials - translated from the Algol 60      #
# Note the "Subrptoghram (n) designations are as specified in the #

MODE BERNTWO   = STRUCT( STRING label, REAL b0, b1, b2 );
MODE BERNTHREE = STRUCT( STRING label, REAL b0, b1, b2, b3 );

PRIO EVAL      = 5; # set the priority of the dyadic EVAL  #

# Subprogram (1): transform monomial coefficients          #
#     a0, a1, a2 to Bernstein coefficients b0, b1, b2      #
PROC tobern2 = ( REAL a0, a1, a2, REF BERNTWO b )VOID:
BEGIN
b0 OF b := a0;
b1 OF b := a0 + ((1/2) * a1);
b2 OF b := a0 + a1 + a2
END # tobern2 # ;

# Subprogram (2): evaluate, at t, the polynomial with      #
#    Bernstein coefficients b0, b1, b2. Use de Casteljau's #
#    algorithm                                             #
OP EVAL = ( BERNTWO b, REAL t )REAL:
BEGIN
REAL s    = 1 - t;
REAL b01  = (s * b0 OF b) + (t * b1 OF b);
REAL b12  = (s * b1 OF b) + (t * b2 OF b);
(s * b01) + (t * b12)
END # EVAL # ;

# Subprogram (3): transform monomial coefficients          #
#     a0, a1, a2, a3 to Bernstein coefficients b0, b1,     #
#     b2, b3                                               #
PROC tobern3 = ( REAL a0, a1, a2, a3, REF BERNTHREE b )VOID:
BEGIN
b0 OF b := a0;
b1 OF b := a0 + ((1/3) * a1);
b2 OF b := a0 + ((2/3) * a1) + ((1/3) * a2);
b3 OF b := a0 + a1 + a2 + a3
END # tobern3 # ;

# Subprogram (4): evaluate, at t, the polynomial           #
#    with Bernstein coefficients b0, b1, b2, b3. Use       #
#    de Casteljau's algorithm                              #
OP EVAL = ( BERNTHREE b, REAL t )REAL:
BEGIN
REAL s    = 1 - t;
REAL b01  = (s * b0 OF b) + (t * b1 OF b);
REAL b12  = (s * b1 OF b) + (t * b2 OF b);
REAL b23  = (s * b2 OF b) + (t * b3 OF b);
REAL b012 = (s * b01) + (t * b12);
REAL b123 = (s * b12) + (t * b23);
(s * b012) + (t * b123)
END # EVAL #;

# Subprogram (5): transform the quadratic Bernstein        #
#    coefficients q0, q1, q2 to the cubic Bernstein        #
#    coefficients c0, c1, c2, c3;                          #
OP   TOBERNTHREE = ( BERNTWO q )BERNTHREE:
BEGIN
HEAP BERNTHREE c;
b0 OF c := b0 OF q;
b1 OF c := ((1/3) * b0 OF q) + ((2/3) * b1 OF q);
b2 OF c := ((2/3) * b1 OF q) + ((1/3) * b2 OF q);
b3 OF c := b2 OF q;
c
END # TOBERNTHREE # ;

BEGIN

# returns x as a string without trailing 0 decoimals    #
PROC f = ( REAL x )STRING:
BEGIN
STRING v       := fixed( x, -14, 11 );
INT    end pos := UPB v;
WHILE IF end pos < LWB v THEN FALSE ELSE v[ end pos ] = "0" FI DO
end pos -:= 1
OD;
IF end pos >= LWB v THEN
IF v[ end pos ] = "." THEN end pos -:= 1 FI
FI;
INT start pos := LWB v;
WHILE IF start pos > end pos THEN FALSE ELSE v[ start pos ] = " " FI DO
start pos +:= 1
OD;
IF end pos < start pos THEN "0" ELSE v[ start pos : end pos ] FI
END # f # ;

PRIO SHOWEVAL = 5;
# prints the result of evaluating p with x             #
OP   SHOWEVAL = ( BERNTWO   p, REAL x )VOID:
print( ( "  ", label OF p, " ( ", f( x ), " ) = ", f( p EVAL x ), newline ) );
# prints the result of evaluating p with x             #
OP   SHOWEVAL = ( BERNTHREE p, REAL x )VOID:
print( ( "  ", label OF p, " ( ", f( x ), " ) = ", f( p EVAL x ), newline ) );
# returns a string representation of the values of p   #
OP   TOSTRING = ( BERNTWO   p )STRING:
"( " + f( b0 OF p ) + ", " + f( b1 OF p ) + ", " + f( b2 OF p ) + " )";
# returns a string representation of the values of p   #
OP   TOSTRING = ( BERNTHREE p )STRING:
"( " + f( b0 OF p ) + ", " + f( b1 OF p ) + ", " + f( b2 OF p ) + ", " + f( b3 OF p ) + " )";
# returns a string representation of the values of p   #
OP   TOSTRING = ( []REAL p )STRING:
BEGIN
STRING result    := "(", separator := "";
FOR i FROM LWB p TO UPB p DO
result   +:= separator + " " + f( p[ i ] );
separator := ","
OD;
result + " )"
END # TOSTRING # ;

BERNTWO   p2 := BERNTWO  ( "p", 0, 0, 0 );
BERNTWO   q2 := BERNTWO  ( "q", 0, 0, 0 );

BERNTHREE p3 := BERNTHREE( "p", 0, 0, 0, 0 );
BERNTHREE q3 := BERNTHREE( "q", 0, 0, 0, 0 );
BERNTHREE r3 := BERNTHREE( "r", 0, 0, 0, 0 );

REAL p0m = 1, p1m = 0, p2m = 0;
REAL q0m = 1, q1m = 2, q2m = 3;
REAL r0m = 1, r1m = 2, r2m = 3, r3m = 4;

tobern2( p0m, p1m, p2m, p2 );
tobern2( q0m, q1m, q2m, q2 );
print( ( "Subprogram (1) examples:", newline ) );
print( ( "  mono ", TOSTRING []REAL( p0m, p1m, p2m ), " --> bern ", TOSTRING p2, newline ) );
print( ( "  mono ", TOSTRING []REAL( q0m, q1m, q2m ), " --> bern ", TOSTRING q2, newline ) );

print( ( "Subprogram (2) examples:", newline ) );
p2 SHOWEVAL 0.25;
p2 SHOWEVAL 7.50;
q2 SHOWEVAL 0.25;
q2 SHOWEVAL 7.50;

tobern3( p0m, p1m, p2m, 0,   p3 );
tobern3( q0m, q1m, q2m, 0,   q3 );
tobern3( r0m, r1m, r2m, r3m, r3 );
print( ( "Subprogram (3) examples:", newline ) );
print( ( "  mono ", TOSTRING []REAL( p0m, p1m, p2m, 0   ), " --> bern ", TOSTRING p3, newline ) );
print( ( "  mono ", TOSTRING []REAL( q0m, q1m, q2m, 0   ), " --> bern ", TOSTRING q3, newline ) );
print( ( "  mono ", TOSTRING []REAL( r0m, r1m, r2m, r3m ), " --> bern ", TOSTRING r3, newline ) );

print( ( "Subprogram (4) examples:", newline ) );
p3 SHOWEVAL 0.25;
p3 SHOWEVAL 7.50;
q3 SHOWEVAL 0.25;
q3 SHOWEVAL 7.50;
r3 SHOWEVAL 0.25;
r3 SHOWEVAL 7.50;

print( ( "Subprogram (5) examples:", newline ) );
print( ( "  bern ", TOSTRING p2, " --> bern ", TOSTRING TOBERNTHREE p2, newline ) );
print( ( "  bern ", TOSTRING q2, " --> bern ", TOSTRING TOBERNTHREE q2, newline ) )

END

END
Output:
Subprogram (1) examples:
mono ( 1, 0, 0 ) --> bern ( 1, 1, 1 )
mono ( 1, 2, 3 ) --> bern ( 1, 2, 6 )
Subprogram (2) examples:
p ( 0.25 ) = 1
p ( 7.5 ) = 1
q ( 0.25 ) = 1.6875
q ( 7.5 ) = 184.75
Subprogram (3) examples:
mono ( 1, 0, 0, 0 ) --> bern ( 1, 1, 1, 1 )
mono ( 1, 2, 3, 0 ) --> bern ( 1, 1.66666666667, 3.33333333333, 6 )
mono ( 1, 2, 3, 4 ) --> bern ( 1, 1.66666666667, 3.33333333333, 10 )
Subprogram (4) examples:
p ( 0.25 ) = 1
p ( 7.5 ) = 1
q ( 0.25 ) = 1.6875
q ( 7.5 ) = 184.75
r ( 0.25 ) = 1.75
r ( 7.5 ) = 1872.25
Subprogram (5) examples:
bern ( 1, 1, 1 ) --> bern ( 1, 1, 1, 1 )
bern ( 1, 2, 6 ) --> bern ( 1, 1.66666666667, 3.33333333333, 6 )


## ATS

The following is full of pedagogical comments, which I hope make this mysterious programming language a bit less mysterious. ATS is a very complicated language, whose typechecker does things most language's typecheckers simply do not do.

(The template system also is complicated, and in fact can cause bad C code to be generated. I view this issue as one of bugginess that a determined programmer works around. It is like gfortran not warning you that your misuse of "ALLOCATABLE" is not going to succeed. The compiler writers have concentrated their efforts on other matters.)

(* The following can be compiled with "patscc -O3
source_file_name.dats", or with your preferred optimizer
setting. The ATS compiler generates C that assumes you will do
aggressive optimization, say "-O2" or better.

I like to add GCC's "-std=gnu2x" flag, as well, though I expect
this flag will at some point be changed to "-std=gnu23" or
similar. Otherwise (with the default patscc settings) you get
"-std=c99".

For adventure, try "patscc -std=gnu2x -Ofast -march=native
source_file_name.dats" *)

(* Some macros that are convenient for type-safe floating point
without actually knowing which floating-point type it will
be. These macros will work if, in the context where they appear,
the typechecker can infer which floating-point type is meant. *)
macdef one_third = g0i2f 1 / g0i2f 3
macdef one_half = g0i2f 1 / g0i2f 2
macdef two_thirds = g0i2f 2 / g0i2f 3

(* We will try to achieve the type-safety of distinguishing between
monomial and Bernstein bases at compile time, but without overhead
at runtime. (Such type-safety can be partly achieved in many other
languages simply by giving the types different names but the same
fields. But then you cannot easily have TYPE-SAFE subprograms that
work on EITHER type. You could have that with a type hierarchy, but
then, typically, you start getting overhead from runtime
polymorphism. You could do it by nesting record types within record
types, but then you start needing the overhead of pointers to the
different nested types. Furthermore, these approaches are all
essentially WORKAROUNDS, rather than direct solutions to the
problem, which is "how to distinguish between a tuple representing
coefficients in ONE basis from the exact same kind of tuple
representing coefficients in A DIFFERENT basis, while also treating
both as coefficients in SOME basis, such as for addition or scalar
multiplication". Here we do that by attaching an object to the
tuple AT TYPECHECKING TIME that is entirely left out after
typechecking is complete.) *)
tkindef monoknd = "rosettacode_monomial_poly"
tkindef bernknd = "rosettacode_bernstein_poly"
dataprop BASIS (polyknd : tkind) =
| MONOMIAL_BASIS (monoknd) of ()
| BERNSTEIN_BASIS (bernknd) of ()

typedef poly_degree2 (polyknd : tkind, coefknd : tkind) =
@(BASIS polyknd | g0float coefknd, g0float coefknd,
g0float coefknd)
typedef poly_degree3 (polyknd : tkind, coefknd : tkind) =
@(BASIS polyknd | g0float coefknd, g0float coefknd,
g0float coefknd, g0float coefknd)

(* The :<> below means that the function is proven to terminate, does
not raise exceptions, does not access or write to memory it does
not "own", etc. In practice, however, such requirements are often
masked. The goal of ATS is not formal proof, but bug reduction,
easier debugging, avoidance of the need for runtime checks, etc. *)
fn {coefknd : tkind}            (* Subprogram (1) *)
mono2bern_degree2 (coefs : poly_degree2 (monoknd, coefknd))
:<> poly_degree2 (bernknd, coefknd) =
(* AN EXAMPLE OF ATS2 TYPE-SAFETY: If you try to call
mono2bern_degree2 with Bernstein coefficients (instead of monomial
coefficients) as the argument, then, AT COMPILE TIME, you get
messages similar to these:

/some_path/bernstein_poly_task.dats: 1051(line=32, offs=31) -- 1052(line=32, offs=32): warning(3): the constraint [S2Eeqeq(S2Eextkind(rosettacode_bernstein_poly); S2Eextkind(rosettacode_monomial_poly))] cannot be translated into a form accepted by the constraint solver.
/some_path/bernstein_poly_task.dats: 1051(line=32, offs=31) -- 1052(line=32, offs=32): error(3): unsolved constraint: C3NSTRprop(C3TKmain(); S2Eeqeq(S2Eextkind(rosettacode_bernstein_poly); S2Eextkind(rosettacode_monomial_poly)))
typechecking has failed: there are some unsolved constraints: please inspect the above reported error message(s) for information.
exit(ATS): uncaught exception: _2tmp_2ATS_2dPostiats_2src_2pats_error_2esats__FatalErrorExn(1025)

AT RUNTIME, however, both kinds of polynomial coefficients are
represented by a plain unboxed tuple (that is, by a C struct) of
three numbers, each being of whichever type "g0float coefknd"
happens to be ("float", "double", "ldouble", etc.). *)
let
val+ @(_ | a0, a1, a2) = coefs
in
@(BERNSTEIN_BASIS () | a0, a0 + (one_half * a1), a0 + a1 + a2)
end

fn {coefknd : tkind}            (* Subprogram (2) *)
evalbern_degree2 (coefs : poly_degree2 (bernknd, coefknd),
t     : g0float coefknd)
:<> g0float coefknd =
let
val+ @(_ | b0, b1, b2) = coefs
and s = g0i2f 1 - t

val b01 = (s * b0) + (t * b1)
and b12 = (s * b1) + (t * b2)

val b012 = (s * b01) + (t * b12)
in
b012
end

fn {coefknd : tkind}            (* Subprogram (3) *)
mono2bern_degree3 (coefs : poly_degree3 (monoknd, coefknd))
:<> poly_degree3 (bernknd, coefknd) =
let
val+ @(_ | a0, a1, a2, a3) = coefs
in
@(BERNSTEIN_BASIS () | a0, a0 + (one_third * a1),
a0 + (two_thirds * a1) + (one_third * a2),
a0 + a1 + a2 + a3)
end

fn {coefknd : tkind}            (* Subprogram (4) *)
evalbern_degree3 (coefs : poly_degree3 (bernknd, coefknd),
t     : g0float coefknd)
:<> g0float coefknd =
let
val+ @(_ | b0, b1, b2, b3) = coefs
and s = g0i2f 1 - t

val b01 = (s * b0) + (t * b1)
and b12 = (s * b1) + (t * b2)
and b23 = (s * b2) + (t * b3)

val b012 = (s * b01) + (t * b12)
and b123 = (s * b12) + (t * b23)

val b0123 = (s * b012) + (t * b123)
in
b0123
end

fn {coefknd : tkind}            (* Subprogram (5) *)
bern_degree2_to_3 (coefs : poly_degree2 (bernknd, coefknd))
:<> poly_degree3 (bernknd, coefknd) =
let
val+ @(_ | q0, q1, q2) = coefs
in
@(BERNSTEIN_BASIS () | q0, (one_third * q0) + (two_thirds * q1),
(two_thirds * q1) + (one_third * q2), q2)
end

(* Let us make it easy to print out coefficients. Note that
print_poly_degree2 operates TYPE-SAFELY on ANY object of type
"poly", without regard to whether it represents monomial
coefficients or Bernstein coefficients. In C we might do such a
thing by casting a pointer of one type to a pointer of another
type, but that is not a TYPE-SAFE operation. *)
fn {coefknd : tkind}
print_poly_degree2 {polyknd : tkind}
(coefs : poly_degree2 (polyknd, coefknd))
: void =
let
val+ @(_ | a0, a1, a2) = coefs
macdef outf = stdout_ref
in
fprint_val<string> (outf, "(");
fprint_val<g0float coefknd> (outf, a0);
fprint_val<string> (outf, ", ");
fprint_val<g0float coefknd> (outf, a1);
fprint_val<string> (outf, ", ");
fprint_val<g0float coefknd> (outf, a2);
fprint_val<string> (outf, ")")
end

fn {coefknd : tkind}
print_poly_degree3 {polyknd : tkind}
(coefs : poly_degree3 (polyknd, coefknd))
: void =
let
val+ @(_ | a0, a1, a2, a3) = coefs
macdef outf = stdout_ref
in
fprint_val<string> (outf, "(");
fprint_val<g0float coefknd> (outf, a0);
fprint_val<string> (outf, ", ");
fprint_val<g0float coefknd> (outf, a1);
fprint_val<string> (outf, ", ");
fprint_val<g0float coefknd> (outf, a2);
fprint_val<string> (outf, ", ");
fprint_val<g0float coefknd> (outf, a3);
fprint_val<string> (outf, ")")
end

fn {coefknd : tkind}
print_mono_degree2 (coefs : poly_degree2 (monoknd, coefknd))
: void =
begin
fprint_val<string> (stdout_ref, "mono ");
print_poly_degree2 (coefs)
end

fn {coefknd : tkind}
print_bern_degree2 (coefs : poly_degree2 (bernknd, coefknd))
: void =
begin
fprint_val<string> (stdout_ref, "bern ");
print_poly_degree2 (coefs)
end

fn {coefknd : tkind}
print_mono_degree3 (coefs : poly_degree3 (monoknd, coefknd))
: void =
begin
fprint_val<string> (stdout_ref, "mono ");
print_poly_degree3 (coefs)
end

fn {coefknd : tkind}
print_bern_degree3 (coefs : poly_degree3 (bernknd, coefknd))
: void =
begin
fprint_val<string> (stdout_ref, "bern ");
print_poly_degree3 (coefs)
end

fn {coefknd : tkind}
evalmono_degree2 (coefs : poly_degree2 (monoknd, coefknd),
t     : g0float coefknd)
:<> g0float coefknd =
let
val+ @(_ | a0, a1, a2) = coefs
in
a0 + (t * (a1 + (t * a2)))  (* Horner form. *)
end

fn {coefknd : tkind}
evalmono_degree3 (coefs : poly_degree3 (monoknd, coefknd),
t     : g0float coefknd)
:<> g0float coefknd =
let
val+ @(_ | a0, a1, a2, a3) = coefs
in
a0 + (t * (a1 + (t * (a2 + (t * a3))))) (* Horner form. *)
end

fn
do_examples () : void =
let
(* I am going to use type "float = g0float fltknd". That is, C
single precision. The notation for such a number ends in an
"F" or "f", just as in C. *)
val pmono2 = @(MONOMIAL_BASIS () | 1.0F, 0.0F, 0.0F)
val qmono2 = @(MONOMIAL_BASIS () | 1.0F, 2.0F, 3.0F)
val pbern2 = mono2bern_degree2 (pmono2)

(* ATS often lets you leave out the argument parentheses, as in
the following line. However, unlike in OCaml or Standard ML,
(where parentheses also are often left out) argument
parentheses do NOT indicate that arguments are being passed as
a tuple. *)
val qbern2 = mono2bern_degree2 qmono2

(* ATS will often (if it might not be confused with argument
parentheses, etc.) let you leave out the "@" in an unboxed
tuple. *)
val pmono3 = (MONOMIAL_BASIS () | 1.0F, 0.0F, 0.0F, 0.0F)
val qmono3 = (MONOMIAL_BASIS () | 1.0F, 2.0F, 3.0F, 0.0F)
val rmono3 = (MONOMIAL_BASIS () | 1.0F, 2.0F, 3.0F, 4.0F)
val pbern3 = mono2bern_degree3 (pmono3)
val qbern3 = mono2bern_degree3 (qmono3)
val rbern3 = mono2bern_degree3 (rmono3)

val pbern3a = bern_degree2_to_3 (pbern2)
val qbern3a = bern_degree2_to_3 (qbern2)
in
println! ("Subprogram (1) examples:");
println! ("  ", pmono2, " --> ", pbern2);
println! ("  ", qmono2, " --> ", qbern2);

println! ("Subprogram (2) examples:");
let
(* The following is written in ATS-isms, showing how to do
things (a) in procedural fashion, (b) without an allocator,
(c) without runtime checks, and yet (d) without risk of going
outside the bounds of an array.

Figuring out how I am doing all that is left partly as a
boring exercise for the reader. (Be warned that the use of
for* is not, as far as I know, documented anywhere but in
mailing list archives.)

xs is an array on the stack, and i is a loop variable on the
stack or in a register. The for* loop works like a C
for-loop, except it is proven to terminate, and it guarantees
that xs is never indexed with any value except 0 or 1.

An alternative would have been to use a regular "for" loop
(without the asterisk) and do runtime bounds checks (raising
an exception on check failure). The compiler will NOT let you
index xs with an out-of-bounds index. *)

var xs : array (float, 2) = @[float][2] (0.25F, 7.50F)
var i : Int
in
for* {i : nat | i <= 2} .<2 - i>. (i : int i) =>
(i := 0; i <> 2; i := i + 1)
let
val x = xs[i]
val ypm = evalmono_degree2 (pmono2, x)
and ypb = evalbern_degree2 (pbern2, x)
in
println! ("  p(", x, ") = ", ypb, " (mono: ", ypm, ")")
end;
for* {i : nat | i <= 2} .<2 - i>. (i : int i) =>
(i := 0; i <> 2; i := i + 1)
let
val x = xs[i]
val yqm = evalmono_degree2 (qmono2, x)
and yqb = evalbern_degree2 (qbern2, x)
in
println! ("  q(", x, ") = ", yqb, " (mono: ", yqm, ")")
end
end;

println! ("Subprogram (3) examples:");
println! ("  ", pmono3, " --> ", pbern3);
println! ("  ", qmono3, " --> ", qbern3);
println! ("  ", rmono3, " --> ", rbern3);

println! ("Subprogram (4) examples:");
let
var xs : array (float, 2) = @[float][2] (0.25F, 7.50F)
var i : Int
in
for* {i : nat | i <= 2} .<2 - i>. (i : int i) =>
(i := 0; i <> 2; i := i + 1)
let
val x = xs[i]
val ypm = evalmono_degree3 (pmono3, x)
and ypb = evalbern_degree3 (pbern3, x)
in
println! ("  p(", x, ") = ", ypb, " (mono: ", ypm, ")")
end;
for* {i : nat | i <= 2} .<2 - i>. (i : int i) =>
(i := 0; i <> 2; i := i + 1)
let
val x = xs[i]
val yqm = evalmono_degree3 (qmono3, x)
and yqb = evalbern_degree3 (qbern3, x)
in
println! ("  q(", x, ") = ", yqb, " (mono: ", yqm, ")")
end;
for* {i : nat | i <= 2} .<2 - i>. (i : int i) =>
(i := 0; i <> 2; i := i + 1)
let
val x = xs[i]
val yrm = evalmono_degree3 (rmono3, x)
and yrb = evalbern_degree3 (rbern3, x)
in
println! ("  r(", x, ") = ", yrb, " (mono: ", yrm, ")")
end
end;

println! ("Subprogram (5) examples:");
println! ("  ", pbern2, " --> ", pbern3a);

(* Although ATS is a "semicolon-as-separator" language, the
last semicolon. The ATS language's designer usually has put in
the semicolon, whereas I, being a bit of a purist, usually
leave it out. (And, yes, I do often get errors due to missing
semicolons; in ATS one catches that at compile time. And, at my
work 30 years ago, we programmed in Turbo/Borland Pascal and we
usually put the semicolon in.) *)
println! ("  ", qbern2, " --> ", qbern3a);
end

implement main0 () = do_examples ()
Output:
Subprogram (1) examples:
mono (1.000000, 0.000000, 0.000000) --> bern (1.000000, 1.000000, 1.000000)
mono (1.000000, 2.000000, 3.000000) --> bern (1.000000, 2.000000, 6.000000)
Subprogram (2) examples:
p(0.250000) = 1.000000 (mono: 1.000000)
p(7.500000) = 1.000000 (mono: 1.000000)
q(0.250000) = 1.687500 (mono: 1.687500)
q(7.500000) = 184.750000 (mono: 184.750000)
Subprogram (3) examples:
mono (1.000000, 0.000000, 0.000000, 0.000000) --> bern (1.000000, 1.000000, 1.000000, 1.000000)
mono (1.000000, 2.000000, 3.000000, 0.000000) --> bern (1.000000, 1.666667, 3.333333, 6.000000)
mono (1.000000, 2.000000, 3.000000, 4.000000) --> bern (1.000000, 1.666667, 3.333333, 10.000000)
Subprogram (4) examples:
p(0.250000) = 1.000000 (mono: 1.000000)
p(7.500000) = 1.000000 (mono: 1.000000)
q(0.250000) = 1.687500 (mono: 1.687500)
q(7.500000) = 184.749771 (mono: 184.750000)
r(0.250000) = 1.750000 (mono: 1.750000)
r(7.500000) = 1872.250000 (mono: 1872.250000)
Subprogram (5) examples:
bern (1.000000, 1.000000, 1.000000) --> bern (1.000000, 1.000000, 1.000000, 1.000000)
bern (1.000000, 2.000000, 6.000000) --> bern (1.000000, 1.666667, 3.333333, 6.000000)

## C

Translation of: Wren
#include <stdio.h>

typedef double dbl;

void tobern2(dbl a0, dbl a1, dbl a2, dbl *b0, dbl *b1, dbl *b2) {
*b0 = a0;
*b1 = a0 + a1 / 2;
*b2 = a0 + a1 + a2;
}

/* uses de Casteljau’s algorithm */
dbl evalbern2(dbl b0, dbl b1, dbl b2, dbl t) {
dbl s = 1.0 - t;
dbl b01 = s * b0 + t * b1;
dbl b12 = s * b1 + t * b2;
return s * b01 + t * b12;
}

void tobern3(dbl a0, dbl a1, dbl a2, dbl a3, dbl *b0, dbl *b1, dbl *b2, dbl *b3) {
*b0 = a0;
*b1 = a0 + a1 / 3;
*b2 = a0 + a1 * 2/3 + a2 / 3;
*b3 = a0 + a1 + a2 + a3;
}

/* uses de Casteljau’s algorithm */
dbl evalbern3(dbl b0, dbl b1, dbl b2, dbl b3, dbl t) {
dbl s = 1 - t;
dbl b01  = s * b0  + t * b1;
dbl b12  = s * b1  + t * b2;
dbl b23  = s * b2  + t * b3;
dbl b012 = s * b01 + t * b12;
dbl b123 = s * b12 + t * b23;
return s * b012 + t * b123;
}

void bern2to3(dbl q0, dbl q1, dbl q2, dbl *c0, dbl *c1, dbl *c2, dbl *c3) {
*c0 = q0;
*c1 = q0 / 3   + q1 * 2/3;
*c2 = q1 * 2/3 + q2 / 3;
*c3 = q2;
}

/* uses Horner's rule */
dbl evalmono2(dbl a0, dbl a1, dbl a2, dbl t) {
return a0 + (t * (a1 + (t * a2)));
}

/* uses Horner's rule */
dbl evalmono3(dbl a0, dbl a1, dbl a2, dbl a3, dbl t) {
return a0 + (t * (a1 + (t * (a2 + (t * a3)))));
}

int main() {
dbl pm0 = 1, pm1 = 0, pm2 = 0, pm3 = 0, pb0, pb1, pb2, pb3, pc0, pc1, pc2, pc3;
dbl qm0 = 1, qm1 = 2, qm2 = 3, qm3 = 0, qb0, qb1, qb2, qb3, qc0, qc1, qc2, qc3;
dbl rm0 = 1, rm1 = 2, rm2 = 3, rm3 = 4, rb0, rb1, rb2, rb3;
dbl x, y, m;
const char *fmt;

printf("Subprogram(1) examples:\n");
tobern2(pm0, pm1, pm2, &pb0, &pb1, &pb2);
tobern2(qm0, qm1, qm2, &qb0, &qb1, &qb2);
fmt = "mono {%g, %g, %g} --> bern {%g, %g, %g}\n";
printf(fmt, pm0, pm1, pm2, pb0, pb1, pb2);
printf(fmt, qm0, qm1, qm2, qb0, qb1, qb2);

printf("\nSubprogram(2) examples:\n");
x = 0.25;
y = evalbern2(pb0, pb1, pb2, x);
m = evalmono2(pm0, pm1, pm2, x);
printf("p(%4.2f) = %g (mono %g)\n", x, y, m);
x = 7.5;
y = evalbern2(pb0, pb1, pb2, x);
m = evalmono2(pm0, pm1, pm2, x);
printf("p(%4.2f) = %g (mono %g)\n", x, y, m);
x = 0.25;
y = evalbern2(qb0, qb1, qb2, x);
m = evalmono2(qm0, qm1, qm2, x);
printf("q(%4.2f) = %g (mono %g)\n", x, y, m);
x = 7.5;
y = evalbern2(qb0, qb1, qb2, x);
m = evalmono2(qm0, qm1, qm2, x);
printf("q(%4.2f) = %g (mono %g)\n", x, y, m);

printf("\nSubprogram(3) examples:\n");
tobern3(pm0, pm1, pm2, pm3, &pb0, &pb1, &pb2, &pb3);
tobern3(qm0, qm1, qm2, qm3, &qb0, &qb1, &qb2, &qb3);
tobern3(rm0, rm1, rm2, rm3, &rb0, &rb1, &rb2, &rb3);
fmt = "mono {%g, %g, %g, %g} --> bern {%0.14g, %0.14g, %0.14g, %0.14g}\n";
printf(fmt, pm0, pm1, pm2, pm3, pb0, pb1, pb2, pb3);
printf(fmt, qm0, qm1, qm2, qm3, qb0, qb1, qb2, qb3);
printf(fmt, rm0, rm1, rm2, rm3, rb0, rb1, rb2, rb3);

printf("\nSubprogram(4) examples:\n");
x = 0.25;
y = evalbern3(pb0, pb1, pb2, pb3, x);
m = evalmono3(pm0, pm1, pm2, pm3, x);
printf("p(%4.2f) = %g (mono %g)\n", x, y, m);
x = 7.5;
y = evalbern3(pb0, pb1, pb2, pb3, x);
m = evalmono3(pm0, pm1, pm2, pm3, x);
printf("p(%4.2f) = %g (mono %g)\n", x, y, m);
x = 0.25;
y = evalbern3(qb0, qb1, qb2, qb3, x);
m = evalmono3(qm0, qm1, qm2, qm3, x);
printf("q(%4.2f) = %g (mono %g)\n", x, y, m);
x = 7.5;
y = evalbern3(qb0, qb1, qb2, qb3, x);
m = evalmono3(qm0, qm1, qm2, qm3, x);
printf("q(%4.2f) = %g (mono %g)\n", x, y, m);
x = 0.25;
y = evalbern3(rb0, rb1, rb2, rb3, x);
m = evalmono3(rm0, rm1, rm2, rm3, x);
printf("r(%4.2f) = %g (mono %g)\n", x, y, m);
x = 7.5;
y = evalbern3(rb0, rb1, rb2, rb3, x);
m = evalmono3(rm0, rm1, rm2, rm3, x);
printf("r(%4.2f) = %g (mono %g)\n", x, y, m);

printf("\nSubprogram(5) examples:\n");
tobern2(pm0, pm1, pm2, &pb0, &pb1, &pb2);
tobern2(qm0, qm1, qm2, &qb0, &qb1, &qb2);
bern2to3(pb0, pb1, pb2, &pc0, &pc1, &pc2, &pc3);
bern2to3(qb0, qb1, qb2, &qc0, &qc1, &qc2, &qc3);
fmt = "mono {%g, %g, %g} --> bern {%0.14g, %0.14g, %0.14g, %0.14g}\n";
printf(fmt, pb0, pb1, pb2, pc0, pc1, pc2, pc3);
printf(fmt, qb0, qb1, qb2, qc0, qc1, qc2, qc3);

return 0;
}

Output:
Subprogram(1) examples:
mono {1, 0, 0} --> bern {1, 1, 1}
mono {1, 2, 3} --> bern {1, 2, 6}

Subprogram(2) examples:
p(0.25) = 1 (mono 1)
p(7.50) = 1 (mono 1)
q(0.25) = 1.6875 (mono 1.6875)
q(7.50) = 184.75 (mono 184.75)

Subprogram(3) examples:
mono {1, 0, 0, 0} --> bern {1, 1, 1, 1}
mono {1, 2, 3, 0} --> bern {1, 1.6666666666667, 3.3333333333333, 6}
mono {1, 2, 3, 4} --> bern {1, 1.6666666666667, 3.3333333333333, 10}

Subprogram(4) examples:
p(0.25) = 1 (mono 1)
p(7.50) = 1 (mono 1)
q(0.25) = 1.6875 (mono 1.6875)
q(7.50) = 184.75 (mono 184.75)
r(0.25) = 1.75 (mono 1.75)
r(7.50) = 1872.25 (mono 1872.25)

Subprogram(5) examples:
mono {1, 1, 1} --> bern {1, 1, 1, 1}
mono {1, 2, 6} --> bern {1, 1.6666666666667, 3.3333333333333, 6}


## FreeBASIC

Translation of: ALGOL 60
Dim Shared b0 As Double, b1 As Double, b2 As Double

Sub tobern2 (Byval a0 As Double, Byval a1 As Double, Byval a2 As Double, _
Byref b0 As Double, Byref b1 As Double, Byref b2 As Double)
' Subprogram (1): transform monomial coefficients
'        a0, a1, a2 to Bernstein coefficients b0, b1, b2

b0 = a0
b1 = a0 + ((1/2) * a1)
b2 = a0 + a1 + a2
End Sub

Function evalbern2 (b0 As Double, b1 As Double, b2 As Double, t As Double) As Double
' Subprogram (2): evaluate, at t, the polynomial with
'        Bernstein coefficients b0, b1, b2. Use de Casteljau's algorithm

Dim As Double s, b01, b12, b012
s = 1 - t
b01 = (s * b0) + (t * b1)
b12 = (s * b1) + (t * b2)
b012 = (s * b01) + (t * b12)
Return b012
End Function

Sub tobern3 (Byval a0 As Double, Byval a1 As Double, Byval a2 As Double, Byval a3 As Double, _
Byref b0 As Double, Byref b1 As Double, Byref b2 As Double, Byref b3 As Double)
' Subprogram (3): transform monomial coefficients
'        a0, a1, a2, a3 to Bernstein coefficients b0, b1, b2, b3

b0 = a0
b1 = a0 + ((1/3) * a1)
b2 = a0 + ((2/3) * a1) + ((1/3) * a2)
b3 = a0 + a1 + a2 + a3
End Sub

Function evalbern3 (b0 As Double, b1 As Double, b2 As Double, _
b3 As Double, t As Double) As Double
' Subprogram (4): evaluate, at t, the polynomial
'        with Bernstein coefficients b0, b1, b2, b3.
'        Use de Casteljau's algorithm

Dim As Double s, b01, b12, b23, b012, b123, b0123
s = 1 - t
b01 = (s * b0) + (t * b1)
b12 = (s * b1) + (t * b2)
b23 = (s * b2) + (t * b3)
b012 = (s * b01) + (t * b12)
b123 = (s * b12) + (t * b23)
b0123 = (s * b012) + (t * b123)
Return b0123
End Function

Sub bern2to3 (Byval q0 As Double, Byval q1 As Double, Byval q2 As Double, _
Byref c0 As Double, Byref c1 As Double, Byref c2 As Double, Byref c3 As Double)
' Subprogram (5): transform the quadratic Bernstein
'        coefficients q0, q1, q2 to the cubic Bernstein
'        coefficients c0, c1, c2, c3

c0 = q0
c1 = ((1/3) * q0) + ((2/3) * q1)
c2 = ((2/3) * q1) + ((1/3) * q2)
c3 = q2
End Sub

Dim As Double p0b2, p1b2, p2b2
Dim As Double q0b2, q1b2, q2b2

Dim As Double p0b3, p1b3, p2b3, p3b3
Dim As Double q0b3, q1b3, q2b3, q3b3
Dim As Double r0b3, r1b3, r2b3, r3b3

Dim As Double pc0, pc1, pc2, pc3
Dim As Double qc0, qc1, qc2, qc3

Dim As Double x, y

Dim As Double p0m = 1, p1m = 0, p2m = 0
Dim As Double q0m = 1, q1m = 2, q2m = 3
Dim As Double r0m = 1, r1m = 2, r2m = 3, r3m = 4

tobern2 (p0m, p1m, p2m, p0b2, p1b2, p2b2)
tobern2 (q0m, q1m, q2m, q0b2, q1b2, q2b2)
Print "Subprogram (1) examples:"
Print Using "  mono (#.##, #.##, #.##) --> bern (#.##, #.##, #.##)"; p0m; p1m; p2m; p0b2; p1b2; p2b2
Print Using "  mono (#.##, #.##, #.##) --> bern (#.##, #.##, #.##)"; q0m; q1m; q2m; q0b2; q1b2; q2b2

Print "Subprogram (2) examples:"
x = 0.25
y = evalbern2 (p0b2, p1b2, p2b2, x)
Print Using "  p (#.##) = ###.##"; x; y
x = 7.50
y = evalbern2 (p0b2, p1b2, p2b2, x)
Print Using "  p (#.##) = ###.##"; x; y
x = 0.25
y = evalbern2 (q0b2, q1b2, q2b2, x)
Print Using "  q (#.##) = ###.##"; x; y
x = 7.50
y = evalbern2 (q0b2, q1b2, q2b2, x)
Print Using "  q (#.##) = ###.##"; x; y

tobern3 (p0m, p1m, p2m, 0, p0b3, p1b3, p2b3, p3b3)
tobern3 (q0m, q1m, q2m, 0, q0b3, q1b3, q2b3, q3b3)
tobern3 (r0m, r1m, r2m, r3m, r0b3, r1b3, r2b3, r3b3)
Print "Subprogram (3) examples:"
Print Using "  mono (#.##, #.##, #.##, 0.00) --> bern (#.##, #.##, #.##, ##.##)"; p0m; p1m; p2m; p0b3; p1b3; p2b3; p3b3
Print Using "  mono (#.##, #.##, #.##, 0.00) --> bern (#.##, #.##, #.##, ##.##)"; q0m; q1m; q2m; q0b3; q1b3; q2b3; q3b3
Print Using "  mono (#.##, #.##, #.##, #.##) --> bern (#.##, #.##, #.##, ##.##)"; r0m; r1m; r2m; r3m; r0b3; r1b3; r2b3; r3b3

Print "Subprogram (4) examples:"
x = 0.25
y = evalbern3 (p0b3, p1b3, p2b3, p3b3, x)
Print Using "  p (#.##) = ####.##"; x; y
x = 7.50
y = evalbern3 (p0b3, p1b3, p2b3, p3b3, x)
Print Using "  p (#.##) = ####.##"; x; y
x = 0.25
y = evalbern3 (q0b3, q1b3, q2b3, q3b3, x)
Print Using "  q (#.##) = ####.##"; x; y
x = 7.50
y = evalbern3 (q0b3, q1b3, q2b3, q3b3, x)
Print Using "  q (#.##) = ####.##"; x; y
x = 0.25
y = evalbern3 (r0b3, r1b3, r2b3, r3b3, x)
Print Using "  r (#.##) = ####.##"; x; y
x = 7.50
y = evalbern3 (r0b3, r1b3, r2b3, r3b3, x)
Print Using "  r (#.##) = ####.##"; x; y

bern2to3 (p0b2, p1b2, p2b2, pc0, pc1, pc2, pc3)
bern2to3 (q0b2, q1b2, q2b2, qc0, qc1, qc2, qc3)
Print "Subprogram (5) examples:"
Print Using "  bern (#.##, #.##, #.##) --> bern (#.##, #.##, #.##, #.##)"; p0b2; p1b2; p2b2; pc0; pc1; pc2; pc3
Print Using "  bern (#.##, #.##, #.##) --> bern (#.##, #.##, #.##, #.##)"; q0b2; q1b2; q2b2; qc0; qc1; qc2; qc3

Sleep

Output:
Subprogram (1) examples:
mono (1.00, 0.00, 0.00) --> bern (1.00, 1.00, 1.00)
mono (1.00, 2.00, 3.00) --> bern (1.00, 2.00, 6.00)
Subprogram (2) examples:
p (0.25) =   1.00
p (7.50) =   1.00
q (0.25) =   1.69
q (7.50) = 184.75
Subprogram (3) examples:
mono (1.00, 0.00, 0.00, 0.00) --> bern (1.00, 1.00, 1.00,  1.00)
mono (1.00, 2.00, 3.00, 0.00) --> bern (1.00, 1.67, 3.33,  6.00)
mono (1.00, 2.00, 3.00, 4.00) --> bern (1.00, 1.67, 3.33, 10.00)
Subprogram (4) examples:
p (0.25) =    1.00
p (7.50) =    1.00
q (0.25) =    1.69
q (7.50) =  184.75
r (0.25) =    1.75
r (7.50) = 1872.25
Subprogram (5) examples:
bern (1.00, 1.00, 1.00) --> bern (1.00, 1.00, 1.00, 1.00)
bern (1.00, 2.00, 6.00) --> bern (1.00, 1.67, 3.33, 6.00)

## Go

Translation of: Wren
package main

import "fmt"

func toBern2(a []float64) []float64 {
return []float64{a[0], a[0] + a[1]/2, a[0] + a[1] + a[2]}
}

// uses de Casteljau's algorithm
func evalBern2(b []float64, t float64) float64 {
s := 1.0 - t
b01 := s*b[0] + t*b[1]
b12 := s*b[1] + t*b[2]
return s*b01 + t*b12
}

func toBern3(a []float64) []float64 {
b := make([]float64, 4)
b[0] = a[0]
b[1] = a[0] + a[1]/3
b[2] = a[0] + a[1]*2/3 + a[2]/3
b[3] = a[0] + a[1] + a[2] + a[3]
return b
}

// uses de Casteljau's algorithm
func evalBern3(b []float64, t float64) float64 {
s := 1.0 - t
b01 := s*b[0] + t*b[1]
b12 := s*b[1] + t*b[2]
b23 := s*b[2] + t*b[3]
b012 := s*b01 + t*b12
b123 := s*b12 + t*b23
return s*b012 + t*b123
}

func bern2to3(q []float64) []float64 {
c := make([]float64, 4)
c[0] = q[0]
c[1] = q[0]/3 + q[1]*2/3
c[2] = q[1]*2/3 + q[2]/3
c[3] = q[2]
return c
}

// uses Horner's rule
func evalMono2(a []float64, t float64) float64 {
return a[0] + (t * (a[1] + (t * a[2])))
}

// uses Horner's rule
func evalMono3(a []float64, t float64) float64 {
return a[0] + (t * (a[1] + (t * (a[2] + (t * a[3])))))
}

func main() {
pm := []float64{1, 0, 0}
qm := []float64{1, 2, 3}
rm := []float64{1, 2, 3, 4}
var x, y, m float64
fmt.Println("Subprogram(1) examples:")
pb2 := toBern2(pm)
qb2 := toBern2(qm)
fmt.Printf("mono %v --> bern %v\n", pm, pb2)
fmt.Printf("mono %v --> bern %v\n", qm, qb2)

fmt.Println("\nSubprogram(2) examples:")
x = 0.25
y = evalBern2(pb2, x)
m = evalMono2(pm, x)
fmt.Printf("p(%4.2f) = %0.14g (mono %0.14g)\n", x, y, m)
x = 7.5
y = evalBern2(pb2, x)
m = evalMono2(pm, x)
fmt.Printf("p(%4.2f) = %0.14g (mono %0.14g)\n", x, y, m)
x = 0.25
y = evalBern2(qb2, x)
m = evalMono2(qm, x)
fmt.Printf("q(%4.2f) = %0.14g (mono %0.14g)\n", x, y, m)
x = 7.5
y = evalBern2(qb2, x)
m = evalMono2(qm, x)
fmt.Printf("q(%4.2f) = %0.14g (mono %0.14g)\n", x, y, m)

fmt.Println("\nSubprogram(3) examples:")
pm = append(pm, 0)
qm = append(qm, 0)
pb3 := toBern3(pm)
qb3 := toBern3(qm)
rb3 := toBern3(rm)
f := "mono $%v --> bern %0.14v\n" fmt.Printf(f, pm, pb3) fmt.Printf(f, qm, qb3) fmt.Printf(f, rm, rb3) fmt.Println("\nSubprogram(4) examples:") x = 0.25 y = evalBern3(pb3, x) m = evalMono3(pm, x) fmt.Printf("p(%4.2f) = %0.14g (mono %0.14g)\n", x, y, m) x = 7.5 y = evalBern3(pb3, x) m = evalMono3(pm, x) fmt.Printf("p(%4.2f) = %0.14g (mono %0.14g)\n", x, y, m) x = 0.25 y = evalBern3(qb3, x) m = evalMono3(qm, x) fmt.Printf("q(%4.2f) = %0.14g (mono %0.14g)\n", x, y, m) x = 7.5 y = evalBern3(qb3, x) m = evalMono3(qm, x) fmt.Printf("q(%4.2f) = %0.14g (mono %0.14g)\n", x, y, m) x = 0.25 y = evalBern3(rb3, x) m = evalMono3(rm, x) fmt.Printf("r(%4.2f) = %0.14g (mono %0.14g)\n", x, y, m) x = 7.5 y = evalBern3(rb3, x) m = evalMono3(rm, x) fmt.Printf("r(%4.2f) = %0.14g (mono %0.14g)\n", x, y, m) fmt.Println("\nSubprogram(5) examples:") pc := bern2to3(pb2) qc := bern2to3(qb2) fmt.Printf("mono %v --> bern %0.14v\n", pb2, pc) fmt.Printf("mono %v --> bern %0.14v\n", qb2, qc) }  Output: Subprogram(1) examples: mono [1 0 0] --> bern [1 1 1] mono [1 2 3] --> bern [1 2 6] Subprogram(2) examples: p(0.25) = 1 (mono 1) p(7.50) = 1 (mono 1) q(0.25) = 1.6875 (mono 1.6875) q(7.50) = 184.75 (mono 184.75) Subprogram(3) examples: mono$[1 0 0 0] --> bern [1 1 1 1]
mono $[1 2 3 0] --> bern [1 1.6666666666667 3.3333333333333 6] mono$[1 2 3 4] --> bern [1 1.6666666666667 3.3333333333333 10]

Subprogram(4) examples:
p(0.25) = 1 (mono 1)
p(7.50) = 1 (mono 1)
q(0.25) = 1.6875 (mono 1.6875)
q(7.50) = 184.75 (mono 184.75)
r(0.25) = 1.75 (mono 1.75)
r(7.50) = 1872.25 (mono 1872.25)

Subprogram(5) examples:
mono [1 1 1] --> bern [1 1 1 1]
mono [1 2 6] --> bern [1 1.6666666666667 3.3333333333333 6]


## jq

Works with jq and gojq, the C and Go implementations of jq

def toBern2(a):
[a[0], a[0] + a[1] / 2,
a[0] + a[1] + a[2]];

# uses de Casteljau's algorithm
def evalBern2($b;$t):
(1 - $t) as$s
| ($s *$b[0] + $t *$b[1]) as $b01 | ($s * $b[1] +$t * $b[2]) as$b12
| $s *$b01 + $t *$b12;

def toBern3(a):
[a[0],
a[0] + a[1] / 3,
a[0] + a[1] * 2/3 + a[2] / 3,
a[0] + a[1] + a[2] + a[3] ];

# uses de Casteljau's algorithm
def evalBern3($b;$t):
(1 - $t) as$s
| ($s *$b[0] + $t *$b[1]) as $b01 | ($s * $b[1] +$t * $b[2]) as$b12
| ($s *$b[2] + $t *$b[3]) as $b23 | ($s * $b01 +$t * $b12) as$b012
| ($s *$b12  + $t *$b23) as $b123 |$s * $b012 +$t * $b123; def bern2to3(q): [q[0], q[0] / 3 + q[1] * 2/3, q[1] * 2/3 + q[2] / 3, q[2]] ; def pm: [1, 0, 0]; def qm: [1, 2, 3]; def rm: [1, 2, 3, 4]; def pb2: toBern2(pm); def qb2: toBern2(qm); "Subprogram(1) examples:", "mono\(pm) --> bern\(pb2)", "mono\(qm) --> bern\(qb2)", "\nSubprogram(2) examples:", ({x: 0.25} | .y = evalBern2(pb2; .x) | "p(\(.x)) = \(.y)" ), ({x: 7.5} | .y = evalBern2(pb2; .x) | "p(\(.x)) = \(.y)" ), ({x: 0.25} | .y = evalBern2(qb2; .x) | "q(\(.x)) = \(.y)" ), ({x: 7.5} | .y = evalBern2(qb2; .x) | "q(\(.x)) = \(.y)" ), "\nSubprogram(3) examples:", ({} | .pm0 = pm + [0] | .qm0 = qm + [0] | .pb3 = toBern3(.pm0) | .qb3 = toBern3(.qm0) | .rb3 = toBern3(rm) | "mono\(.pm0) --> bern\(.pb3)", "mono\(.qm0) --> bern\(.qb3)", "mono\(rm) --> bern\(.rb3)", "\nSubprogram(4) examples:", ( .x = 0.25 | .y = evalBern3(.pb3; .x) | "p(\(.x)) = \(.y)" ), ( .x = 7.5 | .y = evalBern3(.pb3; .x) | "p(\(.x)) = \(.y)" ), ( .x = 0.25 | .y = evalBern3(.qb3; .x) | "q(\(.x)) = \(.y)" ), ( .x = 7.5 | .y = evalBern3(.qb3; .x) | "q(\(.x)) = \(.y)" ), ( .x = 0.25 | .y = evalBern3(.rb3; .x) | "r(\(.x)) = \(.y)" ), ( .x = 7.5 | .y = evalBern3(.rb3; .x) | "r(\(.x)) = \(.y)" ), "\nSubprogram(5) examples:", "mono\(pb2) --> bern\( bern2to3(pb2))", "mono\(qb2) --> bern\( bern2to3(qb2) )" ) Output: Subprogram(1) examples: mono[1,0,0] --> bern[1,1,1] mono[1,2,3] --> bern[1,2,6] Subprogram(2) examples: p(0.25) = 1 p(7.5) = 1 q(0.25) = 1.6875 q(7.5) = 184.75 Subprogram(3) examples: mono[1,0,0,0] --> bern[1,1,1,1] mono[1,2,3,0] --> bern[1,1.6666666666666665,3.333333333333333,6] mono[1,2,3,4] --> bern[1,1.6666666666666665,3.333333333333333,10] Subprogram(4) examples: p(0.25) = 1 p(7.5) = 1 q(0.25) = 1.6874999999999998 q(7.5) = 184.75000000000034 r(0.25) = 1.7499999999999998 r(7.5) = 1872.25 Subprogram(5) examples: mono[1,1,1] --> bern[1,1,1,1] mono[1,2,6] --> bern[1,1.6666666666666665,3.333333333333333,6]  ## Julia Translation of: Python """ rosettacode.org/wiki/Bernstein_basis_polynomials """ """ Subprogram (1). """ monomial_to_bernstein_degree2(mc) = ((a0, a1, a2) = mc; (a0, a0 + ((1/2) * a1), a0 + a1 + a2)) """ Subprogram (2). """ function evaluate_bernstein_degree2(bernstein_coefficients, t) (b0, b1, b2) = bernstein_coefficients # de Casteljau’s algorithm. s = 1 - t b01 = (s * b0) + (t * b1) b12 = (s * b1) + (t * b2) b012 = (s * b01) + (t * b12) return b012 end """ Subprogram (3). """ function monomial_to_bernstein_degree3(monomial_coefficients) (a0, a1, a2, a3) = monomial_coefficients return (a0, a0 + ((1/3) * a1), a0 + ((2/3) * a1) + ((1/3) * a2), a0 + a1 + a2 + a3) end """ Subprogram (4). """ function evaluate_bernstein_degree3(bernstein_coefficients, t) (b0, b1, b2, b3) = bernstein_coefficients # de Casteljau’s algorithm. s = 1 - t b01 = (s * b0) + (t * b1) b12 = (s * b1) + (t * b2) b23 = (s * b2) + (t * b3) b012 = (s * b01) + (t * b12) b123 = (s * b12) + (t * b23) b0123 = (s * b012) + (t * b123) return b0123 end """ Subprogram (5). """ function bernstein_degree2_to_degree3(bernstein_coefficients) (b0, b1, b2) = bernstein_coefficients return (b0, ((1/3) * b0) + ((2/3) * b1), ((2/3) * b1) + ((1/3) * b2), b2) end evaluate_monomial_degree2(mc, t) = ((a0, a1, a2) = mc; a0 + (t * (a1 + (t * a2)))) evaluate_monomial_degree3(mc, t) = ((a0, a1, a2, a3) = mc; a0 + (t * (a1 + (t * (a2 + (t * a3)))))) # # For the following polynomials, use Subprogram (1) to find # coefficients in the degree-2 Bernstein basis: # # p(x) = 1 # q(x) = 1 + 2x + 3x² # # Display the results. # pmono2 = (1, 0, 0) qmono2 = (1, 2, 3) pbern2 = monomial_to_bernstein_degree2(pmono2) qbern2 = monomial_to_bernstein_degree2(qmono2) println("Subprogram (1) examples:") println(" mono ", pmono2, " --> bern ", pbern2) println(" mono ", qmono2, " --> bern ", qbern2) # # Use Subprogram (2) to evaluate p(x) and q(x) at x = 0.25, 7.50. # Display the results. Optionally also display results from evaluating # in the original monomial basis. println("Subprogram (2) examples:") for x in (0.25, 7.50) println(" p(", x, ") = ", evaluate_bernstein_degree2(pbern2, x), " ( mono: ", evaluate_monomial_degree2(pmono2, x), ")") end for x in (0.25, 7.50) println(" q(", x, ") = ", evaluate_bernstein_degree2(qbern2, x), " ( mono: ", evaluate_monomial_degree2(qmono2, x), ")") end # # For the following polynomials, use Subprogram (3) to find # coefficients in the degree-3 Bernstein basis: # # p(x) = 1 # q(x) = 1 + 2x + 3x² # r(x) = 1 + 2x + 3x² + 4x³ # # Display the results. # pmono3 = (1, 0, 0, 0) qmono3 = (1, 2, 3, 0) rmono3 = (1, 2, 3, 4) pbern3 = monomial_to_bernstein_degree3(pmono3) qbern3 = monomial_to_bernstein_degree3(qmono3) rbern3 = monomial_to_bernstein_degree3(rmono3) println("Subprogram (3) examples:") println(" mono ", pmono3, " --> bern ", pbern3) println(" mono ", qmono3, " --> bern ", qbern3) println(" mono ", rmono3, " --> bern ", rbern3) # # Use Subprogram (4) to evaluate p(x), q(x), and r(x) at x = 0.25, # 7.50. Display the results. Optionally also display results from # evaluating in the original monomial basis. println("Subprogram (4) examples:") for x in (0.25, 7.50) println(" p(", x, ") = " , evaluate_bernstein_degree3(pbern3, x), " ( mono: " , evaluate_monomial_degree3(pmono3, x), ")") end for x in (0.25, 7.50) println(" q(", x, ") = ", evaluate_bernstein_degree3(qbern3, x), " ( mono: ", evaluate_monomial_degree3(qmono3, x), ")") end for x in (0.25, 7.50) println(" r(", x, ") = ", evaluate_bernstein_degree3(rbern3, x), " ( mono: ", evaluate_monomial_degree3(rmono3, x), ")") end # # For the following polynomials, using the result of Subprogram (1) # applied to the polynomial, use Subprogram (5) to get coefficients # for the degree-3 Bernstein basis: # # p(x) = 1 # q(x) = 1 + 2x + 3x² # # Display the results. # println("Subprogram (5) examples:") pbern3a = bernstein_degree2_to_degree3(pbern2) qbern3a = bernstein_degree2_to_degree3(qbern2) println(" bern ", pbern2, " --> bern ", pbern3a) println(" bern ", qbern2, " --> bern ", qbern3a)  Output: Same as Python example. ## M4 This works (insofar as it does work) with every m4 I have, including the "legacy" Heirloom Development Tools m4. divert(-1) # # POSIX m4 has only "signed integer arithmetic with at least 32-bit # precision", so I use integers and scaling. # # Be aware that overflows might be silently ignored by m4, resulting # in nonsense being printed. I demonstrate this below (where the value # of the polynomial exceeds four times the cube of 7.50). # # (Were I trying to implement this task more reliably, it would be by # first implementing decimal arithmetic in m4, with a large or # arbitrary number of digits. Which is something I have not, to date, # ever done.) # define(printnum',eval(($1)/10000).eval(($1)%10000)') define(printpoly2',_$0($1)') define(_printpoly2', (printnum($1), printnum($2), printnum($3))')

define(printpoly3',_$0($1)')
define(_printpoly3',
(printnum($1), printnum($2), printnum($3), printnum($4))')

# Subprogram (1).
define(tobern2',_$0($1)')
define(_tobern2',
$1,eval(($1) + (($2) * 5)/10),eval(($1) + ($2) + ($3))')

# Subprogram (2).
define(evalbern2',_$0($1,$2)') define(_evalbern2', pushdef(t',eval(($4)))'pushdef(s',eval(100 - t))dnl
pushdef(b01',eval((s * ($1))/100 + (t * ($2))/100))dnl
pushdef(b12',eval((s * ($2))/100 + (t * ($3))/100))dnl
eval((s * b01)/100 + (t * b12)/100)dnl
popdef(s',t',b01',b12')')

# Subprogram (3).
define(tobern3',_$0($1)')
define(_tobern3',
$1,eval(($1) + (($2) * 3333)/10000),dnl eval(($1) + (($2) * 6667)/10000 + (($3) * 3333)/10000),dnl
eval(($1) + ($2) + ($3) + ($4))')

# Subprogram (4).
define(evalbern3',_$0($1,$2)') define(_evalbern3', pushdef(t',eval(($5)))'pushdef(s',eval(100 - t))dnl
pushdef(b01',eval((s * ($1))/100 + (t * ($2))/100))dnl
pushdef(b12',eval((s * ($2))/100 + (t * ($3))/100))dnl
pushdef(b23',eval((s * ($3))/100 + (t * ($4))/100))dnl
pushdef(b012',eval((s * b01)/100 + (t * b12)/100))dnl
popdef(b01')dnl
pushdef(b123',eval((s * b12)/100 + (t * b23)/100))dnl
popdef(b12',b23')dnl
eval((s * b012)/100 + (t * b123)/100)dnl
popdef(s',t',b012',b123')')

# Subprogram (5).
define(bern2to3',_$0($1)')
define(_bern2to3',
$1,eval((($1) * 3333)/10000 + (($2) * 6667)/10000),dnl eval((($2) * 6667)/10000 + (($3) * 3333)/10000),$3')

define(pmono2',10000,00000,00000'')
define(qmono2',10000,20000,30000'')

define(pbern2',tobern2(pmono2)')
define(qbern2',tobern2(qmono2)')

define(pmono3',10000,00000,00000,00000'')
define(qmono3',10000,20000,30000,00000'')
define(rmono3',10000,20000,30000,40000'')
define(pbern3',tobern3(pmono3)')
define(qbern3',tobern3(qmono3)')
define(rbern3',tobern3(rmono3)')

define(pbern3a',bern2to3(pbern2')')
define(qbern3a',bern2to3(qbern2')')

divert'dnl
Subprogram (1) examples:
mono printpoly2(pmono2) --> bern printpoly2(pbern2')
mono printpoly2(qmono2) --> bern printpoly2(qbern2')
Subprogram (2) examples:
p(0.25) = printnum(evalbern2(pbern2',25))
p(7.50) = printnum(evalbern2(pbern2',750))
q(0.25) = printnum(evalbern2(qbern2',25))
q(7.50) = printnum(evalbern2(qbern2',750))
Subprogram (3) examples:
mono printpoly3(pmono3) --> bern printpoly3(pbern3')
mono printpoly3(qmono3) --> bern printpoly3(qbern3')
mono printpoly3(rmono3) --> bern printpoly3(rbern3')
Subprogram (4) examples:
p(0.25) = printnum(evalbern3(pbern3',25))
p(7.50) = printnum(evalbern3(pbern3',750))
q(0.25) = printnum(evalbern3(qbern3',25)) <-- rounding error
q(7.50) = printnum(evalbern3(qbern3',750)) <-- rounding error
r(0.25) = printnum(evalbern3(rbern3',25)) <-- rounding error
r(7.50) = printnum(evalbern3(rbern3',750)) <-- overflow
Subprogram (5) examples:
printpoly2(pbern2') --> printpoly3(pbern3a')
printpoly2(qbern2') --> printpoly3(qbern3a')
Output:
Subprogram (1) examples:
mono (1.0, 0.0, 0.0) --> bern (1.0, 1.0, 1.0)
mono (1.0, 2.0, 3.0) --> bern (1.0, 2.0, 6.0)
Subprogram (2) examples:
p(0.25) = 1.0
p(7.50) = 1.0
q(0.25) = 1.6875
q(7.50) = 184.7500
Subprogram (3) examples:
mono (1.0, 0.0, 0.0, 0.0) --> bern (1.0, 1.0, 1.0, 1.0)
mono (1.0, 2.0, 3.0, 0.0) --> bern (1.0, 1.6666, 3.3333, 6.0)
mono (1.0, 2.0, 3.0, 4.0) --> bern (1.0, 1.6666, 3.3333, 10.0)
Subprogram (4) examples:
p(0.25) = 1.0
p(7.50) = 1.0
q(0.25) = 1.6872 <-- rounding error
q(7.50) = 184.7306 <-- rounding error
r(0.25) = 1.7497 <-- rounding error
r(7.50) = -2422.-7366 <-- overflow
Subprogram (5) examples:
(1.0, 1.0, 1.0) --> (1.0, 1.0, 1.0, 1.0)
(1.0, 2.0, 6.0) --> (1.0, 1.6667, 3.3332, 6.0)

## Nim

Translation of: Python
type
Coeffs2 = (float, float, float)
Coeffs3 = (float, float, float, float)

# Subprogram (1).
func monomialToBernsteinDegree2(monomialCoefficients: Coeffs2): Coeffs2 =
let (a0, a1, a2) = monomialCoefficients
result = (a0, a0 + ((1/2) * a1), a0 + a1 + a2)

# Subprogram (2).
func evaluateBernsteinDegree2(bernsteinCoefficients: Coeffs2; t: float): float =
let (b0, b1, b2) = bernsteinCoefficients
# de Casteljau’s algorithm.
let s = 1 - t
let b01 = (s * b0) + (t * b1)
let b12 = (s * b1) + (t * b2)
result = (s * b01) + (t * b12)

# Subprogram (3).
func monomialToBernsteinDegree3(monomialCoefficients: Coeffs3): Coeffs3 =
let (a0, a1, a2, a3) = monomialCoefficients
result = (a0, a0 + ((1/3) * a1), a0 + ((2/3) * a1) + ((1/3) * a2), a0 + a1 + a2 + a3)

# Subprogram (4).
func evaluateBernsteinDegree3(bernsteinCoefficients: Coeffs3; t: float): float =
let (b0, b1, b2, b3) = bernsteinCoefficients
# de Casteljau’s algorithm.
let s = 1 - t
let b01 = (s * b0) + (t * b1)
let b12 = (s * b1) + (t * b2)
let b23 = (s * b2) + (t * b3)
let b012 = (s * b01) + (t * b12)
let b123 = (s * b12) + (t * b23)
result = (s * b012) + (t * b123)

# Subprogram (5).
func bernsteinDegree2ToDegree3(bernsteinCoefficients: Coeffs2): Coeffs3 =
let (b0, b1, b2) = bernstein_coefficients
result = (b0, ((1/3) * b0) + ((2/3) * b1), ((2/3) * b1) + ((1/3) * b2), b2)

func evaluateMonomialDegree2(monomialCoefficients: Coeffs2; t: float): float =
let (a0, a1, a2) = monomialCoefficients
# Horner’s rule.
result = a0 + (t * (a1 + (t * a2)))

func evaluateMonomialDegree3(monomialCoefficients: Coeffs3; t: float): float =
let (a0, a1, a2, a3) = monomialCoefficients
# Horner’s rule.
result = a0 + (t * (a1 + (t * (a2 + (t * a3)))))

#
# For the following polynomials, use Subprogram (1) to find
# coefficients in the degree-2 Bernstein basis:
#
#   p(x) = 1
#   q(x) = 1 + 2x + 3x²
#
# Display the results.
#
let pmono2 = (1.0, 0.0, 0.0)
let qmono2 = (1.0, 2.0, 3.0)
let pbern2 = monomialToBernsteinDegree2(pmono2)
let qbern2 = monomialToBernsteinDegree2(qmono2)
echo "Subprogram (1) examples:"
echo "  mono ", pmono2, " --> bern ", pbern2
echo "  mono ", qmono2, " --> bern ", qbern2

#
# Use Subprogram (2) to evaluate p(x) and q(x) at x = 0.25, 7.50.
# Display the results. Optionally also display results from evaluating
# in the original monomial basis.
#
echo "Subprogram (2) examples:"
for x in [0.25, 7.50]:
echo "  p(", x, ") = ", evaluateBernsteinDegree2(pbern2, x),
" (mono: ", evaluateMonomialDegree2(pmono2, x), ')'
for x in [0.25, 7.50]:
echo "  q(", x, ") = ", evaluateBernsteinDegree2(qbern2, x),
" (mono: ", evaluateMonomialDegree2(qmono2, x), ')'

#
# For the following polynomials, use Subprogram (3) to find
# coefficients in the degree-3 Bernstein basis:
#
#   p(x) = 1
#   q(x) = 1 + 2x + 3x²
#   r(x) = 1 + 2x + 3x² + 4x³
#
# Display the results.
#
let pmono3 = (1.0, 0.0, 0.0, 0.0)
let qmono3 = (1.0, 2.0, 3.0, 0.0)
let rmono3 = (1.0, 2.0, 3.0, 4.0)
let pbern3 = monomialToBernsteinDegree3(pmono3)
let qbern3 = monomialToBernsteinDegree3(qmono3)
let rbern3 = monomialToBernsteinDegree3(rmono3)
echo "Subprogram (3) examples:"
echo "  mono ", pmono3, " --> bern ", pbern3
echo "  mono ", qmono3, " --> bern ", qbern3
echo "  mono ", rmono3, " --> bern ", rbern3

#
# Use Subprogram (4) to evaluate p(x), q(x), and r(x) at x = 0.25,
# 7.50.  Display the results. Optionally also display results from
# evaluating in the original monomial basis.
#
echo "Subprogram (4) examples:"
for x in [0.25, 7.50]:
echo "  p(", x, ") = ", evaluateBernsteinDegree3(pbern3, x),
" (mono: ", evaluateMonomialDegree3(pmono3, x), ')'
for x in [0.25, 7.50]:
echo "  q(", x, ") = ", evaluateBernsteinDegree3(qbern3, x),
" (mono: ", evaluateMonomialDegree3(qmono3, x), ')'
for x in [0.25, 7.50]:
echo "  r(", x, ") = ", evaluateBernsteinDegree3(rbern3, x),
" (mono: ", evaluateMonomialDegree3(rmono3, x), ')'

#
# For the following polynomials, using the result of Subprogram (1)
# applied to the polynomial, use Subprogram (5) to get coefficients
# for the degree-3 Bernstein basis:
#
#   p(x) = 1
#   q(x) = 1 + 2x + 3x²
#
# Display the results.
#
echo "Subprogram (5) examples:"
let pbern3a = bernsteinDegree2ToDegree3(pbern2)
let qbern3a = bernsteinDegree2ToDegree3(qbern2)
echo "  bern ", pbern2, "--> bern ", pbern3a
echo "  bern ", qbern2, "--> bern ", qbern3a

Output:
Subprogram (1) examples:
mono (1.0, 0.0, 0.0) --> bern (1.0, 1.0, 1.0)
mono (1.0, 2.0, 3.0) --> bern (1.0, 2.0, 6.0)
Subprogram (2) examples:
p(0.25) = 1.0 (mono: 1.0)
p(7.5) = 1.0 (mono: 1.0)
q(0.25) = 1.6875 (mono: 1.6875)
q(7.5) = 184.75 (mono: 184.75)
Subprogram (3) examples:
mono (1.0, 0.0, 0.0, 0.0) --> bern (1.0, 1.0, 1.0, 1.0)
mono (1.0, 2.0, 3.0, 0.0) --> bern (1.0, 1.666666666666667, 3.333333333333333, 6.0)
mono (1.0, 2.0, 3.0, 4.0) --> bern (1.0, 1.666666666666667, 3.333333333333333, 10.0)
Subprogram (4) examples:
p(0.25) = 1.0 (mono: 1.0)
p(7.5) = 1.0 (mono: 1.0)
q(0.25) = 1.6875 (mono: 1.6875)
q(7.5) = 184.7500000000003 (mono: 184.75)
r(0.25) = 1.75 (mono: 1.75)
r(7.5) = 1872.25 (mono: 1872.25)
Subprogram (5) examples:
bern (1.0, 1.0, 1.0)--> bern (1.0, 1.0, 1.0, 1.0)
bern (1.0, 2.0, 6.0)--> bern (1.0, 1.666666666666667, 3.333333333333333, 6.0)


## ObjectIcon

#!/bin/env oiscript

import
io(),
ipl.lists(list2str)

final abstract class Bernstein ()

public static from_monomial_degree2 (a0_a1_a2)
# Subprogram (1): transform monomial coefficients [a0, a1, a2] to
#                 Bernstein coefficients [b0, b1, b2].
local a0, a1, a2
a0 := a0_a1_a2[1]; a1 := a0_a1_a2[2]; a2 := a0_a1_a2[3]
return [a0, a0 + (0.5 * a1), a0 + a1 + a2]
end

public static evaluate_degree2 (b0_b1_b2, t)
# Subprogram (2): evaluate, at t, the polynomial with Bernstein
#                 coefficients [b0, b1, b2]. Use de Casteljau's
#                 algorithm.
local b0, b1, b2
local s, b01, b12, b012
b0 := b0_b1_b2[1]; b1 := b0_b1_b2[2]; b2 := b0_b1_b2[3]
s := 1 - t
b01 := (s * b0) + (t * b1)
b12 := (s * b1) + (t * b2)
b012 := (s * b01) + (t * b12)
return b012
end

public static from_monomial_degree3 (a0_a1_a2_a3)
# Subprogram (3): transform monomial coefficients [a0, a1, a2, a3]
#                 to Bernstein coefficients [b0, b1, b2, b3].
local a0, a1, a2, a3
a0 := a0_a1_a2_a3[1]; a1 := a0_a1_a2_a3[2]
a2 := a0_a1_a2_a3[3]; a3 := a0_a1_a2_a3[4]
#
# In Object Icon, the same symbol / is used for both floating
# point and integer division. Thus you will get the WRONG result
# if you write 1/3 instead of 1.0/3.0, etc. (This is
# error-encouraging language design but true of many languages. I
# fell victim while writing this code.)
#
return [a0, a0 + ((1.0 / 3.0) * a1),
a0 + ((2.0 / 3.0) * a1) + ((1.0 / 3.0) * a2),
a0 + a1 + a2 + a3]
end

public static evaluate_degree3 (b0_b1_b2_b3, t)
# Subprogram (4): evaluate, at t, the polynomial with Bernstein
#                 coefficients [b0, b1, b2, b3]. Use de Casteljau's
#                 algorithm.
local b0, b1, b2, b3
local s, b01, b12, b23, b012, b123, b0123
b0 := b0_b1_b2_b3[1]; b1 := b0_b1_b2_b3[2]
b2 := b0_b1_b2_b3[3]; b3 := b0_b1_b2_b3[4]
s := 1 - t
b01 := (s * b0) + (t * b1)
b12 := (s * b1) + (t * b2)
b23 := (s * b2) + (t * b3)
b012 := (s * b01) + (t * b12)
b123 := (s * b12) + (t * b23)
b0123 := (s * b012) + (t * b123)
return b0123
end

public static degree2_to_degree3 (q0_q1_q2)
# Subprogram (5): transform the quadratic Bernstein coefficients
#                 [q0, q1, q2] to the cubic Bernstein coefficients
#                 [c0, c1, c2, c3].
local q0, q1, q2
q0 := q0_q1_q2[1]; q1 := q0_q1_q2[2]; q2 := q0_q1_q2[3]
return [q0, ((1.0 / 3.0) * q0) + ((2.0 / 3.0) * q1),
((2.0 / 3.0) * q1) + ((1.0 / 3.0) * q2), q2]
end

end                             # final abstract class Bernstein

final abstract class Monomial ()

public static evaluate_degree2 (a0_a1_a2, t)
# Evaluate, at t, the polynomial with monomial coefficients [a0,
# a1, a2].
local a0, a1, a2
a0 := a0_a1_a2[1]; a1 := a0_a1_a2[2]; a2 := a0_a1_a2[3]
return a0 + (t * (a1 + (t * a2))) # Horner form.
end

public static evaluate_degree3 (a0_a1_a2_a3, t)
# Evaluate, at t, the polynomial with monomial coefficients [a0,
# a1, a2, a3].
local a0, a1, a2, a3
a0 := a0_a1_a2_a3[1]; a1 := a0_a1_a2_a3[2]
a2 := a0_a1_a2_a3[3]; a3 := a0_a1_a2_a3[4]
return a0 + (t * (a1 + (t * (a2 + (t * a3))))) # Horner form.
end

end                             # final abstract class Monomial

procedure lstr (lst)
return "[" || list2str (lst, ", ") || "]"
end

procedure main ()
local x
local pmono2, qmono2, pbern2, qbern2
local pmono3, qmono3, rmono3, pbern3, qbern3, rbern3
local pbern3a, qbern3a

#
# For the following polynomials, use Subprogram (1) to find
# coefficients in the degree-2 Bernstein basis:
#
#   p(x) = 1
#   q(x) = 1 + 2x + 3x²
#
# Display the results.
#
pmono2 := [1, 0, 0]
qmono2 := [1, 2, 3]
pbern2 := Bernstein.from_monomial_degree2 (pmono2)
qbern2 := Bernstein.from_monomial_degree2 (qmono2)
io.write ("Subprogram (1) examples:")
io.write ("  mono ", lstr (pmono2), " --> bern ", lstr (pbern2))
io.write ("  mono ", lstr (qmono2), " --> bern ", lstr (qbern2))

#
# Use Subprogram (2) to evaluate p(x) and q(x) at x = 0.25, 7.50.
# Display the results. Optionally also display results from
# evaluating in the original monomial basis.
#
io.write ("Subprogram (2) examples:")
every x := 0.25 | 7.50 do
io.write ("  p(", x, ") = ",
Bernstein.evaluate_degree2 (pbern2, x),
" (mono: ",
Monomial.evaluate_degree2 (pmono2, x), ")")
every x := 0.25 | 7.50 do
io.write ("  q(", x, ") = ",
Bernstein.evaluate_degree2 (qbern2, x),
" (mono: ",
Monomial.evaluate_degree2 (qmono2, x), ")")

#
# For the following polynomials, use Subprogram (3) to find
# coefficients in the degree-3 Bernstein basis:
#
#   p(x) = 1
#   q(x) = 1 + 2x + 3x²
#   r(x) = 1 + 2x + 3x² + 4x³
#
# Display the results.
#
pmono3 := [1, 0, 0, 0]
qmono3 := [1, 2, 3, 0]
rmono3 := [1, 2, 3, 4]
pbern3 := Bernstein.from_monomial_degree3 (pmono3)
qbern3 := Bernstein.from_monomial_degree3 (qmono3)
rbern3 := Bernstein.from_monomial_degree3 (rmono3)
io.write ("Subprogram (3) examples:")
io.write ("  mono ", lstr (pmono3), " --> bern ", lstr (pbern3))
io.write ("  mono ", lstr (qmono3), " --> bern ", lstr (qbern3))
io.write ("  mono ", lstr (rmono3), " --> bern ", lstr (rbern3))

#
# Use Subprogram (4) to evaluate p(x), q(x), and r(x) at x = 0.25,
# 7.50.  Display the results. Optionally also display results from
# evaluating in the original monomial basis.
#
io.write ("Subprogram (4) examples:")
every x := 0.25 | 7.50 do
io.write ("  p(", x, ") = ",
Bernstein.evaluate_degree3 (pbern3, x),
" (mono: ",
Monomial.evaluate_degree3 (pmono3, x), ")")
every x := 0.25 | 7.50 do
io.write ("  q(", x, ") = ",
Bernstein.evaluate_degree3 (qbern3, x),
" (mono: ",
Monomial.evaluate_degree3 (qmono3, x), ")")
every x := 0.25 | 7.50 do
io.write ("  r(", x, ") = ",
Bernstein.evaluate_degree3 (rbern3, x),
" (mono: ",
Monomial.evaluate_degree3 (rmono3, x), ")")

#
# For the following polynomials, using the result of Subprogram (1)
# applied to the polynomial, use Subprogram (5) to get coefficients
# for the degree-3 Bernstein basis:
#
#   p(x) = 1
#   q(x) = 1 + 2x + 3x²
#
# Display the results.
#
io.write ("Subprogram (5) examples:")
pbern3a := Bernstein.degree2_to_degree3 (pbern2)
qbern3a := Bernstein.degree2_to_degree3 (qbern2)
io.write ("  bern ", lstr (pbern2), " --> bern ", lstr (pbern3a))
io.write ("  bern ", lstr (qbern2), " --> bern ", lstr (qbern3a))
end
Output:
Subprogram (1) examples:
mono [1, 0, 0] --> bern [1, 1.0, 1]
mono [1, 2, 3] --> bern [1, 2.0, 6]
Subprogram (2) examples:
p(0.25) = 1.0 (mono: 1.0)
p(7.5) = 1.0 (mono: 1.0)
q(0.25) = 1.6875 (mono: 1.6875)
q(7.5) = 184.75 (mono: 184.75)
Subprogram (3) examples:
mono [1, 0, 0, 0] --> bern [1, 1.0, 1.0, 1]
mono [1, 2, 3, 0] --> bern [1, 1.666666667, 3.333333333, 6]
mono [1, 2, 3, 4] --> bern [1, 1.666666667, 3.333333333, 10]
Subprogram (4) examples:
p(0.25) = 1.0 (mono: 1.0)
p(7.5) = 1.0 (mono: 1.0)
q(0.25) = 1.6875 (mono: 1.6875)
q(7.5) = 184.75 (mono: 184.75)
r(0.25) = 1.75 (mono: 1.75)
r(7.5) = 1872.25 (mono: 1872.25)
Subprogram (5) examples:
bern [1, 1.0, 1] --> bern [1, 1.0, 1.0, 1]
bern [1, 2.0, 6] --> bern [1, 1.666666667, 3.333333333, 6]


## Phix

Translation of: Python
with javascript_semantics
function m_to_bern2(sequence monomial_coefficients)
atom {a0,a1,a2} = monomial_coefficients,
a01 = a0 + a1/2,
a02 = a0 + a1 + a2
return {a0, a01, a02}
end function

function m_to_bern3(sequence monomial_coefficients)
atom {a0, a1, a2, a3} = monomial_coefficients,
a01 = a0 + a1/3,
a02 = a0 + a1/3*2 + a2/3,
a03 = a0 + a1     + a2    + a3
return {a0, a01, a02, a03}
end function

function bern2_to_bern3(sequence bernstein_coefficients)
atom {b0, b1, b2} = bernstein_coefficients,
b01 = b0/3 + b1*2/3,
b12 =        b1*2/3 + b2/3
return {b0, b01, b12, b2}
end function

function eval_bern2(sequence bernstein_coefficients, atom t)
// using de Casteljau’s algorithm
atom {b0,b1,b2} = bernstein_coefficients,
s = 1-t,
// first mid-points (obvs "mid"dle only when t=0.5)
b01 = s*b0 + t*b1,
b12 = s*b1 + t*b2,
// second mid-point is on the curve
b012 = s*b01 + t*b12
return b012
end function

function eval_bern3(sequence bernstein_coefficients, atom t)
// using de Casteljau’s algorithm
atom {b0, b1, b2, b3} = bernstein_coefficients,
s = 1-t,
// first mid-points (ditto)
b01 = s*b0 + t*b1,
b12 = s*b1 + t*b2,
b23 = s*b2 + t*b3,
// second mid-points
b012 = s*b01 + t*b12,
b123 = s*b12 + t*b23,
// third mid-point is on the curve
b0123 = s*b012 + t*b123
return b0123
end function

function eval_m2(sequence monomial_coefficients, atom t)
atom {a0, a1, a2} = monomial_coefficients
return a0 + t*(a1 + t*a2) -- Horner’s rule
end function

function eval_m3(sequence monomial_coefficients, atom t)
atom {a0, a1, a2, a3} = monomial_coefficients
return a0 + t*(a1 + t*(a2 + t*a3)) -- Horner’s rule
end function

constant pm2 = {1, 0, 0},       -- p(x) = 1
pm3 = {1, 0, 0, 0},    -- (ditto in degree 3)
qm2 = {1, 2, 3},       -- q(x) = 1 + 2x + 3x²
qm3 = {1, 2, 3, 0},    -- (ditto in degree 3)
rm3 = {1, 2, 3, 4},    -- r(x) = 1 + 2x + 3x² + 4x³
pb2 = m_to_bern2(pm2),
pb3 = m_to_bern3(pm3),
qb2 = m_to_bern2(qm2),
qb3 = m_to_bern3(qm3),
rb3 = m_to_bern3(rm3)
printf(1,"  m_to_bern2(%v) --> %v\n", {pm2,pb2})
printf(1,"  m_to_bern2(%v) --> %v\n", {qm2,qb2})
printf(1,"  m_to_bern3(%v) --> %v\n", {pm3,pb3})
printf(1,"  m_to_bern3(%v) --> %v\n", {qm3,qb3})
printf(1,"  m_to_bern3(%v) --> %v\n", {rm3,rb3})
printf(1,"  bern2_to_bern3(%v) --> %v\n", {pb2,bern2_to_bern3(pb2)})
printf(1,"  bern2_to_bern3(%v) --> %v\n", {qb2,bern2_to_bern3(qb2)})

printf(1,"Evaluating bernstein degree 2 examples:\n")
for x in {0.25, 7.50} do
printf(1,"  p(%.2f) = %8g (mono: %g)\n",{x,eval_bern2(pb2,x),eval_m2(pm2,x)})
printf(1,"  q(%.2f) = %8g (mono: %g)\n",{x,eval_bern2(qb2,x),eval_m2(qm2,x)})
end for

printf(1,"Evaluating bernstein degree 3 examples:\n")
for x in {0.25, 7.50} do
printf(1,"  p(%.2f) = %8g (mono: %g)\n",{x,eval_bern3(pb3,x),eval_m3(pm3,x)})
printf(1,"  q(%.2f) = %8g (mono: %g)\n",{x,eval_bern3(qb3,x),eval_m3(qm3,x)})
printf(1,"  r(%.2f) = %8g (mono: %g)\n",{x,eval_bern3(rb3,x),eval_m3(rm3,x)})
end for

Output:
  m_to_bern2({1,0,0}) --> {1,1,1}
m_to_bern2({1,2,3}) --> {1,2,6}
m_to_bern3({1,0,0,0}) --> {1,1,1,1}
m_to_bern3({1,2,3,0}) --> {1,1.666666667,3.333333333,6}
m_to_bern3({1,2,3,4}) --> {1,1.666666667,3.333333333,10}
bern2_to_bern3({1,1,1}) --> {1,1,1,1}
bern2_to_bern3({1,2,6}) --> {1,1.666666667,3.333333333,6}
Evaluating bernstein degree 2 examples:
p(0.25) =        1 (mono: 1)
q(0.25) =   1.6875 (mono: 1.6875)
p(7.50) =        1 (mono: 1)
q(7.50) =   184.75 (mono: 184.75)
Evaluating bernstein degree 3 examples:
p(0.25) =        1 (mono: 1)
q(0.25) =   1.6875 (mono: 1.6875)
r(0.25) =     1.75 (mono: 1.75)
p(7.50) =        1 (mono: 1)
q(7.50) =   184.75 (mono: 184.75)
r(7.50) =  1872.25 (mono: 1872.25)


## Python

#!/bin/env python3

# Subprogram (1).
def monomial_to_bernstein_degree2(monomial_coefficients):
(a0, a1, a2) = monomial_coefficients
return (a0, a0 + ((1/2) * a1), a0 + a1 + a2)

# Subprogram (2).
def evaluate_bernstein_degree2(bernstein_coefficients, t):
(b0, b1, b2) = bernstein_coefficients
# de Casteljau’s algorithm.
s = 1 - t
b01 = (s * b0) + (t * b1)
b12 = (s * b1) + (t * b2)
b012 = (s * b01) + (t * b12)
return b012

# Subprogram (3).
def monomial_to_bernstein_degree3(monomial_coefficients):
(a0, a1, a2, a3) = monomial_coefficients
return (a0, a0 + ((1/3) * a1),
a0 + ((2/3) * a1) + ((1/3) * a2),
a0 + a1 + a2 + a3)

# Subprogram (4).
def evaluate_bernstein_degree3(bernstein_coefficients, t):
(b0, b1, b2, b3) = bernstein_coefficients
# de Casteljau’s algorithm.
s = 1 - t
b01 = (s * b0) + (t * b1)
b12 = (s * b1) + (t * b2)
b23 = (s * b2) + (t * b3)
b012 = (s * b01) + (t * b12)
b123 = (s * b12) + (t * b23)
b0123 = (s * b012) + (t * b123)
return b0123

# Subprogram (5).
def bernstein_degree2_to_degree3(bernstein_coefficients):
(b0, b1, b2) = bernstein_coefficients
return (b0, ((1/3) * b0) + ((2/3) * b1),
((2/3) * b1) + ((1/3) * b2), b2)

def evaluate_monomial_degree2(monomial_coefficients, t):
(a0, a1, a2) = monomial_coefficients
# Horner’s rule.
return a0 + (t * (a1 + (t * a2)))

def evaluate_monomial_degree3(monomial_coefficients, t):
(a0, a1, a2, a3) = monomial_coefficients
# Horner’s rule.
return a0 + (t * (a1 + (t * (a2 + (t * a3)))))

#
# For the following polynomials, use Subprogram (1) to find
# coefficients in the degree-2 Bernstein basis:
#
#   p(x) = 1
#   q(x) = 1 + 2x + 3x²
#
# Display the results.
#
pmono2 = (1, 0, 0)
qmono2 = (1, 2, 3)
pbern2 = monomial_to_bernstein_degree2(pmono2)
qbern2 = monomial_to_bernstein_degree2(qmono2)
print("Subprogram (1) examples:")
print("  mono", pmono2, " --> bern", pbern2)
print("  mono", qmono2, " --> bern", qbern2)

#
# Use Subprogram (2) to evaluate p(x) and q(x) at x = 0.25, 7.50.
# Display the results. Optionally also display results from evaluating
# in the original monomial basis.
#
print("Subprogram (2) examples:")
for x in (0.25, 7.50):
print("  p(", x, ") = ", evaluate_bernstein_degree2(pbern2, x),
" ( mono: ", evaluate_monomial_degree2(pmono2, x), ")")
for x in (0.25, 7.50):
print("  q(", x, ") = ", evaluate_bernstein_degree2(qbern2, x),
" ( mono: ", evaluate_monomial_degree2(qmono2, x), ")")

#
# For the following polynomials, use Subprogram (3) to find
# coefficients in the degree-3 Bernstein basis:
#
#   p(x) = 1
#   q(x) = 1 + 2x + 3x²
#   r(x) = 1 + 2x + 3x² + 4x³
#
# Display the results.
#
pmono3 = (1, 0, 0, 0)
qmono3 = (1, 2, 3, 0)
rmono3 = (1, 2, 3, 4)
pbern3 = monomial_to_bernstein_degree3(pmono3)
qbern3 = monomial_to_bernstein_degree3(qmono3)
rbern3 = monomial_to_bernstein_degree3(rmono3)
print("Subprogram (3) examples:")
print("  mono", pmono3, " --> bern", pbern3)
print("  mono", qmono3, " --> bern", qbern3)
print("  mono", rmono3, " --> bern", rbern3)

#
# Use Subprogram (4) to evaluate p(x), q(x), and r(x) at x = 0.25,
# 7.50.  Display the results. Optionally also display results from
# evaluating in the original monomial basis.
#
print("Subprogram (4) examples:")
for x in (0.25, 7.50):
print("  p(", x, ") = ", evaluate_bernstein_degree3(pbern3, x),
" ( mono: ", evaluate_monomial_degree3(pmono3, x), ")")
for x in (0.25, 7.50):
print("  q(", x, ") = ", evaluate_bernstein_degree3(qbern3, x),
" ( mono: ", evaluate_monomial_degree3(qmono3, x), ")")
for x in (0.25, 7.50):
print("  r(", x, ") = ", evaluate_bernstein_degree3(rbern3, x),
" ( mono: ", evaluate_monomial_degree3(rmono3, x), ")")

#
# For the following polynomials, using the result of Subprogram (1)
# applied to the polynomial, use Subprogram (5) to get coefficients
# for the degree-3 Bernstein basis:
#
#   p(x) = 1
#   q(x) = 1 + 2x + 3x²
#
# Display the results.
#
print("Subprogram (5) examples:")
pbern3a = bernstein_degree2_to_degree3(pbern2)
qbern3a = bernstein_degree2_to_degree3(qbern2)
print("  bern", pbern2, " --> bern", pbern3a)
print("  bern", qbern2, " --> bern", qbern3a)

Output:
Subprogram (1) examples:
mono (1, 0, 0)  --> bern (1, 1.0, 1)
mono (1, 2, 3)  --> bern (1, 2.0, 6)
Subprogram (2) examples:
p( 0.25 ) =  1.0  ( mono:  1.0 )
p( 7.5 ) =  1.0  ( mono:  1.0 )
q( 0.25 ) =  1.6875  ( mono:  1.6875 )
q( 7.5 ) =  184.75  ( mono:  184.75 )
Subprogram (3) examples:
mono (1, 0, 0, 0)  --> bern (1, 1.0, 1.0, 1)
mono (1, 2, 3, 0)  --> bern (1, 1.6666666666666665, 3.333333333333333, 6)
mono (1, 2, 3, 4)  --> bern (1, 1.6666666666666665, 3.333333333333333, 10)
Subprogram (4) examples:
p( 0.25 ) =  1.0  ( mono:  1.0 )
p( 7.5 ) =  1.0  ( mono:  1.0 )
q( 0.25 ) =  1.6874999999999998  ( mono:  1.6875 )
q( 7.5 ) =  184.75000000000034  ( mono:  184.75 )
r( 0.25 ) =  1.7499999999999998  ( mono:  1.75 )
r( 7.5 ) =  1872.25  ( mono:  1872.25 )
Subprogram (5) examples:
bern (1, 1.0, 1)  --> bern (1, 1.0, 1.0, 1)
bern (1, 2.0, 6)  --> bern (1, 1.6666666666666665, 3.333333333333333, 6)

## Raku

Translation of: Wren
# 20230601 Raku programming solution

sub toBern2 { [ @_[0], @_[0]+@_[1]/2, @_[0..2].sum ] }

sub toBern3 (@a) { @a[0], @a[0]+@a[1]/3, @a[0]+@a[1]*2/3+@a[2]/3, @a[0..3].sum }

sub evalBern-N (@b, $t) { # uses de Casteljau's algorithm my ($s, @bern) = 1 - $t, @b.Slip; while ( @bern.elems > 2 ) { @bern = @bern.rotor(2 => -1).map: {$s * .[0] + $t * .[1] }; } return$s * @bern[0] + $t * @bern[1] } sub evaluations (@m, @b,$x) {
my $m = ([o] map {$_ + $x * * }, @m)(0); # Horner's rule return "p({$x.fmt: '%.2f'}) = { evalBern-N @b, $x } (mono$m)";
}

sub bern2to3 (@a) { @a[0], @a[0]/3+@a[1]*2/3, @a[1]*2/3+@a[2]/3, @a[2] }

my (@pm,@qm,@rm) := ([1, 0, 0], [1, 2, 3], [1, 2, 3, 4]);

say "Subprogram(1) examples:";

my (@pb2,@qb2) := (@pm,@qm).map: { toBern2 $_ }; say "mono [{.[0]}] --> bern [{.[1]}]" for (@pm,@pb2,@qm,@qb2).rotor: 2; say "\nSubprogram(2) examples:"; for (@pm,@pb2,@qm,@qb2).rotor(2) X (0.25,7.5) -> [[@m,@b],$x] {
say evaluations @m, @b, $x } say "\nSubprogram(3) examples:"; .push(0) for (@pm,@qm); my (@pb3,@qb3,@rb3) := (@pm,@qm,@rm).map: { toBern3$_ };
say "mono [{.[0]}] --> bern [{.[1]}]" for (@pm,@pb3,@qm,@qb3,@rm,@rb3).rotor: 2;

say "\nSubprogram(4) examples:";

for (@pm,@pb3,@qm,@qb3,@rm,@rb3).rotor(2) X (0.25,7.5) -> [[@m,@b], $x] { say evaluations @m, @b,$x
}

say "\nSubprogram(5) examples:";

my (@pc,@qc) := (@pb2,@qb2).map: { bern2to3 $_ }; say "mono [{.[1]}] --> bern [{.[0]}]" for (@pc,@pb2,@qc,@qb2).rotor: 2;  Output: Subprogram(1) examples: mono [1 0 0] --> bern [1 1 1] mono [1 2 3] --> bern [1 2 6] Subprogram(2) examples: p(0.25) = 1 (mono 1) p(7.50) = 1 (mono 1) p(0.25) = 1.6875 (mono 1.6875) p(7.50) = 184.75 (mono 184.75) Subprogram(3) examples: mono [1 0 0 0] --> bern [1 1 1 1] mono [1 2 3 0] --> bern [1 1.666667 3.333333 6] mono [1 2 3 4] --> bern [1 1.666667 3.333333 10] Subprogram(4) examples: p(0.25) = 1 (mono 1) p(7.50) = 1 (mono 1) p(0.25) = 1.6875 (mono 1.6875) p(7.50) = 184.75 (mono 184.75) p(0.25) = 1.75 (mono 1.75) p(7.50) = 1872.25 (mono 1872.25) Subprogram(5) examples: mono [1 1 1] --> bern [1 1 1 1] mono [1 2 6] --> bern [1 1.666667 3.333333 6] ## Wren Translation of: ALGOL 60 Library: Wren-fmt Library: Wren-math Note that the library method, Math.evalPoly, evaluates polynomials of any degree using Horner's rule but requires the coefficients to be presented in highest to lowest degree order. import "./fmt" for Fmt import "./math" for Math var toBern2 = Fn.new { |a| [a[0], a[0] + a[1] / 2, a[0] + a[1] + a[2]] } // uses de Casteljau's algorithm var evalBern2 = Fn.new { |b, t| var s = 1 - t var b01 = s * b[0] + t * b[1] var b12 = s * b[1] + t * b[2] return s * b01 + t * b12 } var toBern3 = Fn.new { |a| var b = List.filled(4, 0) b[0] = a[0] b[1] = a[0] + a[1] / 3 b[2] = a[0] + a[1] * 2/3 + a[2] / 3 b[3] = a[0] + a[1] + a[2] + a[3] return b } // uses de Casteljau's algorithm var evalBern3 = Fn.new { |b, t| var s = 1 - t var b01 = s * b[0] + t * b[1] var b12 = s * b[1] + t * b[2] var b23 = s * b[2] + t * b[3] var b012 = s * b01 + t * b12 var b123 = s * b12 + t * b23 return s * b012 + t * b123 } var bern2to3 = Fn.new { |q| var c = List.filled(4, 0) c[0] = q[0] c[1] = q[0] / 3 + q[1] * 2/3 c[2] = q[1] * 2/3 + q[2] / 3 c[3] = q[2] return c } var pm = [1, 0, 0] var qm = [1, 2, 3] var rm = [1, 2, 3, 4] var x var y var m System.print("Subprogram(1) examples:") var pb2 = toBern2.call(pm) var qb2 = toBern2.call(qm) Fmt.print("mono$n --> bern $n", pm, pb2) Fmt.print("mono$n --> bern $n", qm, qb2) System.print("\nSubprogram(2) examples:") x = 0.25 y = evalBern2.call(pb2, x) m = Math.evalPoly(pm[-1..0], x) Fmt.print("p($4.2f) = $j (mono$j)", x, y, m)
x = 7.5
y = evalBern2.call(pb2, x)
m = Math.evalPoly(pm[-1..0], x)
Fmt.print("p($4.2f) =$j (mono $j)", x, y, m) x = 0.25 y = evalBern2.call(qb2, x) m = Math.evalPoly(qm[-1..0], x) Fmt.print("q($4.2f) = $j (mono$j)", x, y, m)
x = 7.5
y = evalBern2.call(qb2, x)
m = Math.evalPoly(qm[-1..0], x)
Fmt.print("q($4.2f) =$j (mono $j)", x, y, m) System.print("\nSubprogram(3) examples:") pm.add(0) qm.add(0) var pb3 = toBern3.call(pm) var qb3 = toBern3.call(qm) var rb3 = toBern3.call(rm) Fmt.print("mono$n --> bern $n", pm, pb3) Fmt.print("mono$n --> bern $n", qm, qb3) Fmt.print("mono$n --> bern $n", rm, rb3) System.print("\nSubprogram(4) examples:") x = 0.25 y = evalBern3.call(pb3, x) m = Math.evalPoly(pm[-1..0], x) Fmt.print("p($4.2f) = $j (mono$j)", x, y, m)
x = 7.5
y = evalBern3.call(pb3, x)
m = Math.evalPoly(pm[-1..0], x)
Fmt.print("p($4.2f) =$j (mono $j)", x, y, m) x = 0.25 y = evalBern3.call(qb3, x) m = Math.evalPoly(qm[-1..0], x) Fmt.print("q($4.2f) = $j (mono$j)", x, y, m)
x = 7.5
y = evalBern3.call(qb3, x)
m = Math.evalPoly(qm[-1..0], x)
Fmt.print("q($4.2f) =$j (mono $j)", x, y, m) x = 0.25 y = evalBern3.call(rb3, x) m = Math.evalPoly(rm[-1..0], x) Fmt.print("r($4.2f) = $j (mono$j)", x, y, m)
x = 7.5
y = evalBern3.call(rb3, x)
m = Math.evalPoly(rm[-1..0], x)
Fmt.print("r($4.2f) =$j (mono $j)", x, y, m) System.print("\nSubprogram(5) examples:") var pc = bern2to3.call(pb2) var qc = bern2to3.call(qb2) Fmt.print("mono$n --> bern $n", pb2, pc) Fmt.print("mono$n --> bern \$n", qb2, qc)

Output:
Subprogram(1) examples:
mono [1, 0, 0] --> bern [1, 1, 1]
mono [1, 2, 3] --> bern [1, 2, 6]

Subprogram(2) examples:
p(0.25) = 1 (mono 1)
p(7.50) = 1 (mono 1)
q(0.25) = 1.6875 (mono 1.6875)
q(7.50) = 184.75 (mono 184.75)

Subprogram(3) examples:
mono [1, 0, 0, 0] --> bern [1, 1, 1, 1]
mono [1, 2, 3, 0] --> bern [1, 1.6666666666667, 3.3333333333333, 6]
mono [1, 2, 3, 4] --> bern [1, 1.6666666666667, 3.3333333333333, 10]

Subprogram(4) examples:
p(0.25) = 1 (mono 1)
p(7.50) = 1 (mono 1)
q(0.25) = 1.6875 (mono 1.6875)
q(7.50) = 184.75 (mono 184.75)
r(0.25) = 1.75 (mono 1.75)
r(7.50) = 1872.25 (mono 1872.25)

Subprogram(5) examples:
mono [1, 1, 1] --> bern [1, 1, 1, 1]
mono [1, 2, 6] --> bern [1, 1.6666666666667, 3.3333333333333, 6]


## XPL0

Translation of: ALGOL 60
procedure ToBern2 (A0, A1, A2, B0, B1, B2);
real A0, A1, A2;      \pass by value
real B0, B1, B2;      \pass by reference
\Subprogram (1): transform monomial coefficients
\        A0, A1, A2 to Bernstein coefficients B0, B1, B2;
begin
B0(0) := A0;
B1(0) := A0 + ((1./2.) * A1);
B2(0) := A0 + A1 + A2
end \ToBern2\;

function real EvalBern2 (B0, B1, B2, T);
real B0, B1, B2, T;
\Subprogram (2): evaluate, at T, the polynomial with
\        Bernstein coefficients B0, B1, B2. Use de Casteljau's
\        algorithm;
real S, B01, B12, B012;
begin
S := 1. - T;
B01 := (S * B0) + (T * B1);
B12 := (S * B1) + (T * B2);
B012 := (S * B01) + (T * B12);
return B012
end \EvalBern2\;

procedure ToBern3 (A0, A1, A2, A3, B0, B1, B2, B3);
real A0, A1, A2, A3;
real B0, B1, B2, B3;
\Subprogram (3): transform monomial coefficients
\        A0, A1, A2, A3 to Bernstein coefficients B0, B1,
\        B2, B3;
begin
B0(0) := A0;
B1(0) := A0 + ((1./3.) * A1);
B2(0) := A0 + ((2./3.) * A1) + ((1./3.) * A2);
B3(0) := A0 + A1 + A2 + A3
end \ToBern3\;

function real EvalBern3 (B0, B1, B2, B3, T);
real B0, B1, B2, B3, T;
\Subprogram (4): evaluate, at t, the polynomial
\        with Bernstein coefficients b0, b1, b2, b3. Use
\        de Casteljau's algorithm;
real S, B01, B12, B23, B012, B123, B0123;
begin
S := 1. - T;
B01 := (S * B0) + (T * B1);
B12 := (S * B1) + (T * B2);
B23 := (S * B2) + (T * B3);
B012 := (S * B01) + (T * B12);
B123 := (S * B12) + (T * B23);
B0123 := (S * B012) + (T * B123);
return B0123
end \EvalBern3\;

procedure Bern2To3 (Q0, Q1, Q2, C0, C1, C2, C3);
real Q0, Q1, Q2;
real C0, C1, C2, C3;
\Subprogram (5): transform the quadratic Bernstein
\        coefficients q0, q1, q2 to the cubic Bernstein
\        coefficients c0, c1, c2, c3;
begin
C0(0) := Q0;
C1(0) := ((1./3.) * Q0) + ((2./3.) * Q1);
C2(0) := ((2./3.) * Q1) + ((1./3.) * Q2);
C3(0) := Q2
end \Bern2To3\;

real P0M, P1M, P2M;
real Q0M, Q1M, Q2M;
real R0M, R1M, R2M, R3M;

real P0B2, P1B2, P2B2;
real Q0B2, Q1B2, Q2B2;

real P0B3, P1B3, P2B3, P3B3;
real Q0B3, Q1B3, Q2B3, Q3B3;
real R0B3, R1B3, R2B3, R3B3;

real PC0, PC1, PC2, PC3;
real QC0, QC1, QC2, QC3;

real X, Y;

begin
P0M := 1.;  P1M := 0.;  P2M := 0.;
Q0M := 1.;  Q1M := 2.;  Q2M := 3.;
R0M := 1.;  R1M := 2.;  R2M := 3.;  R3M := 4.;

Format(1, 2);
ToBern2 (P0M, P1M, P2M, @P0B2, @P1B2, @P2B2);
ToBern2 (Q0M, Q1M, Q2M, @Q0B2, @Q1B2, @Q2B2);
Text (0, "Subprogram (1) examples:^m^j");
Text (0, "  mono ( ");
RlOut (0, P0M);   Text (0, ", ");
RlOut (0, P1M);   Text (0, ", ");
RlOut (0, P2M);   Text (0, ") --> bern ( ");
RlOut (0, P0B2);  Text (0, ", ");
RlOut (0, P1B2);  Text (0, ", ");
RlOut (0, P2B2);  Text (0, ")^m^j");
Text (0, "  mono ( ");
RlOut (0, Q0M);   Text (0, ", ");
RlOut (0, Q1M);   Text (0, ", ");
RlOut (0, Q2M);   Text (0, ") --> bern ( ");
RlOut (0, Q0B2);  Text (0, ", ");
RlOut (0, Q1B2);  Text (0, ", ");
RlOut (0, Q2B2);  Text (0, ")^m^j");

Text (0, "Subprogram (2) examples:^m^j");
X := 0.25;
Y := EvalBern2 (P0B2, P1B2, P2B2, X);
Text (0, "  p ( ");  RlOut (0, X);
Text (0, ") = ");    RlOut (0, Y);
Text (0, "^m^j");
X := 7.50;
Y := EvalBern2 (P0B2, P1B2, P2B2, X);
Text (0, "  p ( ");  RlOut (0, X);
Text (0, ") = ");    RlOut (0, Y);
Text (0, "^m^j");
X := 0.25;
Y := EvalBern2 (Q0B2, Q1B2, Q2B2, X);
Text (0, "  q ( ");  RlOut (0, X);
Text (0, ") = ");    RlOut (0, Y);
Text (0, "^m^j");
X := 7.50;
Y := EvalBern2 (Q0B2, Q1B2, Q2B2, X);
Text (0, "  q ( ");  RlOut (0, X);
Text (0, ") = ");    RlOut (0, Y);
Text (0, "^m^j");

ToBern3 (P0M, P1M, P2M, 0.,  @P0B3, @P1B3, @P2B3, @P3B3);
ToBern3 (Q0M, Q1M, Q2M, 0.,  @Q0B3, @Q1B3, @Q2B3, @Q3B3);
ToBern3 (R0M, R1M, R2M, R3M, @R0B3, @R1B3, @R2B3, @R3B3);
Text (0, "Subprogram (3) examples:^m^j");
Text (0, "  mono ( ");
RlOut (0, P0M);   Text (0, ", ");
RlOut (0, P1M);   Text (0, ", ");
RlOut (0, P2M);   Text (0, ", ");
RlOut (0, 0.);    Text (0, ") --> bern ( ");
RlOut (0, P0B3);  Text (0, ", ");
RlOut (0, P1B3);  Text (0, ", ");
RlOut (0, P2B3);  Text (0, ", ");
RlOut (0, P3B3);  Text (0, ")^m^j");
Text (0, "  mono ( ");
RlOut (0, Q0M);   Text (0, ", ");
RlOut (0, Q1M);   Text (0, ", ");
RlOut (0, Q2M);   Text (0, ", ");
RlOut (0, 0.);    Text (0, ") --> bern ( ");
RlOut (0, Q0B3);  Text (0, ", ");
RlOut (0, Q1B3);  Text (0, ", ");
RlOut (0, Q2B3);  Text (0, ", ");
RlOut (0, Q3B3);  Text (0, ")^m^j");
Text (0, "  mono ( ");
RlOut (0, R0M);   Text (0, ", ");
RlOut (0, R1M);   Text (0, ", ");
RlOut (0, R2M);   Text (0, ", ");
RlOut (0, R3M);   Text (0, ") --> bern ( ");
RlOut (0, R0B3);  Text (0, ", ");
RlOut (0, R1B3);  Text (0, ", ");
RlOut (0, R2B3);  Text (0, ", ");
RlOut (0, R3B3);  Text (0, ")^m^j");

Text (0, "Subprogram (4) examples:^m^j");
X := 0.25;
Y := EvalBern3 (P0B3, P1B3, P2B3, P3B3, X);
Text (0, "  p ( ");  RlOut (0, X);
Text (0, ") = ");    RlOut (0, Y);
Text (0, "^m^j");
X := 7.50;
Y := EvalBern3 (P0B3, P1B3, P2B3, P3B3, X);
Text (0, "  p ( ");  RlOut (0, X);
Text (0, ") = ");    RlOut (0, Y);
Text (0, "^m^j");
X := 0.25;
Y := EvalBern3 (Q0B3, Q1B3, Q2B3, Q3B3, X);
Text (0, "  q ( ");  RlOut (0, X);
Text (0, ") = ");    RlOut (0, Y);
Text (0, "^m^j");
X := 7.50;
Y := EvalBern3 (Q0B3, Q1B3, Q2B3, Q3B3, X);
Text (0, "  q ( ");  RlOut (0, X);
Text (0, ") = ");    RlOut (0, Y);
Text (0, "^m^j");
X := 0.25;
Y := EvalBern3 (R0B3, R1B3, R2B3, R3B3, X);
Text (0, "  r ( ");  RlOut (0, X);
Text (0, ") = ");    RlOut (0, Y);
Text (0, "^m^j");
X := 7.50;
Y := EvalBern3 (R0B3, R1B3, R2B3, R3B3, X);
Text (0, "  r ( ");  RlOut (0, X);
Text (0, ") = ");    RlOut (0, Y);
Text (0, "^m^j");

Bern2To3 (P0B2, P1B2, P2B2, @PC0, @PC1, @PC2, @PC3);
Bern2To3 (Q0B2, Q1B2, Q2B2, @QC0, @QC1, @QC2, @QC3);
Text (0, "Subprogram (5) examples:^m^j");
Text (0, "  bern ( ");
RlOut (0, P0B2);  Text (0, ", ");
RlOut (0, P1B2);  Text (0, ", ");
RlOut (0, P2B2);  Text (0, ") --> bern ( ");
RlOut (0, PC0);   Text (0, ", ");
RlOut (0, PC1);   Text (0, ", ");
RlOut (0, PC2);   Text (0, ", ");
RlOut (0, PC3);   Text (0, ")^m^j");
Text (0, "  bern ( ");
RlOut (0, Q0B2);  Text (0, ", ");
RlOut (0, Q1B2);  Text (0, ", ");
RlOut (0, Q2B2);  Text (0, ") --> bern ( ");
RlOut (0, QC0);   Text (0, ", ");
RlOut (0, QC1);   Text (0, ", ");
RlOut (0, QC2);   Text (0, ", ");
RlOut (0, QC3);   Text (0, ")^m^j")
end
Output:
Subprogram (1) examples:
mono ( 1.00, 0.00, 0.00) --> bern ( 1.00, 1.00, 1.00)
mono ( 1.00, 2.00, 3.00) --> bern ( 1.00, 2.00, 6.00)
Subprogram (2) examples:
p ( 0.25) = 1.00
p ( 7.50) = 1.00
q ( 0.25) = 1.69
q ( 7.50) = 184.75
Subprogram (3) examples:
mono ( 1.00, 0.00, 0.00, 0.00) --> bern ( 1.00, 1.00, 1.00, 1.00)
mono ( 1.00, 2.00, 3.00, 0.00) --> bern ( 1.00, 1.67, 3.33, 6.00)
mono ( 1.00, 2.00, 3.00, 4.00) --> bern ( 1.00, 1.67, 3.33, 10.00)
Subprogram (4) examples:
p ( 0.25) = 1.00
p ( 7.50) = 1.00
q ( 0.25) = 1.69
q ( 7.50) = 184.75
r ( 0.25) = 1.75
r ( 7.50) = 1872.25
Subprogram (5) examples:
bern ( 1.00, 1.00, 1.00) --> bern ( 1.00, 1.00, 1.00, 1.00)
bern ( 1.00, 2.00, 6.00) --> bern ( 1.00, 1.67, 3.33, 6.00)
`