[Rcpp-commits] r3325 - pkg/int64/inst/include/int64

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Sat Nov 12 11:18:41 CET 2011


Author: romain
Date: 2011-11-12 11:18:40 +0100 (Sat, 12 Nov 2011)
New Revision: 3325

Modified:
   pkg/int64/inst/include/int64/arith.h
Log:
arithmetic operators with NA handling

Modified: pkg/int64/inst/include/int64/arith.h
===================================================================
--- pkg/int64/inst/include/int64/arith.h	2011-11-12 09:27:48 UTC (rev 3324)
+++ pkg/int64/inst/include/int64/arith.h	2011-11-12 10:18:40 UTC (rev 3325)
@@ -20,17 +20,73 @@
     
 #ifndef int64__arith__h
 #define int64__arith__h
-              
+ 
+/* borrowed from R (arithmetic.c) */
+# define OPPOSITE_SIGNS(x, y) ((x < 0) ^ (y < 0))
+# define GOODISUM(x, y, z) (((x) > 0) ? ((y) < (z)) : ! ((y) < (z)))
+# define GOODIDIFF(x, y, z) (!(OPPOSITE_SIGNS(x, y) && OPPOSITE_SIGNS(x, z)))
+# define GOODIPROD(x, y, z) ((long double) (x) * (long double) (y) == (z))
+
+
 namespace int64{
     namespace internal{
 
-template <typename T> inline T plus(T x1,T x2){ return x1 + x2 ; }        
-template <typename T> inline T minus(T x1,T x2){ return x1 - x2 ; }        
-template <typename T> inline T times(T x1,T x2){ return x1 * x2 ; }        
-template <typename T> inline T divide(T x1,T x2){ return x1/x2 ; }        
-template <typename T> inline T modulo(T x1,T x2){ return x1 % x2 ; }        
-template <typename T> inline T int_div(T x1,T x2){ return x1 / x2 ; }        
+template <typename T> inline T plus(T x1,T x2){ 
+    const T na = int64::LongVector<T>::na ;
+    if( x1 == na || x2 == na ){
+        return na ;
+    }
+    T res = x1 + x2 ;
+    if (res != na && GOODISUM(x1, x2, res)){
+        return res ;
+    } 
+    return na ;
+}        
+template <typename T> inline T minus(T x1,T x2){ 
+    const T na = int64::LongVector<T>::na ;
+    if( x1 == na || x2 == na){
+        return na ;
+    }
+    T res = x1 - x2 ;
+    if( res != na  && GOODIDIFF(x1,x2,res) ){
+        return res ;
+    }
+    return na ;
         
+}        
+template <typename T> inline T times(T x1,T x2){ 
+    const T na = int64::LongVector<T>::na ;
+    if( x1 == na || x2 == na){
+        return na ;
+    }
+    T res = x1 * x2 ;
+    if( res != na && GOODIPROD(x1,x2,res)){
+        return res ;
+    }
+    return na ;
+}        
+template <typename T> inline T divide(T x1,T x2){ 
+    const T na = int64::LongVector<T>::na ;
+    if( x1 == na || x2 == na ){
+        return na ;
+    }
+    return x1/x2 ;
+}        
+template <typename T> inline T modulo(T x1,T x2){ 
+    const T na = int64::LongVector<T>::na ;
+    if( x1 == na || x2 == na ){
+        return na ;
+    }
+    return x1 % x2 ;
+}        
+template <typename T> inline T int_div(T x1,T x2){ 
+    const T na = int64::LongVector<T>::na ;
+    if( x1 == na || x2 == na ){
+        return na ;
+    }
+    return x1 / x2 ;
+}        
+        
 template <typename LONG, LONG Fun(LONG x1, LONG x2)>
 SEXP arith_long_long(SEXP e1, SEXP e2){
     int64::LongVector<LONG> x1( e1 ) ;



More information about the Rcpp-commits mailing list