aboutsummaryrefslogtreecommitdiff
path: root/src/exact_value.c
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-04-01 12:07:41 +0100
committerGinger Bill <bill@gingerbill.org>2017-04-01 12:07:41 +0100
commitdc303cde21d23b1b57a4cb4f667b2cfbe2a39ffd (patch)
tree9ea225d705d2123b818415f6306373eae9d3cd0c /src/exact_value.c
parenta75ccb6fbc529d2fee00f9b456ca7c0c830548ee (diff)
Complex numbers: complex64 complex128
Diffstat (limited to 'src/exact_value.c')
-rw-r--r--src/exact_value.c157
1 files changed, 143 insertions, 14 deletions
diff --git a/src/exact_value.c b/src/exact_value.c
index 7e8e69f50..f1da88fc6 100644
--- a/src/exact_value.c
+++ b/src/exact_value.c
@@ -12,21 +12,27 @@ typedef enum ExactValueKind {
ExactValue_String,
ExactValue_Integer,
ExactValue_Float,
+ ExactValue_Complex,
ExactValue_Pointer,
ExactValue_Compound, // TODO(bill): Is this good enough?
ExactValue_Count,
} ExactValueKind;
+typedef struct Complex128 {
+ f64 real, imag;
+} Complex128;
+
typedef struct ExactValue {
ExactValueKind kind;
union {
- bool value_bool;
- String value_string;
- i64 value_integer; // NOTE(bill): This must be an integer and not a pointer
- f64 value_float;
- i64 value_pointer;
- AstNode *value_compound;
+ bool value_bool;
+ String value_string;
+ i64 value_integer; // NOTE(bill): This must be an integer and not a pointer
+ f64 value_float;
+ i64 value_pointer;
+ Complex128 value_complex;
+ AstNode * value_compound;
};
} ExactValue;
@@ -66,6 +72,13 @@ ExactValue exact_value_float(f64 f) {
return result;
}
+ExactValue exact_value_complex(f64 real, f64 imag) {
+ ExactValue result = {ExactValue_Complex};
+ result.value_complex.real = real;
+ result.value_complex.imag = imag;
+ return result;
+}
+
ExactValue exact_value_pointer(i64 ptr) {
ExactValue result = {ExactValue_Pointer};
result.value_pointer = ptr;
@@ -113,9 +126,7 @@ ExactValue exact_value_integer_from_string(String string) {
return exact_value_integer(result);
}
-
-
-ExactValue exact_value_float_from_string(String string) {
+f64 float_from_string(String string) {
isize i = 0;
u8 *str = string.text;
isize len = string.len;
@@ -190,8 +201,11 @@ ExactValue exact_value_float_from_string(String string) {
while (exp > 0) { scale *= 10.0; exp -= 1; }
}
- f64 result = sign * (frac ? (value / scale) : (value * scale));
- return exact_value_float(result);
+ return sign * (frac ? (value / scale) : (value * scale));
+}
+
+ExactValue exact_value_float_from_string(String string) {
+ return exact_value_float(float_from_string(string));
}
@@ -200,6 +214,12 @@ ExactValue exact_value_from_basic_literal(Token token) {
case Token_String: return exact_value_string(token.string);
case Token_Integer: return exact_value_integer_from_string(token.string);
case Token_Float: return exact_value_float_from_string(token.string);
+ case Token_Imag: {
+ String str = token.string;
+ str.len--; // Ignore the `i`
+ f64 imag = float_from_string(str);
+ return exact_value_complex(0, imag);
+ }
case Token_Rune: {
Rune r = GB_RUNE_INVALID;
gb_utf8_decode(token.string.text, token.string.len, &r);
@@ -245,6 +265,57 @@ ExactValue exact_value_to_float(ExactValue v) {
return r;
}
+ExactValue exact_value_to_complex(ExactValue v) {
+ switch (v.kind) {
+ case ExactValue_Integer:
+ return exact_value_complex(cast(i64)v.value_integer, 0);
+ case ExactValue_Float:
+ return exact_value_complex(v.value_float, 0);
+ case ExactValue_Complex:
+ return v;
+ }
+ ExactValue r = {ExactValue_Invalid};
+ return r;
+}
+
+ExactValue exact_value_real(ExactValue v) {
+ switch (v.kind) {
+ case ExactValue_Integer:
+ case ExactValue_Float:
+ return v;
+ case ExactValue_Complex:
+ return exact_value_float(v.value_complex.real);
+ }
+ ExactValue r = {ExactValue_Invalid};
+ return r;
+}
+
+ExactValue exact_value_imag(ExactValue v) {
+ switch (v.kind) {
+ case ExactValue_Integer:
+ case ExactValue_Float:
+ return exact_value_integer(0);
+ case ExactValue_Complex:
+ return exact_value_float(v.value_complex.imag);
+ }
+ ExactValue r = {ExactValue_Invalid};
+ return r;
+}
+
+ExactValue exact_value_make_imag(ExactValue v) {
+ switch (v.kind) {
+ case ExactValue_Integer:
+ return exact_value_complex(0, exact_value_to_float(v).value_float);
+ case ExactValue_Float:
+ return exact_value_complex(0, v.value_float);
+ default:
+ GB_PANIC("Expected an integer or float type for `exact_value_make_imag`");
+ }
+ ExactValue r = {ExactValue_Invalid};
+ return r;
+}
+
+
ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision) {
switch (op) {
@@ -253,6 +324,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
case ExactValue_Invalid:
case ExactValue_Integer:
case ExactValue_Float:
+ case ExactValue_Complex:
return v;
}
} break;
@@ -271,6 +343,11 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
i.value_float = -i.value_float;
return i;
}
+ case ExactValue_Complex: {
+ f64 real = v.value_complex.real;
+ f64 imag = v.value_complex.imag;
+ return exact_value_complex(-real, -imag);
+ }
}
} break;
@@ -324,8 +401,10 @@ i32 exact_value_order(ExactValue v) {
return 2;
case ExactValue_Float:
return 3;
- case ExactValue_Pointer:
+ case ExactValue_Complex:
return 4;
+ case ExactValue_Pointer:
+ return 5;
default:
GB_PANIC("How'd you get here? Invalid Value.kind");
@@ -346,6 +425,7 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
case ExactValue_Bool:
case ExactValue_String:
+ case ExactValue_Complex:
return;
case ExactValue_Integer:
@@ -356,16 +436,23 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
// TODO(bill): Is this good enough?
*x = exact_value_float(cast(f64)x->value_integer);
return;
+ case ExactValue_Complex:
+ *x = exact_value_complex(cast(f64)x->value_integer, 0);
+ return;
}
break;
case ExactValue_Float:
- if (y->kind == ExactValue_Float)
+ if (y->kind == ExactValue_Float) {
return;
+ } else if (y->kind == ExactValue_Complex) {
+ *x = exact_value_to_complex(*x);
+ return;
+ }
break;
}
- compiler_error("How'd you get here? Invalid ExactValueKind");
+ compiler_error("match_exact_values: How'd you get here? Invalid ExactValueKind %d", x->kind);
}
// TODO(bill): Allow for pointer arithmetic? Or are pointer slices good enough?
@@ -420,6 +507,37 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
default: goto error;
}
} break;
+
+ case ExactValue_Complex: {
+ y = exact_value_to_complex(y);
+ f64 a = x.value_complex.real;
+ f64 b = x.value_complex.imag;
+ f64 c = y.value_complex.real;
+ f64 d = y.value_complex.imag;
+ f64 real = 0;
+ f64 imag = 0;
+ switch (op) {
+ case Token_Add:
+ real = a + c;
+ imag = b + d;
+ break;
+ case Token_Sub:
+ real = a - c;
+ imag = b - d;
+ break;
+ case Token_Mul:
+ real = (a*c - b*d);
+ imag = (b*c + a*d);
+ break;
+ case Token_Quo: {
+ f64 s = c*c + d*d;
+ real = (a*c + b*d)/s;
+ imag = (b*c - a*d)/s;
+ } break;
+ default: goto error;
+ }
+ return exact_value_complex(real, imag);
+ } break;
}
error:
@@ -480,6 +598,17 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
}
} break;
+ case ExactValue_Complex: {
+ f64 a = x.value_complex.real;
+ f64 b = x.value_complex.imag;
+ f64 c = y.value_complex.real;
+ f64 d = y.value_complex.imag;
+ switch (op) {
+ case Token_CmpEq: return cmp_f64(a, c) == 0 && cmp_f64(b, d) == 0;
+ case Token_NotEq: return cmp_f64(a, c) != 0 || cmp_f64(b, d) != 0;
+ }
+ } break;
+
case ExactValue_String: {
String a = x.value_string;
String b = y.value_string;