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. (As much type-safety as we achieve here can be done in
at runtime. (Such type-safety can be partly achieved in many other
many other languages simply by giving the types different names but
languages simply by giving the types different names but the same
the same fields. But then you cannot easily have type-safe
fields. But then you cannot easily have TYPE-SAFE subprograms that
subprograms that work on EITHER type. Perhaps you could do it with
work on EITHER type. You could have that with a type hierarchy, but
a type hierarchy, but then you start getting runtime overhead.) *)
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
message similar to these:
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}
print_mono_degree2 (coefs : poly_degree2 (monoknd, coefknd))
(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, "mono (");
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}
print_bern_degree2 (coefs : poly_degree2 (bernknd, coefknd))
(coefs : poly_degree3 (polyknd, coefknd))
: void =
let
val+ @(_ | b0, b1, b2) = 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, ")")
end

fn {coefknd : tkind}
print_mono_degree3 (coefs : poly_degree3 (monoknd, coefknd))
: void =
: void =
let
let
Line 715: Line 717:
macdef outf = stdout_ref
macdef outf = stdout_ref
in
in
fprint_val<string> (outf, "mono (");
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, ")")
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
end


Line 729: Line 755:
print_bern_degree3 (coefs : poly_degree3 (bernknd, coefknd))
print_bern_degree3 (coefs : poly_degree3 (bernknd, coefknd))
: void =
: void =
let
begin
fprint_val<string> (stdout_ref, "bern ");
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