Last active
April 3, 2019 04:25
-
-
Save tiehuis/272ac675f1f48aea3fccc7fee1f7e9e9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
const builtin = @import("builtin"); | |
const Builder = std.build.Builder; | |
pub fn build(b: *Builder) void { | |
const exe = b.addExecutable("fuzz", "fuzz.zig"); | |
exe.setBuildMode(builtin.Mode.ReleaseFast); | |
exe.linkSystemLibrary("c"); | |
exe.linkSystemLibrary("gmp"); | |
exe.setOutputDir("."); | |
b.default_step.dependOn(&exe.step); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
const big = std.math.big; | |
const Int = big.Int; | |
const Limb = big.Limb; | |
const c = @cImport({ | |
@cDefine("__GMP_FORCE_mpz_abs", ""); // Avoid inlines since we don't parse correctly | |
@cDefine("__GMP_FORCE_mpz_neg", ""); | |
// NOTE: modified randstate enum to avoid duplicate entry in gmp.h by removing LC variant. | |
@cInclude("gmp.h"); | |
@cInclude("stdio.h"); | |
}); | |
var allocator = std.heap.c_allocator; | |
const Aupper = 4096; | |
const Alower = 1; | |
const Rc = 4; // Result count | |
const Ac = 4; // Arg count | |
var Zr: [Rc]Int = undefined; // Zig Results | |
var Za: [Ac]Int = undefined; // Zig Args | |
// GMP Results | |
var Gr_s: [Rc]c.__mpz_struct = undefined; | |
const Gr = blk: { | |
var a: [Rc]*c.__mpz_struct = undefined; | |
for (a) |_, i| { | |
a[i] = &Gr_s[i]; | |
} | |
break :blk a; | |
}; | |
// GMP Args | |
var Ga_s: [Ac]c.__mpz_struct = undefined; | |
const Ga = blk: { | |
var a: [Ac]*c.__mpz_struct = undefined; | |
for (a) |_, i| { | |
a[i] = &Ga_s[i]; | |
} | |
break :blk a; | |
}; | |
var Gscratch_s: c.mpz_t = undefined; | |
const Gscratch = &Gscratch_s[0]; | |
var Grandom_s: c.gmp_randstate_t = undefined; | |
const Grandom = &Grandom_s[0]; | |
var prng: std.rand.DefaultPrng = undefined; | |
const io_order = -1; // least-significant | |
const io_size = Limb.bit_count / 8; | |
const io_endian = 0; // native | |
fn randomA(n: usize) !void { | |
std.debug.assert(n < Ac); | |
for (Za[0..n]) |_, i| { | |
// NOTE: These are always positive. | |
const bitcount = prng.random.intRangeLessThan(usize, Alower, Aupper); | |
c.mpz_rrandomb(Ga[i], Grandom, bitcount); | |
const limb_count = (c.mpz_sizeinbase(Ga[i], 2) + (Limb.bit_count - 1)) / Limb.bit_count; | |
try Za[i].ensureCapacity(limb_count); | |
var countp: usize = undefined; | |
_ = c.mpz_export(Za[i].limbs.ptr, &countp, io_order, io_size, io_endian, 0, Ga[i]); | |
std.debug.assert(limb_count == countp); | |
Za[i].len = countp; | |
} | |
} | |
fn ZtoG(g: *c.__mpz_struct, z: Int) void { | |
c.mpz_import(g, z.len, io_order, io_size, io_endian, 0, z.limbs.ptr); | |
c.mpz_abs(g, g); | |
if (!z.positive) { | |
c.mpz_neg(g, g); | |
} | |
} | |
fn equalR(an: usize, op: u8, rn: usize) !void { | |
std.debug.assert(rn < Rc); | |
for (Zr[0..rn]) |_, i| { | |
ZtoG(Gscratch, Zr[i]); | |
if (c.mpz_cmp(Gr[i], Gscratch) != 0) { | |
for (Ga[0..an]) |ga, j| { | |
_ = c.gmp_printf(c"Ga[%d]: %Zd\n\n", j, ga); | |
} | |
_ = c.gmp_printf(c"%c\n\n", op); | |
for (Gr[0..rn]) |gr, j| { | |
_ = c.gmp_printf( | |
c\\Gr[%d] | |
c\\ %Zd | |
c\\ | |
c\\ | |
, j, gr); | |
} | |
for (Zr[0..rn]) |zr, j| { | |
ZtoG(Gscratch, zr); | |
_ = c.gmp_printf( | |
c\\Zr[%d] | |
c\\ %Zd | |
c\\ | |
c\\ | |
, j, Gscratch); | |
} | |
return error.TestFailure; | |
} | |
} | |
} | |
const Op = enum { | |
Div, | |
Mul, | |
Add, | |
Sub, | |
}; | |
pub fn main() !void { | |
var buf: [8]u8 = undefined; | |
try std.os.getRandomBytes(buf[0..]); | |
const seed = std.mem.readIntSliceLittle(u64, buf[0..8]); | |
prng = std.rand.DefaultPrng.init(seed); | |
for (Zr) |_, i| { | |
Zr[i] = try Int.init(allocator); | |
c.mpz_init(Gr[i]); | |
} | |
for (Za) |_, i| { | |
Za[i] = try Int.init(allocator); | |
c.mpz_init(Ga[i]); | |
} | |
c.mpz_init(Gscratch); | |
c.gmp_randinit_default(Grandom); | |
c.gmp_randseed_ui(Grandom, prng.random.int(c_ulong)); | |
var i: usize = 0; | |
while (true) : (i += 1) { | |
const op = prng.random.int(@TagType(Op)); | |
switch (@intToEnum(Op, op)) { | |
Op.Div => { | |
try randomA(2); | |
if (!Za[1].eqZero()) { | |
try Int.divTrunc(&Zr[0], &Zr[1], Za[0], Za[1]); | |
c.mpz_tdiv_qr(Gr[0], Gr[1], Ga[0], Ga[1]); | |
try equalR(2, '/', 2); | |
} | |
}, | |
Op.Mul => { | |
try randomA(2); | |
try Zr[0].mul(Za[0], Za[1]); | |
c.mpz_mul(Gr[0], Ga[0], Ga[1]); | |
try equalR(2, '*', 1); | |
}, | |
Op.Add => { | |
try randomA(2); | |
try Zr[0].add(Za[0], Za[1]); | |
c.mpz_add(Gr[0], Ga[0], Ga[1]); | |
try equalR(2, '+', 1); | |
}, | |
Op.Sub => { | |
try randomA(2); | |
try Zr[0].sub(Za[0], Za[1]); | |
c.mpz_sub(Gr[0], Ga[0], Ga[1]); | |
try equalR(2, '-', 1); | |
}, | |
} | |
if (i % 10000 == 0) { | |
std.debug.warn("\x1b[A\x1b[2Kcount: {}\n", i); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment