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.

Reply via email to