Skip to content

Commit

Permalink
replace quicksort with blocksort
Browse files Browse the repository at this point in the history
closes #657
  • Loading branch information
andrewrk committed Dec 15, 2017
1 parent c9e0141 commit 75ecfdf
Show file tree
Hide file tree
Showing 4 changed files with 1,099 additions and 60 deletions.
31 changes: 25 additions & 6 deletions std/math/index.zig
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,6 @@ test "math" {
}


pub const Cmp = enum {
Less,
Equal,
Greater,
};

pub fn min(x: var, y: var) -> @typeOf(x + y) {
if (x < y) x else y
}
Expand Down Expand Up @@ -522,3 +516,28 @@ pub fn cast(comptime T: type, x: var) -> %T {
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);
}
62 changes: 58 additions & 4 deletions std/math/sqrt.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,34 @@

const math = @import("index.zig");
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);
switch (T) {
f32 => @inlineCall(sqrt32, x),
f64 => @inlineCall(sqrt64, x),
switch (@typeId(T)) {
TypeId.FloatLiteral => {
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)),
}
}
Expand Down Expand Up @@ -274,3 +296,35 @@ test "math.sqrt64.special" {
assert(math.isNan(sqrt64(-1.0)));
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);
}
37 changes: 37 additions & 0 deletions std/mem.zig
Original file line number Diff line number Diff line change
Expand Up @@ -527,3 +527,40 @@ pub fn max(comptime T: type, slice: []const T) -> T {
test "mem.max" {
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 }))
}
Loading

0 comments on commit 75ecfdf

Please sign in to comment.