Skip to content

Commit 3a8a1d9

Browse files
committed
Added the concept of a bounded scalar
1 parent 269d3be commit 3a8a1d9

5 files changed

Lines changed: 156 additions & 14 deletions

File tree

inst/include/RcppHoney/bind.hpp

Lines changed: 107 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "traits/ctype.hpp"
2323
#include "na.hpp"
2424
#include "exceptions.hpp"
25+
#include "scalar_operator.hpp"
2526

2627
namespace RcppHoney {
2728

@@ -177,9 +178,19 @@ class cbinder : public operand< cbinder< LhsIterator, RhsIterator, NA_VALUE >,
177178
m_rhsEnd(rhsEnd) {
178179

179180
if (lhsDims.first == -1) {
180-
throw bounds_exception();
181+
if (rhsDims.first > 0) {
182+
m_dims.first = rhsDims.first
183+
+ ((rhsDims.second == 0) ? 1 : rhsDims.second);
184+
} else {
185+
throw bounds_exception();
186+
}
181187
} else if (rhsDims.first == -1) {
182-
throw bounds_exception();
188+
if (lhsDims.first > 0) {
189+
m_dims.first = lhsDims.first
190+
+ ((lhsDims.second == 0) ? 1 : lhsDims.second);
191+
} else {
192+
throw bounds_exception();
193+
}
183194
} else if (lhsDims.second == 0 && rhsDims.second == 0) {
184195
if (lhsDims.first == rhsDims.first) {
185196
m_dims.first = lhsDims.first;
@@ -237,5 +248,99 @@ struct make_cbinder
237248
rhs.begin(), rhs.end(), hooks::extract_dims(rhs));
238249
}
239250
};
251+
252+
template< typename T, typename T_ITER, typename T_RESULT, typename U,
253+
typename U_ITER, typename U_RESULT >
254+
RcppHoney::cbinder< T_ITER, U_ITER, (T::NA || U::NA) >
255+
cbind(const RcppHoney::operand< T, T_ITER, T_RESULT > &lhs,
256+
const RcppHoney::operand< U, U_ITER, U_RESULT > &rhs) {
257+
return RcppHoney::make_cbinder< (T::NA || U::NA) >()(lhs, rhs);
258+
}
259+
template< typename T, typename T_ITER, typename T_RESULT, typename U >
260+
typename RcppHoney::traits::enable_if< RcppHoney::traits::is_primitive< U >::value,
261+
RcppHoney::cbinder< T_ITER, typename RcppHoney::scalar_operator< U >::const_iterator, T::NA >
262+
>::type
263+
cbind(const RcppHoney::operand< T, T_ITER, T_RESULT > &lhs, const U &rhs) {
264+
return RcppHoney::make_cbinder< T::NA >()(lhs, RcppHoney::make_scalar_operator()(rhs, lhs.dims().first));
265+
}
266+
template< typename T, typename U, typename U_ITER, typename U_RESULT >
267+
typename RcppHoney::traits::enable_if< RcppHoney::traits::is_primitive< T >::value,
268+
RcppHoney::cbinder< typename RcppHoney::scalar_operator< T >::const_iterator, U_ITER, U::NA >
269+
>::type
270+
cbind(const T &lhs, const RcppHoney::operand< U, U_ITER, U_RESULT > &rhs) {
271+
return RcppHoney::make_cbinder< U::NA >()(RcppHoney::make_scalar_operator()(lhs, rhs.dims().first), rhs);
272+
}
273+
template< typename T, typename U >
274+
typename RcppHoney::traits::enable_if<
275+
(RcppHoney::hook< T >::value && RcppHoney::hook< U >::value),
276+
RcppHoney::cbinder<
277+
typename RcppHoney::hook< T >::const_iterator,
278+
typename RcppHoney::hook< U >::const_iterator,
279+
(RcppHoney::hook< T >::NA || RcppHoney::hook< U >::NA)
280+
>
281+
>::type
282+
cbind(const T &lhs, const U &rhs) {
283+
return RcppHoney::make_cbinder< (RcppHoney::hook< T >::NA || RcppHoney::hook< U >::NA) >()(
284+
lhs,
285+
rhs);
286+
}
287+
template< typename T, typename T_ITER, typename T_RESULT, typename U >
288+
typename RcppHoney::traits::enable_if< RcppHoney::hook< U >::value,
289+
RcppHoney::cbinder<
290+
T_ITER,
291+
typename RcppHoney::hook< U >::const_iterator,
292+
(T::NA || RcppHoney::hook< U >::NA)
293+
>
294+
>::type
295+
cbind(const RcppHoney::operand< T, T_ITER, T_RESULT > &lhs, const U &rhs) {
296+
return RcppHoney::make_cbinder< (T::NA || RcppHoney::hook< U >::NA) >()(
297+
lhs,
298+
rhs);
299+
}
300+
template< typename T, typename U, typename U_ITER, typename U_RESULT >
301+
typename RcppHoney::traits::enable_if< RcppHoney::hook< T >::value,
302+
RcppHoney::cbinder<
303+
typename RcppHoney::hook< T >::const_iterator,
304+
U_ITER,
305+
(U::NA || RcppHoney::hook< T >::NA)
306+
>
307+
>::type
308+
cbind(const T &lhs, const RcppHoney::operand< U, U_ITER, U_RESULT > &rhs) {
309+
return RcppHoney::make_cbinder< (U::NA || RcppHoney::hook< T >::NA) >()(
310+
lhs,
311+
rhs);
312+
}
313+
template< typename T, typename U >
314+
typename RcppHoney::traits::enable_if<
315+
RcppHoney::traits::is_primitive< T >::value
316+
&& RcppHoney::hook< U >::value,
317+
RcppHoney::cbinder<
318+
typename RcppHoney::scalar_operator< T >::const_iterator,
319+
typename RcppHoney::hook< U >::const_iterator,
320+
RcppHoney::hook< U >::NA
321+
>
322+
>::type
323+
cbind(const T &lhs, const U &rhs) {
324+
dims_t dims = RcppHoney::hooks::extract_dims(rhs);
325+
return RcppHoney::make_cbinder< RcppHoney::hook< U >::NA >()(
326+
RcppHoney::make_scalar_operator()(lhs, dims.first),
327+
rhs);
328+
}
329+
template< typename T, typename U >
330+
typename RcppHoney::traits::enable_if<
331+
RcppHoney::traits::is_primitive< U >::value
332+
&& RcppHoney::hook< T >::value,
333+
RcppHoney::cbinder<
334+
typename RcppHoney::hook< T >::const_iterator,
335+
typename RcppHoney::scalar_operator< U >::const_iterator,
336+
RcppHoney::hook< T >::NA
337+
>
338+
>::type
339+
cbind(const T &lhs, const U &rhs) {
340+
dims_t dims = RcppHoney::hooks::extract_dims(lhs);
341+
return RcppHoney::make_cbinder< RcppHoney::hook< T >::NA >()(
342+
lhs,
343+
RcppHoney::make_scalar_operator()(rhs, dims.first));
344+
}
240345

241346
} // namespace RcppHoney

