sort.lua 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. -- $Id: testes/sort.lua $
  2. -- See Copyright Notice in file lua.h
  3. print "testing (parts of) table library"
  4. local maxI = math.maxinteger
  5. local minI = math.mininteger
  6. local function checkerror (msg, f, ...)
  7. local s, err = pcall(f, ...)
  8. assert(not s and string.find(err, msg))
  9. end
  10. do print "testing 'table.create'"
  11. local N = 10000
  12. collectgarbage()
  13. local m = collectgarbage("count") * 1024
  14. local t = table.create(N)
  15. local memdiff = collectgarbage("count") * 1024 - m
  16. assert(memdiff > N * 4)
  17. for i = 1, 20 do
  18. assert(#t == i - 1)
  19. t[i] = 0
  20. end
  21. for i = 1, 20 do t[#t + 1] = i * 10 end
  22. assert(#t == 40 and t[39] == 190)
  23. assert(not T or T.querytab(t) == N)
  24. t = nil
  25. collectgarbage()
  26. m = collectgarbage("count") * 1024
  27. t = table.create(0, 1024)
  28. memdiff = collectgarbage("count") * 1024 - m
  29. assert(memdiff > 1024 * 12)
  30. assert(not T or select(2, T.querytab(t)) == 1024)
  31. local maxint1 = 1 << (string.packsize("i") * 8 - 1)
  32. checkerror("out of range", table.create, maxint1)
  33. checkerror("out of range", table.create, 0, maxint1)
  34. checkerror("table overflow", table.create, 0, maxint1 - 1)
  35. end
  36. print "testing unpack"
  37. local unpack = table.unpack
  38. checkerror("wrong number of arguments", table.insert, {}, 2, 3, 4)
  39. local x,y,z,a,n
  40. a = {}; local lim = _soft and 200 or 2000
  41. for i=1, lim do a[i]=i end
  42. assert(select(lim, unpack(a)) == lim and select('#', unpack(a)) == lim)
  43. x = unpack(a)
  44. assert(x == 1)
  45. x = {unpack(a)}
  46. assert(#x == lim and x[1] == 1 and x[lim] == lim)
  47. x = {unpack(a, lim-2)}
  48. assert(#x == 3 and x[1] == lim-2 and x[3] == lim)
  49. x = {unpack(a, 10, 6)}
  50. assert(next(x) == nil) -- no elements
  51. x = {unpack(a, 11, 10)}
  52. assert(next(x) == nil) -- no elements
  53. x,y = unpack(a, 10, 10)
  54. assert(x == 10 and y == nil)
  55. x,y,z = unpack(a, 10, 11)
  56. assert(x == 10 and y == 11 and z == nil)
  57. a,x = unpack{1}
  58. assert(a==1 and x==nil)
  59. a,x = unpack({1,2}, 1, 1)
  60. assert(a==1 and x==nil)
  61. do
  62. local maxi = (1 << 31) - 1 -- maximum value for an int (usually)
  63. local mini = -(1 << 31) -- minimum value for an int (usually)
  64. checkerror("too many results", unpack, {}, 0, maxi)
  65. checkerror("too many results", unpack, {}, 1, maxi)
  66. checkerror("too many results", unpack, {}, 0, maxI)
  67. checkerror("too many results", unpack, {}, 1, maxI)
  68. checkerror("too many results", unpack, {}, mini, maxi)
  69. checkerror("too many results", unpack, {}, -maxi, maxi)
  70. checkerror("too many results", unpack, {}, minI, maxI)
  71. unpack({}, maxi, 0)
  72. unpack({}, maxi, 1)
  73. unpack({}, maxI, minI)
  74. pcall(unpack, {}, 1, maxi + 1)
  75. local a, b = unpack({[maxi] = 20}, maxi, maxi)
  76. assert(a == 20 and b == nil)
  77. a, b = unpack({[maxi] = 20}, maxi - 1, maxi)
  78. assert(a == nil and b == 20)
  79. local t = {[maxI - 1] = 12, [maxI] = 23}
  80. a, b = unpack(t, maxI - 1, maxI); assert(a == 12 and b == 23)
  81. a, b = unpack(t, maxI, maxI); assert(a == 23 and b == nil)
  82. a, b = unpack(t, maxI, maxI - 1); assert(a == nil and b == nil)
  83. t = {[minI] = 12.3, [minI + 1] = 23.5}
  84. a, b = unpack(t, minI, minI + 1); assert(a == 12.3 and b == 23.5)
  85. a, b = unpack(t, minI, minI); assert(a == 12.3 and b == nil)
  86. a, b = unpack(t, minI + 1, minI); assert(a == nil and b == nil)
  87. end
  88. do -- length is not an integer
  89. local t = setmetatable({}, {__len = function () return 'abc' end})
  90. assert(#t == 'abc')
  91. checkerror("object length is not an integer", table.insert, t, 1)
  92. end
  93. print "testing pack"
  94. a = table.pack()
  95. assert(a[1] == undef and a.n == 0)
  96. a = table.pack(table)
  97. assert(a[1] == table and a.n == 1)
  98. a = table.pack(nil, nil, nil, nil)
  99. assert(a[1] == nil and a.n == 4)
  100. -- testing move
  101. do
  102. checkerror("table expected", table.move, 1, 2, 3, 4)
  103. local function eqT (a, b)
  104. for k, v in pairs(a) do assert(b[k] == v) end
  105. for k, v in pairs(b) do assert(a[k] == v) end
  106. end
  107. local a = table.move({10,20,30}, 1, 3, 2) -- move forward
  108. eqT(a, {10,10,20,30})
  109. -- move forward with overlap of 1
  110. a = table.move({10, 20, 30}, 1, 3, 3)
  111. eqT(a, {10, 20, 10, 20, 30})
  112. -- moving to the same table (not being explicit about it)
  113. a = {10, 20, 30, 40}
  114. table.move(a, 1, 4, 2, a)
  115. eqT(a, {10, 10, 20, 30, 40})
  116. a = table.move({10,20,30}, 2, 3, 1) -- move backward
  117. eqT(a, {20,30,30})
  118. a = {} -- move to new table
  119. assert(table.move({10,20,30}, 1, 3, 1, a) == a)
  120. eqT(a, {10,20,30})
  121. a = {}
  122. assert(table.move({10,20,30}, 1, 0, 3, a) == a) -- empty move (no move)
  123. eqT(a, {})
  124. a = table.move({10,20,30}, 1, 10, 1) -- move to the same place
  125. eqT(a, {10,20,30})
  126. -- moving on the fringes
  127. a = table.move({[maxI - 2] = 1, [maxI - 1] = 2, [maxI] = 3},
  128. maxI - 2, maxI, -10, {})
  129. eqT(a, {[-10] = 1, [-9] = 2, [-8] = 3})
  130. a = table.move({[minI] = 1, [minI + 1] = 2, [minI + 2] = 3},
  131. minI, minI + 2, -10, {})
  132. eqT(a, {[-10] = 1, [-9] = 2, [-8] = 3})
  133. a = table.move({45}, 1, 1, maxI)
  134. eqT(a, {45, [maxI] = 45})
  135. a = table.move({[maxI] = 100}, maxI, maxI, minI)
  136. eqT(a, {[minI] = 100, [maxI] = 100})
  137. a = table.move({[minI] = 100}, minI, minI, maxI)
  138. eqT(a, {[minI] = 100, [maxI] = 100})
  139. a = setmetatable({}, {
  140. __index = function (_,k) return k * 10 end,
  141. __newindex = error})
  142. local b = table.move(a, 1, 10, 3, {})
  143. eqT(a, {})
  144. eqT(b, {nil,nil,10,20,30,40,50,60,70,80,90,100})
  145. b = setmetatable({""}, {
  146. __index = error,
  147. __newindex = function (t,k,v)
  148. t[1] = string.format("%s(%d,%d)", t[1], k, v)
  149. end})
  150. table.move(a, 10, 13, 3, b)
  151. assert(b[1] == "(3,100)(4,110)(5,120)(6,130)")
  152. local stat, msg = pcall(table.move, b, 10, 13, 3, b)
  153. assert(not stat and msg == b)
  154. end
  155. do
  156. -- for very long moves, just check initial accesses and interrupt
  157. -- move with an error
  158. local function checkmove (f, e, t, x, y)
  159. local pos1, pos2
  160. local a = setmetatable({}, {
  161. __index = function (_,k) pos1 = k end,
  162. __newindex = function (_,k) pos2 = k; error() end, })
  163. local st, msg = pcall(table.move, a, f, e, t)
  164. assert(not st and pos1 == x and pos2 == y)
  165. end
  166. checkmove(1, maxI, 0, 1, 0)
  167. checkmove(0, maxI - 1, 1, maxI - 1, maxI)
  168. checkmove(minI, -2, -5, -2, maxI - 6)
  169. checkmove(minI + 1, -1, -2, -1, maxI - 3)
  170. checkmove(minI, -2, 0, minI, 0) -- non overlapping
  171. checkmove(minI + 1, -1, 1, minI + 1, 1) -- non overlapping
  172. end
  173. checkerror("too many", table.move, {}, 0, maxI, 1)
  174. checkerror("too many", table.move, {}, -1, maxI - 1, 1)
  175. checkerror("too many", table.move, {}, minI, -1, 1)
  176. checkerror("too many", table.move, {}, minI, maxI, 1)
  177. checkerror("wrap around", table.move, {}, 1, maxI, 2)
  178. checkerror("wrap around", table.move, {}, 1, 2, maxI)
  179. checkerror("wrap around", table.move, {}, minI, -2, 2)
  180. print"testing sort"
  181. -- strange lengths
  182. local a = setmetatable({}, {__len = function () return -1 end})
  183. assert(#a == -1)
  184. table.sort(a, error) -- should not compare anything
  185. a = setmetatable({}, {__len = function () return maxI end})
  186. checkerror("too big", table.sort, a)
  187. -- test checks for invalid order functions
  188. local function check (t)
  189. local function f(a, b) assert(a and b); return true end
  190. checkerror("invalid order function", table.sort, t, f)
  191. end
  192. check{1,2,3,4}
  193. check{1,2,3,4,5}
  194. check{1,2,3,4,5,6}
  195. function check (a, f)
  196. f = f or function (x,y) return x<y end;
  197. for n = #a, 2, -1 do
  198. assert(not f(a[n], a[n-1]))
  199. end
  200. end
  201. a = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
  202. "Oct", "Nov", "Dec"}
  203. table.sort(a)
  204. check(a)
  205. local function perm (s, n)
  206. n = n or #s
  207. if n == 1 then
  208. local t = {unpack(s)}
  209. table.sort(t)
  210. check(t)
  211. else
  212. for i = 1, n do
  213. s[i], s[n] = s[n], s[i]
  214. perm(s, n - 1)
  215. s[i], s[n] = s[n], s[i]
  216. end
  217. end
  218. end
  219. perm{}
  220. perm{1}
  221. perm{1,2}
  222. perm{1,2,3}
  223. perm{1,2,3,4}
  224. perm{2,2,3,4}
  225. perm{1,2,3,4,5}
  226. perm{1,2,3,3,5}
  227. perm{1,2,3,4,5,6}
  228. perm{2,2,3,3,5,6}
  229. local function timesort (a, n, func, msg, pre)
  230. local x = os.clock()
  231. table.sort(a, func)
  232. x = (os.clock() - x) * 1000
  233. pre = pre or ""
  234. print(string.format("%ssorting %d %s elements in %.2f msec.", pre, n, msg, x))
  235. check(a, func)
  236. end
  237. local limit = 50000
  238. if _soft then limit = 5000 end
  239. a = {}
  240. for i=1,limit do
  241. a[i] = math.random()
  242. end
  243. timesort(a, limit, nil, "random")
  244. timesort(a, limit, nil, "sorted", "re-")
  245. a = {}
  246. for i=1,limit do
  247. a[i] = math.random()
  248. end
  249. local x = os.clock(); local i = 0
  250. table.sort(a, function(x,y) i=i+1; return y<x end)
  251. x = (os.clock() - x) * 1000
  252. print(string.format("Invert-sorting other %d elements in %.2f msec., with %i comparisons",
  253. limit, x, i))
  254. check(a, function(x,y) return y<x end)
  255. table.sort{} -- empty array
  256. for i=1,limit do a[i] = false end
  257. timesort(a, limit, function(x,y) return nil end, "equal")
  258. for i,v in pairs(a) do assert(v == false) end
  259. AA = {"\xE1lo", "\0first :-)", "alo", "then this one", "45", "and a new"}
  260. table.sort(AA)
  261. check(AA)
  262. table.sort(AA, function (x, y)
  263. load(string.format("AA[%q] = ''", x), "")()
  264. collectgarbage()
  265. return x<y
  266. end)
  267. _G.AA = nil
  268. local tt = {__lt = function (a,b) return a.val < b.val end}
  269. a = {}
  270. for i=1,10 do a[i] = {val=math.random(100)}; setmetatable(a[i], tt); end
  271. table.sort(a)
  272. check(a, tt.__lt)
  273. check(a)
  274. print"OK"