aboutsummaryrefslogtreecommitdiff
path: root/src/exact_value.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/exact_value.cpp')
-rw-r--r--src/exact_value.cpp184
1 files changed, 178 insertions, 6 deletions
diff --git a/src/exact_value.cpp b/src/exact_value.cpp
index 520812e44..54d4ef6f2 100644
--- a/src/exact_value.cpp
+++ b/src/exact_value.cpp
@@ -12,6 +12,19 @@ bool are_types_identical(Type *x, Type *y);
struct Complex128 {
f64 real, imag;
};
+struct Quaternion256 {
+ f64 imag, jmag, kmag, real;
+};
+
+Quaternion256 quaternion256_inverse(Quaternion256 x) {
+ f64 invmag2 = 1.0 / (x.real*x.real + x.imag*x.imag + x.jmag*x.jmag + x.kmag*x.kmag);
+ x.real = +x.real * invmag2;
+ x.imag = -x.imag * invmag2;
+ x.jmag = -x.jmag * invmag2;
+ x.kmag = -x.kmag * invmag2;
+ return x;
+}
+
enum ExactValueKind {
ExactValue_Invalid,
@@ -21,6 +34,7 @@ enum ExactValueKind {
ExactValue_Integer,
ExactValue_Float,
ExactValue_Complex,
+ ExactValue_Quaternion,
ExactValue_Pointer,
ExactValue_Compound, // TODO(bill): Is this good enough?
ExactValue_Procedure, // TODO(bill): Is this good enough?
@@ -37,6 +51,7 @@ struct ExactValue {
f64 value_float;
i64 value_pointer;
Complex128 value_complex;
+ Quaternion256 value_quaternion;
Ast * value_compound;
Ast * value_procedure;
};
@@ -61,7 +76,8 @@ HashKey hash_exact_value(ExactValue v) {
return hash_integer(v.value_pointer);
case ExactValue_Complex:
return hashing_proc(&v.value_complex, gb_size_of(Complex128));
-
+ case ExactValue_Quaternion:
+ return hashing_proc(&v.value_quaternion, gb_size_of(Quaternion256));
case ExactValue_Compound:
return hash_pointer(v.value_compound);
case ExactValue_Procedure:
@@ -116,6 +132,15 @@ ExactValue exact_value_complex(f64 real, f64 imag) {
return result;
}
+ExactValue exact_value_quaternion(f64 real, f64 imag, f64 jmag, f64 kmag) {
+ ExactValue result = {ExactValue_Quaternion};
+ result.value_quaternion.real = real;
+ result.value_quaternion.imag = imag;
+ result.value_quaternion.jmag = jmag;
+ result.value_quaternion.kmag = kmag;
+ return result;
+}
+
ExactValue exact_value_pointer(i64 ptr) {
ExactValue result = {ExactValue_Pointer};
result.value_pointer = ptr;
@@ -253,8 +278,10 @@ ExactValue exact_value_from_basic_literal(Token token) {
str.len--; // Ignore the 'i|j|k'
f64 imag = float_from_string(str);
- if (last_rune == 'i') {
- return exact_value_complex(0, imag);
+ switch (last_rune) {
+ case 'i': return exact_value_complex(0, imag);
+ case 'j': return exact_value_quaternion(0, 0, imag, 0);
+ case 'k': return exact_value_quaternion(0, 0, 0, imag);
}
}
case Token_Rune: {
@@ -318,11 +345,26 @@ ExactValue exact_value_to_complex(ExactValue v) {
return exact_value_complex(v.value_float, 0);
case ExactValue_Complex:
return v;
+ // case ExactValue_Quaternion:
+ // return exact_value_complex(v.value_quaternion.real, v.value_quaternion.imag);
+ }
+ ExactValue r = {ExactValue_Invalid};
+ return r;
+}
+ExactValue exact_value_to_quaternion(ExactValue v) {
+ switch (v.kind) {
+ case ExactValue_Integer:
+ return exact_value_quaternion(big_int_to_f64(&v.value_integer), 0, 0, 0);
+ case ExactValue_Float:
+ return exact_value_quaternion(v.value_float, 0, 0, 0);
+ case ExactValue_Complex:
+ return exact_value_quaternion(v.value_complex.real, v.value_complex.imag, 0, 0);
+ case ExactValue_Quaternion:
+ return v;
}
ExactValue r = {ExactValue_Invalid};
return r;
}
-
ExactValue exact_value_real(ExactValue v) {
switch (v.kind) {
@@ -331,6 +373,8 @@ ExactValue exact_value_real(ExactValue v) {
return v;
case ExactValue_Complex:
return exact_value_float(v.value_complex.real);
+ case ExactValue_Quaternion:
+ return exact_value_float(v.value_quaternion.real);
}
ExactValue r = {ExactValue_Invalid};
return r;
@@ -343,6 +387,34 @@ ExactValue exact_value_imag(ExactValue v) {
return exact_value_i64(0);
case ExactValue_Complex:
return exact_value_float(v.value_complex.imag);
+ case ExactValue_Quaternion:
+ return exact_value_float(v.value_quaternion.imag);
+ }
+ ExactValue r = {ExactValue_Invalid};
+ return r;
+}
+
+ExactValue exact_value_jmag(ExactValue v) {
+ switch (v.kind) {
+ case ExactValue_Integer:
+ case ExactValue_Float:
+ case ExactValue_Complex:
+ return exact_value_i64(0);
+ case ExactValue_Quaternion:
+ return exact_value_float(v.value_quaternion.jmag);
+ }
+ ExactValue r = {ExactValue_Invalid};
+ return r;
+}
+
+ExactValue exact_value_kmag(ExactValue v) {
+ switch (v.kind) {
+ case ExactValue_Integer:
+ case ExactValue_Float:
+ case ExactValue_Complex:
+ return exact_value_i64(0);
+ case ExactValue_Quaternion:
+ return exact_value_float(v.value_quaternion.kmag);
}
ExactValue r = {ExactValue_Invalid};
return r;
@@ -361,6 +433,32 @@ ExactValue exact_value_make_imag(ExactValue v) {
return r;
}
+ExactValue exact_value_make_jmag(ExactValue v) {
+ switch (v.kind) {
+ case ExactValue_Integer:
+ return exact_value_quaternion(0, 0, exact_value_to_float(v).value_float, 0);
+ case ExactValue_Float:
+ return exact_value_quaternion(0, 0, v.value_float, 0);
+ default:
+ GB_PANIC("Expected an integer or float type for 'exact_value_make_imag'");
+ }
+ ExactValue r = {ExactValue_Invalid};
+ return r;
+}
+
+ExactValue exact_value_make_kmag(ExactValue v) {
+ switch (v.kind) {
+ case ExactValue_Integer:
+ return exact_value_quaternion(0, 0, 0, exact_value_to_float(v).value_float);
+ case ExactValue_Float:
+ return exact_value_quaternion(0, 0, 0, v.value_float);
+ default:
+ GB_PANIC("Expected an integer or float type for 'exact_value_make_imag'");
+ }
+ ExactValue r = {ExactValue_Invalid};
+ return r;
+}
+
i64 exact_value_to_i64(ExactValue v) {
v = exact_value_to_integer(v);
if (v.kind == ExactValue_Integer) {
@@ -389,6 +487,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision,
case ExactValue_Integer:
case ExactValue_Float:
case ExactValue_Complex:
+ case ExactValue_Quaternion:
return v;
}
break;
@@ -413,6 +512,13 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision,
f64 imag = v.value_complex.imag;
return exact_value_complex(-real, -imag);
}
+ case ExactValue_Quaternion: {
+ f64 real = v.value_quaternion.real;
+ f64 imag = v.value_quaternion.imag;
+ f64 jmag = v.value_quaternion.jmag;
+ f64 kmag = v.value_quaternion.kmag;
+ return exact_value_quaternion(-real, -imag, -jmag, -kmag);
+ }
}
break;
}
@@ -463,8 +569,10 @@ i32 exact_value_order(ExactValue const &v) {
return 3;
case ExactValue_Complex:
return 4;
- case ExactValue_Pointer:
+ case ExactValue_Quaternion:
return 5;
+ case ExactValue_Pointer:
+ return 6;
default:
GB_PANIC("How'd you get here? Invalid Value.kind");
@@ -485,7 +593,7 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
case ExactValue_Bool:
case ExactValue_String:
- case ExactValue_Complex:
+ case ExactValue_Quaternion:
return;
case ExactValue_Integer:
@@ -499,6 +607,9 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
case ExactValue_Complex:
*x = exact_value_complex(big_int_to_f64(&x->value_integer), 0);
return;
+ case ExactValue_Quaternion:
+ *x = exact_value_quaternion(big_int_to_f64(&x->value_integer), 0, 0, 0);
+ return;
}
break;
@@ -509,6 +620,17 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
case ExactValue_Complex:
*x = exact_value_to_complex(*x);
return;
+ case ExactValue_Quaternion:
+ *x = exact_value_to_quaternion(*x);
+ return;
+ }
+ break;
+
+ case ExactValue_Complex:
+ switch (y->kind) {
+ case ExactValue_Quaternion:
+ *x = exact_value_to_quaternion(*x);
+ return;
}
break;
}
@@ -606,6 +728,56 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
break;
}
+ case ExactValue_Quaternion: {
+ y = exact_value_to_quaternion(y);
+ f64 xr = x.value_quaternion.real;
+ f64 xi = x.value_quaternion.imag;
+ f64 xj = x.value_quaternion.jmag;
+ f64 xk = x.value_quaternion.kmag;
+ f64 yr = y.value_quaternion.real;
+ f64 yi = y.value_quaternion.imag;
+ f64 yj = y.value_quaternion.jmag;
+ f64 yk = y.value_quaternion.kmag;
+
+
+ f64 real = 0;
+ f64 imag = 0;
+ f64 jmag = 0;
+ f64 kmag = 0;
+
+ switch (op) {
+ case Token_Add:
+ real = xr + yr;
+ imag = xi + yi;
+ jmag = xj + yj;
+ kmag = xk + yk;
+ break;
+ case Token_Sub:
+ real = xr - yr;
+ imag = xi - yi;
+ jmag = xj - yj;
+ kmag = xk - yk;
+ break;
+ case Token_Mul:
+ imag = xr * yi + xi * yr + xj * yk - xk * yj;
+ jmag = xr * yj - xi * yk + xj * yr + xk * yi;
+ kmag = xr * yk + xi * yj - xj * yi + xk * yr;
+ real = xr * yr - xi * yi - xj * yj - xk * yk;
+ break;
+ case Token_Quo: {
+ f64 invmag2 = 1.0 / (yr*yr + yi*yi + yj*yj + yk*yk);
+ imag = (xr * -yi + xi * +yr + xj * -yk - xk * -yj) * invmag2;
+ jmag = (xr * -yj - xi * -yk + xj * +yr + xk * -yi) * invmag2;
+ kmag = (xr * -yk + xi * -yj - xj * -yi + xk * +yr) * invmag2;
+ real = (xr * +yr - xi * -yi - xj * -yj - xk * -yk) * invmag2;
+ break;
+ }
+ default: goto error;
+ }
+ return exact_value_quaternion(real, imag, jmag, kmag);
+ break;
+ }
+
case ExactValue_String: {
if (op != Token_Add) goto error;