aboutsummaryrefslogtreecommitdiff
path: root/src/exact_value.c
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-05-30 15:23:01 +0100
committerGinger Bill <bill@gingerbill.org>2017-05-30 15:23:01 +0100
commitfec6df65b3306005077ee6124458eaaf3ea7ce2c (patch)
tree8610ed974f5229d3f6eb57b9287112b707f19764 /src/exact_value.c
parent78494e84d59a0b949c6c02d231bca8ba2fcfb1f5 (diff)
Use 128-bit integers for ExactValue integers
Diffstat (limited to 'src/exact_value.c')
-rw-r--r--src/exact_value.c138
1 files changed, 54 insertions, 84 deletions
diff --git a/src/exact_value.c b/src/exact_value.c
index b6e30ef83..fbf52227c 100644
--- a/src/exact_value.c
+++ b/src/exact_value.c
@@ -33,7 +33,7 @@ typedef struct ExactValue {
union {
bool value_bool;
String value_string;
- i64 value_integer; // NOTE(bill): This must be an integer and not a pointer
+ i128 value_integer; // NOTE(bill): This must be an integer and not a pointer
f64 value_float;
i64 value_pointer;
Complex128 value_complex;
@@ -66,7 +66,13 @@ ExactValue exact_value_string(String string) {
return result;
}
-ExactValue exact_value_integer(i64 i) {
+ExactValue exact_value_i64(i64 i) {
+ ExactValue result = {ExactValue_Integer};
+ result.value_integer = i128_from_i64(i);
+ return result;
+}
+
+ExactValue exact_value_i128(i128 i) {
ExactValue result = {ExactValue_Integer};
result.value_integer = i;
return result;
@@ -103,43 +109,7 @@ ExactValue exact_value_pointer(i64 ptr) {
ExactValue exact_value_integer_from_string(String string) {
- // TODO(bill): Allow for numbers with underscores in them
- i32 base = 10;
- bool has_prefix = false;
- if (string.len > 2 && string.text[0] == '0') {
- switch (string.text[1]) {
- case 'b': base = 2; has_prefix = true; break;
- case 'o': base = 8; has_prefix = true; break;
- case 'd': base = 10; has_prefix = true; break;
- case 'z': base = 12; has_prefix = true; break;
- case 'x': base = 16; has_prefix = true; break;
- }
- }
-
- u8 *text = string.text;
- isize len = string.len;
- if (has_prefix) {
- text += 2;
- len -= 2;
- }
-
- i64 result = 0;
- for (isize i = 0; i < len; i++) {
- Rune r = cast(Rune)text[i];
- if (r == '_') {
- continue;
- }
- i64 v = 0;
- v = digit_value(r);
- if (v >= base) {
- break;
- }
- result *= base;
- result += v;
- }
-
-
- return exact_value_integer(result);
+ return exact_value_i128(i128_from_string(string));
}
f64 float_from_string(String string) {
@@ -246,7 +216,7 @@ ExactValue exact_value_from_basic_literal(Token token) {
Rune r = GB_RUNE_INVALID;
gb_utf8_decode(token.string.text, token.string.len, &r);
// gb_printf("%.*s rune: %d\n", LIT(token.string), r);
- return exact_value_integer(r);
+ return exact_value_i64(r);
}
default:
GB_PANIC("Invalid token for basic literal");
@@ -262,15 +232,15 @@ ExactValue exact_value_to_integer(ExactValue v) {
case ExactValue_Integer:
return v;
case ExactValue_Float: {
- i64 i = cast(i64)v.value_float;
- f64 f = cast(f64)i;
+ i128 i = i128_from_f64(v.value_float);
+ f64 f = i128_to_f64(i);
if (f == v.value_float) {
- return exact_value_integer(i);
+ return exact_value_i128(i);
}
} break;
case ExactValue_Pointer:
- return exact_value_integer(cast(i64)cast(intptr)v.value_pointer);
+ return exact_value_i64(cast(i64)cast(intptr)v.value_pointer);
}
ExactValue r = {ExactValue_Invalid};
return r;
@@ -279,7 +249,7 @@ ExactValue exact_value_to_integer(ExactValue v) {
ExactValue exact_value_to_float(ExactValue v) {
switch (v.kind) {
case ExactValue_Integer:
- return exact_value_float(cast(i64)v.value_integer);
+ return exact_value_float(i128_to_f64(v.value_integer));
case ExactValue_Float:
return v;
}
@@ -290,7 +260,7 @@ ExactValue exact_value_to_float(ExactValue v) {
ExactValue exact_value_to_complex(ExactValue v) {
switch (v.kind) {
case ExactValue_Integer:
- return exact_value_complex(cast(i64)v.value_integer, 0);
+ return exact_value_complex(i128_to_f64(v.value_integer), 0);
case ExactValue_Float:
return exact_value_complex(v.value_float, 0);
case ExactValue_Complex:
@@ -304,7 +274,7 @@ ExactValue exact_value_to_complex(ExactValue v) {
ExactValue exact_value_to_quaternion(ExactValue v) {
switch (v.kind) {
case ExactValue_Integer:
- return exact_value_quaternion(cast(i64)v.value_integer, 0, 0, 0);
+ return exact_value_quaternion(i128_to_f64(v.value_integer), 0, 0, 0);
case ExactValue_Float:
return exact_value_quaternion(v.value_float, 0, 0, 0);
case ExactValue_Complex:
@@ -335,7 +305,7 @@ ExactValue exact_value_imag(ExactValue v) {
switch (v.kind) {
case ExactValue_Integer:
case ExactValue_Float:
- return exact_value_integer(0);
+ return exact_value_i64(0);
case ExactValue_Complex:
return exact_value_float(v.value_complex.imag);
case ExactValue_Quaternion:
@@ -350,7 +320,7 @@ ExactValue exact_value_jmag(ExactValue v) {
case ExactValue_Integer:
case ExactValue_Float:
case ExactValue_Complex:
- return exact_value_integer(0);
+ return exact_value_i64(0);
case ExactValue_Quaternion:
return exact_value_float(v.value_quaternion.jmag);
}
@@ -362,7 +332,7 @@ ExactValue exact_value_kmag(ExactValue v) {
case ExactValue_Integer:
case ExactValue_Float:
case ExactValue_Complex:
- return exact_value_integer(0);
+ return exact_value_i64(0);
case ExactValue_Quaternion:
return exact_value_float(v.value_quaternion.kmag);
}
@@ -429,7 +399,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
return v;
case ExactValue_Integer: {
ExactValue i = v;
- i.value_integer = -i.value_integer;
+ i.value_integer = i128_neg(i.value_integer);
return i;
}
case ExactValue_Float: {
@@ -453,12 +423,12 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
} break;
case Token_Xor: {
- i64 i = 0;
+ i128 i = I128_ZERO;
switch (v.kind) {
case ExactValue_Invalid:
return v;
case ExactValue_Integer:
- i = ~v.value_integer;
+ i = i128_not(v.value_integer);
break;
default:
goto failure;
@@ -467,11 +437,11 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
// NOTE(bill): unsigned integers will be negative and will need to be
// limited to the types precision
// IMPORTANT NOTE(bill): Max precision is 64 bits as that's how integers are stored
- if (0 < precision && precision < 64) {
- i &= ~((~0ll)<<precision);
+ if (0 < precision && precision < 128) {
+ i = i128_and(i, i128_not(i128_shl(I128_NEG_ONE, precision)));
}
- return exact_value_integer(i);
+ return exact_value_i128(i);
} break;
case Token_Not: {
@@ -538,13 +508,13 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
return;
case ExactValue_Float:
// TODO(bill): Is this good enough?
- *x = exact_value_float(cast(f64)x->value_integer);
+ *x = exact_value_float(i128_to_f64(x->value_integer));
return;
case ExactValue_Complex:
- *x = exact_value_complex(cast(f64)x->value_integer, 0);
+ *x = exact_value_complex(i128_to_f64(x->value_integer), 0);
return;
case ExactValue_Quaternion:
- *x = exact_value_quaternion(cast(f64)x->value_integer, 0, 0, 0);
+ *x = exact_value_quaternion(i128_to_f64(x->value_integer), 0, 0, 0);
return;
}
break;
@@ -585,27 +555,27 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
break;
case ExactValue_Integer: {
- i64 a = x.value_integer;
- i64 b = y.value_integer;
- i64 c = 0;
+ i128 a = x.value_integer;
+ i128 b = y.value_integer;
+ i128 c = I128_ZERO;
switch (op) {
- case Token_Add: c = a + b; break;
- case Token_Sub: c = a - b; break;
- case Token_Mul: c = a * b; break;
- case Token_Quo: return exact_value_float(fmod(cast(f64)a, cast(f64)b));
- case Token_QuoEq: c = a / b; break; // NOTE(bill): Integer division
- case Token_Mod: c = a % b; break;
- case Token_ModMod: c = ((a % b) + b)%b; break;
- case Token_And: c = a & b; break;
- case Token_Or: c = a | b; break;
- case Token_Xor: c = a ^ b; break;
- case Token_AndNot: c = a&(~b); break;
- case Token_Shl: c = a << b; break;
- case Token_Shr: c = a >> b; break;
+ case Token_Add: c = i128_add(a, b); break;
+ case Token_Sub: c = i128_sub(a, b); break;
+ case Token_Mul: c = i128_mul(a, b); break;
+ case Token_Quo: return exact_value_float(fmod(i128_to_f64(a), i128_to_f64(b)));
+ case Token_QuoEq: c = i128_quo(a, b); break; // NOTE(bill): Integer division
+ case Token_Mod: c = i128_mod(a, b); break;
+ case Token_ModMod: c = i128_mod(i128_add(i128_mod(a, b), b), b); break;
+ case Token_And: c = i128_and (a, b); break;
+ case Token_Or: c = i128_or (a, b); break;
+ case Token_Xor: c = i128_xor (a, b); break;
+ case Token_AndNot: c = i128_and_not(a, b); break;
+ case Token_Shl: c = i128_shl (a, i128_to_u64(b)); break;
+ case Token_Shr: c = i128_shr (a, i128_to_u64(b)); break;
default: goto error;
}
- return exact_value_integer(c);
+ return exact_value_i128(c);
} break;
case ExactValue_Float: {
@@ -732,15 +702,15 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
break;
case ExactValue_Integer: {
- i64 a = x.value_integer;
- i64 b = y.value_integer;
+ i128 a = x.value_integer;
+ i128 b = y.value_integer;
switch (op) {
- case Token_CmpEq: return a == b;
- case Token_NotEq: return a != b;
- case Token_Lt: return a < b;
- case Token_LtEq: return a <= b;
- case Token_Gt: return a > b;
- case Token_GtEq: return a >= b;
+ case Token_CmpEq: return i128_eq(a, b);
+ case Token_NotEq: return i128_ne(a, b);
+ case Token_Lt: return i128_lt(a, b);
+ case Token_LtEq: return i128_le(a, b);
+ case Token_Gt: return i128_gt(a, b);
+ case Token_GtEq: return i128_ge(a, b);
}
} break;