Simplest answer is: use pretend.
For example, CONS(-2, 3 ::INT)$Lisp pretend Fraction INT (I)
No!!! If ever possible avoid Lisp in your program. That's in my eyes
even worse than using pretend. As for Fraction(...) you track the
representation down along the "add" inheritance. Since SPAD doesn't
allow multiple inheritance in the "add" line, that should be easy.
https://github.com/hemmecke/fricas-svn/blob/master/src/algebra/fraction.spad.pamphlet#L314
There you have
Fraction(S: IntegralDomain): QuotientFieldCategory S with
if S has IntegerNumberSystem and S has OpenMath then OpenMath
if S has Canonical and S has GcdDomain and S has canonicalUnitNormal
then Canonical
++ \spad{Canonical} means that equal elements are in fact
identical.
== LocalAlgebra(S, S) add
Rep:= Record(num:S, den:S)
...
Actually, already the definition of Rep as Record is bad, since it makes
the assumption that LocalAlgebra(S, S) has this Record representation.
Better would have been
Rep := LocalAlgebra(S, S)
But OK, that's legacy software.
Anyway, if ever you use "pretend" for your purpose in Fraction(Integer),
you should do something like
([n,d]$Record(num:Integer,den:Integer)) pretend Fraction(Integer)
That is expressing everything in terms of the SPAD language without ever
saying that the underlying assembly language is LISP.
It's important for the future. Maybe some day, we change from LISP to
Forth or to C or LLVM or whatever.
-- FriCAS is free to choose a different canonical form method, a matter
of internal representation etc.
In this case, it will occur (I) ~= (II), and this `pretend' usage will
occur incorrect. Right?
Exactly.
I think, you can decipher what these lines mean
https://github.com/hemmecke/fricas-svn/blob/master/src/algebra/fraction.spad.pamphlet#L316
if S has Canonical and S has GcdDomain and S has canonicalUnitNormal
then Canonical
Moreover, this CONS-pretend is not safe because Axiom's idea of
canonizing a fraction may differ from DoCon's one.
Also right.
Currently, DoCon can form Fraction D only for a GCDRing D.
But even in this restricted case Axiom's method may differ from DoCon's
for some instances of such D.
I guess, currently, it doesn't. At least not for Fraction(Integer). But
Fraction as a generic domain constructor is quite general. It's not so
totally obvious how one would for example make the representation of
Fraction(SUP(INT)) canonical.
This is why I suggest for an Axiom (FriCAS) library to provide
package ... (D : IntegralDomain)
...
fraction(m : FooMode, num : D, den : D) : Fraction D == ...
in which m may be MtPrime or Generic
(may be, to provide the second format for `fraction', with skipped `m').
But the maintenance effort is the same if it lives in your package or in
a separate package in the Algebra library. This "fraction" function has
to know the internal representation of Fraction. And the only place
where the representation should be known is Fraction itself. So one
would have to introduce this function into the Fraction code and *trust*
the programmer that the input is as required. But since that cannot (and
by design should not) be checked, the only place for a good
specification of that function would be the documentation.
The documentation/specification of that function would have to be
changed if the representation changes. But of course, any external code
does not care about the documentation, only a programmer can realize
that there was a change. So programs will after some iterations assume
things that are no longer true.
I wouldn't want to hunt for bugs in such situations. It's already
complicated enough to implement the right mathematics correctly.
MtPrime means that num and den are mutually prime,
that is Ideal(num) + Ideal(den) = (1).
Example:
D = POLY([x,y,z], INT), and gcd(f:D, g) = 1
is found in previous computation (done for a need other than Fraction).
This is a good point to write
(1) fr : Fraction D := fraction(MtPrime, f, g)
instead of (2) fr := (f/g) :: Fraction D
and instead of (3) fr := CONS(f, g)$Lisp pretend Fraction D.
I clearly understand your point. So maybe the idea is to create a domain
Coprime(G: GcdDomain): with
construct: (G, G) -> %
== add
Rep == Product(G, G)
construct(x: G, y: G): % == ...
and in Fraction(D) have a function
fraction: Coprime(D) -> %
such a function "fraction" would trust that elements in Coprime(D) are
supposed to be coprime.
Well, now the problem is, how to construct elements of Coprime(D) in a
typesafe and fast fashion?
Maybe you have a function
gcd: (D, D) -> Union(D, Coprime(D))
where the result is the gcd if the elements are not coprime and the
Coprime(D) element (i.e. a pair), if the input is coprime.
I suggest fraction(m, num, den),
a) where m may be MtPrime or Generic,
b) this operation to be implemented by the Axiom library, not by the user,
Sorry, but we are not in a situation like in Maple or Mathematica. User
code is indistinguishable and treated in exactly the same way as the
library that comes with FriCAS. In Maple or Mathematica, they have a
kernel and then there are (interpreted) user functions. That's not the
case for SPAD files. Domains/Categories/Packages in user defined .spad
files are compile in the same way as library functions just like in any
other ordinary programming language.
c) in simple cases (D = INT, POLY(vars, INT), POLY(vars, Rational), and
such) it will hopefully lead to optimization,
d) which usage is totally safe.
When DoCon puts a string to Axiom, fractions are in their canonical form
by "gi". And it is desirable to avoid gcd when parsing (by dParse)
of such a fraction to Axiom.
OK, this is a situation where your parsing framework should know about
the internal structure of FriCAS domains and Fraction in particular,
i.e. "pretend" should be the way to go.
You should, however, mark such "pretend" places in big bold red letters
[..]
In this case I will need to change dParse each time when FriCAS changes
treating of Fraction.
Yes, that's called maintenance nightmare. ;-)
Also I would need to study just now all the details of treating Fraction
in Axiom -- for the case of D : GcdRing.
This way does not look safe nor nice.
But there are not too many people who would do the job for you. It's
open source and unfortunately, FriCAS is not that wide-spread yet.
So, if Axiom(FriCAS) rejects my above suggestion of joining
fraction(m : Mode, num : D, den : D) : Fraction D,
then I would be forced to apply (num/den) :: Fraction D,
and this will lead to an unneeded gcd computation during the interface.
Well yes that should be the first way to go. I think you should first
program in a typesafe way and only then look for bottlenecks that slow
down your code.
Ralf
--
You received this message because you are subscribed to the Google Groups "FriCAS -
computer algebra system" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/fricas-devel?hl=en.