Skip to content

Instantly share code, notes, and snippets.

@tiehuis
Last active April 3, 2019 04:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tiehuis/272ac675f1f48aea3fccc7fee1f7e9e9 to your computer and use it in GitHub Desktop.
Save tiehuis/272ac675f1f48aea3fccc7fee1f7e9e9 to your computer and use it in GitHub Desktop.
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);
}
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