Skip to content

Instantly share code, notes, and snippets.

@scurest
Created October 24, 2017 19:17
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 scurest/89078cd04a0cbbb7a8e8bec77577fca7 to your computer and use it in GitHub Desktop.
Save scurest/89078cd04a0cbbb7a8e8bec77577fca7 to your computer and use it in GitHub Desktop.
Tests rountripping floating-point numbers by printfing them in zig and then scanfing them in C
#include <stdio.h>
#include <stdint.h>
#include <math.h>
uint32_t f2i(float x) { return *(uint32_t*)(&x); }
float i2f(uint32_t x) { return *(float*)(&x); }
int main() {
uint32_t i = 0;
while (1) {
if (!(isnan(i2f(i)) || isinf(i2f(i)))) {
float x;
if (scanf("%f", &x) != 1) {
printf("stopped abruptly on i=%u\n", i);
return 1;
}
if (f2i(x) != i) {
printf("failed on i = %u\n", i);
return 1;
}
}
if (i == 0x80000000u) break;
++i;
}
printf("ok\n");
return 0;
}
const io = @import("std").io;
const math = @import("std").math;
pub fn main() -> %void {
var i: u32 = 0;
while (true) {
const x = @bitCast(f32, i);
if (!(math.isNan(x) or math.isInf(x))) {
%%io.stdout.printf("{}\n", x);
}
if (i == 0x80000000) break;
i += 1;
}
}
#include <stdio.h>
#include <stdint.h>
#include <math.h>
uint64_t d2l(double x) { return *(uint64_t*)(&x); }
double l2d(uint64_t x) { return *(double*)(&x); }
//xoroshiro128+
uint64_t s[2];
static inline uint64_t rotl(const uint64_t x, int k) {
return (x << k) | (x >> (64 - k));
}
uint64_t next(void) {
const uint64_t s0 = s[0];
uint64_t s1 = s[1];
const uint64_t result = s0 + s1;
s1 ^= s0;
s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b
s[1] = rotl(s1, 36); // c
return result;
}
int main() {
uint32_t num;
if (!scanf("%lu %lu %u", &s[0], &s[1], &num)) {
printf("error\n");
return 1;
}
printf("s[0]=%lu, s[1]=%lu\n", s[0], s[1]);
for (uint32_t i = 0; i != num; ++i) {
uint64_t val = next();
double x = l2d(val);
if (!(isnan(x) || isinf(x))) {
double input;
if (scanf("%lf", &input) != 1) {
printf("stopped abruptly on val=%lu\n", val);
return 1;
}
if (d2l(input) != val) {
printf("failed on val = %lu\n", val);
return 1;
}
}
}
printf("ok\n");
return 0;
}
const io = @import("std").io;
const math = @import("std").math;
const os = @import("std").os;
//xoroshiro128+
var s: [2]u64 = [2]u64 {0, 0};
fn rotl(x: u64, k: u6) -> u64 {
(x << k) | (x >> u6((u32(64) - u32(k))))
}
fn next() -> u64 {
const s0 = s[0];
var s1 = s[1];
const result = s0 +% s1;
s1 ^= s0;
s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b
s[1] = rotl(s1, 36); // c
result
}
// Convert eight bytes to u64 in LE order.
fn buf2u64(b: []u8) -> u64 {
var res: u64 = 0;
{ var i: usize = 0; while (i != 8) : (i += 1) {
res <<= 8;
res |= b[i];
}}
res
}
pub fn main() -> %void {
var buf: [16]u8 = undefined;
%%os.getRandomBytes(buf[0..16]);
s[0] = buf2u64(buf[0..8]);
s[1] = buf2u64(buf[8..16]);
// Number of trials
const num: u32 = 1000000;
%%io.stdout.printf("{} {} {}\n", s[0], s[1], num);
var i: u32 = 0;
while (i != num) : (i += 1) {
const x = @bitCast(f64, next());
if (!(math.isNan(x) or math.isInf(x))) {
%%io.stdout.printf("{}\n", x);
}
}
}
# For exhaustive testing of all positive f32s (+ negative zero)
zig build-exe f32-out.zig
gcc -O2 f32-in.c -of32-in
time ./f32-out | ./f32-in
# For random testing of f64
zig build-exe rand-out.zig
gcc -O2 rand-in.c -orand-in
time ./rand-out | ./rand-in
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment