The function Ops.permutation()
passes binary arithmetic
operators (+
, *
, /
,
and ^
) to the appropriate specialist function.
Multiplication, as in a*b
, is effectively
word_prod(a,b)
; it coerces its arguments to word form.
Raising permutations to integer powers, as in a^n
, is
cycle_power(a,n)
; it coerces a
to cycle form and returns
a cycle. Negative and zero values of n
operate as expected.
Function cycle_power()
is vectorized; it calls
cycle_power_single()
, which is not. This calls vps()
(Vector Power Single), which checks for simple cases such as
pow=0
or the identity permutation; and function vps()
calls function ccps()
which performs the actual
number-theoretic manipulation to raise a cycle to a power.
Raising a permutation to the power of another permutation, as in
a^b
, is idiom for inverse(b)*a*b
, sometimes known as
group action; the notation is motivated by the identities
x^(yz)=(x^y)^z
and (xy)^z=x^z*y^z
.
Permutation addition, as in a+b
, is defined if the cycle
representations of the addends are disjoint. The sum is defined as
the permutation given by juxtaposing the cycles of a
with those
of b
. Note that this operation is commutative. If a
and b
do not have disjoint cycle representations, an error is
returned. This is useful if you want to guarantee that two
permutations commute (NB: permutation a
commutes with
a^i
for i
any integer, and in particular a
commutes with itself. But a+a
returns an error: the operation
checks for disjointness, not commutativity).
Permutation division, as in a/b
, is
a*inverse(b)
. Note that a/b*c
is evaluated left to
right so is equivalent to a*inverse(b)*c
. See note.
Function helper()
sorts out recycling for binary functions, the
behaviour of which is inherited from cbind()
, which also
handles the names of the returned permutation.