[Rd] Inaccurate complex arithmetic of R (Matlab is accurate)

Martin Maechler maechler at stat.math.ethz.ch
Mon Aug 3 19:30:24 CEST 2009


>>>>> "HWB" == Hans W Borchers <hwborchers at googlemail.com>
>>>>>     on Mon, 3 Aug 2009 13:15:11 +0000 (UTC) writes:

    >> 
    HWB> Thanks for pointing out the weak point in this
    HWB> computation. I tried out your suggestions and they both
    HWB> deliver the correct and accurate result.

    HWB> But as a general solution this approach is not
    HWB> feasible. We want to provide "complex-step derivatives"
    HWB> as a new method for computing exact gradients, for
    HWB> example in 'numDeriv::grad' as

    HWB>     grad(fun, x, method="complex-step")

    HWB> and we can not reasonably assume that a user prepares
    HWB> his function specially for calling this method.

    HWB> I tried out other numerical math software besides
    HWB> Matlab, that is Octave, Scilab, Euler and others, and
    HWB> they all return the same correct value up to 15
    HWB> digits. Should we not expect that R is capable of doing
    HWB> the same?

R's  "a ^ b"  on non-Windows typically uses the C library's
'cpow()'  when that is provided  (HAVE_C99_COMPLEX).

Indeed, this seems to use the "general" complex power function
which loses a few bits -- unavoidably.
Our Windows-version of complex  a ^ b  does so as well.

Here's an R version of what (I believe) once was the C library
cpow(); at least I confirm that it has the same slight
inaccuracy [if you are as this very border line case with '1e-15';
	    use  1e-12  and you have no problems !! ]

Cpow <- function(a,b)
{
  ## Purpose: a ^ b  in complex
  ## Find bug in  complex_pow()
  ## -------------------------------------------------------------------------
  ## Author: Martin Maechler, Date: 15 Jan 2000, 21:33

    a <- as.complex(a)
    b <- as.complex(b)

    hypot <- function(x,y)Mod(x + 1i*y)

    logr <- log(hypot(Re(a), Im(a)) );
    logi <- atan2(Im(a), Re(a));
    x <- exp( logr * Re(b) - logi * Im(b) );
    y <- logr * Im(b) + logi * Re(b);

    x * complex(re= cos(y), im= sin(y))
}

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

So, yes we could check for the special case of  "^2" and use
multiplication and then for   " ^ n " and ... ...
and only otherwise call cpow(x,y) {or our own C-version of
that}.

I'm looking into implenting that now.
Expect to hear more about it within 24 hours.

Martin Maechler, ETH Zurich


    HWB> Hans W. Borchers


    HWB> Martin Becker <martin.becker <at> mx.uni-saarland.de>
    HWB> writes:

    >> 
    >> Dear Ravi,
    >> 
    >> the inaccuracy seems to creep in when powers are
    >> calculated. Apparently, some quite general function is
    >> called to calculate the squares, and one can avoid the
    >> error by reformulating the example as follows:
    >> 
    >> rosen <- function(x) { n <- length(x) x1 <- x[2:n] x2 <-
    >> x[1:(n-1)] sum(100*(x1-x2*x2)*(x1-x2*x2) + (1-x2)*(1-x2))
    >> }
    >> 
    >> x0 <- c(0.0094, 0.7146, 0.2179, 0.6883, 0.5757, 0.9549,
    >> 0.7136, 0.0849,
    HWB> 0.4147, 0.4540)
    >> h <- c(1.e-15*1i, 0, 0, 0, 0, 0, 0, 0, 0, 0) xh <- x0 + h
    >> 
    >> rx <- rosen(xh) Re(rx) Im (rx)
    >> 
    >> I don't know which arithmetics are involved in the
    >> application you mentioned, but writing some auxiliary
    >> function for the calculation of x^n when x is complex and
    >> n is (a not too large) integer may solve some of the
    >> numerical issues. A simple version is:
    >> 
    >> powN <- function(x,n) sapply(x,function(x)
    >> prod(rep(x,n)))
    >> 
    >> The corresponding summation in 'rosen' would then read:
    >> 
    >> sum(100*powN(x1-powN(x2,2),2) + powN(1-x2,2))
    >> 
    >> HTH,
    >> 
    >> Martin
    >> 

______________________________________________
    HWB> R-devel at r-project.org mailing list
    HWB> https://stat.ethz.ch/mailman/listinfo/r-devel



More information about the R-devel mailing list