diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-04-01 12:07:41 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-04-01 12:07:41 +0100 |
| commit | dc303cde21d23b1b57a4cb4f667b2cfbe2a39ffd (patch) | |
| tree | 9ea225d705d2123b818415f6306373eae9d3cd0c /src/exact_value.c | |
| parent | a75ccb6fbc529d2fee00f9b456ca7c0c830548ee (diff) | |
Complex numbers: complex64 complex128
Diffstat (limited to 'src/exact_value.c')
| -rw-r--r-- | src/exact_value.c | 157 |
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; |