├── .gitignore ├── ref ├── README ├── spectral-norm.c ├── pidigits.c ├── mandelbrot.c ├── reverse-complement.c ├── fannkuch-redux.c ├── binary-trees.c ├── n-body.c ├── fasta.c ├── regex-redux.c ├── k-nucleotide.c └── include │ └── khash.h ├── README.md ├── src ├── spectral-norm.zig ├── mandelbrot.zig ├── pidigits.zig ├── reverse-complement.zig ├── fannkuch-redux.zig ├── binary-trees.zig ├── regex-redux.zig ├── fasta.zig ├── n-body.zig └── k-nucleotide.zig └── run /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | zig-cache 3 | -------------------------------------------------------------------------------- /ref/README: -------------------------------------------------------------------------------- 1 | C benchmark solutions. 2 | 3 | We take the fastest non-SIMD single-threaded C solution from the site where 4 | available for our reference. These are intended as a relative reference to any 5 | local zig solutions provided. 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [The Computer Language Benchmarks Game](https://benchmarksgame-team.pages.debian.net/benchmarksgame/) in Zig. 2 | 3 | ``` 4 | zig build 5 | ./run 6 | ``` 7 | 8 | ## Dependencies 9 | 10 | - zig (master branch) 11 | - bash 12 | - pcre 13 | - gmp 14 | 15 | NOTE: Running the full set of tests will use about 1GiB of hard drive space. Run 16 | `zig build clean` to clear all build artifacts. 17 | -------------------------------------------------------------------------------- /ref/spectral-norm.c: -------------------------------------------------------------------------------- 1 | /* The Computer Language Benchmarks Game 2 | * http://benchmarksgame.alioth.debian.org/ 3 | * 4 | * Contributed by Sebastien Loisel 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | double eval_A(int i, int j) { return 1.0/((i+j)*(i+j+1)/2+i+1); } 12 | 13 | void eval_A_times_u(int N, const double u[], double Au[]) 14 | { 15 | int i,j; 16 | for(i=0;i 8 | #include 9 | #include 10 | 11 | mpz_t tmp1, tmp2, acc, den, num; 12 | typedef unsigned int ui; 13 | 14 | ui extract_digit(ui nth) { 15 | // joggling between tmp1 and tmp2, so GMP won't have to use temp buffers 16 | mpz_mul_ui(tmp1, num, nth); 17 | mpz_add(tmp2, tmp1, acc); 18 | mpz_tdiv_q(tmp1, tmp2, den); 19 | 20 | return mpz_get_ui(tmp1); 21 | } 22 | 23 | void eliminate_digit(ui d) { 24 | mpz_submul_ui(acc, den, d); 25 | mpz_mul_ui(acc, acc, 10); 26 | mpz_mul_ui(num, num, 10); 27 | } 28 | 29 | void next_term(ui k) { 30 | ui k2 = k * 2U + 1U; 31 | 32 | mpz_addmul_ui(acc, num, 2U); 33 | mpz_mul_ui(acc, acc, k2); 34 | mpz_mul_ui(den, den, k2); 35 | mpz_mul_ui(num, num, k); 36 | } 37 | 38 | int main(int argc, char **argv) { 39 | ui d, k, i; 40 | int n = atoi(argv[1]); 41 | 42 | mpz_init(tmp1); 43 | mpz_init(tmp2); 44 | 45 | mpz_init_set_ui(acc, 0); 46 | mpz_init_set_ui(den, 1); 47 | mpz_init_set_ui(num, 1); 48 | 49 | for (i = k = 0; i < n;) { 50 | next_term(++k); 51 | if (mpz_cmp(num, acc) > 0) 52 | continue; 53 | 54 | d = extract_digit(3); 55 | if (d != extract_digit(4)) 56 | continue; 57 | 58 | putchar('0' + d); 59 | if (++i % 10 == 0) 60 | printf("\t:%u\n", i); 61 | eliminate_digit(d); 62 | } 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /ref/mandelbrot.c: -------------------------------------------------------------------------------- 1 | /* The Computer Language Benchmarks Game 2 | * http://benchmarksgame.alioth.debian.org/ 3 | 4 | contributed by Greg Buchholz 5 | 6 | for the debian (AMD) machine... 7 | compile flags: -O3 -ffast-math -march=athlon-xp -funroll-loops 8 | 9 | for the gp4 (Intel) machine... 10 | compile flags: -O3 -ffast-math -march=pentium4 -funroll-loops 11 | */ 12 | 13 | #include 14 | #include 15 | 16 | int main (int argc, char **argv) 17 | { 18 | int w, h, bit_num = 0; 19 | char byte_acc = 0; 20 | int i, iter = 50; 21 | double x, y, limit = 2.0; 22 | double Zr, Zi, Cr, Ci, Tr, Ti; 23 | 24 | w = h = atoi(argv[1]); 25 | 26 | printf("P4\n%d %d\n",w,h); 27 | 28 | for(y=0;y 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | char *pairs = "ATCGGCTAUAMKRYWWSSYRKMVBHDDHBVNN\n\n"; 17 | char tbl[128]; 18 | 19 | void process(char *from, char *to) { 20 | while (*from++ != '\n'); 21 | 22 | size_t len = to - from; 23 | size_t off = 60 - (len % 61); 24 | 25 | if (off) { 26 | char *m; 27 | for (m = from + 60 - off; m < to; m += 61) { 28 | memmove(m + 1, m, off); 29 | *m = '\n'; 30 | } 31 | } 32 | 33 | char c; 34 | for (to--; from <= to; from++, to--) { 35 | c = tbl[(int)*from], *from = tbl[(int)*to], *to = c; 36 | } 37 | } 38 | 39 | int main() { 40 | char *s; 41 | for (s = pairs; *s; s += 2) { 42 | tbl[toupper(s[0])] = s[1]; 43 | tbl[tolower(s[0])] = s[1]; 44 | } 45 | 46 | 47 | const size_t _1M = 1024 * 1024; 48 | size_t buflen = 8 * 1024, len, end = 0; 49 | char *buf = malloc(buflen); 50 | 51 | int in = fileno(stdin); 52 | while ((len = read(in, buf + end, buflen - 256 - end))) { 53 | if (len < 0) break; 54 | end += len; 55 | if (end >= buflen - 256) { 56 | buflen = (buflen >= _1M) ? buflen + _1M : buflen * 2; 57 | buf = realloc(buf, buflen); 58 | } 59 | } 60 | buf[end] = '>'; 61 | 62 | char *from, *to = buf + end - 1; 63 | while (1) { 64 | for (from = to; *from != '>'; from--); 65 | 66 | process(from, to); 67 | 68 | to = from - 1; 69 | if (to < buf) break; 70 | } 71 | 72 | write(fileno(stdout), buf, end); 73 | free(buf); 74 | 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /src/spectral-norm.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | fn eval_a(i: usize, j: usize) f64 { 4 | return 1.0 / @intToFloat(f64, (i + j) * (i + j + 1) / 2 + i + 1); 5 | } 6 | 7 | fn eval_a_times_u(comptime transpose: bool, au: []f64, u: []const f64) void { 8 | for (au) |*e| { 9 | e.* = 0; 10 | } 11 | 12 | var i: usize = 0; 13 | while (i < au.len) : (i += 1) { 14 | var j: usize = 0; 15 | while (j < au.len) : (j += 1) { 16 | if (transpose) { 17 | au[i] += eval_a(j, i) * u[j]; 18 | } else { 19 | au[i] += eval_a(i, j) * u[j]; 20 | } 21 | } 22 | } 23 | } 24 | 25 | fn eval_ata_times_u(atau: []f64, u: []const f64, scratch: []f64) void { 26 | std.debug.assert(atau.len == u.len and u.len == scratch.len); 27 | 28 | eval_a_times_u(false, scratch, u); 29 | eval_a_times_u(true, atau, scratch); 30 | } 31 | 32 | var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 33 | var allocator = &gpa.allocator; 34 | 35 | pub fn main() !void { 36 | var buffered_stdout = std.io.bufferedWriter(std.io.getStdOut().writer()); 37 | defer buffered_stdout.flush() catch unreachable; 38 | const stdout = buffered_stdout.writer(); 39 | 40 | var args = try std.process.argsAlloc(allocator); 41 | if (args.len < 2) return error.InvalidArguments; 42 | 43 | const n = try std.fmt.parseUnsigned(u64, args[1], 10); 44 | 45 | var u = try allocator.alloc(f64, n); 46 | var v = try allocator.alloc(f64, n); 47 | var scratch = try allocator.alloc(f64, n); 48 | 49 | for (u) |*e| { 50 | e.* = 1; 51 | } 52 | 53 | var i: usize = 0; 54 | while (i < 10) : (i += 1) { 55 | eval_ata_times_u(v, u, scratch); 56 | eval_ata_times_u(u, v, scratch); 57 | } 58 | 59 | var vbv: f64 = 0; 60 | var vv: f64 = 0; 61 | 62 | var j: usize = 0; 63 | while (j < n) : (j += 1) { 64 | vbv += u[i] * v[i]; 65 | vv += v[i] * v[i]; 66 | } 67 | 68 | try stdout.print("{d:.9}\n", .{@sqrt(vbv / vv)}); 69 | } 70 | -------------------------------------------------------------------------------- /src/mandelbrot.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | var buffer: [256]u8 = undefined; 4 | var fixed_allocator = std.heap.FixedBufferAllocator.init(buffer[0..]); 5 | var allocator = &fixed_allocator.allocator; 6 | 7 | pub fn main() !void { 8 | var buffered_stdout = std.io.bufferedWriter(std.io.getStdOut().writer()); 9 | defer buffered_stdout.flush() catch unreachable; 10 | const stdout = buffered_stdout.writer(); 11 | 12 | var args = try std.process.argsAlloc(allocator); 13 | if (args.len < 2) return error.InvalidArguments; 14 | 15 | const w = try std.fmt.parseUnsigned(usize, args[1], 10); 16 | const h = w; 17 | 18 | const iterations = 50; 19 | const limit = 2.0; 20 | 21 | try stdout.print("P4\n{} {}\n", .{ w, h }); 22 | 23 | var ba: u8 = 0; 24 | var bn: u8 = 0; 25 | var y: usize = 0; 26 | while (y < h) : (y += 1) { 27 | var x: usize = 0; 28 | while (x < w) : (x += 1) { 29 | const cr = 2.0 * @intToFloat(f64, x) / @intToFloat(f64, w) - 1.5; 30 | const ci = 2.0 * @intToFloat(f64, y) / @intToFloat(f64, h) - 1.0; 31 | 32 | var zr: f64 = 0.0; 33 | var zi: f64 = 0.0; 34 | var tr: f64 = 0.0; 35 | var ti: f64 = 0.0; 36 | 37 | var i: usize = 0; 38 | while (i < iterations and (tr + ti <= limit * limit)) : (i += 1) { 39 | zi = 2.0 * zr * zi + ci; 40 | zr = tr - ti + cr; 41 | tr = zr * zr; 42 | ti = zi * zi; 43 | } 44 | 45 | ba <<= 1; 46 | if (tr + ti <= limit * limit) { 47 | ba |= 1; 48 | } 49 | 50 | bn += 1; 51 | if (bn == 8) { 52 | try stdout.print("{c}", .{ba}); 53 | ba = 0; 54 | bn = 0; 55 | } else if (x == w - 1) { 56 | ba = std.math.shr(u8, ba, 8 - w % 8); 57 | try stdout.print("{c}", .{ba}); 58 | ba = 0; 59 | bn = 0; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /ref/fannkuch-redux.c: -------------------------------------------------------------------------------- 1 | /* The Computer Language Benchmarks Game 2 | * https://salsa.debian.org/benchmarksgame-team/benchmarksgame/ 3 | * 4 | * converted to C by Joseph Piché 5 | * from Java version by Oleg Mazurov and Isaac Gouy 6 | * 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | inline static int max(int a, int b) 13 | { 14 | return a > b ? a : b; 15 | } 16 | 17 | int fannkuchredux(int n) 18 | { 19 | int perm[n]; 20 | int perm1[n]; 21 | int count[n]; 22 | int maxFlipsCount = 0; 23 | int permCount = 0; 24 | int checksum = 0; 25 | 26 | int i; 27 | 28 | for (i=0; i> 1; 45 | for (i=0; i 0) break; 71 | r++; 72 | } 73 | permCount++; 74 | } 75 | } 76 | 77 | int main(int argc, char *argv[]) 78 | { 79 | int n = argc > 1 ? atoi(argv[1]) : 7; 80 | printf("Pfannkuchen(%d) = %d\n", n, fannkuchredux(n)); 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /src/pidigits.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const c = @cImport(@cInclude("gmp.h")); 3 | 4 | var _storage: [5]c.mpz_t = undefined; 5 | const tmp1 = &_storage[0]; 6 | const tmp2 = &_storage[1]; 7 | const acc = &_storage[2]; 8 | const den = &_storage[3]; 9 | const num = &_storage[4]; 10 | 11 | fn extractDigit(nth: usize) usize { 12 | c.mpz_mul_ui(tmp1, num, nth); 13 | c.mpz_add(tmp2, tmp1, acc); 14 | c.mpz_tdiv_q(tmp1, tmp2, den); 15 | 16 | return @intCast(usize, c.mpz_get_si(tmp1)); 17 | } 18 | 19 | fn eliminateDigit(d: usize) void { 20 | c.mpz_submul_ui(acc, den, d); 21 | c.mpz_mul_ui(acc, acc, 10); 22 | c.mpz_mul_ui(num, num, 10); 23 | } 24 | 25 | fn nextTerm(k: usize) void { 26 | const k2 = k * 2 + 1; 27 | 28 | c.mpz_addmul_ui(acc, num, 2); 29 | c.mpz_mul_ui(acc, acc, k2); 30 | c.mpz_mul_ui(den, den, k2); 31 | c.mpz_mul_ui(num, num, k); 32 | } 33 | 34 | var buffer: [256]u8 = undefined; 35 | var fixed_allocator = std.heap.FixedBufferAllocator.init(buffer[0..]); 36 | var allocator = &fixed_allocator.allocator; 37 | 38 | pub fn main() !void { 39 | var buffered_stdout = std.io.bufferedWriter(std.io.getStdOut().writer()); 40 | defer buffered_stdout.flush() catch unreachable; 41 | const stdout = buffered_stdout.writer(); 42 | 43 | var args = try std.process.argsAlloc(allocator); 44 | if (args.len < 2) return error.InvalidArguments; 45 | 46 | const n = try std.fmt.parseUnsigned(usize, args[1], 10); 47 | 48 | c.mpz_init(tmp1); 49 | c.mpz_init(tmp2); 50 | c.mpz_init_set_ui(acc, 0); 51 | c.mpz_init_set_ui(den, 1); 52 | c.mpz_init_set_ui(num, 1); 53 | 54 | var i: usize = 0; 55 | var k: usize = 0; 56 | while (i < n) { 57 | k += 1; 58 | nextTerm(k); 59 | if (c.mpz_cmp(num, acc) > 0) { 60 | continue; 61 | } 62 | 63 | const d = extractDigit(3); 64 | if (d != extractDigit(4)) { 65 | continue; 66 | } 67 | 68 | try stdout.print("{c}", .{@intCast(u8, '0' + d)}); 69 | i += 1; 70 | if (i % 10 == 0) { 71 | try stdout.print("\t:{}\n", .{i}); 72 | } 73 | eliminateDigit(d); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/reverse-complement.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | fn tolower(c: usize) usize { 4 | return if (c -% 'A' < 26) c | 32 else c; 5 | } 6 | 7 | fn toupper(c: usize) usize { 8 | return if (c -% 'a' < 26) c & 0x5f else c; 9 | } 10 | 11 | const pairs = "ATCGGCTAUAMKRYWWSSYRKMVBHDDHBVNN\n\n"; 12 | const table = block: { 13 | var t: [128]u8 = undefined; 14 | 15 | var i: usize = 0; 16 | while (i < pairs.len) : (i += 2) { 17 | t[toupper(pairs[i])] = pairs[i + 1]; 18 | t[tolower(pairs[i])] = pairs[i + 1]; 19 | } 20 | 21 | break :block t; 22 | }; 23 | 24 | fn process(buf: []u8, ifrom: usize, ito: usize) void { 25 | var from = ifrom + std.mem.indexOfScalar(u8, buf[ifrom..], '\n').? + 1; 26 | var to = ito; 27 | 28 | const len = to - from; 29 | const off = 60 - (len % 61); 30 | 31 | if (off != 0) { 32 | var m = from + 60 - off; 33 | while (m < to) : (m += 61) { 34 | // memmove(m + 1, m, off); 35 | var i: usize = 0; 36 | var t = buf[m]; 37 | while (i < off) : (i += 1) { 38 | std.mem.swap(u8, &buf[m + 1 + i], &t); 39 | } 40 | 41 | buf[m] = '\n'; 42 | } 43 | } 44 | 45 | to -= 1; 46 | while (from <= to) : ({ 47 | from += 1; 48 | to -= 1; 49 | }) { 50 | const c = table[buf[from]]; 51 | buf[from] = table[buf[to]]; 52 | buf[to] = c; 53 | } 54 | } 55 | 56 | var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 57 | var allocator = &gpa.allocator; 58 | 59 | pub fn main() !void { 60 | var buffered_stdout = std.io.bufferedWriter(std.io.getStdOut().writer()); 61 | defer buffered_stdout.flush() catch unreachable; 62 | const stdout = buffered_stdout.writer(); 63 | 64 | var buffered_stdin = std.io.bufferedReader(std.io.getStdIn().reader()); 65 | const stdin = buffered_stdin.reader(); 66 | 67 | const buf = try stdin.readAllAlloc(allocator, std.math.maxInt(usize)); 68 | defer allocator.free(buf); 69 | 70 | var to = buf.len - 1; 71 | while (true) { 72 | const from = std.mem.lastIndexOfScalar(u8, buf[0..to], '>').?; 73 | process(buf, from, to); 74 | 75 | if (from == 0) { 76 | break; 77 | } 78 | 79 | to = from - 1; 80 | } 81 | 82 | _ = try stdout.write(buf); 83 | } 84 | -------------------------------------------------------------------------------- /src/fannkuch-redux.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | var buffer: [2048]u8 = undefined; 4 | var fixed_allocator = std.heap.FixedBufferAllocator.init(buffer[0..]); 5 | var allocator = &fixed_allocator.allocator; 6 | 7 | pub fn main() !void { 8 | var buffered_stdout = std.io.bufferedWriter(std.io.getStdOut().writer()); 9 | defer buffered_stdout.flush() catch unreachable; 10 | const stdout = buffered_stdout.writer(); 11 | 12 | var args = try std.process.argsAlloc(allocator); 13 | if (args.len < 2) return error.InvalidArguments; 14 | 15 | const n = try std.fmt.parseUnsigned(usize, args[1], 10); 16 | 17 | var perm = try allocator.alloc(usize, n); 18 | var perm1 = try allocator.alloc(usize, n); 19 | var count = try allocator.alloc(usize, n); 20 | 21 | var max_flips_count: usize = 0; 22 | var perm_count: usize = 0; 23 | var checksum: isize = 0; 24 | 25 | for (perm1) |*e, i| { 26 | e.* = i; 27 | } 28 | 29 | var r = n; 30 | loop: { 31 | while (true) { 32 | while (r != 1) : (r -= 1) { 33 | count[r - 1] = r; 34 | } 35 | 36 | for (perm) |_, i| { 37 | perm[i] = perm1[i]; 38 | } 39 | 40 | var flips_count: usize = 0; 41 | 42 | while (true) { 43 | const k = perm[0]; 44 | if (k == 0) { 45 | break; 46 | } 47 | 48 | const k2 = (k + 1) >> 1; 49 | var i: usize = 0; 50 | while (i < k2) : (i += 1) { 51 | std.mem.swap(usize, &perm[i], &perm[k - i]); 52 | } 53 | flips_count += 1; 54 | } 55 | 56 | max_flips_count = std.math.max(max_flips_count, flips_count); 57 | if (perm_count % 2 == 0) { 58 | checksum += @intCast(isize, flips_count); 59 | } else { 60 | checksum -= @intCast(isize, flips_count); 61 | } 62 | 63 | while (true) : (r += 1) { 64 | if (r == n) { 65 | break :loop; 66 | } 67 | 68 | const perm0 = perm1[0]; 69 | var i: usize = 0; 70 | while (i < r) { 71 | const j = i + 1; 72 | perm1[i] = perm1[j]; 73 | i = j; 74 | } 75 | 76 | perm1[r] = perm0; 77 | count[r] -= 1; 78 | 79 | if (count[r] > 0) { 80 | break; 81 | } 82 | } 83 | 84 | perm_count += 1; 85 | } 86 | } 87 | 88 | try stdout.print("{}\nPfannkuchen({}) = {}\n", .{ checksum, n, max_flips_count }); 89 | } 90 | -------------------------------------------------------------------------------- /src/binary-trees.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const Allocator = std.mem.Allocator; 3 | 4 | const TreeNode = struct { 5 | l: ?*TreeNode, 6 | r: ?*TreeNode, 7 | 8 | pub fn new(a: *Allocator, l: ?*TreeNode, r: ?*TreeNode) !*TreeNode { 9 | var node = try a.create(TreeNode); 10 | node.l = l; 11 | node.r = r; 12 | return node; 13 | } 14 | 15 | pub fn free(self: *TreeNode, a: *Allocator) void { 16 | a.destroy(self); 17 | } 18 | }; 19 | 20 | fn itemCheck(node: *TreeNode) usize { 21 | if (node.l) |left| { 22 | // either have both nodes or none 23 | return 1 + itemCheck(left) + itemCheck(node.r.?); 24 | } else { 25 | return 1; 26 | } 27 | } 28 | 29 | fn bottomUpTree(a: *Allocator, depth: usize) Allocator.Error!*TreeNode { 30 | if (depth > 0) { 31 | const left = try bottomUpTree(a, depth - 1); 32 | const right = try bottomUpTree(a, depth - 1); 33 | 34 | return try TreeNode.new(a, left, right); 35 | } else { 36 | return try TreeNode.new(a, null, null); 37 | } 38 | } 39 | 40 | fn deleteTree(a: *Allocator, node: *TreeNode) void { 41 | if (node.l) |left| { 42 | // either have both nodes or none 43 | deleteTree(a, left); 44 | deleteTree(a, node.r.?); 45 | } 46 | 47 | a.destroy(node); 48 | } 49 | 50 | var allocator = std.heap.c_allocator; 51 | 52 | pub fn main() !void { 53 | var buffered_stdout = std.io.bufferedWriter(std.io.getStdOut().writer()); 54 | defer buffered_stdout.flush() catch unreachable; 55 | const stdout = buffered_stdout.writer(); 56 | 57 | var args = try std.process.argsAlloc(allocator); 58 | if (args.len < 2) return error.InvalidArguments; 59 | 60 | const n = try std.fmt.parseUnsigned(usize, args[1], 10); 61 | 62 | const min_depth: usize = 4; 63 | const max_depth: usize = n; 64 | const stretch_depth = max_depth + 1; 65 | 66 | const stretch_tree = try bottomUpTree(allocator, stretch_depth); 67 | _ = try stdout.print("stretch tree of depth {}\t check: {}\n", .{ stretch_depth, itemCheck(stretch_tree) }); 68 | deleteTree(allocator, stretch_tree); 69 | 70 | const long_lived_tree = try bottomUpTree(allocator, max_depth); 71 | var depth = min_depth; 72 | while (depth <= max_depth) : (depth += 2) { 73 | var iterations = @floatToInt(usize, std.math.pow(f32, 2, @intToFloat(f32, max_depth - depth + min_depth))); 74 | var check: usize = 0; 75 | 76 | var i: usize = 1; 77 | while (i <= iterations) : (i += 1) { 78 | const temp_tree = try bottomUpTree(allocator, depth); 79 | check += itemCheck(temp_tree); 80 | deleteTree(allocator, temp_tree); 81 | } 82 | 83 | _ = try stdout.print("{}\t trees of depth {}\t check: {}\n", .{ iterations, depth, check }); 84 | } 85 | 86 | _ = try stdout.print("long lived tree of depth {}\t check: {}\n", .{ max_depth, itemCheck(long_lived_tree) }); 87 | deleteTree(allocator, long_lived_tree); 88 | } 89 | -------------------------------------------------------------------------------- /ref/binary-trees.c: -------------------------------------------------------------------------------- 1 | /* The Computer Language Benchmarks Game 2 | * http://benchmarksgame.alioth.debian.org/ 3 | 4 | contributed by Kevin Carson 5 | compilation: 6 | gcc -O3 -fomit-frame-pointer -funroll-loops -static binary-trees.c -lm 7 | icc -O3 -ip -unroll -static binary-trees.c -lm 8 | 9 | *reset* 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | typedef struct tn { 18 | struct tn* left; 19 | struct tn* right; 20 | } treeNode; 21 | 22 | 23 | treeNode* NewTreeNode(treeNode* left, treeNode* right) 24 | { 25 | treeNode* new; 26 | 27 | new = (treeNode*)malloc(sizeof(treeNode)); 28 | 29 | new->left = left; 30 | new->right = right; 31 | 32 | return new; 33 | } /* NewTreeNode() */ 34 | 35 | 36 | long ItemCheck(treeNode* tree) 37 | { 38 | if (tree->left == NULL) 39 | return 1; 40 | else 41 | return 1 + ItemCheck(tree->left) + ItemCheck(tree->right); 42 | } /* ItemCheck() */ 43 | 44 | 45 | treeNode* BottomUpTree(unsigned depth) 46 | { 47 | if (depth > 0) 48 | return NewTreeNode 49 | ( 50 | BottomUpTree(depth - 1), 51 | BottomUpTree(depth - 1) 52 | ); 53 | else 54 | return NewTreeNode(NULL, NULL); 55 | } /* BottomUpTree() */ 56 | 57 | 58 | void DeleteTree(treeNode* tree) 59 | { 60 | if (tree->left != NULL) 61 | { 62 | DeleteTree(tree->left); 63 | DeleteTree(tree->right); 64 | } 65 | 66 | free(tree); 67 | } /* DeleteTree() */ 68 | 69 | 70 | int main(int argc, char* argv[]) 71 | { 72 | unsigned N, depth, minDepth, maxDepth, stretchDepth; 73 | treeNode *stretchTree, *longLivedTree, *tempTree; 74 | 75 | N = atol(argv[1]); 76 | 77 | minDepth = 4; 78 | 79 | if ((minDepth + 2) > N) 80 | maxDepth = minDepth + 2; 81 | else 82 | maxDepth = N; 83 | 84 | stretchDepth = maxDepth + 1; 85 | 86 | stretchTree = BottomUpTree(stretchDepth); 87 | printf 88 | ( 89 | "stretch tree of depth %u\t check: %li\n", 90 | stretchDepth, 91 | ItemCheck(stretchTree) 92 | ); 93 | 94 | DeleteTree(stretchTree); 95 | 96 | longLivedTree = BottomUpTree(maxDepth); 97 | 98 | for (depth = minDepth; depth <= maxDepth; depth += 2) 99 | { 100 | long i, iterations, check; 101 | 102 | iterations = pow(2, maxDepth - depth + minDepth); 103 | 104 | check = 0; 105 | 106 | for (i = 1; i <= iterations; i++) 107 | { 108 | tempTree = BottomUpTree(depth); 109 | check += ItemCheck(tempTree); 110 | DeleteTree(tempTree); 111 | } /* for(i = 1...) */ 112 | 113 | printf 114 | ( 115 | "%li\t trees of depth %u\t check: %li\n", 116 | iterations, 117 | depth, 118 | check 119 | ); 120 | } /* for(depth = minDepth...) */ 121 | 122 | printf 123 | ( 124 | "long lived tree of depth %u\t check: %li\n", 125 | maxDepth, 126 | ItemCheck(longLivedTree) 127 | ); 128 | 129 | return 0; 130 | } /* main() */ 131 | -------------------------------------------------------------------------------- /run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | output_file='build/output.txt' 4 | 5 | input_file1='build/input5000000.txt' 6 | if [ ! -f "$input_file1" ]; then 7 | ./ref/build/fasta 5000000 > "$input_file1" 8 | fi 9 | 10 | input_file2='build/input25000000.txt' 11 | if [ ! -f "$input_file2" ]; then 12 | ./ref/build/fasta 25000000 > "$input_file2" 13 | fi 14 | 15 | input_file3='build/input100000000.txt' 16 | if [ ! -f "$input_file3" ]; then 17 | ./ref/build/fasta 100000000 > "$input_file3" 18 | fi 19 | 20 | echo -e "\nK-NUCLEOTIDE (ZIG) <================================================" 21 | time ./build/k-nucleotide < "$input_file2" > "$output_file" 22 | md5sum "$output_file" 23 | 24 | echo -e "\nK-NUCLEOTIDE (C) <==================================================" 25 | time ./ref/build/k-nucleotide < "$input_file2" > "$output_file" 26 | md5sum "$output_file" 27 | 28 | echo -e "\nFASTA (ZIG) <=======================================================" 29 | time ./build/fasta 25000000 > "$output_file" 30 | md5sum "$output_file" 31 | 32 | echo -e "\nFASTA (C) <=========================================================" 33 | time ./ref/build/fasta 25000000 > "$output_file" 34 | md5sum "$output_file" 35 | 36 | echo -e "\nREGEX REDUX (ZIG) <=================================================" 37 | time ./build/regex-redux < "$input_file1" 38 | 39 | echo -e "\nREGEX REDUX (C) <===================================================" 40 | time ./ref/build/regex-redux < "$input_file1" 41 | 42 | echo -e "\nBINARY-TREES (ZIG) <================================================" 43 | time ./build/binary-trees 21 44 | 45 | echo -e "\nBINARY-TREES (C) <==================================================" 46 | time ./ref/build/binary-trees 21 47 | echo "" 48 | 49 | echo -e "\nFANNKUCH-REDUX (ZIG) <==============================================" 50 | time ./build/fannkuch-redux 12 51 | 52 | echo -e "\nFANNKUCH-REDUX (C) <================================================" 53 | time ./ref/build/fannkuch-redux 12 54 | 55 | echo -e "\nMANDELBROT (ZIG) <==================================================" 56 | time ./build/mandelbrot 16000 > "$output_file" 57 | md5sum "$output_file" 58 | 59 | echo -e "\nMANDELBROT (C) <====================================================" 60 | time ./ref/build/mandelbrot 16000 > "$output_file" 61 | md5sum "$output_file" 62 | 63 | echo -e "\nN-BODY (ZIG) <======================================================" 64 | time ./build/n-body 50000000 65 | 66 | echo -e "\nN-BODY (C) <========================================================" 67 | time ./ref/build/n-body 50000000 68 | 69 | echo -e "\nPIDIGITS (ZIG) <====================================================" 70 | time ./build/pidigits 10000 > "$output_file" 71 | md5sum "$output_file" 72 | 73 | echo -e "\nPIDIGITS (C) <======================================================" 74 | time ./ref/build/pidigits 10000 > "$output_file" 75 | md5sum "$output_file" 76 | 77 | echo -e "\nREVERSE-COMPLEMENT (ZIG) <==========================================" 78 | time ./build/reverse-complement < "$input_file3" > "$output_file" 79 | md5sum "$output_file" 80 | 81 | echo -e "\nREVERSE-COMPLEMENT (C) <============================================" 82 | time ./ref/build/reverse-complement < "$input_file3" > "$output_file" 83 | md5sum "$output_file" 84 | 85 | echo -e "\nSPECTRAL-NORM (ZIG) <===============================================" 86 | time ./build/spectral-norm 5500 87 | 88 | echo -e "\nSPECTRAL-NORM (C) <=================================================" 89 | time ./ref/build/spectral-norm 5500 90 | -------------------------------------------------------------------------------- /src/regex-redux.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const c = @cImport(@cInclude("pcre.h")); 3 | 4 | const Regex = struct { 5 | re: *c.pcre, 6 | re_ex: *c.pcre_extra, 7 | 8 | // Must be given a null-terminated pattern (zig string). 9 | pub fn compile(pattern: []const u8) !Regex { 10 | var result: Regex = undefined; 11 | 12 | var re_eo: c_int = undefined; 13 | var re_e: [*c]const u8 = undefined; 14 | var pattern_c = @ptrCast([*:0]const u8, pattern); 15 | 16 | const re = c.pcre_compile(pattern_c, 0, &re_e, &re_eo, 0); 17 | if (re) |ok_re| { 18 | result.re = ok_re; 19 | } else { 20 | return error.FailedToCompileRegex; 21 | } 22 | 23 | result.re_ex = c.pcre_study(result.re, c.PCRE_STUDY_JIT_COMPILE, &re_e); 24 | return result; 25 | } 26 | }; 27 | 28 | fn substitute(dst: *std.ArrayList(u8), src: []const u8, pattern: []const u8, replacement: []const u8) !usize { 29 | var regex = try Regex.compile(pattern); 30 | dst.shrinkRetainingCapacity(0); 31 | 32 | var pos: c_int = 0; 33 | var m: [3]c_int = undefined; 34 | while (c.pcre_exec(regex.re, regex.re_ex, src.ptr, @intCast(c_int, src.len), pos, 0, &m[0], 3) >= 0) : (pos = m[1]) { 35 | const upos = @intCast(usize, pos); 36 | const clen = @intCast(usize, m[0]) - upos; 37 | try dst.appendSlice(src[upos .. upos + clen]); 38 | try dst.appendSlice(replacement); 39 | } 40 | 41 | const upos = @intCast(usize, pos); 42 | const clen = src.len - upos; 43 | try dst.appendSlice(src[upos .. upos + clen]); 44 | return dst.items.len; 45 | } 46 | 47 | fn countMatches(src: []const u8, pattern: []const u8) !usize { 48 | var regex = try Regex.compile(pattern); 49 | 50 | var count: usize = 0; 51 | var pos: c_int = 0; 52 | var m: [3]c_int = undefined; 53 | while (c.pcre_exec(regex.re, regex.re_ex, src.ptr, @intCast(c_int, src.len), pos, 0, &m[0], 3) >= 0) : (pos = m[1]) { 54 | count += 1; 55 | } 56 | 57 | return count; 58 | } 59 | 60 | const variants = [_][]const u8{ 61 | "agggtaaa|tttaccct", 62 | "[cgt]gggtaaa|tttaccc[acg]", 63 | "a[act]ggtaaa|tttacc[agt]t", 64 | "ag[act]gtaaa|tttac[agt]ct", 65 | "agg[act]taaa|ttta[agt]cct", 66 | "aggg[acg]aaa|ttt[cgt]ccct", 67 | "agggt[cgt]aa|tt[acg]accct", 68 | "agggta[cgt]a|t[acg]taccct", 69 | "agggtaa[cgt]|[acg]ttaccct", 70 | }; 71 | 72 | const subs = [_][]const u8{ 73 | "tHa[Nt]", "<4>", 74 | "aND|caN|Ha[DS]|WaS", "<3>", 75 | "a[NSt]|BY", "<2>", 76 | "<[^>]*>", "|", 77 | "\\|[^|][^|]*\\|", "-", 78 | }; 79 | 80 | var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 81 | var allocator = &gpa.allocator; 82 | 83 | pub fn main() !void { 84 | var buffered_stdout = std.io.bufferedWriter(std.io.getStdOut().writer()); 85 | defer buffered_stdout.flush() catch unreachable; 86 | const stdout = buffered_stdout.writer(); 87 | 88 | var buffered_stdin = std.io.bufferedReader(std.io.getStdIn().reader()); 89 | const stdin = buffered_stdin.reader(); 90 | 91 | var seq: [2]std.ArrayList(u8) = undefined; 92 | seq[1] = std.ArrayList(u8).init(allocator); 93 | defer seq[1].deinit(); 94 | 95 | const input = try stdin.readAllAlloc(allocator, std.math.maxInt(usize)); 96 | const ilen = input.len; 97 | seq[0] = std.ArrayList(u8).fromOwnedSlice(allocator, input); 98 | defer seq[0].deinit(); 99 | 100 | const clen = try substitute(&seq[1], seq[0].items, ">.*|\n", ""); 101 | for (variants) |variant| { 102 | _ = try stdout.print("{s} {}\n", .{ variant, countMatches(seq[1].items, variant) }); 103 | } 104 | 105 | var slen: usize = 0; 106 | 107 | var i: usize = 0; 108 | var flip: usize = 1; 109 | while (i < subs.len) : (i += 2) { 110 | slen = try substitute(&seq[1 - flip], seq[flip].items, subs[i], subs[i + 1]); 111 | flip = 1 - flip; 112 | } 113 | 114 | _ = try stdout.print("\n{}\n{}\n{}\n", .{ ilen, clen, slen }); 115 | } 116 | -------------------------------------------------------------------------------- /src/fasta.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | const max_line_length = 60; 4 | 5 | const im = 139968; 6 | const ia = 3877; 7 | const ic = 29573; 8 | var seed: u32 = 42; 9 | fn nextRandom(max: f64) f64 { 10 | seed = (seed * ia + ic) % im; 11 | return max * @intToFloat(f64, seed) / @intToFloat(f64, im); 12 | } 13 | 14 | const AminoAcid = struct { 15 | l: u8, 16 | p: f64, 17 | }; 18 | 19 | fn repeatAndWrap(out: anytype, comptime sequence: []const u8, count: usize) void { 20 | var padded_sequence: [sequence.len + max_line_length]u8 = undefined; 21 | for (padded_sequence) |*e, i| { 22 | e.* = sequence[i % sequence.len]; 23 | } 24 | 25 | var off: usize = 0; 26 | var idx: usize = 0; 27 | while (idx < count) { 28 | const rem = count - idx; 29 | const line_length = std.math.min(@as(usize, max_line_length), rem); 30 | 31 | _ = out.write(padded_sequence[off .. off + line_length]) catch unreachable; 32 | _ = out.writeByte('\n') catch unreachable; 33 | 34 | off += line_length; 35 | if (off > sequence.len) { 36 | off -= sequence.len; 37 | } 38 | idx += line_length; 39 | } 40 | } 41 | 42 | fn generateAndWrap(out: anytype, comptime nucleotides: []const AminoAcid, count: usize) void { 43 | var cum_prob: f64 = 0; 44 | var cum_prob_total: [nucleotides.len]f64 = undefined; 45 | for (nucleotides) |n, i| { 46 | cum_prob += n.p; 47 | cum_prob_total[i] = cum_prob * im; 48 | } 49 | 50 | var line: [max_line_length + 1]u8 = undefined; 51 | line[max_line_length] = '\n'; 52 | 53 | var idx: usize = 0; 54 | while (idx < count) { 55 | const rem = count - idx; 56 | const line_length = std.math.min(@as(usize, max_line_length), rem); 57 | 58 | for (line[0..line_length]) |*col| { 59 | const r = nextRandom(im); 60 | 61 | var c: usize = 0; 62 | for (cum_prob_total) |n| { 63 | if (n <= r) { 64 | c += 1; 65 | } 66 | } 67 | 68 | col.* = nucleotides[c].l; 69 | } 70 | 71 | line[line_length] = '\n'; 72 | _ = out.write(line[0 .. line_length + 1]) catch unreachable; 73 | idx += line_length; 74 | } 75 | } 76 | 77 | var buffer: [256]u8 = undefined; 78 | var fixed_allocator = std.heap.FixedBufferAllocator.init(buffer[0..]); 79 | var allocator = &fixed_allocator.allocator; 80 | 81 | pub fn main() !void { 82 | var buffered_stdout = std.io.bufferedWriter(std.io.getStdOut().writer()); 83 | defer buffered_stdout.flush() catch unreachable; 84 | const stdout = buffered_stdout.writer(); 85 | 86 | var args = try std.process.argsAlloc(allocator); 87 | if (args.len < 2) return error.InvalidArguments; 88 | 89 | const n = try std.fmt.parseUnsigned(u64, args[1], 10); 90 | 91 | const homo_sapiens_alu = "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTC" ++ 92 | "AGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCG" ++ 93 | "TGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGG" ++ 94 | "AGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; 95 | _ = try stdout.write(">ONE Homo sapiens alu\n"); 96 | repeatAndWrap(stdout, homo_sapiens_alu, 2 * n); 97 | 98 | const iub_nucleotide_info = &[_]AminoAcid{ 99 | AminoAcid{ .l = 'a', .p = 0.27 }, 100 | AminoAcid{ .l = 'c', .p = 0.12 }, 101 | AminoAcid{ .l = 'g', .p = 0.12 }, 102 | AminoAcid{ .l = 't', .p = 0.27 }, 103 | AminoAcid{ .l = 'B', .p = 0.02 }, 104 | AminoAcid{ .l = 'D', .p = 0.02 }, 105 | AminoAcid{ .l = 'H', .p = 0.02 }, 106 | AminoAcid{ .l = 'K', .p = 0.02 }, 107 | AminoAcid{ .l = 'M', .p = 0.02 }, 108 | AminoAcid{ .l = 'N', .p = 0.02 }, 109 | AminoAcid{ .l = 'R', .p = 0.02 }, 110 | AminoAcid{ .l = 'S', .p = 0.02 }, 111 | AminoAcid{ .l = 'V', .p = 0.02 }, 112 | AminoAcid{ .l = 'W', .p = 0.02 }, 113 | AminoAcid{ .l = 'Y', .p = 0.02 }, 114 | }; 115 | _ = try stdout.write(">TWO IUB ambiguity codes\n"); 116 | generateAndWrap(stdout, iub_nucleotide_info, 3 * n); 117 | 118 | const homo_sapien_nucleotide_info = &[_]AminoAcid{ 119 | AminoAcid{ .l = 'a', .p = 0.3029549426680 }, 120 | AminoAcid{ .l = 'c', .p = 0.1979883004921 }, 121 | AminoAcid{ .l = 'g', .p = 0.1975473066391 }, 122 | AminoAcid{ .l = 't', .p = 0.3015094502008 }, 123 | }; 124 | _ = try stdout.write(">THREE Homo sapiens frequency\n"); 125 | generateAndWrap(stdout, homo_sapien_nucleotide_info, 5 * n); 126 | } 127 | -------------------------------------------------------------------------------- /src/n-body.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | const solar_mass = 4.0 * std.math.pi * std.math.pi; 4 | const year = 365.24; 5 | 6 | const Planet = struct { 7 | x: f64, 8 | y: f64, 9 | z: f64, 10 | vx: f64, 11 | vy: f64, 12 | vz: f64, 13 | mass: f64, 14 | }; 15 | 16 | fn advance(bodies: []Planet, dt: f64, steps: usize) void { 17 | var i: usize = 0; 18 | while (i < steps) : (i += 1) { 19 | for (bodies) |*bi, j| { 20 | for (bodies[j + 1 ..]) |*bj| { 21 | const dx = bi.x - bj.x; 22 | const dy = bi.y - bj.y; 23 | const dz = bi.z - bj.z; 24 | 25 | const dsq = dx * dx + dy * dy + dz * dz; 26 | const dst = @sqrt(dsq); 27 | const mag = dt / (dsq * dst); 28 | const mi = bi.mass; 29 | 30 | bi.vx -= dx * bj.mass * mag; 31 | bi.vy -= dy * bj.mass * mag; 32 | bi.vz -= dz * bj.mass * mag; 33 | 34 | bj.vx += dx * mi * mag; 35 | bj.vy += dy * mi * mag; 36 | bj.vz += dz * mi * mag; 37 | } 38 | } 39 | 40 | for (bodies) |*bi| { 41 | bi.x += dt * bi.vx; 42 | bi.y += dt * bi.vy; 43 | bi.z += dt * bi.vz; 44 | } 45 | } 46 | } 47 | 48 | fn energy(bodies: []const Planet) f64 { 49 | var e: f64 = 0.0; 50 | 51 | for (bodies) |bi, i| { 52 | e += 0.5 * (bi.vx * bi.vx + bi.vy * bi.vy + bi.vz * bi.vz) * bi.mass; 53 | 54 | for (bodies[i + 1 ..]) |bj| { 55 | const dx = bi.x - bj.x; 56 | const dy = bi.y - bj.y; 57 | const dz = bi.z - bj.z; 58 | const dist = @sqrt(dx * dx + dy * dy + dz * dz); 59 | e -= bi.mass * bj.mass / dist; 60 | } 61 | } 62 | 63 | return e; 64 | } 65 | 66 | fn offset_momentum(bodies: []Planet) void { 67 | var px: f64 = 0.0; 68 | var py: f64 = 0.0; 69 | var pz: f64 = 0.0; 70 | 71 | for (bodies) |b| { 72 | px += b.vx * b.mass; 73 | py += b.vy * b.mass; 74 | pz += b.vz * b.mass; 75 | } 76 | 77 | var sun = &bodies[0]; 78 | sun.vx = -px / solar_mass; 79 | sun.vy = -py / solar_mass; 80 | sun.vz = -pz / solar_mass; 81 | } 82 | 83 | const solar_bodies = [_]Planet{ 84 | // Sun 85 | Planet{ 86 | .x = 0.0, 87 | .y = 0.0, 88 | .z = 0.0, 89 | .vx = 0.0, 90 | .vy = 0.0, 91 | .vz = 0.0, 92 | .mass = solar_mass, 93 | }, 94 | // Jupiter 95 | Planet{ 96 | .x = 4.84143144246472090e+00, 97 | .y = -1.16032004402742839e+00, 98 | .z = -1.03622044471123109e-01, 99 | .vx = 1.66007664274403694e-03 * year, 100 | .vy = 7.69901118419740425e-03 * year, 101 | .vz = -6.90460016972063023e-05 * year, 102 | .mass = 9.54791938424326609e-04 * solar_mass, 103 | }, 104 | // Saturn 105 | Planet{ 106 | .x = 8.34336671824457987e+00, 107 | .y = 4.12479856412430479e+00, 108 | .z = -4.03523417114321381e-01, 109 | .vx = -2.76742510726862411e-03 * year, 110 | .vy = 4.99852801234917238e-03 * year, 111 | .vz = 2.30417297573763929e-05 * year, 112 | .mass = 2.85885980666130812e-04 * solar_mass, 113 | }, 114 | // Uranus 115 | Planet{ 116 | .x = 1.28943695621391310e+01, 117 | .y = -1.51111514016986312e+01, 118 | .z = -2.23307578892655734e-01, 119 | .vx = 2.96460137564761618e-03 * year, 120 | .vy = 2.37847173959480950e-03 * year, 121 | .vz = -2.96589568540237556e-05 * year, 122 | .mass = 4.36624404335156298e-05 * solar_mass, 123 | }, 124 | // Neptune 125 | Planet{ 126 | .x = 1.53796971148509165e+01, 127 | .y = -2.59193146099879641e+01, 128 | .z = 1.79258772950371181e-01, 129 | .vx = 2.68067772490389322e-03 * year, 130 | .vy = 1.62824170038242295e-03 * year, 131 | .vz = -9.51592254519715870e-05 * year, 132 | .mass = 5.15138902046611451e-05 * solar_mass, 133 | }, 134 | }; 135 | 136 | var buffer: [256]u8 = undefined; 137 | var fixed_allocator = std.heap.FixedBufferAllocator.init(buffer[0..]); 138 | var allocator = &fixed_allocator.allocator; 139 | 140 | pub fn main() !void { 141 | var buffered_stdout = std.io.bufferedWriter(std.io.getStdOut().writer()); 142 | defer buffered_stdout.flush() catch unreachable; 143 | const stdout = buffered_stdout.writer(); 144 | 145 | var args = try std.process.argsAlloc(allocator); 146 | if (args.len < 2) return error.InvalidArguments; 147 | 148 | const n = try std.fmt.parseUnsigned(u64, args[1], 10); 149 | 150 | var bodies = solar_bodies; 151 | 152 | offset_momentum(bodies[0..]); 153 | _ = try stdout.print("{d:.9}\n", .{energy(bodies[0..])}); 154 | 155 | advance(bodies[0..], 0.01, n); 156 | _ = try stdout.print("{d:.9}\n", .{energy(bodies[0..])}); 157 | } 158 | -------------------------------------------------------------------------------- /src/k-nucleotide.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | const HashMap = std.AutoHashMap(u64, u32); 4 | 5 | inline fn codeForNucleotide(nucleotide: u8) u8 { 6 | const lookup = [_]u8{ ' ', 0, ' ', 1, 3, ' ', ' ', 2 }; 7 | return lookup[nucleotide & 0x7]; 8 | } 9 | 10 | inline fn nucleotideForCode(code: u8) u8 { 11 | return "ACGT"[code & 0x3]; 12 | } 13 | 14 | fn kvLessThan(_: void, lhs: HashMap.KV, rhs: HashMap.KV) bool { 15 | if (lhs.value < rhs.value) return false; 16 | if (lhs.value > rhs.value) return true; 17 | return lhs.key < rhs.key; 18 | } 19 | 20 | fn generateFrequenciesForLength(allocator: *std.mem.Allocator, poly: []const u8, comptime desired_length: usize, output: []u8) !void { 21 | var hash = HashMap.init(allocator); 22 | defer hash.deinit(); 23 | 24 | const mask = (@as(u64, 1) << (2 * desired_length)) - 1; 25 | 26 | { 27 | var key: u64 = 0; 28 | var i: usize = 0; 29 | 30 | while (i < desired_length - 1) : (i += 1) { 31 | key = ((key << 2) & mask) | poly[i]; 32 | } 33 | 34 | while (i < poly.len) : (i += 1) { 35 | key = ((key << 2) & mask) | poly[i]; 36 | var entry = try hash.getOrPutValue(key, 0); 37 | entry.value_ptr.* += 1; 38 | } 39 | } 40 | 41 | var list = try allocator.alloc(HashMap.KV, hash.count()); 42 | defer allocator.free(list); 43 | 44 | var i: usize = 0; 45 | var it = hash.iterator(); 46 | while (it.next()) |entry| { 47 | list[i] = HashMap.KV{ .key = entry.key_ptr.*, .value = entry.value_ptr.* }; 48 | i += 1; 49 | } 50 | 51 | std.sort.sort(HashMap.KV, list, {}, kvLessThan); 52 | 53 | var position: usize = 0; 54 | for (list) |*entry| { 55 | var olig: [desired_length]u8 = undefined; 56 | 57 | for (olig) |*e, j| { 58 | const shift = @intCast(u6, 2 * (olig.len - j - 1)); 59 | e.* = nucleotideForCode(@truncate(u8, entry.key >> shift)); 60 | } 61 | 62 | const slice = try std.fmt.bufPrint( 63 | output[position..], 64 | "{s} {d:.3}\n", 65 | .{ olig[0..], 100.0 * @intToFloat(f64, entry.value) / @intToFloat(f64, poly.len - desired_length + 1) }, 66 | ); 67 | position += slice.len; 68 | output[position] = 0; 69 | } 70 | } 71 | 72 | fn generateCount(allocator: *std.mem.Allocator, poly: []const u8, comptime olig: []const u8, output: []u8) !void { 73 | var hash = HashMap.init(allocator); 74 | defer hash.deinit(); 75 | 76 | const mask = (@as(u64, 1) << (2 * olig.len)) - 1; 77 | 78 | { 79 | var key: u64 = 0; 80 | var i: usize = 0; 81 | 82 | while (i < olig.len - 1) : (i += 1) { 83 | key = ((key << 2) & mask) | poly[i]; 84 | } 85 | 86 | while (i < poly.len) : (i += 1) { 87 | key = ((key << 2) & mask) | poly[i]; 88 | var entry = try hash.getOrPutValue(key, 0); 89 | entry.value_ptr.* += 1; 90 | } 91 | } 92 | 93 | { 94 | var key: u64 = 0; 95 | 96 | for (olig) |_, i| { 97 | key = ((key << 2) & mask) | codeForNucleotide(olig[i]); 98 | } 99 | 100 | const count = hash.get(key) orelse 0; 101 | const slice = try std.fmt.bufPrint(output, "{}\t{s}", .{ count, olig }); 102 | output[slice.len] = 0; 103 | } 104 | } 105 | 106 | pub fn main() !void { 107 | var allocator = std.heap.c_allocator; 108 | 109 | var buffered_stdout = std.io.bufferedWriter(std.io.getStdOut().writer()); 110 | defer buffered_stdout.flush() catch unreachable; 111 | const stdout = buffered_stdout.writer(); 112 | 113 | var buffered_stdin = std.io.bufferedReader(std.io.getStdIn().reader()); 114 | const stdin = buffered_stdin.reader(); 115 | 116 | var buffer: [4096]u8 = undefined; 117 | 118 | while (try stdin.readUntilDelimiterOrEof(buffer[0..], '\n')) |line| { 119 | if (std.mem.startsWith(u8, line, ">THREE")) { 120 | break; 121 | } 122 | } 123 | 124 | var poly = std.ArrayList(u8).init(allocator); 125 | defer poly.deinit(); 126 | 127 | while (try stdin.readUntilDelimiterOrEof(buffer[0..], '\n')) |line| { 128 | for (line) |c| { 129 | try poly.append(codeForNucleotide(c)); 130 | } 131 | } 132 | 133 | const poly_shrunk = poly.toOwnedSlice(); 134 | 135 | const counts = [_]u8{ 1, 2 }; 136 | const entries = [_][]const u8{ "GGT", "GGTA", "GGTATT", "GGTATTTTAATT", "GGTATTTTAATTTATAGT" }; 137 | 138 | var output: [counts.len + entries.len][4096]u8 = undefined; 139 | 140 | inline for (counts) |count, i| { 141 | try generateFrequenciesForLength(allocator, poly_shrunk, count, output[i][0..]); 142 | } 143 | 144 | inline for (entries) |entry, i| { 145 | try generateCount(allocator, poly_shrunk, entry, output[i + counts.len][0..]); 146 | } 147 | 148 | for (output) |entry| { 149 | const entry_len = std.mem.indexOfScalarPos(u8, entry[0..], 0, 0) orelse unreachable; 150 | _ = try stdout.print("{s}\n", .{entry[0..entry_len]}); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /ref/n-body.c: -------------------------------------------------------------------------------- 1 | /* The Computer Language Benchmarks Game 2 | http://benchmarksgame.alioth.debian.org/ 3 | 4 | contributed by Mark C. Lewis 5 | modified slightly by Chad Whipkey 6 | converted from java to c++,added sse support, by Branimir Maksimovic 7 | converted from c++ to c, by Alexey Medvedchikov 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define PI 3.141592653589793 16 | #define SOLAR_MASS ( 4 * PI * PI ) 17 | #define DAYS_PER_YEAR 365.24 18 | 19 | struct body { 20 | double x[3], fill, v[3], mass; 21 | }; 22 | 23 | static struct body solar_bodies[] = { 24 | /* sun */ 25 | { 26 | .x = { 0., 0., 0. }, 27 | .v = { 0., 0., 0. }, 28 | .mass = SOLAR_MASS 29 | }, 30 | /* jupiter */ 31 | { 32 | .x = { 4.84143144246472090e+00, 33 | -1.16032004402742839e+00, 34 | -1.03622044471123109e-01 }, 35 | .v = { 1.66007664274403694e-03 * DAYS_PER_YEAR, 36 | 7.69901118419740425e-03 * DAYS_PER_YEAR, 37 | -6.90460016972063023e-05 * DAYS_PER_YEAR }, 38 | .mass = 9.54791938424326609e-04 * SOLAR_MASS 39 | }, 40 | /* saturn */ 41 | { 42 | .x = { 8.34336671824457987e+00, 43 | 4.12479856412430479e+00, 44 | -4.03523417114321381e-01 }, 45 | .v = { -2.76742510726862411e-03 * DAYS_PER_YEAR, 46 | 4.99852801234917238e-03 * DAYS_PER_YEAR, 47 | 2.30417297573763929e-05 * DAYS_PER_YEAR }, 48 | .mass = 2.85885980666130812e-04 * SOLAR_MASS 49 | }, 50 | /* uranus */ 51 | { 52 | .x = { 1.28943695621391310e+01, 53 | -1.51111514016986312e+01, 54 | -2.23307578892655734e-01 }, 55 | .v = { 2.96460137564761618e-03 * DAYS_PER_YEAR, 56 | 2.37847173959480950e-03 * DAYS_PER_YEAR, 57 | -2.96589568540237556e-05 * DAYS_PER_YEAR }, 58 | .mass = 4.36624404335156298e-05 * SOLAR_MASS 59 | }, 60 | /* neptune */ 61 | { 62 | .x = { 1.53796971148509165e+01, 63 | -2.59193146099879641e+01, 64 | 1.79258772950371181e-01 }, 65 | .v = { 2.68067772490389322e-03 * DAYS_PER_YEAR, 66 | 1.62824170038242295e-03 * DAYS_PER_YEAR, 67 | -9.51592254519715870e-05 * DAYS_PER_YEAR }, 68 | .mass = 5.15138902046611451e-05 * SOLAR_MASS 69 | } 70 | }; 71 | 72 | static const int BODIES_SIZE = sizeof(solar_bodies) / sizeof(solar_bodies[0]); 73 | 74 | void offset_momentum(struct body *bodies, unsigned int nbodies) 75 | { 76 | unsigned int i, k; 77 | for (i = 0; i < nbodies; ++i) 78 | for (k = 0; k < 3; ++k) 79 | bodies[0].v[k] -= bodies[i].v[k] * bodies[i].mass 80 | / SOLAR_MASS; 81 | } 82 | 83 | void bodies_advance(struct body *bodies, unsigned int nbodies, double dt) 84 | { 85 | unsigned int N = (nbodies - 1) * nbodies / 2; 86 | static struct { 87 | double dx[3], fill; 88 | } r[1000]; 89 | static __attribute__((aligned(16))) double mag[1000]; 90 | unsigned int i, j, k, m; 91 | __m128d dx[3] = {0}, dsquared, distance, dmag; 92 | 93 | for(k = 0, i = 0; i < nbodies - 1; ++i) 94 | for(j = i + 1; j < nbodies; ++j, ++k) 95 | for ( m = 0; m < 3; ++m) 96 | r[k].dx[m] = bodies[i].x[m] - bodies[j].x[m]; 97 | 98 | for (i = 0; i < N; i += 2) { 99 | for (m = 0; m < 3; ++m) { 100 | dx[m] = _mm_loadl_pd(dx[m], &r[i].dx[m]); 101 | dx[m] = _mm_loadh_pd(dx[m], &r[i+1].dx[m]); 102 | } 103 | 104 | dsquared = dx[0] * dx[0] + dx[1] * dx[1] + dx[2] * dx[2]; 105 | distance = _mm_cvtps_pd(_mm_rsqrt_ps(_mm_cvtpd_ps(dsquared))); 106 | 107 | for (j = 0; j < 2; ++j) 108 | distance = distance * _mm_set1_pd(1.5) 109 | - ((_mm_set1_pd(0.5) * dsquared) * distance) 110 | * (distance * distance); 111 | 112 | dmag = _mm_set1_pd(dt) / (dsquared) * distance; 113 | _mm_store_pd(&mag[i], dmag); 114 | } 115 | 116 | for (i = 0, k = 0; i < nbodies - 1; ++i) 117 | for ( j = i + 1; j < nbodies; ++j, ++k) 118 | for ( m = 0; m < 3; ++m) { 119 | bodies[i].v[m] -= r[k].dx[m] * bodies[j].mass 120 | * mag[k]; 121 | bodies[j].v[m] += r[k].dx[m] * bodies[i].mass 122 | * mag[k]; 123 | } 124 | 125 | for (i = 0; i < nbodies; ++i) 126 | for ( m = 0; m < 3; ++m) 127 | bodies[i].x[m] += dt * bodies[i].v[m]; 128 | } 129 | 130 | double bodies_energy(struct body *bodies, unsigned int nbodies) { 131 | double dx[3], distance, e = 0.0; 132 | unsigned int i, j, k; 133 | 134 | for (i=0; i < nbodies; ++i) { 135 | e += bodies[i].mass * ( bodies[i].v[0] * bodies[i].v[0] 136 | + bodies[i].v[1] * bodies[i].v[1] 137 | + bodies[i].v[2] * bodies[i].v[2] ) / 2.; 138 | 139 | for (j=i+1; j < nbodies; ++j) { 140 | for (k = 0; k < 3; ++k) 141 | dx[k] = bodies[i].x[k] - bodies[j].x[k]; 142 | 143 | distance = sqrt(dx[0] * dx[0] + dx[1] * dx[1] 144 | + dx[2] * dx[2]); 145 | e -= (bodies[i].mass * bodies[j].mass) / distance; 146 | } 147 | } 148 | return e; 149 | } 150 | 151 | int main(int argc, char** argv) 152 | { 153 | int i, n = atoi(argv[1]); 154 | offset_momentum(solar_bodies, BODIES_SIZE); 155 | printf("%.9f\n", bodies_energy(solar_bodies, BODIES_SIZE)); 156 | for (i = 0; i < n; ++i) 157 | bodies_advance(solar_bodies, BODIES_SIZE, 0.01); 158 | printf("%.9f\n", bodies_energy(solar_bodies, BODIES_SIZE)); 159 | return 0; 160 | } 161 | -------------------------------------------------------------------------------- /ref/fasta.c: -------------------------------------------------------------------------------- 1 | // The Computer Language Benchmarks Game 2 | // http://benchmarksgame.alioth.debian.org/ 3 | // 4 | // Contributed by Jeremy Zerfas 5 | 6 | // This controls the width of lines that are output by this program. 7 | #define MAXIMUM_LINE_WIDTH 60 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | // intptr_t should be the native integer type on most sane systems. 15 | typedef intptr_t intnative_t; 16 | 17 | typedef struct{ 18 | char letter; 19 | float probability; 20 | } nucleotide_info; 21 | 22 | 23 | // Repeatedly print string_To_Repeat until it has printed 24 | // number_Of_Characters_To_Create. The output is also wrapped to 25 | // MAXIMUM_LINE_WIDTH columns. 26 | static void repeat_And_Wrap_String(const char string_To_Repeat[], 27 | const intnative_t number_Of_Characters_To_Create){ 28 | const intnative_t string_To_Repeat_Length=strlen(string_To_Repeat); 29 | 30 | // Create an extended_String_To_Repeat which is a copy of string_To_Repeat 31 | // but extended with another copy of the first MAXIMUM_LINE_WIDTH characters 32 | // of string_To_Repeat appended to the end. Later on this allows us to 33 | // generate a line of output just by doing simple memory copies using an 34 | // appropriate offset into extended_String_To_Repeat. 35 | char extended_String_To_Repeat[string_To_Repeat_Length+MAXIMUM_LINE_WIDTH]; 36 | for(intnative_t column=0; column0;){ 48 | // Figure out the length of the line we need to write. If it's less than 49 | // MAXIMUM_LINE_WIDTH then we also need to add a line feed in the right 50 | // spot too. 51 | intnative_t line_Length=MAXIMUM_LINE_WIDTH; 52 | if(current_Number_Of_Characters_To_Createstring_To_Repeat_Length) 63 | offset-=string_To_Repeat_Length; 64 | 65 | // Output the line to stdout and update the 66 | // current_Number_Of_Characters_To_Create. 67 | fwrite(line, line_Length+1, 1, stdout); 68 | current_Number_Of_Characters_To_Create-=line_Length; 69 | } 70 | } 71 | 72 | 73 | // Generate a floating point pseudorandom number from 0.0 to max using a linear 74 | // congruential generator. 75 | #define IM 139968 76 | #define IA 3877 77 | #define IC 29573 78 | #define SEED 42 79 | static inline float get_LCG_Pseudorandom_Number(const float max){ 80 | static uint32_t seed=SEED; 81 | seed=(seed*IA + IC)%IM; 82 | return max/IM*seed; 83 | } 84 | 85 | 86 | // Print a pseudorandom DNA sequence that is number_Of_Characters_To_Create 87 | // characters long and made up of the nucleotides specified in 88 | // nucleotides_Information and occurring at the frequencies specified in 89 | // nucleotides_Information. The output is also wrapped to MAXIMUM_LINE_WIDTH 90 | // columns. 91 | static void generate_And_Wrap_Pseudorandom_DNA_Sequence( 92 | const nucleotide_info nucleotides_Information[], 93 | const intnative_t number_Of_Nucleotides, 94 | const intnative_t number_Of_Characters_To_Create){ 95 | 96 | // Cumulate the probabilities. Note that the probability is being multiplied 97 | // by IM because later on we'll also be calling the random number generator 98 | // with a value that is multiplied by IM. Since the random number generator 99 | // does a division by IM this allows the compiler to cancel out the 100 | // multiplication and division by IM with each other without requiring any 101 | // changes to the random number generator code whose code was explicitly 102 | // defined in the rules. 103 | float cumulative_Probabilities[number_Of_Nucleotides], 104 | cumulative_Probability=0.0; 105 | for(intnative_t i=0; i0;){ 116 | // Figure out the length of the line we need to write. If it's less than 117 | // MAXIMUM_LINE_WIDTH then we also need to add a line feed in the right 118 | // spot too. 119 | intnative_t line_Length=MAXIMUM_LINE_WIDTH; 120 | if(current_Number_Of_Characters_To_CreateONE Homo sapiens alu\n", stdout); 161 | const char homo_Sapiens_Alu[]= 162 | "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTC" 163 | "AGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCG" 164 | "TGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGG" 165 | "AGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; 166 | repeat_And_Wrap_String(homo_Sapiens_Alu, 2*n); 167 | 168 | fputs(">TWO IUB ambiguity codes\n", stdout); 169 | nucleotide_info iub_Nucleotides_Information[]={ 170 | {'a', 0.27}, {'c', 0.12}, {'g', 0.12}, {'t', 0.27}, {'B', 0.02}, 171 | {'D', 0.02}, {'H', 0.02}, {'K', 0.02}, {'M', 0.02}, {'N', 0.02}, 172 | {'R', 0.02}, {'S', 0.02}, {'V', 0.02}, {'W', 0.02}, {'Y', 0.02}}; 173 | generate_And_Wrap_Pseudorandom_DNA_Sequence(iub_Nucleotides_Information, 174 | sizeof(iub_Nucleotides_Information)/sizeof(nucleotide_info), 3*n); 175 | 176 | fputs(">THREE Homo sapiens frequency\n", stdout); 177 | nucleotide_info homo_Sapien_Nucleotides_Information[]={ 178 | {'a', 0.3029549426680}, {'c', 0.1979883004921}, 179 | {'g', 0.1975473066391}, {'t', 0.3015094502008}}; 180 | generate_And_Wrap_Pseudorandom_DNA_Sequence( 181 | homo_Sapien_Nucleotides_Information, 182 | sizeof(homo_Sapien_Nucleotides_Information)/sizeof(nucleotide_info), 5*n); 183 | 184 | return 0; 185 | } 186 | -------------------------------------------------------------------------------- /ref/regex-redux.c: -------------------------------------------------------------------------------- 1 | // The Computer Language Benchmarks Game 2 | // https://salsa.debian.org/benchmarksgame-team/benchmarksgame/ 3 | // 4 | // Contributed by Jeremy Zerfas 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | typedef struct { 12 | char * data; 13 | int capacity, size; 14 | } string; 15 | 16 | 17 | // Function for searching a src_String for a pattern, replacing it with some 18 | // specified replacement, and storing the result in dst_String. 19 | static void replace(char const * const pattern, char const * const replacement 20 | , string const * const src_String, string * const dst_String 21 | , pcre_jit_stack * const stack){ 22 | 23 | char const * error; 24 | int offset, pos=0, match[3]; 25 | int const replacement_Size=strlen(replacement); 26 | 27 | // Compile and study pattern. 28 | pcre * regex=pcre_compile(pattern, 0, &error, &offset, NULL); 29 | pcre_extra * aid=pcre_study(regex, PCRE_STUDY_JIT_COMPILE, &error); 30 | 31 | // Find each match of the pattern in src_String and append the characters 32 | // preceding each match and the replacement text to dst_String. 33 | while(pcre_jit_exec(regex, aid, src_String->data, src_String->size 34 | , pos, 0, match, 3, stack)>=0){ 35 | 36 | // Allocate more memory for dst_String if there is not enough space for 37 | // the characters preceding the match and the replacement text. 38 | while(dst_String->size+match[0]-pos+replacement_Size 39 | >dst_String->capacity) 40 | dst_String->data=realloc(dst_String->data, dst_String->capacity*=2); 41 | 42 | // Append the characters preceding the match and the replacement text to 43 | // dst_String and update the size of dst_String. 44 | memcpy(dst_String->data+dst_String->size, src_String->data+pos 45 | , match[0]-pos); 46 | memcpy(dst_String->data+dst_String->size+match[0]-pos, replacement 47 | , replacement_Size); 48 | dst_String->size+=match[0]-pos+replacement_Size; 49 | 50 | // Update pos to continue searching after the current match. 51 | pos=match[1]; 52 | } 53 | 54 | pcre_free_study(aid); 55 | pcre_free(regex); 56 | 57 | // Allocate more memory for dst_String if there is not enough space for 58 | // the characters following the last match (or the entire src_String if 59 | // there was no match). 60 | while(dst_String->size+src_String->size-pos>dst_String->capacity) 61 | dst_String->data=realloc(dst_String->data, dst_String->capacity*=2); 62 | 63 | // Append the characters following the last match (or the entire src_String 64 | // if there was no match) to dst_String and update the size of dst_String. 65 | memcpy(dst_String->data+dst_String->size, src_String->data+pos 66 | , src_String->size-pos); 67 | dst_String->size+=src_String->size-pos; 68 | } 69 | 70 | 71 | int main(void){ 72 | char const * const count_Info[]={ 73 | "agggtaaa|tttaccct", 74 | "[cgt]gggtaaa|tttaccc[acg]", 75 | "a[act]ggtaaa|tttacc[agt]t", 76 | "ag[act]gtaaa|tttac[agt]ct", 77 | "agg[act]taaa|ttta[agt]cct", 78 | "aggg[acg]aaa|ttt[cgt]ccct", 79 | "agggt[cgt]aa|tt[acg]accct", 80 | "agggta[cgt]a|t[acg]taccct", 81 | "agggtaa[cgt]|[acg]ttaccct" 82 | }, * const replace_Info[][2]={ 83 | {"tHa[Nt]", "<4>"}, 84 | {"aND|caN|Ha[DS]|WaS", "<3>"}, 85 | {"a[NSt]|BY", "<2>"}, 86 | {"<[^>]*>", "|"}, 87 | {"\\|[^|][^|]*\\|", "-"} 88 | }; 89 | 90 | string input={malloc(16384), 16384}, sequences={malloc(16384), 16384}; 91 | int postreplace_Size; 92 | 93 | 94 | // Read in input from stdin until we reach the end or encounter an error. 95 | for(int bytes_Read; 96 | (bytes_Read=fread(input.data+input.size, 1, input.capacity-input.size 97 | , stdin))>0;) 98 | // Update the size of input to reflect the newly read input and if 99 | // we've reached the full capacity of the input string then also double 100 | // its size. 101 | if((input.size+=bytes_Read)==input.capacity) 102 | input.data=realloc(input.data, input.capacity*=2); 103 | 104 | 105 | #pragma omp parallel 106 | { 107 | pcre_jit_stack * const stack=pcre_jit_stack_alloc(16384, 16384); 108 | 109 | 110 | // Find all sequence descriptions and new lines in input, replace them 111 | // with empty strings, and store the result in the sequences string. 112 | #pragma omp single 113 | { 114 | replace(">.*\\n|\\n", "", &input, &sequences, stack); 115 | 116 | free(input.data); 117 | } 118 | 119 | 120 | // Have one thread start working on performing all the replacements 121 | // serially. 122 | #pragma omp single nowait 123 | { 124 | // We'll use two strings when doing all the replacements, searching 125 | // for patterns in prereplace_String and using postreplace_String to 126 | // store the string after the replacements have been made. After 127 | // each iteration these two then get swapped. Start out with both 128 | // strings having the same capacity as the sequences string and also 129 | // copy the sequences string into prereplace_String for the initial 130 | // iteration. 131 | string prereplace_String={ 132 | malloc(sequences.capacity), sequences.capacity, sequences.size 133 | }, postreplace_String={ 134 | malloc(sequences.capacity), sequences.capacity 135 | }; 136 | memcpy(prereplace_String.data, sequences.data, sequences.size); 137 | 138 | // Iterate through all the replacement patterns and their 139 | // replacements in replace_Info[]. 140 | for(int i=0; i=0){ 180 | 181 | count++; 182 | 183 | // Update pos to continue searching after the current match. 184 | pos=match[1]; 185 | } 186 | 187 | pcre_free_study(aid); 188 | pcre_free(regex); 189 | 190 | // Print the count for each pattern in the correct order. 191 | #pragma omp ordered 192 | printf("%s %d\n", count_Info[i], count); 193 | } 194 | 195 | 196 | pcre_jit_stack_free(stack); 197 | } 198 | 199 | 200 | free(sequences.data); 201 | 202 | // Print the size of the original input, the size of the input without the 203 | // sequence descriptions & new lines, and the size after having made all the 204 | // replacements. 205 | printf("\n%d\n%d\n%d\n", input.size, sequences.size, postreplace_Size); 206 | return 0; 207 | } 208 | -------------------------------------------------------------------------------- /ref/k-nucleotide.c: -------------------------------------------------------------------------------- 1 | // The Computer Language Benchmarks Game 2 | // http://benchmarksgame.alioth.debian.org/ 3 | // 4 | // Contributed by Jeremy Zerfas 5 | 6 | // This controls the maximum length for each set of oligonucleotide frequencies 7 | // and each oligonucleotide count output by this program. 8 | #define MAXIMUM_OUTPUT_LENGTH 4096 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | // Define a custom hash function to use instead of khash's default hash 18 | // function. This custom hash function uses a simpler bit shift and XOR which 19 | // results in several percent faster performance compared to when khash's 20 | // default hash function is used. 21 | #define CUSTOM_HASH_FUNCTION(key) ((key) ^ (key)>>7) 22 | 23 | KHASH_INIT(oligonucleotide, uint64_t, uint32_t, 1, CUSTOM_HASH_FUNCTION 24 | , kh_int64_hash_equal) 25 | 26 | // intptr_t should be the native integer type on most sane systems. 27 | typedef intptr_t intnative_t; 28 | 29 | typedef struct { 30 | uint64_t key; 31 | uint32_t value; 32 | } element; 33 | 34 | 35 | // Macro to convert a nucleotide character to a code. Note that upper and lower 36 | // case ASCII letters only differ in the fifth bit from the right and we only 37 | // need the three least significant bits to differentiate the letters 'A', 'C', 38 | // 'G', and 'T'. Spaces in this array/string will never be used as long as 39 | // characters other than 'A', 'C', 'G', and 'T' aren't used. 40 | #define code_For_Nucleotide(nucleotide) (" \0 \1\3 \2"[nucleotide & 0x7]) 41 | 42 | 43 | // And one more macro to convert the codes back to nucleotide characters. 44 | #define nucleotide_For_Code(code) ("ACGT"[code & 0x3]) 45 | 46 | 47 | // Function to use when sorting elements with qsort() later. Elements with 48 | // larger values will come first and in cases of identical values then elements 49 | // with smaller keys will come first. 50 | static int element_Compare(const element * const left_Element 51 | , const element * const right_Element){ 52 | 53 | // Sort based on element values. 54 | if(left_Element->value < right_Element->value) return 1; 55 | if(left_Element->value > right_Element->value) return -1; 56 | 57 | // If we got here then both items have the same value so then sort based on 58 | // key. 59 | return left_Element->key > right_Element->key ? 1 : -1; 60 | } 61 | 62 | 63 | // Generate frequencies for all oligonucleotides in polynucleotide that are of 64 | // desired_Length_For_Oligonucleotides and then save it to output. 65 | static void generate_Frequencies_For_Desired_Length_Oligonucleotides( 66 | const char * const polynucleotide, const intnative_t polynucleotide_Length 67 | , const intnative_t desired_Length_For_Oligonucleotides, char * const output){ 68 | 69 | khash_t(oligonucleotide) * hash_Table=kh_init(oligonucleotide); 70 | 71 | uint64_t key=0; 72 | const uint64_t mask=((uint64_t)1<<2*desired_Length_For_Oligonucleotides)-1; 73 | 74 | // For the first several nucleotides we only need to append them to key in 75 | // preparation for the insertion of complete oligonucleotides to hash_Table. 76 | for(intnative_t i=0; i-1; j--){ 118 | oligonucleotide[j]=nucleotide_For_Code(elements_Array[i].key); 119 | elements_Array[i].key>>=2; 120 | } 121 | oligonucleotide[desired_Length_For_Oligonucleotides]='\0'; 122 | 123 | // Output the frequency for oligonucleotide to output. 124 | output_Position+=snprintf(output+output_Position 125 | , MAXIMUM_OUTPUT_LENGTH-output_Position, "%s %.3f\n", oligonucleotide 126 | , 100.0f*elements_Array[i].value 127 | /(polynucleotide_Length-desired_Length_For_Oligonucleotides+1)); 128 | } 129 | 130 | free(elements_Array); 131 | } 132 | 133 | 134 | // Generate a count for the number of times oligonucleotide appears in 135 | // polynucleotide and then save it to output. 136 | static void generate_Count_For_Oligonucleotide( 137 | const char * const polynucleotide, const intnative_t polynucleotide_Length 138 | , const char * const oligonucleotide, char * const output){ 139 | const intnative_t oligonucleotide_Length=strlen(oligonucleotide); 140 | 141 | khash_t(oligonucleotide) * const hash_Table=kh_init(oligonucleotide); 142 | 143 | uint64_t key=0; 144 | const uint64_t mask=((uint64_t)1<<2*oligonucleotide_Length)-1; 145 | 146 | // For the first several nucleotides we only need to append them to key in 147 | // preparation for the insertion of complete oligonucleotides to hash_Table. 148 | for(intnative_t i=0; iTHREE", buffer 188 | , sizeof(">THREE")-1)); 189 | 190 | // Start with 1 MB of storage for reading in the polynucleotide and grow 191 | // geometrically. 192 | intnative_t polynucleotide_Capacity=1048576; 193 | intnative_t polynucleotide_Length=0; 194 | char * polynucleotide=malloc(polynucleotide_Capacity); 195 | 196 | // Start reading and encoding the third polynucleotide. 197 | while(fgets(buffer, sizeof(buffer), stdin) && buffer[0]!='>'){ 198 | for(intnative_t i=0; buffer[i]!='\0'; i++) 199 | if(buffer[i]!='\n') 200 | polynucleotide[polynucleotide_Length++] 201 | =code_For_Nucleotide(buffer[i]); 202 | 203 | // Make sure we still have enough memory allocated for any potential 204 | // nucleotides in the next line. 205 | if(polynucleotide_Capacity-polynucleotide_Length 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | */ 25 | 26 | /* 27 | An example: 28 | 29 | #include "khash.h" 30 | KHASH_MAP_INIT_INT(32, char) 31 | int main() { 32 | int ret, is_missing; 33 | khiter_t k; 34 | khash_t(32) *h = kh_init(32); 35 | k = kh_put(32, h, 5, &ret); 36 | kh_value(h, k) = 10; 37 | k = kh_get(32, h, 10); 38 | is_missing = (k == kh_end(h)); 39 | k = kh_get(32, h, 5); 40 | kh_del(32, h, k); 41 | for (k = kh_begin(h); k != kh_end(h); ++k) 42 | if (kh_exist(h, k)) kh_value(h, k) = 1; 43 | kh_destroy(32, h); 44 | return 0; 45 | } 46 | */ 47 | 48 | /* 49 | 2013-05-02 (0.2.8): 50 | 51 | * Use quadratic probing. When the capacity is power of 2, stepping function 52 | i*(i+1)/2 guarantees to traverse each bucket. It is better than double 53 | hashing on cache performance and is more robust than linear probing. 54 | 55 | In theory, double hashing should be more robust than quadratic probing. 56 | However, my implementation is probably not for large hash tables, because 57 | the second hash function is closely tied to the first hash function, 58 | which reduce the effectiveness of double hashing. 59 | 60 | Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php 61 | 62 | 2011-12-29 (0.2.7): 63 | 64 | * Minor code clean up; no actual effect. 65 | 66 | 2011-09-16 (0.2.6): 67 | 68 | * The capacity is a power of 2. This seems to dramatically improve the 69 | speed for simple keys. Thank Zilong Tan for the suggestion. Reference: 70 | 71 | - http://code.google.com/p/ulib/ 72 | - http://nothings.org/computer/judy/ 73 | 74 | * Allow to optionally use linear probing which usually has better 75 | performance for random input. Double hashing is still the default as it 76 | is more robust to certain non-random input. 77 | 78 | * Added Wang's integer hash function (not used by default). This hash 79 | function is more robust to certain non-random input. 80 | 81 | 2011-02-14 (0.2.5): 82 | 83 | * Allow to declare global functions. 84 | 85 | 2009-09-26 (0.2.4): 86 | 87 | * Improve portability 88 | 89 | 2008-09-19 (0.2.3): 90 | 91 | * Corrected the example 92 | * Improved interfaces 93 | 94 | 2008-09-11 (0.2.2): 95 | 96 | * Improved speed a little in kh_put() 97 | 98 | 2008-09-10 (0.2.1): 99 | 100 | * Added kh_clear() 101 | * Fixed a compiling error 102 | 103 | 2008-09-02 (0.2.0): 104 | 105 | * Changed to token concatenation which increases flexibility. 106 | 107 | 2008-08-31 (0.1.2): 108 | 109 | * Fixed a bug in kh_get(), which has not been tested previously. 110 | 111 | 2008-08-31 (0.1.1): 112 | 113 | * Added destructor 114 | */ 115 | 116 | 117 | #ifndef __AC_KHASH_H 118 | #define __AC_KHASH_H 119 | 120 | /*! 121 | @header 122 | 123 | Generic hash table library. 124 | */ 125 | 126 | #define AC_VERSION_KHASH_H "0.2.8" 127 | 128 | #include 129 | #include 130 | #include 131 | 132 | /* compiler specific configuration */ 133 | 134 | #if UINT_MAX == 0xffffffffu 135 | typedef unsigned int khint32_t; 136 | #elif ULONG_MAX == 0xffffffffu 137 | typedef unsigned long khint32_t; 138 | #endif 139 | 140 | #if ULONG_MAX == ULLONG_MAX 141 | typedef unsigned long khint64_t; 142 | #else 143 | typedef unsigned long long khint64_t; 144 | #endif 145 | 146 | #ifndef kh_inline 147 | #ifdef _MSC_VER 148 | #define kh_inline __inline 149 | #else 150 | #define kh_inline inline 151 | #endif 152 | #endif /* kh_inline */ 153 | 154 | #ifndef klib_unused 155 | #if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3) 156 | #define klib_unused __attribute__ ((__unused__)) 157 | #else 158 | #define klib_unused 159 | #endif 160 | #endif /* klib_unused */ 161 | 162 | typedef khint32_t khint_t; 163 | typedef khint_t khiter_t; 164 | 165 | #define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2) 166 | #define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1) 167 | #define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3) 168 | #define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1))) 169 | #define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1))) 170 | #define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1))) 171 | #define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1)) 172 | 173 | #define __ac_fsize(m) ((m) < 16? 1 : (m)>>4) 174 | 175 | #ifndef kroundup32 176 | #define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) 177 | #endif 178 | 179 | #ifndef kcalloc 180 | #define kcalloc(N,Z) calloc(N,Z) 181 | #endif 182 | #ifndef kmalloc 183 | #define kmalloc(Z) malloc(Z) 184 | #endif 185 | #ifndef krealloc 186 | #define krealloc(P,Z) realloc(P,Z) 187 | #endif 188 | #ifndef kfree 189 | #define kfree(P) free(P) 190 | #endif 191 | 192 | static const double __ac_HASH_UPPER = 0.77; 193 | 194 | #define __KHASH_TYPE(name, khkey_t, khval_t) \ 195 | typedef struct kh_##name##_s { \ 196 | khint_t n_buckets, size, n_occupied, upper_bound; \ 197 | khint32_t *flags; \ 198 | khkey_t *keys; \ 199 | khval_t *vals; \ 200 | } kh_##name##_t; 201 | 202 | #define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \ 203 | extern kh_##name##_t *kh_init_##name(void); \ 204 | extern void kh_destroy_##name(kh_##name##_t *h); \ 205 | extern void kh_clear_##name(kh_##name##_t *h); \ 206 | extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \ 207 | extern int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \ 208 | extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \ 209 | extern void kh_del_##name(kh_##name##_t *h, khint_t x); 210 | 211 | #define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ 212 | SCOPE kh_##name##_t *kh_init_##name(void) { \ 213 | return (kh_##name##_t*)kcalloc(1, sizeof(kh_##name##_t)); \ 214 | } \ 215 | SCOPE void kh_destroy_##name(kh_##name##_t *h) \ 216 | { \ 217 | if (h) { \ 218 | kfree((void *)h->keys); kfree(h->flags); \ 219 | kfree((void *)h->vals); \ 220 | kfree(h); \ 221 | } \ 222 | } \ 223 | SCOPE void kh_clear_##name(kh_##name##_t *h) \ 224 | { \ 225 | if (h && h->flags) { \ 226 | memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \ 227 | h->size = h->n_occupied = 0; \ 228 | } \ 229 | } \ 230 | SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \ 231 | { \ 232 | if (h->n_buckets) { \ 233 | khint_t k, i, last, mask, step = 0; \ 234 | mask = h->n_buckets - 1; \ 235 | k = __hash_func(key); i = k & mask; \ 236 | last = i; \ 237 | while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \ 238 | i = (i + (++step)) & mask; \ 239 | if (i == last) return h->n_buckets; \ 240 | } \ 241 | return __ac_iseither(h->flags, i)? h->n_buckets : i; \ 242 | } else return 0; \ 243 | } \ 244 | SCOPE int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \ 245 | { /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \ 246 | khint32_t *new_flags = 0; \ 247 | khint_t j = 1; \ 248 | { \ 249 | kroundup32(new_n_buckets); \ 250 | if (new_n_buckets < 4) new_n_buckets = 4; \ 251 | if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; /* requested size is too small */ \ 252 | else { /* hash table size to be changed (shrink or expand); rehash */ \ 253 | new_flags = (khint32_t*)kmalloc(__ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ 254 | if (!new_flags) return -1; \ 255 | memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ 256 | if (h->n_buckets < new_n_buckets) { /* expand */ \ 257 | khkey_t *new_keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ 258 | if (!new_keys) { kfree(new_flags); return -1; } \ 259 | h->keys = new_keys; \ 260 | if (kh_is_map) { \ 261 | khval_t *new_vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \ 262 | if (!new_vals) { kfree(new_flags); return -1; } \ 263 | h->vals = new_vals; \ 264 | } \ 265 | } /* otherwise shrink */ \ 266 | } \ 267 | } \ 268 | if (j) { /* rehashing is needed */ \ 269 | for (j = 0; j != h->n_buckets; ++j) { \ 270 | if (__ac_iseither(h->flags, j) == 0) { \ 271 | khkey_t key = h->keys[j]; \ 272 | khval_t val; \ 273 | khint_t new_mask; \ 274 | new_mask = new_n_buckets - 1; \ 275 | if (kh_is_map) val = h->vals[j]; \ 276 | __ac_set_isdel_true(h->flags, j); \ 277 | while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \ 278 | khint_t k, i, step = 0; \ 279 | k = __hash_func(key); \ 280 | i = k & new_mask; \ 281 | while (!__ac_isempty(new_flags, i)) i = (i + (++step)) & new_mask; \ 282 | __ac_set_isempty_false(new_flags, i); \ 283 | if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { /* kick out the existing element */ \ 284 | { khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \ 285 | if (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \ 286 | __ac_set_isdel_true(h->flags, i); /* mark it as deleted in the old hash table */ \ 287 | } else { /* write the element and jump out of the loop */ \ 288 | h->keys[i] = key; \ 289 | if (kh_is_map) h->vals[i] = val; \ 290 | break; \ 291 | } \ 292 | } \ 293 | } \ 294 | } \ 295 | if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \ 296 | h->keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ 297 | if (kh_is_map) h->vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \ 298 | } \ 299 | kfree(h->flags); /* free the working space */ \ 300 | h->flags = new_flags; \ 301 | h->n_buckets = new_n_buckets; \ 302 | h->n_occupied = h->size; \ 303 | h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \ 304 | } \ 305 | return 0; \ 306 | } \ 307 | SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \ 308 | { \ 309 | khint_t x; \ 310 | if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \ 311 | if (h->n_buckets > (h->size<<1)) { \ 312 | if (kh_resize_##name(h, h->n_buckets - 1) < 0) { /* clear "deleted" elements */ \ 313 | *ret = -1; return h->n_buckets; \ 314 | } \ 315 | } else if (kh_resize_##name(h, h->n_buckets + 1) < 0) { /* expand the hash table */ \ 316 | *ret = -1; return h->n_buckets; \ 317 | } \ 318 | } /* TODO: to implement automatically shrinking; resize() already support shrinking */ \ 319 | { \ 320 | khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \ 321 | x = site = h->n_buckets; k = __hash_func(key); i = k & mask; \ 322 | if (__ac_isempty(h->flags, i)) x = i; /* for speed up */ \ 323 | else { \ 324 | last = i; \ 325 | while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \ 326 | if (__ac_isdel(h->flags, i)) site = i; \ 327 | i = (i + (++step)) & mask; \ 328 | if (i == last) { x = site; break; } \ 329 | } \ 330 | if (x == h->n_buckets) { \ 331 | if (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \ 332 | else x = i; \ 333 | } \ 334 | } \ 335 | } \ 336 | if (__ac_isempty(h->flags, x)) { /* not present at all */ \ 337 | h->keys[x] = key; \ 338 | __ac_set_isboth_false(h->flags, x); \ 339 | ++h->size; ++h->n_occupied; \ 340 | *ret = 1; \ 341 | } else if (__ac_isdel(h->flags, x)) { /* deleted */ \ 342 | h->keys[x] = key; \ 343 | __ac_set_isboth_false(h->flags, x); \ 344 | ++h->size; \ 345 | *ret = 2; \ 346 | } else *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \ 347 | return x; \ 348 | } \ 349 | SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \ 350 | { \ 351 | if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \ 352 | __ac_set_isdel_true(h->flags, x); \ 353 | --h->size; \ 354 | } \ 355 | } 356 | 357 | #define KHASH_DECLARE(name, khkey_t, khval_t) \ 358 | __KHASH_TYPE(name, khkey_t, khval_t) \ 359 | __KHASH_PROTOTYPES(name, khkey_t, khval_t) 360 | 361 | #define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ 362 | __KHASH_TYPE(name, khkey_t, khval_t) \ 363 | __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) 364 | 365 | #define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ 366 | KHASH_INIT2(name, static kh_inline klib_unused, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) 367 | 368 | /* --- BEGIN OF HASH FUNCTIONS --- */ 369 | 370 | /*! @function 371 | @abstract Integer hash function 372 | @param key The integer [khint32_t] 373 | @return The hash value [khint_t] 374 | */ 375 | #define kh_int_hash_func(key) (khint32_t)(key) 376 | /*! @function 377 | @abstract Integer comparison function 378 | */ 379 | #define kh_int_hash_equal(a, b) ((a) == (b)) 380 | /*! @function 381 | @abstract 64-bit integer hash function 382 | @param key The integer [khint64_t] 383 | @return The hash value [khint_t] 384 | */ 385 | #define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11) 386 | /*! @function 387 | @abstract 64-bit integer comparison function 388 | */ 389 | #define kh_int64_hash_equal(a, b) ((a) == (b)) 390 | /*! @function 391 | @abstract const char* hash function 392 | @param s Pointer to a null terminated string 393 | @return The hash value 394 | */ 395 | static kh_inline khint_t __ac_X31_hash_string(const char *s) 396 | { 397 | khint_t h = (khint_t)*s; 398 | if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)*s; 399 | return h; 400 | } 401 | /*! @function 402 | @abstract Another interface to const char* hash function 403 | @param key Pointer to a null terminated string [const char*] 404 | @return The hash value [khint_t] 405 | */ 406 | #define kh_str_hash_func(key) __ac_X31_hash_string(key) 407 | /*! @function 408 | @abstract Const char* comparison function 409 | */ 410 | #define kh_str_hash_equal(a, b) (strcmp(a, b) == 0) 411 | 412 | static kh_inline khint_t __ac_Wang_hash(khint_t key) 413 | { 414 | key += ~(key << 15); 415 | key ^= (key >> 10); 416 | key += (key << 3); 417 | key ^= (key >> 6); 418 | key += ~(key << 11); 419 | key ^= (key >> 16); 420 | return key; 421 | } 422 | #define kh_int_hash_func2(key) __ac_Wang_hash((khint_t)key) 423 | 424 | /* --- END OF HASH FUNCTIONS --- */ 425 | 426 | /* Other convenient macros... */ 427 | 428 | /*! 429 | @abstract Type of the hash table. 430 | @param name Name of the hash table [symbol] 431 | */ 432 | #define khash_t(name) kh_##name##_t 433 | 434 | /*! @function 435 | @abstract Initiate a hash table. 436 | @param name Name of the hash table [symbol] 437 | @return Pointer to the hash table [khash_t(name)*] 438 | */ 439 | #define kh_init(name) kh_init_##name() 440 | 441 | /*! @function 442 | @abstract Destroy a hash table. 443 | @param name Name of the hash table [symbol] 444 | @param h Pointer to the hash table [khash_t(name)*] 445 | */ 446 | #define kh_destroy(name, h) kh_destroy_##name(h) 447 | 448 | /*! @function 449 | @abstract Reset a hash table without deallocating memory. 450 | @param name Name of the hash table [symbol] 451 | @param h Pointer to the hash table [khash_t(name)*] 452 | */ 453 | #define kh_clear(name, h) kh_clear_##name(h) 454 | 455 | /*! @function 456 | @abstract Resize a hash table. 457 | @param name Name of the hash table [symbol] 458 | @param h Pointer to the hash table [khash_t(name)*] 459 | @param s New size [khint_t] 460 | */ 461 | #define kh_resize(name, h, s) kh_resize_##name(h, s) 462 | 463 | /*! @function 464 | @abstract Insert a key to the hash table. 465 | @param name Name of the hash table [symbol] 466 | @param h Pointer to the hash table [khash_t(name)*] 467 | @param k Key [type of keys] 468 | @param r Extra return code: -1 if the operation failed; 469 | 0 if the key is present in the hash table; 470 | 1 if the bucket is empty (never used); 2 if the element in 471 | the bucket has been deleted [int*] 472 | @return Iterator to the inserted element [khint_t] 473 | */ 474 | #define kh_put(name, h, k, r) kh_put_##name(h, k, r) 475 | 476 | /*! @function 477 | @abstract Retrieve a key from the hash table. 478 | @param name Name of the hash table [symbol] 479 | @param h Pointer to the hash table [khash_t(name)*] 480 | @param k Key [type of keys] 481 | @return Iterator to the found element, or kh_end(h) if the element is absent [khint_t] 482 | */ 483 | #define kh_get(name, h, k) kh_get_##name(h, k) 484 | 485 | /*! @function 486 | @abstract Remove a key from the hash table. 487 | @param name Name of the hash table [symbol] 488 | @param h Pointer to the hash table [khash_t(name)*] 489 | @param k Iterator to the element to be deleted [khint_t] 490 | */ 491 | #define kh_del(name, h, k) kh_del_##name(h, k) 492 | 493 | /*! @function 494 | @abstract Test whether a bucket contains data. 495 | @param h Pointer to the hash table [khash_t(name)*] 496 | @param x Iterator to the bucket [khint_t] 497 | @return 1 if containing data; 0 otherwise [int] 498 | */ 499 | #define kh_exist(h, x) (!__ac_iseither((h)->flags, (x))) 500 | 501 | /*! @function 502 | @abstract Get key given an iterator 503 | @param h Pointer to the hash table [khash_t(name)*] 504 | @param x Iterator to the bucket [khint_t] 505 | @return Key [type of keys] 506 | */ 507 | #define kh_key(h, x) ((h)->keys[x]) 508 | 509 | /*! @function 510 | @abstract Get value given an iterator 511 | @param h Pointer to the hash table [khash_t(name)*] 512 | @param x Iterator to the bucket [khint_t] 513 | @return Value [type of values] 514 | @discussion For hash sets, calling this results in segfault. 515 | */ 516 | #define kh_val(h, x) ((h)->vals[x]) 517 | 518 | /*! @function 519 | @abstract Alias of kh_val() 520 | */ 521 | #define kh_value(h, x) ((h)->vals[x]) 522 | 523 | /*! @function 524 | @abstract Get the start iterator 525 | @param h Pointer to the hash table [khash_t(name)*] 526 | @return The start iterator [khint_t] 527 | */ 528 | #define kh_begin(h) (khint_t)(0) 529 | 530 | /*! @function 531 | @abstract Get the end iterator 532 | @param h Pointer to the hash table [khash_t(name)*] 533 | @return The end iterator [khint_t] 534 | */ 535 | #define kh_end(h) ((h)->n_buckets) 536 | 537 | /*! @function 538 | @abstract Get the number of elements in the hash table 539 | @param h Pointer to the hash table [khash_t(name)*] 540 | @return Number of elements in the hash table [khint_t] 541 | */ 542 | #define kh_size(h) ((h)->size) 543 | 544 | /*! @function 545 | @abstract Get the number of buckets in the hash table 546 | @param h Pointer to the hash table [khash_t(name)*] 547 | @return Number of buckets in the hash table [khint_t] 548 | */ 549 | #define kh_n_buckets(h) ((h)->n_buckets) 550 | 551 | /*! @function 552 | @abstract Iterate over the entries in the hash table 553 | @param h Pointer to the hash table [khash_t(name)*] 554 | @param kvar Variable to which key will be assigned 555 | @param vvar Variable to which value will be assigned 556 | @param code Block of code to execute 557 | */ 558 | #define kh_foreach(h, kvar, vvar, code) { khint_t __i; \ 559 | for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ 560 | if (!kh_exist(h,__i)) continue; \ 561 | (kvar) = kh_key(h,__i); \ 562 | (vvar) = kh_val(h,__i); \ 563 | code; \ 564 | } } 565 | 566 | /*! @function 567 | @abstract Iterate over the values in the hash table 568 | @param h Pointer to the hash table [khash_t(name)*] 569 | @param vvar Variable to which value will be assigned 570 | @param code Block of code to execute 571 | */ 572 | #define kh_foreach_value(h, vvar, code) { khint_t __i; \ 573 | for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ 574 | if (!kh_exist(h,__i)) continue; \ 575 | (vvar) = kh_val(h,__i); \ 576 | code; \ 577 | } } 578 | 579 | /* More conenient interfaces */ 580 | 581 | /*! @function 582 | @abstract Instantiate a hash set containing integer keys 583 | @param name Name of the hash table [symbol] 584 | */ 585 | #define KHASH_SET_INIT_INT(name) \ 586 | KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal) 587 | 588 | /*! @function 589 | @abstract Instantiate a hash map containing integer keys 590 | @param name Name of the hash table [symbol] 591 | @param khval_t Type of values [type] 592 | */ 593 | #define KHASH_MAP_INIT_INT(name, khval_t) \ 594 | KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal) 595 | 596 | /*! @function 597 | @abstract Instantiate a hash map containing 64-bit integer keys 598 | @param name Name of the hash table [symbol] 599 | */ 600 | #define KHASH_SET_INIT_INT64(name) \ 601 | KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal) 602 | 603 | /*! @function 604 | @abstract Instantiate a hash map containing 64-bit integer keys 605 | @param name Name of the hash table [symbol] 606 | @param khval_t Type of values [type] 607 | */ 608 | #define KHASH_MAP_INIT_INT64(name, khval_t) \ 609 | KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal) 610 | 611 | typedef const char *kh_cstr_t; 612 | /*! @function 613 | @abstract Instantiate a hash map containing const char* keys 614 | @param name Name of the hash table [symbol] 615 | */ 616 | #define KHASH_SET_INIT_STR(name) \ 617 | KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal) 618 | 619 | /*! @function 620 | @abstract Instantiate a hash map containing const char* keys 621 | @param name Name of the hash table [symbol] 622 | @param khval_t Type of values [type] 623 | */ 624 | #define KHASH_MAP_INIT_STR(name, khval_t) \ 625 | KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal) 626 | 627 | #endif /* __AC_KHASH_H */ 628 | --------------------------------------------------------------------------------