Henrik Bengtsson
2008-Feb-27 06:03 UTC
[Rd] Warnings generated by log2()/log10() are really large/takes a long time to display
x <- rnorm(1e6); y <- log(x); # or logb(x) or log1p(x) w <- warnings(); print(object.size(w)); ## [1] 480 str(w); $ NaNs produced: language log(x) - attr(*, "dots")= list() - attr(*, "class")= chr "warnings" y <- log2(x); # or log10(x) w <- warnings(); print(object.size(w)); ## [1] 8000536 str(w); ## List of 1 ## $ NaNs produced: language log(c(2.12082478659910, 1.40263187453398, 1.574125429 ## 83486, -0.816399069824751, 0.215940065840533, 1.20975177084379, -0.340287874362 ## 813, 0.117151537611550, ... ## - attr(*, "dots")= list() ## - attr(*, "class")= chr "warnings" Note also how long it takes to display and str() the warning. I have observed this on R v2.6.2 and R v2.7.0 (2008-02-11 r44432) on both WinXP and Linux. /Henrik
Martin Maechler
2008-Feb-27 08:44 UTC
[Rd] Warnings generated by log2()/log10() are really large/takes a long time to display
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