├── .Rbuildignore ├── .gitignore ├── .travis.yml ├── DESCRIPTION ├── Doxyfile ├── NAMESPACE ├── R ├── RcppExports.R ├── plugin.R └── unit.tests.R ├── README.md ├── RcppHoney.Rproj ├── configure ├── doxygen ├── LICENSE ├── customdoxygen.css ├── doxy-boot.js ├── footer.html └── header.html ├── inst ├── include │ ├── RcppHoney.hpp │ ├── RcppHoney │ │ ├── binary_operator.hpp │ │ ├── bind.hpp │ │ ├── default_hooks.hpp │ │ ├── exceptions.hpp │ │ ├── functions.hpp │ │ ├── functors.hpp │ │ ├── hook.hpp │ │ ├── na.hpp │ │ ├── operand.hpp │ │ ├── operators.hpp │ │ ├── scalar_operator.hpp │ │ ├── storage.hpp │ │ ├── traits │ │ │ ├── ctype.hpp │ │ │ ├── enable_if.hpp │ │ │ ├── if_else.hpp │ │ │ ├── integral_constant.hpp │ │ │ ├── is_primitive.hpp │ │ │ ├── result_of.hpp │ │ │ └── widest_numeric_type.hpp │ │ └── unary_operator.hpp │ └── RcppHoneyForward.hpp ├── tools │ └── r-stripper │ │ ├── stripper │ │ └── stripper.R └── unitTests │ ├── cpp │ ├── functions.cpp │ └── operators.cpp │ ├── runTests.R │ ├── runit.functions.R │ └── runit.operators.R ├── man └── example_manually_hooked.Rd ├── src ├── Makevars ├── RcppExports.cpp ├── annoyance.c └── examples.cpp ├── tests └── doRUnit.R └── vignettes ├── functions.Rmd └── introduction.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^\.travis\.yml$ 4 | ^doxygen.*$ 5 | ^Doxyfile$ 6 | ^README.md$ 7 | ^src/Makevars\.R_STRIP_LINKER_OPTION\.bak$ 8 | ^doc 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | src/*.o 6 | src/*.so 7 | src/*.dll 8 | src/symbols.rds 9 | src/Makevars.R_STRIP_LINKER_OPTION.bak 10 | doc 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # See the r-travis repo and its wiki 2 | # https://github.com/eddelbuettel/r-travis/ 3 | 4 | language: c 5 | 6 | sudo: required 7 | 8 | dist: trusty 9 | 10 | before_install: 11 | - curl -OLs http://eddelbuettel.github.io/r-travis/run.sh && chmod 0755 run.sh 12 | - ./run.sh bootstrap 13 | 14 | install: 15 | - ./run.sh install_r Rcpp 16 | - ./run.sh install_aptget r-cran-runit r-cran-knitr r-cran-rmarkdown 17 | 18 | script: 19 | - ./run.sh run_tests 20 | 21 | after_failure: 22 | - ./run.sh dump_logs 23 | 24 | notifications: 25 | email: 26 | on_success: change 27 | on_failure: change 28 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: RcppHoney 2 | Type: Package 3 | Title: Iterator Based Expression Template Expansion of Standard Operators 4 | Version: 0.1.7 5 | Author: Daniel C. Dillon 6 | Maintainer: Daniel C. Dillon 7 | URL: https://github.com/dcdillon/RcppHoney 8 | BugReports: https://github.com/dcdillon/RcppHoney/issues 9 | VignetteBuilder: knitr 10 | Description: Creates an easy way to use expression templates with R 11 | semantics on any iterator based structure. 12 | License: GPL (>= 2) 13 | LazyData: TRUE 14 | Imports: 15 | Rcpp (>= 0.12.12) 16 | Suggests: 17 | RUnit, 18 | knitr, 19 | rmarkdown 20 | LinkingTo: 21 | Rcpp 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | useDynLib(RcppHoney) 2 | 3 | import(Rcpp) 4 | 5 | export(example_manually_hooked) 6 | -------------------------------------------------------------------------------- /R/RcppExports.R: -------------------------------------------------------------------------------- 1 | # This file was generated by Rcpp::compileAttributes 2 | # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 | 4 | example_manually_hooked <- function() { 5 | .Call('RcppHoney_example_manually_hooked', PACKAGE = 'RcppHoney') 6 | } 7 | 8 | -------------------------------------------------------------------------------- /R/plugin.R: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2016 Daniel C. Dillon 2 | # 3 | # This file is part of RcppHoney. 4 | # 5 | # RcppHoney is free software: you can redistribute it and/or modify it 6 | # under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # RcppHoney is distributed in the hope that it will be useful, but 11 | # WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with RcppHoney. If not, see . 17 | 18 | # Return the appropriate option to pass the linker to cause it to strip 19 | # debugging symbols out of a shared library. This only takes actual linkers 20 | # (ld, gold, etc.) and not "wrappers" (gcc, clang, etc.). Returns the option 21 | # that the linker needs or empty string if it is unknown. 22 | .getLinkerOptions <- function(cmd) { 23 | if (cmd != "") { 24 | output <- system(paste0(cmd, " --version 2>&1"), intern=TRUE) 25 | 26 | if (grepl("^GNU ld", output[1])) { 27 | return("-S") 28 | } else if (grepl("^GNU gold", output[1])) { 29 | return("-S") 30 | } else if (grepl("Solaris Link Editors", output[1])) { 31 | return("-zstrip-class=debug") 32 | } 33 | } 34 | 35 | return("") 36 | } 37 | 38 | # Given a linker (ld, gold, etc.) or a linker "wrapper" (gcc, clang, etc.), 39 | # determine the option that can be passed to cause it to strip debugging 40 | # symbols out of a shared library. Returns the option needed by this 41 | # executable to strip the library or empty string if it is unknown. 42 | .getLinkerOrWrapperOptions <- function(cmd) { 43 | if (cmd != "") { 44 | # First see if this is a linker in its own right and what option it 45 | # will need. 46 | linkerOption <- .getLinkerOptions(cmd) 47 | 48 | if (linkerOption != "") 49 | { 50 | return(linkerOption) 51 | } 52 | 53 | # If it's not a linker, assume it's a "wrapper" and try to figure out 54 | # what linker it will actually call. 55 | output <- system(paste0(cmd, " --version"), intern=TRUE) 56 | 57 | if (grepl("gcc|clang|g\\+\\+", output[1])) { 58 | linkerCommand <- system(paste0(cmd, " --print-prog-name=ld"), 59 | intern=TRUE) 60 | 61 | linkerOption <- .getLinkerOptions(linkerCommand) 62 | 63 | if (linkerOption != "") { 64 | return(paste0("-Wl,", linkerOption)) 65 | } 66 | } 67 | } 68 | 69 | return("") 70 | } 71 | 72 | # Given the name of an R configuration value that specifies what command will 73 | # be executed to link a shared library, return the command line options that 74 | # can be passed to it to cause it to strip debugging symbols from the resulting 75 | # shared library. Returns empty string if it is unknown. 76 | .getStripLinkerOption <- function(rConfigParam) { 77 | rLinkerCommand <- system(paste0(file.path(R.home("bin"), "R"), 78 | " CMD config ", rConfigParam), intern=TRUE) 79 | 80 | if (rLinkerCommand != "") { 81 | return(.getLinkerOrWrapperOptions(rLinkerCommand)) 82 | } 83 | 84 | return("") 85 | } 86 | 87 | # If there is a single command line option that can be passed to all the linker 88 | # executables that R will call, return it. Return empty string otherwise. 89 | .getUniversalStripLinkerOption <- function() { 90 | tryCatch({ 91 | possibleLinkerOptions <- c() 92 | possibleLinkerOptions <- c(possibleLinkerOptions, 93 | .getStripLinkerOption("SHLIB_LD")) 94 | possibleLinkerOptions <- c(possibleLinkerOptions, 95 | .getStripLinkerOption("SHLIB_CXXLD")) 96 | 97 | # If all of the possible linkers will accept the same command, return it. 98 | if (all.equal(rep(possibleLinkerOptions[1], length(possibleLinkerOptions)), 99 | possibleLinkerOptions)) { 100 | 101 | return(possibleLinkerOptions[1]) 102 | } 103 | }, 104 | warning = function(w) {return("")}, 105 | error = function(e) {return("")}) 106 | 107 | return("") 108 | } 109 | 110 | inlineCxxPlugin <- Rcpp::Rcpp.plugin.maker( 111 | libs = .getUniversalStripLinkerOption()) 112 | -------------------------------------------------------------------------------- /R/unit.tests.R: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2010 - 2015 Dirk Eddelbuettel, Romain Francois and Douglas Bates 2 | # 3 | # This file is part of RcppHoney. 4 | # 5 | # RcppHoney is free software: you can redistribute it and/or modify it 6 | # under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # RcppHoney is distributed in the hope that it will be useful, but 11 | # WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with RcppHoney. If not, see . 17 | 18 | unit_test_setup <- function(file = NULL, packages = NULL) { 19 | function(){ 20 | if (!is.null(packages)) { 21 | for (p in packages) { 22 | suppressMessages(requireNamespace(p)) 23 | } 24 | } 25 | if (!is.null(file)) { 26 | if (exists("pathRcppHoneyTests")) { 27 | sourceCpp(file.path(get("pathRcppHoneyTests"), "cpp", file)) 28 | } else if (file.exists(file.path("cpp", file))) { 29 | sourceCpp(file.path( "cpp", file)) 30 | } else { 31 | sourceCpp(system.file("unitTests", "cpp", file, package="RcppHoney")) 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RcppHoney [![Build Status](https://travis-ci.org/dcdillon/RcppHoney.svg?branch=master)](https://travis-ci.org/dcdillon/RcppHoney) [![License](http://img.shields.io/badge/license-GPL%20%28%3E=%202%29-brightgreen.svg?style=flat)](http://www.gnu.org/licenses/gpl-2.0.html) [![CRAN](http://www.r-pkg.org/badges/version/RcppHoney)](http://cran.r-project.org/package=RcppHoney) [![Downloads](http://cranlogs.r-pkg.org/badges/RcppHoney?color=brightgreen)](http://www.r-pkg.org/pkg/RcppHoney) 2 | 3 | ### Description 4 | 5 | `RcppHoney` provides functions and operators with R semantics for any container type that has a `const_iterator`. All operators and functions are implemented as expression templates to minimize temporary copies of containers. It is integrated with `Rcpp::wrap` functionality so that results can easily be exported to `R`. 6 | 7 | The goal is to provide full featured interoperability between any iterator based structures and `R` to reduce development time and simplify code. 8 | 9 | `RcppHoney` is now in a beta state so the API should no longer be changing. 10 | 11 | ### Example 12 | 13 | ```c++ 14 | // [[Rcpp::plugins(cpp11)]] 15 | 16 | // Tell Rcpp that we need RcppHoney 17 | 18 | // [[Rcpp::depends(RcppHoney)]] 19 | 20 | #include // we have to do this because we're going to hook in a non-default structure 21 | #include 22 | 23 | // We have to declare our hooks before we include RcppHoney.hpp 24 | namespace RcppHoney { 25 | namespace hooks { 26 | 27 | // Hook in all std::list types (could be more specific) 28 | template< typename T, typename A > 29 | traits::true_type is_hooked(const std::list< T, A > &val); 30 | 31 | // Tell RcppHoney that NA has meaning in std::list 32 | template< typename T, typename A > 33 | traits::true_type has_na(const std::list< T, A > &val); 34 | 35 | // Tell RcppHoney that it needs to create basic (e.g. std::list + std::list) operators 36 | template< typename T, typename A > 37 | traits::true_type needs_basic_operators(const std::list< T, A > &val); 38 | 39 | // Tell RcppHoney that it needs to create scalar (e.g. std::list + int/double) operators 40 | template< typename T, typename A > 41 | traits::true_type needs_scalar_operators(const std::list< T, A > &val); 42 | 43 | // Tell RcppHoney that this set of types is part of the FAMILY_USER + 1 family. 44 | // This is used in conjunction with needs_basic_operators. If you have 45 | // needs_basic_operators return RcppHoney::traits::false_type, then only types 46 | // that are not part of the same family will have binary operators created 47 | // between them. 48 | template< typename T, typename A > 49 | traits::int_constant< FAMILY_USER + 1 > family(const std::list< T, A > &val); 50 | 51 | } // namespace hooks 52 | } // namespace RcppHoney 53 | 54 | #include 55 | 56 | // Let's also add a couple custom honey functions 57 | namespace RcppHoney { 58 | 59 | // first define functors for them in the RcppHoney::functors namespace 60 | namespace functors { 61 | 62 | template< typename Iterator, bool NA > 63 | struct my_unary_functor : public unary_result_dims { 64 | typedef typename std::iterator_traits< Iterator >::value_type rhs_value_type; 65 | // since we're just adding a double to the input value the return type should be 66 | // the widest numeric type of rhs and double 67 | typedef typename traits::widest_numeric_type< rhs_value_type, double >::type return_type; 68 | return_type operator()(Iterator &rhs) const { 69 | if (NA) { 70 | if (na< typename traits::ctype< typename std::iterator_traits< Iterator >::value_type >::type >::is_na(*rhs)) { 71 | return na< return_type >::VALUE(); 72 | } else { 73 | return *rhs + 1.0; 74 | } 75 | } else { 76 | return *rhs + 1.0; 77 | } 78 | } 79 | }; 80 | 81 | template< typename LhsIterator, typename RhsIterator, bool NA = true > 82 | struct my_binary_functor : binary_result_dims { 83 | typedef typename std::iterator_traits< LhsIterator >::value_type lhs_value_type; 84 | typedef typename std::iterator_traits< RhsIterator >::value_type rhs_value_type; 85 | 86 | // since we're just adding a double to the sum of the two inputs, the return type 87 | // should be the widest numeric type of lhs, rhs, and double 88 | typedef typename traits::widest_numeric_type< 89 | double, 90 | typename traits::widest_numeric_type< lhs_value_type, rhs_value_type >::type 91 | >::type return_type; 92 | 93 | inline return_type operator()(LhsIterator &lhs, RhsIterator &rhs) const { 94 | if (NA) { 95 | if (!na< typename traits::ctype< lhs_value_type >::type >::is_na(*lhs) 96 | && !na< typename traits::ctype< rhs_value_type >::type >::is_na(*rhs)) { 97 | return *lhs + *rhs + 2.0; 98 | } 99 | 100 | return na< return_type >::VALUE(); 101 | } else { 102 | return ::Rf_fprec(*lhs, *rhs); 103 | } 104 | } 105 | }; 106 | 107 | } // namespace functors 108 | 109 | // now we define the functions in th RcppHoney namespace 110 | RCPP_HONEY_GENERATE_UNARY_FUNCTION(my_unary_function, my_unary_functor) 111 | RCPP_HONEY_GENERATE_BINARY_FUNCTION(my_binary_function, my_binary_functor) 112 | 113 | } // namespace RcppHoney 114 | 115 | // [[Rcpp::export]] 116 | Rcpp::NumericVector rcpphoney_example() { 117 | 118 | // We manually hooked std::list in to RcppHoney so we'll create one 119 | std::list< int > l {1, 2, 3, 4, 5}; // c++11 for brevity here, but not required for RcppHoney 120 | 121 | // std::vector is already hooked in to RcppHoney in default_hooks.hpp so we'll 122 | // create one of those too 123 | std::vector< int > v {1, 2, 3, 4, 5}; // c++11 for brevity here, but not required for RcppHoney 124 | 125 | // And for good measure, let's create an Rcpp::NumericVector which is also hooked by default 126 | Rcpp::NumericVector v2(v.begin(), v.end()); 127 | 128 | // Now do some weird operations incorporating std::vector, std::list, Rcpp::NumericVector 129 | // and some RcppHoney functions and return it. The return value will be equal to the following 130 | // R snippet: 131 | // v <- 1:5 132 | // result <- v + v + log(v) - v - v + sqrt(v) + -v + (v + 1.0) + (v + v + 2.0) 133 | 134 | // We can store our result in any of RcppHoney::LogicalVector, RcppHoney::IntegerVector, or 135 | // RcppHoney::NumericVector and simply return it to R. These classes inherit from their 136 | // Rcpp counterparts and add a new constructor. The only copy of the data, in this case, is when 137 | // we assign our expression to retval. Since it is then a "native" R type, returning it is a 138 | // shallow copy. Alternatively we could write this as: 139 | // return Rcpp::wrap(l + v + RcppHoney::log(v) - v - l + RcppHoney::sqrt(v) + -v2 140 | // + RcppHoney::my_unary_function(l) + RcppHoney::my_binary_function(l, v); 141 | 142 | RcppHoney::NumericVector retval 143 | = l + v + RcppHoney::log(v) - v - l + RcppHoney::sqrt(v) + -v2 144 | + RcppHoney::my_unary_function(l) + RcppHoney::my_binary_function(l, v); 145 | return retval; 146 | } 147 | ``` 148 | 149 | ### Installation 150 | 151 | RcppHoney is now a in beta state! 152 | 153 | RcppHoney is available via the [CRAN](http://cran.r-project.org) network, 154 | and can be installed from within R via 155 | 156 | ```R 157 | install.packages("RcppHoney") 158 | ``` 159 | 160 | RcppHoney can also be installed from the github sources by running 161 | 162 | ``` 163 | git clone git@github.com:dcdillon/RcppHoney 164 | R CMD INSTALL RcppHoney 165 | ``` 166 | 167 | ### Authors 168 | 169 | Daniel C. Dillon 170 | 171 | ### License 172 | 173 | GPL (>= 2) 174 | -------------------------------------------------------------------------------- /RcppHoney.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 4 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | ./inst/tools/r-stripper/stripper 2 | -------------------------------------------------------------------------------- /doxygen/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /doxygen/customdoxygen.css: -------------------------------------------------------------------------------- 1 | h1, .h1, h2, .h2, h3, .h3{ 2 | font-weight: 200 !important; 3 | } 4 | 5 | #navrow1, #navrow2, #navrow3, #navrow4, #navrow5{ 6 | border-bottom: 1px solid #EEEEEE; 7 | } 8 | 9 | .adjust-right { 10 | margin-left: 30px !important; 11 | font-size: 1.15em !important; 12 | } 13 | .navbar{ 14 | border: 0px solid #222 !important; 15 | } 16 | table{ 17 | white-space:pre-wrap !important; 18 | } 19 | /* 20 | =========================== 21 | */ 22 | 23 | 24 | /* Sticky footer styles 25 | -------------------------------------------------- */ 26 | html, 27 | body { 28 | height: 100%; 29 | /* The html and body elements cannot have any padding or margin. */ 30 | } 31 | 32 | /* Wrapper for page content to push down footer */ 33 | #wrap { 34 | min-height: 100%; 35 | height: auto; 36 | /* Negative indent footer by its height */ 37 | margin: 0 auto -60px; 38 | /* Pad bottom by footer height */ 39 | padding: 0 0 60px; 40 | } 41 | 42 | /* Set the fixed height of the footer here */ 43 | #footer { 44 | font-size: 0.9em; 45 | padding: 8px 0px; 46 | background-color: #f5f5f5; 47 | } 48 | 49 | .footer-row { 50 | line-height: 44px; 51 | } 52 | 53 | #footer > .container { 54 | padding-left: 15px; 55 | padding-right: 15px; 56 | } 57 | 58 | .footer-follow-icon { 59 | margin-left: 3px; 60 | text-decoration: none !important; 61 | } 62 | 63 | .footer-follow-icon img { 64 | width: 20px; 65 | } 66 | 67 | .footer-link { 68 | padding-top: 5px; 69 | display: inline-block; 70 | color: #999999; 71 | text-decoration: none; 72 | } 73 | 74 | .footer-copyright { 75 | text-align: center; 76 | } 77 | 78 | 79 | @media (min-width: 992px) { 80 | .footer-row { 81 | text-align: left; 82 | } 83 | 84 | .footer-icons { 85 | text-align: right; 86 | } 87 | } 88 | @media (max-width: 991px) { 89 | .footer-row { 90 | text-align: center; 91 | } 92 | 93 | .footer-icons { 94 | text-align: center; 95 | } 96 | } 97 | 98 | /* DOXYGEN Code Styles 99 | ----------------------------------- */ 100 | 101 | 102 | a.qindex { 103 | font-weight: bold; 104 | } 105 | 106 | a.qindexHL { 107 | font-weight: bold; 108 | background-color: #9CAFD4; 109 | color: #ffffff; 110 | border: 1px double #869DCA; 111 | } 112 | 113 | .contents a.qindexHL:visited { 114 | color: #ffffff; 115 | } 116 | 117 | a.code, a.code:visited, a.line, a.line:visited { 118 | color: #4665A2; 119 | } 120 | 121 | a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { 122 | color: #4665A2; 123 | } 124 | 125 | /* @end */ 126 | 127 | dl.el { 128 | margin-left: -1cm; 129 | } 130 | 131 | pre.fragment { 132 | border: 1px solid #C4CFE5; 133 | background-color: #FBFCFD; 134 | padding: 4px 6px; 135 | margin: 4px 8px 4px 2px; 136 | overflow: auto; 137 | word-wrap: break-word; 138 | font-size: 9pt; 139 | line-height: 125%; 140 | font-family: monospace, fixed; 141 | font-size: 105%; 142 | } 143 | 144 | div.fragment { 145 | padding: 4px 6px; 146 | margin: 4px 8px 4px 2px; 147 | border: 1px solid #C4CFE5; 148 | } 149 | 150 | div.line { 151 | font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; 152 | font-size: 12px; 153 | min-height: 13px; 154 | line-height: 1.0; 155 | text-wrap: unrestricted; 156 | white-space: -moz-pre-wrap; /* Moz */ 157 | white-space: -pre-wrap; /* Opera 4-6 */ 158 | white-space: -o-pre-wrap; /* Opera 7 */ 159 | white-space: pre-wrap; /* CSS3 */ 160 | word-wrap: normal; /* IE 5.5+ */ 161 | text-indent: -53px; 162 | padding-left: 53px; 163 | padding-bottom: 0px; 164 | margin: 0px; 165 | -webkit-transition-property: background-color, box-shadow; 166 | -webkit-transition-duration: 0.5s; 167 | -moz-transition-property: background-color, box-shadow; 168 | -moz-transition-duration: 0.5s; 169 | -ms-transition-property: background-color, box-shadow; 170 | -ms-transition-duration: 0.5s; 171 | -o-transition-property: background-color, box-shadow; 172 | -o-transition-duration: 0.5s; 173 | transition-property: background-color, box-shadow; 174 | transition-duration: 0.5s; 175 | } 176 | div.line:hover{ 177 | background-color: #FBFF00; 178 | } 179 | 180 | div.line.glow { 181 | background-color: cyan; 182 | box-shadow: 0 0 10px cyan; 183 | } 184 | 185 | 186 | span.lineno { 187 | padding-right: 4px; 188 | text-align: right; 189 | color:rgba(0,0,0,0.3); 190 | border-right: 1px solid #EEE; 191 | border-left: 1px solid #EEE; 192 | background-color: #FFF; 193 | white-space: pre; 194 | font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace ; 195 | } 196 | span.lineno a { 197 | background-color: #FAFAFA; 198 | cursor:pointer; 199 | } 200 | 201 | span.lineno a:hover { 202 | background-color: #EFE200; 203 | color: #1e1e1e; 204 | } 205 | 206 | div.groupHeader { 207 | margin-left: 16px; 208 | margin-top: 12px; 209 | font-weight: bold; 210 | } 211 | 212 | div.groupText { 213 | margin-left: 16px; 214 | font-style: italic; 215 | } 216 | 217 | /* @group Code Colorization */ 218 | 219 | span.keyword { 220 | color: #008000 221 | } 222 | 223 | span.keywordtype { 224 | color: #604020 225 | } 226 | 227 | span.keywordflow { 228 | color: #e08000 229 | } 230 | 231 | span.comment { 232 | color: #800000 233 | } 234 | 235 | span.preprocessor { 236 | color: #806020 237 | } 238 | 239 | span.stringliteral { 240 | color: #002080 241 | } 242 | 243 | span.charliteral { 244 | color: #008080 245 | } 246 | 247 | span.vhdldigit { 248 | color: #ff00ff 249 | } 250 | 251 | span.vhdlchar { 252 | color: #000000 253 | } 254 | 255 | span.vhdlkeyword { 256 | color: #700070 257 | } 258 | 259 | span.vhdllogic { 260 | color: #ff0000 261 | } 262 | 263 | blockquote { 264 | background-color: #F7F8FB; 265 | border-left: 2px solid #9CAFD4; 266 | margin: 0 24px 0 4px; 267 | padding: 0 12px 0 16px; 268 | } 269 | 270 | /*---------------- Search Box */ 271 | 272 | #search-box { 273 | margin: 10px 0px; 274 | } 275 | #search-box .close { 276 | display: none; 277 | position: absolute; 278 | right: 0px; 279 | padding: 6px 12px; 280 | z-index: 5; 281 | } 282 | 283 | /*---------------- Search results window */ 284 | 285 | #search-results-window { 286 | display: none; 287 | } 288 | 289 | iframe#MSearchResults { 290 | width: 100%; 291 | height: 15em; 292 | } 293 | 294 | .SRChildren { 295 | padding-left: 3ex; padding-bottom: .5em 296 | } 297 | .SRPage .SRChildren { 298 | display: none; 299 | } 300 | a.SRScope { 301 | display: block; 302 | } 303 | a.SRSymbol:focus, a.SRSymbol:active, 304 | a.SRScope:focus, a.SRScope:active { 305 | text-decoration: underline; 306 | } 307 | span.SRScope { 308 | padding-left: 4px; 309 | } 310 | .SRResult { 311 | display: none; 312 | } 313 | 314 | /* class and file list */ 315 | .directory .icona, 316 | .directory .arrow { 317 | height: auto; 318 | } 319 | .directory .icona .icon { 320 | height: 16px; 321 | } 322 | .directory .icondoc { 323 | background-position: 0px 0px; 324 | height: 20px; 325 | } 326 | .directory .iconfopen { 327 | background-position: 0px 0px; 328 | } 329 | .directory td.entry { 330 | padding: 7px 8px 6px 8px; 331 | } 332 | 333 | .table > tbody > tr > td.memSeparator { 334 | line-height: 0; 335 | .table-hover; 336 | 337 | } 338 | 339 | .memItemLeft, .memTemplItemLeft { 340 | white-space: normal; 341 | } 342 | 343 | /* enumerations */ 344 | .panel-body thead > tr { 345 | background-color: #e0e0e0; 346 | } 347 | 348 | /* todo lists */ 349 | .todoname, 350 | .todoname a { 351 | font-weight: bold; 352 | } 353 | 354 | /* Class title */ 355 | .summary { 356 | margin-top: 25px; 357 | } 358 | .page-header { 359 | margin: 20px 0px !important; 360 | } 361 | .page-header .title { 362 | display: inline-block; 363 | } 364 | .page-header .pull-right { 365 | margin-top: 0.3em; 366 | margin-left: 0.5em; 367 | } 368 | .page-header .label { 369 | font-size: 50%; 370 | } 371 | -------------------------------------------------------------------------------- /doxygen/doxy-boot.js: -------------------------------------------------------------------------------- 1 | $( document ).ready(function() { 2 | 3 | $("div.headertitle").addClass("page-header"); 4 | $("div.title").addClass("h1"); 5 | 6 | $('li > a[href="index.html"] > span').before(" "); 7 | $('li > a[href="modules.html"] > span').before(" "); 8 | $('li > a[href="namespaces.html"] > span').before(" "); 9 | $('li > a[href="annotated.html"] > span').before(" "); 10 | $('li > a[href="classes.html"] > span').before(" "); 11 | $('li > a[href="inherits.html"] > span').before(" "); 12 | $('li > a[href="functions.html"] > span').before(" "); 13 | $('li > a[href="functions_func.html"] > span').before(" "); 14 | $('li > a[href="functions_vars.html"] > span').before(" "); 15 | $('li > a[href="functions_enum.html"] > span').before(" "); 16 | $('li > a[href="functions_eval.html"] > span').before(" "); 17 | $('img[src="ftv2ns.png"]').replaceWith('N '); 18 | $('img[src="ftv2cl.png"]').replaceWith('C '); 19 | 20 | $("ul.tablist").addClass("nav nav-pills nav-justified"); 21 | $("ul.tablist").css("margin-top", "0.5em"); 22 | $("ul.tablist").css("margin-bottom", "0.5em"); 23 | $("li.current").addClass("active"); 24 | $("iframe").attr("scrolling", "yes"); 25 | 26 | $("#nav-path > ul").addClass("breadcrumb"); 27 | 28 | $("table.params").addClass("table"); 29 | $("div.ingroups").wrapInner(""); 30 | $("div.levels").css("margin", "0.5em"); 31 | $("div.levels > span").addClass("btn btn-default btn-xs"); 32 | $("div.levels > span").css("margin-right", "0.25em"); 33 | 34 | $("table.directory").addClass("table table-striped"); 35 | $("div.summary > a").addClass("btn btn-default btn-xs"); 36 | $("table.fieldtable").addClass("table"); 37 | $(".fragment").addClass("well"); 38 | $(".memitem").addClass("panel panel-default"); 39 | $(".memproto").addClass("panel-heading"); 40 | $(".memdoc").addClass("panel-body"); 41 | $("span.mlabel").addClass("label label-info"); 42 | 43 | $("table.memberdecls").addClass("table"); 44 | $("[class^=memitem]").addClass("active"); 45 | 46 | $("div.ah").addClass("btn btn-default"); 47 | $("span.mlabels").addClass("pull-right"); 48 | $("table.mlabels").css("width", "100%") 49 | $("td.mlabels-right").addClass("pull-right"); 50 | 51 | $("div.ttc").addClass("panel panel-primary"); 52 | $("div.ttname").addClass("panel-heading"); 53 | $("div.ttname a").css("color", 'white'); 54 | $("div.ttdef,div.ttdoc,div.ttdeci").addClass("panel-body"); 55 | 56 | $('div.fragment.well div.line:first').css('margin-top', '2px'); 57 | $('div.fragment.well div.line:last').css('margin-bottom', '2px'); 58 | 59 | $('table.doxtable').removeClass('doxtable').addClass('table table-striped table-bordered').each(function(){ 60 | $(this).prepend(''); 61 | $(this).find('tbody > tr:first').prependTo($(this).find('thead')); 62 | 63 | $(this).find('td > span.success').parent().addClass('success'); 64 | $(this).find('td > span.warning').parent().addClass('warning'); 65 | $(this).find('td > span.danger').parent().addClass('danger'); 66 | }); 67 | 68 | 69 | 70 | if($('div.fragment.well div.ttc').length > 0) 71 | { 72 | $('div.fragment.well div.line:first').parent().removeClass('fragment well'); 73 | } 74 | 75 | $('table.memberdecls').find('.memItemRight').each(function(){ 76 | $(this).contents().appendTo($(this).siblings('.memItemLeft')); 77 | $(this).siblings('.memItemLeft').attr('align', 'left'); 78 | }); 79 | 80 | $('table.memberdecls').find('.memTemplItemRight').each(function(){ 81 | $(this).contents().appendTo($(this).siblings('.memTemplItemLeft')); 82 | $(this).siblings('.memTemplItemLeft').attr('align', 'left'); 83 | }); 84 | 85 | function getOriginalWidthOfImg(img_element) { 86 | var t = new Image(); 87 | t.src = (img_element.getAttribute ? img_element.getAttribute("src") : false) || img_element.src; 88 | return t.width; 89 | } 90 | 91 | $('div.dyncontent').find('img').each(function(){ 92 | if(getOriginalWidthOfImg($(this)[0]) > $('#content>div.container').width()) 93 | $(this).css('width', '100%'); 94 | }); 95 | 96 | 97 | /* responsive search box */ 98 | $('#MSearchBox').parent().remove(); 99 | 100 | var nav_container = $('
'); 101 | $('#navrow1').parent().prepend(nav_container); 102 | 103 | var left_nav = $('
'); 104 | for (i = 0; i < 6; i++) { 105 | var navrow = $('#navrow' + i + ' > ul.tablist').detach(); 106 | left_nav.append(navrow); 107 | $('#navrow' + i).remove(); 108 | } 109 | var right_nav = $('
').append('\ 110 | '); 121 | $(nav_container).append(left_nav); 122 | $(nav_container).append(right_nav); 123 | 124 | $('#MSearchSelectWindow .SelectionMark').remove(); 125 | var search_selectors = $('#MSearchSelectWindow .SelectItem'); 126 | for (var i = 0; i < search_selectors.length; i += 1) { 127 | var element_a = $('').text($(search_selectors[i]).text()); 128 | 129 | element_a.click(function(){ 130 | $('#search-box .dropdown-menu li').removeClass('active'); 131 | $(this).parent().addClass('active'); 132 | searchBox.OnSelectItem($('#search-box li a').index(this)); 133 | searchBox.Search(); 134 | return false; 135 | }); 136 | 137 | var element = $('
  • ').append(element_a); 138 | $('#search-box .dropdown-menu').append(element); 139 | } 140 | $('#MSearchSelectWindow').remove(); 141 | 142 | $('#search-box .close').click(function (){ 143 | searchBox.CloseResultsWindow(); 144 | }); 145 | 146 | $('body').append('
    '); 147 | $('body').append('
    '); 148 | $('body').append('
    '); 149 | 150 | searchBox.searchLabel = ''; 151 | searchBox.DOMSearchField = function() { 152 | return document.getElementById("search-field"); 153 | } 154 | searchBox.DOMSearchClose = function(){ 155 | return document.getElementById("search-close"); 156 | } 157 | 158 | 159 | /* search results */ 160 | var results_iframe = $('#MSearchResults').detach(); 161 | $('#MSearchResultsWindow') 162 | .attr('id', 'search-results-window') 163 | .addClass('panel panel-default') 164 | .append( 165 | '
    \ 166 |

    Search Results

    \ 167 |
    \ 168 |
    ' 169 | ); 170 | $('#search-results-window .panel-body').append(results_iframe); 171 | 172 | searchBox.DOMPopupSearchResultsWindow = function() { 173 | return document.getElementById("search-results-window"); 174 | } 175 | 176 | function update_search_results_window() { 177 | $('#search-results-window').removeClass('panel-default panel-success panel-warning panel-danger') 178 | var status = $('#MSearchResults').contents().find('.SRStatus:visible'); 179 | if (status.length > 0) { 180 | switch(status.attr('id')) { 181 | case 'Loading': 182 | case 'Searching': 183 | $('#search-results-window').addClass('panel-warning'); 184 | break; 185 | case 'NoMatches': 186 | $('#search-results-window').addClass('panel-danger'); 187 | break; 188 | default: 189 | $('#search-results-window').addClass('panel-default'); 190 | } 191 | } else { 192 | $('#search-results-window').addClass('panel-success'); 193 | } 194 | } 195 | $('#MSearchResults').load(function() { 196 | $('#MSearchResults').contents().find('link[href="search.css"]').attr('href','../doxygen.css'); 197 | $('#MSearchResults').contents().find('head').append( 198 | ''); 199 | 200 | update_search_results_window(); 201 | 202 | // detect status changes (only for search with external search backend) 203 | var observer = new MutationObserver(function(mutations) { 204 | update_search_results_window(); 205 | }); 206 | var config = { attributes: true}; 207 | 208 | var targets = $('#MSearchResults').contents().find('.SRStatus'); 209 | for (i = 0; i < targets.length; i++) { 210 | observer.observe(targets[i], config); 211 | } 212 | }); 213 | 214 | 215 | /* enumerations */ 216 | $('table.fieldtable').removeClass('fieldtable').addClass('table table-striped table-bordered').each(function(){ 217 | $(this).prepend(''); 218 | $(this).find('tbody > tr:first').prependTo($(this).find('thead')); 219 | 220 | $(this).find('td > span.success').parent().addClass('success'); 221 | $(this).find('td > span.warning').parent().addClass('warning'); 222 | $(this).find('td > span.danger').parent().addClass('danger'); 223 | }); 224 | 225 | /* todo list */ 226 | var todoelements = $('.contents > .textblock > dl.reflist > dt, .contents > .textblock > dl.reflist > dd'); 227 | for (var i = 0; i < todoelements.length; i += 2) { 228 | $('.contents > .textblock').append( 229 | '
    ' 230 | + "
    " + $(todoelements[i]).html() + "
    " 231 | + "
    " + $(todoelements[i+1]).html() + "
    " 232 | + '
    '); 233 | } 234 | $('.contents > .textblock > dl').remove(); 235 | 236 | 237 | $(".memitem").removeClass('memitem'); 238 | $(".memproto").removeClass('memproto'); 239 | $(".memdoc").removeClass('memdoc'); 240 | $("span.mlabel").removeClass('mlabel'); 241 | $("table.memberdecls").removeClass('memberdecls'); 242 | $("[class^=memitem]").removeClass('memitem'); 243 | $("span.mlabels").removeClass('mlabels'); 244 | $("table.mlabels").removeClass('mlabels'); 245 | $("td.mlabels-right").removeClass('mlabels-right'); 246 | $(".navpath").removeClass('navpath'); 247 | $("li.navelem").removeClass('navelem'); 248 | $("a.el").removeClass('el'); 249 | $("div.ah").removeClass('ah'); 250 | $("div.header").removeClass("header"); 251 | 252 | $('.mdescLeft').each(function(){ 253 | if($(this).html()==" ") { 254 | $(this).siblings('.mdescRight').attr('colspan', 2); 255 | $(this).remove(); 256 | } 257 | }); 258 | $('td.memItemLeft').each(function(){ 259 | if($(this).siblings('.memItemRight').html()=="") { 260 | $(this).attr('colspan', 2); 261 | $(this).siblings('.memItemRight').remove(); 262 | } 263 | }); 264 | $('td.memTemplItemLeft').each(function(){ 265 | if($(this).siblings('.memTemplItemRight').html()=="") { 266 | $(this).attr('colspan', 2); 267 | $(this).siblings('.memTemplItemRight').remove(); 268 | } 269 | }); 270 | searchBox.CloseResultsWindow(); 271 | }); 272 | -------------------------------------------------------------------------------- /doxygen/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /doxygen/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | $projectname: $title 15 | $title 16 | 17 | 18 | $treeview 19 | $search 20 | $mathjax 21 | 22 | $extrastylesheet 23 | 24 | 25 | 26 | 27 | 28 | 29 | 36 |
    37 |
    38 |
    39 |
    40 |
    41 |
    42 | 43 | -------------------------------------------------------------------------------- /inst/include/RcppHoney.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | #include "RcppHoneyForward.hpp" 21 | #include 22 | #include "RcppHoney/hook.hpp" 23 | #include "RcppHoney/bind.hpp" 24 | #include "RcppHoney/operators.hpp" 25 | #include "RcppHoney/functions.hpp" 26 | #include "RcppHoney/storage.hpp" 27 | 28 | -------------------------------------------------------------------------------- /inst/include/RcppHoney/binary_operator.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | #include "operand.hpp" 24 | #include "hook.hpp" 25 | #include "exceptions.hpp" 26 | 27 | namespace RcppHoney { 28 | 29 | template< typename LhsIterator, typename RhsIterator, typename Op, 30 | bool NA_VALUE > 31 | struct binary_operator_iterator : public std::iterator< 32 | std::bidirectional_iterator_tag, 33 | typename Op::return_type 34 | > { 35 | private: 36 | LhsIterator m_lhsPos; 37 | RhsIterator m_rhsPos; 38 | typename Op::return_type m_value; 39 | bool m_dirty; 40 | const Op *m_operator; 41 | 42 | public: 43 | inline binary_operator_iterator() : m_dirty(true), m_operator(NULL) {} 44 | 45 | inline binary_operator_iterator(const LhsIterator &lhsPos, 46 | const RhsIterator &rhsPos, const Op *op) : m_lhsPos(lhsPos), 47 | m_rhsPos(rhsPos), m_dirty(true), m_operator(op) {} 48 | 49 | inline typename Op::return_type operator*() { 50 | if (m_dirty) { 51 | m_value = (*m_operator)(m_lhsPos, m_rhsPos); 52 | m_dirty = false; 53 | } 54 | 55 | return m_value; 56 | } 57 | 58 | inline binary_operator_iterator &operator++() { 59 | ++m_lhsPos; 60 | ++m_rhsPos; 61 | m_dirty = true; 62 | return *this; 63 | } 64 | 65 | inline binary_operator_iterator operator++(int) { 66 | binary_operator_iterator i = *this; 67 | operator++(); 68 | return i; 69 | } 70 | 71 | inline binary_operator_iterator &operator--() { 72 | --m_lhsPos; 73 | --m_rhsPos; 74 | m_dirty = true; 75 | return *this; 76 | } 77 | 78 | inline binary_operator_iterator operator--(int) { 79 | binary_operator_iterator i = *this; 80 | operator--(); 81 | return this; 82 | } 83 | 84 | inline bool operator==(const binary_operator_iterator &rhs) const { 85 | return m_lhsPos == rhs.m_lhsPos 86 | || m_rhsPos == rhs.m_rhsPos; 87 | } 88 | 89 | inline bool operator!=(const binary_operator_iterator &rhs) const { 90 | return !operator==(rhs); 91 | } 92 | }; 93 | 94 | template< typename LhsIterator, typename RhsIterator, typename Op, 95 | bool NA_VALUE > 96 | struct binary_operator_result_type { 97 | typedef typename Op::return_type result_type; 98 | }; 99 | 100 | template< typename LhsIterator, typename RhsIterator, typename Op, bool NA_VALUE > 101 | class binary_operator : public operand< 102 | binary_operator< LhsIterator, RhsIterator, Op, NA_VALUE >, 103 | binary_operator_iterator< LhsIterator, RhsIterator, Op, NA_VALUE >, 104 | typename binary_operator_result_type< 105 | LhsIterator, 106 | RhsIterator, 107 | Op, 108 | NA_VALUE 109 | >::result_type 110 | > { 111 | public: 112 | typedef typename Op::return_type result_type; 113 | static const bool NA = NA_VALUE; 114 | 115 | public: 116 | typedef binary_operator_iterator< 117 | LhsIterator, 118 | RhsIterator, 119 | Op, 120 | NA_VALUE 121 | > const_iterator; 122 | typedef const_iterator iterator; 123 | 124 | private: 125 | LhsIterator m_lhsBegin; 126 | LhsIterator m_lhsEnd; 127 | RhsIterator m_rhsBegin; 128 | RhsIterator m_rhsEnd; 129 | dims_t m_dims; 130 | Op m_operator; 131 | 132 | public: 133 | binary_operator(LhsIterator lhsBegin, LhsIterator lhsEnd, dims_t lhsDims, 134 | RhsIterator rhsBegin, RhsIterator rhsEnd, dims_t rhsDims, const Op &op) : 135 | m_lhsBegin(lhsBegin), m_lhsEnd(lhsEnd), m_rhsBegin(rhsBegin), 136 | m_rhsEnd(rhsEnd), m_operator(op) { 137 | 138 | m_dims = m_operator.result_dims(lhsDims, rhsDims); 139 | } 140 | 141 | dims_t dims() const {return m_dims;} 142 | int64_t size() const { 143 | return (m_dims.second != 0) ? m_dims.first * m_dims.second 144 | : m_dims.first; 145 | } 146 | const_iterator begin() const { 147 | return const_iterator(m_lhsBegin, m_rhsBegin, &m_operator); 148 | } 149 | 150 | const_iterator end() const { 151 | return const_iterator(m_lhsEnd, m_rhsEnd, &m_operator); 152 | } 153 | }; 154 | 155 | template< bool NA > 156 | struct make_binary_operator 157 | { 158 | template< typename LHS, typename RHS, typename Op > 159 | binary_operator< 160 | typename LHS::const_iterator, 161 | typename RHS::const_iterator, 162 | Op, 163 | NA 164 | > operator()(const LHS &lhs, const RHS &rhs, const Op &op) { 165 | return binary_operator< 166 | typename LHS::const_iterator, 167 | typename RHS::const_iterator, 168 | Op, 169 | NA 170 | >(lhs.begin(), lhs.end(), hooks::extract_dims(lhs), rhs.begin(), 171 | rhs.end(), hooks::extract_dims(rhs), op); 172 | } 173 | }; 174 | 175 | } // namespace RcppHoney 176 | -------------------------------------------------------------------------------- /inst/include/RcppHoney/bind.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | #include 21 | #include "traits/widest_numeric_type.hpp" 22 | #include "traits/ctype.hpp" 23 | #include "na.hpp" 24 | #include "exceptions.hpp" 25 | #include "scalar_operator.hpp" 26 | 27 | namespace RcppHoney { 28 | 29 | template< typename LhsIterator, typename RhsIterator, bool NA_VALUE > 30 | class cbinder_result_type { 31 | public: 32 | typedef typename std::iterator_traits< LhsIterator >::value_type lhs_type; 33 | typedef typename std::iterator_traits< RhsIterator >::value_type rhs_type; 34 | typedef typename traits::widest_numeric_type< 35 | lhs_type, 36 | rhs_type 37 | >::type result_type; 38 | }; 39 | 40 | template< typename LhsIterator, typename RhsIterator, bool NA_VALUE > 41 | class cbinder_iterator : 42 | public std::iterator< std::bidirectional_iterator_tag, 43 | typename cbinder_result_type< 44 | LhsIterator, 45 | RhsIterator, 46 | NA_VALUE 47 | >::result_type 48 | > { 49 | 50 | public: 51 | typedef typename cbinder_result_type< LhsIterator, 52 | RhsIterator, NA_VALUE >::result_type result_type; 53 | typedef typename std::iterator_traits< LhsIterator >::value_type lhs_type; 54 | typedef typename std::iterator_traits< RhsIterator >::value_type rhs_type; 55 | 56 | private: 57 | bool m_dirty; 58 | bool m_onLhs; 59 | LhsIterator m_lhsPos; 60 | LhsIterator m_lhsEnd; 61 | RhsIterator m_rhsPos; 62 | RhsIterator m_rhsEnd; 63 | result_type m_value; 64 | 65 | public: 66 | inline cbinder_iterator() : m_dirty(true), m_onLhs(true) {} 67 | 68 | inline cbinder_iterator(const LhsIterator &lhsPos, 69 | const LhsIterator &lhsEnd, const RhsIterator &rhsPos, 70 | const RhsIterator &rhsEnd) : m_dirty(true), 71 | m_onLhs(lhsPos != lhsEnd), m_lhsPos(lhsPos), m_lhsEnd(lhsEnd), 72 | m_rhsPos(rhsPos), m_rhsEnd(rhsEnd) {} 73 | 74 | inline result_type operator*() { 75 | if (m_dirty) { 76 | if (m_onLhs) { 77 | if (NA_VALUE) { 78 | lhs_type val = *m_lhsPos; 79 | 80 | if (na< 81 | typename traits::ctype< lhs_type >::type 82 | >::is_na(val)) { 83 | 84 | m_value = na< result_type >::VALUE(); 85 | } else { 86 | m_value = val; 87 | } 88 | } else { 89 | m_value = *m_lhsPos; 90 | } 91 | } else { 92 | if (NA_VALUE) { 93 | rhs_type val = *m_rhsPos; 94 | 95 | if (na< 96 | typename traits::ctype< rhs_type >::type 97 | >::is_na(val)) { 98 | 99 | m_value = na< result_type >::VALUE(); 100 | } else { 101 | m_value = val; 102 | } 103 | } else { 104 | m_value = *m_rhsPos; 105 | } 106 | } 107 | 108 | m_dirty = false; 109 | } 110 | 111 | return m_value; 112 | } 113 | 114 | inline cbinder_iterator &operator++() { 115 | if (m_onLhs) { 116 | ++m_lhsPos; 117 | 118 | if (m_lhsPos == m_lhsEnd) { 119 | m_onLhs = false; 120 | } 121 | } else { 122 | ++m_rhsPos; 123 | } 124 | 125 | m_dirty = true; 126 | 127 | return *this; 128 | } 129 | 130 | inline cbinder_iterator operator++(int) { 131 | cbinder_iterator i = *this; 132 | operator++(); 133 | return i; 134 | } 135 | 136 | inline cbinder_iterator &operator--() { 137 | if (m_onLhs) { 138 | --m_lhsPos; 139 | 140 | if (m_lhsPos == m_lhsEnd) { 141 | m_onLhs = false; 142 | } 143 | } else { 144 | --m_rhsPos; 145 | } 146 | 147 | m_dirty = true; 148 | 149 | return *this; 150 | } 151 | 152 | inline cbinder_iterator operator--(int) { 153 | cbinder_iterator i = *this; 154 | operator--(); 155 | return this; 156 | } 157 | 158 | inline bool operator==(const cbinder_iterator &rhs) const { 159 | if (m_onLhs) { 160 | return m_lhsPos == rhs.m_lhsPos; 161 | } else { 162 | return m_rhsPos == rhs.m_rhsPos; 163 | } 164 | } 165 | 166 | inline bool operator!=(const cbinder_iterator &rhs) const { 167 | return !operator==(rhs); 168 | } 169 | }; 170 | 171 | template< typename LhsIterator, typename RhsIterator, bool NA_VALUE > 172 | class cbinder : 173 | public operand< 174 | cbinder< LhsIterator, RhsIterator, NA_VALUE >, 175 | cbinder_iterator< LhsIterator, RhsIterator, NA_VALUE >, 176 | typename cbinder_result_type< 177 | LhsIterator, 178 | RhsIterator, 179 | NA_VALUE 180 | >::result_type 181 | > { 182 | 183 | public: 184 | typedef cbinder_iterator< LhsIterator, RhsIterator, NA_VALUE > const_iterator; 185 | typedef const_iterator iterator; 186 | typedef typename cbinder_result_type< 187 | LhsIterator, 188 | RhsIterator, 189 | NA_VALUE 190 | >::result_type result_type; 191 | 192 | static const bool NA = NA_VALUE; 193 | 194 | private: 195 | LhsIterator m_lhsBegin; 196 | LhsIterator m_lhsEnd; 197 | RhsIterator m_rhsBegin; 198 | RhsIterator m_rhsEnd; 199 | dims_t m_dims; 200 | 201 | public: 202 | cbinder(LhsIterator lhsBegin, LhsIterator lhsEnd, dims_t lhsDims, 203 | RhsIterator rhsBegin, RhsIterator rhsEnd, dims_t rhsDims) : 204 | m_lhsBegin(lhsBegin), m_lhsEnd(lhsEnd), m_rhsBegin(rhsBegin), 205 | m_rhsEnd(rhsEnd) { 206 | 207 | if (lhsDims.first == -1) { 208 | if (rhsDims.first > 0) { 209 | m_dims.first = rhsDims.first 210 | + ((rhsDims.second == 0) ? 1 : rhsDims.second); 211 | } else { 212 | throw bounds_exception(); 213 | } 214 | } else if (rhsDims.first == -1) { 215 | if (lhsDims.first > 0) { 216 | m_dims.first = lhsDims.first 217 | + ((lhsDims.second == 0) ? 1 : lhsDims.second); 218 | } else { 219 | throw bounds_exception(); 220 | } 221 | } else if (lhsDims.second == 0 && rhsDims.second == 0) { 222 | if (lhsDims.first == rhsDims.first) { 223 | m_dims.first = lhsDims.first; 224 | m_dims.second = 2; 225 | } else { 226 | throw bounds_exception(); 227 | } 228 | } 229 | else if (lhsDims.second == 0) { 230 | if (lhsDims.first == rhsDims.first) { 231 | m_dims.first = lhsDims.first; 232 | m_dims.second = rhsDims.second + 1; 233 | } else { 234 | throw bounds_exception(); 235 | } 236 | } else if (rhsDims.second == 0) { 237 | if (lhsDims.first == rhsDims.first) { 238 | m_dims.first = lhsDims.first; 239 | m_dims.second = lhsDims.second + 1; 240 | } else { 241 | throw bounds_exception(); 242 | } 243 | } else if (lhsDims.first == rhsDims.first) { 244 | m_dims.first = lhsDims.first; 245 | m_dims.second = lhsDims.second + rhsDims.second; 246 | } else { 247 | throw bounds_exception(); 248 | } 249 | } 250 | 251 | dims_t dims() const {return m_dims;} 252 | int64_t size() const { 253 | return (m_dims.second != 0) ? m_dims.first * m_dims.second 254 | : m_dims.first; 255 | } 256 | 257 | const_iterator begin() const { 258 | return const_iterator(m_lhsBegin, m_lhsEnd, m_rhsBegin, m_rhsEnd); 259 | } 260 | 261 | const_iterator end() const { 262 | return const_iterator(m_lhsEnd, m_lhsEnd, m_rhsEnd, m_rhsEnd); 263 | } 264 | }; 265 | 266 | template< bool NA > 267 | struct make_cbinder 268 | { 269 | template< typename LHS, typename RHS > 270 | cbinder< typename LHS::const_iterator, typename RHS::const_iterator, NA > 271 | operator()(const LHS &lhs, const RHS &rhs) { 272 | 273 | return cbinder< 274 | typename LHS::const_iterator, 275 | typename RHS::const_iterator, 276 | NA 277 | >(lhs.begin(), lhs.end(), hooks::extract_dims(lhs), rhs.begin(), 278 | rhs.end(), hooks::extract_dims(rhs)); 279 | } 280 | }; 281 | 282 | template< typename T, typename T_ITER, typename T_RESULT, typename U, 283 | typename U_ITER, typename U_RESULT > 284 | RcppHoney::cbinder< T_ITER, U_ITER, (T::NA || U::NA) > 285 | cbind(const RcppHoney::operand< T, T_ITER, T_RESULT > &lhs, 286 | const RcppHoney::operand< U, U_ITER, U_RESULT > &rhs) { 287 | return RcppHoney::make_cbinder< (T::NA || U::NA) >()(lhs, rhs); 288 | } 289 | 290 | template< typename T, typename T_ITER, typename T_RESULT, typename U > 291 | typename RcppHoney::traits::enable_if< 292 | RcppHoney::traits::is_primitive< U >::value, 293 | RcppHoney::cbinder< 294 | T_ITER, 295 | typename RcppHoney::scalar_operator< U >::const_iterator, 296 | T::NA 297 | > 298 | >::type 299 | cbind(const RcppHoney::operand< T, T_ITER, T_RESULT > &lhs, const U &rhs) { 300 | return RcppHoney::make_cbinder< T::NA >()(lhs, 301 | RcppHoney::make_scalar_operator()(rhs, lhs.dims().first)); 302 | } 303 | 304 | template< typename T, typename U, typename U_ITER, typename U_RESULT > 305 | typename RcppHoney::traits::enable_if< 306 | RcppHoney::traits::is_primitive< T >::value, 307 | RcppHoney::cbinder< 308 | typename RcppHoney::scalar_operator< T >::const_iterator, 309 | U_ITER, 310 | U::NA 311 | > 312 | >::type 313 | cbind(const T &lhs, const RcppHoney::operand< U, U_ITER, U_RESULT > &rhs) { 314 | return RcppHoney::make_cbinder< U::NA >()( 315 | RcppHoney::make_scalar_operator()(lhs, rhs.dims().first), rhs); 316 | } 317 | 318 | template< typename T, typename U > 319 | typename RcppHoney::traits::enable_if< 320 | (RcppHoney::hook< T >::value && RcppHoney::hook< U >::value), 321 | RcppHoney::cbinder< 322 | typename RcppHoney::hook< T >::const_iterator, 323 | typename RcppHoney::hook< U >::const_iterator, 324 | (RcppHoney::hook< T >::NA || RcppHoney::hook< U >::NA) 325 | > 326 | >::type 327 | cbind(const T &lhs, const U &rhs) { 328 | return RcppHoney::make_cbinder< 329 | (RcppHoney::hook< T >::NA || RcppHoney::hook< U >::NA) 330 | >()(lhs, rhs); 331 | } 332 | template< typename T, typename T_ITER, typename T_RESULT, typename U > 333 | typename RcppHoney::traits::enable_if< RcppHoney::hook< U >::value, 334 | RcppHoney::cbinder< 335 | T_ITER, 336 | typename RcppHoney::hook< U >::const_iterator, 337 | (T::NA || RcppHoney::hook< U >::NA) 338 | > 339 | >::type 340 | cbind(const RcppHoney::operand< T, T_ITER, T_RESULT > &lhs, const U &rhs) { 341 | return RcppHoney::make_cbinder< (T::NA || RcppHoney::hook< U >::NA) >()( 342 | lhs, 343 | rhs); 344 | } 345 | template< typename T, typename U, typename U_ITER, typename U_RESULT > 346 | typename RcppHoney::traits::enable_if< RcppHoney::hook< T >::value, 347 | RcppHoney::cbinder< 348 | typename RcppHoney::hook< T >::const_iterator, 349 | U_ITER, 350 | (U::NA || RcppHoney::hook< T >::NA) 351 | > 352 | >::type 353 | cbind(const T &lhs, const RcppHoney::operand< U, U_ITER, U_RESULT > &rhs) { 354 | return RcppHoney::make_cbinder< (U::NA || RcppHoney::hook< T >::NA) >()( 355 | lhs, 356 | rhs); 357 | } 358 | template< typename T, typename U > 359 | typename RcppHoney::traits::enable_if< 360 | RcppHoney::traits::is_primitive< T >::value 361 | && RcppHoney::hook< U >::value, 362 | RcppHoney::cbinder< 363 | typename RcppHoney::scalar_operator< T >::const_iterator, 364 | typename RcppHoney::hook< U >::const_iterator, 365 | RcppHoney::hook< U >::NA 366 | > 367 | >::type 368 | cbind(const T &lhs, const U &rhs) { 369 | dims_t dims = RcppHoney::hooks::extract_dims(rhs); 370 | return RcppHoney::make_cbinder< RcppHoney::hook< U >::NA >()( 371 | RcppHoney::make_scalar_operator()(lhs, dims.first), 372 | rhs); 373 | } 374 | template< typename T, typename U > 375 | typename RcppHoney::traits::enable_if< 376 | RcppHoney::traits::is_primitive< U >::value 377 | && RcppHoney::hook< T >::value, 378 | RcppHoney::cbinder< 379 | typename RcppHoney::hook< T >::const_iterator, 380 | typename RcppHoney::scalar_operator< U >::const_iterator, 381 | RcppHoney::hook< T >::NA 382 | > 383 | >::type 384 | cbind(const T &lhs, const U &rhs) { 385 | dims_t dims = RcppHoney::hooks::extract_dims(lhs); 386 | return RcppHoney::make_cbinder< RcppHoney::hook< T >::NA >()( 387 | lhs, 388 | RcppHoney::make_scalar_operator()(rhs, dims.first)); 389 | } 390 | 391 | } // namespace RcppHoney -------------------------------------------------------------------------------- /inst/include/RcppHoney/default_hooks.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | namespace RcppHoney { 21 | namespace hooks { 22 | 23 | // hooks for std::vector 24 | template< typename T, typename A> 25 | RcppHoney::traits::true_type is_hooked(const std::vector< T, A > &val); 26 | 27 | // hooks for std::set 28 | template< typename T, typename C, typename A > 29 | RcppHoney::traits::true_type is_hooked(const std::set< T, C, A > &val); 30 | 31 | // hooks for Rcpp::VectorBase 32 | template< int RTYPE, bool NA, typename T > 33 | RcppHoney::traits::true_type is_hooked( 34 | const Rcpp::VectorBase< RTYPE, NA, T > &val); 35 | 36 | // return the appropriate NA value 37 | template< int RTYPE, typename T > 38 | RcppHoney::traits::false_type has_na( 39 | const Rcpp::VectorBase< RTYPE, false, T > &val); 40 | 41 | template< int RTYPE, typename T > 42 | RcppHoney::traits::true_type has_na( 43 | const Rcpp::VectorBase< RTYPE, true, T > &val); 44 | 45 | // assert that we need to create basic operators 46 | template< int RTYPE, bool NA, typename T > 47 | RcppHoney::traits::true_type needs_basic_operators( 48 | const Rcpp::VectorBase< RTYPE, NA, T > &val); 49 | 50 | // assert that we need to create type + scalar operators 51 | template< int RTYPE, bool NA, typename T > 52 | RcppHoney::traits::true_type needs_scalar_operators( 53 | const Rcpp::VectorBase< RTYPE, NA, T > &val); 54 | 55 | // call this family 2 56 | template< int RTYPE, bool NA, typename T > 57 | RcppHoney::traits::int_constant< 2 > family( 58 | const Rcpp::VectorBase< RTYPE, NA, T > &val); 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | // hooks for Rcpp::VectorBase 67 | template< int RTYPE, template< class > class StoragePolicy > 68 | RcppHoney::traits::true_type is_hooked( 69 | const Rcpp::Matrix< RTYPE, StoragePolicy > &val); 70 | 71 | // return the appropriate NA value 72 | template< int RTYPE, template< class > class StoragePolicy > 73 | RcppHoney::traits::true_type has_na( 74 | const Rcpp::Matrix< RTYPE, StoragePolicy > &val); 75 | 76 | // assert that we need to create basic operators 77 | template< int RTYPE, template< class > class StoragePolicy > 78 | RcppHoney::traits::true_type needs_basic_operators( 79 | const Rcpp::Matrix< RTYPE, StoragePolicy > &val); 80 | 81 | // assert that we need to create type + scalar operators 82 | template< int RTYPE, template< class > class StoragePolicy > 83 | RcppHoney::traits::true_type needs_scalar_operators( 84 | const Rcpp::Matrix< RTYPE, StoragePolicy > &val); 85 | 86 | // call this family 3 87 | template< int RTYPE, template< class > class StoragePolicy > 88 | RcppHoney::traits::int_constant< 3 > family( 89 | const Rcpp::Matrix< RTYPE, StoragePolicy > &val); 90 | 91 | template< int RTYPE, template< class > class StoragePolicy > 92 | dims_t extract_dims( 93 | const Rcpp::Matrix< RTYPE, StoragePolicy > &obj) 94 | { 95 | return dims_t(obj.nrow(), obj.ncol()); 96 | } 97 | 98 | template< typename T, typename T_ITER, typename T_RESULT > 99 | dims_t extract_dims(const operand< T, T_ITER, T_RESULT > &obj) { 100 | return obj.dims(); 101 | } 102 | 103 | } // namespace hooks 104 | } // namespace RcppHoney 105 | -------------------------------------------------------------------------------- /inst/include/RcppHoney/exceptions.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | namespace RcppHoney { 23 | 24 | class bounds_exception : public std::exception { 25 | virtual const char *what() const throw() { 26 | return "operand size mismatch"; 27 | } 28 | }; 29 | 30 | } // namespace RcppHoney 31 | -------------------------------------------------------------------------------- /inst/include/RcppHoney/hook.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | #include "traits/integral_constant.hpp" 21 | #include "traits/result_of.hpp" 22 | #include "default_hooks.hpp" 23 | 24 | namespace RcppHoney { 25 | 26 | namespace hooks { 27 | 28 | template< typename T > 29 | T create_type(); 30 | 31 | traits::false_type is_hooked(...); 32 | 33 | traits::true_type has_na(...); 34 | 35 | traits::true_type needs_basic_operators(...); 36 | 37 | traits::true_type needs_scalar_operators(...); 38 | 39 | traits::int_constant< 1 > family(...); 40 | 41 | template< typename T > 42 | dims_t extract_dims(const T &obj) { 43 | return dims_t(obj.size(), 0); 44 | } 45 | 46 | } // namespace hooks 47 | 48 | template< typename T, typename U = typename T::const_iterator > 49 | struct hook { 50 | static const bool value = 51 | (sizeof(::RcppHoney::hooks::is_hooked(hooks::create_type< T >())) 52 | == sizeof(traits::true_type)); 53 | static const bool NA = 54 | sizeof(hooks::has_na(hooks::create_type< T >())) 55 | == sizeof(traits::true_type); 56 | static const bool NEED_BASIC_OPERATORS = 57 | sizeof(hooks::needs_basic_operators(hooks::create_type< T>())) 58 | == sizeof(traits::true_type); 59 | static const bool NEED_SCALAR_OPERATORS = 60 | sizeof(hooks::needs_scalar_operators(hooks::create_type< T >())) 61 | == sizeof(traits::true_type); 62 | static const int FAMILY = 63 | sizeof(hooks::family(hooks::create_type< T >())) / sizeof(long); 64 | 65 | typedef U const_iterator; 66 | }; 67 | 68 | 69 | } // namespace RcppHoney 70 | -------------------------------------------------------------------------------- /inst/include/RcppHoney/na.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include "traits/ctype.hpp" 23 | 24 | namespace RcppHoney { 25 | 26 | template< typename T > 27 | struct na {}; 28 | 29 | template<> 30 | struct na< int > { 31 | static const int VALUE() {return NA_INTEGER;} 32 | static const bool is_na(int val) {return NA_INTEGER == val;} 33 | }; 34 | 35 | template<> 36 | struct na< double > { 37 | static const double VALUE() {return NA_REAL;} 38 | static const bool is_na(double val) {return R_IsNA(val);} 39 | }; 40 | 41 | template< typename T > 42 | struct rtype {}; 43 | 44 | template<> 45 | struct rtype< int > { 46 | static const int value = INTSXP; 47 | }; 48 | 49 | template<> 50 | struct rtype< double > { 51 | static const int value = REALSXP; 52 | }; 53 | 54 | template< typename T > 55 | bool is_na(const T &lhs) { 56 | return na< typename traits::ctype< T >::type >::is_na(lhs); 57 | } 58 | 59 | template< typename T, typename U > 60 | bool either_na(const T &lhs, const U &rhs) { 61 | return na< typename traits::ctype< T >::type >::is_na(lhs) 62 | || na< typename traits::ctype< U >::type >::is_na(rhs); 63 | } 64 | 65 | } // namespace RcppHoney 66 | -------------------------------------------------------------------------------- /inst/include/RcppHoney/operand.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace RcppHoney { 25 | 26 | template< typename T, typename T_ITER, typename T_RESULT > 27 | class operand 28 | { 29 | public: 30 | typedef T_ITER const_iterator; 31 | typedef const_iterator iterator; 32 | typedef T_RESULT result_type; 33 | 34 | public: 35 | dims_t dims() const { 36 | return static_cast< const T * >(this)->dims(); 37 | } 38 | 39 | int64_t size() const { 40 | return static_cast< const T * >(this)->size(); 41 | } 42 | 43 | const_iterator begin() const { 44 | return static_cast< const T * >(this)->begin(); 45 | } 46 | 47 | const_iterator end() const { 48 | return static_cast< const T * >(this)->end(); 49 | } 50 | 51 | result_type operator[](ptrdiff_t n) const { 52 | return *(static_cast< const T * >(this)->begin() + n); 53 | } 54 | 55 | operator SEXP() const 56 | { 57 | const int RTYPE = Rcpp::traits::r_sexptype_traits< T_RESULT >::rtype; 58 | RcppHoney::dims_t dim = dims(); 59 | 60 | if (dim.second == 0) { 61 | Rcpp::Shield< SEXP > x(Rf_allocVector(RTYPE, size())); 62 | std::copy(begin(), end(), 63 | Rcpp::internal::r_vector_start< RTYPE >(x)); 64 | return x; 65 | } else { 66 | Rcpp::Shield< SEXP > x(Rf_allocMatrix(RTYPE, dim.first, 67 | dim.second)); 68 | std::copy(begin(), end(), 69 | Rcpp::internal::r_vector_start< RTYPE >(x)); 70 | return x; 71 | } 72 | } 73 | }; 74 | 75 | } // namespace RcppHoney 76 | -------------------------------------------------------------------------------- /inst/include/RcppHoney/operators.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | #include "operand.hpp" 21 | #include "scalar_operator.hpp" 22 | #include "unary_operator.hpp" 23 | #include "binary_operator.hpp" 24 | #include "functors.hpp" 25 | #include "hook.hpp" 26 | #include "traits/enable_if.hpp" 27 | #include "traits/is_primitive.hpp" 28 | 29 | #define RCPP_HONEY_GENERATE_BINARY_OPERATOR(_OP_, _FUNCTOR_) \ 30 | template< typename T, typename T_ITER, typename T_RESULT, typename U, \ 31 | typename U_ITER, typename U_RESULT > \ 32 | inline RcppHoney::binary_operator< T_ITER, U_ITER, \ 33 | RcppHoney::functors:: _FUNCTOR_ < T_ITER, U_ITER, (T::NA || U::NA) >, \ 34 | (T::NA || U::NA) \ 35 | > \ 36 | operator _OP_ (const RcppHoney::operand< T, T_ITER, T_RESULT > &lhs, \ 37 | const RcppHoney::operand< U, U_ITER, U_RESULT > &rhs) { \ 38 | \ 39 | return RcppHoney::make_binary_operator< (T::NA || U::NA) >()( \ 40 | lhs, rhs, \ 41 | RcppHoney::functors:: _FUNCTOR_ < \ 42 | T_ITER, \ 43 | U_ITER, \ 44 | (T::NA || U::NA) \ 45 | >() \ 46 | ); \ 47 | } \ 48 | \ 49 | template< typename T, typename T_ITER, typename T_RESULT, typename U > \ 50 | inline typename RcppHoney::traits::enable_if< \ 51 | RcppHoney::traits::is_primitive< U >::value, \ 52 | RcppHoney::binary_operator< \ 53 | T_ITER, \ 54 | typename RcppHoney::scalar_operator< U >::const_iterator, \ 55 | RcppHoney::functors:: _FUNCTOR_ < \ 56 | T_ITER, \ 57 | typename RcppHoney::scalar_operator< U >::const_iterator, \ 58 | T::NA \ 59 | >, \ 60 | T::NA \ 61 | > \ 62 | >::type \ 63 | operator _OP_ (const RcppHoney::operand< T, T_ITER, T_RESULT > &lhs, \ 64 | const U &rhs) { \ 65 | \ 66 | return RcppHoney::make_binary_operator< T::NA >()(lhs, \ 67 | RcppHoney::make_scalar_operator()(rhs), \ 68 | RcppHoney::functors:: _FUNCTOR_ < \ 69 | T_ITER, \ 70 | typename RcppHoney::scalar_operator< U >::const_iterator, \ 71 | T::NA \ 72 | >() \ 73 | ); \ 74 | } \ 75 | \ 76 | template< typename T, typename U, typename U_ITER, typename U_RESULT > \ 77 | inline typename RcppHoney::traits::enable_if< \ 78 | RcppHoney::traits::is_primitive< T >::value, \ 79 | RcppHoney::binary_operator< \ 80 | typename RcppHoney::scalar_operator< T >::const_iterator, \ 81 | U_ITER, \ 82 | RcppHoney::functors:: _FUNCTOR_ < \ 83 | typename RcppHoney::scalar_operator< T >::const_iterator, \ 84 | U_ITER, \ 85 | U::NA \ 86 | >, \ 87 | U::NA \ 88 | > \ 89 | >::type \ 90 | operator _OP_ (const T &lhs, \ 91 | const RcppHoney::operand< U, U_ITER, U_RESULT > &rhs) { \ 92 | \ 93 | return RcppHoney::make_binary_operator< U::NA >()( \ 94 | RcppHoney::make_scalar_operator()(lhs), \ 95 | rhs, \ 96 | RcppHoney::functors:: _FUNCTOR_ < \ 97 | typename RcppHoney::scalar_operator< T >::const_iterator, \ 98 | U_ITER, \ 99 | U::NA \ 100 | >() \ 101 | ); \ 102 | } \ 103 | \ 104 | template< typename T, typename U > \ 105 | inline typename RcppHoney::traits::enable_if< \ 106 | (RcppHoney::hook< T >::value && RcppHoney::hook< U >::value \ 107 | && (((RcppHoney::hook< T >::FAMILY == 1 \ 108 | || RcppHoney::hook< U >::FAMILY == 1) \ 109 | || RcppHoney::hook< T >::FAMILY \ 110 | != RcppHoney::hook< U >::FAMILY) \ 111 | || RcppHoney::hook< T >::NEED_BASIC_OPERATORS)), \ 112 | RcppHoney::binary_operator< \ 113 | typename RcppHoney::hook< T >::const_iterator, \ 114 | typename RcppHoney::hook< U >::const_iterator, \ 115 | RcppHoney::functors:: _FUNCTOR_ < \ 116 | typename RcppHoney::hook< T >::const_iterator, \ 117 | typename RcppHoney::hook< U >::const_iterator, \ 118 | (RcppHoney::hook< T >::NA || RcppHoney::hook< U >::NA) \ 119 | >, \ 120 | (RcppHoney::hook< T >::NA || RcppHoney::hook< U >::NA) \ 121 | > \ 122 | >::type \ 123 | operator _OP_ (const T &lhs, const U &rhs) { \ 124 | return RcppHoney::make_binary_operator< \ 125 | (RcppHoney::hook< T >::NA || RcppHoney::hook< U >::NA) \ 126 | >()(lhs, \ 127 | rhs, \ 128 | RcppHoney::functors:: _FUNCTOR_ < \ 129 | typename RcppHoney::hook< T >::const_iterator, \ 130 | typename RcppHoney::hook< U >::const_iterator, \ 131 | (RcppHoney::hook< T >::NA || RcppHoney::hook< U >::NA) \ 132 | >() \ 133 | ); \ 134 | } \ 135 | \ 136 | template< typename T, typename T_ITER, typename T_RESULT, typename U > \ 137 | inline typename RcppHoney::traits::enable_if< RcppHoney::hook< U >::value, \ 138 | RcppHoney::binary_operator< \ 139 | T_ITER, \ 140 | typename RcppHoney::hook< U >::const_iterator, \ 141 | RcppHoney::functors:: _FUNCTOR_ < \ 142 | T_ITER, \ 143 | typename RcppHoney::hook< U >::const_iterator, \ 144 | (T::NA || RcppHoney::hook< U >::NA) \ 145 | >, \ 146 | (T::NA || RcppHoney::hook< U >::NA) \ 147 | > \ 148 | >::type \ 149 | operator _OP_ (const RcppHoney::operand< T, T_ITER, T_RESULT > &lhs, \ 150 | const U &rhs) { \ 151 | \ 152 | return RcppHoney::make_binary_operator< \ 153 | (T::NA || RcppHoney::hook< U >::NA) \ 154 | >()(lhs, \ 155 | rhs, \ 156 | RcppHoney::functors:: _FUNCTOR_ < \ 157 | T_ITER, \ 158 | typename RcppHoney::hook< U >::const_iterator, \ 159 | (T::NA || RcppHoney::hook< U >::NA) \ 160 | >() \ 161 | ); \ 162 | } \ 163 | \ 164 | template< typename T, typename U, typename U_ITER, typename U_RESULT > \ 165 | inline typename RcppHoney::traits::enable_if< RcppHoney::hook< T >::value, \ 166 | RcppHoney::binary_operator< \ 167 | typename RcppHoney::hook< T >::const_iterator, \ 168 | U_ITER, \ 169 | RcppHoney::functors:: _FUNCTOR_ < \ 170 | typename RcppHoney::hook< T >::const_iterator, \ 171 | U_ITER, \ 172 | (U::NA || RcppHoney::hook< T >::NA) \ 173 | >, \ 174 | (U::NA || RcppHoney::hook< T >::NA) \ 175 | > \ 176 | >::type \ 177 | operator _OP_ (const T &lhs, \ 178 | const RcppHoney::operand< U, U_ITER, U_RESULT > &rhs) { \ 179 | \ 180 | return RcppHoney::make_binary_operator< \ 181 | (U::NA || RcppHoney::hook< T >::NA) \ 182 | >()(lhs, \ 183 | rhs, \ 184 | RcppHoney::functors:: _FUNCTOR_ < \ 185 | typename RcppHoney::hook< T >::const_iterator, \ 186 | U_ITER, \ 187 | (U::NA || RcppHoney::hook< T >::NA) \ 188 | >() \ 189 | ); \ 190 | } \ 191 | \ 192 | template< typename T, typename U > \ 193 | inline typename RcppHoney::traits::enable_if< \ 194 | RcppHoney::traits::is_primitive< T >::value \ 195 | && RcppHoney::hook< U >::value \ 196 | && RcppHoney::hook< U >::NEED_SCALAR_OPERATORS, \ 197 | RcppHoney::binary_operator< \ 198 | typename RcppHoney::scalar_operator< T >::const_iterator, \ 199 | typename RcppHoney::hook< U >::const_iterator, \ 200 | RcppHoney::functors:: _FUNCTOR_ < \ 201 | typename RcppHoney::scalar_operator< T >::const_iterator, \ 202 | typename RcppHoney::hook< U >::const_iterator, \ 203 | RcppHoney::hook< U >::NA \ 204 | >, \ 205 | RcppHoney::hook< U >::NA \ 206 | > \ 207 | >::type \ 208 | operator _OP_ (const T &lhs, const U &rhs) { \ 209 | return RcppHoney::make_binary_operator< RcppHoney::hook< U >::NA >()( \ 210 | RcppHoney::make_scalar_operator()(lhs), \ 211 | rhs, \ 212 | RcppHoney::functors:: _FUNCTOR_ < \ 213 | typename RcppHoney::scalar_operator< T >::const_iterator, \ 214 | typename RcppHoney::hook< U >::const_iterator, \ 215 | RcppHoney::hook< U >::NA \ 216 | >()); \ 217 | } \ 218 | \ 219 | template< typename T, typename U > \ 220 | inline typename RcppHoney::traits::enable_if< \ 221 | RcppHoney::traits::is_primitive< U >::value \ 222 | && RcppHoney::hook< T >::value \ 223 | && RcppHoney::hook< T >::NEED_SCALAR_OPERATORS, \ 224 | RcppHoney::binary_operator< \ 225 | typename RcppHoney::hook< T >::const_iterator, \ 226 | typename RcppHoney::scalar_operator< U >::const_iterator, \ 227 | RcppHoney::functors:: _FUNCTOR_ < \ 228 | typename RcppHoney::hook< T >::const_iterator, \ 229 | typename RcppHoney::scalar_operator< U >::const_iterator, \ 230 | RcppHoney::hook< T >::NA \ 231 | >, \ 232 | RcppHoney::hook< T >::NA \ 233 | > \ 234 | >::type \ 235 | operator _OP_ (const T &lhs, const U &rhs) { \ 236 | return RcppHoney::make_binary_operator< RcppHoney::hook< T >::NA >()( \ 237 | lhs, \ 238 | RcppHoney::make_scalar_operator()(rhs), \ 239 | RcppHoney::functors:: _FUNCTOR_ < \ 240 | typename RcppHoney::hook< T >::const_iterator, \ 241 | typename RcppHoney::scalar_operator< U >::const_iterator, \ 242 | RcppHoney::hook< T >::NA \ 243 | >()); \ 244 | } 245 | 246 | 247 | RCPP_HONEY_GENERATE_BINARY_OPERATOR(+, plus) 248 | RCPP_HONEY_GENERATE_BINARY_OPERATOR(-, minus) 249 | RCPP_HONEY_GENERATE_BINARY_OPERATOR(*, times) 250 | RCPP_HONEY_GENERATE_BINARY_OPERATOR(/, divided_by) 251 | RCPP_HONEY_GENERATE_BINARY_OPERATOR(>, greater) 252 | RCPP_HONEY_GENERATE_BINARY_OPERATOR(>=, greater_equal) 253 | RCPP_HONEY_GENERATE_BINARY_OPERATOR(<, less) 254 | RCPP_HONEY_GENERATE_BINARY_OPERATOR(<=, less_equal) 255 | RCPP_HONEY_GENERATE_BINARY_OPERATOR(==, equal) 256 | RCPP_HONEY_GENERATE_BINARY_OPERATOR(!=, not_equal) 257 | 258 | #define RCPP_HONEY_GENERATE_UNARY_OPERATOR(_OP_, _FUNCTOR_) \ 259 | template< typename T, typename T_ITER, typename T_RESULT > \ 260 | RcppHoney::unary_operator< \ 261 | T_ITER, \ 262 | RcppHoney::functors:: _FUNCTOR_ , \ 263 | T::NA \ 264 | > \ 265 | operator _OP_ (const RcppHoney::operand< T, T_ITER, T_RESULT > &rhs) { \ 266 | return RcppHoney::make_unary_operator< T::NA >()(rhs, \ 267 | RcppHoney::functors:: _FUNCTOR_ < T_ITER, T::NA >()); \ 268 | } \ 269 | \ 270 | template< typename T > \ 271 | typename RcppHoney::traits::enable_if< \ 272 | RcppHoney::hook< T >::value, \ 273 | RcppHoney::unary_operator< \ 274 | typename RcppHoney::hook< T >::const_iterator, \ 275 | RcppHoney::functors:: _FUNCTOR_ < \ 276 | typename RcppHoney::hook< T >::const_iterator, \ 277 | RcppHoney::hook< T >::NA \ 278 | >, \ 279 | RcppHoney::hook< T >::NA \ 280 | > \ 281 | >::type \ 282 | operator _OP_ (const T &rhs) { \ 283 | return RcppHoney::make_unary_operator< RcppHoney::hook< T >::NA >()(rhs, \ 284 | RcppHoney::functors:: _FUNCTOR_ < \ 285 | typename RcppHoney::hook< T >::const_iterator, \ 286 | RcppHoney::hook< T >::NA \ 287 | >()); \ 288 | } 289 | 290 | RCPP_HONEY_GENERATE_UNARY_OPERATOR(-, unary_minus) 291 | RCPP_HONEY_GENERATE_UNARY_OPERATOR(!, unary_not) 292 | -------------------------------------------------------------------------------- /inst/include/RcppHoney/scalar_operator.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | #include "operand.hpp" 24 | 25 | namespace RcppHoney { 26 | 27 | template< typename T > 28 | struct scalar_operator_iterator 29 | : public std::iterator< std::bidirectional_iterator_tag, T > { 30 | private: 31 | T m_value; 32 | uint64_t m_count; 33 | 34 | public: 35 | inline scalar_operator_iterator() {} 36 | 37 | inline scalar_operator_iterator(const T &val) : m_value(val), m_count(0) {} 38 | 39 | inline scalar_operator_iterator(const T &val, const uint64_t count) 40 | : m_value(val), m_count(count) {} 41 | 42 | inline T operator*() { 43 | return m_value; 44 | } 45 | 46 | inline scalar_operator_iterator &operator++() { 47 | ++m_count; 48 | return *this; 49 | } 50 | 51 | inline scalar_operator_iterator operator++(int) { 52 | scalar_operator_iterator i = *this; 53 | operator++(); 54 | return i; 55 | } 56 | 57 | inline scalar_operator_iterator &operator--() { 58 | --m_count; 59 | return *this; 60 | } 61 | 62 | inline scalar_operator_iterator operator--(int) { 63 | scalar_operator_iterator i = *this; 64 | operator--(); 65 | return i; 66 | } 67 | 68 | inline bool operator==(const scalar_operator_iterator &rhs) const { 69 | return m_count == rhs.m_count; 70 | } 71 | 72 | inline bool operator!=(const scalar_operator_iterator &rhs) const { 73 | return !operator==(rhs); 74 | } 75 | }; 76 | 77 | template< typename T > 78 | struct scalar_operator_result_type { 79 | typedef T result_type; 80 | }; 81 | 82 | template< typename T > 83 | class scalar_operator 84 | : public operand< 85 | scalar_operator< T >, 86 | scalar_operator_iterator< T >, 87 | typename scalar_operator_result_type< T >::result_type 88 | > { 89 | public: 90 | typedef typename scalar_operator_result_type< T >::result_type result_type; 91 | static const bool NA = false; 92 | 93 | public: 94 | typedef scalar_operator_iterator< T > const_iterator; 95 | typedef const_iterator iterator; 96 | 97 | private: 98 | T m_value; 99 | dims_t m_dims; 100 | 101 | public: 102 | scalar_operator(const T &val) : m_value(val) { 103 | m_dims.first = -1; 104 | m_dims.second = 0; 105 | } 106 | 107 | scalar_operator(const T &val, uint64_t maxSize) : m_value(val) { 108 | m_dims.first = maxSize; 109 | m_dims.second = 0; 110 | } 111 | 112 | dims_t dims() const {return m_dims;} 113 | uint64_t size() const {return m_dims.first;} 114 | const_iterator begin() const {return const_iterator(m_value);} 115 | const_iterator end() const {return const_iterator(m_value, m_dims.first);} 116 | }; 117 | 118 | struct make_scalar_operator { 119 | template< typename T > 120 | scalar_operator< T > operator()(const T &obj) { 121 | return scalar_operator< T >(obj); 122 | } 123 | 124 | template< typename T > 125 | scalar_operator< T > operator()(const T &obj, uint64_t count) { 126 | return scalar_operator< T >(obj, count); 127 | } 128 | }; 129 | 130 | } // namespace RcppHoney 131 | -------------------------------------------------------------------------------- /inst/include/RcppHoney/storage.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | #include "operand.hpp" 21 | #include 22 | 23 | namespace RcppHoney { 24 | 25 | class LogicalVector : public Rcpp::LogicalVector { 26 | public: 27 | template< typename T, typename T_ITER, typename T_RESULT > 28 | LogicalVector(const operand< T, T_ITER, T_RESULT > &rhs) 29 | : Rcpp::LogicalVector(rhs.size()) { 30 | std::copy(rhs.begin(), rhs.end(), begin()); 31 | } 32 | }; 33 | 34 | class IntegerVector : public Rcpp::IntegerVector { 35 | public: 36 | template< typename T, typename T_ITER, typename T_RESULT > 37 | IntegerVector(const operand< T, T_ITER, T_RESULT > &rhs) 38 | : Rcpp::IntegerVector(rhs.size()) { 39 | std::copy(rhs.begin(), rhs.end(), begin()); 40 | } 41 | }; 42 | 43 | class NumericVector : public Rcpp::NumericVector { 44 | public: 45 | template< typename T, typename T_ITER, typename T_RESULT > 46 | NumericVector(const operand< T, T_ITER, T_RESULT > &rhs) 47 | : Rcpp::NumericVector(rhs.size()) { 48 | std::copy(rhs.begin(), rhs.end(), begin()); 49 | } 50 | }; 51 | 52 | class LogicalMatrix : public Rcpp::LogicalMatrix { 53 | public: 54 | template< typename T, typename T_ITER, typename T_RESULT > 55 | LogicalMatrix(const operand< T, T_ITER, T_RESULT > &rhs) 56 | : Rcpp::LogicalMatrix(rhs.dims().first, rhs.dims().second) { 57 | std::copy(rhs.begin(), rhs.end(), begin()); 58 | } 59 | }; 60 | 61 | class IntegerMatrix : public Rcpp::IntegerMatrix { 62 | public: 63 | template< typename T, typename T_ITER, typename T_RESULT > 64 | IntegerMatrix(const operand< T, T_ITER, T_RESULT > &rhs) 65 | : Rcpp::IntegerMatrix(rhs.dims().first, rhs.dims().second) { 66 | std::copy(rhs.begin(), rhs.end(), begin()); 67 | } 68 | }; 69 | 70 | class NumericMatrix : public Rcpp::NumericMatrix { 71 | public: 72 | template< typename T, typename T_ITER, typename T_RESULT > 73 | NumericMatrix(const operand< T, T_ITER, T_RESULT > &rhs) 74 | : Rcpp::NumericMatrix(rhs.dims().first, rhs.dims().second) { 75 | std::copy(rhs.begin(), rhs.end(), begin()); 76 | } 77 | }; 78 | 79 | 80 | 81 | } // namespace RcppHoney 82 | -------------------------------------------------------------------------------- /inst/include/RcppHoney/traits/ctype.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | namespace RcppHoney { 21 | namespace traits { 22 | 23 | typedef struct {char a[1];} CTYPE_CHAR; 24 | typedef struct {char a[2];} CTYPE_SHORT; 25 | typedef struct {char a[3];} CTYPE_INT; 26 | typedef struct {char a[4];} CTYPE_LONG; 27 | typedef struct {char a[6];} CTYPE_FLOAT; 28 | typedef struct {char a[7];} CTYPE_DOUBLE; 29 | typedef struct {char a[8];} CTYPE_LONG_DOUBLE; 30 | typedef struct {char a[9];} CTYPE_STRING; 31 | typedef struct {char a[10];} CTYPE_UNSIGNED_CHAR; 32 | typedef struct {char a[11];} CTYPE_UNSIGNED_SHORT; 33 | typedef struct {char a[12];} CTYPE_UNSIGNED_INT; 34 | typedef struct {char a[13];} CTYPE_UNSIGNED_LONG; 35 | typedef struct {char a[15];} CTYPE_RCOMPLEX; 36 | typedef struct {char a[128];} CTYPE_UNKNOWN; 37 | 38 | template< std::size_t I > 39 | struct ctype_helper { static const bool value = false; }; 40 | 41 | template<> 42 | struct ctype_helper< sizeof(CTYPE_CHAR) > { 43 | typedef char type; 44 | static const bool value = true; 45 | }; 46 | 47 | template<> 48 | struct ctype_helper< sizeof(CTYPE_SHORT) > { 49 | typedef short type; 50 | static const bool value = true; 51 | }; 52 | 53 | template<> 54 | struct ctype_helper< sizeof(CTYPE_INT) > { 55 | typedef int type; 56 | static const bool value = true; 57 | }; 58 | 59 | template<> 60 | struct ctype_helper< sizeof(CTYPE_LONG) > { 61 | typedef long type; 62 | static const bool value = true; 63 | }; 64 | 65 | template<> 66 | struct ctype_helper< sizeof(CTYPE_FLOAT) > { 67 | typedef float type; 68 | static const bool value = true; 69 | }; 70 | 71 | template<> 72 | struct ctype_helper< sizeof(CTYPE_DOUBLE) > { 73 | typedef double type; 74 | static const bool value = true; 75 | }; 76 | 77 | template<> 78 | struct ctype_helper< sizeof(CTYPE_LONG_DOUBLE) > { 79 | typedef long double type; 80 | static const bool value = true; 81 | }; 82 | 83 | template<> 84 | struct ctype_helper< sizeof(CTYPE_STRING) > { 85 | typedef std::string type; 86 | static const bool value = true; 87 | }; 88 | 89 | template<> 90 | struct ctype_helper< sizeof(CTYPE_UNSIGNED_CHAR) > { 91 | typedef unsigned char type; 92 | static const bool value = true; 93 | }; 94 | 95 | template<> 96 | struct ctype_helper< sizeof(CTYPE_UNSIGNED_SHORT) > { 97 | typedef unsigned short type; 98 | static const bool value = true; 99 | }; 100 | 101 | template<> 102 | struct ctype_helper< sizeof(CTYPE_UNSIGNED_INT) > { 103 | typedef unsigned int type; 104 | static const bool value = true; 105 | }; 106 | 107 | template<> 108 | struct ctype_helper< sizeof(CTYPE_UNSIGNED_LONG) > { 109 | typedef unsigned long type; 110 | static const bool value = true; 111 | }; 112 | 113 | template<> 114 | struct ctype_helper< sizeof(CTYPE_RCOMPLEX) > { 115 | typedef Rcomplex type; 116 | static const bool value = true; 117 | }; 118 | 119 | template< typename T > 120 | struct ctype 121 | { 122 | static CTYPE_CHAR test(const char &); 123 | static CTYPE_SHORT test(const short &); 124 | static CTYPE_INT test(const int &); 125 | static CTYPE_LONG test(const long &); 126 | static CTYPE_FLOAT test(const float &); 127 | static CTYPE_DOUBLE test(const double &); 128 | static CTYPE_LONG_DOUBLE test(const long double &); 129 | static CTYPE_STRING test(const std::string &); 130 | static CTYPE_UNSIGNED_CHAR test(const unsigned char &); 131 | static CTYPE_UNSIGNED_SHORT test(const unsigned short &); 132 | static CTYPE_UNSIGNED_INT test(const unsigned int &); 133 | static CTYPE_UNSIGNED_LONG test(const unsigned long &); 134 | static CTYPE_RCOMPLEX test(const Rcomplex &); 135 | static CTYPE_UNKNOWN test(...); 136 | 137 | static T make(); 138 | 139 | typedef typename ctype_helper< sizeof(test(make())) >::type type; 140 | }; 141 | 142 | template< typename T > 143 | struct decays_to_ctype 144 | { 145 | static CTYPE_CHAR test(const char &); 146 | static CTYPE_SHORT test(const short &); 147 | static CTYPE_INT test(const int &); 148 | static CTYPE_LONG test(const long &); 149 | static CTYPE_FLOAT test(const float &); 150 | static CTYPE_DOUBLE test(const double &); 151 | static CTYPE_LONG_DOUBLE test(const long double &); 152 | static CTYPE_STRING test(const std::string &); 153 | static CTYPE_UNSIGNED_CHAR test(const unsigned char &); 154 | static CTYPE_UNSIGNED_SHORT test(const unsigned short &); 155 | static CTYPE_UNSIGNED_INT test(const unsigned int &); 156 | static CTYPE_UNSIGNED_LONG test(const unsigned long &); 157 | static CTYPE_RCOMPLEX test(const Rcomplex &); 158 | static CTYPE_UNKNOWN test(...); 159 | 160 | static T make(); 161 | 162 | static const bool value = ctype_helper< sizeof(test(make())) >::value; 163 | }; 164 | 165 | } // namespace traits 166 | } // namespace RcppHoney 167 | -------------------------------------------------------------------------------- /inst/include/RcppHoney/traits/enable_if.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | namespace RcppHoney { 21 | namespace traits { 22 | 23 | template< bool VAL, typename T > 24 | struct enable_if { 25 | }; 26 | 27 | template< typename T > 28 | struct enable_if< true, T > { 29 | typedef T type; 30 | }; 31 | 32 | } // namespace traits 33 | } // namespace RcppHoney 34 | -------------------------------------------------------------------------------- /inst/include/RcppHoney/traits/if_else.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | namespace RcppHoney { 21 | namespace traits { 22 | 23 | template< bool B, typename LHS = void, typename RHS = void > 24 | struct if_else {}; 25 | 26 | template< typename LHS, typename RHS > 27 | struct if_else< true, LHS, RHS > { 28 | typedef LHS type; 29 | }; 30 | 31 | template< typename LHS, typename RHS > 32 | struct if_else< false, LHS, RHS > { 33 | typedef RHS type; 34 | }; 35 | 36 | } // namespace traits 37 | } // namespace RcppHoney 38 | -------------------------------------------------------------------------------- /inst/include/RcppHoney/traits/integral_constant.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | namespace RcppHoney { 21 | namespace traits { 22 | 23 | struct true_type { 24 | static const bool value = true; 25 | }; 26 | 27 | struct false_type { 28 | static const bool value = false; 29 | char pad[64]; // makes sizeof(false_type) different than sizeof(true_type) 30 | }; 31 | 32 | template< int VALUE > 33 | struct int_constant { 34 | static const int value = VALUE; 35 | const long size[VALUE]; // makes sizeof(int_constant::size) == VALUE 36 | }; 37 | 38 | } // namespace traits 39 | } // namespace RcppHoney 40 | -------------------------------------------------------------------------------- /inst/include/RcppHoney/traits/is_primitive.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | namespace RcppHoney { 21 | namespace traits { 22 | 23 | template< typename T > 24 | struct is_primitive { 25 | static const bool value = false; 26 | }; 27 | 28 | template<> 29 | struct is_primitive< int > { 30 | static const bool value = true; 31 | }; 32 | 33 | template<> 34 | struct is_primitive< double > { 35 | static const bool value = true; 36 | }; 37 | 38 | //template<> 39 | //struct is_primitive< Rcomplex > { 40 | // static const bool value = true; 41 | //}; 42 | 43 | } // namespace traits 44 | } // namespace RcppHoney 45 | -------------------------------------------------------------------------------- /inst/include/RcppHoney/traits/result_of.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | namespace RcppHoney { 21 | namespace traits { 22 | 23 | template< typename T > 24 | struct result_of { 25 | }; 26 | 27 | template< typename T, typename U > 28 | struct result_of< T (*)(U) > { 29 | typedef T type; 30 | }; 31 | 32 | } // namespace traits 33 | } // namespace RcppHoney 34 | -------------------------------------------------------------------------------- /inst/include/RcppHoney/traits/widest_numeric_type.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | #include "ctype.hpp" 21 | #include "if_else.hpp" 22 | 23 | namespace RcppHoney { 24 | namespace traits { 25 | 26 | template < typename T > 27 | struct numeric_index {}; 28 | 29 | template<> 30 | struct numeric_index< bool > { static const char value = 0; }; 31 | 32 | template<> 33 | struct numeric_index< short > { static const char value = 1; }; 34 | 35 | template<> 36 | struct numeric_index< int > { static const char value = 2; }; 37 | 38 | template<> 39 | struct numeric_index< long > { static const char value = 3; }; 40 | 41 | template<> 42 | struct numeric_index< float > { static const char value = 5; }; 43 | 44 | template<> 45 | struct numeric_index< double > { static const char value = 6; }; 46 | 47 | template<> 48 | struct numeric_index< long double > { static const char value = 7; }; 49 | 50 | template<> 51 | struct numeric_index< Rcomplex > { static const char value = 8; }; 52 | 53 | template< typename LHS, typename RHS > 54 | struct widest_numeric_type { 55 | typedef typename if_else< 56 | (numeric_index< typename ctype< LHS >::type >::value 57 | > numeric_index< typename ctype< RHS >::type >::value), 58 | typename ctype< LHS >::type, 59 | typename ctype< RHS >::type >::type type; 60 | }; 61 | 62 | } // namespace traits 63 | } // namespace RcppHoney 64 | -------------------------------------------------------------------------------- /inst/include/RcppHoney/unary_operator.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | #include "operand.hpp" 24 | #include "hook.hpp" 25 | 26 | namespace RcppHoney { 27 | 28 | template< typename InputIterator, typename Op, bool NA_VALUE > 29 | struct unary_operator_iterator 30 | : public std::iterator< 31 | std::bidirectional_iterator_tag, 32 | typename Op::return_type 33 | > { 34 | private: 35 | InputIterator m_pos; 36 | typename Op::return_type m_value; 37 | bool m_dirty; 38 | Op m_operator; 39 | 40 | public: 41 | inline unary_operator_iterator() : m_dirty(true) {} 42 | 43 | inline unary_operator_iterator(const InputIterator &pos, const Op &op) 44 | : m_pos(pos), m_dirty(true), m_operator(op) {} 45 | 46 | inline typename Op::return_type operator*() { 47 | if (m_dirty) { 48 | m_value = m_operator(m_pos); 49 | m_dirty = false; 50 | } 51 | 52 | return m_value; 53 | } 54 | 55 | inline unary_operator_iterator &operator++() { 56 | ++m_pos; 57 | m_dirty = true; 58 | return *this; 59 | } 60 | 61 | inline unary_operator_iterator operator++(int) { 62 | unary_operator_iterator i = *this; 63 | operator++(); 64 | return i; 65 | } 66 | 67 | inline unary_operator_iterator &operator--() { 68 | --m_pos; 69 | m_dirty = true; 70 | return *this; 71 | } 72 | 73 | inline unary_operator_iterator operator--(int) { 74 | unary_operator_iterator i = *this; 75 | operator--(); 76 | return *this; 77 | } 78 | 79 | inline bool operator==(const unary_operator_iterator &rhs) const { 80 | return m_pos == rhs.m_pos; 81 | } 82 | 83 | inline bool operator!=(const unary_operator_iterator &rhs) const { 84 | return !operator==(rhs); 85 | } 86 | }; 87 | 88 | template< typename InputIterator, typename Op, bool NA_VALUE > 89 | struct unary_operator_result_type { 90 | typedef typename Op::return_type result_type; 91 | }; 92 | 93 | template< typename InputIterator, typename Op, bool NA_VALUE > 94 | class unary_operator 95 | : public operand< 96 | unary_operator< InputIterator, Op, NA_VALUE >, 97 | unary_operator_iterator< InputIterator, Op, NA_VALUE >, 98 | typename unary_operator_result_type< 99 | InputIterator, 100 | Op, 101 | NA_VALUE 102 | >::result_type 103 | > { 104 | public: 105 | typedef typename unary_operator_result_type< 106 | InputIterator, 107 | Op, 108 | NA_VALUE 109 | >::result_type result_type; 110 | 111 | static const bool NA = NA_VALUE; 112 | 113 | public: 114 | typedef unary_operator_iterator< 115 | InputIterator, 116 | Op, 117 | NA_VALUE 118 | > const_iterator; 119 | 120 | typedef const_iterator iterator; 121 | 122 | private: 123 | InputIterator m_begin; 124 | InputIterator m_end; 125 | dims_t m_dims; 126 | Op m_operator; 127 | 128 | public: 129 | unary_operator(const InputIterator &begin, const InputIterator &end, 130 | dims_t dims, const Op &op) : m_begin(begin), m_end(end), 131 | m_dims(op.result_dims(dims)), m_operator(op) 132 | { 133 | } 134 | 135 | dims_t dims() const {return m_dims;} 136 | 137 | int64_t size() const { 138 | return (m_dims.second != 0) ? m_dims.first * m_dims.second 139 | : m_dims.first; 140 | } 141 | const_iterator begin() const {return const_iterator(m_begin, m_operator);} 142 | const_iterator end() const {return const_iterator(m_end, m_operator);} 143 | }; 144 | 145 | template< bool NA > 146 | struct make_unary_operator { 147 | template< typename T, typename Op > 148 | unary_operator< typename T::const_iterator, Op, NA > operator()( 149 | const T &obj, const Op &op) { 150 | return unary_operator< typename T::const_iterator, Op, NA >(obj.begin(), 151 | obj.end(), hooks::extract_dims(obj), op); 152 | } 153 | }; 154 | 155 | } // namespace RcppHoney 156 | -------------------------------------------------------------------------------- /inst/include/RcppHoneyForward.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 Daniel C. Dillon 2 | // 3 | // This file is part of RcppHoney. 4 | // 5 | // RcppHoney is free software: you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // RcppHoney is distributed in the hope that it will be useful, but 11 | // WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with RcppHoney. If not, see . 17 | 18 | #pragma once 19 | 20 | #include 21 | #include "RcppHoney/traits/ctype.hpp" 22 | #include "RcppHoney/traits/enable_if.hpp" 23 | #include "RcppHoney/traits/if_else.hpp" 24 | #include "RcppHoney/traits/integral_constant.hpp" 25 | #include "RcppHoney/traits/is_primitive.hpp" 26 | #include "RcppHoney/traits/result_of.hpp" 27 | #include "RcppHoney/traits/widest_numeric_type.hpp" 28 | #include 29 | 30 | namespace RcppHoney { 31 | 32 | typedef std::pair< uint64_t, uint64_t > dims_t; 33 | 34 | template< typename T, typename T_ITER, typename T_RESULT > 35 | class operand; 36 | 37 | template< typename LhsIterator, typename RhsIterator, typename Op, 38 | bool NA_VALUE > 39 | class binary_operator; 40 | 41 | namespace hooks { 42 | 43 | static const int FAMILY_USER = 1024; 44 | 45 | template< typename T, typename U = typename T::const_iterator > 46 | struct const_iterator { 47 | typedef typename T::const_iterator type; 48 | }; 49 | 50 | 51 | } // namespace hooks 52 | 53 | } // namespace RcppHoney 54 | -------------------------------------------------------------------------------- /inst/tools/r-stripper/stripper: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2016 Daniel C. Dillon 2 | # 3 | # r-stripper is free software: you can redistribute it and/or modify it 4 | # under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 2 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # r-stripper is distributed in the hope that it will be useful, but 9 | # WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with r-stripper. If not, see . 15 | 16 | if [ -z $R_HOME ]; then 17 | R_HOME=`R RHOME` 18 | fi 19 | 20 | if [ "$R_HOME" = "" ]; then 21 | echo "Could not find R_HOME." 22 | exit 0 23 | fi 24 | 25 | if [ -z $1 ]; then 26 | $R_HOME/bin/Rscript inst/tools/r-stripper/stripper.R 27 | else 28 | $R_HOME/bin/Rscript inst/tools/r-stripper/stripper.R "$1" 29 | fi 30 | -------------------------------------------------------------------------------- /inst/tools/r-stripper/stripper.R: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2016 Daniel C. Dillon 2 | # 3 | # This file is part of r-stripper. 4 | # 5 | # r-stripper is free software: you can redistribute it and/or modify it 6 | # under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # r-stripper is distributed in the hope that it will be useful, but 11 | # WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with r-stripper. If not, see . 17 | 18 | # Return the appropriate option to pass the linker to cause it to strip 19 | # debugging symbols out of a shared library. This only takes actual linkers 20 | # (ld, gold, etc.) and not "wrappers" (gcc, clang, etc.). Returns the option 21 | # that the linker needs or empty string if it is unknown. 22 | .getLinkerOptions <- function(cmd) { 23 | if (cmd != "") { 24 | output <- system(paste0(cmd, " --version 2>&1"), intern=TRUE) 25 | 26 | if (grepl("^GNU ld", output[1])) { 27 | return("-S") 28 | } else if (grepl("^GNU gold", output[1])) { 29 | return("-S") 30 | } else if (grepl("Solaris Link Editors", output[1])) { 31 | return("-zstrip-class=debug") 32 | } 33 | } 34 | 35 | return("") 36 | } 37 | 38 | # Given a linker (ld, gold, etc.) or a linker "wrapper" (gcc, clang, etc.), 39 | # determine the option that can be passed to cause it to strip debugging 40 | # symbols out of a shared library. Returns the option needed by this 41 | # executable to strip the library or empty string if it is unknown. 42 | .getLinkerOrWrapperOptions <- function(cmd) { 43 | if (cmd != "") { 44 | # First see if this is a linker in its own right and what option it 45 | # will need. 46 | linkerOption <- .getLinkerOptions(cmd) 47 | 48 | if (linkerOption != "") 49 | { 50 | return(linkerOption) 51 | } 52 | 53 | # If it's not a linker, assume it's a "wrapper" and try to figure out 54 | # what linker it will actually call. 55 | output <- system(paste0(cmd, " --version"), intern=TRUE) 56 | 57 | if (grepl("gcc|clang|g\\+\\+", output[1])) { 58 | linkerCommand <- system(paste0(cmd, " --print-prog-name=ld"), 59 | intern=TRUE) 60 | 61 | linkerOption <- .getLinkerOptions(linkerCommand) 62 | 63 | if (linkerOption != "") { 64 | return(paste0("-Wl,", linkerOption)) 65 | } 66 | } 67 | } 68 | 69 | return("") 70 | } 71 | 72 | # Given the name of an R configuration value that specifies what command will 73 | # be executed to link a shared library, return the command line options that 74 | # can be passed to it to cause it to strip debugging symbols from the resulting 75 | # shared library. Returns empty string if it is unknown. 76 | .getStripLinkerOption <- function(rConfigParam) { 77 | rLinkerCommand <- system(paste0(file.path(R.home("bin"), "R"), 78 | " CMD config ", rConfigParam), intern=TRUE) 79 | 80 | if (rLinkerCommand != "") { 81 | return(.getLinkerOrWrapperOptions(rLinkerCommand)) 82 | } 83 | 84 | return("") 85 | } 86 | 87 | # If there is a single command line option that can be passed to all the linker 88 | # executables that R will call, return it. Return empty string otherwise. 89 | .getUniversalStripLinkerOption <- function(fail) { 90 | tryCatch({ 91 | if (!fail) { 92 | possibleLinkerOptions <- c() 93 | possibleLinkerOptions <- c(possibleLinkerOptions, 94 | .getStripLinkerOption("SHLIB_LD")) 95 | possibleLinkerOptions <- c(possibleLinkerOptions, 96 | .getStripLinkerOption("SHLIB_CXXLD")) 97 | } else { 98 | possibleLinkerOptions <- .getStripLinkerOption("F77") 99 | } 100 | 101 | # If all of the possible linkers will accept the same command, return it. 102 | if (all.equal(rep(possibleLinkerOptions[1], length(possibleLinkerOptions)), 103 | possibleLinkerOptions)) { 104 | 105 | return(possibleLinkerOptions[1]) 106 | } 107 | }, 108 | warning = function(w) {return("")}, 109 | error = function(e) {return("")}) 110 | 111 | return("") 112 | } 113 | 114 | # Write the appropriate argument to a Makevars file 115 | .writeMakevars <- function(fileName, argument, createIfMissing) { 116 | 117 | if (file.exists(fileName)) { 118 | lines <- readLines(fileName) 119 | file.rename(fileName, paste0(fileName, ".r-stripper.bak")) 120 | } else if (createIfMissing) { 121 | lines <- c() 122 | } else { 123 | return(FALSE) 124 | } 125 | 126 | outfile <- file(fileName, open="w") 127 | 128 | i <- 1 129 | foundPkgLibs <- FALSE 130 | 131 | while (i <= length(lines)) { 132 | line <- lines[i] 133 | 134 | if (grepl(".*PKG_LIBS.*=", line)) { 135 | foundPkgLibs <- TRUE 136 | found <- FALSE 137 | 138 | while (i + 1 <= length(lines) 139 | && substr(line, nchar(line), nchar(line)) == "\\") { 140 | 141 | if (grepl("R_STRIPPER_ARGUMENT", line)) { 142 | found <- TRUE 143 | } 144 | 145 | writeLines(line, outfile) 146 | 147 | i <- i + 1 148 | line <- lines[i] 149 | } 150 | 151 | # Something is not formatted correctly in Makevars 152 | if (i + 1 > length(lines) 153 | && substr(line, nchar(line), nchar(line)) == "\\") { 154 | close(outfile) 155 | file.rename(paste0(fileName, ".r-stripper.bak"), fileName) 156 | return(FALSE) 157 | } 158 | 159 | if (!found && !grepl("R_STRIPPER_ARGUMENT", line)) { 160 | line <- paste0(line, " $(R_STRIPPER_ARGUMENT)") 161 | } 162 | 163 | writeLines(line, outfile) 164 | } else if (grepl("R_STRIPPER_ARGUMENT", line)) { 165 | # do nothing, we'll purge this line and write it back later 166 | } else { 167 | # not a line we're interested in, just write it back 168 | writeLines(line, outfile) 169 | } 170 | 171 | i <- i + 1 172 | } 173 | 174 | if (!foundPkgLibs) { 175 | writeLines("PKG_LIBS = $(R_STRIPPER_ARGUMENT)", outfile) 176 | } 177 | 178 | writeLines(paste0("R_STRIPPER_ARGUMENT = ", argument), outfile) 179 | 180 | close(outfile) 181 | 182 | return(TRUE) 183 | } 184 | 185 | args <- commandArgs(trailingOnly = TRUE) 186 | 187 | fail <- FALSE 188 | 189 | if (length(args) > 0 && args[1] == "fail") { 190 | fail <- TRUE 191 | } 192 | 193 | argument <- .getUniversalStripLinkerOption(fail) 194 | 195 | if (argument != "") { 196 | .writeMakevars("src/Makevars", argument, TRUE) 197 | .writeMakevars("src/Makevars.win", argument, FALSE) 198 | } 199 | -------------------------------------------------------------------------------- /inst/unitTests/cpp/functions.cpp: -------------------------------------------------------------------------------- 1 | // [[Rcpp::depends(RcppHoney)]] 2 | 3 | #include 4 | 5 | // TEST FUNCTION PARAMETER TYPES 6 | 7 | // [[Rcpp::export]] 8 | Rcpp::NumericVector test_unary_function_hooked(std::vector< int > v) { 9 | return Rcpp::wrap(RcppHoney::log(v)); 10 | } 11 | 12 | // [[Rcpp::export]] 13 | Rcpp::NumericVector test_unary_function_operand(std::vector< int > v) { 14 | return Rcpp::wrap(RcppHoney::log(v + v)); 15 | } 16 | 17 | // [[Rcpp::export]] 18 | Rcpp::NumericVector test_binary_function_hooked_scalar(std::vector< int > v1, 19 | double s) { 20 | 21 | return Rcpp::wrap(RcppHoney::pow(v1, s)); 22 | } 23 | 24 | // [[Rcpp::export]] 25 | Rcpp::NumericVector test_binary_function_scalar_hooked(double s, 26 | std::vector< int > v1) { 27 | 28 | return Rcpp::wrap(RcppHoney::pow(s, v1)); 29 | } 30 | 31 | // [[Rcpp::export]] 32 | Rcpp::NumericVector test_binary_function_hooked_hooked(std::vector< int > v1, 33 | std::vector< int > v2) { 34 | 35 | return Rcpp::wrap(RcppHoney::pow(v1, v2)); 36 | } 37 | 38 | // [[Rcpp::export]] 39 | Rcpp::NumericVector test_binary_function_hooked_other_hooked( 40 | std::vector< int > v1, Rcpp::NumericVector v2) { 41 | 42 | return Rcpp::wrap(RcppHoney::pow(v1, v2)); 43 | } 44 | 45 | // [[Rcpp::export]] 46 | Rcpp::NumericVector test_binary_function_other_hooked_hooked( 47 | Rcpp::NumericVector v1, std::vector< int > v2) { 48 | 49 | return Rcpp::wrap(RcppHoney::pow(v1, v2)); 50 | } 51 | 52 | // [[Rcpp::export]] 53 | Rcpp::NumericVector test_binary_function_operand_scalar(std::vector< int > v1, 54 | std::vector< int > v2, double s) { 55 | 56 | return Rcpp::wrap(RcppHoney::pow(v1 + v2, s)); 57 | } 58 | 59 | // [[Rcpp::export]] 60 | Rcpp::NumericVector test_binary_function_scalar_operand(double s, 61 | std::vector< int > v1, std::vector< int > v2) { 62 | 63 | return Rcpp::wrap(RcppHoney::pow(s, v1 + v2)); 64 | } 65 | 66 | // [[Rcpp::export]] 67 | Rcpp::NumericVector test_binary_function_operand_hooked(std::vector< int > v1, 68 | std::vector< int > v2, Rcpp::NumericVector v3) { 69 | 70 | return Rcpp::wrap(RcppHoney::pow(v1 + v2, v3)); 71 | } 72 | 73 | // [[Rcpp::export]] 74 | Rcpp::NumericVector test_binary_function_hooked_operand(Rcpp::NumericVector v1, 75 | std::vector< int > v2, std::vector< int > v3) { 76 | 77 | return Rcpp::wrap(RcppHoney::pow(v1, v2 + v3)); 78 | } 79 | 80 | // [[Rcpp::export]] 81 | Rcpp::NumericVector test_binary_function_operand_operand(std::vector< int > v1, 82 | std::vector< int > v2) { 83 | 84 | return Rcpp::wrap(RcppHoney::pow(v1 + v2, v2 + v2)); 85 | } 86 | 87 | 88 | 89 | 90 | 91 | // TEST INDIVIDUAL FUNCTIONS 92 | 93 | // [[Rcpp::export]] 94 | Rcpp::NumericVector test_log(Rcpp::NumericVector v) { 95 | return Rcpp::wrap(RcppHoney::log(v)); 96 | } 97 | 98 | // [[Rcpp::export]] 99 | Rcpp::NumericVector test_exp(Rcpp::NumericVector v) { 100 | return Rcpp::wrap(RcppHoney::exp(v)); 101 | } 102 | 103 | // [[Rcpp::export]] 104 | Rcpp::NumericVector test_sqrt(Rcpp::NumericVector v) { 105 | return Rcpp::wrap(RcppHoney::sqrt(v)); 106 | } 107 | 108 | // [[Rcpp::export]] 109 | Rcpp::NumericVector test_acos(Rcpp::NumericVector v) { 110 | return Rcpp::wrap(RcppHoney::acos(v)); 111 | } 112 | 113 | // [[Rcpp::export]] 114 | Rcpp::NumericVector test_asin(Rcpp::NumericVector v) { 115 | return Rcpp::wrap(RcppHoney::asin(v)); 116 | } 117 | 118 | // [[Rcpp::export]] 119 | Rcpp::NumericVector test_atan(Rcpp::NumericVector v) { 120 | return Rcpp::wrap(RcppHoney::atan(v)); 121 | } 122 | 123 | // [[Rcpp::export]] 124 | Rcpp::NumericVector test_ceil(Rcpp::NumericVector v) { 125 | return Rcpp::wrap(RcppHoney::ceil(v)); 126 | } 127 | 128 | // [[Rcpp::export]] 129 | Rcpp::NumericVector test_cos(Rcpp::NumericVector v) { 130 | return Rcpp::wrap(RcppHoney::cos(v)); 131 | } 132 | 133 | // [[Rcpp::export]] 134 | Rcpp::NumericVector test_cosh(Rcpp::NumericVector v) { 135 | return Rcpp::wrap(RcppHoney::cosh(v)); 136 | } 137 | 138 | // [[Rcpp::export]] 139 | Rcpp::NumericVector test_floor(Rcpp::NumericVector v) { 140 | return Rcpp::wrap(RcppHoney::floor(v)); 141 | } 142 | 143 | // [[Rcpp::export]] 144 | Rcpp::NumericVector test_log10(Rcpp::NumericVector v) { 145 | return Rcpp::wrap(RcppHoney::log10(v)); 146 | } 147 | 148 | // [[Rcpp::export]] 149 | Rcpp::NumericVector test_sin(Rcpp::NumericVector v) { 150 | return Rcpp::wrap(RcppHoney::sin(v)); 151 | } 152 | 153 | // [[Rcpp::export]] 154 | Rcpp::NumericVector test_sinh(Rcpp::NumericVector v) { 155 | return Rcpp::wrap(RcppHoney::sinh(v)); 156 | } 157 | 158 | // [[Rcpp::export]] 159 | Rcpp::NumericVector test_tan(Rcpp::NumericVector v) { 160 | return Rcpp::wrap(RcppHoney::tan(v)); 161 | } 162 | 163 | // [[Rcpp::export]] 164 | Rcpp::NumericVector test_tanh(Rcpp::NumericVector v) { 165 | return Rcpp::wrap(RcppHoney::tanh(v)); 166 | } 167 | 168 | // [[Rcpp::export]] 169 | Rcpp::NumericVector test_abs(Rcpp::NumericVector v) { 170 | return Rcpp::wrap(RcppHoney::abs(v)); 171 | } 172 | 173 | // [[Rcpp::export]] 174 | Rcpp::NumericVector test_gamma(Rcpp::NumericVector v) { 175 | return Rcpp::wrap(RcppHoney::gamma(v)); 176 | } 177 | 178 | // [[Rcpp::export]] 179 | Rcpp::NumericVector test_lgamma(Rcpp::NumericVector v) { 180 | return Rcpp::wrap(RcppHoney::lgamma(v)); 181 | } 182 | 183 | // [[Rcpp::export]] 184 | Rcpp::NumericVector test_digamma(Rcpp::NumericVector v) { 185 | return Rcpp::wrap(RcppHoney::digamma(v)); 186 | } 187 | 188 | // [[Rcpp::export]] 189 | Rcpp::NumericVector test_trigamma(Rcpp::NumericVector v) { 190 | return Rcpp::wrap(RcppHoney::trigamma(v)); 191 | } 192 | 193 | // [[Rcpp::export]] 194 | Rcpp::NumericVector test_tetragamma(Rcpp::NumericVector v) { 195 | return Rcpp::wrap(RcppHoney::tetragamma(v)); 196 | } 197 | 198 | // [[Rcpp::export]] 199 | Rcpp::NumericVector test_pentagamma(Rcpp::NumericVector v) { 200 | return Rcpp::wrap(RcppHoney::pentagamma(v)); 201 | } 202 | 203 | // [[Rcpp::export]] 204 | Rcpp::NumericVector test_factorial(Rcpp::NumericVector v) { 205 | return Rcpp::wrap(RcppHoney::factorial(v)); 206 | } 207 | 208 | // [[Rcpp::export]] 209 | Rcpp::NumericVector test_lfactorial(Rcpp::NumericVector v) { 210 | return Rcpp::wrap(RcppHoney::lfactorial(v)); 211 | } 212 | 213 | // [[Rcpp::export]] 214 | Rcpp::NumericVector test_trunc(Rcpp::NumericVector v) { 215 | return Rcpp::wrap(RcppHoney::trunc(v)); 216 | } 217 | 218 | // [[Rcpp::export]] 219 | Rcpp::NumericVector test_diff(Rcpp::NumericVector v) { 220 | return Rcpp::wrap(RcppHoney::diff(v)); 221 | } 222 | 223 | // [[Rcpp::export]] 224 | Rcpp::NumericVector test_pow(Rcpp::NumericVector v1, 225 | Rcpp::NumericVector v2) { 226 | 227 | return Rcpp::wrap(RcppHoney::pow(v1, v2)); 228 | } 229 | 230 | // [[Rcpp::export]] 231 | Rcpp::NumericVector test_choose(Rcpp::NumericVector v1, 232 | Rcpp::NumericVector v2) { 233 | 234 | return Rcpp::wrap(RcppHoney::choose(v1, v2)); 235 | } 236 | 237 | // [[Rcpp::export]] 238 | Rcpp::NumericVector test_lchoose(Rcpp::NumericVector v1, 239 | Rcpp::NumericVector v2) { 240 | 241 | return Rcpp::wrap(RcppHoney::lchoose(v1, v2)); 242 | } 243 | 244 | // [[Rcpp::export]] 245 | Rcpp::NumericVector test_beta(Rcpp::NumericVector v1, Rcpp::NumericVector v2) { 246 | return Rcpp::wrap(RcppHoney::beta(v1, v2)); 247 | } 248 | 249 | // [[Rcpp::export]] 250 | Rcpp::NumericVector test_lbeta(Rcpp::NumericVector v1, Rcpp::NumericVector v2) { 251 | return Rcpp::wrap(RcppHoney::lbeta(v1, v2)); 252 | } 253 | 254 | // [[Rcpp::export]] 255 | Rcpp::NumericVector test_psigamma(Rcpp::NumericVector v1, 256 | Rcpp::NumericVector v2) { 257 | 258 | return Rcpp::wrap(RcppHoney::psigamma(v1, v2)); 259 | } 260 | 261 | // [[Rcpp::export]] 262 | Rcpp::NumericVector test_round(Rcpp::NumericVector v1, Rcpp::NumericVector v2) { 263 | return Rcpp::wrap(RcppHoney::round(v1, v2)); 264 | } 265 | 266 | // [[Rcpp::export]] 267 | Rcpp::NumericVector test_signif(Rcpp::NumericVector v1, 268 | Rcpp::NumericVector v2) { 269 | 270 | return Rcpp::wrap(RcppHoney::signif(v1, v2)); 271 | } 272 | 273 | // [[Rcpp::export]] 274 | Rcpp::NumericVector test_cumsum(Rcpp::NumericVector v) { 275 | return Rcpp::wrap(RcppHoney::cumsum(v)); 276 | } 277 | 278 | // [[Rcpp::export]] 279 | Rcpp::NumericVector test_cumsum_matrix(Rcpp::NumericMatrix m) { 280 | return Rcpp::wrap(RcppHoney::cumsum(m)); 281 | } 282 | 283 | // [[Rcpp::export]] 284 | Rcpp::NumericVector test_cumsum_operand(Rcpp::NumericMatrix m) { 285 | return Rcpp::wrap(RcppHoney::cumsum(RcppHoney::log(m))); 286 | } 287 | 288 | // [[Rcpp::export]] 289 | Rcpp::NumericVector test_cumprod(Rcpp::NumericVector v) { 290 | return Rcpp::wrap(RcppHoney::cumprod(v)); 291 | } 292 | 293 | // [[Rcpp::export]] 294 | Rcpp::NumericVector test_cumprod_matrix(Rcpp::NumericMatrix m) { 295 | return Rcpp::wrap(RcppHoney::cumprod(m)); 296 | } 297 | 298 | // [[Rcpp::export]] 299 | Rcpp::NumericVector test_cumprod_operand(Rcpp::NumericMatrix m) { 300 | return Rcpp::wrap(RcppHoney::cumprod(RcppHoney::log(m))); 301 | } 302 | 303 | // [[Rcpp::export]] 304 | Rcpp::NumericVector test_cummin(Rcpp::NumericVector v) { 305 | return Rcpp::wrap(RcppHoney::cummin(v)); 306 | } 307 | 308 | // [[Rcpp::export]] 309 | Rcpp::NumericVector test_cummin_matrix(Rcpp::NumericMatrix m) { 310 | return Rcpp::wrap(RcppHoney::cummin(m)); 311 | } 312 | 313 | // [[Rcpp::export]] 314 | Rcpp::NumericVector test_cummin_operand(Rcpp::NumericMatrix m) { 315 | return Rcpp::wrap(RcppHoney::cummin(RcppHoney::log(m))); 316 | } 317 | 318 | // [[Rcpp::export]] 319 | Rcpp::NumericVector test_cummax(Rcpp::NumericVector v) { 320 | return Rcpp::wrap(RcppHoney::cummax(v)); 321 | } 322 | 323 | // [[Rcpp::export]] 324 | Rcpp::NumericVector test_cummax_matrix(Rcpp::NumericMatrix m) { 325 | return Rcpp::wrap(RcppHoney::cummax(m)); 326 | } 327 | 328 | // [[Rcpp::export]] 329 | Rcpp::NumericVector test_cummax_operand(Rcpp::NumericMatrix m) { 330 | return Rcpp::wrap(RcppHoney::cummax(RcppHoney::log(m))); 331 | } 332 | 333 | // [[Rcpp::export]] 334 | Rcpp::NumericMatrix test_cbind_vector_scalar(std::vector< double > v, 335 | double s) { 336 | 337 | return Rcpp::wrap(RcppHoney::cbind(v, s)); 338 | } 339 | // [[Rcpp::export]] 340 | Rcpp::NumericMatrix test_cbind_scalar_vector(double s, 341 | std::vector< double > v) { 342 | 343 | return Rcpp::wrap(RcppHoney::cbind(s, v)); 344 | } 345 | 346 | // [[Rcpp::export]] 347 | Rcpp::NumericMatrix test_cbind_vector_vector(std::vector< double > v1, 348 | Rcpp::NumericVector v2) { 349 | 350 | return Rcpp::wrap(RcppHoney::cbind(v1, v2)); 351 | } 352 | 353 | // [[Rcpp::export]] 354 | Rcpp::NumericMatrix test_cbind_matrix_vector(Rcpp::NumericMatrix m, 355 | std::vector< double > v) { 356 | 357 | return Rcpp::wrap(RcppHoney::cbind(m, v)); 358 | } 359 | 360 | // [[Rcpp::export]] 361 | Rcpp::NumericMatrix test_cbind_vector_matrix(std::vector< double > v, 362 | Rcpp::NumericMatrix m) { 363 | 364 | return Rcpp::wrap(RcppHoney::cbind(v, m)); 365 | } 366 | 367 | // [[Rcpp::export]] 368 | Rcpp::NumericMatrix test_cbind_matrix_matrix(Rcpp::NumericMatrix m1, 369 | Rcpp::NumericMatrix m2) { 370 | 371 | return Rcpp::wrap(RcppHoney::cbind(m1, m2)); 372 | } -------------------------------------------------------------------------------- /inst/unitTests/cpp/operators.cpp: -------------------------------------------------------------------------------- 1 | // [[Rcpp::depends(RcppHoney)]] 2 | 3 | #include 4 | 5 | // [[Rcpp::export]] 6 | Rcpp::NumericVector test_hooked_plus_scalar(std::vector< int > v1, double s) { 7 | return Rcpp::wrap(v1 + s); 8 | } 9 | 10 | // [[Rcpp::export]] 11 | Rcpp::NumericVector test_scalar_plus_hooked(double s, std::vector< int > v1) { 12 | return Rcpp::wrap(s + v1); 13 | } 14 | 15 | // [[Rcpp::export]] 16 | Rcpp::NumericVector test_hooked_plus_hooked(std::vector< int > v1, 17 | std::vector< int > v2) { 18 | 19 | return Rcpp::wrap(v1 + v2); 20 | } 21 | 22 | // [[Rcpp::export]] 23 | Rcpp::NumericVector test_hooked_plus_other_hooked(std::vector< int > v1, 24 | Rcpp::NumericVector v2) { 25 | 26 | return Rcpp::wrap(v1 + v2); 27 | } 28 | 29 | // [[Rcpp::export]] 30 | Rcpp::NumericVector test_other_hooked_plus_hooked(Rcpp::NumericVector v1, 31 | std::vector< int > v2) { 32 | 33 | return Rcpp::wrap(v1 + v2); 34 | } 35 | 36 | // [[Rcpp::export]] 37 | Rcpp::NumericVector test_operand_plus_scalar(std::vector< int > v1, 38 | std::vector< int > v2, double s) { 39 | 40 | return Rcpp::wrap((v1 + v2) + s); 41 | } 42 | 43 | // [[Rcpp::export]] 44 | Rcpp::NumericVector test_scalar_plus_operand(double s, std::vector< int > v1, 45 | std::vector< int > v2) { 46 | 47 | return Rcpp::wrap(s + (v1 + v2)); 48 | } 49 | 50 | // [[Rcpp::export]] 51 | Rcpp::NumericVector test_operand_plus_hooked(std::vector< int > v1, 52 | std::vector< int > v2, Rcpp::NumericVector v3) { 53 | 54 | return Rcpp::wrap((v1 + v2) + v3); 55 | } 56 | 57 | // [[Rcpp::export]] 58 | Rcpp::NumericVector test_hooked_plus_operand(Rcpp::NumericVector v1, 59 | std::vector< int > v2, std::vector< int > v3) { 60 | 61 | return Rcpp::wrap(v1 + (v2 + v3)); 62 | } 63 | 64 | // [[Rcpp::export]] 65 | Rcpp::NumericVector test_operand_plus_operand(std::vector< int > v1, 66 | std::vector< int > v2) { 67 | 68 | return Rcpp::wrap((v1 + v2) + (v1 + v2)); 69 | } 70 | 71 | // [[Rcpp::export]] 72 | Rcpp::NumericVector test_unary_operator_hooked(std::vector< int > v) { 73 | return Rcpp::wrap(-v); 74 | } 75 | 76 | // [[Rcpp::export]] 77 | Rcpp::NumericVector test_unary_operator_operand(std::vector< int > v) { 78 | return Rcpp::wrap(-(v + v)); 79 | } 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | // [[Rcpp::export]] 92 | Rcpp::IntegerMatrix test_matrix_plus_scalar(Rcpp::IntegerMatrix m1, double s) { 93 | return Rcpp::wrap(m1 + s); 94 | } 95 | 96 | // [[Rcpp::export]] 97 | Rcpp::IntegerMatrix test_scalar_plus_matrix(double s, Rcpp::IntegerMatrix m1) { 98 | return Rcpp::wrap(s + m1); 99 | } 100 | 101 | // [[Rcpp::export]] 102 | Rcpp::NumericMatrix test_matrix_plus_matrix(Rcpp::NumericMatrix m1, 103 | Rcpp::NumericMatrix m2) 104 | { 105 | return Rcpp::wrap(m1 + m2); 106 | } 107 | 108 | // [[Rcpp::export]] 109 | Rcpp::NumericMatrix test_matrix_unary_operator(Rcpp::NumericMatrix m) { 110 | return Rcpp::wrap(-m); 111 | } 112 | 113 | // [[Rcpp::export]] 114 | Rcpp::NumericMatrix test_matrix_unary_operator_operand(Rcpp::NumericMatrix m) { 115 | return Rcpp::wrap(-(m + m)); 116 | } -------------------------------------------------------------------------------- /inst/unitTests/runTests.R: -------------------------------------------------------------------------------- 1 | require(Rcpp) 2 | pkg <- "RcppHoney" 3 | 4 | if (require("RUnit", quietly = TRUE)) { 5 | 6 | library(package=pkg, character.only = TRUE) 7 | if (!(exists("path") && file.exists(path))) 8 | path <- system.file("unitTests", package = pkg) 9 | 10 | ## --- Testing --- 11 | 12 | ## Define tests 13 | testSuite <- defineTestSuite(name=paste(pkg, "unit testing"), dirs = path) 14 | 15 | if (interactive()) { 16 | cat("Now have RUnit Test Suite 'testSuite' for package '", pkg, "' :\n", sep='') 17 | str(testSuite) 18 | cat('', "Consider doing", 19 | "\t tests <- runTestSuite(testSuite)", "\nand later", 20 | "\t printTextProtocol(tests)", '', sep="\n") 21 | } else { ## run from shell / Rscript / R CMD Batch / ... 22 | ## Run 23 | tests <- runTestSuite(testSuite) 24 | 25 | if (file.access(path, 02) != 0) { 26 | ## cannot write to path -> use writable one 27 | tdir <- tempfile(paste(pkg, "unitTests", sep="_")) 28 | dir.create(tdir) 29 | pathReport <- file.path(tdir, "report") 30 | cat("RUnit reports are written into ", tdir, "/report.(txt|html)", sep = "") 31 | } else { 32 | pathReport <- file.path(path, "report") 33 | } 34 | 35 | ## Print results 36 | ## printTextProtocol(tests) 37 | printTextProtocol(tests, fileName=paste(pathReport, ".txt", sep="")) 38 | ## Print HTML version to a file 39 | ## printHTMLProtocol has problems on Mac OS X 40 | if (Sys.info()["sysname"] != "Darwin") 41 | printHTMLProtocol(tests, fileName=paste(pathReport, ".html", sep="")) 42 | 43 | ## stop() if there are any failures i.e. FALSE to unit test. 44 | ## This will cause R CMD check to return error and stop 45 | if (getErrors(tests)$nFail > 0) { 46 | stop("one of the unit tests failed") 47 | } 48 | } 49 | } else { 50 | cat("R package 'RUnit' cannot be loaded -- no unit tests run\n", "for package", pkg,"\n") 51 | } 52 | -------------------------------------------------------------------------------- /inst/unitTests/runit.functions.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/r -t 2 | # 3 | # Copyright (C) 2016 Daniel C. Dillon 4 | # 5 | # This file is part of RcppHoney. 6 | # 7 | # RcppHoney is free software: you can redistribute it and/or modify it 8 | # under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # RcppHoney is distributed in the hope that it will be useful, but 13 | # WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with RcppHoney. If not, see . 19 | 20 | .setUp <- RcppHoney:::unit_test_setup("functions.cpp", "RcppHoney") 21 | 22 | pow <- function(x, y) {x ^ y} 23 | 24 | test.unary.function <- function() { 25 | v <- 1:100 26 | checkEquals(log(v), test_unary_function_hooked(v)) 27 | checkEquals(log(v + v), test_unary_function_operand(v)) 28 | } 29 | 30 | test.binary.function.hooked.and.scalar <- function() { 31 | v <- 1:5 32 | s <- 2 33 | checkEquals(pow(v, s), test_binary_function_hooked_scalar(v, s)) 34 | checkEquals(pow(s, v), test_binary_function_scalar_hooked(s, v)) 35 | } 36 | 37 | test.binary.function.hooked.and.hooked <- function() { 38 | v <- 1:5 39 | checkEquals(pow(v, v), test_binary_function_hooked_hooked(v, v)) 40 | checkEquals(pow(v, v), test_binary_function_hooked_other_hooked(v, v)) 41 | checkEquals(pow(v, v), test_binary_function_other_hooked_hooked(v, v)) 42 | } 43 | 44 | test.binary.function.operand.and.scalar <- function() { 45 | v <- 1:5 46 | s <- 2 47 | checkEquals(pow((v + v), s), test_binary_function_operand_scalar(v, v, s)) 48 | checkEquals(pow(s, (v + v)), test_binary_function_scalar_operand(s, v, v)) 49 | } 50 | 51 | test.binary.function.operand.and.hooked <- function() { 52 | v <- 1:5 53 | checkEquals(pow((v + v), v), test_binary_function_operand_hooked(v, v, v)) 54 | checkEquals(pow(v, (v + v)), test_binary_function_hooked_operand(v, v, v)) 55 | } 56 | 57 | test.binary.function.operand.and.operand <- function() { 58 | v <- 1:4 59 | checkEquals(pow(v + v, v + v), test_binary_function_operand_operand(v, v)) 60 | } 61 | 62 | test.na.unary.function <- function() { 63 | v <- 1:100 64 | v <- c(v, NA) 65 | checkEquals(log(v), test_unary_function_hooked(v)) 66 | checkEquals(log(v + v), test_unary_function_operand(v)) 67 | } 68 | 69 | test.na.binary.function.hooked.and.scalar <- function() { 70 | v <- 1:5 71 | v <- c(v, NA) 72 | s <- 2 73 | checkEquals(pow(v, s), test_binary_function_hooked_scalar(v, s)) 74 | checkEquals(pow(s, v), test_binary_function_scalar_hooked(s, v)) 75 | } 76 | 77 | test.na.binary.function.hooked.and.hooked <- function() { 78 | v <- 1:5 79 | v <- c(v, NA) 80 | checkEquals(pow(v, v), test_binary_function_hooked_hooked(v, v)) 81 | checkEquals(pow(v, v), test_binary_function_hooked_other_hooked(v, v)) 82 | checkEquals(pow(v, v), test_binary_function_other_hooked_hooked(v, v)) 83 | } 84 | 85 | test.na.binary.function.operand.and.scalar <- function() { 86 | v <- 1:5 87 | v <- c(v, NA) 88 | s <- 2 89 | checkEquals(pow((v + v), s), test_binary_function_operand_scalar(v, v, s)) 90 | checkEquals(pow(s, (v + v)), test_binary_function_scalar_operand(s, v, v)) 91 | } 92 | 93 | test.na.binary.function.operand.and.hooked <- function() { 94 | v <- 1:5 95 | v <- c(v, NA) 96 | checkEquals(pow((v + v), v), test_binary_function_operand_hooked(v, v, v)) 97 | checkEquals(pow(v, (v + v)), test_binary_function_hooked_operand(v, v, v)) 98 | } 99 | 100 | test.na.binary.function.operand.and.operand <- function() { 101 | v <- 1:4 102 | v <- c(v, NA) 103 | checkEquals(pow(v + v, v + v), test_binary_function_operand_operand(v, v)) 104 | } 105 | 106 | 107 | 108 | 109 | 110 | test.unary.functions <- function() { 111 | v <- c(.1, .2, .3, .4, .5, .6, .7, .8, .9, 1) 112 | m <- matrix(v, 5, 2) 113 | 114 | checkEquals(log(v), test_log(v)) 115 | checkEquals(exp(v), test_exp(v)) 116 | checkEquals(sqrt(v), test_sqrt(v)) 117 | checkEquals(acos(v), test_acos(v)) 118 | checkEquals(asin(v), test_asin(v)) 119 | checkEquals(atan(v), test_atan(v)) 120 | checkEquals(ceiling(v), test_ceil(v)) 121 | checkEquals(cos(v), test_cos(v)) 122 | checkEquals(cosh(v), test_cosh(v)) 123 | checkEquals(floor(v), test_floor(v)) 124 | checkEquals(log10(v), test_log10(v)) 125 | checkEquals(sin(v), test_sin(v)) 126 | checkEquals(sinh(v), test_sinh(v)) 127 | checkEquals(tan(v), test_tan(v)) 128 | checkEquals(tanh(v), test_tanh(v)) 129 | checkEquals(abs(v), test_abs(v)) 130 | checkEquals(gamma(v), test_gamma(v)) 131 | checkEquals(lgamma(v), test_lgamma(v)) 132 | checkEquals(digamma(v), test_digamma(v)) 133 | checkEquals(trigamma(v), test_trigamma(v)) 134 | checkEquals(psigamma(v, 2), test_tetragamma(v)) 135 | checkEquals(psigamma(v, 3), test_pentagamma(v)) 136 | checkEquals(factorial(v), test_factorial(v)) 137 | checkEquals(lfactorial(v), test_lfactorial(v)) 138 | checkEquals(trunc(v), test_trunc(v)) 139 | checkEquals(diff(v), test_diff(v)) 140 | checkEquals(cumsum(v), test_cumsum(v)) 141 | checkEquals(cumsum(m), test_cumsum_matrix(m)) 142 | checkEquals(cumsum(log(m)), test_cumsum_operand(m)) 143 | checkEquals(cumprod(v), test_cumprod(v)) 144 | checkEquals(cumprod(m), test_cumprod_matrix(m)) 145 | checkEquals(cumprod(log(m)), test_cumprod_operand(m)) 146 | checkEquals(cummin(v), test_cummin(v)) 147 | checkEquals(cummin(m), test_cummin_matrix(m)) 148 | checkEquals(cummin(log(m)), test_cummin_operand(m)) 149 | checkEquals(cummax(v), test_cummax(v)) 150 | checkEquals(cummax(m), test_cummax_matrix(m)) 151 | checkEquals(cummax(log(m)), test_cummax_operand(m)) 152 | } 153 | 154 | test.binary.functions <- function() { 155 | v1 <- c(.1, .2, .3, .4, .5, .6, .7, .8, .9, 1) 156 | v2 <- 1:10 157 | checkEquals(pow(v1, v2), test_pow(v1, v2)) 158 | checkEquals(choose(v1, v2), test_choose(v1, v2)) 159 | checkEquals(lchoose(v1, v2), test_lchoose(v1, v2)) 160 | checkEquals(beta(v1, v2), test_beta(v1, v2)) 161 | checkEquals(lbeta(v1, v2), test_lbeta(v1, v2)) 162 | checkEquals(psigamma(v1, v2), test_psigamma(v1, v2)) 163 | checkEquals(round(v1, v2), test_round(v1, v2)) 164 | checkEquals(signif(v1, v2), test_signif(v1, v2)) 165 | } 166 | 167 | test.na.unary.functions <- function() { 168 | v <- c(.1, .2, .3, .4, NA, .5, .6, .7, .8, .9, 1, NA) 169 | checkEquals(log(v), test_log(v)) 170 | checkEquals(exp(v), test_exp(v)) 171 | checkEquals(sqrt(v), test_sqrt(v)) 172 | checkEquals(acos(v), test_acos(v)) 173 | checkEquals(asin(v), test_asin(v)) 174 | checkEquals(atan(v), test_atan(v)) 175 | checkEquals(ceiling(v), test_ceil(v)) 176 | checkEquals(cos(v), test_cos(v)) 177 | checkEquals(cosh(v), test_cosh(v)) 178 | checkEquals(floor(v), test_floor(v)) 179 | checkEquals(log10(v), test_log10(v)) 180 | checkEquals(sin(v), test_sin(v)) 181 | checkEquals(sinh(v), test_sinh(v)) 182 | checkEquals(tan(v), test_tan(v)) 183 | checkEquals(tanh(v), test_tanh(v)) 184 | checkEquals(abs(v), test_abs(v)) 185 | checkEquals(gamma(v), test_gamma(v)) 186 | checkEquals(lgamma(v), test_lgamma(v)) 187 | checkEquals(digamma(v), test_digamma(v)) 188 | checkEquals(trigamma(v), test_trigamma(v)) 189 | checkEquals(psigamma(v, 2), test_tetragamma(v)) 190 | checkEquals(psigamma(v, 3), test_pentagamma(v)) 191 | checkEquals(factorial(v), test_factorial(v)) 192 | checkEquals(lfactorial(v), test_lfactorial(v)) 193 | checkEquals(trunc(v), test_trunc(v)) 194 | checkEquals(diff(v), test_diff(v)) 195 | } 196 | 197 | test.na.binary.functions <- function() { 198 | v1 <- c(.1, .2, .3, .4, .5, NA, .6, .7, .8, .9, 1, NA) 199 | v2 <- 1:12 200 | checkEquals(pow(v1, v2), test_pow(v1, v2)) 201 | checkEquals(choose(v1, v2), test_choose(v1, v2)) 202 | checkEquals(lchoose(v1, v2), test_lchoose(v1, v2)) 203 | checkEquals(beta(v1, v2), test_beta(v1, v2)) 204 | checkEquals(lbeta(v1, v2), test_lbeta(v1, v2)) 205 | checkEquals(psigamma(v1, v2), test_psigamma(v1, v2)) 206 | checkEquals(round(v1, v2), test_round(v1, v2)) 207 | checkEquals(signif(v1, v2), test_signif(v1, v2)) 208 | } 209 | 210 | test.cbind <- function() { 211 | v1 <- 1:10 212 | v2 <- 11:20 213 | 214 | v3 <- 100:101 215 | 216 | m1 <- matrix(1:10, 2, 5) 217 | m2 <- matrix(11:20, 2, 5) 218 | 219 | checkEquals(unname(cbind(1, v2)), test_cbind_scalar_vector(1, v2)) 220 | checkEquals(unname(cbind(v1, 1)), test_cbind_vector_scalar(v1, 1)) 221 | checkEquals(unname(cbind(v1, v2)), test_cbind_vector_vector(v1, v2)) 222 | checkEquals(unname(cbind(m1, v3)), test_cbind_matrix_vector(m1, v3)) 223 | checkEquals(unname(cbind(v3, m1)), test_cbind_vector_matrix(v3, m1)) 224 | checkEquals(unname(cbind(m1, m2)), test_cbind_matrix_matrix(m1, m2)) 225 | } 226 | -------------------------------------------------------------------------------- /inst/unitTests/runit.operators.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/r -t 2 | # 3 | # Copyright (C) 2016 Daniel C. Dillon 4 | # 5 | # This file is part of RcppHoney. 6 | # 7 | # RcppHoney is free software: you can redistribute it and/or modify it 8 | # under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # RcppHoney is distributed in the hope that it will be useful, but 13 | # WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with RcppHoney. If not, see . 19 | 20 | .setUp <- RcppHoney:::unit_test_setup("operators.cpp", "RcppHoney") 21 | 22 | test.hooked.and.scalar <- function() { 23 | v <- 1:100 24 | m <- matrix(1:100, 10, 10) 25 | s <- 15 26 | checkEquals(v + s, test_hooked_plus_scalar(v, s)) 27 | checkEquals(s + v, test_scalar_plus_hooked(s, v)) 28 | checkEquals(m + s, test_matrix_plus_scalar(m, s)) 29 | checkEquals(s + m, test_scalar_plus_matrix(s, m)) 30 | } 31 | 32 | test.hooked.and.hooked <- function() { 33 | v <- 1:100 34 | checkEquals(v + v, test_hooked_plus_hooked(v, v)) 35 | checkEquals(v + v, test_hooked_plus_other_hooked(v, v)) 36 | checkEquals(v + v, test_other_hooked_plus_hooked(v, v)) 37 | } 38 | 39 | test.operand.and.scalar <- function() { 40 | v <- 1:100 41 | s <- 15 42 | checkEquals((v + v) + s, test_operand_plus_scalar(v, v, s)) 43 | checkEquals(s + (v + v), test_scalar_plus_operand(s, v, v)) 44 | } 45 | 46 | test.operand.and.hooked <- function() { 47 | v <- 1:100 48 | checkEquals((v + v) + v, test_operand_plus_hooked(v, v, v)) 49 | checkEquals(v + (v + v), test_hooked_plus_operand(v, v, v)) 50 | } 51 | 52 | test.operand.and.operand <- function() { 53 | v <- 1:100 54 | checkEquals((v + v) + (v + v), test_operand_plus_operand(v, v)) 55 | } 56 | 57 | test.unary.operator <- function() { 58 | v <- 1:100 59 | checkEquals(-v, test_unary_operator_hooked(v)) 60 | checkEquals(-(v + v), test_unary_operator_operand(v)) 61 | } 62 | 63 | test.na.hooked.and.scalar <- function() { 64 | v <- 1:100 65 | v <- c(v, NA) 66 | s <- 15 67 | checkEquals(v + s, test_hooked_plus_scalar(v, s)) 68 | checkEquals(s + v, test_scalar_plus_hooked(s, v)) 69 | } 70 | 71 | test.na.hooked.and.hooked <- function() { 72 | v <- 1:100 73 | v <- c(v, NA) 74 | checkEquals(v + v, test_hooked_plus_hooked(v, v)) 75 | checkEquals(v + v, test_hooked_plus_other_hooked(v, v)) 76 | checkEquals(v + v, test_other_hooked_plus_hooked(v, v)) 77 | } 78 | 79 | test.na.operand.and.scalar <- function() { 80 | v <- 1:100 81 | v <- c(v, NA) 82 | s <- 15 83 | checkEquals((v + v) + s, test_operand_plus_scalar(v, v, s)) 84 | checkEquals(s + (v + v), test_scalar_plus_operand(s, v, v)) 85 | } 86 | 87 | test.na.operand.and.hooked <- function() { 88 | v <- 1:100 89 | v <- c(v, NA) 90 | checkEquals((v + v) + v, test_operand_plus_hooked(v, v, v)) 91 | checkEquals(v + (v + v), test_hooked_plus_operand(v, v, v)) 92 | } 93 | 94 | test.na.operand.and.operand <- function() { 95 | v <- 1:100 96 | v <- c(v, NA) 97 | checkEquals((v + v) + (v + v), test_operand_plus_operand(v, v)) 98 | } 99 | 100 | test.na.unary.operator <- function() { 101 | v <- 1:100 102 | v <- c(v, NA) 103 | checkEquals(-v, test_unary_operator_hooked(v)) 104 | checkEquals(-(v + v), test_unary_operator_operand(v)) 105 | } 106 | 107 | test.matrix.plus.matrix <- function() { 108 | m <- matrix(c(1, 2, 3, 4), 2, 2) 109 | checkIdentical(m + m, test_matrix_plus_matrix(m, m)) 110 | } 111 | 112 | test.matrix.unary.operator <- function() { 113 | m <- matrix(c(1, 2, 3, 4), 2, 2) 114 | checkIdentical(-m, test_matrix_unary_operator(m)) 115 | checkIdentical(-(m + m), test_matrix_unary_operator_operand(m)) 116 | } -------------------------------------------------------------------------------- /man/example_manually_hooked.Rd: -------------------------------------------------------------------------------- 1 | \name{example_manually_hooked} 2 | \alias{example_manually_hooked} 3 | \title{ 4 | example_manually_hooked 5 | } 6 | \description{ 7 | Simple demonstration of RcppHoney functionality. 8 | } 9 | \usage{ 10 | example_manually_hooked() 11 | } 12 | \value{ 13 | A numeric vector. 14 | } 15 | \author{ 16 | Daniel C. Dillon 17 | } 18 | \examples{ 19 | library(RcppHoney) 20 | v <- 1:5 21 | all.equal(example_manually_hooked(), 42 + (v + v + 2.0) + v + v + log(v) - v - 22 | v + sqrt(v) + -v + (v + 1.0) + 42) 23 | } 24 | -------------------------------------------------------------------------------- /src/Makevars: -------------------------------------------------------------------------------- 1 | PKG_CPPFLAGS = -I../inst/include/ 2 | -------------------------------------------------------------------------------- /src/RcppExports.cpp: -------------------------------------------------------------------------------- 1 | // This file was generated by Rcpp::compileAttributes 2 | // Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 | 4 | #include 5 | 6 | using namespace Rcpp; 7 | 8 | // example_manually_hooked 9 | Rcpp::NumericVector example_manually_hooked(); 10 | RcppExport SEXP RcppHoney_example_manually_hooked() { 11 | BEGIN_RCPP 12 | Rcpp::RObject __result; 13 | Rcpp::RNGScope __rngScope; 14 | __result = Rcpp::wrap(example_manually_hooked()); 15 | return __result; 16 | END_RCPP 17 | } 18 | -------------------------------------------------------------------------------- /src/annoyance.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void R_init_RcppHoney(DllInfo* info) 6 | { 7 | R_registerRoutines(info, NULL, NULL, NULL, NULL); 8 | R_useDynamicSymbols(info, TRUE); 9 | } 10 | -------------------------------------------------------------------------------- /src/examples.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // We have to declare our hooks before we include RcppHoney.hpp 5 | 6 | namespace RcppHoney { 7 | namespace hooks { 8 | 9 | // define any user hooks here as follows 10 | template< typename T, typename A > 11 | traits::true_type is_hooked(const std::list< T, A > &val); 12 | 13 | // set NA to true 14 | template< typename T, typename A > 15 | traits::true_type has_na(const std::list< T, A > &val); 16 | 17 | // assert that we need to create basic operators 18 | template< typename T, typename A > 19 | RcppHoney::traits::true_type needs_basic_operators(const std::list< T, A > &val); 20 | 21 | // assert that we need to create type + scalar operators 22 | template< typename T, typename A > 23 | RcppHoney::traits::true_type needs_scalar_operators(const std::list< T, A > &val); 24 | 25 | // give this a family identifier (has to be unique and has to be > FAMILY_USER) 26 | template< typename T, typename A > 27 | RcppHoney::traits::int_constant< FAMILY_USER + 1 > family(const std::list< T, A > &val); 28 | 29 | } // namespace hooks 30 | } // namespace RcppHoney 31 | 32 | #include 33 | 34 | // Let's also add a couple custom honey functions 35 | namespace RcppHoney { 36 | 37 | // first define functors for them in the RcppHoney::functors namespace 38 | namespace functors { 39 | 40 | template< typename Iterator, bool NA > 41 | struct my_unary_functor : public unary_result_dims { 42 | typedef typename std::iterator_traits< Iterator >::value_type rhs_value_type; 43 | // since we're just adding a double to the input value the return type should be 44 | // the widest numeric type of rhs and double 45 | typedef typename traits::widest_numeric_type< rhs_value_type, double >::type return_type; 46 | return_type operator()(Iterator &rhs) const { 47 | if (NA) { 48 | if (na< typename traits::ctype< typename std::iterator_traits< Iterator >::value_type >::type >::is_na(*rhs)) { 49 | return na< return_type >::VALUE(); 50 | } else { 51 | return *rhs + 1.0; 52 | } 53 | } else { 54 | return *rhs + 1.0; 55 | } 56 | } 57 | }; 58 | 59 | template< typename LhsIterator, typename RhsIterator, bool NA = true > 60 | struct my_binary_functor : public binary_result_dims { 61 | typedef typename std::iterator_traits< LhsIterator >::value_type lhs_value_type; 62 | typedef typename std::iterator_traits< RhsIterator >::value_type rhs_value_type; 63 | 64 | // since we're just adding a double to the sum of the two inputs, the return type 65 | // should be the widest numeric type of lhs, rhs, and double 66 | typedef typename traits::widest_numeric_type< 67 | double, 68 | typename traits::widest_numeric_type< lhs_value_type, rhs_value_type >::type 69 | >::type return_type; 70 | 71 | inline return_type operator()(LhsIterator &lhs, RhsIterator &rhs) const { 72 | if (NA) { 73 | if (!na< typename traits::ctype< lhs_value_type >::type >::is_na(*lhs) 74 | && !na< typename traits::ctype< rhs_value_type >::type >::is_na(*rhs)) { 75 | return *lhs + *rhs + 2.0; 76 | } 77 | 78 | return na< return_type >::VALUE(); 79 | } else { 80 | return ::Rf_fprec(*lhs, *rhs); 81 | } 82 | } 83 | }; 84 | 85 | } // namespace functors 86 | 87 | // now we define the functions in th RcppHoney namespace 88 | RCPP_HONEY_GENERATE_UNARY_FUNCTION(my_unary_function, my_unary_functor) 89 | RCPP_HONEY_GENERATE_BINARY_FUNCTION(my_binary_function, my_binary_functor) 90 | 91 | } // namespace RcppHoney 92 | 93 | // [[Rcpp::export]] 94 | Rcpp::NumericVector example_manually_hooked() { 95 | 96 | // we manually hooked std::list in to RcppHoney so we'll create one 97 | std::list< int > l; 98 | l.push_back(1); 99 | l.push_back(2); 100 | l.push_back(3); 101 | l.push_back(4); 102 | l.push_back(5); 103 | 104 | // std::vector is already hooked in to RcppHoney in default_hooks.hpp so we'll 105 | // create one of those too 106 | std::vector< int > v; 107 | v.push_back(1); 108 | v.push_back(2); 109 | v.push_back(3); 110 | v.push_back(4); 111 | v.push_back(5); 112 | 113 | // and for good measure, let's create an Rcpp::NumericVector which is also hooked by default 114 | Rcpp::NumericVector v2(v.begin(), v.end()); 115 | 116 | // now do some weird operations incorporating both std::vector and std::list and some 117 | // RcppHoney functions, and our custom functions and return it. 118 | RcppHoney::NumericVector retval 119 | = 42 + RcppHoney::my_binary_function(v, l) + l + v + RcppHoney::log(v) - v - l 120 | + RcppHoney::sqrt(v) + -v2 + RcppHoney::my_unary_function(v) + 42; 121 | return retval; 122 | } 123 | -------------------------------------------------------------------------------- /tests/doRUnit.R: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2010 - 2013 Dirk Eddelbuettel, Romain Francois and Douglas Bates 2 | # Copyright (C) 2014 Dirk Eddelbuettel 3 | # Earlier copyrights Gregor Gorjanc, Martin Maechler and Murray Stokely as detailed below 4 | # 5 | # This file is part of RcppHoney. 6 | # 7 | # RcppHoney is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License as 9 | # published by the Free Software Foundation, either version 2 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # RcppHoney is distributed in the hope that it will be useful, but 13 | # WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | # General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with RcppHoney. If not, see . 19 | 20 | ## doRUnit.R --- Run RUnit tests 21 | ## 22 | ## with credits to package fUtilities in RMetrics 23 | ## which credits Gregor Gojanc's example in CRAN package 'gdata' 24 | ## as per the R Wiki http://wiki.r-project.org/rwiki/doku.php?id=developers:runit 25 | ## and changed further by Martin Maechler 26 | ## and more changes by Murray Stokely in HistogramTools 27 | ## and then used adapted in RProtoBuf 28 | ## and now used in Rcpp and here 29 | ## 30 | ## Dirk Eddelbuettel, Feb - June 2014 31 | 32 | stopifnot(require(RUnit, quietly=TRUE)) 33 | stopifnot(require(RcppHoney, quietly=TRUE)) 34 | 35 | ## Define tests 36 | testSuite <- defineTestSuite(name="RcppHoney Unit Tests", 37 | dirs=system.file("unitTests", package = "RcppHoney"), 38 | testFuncRegexp = "^[Tt]est.+") 39 | 40 | ## without this, we get (or used to get) unit test failures 41 | Sys.setenv("R_TESTS"="") 42 | 43 | ## Run tests 44 | tests <- runTestSuite(testSuite) 45 | 46 | ## Print results 47 | printTextProtocol(tests) 48 | 49 | ## Return success or failure to R CMD CHECK 50 | if (getErrors(tests)$nFail > 0) { 51 | stop("TEST FAILED!") 52 | } 53 | if (getErrors(tests)$nErr > 0) { 54 | stop("TEST HAD ERRORS!") 55 | } 56 | if (getErrors(tests)$nTestFunc < 1) { 57 | stop("NO TEST FUNCTIONS RUN!") 58 | } 59 | -------------------------------------------------------------------------------- /vignettes/functions.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Adding a Custom Function to RcppHoney" 3 | author: Daniel C. Dillon 4 | date: "`r Sys.Date()`" 5 | output: 6 | html_vignette: 7 | toc: true 8 | toc_depth: 4 9 | vignette: > 10 | %\VignetteIndexEntry{RcppHoney - Custom Functions} 11 | %\VignetteEngine{knitr::rmarkdown} 12 | %\VignetteEncoding{UTF-8} 13 | --- 14 | 15 | ```{r setup, include=FALSE} 16 | knitr::opts_chunk$set(echo = TRUE) 17 | ``` 18 | 19 | ## Introduction 20 | 21 | `RcppHoney` provides default functions that are executed appropriately with 22 | [expression templates](https://en.wikipedia.org/wiki/Expression_templates), 23 | however a user may want to use a function of his/her own in an `RcppHoney` 24 | expression (and also reap the benefits of expression templates). Fortunately 25 | there is a fairly easy way to accomplish this. 26 | 27 | ## The Example (for the impatient) 28 | 29 | What follows essentially uses the same pattern as a native `RcppHoney` function 30 | and must simply be defined by the user before using it in code. For this 31 | example, let us suppose we have created a unary function `foo` that returns an 32 | `int` and takes a `double` as its lone parameter and a binary function `bar` 33 | that is overloaded such that its return type is the wider of the two parameter 34 | types and the parameter types are some permutation of `int`, and `double`. 35 | 36 | ```{Rcpp} 37 | // Let Rcpp know we need RcppHoney 38 | // [[Rcpp::depends(RcppHoney)]] 39 | 40 | #include 41 | 42 | int foo(double d) { 43 | if (d >= 0) { 44 | return int(d + .5); 45 | } else { 46 | return int(d - .5); 47 | } 48 | } 49 | 50 | int bar(int x, int y) {return x + y;} 51 | double bar(int x, double y) {return x + y;} 52 | double bar(double x, int y) {return x + y;} 53 | double bar(double x, double y) {return x + y;} 54 | 55 | namespace RcppHoney { 56 | namespace functors { 57 | 58 | template< typename Iterator, bool NA > 59 | struct foo : public unary_result_dims { 60 | typedef int return_type; 61 | return_type operator()(Iterator &rhs) const { 62 | if (NA) { 63 | if (na< typename traits::ctype< 64 | typename std::iterator_traits< Iterator >::value_type 65 | >::type >::is_na(*rhs)) { 66 | return na< return_type >::VALUE(); 67 | } else { 68 | return ::foo(*rhs); 69 | } 70 | } else { 71 | return ::foo(*rhs); 72 | } 73 | } 74 | }; 75 | 76 | template< typename LhsIterator, typename RhsIterator, bool NA = true > 77 | struct bar : public binary_result_dims { 78 | typedef typename std::iterator_traits< LhsIterator >::value_type 79 | lhs_value_type; 80 | typedef typename std::iterator_traits< RhsIterator >::value_type 81 | rhs_value_type; 82 | typedef typename traits::widest_numeric_type< lhs_value_type, 83 | rhs_value_type >::type return_type; 84 | 85 | inline return_type operator()(LhsIterator &lhs, RhsIterator &rhs) const { 86 | if (NA) { 87 | if (!na< typename traits::ctype< lhs_value_type >::type 88 | >::is_na(*lhs) && !na< typename traits::ctype< 89 | rhs_value_type >::type >::is_na(*rhs)) { 90 | return ::bar(*lhs, *rhs); 91 | } 92 | 93 | return na< return_type >::VALUE(); 94 | } else { 95 | return ::bar(*lhs, *rhs); 96 | } 97 | } 98 | }; 99 | 100 | } // namespace functors 101 | } // namespace RcppHoney 102 | 103 | namespace RcppHoney { 104 | 105 | RCPP_HONEY_GENERATE_UNARY_FUNCTION(foo, foo) 106 | RCPP_HONEY_GENERATE_BINARY_FUNCTION(bar, bar) 107 | 108 | } 109 | 110 | // [[Rcpp::export]] 111 | Rcpp::NumericVector example_custom_function(Rcpp::NumericVector v, 112 | Rcpp::NumericVector w) { 113 | 114 | RcppHoney::NumericVector retval = RcppHoney::foo(v) + RcppHoney::bar(v, w); 115 | return retval; 116 | } 117 | ``` 118 | 119 | Now it is time to understand what this all means. 120 | 121 | ## Background 122 | 123 | First, let us discuss how functions are applied. `RcppHoney` essentially builds 124 | up iterators that know how to execute the expression for each element in the 125 | container. When that iterator is dereferenced, the magic happens. Each 126 | sub-expression along the way is evaluated to come to a final value of the 127 | dereferenced iterator. The operations that need to be executed are defined by 128 | [function objects](https://en.wikipedia.org/wiki/Function_object). These 129 | function objects implement `operator()(operand1, [operand2])` which 130 | which means that as long as we know the type of the function object (and how to 131 | construct it), we can apply it to the appropriate operands. These function 132 | objects in `RcppHoney` live in the `RcppHoney::functor` namespace because it's 133 | shorter to type than `RcppHoney::function_objects`. 134 | 135 | Function objects in `RcppHoney` take iterators as their operands so that we can 136 | pass unevaluated expressions along to each of them and, again, defer the actual 137 | operations until the final iterator dereferencing. `RcppHoney` currently only 138 | supports unary and binary functions. Ternary functions are currently not 139 | supported, but may be in the future (this is a result of the combinatorial 140 | explosion of function definitions that must be created to handle increasing 141 | numbers of operands and lack of a current use case). 142 | 143 | Let us look at `RcppHoney::functors::log` and `RcppHoney::functors::pow`: 144 | 145 | ```c++ 146 | // From RcppHoney/functors.hpp 147 | 148 | namespace RcppHoney { 149 | namespace functors { 150 | 151 | template< typename Iterator, bool NA > 152 | struct log : public binary_result_dims { 153 | typedef double return_type; 154 | return_type operator()(Iterator &rhs) const { 155 | if (NA) { 156 | if (na< typename traits::ctype< typename std::iterator_traits< Iterator >::value_type >::type >::is_na(*rhs)) { 157 | return na< return_type >::VALUE(); 158 | } else { 159 | return std::log(*rhs); 160 | } 161 | } else { 162 | return std::log(*rhs); 163 | } 164 | } 165 | }; 166 | 167 | template< typename LhsIterator, typename RhsIterator, bool NA = true > 168 | struct pow : public binary_result_dims { 169 | typedef typename std::iterator_traits< LhsIterator >::value_type lhs_value_type; 170 | typedef typename std::iterator_traits< RhsIterator >::value_type rhs_value_type; 171 | typedef double return_type; 172 | 173 | inline return_type operator()(LhsIterator &lhs, RhsIterator &rhs) const { 174 | if (NA) { 175 | if (!na< typename traits::ctype< lhs_value_type >::type >::is_na(*lhs) 176 | && !na< typename traits::ctype< rhs_value_type >::type >::is_na(*rhs)) { 177 | return std::pow(*lhs, *rhs); 178 | } 179 | 180 | return na< return_type >::VALUE(); 181 | } else { 182 | return std::pow(*lhs, *rhs); 183 | } 184 | } 185 | }; 186 | 187 | } // namespace functors 188 | } // namespace RcppHoney 189 | ``` 190 | 191 | Let us deconstruct this a bit. First note that the both `log` and `pow` are 192 | templated. 193 | 194 | ```c++ 195 | template< typename Iterator, bool NA > 196 | struct log; 197 | 198 | template< typename LhsIterator, typename RhsIterator, bool NA > 199 | ``` 200 | 201 | They are both templated over the operand iterator type(s) and a boolean 202 | value `NA`. This is a requirement for `RcppHoney` function objects. The 203 | iterator types (`Iterator`, `LhsIterator`, and `RhsIterator`) tell us what kind 204 | of operands to expect. The `NA` boolean lets us handle this function 205 | differently depending on whether the user wants to respect the `NA` values from 206 | `R` which are non-standard extensions of the common `C++` types `int` and 207 | `double`. They also both inherit from `binary_result_dims`. This is a 208 | convenience class that defines the `dims_t result_dims(const dims_t &lhs, 209 | const dims_t &rhs)` method for the functor. Given the dimensions of the RHS 210 | and LHS, this function will simply return the dimensions of the result. There 211 | are a couple of special cases with `dims_t` (which is defined as a 212 | `std::pair< uint64_t, uint64_t >`). If `dims.first == -1` this indicates that 213 | the result is a scalar (and will allow itself to work in a binary operator with 214 | operands of any dimension). If `dims.second == 0`, then the operand is a vector 215 | and can interoperate with other vectors of the same length. If 216 | `dims.second != 0` then we are dealing with a matrix. In practice, you will 217 | likely not need to worry about these things and inheriting from 218 | `binary_result_dims` or `unary_result_dims` will be sufficient. 219 | 220 | Each of the structs includes a local `typedef` called `return_type`. This 221 | tells `RcppHoney` what the return type of this function object is going to be. 222 | In these two cases, `return_type` is simply another name for `double` because 223 | both `std::pow` and `std::log` have a return type of `double`. 224 | 225 | Now to the meat of it. Both structs define `operator()(...)`. For `log`, which 226 | only takes one parameter, this function takes one parameter of type `Iterator`, 227 | over which the `struct` is templated. For `pow`, which takes two parameters, 228 | the `operator()(...)` function takes two parameters of types `LhsIterator` and 229 | `RhsIterator` respectively. 230 | 231 | The bodies of the `operator()(...)` functions are actually quite simple. If 232 | `NA` is `true` then we check for `NA` values and return the appropriate value 233 | if the operands are `NA`. Otherwise we simply apply the function to the 234 | dereferenced value(s) of the operand(s). 235 | 236 | Any function object defined by these rules is fair game for use in 237 | `RcppHoney`. 238 | 239 | Now we have function objects, but in general they are somewhat annoying to call 240 | as we have to instantiate an object of the function object's type and then 241 | call `operator()(...)` on it. Also, we need to already know the iterator(s) 242 | that we want to use as the operand(s). This is far from convenient, so we 243 | create functions in the `RcppHoney` namespace that can take any of the types 244 | that are "hooked" in to `RcppHoney`. 245 | 246 | For unary functions like `log` the function signatures that need to be created 247 | are as follows (in pseudoish code): 248 | 249 | ```c++ 250 | namespace RcppHoney { 251 | 252 | operand< ... > log(const operand< ... > &); 253 | operand< ... > log(const hooked_type &); 254 | 255 | } // namespace 256 | ``` 257 | 258 | For binary functions like `pow` the function signatures that need to be created 259 | are: 260 | 261 | ```c++ 262 | namespace RcppHoney { 263 | 264 | operand< ... > pow(const operand< ... > &, const operand< ... > &); 265 | operand< ... > pow(const scalar &, const operand< ... > &); 266 | operand< ... > pow(const operand< ... > &, const scalar &); 267 | operand< ... > pow(const scalar &, const hooked_type &); 268 | operand< ... > pow(const hooked_type &, const scalar &); 269 | operand< ... > pow(const operand< ... > &, const hooked_type &); 270 | operand< ... > pow(const hooked_type &, const operand< ... > &); 271 | operand< ... > pow(const hooked_type &, const hooked_type &); 272 | 273 | } // namespace RcppHoney 274 | ``` 275 | 276 | Fortunately, `RcppHoney` provides macros to define these for us. 277 | 278 | ```c++ 279 | RCPP_HONEY_GENERATE_UNARY_FUNCTION(FUNCTION_NAME, FUNCTOR_NAME) 280 | RCPP_HONEY_GENERATE_BINARY_FUNCTION(FUNCTION_NAME, FUNCTOR_NAME) 281 | ``` 282 | 283 | `RcppHoney` makes some assumptions about the namespaces that these macro 284 | parameters live in, so all we need to say to create all the functions is: 285 | 286 | ```c++ 287 | RCPP_HONEY_GENERATE_UNARY_FUNCTION(log, log) 288 | RCPP_HONEY_GENERATE_BINARY_FUNCTION(pow, pow) 289 | ``` 290 | 291 | ## The Example (explained) 292 | 293 | When we added `RcppHoney` functions for `foo` and `bar` we wrote a lot of 294 | unexplained code. Here we will go through it step by step in more detail. 295 | 296 | #### The Functions 297 | 298 | First we have the functions that we wish to use with `RcppHoney` objects (and 299 | hooked objects). These functions are fairly representative of the types of 300 | functions that we might want to leverage inside `RcppHoney` expressions. There 301 | is a third class of function which we might want to add which is the truly 302 | templated function. This is, in essence, a more general case of the `bar` 303 | example and is left as an exercise for the reader. 304 | 305 | ```c++ 306 | int foo(double d) { 307 | if (d >= 0) { 308 | return int(d + .5); 309 | } else { 310 | return int(d - .5); 311 | } 312 | } 313 | 314 | int bar(int x, int y) {return x + y;} 315 | double bar(int x, double y) {return x + y;} 316 | double bar(double x, int y) {return x + y;} 317 | double bar(double x, double y) {return x + y;} 318 | ``` 319 | 320 | #### The Function Objects 321 | 322 | Next we need to create our function object wrappers for these functions: 323 | 324 | ```c++ 325 | namespace RcppHoney { 326 | namespace functors { 327 | 328 | template< typename Iterator, bool NA > 329 | struct foo { 330 | typedef int return_type; 331 | return_type operator()(Iterator &rhs) const { 332 | if (NA) { 333 | if (na< typename traits::ctype< 334 | typename std::iterator_traits< Iterator >::value_type 335 | >::type >::is_na(*rhs)) { 336 | return na< return_type >::VALUE(); 337 | } else { 338 | return ::foo(*rhs); 339 | } 340 | } else { 341 | return ::foo(*rhs); 342 | } 343 | } 344 | }; 345 | 346 | template< typename LhsIterator, typename RhsIterator, bool NA = true > 347 | struct bar { 348 | typedef typename std::iterator_traits< LhsIterator >::value_type 349 | lhs_value_type; 350 | typedef typename std::iterator_traits< RhsIterator >::value_type 351 | rhs_value_type; 352 | typedef typename traits::widest_numeric_type< lhs_value_type, 353 | rhs_value_type >::type return_type; 354 | 355 | inline return_type operator()(LhsIterator &lhs, RhsIterator &rhs) const { 356 | if (NA) { 357 | if (!na< typename traits::ctype< lhs_value_type >::type 358 | >::is_na(*lhs) && !na< typename traits::ctype< 359 | rhs_value_type >::type >::is_na(*rhs)) { 360 | return ::bar(*lhs, *rhs); 361 | } 362 | 363 | return na< return_type >::VALUE(); 364 | } else { 365 | return ::bar(*lhs, *rhs); 366 | } 367 | } 368 | }; 369 | 370 | } // namespace functors 371 | } // namespace RcppHoney 372 | ``` 373 | 374 | There is a little bit of magic here using `std::iterator_traits`, 375 | `traits::ctype` and `traits::widest_numeric_type`. The full implementation of 376 | these is beyond the scope of this document, but in brief: 377 | 378 | * `std::iterator_traits` is part of the `C++` standard library and is 379 | described [here](http://en.cppreference.com/w/cpp/iterator/iterator_traits). 380 | * `traits::ctype` lets us derive the best `C++` type for a given type. It 381 | is restricted to `int`, `double`, and `Rcomplex` because these are the types 382 | that `R` supports. 383 | * `traits::widest_numeric_type` lets us pick the "wider" of the two types 384 | 385 | The practical upshot of it all is that with these classes, we can code our 386 | function objects to know their `return_type` and also appropriately test for 387 | `NA` values if the `NA` template parameter is `true`. It is important to note 388 | here that we have added an `if` statement with respect to the `NA` template 389 | value. We could also accomplish this with 390 | [template specialization](https://en.wikipedia.org/wiki/Generic_programming#Template_specialization) 391 | however, the `NA` template value is known at compile time and compilers are 392 | smart enough to simply optimize out things that look like `if (false)` at 393 | compile time. 394 | 395 | It is also important to note that these function objects _MUST_ be defined in 396 | the `RcppHoney::functors` namespace. This is because the macros use to create 397 | the functions that will use these function objects assume that to be the case. 398 | 399 | #### The Integration 400 | 401 | Finally, we need to declare our functions to actually integrate this with 402 | `RcppHoney`. They should be declared inside the `RcppHoney` namespace. 403 | This restriction could technically be removed, but it can help prevent name 404 | collisions, so we have decided to keep it. 405 | 406 | ```c++ 407 | namespace RcppHoney { 408 | 409 | RCPP_HONEY_GENERATE_UNARY_FUNCTION(foo, foo) 410 | RCPP_HONEY_GENERATE_BINARY_FUNCTION(bar, bar) 411 | 412 | } // namespace RcppHoney 413 | ``` 414 | 415 | ## Wrapping Up 416 | 417 | Integrating our own custom functions with `RcppHoney` can add flexibility to 418 | our code as well as help with performance. By following this pattern we can 419 | get expression template evaluation within `RcppHoney` for any unary or binary 420 | function that we wish to use. 421 | -------------------------------------------------------------------------------- /vignettes/introduction.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "RcppHoney Introduction" 3 | author: Daniel C. Dillon 4 | date: "`r Sys.Date()`" 5 | output: 6 | html_vignette: 7 | toc: true 8 | toc_depth: 4 9 | vignette: > 10 | %\VignetteIndexEntry{RcppHoney Introduction} 11 | %\VignetteEngine{knitr::rmarkdown} 12 | %\VignetteEncoding{UTF-8} 13 | --- 14 | 15 | ```{r setup, include=FALSE} 16 | knitr::opts_chunk$set(echo = TRUE) 17 | ``` 18 | 19 | ## Rationale 20 | 21 | In `C++` we often have containers that are not compatible with `R` or `Rcpp` 22 | with data already in them (`std::vector`, `std::set`, etc.). One would like 23 | to be able to operate on these containers without having to copy them into 24 | `Rcpp` structures like `IntegerVector`. `RcppHoney` aims to address this 25 | problem by providing operators and functions with `R` semantics that can be 26 | used on any iterator-based container. 27 | 28 | ## Introduction 29 | 30 | `RcppHoney` allows any iterator-based container to be "hooked" in. Once a 31 | container type is hooked to `RcppHoney`, it is granted operators (+, -, \*, /, 32 | etc.) and a host of other mathematical functions that can be run on it. It also 33 | becomes interoperable with any other hooked data structure. This lets us 34 | write expressions that look like `std::vector + Rcpp::IntegerVector + 35 | log(Rcpp::NumericVector)` and get the expected results. 36 | 37 | ## Implementation 38 | 39 | `RcppHoney` has several structures that are hooked in by default. Currently 40 | they are `std::vector`, `std::set`, and `Rcpp::VectorBase`. The ability to 41 | hook in custom structures is also provided. 42 | 43 | All operators and functions are implemented as 44 | [expression templates](https://en.wikipedia.org/wiki/Expression_templates) 45 | to minimize memory usage and enhance performance. The goal here is to only 46 | copy the data into an `R` compatible structure when we must (i.e. when we 47 | return it to `R`). This is achieved through the use of the `RcppHoney::operand` 48 | class. `RcppHoney::operand` provides an iterable interface to the result 49 | types of operators and functions. 50 | 51 | `RcppHoney` currently provides all the basic mathematical operators (+, -, \*, 52 | /) as well as some common 53 | [functions](https://github.com/dcdillon/RcppHoney/blob/master/inst/include/RcppHoney/functions.hpp#L53-L112) 54 | (abs, sin, cos, exp, etc.). Eventually all of the functionality provided by 55 | `Rcpp::sugar` as well as anything else we can think of will be supported. 56 | 57 | Enough about the abstract though...let's see it in action. 58 | 59 | ## Example 60 | 61 | The following example shows how to hook in a custom data structure 62 | (in this case `std::list`) as well as the types of expressions that can be 63 | created once a data structure is hooked in. 64 | 65 | ```{Rcpp} 66 | // Let Rcpp know we need RcppHoney 67 | // [[Rcpp::depends(RcppHoney)]] 68 | 69 | // we have to do this because we're going to hook in a non-default structure 70 | // otherwise we'd just #include 71 | #include 72 | #include 73 | 74 | // We're going to use the std::list class later so include it now 75 | #include 76 | 77 | // We have to declare our hooks before we include RcppHoney.hpp 78 | namespace RcppHoney { 79 | namespace hooks { 80 | 81 | // Hook in all std::list types (could be more specific) 82 | template< typename T, typename A > 83 | traits::true_type is_hooked(const std::list< T, A > &val); 84 | 85 | // Tell RcppHoney that NA has meaning in std::list 86 | template< typename T, typename A > 87 | traits::true_type has_na(const std::list< T, A > &val); 88 | 89 | // Tell RcppHoney that it needs to create basic (e.g. std::list + std::list) 90 | // operators 91 | template< typename T, typename A > 92 | traits::true_type needs_basic_operators(const std::list< T, A > &val); 93 | 94 | // Tell RcppHoney that it needs to create scalar (e.g. std::list + int/double) 95 | // operators 96 | template< typename T, typename A > 97 | traits::true_type needs_scalar_operators(const std::list< T, A > &val); 98 | 99 | // Tell RcppHoney that this set of types is part of the FAMILY_USER + 1 family. 100 | // This is used in conjunction with needs_basic_operators. If you have 101 | // needs_basic_operators return RcppHoney::traits::false_type, then only types 102 | // that are not part of the same family will have binary operators created 103 | // between them. 104 | template< typename T, typename A > 105 | traits::int_constant< FAMILY_USER + 1 > family(const std::list< T, A > &val); 106 | 107 | } // namespace hooks 108 | } // namespace RcppHoney 109 | 110 | #include 111 | 112 | // [[Rcpp::export]] 113 | Rcpp::NumericVector example_manually_hooked() { 114 | 115 | // We manually hooked std::list in to RcppHoney so we'll create one 116 | std::list< int > l; 117 | l.push_back(1); l.push_back(2); l.push_back(3); l.push_back(4); l.push_back(5); 118 | 119 | // std::vector is already hooked in to RcppHoney in default_hooks.hpp so 120 | // we'll create one of those too 121 | std::vector< int > v(l.begin(), l.end()); 122 | 123 | // And for good measure, let's create an Rcpp::NumericVector which is 124 | // also hooked by default 125 | Rcpp::NumericVector v2(v.begin(), v.end()); 126 | 127 | // Now do some weird operations incorporating std::vector, std::list, 128 | // Rcpp::NumericVector and some RcppHoney functions and return it. The 129 | // return value will be equal to the following R snippet: 130 | // v <- 1:5 131 | // result <- 42 + v + v + log(v) - v - v + sqrt(v) + -v + 42 132 | 133 | // We can store our result in any of RcppHoney::LogicalVector, 134 | // RcppHoney::IntegerVector, or RcppHoney::NumericVector and simply return 135 | // it to R. These classes inherit from their Rcpp counterparts and add a 136 | // new constructor. The only copy of the data, in this case, is when we 137 | // assign our expression to retval. Since it is then a "native" R type, 138 | // returning it is a shallow copy. Alternatively we could write this as: 139 | // return Rcpp::wrap(1 + v + RcppHoney::log(v) - v - 1 140 | // + RcppHoney::sqrt(v) + -v2); 141 | 142 | RcppHoney::NumericVector retval 143 | = 42 + l + v + RcppHoney::log(v) - v - l + RcppHoney::sqrt(v) + -v2 144 | + 42; 145 | return retval; 146 | } 147 | ``` 148 | 149 | ## Conclusion 150 | 151 | `RcppHoney` is a powerful tool for allowing different container types to 152 | interoperate under `Rcpp`. It can save development time as well as help the 153 | user generate faster and more readable code. 154 | --------------------------------------------------------------------------------