diff --git a/test/makefile b/test/makefile index 6865ee0..af3137a 100644 --- a/test/makefile +++ b/test/makefile @@ -37,7 +37,7 @@ run: $(SRC) $(OUTPUT) ./$(OUTPUT) verify: $(SRC) $(OUTPUT) - ./$(OUTPUT) | grep "NOT passed" -A 1 --group-separator='' || true + ./$(OUTPUT) | grep "NOT passed" -A 2 --group-separator='' || true time-linux: @echo "Requires /bin/time, found on GNU/Linux systems" && echo diff --git a/test/test b/test/test index cd8449d..d2f0a34 100755 Binary files a/test/test and b/test/test differ diff --git a/test/test.c b/test/test.c index 70ea1f9..cd16c62 100644 --- a/test/test.c +++ b/test/test.c @@ -4,8 +4,7 @@ #include #include -#define PERCENTAGE_TOLERANCE 1.0 / 1000.0 -#define PERCENTAGE_TOLERANCE_LOGNORMAL 5.0 / 1000.0 +#define TOLERANCE 5.0 / 1000.0 #define MAX_NAME_LENGTH 500 // Structs @@ -27,7 +26,7 @@ void test_array_expectations(struct array_expectations e) double std = array_std(e.array, e.n); double delta_std = std - e.expected_std; - if (fabs(delta_mean) / fabs(mean) > e.tolerance) { + if ((fabs(delta_mean) / fabs(mean) > e.tolerance) && (fabs(delta_mean) > e.tolerance)) { printf("[-] Mean test for %s NOT passed.\n", e.name); printf("Mean of %s: %f, vs expected mean: %f\n", e.name, mean, e.expected_mean); printf("delta: %f, relative delta: %f\n", delta_mean, delta_mean / fabs(mean)); @@ -35,7 +34,7 @@ void test_array_expectations(struct array_expectations e) printf("[x] Mean test for %s PASSED\n", e.name); } - if (fabs(delta_std) / fabs(std) > e.tolerance) { + if ((fabs(delta_std) / fabs(std) > e.tolerance) && (fabs(delta_std) > e.tolerance)) { printf("[-] Std test for %s NOT passed.\n", e.name); printf("Std of %s: %f, vs expected std: %f\n", e.name, std, e.expected_std); printf("delta: %f, relative delta: %f\n", delta_std, delta_std / fabs(std)); @@ -62,7 +61,7 @@ void test_unit_uniform(uint64_t* seed) .name = "unit uniform", .expected_mean = 0.5, .expected_std = sqrt(1.0 / 12.0), - .tolerance = 1 * PERCENTAGE_TOLERANCE, + .tolerance = TOLERANCE, }; test_array_expectations(expectations); @@ -87,7 +86,7 @@ void test_uniform(double start, double end, uint64_t* seed) .name = name, .expected_mean = (start + end) / 2, .expected_std = sqrt(1.0 / 12.0) * fabs(end - start), - .tolerance = fabs(end - start) * PERCENTAGE_TOLERANCE, + .tolerance = fabs(end - start) * TOLERANCE, }; test_array_expectations(expectations); @@ -111,7 +110,7 @@ void test_unit_normal(uint64_t* seed) .name = "unit normal", .expected_mean = 0, .expected_std = 1, - .tolerance = 1 * PERCENTAGE_TOLERANCE, + .tolerance = TOLERANCE, }; test_array_expectations(expectations); @@ -136,7 +135,7 @@ void test_normal(double mean, double std, uint64_t* seed) .name = name, .expected_mean = mean, .expected_std = std, - .tolerance = std * PERCENTAGE_TOLERANCE, + .tolerance = TOLERANCE, }; test_array_expectations(expectations); @@ -162,7 +161,41 @@ void test_lognormal(double logmean, double logstd, uint64_t* seed) .name = name, .expected_mean = exp(logmean + pow(logstd, 2) / 2), .expected_std = sqrt((exp(pow(logstd, 2)) - 1) * exp(2 * logmean + pow(logstd, 2))), - .tolerance = exp(logstd) * PERCENTAGE_TOLERANCE_LOGNORMAL, + .tolerance = TOLERANCE, + }; + + test_array_expectations(expectations); + free(name); + free(lognormal_array); +} + +// Test lognormal to +void test_to(double low, double high, uint64_t* seed) +{ + int n = 10 * 1000 * 1000; + double* lognormal_array = malloc(sizeof(double) * n); + + for (int i = 0; i < n; i++) { + lognormal_array[i] = sample_to(low, high, seed); + } + + + char* name = malloc(MAX_NAME_LENGTH * sizeof(char)); + snprintf(name, MAX_NAME_LENGTH, "to(%f, %f)", low, high); + + const double NORMAL95CONFIDENCE = 1.6448536269514722; + double loglow = logf(low); + double loghigh = logf(high); + double logmean = (loglow + loghigh) / 2; + double logstd = (loghigh - loglow) / (2.0 * NORMAL95CONFIDENCE); + + struct array_expectations expectations = { + .array = lognormal_array, + .n = n, + .name = name, + .expected_mean = exp(logmean + pow(logstd, 2) / 2), + .expected_std = sqrt((exp(pow(logstd, 2)) - 1) * exp(2 * logmean + pow(logstd, 2))), + .tolerance = TOLERANCE, }; test_array_expectations(expectations); @@ -189,7 +222,7 @@ void test_beta(double a, double b, uint64_t* seed) .name = name, .expected_mean = a / (a + b), .expected_std = sqrt((a * b) / (pow(a + b, 2) * (a + b + 1))), - .tolerance = PERCENTAGE_TOLERANCE, + .tolerance = TOLERANCE, }; test_array_expectations(expectations); @@ -244,8 +277,8 @@ int main() } } - printf("Testing very small lognormals\n"); - for (int i = 0; i < 10; i++) { + printf("Testing smaller lognormals\n"); + for (int i = 0; i < 100; i++) { double mean = sample_uniform(-1, 1, seed); double std = sample_uniform(0, 1, seed); if (std > 0) { @@ -253,8 +286,8 @@ int main() } } - printf("Testing small lognormals\n"); - for (int i = 0; i < 10; i++) { + printf("Testing larger lognormals\n"); + for (int i = 0; i < 100; i++) { double mean = sample_uniform(-1, 5, seed); double std = sample_uniform(0, 5, seed); if (std > 0) { @@ -262,6 +295,15 @@ int main() } } + printf("Testing lognormals — sample_to(low, high) syntax\n"); + for (int i = 0; i < 100; i++) { + double low = sample_uniform(0, 1000 * 1000, seed); + double high = sample_uniform(0, 1000 * 1000, seed); + if (low < high) { + test_to(low, high, seed); + } + } + printf("Testing beta distribution\n"); for (int i = 0; i < 100; i++) { double a = sample_uniform(0, 1000, seed);