forked from github/server
short and sweet math with fractions.
goinf to use this for magres.
This commit is contained in:
parent
158e0646e1
commit
234eb62226
|
@ -6,6 +6,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <util/log.h>
|
#include <util/log.h>
|
||||||
|
#include <util/variant.h>
|
||||||
|
|
||||||
#pragma warning(disable: 4210)
|
#pragma warning(disable: 4210)
|
||||||
|
|
||||||
|
@ -85,6 +86,7 @@ int RunAllTests(int argc, char *argv[])
|
||||||
ADD_SUITE(unicode);
|
ADD_SUITE(unicode);
|
||||||
ADD_SUITE(strings);
|
ADD_SUITE(strings);
|
||||||
ADD_SUITE(log);
|
ADD_SUITE(log);
|
||||||
|
ADD_SUITE(variant);
|
||||||
ADD_SUITE(rng);
|
ADD_SUITE(rng);
|
||||||
/* items */
|
/* items */
|
||||||
ADD_SUITE(xerewards);
|
ADD_SUITE(xerewards);
|
||||||
|
|
|
@ -28,6 +28,7 @@ log.test.c
|
||||||
# translation.test.c
|
# translation.test.c
|
||||||
umlaut.test.c
|
umlaut.test.c
|
||||||
unicode.test.c
|
unicode.test.c
|
||||||
|
variant.test.c
|
||||||
# xml.test.c
|
# xml.test.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,39 @@
|
||||||
|
#include <platform.h>
|
||||||
#include "variant.h"
|
#include "variant.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
static int lcd(int a, int b) {
|
static int gcd(int a, int b) {
|
||||||
return a * b;
|
const int primes[] = { 3, 5, 7, 11, 13, 17, 19, 23, 0 };
|
||||||
|
int i = 0, g = 1, p = 2;
|
||||||
|
while (p && p <= a && p <= b) {
|
||||||
|
if (a % p == 0 && b % p == 0) {
|
||||||
|
a /= p;
|
||||||
|
b /= p;
|
||||||
|
g *= p;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p = primes[i++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
variant frac_add(variant a, variant b)
|
static int lcm(int a, int b) {
|
||||||
|
int x;
|
||||||
|
if (a == b) return a;
|
||||||
|
x = (a * b);
|
||||||
|
x = (x > 0 ? x : -x) / gcd(a, b);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
variant frac_make(int num, int den)
|
||||||
{
|
{
|
||||||
int num, den;
|
|
||||||
variant v;
|
variant v;
|
||||||
den = lcd(a.sa[1], b.sa[1]);
|
int g = gcd(num, den);
|
||||||
num = a.sa[0] * lcd / a.sa[1] + b.sa[0] * lcd / b.sa[1];
|
num /= g;
|
||||||
|
den /= g;
|
||||||
assert(num >= SHRT_MIN && num <= SHRT_MAX);
|
assert(num >= SHRT_MIN && num <= SHRT_MAX);
|
||||||
assert(den >= SHRT_MIN && den <= SHRT_MAX);
|
assert(den >= SHRT_MIN && den <= SHRT_MAX);
|
||||||
v.sa[0] = (short)num;
|
v.sa[0] = (short)num;
|
||||||
|
@ -18,19 +41,20 @@ variant frac_add(variant a, variant b)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variant frac_add(variant a, variant b)
|
||||||
|
{
|
||||||
|
int num, den;
|
||||||
|
den = lcm(a.sa[1], b.sa[1]);
|
||||||
|
num = a.sa[0] * den / a.sa[1] + b.sa[0] * den / b.sa[1];
|
||||||
|
return frac_make(num, den);
|
||||||
|
}
|
||||||
|
|
||||||
variant frac_mul(variant a, variant b)
|
variant frac_mul(variant a, variant b)
|
||||||
{
|
{
|
||||||
variant v = a;
|
return frac_make(a.sa[0] * b.sa[0], a.sa[1] * b.sa[1]);
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
variant frac_div(variant a, variant b)
|
variant frac_div(variant a, variant b)
|
||||||
{
|
{
|
||||||
variant v = a;
|
return frac_make(a.sa[0] * b.sa[1], a.sa[1] * b.sa[0]);
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ extern "C" {
|
||||||
VAR_FLOAT
|
VAR_FLOAT
|
||||||
} variant_type;
|
} variant_type;
|
||||||
|
|
||||||
|
variant frac_make(int num, int den);
|
||||||
variant frac_add(variant a, variant b);
|
variant frac_add(variant a, variant b);
|
||||||
variant frac_mul(variant a, variant b);
|
variant frac_mul(variant a, variant b);
|
||||||
variant frac_div(variant a, variant b);
|
variant frac_div(variant a, variant b);
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include <platform.h>
|
||||||
|
#include "variant.h"
|
||||||
|
|
||||||
|
#include <CuTest.h>
|
||||||
|
|
||||||
|
static void test_fractions(CuTest *tc) {
|
||||||
|
variant a, b;
|
||||||
|
a = frac_make(120, 12000);
|
||||||
|
CuAssertIntEquals(tc, 1, a.sa[0]);
|
||||||
|
CuAssertIntEquals(tc, 100, a.sa[1]);
|
||||||
|
b = frac_make(23, 2300);
|
||||||
|
a = frac_add(a, b);
|
||||||
|
CuAssertIntEquals(tc, 1, a.sa[0]);
|
||||||
|
CuAssertIntEquals(tc, 50, a.sa[1]);
|
||||||
|
a = frac_mul(a, b);
|
||||||
|
CuAssertIntEquals(tc, 1, a.sa[0]);
|
||||||
|
CuAssertIntEquals(tc, 5000, a.sa[1]);
|
||||||
|
a = frac_div(b, b);
|
||||||
|
CuAssertIntEquals(tc, 1, a.sa[0]);
|
||||||
|
CuAssertIntEquals(tc, 1, a.sa[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
CuSuite *get_variant_suite(void)
|
||||||
|
{
|
||||||
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
SUITE_ADD_TEST(suite, test_fractions);
|
||||||
|
return suite;
|
||||||
|
}
|
Loading…
Reference in New Issue