2
0

spectralnorm.lua 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. -- Spectral norm benchmark from benchmarks game
  2. -- https://benchmarksgame-team.pages.debian.net/benchmarksgame/description/spectralnorm.html
  3. --
  4. -- Original C# code:
  5. -- https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/spectralnorm-csharpcore-1.html
  6. --
  7. -- Code by Hugo Gualandi. It is translated directly from the C# specification
  8. -- with the following main differences:
  9. -- - The A() function uses 1-based indexing instead of 0-based
  10. -- - The A() function multiplies by 0.5 instead of doing an integer division.
  11. -- According to my measurements, this is not a significant difference, and
  12. -- the multiplication by 0.5 has the advantage that it works on LuaJIT too.
  13. -- - Some of the "out" tables not initialized with zeroes.
  14. --
  15. -- Expected output (N = 5500):
  16. -- 1.274224153
  17. -- Return A[i][j], for the infinite matrix A
  18. --
  19. -- A = 1/1 1/2 1/4 ...
  20. -- 1/3 1/5 ... ...
  21. -- 1/6 ... ... ...
  22. -- ... ... ... ...
  23. local function A(i, j)
  24. local ij = i + j
  25. return 1.0 / ((ij-1) * (ij-2) * 0.5 + i)
  26. end
  27. -- Multiply vector v by matrix A
  28. local function MultiplyAv(N, v, out)
  29. for i = 1, N do
  30. local s = 0.0
  31. for j = 1, N do
  32. s = s + A(i,j) * v[j]
  33. end
  34. out[i] = s
  35. end
  36. end
  37. -- Multiply vector v by matrix A transposed
  38. local function MultiplyAtv(N, v, out)
  39. for i=1, N do
  40. local s = 0.0
  41. for j = 1, N do
  42. s = s + A(j,i) * v[j]
  43. end
  44. out[i] = s
  45. end
  46. end
  47. -- Multiply vector v by matrix A and then by matrix A transposed
  48. local function MultiplyAtAv(N, v, out)
  49. local u = {}
  50. MultiplyAv(N, v, u)
  51. MultiplyAtv(N, u, out)
  52. end
  53. local function Approximate(N)
  54. -- Create unit vector
  55. local u = {}
  56. for i = 1, N do
  57. u[i] = 1.0
  58. end
  59. -- 20 steps of the power method
  60. local v = {}
  61. for _ = 1, 10 do
  62. MultiplyAtAv(N, u, v)
  63. MultiplyAtAv(N, v, u)
  64. end
  65. local vBv = 0.0
  66. local vv = 0.0
  67. for i = 1, N do
  68. local ui = u[i]
  69. local vi = v[i]
  70. vBv = vBv + ui*vi
  71. vv = vv + vi*vi
  72. end
  73. return math.sqrt(vBv/vv)
  74. end
  75. return function(N)
  76. N = N or 5500
  77. local res = Approximate(N)
  78. print(string.format("%0.9f", res))
  79. end