list.lua 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. -- This code is derived from the SOM benchmarks, see AUTHORS.md file.
  2. --
  3. -- Copyright (c) 2016 Francois Perrad <[email protected]>
  4. --
  5. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  6. -- of this software and associated documentation files (the 'Software'), to deal
  7. -- in the Software without restriction, including without limitation the rights
  8. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. -- copies of the Software, and to permit persons to whom the Software is
  10. -- furnished to do so, subject to the following conditions:
  11. --
  12. -- The above copyright notice and this permission notice shall be included in
  13. -- all copies or substantial portions of the Software.
  14. --
  15. -- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. -- THE SOFTWARE.
  22. --[[
  23. The module 'bit' is available with:
  24. * LuaJIT
  25. * LuaBitOp extension which is available for:
  26. * Lua 5.1
  27. * Lua 5.2
  28. The module 'bit32' is available with:
  29. * Lua 5.2
  30. * Lua 5.3 when compiled with LUA_COMPAT_5_2
  31. The bitwise operators are added to Lua 5.3 as new lexemes (there causes
  32. lexical error in older version)
  33. --]]
  34. local band, bxor, rshift
  35. if _VERSION < 'Lua 5.3' then
  36. local bit = bit32 or require'bit'
  37. band = bit.band
  38. bxor = bit.bxor
  39. rshift = bit.rshift
  40. else
  41. band = assert(load'--[[band]] return function (a, b) return a & b end')()
  42. bxor = assert(load'--[[bxor]] return function (a, b) return a ~ b end')()
  43. rshift = assert(load'--[[rshift]] return function (a, b) return a >> b end')()
  44. end
  45. local alloc_array
  46. local ok, table_new = pcall(require, 'table.new') -- LuaJIT 2.1 extension
  47. if ok then
  48. alloc_array = function (n)
  49. local t = table_new(n, 1)
  50. t.n = n
  51. return t
  52. end
  53. else
  54. alloc_array = function (n)
  55. local t = {}
  56. t.n = n
  57. return t
  58. end
  59. end
  60. local Vector = {_CLASS = 'Vector'} do
  61. local floor = math.floor
  62. function Vector.new (size)
  63. local obj = {
  64. storage = alloc_array(size or 50),
  65. first_idx = 1,
  66. last_idx = 1,
  67. }
  68. return setmetatable(obj, {__index = Vector})
  69. end
  70. function Vector.with (elem)
  71. local v = Vector.new(1)
  72. v:append(elem)
  73. return v
  74. end
  75. function Vector:at (idx)
  76. if idx > self.storage.n then
  77. return nil
  78. end
  79. return self.storage[idx]
  80. end
  81. function Vector:at_put (idx, val)
  82. if idx > self.storage.n then
  83. local new_n = self.storage.n
  84. while idx > new_n do
  85. new_n = new_n * 2
  86. end
  87. local new_storage = alloc_array(new_n)
  88. for i = 1, self.storage.n do
  89. new_storage[i] = self.storage[i]
  90. end
  91. self.storage = new_storage
  92. end
  93. self.storage[idx] = val
  94. if self.last_idx < idx + 1 then
  95. self.last_idx = idx + 1
  96. end
  97. end
  98. function Vector:append (elem)
  99. if self.last_idx > self.storage.n then
  100. -- Need to expand capacity first
  101. local new_storage = alloc_array(2 * self.storage.n)
  102. for i = 1, self.storage.n do
  103. new_storage[i] = self.storage[i]
  104. end
  105. self.storage = new_storage
  106. end
  107. self.storage[self.last_idx] = elem
  108. self.last_idx = self.last_idx + 1
  109. end
  110. function Vector:is_empty ()
  111. return self.last_idx == self.first_idx
  112. end
  113. function Vector:each (fn)
  114. for i = self.first_idx, self.last_idx - 1 do
  115. fn(self.storage[i])
  116. end
  117. end
  118. function Vector:has_some (fn)
  119. for i = self.first_idx, self.last_idx - 1 do
  120. if fn(self.storage[i]) then
  121. return true
  122. end
  123. end
  124. return false
  125. end
  126. function Vector:get_one (fn)
  127. for i = self.first_idx, self.last_idx - 1 do
  128. local e = self.storage[i]
  129. if fn(e) then
  130. return e
  131. end
  132. end
  133. return nil
  134. end
  135. function Vector:remove_first ()
  136. if self:is_empty() then
  137. return nil
  138. end
  139. self.first_idx = self.first_idx + 1
  140. return self.storage[self.first_idx - 1]
  141. end
  142. function Vector:remove (obj)
  143. local new_array = alloc_array(self:capacity())
  144. local new_last = 1
  145. local found = false
  146. self:each(function (it)
  147. if it == obj then
  148. found = true
  149. else
  150. new_array[new_last] = it
  151. new_last = new_last + 1
  152. end
  153. end)
  154. self.storage = new_array
  155. self.last_idx = new_last
  156. self.first_idx = 1
  157. return found
  158. end
  159. function Vector:remove_all ()
  160. self.first_idx = 1
  161. self.last_idx = 1
  162. self.storage = alloc_array(self:capacity())
  163. end
  164. function Vector:size ()
  165. return self.last_idx - self.first_idx
  166. end
  167. function Vector:capacity ()
  168. return self.storage.n
  169. end
  170. function Vector:sort (fn)
  171. -- Make the argument, block, be the criterion for ordering elements of
  172. -- the receiver.
  173. -- Sort blocks with side effects may not work right.
  174. if self:size() > 0 then
  175. self:sort_range(self.first_idx, self.last_idx - 1, fn)
  176. end
  177. end
  178. function Vector:sort_range (i, j, fn)
  179. assert(fn)
  180. -- The prefix d means the data at that index.
  181. local n = j + 1 - i
  182. if n <= 1 then
  183. -- Nothing to sort
  184. return
  185. end
  186. local storage = self.storage
  187. -- Sort di, dj
  188. local di = storage[i]
  189. local dj = storage[j]
  190. -- i.e., should di precede dj?
  191. if not fn(di, dj) then
  192. local tmp = storage[i]
  193. storage[i] = storage[j]
  194. storage[j] = tmp
  195. local tt = di
  196. di = dj
  197. dj = tt
  198. end
  199. -- NOTE: For DeltaBlue, this is never reached.
  200. if n > 2 then -- More than two elements.
  201. local ij = floor((i + j) / 2) -- ij is the midpoint of i and j.
  202. local dij = storage[ij] -- Sort di,dij,dj. Make dij be their median.
  203. if fn(di, dij) then -- i.e. should di precede dij?
  204. if not fn(dij, dj) then -- i.e., should dij precede dj?
  205. local tmp = storage[j]
  206. storage[j] = storage[ij]
  207. storage[ij] = tmp
  208. dij = dj
  209. end
  210. else -- i.e. di should come after dij
  211. local tmp = storage[i]
  212. storage[i] = storage[ij]
  213. storage[ij] = tmp
  214. dij = di
  215. end
  216. if n > 3 then -- More than three elements.
  217. -- Find k>i and l<j such that dk,dij,dl are in reverse order.
  218. -- Swap k and l. Repeat this procedure until k and l pass each other.
  219. local k = i
  220. local l = j - 1
  221. while true do
  222. -- i.e. while dl succeeds dij
  223. while k <= l and fn(dij, storage[l]) do
  224. l = l - 1
  225. end
  226. k = k + 1
  227. -- i.e. while dij succeeds dk
  228. while k <= l and fn(storage[k], dij) do
  229. k = k + 1
  230. end
  231. if k > l then
  232. break
  233. end
  234. local tmp = storage[k]
  235. storage[k] = storage[l]
  236. storage[l] = tmp
  237. end
  238. -- Now l < k (either 1 or 2 less), and di through dl are all
  239. -- less than or equal to dk through dj. Sort those two segments.
  240. self:sort_range(i, l, fn)
  241. self:sort_range(k, j, fn)
  242. end
  243. end
  244. end
  245. end -- class Vector
  246. local Set = {_CLASS = 'Set'} do
  247. local INITIAL_SIZE = 10
  248. function Set.new (size)
  249. local obj = {
  250. items = Vector.new(size or INITIAL_SIZE)
  251. }
  252. return setmetatable(obj, {__index = Set})
  253. end
  254. function Set:size ()
  255. return self.items:size()
  256. end
  257. function Set:each (fn)
  258. self.items:each(fn)
  259. end
  260. function Set:has_some (fn)
  261. return self.items:has_some(fn)
  262. end
  263. function Set:get_one (fn)
  264. return self.items:get_one(fn)
  265. end
  266. function Set:add (obj)
  267. if not self:contains(obj) then
  268. self.items:append(obj)
  269. end
  270. end
  271. function Set:remove_all ()
  272. self.items:remove_all()
  273. end
  274. function Set:collect (fn)
  275. local coll = Vector.new()
  276. self:each(function (it)
  277. coll:append(fn(it))
  278. end)
  279. return coll
  280. end
  281. function Set:contains (obj)
  282. return self:has_some(function (it) return it == obj end)
  283. end
  284. end -- class Set
  285. local IdentitySet = {_CLASS = 'IdentitySet'} do
  286. setmetatable(IdentitySet, {__index = Set})
  287. function IdentitySet.new (size)
  288. local obj = Set.new(size)
  289. return setmetatable(obj, {__index = IdentitySet})
  290. end
  291. function IdentitySet:contains (obj)
  292. return self:has_some(function (it) return it == obj end)
  293. end
  294. end -- class IdentitySet
  295. local Entry = {_CLASS = 'Entry'} do
  296. function Entry.new (hash, key, value, next)
  297. local obj = {
  298. hash = hash,
  299. key = key,
  300. value = value,
  301. next = next,
  302. }
  303. return setmetatable(obj, {__index = Entry})
  304. end
  305. function Entry:match (hash, key)
  306. return self.hash == hash and self.key == key
  307. end
  308. end -- class Entry
  309. local Dictionary = {_CLASS = 'Dictionary'} do
  310. local INITIAL_CAPACITY = 16
  311. function Dictionary.new (size)
  312. local obj = {
  313. buckets = alloc_array(size or INITIAL_CAPACITY),
  314. size = 0,
  315. }
  316. return setmetatable(obj, {__index = Dictionary})
  317. end
  318. function Dictionary:hash (key)
  319. if not key then
  320. return 0
  321. end
  322. local hash = key:custom_hash()
  323. return bxor(hash, rshift(hash, 16))
  324. end
  325. function Dictionary:is_empty ()
  326. return self.size == 0
  327. end
  328. function Dictionary:get_bucket_idx (hash)
  329. return band(self.buckets.n - 1, hash) + 1
  330. end
  331. function Dictionary:get_bucket (hash)
  332. return self.buckets[self:get_bucket_idx(hash)]
  333. end
  334. function Dictionary:at (key)
  335. local hash = self:hash(key)
  336. local e = self:get_bucket(hash)
  337. while e do
  338. if e:match(hash, key) then
  339. return e.value
  340. end
  341. e = e.next
  342. end
  343. return nil
  344. end
  345. function Dictionary:contains_key (key)
  346. local hash = self:hash(key)
  347. local e = self:get_bucket(hash)
  348. while e do
  349. if e.match(hash, key) then
  350. return true
  351. end
  352. e = e.next
  353. end
  354. return false
  355. end
  356. function Dictionary:at_put (key, value)
  357. local hash = self:hash(key)
  358. local i = self:get_bucket_idx(hash)
  359. local current = self.buckets[i]
  360. if not current then
  361. self.buckets[i] = self:new_entry(key, value, hash)
  362. self.size = self.size + 1
  363. else
  364. self:insert_bucket_entry(key, value, hash, current)
  365. end
  366. if self.size > self.buckets.n then
  367. self:resize()
  368. end
  369. end
  370. function Dictionary:new_entry (key, value, hash)
  371. return Entry.new(hash, key, value, nil)
  372. end
  373. function Dictionary:insert_bucket_entry (key, value, hash, head)
  374. local current = head
  375. while true do
  376. if current:match(hash, key) then
  377. current.value = value
  378. return
  379. end
  380. if not current.next then
  381. self.size = self.size + 1
  382. current.next = self:new_entry(key, value, hash)
  383. return
  384. end
  385. current = current.next
  386. end
  387. end
  388. function Dictionary:resize ()
  389. local old_storage = self.buckets
  390. self.buckets = alloc_array(old_storage.n * 2)
  391. self:transfer_entries(old_storage)
  392. end
  393. function Dictionary:transfer_entries (old_storage)
  394. local buckets = self.buckets
  395. for i = 1, old_storage.n do
  396. local current = old_storage[i]
  397. if current then
  398. old_storage[i] = nil
  399. if not current.next then
  400. local hash = band(current.hash, buckets.n - 1) + 1
  401. buckets[hash] = current
  402. else
  403. self:split_bucket(old_storage, i, current)
  404. end
  405. end
  406. end
  407. end
  408. function Dictionary:split_bucket (old_storage, i, head)
  409. local lo_head, lo_tail = nil, nil
  410. local hi_head, hi_tail = nil, nil
  411. local current = head
  412. while current do
  413. if band(current.hash, old_storage.n) == 0 then
  414. if not lo_tail then
  415. lo_head = current
  416. else
  417. lo_tail.next = current
  418. end
  419. lo_tail = current
  420. else
  421. if not hi_tail then
  422. hi_head = current
  423. else
  424. hi_tail.next = current
  425. end
  426. hi_tail = current
  427. end
  428. current = current.next
  429. end
  430. if lo_tail then
  431. lo_tail.next = nil
  432. self.buckets[i] = lo_head
  433. end
  434. if hi_tail then
  435. hi_tail.next = nil
  436. self.buckets[i + old_storage.n] = hi_head
  437. end
  438. end
  439. function Dictionary:remove_all ()
  440. self.buckets = alloc_array(self.buckets.n)
  441. self.size = 0
  442. end
  443. function Dictionary:keys ()
  444. local keys = Vector.new(self.size)
  445. local buckets = self.buckets
  446. for i = 1, buckets.n do
  447. local current = buckets[i]
  448. while current do
  449. keys:append(current.key)
  450. current = current.next
  451. end
  452. end
  453. return keys
  454. end
  455. function Dictionary:values ()
  456. local vals = Vector.new(self.size)
  457. local buckets = self.buckets
  458. for i = 1, buckets.n do
  459. local current = buckets[i]
  460. while current do
  461. vals:append(current.value)
  462. current = current.next
  463. end
  464. end
  465. return vals
  466. end
  467. end -- class Dictionary
  468. local IdEntry = {_CLASS = 'IdEntry'} do
  469. setmetatable(IdEntry, {__index = Entry})
  470. function IdEntry.new (hash, key, value, next)
  471. local obj = Entry.new (hash, key, value, next)
  472. return setmetatable(obj, {__index = IdEntry})
  473. end
  474. function IdEntry:match (hash, key)
  475. return self.hash == hash and self.key == key
  476. end
  477. end -- class IdEntry
  478. local IdentityDictionary = {_CLASS = 'IdentityDictionary'} do
  479. setmetatable(IdentityDictionary, {__index = Dictionary})
  480. function IdentityDictionary.new (size)
  481. local obj = Dictionary.new (size)
  482. return setmetatable(obj, {__index = Dictionary})
  483. end
  484. function IdentityDictionary:new_entry (key, value, hash)
  485. return IdEntry.new(hash, key, value, nil)
  486. end
  487. end -- class IdentityDictionary
  488. local Random = {_CLASS = 'Random'} do
  489. function Random.new ()
  490. local obj = {seed = 74755}
  491. return setmetatable(obj, {__index = Random})
  492. end
  493. function Random:next ()
  494. self.seed = band(((self.seed * 1309) + 13849), 65535);
  495. return self.seed;
  496. end
  497. end -- class Random
  498. ---------------------------------
  499. local benchmark = {} do
  500. function benchmark:inner_benchmark_loop (inner_iterations)
  501. for _ = 1, inner_iterations do
  502. if not self:verify_result(self:benchmark()) then
  503. return false
  504. end
  505. end
  506. return true
  507. end
  508. function benchmark:benchmark ()
  509. error 'subclass_responsibility'
  510. end
  511. function benchmark:verify_result ()
  512. error 'subclass_responsibility'
  513. end
  514. end
  515. ---------------------------------
  516. local Element = {_CLASS = 'Element'} do
  517. function Element.new (v)
  518. local obj = {val = v, next = nil}
  519. return setmetatable(obj, {__index = Element})
  520. end
  521. function Element:length ()
  522. if not self.next then
  523. return 1
  524. else
  525. return 1 + self.next:length()
  526. end
  527. end
  528. end -- class Element
  529. local list = {} do
  530. setmetatable(list, {__index = benchmark})
  531. function list:benchmark ()
  532. local result = self:tail(self:make_list(15),
  533. self:make_list(10),
  534. self:make_list(6))
  535. return result:length()
  536. end
  537. function list:make_list (length)
  538. if length == 0 then
  539. return nil
  540. else
  541. local e = Element.new(length)
  542. e.next = self:make_list(length - 1)
  543. return e
  544. end
  545. end
  546. function list:is_shorter_than (x, y)
  547. local x_tail, y_tail = x, y
  548. while y_tail do
  549. if not x_tail then
  550. return true
  551. end
  552. x_tail = x_tail.next
  553. y_tail = y_tail.next
  554. end
  555. return false
  556. end
  557. function list:tail (x, y, z)
  558. if self:is_shorter_than(y, x) then
  559. return self:tail(self:tail(x.next, y, z),
  560. self:tail(y.next, z, x),
  561. self:tail(z.next, x, y))
  562. else
  563. return z
  564. end
  565. end
  566. function list:verify_result (result)
  567. return 10 == result
  568. end
  569. end -- object list
  570. return function(N)
  571. list:inner_benchmark_loop(N)
  572. end