From maechler at stat.math.ethz.ch  Wed Feb 27 09:44:44 2008
From: maechler at stat.math.ethz.ch (Martin Maechler)
Date: Wed, 27 Feb 2008 09:44:44 +0100
Subject: [Rd] Warnings generated by log2()/log10() are really
	large/takes a long time to display
In-Reply-To: <59d7961d0802262203y16b6b24dmebca4a29deca59f5@mail.gmail.com>
References: <59d7961d0802262203y16b6b24dmebca4a29deca59f5@mail.gmail.com>
Message-ID: <18373.8956.152890.662124@stat.math.ethz.ch>

Thank you Henrik,

>>>>> "HenrikB" == Henrik Bengtsson <hb at stat.berkeley.edu>
>>>>>     on Tue, 26 Feb 2008 22:03:24 -0800 writes:

{with many superfluous empty statements ( i.e., trailing ";" ):

    HenrikB> x <- rnorm(1e6);

    [................]


    HenrikB> y <- log2(x);  # or log10(x)
    HenrikB> w <- warnings();
    HenrikB> print(object.size(w));
    HenrikB> ## [1] 8000536
    HenrikB> str(w);
    HenrikB> ## List of 1
    HenrikB> ##  $ NaNs produced: language log(c(2.12082478659910,
    HenrikB> 1.40263187453398, 1.574125429
    HenrikB> ## 83486, -0.816399069824751,  0.215940065840533, 1.20975177084379,
    HenrikB> -0.340287874362
    HenrikB> ## 813, 0.117151537611550,  ...
    HenrikB> ##  - attr(*, "dots")= list()
    HenrikB> ##  - attr(*, "class")= chr "warnings"

    HenrikB> Note also how long it takes to display and str() the warning.

Yes, indeed.
It's a subtle problem and happens
because in do_log1arg() a new call is constructed in which 'x'
has already been evaluated.

A subtle fix to the subtle problem
is to replace  CAR(args) by CADR(call) in there

--- arithmetic.c	(Revision 44626)
+++ arithmetic.c	(working copy)
@@ -1372,7 +1372,9 @@
     if(PRIMVAL(op) == 10) tmp = ScalarReal(10.0);
     if(PRIMVAL(op) == 2)  tmp = ScalarReal(2.0);
 
-    PROTECT(Call = lang3(install("log"), CAR(args), tmp));
+    /* CADR(call) instead of CAR(args), since 'args' have been
+     * evaluated in Dispatch*(..) above : */
+    PROTECT(Call = lang3(install("log"), CADR(call), tmp));
     res = eval(Call, env);
     UNPROTECT(1);
     return res;

-----

That does fix the problem you've reported (and passes "make check")
but I'm not quite at ease with it, since it will lead to
effectively evaluate the argument *twice*.

A different approach that I'd find cleaner
would be to *not* construct and eval() a
new Call inside do_log1arg, but I assume there had been a good
reason for doing things they way they are now...

Martin Maechler, ETH Zurich



[Rd] Warnings generated by log2()/log10() are really large/takes a long time to display
Martin Maechler