replace quicksort with blocksort

closes #657
This commit is contained in:
Andrew Kelley 2017-12-14 19:41:35 -05:00
parent c9e01412a4
commit 75ecfdf66d
4 changed files with 1102 additions and 63 deletions

View File

@ -174,12 +174,6 @@ test "math" {
} }
pub const Cmp = enum {
Less,
Equal,
Greater,
};
pub fn min(x: var, y: var) -> @typeOf(x + y) { pub fn min(x: var, y: var) -> @typeOf(x + y) {
if (x < y) x else y if (x < y) x else y
} }
@ -522,3 +516,28 @@ pub fn cast(comptime T: type, x: var) -> %T {
return T(x); return T(x);
} }
} }
pub fn floorPowerOfTwo(comptime T: type, value: T) -> T {
var x = value;
comptime var i = 1;
inline while(T.bit_count > i) : (i *= 2) {
x |= (x >> i);
}
return x - (x >> 1);
}
test "math.floorPowerOfTwo" {
testFloorPowerOfTwo();
comptime testFloorPowerOfTwo();
}
fn testFloorPowerOfTwo() {
assert(floorPowerOfTwo(u32, 63) == 32);
assert(floorPowerOfTwo(u32, 64) == 64);
assert(floorPowerOfTwo(u32, 65) == 64);
assert(floorPowerOfTwo(u4, 7) == 4);
assert(floorPowerOfTwo(u4, 8) == 8);
assert(floorPowerOfTwo(u4, 9) == 8);
}

View File

@ -7,12 +7,34 @@
const math = @import("index.zig"); const math = @import("index.zig");
const assert = @import("../debug.zig").assert; const assert = @import("../debug.zig").assert;
const builtin = @import("builtin");
const TypeId = builtin.TypeId;
pub fn sqrt(x: var) -> @typeOf(x) { pub fn sqrt(x: var) -> (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typeOf(x).bit_count / 2) else @typeOf(x)) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { switch (@typeId(T)) {
f32 => @inlineCall(sqrt32, x), TypeId.FloatLiteral => {
f64 => @inlineCall(sqrt64, x), return T(sqrt64(x))
},
TypeId.Float => {
return switch (T) {
f32 => sqrt32(x),
f64 => sqrt64(x),
else => @compileError("sqrt not implemented for " ++ @typeName(T)),
};
},
TypeId.IntLiteral => comptime {
if (x > @maxValue(u128)) {
@compileError("sqrt not implemented for comptime_int greater than 128 bits");
}
if (x < 0) {
@compileError("sqrt on negative number");
}
return T(sqrt_int(u128, x));
},
TypeId.Int => {
return sqrt_int(T, x);
},
else => @compileError("sqrt not implemented for " ++ @typeName(T)), else => @compileError("sqrt not implemented for " ++ @typeName(T)),
} }
} }
@ -274,3 +296,35 @@ test "math.sqrt64.special" {
assert(math.isNan(sqrt64(-1.0))); assert(math.isNan(sqrt64(-1.0)));
assert(math.isNan(sqrt64(math.nan(f64)))); assert(math.isNan(sqrt64(math.nan(f64))));
} }
fn sqrt_int(comptime T: type, value: T) -> @IntType(false, T.bit_count / 2) {
var op = value;
var res: T = 0;
var one: T = 1 << (T.bit_count - 2);
// "one" starts at the highest power of four <= than the argument.
while (one > op) {
one >>= 2;
}
while (one != 0) {
if (op >= res + one) {
op -= res + one;
res += 2 * one;
}
res >>= 1;
one >>= 2;
}
const ResultType = @IntType(false, T.bit_count / 2);
return ResultType(res);
}
test "math.sqrt_int" {
assert(sqrt_int(u32, 3) == 1);
assert(sqrt_int(u32, 4) == 2);
assert(sqrt_int(u32, 5) == 2);
assert(sqrt_int(u32, 8) == 2);
assert(sqrt_int(u32, 9) == 3);
assert(sqrt_int(u32, 10) == 3);
}

View File

@ -527,3 +527,40 @@ pub fn max(comptime T: type, slice: []const T) -> T {
test "mem.max" { test "mem.max" {
assert(max(u8, "abcdefg") == 'g'); assert(max(u8, "abcdefg") == 'g');
} }
pub fn swap(comptime T: type, a: &T, b: &T) {
const tmp = *a;
*a = *b;
*b = tmp;
}
/// In-place order reversal of a slice
pub fn reverse(comptime T: type, items: []T) {
var i: usize = 0;
const end = items.len / 2;
while (i < end) : (i += 1) {
swap(T, &items[i], &items[items.len - i - 1]);
}
}
test "std.mem.reverse" {
var arr = []i32{ 5, 3, 1, 2, 4 };
reverse(i32, arr[0..]);
assert(eql(i32, arr, []i32{ 4, 2, 1, 3, 5 }))
}
/// In-place rotation of the values in an array ([0 1 2 3] becomes [1 2 3 0] if we rotate by 1)
/// Assumes 0 <= amount <= items.len
pub fn rotate(comptime T: type, items: []T, amount: usize) {
reverse(T, items[0..amount]);
reverse(T, items[amount..]);
reverse(T, items);
}
test "std.mem.rotate" {
var arr = []i32{ 5, 3, 1, 2, 4 };
rotate(i32, arr[0..], 2);
assert(eql(i32, arr, []i32{ 1, 2, 4, 5, 3 }))
}

File diff suppressed because it is too large Load Diff