MathGroup Archive 2004

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Why overloaded arithmetic operations are so slow?

  • To: mathgroup at
  • Subject: [mg49914] Re: [mg49729] Why overloaded arithmetic operations are so slow?
  • From: "Fred Simons" <f.h.simons at>
  • Date: Fri, 6 Aug 2004 03:09:29 -0400 (EDT)
  • References: <>
  • Sender: owner-wri-mathgroup at

Dear Sergey,

To explain what is going on I define a function that will produce a list of

p[n_] :=  zz /@ Table[Random[Integer, {1,1000}], {n}]

and adapt the assignment to zz to visualize the evaluation process:

zz/:Plus[z1_zz,z2_zz]:=(Print[{z1, z2}];zz[First[z1]+First[z2]])

The function Plus has attributes OneIdentity and Flat and these will be used
before the rule for zz is applied. That means that the arguments of Plus
will be sorted. The definition for zz uses only two arguments, so the
attribute Flat will be used to 'rewrite' the expression in such a way that
the rule for zz can be applied. Here is a small example.

Plus @@%

From In[4]:=
From In[4]:=
From In[4]:=

Indeed, the arguments are sorted, brackets are placed around the first two
arguments and the rule is applied, the arguments are sorted, brackets are
placed around the first two arguments and the rule is applied and so on. But
when we look at a larger example, we observe that the pattern matcher does
not simply place brackets around the first two arguments. It seems to
consider practically all possibilities before brackets are placed. In the
following example we observe that nearly all the time is used for the
transition from 15 to 14 arguments.

Plus @@%

Hence in this example the patternmatcher could be improved. But actually the
problem is due to a not quite adequate definition for zz. What you really
want to do is repeatedly combining two arguments of Plus leaving the others
untouched. That can be done in the following way:

zz/:Plus[z1_zz,z2_zz, z3___]:=Plus[zz[First[z1]+First[z2]], z3]

Total[p[254]] // Timing
{0.032 Second,zz[126441]}

Or without the recursion:

zz/:Plus[z1__zz]:=zz[Plus @@ First /@ {z1}]

(Total[test]) // Timing
{0.266 Second,zz[4990657]}

I hoppe this answers your question. But if this example really is your
problem, it can be done much easier and faster without the zz-rule:

test = p[20000];
Total[test]// Timing
zz[Fold[#1+#2[[1]]&, 0, test]] // Timing
zz[Total[First/@test]] // Timing
{2.75 Second,zz[9987173]}
{0.047 Second,zz[9987173]}
{0.015 Second,zz[9987173]}

Kind regards,

Fred Simons
Eindhoven University of Technology

----- Original Message -----
From: "Sergey Afonin" <serg at>
To: mathgroup at
Subject: [mg49914] [mg49729] Why overloaded arithmetic operations are so slow?

> Hi all.
> In "The Mathematica Book" (2.5.10) one can read that overloading
> standard arithmetic operations, such as Plus, for user-defined data is
> "much more convenient" than defining specific functions. But how this
> can be done efficiently? I want to define type of the form zz[Number]
> with the addition
> zz /: Plus[z1_zz, z2_zz] := zz[First[z1] + First[z2]]
> In fact, zz are "normal" numbers. The following statement prints out
> the time spent for addition wrt the number of elements...
> Do[Print[Timing[Plus @@ Table[zz[10^(i - 1)], {i, n}]]], {n, 15}]
> {0. Second, zz[1]}
> {0. Second, zz[11]}
> {0. Second, zz[111]}
> {0. Second, zz[1111]}
> {0. Second, zz[11111]}
> {0. Second, zz[111111]}
> {0. Second, zz[1111111]}
> {0.02 Second, zz[11111111]}
> {0.03 Second, zz[111111111]}
> {0.12 Second, zz[1111111111]}
> {0.35 Second, zz[11111111111]}
> {1.07 Second, zz[111111111111]}
> {3.31 Second, zz[1111111111111]}
> {10.07 Second, zz[11111111111111]}
> {30.81 Second, zz[111111111111111]}
> Is it normal?
> Best regards,
> Sergey Afonin

  • Prev by Date: Re: populate a list with random numbers from normal distribution?
  • Next by Date: Mathematica on Linux - problems compiling for Netsolve
  • Previous by thread: Continuous Distributions
  • Next by thread: Mathematica on Linux - problems compiling for Netsolve