First of all, I am confused about Python and macros.  If I read this
posting from March, 2009,
Python doesn't have macros.

http://blog.pythonisito.com/2009/03/python-macros.html

So maybe this guy is misinformed?


...snip...
>
> Right, but you could write a similar macro in python. {Scratches
> head}.

Does Python have macros?


>
> > > How would it cope with the new proposed addadd, subadd and sumdiff
> > > functions of MPIR?
>
> > I don't know what those functions do, but guessing that mpir_addadd
> > (target,a,b,c)
> > does target:=a+b+c,
>
> yep
>
>
> > As I recall MPFR is all "state based" not "functional" in style (in
> > terms of its interface),
> > and I think GMP and therefore MPIR are similar.
> > That is, you cannot take
> > a:=b+c*d  and convert (or compile it) into
> > set(a, plus(b,times(c,d))).
>
> OK, so a functional language like lisp is useless for interfacing to
> non-functional languages like C. Good point.

Actually, you totally miss the point, because I take a lisp expression
like
(setf a (+ b (* c d))     ;; functional form

and I compile it into different lisp expressions (a sequence)
which maps exactly into calls to mutating commands.

  And of course most
computers today use an imperative style of opcode/operand(s)
instruction
set, and so ANY programming language interfaces to imperative
commands.

You seem to forget that a large part of C is functional in form; there
is even
a conditional EXPRESSION e.g.

    a<b ? a : b;

And furthermore, at least one Lisp system (and perhaps 3 or more) work
by
translating Lisp code into C, which is subsequently run through a C
compiler.

The matter of functional or non-functional form is largely
irrelevant.  If you wish to think about a true
conflict between a C mind-set and a Lisp mind-set, I think you should
concentrate on memory
allocation, de-allocation, and sharing. Interfacing between C and Lisp
can be tricky when some
program must allocate the space which is then used by the other.  If
Lisp allocates space,
it would be a bad situation if C deallocates it.  (And vice versa).






>
>
> > OK, so why does Sage have 5000 lines with mpz_.... ?
>
> Because we either don't have your macro, which you admit is not part
> of Lisp, but something you wrote, or many, many people coding away on
> Sage don't know of the existence of such a thing if it exists.

Well, if you were writing in Lisp and wanted to use MPFR or GMP, you
might find my generic
arithmetic code on the internet,  or you might find something
similar.  We are not
talking rocket science, in terms of Lisp, so you might even write it
yourself.

>
> Or, just maybe, there are instances in the hundreds of thousands of
> lines of Sage python code where your macro wouldn't do the optimal
> thing, so someone wrote their own specialised code which does the
> correct thing.

Actually, since my code compiles pretty directly into what a compiler
writer
would call 3-address code, and the 3-address code is implemented by
GMP, MPFR, and probably similar libraries,  there is not much argument
for "optimization".

>
> > If I wrote a whole suite of programs to use mpz_ or mpfr_  or
> > interval_  or .... programs
> > I would hardly ever use those programs explicitly.  I would use use
> > ordinary operations
> > like +, *,   etc.  and have them magically macro-expanded to calls to
> > those library functions.
>
> So what do you suppose the other few hundred thousand lines of Sage
> python code do?

I assumed they did thing like parsing, plotting, and parceling out the
various things to the 83 different packages
using whatever tools fell to hand.  If there are gobs of original code
from William Stein's efforts to re-code
Magma in python (or Cython or C or ...), that might take lots of
space.

Writing yet another parser, yet another plotting program ... would not
ordinarily use bignumbers much.
The parser might have a call to convert a string to a bignum.  So
that's one spot or two.


>
> I'd be really surprised if the number of lines of code in the examples
> you posted on your website is even remotely similar to the number of
> lines of code in Sage.

I should hope not.  But you can look.  I would expect that if I wished
to write a few hundred thousand lines
of code, say duplicating the features of Matlab (or Octave or Euclid
or some similar numerical matrix
package) but using bigfloats from MPFR,  I would not have a single raw
call to any mpfr program
in the source code for that additional package.  Of course, after
macro-expansion, that code would
consist largely of calls to mpfr programs.


>
> When you have a really efficient computational algebra package written
> in Lisp with the depth of functionality of Sage posted on your
> website, then we'll do a comparison of the number of lines of
> mpfr_this and mpz_that.

I really don't know what you mean by a really efficient computational
algebra package ...with the depth of Sage etc.
But if the Sage program in question achieves its objectives by
sequential calls to programs in the
MPIR or GMP library, that the program I would write in Lisp could
achieve the same objectives by the same
sequential calls to the same programs, but without mentioning them
explicitly.  The question would then
remain as to the (presumably much less time-consuming) code in-between
the calls to those programs.
Then one is comparing the cost of executing loops, counting,
marshalling arguments, etc.  in Python
vs. Lisp.  Lisp is ordinarily compiled into native binary code.  (some
exceptions: CLISP is a byte-code interpreter,
there are some Lisps running on the Java Virtual Machine).  Python, I
gather, is not so efficient, hence
the need for Cython.  I would expect Lisp to win over Python, and
possibly over Cython.
Some Lisps compile to C, some Lisps compile to assembler.

>
>
>
> > > Does Lisp automatically deal with the case where the (2*i - 1)
> > > overflows?
>
> > there are two places for overflow, 2*i is the first one.
> > mpfr_mul_ui(target1,i,2)  would not overflow, since the target is a
> > bigfloat.  [oh, by the way, I think there
> > is also a 4th argument which is the rounding mode, usually
> > *nearest*],.
>
> That's terribly inefficient. It's much more efficient to multiply the
> 2*i in a machine word than to pull out an mpfr for the purpose.
> Possibly where some of those 5000 lines come from.

No problem.  If you know that i is small, then you can leave it as a
fixnum, and
instead of writing (* 2 i)  you could write  (cl::* 2 i)   or even
(lsh i 1),  which is
a left shift.

While you may think it is terribly inefficient, multiplying i by 2 and
storing in a temporary is just going to overwrite some storage
(at least until the point when the temporary must be enlarged because
the number is too big...)

>
>
>
>
>
> > The next place is
> > mpfr_sub_ui(target2,target1,1).
> > That won't overflow either.
>
> > The chance that you are interested in evaluating a Legendre polynomial
> > of degree 2^32 or so is pretty remote, I think.
> > But this particular expression would be OK.
>
> >  Of course Sage has to deal with that.

And my code would work just fine regardless.

 But I am not seeing
>
> > > any reason why you couldn't code up a macro, similar to the one your
> > > Lisp gives you which allows evaluation of expressions such as these in
> > > an optimal manner.
>
> > I agree with you entirely, which is why I asked about the 5000 lines
> > with mpz.
> > One possible answer is, "#...@#$%$, Python doesn't have macros."
>
> But I bet cython does. It also depends what you want to call a macro.

Uh,  do I read into this an admission that PYTHON DOES NOT HAVE
MACROS?

I am not the one calling something a macro or not.  It is YOU who
seems to
think that Python does not have macros.  By the way, one could always
have
a macro processor on top of Python.  There are 2 computer algebra
systems
that use "external"  or meta-macro processors that I know about.
Maybe 3.
Maple used (maybe still does use) something called Margay to process
its C code.
Altran used (I think) M6 to process its code (in assembler? fortran?
B? ??)
Even Mathematica used a macro processor (maybe still does) which
constituted
an object-oriented extension of C.

I truly did not know (until today) that Python had no macro processing
capability.
I don't know what excuses you might have for saying "it depends".  But
it's
awfully handy.
>
> I'm wondering why you used postfix instead of infix?

huh??  postfix would be something like   A B C * +        for     a
+b*c.

Lisp uses parenthesized prefix,   (+ a (* b c))




> Could it be due
> to some limitation of lisp which makes it difficult to deal with infix
> expressions.

I can't imagine what you are driving at.  The Maxima parser deals with
infix expressions.
There are many parsers for nearly every language written in Lisp.
Parenthesized prefix
notation is not something Lisp programmers had to settle for because
the "good syntax"
was too difficult.

> Let me hazard a guess. You *could* write an infix version
> in Lisp, but it would be *much* more complicated.

I would not have to write one; there are many. CGOL is one I have
used,
but frankly I haven't used it in years.

> Whereas Python has
> lots of nice expression parsing libraries which do this trivially for
> you.

Except Python doesn't have macros, which operate on the parsed
expressions;
in Lisp, the parsed expressions have the same form as the programs
(and data)
and so macro expansion programs are much simpler.  [Though they can be
quite tricky, nevertheless!]

actually, Lisp doesn't need a special parsing library to convert a
character string

(+ a (* b c))   to the intermediate expression tree.  The Lisp program
that does
this is called READ.


>
> ... snip....
>
> By and large Python is much easier to use than most other languages.

So you are familiar with most other languages?


> So even if it were true that python didn't have a convenient level
> upon which to implement such a thing, the enormous number of other
> conveniences over a language like Lisp far outweigh this disadvantage.

Actually, I assumed the advantage of Python was that it had many
libraries to access
operating system facilities in a manner that was relatively
independent of the operating
system.
And that, although it had a foolish policy regarding indentation, it
was nevertheless
not too much unlike Lisp, and only a moderate factor slower.


> I couldn't help noticing the enormous number of parentheses in your
> postfix expression as compared to the much nicer python infix.

I guess you mean parenthesized prefix.

> I hope
> you have a good magnifying glass or a decent editor to see which ones
> match up with which.

Actually the editor does all the work.  One way it shows how things
line up
is by indenting.  The editor always indents correctly, according to
the proper
syntax of the programming language. The human looks at it and see that
items that should be on the same level are indented differently and so
inserts or removes the
occasional parenthesis.  The program is then automatically re-
indented.

The non-lisp programmer seems to think that lisp programmers spend a
lot of time balancing or counting parentheses.
Actually, no time at all.  My guess is that a python programmer spends
a lot more time indenting. But that's only a guess.

>
> But your premise is flawed. Sage does just fine in terms of offering
> oodles of "other" arithmetics. That's kind of what Sage is. And it was
> written in Python.

Well, I was hoping that was the case, as I said for the umpteenth
time,
which is why having 5,000 lines with mpz_   seemed odd.

>
> Yes, python doesn't have macros in the sense that you mean them.

Aha, a totally explicit admission. Thanks.

> But
> Sage itself does have a preprocessor, which could be used in theory to
> provide the sorts of macros you are talking about.

OK, like M6, perhaps, that maps strings to strings?

>  It has not been
> done because of a (valid) design decision to keep the syntax as close
> to python as possible (the Sage preprocessor does almost nothing).

If it were a good decision, I think one would not have to write mpz_s
so much.


> Having said that, making mpz's and the like, easy to use, is not
> really that hard without macros. And at the level William was talking
> about, you can use Cython anyhow, so what's the problem.

Well, is 5000 lines of Cython  better than 5000 lines of Python?
>
>
>
> > > Sage has a very powerful collection of "arithmetics". I mean you can
> > > multiply matrices, polynomials, group elements, all sorts of things,
> > > with a * operator.
>
> > OK, how hard is it to add another kind of arithmetic? (say, for
> > argument's sake
> > complex numbers are not built in. How hard would it be to add them?
> > Would you have
> > to write complex_add(a,b),  complex_mul(c,d)  etc etc??  I hope not.
> > But then why would you have to write mpz_..()  all over the place?
>
> But the vast majority of things you are going to want to do are going
> to not be arithmetic things. E.g. with polynomials over Z, you have +,
> *, -, ^  and pretty much I've run out of symbols. But there's 139
> functions in FLINT of the form fmpz_poly_blah(). A very small number
> of them do +, *, -, ^.

OK, now we are talking.  It seems that except for +, *, - ,^   [I
would add /, and grouping()]
there is not much point in using infix.  So why does the language have
so much
special syntax for arithmetic?? Why do students need to learn about
precedence and such
when it is SO confusing.

And I take it, from your answer, that if Python did not have complex
arithmetic,
you would have to write complex_add(a,b)  etc.  Really??

>
> Here for example is the code which handles multiplication of
> polynomials, so that people can just type f*g:
>
>     cpdef RingElement _mul_(self, RingElement right):
>         r"""
>         Returns self multiplied by right.
>
>         EXAMPLES::
>
>             sage: R.<x> = PolynomialRing(ZZ)
>             sage: (x - 2)*(x^2 - 8*x + 16)
>             x^3 - 10*x^2 + 32*x - 32
>         """
>         cdef Polynomial_integer_dense_flint x = self._new()
>         _sig_on
>         fmpz_poly_mul(x.__poly, self.__poly,
>                 (<Polynomial_integer_dense_flint>right).__poly)
>         _sig_off
>         return x
>
Well, this is kind of interesting.  Let me suggest how this would look
in (my) generic arithmetic package, assuming we were happy with
whatever flint representation was for a polynomial.  I'm going to take
some liberties with the details; it can be found online if you care

(defmethod  poly::* ((x Polynomial_integer_dense_flint)
                                (y Polynomial_integer_dense_flint))
  (let ((answer (fmpz_poly_init 0))   ;; or something to create a
polynomial 0
    (fmpz_poly_mul (poly_part answer) (poly_part x) (poly_part y))
    answer))

I don't know about this  sig_on stuff, but that presumably could be
done too.

> It's written in cython of course, not python, as most of the stuff
> which uses C libraries should be. Sage handles the rest.

The program above is written in common lisp, using the common lisp
object system.
It can be compiled to binary code.  No need to introduce another
language like Cython.

There is a refrain that seems to occur here.  Python is great, but
when it sucks we use Cython.

Now regarding the calls to mpz_add, there are about 100 or so.

In my generic arithmetic package there are two required source code
line mentioning mpz_add.

one of them is .. in this declaration

  (ff:def-foreign-call   ;; this associates the lisp name mpz_add with
the entry point __gmpz_add.  Almost all the other declarations look
the same..
   (mpz_add  "__gmpz_add")
   ((target mpz  (simple-array (signed-byte 32) (3)))
    (op1 mpz  (simple-array (signed-byte 32) (3)))
    (op2 mpz  (simple-array (signed-byte 32) (3))))
   :returning :void
   :arg-checking nil :call-direct t)


and the other is this call to a macro, which is then used by the
compiler to replace "+"  by mpz_add

(defarithmetic + mpz_add)

in fact I use mpz_add in a few other places that have to do with input
and output,  and I use some code for multiplying by a power of 2,
converting from strings, etc.
but they are all in one file. The first 9 pages of gmp.lisp

>
>
>
>
>
> > > The original discussion was about in_place operators, which Sage does
> > > allow. The example William gave was:
>
> > > sage: n = 15
> > > sage: n._iadd_(5)
> > > 20
> > > sage: n
> > > 20
>
> > > I don't see any lines of mpfr_add's there, do you?
>
> > No, Sage might have in_place operators, and MPIR might have in_place
> > operators, but that
> > doesn't mean that Sage can use the in_place operators in MPIR with the
> > above syntax.
>
> Of course it can. Here is one of your 5000 lines of mpz_add's:
>
>     cpdef ModuleElement _iadd_(self, ModuleElement right):
>         # self and right are guaranteed to be Integers, self safe to
> mutate
>         mpz_add(self.value, self.value,
> ...
>
> read more »

oops.... I can't read more without sending this mail off,.
So I'll send it off.

RJF


....
--~--~---------~--~----~------------~-------~--~----~
To post to this group, send an email to sage-devel@googlegroups.com
To unsubscribe from this group, send an email to 
sage-devel-unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/sage-devel
URLs: http://www.sagemath.org
-~----------~----~----~----~------~----~------~--~---

Reply via email to