Numeric: fromfunction() performance

Pearu Peterson pearu at cens.ioc.ee
Tue Oct 15 08:39:10 EDT 2002


On 15 Oct 2002, jsaul wrote:

> Hi there,
> 
> I have a code in which an array is created 'on the fly' using
> Numeric's fromfunction() command:
> 
>     import Numeric
> 
>     x1,x2,nf = 1.08E-8, 6.28E-3, 100000
>     q = Numeric.fromfunction (lambda i,k: - x1*i*i - 1j*i*x2 , (nf,1))
>     q.shape = (nf,) # make it a one-dimensional array (arhhh)
>     q = Numeric.exp(q)
> 
> Surprisingly, the fromfunction() statement takes quite long to
> execute, while exp() is very quick, because it's coded in C.
> Is there any way to improve the speed of the fromfunction() call?
> 
> And, is there a way to avoid that 'shape' statement?
> fromfunction() apparently refuses to produce a one-dimensional
> array of length nf, so I currently achieve that by computing a
> nfX1 matrix, which I then re-shape to a 1-D array. Not quite
> an elegant way...
> 
> What I actually want is a (quicker) construct corresponding to
> 
>     for i in range(0, nf):
>         q[i] = cmath.exp(-x1*i*i -1j*i*x2)
> 
> Which is much too slow.

It seems that you are trying to evaluate genus 1 Riemann theta function
that, by definition, reads (I hope you can read Latex)

  \theta(\phi) = \sum_{n=-\infty}^{\infty} \exp(-b*n*n+sqrt(-1)*n*\phi)

It can be rewritten in the following form (after using Poisson
formula)

  \theta(\phi) = \sqrt{2\pi/b} \sum_{n=-\infty}^{\infty} 
                     \exp(-(\phi-2\pi n)^2/(4 b))

Now, if you want to evaluate \theta(\phi) numerically, then
the first formula is most efficient if b<2\pi and use the second formula
if b>2\pi. Also note that when truncating the series, it is enough to
use only terms that have
  |n| <= ceil(2.2\sqrt(p/b))  for the first formula
  |n| <= ceil(0.2\sqrt(p b))  for the second formula

where p is the number of digits you want to be correct, take p=16 if you
are working on 32-bit computer. If you are using the right formula for
the given b, then the max(|n|) never exceeds 4 (c.f. your nf=100000).

Another hint is that when you evaluate series numerically then you should
sum starting from the terms with smallest value.

I have a Fortran program that evaluates \theta function and its
derivatives upto 20th order. It can be called from Python using f2py. 
If you are interested, I can send the sources to you.

HTH,
	Pearu





More information about the Python-list mailing list