Skip to content

Instantly share code, notes, and snippets.

@sononum
Created November 16, 2012 18:05
Show Gist options
  • Save sononum/4089490 to your computer and use it in GitHub Desktop.
Save sononum/4089490 to your computer and use it in GitHub Desktop.
//
// main.c
// detrand
//
// Created by Ulrich Zurucker on 11/16/12.
// Copyright (c) 2012 cmrr.de. All rights reserved.
//
#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>
#include <math.h>
#define EPSILON (1.0E-12)
typedef struct {
long long num, denom;
} rational_t;
static long long gcd(long long a, long long b) {
return b == 0 ? a : gcd(b, a % b);
}
void rational_init(rational_t* out_rat, long long numerator, long long denominator) {
if (denominator < 0) {
numerator *= -1;
denominator *= -1;
}
long long g = abs(gcd(numerator, denominator));
out_rat->num = numerator / g;
out_rat->denom = denominator / g;
}
void rational_add(rational_t* out_rat, rational_t* a) {
long long n = out_rat->num + a->num;
long long d = out_rat->denom * a->denom;
rational_init(out_rat, n, d);
}
void rational_sub(rational_t* out_rat, rational_t* a) {
long long n = out_rat->num * a->denom - a->num * out_rat->denom;
long long d = out_rat->denom * a->denom;
rational_init(out_rat, n, d);
}
void rational_mul(rational_t* out_rat, rational_t* a) {
long long n = out_rat->num * a->num;
long long d = out_rat->denom * a->denom;
rational_init(out_rat, n, d);
}
void rational_div(rational_t* out_rat, rational_t* a) {
long long n = out_rat->num * a->denom;
long long d = out_rat->denom * a->num;
rational_init(out_rat, n, d);
}
typedef struct {
unsigned char hash1[SHA_DIGEST_LENGTH];
unsigned char hash2[SHA_DIGEST_LENGTH];
unsigned char* readhash;
unsigned char* writehash;
long long position;
} det_rand_t;
void det_rand_init(det_rand_t* in_detrand, const void* init_data, size_t data_len) {
in_detrand->position = 0;
in_detrand->writehash = in_detrand->readhash = in_detrand->hash1;
SHA1(init_data, data_len, in_detrand->writehash);
in_detrand->writehash = in_detrand->hash2;
}
void det_rand_get_char(det_rand_t* in_det_rand, unsigned char* out_char) {
unsigned bufferpos = in_det_rand->position % SHA_DIGEST_LENGTH;
if (!bufferpos) {
SHA1(in_det_rand->readhash, SHA_DIGEST_LENGTH, in_det_rand->writehash);
unsigned char* swap = in_det_rand->readhash;
in_det_rand->readhash = in_det_rand->writehash;
in_det_rand->writehash = swap;
}
in_det_rand->position++;
*out_char = in_det_rand->readhash[bufferpos];
}
void det_rand_get_data(det_rand_t* in_det_rand, void* out_data, size_t len) {
for (int i=0; i<len; ++i) {
det_rand_get_char(in_det_rand, &out_data[i]);
}
}
static int do_test(float a, float b, float c, rational_t* qa, rational_t* qb, rational_t *qc) {
double d1 = (a - b);
double e1 = c * (a-b);
double e2 = a * c - b * c;
rational_sub(qa, qb);
rational_mul(qc, qa);
double exact = (double) qc->num / (double) qc->denom;
double k1 = fabs(e1 - exact);
double k2 = fabs(e2 - exact);
if (k1 > EPSILON || k2 > EPSILON) {
double deltaa = fabs(1.0 - e1 / exact);
double deltab = fabs(1.0 - e2 / exact);
if (deltaa < deltab) {
return 1;
} else if (deltaa > deltab) {
return -1;
}
}
return 0;
}
int main(int argc, char *argv[])
{
const char* data = "when i grow up i want to be a computer scientist";
size_t length = strlen(data);
det_rand_t detrand;
det_rand_init(&detrand, data, length);
long awin = 0;
long bwin = 0;
long ok = 0;
long count = 1;
printf("a,b,c,(a-b)*c,delta,a*c-b*c,delta,winner\n");
while (1) {
int an, ad, bn, bd, cn, cd;
det_rand_get_data(&detrand, &an, sizeof(an));
det_rand_get_data(&detrand, &bn, sizeof(bn));
det_rand_get_data(&detrand, &cn, sizeof(cn));
det_rand_get_data(&detrand, &ad, sizeof(ad));
det_rand_get_data(&detrand, &bd, sizeof(bd));
det_rand_get_data(&detrand, &cd, sizeof(cd));
an /= 8192;
bn /= 8192;
cn /= 8192;
ad /= 8192;
bd /= 8192;
cd /= 8192;
unsigned char ans, bns, cns, ads, bds, cds;
det_rand_get_char(&detrand, &ans);
det_rand_get_char(&detrand, &bns);
det_rand_get_char(&detrand, &cns);
det_rand_get_char(&detrand, &ads);
det_rand_get_char(&detrand, &bds);
det_rand_get_char(&detrand, &cds);
ads &= 0x0F;
bds &= 0x0F;
cds &= 0x0F;
ans &= 0x0F;
bns &= 0x0F;
cns &= 0x0F;
an >>= 8 - ans;
bn >>= 8 - bns;
cn >>= 8 - cns;
ad >>= 8 - ads;
bd >>= 8 - bds;
cd >>= 8 - cds;
float a, b, c;
if (ad && bd && cd && an && bn && cn) {
a = (float) an / (float) ad;
b = (float) bn / (float) bd;
c = (float) cn / (float) cd;
rational_t qa, qb, qc;
rational_init(&qa, an, ad);
rational_init(&qb, bn, bd);
rational_init(&qc, cn, cd);
int r = do_test(a, b, c, &qa, &qb, &qc);
if (r == -1) {
bwin++;
} else if (r == 1) {
awin++;
} else if (r == 0) {
ok++;
}
count++;
}
if (count % 100000 == 0) {
printf("A:\t%d\tB:\t%d\tok:\t%d\n", awin * 1000 / count, bwin * 1000 / count, ok * 1000 / count);
}
}
return 0;
}
all: detrand
detrand: main.c
cc -o detrand main.c -lssl -lcrypto
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment