| 1 | (******************************************************************************* |
|---|
| 2 | Copyright 2009 Sun Microsystems, Inc., |
|---|
| 3 | 4150 Network Circle, Santa Clara, California 95054, U.S.A. |
|---|
| 4 | All rights reserved. |
|---|
| 5 | |
|---|
| 6 | U.S. Government Rights - Commercial software. |
|---|
| 7 | Government users are subject to the Sun Microsystems, Inc. standard |
|---|
| 8 | license agreement and applicable provisions of the FAR and its supplements. |
|---|
| 9 | |
|---|
| 10 | Use is subject to license terms. |
|---|
| 11 | |
|---|
| 12 | This distribution may include materials developed by third parties. |
|---|
| 13 | |
|---|
| 14 | Sun, Sun Microsystems, the Sun logo and Java are trademarks or registered |
|---|
| 15 | trademarks of Sun Microsystems, Inc. in the U.S. and other countries. |
|---|
| 16 | ******************************************************************************) |
|---|
| 17 | |
|---|
| 18 | component HeapShakedown |
|---|
| 19 | import Heap.{...} |
|---|
| 20 | import List.{...} |
|---|
| 21 | export Executable |
|---|
| 22 | |
|---|
| 23 | appending[\T\](xs: List[\T\]...): List[\T\] = |
|---|
| 24 | xs.generate[\List[\T\]\](Concat[\T\], identity[\List[\T\]\]) |
|---|
| 25 | |
|---|
| 26 | showData(headers: List[\String\], data:List[\List[\RR64\]\]): () = do |
|---|
| 27 | n = |headers| |
|---|
| 28 | for datum <- data do |
|---|
| 29 | sz = |datum| |
|---|
| 30 | if (sz < n) then |
|---|
| 31 | fail("FAIL: only " sz " data points, expected " n) |
|---|
| 32 | elif (n < sz) then |
|---|
| 33 | println("FAIL: too many! Expected " n " data points, got " sz) |
|---|
| 34 | println(" and will discard the extras.") |
|---|
| 35 | end |
|---|
| 36 | end |
|---|
| 37 | println( |
|---|
| 38 | BIG ||[(i,l) <- headers.indexValuePairs] |
|---|
| 39 | //l (BIG ||[row <- data] "," row[i])) |
|---|
| 40 | end |
|---|
| 41 | |
|---|
| 42 | checkFull(h0: Heap[\ZZ32,ZZ32\], n:ZZ32): () = |
|---|
| 43 | if h0.isEmpty then |
|---|
| 44 | if NOT (n=0) then fail("empty with n=/=0") end |
|---|
| 45 | else |
|---|
| 46 | flags : Array[\Boolean,ZZ32\] = array[\Boolean\](n).fill(false) |
|---|
| 47 | (k:ZZ32, v:ZZ32, h:Heap[\ZZ32,ZZ32\]) := h0.extractMinimum().get |
|---|
| 48 | k_prev : ZZ32 := k |
|---|
| 49 | expected: ZZ32 := 1 |
|---|
| 50 | flags[v] := true |
|---|
| 51 | failed : Boolean := false |
|---|
| 52 | while NOT h.isEmpty AND expected <= n do |
|---|
| 53 | (k,v,h) := h.extractMinimum().get |
|---|
| 54 | if k < k_prev then |
|---|
| 55 | println("FAIL: Keys " k_prev " and " k " out of order.") |
|---|
| 56 | failed := true |
|---|
| 57 | end |
|---|
| 58 | if flags[v] then |
|---|
| 59 | println("FAIL: Duplicate value " v " found.") |
|---|
| 60 | failed := true |
|---|
| 61 | end |
|---|
| 62 | (k_prev, flags[v]) := (k,true) |
|---|
| 63 | expected += 1 |
|---|
| 64 | end |
|---|
| 65 | if NOT h.isEmpty then |
|---|
| 66 | println("FAIL: Too many elements.") |
|---|
| 67 | failed := true |
|---|
| 68 | elif expected < n then |
|---|
| 69 | println("FAIL: Not enough elements.") |
|---|
| 70 | failed := true |
|---|
| 71 | end |
|---|
| 72 | if failed then |
|---|
| 73 | h := h0 |
|---|
| 74 | expected := 0 |
|---|
| 75 | println(h.asDebugString) |
|---|
| 76 | while NOT h.isEmpty AND expected <= n do |
|---|
| 77 | (k,v,h) := h.extractMinimum().get |
|---|
| 78 | println(expected ": min = (" k "," v ")") |
|---|
| 79 | println(h.asDebugString) |
|---|
| 80 | expected += 1 |
|---|
| 81 | end |
|---|
| 82 | end |
|---|
| 83 | end |
|---|
| 84 | |
|---|
| 85 | object TestReduction extends AssociativeReduction[\(ZZ32,ZZ32,ZZ32)\] |
|---|
| 86 | getter asString(): String = "HeapShakedown.TestReduction" |
|---|
| 87 | simpleJoin(a:Any, b:Any): Any = fail("Bogus non-tuple data in TestReduction") |
|---|
| 88 | simpleJoin(a:(ZZ32,ZZ32,ZZ32), b:(ZZ32,ZZ32,ZZ32)):(ZZ32,ZZ32,ZZ32) = do |
|---|
| 89 | (mn_a,sz_a,mx_a) = a |
|---|
| 90 | (mn_b,sz_b,mx_b) = b |
|---|
| 91 | assert(mx_a <= mn_b, "Left max " mx_a " larger than right min " mn_b) |
|---|
| 92 | (mn_a,sz_a+sz_b,mx_a) |
|---|
| 93 | end |
|---|
| 94 | end |
|---|
| 95 | |
|---|
| 96 | checkGen(h:Heap[\ZZ32,ZZ32\], n:ZZ32): () = do |
|---|
| 97 | flags : Array[\Boolean,ZZ32\] = array[\Boolean\](n).fill(false) |
|---|
| 98 | sing(k:ZZ32,v:ZZ32): Maybe[\(ZZ32,ZZ32,ZZ32)\] = do |
|---|
| 99 | dup = atomic do d = flags[v]; flags[v] := true; d end |
|---|
| 100 | if dup then |
|---|
| 101 | println("FAIL: dup of " k "," v) |
|---|
| 102 | end |
|---|
| 103 | Just[\(ZZ32,ZZ32,ZZ32)\](k,1,k) |
|---|
| 104 | end |
|---|
| 105 | (mn,sz,mx) = h.generate[\AnyMaybe\](TestReduction, sing).getDefault(0,0,0) |
|---|
| 106 | assert(n,sz," size versus computed size") |
|---|
| 107 | if (sz > 0) then |
|---|
| 108 | (mn_k, mn_v) = h.minimum.get |
|---|
| 109 | assert(mn,mn_k," computed minimum versus .minimum") |
|---|
| 110 | end |
|---|
| 111 | end |
|---|
| 112 | |
|---|
| 113 | timeDiffMS(start:ZZ64, fin:ZZ64): RR64 = |
|---|
| 114 | (fin-start) / 10^6 |
|---|
| 115 | |
|---|
| 116 | lg(n:ZZ32):ZZ32 = |
|---|
| 117 | if n <= 1 then 0 |
|---|
| 118 | else 1 + lg(n DIV 2) end |
|---|
| 119 | |
|---|
| 120 | spread(n:ZZ32):(ZZ32,ZZ32) = do |
|---|
| 121 | c1 : ZZ32 = -761155213 |
|---|
| 122 | c2 : ZZ32 = -412293886 |
|---|
| 123 | (c1 n + c2, n) |
|---|
| 124 | end |
|---|
| 125 | |
|---|
| 126 | timeHdr(desc:String): List[\String\] = do |
|---|
| 127 | print(".") |
|---|
| 128 | res : List[\String\] = <|[\String\] desc, desc "/n", desc "/nlgn" |> |
|---|
| 129 | res |
|---|
| 130 | end |
|---|
| 131 | |
|---|
| 132 | timeDump(s,slgs,t): List[\RR64\] = do |
|---|
| 133 | print(".") |
|---|
| 134 | <| t asif RR64, t/s, t/slgs |> |
|---|
| 135 | end |
|---|
| 136 | |
|---|
| 137 | testHeap(s:ZZ32,c:Generator[\(ZZ32,ZZ32)\]->Heap[\ZZ32,ZZ32\], |
|---|
| 138 | g:Generator[\(ZZ32,ZZ32)\]):() = do |
|---|
| 139 | slgs = s lg s |
|---|
| 140 | print(".") |
|---|
| 141 | startTime = nanoTime() |
|---|
| 142 | h = c(g) |
|---|
| 143 | build = nanoTime() |
|---|
| 144 | checkFull(h,s) |
|---|
| 145 | consume=nanoTime() |
|---|
| 146 | checkGen(h,s) |
|---|
| 147 | gen=nanoTime() |
|---|
| 148 | print(".") |
|---|
| 149 | appending[\RR64\]( |
|---|
| 150 | timeDump(s,slgs,timeDiffMS(startTime,build)), |
|---|
| 151 | timeDump(s,slgs,timeDiffMS(build,consume)), |
|---|
| 152 | timeDump(s,slgs,timeDiffMS(consume,gen))) |
|---|
| 153 | end |
|---|
| 154 | |
|---|
| 155 | run():() = do |
|---|
| 156 | samples: List[\ZZ32\] = <|0 asif ZZ32,1,2,4,16,64,256,1024,4096|> |
|---|
| 157 | headers: List[\String\] = appending[\String\]( |
|---|
| 158 | <|[\String\]"" "n","n lg n"|>, |
|---|
| 159 | timeHdr("lbuild"), |
|---|
| 160 | timeHdr("lconsume"), |
|---|
| 161 | timeHdr("lgen"), |
|---|
| 162 | timeHdr("ulbuild"), |
|---|
| 163 | timeHdr("ulconsume"), |
|---|
| 164 | timeHdr("ulgen"), |
|---|
| 165 | timeHdr("build"), |
|---|
| 166 | timeHdr("consume"), |
|---|
| 167 | timeHdr("gen"), |
|---|
| 168 | timeHdr("ubuild"), |
|---|
| 169 | timeHdr("uconsume"), |
|---|
| 170 | timeHdr("ugen") ) |
|---|
| 171 | table: List[\List[\RR64\]\] = samples.generate[\List[\List[\RR64\]\]\]( |
|---|
| 172 | Concat[\List[\RR64\]\], |
|---|
| 173 | fn (s: ZZ32): List[\List[\RR64\]\] => |
|---|
| 174 | singleton[\List[\RR64\]\]( |
|---|
| 175 | appending[\RR64\]( |
|---|
| 176 | <| 1.0 s, s lg s |>, |
|---|
| 177 | testHeap(s,lazy[\ZZ32,ZZ32\],(0#s).indexValuePairs), |
|---|
| 178 | testHeap(s,lazy[\ZZ32,ZZ32\],(0#s).map[\(ZZ32,ZZ32)\](spread)), |
|---|
| 179 | testHeap(s,pairing[\ZZ32,ZZ32\],(0#s).indexValuePairs), |
|---|
| 180 | testHeap(s,pairing[\ZZ32,ZZ32\],(0#s).map[\(ZZ32,ZZ32)\](spread)) |
|---|
| 181 | ))) |
|---|
| 182 | showData(headers,table) |
|---|
| 183 | end |
|---|
| 184 | |
|---|
| 185 | end |
|---|