(-2) %% 12 --- was a bug fix in 0.63.3 {{and musings about S ..}}

Martin Maechler Martin Maechler <maechler@stat.math.ethz.ch>
Wed, 24 Mar 1999 11:37:24 +0100


>>>>> "PaulG" == Paul Gilbert <pgilbert@bank-banque-canada.ca> writes:

    PaulG> (-2) %% 12 seems to give the wrong result in R pre 63.3:
    >> e1 <- -2 ;  e2 <- 12  ; e1 %% e2
    PaulG> [1] -2
    >> e1 - floor(e1/e2) * e2
    PaulG> [1] 10

    PaulG> In Splus:
    >> e1 <- -2 ; e2 <- 12 ;  e1 %% e2
    PaulG> [1] 10
    >> e1 - floor(e1/e2) * e2
    PaulG> [1] 10

Thank you, Paul, for bringing up this topic (again).

Short answer:  
      This is has been changed in 0.63.3
      and is mentioned in the "Bug Fixes" part of NEWS (and was even on R-announce!)
      NEWS>>
      NEWS>>   o   a %% b -- is now periodic instead of symmetric; more S compatible.
      NEWS>>



Longer answer:

      There are two problems:

      1) ANSI C leaves the semantics of "a % b" (corresponding to R's "a %% b")
	 UNDEFINED whenever one of a or b is negative.

	 IMHO, this *is* a horrible fact  (showing how little some computer scientists
					   care about mathematical computing..).

         Older versions of R used to do what you mention above which is
         what C (and hence R) do on at least Solaris and Linux-Intel.


      2) S-plus  DOES give different answers __solely__ depending on the
         storage.mode  of  a (and/or b)

	 [being on the S version 4  mailing list, I've tried to start a
	  discussion on this,about a year ago, but nobody has even answered me...
	 So, the problem was not addressed for S-plus 5 and hence probably never will]

	 This is S-plus (any version AFAIK; certainly both 3.4 and 5.0 for Unix)

	    > version
	    Version 3.4 Release 1 for Sun SPARC, SunOS 5.3 : 1996 
	    > d3 <- as.numeric(3) # 'd' for double
	    > i3 <- as.integer(3)

	    ## These two differ, but I think they should not ...
	    > d3 %% c(-5:4)
	     [1] -2 -1  0 -1  0  3  0  1  0  3
	    > i3 %% c(-5:4)
	     [1] 3 3 0 1 0 3 0 1 0 3

	    > (-d3) %% c(-5:4)
	     [1] -3 -3  0 -1  0 -3  0  1  0  1
	    > (-i3) %% c(-5:4)
	     [1]  2  1  0  1  0 -3  0  1  0  1
	    > 

---

The Current [0.63.3, but not earlier] and future versions of R
will be consistent and deliver

    R> d3 <- as.numeric(3) # 'd' for double
    R> i3 <- as.integer(3)

    R> ## These two differ, but I think they should not ...
    R> d3 %% c(-5:4) # -2 -1  0 -1  0  3  0  1  0  3
     [1]  -2  -1   0  -1   0 NaN   0   1   0   3
    R> i3 %% c(-5:4) #  3  3  0  1  0  3  0  1  0  3
     [1] -2 -1  0 -1  0 NA  0  1  0  3

    R> (-d3) %% c(-5:4)# -3 -3  0 -1  0 -3  0  1  0  1
     [1]  -3  -3   0  -1   0 NaN   0   1   0   1
    R> (-i3) %% c(-5:4)#  2  1  0  1  0 -3  0  1  0  1
     [1] -3 -3  0 -1  0 NA  0  1  0  1
    R> 

Note that R's result now is the same, not depending on the storage.mode of
a or b.

The help page on "%%" now has a section
 
    `%%' indicates `x mod y' and `%/%' indicates integer
     division. It is guaranteed that `x  ==  (x %% y)  +  y
     * ( x %/% y )' unless `y == 0' where the result is `NA'
     or `NaN' (depending on the `typeof' of the arguments).

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

Remark:

 In S version 4 (and S-plus 5.0)

    "3" or "-3" are integers  whereas they used to be
    "numeric", i.e., "double" in Sv3 (i.e. S-plus x.y with x <= 4).

 Consequence:  S(plus)  ``seems to'' be non backward compatible even in
	       this low level aspect:

    Version 5.0 Release 3 for Sun SPARC, SunOS 5.5 : 1998   gives
	    > 11 %% -3
	    [1] 2
    whereas  Version 3.4 Release 1 for Sun SPARC, SunOS 5.3 : 1996   gives
	     > 11 %% -3
	     [1] -1

  (and I still don't understand why nobody on the S version 4 beta list
   had answered my concern then ...)

Martin
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-devel-request@stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._