# 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}


## C#

Translation of: Go
using System;

class Program
{
static double[] ToBern2(double[] a)
{
return new double[] { a[0], a[0] + a[1] / 2, a[0] + a[1] + a[2] };
}

static double EvalBern2(double[] b, double t)
{
double s = 1.0 - t;
double b01 = s * b[0] + t * b[1];
double b12 = s * b[1] + t * b[2];
return s * b01 + t * b12;
}

static double[] ToBern3(double[] a)
{
return new double[] { a[0], a[0] + a[1] / 3, a[0] + a[1] * 2 / 3 + a[2] / 3, a[0] + a[1] + a[2] + a[3] };
}

static double EvalBern3(double[] b, double t)
{
double s = 1.0 - t;
double b01 = s * b[0] + t * b[1];
double b12 = s * b[1] + t * b[2];
double b23 = s * b[2] + t * b[3];
double b012 = s * b01 + t * b12;
double b123 = s * b12 + t * b23;
return s * b012 + t * b123;
}

static double[] Bern2To3(double[] q)
{
return new double[] { q[0], q[0] / 3 + q[1] * 2 / 3, q[1] * 2 / 3 + q[2] / 3, q[2] };
}

static double EvalMono2(double[] a, double t)
{
return a[0] + (t * (a[1] + (t * a[2])));
}

static double EvalMono3(double[] a, double t)
{
return a[0] + (t * (a[1] + (t * (a[2] + (t * a[3])))));
}

static void Main(string[] args)
{
double[] pm = { 1, 0, 0 };
double[] qm = { 1, 2, 3 };
double[] rm = { 1, 2, 3, 4 };
double x, y, m;

Console.WriteLine("Subprogram(1) examples:");
var pb2 = ToBern2(pm);
var qb2 = ToBern2(qm);
Console.WriteLine($"mono [{string.Join(", ", pm)}] --> bern [{string.Join(", ", pb2)}]"); Console.WriteLine($"mono [{string.Join(", ", qm)}] --> bern [{string.Join(", ", qb2)}]");

Console.WriteLine("\nSubprogram(2) examples:");
x = 0.25;
y = EvalBern2(pb2, x);
m = EvalMono2(pm, x);
Console.WriteLine($"p({x:F2}) = {y:G14} (mono {m:G14})"); x = 7.5; y = EvalBern2(pb2, x); m = EvalMono2(pm, x); Console.WriteLine($"p({x:F2}) = {y:G14} (mono {m:G14})");

x = 0.25;
y = EvalBern2(qb2, x);
m = EvalMono2(qm, x);
Console.WriteLine($"q({x:F2}) = {y:G14} (mono {m:G14})"); x = 7.5; y = EvalBern2(qb2, x); m = EvalMono2(qm, x); Console.WriteLine($"q({x:F2}) = {y:G14} (mono {m:G14})");

Console.WriteLine("\nSubprogram(3) examples:");
var pb3 = ToBern3(new double[] { pm[0], pm[1], pm[2], 0 });
var qb3 = ToBern3(new double[] { qm[0], qm[1], qm[2], 0 });
var rb3 = ToBern3(rm);
Console.WriteLine($"mono [{string.Join(", ", pm)}] --> bern [{string.Join(", ", pb3)}]"); Console.WriteLine($"mono [{string.Join(", ", qm)}] --> bern [{string.Join(", ", qb3)}]");
Console.WriteLine($"mono [{string.Join(", ", rm)}] --> bern [{string.Join(", ", rb3)}]"); Console.WriteLine("\nSubprogram(4) examples:"); x = 0.25; y = EvalBern3(pb3, x); m = EvalMono3(new double[] { pm[0], pm[1], pm[2], 0 }, x); Console.WriteLine($"p({x:F2}) = {y:G14} (mono {m:G14})");
x = 7.5;
y = EvalBern3(pb3, x);
m = EvalMono3(new double[] { pm[0], pm[1], pm[2], 0 }, x);
Console.WriteLine($"p({x:F2}) = {y:G14} (mono {m:G14})"); x = 0.25; y = EvalBern3(qb3, x); m = EvalMono3(new double[] { qm[0], qm[1], qm[2], 0 }, x); Console.WriteLine($"q({x:F2}) = {y:G14} (mono {m:G14})");
x = 7.5;
y = EvalBern3(qb3, x);
m = EvalMono3(new double[] { qm[0], qm[1], qm[2], 0 }, x);
Console.WriteLine($"q({x:F2}) = {y:G14} (mono {m:G14})"); x = 0.25; y = EvalBern3(rb3, x); m = EvalMono3(rm, x); Console.WriteLine($"r({x:F2}) = {y:G14} (mono {m:G14})");
x = 7.5;
y = EvalBern3(rb3, x);
m = EvalMono3(rm, x);
Console.WriteLine($"r({x:F2}) = {y:G14} (mono {m:G14})"); Console.WriteLine("\nSubprogram(5) examples:"); var pc = Bern2To3(pb2); var qc = Bern2To3(qb2); Console.WriteLine($"bern [{string.Join(", ", pb2)}] --> bern3 [{string.Join(", ", pc)}]");
Console.WriteLine($"bern [{string.Join(", ", qb2)}] --> bern3 [{string.Join(", ", 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] --> bern [1, 1, 1, 1] mono [1, 2, 3] --> bern [1, 1.66666666666667, 3.33333333333333, 6] mono [1, 2, 3, 4] --> bern [1, 1.66666666666667, 3.33333333333333, 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: bern [1, 1, 1] --> bern3 [1, 1, 1, 1] bern [1, 2, 6] --> bern3 [1, 1.66666666666667, 3.33333333333333, 6]  ## C++ #include <cstdint> #include <iostream> #include <vector> std::string to_string(const std::vector<double>& list) { std::string result = "["; for ( uint64_t i = 0; i < list.size() - 1; ++i ) { result += std::to_string(list[i]) + ", "; } result += std::to_string(list.back()) + "]"; return result; } // Subprogram (1) std::vector<double> monomial_to_bernstein_degree2(const std::vector<double>& monomial) { return std::vector<double>{ monomial[0], monomial[0] + ( monomial[1] / 2.0 ), monomial[0] + monomial[1] + monomial[2] }; } // Subprogram (2) double evaluate_bernstein_degree2(const std::vector<double>& bernstein, const double& t) { // de Casteljau’s algorithm const double s = 1 - t; const double b01 = ( s * bernstein[0] ) + ( t * bernstein[1] ); const double b12 = ( s * bernstein[1] ) + ( t * bernstein[2] ); return ( s * b01 ) + ( t * b12 ); } // Subprogram (3) std::vector<double> monomial_to_bernstein_degree3(const std::vector<double>& monomial) { return std::vector<double>{ monomial[0], monomial[0] + ( monomial[1] / 3.0 ), monomial[0] + ( 2.0 * monomial[1] / 3.0 ) + ( monomial[2] / 3.0 ), monomial[0] + monomial[1] + monomial[2] + monomial[3] }; } // Subprogram (4) double evaluate_bernstein_degree3(const std::vector<double>& bernstein, const double& t) { // de Casteljau’s algorithm const double s = 1 - t; const double b01 = ( s * bernstein[0] ) + ( t * bernstein[1] ); const double b12 = ( s * bernstein[1] ) + ( t * bernstein[2] ); const double b23 = ( s * bernstein[2] ) + ( t * bernstein[3] ); const double b012 = ( s * b01 ) + ( t * b12 ); const double b123 = ( s * b12 ) + ( t * b23 ); return ( s * b012 ) + ( t * b123 ); } // Subprogram (5) std::vector<double> bernstein_degree2_to_degree3(const std::vector<double>& bernstein) { return std::vector<double>{ bernstein[0], ( bernstein[0] / 3.0 ) + ( 2.0 * bernstein[1] / 3.0 ), ( 2.0 * bernstein[1] / 3.0 ) + ( bernstein[2] / 3.0 ), bernstein[2] }; } double evaluate_monomial_degree2(const std::vector<double>& monomial, const double& t) { // Horner’s rule return monomial[0] + ( t * ( monomial[1] + ( t * monomial[2] ) ) ); } double evaluate_monomial_degree3(const std::vector<double>& monomial, const double& t) { // Horner’s rule return monomial[0] + ( t * ( monomial[1] + ( t * ( monomial[2] + ( t * monomial[3] ) ) ) ) ); } int main() { /** * For the following polynomials, use Subprogram (1) to find coefficients in the degree-2 Bernstein basis: * * p(x) = 1 * q(x) = 1 + 2x + 3x² */ std::vector<double> pMonomial2 = { 1.0, 0.0, 0.0 }; std::vector<double> qMonomial2 = { 1.0, 2.0, 3.0 }; std::vector<double> pBernstein2 = monomial_to_bernstein_degree2(pMonomial2); std::vector<double> qBernstein2 = monomial_to_bernstein_degree2(qMonomial2); std::cout << "Subprogram (1) examples:" << std::endl; std::cout << " monomial " + to_string(pMonomial2) + " --> bernstein " + to_string(pBernstein2) << std::endl; std::cout << " monomial " + to_string(qMonomial2) + " --> bernstein " + to_string(qBernstein2) << std::endl; /** * 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. */ std::cout << "Subprogram (2) examples:" << std::endl; for ( const double& x : { 0.25, 7.50 } ) { std::cout << " p(" << x << ") = " << evaluate_bernstein_degree2(pBernstein2, x) << " ( mono: " << evaluate_monomial_degree2(pMonomial2, x) << " )" << std::endl; } for ( const double& x : { 0.25, 7.50 } ) { std::cout << " q(" << x << ") = " << evaluate_bernstein_degree2(qBernstein2, x) << " ( mono: " << evaluate_monomial_degree2(qMonomial2, x) << " )" << std::endl; } /** * 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. */ std::vector<double> pMonomial3 = { 1.0, 0.0, 0.0, 0.0 }; std::vector<double> qMonomial3 = { 1.0, 2.0, 3.0, 0.0 }; std::vector<double> rMonomial3 = { 1.0, 2.0, 3.0, 4.0 }; std::vector<double> pBernstein3 = monomial_to_bernstein_degree3(pMonomial3); std::vector<double> qBernstein3 = monomial_to_bernstein_degree3(qMonomial3); std::vector<double> rBernstein3 = monomial_to_bernstein_degree3(rMonomial3); std::cout << "Subprogram (3) examples:" << std::endl; std::cout << " monomial " + to_string(pMonomial3) + " --> bernstein " + to_string(pBernstein3) << std::endl; std::cout << " monomial " + to_string(qMonomial3) + " --> bernstein " + to_string(qBernstein3) << std::endl; std::cout << " monomial " + to_string(rMonomial3) + " --> bernstein " + to_string(rBernstein3) << std::endl; /** * 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. */ std::cout << "Subprogram (4) examples:" << std::endl; for ( const double& x : { 0.25, 7.50 } ) { std::cout << " p(" << x << ") = " << evaluate_bernstein_degree3(pBernstein3, x) << " ( mono: " << evaluate_monomial_degree3(pMonomial3, x) << " )" << std::endl; } for ( const double& x : { 0.25, 7.50 } ) { std::cout << " q(" << x << ") = " << evaluate_bernstein_degree3(qBernstein3, x) << " ( mono: " << evaluate_monomial_degree3(qMonomial3, x) << " )" << std::endl; } for ( const double& x : { 0.25, 7.50 } ) { std::cout << " r(" << x << ") = " << evaluate_bernstein_degree3(rBernstein3, x) << " ( mono: " << evaluate_monomial_degree3(rMonomial3, x) << " )" << std::endl; } /** * 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. */ std::cout << "Subprogram (5) examples:" << std::endl; std::vector<double> pBernstein3a = bernstein_degree2_to_degree3(pBernstein2); std::vector<double> qBernstein3a = bernstein_degree2_to_degree3(qBernstein2); std::cout << " bernstein " + to_string(pBernstein2) + " --> bernstein " + to_string(pBernstein3a) << std::endl; std::cout << " bernstein " + to_string(qBernstein2) + " --> bernstein " + to_string(qBernstein3a) << std::endl; }  Output: Subprogram (1) examples: monomial [1.000000, 0.000000, 0.000000] --> bernstein [1.000000, 1.000000, 1.000000] monomial [1.000000, 2.000000, 3.000000] --> bernstein [1.000000, 2.000000, 6.000000] Subprogram (2) examples: p(0.25) = 1 ( mono: 1 ) p(7.5) = 1 ( mono: 1 ) q(0.25) = 1.6875 ( mono: 1.6875 ) q(7.5) = 184.75 ( mono: 184.75 ) Subprogram (3) examples: monomial [1.000000, 0.000000, 0.000000, 0.000000] --> bernstein [1.000000, 1.000000, 1.000000, 1.000000] monomial [1.000000, 2.000000, 3.000000, 0.000000] --> bernstein [1.000000, 1.666667, 3.333333, 6.000000] monomial [1.000000, 2.000000, 3.000000, 4.000000] --> bernstein [1.000000, 1.666667, 3.333333, 10.000000] Subprogram (4) examples: p(0.25) = 1 ( mono: 1 ) p(7.5) = 1 ( mono: 1 ) 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: bernstein [1.000000, 1.000000, 1.000000] --> bernstein [1.000000, 1.000000, 1.000000, 1.000000] bernstein [1.000000, 2.000000, 6.000000] --> bernstein [1.000000, 1.666667, 3.333333, 6.000000]  ## 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]  ## Java import java.util.Arrays; import java.util.List; public final class BernsteinBasisPolynomials { public static void main(String[] args) { /** * For the following polynomials, use Subprogram (1) to find coefficients in the degree-2 Bernstein basis: * * p(x) = 1 * q(x) = 1 + 2x + 3x² */ QuadraticCoefficients pMonomial2 = new QuadraticCoefficients(1.0, 0.0, 0.0); QuadraticCoefficients qMonomial2 = new QuadraticCoefficients(1.0, 2.0, 3.0); QuadraticCoefficients pBernstein2 = monomialToBernsteinDegree2(pMonomial2); QuadraticCoefficients qBernstein2 = monomialToBernsteinDegree2(qMonomial2); System.out.println("Subprogram (1) examples:"); System.out.println(" monomial " + pMonomial2 + " --> bernstein " + pBernstein2); System.out.println(" monomial " + qMonomial2 + " --> bernstein " + qBernstein2); /** * 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. */ System.out.println("Subprogram (2) examples:"); for ( double x : List.of( 0.25, 7.50 ) ) { System.out.println(" p(" + x + ") = " + evaluateBernsteinDegree2(pBernstein2, x) + " ( mono: " + evaluateMonomialDegree2(pMonomial2, x) + " )"); } for ( double x : List.of( 0.25, 7.50 ) ) { System.out.println(" q(" + x + ") = " + evaluateBernsteinDegree2(qBernstein2, x) + " ( mono: " + evaluateMonomialDegree2(qMonomial2, 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. */ CubicCoefficients pMonomial3 = new CubicCoefficients(1.0, 0.0, 0.0, 0.0); CubicCoefficients qMonomial3 = new CubicCoefficients(1.0, 2.0, 3.0, 0.0); CubicCoefficients rMonomial3 = new CubicCoefficients(1.0, 2.0, 3.0, 4.0); CubicCoefficients pBernstein3 = monomialToBernsteinDegree3(pMonomial3); CubicCoefficients qBernstein3 = monomialToBernsteinDegree3(qMonomial3); CubicCoefficients rBernstein3 = monomialToBernsteinDegree3(rMonomial3); System.out.println("Subprogram (3) examples:"); System.out.println(" monomial " + pMonomial3 + " --> bernstein " + pBernstein3); System.out.println(" monomial " + qMonomial3 + " --> bernstein " + qBernstein3); System.out.println(" monomial " + rMonomial3 + " --> bernstein " + rBernstein3); /** * 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. */ System.out.println("Subprogram (4) examples:"); for ( double x : List.of( 0.25, 7.50 ) ) { System.out.println(" p(" + x + ") = " + evaluateBernsteinDegree3(pBernstein3, x) + " ( mono: " + evaluateMonomialDegree3(pMonomial3, x) + " )"); } for ( double x : List.of( 0.25, 7.50 ) ) { System.out.println(" q(" + x + ") = " + evaluateBernsteinDegree3(qBernstein3, x) + " ( mono: " + evaluateMonomialDegree3(qMonomial3, x) + " )"); } for ( double x : List.of( 0.25, 7.50 ) ) { System.out.println(" r(" + x + ") = " + evaluateBernsteinDegree3(rBernstein3, x) + " ( mono: " + evaluateMonomialDegree3(rMonomial3, 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. */ System.out.println("Subprogram (5) examples:"); CubicCoefficients pBernstein3a = bernsteinDegree2ToDegree3(pBernstein2); CubicCoefficients qBernstein3a = bernsteinDegree2ToDegree3(qBernstein2); System.out.println(" bernstein " + pBernstein2 + " --> bernstein " + pBernstein3a); System.out.println(" bernstein " + qBernstein2 + " --> bernstein " + qBernstein3a); } private static record QuadraticCoefficients(double q0, double q1, double q2) { @Override public String toString() { return Arrays.asList(q0, q1, q2).toString(); } } private static record CubicCoefficients(double c0, double c1, double c2, double c3) { @Override public String toString() { return Arrays.asList(c0, c1, c2, c3).toString(); } } // Subprogram (1) private static QuadraticCoefficients monomialToBernsteinDegree2(QuadraticCoefficients monomial) { return new QuadraticCoefficients( monomial.q0, monomial.q0 + ( monomial.q1 / 2.0 ), monomial.q0 + monomial.q1 + monomial.q2 ); } // Subprogram (2) private static double evaluateBernsteinDegree2(QuadraticCoefficients bernstein, double t) { // de Casteljau’s algorithm final double s = 1 - t; final double b01 = ( s * bernstein.q0 ) + ( t * bernstein.q1 ); final double b12 = ( s * bernstein.q1 ) + ( t * bernstein.q2 ); return ( s * b01 ) + ( t * b12 ); } // Subprogram (3) private static CubicCoefficients monomialToBernsteinDegree3(CubicCoefficients monomial) { return new CubicCoefficients( monomial.c0, monomial.c0 + ( monomial.c1 / 3.0 ), monomial.c0 + ( 2.0 * monomial.c1 / 3.0 ) + ( monomial.c2 / 3.0 ), monomial.c0 + monomial.c1 + monomial.c2 + monomial.c3 ); } // Subprogram (4) private static double evaluateBernsteinDegree3(CubicCoefficients bernstein, double t) { // de Casteljau’s algorithm final double s = 1 - t; final double b01 = ( s * bernstein.c0 ) + ( t * bernstein.c1 ); final double b12 = ( s * bernstein.c1 ) + ( t * bernstein.c2 ); final double b23 = ( s * bernstein.c2 ) + ( t * bernstein.c3 ); final double b012 = ( s * b01 ) + ( t * b12 ); final double b123 = ( s * b12 ) + ( t * b23 ); return ( s * b012 ) + ( t * b123 ); } // Subprogram (5) private static CubicCoefficients bernsteinDegree2ToDegree3(QuadraticCoefficients bernstein) { return new CubicCoefficients( bernstein.q0, ( bernstein.q0 / 3.0 ) + ( 2.0 * bernstein.q1 / 3.0 ), ( 2.0 * bernstein.q1 / 3.0 ) + ( bernstein.q2 / 3.0 ), bernstein.q2 ); } private static double evaluateMonomialDegree2(QuadraticCoefficients monomial, double t) { // Horner’s rule return monomial.q0 + ( t * ( monomial.q1 + ( t * monomial.q2 ) ) ); } private static double evaluateMonomialDegree3(CubicCoefficients monomial, double t) { // Horner’s rule return monomial.c0 + ( t * ( monomial.c1 + ( t * ( monomial.c2 + ( t * monomial.c3 ) ) ) ) ); } }  Output: Subprogram (1) examples: monomial [1.0, 0.0, 0.0] --> bernstein [1.0, 1.0, 1.0] monomial [1.0, 2.0, 3.0] --> bernstein [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: monomial [1.0, 0.0, 0.0, 0.0] --> bernstein [1.0, 1.0, 1.0, 1.0] monomial [1.0, 2.0, 3.0, 0.0] --> bernstein [1.0, 1.6666666666666665, 3.333333333333333, 6.0] monomial [1.0, 2.0, 3.0, 4.0] --> bernstein [1.0, 1.6666666666666665, 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.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: bernstein [1.0, 1.0, 1.0] --> bernstein [1.0, 1.0, 1.0, 1.0] bernstein [1.0, 2.0, 6.0] --> bernstein [1.0, 1.6666666666666665, 3.333333333333333, 6.0]  ## jq Adapted from Wren 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:")
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)
`