|
25 | 25 | namespace Rcpp{ |
26 | 26 | namespace sugar{ |
27 | 27 |
|
| 28 | + // Kept out of line: inlining the error path keeps the compiler from |
| 29 | + // optimizing the loops that follow these checks. |
| 30 | +#if defined(__GNUC__) |
| 31 | + __attribute__((noinline, cold)) |
| 32 | +#endif |
| 33 | + inline void NORET stop_sizes(const char* fmt, R_xlen_t n1, R_xlen_t n2) { |
| 34 | + stop(fmt, n1, n2); |
| 35 | + } |
| 36 | + |
28 | 37 | // Sugar doesn't recycle the way R does: the vectors an expression |
29 | 38 | // combines must all have the same length. |
30 | 39 | inline void check_sizes(R_xlen_t n1, R_xlen_t n2) { |
31 | 40 | if (n1 != n2) |
32 | | - stop("sugar operands have different lengths (%d and %d)", n1, n2); |
| 41 | + stop_sizes("sugar operands have different lengths (%d and %d)", n1, n2); |
33 | 42 | } |
34 | 43 |
|
35 | 44 | inline void check_sizes(R_xlen_t n1, R_xlen_t n2, R_xlen_t n3) { |
36 | | - if (n1 != n2 || n1 != n3) |
37 | | - stop("sugar operands have different lengths (%d, %d and %d)", n1, n2, n3); |
| 45 | + check_sizes(n1, n2); |
| 46 | + check_sizes(n1, n3); |
38 | 47 | } |
39 | 48 |
|
40 | 49 | // Likewise, a vector assigned into a range, row or column must have the |
41 | 50 | // same length as that target. |
42 | 51 | inline void check_assign_size(R_xlen_t target, R_xlen_t value) { |
43 | 52 | if (target != value) |
44 | | - stop("cannot assign a vector of length %d to a target of length %d", value, target); |
| 53 | + stop_sizes("cannot assign a vector of length %d to a target of length %d", value, target); |
45 | 54 | } |
46 | 55 |
|
47 | 56 | } // sugar |
|
0 commit comments