user
The 

n
+
1
{\displaystyle {\displaystyle n+1}}
 Bernstein basis polynomials of degree 

n
{\displaystyle {\displaystyle n}}
 are defined as

:   b

    k
    ,
    n
    (
    t
    )
    =

    (

    n
    k

    )

    t

    k


    (

    1
    −
    t
    )

    n
    −
    k
    ,

    k
    =
    0
    ,
    …
    ,
    n
    {\displaystyle {\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.

The task is as follows:

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: 

   p
   (
   x
   )
   =
   1
   {\displaystyle {\displaystyle p(x)=1}}
   , 

   q
   (
   x
   )
   =
   1
   +
   2
   x
   +
   3

   x

   2
   {\displaystyle {\displaystyle q(x)=1+2x+3x^{2}}}
   . Display the results.
7. Use *Subprogram (2)* to evaluate 

   p
   (
   x
   )
   {\displaystyle {\displaystyle p(x)}}
    and 

   q
   (
   x
   )
   {\displaystyle {\displaystyle q(x)}}
    at 

   x
   =
   0.25
   {\displaystyle {\displaystyle x=0.25}}
    and at 

   x
   =
   7.50
   {\displaystyle {\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 

   p
   (
   x
   )
   {\displaystyle {\displaystyle p(x)}}
    and 

   q
   (
   x
   )
   {\displaystyle {\displaystyle q(x)}}
   , and additionally also for 

   r
   (
   x
   )
   =
   1
   +
   2
   x
   +
   3

   x

   2
   +
   4

   x

   3
   {\displaystyle {\displaystyle r(x)=1+2x+3x^{2}+4x^{3}}}
   . Display the results.
9. Use *Subprogram (4)* to evaluate 

   p
   (
   x
   )
   {\displaystyle {\displaystyle p(x)}}
   , 

   q
   (
   x
   )
   {\displaystyle {\displaystyle q(x)}}
   , and 

   r
   (
   x
   )
   {\displaystyle {\displaystyle r(x)}}
    at 

   x
   =
   0.25
   {\displaystyle {\displaystyle x=0.25}}
    and 

   x
   =
   7.50
   {\displaystyle {\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 

   p
   (
   x
   )
   {\displaystyle {\displaystyle p(x)}}
    and 

   q
   (
   x
   )
   {\displaystyle {\displaystyle q(x)}}
   .)
10. Use *Subprogram (5)* to get degree-3 Bernstein coefficients for 

    p
    (
    x
    )
    {\displaystyle {\displaystyle p(x)}}
     and 

    q
    (
    x
    )
    {\displaystyle {\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;

```
assistant
**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]
```

You may Attempt This Online!