From 960830e3af03a796747f12b2eeac4cbf41970ed0 Mon Sep 17 00:00:00 2001 From: nathan-russell Date: Mon, 24 Oct 2016 14:55:36 -0400 Subject: [PATCH 1/2] Refactoring of eye, ones, and zeros --- ChangeLog | 12 +- inst/NEWS.Rd | 6 +- inst/include/Rcpp/sugar/matrix/eye.h | 159 ------------------ .../Rcpp/sugar/matrix/matrix_functions.h | 1 - inst/include/Rcpp/traits/one_type.h | 78 +++++++++ inst/include/Rcpp/traits/traits.h | 2 + inst/include/Rcpp/vector/MatrixBase.h | 37 +++- inst/unitTests/cpp/Matrix.cpp | 66 ++++++++ inst/unitTests/cpp/sugar.cpp | 65 ------- inst/unitTests/runit.Matrix.R | 90 ++++++++++ inst/unitTests/runit.sugar.R | 91 ---------- 11 files changed, 285 insertions(+), 322 deletions(-) delete mode 100644 inst/include/Rcpp/sugar/matrix/eye.h create mode 100644 inst/include/Rcpp/traits/one_type.h diff --git a/ChangeLog b/ChangeLog index 9105547aa..89c56cdd6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2016-10-24 Nathan Russell + + * inst/include/Rcpp/vector/MatrixBase.h: Change sugar + functions eye(), ones(), and zeros() into static methods + in MatrixBase + * inst/include/Rcpp/traits/one_type.h: Idem + * inst/include/Rcpp/traits/traits.h: Idem + * inst/unitTests/cpp/Matrix.cpp: Idem + * inst/unitTests/runit.Matrix.R: Idem + 2016-10-23 Nathan Russell * inst/include/Rcpp/sugar/matrix/eye.h: New functions @@ -7,12 +17,12 @@ * inst/unitTests/runit.sugar.R: Idem * inst/unitTests/runit.dispatch.R (test.ExpressionVector): Use expression rather than parse, correct typo + 2016-10-22 Qiang Kou * inst/include/Rcpp/hash/IndexHash.h: change hashing function to return unsigned int * inst/include/Rcpp/hash/SelfHash.h: Ditto - 2016-10-21 Qiang Kou * inst/include/Rcpp/barrier.h: Change string_elt/vector_elt to accept R_xlen_t diff --git a/inst/NEWS.Rd b/inst/NEWS.Rd index 3c018679e..588500804 100644 --- a/inst/NEWS.Rd +++ b/inst/NEWS.Rd @@ -9,15 +9,15 @@ \itemize{ \item String and vector elements now use extended \code{R_xlen_t} indices (Qiang in PR \ghpr{560}) - \item Hashing functions now return unsigned int (Qiang in PR \ghpr{561}) + \item Hashing functions now return unsigned int (Qiang in PR \ghpr{561}) + \item Added static methods \code{eye()}, \code{ones()}, and \code{zeros()} + for select matrix types (Nathan Russell in PR \ghpr{569}) } \item Changes in Rcpp Sugar: \itemize{ \item Added new Sugar functions \code{rowSums()}, \code{colSums()}, \code{rowMeans()}, \code{colMeans()} (PR \ghpr{551} by Nathan Russell fixing \ghit{549}) - \item Added new (matrix) Sugar functions \code{eye()}, - \code{ones()}, \code{zeros()} (PR \ghpr{566} by Nathan Russell) } \item Changes in Rcpp unit tests \itemize{ diff --git a/inst/include/Rcpp/sugar/matrix/eye.h b/inst/include/Rcpp/sugar/matrix/eye.h deleted file mode 100644 index a498fdf24..000000000 --- a/inst/include/Rcpp/sugar/matrix/eye.h +++ /dev/null @@ -1,159 +0,0 @@ -// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- -// -// eye.h: Rcpp R/C++ interface class library -- eye, ones, zeros -// -// Copyright (C) 2016 Nathan Russell -// -// This file is part of Rcpp. -// -// Rcpp is free software: you can redistribute it and/or modify it -// under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// Rcpp is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Rcpp. If not, see . - -#ifndef Rcpp__sugar__eye_h -#define Rcpp__sugar__eye_h - -namespace Rcpp { -namespace traits { - -template -struct allowed_matrix_type; - -template<> -struct allowed_matrix_type {}; - -template -class one_type { -private: - Rcomplex op(true_type) const { - Rcomplex res; - res.i = 0.0; - res.r = 1.0; - return res; - } - - T op(false_type) const { - return static_cast(1); - } - -public: - operator T() const { - return op(typename same_type::type()); - } -}; - -template -class zero_type { -private: - Rcomplex op(true_type) const { - Rcomplex res; - res.i = 0.0; - res.r = 0.0; - return res; - } - - T op(false_type) const { - return static_cast(0); - } - -public: - operator T() const { - return op(typename same_type::type()); - } -}; - -} // traits - -class eye { -private: - int n; - -public: - eye(const int n_) - : n(n_) - {} - - template - operator Matrix() const { - typedef typename traits::storage_type::type stored_type; - - const bool enabled = - traits::is_arithmetic::value || - traits::same_type::value; - - (void)sizeof(traits::allowed_matrix_type); - - typedef traits::one_type one_type; - - return Matrix::diag(n, one_type()); - } -}; - -class ones { -private: - int n; - -public: - ones(const int n_) - : n(n_) - {} - - template - operator Matrix() const { - typedef typename traits::storage_type::type stored_type; - - const bool enabled = - traits::is_arithmetic::value || - traits::same_type::value; - - (void)sizeof(traits::allowed_matrix_type); - - typedef traits::one_type one_type; - - Matrix res(n, n); - std::fill(res.begin(), res.end(), one_type()); - - return res; - } -}; - -class zeros { -private: - int n; - -public: - zeros(const int n_) - : n(n_) - {} - - template - operator Matrix() const { - typedef typename traits::storage_type::type stored_type; - - const bool enabled = - traits::is_arithmetic::value || - traits::same_type::value; - - (void)sizeof(traits::allowed_matrix_type); - - typedef traits::zero_type zero_type; - - Matrix res(n, n); - std::fill(res.begin(), res.end(), zero_type()); - - return res; - } -}; - -} // Rcpp - -#endif // Rcpp__sugar__eye_h diff --git a/inst/include/Rcpp/sugar/matrix/matrix_functions.h b/inst/include/Rcpp/sugar/matrix/matrix_functions.h index 6e595f67e..1635f634c 100644 --- a/inst/include/Rcpp/sugar/matrix/matrix_functions.h +++ b/inst/include/Rcpp/sugar/matrix/matrix_functions.h @@ -29,6 +29,5 @@ #include #include #include -#include #endif diff --git a/inst/include/Rcpp/traits/one_type.h b/inst/include/Rcpp/traits/one_type.h new file mode 100644 index 000000000..4627cf5ea --- /dev/null +++ b/inst/include/Rcpp/traits/one_type.h @@ -0,0 +1,78 @@ +// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- +// +// one_type.h: Rcpp R/C++ interface class library -- traits functions for eye, ones, zeros +// +// Copyright (C) 2016 Nathan Russell +// +// This file is part of Rcpp. +// +// Rcpp is free software: you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// Rcpp is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Rcpp. If not, see . + +#ifndef Rcpp__traits__one_type__h +#define Rcpp__traits__one_type__h + +namespace Rcpp { +namespace traits { + +template +struct allowed_matrix_type; + +template <> +struct allowed_matrix_type {}; + +template +class one_type { +private: + Rcomplex op(true_type) const { + Rcomplex res; + res.i = 0.0; + res.r = 1.0; + return res; + } + + T op(false_type) const { + return static_cast(1); + } + +public: + operator T() const { + return op(typename same_type::type()); + } +}; + +template +class zero_type { +private: + Rcomplex op(true_type) const { + Rcomplex res; + res.i = 0.0; + res.r = 0.0; + return res; + } + + T op(false_type) const { + return static_cast(0); + } + +public: + operator T() const { + return op(typename same_type::type()); + } +}; + +} // traits +} // Rcpp + +#endif // Rcpp__traits__one_type__h + diff --git a/inst/include/Rcpp/traits/traits.h b/inst/include/Rcpp/traits/traits.h index b60151660..c10b22853 100644 --- a/inst/include/Rcpp/traits/traits.h +++ b/inst/include/Rcpp/traits/traits.h @@ -76,5 +76,7 @@ struct int2type { enum { value = I }; }; #include #include +#include + #endif diff --git a/inst/include/Rcpp/vector/MatrixBase.h b/inst/include/Rcpp/vector/MatrixBase.h index 225130a26..96decae33 100644 --- a/inst/include/Rcpp/vector/MatrixBase.h +++ b/inst/include/Rcpp/vector/MatrixBase.h @@ -2,8 +2,9 @@ // // MatrixBase.h: Rcpp R/C++ interface class library -- // -// Copyright (C) 2010 - 2013 Dirk Eddelbuettel and Romain Francois -// +// Copyright (C) 2010 - 2016 Dirk Eddelbuettel and Romain Francois +// Copyright (C) 2016 Dirk Eddelbuettel and Romain Francois and Nathan Russell +// // This file is part of Rcpp. // // Rcpp is free software: you can redistribute it and/or modify it @@ -47,6 +48,38 @@ namespace Rcpp{ inline R_xlen_t nrow() const { return static_cast(*this).nrow() ; } inline R_xlen_t ncol() const { return static_cast(*this).ncol() ; } + static MATRIX eye(int n) { + const bool enabled = + traits::is_arithmetic::value || + traits::same_type::value; + (void)sizeof(traits::allowed_matrix_type); + + return MATRIX::diag(n, traits::one_type()); + } + + static MATRIX ones(int n) { + const bool enabled = + traits::is_arithmetic::value || + traits::same_type::value; + (void)sizeof(traits::allowed_matrix_type); + + MATRIX res(n, n); + std::fill( + res.begin(), res.end(), + traits::one_type() + ); + return res; + } + + static MATRIX zeros(int n) { + const bool enabled = + traits::is_arithmetic::value || + traits::same_type::value; + (void)sizeof(traits::allowed_matrix_type); + + return MATRIX(n, n); + } + class iterator { public: typedef stored_type reference ; diff --git a/inst/unitTests/cpp/Matrix.cpp b/inst/unitTests/cpp/Matrix.cpp index f26a9c81f..a6f387dd8 100644 --- a/inst/unitTests/cpp/Matrix.cpp +++ b/inst/unitTests/cpp/Matrix.cpp @@ -331,3 +331,69 @@ NumericMatrix matrix_scalar_divide(const NumericMatrix & x, double y) { NumericMatrix matrix_scalar_divide2(const NumericMatrix & x, double y) { return y / x; } + +// 24 October 2016 +// eye, ones, and zeros static member functions + +// [[Rcpp::export]] +Rcpp::NumericMatrix dbl_eye(int n) { + return Rcpp::NumericMatrix::eye(n); +} + +// [[Rcpp::export]] +Rcpp::IntegerMatrix int_eye(int n) { + return Rcpp::IntegerMatrix::eye(n); +} + +// [[Rcpp::export]] +Rcpp::ComplexMatrix cx_eye(int n) { + return Rcpp::ComplexMatrix::eye(n); +} + +// [[Rcpp::export]] +Rcpp::LogicalMatrix lgl_eye(int n) { + return Rcpp::LogicalMatrix::eye(n); +} + + +// [[Rcpp::export]] +Rcpp::NumericMatrix dbl_ones(int n) { + return Rcpp::NumericMatrix::ones(n); +} + +// [[Rcpp::export]] +Rcpp::IntegerMatrix int_ones(int n) { + return Rcpp::IntegerMatrix::ones(n); +} + +// [[Rcpp::export]] +Rcpp::ComplexMatrix cx_ones(int n) { + return Rcpp::ComplexMatrix::ones(n); +} + +// [[Rcpp::export]] +Rcpp::LogicalMatrix lgl_ones(int n) { + return Rcpp::LogicalMatrix::ones(n); +} + + +// [[Rcpp::export]] +Rcpp::NumericMatrix dbl_zeros(int n) { + return Rcpp::NumericMatrix::zeros(n); +} + +// [[Rcpp::export]] +Rcpp::IntegerMatrix int_zeros(int n) { + return Rcpp::IntegerMatrix::zeros(n); +} + +// [[Rcpp::export]] +Rcpp::ComplexMatrix cx_zeros(int n) { + return Rcpp::ComplexMatrix::zeros(n); +} + +// [[Rcpp::export]] +Rcpp::LogicalMatrix lgl_zeros(int n) { + return Rcpp::LogicalMatrix::zeros(n); +} + diff --git a/inst/unitTests/cpp/sugar.cpp b/inst/unitTests/cpp/sugar.cpp index 0a671584e..0327953d0 100644 --- a/inst/unitTests/cpp/sugar.cpp +++ b/inst/unitTests/cpp/sugar.cpp @@ -1116,68 +1116,3 @@ Rcpp::ComplexVector cx_col_means(Rcpp::ComplexMatrix x, bool na_rm = false) { return colMeans(x, na_rm); } - -// 23 October 2016 -// non-member eye, ones, and zeros functions - -// [[Rcpp::export]] -Rcpp::NumericMatrix dbl_eye(int n) { - return Rcpp::eye(n); -} - -// [[Rcpp::export]] -Rcpp::IntegerMatrix int_eye(int n) { - return Rcpp::eye(n); -} - -// [[Rcpp::export]] -Rcpp::ComplexMatrix cx_eye(int n) { - return Rcpp::eye(n); -} - -// [[Rcpp::export]] -Rcpp::LogicalMatrix lgl_eye(int n) { - return Rcpp::eye(n); -} - - -// [[Rcpp::export]] -Rcpp::NumericMatrix dbl_ones(int n) { - return Rcpp::ones(n); -} - -// [[Rcpp::export]] -Rcpp::IntegerMatrix int_ones(int n) { - return Rcpp::ones(n); -} - -// [[Rcpp::export]] -Rcpp::ComplexMatrix cx_ones(int n) { - return Rcpp::ones(n); -} - -// [[Rcpp::export]] -Rcpp::LogicalMatrix lgl_ones(int n) { - return Rcpp::ones(n); -} - - -// [[Rcpp::export]] -Rcpp::NumericMatrix dbl_zeros(int n) { - return Rcpp::zeros(n); -} - -// [[Rcpp::export]] -Rcpp::IntegerMatrix int_zeros(int n) { - return Rcpp::zeros(n); -} - -// [[Rcpp::export]] -Rcpp::ComplexMatrix cx_zeros(int n) { - return Rcpp::zeros(n); -} - -// [[Rcpp::export]] -Rcpp::LogicalMatrix lgl_zeros(int n) { - return Rcpp::zeros(n); -} diff --git a/inst/unitTests/runit.Matrix.R b/inst/unitTests/runit.Matrix.R index d3af0ce98..e40201e8a 100644 --- a/inst/unitTests/runit.Matrix.R +++ b/inst/unitTests/runit.Matrix.R @@ -249,4 +249,94 @@ if (.runThisTest) { checkEquals(matrix_scalar_divide(M, 2), M / 2, msg="matrix / scalar") checkEquals(matrix_scalar_divide2(M, 2), 2 / M, msg="scalar / matrix") } + + ## 23 October 2016 + ## eye function + test.Matrix.eye <- function() { + + checkEquals( + dbl_eye(3), + diag(1.0, 3, 3), + "eye - numeric" + ) + + checkEquals( + int_eye(3), + diag(1L, 3, 3), + "eye - integer" + ) + + checkEquals( + cx_eye(3), + diag(1.0 + 0i, 3, 3), + "eye - complex" + ) + + ## diag(TRUE, 3, 3) was registering as + ## a numeric matrix on Travis for some reason + mat <- matrix(FALSE, 3, 3) + diag(mat) <- TRUE + checkEquals( + lgl_eye(3), + mat, + "eye - logical" + ) + } + + ## ones function + test.Matrix.ones <- function() { + + checkEquals( + dbl_ones(3), + matrix(1.0, 3, 3), + "ones - numeric" + ) + + checkEquals( + int_ones(3), + matrix(1L, 3, 3), + "ones - integer" + ) + + checkEquals( + cx_ones(3), + matrix(1.0 + 0i, 3, 3), + "ones - complex" + ) + + checkEquals( + lgl_ones(3), + matrix(TRUE, 3, 3), + "ones - logical" + ) + } + + ## zeros function + test.Matrix.zeros <- function() { + + checkEquals( + dbl_zeros(3), + matrix(0.0, 3, 3), + "zeros - numeric" + ) + + checkEquals( + int_zeros(3), + matrix(0L, 3, 3), + "zeros - integer" + ) + + checkEquals( + cx_zeros(3), + matrix(0.0 + 0i, 3, 3), + "zeros - complex" + ) + + checkEquals( + lgl_zeros(3), + matrix(FALSE, 3, 3), + "zeros - logical" + ) + } + } diff --git a/inst/unitTests/runit.sugar.R b/inst/unitTests/runit.sugar.R index b1c9a4435..f4b4c7939 100644 --- a/inst/unitTests/runit.sugar.R +++ b/inst/unitTests/runit.sugar.R @@ -1610,95 +1610,4 @@ if (.runThisTest) { } - - ## 23 October 2016 - ## sugar eye function - test.sugar.eye <- function() { - - checkEquals( - dbl_eye(3), - diag(1.0, 3, 3), - "eye - numeric" - ) - - checkEquals( - int_eye(3), - diag(1L, 3, 3), - "eye - integer" - ) - - checkEquals( - cx_eye(3), - diag(1.0 + 0i, 3, 3), - "eye - complex" - ) - - ## diag(TRUE, 3, 3) was registering as - ## a numeric matrix on Travis for some reason - mat <- matrix(FALSE, 3, 3) - diag(mat) <- TRUE - checkEquals( - lgl_eye(3), - mat, - "eye - logical" - ) - } - - ## sugar ones function - test.sugar.ones <- function() { - - checkEquals( - dbl_ones(3), - matrix(1.0, 3, 3), - "ones - numeric" - ) - - checkEquals( - int_ones(3), - matrix(1L, 3, 3), - "ones - integer" - ) - - checkEquals( - cx_ones(3), - matrix(1.0 + 0i, 3, 3), - "ones - complex" - ) - - checkEquals( - lgl_ones(3), - matrix(TRUE, 3, 3), - "ones - logical" - ) - } - - ## sugar ones function - test.sugar.zeros <- function() { - - checkEquals( - dbl_zeros(3), - matrix(0.0, 3, 3), - "zeros - numeric" - ) - - checkEquals( - int_zeros(3), - matrix(0L, 3, 3), - "zeros - integer" - ) - - checkEquals( - cx_zeros(3), - matrix(0.0 + 0i, 3, 3), - "zeros - complex" - ) - - checkEquals( - lgl_zeros(3), - matrix(FALSE, 3, 3), - "zeros - logical" - ) - } - } - From e696eea7d0b21202b3cb60f3df4f13760b5295e1 Mon Sep 17 00:00:00 2001 From: nathan-russell Date: Mon, 24 Oct 2016 15:57:21 -0400 Subject: [PATCH 2/2] Merge upstream changes --- ChangeLog | 1 + inst/NEWS.Rd | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index e2443b07f..e54cd7e92 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,7 @@ * inst/include/Rcpp/traits/traits.h: Idem * inst/unitTests/cpp/Matrix.cpp: Idem * inst/unitTests/runit.Matrix.R: Idem + 2016-10-24 Qiang Kou * inst/include/Rcpp/sugar/Range.h: Range sugar uses R_xlen_t as start/end type diff --git a/inst/NEWS.Rd b/inst/NEWS.Rd index a28a9b651..4c167d83d 100644 --- a/inst/NEWS.Rd +++ b/inst/NEWS.Rd @@ -18,8 +18,6 @@ \item Added new Sugar functions \code{rowSums()}, \code{colSums()}, \code{rowMeans()}, \code{colMeans()} (PR \ghpr{551} by Nathan Russell fixing \ghit{549}) - \item Added new (matrix) Sugar functions \code{eye()}, - \code{ones()}, \code{zeros()} (PR \ghpr{566} by Nathan Russell) \item \code{Range} Sugar now used \code{R_xlen_t} type for start/end (PR \ghpr{568} by Qiang Kou) }