Created
November 16, 2012 18:05
-
-
Save sononum/4089490 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
// | |
// 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; | |
} |
This file contains hidden or 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
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