1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- -- Spectral norm benchmark from benchmarks game
- -- https://benchmarksgame-team.pages.debian.net/benchmarksgame/description/spectralnorm.html
- --
- -- Original C# code:
- -- https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/spectralnorm-csharpcore-1.html
- --
- -- Code by Hugo Gualandi. It is translated directly from the C# specification
- -- with the following main differences:
- -- - The A() function uses 1-based indexing instead of 0-based
- -- - The A() function multiplies by 0.5 instead of doing an integer division.
- -- According to my measurements, this is not a significant difference, and
- -- the multiplication by 0.5 has the advantage that it works on LuaJIT too.
- -- - Some of the "out" tables not initialized with zeroes.
- --
- -- Expected output (N = 5500):
- -- 1.274224153
- -- Return A[i][j], for the infinite matrix A
- --
- -- A = 1/1 1/2 1/4 ...
- -- 1/3 1/5 ... ...
- -- 1/6 ... ... ...
- -- ... ... ... ...
- local function A(i, j)
- local ij = i + j
- return 1.0 / ((ij-1) * (ij-2) * 0.5 + i)
- end
- -- Multiply vector v by matrix A
- local function MultiplyAv(N, v, out)
- for i = 1, N do
- local s = 0.0
- for j = 1, N do
- s = s + A(i,j) * v[j]
- end
- out[i] = s
- end
- end
- -- Multiply vector v by matrix A transposed
- local function MultiplyAtv(N, v, out)
- for i=1, N do
- local s = 0.0
- for j = 1, N do
- s = s + A(j,i) * v[j]
- end
- out[i] = s
- end
- end
- -- Multiply vector v by matrix A and then by matrix A transposed
- local function MultiplyAtAv(N, v, out)
- local u = {}
- MultiplyAv(N, v, u)
- MultiplyAtv(N, u, out)
- end
- local function Approximate(N)
- -- Create unit vector
- local u = {}
- for i = 1, N do
- u[i] = 1.0
- end
- -- 20 steps of the power method
- local v = {}
- for _ = 1, 10 do
- MultiplyAtAv(N, u, v)
- MultiplyAtAv(N, v, u)
- end
- local vBv = 0.0
- local vv = 0.0
- for i = 1, N do
- local ui = u[i]
- local vi = v[i]
- vBv = vBv + ui*vi
- vv = vv + vi*vi
- end
- return math.sqrt(vBv/vv)
- end
- return function(N)
- N = N or 5500
- local res = Approximate(N)
- print(string.format("%0.9f", res))
- end
|