Addition-chain exponentiation: Difference between revisions

m
(→‎{{header|Haskell}}: added solution)
m (→‎{{header|Wren}}: Minor tidy)
 
(11 intermediate revisions by 3 users not shown)
Line 1:
[[Category:Matrices]]
{{draft task|Logic}}{{wikipedia|Addition-chain exponentiation}}
In cases of special objects (such as with [[wp:Matrix (mathematics)|matrices]]) the operation of multiplication can be excessively expensive. In these cases the operation of multiplication should be avoided or reduced to a minimum.
Line 89 ⟶ 90:
=={{header|C}}==
Using complex instead of matrix. Requires [[Addition-chain exponentiation/Achain.c|Achain.c]]. It takes a long while to compute the shortest addition chains, such that if you don't have the chain lengths precomputed and stored somewhere, you are probably better off with a binary chain (normally not shortest but very simple to calculate) whatever you intend to use the chains for.
<langsyntaxhighlight lang="c">#include <stdio.h>
 
#include "achain.c" /* not common practice */
Line 159 ⟶ 160:
printf("%14d %7d %7d\n", i, seq_len(i), bin_len(i));
return 0;
}</langsyntaxhighlight>
output
<pre>...
Line 189 ⟶ 190:
 
Calculating A ^ (m * n) from scratch using this method would take 'for ever' so I've calculated it instead as (A ^ m) ^ n.
<langsyntaxhighlight lang="go">package main
 
import (
Line 592 ⟶ 593:
mx2 := mxs[0].pow(n, false)
mx2.print()
}</langsyntaxhighlight>
 
{{out}}
Line 662 ⟶ 663:
I think it should nevertheless be retained as it is an interesting approach and there are other solutions to this task which are based on it.
 