inst/include/RcppHoney/functions.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,6 @@ _FNAME_ (const T &lhs, const U &rhs) {
313313
RcppHoney::make_scalar_operator()(rhs)); \
314314
}
315315

316-
RCPP_HONEY_GENERATE_BINARY_OPERAND(cbind, cbinder)
317-
318316
RCPP_HONEY_GENERATE_UNARY_FUNCTION(log, log)
319317
RCPP_HONEY_GENERATE_UNARY_FUNCTION(exp, exp)
320318
RCPP_HONEY_GENERATE_UNARY_FUNCTION(sqrt, sqrt)

inst/include/RcppHoney/scalar_operator.hpp

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,34 +28,44 @@ template< typename T >
2828
struct scalar_operator_iterator : public std::iterator< std::bidirectional_iterator_tag, T > {
2929
private:
3030
T m_value;
31+
uint64_t m_count;
3132

3233
public:
3334
inline scalar_operator_iterator() {}
3435

35-
inline scalar_operator_iterator(const T &val) : m_value(val) {}
36+
inline scalar_operator_iterator(const T &val) : m_value(val), m_count(0) {}
3637

38+
inline scalar_operator_iterator(const T &val, const uint64_t count)
39+
: m_value(val), m_count(count) {}
40+
3741
inline T operator*() {
3842
return m_value;
3943
}
4044

4145
inline scalar_operator_iterator &operator++() {
46+
++m_count;
4247
return *this;
4348
}
4449

4550
inline scalar_operator_iterator operator++(int) {
46-
return *this;
51+
scalar_operator_iterator i = *this;
52+
operator++();
53+
return i;
4754
}
4855

4956
inline scalar_operator_iterator &operator--() {
50-
return *this;
57+
--m_count;
58+
return *this;
5159
}
5260

5361
inline scalar_operator_iterator operator--(int) {
54-
return *this;
62+
scalar_operator_iterator i = *this;
63+
operator--();
64+
return i;
5565
}
5666

5767
inline bool operator==(const scalar_operator_iterator &rhs) const {
58-
return false;
68+
return m_count == rhs.m_count;
5969
}
6070

6171
inline bool operator!=(const scalar_operator_iterator &rhs) const {
@@ -80,21 +90,35 @@ class scalar_operator : public operand< scalar_operator< T >, scalar_operator_it
8090

8191
private:
8292
T m_value;
93+
dims_t m_dims;
94+
8395
public:
84-
scalar_operator(const T &val) :
85-
m_value(val) {}
96+
scalar_operator(const T &val) : m_value(val) {
97+
m_dims.first = -1;
98+
m_dims.second = 0;
99+
}
100+
101+
scalar_operator(const T &val, uint64_t maxSize) : m_value(val) {
102+
m_dims.first = maxSize;
103+
m_dims.second = 0;
104+
}
86105

87-
dims_t dims() const {return std::make_pair(-1, 0);}
88-
uint64_t size() const {return -1;}
106+
dims_t dims() const {return m_dims;}
107+
uint64_t size() const {return m_dims.first;}
89108
const_iterator begin() const {return const_iterator(m_value);}
90-
const_iterator end() const {return const_iterator(m_value);}
109+
const_iterator end() const {return const_iterator(m_value, m_dims.first);}
91110
};
92111

93112
struct make_scalar_operator {
94113
template< typename T >
95114
scalar_operator< T > operator()(const T &obj) {
96115
return scalar_operator< T >(obj);
97116
}
117+
118+
template< typename T >
119+
scalar_operator< T > operator()(const T &obj, uint64_t count) {
120+
return scalar_operator< T >(obj, count);
121+
}
98122
};
99123

100124
} // namespace RcppHoney

