Bernstein basis polynomials: Difference between revisions
Content added Content deleted
(Added more explanation of the type-safety design: why what C/Pascal/C++/etc. do is inadequate.) |
(→{{header|ATS}}: More pedagogical commentary. Also, I modularized the polynomial-printing code, demonstrating more aspects of the type system.) |
||
Line 572: | Line 572: | ||
(* We will try to achieve the type-safety of distinguishing between |
(* We will try to achieve the type-safety of distinguishing between |
||
monomial and Bernstein bases at compile time, but without overhead |
monomial and Bernstein bases at compile time, but without overhead |
||
at runtime. ( |
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 monoknd = "rosettacode_monomial_poly" |
||
tkindef bernknd = "rosettacode_bernstein_poly" |
tkindef bernknd = "rosettacode_bernstein_poly" |
||
Line 601: | Line 612: | ||
mono2bern_degree2 with Bernstein coefficients (instead of monomial |
mono2bern_degree2 with Bernstein coefficients (instead of monomial |
||
coefficients) as the argument, then, AT COMPILE TIME, you get |
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): warning(3): the constraint [S2Eeqeq(S2Eextkind(rosettacode_bernstein_poly); S2Eextkind(rosettacode_monomial_poly))] cannot be translated into a form accepted by the constraint solver. |
||
Line 675: | Line 686: | ||
end |
end |
||
(* Let us make it easy to print out coefficients. |
(* 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} |
fn {coefknd : tkind} |
||
print_poly_degree2 {polyknd : tkind} |
|||
⚫ | |||
(coefs : poly_degree2 (polyknd, coefknd)) |
|||
: void = |
: void = |
||
let |
let |
||
Line 683: | Line 700: | ||
macdef outf = stdout_ref |
macdef outf = stdout_ref |
||
in |
in |
||
fprint_val<string> (outf, " |
fprint_val<string> (outf, "("); |
||
fprint_val<g0float coefknd> (outf, a0); |
fprint_val<g0float coefknd> (outf, a0); |
||
fprint_val<string> (outf, ", "); |
fprint_val<string> (outf, ", "); |
||
Line 693: | Line 710: | ||
fn {coefknd : tkind} |
fn {coefknd : tkind} |
||
print_poly_degree3 {polyknd : tkind} |
|||
⚫ | |||
⚫ | |||
⚫ | |||
let |
|||
val+ @(_ | b0, b1, b2) = coefs |
|||
macdef outf = stdout_ref |
|||
in |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
fprint_val<string> (outf, ", "); |
|||
fprint_val<g0float coefknd> (outf, b2); |
|||
fprint_val<string> (outf, ")") |
|||
⚫ | |||
⚫ | |||
⚫ | |||
: void = |
: void = |
||
let |
let |
||
Line 715: | Line 717: | ||
macdef outf = stdout_ref |
macdef outf = stdout_ref |
||
in |
in |
||
fprint_val<string> (outf, " |
fprint_val<string> (outf, "("); |
||
fprint_val<g0float coefknd> (outf, a0); |
fprint_val<g0float coefknd> (outf, a0); |
||
fprint_val<string> (outf, ", "); |
fprint_val<string> (outf, ", "); |
||
Line 724: | Line 726: | ||
fprint_val<g0float coefknd> (outf, a3); |
fprint_val<g0float coefknd> (outf, a3); |
||
fprint_val<string> (outf, ")") |
fprint_val<string> (outf, ")") |
||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
begin |
|||
⚫ | |||
print_poly_degree2 (coefs) |
|||
end |
|||
fn {coefknd : tkind} |
|||
⚫ | |||
: void = |
|||
begin |
|||
⚫ | |||
print_poly_degree2 (coefs) |
|||
end |
|||
fn {coefknd : tkind} |
|||
print_mono_degree3 (coefs : poly_degree3 (monoknd, coefknd)) |
|||
: void = |
|||
begin |
|||
⚫ | |||
print_poly_degree3 (coefs) |
|||
end |
end |
||
Line 729: | Line 755: | ||
print_bern_degree3 (coefs : poly_degree3 (bernknd, coefknd)) |
print_bern_degree3 (coefs : poly_degree3 (bernknd, coefknd)) |
||
: void = |
: void = |
||
begin |
|||
⚫ | |||
val+ @(_ | b0, b1, b2, b3) = coefs |
|||
print_poly_degree3 (coefs) |
|||
macdef outf = stdout_ref |
|||
in |
|||
fprint_val<string> (outf, "bern ("); |
|||
fprint_val<g0float coefknd> (outf, b0); |
|||
fprint_val<string> (outf, ", "); |
|||
fprint_val<g0float coefknd> (outf, b1); |
|||
fprint_val<string> (outf, ", "); |
|||
fprint_val<g0float coefknd> (outf, b2); |
|||
fprint_val<string> (outf, ", "); |
|||
fprint_val<g0float coefknd> (outf, b3); |
|||
fprint_val<string> (outf, ")") |
|||
end |
end |
||