conditional exports and aldor compilation

20 views
Skip to first unread message

Ralf Hemmecke

unread,
Nov 26, 2011, 6:49:55 AM11/26/11
to fricas-devel
Hi Waldek,

I need some hints.

After a few fixes wrt the aldor-interface, I am stuck with the following
error.

#1 (Error) Argument 2 of `FiniteDivisor' did not match any possible
parameter type.
The rejected type is UnivariatePolynomialCategory(#1 pretend Ring).
Expected type UnivariatePolynomialCategory(#2 pretend Field).

It steams from ap/PFO.ap. The original code is in pfo.spad.pamphlet
(copied below). What looks a bit strange and that is where this error
comes from is the translation of

if R0 has CharacteristicZero and F has AlgebraicallyClosedField then
simplifyCoeffs : (FD, List K) -> N

into the .ap format. That's done via |makeAxExportForm| from ax.boot.
(See generate-ax-file in src/aldor/gendepap.lsp.)

Only in this "if" body there appear |PretendTo| expressions (see below)
that seem to let the aldor compilation fail. For sure there must be some
technicalities to ensure that inside that "if" body R0 and F belong
additionally to other categories, but I don't quite understand why I see
"(|PretendTo| |#2| |Field|)" or (|PretendTo| |#1| |Ring|)".

I don't know exactly which part of the FriCAS code is responsible for
this, but I've the feeling that it is not ax.boot, since that is just
translating the available data structures.

Anyway, this generation even looks wrong to me. Let's suppose the
context is Foo: Cat1. Then

if Foo has Cat2 then CODE

should mean that inside CODE we can claim Foo: Join(Cat1, Cat2).

But as you see below, it looks as if FriCAS just "|PretendTo| whatever
FiniteDivisor or UnivariatePolynomialCategory is originally defined.

UnivariatePolynomialCategory(R:Ring): Category == ...
FiniteDivisorCategory(F, UP, UPUP, R): Category == Result where
F : Field
...

Do you think the generated code is correct and Aldor simply shouldn't
fail? Or is the error rather on the FriCAS side?

Ralf

PS: Removing all the |PretendTo| expressions from the .ap file and
simply writing

(|If| (|Test| (|Has| |#1| |CharacteristicZero|))
(|If| (|Test| (|Has| |#2| |AlgebraicallyClosedField|))
(|Declare| |simplifyCoeffs|
(|Apply| ->
(|Comma|
(|Apply| |FiniteDivisor| |#2| |#3| |#4| |#5|)
(|Apply| |List| (|Apply| |Kernel| |#2|)))
|NonNegativeInteger|))
NIL)
NIL)

let's aldor compile PFO.ap without any error message.


====================================
from pfo.spad.pamphlet
https://github.com/hemmecke/fricas-svn/blob/master/src/algebra/pfo.spad.pamphlet#L154
====================================
PointsOfFiniteOrder(R0, F, UP, UPUP, R): Exports == Implementation where
R0 : Join(Comparable, IntegralDomain, RetractableTo Integer)
F : FunctionSpace R0
UP : UnivariatePolynomialCategory F
UPUP : UnivariatePolynomialCategory Fraction UP
R : FunctionFieldCategory(F, UP, UPUP)

PI ==> PositiveInteger
N ==> NonNegativeInteger
Z ==> Integer
Q ==> Fraction Integer
UPF ==> SparseUnivariatePolynomial F
UPQ ==> SparseUnivariatePolynomial Q
QF ==> Fraction UP
UPUPQ ==> SparseUnivariatePolynomial Fraction UPQ
UP2 ==> SparseUnivariatePolynomial UPQ
UP3 ==> SparseUnivariatePolynomial UP2
FD ==> FiniteDivisor(F, UP, UPUP, R)
K ==> Kernel F
REC ==> Record(ncurve:UP3, disc:Z, dfpoly:UPQ)
RC0 ==> Record(ncurve:UPUPQ, disc:Z)
ID ==> FractionalIdeal(UP, QF, UPUP, R)
SMP ==> SparseMultivariatePolynomial(R0,K)

Exports ==> with
order : FD -> Union(N, "failed")
++ order(f) \undocumented
torsion? : FD -> Boolean
++ torsion?(f) \undocumented
torsionIfCan : FD -> Union(Record(order:N, function:R), "failed")
++ torsionIfCan(f)\ undocumented
cmult : List SMP -> SMP
++ cmult(x) should be local but conditional
possibleOrder : FD -> N
if R0 has CharacteristicZero and F has AlgebraicallyClosedField then
simplifyCoeffs : (FD, List K) -> N
++ simplifyCoeffs(d, la) should be local but conditional

====================================
from PFO.ap
====================================
(|If| (|Test| (|Has| |#1| |CharacteristicZero|))
(|If| (|Test| (|Has| |#2| |AlgebraicallyClosedField|))
(|Declare| |simplifyCoeffs|
(|Apply| ->
(|Comma|
(|Apply| |FiniteDivisor| (|PretendTo| |#2| |Field|)
(|PretendTo| |#3|
(|Apply| |UnivariatePolynomialCategory|
(|PretendTo| |#1| |Ring|)))
(|PretendTo| |#4|
(|Apply| |UnivariatePolynomialCategory|
(|PretendTo|
(|Apply| |Fraction|
(|PretendTo| |#2| |IntegralDomain|))
|Ring|)))
(|PretendTo| |#5|
(|Apply| |FunctionFieldCategory|
(|PretendTo| |#1| |UniqueFactorizationDomain|)
(|PretendTo| |#2|
(|Apply| |UnivariatePolynomialCategory|
(|PretendTo| |#1| |Ring|)))
(|PretendTo| |#3|
(|Apply| |UnivariatePolynomialCategory|
(|PretendTo|
(|Apply| |Fraction|
(|PretendTo| |#2| |IntegralDomain|))
|Ring|))))))
(|Apply| |List|
(|PretendTo|
(|Apply| |Kernel| (|PretendTo| |#2| |Comparable|))
|Type|)))
|NonNegativeInteger|))
NIL)
NIL)

Waldek Hebisch

unread,
Nov 27, 2011, 11:58:24 AM11/27/11
to fricas...@googlegroups.com
Ralf Hemmecke wrote:
>
> Hi Waldek,
>
> I need some hints.
>
> After a few fixes wrt the aldor-interface, I am stuck with the following
> error.
>
> #1 (Error) Argument 2 of `FiniteDivisor' did not match any possible
> parameter type.
> The rejected type is UnivariatePolynomialCategory(#1 pretend Ring).
> Expected type UnivariatePolynomialCategory(#2 pretend Field).
>
> It steams from ap/PFO.ap. The original code is in pfo.spad.pamphlet
> (copied below). What looks a bit strange and that is where this error
> comes from is the translation of
>
> if R0 has CharacteristicZero and F has AlgebraicallyClosedField then
> simplifyCoeffs : (FD, List K) -> N
>
> into the .ap format. That's done via |makeAxExportForm| from ax.boot.
> (See generate-ax-file in src/aldor/gendepap.lsp.)
>
> Only in this "if" body there appear |PretendTo| expressions (see below)
> that seem to let the aldor compilation fail. For sure there must be some
> technicalities to ensure that inside that "if" body R0 and F belong
> additionally to other categories, but I don't quite understand why I see
> "(|PretendTo| |#2| |Field|)" or (|PretendTo| |#1| |Ring|)".
>
> I don't know exactly which part of the FriCAS code is responsible for
> this, but I've the feeling that it is not ax.boot, since that is just
> translating the available data structures.

AFAICS the relevant code in ax.boot is triggered by '$pretendFlag'.
You may try to see what happens when '$pretendFlag' is always false.
I am affraid this code is necessary: it looks that pretends try
tu say that arguments have expected types. Assumung that Spad
compiler already checked arument types it is reasonable strategy.
However, it seems that 'axFormatType' function from ax.boot got
confused due to nesting and changing meaning of '#1', '#2', ...
Namely, we have

PointsOfFiniteOrder(R0, F, UP, UPUP, R): ...

here #1 is R0, #2 is F, #3 is UP. But then we have:

FD ==> FiniteDivisor(F, UP, UPUP, R)

FiniteDivisor has its own #1 which is F, #2 which is UP,...
This part seem to be handled correctly, 'axFormatType' substitutes
proper values for arguments of FiniteDivisor. However, the
second argument of FiniteDivisor, that is UP is declared to be
of type 'UnivariatePolynomialCategory(#1)'. Here '#1' refers
to first argument of FiniteDivisor, while apparenty 'axFormatType'
uses first argument of PointsOfFiniteOrder.

> Anyway, this generation even looks wrong to me. Let's suppose the
> context is Foo: Cat1. Then
>
> if Foo has Cat2 then CODE
>
> should mean that inside CODE we can claim Foo: Join(Cat1, Cat2).
>
> But as you see below, it looks as if FriCAS just "|PretendTo| whatever
> FiniteDivisor or UnivariatePolynomialCategory is originally defined.

No, IIUC arguments to types are pretended to be of correct type.
Conditions means that it is not entirely trivial to decide
if argument types are correct. Minor difference between Spad
compiler and Aldor could lead to type error if you try to just
pass types 'as is'.

> Do you think the generated code is correct and Aldor simply shouldn't
> fail? Or is the error rather on the FriCAS side?

As I wrote, I think that 'ax.boot' produced wrong code.

> ====================================
> from PFO.ap
> ====================================
> (|If| (|Test| (|Has| |#1| |CharacteristicZero|))
> (|If| (|Test| (|Has| |#2| |AlgebraicallyClosedField|))
> (|Declare| |simplifyCoeffs|
> (|Apply| ->
> (|Comma|
> (|Apply| |FiniteDivisor| (|PretendTo| |#2| |Field|)
> (|PretendTo| |#3|
> (|Apply| |UnivariatePolynomialCategory|
> (|PretendTo| |#1| |Ring|)))

^^^^^^^^^^^^^^^^^^^^^^^^
This is wrong, insted we should have (|PretendTo| |#2| |Field|).


--
Waldek Hebisch
heb...@math.uni.wroc.pl

Ralf Hemmecke

unread,
Nov 27, 2011, 5:35:32 PM11/27/11
to fricas...@googlegroups.com
First of all, thanks Waldek!

I cannot yet say whether I can fix ax.boot easily, but at least your
hints sound better than I thought.

> AFAICS the relevant code in ax.boot is triggered by '$pretendFlag'.
> You may try to see what happens when '$pretendFlag' is always false.
> I am affraid this code is necessary: it looks that pretends try
> tu say that arguments have expected types.

Well, that is something I don't actually believe. IIUC, the .ap format
is basically aldor synax in a lisp-like form. Since Aldor itself does
not need a "pretend" in the body of an "if dom has cat then ..."
construction, I don't think the |PretendTo| would be necessary in the
.ap file. I'll report back after checking.

Maybe, I should also contact Peter Broadbery. Perhaps, he knows why this
code got into ax.boot in the first place.

> Assumung that Spad
> compiler already checked arument types it is reasonable strategy.

I don't quite understand. Let's make an artificial example.

CatA(T: SemiRng): Category == with
foo: % -> %
if T has Ring then
bar: % -> %

CatB(X: AbelianMonoid): Category == with
if X has Ring then CatA(X)


Should Cat(Integer) be exporting bar or not? I think, it should, if CatB
is translated as you say then it would mean

if Integer has Ring then CatA(Integer pretend SemiRng)

I already had difficulties understanding how "has" works and probably
the "pretend SemiRng" will not prevent "T has Ring" to return true for
T=Integer. Still, it looks a bit confusing to me.

>> ====================================
>> from PFO.ap
>> ====================================
>> (|If| (|Test| (|Has| |#1| |CharacteristicZero|))
>> (|If| (|Test| (|Has| |#2| |AlgebraicallyClosedField|))
>> (|Declare| |simplifyCoeffs|
>> (|Apply| ->
>> (|Comma|
>> (|Apply| |FiniteDivisor| (|PretendTo| |#2| |Field|)
>> (|PretendTo| |#3|
>> (|Apply| |UnivariatePolynomialCategory|
>> (|PretendTo| |#1| |Ring|)))
> ^^^^^^^^^^^^^^^^^^^^^^^^
> This is wrong, insted we should have (|PretendTo| |#2| |Field|).

Aha, that's a good catch. I also wanted to see |Field| there, but that
also the |#1| is wrong, I didin't see. Thanks a lot.

Ralf

Waldek Hebisch

unread,
Nov 28, 2011, 12:35:06 PM11/28/11
to fricas...@googlegroups.com
Ralf Hemmecke wrote:
> > Assumung that Spad
> > compiler already checked arument types it is reasonable strategy.
>
> I don't quite understand. Let's make an artificial example.
>
> CatA(T: SemiRng): Category == with
> foo: % -> %
> if T has Ring then
> bar: % -> %
>
> CatB(X: AbelianMonoid): Category == with
> if X has Ring then CatA(X)
>
>
> Should Cat(Integer) be exporting bar or not? I think, it should, if CatB
> is translated as you say then it would mean
>
> if Integer has Ring then CatA(Integer pretend SemiRng)
>
> I already had difficulties understanding how "has" works and probably
> the "pretend SemiRng" will not prevent "T has Ring" to return true for
> T=Integer. Still, it looks a bit confusing to me.

At least in Spad checking if 'T has Ring' uses actual value of T,
so the test will give true. OTOH during compilation compiler may
lack some information (which will be true at runtime) and
either signal error or generate suboptimal code.

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Ralf Hemmecke

unread,
Dec 7, 2011, 7:52:54 PM12/7/11
to fricas...@googlegroups.com, aldor-l, Stephen Watt
Just for the record... and in continuation of
http://groups.google.com/group/fricas-devel/browse_thread/thread/c7d1c908a07758d2

The following seems to reveal a weakness of the Aldor compiler.

In ax.boot I've set the $pretendFlag to false.

axFormatCondOp op ==
$pretendFlag:local := false
axFormatOp op

This, however, prevents the compilation for HOAGG.ap.

"ap/HOAGG.ap", line 15:
(|If| (|Test| (|Has| |#1| (|Apply| |Evalable| |#1|)))
..............................................................^
[L15 C63] #1 (Error) Argument 1 of `Evalable' did not match any possible
parameter type.
The rejected type is Type.
Expected type SetCategory.

The original lines are
https://github.com/hemmecke/fricas-svn/blob/master/src/algebra/aggcat.spad.pamphlet#L113

HomogeneousAggregate(S:Type): Category == Aggregate with
if S has CoercibleTo(OutputForm) then CoercibleTo(OutputForm)
if S has SetCategory then SetCategory
if S has SetCategory then
if S has Evalable S then Evalable S
...

The HOAGG.ap file does not look bad.

(|If| (|Test| (|Has| |#1| |SetCategory|))
(|If| (|Test| (|Has| |#1| (|Apply| |Evalable| |#1|)))
(|Apply| |Evalable| |#1|) NIL)
NIL)

whereas the code generated with "$pretendFlag:local := true" is:

(|If| (|Test| (|Has| |#1| |SetCategory|))
(|If|
(|Test|
(|Has| |#1|
(|Apply| |Evalable| (|PretendTo| |#1| |SetCategory|))))
(|Apply| |Evalable| (|PretendTo| |#1| |SetCategory|)) NIL)
NIL)

Obviously, the Aldor compiler is here weaker than the SPAD compiler.
From my understanding of Aldor

if S has SetCategory then
if S has Evalable S then Evalable S

should compile just fine without manually doing something like

if S has SetCategory then
if S has Evalable(S pretend SetCategory) then Evalable S

:-(

Ralf

hemmecke

unread,
Dec 13, 2011, 7:17:20 PM12/13/11
to FriCAS - computer algebra system
The following program demonstrates a bug in the SPAD compiler.
The file compiles fine with r1168.
The compiler should actually refuse this program, because in
if R has Algebra(R)
it is only known that "R has SetCategory". So in my understanding
it is not known that R satisfies the conditions to be an argument for
the
"Algebra" constructor.

And even if the category part were OK, the add part misses
implementations
for the functions exported by Algebra(R).

Ralf

---rhxBEGIN parametricConditional.spad
)abbrev package PCXX ParametricXConditional
ParametricXConditional(R: BasicType): Exports == Implementation where
Exports ==> with
order: R -> R
if R has SetCategory then
if R has Algebra(R) then Algebra(R)
Implementation ==> add
order(r: R): R == r
---rhxEND parametricConditional.spad

Waldek Hebisch

unread,
Dec 14, 2011, 9:39:18 AM12/14/11
to fricas...@googlegroups.com

Yes, this is known problem: currently Spad compiler do not check
that parameters to constructors in some context (basicaly in
"category part") are of correct type. This is on todo list, but
requires some work.

--
Waldek Hebisch
heb...@math.uni.wroc.pl

hemmecke

unread,
Dec 15, 2011, 6:58:44 PM12/15/11
to FriCAS - computer algebra system
Status update.

I believe, I've found where ax.boot needs to be fixed.

The translation will call

)lisp (|axFormatType| '(|FiniteDivisor| |#2| |#3| |#4| |#5|))

with $pretendFlag being true. That ends up in figuring out the |
PretendTo| things from the output of

)lisp (GETDATABASE '|FiniteDivisor| 'CONSTRUCTORMODEMAP)

The problem simply is that one would have to replace |#1| by |#2|, |
#2| by |#3|, etc. as given in the |axFormatType| call and probably do
this recursively.

I guess, I cannot manage to fix it too quickly since I'd have to find
my way through "programming in BOOT".

Would be good if the interface were fixed, but maybe after fixing
that, other problems pop up. So don't let the release be delayed.

Ralf

Bill Page

unread,
Dec 15, 2011, 10:21:43 PM12/15/11
to fricas...@googlegroups.com
Ralf,

If you really wanted to do that everywhere in the result of axFormatType, in the file 'interp/ax.boot' you could change the line

     MEMQ(typeform, $FormalMapVariableList) => typeform

to

     MEMQ(typeform, $FormalMapVariableList) =>
        SUBLISLIS(rest $FormalMapVariableList, $FormalMapVariableList, typeform)

but I have some doubts that this can be the correct solution in general.  What happens to |#1| ? What is the underlying reason for this change?  What changed in FriCAS to make this necessary?  Or are you saying that this is necessary only in the case of FiniteDivisor ?  I notice that there are numerous such special cases in the 'ax.boot' code.

Note: For debugging BOOT programming I find Lisp syntax


  )lisp (|axFormatType| '(|FiniteDivisor| |#2| |#3| |#4| |#5|))

sometimes a bit inconvenient. Maybe the )boot command is another thing that needs more documentation. The command )boot converts from BOOT syntax to Lisp and then executes the Lisp. For example.

(1) -> )boot axFormatType( [ 'FiniteDivisor, '_#1, '_#2, '_#3, '_#4 ] )                  

(EVAL-WHEN (EVAL LOAD)
  (PROG ()
    (RETURN (|axFormatType| (LIST '|FiniteDivisor| '|#1| '|#2| '|#3| '|#4|)))))

Value = (|Apply| |FiniteDivisor| |#2| |#3| |#4| |#5|)

This is the result after changing 'ax.boot' as I suggested above and running

 (1) -> )read /home/wspage/fricas-src/src//interp/ax.boot 

Regards,
Bill Page.


--
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 fricas...@googlegroups.com.
To unsubscribe from this group, send email to fricas-devel...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/fricas-devel?hl=en.


Bill Page

unread,
Dec 15, 2011, 10:27:04 PM12/15/11
to fricas...@googlegroups.com
Oops. Actually I intended to show this output

(1) -> )boot $pretendFlag := true

(EVAL-WHEN (EVAL LOAD) (SETQ |$pretendFlag| T))
Value = T

(1) -> )boot axFormatType(['FiniteDivisor, '_#1, '_#2, '_#3, '_#4])

(EVAL-WHEN (EVAL LOAD)
  (PROG ()
    (RETURN (|axFormatType| (LIST '|FiniteDivisor| '|#1| '|#2| '|#3| '|#4|)))))
Value = (|Apply| |FiniteDivisor| (|PretendTo| |#2| |Field|)
         (|PretendTo| |#3|
          (|Apply| |UnivariatePolynomialCategory| (|PretendTo| |#2| |Ring|)))

         (|PretendTo| |#4|
          (|Apply| |UnivariatePolynomialCategory|
           (|PretendTo|
            (|Apply| |Fraction| (|PretendTo| |#3| |IntegralDomain|)) |Ring|)))

         (|PretendTo| |#5|
          (|Apply| |FunctionFieldCategory|
           (|PretendTo| |#2| |UniqueFactorizationDomain|)

           (|PretendTo| |#3|
            (|Apply| |UnivariatePolynomialCategory| (|PretendTo| |#1| |Ring|)))
           (|PretendTo| |#4|
            (|Apply| |UnivariatePolynomialCategory|
             (|PretendTo|
              (|Apply| |Fraction| (|PretendTo| |#2| |IntegralDomain|))
              |Ring|))))))
(1) ->

Ralf Hemmecke

unread,
Dec 16, 2011, 9:20:26 AM12/16/11
to fricas...@googlegroups.com
Bill,

> MEMQ(typeform, $FormalMapVariableList) =>
> SUBLISLIS(rest $FormalMapVariableList, $FormalMapVariableList,
> typeform)

Thanks for this hint.

And no, there is no general shift in parameters. That is particular for
this very case.

PointsOfFiniteOrder(R0, F, UP, UPUP, R): Exports == Implementation where
...


FD ==> FiniteDivisor(F, UP, UPUP, R)

i.e. the first argument of FiniteDivisor is really #2.

> Note: For debugging BOOT programming I find Lisp syntax

Thank you. That's very helpful.

Ralf

Bill Page

unread,
Dec 16, 2011, 9:46:27 AM12/16/11
to fricas...@googlegroups.com
Ralf,

On Fri, Dec 16, 2011 at 9:20 AM, you wrote:
>...


> And no, there is no general shift in parameters. That is particular for this very case.
>
> PointsOfFiniteOrder(R0, F, UP, UPUP, R): Exports == Implementation where
>   ...
>
>   FD  ==> FiniteDivisor(F, UP, UPUP, R)
>
> i.e. the first argument of FiniteDivisor is really #2.
>

Ah. Then if this actually worked properly before some recent change to
FriCAS I wonder if if might something to do with a change in the way
macros are processed?

Regards,
Bill Page.

Ralf Hemmecke

unread,
Dec 16, 2011, 1:56:28 PM12/16/11
to fricas...@googlegroups.com
>> FD ==> FiniteDivisor(F, UP, UPUP, R)

> Ah. Then if this actually worked properly before some recent change to


> FriCAS I wonder if if might something to do with a change in the way
> macros are processed?

No, this FD stuff was simply not in a pamphlet. Thus nothing had
triggered this bug before. Other "if ... has ..." stuff that was already
in the Algebra code, was not as involved as this new code.
Look up revision 1144.

Ralf

hemmecke

unread,
Dec 18, 2011, 1:47:59 PM12/18/11
to FriCAS - computer algebra system
Another status update.

I'm near to complete a fix to ax.boot.

Instead of just producing a simple workaround, I produced something
that is in line with my question to Stephen Watt at
http://aldor.org/pipermail/aldor-l_aldor.org/2011-December/001328.html
i.e. I take the category of the argument and Join it with the category
that appears in the "has" expression.

I wouldn't need $pretendFlag anymore if there weren't another place
where $pretendFlag is used in ax.boot.

getDefaultingOps catname ==
not(name:=hasDefaultPackage catname) => nil
$infovec: local := getInfovec name
opTable := $infovec.1
$opList:local := nil
for i in 0..MAXINDEX opTable repeat
op := opTable.i
i := i + 1
startIndex := opTable.i
stopIndex :=
i + 1 > MAXINDEX opTable => MAXINDEX getCodeVector()
opTable.(i + 2)
curIndex := startIndex
while curIndex < stopIndex repeat
curIndex := get1defaultOp(op,curIndex)
$pretendFlag : local := true
catops := GETDATABASE(catname, 'OPERATIONALIST)
[axFormatDefaultOpSig(op,sig,catops) for opsig in $opList | opsig is
[op,sig]]

I actually would have liked to replace the flag in this position with
my new machinery. Unfortunately, it seems to be impossible. This all
has to do with operations in category defaults.

Look for example at VectorCategory. It has a default package that
looks like this.

VectorCategory(R:Type): Category == OneDimensionalArrayAggregate R
with
...
if R has RadicalCategory and R has Ring then
length: % -> R
++ length(v) computes the sqrt(dot(v,v)), i.e. the magnitude
magnitude: % -> R
++ magnitude(v) computes the sqrt(dot(v,v)), i.e. the length
add
...
if R has RadicalCategory and R has Ring then
length p ==
sqrt(dot(p,p))
magnitude p ==
sqrt(dot(p,p))

But it seems that FriCAS doesn't store the "if R has ... then"
conditions.

(1) -> )boot name := hasDefaultPackage('VectorCategory)
(EVAL-WHEN (EVAL LOAD) (SETQ |name| (|hasDefaultPackage| '|
VectorCategory|)))
Value = |VectorCategory&|
(1) -> )boot GETDATABASE(name, 'CONSTRUCTORMODEMAP)
(EVAL-WHEN (EVAL LOAD)
(PROG () (RETURN (GETDATABASE |name| 'CONSTRUCTORMODEMAP))))
Value = (((|VectorCategory&| |#1| |#2|)
(CATEGORY |domain| (SIGNATURE |magnitude| (|#2| |#1|))
(SIGNATURE |length| (|#2| |#1|))
(SIGNATURE |cross| (|#1| |#1| |#1|))
(SIGNATURE |outerProduct| ((|Matrix| |#2|) |#1| |#1|))
(SIGNATURE |dot| (|#2| |#1| |#1|)) (SIGNATURE * (|#1| |#1| |
#2|))
(SIGNATURE * (|#1| |#2| |#1|)) (SIGNATURE * (|#1| (|
Integer|) |#1|))
(SIGNATURE - (|#1| |#1| |#1|)) (SIGNATURE - (|#1| |#1|))
(SIGNATURE |zero| (|#1| (|NonNegativeInteger|)))
(SIGNATURE + (|#1| |#1| |#1|)))
(|VectorCategory| |#2|) (|Type|))
(T |VectorCategory&|))

If that is true, it's not (yet) completely bad since I would simply
use the old machinery for this cases (and for the current algebra
library that still works).

However, the old machinery is inherently wrong (IMHO), since it simply
looks at the involved type constructors and pretends their arguments
to be of the correct type regardless of the actual stuff that appears
in the "has" expression.

So, if FriCAS indeed doesn't store the signature as above, I'm out of
luck, otherwise please let me know how I can extract the "if"
structure of the default package.

Thanks in advance.
Ralf

Ralf Hemmecke

unread,
Dec 18, 2011, 6:13:09 PM12/18/11
to fricas...@googlegroups.com
Hi Waldek,

My new machinery did not consider situations of the form

if % has Ring then
minPoly: K -> SparseUnivariatePolynomial %
++ minPoly(k) returns p such that \spad{p(k) = 0}.

This is actual code from the code of ExpressionSpace.

https://github.com/hemmecke/fricas-svn/blob/master/src/algebra/fspace.spad.pamphlet#L165

Although this might be a syntactically correct statement and it probably
also works, since "% has Ring" is evaluated at runtime, it still looks a
bit wierd to me.

Why? Because it needs something like

D: Join(ExpressionSpace, Ring)

in order for D to provide "minPoly".

So an "external" category triggers whether "minPoly" is exported or not.

But, OK, that's the way it is.

Only one question, where can I find the code that deals with this case?

Will it also just doe something like

if % has T then
foo: X -> Dom(% pretend S)

where S is the category from the argument of Dom, i.e. Dom was defined as:

Dome(D: S): with ...

?

There is no checking of Join(categoryOf(%), T) actually refines S (so it
is somewhat unsafe, but at least it should work.

Ralf

PS: The documentation for "minPoly is questionable.
1) Always returning the zero polynomial would perfectly match the
specification.
2) Nothing says that the returned polynomial has minimal degree.
3) Nothing says that a *non-zero* polynomial exists (and in general
domains it certainly doesn't).

Waldek Hebisch

unread,
Dec 19, 2011, 10:47:25 AM12/19/11
to fricas...@googlegroups.com
Ralf Hemmecke wrote:
>
> Hi Waldek,
>
> My new machinery did not consider situations of the form
>
> if % has Ring then
> minPoly: K -> SparseUnivariatePolynomial %
> ++ minPoly(k) returns p such that \spad{p(k) = 0}.
>
> This is actual code from the code of ExpressionSpace.
>
> https://github.com/hemmecke/fricas-svn/blob/master/src/algebra/fspace.spad.pamphlet#L165
>
> Although this might be a syntactically correct statement and it probably
> also works, since "% has Ring" is evaluated at runtime, it still looks a
> bit wierd to me.
>
> Why? Because it needs something like
>
> D: Join(ExpressionSpace, Ring)
>
> in order for D to provide "minPoly".
>
> So an "external" category triggers whether "minPoly" is exported or not.
>
> But, OK, that's the way it is.

The only thing which raises questions is why Ring is enough
(it is clear that Field is sufficient). Otherwise I do not
consider this weird: we simply write conditions that are needed
to implement given function. In this place it immaterial
when '% has Ring'.

>
> Only one question, where can I find the code that deals with this case?

I am affraid there is no simple answer: all exports carry conditions.
Handling of conditions is spread out into several places: JoinInner
(and functions it calls) is responsible for merging export lists.
'knownInfo' decides if conditions is true in given context (and
context changes dynamically during compilation). Modemap selection
checks (using 'knownInfo') if conditions are satisfied and if
not it skips given modemap.

> Will it also just doe something like
>
> if % has T then
> foo: X -> Dom(% pretend S)
>
> where S is the category from the argument of Dom, i.e. Dom was defined as:
>
> Dome(D: S): with ...
>
> ?
>
> There is no checking of Join(categoryOf(%), T) actually refines S (so it
> is somewhat unsafe, but at least it should work.

I think it is safe in the sense that to actually use conditional
export you need to create appropriate domains. My impression
is that checks done at creation time prevents using incorrect
constructs. However, even if this impression is correct it
would be better to reject wrong constructs early, rather
than compiling wrong code which can not be correctly called.

> Ralf
>
> PS: The documentation for "minPoly is questionable.
> 1) Always returning the zero polynomial would perfectly match the
> specification.
> 2) Nothing says that the returned polynomial has minimal degree.
> 3) Nothing says that a *non-zero* polynomial exists (and in general
> domains it certainly doesn't).

AFAICS for transcendental kernels 'minPoly' returns linear
polynomial. But returning 0 probably would be good enough.
Anyway, I am not sure if I want to comit to always
returning nonzero result.

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Waldek Hebisch

unread,
Dec 19, 2011, 10:54:12 AM12/19/11
to fricas...@googlegroups.com
Ralf Hemmecke wrote:
>
> Another status update.
>
> I'm near to complete a fix to ax.boot.
>
<snip>

I am affraid that indeed FriCAS does not store conditions in
export lists of default packages. I remember a place in
compiler which essentialy throws away all such conditions,
and it seems that this is want gets stored. I tried to
keep conditions, but currently this is too complicated
for Spad compiler. Throwing away conditions is causing some
problems, but they are handled (partialy ...) in a special way.

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Ralf Hemmecke

unread,
Dec 31, 2011, 1:58:14 PM12/31/11
to fricas...@googlegroups.com
Success! Fixed FriCAS-Aldor-Interface again! Please test!

> I am affraid that indeed FriCAS does not store conditions in
> export lists of default packages.

OK. I took the old machinery for this case.

And wrt
http://groups.google.com/group/fricas-devel/browse_thread/thread/37ac49e7eea7fe59?hl=en
I simply used

SUBLISLIS($FormalMapVariableList, $TriangleVariableList, argtypes)

to translate the |t#i| arguments into |#i|.

I've pushed a few patches to the fix-aldor-interface branch on my github
account.

https://github.com/hemmecke/fricas/tree/fix-aldor-interface

Look at the complete differences here:
https://github.com/hemmecke/fricas/compare/fix-aldor-interface

I'll probably add a few more comments before I'll commit it to the SVN
trunk, but I wanted to make the fix available in 2011. ;-)

The basic idea is for something like

HomogeneousAggregate(S:Type): Category == Aggregate with

if S has SetCategory then
if S has Evalable S then Evalable S
...

ax.boot will now produce

(|If| (|Test| (|Has| |#1| |SetCategory|))
(|If| (|Test|
(|Has| |#1|
(|Apply| |Evalable|
(|PretendTo| |#1| |SetCategory|))))
(|Apply| |Evalable|
(|PretendTo| |#1|

(|With|
(|Apply| |Join|


(|Apply| |Evalable| (|PretendTo| |#1| |SetCategory|))

|SetCategory|)
NIL)))
NIL)
NIL)

in other words

if S has SetCategory then
if S has Evalable(S pretend SetCategory) then

Evalable(S pretend Join(
Evalable(S pretend SetCategory),
SetCategory
)
)

If we had S:T instead of the special S:Type from aboe, the type T would
be joined appropriately, i.e. you would see Join(SetCategory, T) instead
of just SetCategory inside the |PretendTo|.

Please test whether a build with --enable-aldor works for you.

Waldek, I'll add a few more comments to ax.boot and then commit the
series. Are you OK with that?

Ralf

PS:
Here is the log for the respective commits.

commit 6ffaf7f850caf532e955e7a3b8a95e2105562f25
Author: Ralf Hemmecke <ra...@hemmecke.de>
Date: Sat Dec 31 00:27:30 2011 +0100

fix aldor-interface

commit 07e6ab9c2ff0744765dc7f2a4c29d7737b8ebe71
Author: Ralf Hemmecke <ra...@hemmecke.de>
Date: Wed Nov 23 22:04:41 2011 +0100

enable Matrix over SemiRng+AbelianMonoid

commit 47e3343112cef23c0c94118c00687986c8cbd191
Author: Ralf Hemmecke <ra...@hemmecke.de>
Date: Wed Nov 23 10:41:50 2011 +0100

remove "r"::Symbol from type

The translation in src/interp/ax.boot can currently not cope with
UnivariatePolynomial("r"::Sy, FI)
It will be wrongly translated into something involving "Enumeration".
The compilation for libaldor.al then aborts with

"ap/CKP.ap", line 28:
(|Apply| |::| (|Apply| |Enumeration| |r|) |Symbol|)
..................^
[L28 C19] #1 (Error) There are no suitable meanings for the
operator `::'.

The translation into an Enumeration type is clearly wrong here.

Removing the need for an explicit name of the polynomial variable
seems to
be appropriate even without the above bug in ax.boot.

commit 3144e92659cbedc1aa6186f9e74bfb0116bdc92f
Author: Ralf Hemmecke <ra...@hemmecke.de>
Date: Sun Nov 20 23:37:57 2011 +0100

fix argument order in jet package (JGB)

Aldor requires that dependency of arguments is "increasing".

commit 3fd1f4bb883fa617b9469831f3bb8b765b359094
Author: Ralf Hemmecke <ra...@hemmecke.de>
Date: Sat Dec 31 16:14:23 2011 +0100

enable configuration of local aldor source files

If a checkout of trunk (revision 23) of the Aldor SVN repository is in
directory D then "configure --enable-aldor=$D" will take the necessary
sourcefiles from this directory instead of contacting the Internet.

commit 9c0c639c91e77624887b12deb31f3cff397a04d4
Author: Ralf Hemmecke <ra...@hemmecke.de>
Date: Sat Dec 31 14:37:22 2011 +0100

allow ALDORSOURCE in local file system

This allows for "make ALDORSOURCE=$HOME/path/to/aldor-trunk" in order
to build libaldor.al and use the necessary .as files from the local
file system.


Bill Page

unread,
Dec 31, 2011, 7:10:03 PM12/31/11
to fricas...@googlegroups.com
Thank you Ralf !!

I retrieved your modified branch with the command:

$ git clone https://github.com/hemmecke/fricas.git -b fix-aldor-interface

Then configured using your new local Aldor source option:

$ mkdir fricas-build
$ cd fricas-build
$ ../fricas/configure --with-lisp=sbcl --enable-aldor=$HOME/aldor-src

The build:

$ make -j4

Install

$ su
$ make install

Running produces:

wspage@intel:~> fricas
Checking for foreign routines
AXIOM="/usr/local/lib/fricas/target/x86_64-suse-linux"
spad-lib="/usr/local/lib/fricas/target/x86_64-suse-linux/lib/libspad.so"
foreign routines found
STYLE-WARNING: Undefined alien: "gmp_wrap_sb_isqrt"
STYLE-WARNING: Undefined alien: "gmp_wrap_sb_mul"
STYLE-WARNING: Undefined alien: "gmp_wrap_sb_gcd"
STYLE-WARNING: Undefined alien: "gmp_wrap_sb_div_rem"
STYLE-WARNING: Undefined alien: "gmp_wrap_sb_isqrt"
STYLE-WARNING: Undefined alien: "gmp_wrap_sb_mul"
STYLE-WARNING: Undefined alien: "gmp_wrap_sb_gcd"
STYLE-WARNING: Undefined alien: "gmp_wrap_sb_div_rem"
openServer result 0
FriCAS (AXIOM fork) Computer Algebra System
Version: FriCAS 2011-12-12
Timestamp: Saturday December 31, 2011 at 18:22:07
-----------------------------------------------------------------------------
Issue )copyright to view copyright notices.
Issue )summary for a summary of useful system commands.
Issue )quit to leave FriCAS and return to shell.
-----------------------------------------------------------------------------


(1) -> (HyperDoc) Cannot load font
-adobe-courier-medium-r-normal--18-*-*-*-m-*-iso8859-1 ; using
default.
(HyperDoc) Cannot load font
-adobe-courier-medium-r-normal--18-*-*-*-m-*-iso8859-1 ; using
default.
(HyperDoc) Cannot load font
-adobe-courier-medium-r-normal--18-*-*-*-m-*-iso8859-1 ; using
default.
(HyperDoc) Cannot load font
-adobe-courier-bold-r-normal--18-*-*-*-m-*-iso8859-1 ; using default.
(HyperDoc) Cannot load font
-adobe-courier-bold-o-normal--18-*-*-*-m-*-iso8859-1 ; using default.
(HyperDoc) Cannot load font
-adobe-courier-medium-o-normal--18-*-*-*-m-*-iso8859-1 ; using
default.
(HyperDoc) Cannot load font
-adobe-courier-bold-r-normal--18-*-*-*-m-*-iso8859-1 ; using default.

---

Should I be concerned about the STYLE-WARNING messages on start up?

I thought the hyperdoc "Cannot load font" messages had disappeared but
now I see them again. I am not sure why.

Everything seems ok.

As a perhaps a somewhat difficult test I tried the Aldor source at:

http://axiom-wiki.newsynthesis.org/SandBoxAldorJoinAndMeet

It compiles fine and returns the same results as shown on this page
except for this case:

(1) -> f$DM12

>> System error:
The value
#1=#(0
#2=(#
. #3=(#S(FOAM-USER::|Struct-runtime-51|
:|rtAssertMessage-0| (# . #3#)
:|dbgPaused?-1| NIL
:|rtDebugPaused!-2| (# . #3#)
:|rtDebugPaused?-3| (# . #3#)
:|rtDebugStep-4| (# . #3#)
:|rtDebugCall-5| (# . #3#)
:|rtDebugCatch-6| (# . #3#)
:|rtDebugThrow-7| (# . #3#)
:|rtDebugAssign-8| (# . #3#)
:|rtDebugExit-9| (# . #3#)
:|rtDebugReturn-10| (# . #3#)
:|rtDebugInside-11| (# . #3#)
:|rtDebugEnter-12| (# . #3#)
:|rtDebugInit-13| (# . #3#)
:|rtDoDebug-14| (# . #3#)
:|rtSingleParamNameFn-15| (# . #3#)
:|rtConstNameFn-16| (# . #3#)
:|namePartFrString-17| (# . #3#)
:|namePartFrOther-18| (# . #3#)
:|namePartConcat-19| (# . #3#)
:|rtLazyDomFrInit-20| (# . #3#)
:|rtLazyCatFrInit-21| (# . #3#)
:|rtDelayedGetExport!-22| (# . #3#)
:|rtDelayedInit!-23| (# . #3#)
:|rtCacheDynamicAdd-24| (# . #3#)
:|rtCacheDynamicCheck-25| (# . #3#)
:|rtCacheDynamicMake-26| (# . #3#)
:|rtCacheAdd-27| (# . #3#)
:|rtCacheCheck-28| (# . #3#)
:|rtCacheExplicitMake-29| (# . #3#)
:|rtCacheMake-30| (# . #3#)
:|domainPrepare!-31| (# . #3#)
:|rtAddStrings-32| (# . #3#)
:|rtConstSIntFn-33| (# . #3#)
:|lazyForceImport-34| (# . #3#)
:|lazyGetExport!-35| (# . #3#)
:|extendFill!-36| (# . #3#)
:|extendMake-37| (# . #3#)
:|noOperation-38| (# . #3#)
:|categoryFill!-39| (# . #3#)
:|categoryMakeDummy-40| (# . #3#)
:|categoryName-41| (# . #3#)
:|categoryBuild-42| (# . #3#)
:|categoryMake-43| (# . #3#)
:|categoryAddExports!-44| (# . #3#)
:|categoryAddNameFn!-45| (# . #3#)
:|categoryAddParents!-46| (# . #3#)
:|domainFill!-47| (# . #3#)
:|domainMakeDummy-48| (# . #3#)
:|domainName-49| (# . #3#)
:|domainHash!-50| (# . #3#)
:|domainTestExport!-51| (# . #3#)
:|domainGetExport!-52| (# . #3#)
:|domainAddNameFn!-53| (# . #3#)
:|domainAddHash!-54| (# . #3#)
:|domainAddParents!-55| (# . #3#)
:|domainAddDefaults!-56| (# . #3#)
:|domainAddExports!-57| (# . #3#)
:|domainMakeDispatch-58| (# . #3#)
:|domainMake-59| (# . #3#)
:PRINT-60 (# . #3#)
:|box-61| (1)
:|ddv-62| #(0 #4=(# . #3#) NIL #5=(# . #3#) #6=(# . #3#)
#7=(# . #3#))
:|edv-63| #(0 #8=(# . #3#) NIL #9=(# . #3#) #10=(# . #3#)
#11=(# . #3#))
:|adv-64| #1#
:|inheritToDummy-65| #7#
:|hashDummy-66| #6#
:|getDummy-67| #5#
:|nameDummy-68| #4#
:|inheritToExtend-69| #11#
:|nameExtend-70| #8#
:|hashExtend-71| #10#
:|getExtend-72| #9#
:|inheritTo-73| #12=(# . #3#)
:|name-74| #2#
:|hash-75| #13=(# . #3#)
:|get-76| #14=(# . #3#)
:|domainStdName-77| (# . #3#)
:|serialThis-78| 14
:|inheritTo-79| #15=(# . #3#)
:|get-80| #16=(# . #3#)
:|domHash-81| #17=(# . #3#)
:|name-82| #18=(# . #3#)
:|pdv-83| #(0 #18# NIL #16# #17# #15#)
:|ddv-84| NIL
:|dv-85| #(10 #19=(# . #3#) NIL #20=(# . #3#) #21=(# . #3#)
#22=(# . #3#) #23=(# . #3#) #24=(# . #3#))
:|parentCountDummy-86| (# . #3#)
:|parentGetDummy-87| (# . #3#)
:|hashDummy-88| (# . #3#)
:|getDummy-89| (# . #3#)
:|buildDummy-90| (# . #3#)
:|nameDummy-91| (# . #3#)
:|parentGet-92| #24#
:|parentCount0-93| #23#
:|hash0-94| #21#
:|get0-95| #20#
:|build0-96| #22#
:|name0-97| #19#
:|parentGet-98| (# . #3#)
:|parentCount0-99| (# . #3#)
:|hash0-100| (# . #3#)
:|get0-101| (# . #3#)
:|build0-102| (# . #3#)
:|name0-103| (# . #3#)
:|pcdv-104| NIL
:|codes-105| (51492427 200121 318525310 306472243 749482564
766522704 585283853 206475020 318069373
301553003 357262396 318528389 113320568
51509389 477900237 318266229 318461307
55906833 680872954 200103 200090 5509732
318204816 318396813 200102 865800279 200089
143562022 715582562 51492941 682776373
352145423 200076 25941349 770345191 318266239
200101 44638651 506619364 287357190 76356179
200086 51500205 9730346 632239194 783695654
200084 200083 581887332 495481649 51488814
200143 200145 200144 51482908)
:|names-106| ("<=%
(1) ->

--

The printing of this error message seems to be terminated early.

I am not sure yet why this result differs from an old version of
FriCAS and the Aldor interface.

Regards,
Bill Page.

Bill Page

unread,
Jan 1, 2012, 1:02:11 PM1/1/12
to fricas...@googlegroups.com
Ralf,

Here is a simple example of the problem I reported yesterday.

FriCAS (AXIOM fork) Computer Algebra System
Version: FriCAS 2011-12-12
Timestamp: Saturday December 31, 2011 at 18:22:07
-----------------------------------------------------------------------------
Issue )copyright to view copyright notices.
Issue )summary for a summary of useful system commands.
Issue )quit to leave FriCAS and return to shell.
-----------------------------------------------------------------------------


(1) -> )sys cat simple.as
-- simple.as:
#include "axiom"
#pile

dd1: with
f: ()->Integer
== add
f():Integer == 1
--
(1) -> )co simple.as
Compiling FriCAS source code from file /home/wspage/simple.as using
AXIOM-XL compiler and options
-O -Fasy -Fao -Flsp -laxiom -Mno-ALDOR_W_WillObsolete -DAxiom -Y
$AXIOM/algebra -I $AXIOM/algebra
Use the system command )set compiler args to change these
options.
Compiling Lisp source code from file ./simple.lsp
Issuing )library command for simple
Reading /home/wspage/simple.asy
dd1 is now explicitly exposed in frame frame1
dd1 will be automatically loaded when needed from
/home/wspage/simple
(1) -> )sh dd1
dd1 is a domain constructor
Abbreviation for dd1 is DD1
This constructor is exposed in this frame.
------------------------------- Operations --------------------------------

(1) -> f()$dd1

:|box-61| (NIL)
:|ddv-62| NIL
:|edv-63| NIL
:|adv-64| #1#
:|inheritToDummy-65| (# . #3#)
:|hashDummy-66| (# . #3#)
:|getDummy-67| (# . #3#)
:|nameDummy-68| (# . #3#)
:|inheritToExtend-69| (# . #3#)
:|nameExtend-70| (# . #3#)
:|hashExtend-71| (# . #3#)
:|getExtend-72| (# . #3#)
:|inheritTo-73| #4=(# . #3#)
:|name-74| #2#
:|hash-75| #5=(# . #3#)
:|get-76| #6=(# . #3#)


:|domainStdName-77| (# . #3#)
:|serialThis-78| 1

:|inheritTo-79| (# . #3#)
:|get-80| (# . #3#)
:|domHash-81| (# . #3#)
:|name-82| (# . #3#)
:|pdv-83| NIL
:|ddv-84| NIL
:|dv-85| NIL


:|parentCountDummy-86| (# . #3#)
:|parentGetDummy-87| (# . #3#)
:|hashDummy-88| (# . #3#)
:|getDummy-89| (# . #3#)
:|buildDummy-90| (# . #3#)
:|nameDummy-91| (# . #3#)

:|parentGet-92| (# . #3#)
:|parentCount0-93| (# . #3#)
:|hash0-94| (# . #3#)
:|get0-95| (# . #3#)
:|build0-96| (# . #3#)
:|name0-97| (# . #3#)


:|parentGet-98| (# . #3#)
:|parentCount0-99| (# . #3#)
:|hash0-100| (# . #3#)
:|get0-101| (# . #3#)
:|build0-102| (# . #3#)
:|name0-103| (# . #3#)
:|pcdv-104| NIL

:|codes-105| (200143 51482908)
:|names-106| ("ff type
LIST.

(1) ->

Regards,
Bill Page.

On Sat, Dec 31, 2011 at 1:58 PM, Ralf Hemmecke <ra...@hemmecke.de> wrote:

> Success! Fixed FriCAS-Aldor-Interface again! Please test!
>

> ...

Ralf Hemmecke

unread,
Jan 1, 2012, 6:44:28 PM1/1/12
to fricas...@googlegroups.com
> wspage@intel:~> fricas
> Checking for foreign routines
> AXIOM="/usr/local/lib/fricas/target/x86_64-suse-linux"
> spad-lib="/usr/local/lib/fricas/target/x86_64-suse-linux/lib/libspad.so"
> foreign routines found
> STYLE-WARNING: Undefined alien: "gmp_wrap_sb_isqrt"
> STYLE-WARNING: Undefined alien: "gmp_wrap_sb_mul"
> STYLE-WARNING: Undefined alien: "gmp_wrap_sb_gcd"
> STYLE-WARNING: Undefined alien: "gmp_wrap_sb_div_rem"
> STYLE-WARNING: Undefined alien: "gmp_wrap_sb_isqrt"
> STYLE-WARNING: Undefined alien: "gmp_wrap_sb_mul"
> STYLE-WARNING: Undefined alien: "gmp_wrap_sb_gcd"
> STYLE-WARNING: Undefined alien: "gmp_wrap_sb_div_rem"
> openServer result 0

> Should I be concerned about the STYLE-WARNING messages on start up?

No probably not. I get them too.
See
http://groups.google.com/group/fricas-devel/browse_thread/thread/5e51a28742cc658d/b33462f4dddd0516#b33462f4dddd0516

> I thought the hyperdoc "Cannot load font" messages had disappeared but


> now I see them again. I am not sure why.

I got similar messages. But since I am now running on a new laptop, I
thought that was because I do not yet have installed everything correctly.

Ralf

Ralf Hemmecke

unread,
Jan 1, 2012, 6:55:42 PM1/1/12
to fricas...@googlegroups.com
Thank you Bill for testing.

> Here is a simple example of the problem I reported yesterday.

> -- simple.as:


> #include "axiom"
> #pile
>
> dd1: with
> f: ()->Integer
> == add
> f():Integer == 1

I can reproduce this error that you've reported. I'll check revision
1036. (I think that was the version up to which the aldor-interface
compiled.)

I have some suspicion that there also might be a problem with 32bit vs
64bit. More about that when I find more time to work on the issue.

Ralf


Bill Page

unread,
Jan 1, 2012, 7:02:11 PM1/1/12
to fricas...@googlegroups.com
Found this:

http://enteropia.wordpress.com/2011/04/29/hyperdoc-fonts-problem-in-ubuntu-11-04/

"To solve the problem one should actually install these fonts. I’m not
sure where are they exactly, but installing the following packages
helps:

xfonts-100dpi
xfonts-75dpi"

---

But I don't know how to do this on Open SuSE 11.4

Regards,
Bill Page.


On Sun, Jan 1, 2012 at 6:44 PM, Ralf Hemmecke <ra...@hemmecke.de> wrote:
> ...

Ralf Hemmecke

unread,
Jan 1, 2012, 7:33:50 PM1/1/12
to fricas...@googlegroups.com
> xfonts-100dpi
> xfonts-75dpi

Super! Thanks. After installing and restarting the X server, HyperDoc
works with a proper font again.

Ralf

Waldek Hebisch

unread,
Jan 4, 2012, 12:18:01 PM1/4/12
to fricas...@googlegroups.com

Generaly looks OK. However, in axFormatOp (in ax.boot) original
version treated both branches of 'If' in symmetric way. Your
new version is asymmetric. Why?

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Ralf Hemmecke

unread,
Jan 4, 2012, 1:51:45 PM1/4/12
to fricas...@googlegroups.com
> Generaly looks OK. However, in axFormatOp (in ax.boot) original
> version treated both branches of 'If' in symmetric way. Your
> new version is asymmetric. Why?

Because it is assymetric! In

if X has T then A else B

the B branch would not have to augment X with type T.
Note that I collect all the T that appear in a "has" construction.

It was not a problem in the original $pretendFlag-Version, because
there, the T would have been ignored for both branches.

A problem would be something of the form

if not(X has T) then A else B

but the has construction is very special anyway. Maybe any logical
connectives that involve "X has T" inside a "if" condition should be
forbidden.

For example, one cannot sensibly augment the type of X inside A in a
construction like

if X has T or prime? p then A else B

(Well, "and" could be allowed and transformed into multiple if's.)

I'm going to work on more documentation tonight. And also on the issue
that Bill reported.

Ralf

Ralf Hemmecke

unread,
Jan 4, 2012, 5:51:29 PM1/4/12
to fricas...@googlegroups.com
Hallo,

The problem that Bill mentioned in
http://groups.google.com/group/fricas-devel/browse_thread/thread/c7d1c908a07758d2#2986bcb34b99282b
is not connected to my fix of the aldor-interface.

We know that commit 258a341a38cd10232a0e62c47369926a2f8960d7 (r1036)
compiles fine and also

-- simple.as:
#include "axiom"
#pile

dd1: with
f: ()->Integer
== add
f():Integer == 1

------------------

compiles fine with r1036. Calling f() correctly gives 1.

Now look at the branch ai-test-bootsys at
https://github.com/hemmecke/fricas/commit/15c1c188713748d81d1fe0d5a647a1f1203a3dee
It is basically r1037 with two fixes that make it actually compile
libaxiom.al.

It leads to the same problem that Bill mentioned.

Waldek, do you have an idea where I can start looking deeper?

It seems that again I have to compile some files with depsys and some
with bootsys. I remember that last time I did it, it took quite a long
time to figure out the problematic file. :-(

Ralf

=======================================================
git clone https://github.com/hemmecke/fricas.git -b ai-test-bootsys
cd fricas
configure --enable-aldor --prefix=$HOME/software
make -j8
make install
$HOME/software/bin/fricas

Checking for foreign routines
AXIOM="/home/hemmecke/software/lib/fricas/target/x86_64-unknown-linux"
spad-lib="/home/hemmecke/software/lib/fricas/target/x86_64-unknown-linux/lib/libspad.so"
foreign routines found
STYLE-WARNING: Undefined alien: "gmp_sb_isqrt"
STYLE-WARNING: Undefined alien: "gmp_sb_mul"
STYLE-WARNING: Undefined alien: "gmp_sb_gcd"
STYLE-WARNING: Undefined alien: "gmp_sb_div_rem"
STYLE-WARNING: Undefined alien: "gmp_sb_isqrt"
STYLE-WARNING: Undefined alien: "gmp_sb_mul"
STYLE-WARNING: Undefined alien: "gmp_sb_gcd"
STYLE-WARNING: Undefined alien: "gmp_sb_div_rem"
openServer result 0


FriCAS (AXIOM fork) Computer Algebra System

Version: FriCAS 15c1c188713748d81d1fe0d5a647a1f1203a3dee
Timestamp: Wednesday January 4, 2012 at 22:43:32


-----------------------------------------------------------------------------
Issue )copyright to view copyright notices.
Issue )summary for a summary of useful system commands.
Issue )quit to leave FriCAS and return to shell.
-----------------------------------------------------------------------------

(1) -> )co simple.as
Compiling FriCAS source code from file

/home/hemmecke/scratch/simple.as using AXIOM-XL compiler and


options
-O -Fasy -Fao -Flsp -laxiom -Mno-ALDOR_W_WillObsolete -DAxiom -Y
$AXIOM/algebra -I $AXIOM/algebra
Use the system command )set compiler args to change these
options.
Compiling Lisp source code from file ./simple.lsp
Issuing )library command for simple

Reading /home/hemmecke/scratch/simple.asy


dd1 is now explicitly exposed in frame frame1
dd1 will be automatically loaded when needed from

/home/hemmecke/scratch/simple
(1) -> f()

:|table-107| (# . #3#)
:|primes-108| #(32 32
#(2 3 7 13 31 61 127 251 509 1021
2039 4093
8191 16381 32749 65521 131071 262139
524287 1048573 2097143 4194301
8388593
16777213 33554393 67108859 134217689
268435399 536870909 1073741789
2147483647
-5)))
NIL))
NIL #6# #5# #4#)
is not of type
LIST.

Ralf Hemmecke

unread,
Jan 5, 2012, 10:38:28 AM1/5/12
to fricas...@googlegroups.com, Waldek Hebisch
Hi Waldek,

just a short note. Last night I've found out that the problematic file
is src/interp/interop.boot. When I compile this file in my test-bootsys
branch (i.e basically this is r1037 with small fixes to make libaxiom.al
compile) by using depsys (other files with bootsys) then Bill's problem
does not appear. Compiling it with bootsys, leads to the error.

So there must be something strange in the generated interop.clisp file.
My understanding of LISP is however not so well established that I would
be able to compare the two files.

Some hints are very much appreciated.

The only thing, I've realized is that the order of ELT and CAR is
exchanged between depsys and bootsys. Is this correct?

Ralf

=== with depsys ===
(DEFUN |devaluate| (|d|)
(PROG (|d'| |ISTMP#1|)
(RETURN
(COND
((|isDomain| |d|)
(|DNameToSExpr| (SPADCALL (CDR |d|) (ELT (CAR |d|) 1))))
((NULL (REFVECP |d|)) |d|)
((AND (QSGREATERP (QVSIZE |d|) 5)
(PROGN
(SPADLET |ISTMP#1| (QREFELT |d| 3))
(AND (PAIRP |ISTMP#1|) (EQ (QCDR |ISTMP#1|) NIL)
(EQ (QCAR |ISTMP#1|) '|Category|))))
(QREFELT |d| 0))
((QSGREATERP (QVSIZE |d|) 0) (SPADLET |d'| (QREFELT |d| 0))
(COND ((|isFunctor| |d'|) |d'|) (#1='T |d|)))
(#1# |d|)))))

=== with bootsys ===
(DEFUN |devaluate| (|d|)
(PROG (|ISTMP#1| |d'|)
(RETURN
(COND
((|isDomain| |d|)
(|DNameToSExpr| (SPADCALL (CDR |d|) (CAR (ELT |d| 1)))))
((NULL (REFVECP |d|)) |d|)
((AND (QSGREATERP (QVSIZE |d|) 5)
(PROGN
(SETQ |ISTMP#1| (QREFELT |d| 3))
(AND (CONSP |ISTMP#1|) (EQ (CDR |ISTMP#1|) NIL)
(EQ (CAR |ISTMP#1|) '|Category|))))
(QREFELT |d| 0))
((QSGREATERP (QVSIZE |d|) 0)
(PROGN
(SETQ |d'| (QREFELT |d| 0))
(COND ((|isFunctor| |d'|) |d'|) (#1='T |d|))))
(#1# |d|)))))

bootsys-interpo.clisp
depsys-interpo.clisp

Waldek Hebisch

unread,
Jan 5, 2012, 11:11:07 AM1/5/12
to fricas...@googlegroups.com

The error message alone gives too little information. Backtrace
typically gives more information -- sometimes it is possible
to identify routine containing error, in other cases it
may give good start point for tracing.

If I had to guess the first suspect is 'interop.boot', but
IME guesses usually are wrong...

BTW: given about 100 files in 'src/interp' binary search
needs about 7 iterations. On my machine build needs
slightly more than 7 minutes, so the whole thing is
doable in about 1-2 hours. Most of bugs needs more time...

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Waldek Hebisch

unread,
Jan 5, 2012, 11:18:01 AM1/5/12
to fricas...@googlegroups.com
Ralf Hemmecke wrote:
>
> Hi Waldek,
>
> just a short note. Last night I've found out that the problematic file
> is src/interp/interop.boot. When I compile this file in my test-bootsys
> branch (i.e basically this is r1037 with small fixes to make libaxiom.al
> compile) by using depsys (other files with bootsys) then Bill's problem
> does not appear. Compiling it with bootsys, leads to the error.
>
> So there must be something strange in the generated interop.clisp file.
> My understanding of LISP is however not so well established that I would
> be able to compare the two files.
>
> Some hints are very much appreciated.
>
> The only thing, I've realized is that the order of ELT and CAR is
> exchanged between depsys and bootsys. Is this correct?
>

Looking at 'devaluate' I see a problem:

devaluate(d) ==
isDomain d =>
-- ?need a shortcut for old domains
-- ELT(CAR d, 0) = 'oldAxiomDomain => ...
-- FIXP(ELT(CAR d,0)) => d
DNameToSExpr(SPADCALL(CDR d,CAR(d).1))
^^^^^^^^
problem
not REFVECP d => d
QSGREATERP(QVSIZE d,5) and QREFELT(d,3) is ['Category] => QREFELT(d,0)
QSGREATERP(QVSIZE d,0) =>
d':=QREFELT(d,0)
isFunctor d' => d'
d
d

This is know syntactic difference between old Boot and Shoe,
try replacing this by '(CAR(d)).1' to force correct precedence.

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Ralf Hemmecke

unread,
Jan 5, 2012, 11:19:16 AM1/5/12
to fricas...@googlegroups.com
> If I had to guess the first suspect is 'interop.boot', but
> IME guesses usually are wrong...

You hit it without running make. Well done!

> The error message alone gives too little information. Backtrace
> typically gives more information -- sometimes it is possible
> to identify routine containing error, in other cases it
> may give good start point for tracing.

Backtrace? How?

And how to start tracing? By using ")trace some-func"?
Now which function to trace is the question.

Looks like I will become a lisp expert after that. ;-)

Ralf

Ralf Hemmecke

unread,
Jan 5, 2012, 11:24:13 AM1/5/12
to fricas...@googlegroups.com
> This is know syntactic difference between old Boot and Shoe,
> try replacing this by '(CAR(d)).1' to force correct precedence.

Ah, good. I'll try that tonight.

Waldek, Just for curiosity, where can I find the actual definition of
ELT. With grep I was unable to find it.

Ralf

Waldek Hebisch

unread,
Jan 5, 2012, 11:25:00 AM1/5/12
to fricas...@googlegroups.com
Ralf Hemmecke wrote:
>
> > The error message alone gives too little information. Backtrace
> > typically gives more information -- sometimes it is possible
> > to identify routine containing error, in other cases it
> > may give good start point for tracing.
>
> Backtrace? How?

)set break break

Run program up to error -- you will be thrown int Lisp debugger.
Then:

backtrace

>
> And how to start tracing? By using ")trace some-func"?
> Now which function to trace is the question.

At Lisp level (which usually works better for Boot functions
than FriCAS trace):

)lisp (trace |devaluate|)

Lisp by default upcases names, so Boot name goes in bars.
Onece done:

)lisp (untrace |devaluate|)

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Waldek Hebisch

unread,
Jan 5, 2012, 11:29:05 AM1/5/12
to fricas...@googlegroups.com
ELT is part of Common Lisp:

http://www.lispworks.com/documentation/HyperSpec/Body/f_elt.htm#elt

ELT is 0 based.

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Ralf Hemmecke

unread,
Jan 5, 2012, 11:31:38 AM1/5/12
to fricas...@googlegroups.com
> DNameToSExpr(SPADCALL(CDR d,CAR(d).1))
> ^^^^^^^^
> problem

> This is know syntactic difference between old Boot and Shoe,
> try replacing this by '(CAR(d)).1' to force correct precedence.

BTW, are you saying that in Shoe the . binds stronger than (prefix)
function application?

Since in SPAD I would expect car(d).1 to be equivalent to (car d).1, I
think that should also be the case for SHOE. (OK, that doesn't have
priority (since there are too view people working with boot/shoe), but
still I think that having the precedence like car(d.1) is confusing.

Ralf

Bill Page

unread,
Jan 5, 2012, 1:42:56 PM1/5/12
to fricas...@googlegroups.com
Thanks Ralf and Waldek!

I can confirm that the precedence change in the BOOT language
identified by Waldek - when applied to all relevant cases of dot
following parenthesis, i.e. xxx).yyy in interop.boot - does in fact
solve the problem that I reported earlier.

I've attached a patch which also cleans up most of the CAR and CDR
lisp-isms in this code at the same time.

interop.patch

Ralf Hemmecke

unread,
Jan 5, 2012, 2:05:28 PM1/5/12
to fricas...@googlegroups.com
> DNameToSExpr(SPADCALL(CDR d,CAR(d).1))
> ^^^^^^^^
> problem

> This is know syntactic difference between old Boot and Shoe,
> try replacing this by '(CAR(d)).1' to force correct precedence.

Oh, maybe then also this is treated differently in SHOE.

$kind :=
pname.(MAXINDEX pname) = char '_& => 'x
DOWNCASE (PNAME kind).0

https://github.com/hemmecke/fricas/blob/master/src/interp/br-data.boot#L105

No, it doesn't, the respective lines via depsys as well as bootsys are.

(SETQ |$kind|
(COND
((EQUAL (ELT |pname| (MAXINDEX |pname|))
(|char| '&))
'|x|)
(#1# (DOWNCASE (ELT (PNAME |kind|) 0)))))

Is this because ther is a space after DOWNCASE or because there is
"PNAME kind" i.e. a function application instead of a single variable
inside the parentheses?

I hope it is not the space that makes the difference. What is the actual
rule for Shoe?

Ralf

Ralf Hemmecke

unread,
Jan 5, 2012, 8:56:51 PM1/5/12
to fricas...@googlegroups.com
Hello,

Now the aldor-interface seems to work again. I've just rebased my
commits on github and included the (CAR d).i fix. I've also added a few
more lines of documentation.

The following should work.

git clone https://github.com/hemmecke/fricas.git -b fix-aldor-interface


cd fricas
configure --enable-aldor --prefix=$HOME/software
make -j8
make install
$HOME/software/bin/fricas

If I don't hear anything negative, I will commit to trunk in about 12 hours.

Ralf

PS: Bill, I haven't applied your patch, because I wanted to separate
issues, i.e. "fixing a regression bug" vs. "making a .boot file less
lispish".

On 01/04/2012 06:18 PM, Waldek Hebisch wrote:
> Ralf Hemmecke wrote:
>>
>> Success! Fixed FriCAS-Aldor-Interface again! Please test!

>> Please test whether a build with --enable-aldor works for you.

Bill Page

unread,
Jan 5, 2012, 10:16:19 PM1/5/12
to fricas...@googlegroups.com
Ralf,

Thanks for your work on this.

Re: Fixing lisp-ish boot. Your choice. Maybe we'll find time to do it
some day, eh?

I took a quick look for other suspicious cases of ). in the boot code.
I found this one:

+411 src/interp/category.boot

PrinAncb:= first(b).(4)

This is probably correct but it seems crazy to write it this way if
you really mean

PrinAncb:= first(b.4)

Sometimes you really have to wonder what they were smoking back in the
lab ... ;)

Regards,
Bill.

Ralf Hemmecke

unread,
Jan 5, 2012, 10:45:21 PM1/5/12
to fricas...@googlegroups.com
> Re: Fixing lisp-ish boot. Your choice. Maybe we'll find time to do it
> some day, eh?

Well, I'm not against your patch, I just wanted to separate issues.
After I've committed to trunk, Waldek will probably allow you to commit
your patch. But maybe one should do it for all .boot files in one
commit, since it is basically just a syntactic thing.

> I took a quick look for other suspicious cases of ). in the boot code.
> I found this one:
>
> +411 src/interp/category.boot
>
> PrinAncb:= first(b).(4)
>
> This is probably correct but it seems crazy to write it this way if
> you really mean
>
> PrinAncb:= first(b.4)
>
> Sometimes you really have to wonder what they were smoking back in the
> lab ... ;)

Interesting

PrinAncb:= first(b).(4)

gives

with bootsys
(SETQ |PrinAncb| (CAR (ELT (|CatEval| |bname|) 4)))

with depsys
(SPADLET |PrinAncb| (CAR (ELT (|CatEval| |bname|) 4)))

Why is it basically the same here and makes a difference for "CAR(d).1".
I'm a bit confused now.

Ralf

Bill Page

unread,
Jan 5, 2012, 11:08:35 PM1/5/12
to fricas...@googlegroups.com
Ralf,

On Thu, Jan 5, 2012 at 10:45 PM, you wrote:
> Bill Page wrote:
>> Re: Fixing lisp-ish boot. Your choice. Maybe we'll find time to do it
>> some day, eh?
>
> Well, I'm not against your patch, I just wanted to separate issues. After
> I've committed to trunk, Waldek will probably allow you to commit your
> patch. But maybe one should do it for all .boot files in one commit, since
> it is basically just a syntactic thing.
>

You are right. But there is a lot of junk in these files and it is
hard to know what to worry about and clean up and what not. I suppose
that there is a valid argument that many of the uses of CAR, CDR, .0,
.1 etc. are actually in lieu of more meaningful data structure "access
functions". So just a syntactic substitution is not of much real
value. To do it right and improve the readability of the code one
should have to define some appropriately named macros or such. (I
think Gaby has gone in that direction in some OpenAxiom boot code.)
Still to my eyes the Lisp functions seemingly randomly mixed into the
Boot code is disturbing.

Regards,
Bill Page.

Bill Page

unread,
Jan 6, 2012, 11:52:19 AM1/6/12
to fricas...@googlegroups.com
Ralf,

To appreciate just how much effort Gaby has put into improving the
readability of Boot code in OpenAxiom it is very instructive to look
at JoinInner in both FriCAS and OpenAxiom. Just attempting to decode
how FriCAS actually ends up producing the output you show nearly
boggles my mind. But in OpenAxiom this same code is written as:

PrinAncb := categoryPrincipals CatEval(bname,$e)

If FriCAS does not soon adopt a similar approach I cannot imagine a good future.

But of course advocating is one thing, finding time, energy and help
to do it is another.

Regards,
Bill Page.

On Thu, Jan 5, 2012 at 10:45 PM, you wrote:

> Bill Page wroteL

Waldek Hebisch

unread,
Jan 6, 2012, 3:26:00 PM1/6/12
to fricas...@googlegroups.com
Bill Page wrote:
>
> To appreciate just how much effort Gaby has put into improving the
> readability of Boot code in OpenAxiom it is very instructive to look
> at JoinInner in both FriCAS and OpenAxiom. Just attempting to decode
> how FriCAS actually ends up producing the output you show nearly
> boggles my mind. But in OpenAxiom this same code is written as:
>
> PrinAncb := categoryPrincipals CatEval(bname,$e)
>
> If FriCAS does not soon adopt a similar approach I cannot imagine a good fu=
> ture.
>

Well, I agree that OpenAxiom code _looks_ better. You say
that 'attempting to decode how FriCAS actually ends up
producing the output' boggles your mind. However, have you
tried to understand what OpenAxiom is doing?

FYI FriCAS code was rewritten this summer and what it is
doing now is much simpler (and faster) than original version.
Actually original did crazy things and the only reason I
find for doing such things is that previous authors did
not fully understand what it is doing. AFAICS OpenAxiom
still contains at least part of original craziness.


--
Waldek Hebisch
heb...@math.uni.wroc.pl

Waldek Hebisch

unread,
Jan 6, 2012, 3:38:15 PM1/6/12
to fricas...@googlegroups.com
Ralf Hemmecke wrote:
>
> > Re: Fixing lisp-ish boot. Your choice. Maybe we'll find time to do it
> > some day, eh?
>
> Well, I'm not against your patch, I just wanted to separate issues.
> After I've committed to trunk, Waldek will probably allow you to commit
> your patch.

Yes Bill (after test).

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Bill Page

unread,
Jan 6, 2012, 3:44:04 PM1/6/12
to fricas...@googlegroups.com
Waldek,

On Fri, Jan 6, 2012 at 3:26 PM, you wrote:
>
> Well, I agree that OpenAxiom code _looks_ better.  You
> say that 'attempting to decode how FriCAS actually ends up
> producing the output' boggles your mind.  However, have you
> tried to understand what OpenAxiom is doing?
>

Yes - at least in this and a few other instances. In fact I've been
trying to do this for years now in all flavors of Axiom. I suppose it
comes down to a form of documentation - kind of the opposite of what
Tim Daly originally proposed for Axiom - readability of the code
versus coding from a document (literate programming). I think that is
what OpenAxiom is trying to do. I am encourage by Gaby's progress.

> FYI FriCAS code was rewritten this summer and what it is
> doing now is much simpler (and faster) than original version.

I am also aware of all the work that you have been doing to improve
FriCAS and it was certainly not my intention either directly or
indirectly to be critical. FriCAS still remains my main tool of
choice for computer algebra and I appreciate the hard work that you
are putting into it. My concern about the future has to do with the
total amount of effort for someone to get to the level of
understanding of the code to make substantial improvements.

> Actually original did crazy things and the only reason I
> find for doing such things is that previous authors did
> not fully understand what it is doing.  AFAICS OpenAxiom
> still contains at least part of original craziness.
>

I am sure you are correct. Improvement has to be an iterative process.
I should add the usual encouragement that more sharing of
understanding and methods would be beneficial to both projects.

Regards,
Bill Page.

Waldek Hebisch

unread,
Jan 6, 2012, 4:12:43 PM1/6/12
to fricas...@googlegroups.com
Ralf Hemmecke wrote:
>
> > I took a quick look for other suspicious cases of ). in the boot code.
> > I found this one:
> >
> > +411 src/interp/category.boot
> >
> > PrinAncb:= first(b).(4)
> >
> > This is probably correct but it seems crazy to write it this way if
> > you really mean
> >
> > PrinAncb:= first(b.4)
> >
> > Sometimes you really have to wonder what they were smoking back in the
> > lab ... ;)
>
> Interesting
>
> PrinAncb:= first(b).(4)
>
> gives
>
> with bootsys
> (SETQ |PrinAncb| (CAR (ELT (|CatEval| |bname|) 4)))
>
> with depsys
> (SPADLET |PrinAncb| (CAR (ELT (|CatEval| |bname|) 4)))
>
> Why is it basically the same here and makes a difference for "CAR(d).1".
> I'm a bit confused now.
>

Well, with depsys:

PrinAncb:= first(b).(4)

gives

(SPADLET |PrinAncb| (ELT (CAR |b|) 4))

while

PrinAncb:= first (b).(4)

gives

(SPADLET |PrinAncb| (CAR (ELT |b| 4)))

Namely, precedence depends on presence or absence of space: without
space application have higher precence than ., with space lower.

BTW: NAG version was:

PrinAncb:= first (CatEval bname).(4)

Later I noticed that we can just use 'b' instead of 'CatEval bname'
so I replaced it by

PrinAncb:= first (b).(4)

For uniform look I changed this to:

PrinAncb:= first(b).(4)

but otherwise I did not look to much at this. The change was
after switch to Shoe, so both versions had the same effect.

I must say that for me this example show how bad is practice
of ommiting parenthesis in function call with single argument
(note that with mandatory parenthesis there would be no question
of precedence -- call would always have higher precedence than '.').

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Ralf Hemmecke

unread,
Jan 6, 2012, 5:04:53 PM1/6/12
to fricas...@googlegroups.com
Just for the record...

---rhxBEGIN paren.as
#include "aldor"
#include "aldorio"
I ==> MachineInteger;
main(): () == {
import from I, List I, List List I;
ll: List List I := [[1,2,3],[4,5,6],[7,8,9]];
a := first ll.2;
b := first (ll).2;
c := first(ll).3;
stdout << "a = " << a << newline;
stdout << "b = " << b << newline;
stdout << "c = " << c << newline;
}
main()
---rhxEnd paren.as

aldor -laldor -fx paren.as
./paren
a = 4
b = 2
c = 3

Looks like parens force precedence of prefix function application over
the dot application.

I think, like in Fortress where

a+b * c

leads to an error because the spacing might be misleading for humans,
there should also be a warning (at least) in cases a and b.

Even case c is only clear if one knows just one language. But with all
the different languages around, it's like *int[], where a non-native C
programmer constantly has to look up precedence rules.

Ralf

Ralf Hemmecke

unread,
Jan 6, 2012, 7:03:08 PM1/6/12
to fricas...@googlegroups.com
For completeness...

---rhxBEGIN paren.spad
)abbrev package TMP Tmp
I ==> SingleInteger
Tmp(): with
foo: () -> List I
== add
foo(): List I ==
--import from I, List I, List List I;


ll: List List I := [[1,2,3],[4,5,6],[7,8,9]]
a := first ll.2
b := first (ll).2
c := first(ll).3

[a,b,c]
---rhxEND paren.spad

(3) -> foo()

(3) [4,4,3]
Type: List(SingleInteger)

SPAD decides upon a space while for Aldor the parentheses make the
difference.

So, Spad =!= Aldor as we all know. ;-)

Ralf

Bill Page

unread,
Jan 6, 2012, 7:05:48 PM1/6/12
to fricas...@googlegroups.com
On Fri, Jan 6, 2012 at 5:04 PM, Ralf Hemmecke wrote:
> ...
> [in Aldor]

>
> ll: List List I := [[1,2,3],[4,5,6],[7,8,9]];
> a := first ll.2;
> b := first (ll).2;
> c := first(ll).3;
> ...

> a = 4
> b = 2
> c = 3
>
> Looks like parens force precedence of prefix function application over the
> dot application.
>


The FriCAS interpreter seems to behave the same way as Aldor. This is
OK, but having first been told that . binds more tightly than function
application, I think the way Shoe compiles boot code is more
consistent. Apparently in Shoe space has no meaning except to delimit
names when necessary, parenthesis only affect grouping and function
application is always denoted by juxtaposition. This means that a, b,
and c all have the same meaning.

(1) -> )boot ll:=[[1,2,3],[4,5,6],[7,8,9]]

(EVAL-WHEN (EVAL LOAD)
(SETQ |ll| (LIST (LIST 1 2 3) (LIST 4 5 6) (LIST 7 8 9))))
Value = ((1 2 3) (4 5 6) (7 8 9))

(1) -> )boot a:=first ll.1

(EVAL-WHEN (EVAL LOAD) (SETQ |a| (CAR (ELT |ll| 1))))
Value = 4

(1) -> )boot b:=first (ll).1

(EVAL-WHEN (EVAL LOAD) (SETQ |b| (CAR (ELT |ll| 1))))
Value = 4

(1) -> )boot c:=first(ll).2

(EVAL-WHEN (EVAL LOAD) (SETQ |c| (CAR (ELT |ll| 2))))
Value = 7

Changing the meaning always requires the use of parenthesis for grouping:

(1) -> )boot d:=(first ll).2

(EVAL-WHEN (EVAL LOAD) (SETQ |d| (ELT (CAR |ll|) 2)))
Value = 3

Given that the use of parenthesis with unary operators is optional, I
rather like it this way.

Now it seems annoying that Spad has yet another way of parsing this, see (2):

(1) -> )sys cat paren.spad
--- paren.spad
)abbrev domain MAIN main
I ==> Integer
main(): with
a:()->I
b:()->I
c:()->I
== add


ll: List List I := [[1,2,3],[4,5,6],[7,8,9]]

a() == first ll.2
b() == first (ll).2
c() == first(ll).3
---
(1) -> )co paren.spad
Compiling FriCAS source code from file /home/wspage/paren.spad using
old system compiler.
...
main is now explicitly exposed in frame frame1
main will be automatically loaded when needed from
/home/wspage/MAIN.NRLIB/MAIN

(1) -> a()

(1) 4
Type: PositiveInteger
(2) -> b()

(2) 4
Type: PositiveInteger
(3) -> c()

(3) 3
Type: PositiveInteger
(4) ->


> On 01/06/2012 10:12 PM, Waldek Hebisch wrote:

>> ...


>> I must say that for me this example show how bad is practice

>> of omiting parenthesis in function call with single argument

Waldek Hebisch

unread,
Jan 7, 2012, 11:38:17 AM1/7/12
to fricas...@googlegroups.com
Bill Page wrote:
>
> Waldek,
>
> On Fri, Jan 6, 2012 at 3:26 PM, you wrote:
> >
> > Well, I agree that OpenAxiom code _looks_ better. =A0You

> > say that 'attempting to decode how FriCAS actually ends up
> > producing the output' boggles your mind. =A0However, have you

> > tried to understand what OpenAxiom is doing?
> >
>
> Yes - at least in this and a few other instances. In fact I've been
> trying to do this for years now in all flavors of Axiom. I suppose it
> comes down to a form of documentation - kind of the opposite of what
> Tim Daly originally proposed for Axiom - readability of the code
> versus coding from a document (literate programming). I think that is
> what OpenAxiom is trying to do. I am encourage by Gaby's progress.
>
> > FYI FriCAS code was rewritten this summer and what it is
> > doing now is much simpler (and faster) than original version.
>
> I am also aware of all the work that you have been doing to improve
> FriCAS and it was certainly not my intention either directly or
> indirectly to be critical. FriCAS still remains my main tool of
> choice for computer algebra and I appreciate the hard work that you
> are putting into it. My concern about the future has to do with the
> total amount of effort for someone to get to the level of
> understanding of the code to make substantial improvements.
>

I am a bit disappointed that after rewrite you find FriCAS
version so hard to understand. Could you say what OpenAxiom
version easier to you? Is it difference between:

PrinAncb := categoryPrincipals CatEval(bname,$e)

and

PrinAncb:= first(b).(4)

(and similar places)?

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Gabriel Dos Reis

unread,
Jan 7, 2012, 12:46:56 PM1/7/12
to fricas...@googlegroups.com, open-axi...@lists.sf.net
Waldek Hebisch <heb...@math.uni.wroc.pl> writes:

which parts of the OpenAxiom's rewrite are you objecting too?

-- Gaby

Gabriel Dos Reis

unread,
Jan 7, 2012, 12:56:07 PM1/7/12
to fricas...@googlegroups.com, open-axi...@lists.sf.net
Bill Page <bill...@newsynthesis.org> writes:

| Ralf,
|
| To appreciate just how much effort Gaby has put into improving the
| readability of Boot code in OpenAxiom it is very instructive to look
| at JoinInner in both FriCAS and OpenAxiom. Just attempting to decode
| how FriCAS actually ends up producing the output you show nearly
| boggles my mind. But in OpenAxiom this same code is written as:
|
| PrinAncb := categoryPrincipals CatEval(bname,$e)
|
| If FriCAS does not soon adopt a similar approach I cannot imagine a good future.
|
| But of course advocating is one thing, finding time, energy and help
| to do it is another.

I can't agree more with the last sentence :-)

Regarding the debate of f(a.x) vs. f(a).x vs. (f(a)).x, I changed
OpenAxiom's Boot parser long ago to parser f(a).x the way the Spad parser
(and the interpreter) does, e.g. take the `x'-part of the result of
applying `f' to `a'. It was a difference that does not need to be there;
it confused occasionally, and it did not bring much.

I take it from conversations with original AXIOM designers and
implementors that Boot was really intended to be a form of AXIOM script
(except the handling of '$').

-- Gaby

Waldek Hebisch

unread,
Jan 7, 2012, 2:09:45 PM1/7/12
to fricas...@googlegroups.com, open-axi...@lists.sf.net

I do not object what OpenAxiom did. But it is possible to
simplify code more. For example OpenAxiom contains line:

resizeBuffer(principal,n + 1)

But whole business with extending domain vector and string
data here is completly unnecesary.

I did not analyze OpenAxiom version in detail, but given
that original contained several things like this (computing
unused things, nedlessy recomputing things) and OpenAxiom
version is significantly longer than FriCAS version, I think
that OpenAxiom may be significantly simplified.

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Bill Page

unread,
Jan 7, 2012, 4:29:13 PM1/7/12
to fricas...@googlegroups.com
On Sat, Jan 7, 2012 at 11:38 AM, Waldek Hebisch wrote:
> ...

> I am a bit disappointed that after rewrite you find FriCAS
> version so hard to understand.  Could you say what OpenAxiom
> version easier to you?  Is it difference between:
>
> PrinAncb := categoryPrincipals CatEval(bname,$e)
>
> and
>
> PrinAncb:= first(b).(4)
>
> (and similar places)?
>

My first difficulty started with Ralf's observation:

On Thu, Jan 5, 2012 at 10:45 PM, Ralf Hemmecke <ra...@hemmecke.de> wrote:
> ...


> Interesting
>
> PrinAncb:= first(b).(4)
>
> gives
>
> with bootsys
> (SETQ |PrinAncb| (CAR (ELT (|CatEval| |bname|) 4)))
>
> with depsys
> (SPADLET |PrinAncb| (CAR (ELT (|CatEval| |bname|) 4)))
>
> Why is it basically the same here and makes a difference for "CAR(d).1".
> I'm a bit confused now.

How is it possible that b can be replaced with '(|CatEval| |bname|)'
??? 'bname:=b.(0)' but it is just 'b' that is passed to 'first' ...
Where is 'CatEval'? To find out I must study very carefully the
function 'FindFundAncs'. For me this was very hard. As usual in Axiom
code, the comments are not helpful and sometimes even misleading.

I was very surprised when you admitted in another email in this chain
that you had deliberately replaced the expression containing CatEval
with just p. :(

My second difficulty is to what is the significance of 'first(b).(4)'.
I am asked to believe the comment:
--Principal Ancestors of b
but I do not know (yet) what is b. What is the structure of b? For
this purpose the name 'b' alone is of no help.

Both of these questions are easily answered from the OpenAxiom version
of the code. Or at the very least I am reassured that the comment is
indeed correct. Also in OpenAxiom the function ''FindFundAncs' has
been eliminated and 'JoinInner' function has been simplified so that
I have some confidence that I could really understand in detail of
what JoinInner actually does. With the FriCAS version I find I am
still uncertain.

I am especially convinced that using accessor macros such as '
categoryPrincipals' makes is easier to read the code without having to
first memorize the basic Axiom data structures.

Regards,
Bill Page.

Waldek Hebisch

unread,
Jan 9, 2012, 9:17:18 AM1/9/12
to fricas...@googlegroups.com
Bill Page wrote:
>
> On Sat, Jan 7, 2012 at 11:38 AM, Waldek Hebisch wrote:
> > ...
> > I am a bit disappointed that after rewrite you find FriCAS
> > version so hard to understand. =A0Could you say what OpenAxiom
> > version easier to you? =A0Is it difference between:
> >
> > PrinAncb :=3D categoryPrincipals CatEval(bname,$e)
> >
> > and
> >
> > PrinAncb:=3D first(b).(4)

> >
> > (and similar places)?
> >
>
> My first difficulty started with Ralf's observation:
>
> On Thu, Jan 5, 2012 at 10:45 PM, Ralf Hemmecke <ra...@hemmecke.de> wrote:
> > ...
> > Interesting
> >
> > PrinAncb:= first(b).(4)
> >
> > gives
> >
...

>
> How is it possible that b can be replaced with '(|CatEval| |bname|)'
> ??? 'bname:=b.(0)' but it is just 'b' that is passed to 'first' ...
> Where is 'CatEval'? To find out I must study very carefully the
> function 'FindFundAncs'. For me this was very hard. As usual in Axiom
> code, the comments are not helpful and sometimes even misleading.

Actually, the only tricky thing is that the line should be:

PrinAncb := first(b.4)

Otherwise, here FriCAS is much simpler than original (and OpenAxiom).
Namely, b is binary representation of category (category vector).
b.0 is name of category. CatEval given name of categry produces
binary representation. So

bname:=b.(0)
CatEval(bname)

is a roundabout way of saying 'b'.

> I was very surprised when you admitted in another email in this chain
> that you had deliberately replaced the expression containing CatEval

> with just b. :(

Yes, why do all this back and forth conversions when using 'b'
just works.

> My second difficulty is to what is the significance of 'first(b).(4)'.
> I am asked to believe the comment:
> --Principal Ancestors of b
> but I do not know (yet) what is b. What is the structure of b? For
> this purpose the name 'b' alone is of no help.
>
> Both of these questions are easily answered from the OpenAxiom version
> of the code. Or at the very least I am reassured that the comment is
> indeed correct. Also in OpenAxiom the function ''FindFundAncs' has
> been eliminated and 'JoinInner' function has been simplified so that
> I have some confidence that I could really understand in detail of
> what JoinInner actually does. With the FriCAS version I find I am
> still uncertain.

Well, at least I still see 'FindFundAncs' in OpenAxiom. I am
not convinced that you really understand details of OpenAxiom
version. Clearly you missed the point that CatEval(bname) is
a no-op. Did you understand purpose of 'reallynew' and
machinations with 'resizeBuffer'? In fact the result of
this are unused and the machnations are pointless (and absent
from FriCAS version).

FYI, in FriCAS version in frist step we form list of categories
to join. At first one may think that we are already
given a list of categories (namely argumets to Join) and
there is nothing to do. But, unfortuanatly, for technical
reasons we need to add conditional ancestors of them.
This is similar in OpenAxion, but FriCAS version is
simpoler because there are no attributes in FriCAS
and FriCAS skips some optimizations here.

After that we need to find fundamental ancestors of join.
In FriCAS this is done by the 'find_ffl' routine. I admit,
the name is uninspiring. Probably the best name would
be FindFundAncs (or in full FindFundamentalAncestors)
but the name is taken by existing routine :(. I will
probably change name to 'JoinFundamentalAncestors'.
Anyway, given list of categories and conditions
'find_ffl' produces fundamental ancestors of the join.

BTW: 'find_ffl' and FindFundAncs are essentially doing
the same thing, but use different representation of
data.

After that FriCAS version forms union of list of
signatures -- for unconditianal part of join that
is strigthforward loop using SigListUnion. For
conditional members of join we need to adjust conditions, so the
loop is slightly more complicated.

> I am especially convinced that using accessor macros such as '
> categoryPrincipals' makes is easier to read the code without having to
> first memorize the basic Axiom data structures.

Yes, accessors with meaningful names help. However, note:

- accessors can hide some aspect of operation. In particular
they do not help to find simplifications made in FriCAS
version
- introducing accessors leads to a lot of textual change
without changing functionality. This makes tracing
history of functional changes harder.
- textual change interferes with other developement.

So developement cost of accessors is much higher then one
would think at first. And names which are good at one
point of time probably will be not so good in the future,
for example OpenAxiom has 'categoryAttributes' but
attributes are gone in FriCAS, so the name would be
misleading...

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Bill Page

unread,
Jan 9, 2012, 10:27:55 AM1/9/12
to fricas...@googlegroups.com

Actually that is not tricky at all once you know that . has higher
priority than function application.

> Otherwise, here FriCAS is much simpler than original (and OpenAxiom).

> Namely, b is binary representation of category (category vector).
> b.0 is name of category.  CatEval given name of categry produces
> binary representation.

This paragraph would make a very useful comment in the source code.

> So
>
> bname:=b.(0)
> CatEval(bname)
>
> is a roundabout way of saying 'b'.
>

Yes, but Ralf reported this:

>> > Interesting
>> >
>> > PrinAncb:= first(b).(4)
>> >
>> > gives
>> >

>> > with bootsys
>> > (SETQ |PrinAncb| (CAR (ELT (|CatEval| |bname|) 4)))
>> >
>> > with depsys
>> > (SPADLET |PrinAncb| (CAR (ELT (|CatEval| |bname|) 4)))

In this result we do see '(|CatEval| |bname|)' not 'b'.

>> I was very surprised when you admitted in another email in this chain
>> that you had deliberately replaced the expression containing CatEval
>> with just b.  :(
>
> Yes, why do all this back and forth conversions when using 'b'
> just works.
>

Sure 'b' works. You wrote 'b' but the result contains CatEval anyway.
Why not just write what it is?

>> My second difficulty is to what is the significance of 'first(b).(4)'.
>> I am asked to believe the comment:
>>   --Principal Ancestors of b
>> but I do not know (yet) what is b. What is the structure of b?  For
>> this purpose the name 'b' alone is of no help.
>>
>> Both of these questions are easily answered from the OpenAxiom version
>> of the code. Or at the very least I am reassured that the comment is
>> indeed correct.  Also in OpenAxiom the function ''FindFundAncs' has
>> been eliminated and  'JoinInner' function has been simplified so that
>> I have some confidence that I could really understand in detail of
>> what JoinInner actually does. With the FriCAS version I find I am
>> still uncertain.
>
> Well, at least I still see 'FindFundAncs' in OpenAxiom.  I am
> not convinced that you really understand details of OpenAxiom
> version.

I am sorry that was as they say, a "thinko". What I should have said
is that 'find_ffl' was eliminated.

>  Clearly you missed the point that CatEval(bname) is
> a no-op.

No I did not miss that even when first reading. I deduced that it
seemed to behave that way in this case but without further analysis I
could not be sure that this is always the case. Purpose there is some
good reason that these categories are being re-evaluated? Perhaps
there is some side-effect that necessitates it?

> Did you understand purpose of 'reallynew' and
> machinations with 'resizeBuffer'?  In fact the result of
> this are unused and the machnations are pointless (and absent
> from FriCAS version).
>

No, I had not reason to try to understand this. I agree that it is
much simpler in the FriCAS version but I would be very difficult for
me to prove that it is equivalent. There seems to be nothing
immediately available in the source code or comments that suggests
this simplification. Your knowledge of how this works is critical
here.

> FYI, in FriCAS version in frist step we form list of categories
> to join.  At first one may think that we are already
> given a list of categories (namely argumets to Join) and
> there is nothing to do.  But, unfortuanatly, for technical
> reasons we need to add conditional ancestors of them.
> This is similar in OpenAxion, but FriCAS version is
> simpoler because there are no attributes in FriCAS
> and FriCAS skips some optimizations here.
>
> After that we need to find fundamental ancestors of join.
> In FriCAS this is done by the 'find_ffl' routine.  I admit,
> the name is uninspiring.  Probably the best name would
> be FindFundAncs (or in full FindFundamentalAncestors)
> but the name is taken by existing routine :(.  I will
> probably change name to 'JoinFundamentalAncestors'.

Yes, this would be good although perhaps there is no need for a
separate function?

> Anyway, given list of categories and conditions
> 'find_ffl' produces fundamental ancestors of the join.
>
> BTW: 'find_ffl' and FindFundAncs are essentially doing
> the same thing, but use different representation of
> data.
>

In OpenAxiom 'find_ffl' has been eliminated (my earlier mistake).

> After that FriCAS version forms union of list of
> signatures -- for unconditianal part of join that
> is strigthforward loop using SigListUnion.  For
> conditional members of join we need to adjust conditions, so the
> loop is slightly more complicated.

I would propose that the explanation you have provided in this email
should become comments in the source concerning 'JoinInner'.

>
>> I am especially convinced that using accessor macros such as '
>> categoryPrincipals' makes is easier to read the code without having to
>> first memorize the basic Axiom data structures.
>
> Yes, accessors with meaningful names help.  However, note:
>
> - accessors can hide some aspect of operation.  In particular
>  they do not help to find simplifications made in FriCAS
>  version

It is the purpose of accessors to high some details of the
implementation in order to help ensure modularity. I am still not
convinced that the change made in FriCAS is a good thing.

> - introducing accessors leads to a lot of textual change
>  without changing functionality.  This makes tracing
>  history of functional changes harder.
> - textual change interferes with other developement.
>

I find this an odd conclusion. It is like saying that documentation
interferes with understanding ... :(

> So developement cost of accessors is much higher then one
> would think at first.  And names which are good at one
> point of time probably will be not so good in the future,

But tracking changes to names reflects exactly the history of
functional changes that you mention above, no? Choosing a meaningful
name is part of the documentation.

> for example OpenAxiom has 'categoryAttributes' but
> attributes are gone in FriCAS, so the name would be
> misleading...
>

I think implementing attributes as categories is a separate issue. I
am not against this change but although the impact on the code in the
library is small, I think the change does deserve more discussion from
the point of view of the semantics of the Spad language. In any case
since attributes have been eliminated, of course there would be no
need then of 'categoryAttributes'.

Regards,
Bill Page.

Waldek Hebisch

unread,
Jan 9, 2012, 11:55:15 AM1/9/12
to fricas...@googlegroups.com
Bill Page wrote:
>
> On Mon, Jan 9, 2012 at 9:17 AM, Waldek Hebisch wrote:
> > Bill Page wrote:
> >>
> >> On Sat, Jan 7, 2012 at 11:38 AM, Waldek Hebisch wrote:
> >>
> > So
> >
> > bname:= b.(0)

> > CatEval(bname)
> >
> > is a roundabout way of saying 'b'.
> >
>
> Yes, but Ralf reported this:
>
> >> > Interesting
> >> >
> >> > PrinAncb:=3D first(b).(4)

> >> >
> >> > gives
> >> >
> >> > with bootsys
> >> > (SETQ |PrinAncb| (CAR (ELT (|CatEval| |bname|) 4)))
> >> >
> >> > with depsys
> >> > (SPADLET |PrinAncb| (CAR (ELT (|CatEval| |bname|) 4)))
>
> In this result we do see '(|CatEval| |bname|)' not 'b'.

I do not know how Ralf gets this. I see:

)boot PrinAncb := first(b).(4)
(EVAL-WHEN (EVAL LOAD) (SETQ |PrinAncb| (CAR (ELT |b| 4))))


and the same in generated 'category.clisp' file. 'CatEval'
was in old version:

PrinAncb := first (CatEval bname).(4)

>

> >> I was very surprised when you admitted in another email in this chain
> >> that you had deliberately replaced the expression containing CatEval

> >> with just b.0 :(


> >
> > Yes, why do all this back and forth conversions when using 'b'
> > just works.
> >
>
> Sure 'b' works. You wrote 'b' but the result contains CatEval anyway.
> Why not just write what it is?

No, now we just have 'b'.



> >> My second difficulty is to what is the significance of 'first(b).(4)'.
> >> I am asked to believe the comment:

> >> =A0 --Principal Ancestors of b
> >> but I do not know (yet) what is b. What is the structure of b? =A0For


> >> this purpose the name 'b' alone is of no help.
> >>
> >> Both of these questions are easily answered from the OpenAxiom version
> >> of the code. Or at the very least I am reassured that the comment is

> >> indeed correct. =A0Also in OpenAxiom the function ''FindFundAncs' has
> >> been eliminated and =A0'JoinInner' function has been simplified so that


> >> I have some confidence that I could really understand in detail of
> >> what JoinInner actually does. With the FriCAS version I find I am
> >> still uncertain.
> >

> > Well, at least I still see 'FindFundAncs' in OpenAxiom. =A0I am


> > not convinced that you really understand details of OpenAxiom
> > version.
>
> I am sorry that was as they say, a "thinko". What I should have said
> is that 'find_ffl' was eliminated.
>

> > =A0Clearly you missed the point that CatEval(bname) is


> > a no-op.
>
> No I did not miss that even when first reading. I deduced that it
> seemed to behave that way in this case but without further analysis I
> could not be sure that this is always the case. Purpose there is some
> good reason that these categories are being re-evaluated? Perhaps
> there is some side-effect that necessitates it?

Ok, in FriCAS you are saved such questions.

> >=A0Did you understand purpose of 'reallynew' and
> > machinations with 'resizeBuffer'? =A0In fact the result of


> > this are unused and the machnations are pointless (and absent
> > from FriCAS version).
> >
>
> No, I had not reason to try to understand this. I agree that it is
> much simpler in the FriCAS version but I would be very difficult for
> me to prove that it is equivalent. There seems to be nothing
> immediately available in the source code or comments that suggests
> this simplification. Your knowledge of how this works is critical
> here.

To notice that one can get rid of this requires effort. But
once it is removed understanding source is easier. In fact,
when working on JoinInner at first I was worried that numbers
produced in this part will change and that this may break
something. But analyzing effect of change showed that
numbers are not used at all. So what I did saves this
effort form persons trying to work with FriCAS sources.

> > FYI, in FriCAS version in frist step we form list of categories

> > to join. =A0At first one may think that we are already


> > given a list of categories (namely argumets to Join) and

> > there is nothing to do. =A0But, unfortuanatly, for technical


> > reasons we need to add conditional ancestors of them.
> > This is similar in OpenAxion, but FriCAS version is
> > simpoler because there are no attributes in FriCAS
> > and FriCAS skips some optimizations here.
> >
> > After that we need to find fundamental ancestors of join.

> > In FriCAS this is done by the 'find_ffl' routine. =A0I admit,
> > the name is uninspiring. =A0Probably the best name would


> > be FindFundAncs (or in full FindFundamentalAncestors)

> > but the name is taken by existing routine :(. =A0I will


> > probably change name to 'JoinFundamentalAncestors'.
>
> Yes, this would be good although perhaps there is no need for a
> separate function?

Separate function makes clear that computations are used
only for their result and no variables (except
for FundamentalAncestors to which we assign the result)
in JoinInner are changed. In other words instead of
one big piece where potentially all things may interact
we have two almost independent parts. For me it is
much clearer.

> > Anyway, given list of categories and conditions
> > 'find_ffl' produces fundamental ancestors of the join.
> >
> > BTW: 'find_ffl' and FindFundAncs are essentially doing
> > the same thing, but use different representation of
> > data.
> >
>
> In OpenAxiom 'find_ffl' has been eliminated (my earlier mistake).

No, 'find_ffl' was never in OpenAxiom. It was introduced
in FriCAS.

> >
> >> I am especially convinced that using accessor macros such as '
> >> categoryPrincipals' makes is easier to read the code without having to
> >> first memorize the basic Axiom data structures.
> >

> > Yes, accessors with meaningful names help. =A0However, note:
> >
> > - accessors can hide some aspect of operation. =A0In particular
> > =A0they do not help to find simplifications made in FriCAS
> > =A0version


>
> It is the purpose of accessors to high some details of the
> implementation in order to help ensure modularity. I am still not
> convinced that the change made in FriCAS is a good thing.

To make things clear: in FriCAS I did not eliminate accessors.
In fact, even though FriCAS JoinInner is significantly
changed, still most lines come from original.
The changes eliminate useless computations (for example,
unnecessary CatEval took measurable time).

> > - introducing accessors leads to a lot of textual change

> > =A0without changing functionality. =A0This makes tracing
> > =A0history of functional changes harder.


> > - textual change interferes with other developement.
> >
>
> I find this an odd conclusion. It is like saying that documentation
> interferes with understanding ... :(

What is odd about this:

1) In FriCAS I can take a name and typically I will find it
in old versions. This speeds up checking history.
2) Volume of changes is _much_ smaller.
3) Have you never met situation where you have "almost ready"
patch, but then you need to do something else and when
you come back to the patch you see that it no longer
applies?


>
> > So developement cost of accessors is much higher then one

> > would think at first. =A0And names which are good at one


> > point of time probably will be not so good in the future,
>
> But tracking changes to names reflects exactly the history of
> functional changes that you mention above, no?

In my linguo renaming is not a functional change.

> Choosing a meaningful
> name is part of the documentation.
>
> > for example OpenAxiom has 'categoryAttributes' but
> > attributes are gone in FriCAS, so the name would be
> > misleading...
> >
>
> I think implementing attributes as categories is a separate issue. I
> am not against this change but although the impact on the code in the
> library is small, I think the change does deserve more discussion from
> the point of view of the semantics of the Spad language. In any case
> since attributes have been eliminated, of course there would be no
> need then of 'categoryAttributes'.

My point is that corresponding entry in domain vector is still
there. It contains conditional categories (the same holds for
original and OpenAxiom). The only thing which changed is
the there are no attributes in this field, but we still need
an accessor.

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Ralf Hemmecke

unread,
Jan 10, 2012, 5:27:19 AM1/10/12
to fricas...@googlegroups.com
>> Yes, but Ralf reported this:
>>
>>>>> Interesting
>>>>>
>>>>> PrinAncb:=3D first(b).(4)
>>>>>
>>>>> gives
>>>>>
>>>>> with bootsys
>>>>> (SETQ |PrinAncb| (CAR (ELT (|CatEval| |bname|) 4)))
>>>>>
>>>>> with depsys
>>>>> (SPADLET |PrinAncb| (CAR (ELT (|CatEval| |bname|) 4)))
>>
>> In this result we do see '(|CatEval| |bname|)' not 'b'.
>
> I do not know how Ralf gets this.

I'm sorry for causing this confusion. I didn't know that category.boot
changed. So I cited the line

PrinAncb := first(b).(4)

from trunk at that time (approx r1262), but took the output for bootsys
and depsys from my logs of the compilation of r1036 (and my testing
patches) where category.boot still contained the lines.

PrinAncb:= first (CatEval bname).(4)

--Principal Ancestors of b

Ralf

Reply all
Reply to author
Forward
0 new messages