Skip to content

Commit 0010c56

Browse files
committed
Merge pull request #320 from MattPD/patch-4
Update var.h
2 parents 384e7e4 + 912ad87 commit 0010c56

File tree

4 files changed

+42
-22
lines changed

4 files changed

+42
-22
lines changed

ChangeLog

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
2015-07-07 Matt P. Dziubinski <[email protected]>
2+
3+
* inst/include/Rcpp/sugar/functions/var.h: Variance -- changed from
4+
the unstable formula back to the stable (two-pass) formula, fixed
5+
support for complex numbers (formula correction).
6+
* inst/unitTests/runit.sugar.var.R: Added tests for complex variance
7+
computation, applied simple code refactoring.
8+
19
2015-07-04 Dirk Eddelbuettel <[email protected]>
210

311
* vignettes/Rcpp.bib: Updated reference to several CRAN packages
@@ -6,7 +14,7 @@
614

715
* .clang_format: Added
816

9-
2015-06-25 Kevin Ushey <[email protected]>
17+
2015-06-25 Kevin Ushey <[email protected]>
1018

1119
* inst/include/Rcpp/api/meat/Rcpp_eval.h: reset error after Rcpp_eval
1220
* inst/unitTests/cpp/Function.cpp: unit tests

inst/NEWS.Rd

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
\itemize{
99
\item All internal length variables have been changed from \code{R_len_t}
1010
to \code{R_xlen_t} to support vectors longer than 2^31-1 elements (via
11-
pull request 303 by Qiang Kou)
12-
\item The sugar function \code{sapply} now supports lambda functions
11+
pull request 303 by Qiang Kou).
12+
\item The sugar function \code{sapply} now supports lambda functions.
13+
\item The \code{var} sugar function now uses a more robust two-pass
14+
method, supports complex numbers, with new unit tests added.
1315
\item \code{String} constructors now allow encodings (via pull request 310
14-
by Qiang Kou)
16+
by Qiang Kou).
1517
}
1618
\item Changes in Rcpp Attributes:
1719
\itemize{

inst/include/Rcpp/sugar/functions/var.h

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@ class Var : public Lazy< double , Var<RTYPE,NA,T> > {
3434
Var( const VEC_TYPE& object_ ) : object(object_){}
3535

3636
double get() const{
37-
double
38-
m = mean(object).get(),
39-
ssq = sum( pow(object, 2.0) ).get();
40-
return (ssq - m * m * object.size()) / (object.size() - 1);
37+
const double average = mean(object).get();
38+
const R_xlen_t sample_size = object.size();
39+
double sum_squared_deviations = 0.0;
40+
for (R_xlen_t i = 0; i != sample_size; ++i)
41+
sum_squared_deviations += std::pow(object[i] - average, 2.0);
42+
return sum_squared_deviations / (sample_size - 1);
4143
}
4244

4345
private:
@@ -52,13 +54,14 @@ class Var<CPLXSXP,NA,T> : public Lazy< double , Var<CPLXSXP,NA,T> > {
5254
Var( const VEC_TYPE& object_ ) : object(object_){}
5355

5456
double get() const{
55-
double sq = 0, ssq = 0;
56-
for(R_xlen_t i = 0;i < object.size();i++) {
57-
Rcomplex z = object[i];
58-
sq += z.r;
59-
ssq += z.r * z.r;
57+
const Rcomplex average = mean(object).get();
58+
const R_xlen_t sample_size = object.size();
59+
double sum_squared_deviations_magnitudes = 0.0;
60+
for (R_xlen_t i = 0; i != sample_size; ++i) {
61+
const Rcomplex deviation = object[i] - average;
62+
sum_squared_deviations_magnitudes += deviation.r * deviation.r + deviation.i * deviation.i;
6063
}
61-
return (ssq - sq * sq / object.size()) / (object.size() - 1);
64+
return sum_squared_deviations_magnitudes / (sample_size - 1);
6265
}
6366

6467
private:

inst/unitTests/runit.sugar.var.R

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,21 @@
2323
if (.runThisTest) {
2424

2525
test.Sugar.var <- function() {
26-
f1 <- Rcpp::cppFunction('double myVar(NumericVector x) { return(var(x)); }')
27-
f2 <- Rcpp::cppFunction('double myVar(IntegerVector x) { return(var(x)); }')
28-
f3 <- Rcpp::cppFunction('double myVar(ComplexVector x) { return(var(x)); }')
29-
f4 <- Rcpp::cppFunction('double myVar(LogicalVector x) { return(var(x)); }')
30-
checkEquals(f1((1:10) * 1.1), var((1:10) * 1.1))
31-
checkEquals(f2(1:10), var(1:10))
32-
checkEquals(f3(1:10 + (1 + 1i)), var(1:10 + (1 + 1i)))
33-
checkEquals(f4(c(T, F, T, F, T)), var(c(T, F, T, F, T)))
26+
fNumeric <- Rcpp::cppFunction('double myVar(NumericVector x) { return(var(x)); }')
27+
fInteger <- Rcpp::cppFunction('double myVar(IntegerVector x) { return(var(x)); }')
28+
fComplex <- Rcpp::cppFunction('double myVar(ComplexVector x) { return(var(x)); }')
29+
fLogical <- Rcpp::cppFunction('double myVar(LogicalVector x) { return(var(x)); }')
30+
test_data_real <- 1:10
31+
checkEquals(fNumeric(test_data_real * 1.1), var(test_data_real * 1.1))
32+
checkEquals(fInteger(test_data_real), var(test_data_real))
33+
test_data_complex_1 <- complex(real = 5:1, imag = 2:6)
34+
test_data_complex_2 <- complex(real = 1:5, imag = 6:10)
35+
test_data_complex_1_known_var <- 5
36+
test_data_complex_2_known_var <- 5
37+
checkEquals(fComplex(test_data_complex_1), test_data_complex_1_known_var)
38+
checkEquals(fComplex(test_data_complex_2), test_data_complex_2_known_var)
39+
test_data_logical <- c(TRUE, FALSE, TRUE, FALSE, TRUE)
40+
checkEquals(fLogical(test_data_logical), var(test_data_logical))
3441
}
3542

3643
}

0 commit comments

Comments
 (0)