mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-18 08:41:31 -07:00
Complex numbers: complex64 complex128
This commit is contained in:
+143
-14
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user