Euclidean chains: an informal presentation
The method
We present a method for generating an addition chain for
some n > 0:
- if n=3 then return the chain (1,2,3).
- if n=2^p for some p, then return the chain
(1,2,4,...,n)
- in other cases, choose some 1 < p < n, and build
a chain for n containing p.
We need a method to build a chain for n containing p:
- if n=pq, for some q, then build a chain
(1,2,...p)
for p, build a chain (1,2,...,q) for q,
then return the chain (1,2,...,p,2p,...,qp)
- if n=pq+r (0 < r < p), then build a chain
(1,2,...,r,...p) for p containing r,
build a chain (1,2,...,q) for q,
then return the chain (1,2,...,r,...,p,2p,...,qp,qp+r)
The chains we build this way are called euclidean chains, because
of the use of the euclidean division.
An example
Let n=87; since 87 is not a power of 2, let us choose
some intermediate step, for instance p=10.
So we have to build a chain ending in 87 and containing 10.
87=8 x 10 +7.
So first build a chain for 10 containing 7, a chain for 8, and combine them.
Since 10=1 x 7 + 3, we have to build a chain for 7 containing 3, a chain for
1, and combine them,
and so on ...
we compose the chain (1,2,3,6,7) and the chain (1) to get
(1,2,3,6,7,10)
we compose the chains (1,2,3,6,7,10)
and (1,2,4,8) to get
(1,2,3,6,7,10,20,40,80,87).
The figure below shows the dependencies in the computation of
x^87 following the preceding chain.
Strategies
The reader must have noticed that the algorithm presented above
contains some indeterminism in the sentence "choose some p".
We get rid of this indeterminism by considering a parameter called
a strategy: a function
which, applied to some n gives a p such that
1 < p < n.
Efficiency of euclidean chain generation depends strongly of the choosen
strategy (see the joint paper ).
Coding the chains
It would be inefficient to generate first an addition chain for nas an integer sequence, then use it
to compute x^n.
The algorithm we study here generates not a sequence of integers, but
builds direcltly a code for a little abstract machine operating on a monoid, containing
a register and a stack.
Its operations are SQR
(square the contents of the register),
MUL
(pop and multiply), PUSH
, and SWAP
(exchange
the two highest levels of the stack).
For more details, see ...
Notations
In the method presented above, we use the sentences:
"build a chain for n ", and
"build a chain for n containing p".
Since the chains are represented by "machine code", we have to specify
- in the last case - , whether the value x^p has to be saved
on the stack.
This is why we consider three functions for code generation:
-
(Call_M n)
builds a code for computing
x^n, x being the value of the register.
-
(Call_C n p)
builds a code for computing
x^n, x being the value of the register,
and we impose that the value x^p is computed before
x^n.
-
(Call_K n p)
is like
(Call_C n p)
, but the value x^p
is stored on the top of the stack.
Examples of code
We use again our favourite example: chain generation for n=87,
using the dichotomic strategy .
- Code c1for computing x^3 and pushing x on the stack.
PUSH PUSH SQR MUL
- Code c2 for computing x^2:
SQR
- Code c3 for computing x^7 and pushing x^3
on the stack:
c3=c1 PUSH SWAP c2 MUL
= PUSH PUSH SQR MUL PUSH SWAP SQR MUL
- Code c4 for computing x^10 and pushing x^7
on the stack:
c4=c3 PUSH SWAP MUL
=PUSH PUSH SQR MUL PUSH SWAP SQR MUL PUSH SWAP MUL
- Code c5 for computing x^8:
SQR SQR SQR
- Code c5 for computing x^87 (passing by x^10)
c6=c4 c5 MUL
= PUSH PUSH SQR MUL PUSH SWAP SQR MUL PUSH SWAP MUL
SQR SQR SQR MUL