inst/unitTests/cpp/functions.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,19 @@ Rcpp::NumericVector test_cummax_operand(Rcpp::NumericMatrix m) {
300300
return Rcpp::wrap(RcppHoney::cummax(RcppHoney::log(m)));
301301
}
302302

303+
// [[Rcpp::export]]
304+
Rcpp::NumericMatrix test_cbind_vector_scalar(std::vector< double > v,
305+
double s) {
306+
307+
return Rcpp::wrap(RcppHoney::cbind(v, s));
308+
}
309+
// [[Rcpp::export]]
310+
Rcpp::NumericMatrix test_cbind_scalar_vector(double s,
311+
std::vector< double > v) {
312+
313+
return Rcpp::wrap(RcppHoney::cbind(s, v));
314+
}
315+
303316
// [[Rcpp::export]]
304317
Rcpp::NumericMatrix test_cbind_vector_vector(std::vector< double > v1,
305318
Rcpp::NumericVector v2) {

inst/unitTests/runit.functions.R

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ test.cbind <- function() {
216216
m1 <- matrix(1:10, 2, 5)
217217
m2 <- matrix(11:20, 2, 5)
218218

219+
checkEquals(unname(cbind(1, v2)), test_cbind_scalar_vector(1, v2))
220+
checkEquals(unname(cbind(v1, 1)), test_cbind_vector_scalar(v1, 1))
219221
checkEquals(unname(cbind(v1, v2)), test_cbind_vector_vector(v1, v2))
220222
checkEquals(unname(cbind(m1, v3)), test_cbind_matrix_vector(m1, v3))
221223
checkEquals(unname(cbind(v3, m1)), test_cbind_vector_matrix(v3, m1))

0 commit comments

Comments
 (0)