diff --git a/tests/bench/rbmap.swift b/tests/bench/rbmap.swift new file mode 100644 index 0000000000..eb869423f6 --- /dev/null +++ b/tests/bench/rbmap.swift @@ -0,0 +1,128 @@ +enum Color { + case Red + case Black +} + +indirect enum Tree { + case Leaf + case Node(Color, Tree, UInt64, Bool, Tree) +} + +func balance1(_ kv : UInt64, _ vv : Bool, _ t : Tree, _ n : Tree) -> Tree { + switch n { + case let .Node(_, .Node(.Red, l, kx, vx, r1), ky, vy, r2): + return .Node(.Red, .Node(.Black, l, kx, vx, r1), ky, vy, .Node(.Black, r2, kv, vv, t)) + case let .Node(_, l1, ky, vy, .Node(.Red, l2, kx, vx, r)): + return .Node(.Red, .Node(.Black, l1, ky, vy, l2), kx, vx, .Node(.Black, r, kv, vv, t)) + case let .Node(_, l, ky, vy, r): + return .Node(.Black, .Node(.Red, l, ky, vy, r), kv, vv, t) + default: + return .Leaf + } +} + +func balance2(_ t : Tree, _ kv : UInt64, _ vv : Bool, _ n : Tree) -> Tree { + switch n { + case let .Node(_, .Node(.Red, l, kx1, vx1, r1), ky, vy, r2): + return .Node(.Red, .Node(.Black, t, kv, vv, l), kx1, vx1, .Node(.Black, r1, ky, vy, r2)) + case let .Node(_, l1, ky, vy, .Node(.Red, l2, kx2, vx2, r2)): + return .Node(.Red, .Node(.Black, t, kv, vv, l1), ky, vy, .Node(.Black, l2, kx2, vx2, r2)) + case let .Node (_, l, ky, vy, r): + return .Node(.Black, t, kv, vv, .Node(.Red, l, ky, vy, r)) + default: + return .Leaf + } +} + +func is_red (_ t : Tree) -> Bool { + switch t { + case .Node(.Red, _, _, _, _): + return true + default: + return false + } +} + +func ins(_ t : Tree, _ kx : UInt64, _ vx : Bool) -> Tree { + switch t { + case .Leaf: + return .Node(.Red, .Leaf, kx, vx, .Leaf) + case let .Node(.Red, a, ky, vy, b): + if kx < ky { + return .Node(.Red, ins(a, kx, vx), ky, vy, b) + } else if ky == kx { + return .Node(.Red, a, kx, vx, b) + } else { + return .Node(.Red, a, ky, vy, ins(b, kx, vx)) + } + case let .Node(.Black, a, ky, vy, b): + if kx < ky { + if is_red(a) { + return balance1(ky, vy, b, ins(a, kx, vx)) + } else { + return .Node(.Black, ins(a, kx, vx), ky, vy, b) + } + } else if kx == ky { + return .Node(.Black, a, kx, vx, b) + } else { + if is_red(b) { + return balance2(a, ky, vy, ins(b, kx, vx)) + } else { + return .Node(.Black, a, ky, vy, ins(b, kx, vx)) + } + } + } +} + +func set_black (_ n : Tree) -> Tree { + switch n { + case let .Node (_, l, k, v, r): + return .Node (.Black, l, k, v, r) + default: + return n + } +} + +func insert (_ t : Tree, _ k : UInt64, _ v : Bool) -> Tree { + if is_red(t) { + return set_black(ins(t, k, v)) + } else { + return ins(t, k, v) + } +} + +func fold (_ f : (_ k : UInt64, _ v : Bool, _ d : UInt64) -> UInt64, _ n : Tree, _ d : UInt64) -> UInt64 { + switch n { + case .Leaf: + return d + case let .Node(_, l, k, v, r): + return fold(f, r, f(k, v, fold(f, l, d))) + } +} + +func mk_map (_ n : UInt64) -> Tree { + var i = n + var m : Tree = .Leaf + while i > 0 { + i = i - 1 + m = insert(m, i, (i%10 == 0)) + } + return m +} + +func aux (_ k : UInt64, _ v : Bool, _ r : UInt64) -> UInt64 { + if v { + return r + 1 + } else { + return r + } +} + +if CommandLine.arguments.count != 2 { + print("Incorrect number of arguments") +} else { + let num = UInt64(CommandLine.arguments[1]) + let m = mk_map(num!) + let v = fold(aux, m, 0) + print(v) +}