operator | action | functions like |
---|---|---|
+ | add | bc.d |
- | substract | bc.d |
* | multiply | bc.d |
/ | divide | bc.d |
^ | raise to power | bc.d |
%/% | floored integer divide | bc.i |
%% | modulo | bc.i |
Additional Details
1 Overload method tables
The overloaded operators from the ‘broadcast’ package attempts to mimic the base operators accurately, except that broadcasting is used (obviously).
The following tables overview the behaviour of the operators.
1.1 Regular Arithmetic operators
If both sides of the operators given here are numeric or logical, the following holds:
1.2 Complex Arithmetic operators
If at least one of the arguments of the operators given here are complex, the following holds:
operator | action | functions like |
---|---|---|
+ | add | bc.cplx |
- | substract | bc.cplx |
* | multiply | bc.cplx |
/ | divide | bc.cplx |
1.3 Logical Operators
If both sides of the operators given here are complex, numeric or logical, the following holds:
operator | action | functions like |
---|---|---|
& | and | bc.b |
| | or | bc.b |
1.4 Bit-wise operators
If both sides of the operators given here are type of raw, the following holds:
operator | action | functions like |
---|---|---|
& | bit-wise and | bc.bit |
| | bit-wise or | bc.bit |
1.5 Relational operators
For relational operators, ‘broadcast’ first finds the “highest” (or most complex) atomic type of both sides, coerces both sides to said type, and then performs the broadcasted relational operation. Recursive types are not supported.
The types, from complex to simple, are: character
, complex
, numeric
(also known as double
), integer
, logical
, and raw
.
2 Compatibility with Custom Methods
Consider a classed vector like the following:
<- 1:10
x class(x) <- "someclass"
print(class(x))
#> [1] "someclass"
Setting a vector or array as a “broadcaster” using the broadcaster()<-
function, will add the “broadcaster” class attribute;
but note that the “broadcaster” class will be placed last in the class attribute:
broadcaster(x) <- TRUE
print(class(x))
#> [1] "someclass" "broadcaster"
Notice how the “broadcaster” class comes after the “someclass” class.
Let’s make a quick ’n dirty (and not at all smart) +
method for “somceclass”, which will just print some text:
`+.someclass` <- function(e1, e2) {print("someclass method called")}
What will happen? Will the +
method for the broadcaster be called, or the +
method for “someclass”?
Well, since the “broadcaster” class is intentionally placed last, operator methods for the overriding classes will always “win” over the “broadcaster” class. In this case, if there are methods for the base operators (such as +
, -
, etc.) for the “someclass” class, the method for “someclass” will be called, rather than the broadcaster method:
<- array(1:10, c(1, 10))
y class(y) <- "someclass"
broadcaster(y) <- TRUE
+ y
x #> [1] "someclass method called"
#> [1] "someclass method called"
Notice how the +
method for “someclass” is called, rather than the +
method for the broadcaster.
This ensures compatibility with custom classes.
After all, some classes may not be intended to be broadcasted, or they may not be compatible with the base ‘R’ way of arithmetic (which is what ‘broadcast’ mimics), or they may need careful handling of attributes.
Authors of these custom classes can make their methods use broadcasting if a broadcaster vector/array is detected, if they so choose; only they know what is appropriate for their classes and what isn’t.