<langsyntaxhighlight lang="go">/*
Continued fraction addition chains, as described in "Efficient computation
of addition chains" by F. Bergeron, J. Berstel, and S. Brlek, published in
Line 869 ⟶ 870:
}
return m3
}</langsyntaxhighlight>
Output (manually wrapped at 80 columns.)
<pre>
Line 922 ⟶ 923:
Generators of a nearly-optimal addition chains for a given number.
 
<langsyntaxhighlight lang="haskell">dichotomicChain :: Integral a => a -> [a]
dichotomicChain n
| n == 3 = [3, 2, 1]
Line 943 ⟶ 944:
binaryChain 1 = [1]
binaryChain n | even n = n : binaryChain (n `div` 2)
| odd n = n : binaryChain (n - 1)</langsyntaxhighlight>
 
<pre>λ> dichotomicChain 31415
Line 961 ⟶ 962:
 
Universal monoid multiplication that uses additive chain
<langsyntaxhighlight lang="haskell">times :: (Monoid p, Integral a) => a -> p -> p
0 `times` _ = mempty
n `times` x = res
Line 968 ⟶ 969:
ch = reverse $ dichotomicChain n
f (p:ps, c1, i) c2 = let Just j = elemIndex (c2-c1) ch
in ((p <> ((p:ps) !! (i-j))):p:ps, c2, i+1)</langsyntaxhighlight>
 
<pre>λ> 31 `times` "a"
Line 981 ⟶ 982:
Implementation of matrix multiplication as monoidal operation.
 
<langsyntaxhighlight lang="haskell">data M a = M [[a]] | I deriving Show
 
instance Num a => Semigroup (M a) where
Line 990 ⟶ 991:
 
instance Num a => Monoid (M a) where
mempty = I</langsyntaxhighlight>
 
<pre>-- matrix multiplication
Line 1,050 ⟶ 1,051:
[0.0,0.0,0.0,0.0,1.0,0.0],
[0.0,0.0,0.0,0.0,0.0,1.0]]</pre>
 
 
=={{header|Julia}}==
Uses an iterator to generate A003313 (the first 100 values). Uses the Knuth path method for the larger integers. This gives a chain length of 18 for both 27182 and 31415.
<syntaxhighlight lang="julia">import Base.iterate
 
mutable struct AdditionChains{T}
chains::Vector{Vector{T}}
work_chain::Int
work_element::Int
AdditionChains{T}() where T = new{T}([[one(T)]], 1, 1)
end
 
function Base.iterate(acs::AdditionChains, state = 1)
i, j = acs.work_chain, acs.work_element
newchain = [acs.chains[i]; acs.chains[i][end] + acs.chains[i][j]]
push!(acs.chains, newchain)
if j == length(acs.chains[i])
acs.work_chain += 1
acs.work_element = 1
else
acs.work_element += 1
end
return newchain, state + 1
end
 
function findchain!(acs::AdditionChains, n)
@assert n > 0
n == 1 && return [one(eltype(first(acs.chains)))]
idx = findfirst(a -> a[end] == n, acs.chains)
if idx == nothing
for (i, chain) in enumerate(acs)
chain[end] == n && return chain
end
end
return acs.chains[idx]
end
 
""" memoization for knuth_path """
const knuth_path_p, knuth_path_lvl = Dict(1 => 0), [[1]]
 
""" knuth path method for addition chains """
function knuth_path(n)::Vector{Int}
iszero(n) && return Int[]
while !haskey(knuth_path_p, n)
q = Int[]
for x in first(knuth_path_lvl), y in knuth_path(x)
if !haskey(knuth_path_p, x + y)
knuth_path_p[x + y] = x
push!(q, x + y)
end
end
knuth_path_lvl[begin] = q
end
return push!(knuth_path(knuth_path_p[n]), n)
end
 
function pow(x, chain)
p, products = 0, Dict{Int, typeof(x)}(0 => one(x), 1 => x)
for i in chain
products[i] = products[p] * products[i - p]
p = i
end
return products[chain[end]]
end
 
function test_addition_chains()
additionchain = AdditionChains{Int}()
println("First one hundred addition chain lengths:")
for i in 1:100
print(rpad(length(findchain!(additionchain, i)) -1, 3), i % 10 == 0 ? "\n" : "")
end
println("\nKnuth chains for addition chains of 31415 and 27182:")
expchains = Dict(i => knuth_path(i) for i in [31415, 27182])
for (n, chn) in expchains
println("Exponent: ", rpad(n, 10), "\n Addition Chain: $(chn[begin:end-1]))")
end
println("\n1.00002206445416^31415 = ", pow(1.00002206445416, expchains[31415]))
println("1.00002550055251^27182 = ", pow(1.00002550055251, expchains[27182]))
println("1.00002550055251^(27182 * 31415) = ", pow(BigFloat(pow(1.00002550055251, expchains[27182])), expchains[31415]))
println("(1.000025 + 0.000058i)^27182 = ", pow(Complex(1.000025, 0.000058), expchains[27182]))
println("(1.000022 + 0.000050i)^31415 = ", pow(Complex(1.000022, 0.000050), expchains[31415]))
x = sqrt(1/2)
matrixA = [x 0 x 0 0 0; 0 x 0 x 0 0; 0 x 0 -x 0 0; -x 0 x 0 0 0; 0 0 0 0 0 1; 0 0 0 0 1 0]
println("matrix A ^ 27182 = ")
display(pow(matrixA, expchains[27182]))
println("matrix A ^ 31415 = ")
display(round.(pow(matrixA, expchains[31415]), digits=6))
println("(matrix A ^ 27182) ^ 31415 = ")
display(pow(pow(matrixA, expchains[27182]), expchains[31415]))
end
 
test_addition_chains()
</syntaxhighlight>{{out}}
<pre>
First one hundred addition chain lengths:
0 1 2 2 3 3 4 3 4 4
5 4 5 5 5 4 5 5 6 5
6 6 6 5 6 6 6 6 7 6
7 5 6 6 7 6 7 7 7 6
7 7 7 7 7 7 8 6 7 7
7 7 8 7 8 7 8 8 8 7
8 8 8 6 7 7 8 7 8 8
9 7 8 8 8 8 8 8 9 7
8 8 8 8 8 8 9 8 9 8
9 8 9 9 9 7 8 8 8 8
 
Knuth chains for addition chains of 31415 and 27182:
Exponent: 27182
Addition Chain: [1, 2, 3, 5, 7, 14, 21, 35, 70, 140, 143, 283, 566, 849, 1698, 3396, 6792, 6799, 13591])
Exponent: 31415
Addition Chain: [1, 2, 3, 5, 7, 14, 28, 56, 61, 122, 244, 488, 976, 1952, 3904, 7808, 15616, 15677, 31293])
 
1.00002206445416^31415 = 1.9999999998924638
1.00002550055251^27182 = 1.9999999999792688
1.00002550055251^(27182 * 31415) = 7.199687435551025768365237017391630520475805934721292725697031724530209692195819e+9456
(1.000025 + 0.000058i)^27182 = -0.01128636963542673 + 1.9730308496660347im
(1.000022 + 0.000050i)^31415 = 0.00016144681325535107 + 1.9960329014194498im
matrix A ^ 27182 =
6×6 Matrix{Float64}:
-0.5 -0.5 -0.5 0.5 0.0 0.0
0.5 -0.5 -0.5 -0.5 0.0 0.0
-0.5 -0.5 0.5 -0.5 0.0 0.0
0.5 -0.5 0.5 0.5 0.0 0.0
0.0 0.0 0.0 0.0 1.0 0.0
0.0 0.0 0.0 0.0 0.0 1.0
matrix A ^ 31415 =
6×6 Matrix{Float64}:
0.707107 0.0 -0.0 -0.707107 0.0 0.0
-0.0 0.707107 0.707107 -0.0 0.0 0.0
0.707107 -0.0 -0.0 0.707107 0.0 0.0
0.0 0.707107 -0.707107 -0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 1.0
0.0 0.0 0.0 0.0 1.0 0.0
(matrix A ^ 27182) ^ 31415 =
6×6 Matrix{Float64}:
-0.5 0.5 -0.5 0.5 0.0 0.0
-0.5 -0.5 -0.5 -0.5 0.0 0.0
-0.5 -0.5 0.5 0.5 0.0 0.0
0.5 -0.5 -0.5 0.5 0.0 0.0
0.0 0.0 0.0 0.0 1.0 0.0
0.0 0.0 0.0 0.0 0.0 1.0
</pre>
 
=={{header|Nim}}==
{{trans|Go}}
<langsyntaxhighlight Nimlang="nim">import math, sequtils, strutils
 
const
Line 1,386 ⟶ 1,530:
echo "Exponent: $1 x $2 = $3".format(m, n, m * n)
echo "A ^ $1 = (A ^ $2) ^ $3:\n".format(m * n, m, n)
echo mxs[0].pow(n, false)</langsyntaxhighlight>
 
{{out}}
Line 1,486 ⟶ 1,630:
Note that "tries" overflows (crashes) at 1073741824, which I kept in as a deliberate limiter.
 
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
Line 1,553 ⟶ 1,697:
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"addition_chain(31,8):%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">addition_chain</span><span style="color: #0000FF;">(</span><span style="color: #000000;">31</span><span style="color: #0000FF;">,</span><span style="color: #000000;">8</span><span style="color: #0000FF;">))})</span>
<!--</langsyntaxhighlight>-->
 
{{out}}
Line 1,607 ⟶ 1,751:
--1.00003 ^ 27182 (20) = 1.9999999999727968238298855
--1.00003 ^ 27182 (19) = 1.9999999999727968238298527</pre>
 
=={{header|Python}}==
<syntaxhighlight lang="python">''' Rosetta Code task Addition-chain_exponentiation '''
 
from math import sqrt
from numpy import array
from mpmath import mpf
 
 
class AdditionChains:
''' two methods of calculating addition chains '''
 
def __init__(self):
''' memoization for knuth_path '''
self.chains, self.idx, self.pos = [[1]], 0, 0
self.pat, self.lvl = {1: 0}, [[1]]
 
def add_chain(self):
''' method 1: add chains depth then breadth first until done '''
newchain = self.chains[self.idx].copy()
newchain.append(self.chains[self.idx][-1] +
self.chains[self.idx][self.pos])
self.chains.append(newchain)
if self.pos == len(self.chains[self.idx])-1:
self.idx += 1
self.pos = 0
else:
self.pos += 1
return newchain
 
def find_chain(self, nexp):
''' method 1 interface: search for chain ending with n, adding more as needed '''
assert nexp > 0
if nexp == 1:
return [1]
chn = next((a for a in self.chains if a[-1] == nexp), None)
if chn is None:
while True:
chn = self.add_chain()
if chn[-1] == nexp:
break
 
return chn
 
def knuth_path(self, ngoal):
''' method 2: knuth method, uses memoization to search for a shorter chain '''
if ngoal < 1:
return []
while not ngoal in self.pat:
new_lvl = []
for i in self.lvl[0]:
for j in self.knuth_path(i):
if not i + j in self.pat:
self.pat[i + j] = i
new_lvl.append(i + j)
 
self.lvl[0] = new_lvl
 
returnpath = self.knuth_path(self.pat[ngoal])
returnpath.append(ngoal)
return returnpath
 
 
def cpow(xbase, chain):
''' raise xbase by an addition exponentiation chain for what becomes x**chain[-1] '''
pows, products = 0, {0: 1, 1: xbase}
for i in chain:
products[i] = products[pows] * products[i - pows]
pows = i
return products[chain[-1]]
 
 
if __name__ == '__main__':
# test both addition chain methods
acs = AdditionChains()
print('First one hundred addition chain lengths:')
for k in range(1, 101):
print(f'{len(acs.find_chain(k))-1:3}', end='\n'if k % 10 == 0 else '')
 
print('\nKnuth chains for addition chains of 31415 and 27182:')
chns = {m: acs.knuth_path(m) for m in [31415, 27182]}
for (num, cha) in chns.items():
print(f'Exponent: {num:10}\n Addition Chain: {cha[:-1]}')
print('\n1.00002206445416^31415 =', cpow(1.00002206445416, chns[31415]))
print('1.00002550055251^27182 =', cpow(1.00002550055251, chns[27182]))
print('1.000025 + 0.000058i)^27182 =',
cpow(complex(1.000025, 0.000058), chns[27182]))
print('1.000022 + 0.000050i)^31415 =',
cpow(complex(1.000022, 0.000050), chns[31415]))
sq05 = mpf(sqrt(0.5))
mat = array([[sq05, 0, sq05, 0, 0, 0], [0, sq05, 0, sq05, 0, 0], [0, sq05, 0, -sq05, 0, 0],
[-sq05, 0, sq05, 0, 0, 0], [0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 1, 0]])
print('matrix A ^ 27182 =')
print(cpow(mat, chns[27182]))
print('matrix A ^ 31415 =')
print(cpow(mat, chns[31415]))
print('(matrix A ** 27182) ** 31415 =')
print(cpow(cpow(mat, chns[27182]), chns[31415]))
</syntaxhighlight>{{out}}
<pre>
First one hundred addition chain lengths:
0 1 2 2 3 3 4 3 4 4
5 4 5 5 5 4 5 5 6 5
6 6 6 5 6 6 6 6 7 6
7 5 6 6 7 6 7 7 7 6
7 7 7 7 7 7 8 6 7 7
7 7 8 7 8 7 8 8 8 7
8 8 8 6 7 7 8 7 8 8
9 7 8 8 8 8 8 8 9 7
8 8 8 8 8 8 9 8 9 8
9 8 9 9 9 7 8 8 8 8
 
Knuth chains for addition chains of 31415 and 27182:
Exponent: 31415
Addition Chain: [1, 2, 3, 5, 7, 14, 28, 56, 61, 122, 244, 488, 976, 1952, 3904, 7808, 15616, 15677, 31293]
Exponent: 27182
Addition Chain: [1, 2, 3, 5, 7, 14, 21, 35, 70, 140, 143, 283, 566, 849, 1698, 3396, 6792, 6799, 13591]
 
1.00002206445416^31415 = 1.9999999998924638
1.00002550055251^27182 = 1.9999999999792688
1.000025 + 0.000058i)^27182 = (-0.01128636963542673+1.9730308496660347j)
1.000022 + 0.000050i)^31415 = (0.00016144681325535107+1.9960329014194498j)
matrix A ^ 27182 =
[[mpf('5.0272320351359433e-4092') 0 mpf('5.0272320351359433e-4092') 0 0 0]
[0 mpf('5.0272320351359433e-4092') 0 mpf('5.0272320351359433e-4092') 0 0]
[0 mpf('5.0272320351359433e-4092') 0 mpf('5.0272320351359433e-4092') 0 0]
[mpf('5.0272320351359433e-4092') 0 mpf('5.0272320351359433e-4092') 0 0 0]
[0 0 0 0 0 1]
[0 0 0 0 1 0]]
matrix A ^ 31415 =
[[mpf('3.7268602513250562e-4729') 0 mpf('3.7268602513250562e-4729') 0 0 0]
[0 mpf('3.7268602513250562e-4729') 0 mpf('3.7268602513250562e-4729') 0 0]
[0 mpf('3.7268602513250562e-4729') 0 mpf('-3.7268602513250562e-4729') 0
0]
[mpf('-3.7268602513250562e-4729') 0 mpf('3.7268602513250562e-4729') 0 0
0]
[0 0 0 0 0 1]
[0 0 0 0 1 0]]
(matrix A ** 27182) ** 31415 =
[[mpf('1.77158544475749e-128528148') 0 mpf('1.77158544475749e-128528148')
0 0 0]
[0 mpf('1.77158544475749e-128528148') 0
mpf('1.77158544475749e-128528148') 0 0]
[0 mpf('1.77158544475749e-128528148') 0
mpf('1.77158544475749e-128528148') 0 0]
[mpf('1.77158544475749e-128528148') 0 mpf('1.77158544475749e-128528148')
0 0 0]
[0 0 0 0 0 1]
[0 0 0 0 1 0]]
</pre>
 
=={{header|Racket}}==
Line 1,614 ⟶ 1,908:
 
The addition chains correspond to binary exponentiation.
<langsyntaxhighlight lang="racket">
#lang racket
(define (chain n)
Line 1,655 ⟶ 1,949:
(test 1.00002206445416 31415)
(test 1.00002550055251 27182)
</syntaxhighlight>
</lang>
Output:
<langsyntaxhighlight lang="racket">
Chain for 31415
((31415 31414 1) (31414 15707 15707) (15707 15706 1) (15706 7853 7853) (7853 7852 1) (7852 3926 3926) (3926 1963 1963) (1963 1962 1) (1962 981 981) (981 980 1) (980 490 490) (490 245 245) (245 244 1) (244 122 122) (122 61 61) (61 60 1) (60 30 30) (30 15 15) (15 14 1) (14 7 7) (7 6 1) (6 3 3) (3 2 1) (2 1 1))
Line 1,667 ⟶ 1,961:
1.00002550055251 ^ 27182 = 1.9999999999774538
Multiplications: 21
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
{{trans|Python}}
<syntaxhighlight lang="raku" line># 20230327 Raku programming solution
 
use Math::Matrix;
 
class AdditionChains { has ( $.idx, $.pos, @.chains, @.lvl, %.pat ) is rw;
 
method add_chain {
# method 1: add chains depth then breadth first until done
return gather given self {
take my $newchain = .chains[.idx].clone.append:
.chains[.idx][*-1] + .chains[.idx][.pos];
.chains.append: $newchain;
.pos == +.chains[.idx]-1 ?? ( .idx += 1 && .pos = 0 ) !! .pos += 1;
}
}
 
method find_chain(\nexp where nexp > 0) {
# method 1 interface: search for chain ending with n, adding more as needed
return ([1],) if nexp == 1;
my @chn = self.chains.grep: *.[*-1] == nexp // [];
unless @chn.Bool {
repeat { @chn = self.add_chain } until @chn[*-1][*-1] == nexp
}
return @chn
}
 
method knuth_path(\ngoal) {
# method 2: knuth method, uses memoization to search for a shorter chain
return [] if ngoal < 1;
until self.pat{ngoal}:exists {
self.lvl[0] = [ gather for self.lvl[0].Array -> \i {
for self.knuth_path(i).Array -> \j {
unless self.pat{i + j}:exists {
self.pat{i + j} = i and take i + j
}
}
} ]
}
return self.knuth_path(self.pat{ngoal}).append: ngoal
}
 
multi method cpow(\xbase, \chain) {
# raise xbase by an addition exponentiation chain for what becomes x**chain[-1]
my ($pows, %products) = 0, 1 => xbase;
 
%products{0} = xbase ~~ Math::Matrix
?? Math::Matrix.new([ [ 1 xx xbase.size[1] ] xx xbase.size[0] ]) !! 1;
 
for chain.Array -> \i {
%products{i} = %products{$pows} * %products{i - $pows};
$pows = i
}
return %products{ chain[*-1] }
}
}
 
my $chn = AdditionChains.new( idx => 0, pos => 0,
chains => ([1],), lvl => ([1],), pat => {1=>0} );
 
say 'First one hundred addition chain lengths:';
.Str.say for ( (1..100).map: { +$chn.find_chain($_)[0] - 1 } ).rotor: 10;
 
my %chns = (31415, 27182).map: { $_ => $chn.knuth_path: $_ };
 
say "\nKnuth chains for addition chains of 31415 and 27182:";
say "Exponent: $_\n Addition Chain: %chns{$_}[0..*-2]" for %chns.keys;
say '1.00002206445416^31415 = ', $chn.cpow(1.00002206445416, %chns{31415});
say '1.00002550055251^27182 = ', $chn.cpow(1.00002550055251, %chns{27182});
say '(1.000025 + 0.000058i)^27182 = ', $chn.cpow: 1.000025+0.000058i, %chns{27182};
say '(1.000022 + 0.000050i)^31415 = ', $chn.cpow: 1.000022+0.000050i, %chns{31415};
 
my \sq05 = 0.5.sqrt;
my \mat = Math::Matrix.new( [[sq05, 0, sq05, 0, 0, 0],
[ 0, sq05, 0, sq05, 0, 0],
[ 0, sq05, 0, -sq05, 0, 0],
[-sq05, 0, sq05, 0, 0, 0],
[ 0, 0, 0, 0, 0, 1],
[ 0, 0, 0, 0, 1, 0]] );
 
say 'matrix A ^ 27182 =';
say my $res27182 = $chn.cpow(mat, %chns{27182});
say 'matrix A ^ 31415 =';
say $chn.cpow(mat, %chns{31415});
say '(matrix A ** 27182) ** 31415 =';
say $chn.cpow($res27182, %chns{31415});
</syntaxhighlight>
{{out}}
<pre>First one hundred addition chain lengths:
0 1 2 2 3 3 4 3 4 4
5 4 5 5 5 4 5 5 6 5
6 6 6 5 6 6 6 6 7 6
7 5 6 6 7 6 7 7 7 6
7 7 7 7 7 7 8 6 7 7
7 7 8 7 8 7 8 8 8 7
8 8 8 6 7 7 8 7 8 8
9 7 8 8 8 8 8 8 9 7
8 8 8 8 8 8 9 8 9 8
9 8 9 9 9 7 8 8 8 8
 
Knuth chains for addition chains of 31415 and 27182:
Exponent: 27182
Addition Chain: 1 2 3 5 7 14 21 35 70 140 143 283 566 849 1698 3396 6792 6799 13591
Exponent: 31415
Addition Chain: 1 2 3 5 7 14 28 56 61 122 244 488 976 1952 3904 7808 15616 15677 31293
1.00002206445416^31415 = 1.9999999998924638
1.00002550055251^27182 = 1.999999999974053
(1.000025 + 0.000058i)^27182 = -0.01128636963542673+1.9730308496660347i
(1.000022 + 0.000050i)^31415 = 0.00016144681325535107+1.9960329014194498i
matrix A ^ 27182 =
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 1
0 0 0 0 1 0
matrix A ^ 31415 =
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 -0 0 0
-0 0 0 0 0 0
0 0 0 0 0 1
0 0 0 0 1 0
(matrix A ** 27182) ** 31415 =
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 1
0 0 0 0 1 0</pre>
 
=={{header|Tcl}}==
Line 1,674 ⟶ 2,100:
Using code at [[Matrix multiplication#Tcl]] and [[Matrix Transpose#Tcl]] (not shown here).
{{trans|Go}}
<langsyntaxhighlight lang="tcl"># Continued fraction addition chains, as described in "Efficient computation
# of addition chains" by F. Bergeron, J. Berstel, and S. Brlek, published in
# Journal de théorie des nombres de Bordeaux, 6 no. 1 (1994), p. 21-38,
Line 1,761 ⟶ 2,187:
puts "A**$mn"; set countMult 0
print_matrix [apply $pow_mn $A] %6.3f
puts "$countMult matrix multiplies"</langsyntaxhighlight>
{{out}}
<pre>A**31415
Line 1,793 ⟶ 2,219:
{{libheader|Wren-fmt}}
This is very slow (12 mins 50 secs) compared to Go (25 seconds) but, given the amount of calculation involved, not too bad for the Wren interpreter.
<langsyntaxhighlight ecmascriptlang="wren">import "./dynamic" for Struct
import "./fmt" for Fmt
 
var Save = Struct.create("Save", ["p", "i", "v"])
Line 2,150 ⟶ 2,576:
Fmt.print("A ^ $d = (A ^ $d) ^ $d:-\n", m*n, m, n)
var mx2 = pow.call(mxs[0], n, false)
print.call(mx2)</langsyntaxhighlight>
 
{{out}}
Line 2,215 ⟶ 2,641:
[ 0.000000 0.000000 0.000000 0.000000 0.000000 1.000000]
</pre>
 
 
{{omit from|Brlcad}}
Line 2,221 ⟶ 2,648:
{{omit from|Openscad}}
{{omit from|TPP}}
 
[[Category:Matrices]]
9,485

edits