mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-22 06:15:20 +00:00
Built-in Quaternions (Not just an April Fool's Joke any more)
This commit is contained in:
@@ -1129,6 +1129,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
|
||||
case runtime.Type_Info_Rune: fmt_arg(fi, v, verb);
|
||||
case runtime.Type_Info_Float: fmt_arg(fi, v, verb);
|
||||
case runtime.Type_Info_Complex: fmt_arg(fi, v, verb);
|
||||
case runtime.Type_Info_Quaternion: fmt_arg(fi, v, verb);
|
||||
case runtime.Type_Info_String: fmt_arg(fi, v, verb);
|
||||
|
||||
case runtime.Type_Info_Pointer:
|
||||
@@ -1386,6 +1387,31 @@ fmt_complex :: proc(fi: ^Info, c: complex128, bits: int, verb: rune) {
|
||||
}
|
||||
}
|
||||
|
||||
fmt_quaternion :: proc(fi: ^Info, q: quaternion256, bits: int, verb: rune) {
|
||||
switch verb {
|
||||
case 'f', 'F', 'v', 'h', 'H':
|
||||
r, i, j, k := real(q), imag(q), jmag(q), kmag(q);
|
||||
|
||||
fmt_float(fi, r, bits/4, verb);
|
||||
|
||||
if !fi.plus && i >= 0 do strings.write_rune(fi.buf, '+');
|
||||
fmt_float(fi, i, bits/4, verb);
|
||||
strings.write_rune(fi.buf, 'i');
|
||||
|
||||
if !fi.plus && j >= 0 do strings.write_rune(fi.buf, '+');
|
||||
fmt_float(fi, j, bits/4, verb);
|
||||
strings.write_rune(fi.buf, 'j');
|
||||
|
||||
if !fi.plus && k >= 0 do strings.write_rune(fi.buf, '+');
|
||||
fmt_float(fi, k, bits/4, verb);
|
||||
strings.write_rune(fi.buf, 'k');
|
||||
|
||||
case:
|
||||
fmt_bad_verb(fi, verb);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fmt_arg :: proc(fi: ^Info, arg: any, verb: rune) {
|
||||
if arg == nil {
|
||||
strings.write_string(fi.buf, "<nil>");
|
||||
@@ -1434,6 +1460,9 @@ fmt_arg :: proc(fi: ^Info, arg: any, verb: rune) {
|
||||
case complex64: fmt_complex(fi, complex128(a), 64, verb);
|
||||
case complex128: fmt_complex(fi, a, 128, verb);
|
||||
|
||||
case quaternion128: fmt_quaternion(fi, quaternion256(a), 128, verb);
|
||||
case quaternion256: fmt_quaternion(fi, a, 256, verb);
|
||||
|
||||
case i8: fmt_int(fi, u64(a), true, 8, verb);
|
||||
case u8: fmt_int(fi, u64(a), false, 8, verb);
|
||||
case i16: fmt_int(fi, u64(a), true, 16, verb);
|
||||
|
||||
@@ -12,6 +12,7 @@ Type_Kind :: enum {
|
||||
Rune,
|
||||
Float,
|
||||
Complex,
|
||||
Quaternion,
|
||||
String,
|
||||
Boolean,
|
||||
Any,
|
||||
@@ -42,6 +43,7 @@ type_kind :: proc(T: typeid) -> Type_Kind {
|
||||
case runtime.Type_Info_Rune: return .Rune;
|
||||
case runtime.Type_Info_Float: return .Float;
|
||||
case runtime.Type_Info_Complex: return .Complex;
|
||||
case runtime.Type_Info_Quaternion: return .Quaternion;
|
||||
case runtime.Type_Info_String: return .String;
|
||||
case runtime.Type_Info_Boolean: return .Boolean;
|
||||
case runtime.Type_Info_Any: return .Any;
|
||||
|
||||
@@ -47,16 +47,17 @@ Type_Info_Endianness :: enum u8 {
|
||||
}
|
||||
|
||||
// Variant Types
|
||||
Type_Info_Named :: struct {name: string, base: ^Type_Info};
|
||||
Type_Info_Integer :: struct {signed: bool, endianness: Type_Info_Endianness};
|
||||
Type_Info_Rune :: struct {};
|
||||
Type_Info_Float :: struct {};
|
||||
Type_Info_Complex :: struct {};
|
||||
Type_Info_String :: struct {is_cstring: bool};
|
||||
Type_Info_Boolean :: struct {};
|
||||
Type_Info_Any :: struct {};
|
||||
Type_Info_Type_Id :: struct {};
|
||||
Type_Info_Pointer :: struct {
|
||||
Type_Info_Named :: struct {name: string, base: ^Type_Info};
|
||||
Type_Info_Integer :: struct {signed: bool, endianness: Type_Info_Endianness};
|
||||
Type_Info_Rune :: struct {};
|
||||
Type_Info_Float :: struct {};
|
||||
Type_Info_Complex :: struct {};
|
||||
Type_Info_Quaternion :: struct {};
|
||||
Type_Info_String :: struct {is_cstring: bool};
|
||||
Type_Info_Boolean :: struct {};
|
||||
Type_Info_Any :: struct {};
|
||||
Type_Info_Type_Id :: struct {};
|
||||
Type_Info_Pointer :: struct {
|
||||
elem: ^Type_Info // nil -> rawptr
|
||||
};
|
||||
Type_Info_Procedure :: struct {
|
||||
@@ -135,6 +136,7 @@ Type_Info :: struct {
|
||||
Type_Info_Rune,
|
||||
Type_Info_Float,
|
||||
Type_Info_Complex,
|
||||
Type_Info_Quaternion,
|
||||
Type_Info_String,
|
||||
Type_Info_Boolean,
|
||||
Type_Info_Any,
|
||||
@@ -163,6 +165,7 @@ Typeid_Kind :: enum u8 {
|
||||
Rune,
|
||||
Float,
|
||||
Complex,
|
||||
Quaternion,
|
||||
String,
|
||||
Boolean,
|
||||
Any,
|
||||
|
||||
@@ -357,6 +357,11 @@ complex128_eq :: inline proc "contextless" (a, b: complex128) -> bool { return r
|
||||
complex128_ne :: inline proc "contextless" (a, b: complex128) -> bool { return real(a) != real(b) || imag(a) != imag(b); }
|
||||
|
||||
|
||||
quaternion128_eq :: inline proc "contextless" (a, b: quaternion128) -> bool { return real(a) == real(b) && imag(a) == imag(b) && jmag(a) == jmag(b) && kmag(a) == kmag(b); }
|
||||
quaternion128_ne :: inline proc "contextless" (a, b: quaternion128) -> bool { return real(a) != real(b) || imag(a) != imag(b) || jmag(a) != jmag(b) || kmag(a) != kmag(b); }
|
||||
|
||||
quaternion256_eq :: inline proc "contextless" (a, b: quaternion256) -> bool { return real(a) == real(b) && imag(a) == imag(b) && jmag(a) == jmag(b) && kmag(a) == kmag(b); }
|
||||
quaternion256_ne :: inline proc "contextless" (a, b: quaternion256) -> bool { return real(a) != real(b) || imag(a) != imag(b) || jmag(a) != jmag(b) || kmag(a) != kmag(b); }
|
||||
|
||||
|
||||
bounds_check_error :: proc "contextless" (file: string, line, column: int, index, count: int) {
|
||||
@@ -546,9 +551,16 @@ abs_complex128 :: inline proc "contextless" (x: complex128) -> f64 {
|
||||
r, i := real(x), imag(x);
|
||||
return _sqrt_f64(r*r + i*i);
|
||||
}
|
||||
abs_quaternion128 :: inline proc "contextless" (x: quaternion128) -> f32 {
|
||||
r, i, j, k := real(x), imag(x), jmag(x), kmag(x);
|
||||
return _sqrt_f32(r*r + i*i + j*j + k*k);
|
||||
}
|
||||
abs_quaternion256 :: inline proc "contextless" (x: quaternion256) -> f64 {
|
||||
r, i, j, k := real(x), imag(x), jmag(x), kmag(x);
|
||||
return _sqrt_f64(r*r + i*i + j*j + k*k);
|
||||
}
|
||||
|
||||
|
||||
quo_complex64 :: proc(n, m: complex64) -> complex64 {
|
||||
quo_complex64 :: proc "contextless" (n, m: complex64) -> complex64 {
|
||||
e, f: f32;
|
||||
|
||||
if abs(real(m)) >= abs(imag(m)) {
|
||||
@@ -566,7 +578,7 @@ quo_complex64 :: proc(n, m: complex64) -> complex64 {
|
||||
return complex(e, f);
|
||||
}
|
||||
|
||||
quo_complex128 :: proc(n, m: complex128) -> complex128 {
|
||||
quo_complex128 :: proc "contextless" (n, m: complex128) -> complex128 {
|
||||
e, f: f64;
|
||||
|
||||
if abs(real(m)) >= abs(imag(m)) {
|
||||
@@ -583,3 +595,55 @@ quo_complex128 :: proc(n, m: complex128) -> complex128 {
|
||||
|
||||
return complex(e, f);
|
||||
}
|
||||
|
||||
mul_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 {
|
||||
q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q);
|
||||
r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r);
|
||||
|
||||
t0 := r0*q0 - r1*q1 - r2*q2 - r3*q3;
|
||||
t1 := r0*q1 + r1*q0 - r2*q3 + r3*q2;
|
||||
t2 := r0*q2 + r1*q3 + r2*q0 - r3*q1;
|
||||
t3 := r0*q3 - r1*q2 + r2*q1 + r3*q0;
|
||||
|
||||
return quaternion(t0, t1, t2, t3);
|
||||
}
|
||||
|
||||
mul_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 {
|
||||
q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q);
|
||||
r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r);
|
||||
|
||||
t0 := r0*q0 - r1*q1 - r2*q2 - r3*q3;
|
||||
t1 := r0*q1 + r1*q0 - r2*q3 + r3*q2;
|
||||
t2 := r0*q2 + r1*q3 + r2*q0 - r3*q1;
|
||||
t3 := r0*q3 - r1*q2 + r2*q1 + r3*q0;
|
||||
|
||||
return quaternion(t0, t1, t2, t3);
|
||||
}
|
||||
|
||||
quo_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 {
|
||||
q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q);
|
||||
r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r);
|
||||
|
||||
invmag2 := 1.0 / (r0*r0 + r1*r1 + r2*r2 + r3*r3);
|
||||
|
||||
t0 := (r0*q0 + r1*q1 + r2*q2 + r3*q3) * invmag2;
|
||||
t1 := (r0*q1 - r1*q0 - r2*q3 - r3*q2) * invmag2;
|
||||
t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2;
|
||||
t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2;
|
||||
|
||||
return quaternion(t0, t1, t2, t3);
|
||||
}
|
||||
|
||||
quo_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 {
|
||||
q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q);
|
||||
r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r);
|
||||
|
||||
invmag2 := 1.0 / (r0*r0 + r1*r1 + r2*r2 + r3*r3);
|
||||
|
||||
t0 := (r0*q0 + r1*q1 + r2*q2 + r3*q3) * invmag2;
|
||||
t1 := (r0*q1 - r1*q0 - r2*q3 - r3*q2) * invmag2;
|
||||
t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2;
|
||||
t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2;
|
||||
|
||||
return quaternion(t0, t1, t2, t3);
|
||||
}
|
||||
|
||||
@@ -326,7 +326,7 @@ union_type :: proc() {
|
||||
}
|
||||
|
||||
parametric_polymorphism :: proc() {
|
||||
fmt.println("# parametric_polymorphism");
|
||||
fmt.println("\n# parametric_polymorphism");
|
||||
|
||||
print_value :: proc(value: $T) {
|
||||
fmt.printf("print_value: %T %v\n", value, value);
|
||||
@@ -561,7 +561,7 @@ prefix_table := [?]string{
|
||||
|
||||
threading_example :: proc() {
|
||||
when os.OS == "windows" {
|
||||
fmt.println("# threading_example");
|
||||
fmt.println("\n# threading_example");
|
||||
|
||||
worker_proc :: proc(t: ^thread.Thread) -> int {
|
||||
for iteration in 1..5 {
|
||||
@@ -601,7 +601,7 @@ threading_example :: proc() {
|
||||
}
|
||||
|
||||
array_programming :: proc() {
|
||||
fmt.println("# array_programming");
|
||||
fmt.println("\n# array_programming");
|
||||
{
|
||||
a := [3]f32{1, 2, 3};
|
||||
b := [3]f32{5, 6, 7};
|
||||
@@ -646,7 +646,7 @@ array_programming :: proc() {
|
||||
}
|
||||
|
||||
named_proc_return_parameters :: proc() {
|
||||
fmt.println("# named proc return parameters");
|
||||
fmt.println("\n# named proc return parameters");
|
||||
|
||||
foo0 :: proc() -> int {
|
||||
return 123;
|
||||
@@ -668,7 +668,7 @@ named_proc_return_parameters :: proc() {
|
||||
|
||||
|
||||
using_enum :: proc() {
|
||||
fmt.println("# using enum");
|
||||
fmt.println("\n# using enum");
|
||||
|
||||
using Foo :: enum {A, B, C};
|
||||
|
||||
@@ -680,7 +680,7 @@ using_enum :: proc() {
|
||||
}
|
||||
|
||||
map_type :: proc() {
|
||||
fmt.println("# map type");
|
||||
fmt.println("\n# map type");
|
||||
|
||||
// enums of type u16, u32, i16 & i32 also work
|
||||
Enum_u8 :: enum u8 {
|
||||
@@ -735,7 +735,7 @@ map_type :: proc() {
|
||||
}
|
||||
|
||||
implicit_selector_expression :: proc() {
|
||||
fmt.println("# implicit selector expression");
|
||||
fmt.println("\n# implicit selector expression");
|
||||
|
||||
Foo :: enum {A, B, C};
|
||||
|
||||
@@ -763,7 +763,7 @@ implicit_selector_expression :: proc() {
|
||||
}
|
||||
|
||||
explicit_procedure_overloading :: proc() {
|
||||
fmt.println("# explicit procedure overloading");
|
||||
fmt.println("\n# explicit procedure overloading");
|
||||
|
||||
add_ints :: proc(a, b: int) -> int {
|
||||
x := a + b;
|
||||
@@ -797,7 +797,7 @@ explicit_procedure_overloading :: proc() {
|
||||
}
|
||||
|
||||
complete_switch :: proc() {
|
||||
fmt.println("# complete_switch");
|
||||
fmt.println("\n# complete_switch");
|
||||
{ // enum
|
||||
using Foo :: enum {
|
||||
A,
|
||||
@@ -947,7 +947,7 @@ deferred_procedure_associations :: proc() {
|
||||
}
|
||||
|
||||
reflection :: proc() {
|
||||
fmt.println("# reflection");
|
||||
fmt.println("\n# reflection");
|
||||
|
||||
Foo :: struct {
|
||||
x: int `tag1`,
|
||||
@@ -981,6 +981,45 @@ reflection :: proc() {
|
||||
}
|
||||
}
|
||||
|
||||
quaternions :: proc() {
|
||||
fmt.println("\n# quaternions");
|
||||
|
||||
{ // Quaternion operations
|
||||
q := 1 + 2i + 3j + 4k;
|
||||
r := quaternion(5, 6, 7, 8);
|
||||
t := q * r;
|
||||
fmt.printf("(%v) * (%v) = %v\n", q, r, t);
|
||||
v := q / r;
|
||||
fmt.printf("(%v) / (%v) = %v\n", q, r, v);
|
||||
u := q + r;
|
||||
fmt.printf("(%v) + (%v) = %v\n", q, r, u);
|
||||
s := q - r;
|
||||
fmt.printf("(%v) - (%v) = %v\n", q, r, s);
|
||||
}
|
||||
{ // The quaternion types
|
||||
q128: quaternion128; // 4xf32
|
||||
q256: quaternion256; // 4xf64
|
||||
q128 = quaternion(1, 0, 0, 0);
|
||||
q256 = 1; // quaternion(1, 0, 0, 0);
|
||||
}
|
||||
{ // Built-in procedures
|
||||
q := 1 + 2i + 3j + 4k;
|
||||
fmt.println("q =", q);
|
||||
fmt.println("real(q) =", real(q));
|
||||
fmt.println("imag(q) =", imag(q));
|
||||
fmt.println("jmag(q) =", jmag(q));
|
||||
fmt.println("kmag(q) =", kmag(q));
|
||||
fmt.println("conj(q) =", conj(q));
|
||||
fmt.println("abs(q) =", abs(q));
|
||||
}
|
||||
{ // Conversion of a complex type to a quaternion type
|
||||
c := 1 + 2i;
|
||||
q := quaternion256(c);
|
||||
fmt.println(c);
|
||||
fmt.println(q);
|
||||
}
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
when true {
|
||||
general_stuff();
|
||||
@@ -1000,5 +1039,6 @@ main :: proc() {
|
||||
diverging_procedures();
|
||||
deferred_procedure_associations();
|
||||
reflection();
|
||||
quaternions();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,6 +497,14 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type
|
||||
if (is_type_complex(dst)) {
|
||||
return 1;
|
||||
}
|
||||
if (is_type_quaternion(dst)) {
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
case Basic_UntypedQuaternion:
|
||||
if (is_type_quaternion(dst)) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1438,7 +1446,7 @@ bool check_representable_as_constant(CheckerContext *c, ExactValue in_value, Typ
|
||||
ExactValue imag = exact_value_imag(v);
|
||||
if (real.kind != ExactValue_Invalid &&
|
||||
imag.kind != ExactValue_Invalid) {
|
||||
if (out_value) *out_value = exact_binary_operator_value(Token_Add, real, exact_value_make_imag(imag));
|
||||
if (out_value) *out_value = exact_value_complex(exact_value_to_f64(real), exact_value_to_f64(imag));
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -1449,6 +1457,36 @@ bool check_representable_as_constant(CheckerContext *c, ExactValue in_value, Typ
|
||||
default: GB_PANIC("Compiler error: Unknown complex type!"); break;
|
||||
}
|
||||
|
||||
return false;
|
||||
} else if (is_type_quaternion(type)) {
|
||||
ExactValue v = exact_value_to_quaternion(in_value);
|
||||
if (v.kind != ExactValue_Quaternion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (type->Basic.kind) {
|
||||
case Basic_quaternion128:
|
||||
case Basic_quaternion256: {
|
||||
ExactValue real = exact_value_real(v);
|
||||
ExactValue imag = exact_value_imag(v);
|
||||
ExactValue jmag = exact_value_jmag(v);
|
||||
ExactValue kmag = exact_value_kmag(v);
|
||||
if (real.kind != ExactValue_Invalid &&
|
||||
imag.kind != ExactValue_Invalid) {
|
||||
if (out_value) *out_value = exact_value_quaternion(exact_value_to_f64(real), exact_value_to_f64(imag), exact_value_to_f64(jmag), exact_value_to_f64(kmag));
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Basic_UntypedComplex:
|
||||
if (out_value) *out_value = exact_value_to_quaternion(*out_value);
|
||||
return true;
|
||||
case Basic_UntypedQuaternion:
|
||||
return true;
|
||||
|
||||
default: GB_PANIC("Compiler error: Unknown complex type!"); break;
|
||||
}
|
||||
|
||||
return false;
|
||||
} else if (is_type_pointer(type)) {
|
||||
if (in_value.kind == ExactValue_Pointer) {
|
||||
@@ -1481,10 +1519,14 @@ void check_is_expressible(CheckerContext *c, Operand *o, Type *type) {
|
||||
if (!is_type_integer(o->type) && is_type_integer(type)) {
|
||||
error(o->expr, "'%s' truncated to '%s'", a, b);
|
||||
} else {
|
||||
#if 0
|
||||
gbAllocator ha = heap_allocator();
|
||||
String str = big_int_to_string(ha, &o->value.value_integer);
|
||||
defer (gb_free(ha, str.text));
|
||||
error(o->expr, "'%s = %.*s' overflows '%s'", a, LIT(str), b);
|
||||
#else
|
||||
error(o->expr, "Cannot convert '%s' to '%s'", a, b);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
error(o->expr, "Cannot convert '%s' to '%s'", a, b);
|
||||
@@ -1759,6 +1801,21 @@ void check_comparison(CheckerContext *c, Operand *x, Operand *y, TokenKind op) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (is_type_quaternion(x->type) || is_type_quaternion(y->type)) {
|
||||
switch (op) {
|
||||
case Token_CmpEq:
|
||||
switch (8*size) {
|
||||
case 128: add_package_dependency(c, "runtime", "quaternion128_eq"); break;
|
||||
case 256: add_package_dependency(c, "runtime", "quaternion256_eq"); break;
|
||||
}
|
||||
break;
|
||||
case Token_NotEq:
|
||||
switch (8*size) {
|
||||
case 128: add_package_dependency(c, "runtime", "quaternion128_ne"); break;
|
||||
case 256: add_package_dependency(c, "runtime", "quaternion256_ne"); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1978,6 +2035,14 @@ bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_type_complex(src) && is_type_quaternion(dst)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_type_quaternion(src) && is_type_quaternion(dst)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_type_bit_field_value(src) && is_type_integer(dst)) {
|
||||
return true;
|
||||
}
|
||||
@@ -2557,6 +2622,8 @@ ExactValue convert_exact_value_for_type(ExactValue v, Type *type) {
|
||||
v = exact_value_to_integer(v);
|
||||
} else if (is_type_complex(t)) {
|
||||
v = exact_value_to_complex(v);
|
||||
} else if (is_type_quaternion(t)) {
|
||||
v = exact_value_to_quaternion(v);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
@@ -2652,6 +2719,7 @@ void convert_to_typed(CheckerContext *c, Operand *operand, Type *target_type) {
|
||||
case Basic_UntypedInteger:
|
||||
case Basic_UntypedFloat:
|
||||
case Basic_UntypedComplex:
|
||||
case Basic_UntypedQuaternion:
|
||||
case Basic_UntypedRune:
|
||||
if (!is_type_numeric(target_type)) {
|
||||
operand->mode = Addressing_Invalid;
|
||||
@@ -3769,10 +3837,98 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_quaternion: {
|
||||
// quaternion :: proc(real, imag, jmag, kmag: float_type) -> complex_type
|
||||
Operand x = *operand;
|
||||
Operand y = {};
|
||||
Operand z = {};
|
||||
Operand w = {};
|
||||
|
||||
// NOTE(bill): Invalid will be the default till fixed
|
||||
operand->type = t_invalid;
|
||||
operand->mode = Addressing_Invalid;
|
||||
|
||||
check_expr(c, &y, ce->args[1]);
|
||||
if (y.mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
check_expr(c, &z, ce->args[2]);
|
||||
if (y.mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
check_expr(c, &w, ce->args[3]);
|
||||
if (y.mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
convert_to_typed(c, &x, y.type); if (x.mode == Addressing_Invalid) return false;
|
||||
convert_to_typed(c, &y, x.type); if (y.mode == Addressing_Invalid) return false;
|
||||
convert_to_typed(c, &z, x.type); if (z.mode == Addressing_Invalid) return false;
|
||||
convert_to_typed(c, &w, x.type); if (w.mode == Addressing_Invalid) return false;
|
||||
if (x.mode == Addressing_Constant &&
|
||||
y.mode == Addressing_Constant &&
|
||||
z.mode == Addressing_Constant &&
|
||||
w.mode == Addressing_Constant) {
|
||||
if (is_type_numeric(x.type) && exact_value_imag(x.value).value_float == 0) {
|
||||
x.type = t_untyped_float;
|
||||
}
|
||||
if (is_type_numeric(y.type) && exact_value_imag(y.value).value_float == 0) {
|
||||
y.type = t_untyped_float;
|
||||
}
|
||||
if (is_type_numeric(z.type) && exact_value_imag(z.value).value_float == 0) {
|
||||
z.type = t_untyped_float;
|
||||
}
|
||||
if (is_type_numeric(w.type) && exact_value_imag(w.value).value_float == 0) {
|
||||
w.type = t_untyped_float;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(are_types_identical(x.type, y.type) && are_types_identical(x.type, z.type) && are_types_identical(x.type, w.type))) {
|
||||
gbString tx = type_to_string(x.type);
|
||||
gbString ty = type_to_string(y.type);
|
||||
gbString tz = type_to_string(z.type);
|
||||
gbString tw = type_to_string(w.type);
|
||||
error(call, "Mismatched types to 'quaternion', '%s' vs '%s' vs '%s' vs '%s'", tx, ty, tz, tw);
|
||||
gb_string_free(tw);
|
||||
gb_string_free(tz);
|
||||
gb_string_free(ty);
|
||||
gb_string_free(tx);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_type_float(x.type)) {
|
||||
gbString s = type_to_string(x.type);
|
||||
error(call, "Arguments have type '%s', expected a floating point", s);
|
||||
gb_string_free(s);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (x.mode == Addressing_Constant && y.mode == Addressing_Constant && z.mode == Addressing_Constant && w.mode == Addressing_Constant) {
|
||||
f64 r = exact_value_to_float(x.value).value_float;
|
||||
f64 i = exact_value_to_float(y.value).value_float;
|
||||
f64 j = exact_value_to_float(z.value).value_float;
|
||||
f64 k = exact_value_to_float(w.value).value_float;
|
||||
operand->value = exact_value_quaternion(r, i, j, k);
|
||||
operand->mode = Addressing_Constant;
|
||||
} else {
|
||||
operand->mode = Addressing_Value;
|
||||
}
|
||||
|
||||
BasicKind kind = core_type(x.type)->Basic.kind;
|
||||
switch (kind) {
|
||||
case Basic_f32: operand->type = t_quaternion128; break;
|
||||
case Basic_f64: operand->type = t_quaternion256; break;
|
||||
case Basic_UntypedFloat: operand->type = t_untyped_quaternion; break;
|
||||
default: GB_PANIC("Invalid type"); break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_real:
|
||||
case BuiltinProc_imag: {
|
||||
// real :: proc(x: type) -> float_type
|
||||
// proc imag(x: type) -> float_type
|
||||
// imag :: proc(x: type) -> float_type
|
||||
|
||||
Operand *x = operand;
|
||||
if (is_type_untyped(x->type)) {
|
||||
@@ -3780,7 +3936,12 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
if (is_type_numeric(x->type)) {
|
||||
x->type = t_untyped_complex;
|
||||
}
|
||||
} else {
|
||||
} else if (is_type_quaternion(x->type)) {
|
||||
convert_to_typed(c, x, t_quaternion256);
|
||||
if (x->mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
} else{
|
||||
convert_to_typed(c, x, t_complex128);
|
||||
if (x->mode == Addressing_Invalid) {
|
||||
return false;
|
||||
@@ -3788,9 +3949,9 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_type_complex(x->type)) {
|
||||
if (!is_type_complex(x->type) && !is_type_quaternion(x->type)) {
|
||||
gbString s = type_to_string(x->type);
|
||||
error(call, "Argument has type '%s', expected a complex type", s);
|
||||
error(call, "Argument has type '%s', expected a complex or quaternion type", s);
|
||||
gb_string_free(s);
|
||||
return false;
|
||||
}
|
||||
@@ -3808,7 +3969,57 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
switch (kind) {
|
||||
case Basic_complex64: x->type = t_f32; break;
|
||||
case Basic_complex128: x->type = t_f64; break;
|
||||
case Basic_quaternion128: x->type = t_f32; break;
|
||||
case Basic_quaternion256: x->type = t_f64; break;
|
||||
case Basic_UntypedComplex: x->type = t_untyped_float; break;
|
||||
case Basic_UntypedQuaternion: x->type = t_untyped_float; break;
|
||||
default: GB_PANIC("Invalid type"); break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_jmag:
|
||||
case BuiltinProc_kmag: {
|
||||
// jmag :: proc(x: type) -> float_type
|
||||
// kmag :: proc(x: type) -> float_type
|
||||
|
||||
Operand *x = operand;
|
||||
if (is_type_untyped(x->type)) {
|
||||
if (x->mode == Addressing_Constant) {
|
||||
if (is_type_numeric(x->type)) {
|
||||
x->type = t_untyped_complex;
|
||||
}
|
||||
} else{
|
||||
convert_to_typed(c, x, t_quaternion256);
|
||||
if (x->mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_type_quaternion(x->type)) {
|
||||
gbString s = type_to_string(x->type);
|
||||
error(call, "Argument has type '%s', expected a quaternion type", s);
|
||||
gb_string_free(s);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (x->mode == Addressing_Constant) {
|
||||
switch (id) {
|
||||
case BuiltinProc_jmag: x->value = exact_value_jmag(x->value); break;
|
||||
case BuiltinProc_kmag: x->value = exact_value_kmag(x->value); break;
|
||||
}
|
||||
} else {
|
||||
x->mode = Addressing_Value;
|
||||
}
|
||||
|
||||
BasicKind kind = core_type(x->type)->Basic.kind;
|
||||
switch (kind) {
|
||||
case Basic_quaternion128: x->type = t_f32; break;
|
||||
case Basic_quaternion256: x->type = t_f64; break;
|
||||
case Basic_UntypedComplex: x->type = t_untyped_float; break;
|
||||
case Basic_UntypedQuaternion: x->type = t_untyped_float; break;
|
||||
default: GB_PANIC("Invalid type"); break;
|
||||
}
|
||||
|
||||
@@ -3822,12 +4033,24 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
if (x->mode == Addressing_Constant) {
|
||||
ExactValue v = exact_value_to_complex(x->value);
|
||||
f64 r = v.value_complex.real;
|
||||
f64 i = v.value_complex.imag;
|
||||
f64 i = -v.value_complex.imag;
|
||||
x->value = exact_value_complex(r, i);
|
||||
x->mode = Addressing_Constant;
|
||||
} else {
|
||||
x->mode = Addressing_Value;
|
||||
}
|
||||
} else if (is_type_quaternion(x->type)) {
|
||||
if (x->mode == Addressing_Constant) {
|
||||
ExactValue v = exact_value_to_quaternion(x->value);
|
||||
f64 r = v.value_quaternion.real;
|
||||
f64 i = -v.value_quaternion.imag;
|
||||
f64 j = -v.value_quaternion.jmag;
|
||||
f64 k = -v.value_quaternion.kmag;
|
||||
x->value = exact_value_quaternion(r, i, j, k);
|
||||
x->mode = Addressing_Constant;
|
||||
} else {
|
||||
x->mode = Addressing_Value;
|
||||
}
|
||||
} else {
|
||||
gbString s = type_to_string(x->type);
|
||||
error(call, "Expected a complex or quaternion, got '%s'", s);
|
||||
@@ -4226,6 +4449,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
if (are_types_identical(bt, t_f64)) add_package_dependency(c, "runtime", "abs_f64");
|
||||
if (are_types_identical(bt, t_complex64)) add_package_dependency(c, "runtime", "abs_complex64");
|
||||
if (are_types_identical(bt, t_complex128)) add_package_dependency(c, "runtime", "abs_complex128");
|
||||
if (are_types_identical(bt, t_quaternion128)) add_package_dependency(c, "runtime", "abs_quaternion128");
|
||||
if (are_types_identical(bt, t_quaternion256)) add_package_dependency(c, "runtime", "abs_quaternion256");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6232,8 +6457,11 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
|
||||
case Token_Imag: {
|
||||
String s = bl->token.string;
|
||||
Rune r = s[s.len-1];
|
||||
// NOTE(bill, 2019-08-25): Allow for quaternions by having j and k imaginary numbers
|
||||
switch (r) {
|
||||
case 'i': t = t_untyped_complex; break;
|
||||
case 'i': t = t_untyped_complex; break;
|
||||
case 'j': t = t_untyped_quaternion; break;
|
||||
case 'k': t = t_untyped_quaternion; break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -1610,6 +1610,10 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) {
|
||||
|
||||
str_lit("quo_complex64"),
|
||||
str_lit("quo_complex128"),
|
||||
str_lit("mul_quaternion128"),
|
||||
str_lit("mul_quaternion256"),
|
||||
str_lit("quo_quaternion128"),
|
||||
str_lit("quo_quaternion256"),
|
||||
|
||||
str_lit("umodti3"),
|
||||
str_lit("udivti3"),
|
||||
@@ -1891,6 +1895,7 @@ void init_core_type_info(Checker *c) {
|
||||
t_type_info_integer = find_core_type(c, str_lit("Type_Info_Integer"));
|
||||
t_type_info_rune = find_core_type(c, str_lit("Type_Info_Rune"));
|
||||
t_type_info_float = find_core_type(c, str_lit("Type_Info_Float"));
|
||||
t_type_info_quaternion = find_core_type(c, str_lit("Type_Info_Quaternion"));
|
||||
t_type_info_complex = find_core_type(c, str_lit("Type_Info_Complex"));
|
||||
t_type_info_string = find_core_type(c, str_lit("Type_Info_String"));
|
||||
t_type_info_boolean = find_core_type(c, str_lit("Type_Info_Boolean"));
|
||||
@@ -1915,6 +1920,7 @@ void init_core_type_info(Checker *c) {
|
||||
t_type_info_integer_ptr = alloc_type_pointer(t_type_info_integer);
|
||||
t_type_info_rune_ptr = alloc_type_pointer(t_type_info_rune);
|
||||
t_type_info_float_ptr = alloc_type_pointer(t_type_info_float);
|
||||
t_type_info_quaternion_ptr = alloc_type_pointer(t_type_info_quaternion);
|
||||
t_type_info_complex_ptr = alloc_type_pointer(t_type_info_complex);
|
||||
t_type_info_string_ptr = alloc_type_pointer(t_type_info_string);
|
||||
t_type_info_boolean_ptr = alloc_type_pointer(t_type_info_boolean);
|
||||
|
||||
@@ -16,8 +16,11 @@ enum BuiltinProcId {
|
||||
BuiltinProc_swizzle,
|
||||
|
||||
BuiltinProc_complex,
|
||||
BuiltinProc_quaternion,
|
||||
BuiltinProc_real,
|
||||
BuiltinProc_imag,
|
||||
BuiltinProc_jmag,
|
||||
BuiltinProc_kmag,
|
||||
BuiltinProc_conj,
|
||||
|
||||
BuiltinProc_expand_to_tuple,
|
||||
@@ -172,8 +175,11 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
||||
{STR_LIT("swizzle"), 1, true, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
|
||||
{STR_LIT("complex"), 2, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
{STR_LIT("quaternion"), 4, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
{STR_LIT("real"), 1, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
{STR_LIT("imag"), 1, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
{STR_LIT("jmag"), 1, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
{STR_LIT("kmag"), 1, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
{STR_LIT("conj"), 1, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
|
||||
{STR_LIT("expand_to_tuple"), 1, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
245
src/ir.cpp
245
src/ir.cpp
@@ -3853,6 +3853,60 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *
|
||||
return ir_emit_load(proc, res);
|
||||
}
|
||||
|
||||
if (is_type_quaternion(t_left)) {
|
||||
ir_emit_comment(proc, str_lit("complex.arith.begin"));
|
||||
defer (ir_emit_comment(proc, str_lit("complex.arith.end")));
|
||||
|
||||
right = ir_emit_conv(proc, right, t_left);
|
||||
|
||||
Type *ft = base_complex_elem_type(t_left);
|
||||
|
||||
if (op == Token_Add || op == Token_Sub) {
|
||||
irValue *res = ir_add_local_generated(proc, type, false); // NOTE: initialized in full later
|
||||
irValue *x0 = ir_emit_struct_ev(proc, left, 0);
|
||||
irValue *x1 = ir_emit_struct_ev(proc, left, 1);
|
||||
irValue *x2 = ir_emit_struct_ev(proc, left, 2);
|
||||
irValue *x3 = ir_emit_struct_ev(proc, left, 3);
|
||||
|
||||
irValue *y0 = ir_emit_struct_ev(proc, right, 0);
|
||||
irValue *y1 = ir_emit_struct_ev(proc, right, 1);
|
||||
irValue *y2 = ir_emit_struct_ev(proc, right, 2);
|
||||
irValue *y3 = ir_emit_struct_ev(proc, right, 3);
|
||||
|
||||
irValue *z0 = ir_emit_arith(proc, op, x0, y0, ft);
|
||||
irValue *z1 = ir_emit_arith(proc, op, x1, y1, ft);
|
||||
irValue *z2 = ir_emit_arith(proc, op, x2, y2, ft);
|
||||
irValue *z3 = ir_emit_arith(proc, op, x3, y3, ft);
|
||||
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 0), z0);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 1), z1);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 2), z2);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 3), z3);
|
||||
|
||||
return ir_emit_load(proc, res);
|
||||
} else if (op == Token_Mul) {
|
||||
auto args = array_make<irValue *>(heap_allocator(), 2);
|
||||
args[0] = left;
|
||||
args[1] = right;
|
||||
|
||||
switch (8*type_size_of(ft)) {
|
||||
case 32: return ir_emit_runtime_call(proc, "mul_quaternion128", args);
|
||||
case 64: return ir_emit_runtime_call(proc, "mul_quaternion256", args);
|
||||
default: GB_PANIC("Unknown float type"); break;
|
||||
}
|
||||
} else if (op == Token_Quo) {
|
||||
auto args = array_make<irValue *>(heap_allocator(), 2);
|
||||
args[0] = left;
|
||||
args[1] = right;
|
||||
|
||||
switch (8*type_size_of(ft)) {
|
||||
case 32: return ir_emit_runtime_call(proc, "quo_quaternion128", args);
|
||||
case 64: return ir_emit_runtime_call(proc, "quo_quaternion256", args);
|
||||
default: GB_PANIC("Unknown float type"); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
if (op == Token_Add) {
|
||||
@@ -4188,7 +4242,7 @@ irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irVal
|
||||
}
|
||||
|
||||
if (is_type_complex(a)) {
|
||||
char *runtime_proc = "";
|
||||
char const *runtime_proc = "";
|
||||
i64 sz = 8*type_size_of(a);
|
||||
switch (sz) {
|
||||
case 64:
|
||||
@@ -4212,6 +4266,31 @@ irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irVal
|
||||
return ir_emit_runtime_call(proc, runtime_proc, args);
|
||||
}
|
||||
|
||||
if (is_type_quaternion(a)) {
|
||||
char const *runtime_proc = "";
|
||||
i64 sz = 8*type_size_of(a);
|
||||
switch (sz) {
|
||||
case 128:
|
||||
switch (op_kind) {
|
||||
case Token_CmpEq: runtime_proc = "quaternion128_eq"; break;
|
||||
case Token_NotEq: runtime_proc = "quaternion128_ne"; break;
|
||||
}
|
||||
break;
|
||||
case 256:
|
||||
switch (op_kind) {
|
||||
case Token_CmpEq: runtime_proc = "quaternion256_eq"; break;
|
||||
case Token_NotEq: runtime_proc = "quaternion256_ne"; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
GB_ASSERT(runtime_proc != nullptr);
|
||||
|
||||
auto args = array_make<irValue *>(ir_allocator(), 2);
|
||||
args[0] = left;
|
||||
args[1] = right;
|
||||
return ir_emit_runtime_call(proc, runtime_proc, args);
|
||||
}
|
||||
|
||||
if (is_type_bit_set(a)) {
|
||||
switch (op_kind) {
|
||||
case Token_Lt:
|
||||
@@ -4295,11 +4374,18 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) {
|
||||
case 0: result_type = alloc_type_pointer(ft); break;
|
||||
case 1: result_type = alloc_type_pointer(ft); break;
|
||||
}
|
||||
} else if (is_type_quaternion(t)) {
|
||||
Type *ft = base_complex_elem_type(t);
|
||||
switch (index) {
|
||||
case 0: result_type = alloc_type_pointer(ft); break;
|
||||
case 1: result_type = alloc_type_pointer(ft); break;
|
||||
case 2: result_type = alloc_type_pointer(ft); break;
|
||||
case 3: result_type = alloc_type_pointer(ft); break;
|
||||
}
|
||||
} else if (is_type_slice(t)) {
|
||||
switch (index) {
|
||||
case 0: result_type = alloc_type_pointer(alloc_type_pointer(t->Slice.elem)); break;
|
||||
case 1: result_type = alloc_type_pointer(t_int); break;
|
||||
case 2: result_type = alloc_type_pointer(t_int); break;
|
||||
}
|
||||
} else if (is_type_string(t)) {
|
||||
switch (index) {
|
||||
@@ -4370,6 +4456,17 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Basic_quaternion128: case Basic_quaternion256:
|
||||
{
|
||||
Type *ft = base_complex_elem_type(t);
|
||||
switch (index) {
|
||||
case 0: result_type = ft; break;
|
||||
case 1: result_type = ft; break;
|
||||
case 2: result_type = ft; break;
|
||||
case 3: result_type = ft; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Type_Struct:
|
||||
@@ -4752,6 +4849,8 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
||||
ev = exact_value_to_float(ev);
|
||||
} else if (is_type_complex(dst)) {
|
||||
ev = exact_value_to_complex(ev);
|
||||
} else if (is_type_quaternion(dst)) {
|
||||
ev = exact_value_to_quaternion(ev);
|
||||
} else if (is_type_string(dst)) {
|
||||
// Handled elsewhere
|
||||
GB_ASSERT_MSG(ev.kind == ExactValue_String, "%d", ev.kind);
|
||||
@@ -4875,6 +4974,49 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
||||
return ir_emit_load(proc, gen);
|
||||
}
|
||||
|
||||
if (is_type_quaternion(src) && is_type_quaternion(dst)) {
|
||||
// @QuaternionLayout
|
||||
Type *ft = base_complex_elem_type(dst);
|
||||
irValue *gen = ir_add_local_generated(proc, dst, false);
|
||||
irValue *q0 = ir_emit_conv(proc, ir_emit_struct_ev(proc, value, 0), ft);
|
||||
irValue *q1 = ir_emit_conv(proc, ir_emit_struct_ev(proc, value, 1), ft);
|
||||
irValue *q2 = ir_emit_conv(proc, ir_emit_struct_ev(proc, value, 2), ft);
|
||||
irValue *q3 = ir_emit_conv(proc, ir_emit_struct_ev(proc, value, 3), ft);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 0), q0);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 1), q1);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 2), q2);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 3), q3);
|
||||
return ir_emit_load(proc, gen);
|
||||
}
|
||||
|
||||
if (is_type_float(src) && is_type_complex(dst)) {
|
||||
Type *ft = base_complex_elem_type(dst);
|
||||
irValue *gen = ir_add_local_generated(proc, dst, true);
|
||||
irValue *real = ir_emit_conv(proc, value, ft);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 0), real);
|
||||
return ir_emit_load(proc, gen);
|
||||
}
|
||||
if (is_type_float(src) && is_type_quaternion(dst)) {
|
||||
Type *ft = base_complex_elem_type(dst);
|
||||
irValue *gen = ir_add_local_generated(proc, dst, true);
|
||||
irValue *real = ir_emit_conv(proc, value, ft);
|
||||
// @QuaternionLayout
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 3), real);
|
||||
return ir_emit_load(proc, gen);
|
||||
}
|
||||
if (is_type_complex(src) && is_type_quaternion(dst)) {
|
||||
Type *ft = base_complex_elem_type(dst);
|
||||
irValue *gen = ir_add_local_generated(proc, dst, true);
|
||||
irValue *real = ir_emit_conv(proc, ir_emit_struct_ev(proc, value, 0), ft);
|
||||
irValue *imag = ir_emit_conv(proc, ir_emit_struct_ev(proc, value, 1), ft);
|
||||
// @QuaternionLayout
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 3), real);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 0), imag);
|
||||
return ir_emit_load(proc, gen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// float <-> integer
|
||||
if (is_type_float(src) && is_type_integer(dst)) {
|
||||
irConvKind kind = irConv_fptosi;
|
||||
@@ -5315,6 +5457,7 @@ enum Typeid_Kind : u8 {
|
||||
Typeid_Rune,
|
||||
Typeid_Float,
|
||||
Typeid_Complex,
|
||||
Typeid_Quaternion,
|
||||
Typeid_String,
|
||||
Typeid_Boolean,
|
||||
Typeid_Any,
|
||||
@@ -6067,17 +6210,77 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
|
||||
return ir_emit_load(proc, dst);
|
||||
}
|
||||
|
||||
case BuiltinProc_quaternion: {
|
||||
ir_emit_comment(proc, str_lit("quaternion"));
|
||||
irValue *real = ir_build_expr(proc, ce->args[0]);
|
||||
irValue *imag = ir_build_expr(proc, ce->args[1]);
|
||||
irValue *jmag = ir_build_expr(proc, ce->args[2]);
|
||||
irValue *kmag = ir_build_expr(proc, ce->args[3]);
|
||||
|
||||
// @QuaternionLayout
|
||||
irValue *dst = ir_add_local_generated(proc, tv.type, false);
|
||||
Type *ft = base_complex_elem_type(tv.type);
|
||||
real = ir_emit_conv(proc, real, ft);
|
||||
imag = ir_emit_conv(proc, imag, ft);
|
||||
jmag = ir_emit_conv(proc, jmag, ft);
|
||||
kmag = ir_emit_conv(proc, kmag, ft);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, dst, 3), real);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, dst, 0), imag);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, dst, 1), jmag);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, dst, 2), kmag);
|
||||
|
||||
return ir_emit_load(proc, dst);
|
||||
}
|
||||
|
||||
case BuiltinProc_real: {
|
||||
ir_emit_comment(proc, str_lit("real"));
|
||||
irValue *val = ir_build_expr(proc, ce->args[0]);
|
||||
irValue *real = ir_emit_struct_ev(proc, val, 0);
|
||||
return ir_emit_conv(proc, real, tv.type);
|
||||
if (is_type_complex(ir_type(val))) {
|
||||
irValue *real = ir_emit_struct_ev(proc, val, 0);
|
||||
return ir_emit_conv(proc, real, tv.type);
|
||||
} else if (is_type_quaternion(ir_type(val))) {
|
||||
// @QuaternionLayout
|
||||
irValue *real = ir_emit_struct_ev(proc, val, 3);
|
||||
return ir_emit_conv(proc, real, tv.type);
|
||||
}
|
||||
GB_PANIC("invalid type for real");
|
||||
return nullptr;
|
||||
}
|
||||
case BuiltinProc_imag: {
|
||||
ir_emit_comment(proc, str_lit("imag"));
|
||||
irValue *val = ir_build_expr(proc, ce->args[0]);
|
||||
irValue *imag = ir_emit_struct_ev(proc, val, 1);
|
||||
return ir_emit_conv(proc, imag, tv.type);
|
||||
if (is_type_complex(ir_type(val))) {
|
||||
irValue *imag = ir_emit_struct_ev(proc, val, 1);
|
||||
return ir_emit_conv(proc, imag, tv.type);
|
||||
} else if (is_type_quaternion(ir_type(val))) {
|
||||
// @QuaternionLayout
|
||||
irValue *imag = ir_emit_struct_ev(proc, val, 0);
|
||||
return ir_emit_conv(proc, imag, tv.type);
|
||||
}
|
||||
GB_PANIC("invalid type for imag");
|
||||
return nullptr;
|
||||
}
|
||||
case BuiltinProc_jmag: {
|
||||
ir_emit_comment(proc, str_lit("jmag"));
|
||||
irValue *val = ir_build_expr(proc, ce->args[0]);
|
||||
if (is_type_quaternion(ir_type(val))) {
|
||||
// @QuaternionLayout
|
||||
irValue *imag = ir_emit_struct_ev(proc, val, 1);
|
||||
return ir_emit_conv(proc, imag, tv.type);
|
||||
}
|
||||
GB_PANIC("invalid type for jmag");
|
||||
return nullptr;
|
||||
}
|
||||
case BuiltinProc_kmag: {
|
||||
ir_emit_comment(proc, str_lit("kmag"));
|
||||
irValue *val = ir_build_expr(proc, ce->args[0]);
|
||||
if (is_type_quaternion(ir_type(val))) {
|
||||
// @QuaternionLayout
|
||||
irValue *imag = ir_emit_struct_ev(proc, val, 2);
|
||||
return ir_emit_conv(proc, imag, tv.type);
|
||||
}
|
||||
GB_PANIC("invalid type for kmag");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
case BuiltinProc_conj: {
|
||||
@@ -6092,6 +6295,20 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
|
||||
imag = ir_emit_unary_arith(proc, Token_Sub, imag, ir_type(imag));
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 0), real);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 1), imag);
|
||||
} else if (is_type_quaternion(t)) {
|
||||
// @QuaternionLayout
|
||||
res = ir_add_local_generated(proc, tv.type, false);
|
||||
irValue *real = ir_emit_struct_ev(proc, val, 3);
|
||||
irValue *imag = ir_emit_struct_ev(proc, val, 0);
|
||||
irValue *jmag = ir_emit_struct_ev(proc, val, 1);
|
||||
irValue *kmag = ir_emit_struct_ev(proc, val, 2);
|
||||
imag = ir_emit_unary_arith(proc, Token_Sub, imag, ir_type(imag));
|
||||
jmag = ir_emit_unary_arith(proc, Token_Sub, jmag, ir_type(jmag));
|
||||
kmag = ir_emit_unary_arith(proc, Token_Sub, kmag, ir_type(kmag));
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 3), real);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 0), imag);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 1), jmag);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 2), kmag);
|
||||
}
|
||||
return ir_emit_load(proc, res);
|
||||
}
|
||||
@@ -6162,7 +6379,16 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
|
||||
return x;
|
||||
}
|
||||
ir_emit_comment(proc, str_lit("abs"));
|
||||
if (is_type_complex(t)) {
|
||||
if (is_type_quaternion(t)) {
|
||||
i64 sz = 8*type_size_of(t);
|
||||
auto args = array_make<irValue *>(ir_allocator(), 1);
|
||||
args[0] = x;
|
||||
switch (sz) {
|
||||
case 128: return ir_emit_runtime_call(proc, "abs_quaternion128", args);
|
||||
case 256: return ir_emit_runtime_call(proc, "abs_quaternion256", args);
|
||||
}
|
||||
GB_PANIC("Unknown complex type");
|
||||
} else if (is_type_complex(t)) {
|
||||
i64 sz = 8*type_size_of(t);
|
||||
auto args = array_make<irValue *>(ir_allocator(), 1);
|
||||
args[0] = x;
|
||||
@@ -9876,6 +10102,11 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_complex_ptr);
|
||||
break;
|
||||
|
||||
case Basic_quaternion128:
|
||||
case Basic_quaternion256:
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_quaternion_ptr);
|
||||
break;
|
||||
|
||||
case Basic_rawptr:
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_pointer_ptr);
|
||||
break;
|
||||
|
||||
@@ -418,20 +418,23 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t, bool in_struct) {
|
||||
}
|
||||
return;
|
||||
|
||||
// case Basic_f16: ir_write_str_lit(f, "half"); return;
|
||||
case Basic_f32: ir_write_str_lit(f, "float"); return;
|
||||
case Basic_f64: ir_write_str_lit(f, "double"); return;
|
||||
// case Basic_f16: ir_write_str_lit(f, "half"); return;
|
||||
case Basic_f32: ir_write_str_lit(f, "float"); return;
|
||||
case Basic_f64: ir_write_str_lit(f, "double"); return;
|
||||
|
||||
// case Basic_complex32: ir_write_str_lit(f, "%%..complex32"); return;
|
||||
case Basic_complex64: ir_write_str_lit(f, "%..complex64"); return;
|
||||
case Basic_complex128: ir_write_str_lit(f, "%..complex128"); return;
|
||||
// case Basic_complex32: ir_write_str_lit(f, "%%..complex32"); return;
|
||||
case Basic_complex64: ir_write_str_lit(f, "%..complex64"); return;
|
||||
case Basic_complex128: ir_write_str_lit(f, "%..complex128"); return;
|
||||
|
||||
case Basic_any: ir_write_str_lit(f, "%..any"); return;
|
||||
case Basic_rawptr: ir_write_str_lit(f, "%..rawptr"); return;
|
||||
case Basic_string: ir_write_str_lit(f, "%..string"); return;
|
||||
case Basic_cstring: ir_write_str_lit(f, "i8*"); return;
|
||||
case Basic_quaternion128: ir_write_str_lit(f, "%..quaternion128"); return;
|
||||
case Basic_quaternion256: ir_write_str_lit(f, "%..quaternion256"); return;
|
||||
|
||||
case Basic_typeid: ir_write_str_lit(f, "%..typeid"); return;
|
||||
case Basic_any: ir_write_str_lit(f, "%..any"); return;
|
||||
case Basic_rawptr: ir_write_str_lit(f, "%..rawptr"); return;
|
||||
case Basic_string: ir_write_str_lit(f, "%..string"); return;
|
||||
case Basic_cstring: ir_write_str_lit(f, "i8*"); return;
|
||||
|
||||
case Basic_typeid: ir_write_str_lit(f, "%..typeid"); return;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -811,6 +814,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
|
||||
break;
|
||||
}
|
||||
case ExactValue_Complex: {
|
||||
// xy/ri format
|
||||
type = core_type(type);
|
||||
GB_ASSERT_MSG(is_type_complex(type), "%s", type_to_string(type));
|
||||
Type *ft = base_complex_elem_type(type);
|
||||
@@ -823,6 +827,26 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
|
||||
ir_write_byte(f, '}');
|
||||
break;
|
||||
}
|
||||
|
||||
case ExactValue_Quaternion: {
|
||||
// xyzw/ijkr format
|
||||
type = core_type(type);
|
||||
GB_ASSERT_MSG(is_type_quaternion(type), "%s", type_to_string(type));
|
||||
Type *ft = base_complex_elem_type(type);
|
||||
ir_write_byte(f, ' ');
|
||||
ir_write_byte(f, '{');
|
||||
ir_print_type(f, m, ft); ir_write_byte(f, ' ');
|
||||
ir_print_exact_value(f, m, exact_value_float(value.value_quaternion.imag), ft);
|
||||
ir_write_str_lit(f, ", "); ir_print_type(f, m, ft); ir_write_byte(f, ' ');
|
||||
ir_print_exact_value(f, m, exact_value_float(value.value_quaternion.jmag), ft);
|
||||
ir_write_str_lit(f, ", "); ir_print_type(f, m, ft); ir_write_byte(f, ' ');
|
||||
ir_print_exact_value(f, m, exact_value_float(value.value_quaternion.kmag), ft);
|
||||
ir_write_str_lit(f, ", "); ir_print_type(f, m, ft); ir_write_byte(f, ' ');
|
||||
ir_print_exact_value(f, m, exact_value_float(value.value_quaternion.real), ft);
|
||||
ir_write_byte(f, '}');
|
||||
break;
|
||||
}
|
||||
|
||||
case ExactValue_Pointer:
|
||||
if (value.value_pointer == 0) {
|
||||
if (is_type_typeid(type)) {
|
||||
@@ -2246,6 +2270,13 @@ void print_llvm_ir(irGen *ir) {
|
||||
ir_print_encoded_local(f, str_lit("..complex128"));
|
||||
ir_write_str_lit(f, " = type {double, double} ; Basic_complex128\n");
|
||||
|
||||
ir_print_encoded_local(f, str_lit("..quaternion64"));
|
||||
ir_write_str_lit(f, " = type {half, half, half, half} ; Basic_quaternion64\n");
|
||||
ir_print_encoded_local(f, str_lit("..quaternion128"));
|
||||
ir_write_str_lit(f, " = type {float, float, float, float} ; Basic_quaternion128\n");
|
||||
ir_print_encoded_local(f, str_lit("..quaternion256"));
|
||||
ir_write_str_lit(f, " = type {double, double, double, double} ; Basic_quaternion256\n");
|
||||
|
||||
ir_print_encoded_local(f, str_lit("..typeid"));
|
||||
ir_write_str_lit(f, " = type ");
|
||||
ir_print_type(f, m, t_uintptr);
|
||||
|
||||
@@ -745,7 +745,10 @@ exponent:
|
||||
scan_mantissa(t, 10);
|
||||
}
|
||||
|
||||
if (t->curr_rune == 'i') {
|
||||
switch (t->curr_rune) {
|
||||
case 'i':
|
||||
case 'j':
|
||||
case 'k':
|
||||
token.kind = Token_Imag;
|
||||
advance_to_next_rune(t);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,9 @@ enum BasicKind {
|
||||
Basic_complex64,
|
||||
Basic_complex128,
|
||||
|
||||
Basic_quaternion128,
|
||||
Basic_quaternion256,
|
||||
|
||||
Basic_int,
|
||||
Basic_uint,
|
||||
Basic_uintptr,
|
||||
@@ -66,6 +69,7 @@ enum BasicKind {
|
||||
Basic_UntypedInteger,
|
||||
Basic_UntypedFloat,
|
||||
Basic_UntypedComplex,
|
||||
Basic_UntypedQuaternion,
|
||||
Basic_UntypedString,
|
||||
Basic_UntypedRune,
|
||||
Basic_UntypedNil,
|
||||
@@ -82,17 +86,18 @@ enum BasicFlag {
|
||||
BasicFlag_Unsigned = GB_BIT(2),
|
||||
BasicFlag_Float = GB_BIT(3),
|
||||
BasicFlag_Complex = GB_BIT(4),
|
||||
BasicFlag_Pointer = GB_BIT(5),
|
||||
BasicFlag_String = GB_BIT(6),
|
||||
BasicFlag_Rune = GB_BIT(7),
|
||||
BasicFlag_Untyped = GB_BIT(8),
|
||||
BasicFlag_Quaternion = GB_BIT(5),
|
||||
BasicFlag_Pointer = GB_BIT(6),
|
||||
BasicFlag_String = GB_BIT(7),
|
||||
BasicFlag_Rune = GB_BIT(8),
|
||||
BasicFlag_Untyped = GB_BIT(9),
|
||||
|
||||
BasicFlag_LLVM = GB_BIT(10),
|
||||
BasicFlag_LLVM = GB_BIT(11),
|
||||
|
||||
BasicFlag_EndianLittle = GB_BIT(13),
|
||||
BasicFlag_EndianBig = GB_BIT(14),
|
||||
|
||||
BasicFlag_Numeric = BasicFlag_Integer | BasicFlag_Float | BasicFlag_Complex,
|
||||
BasicFlag_Numeric = BasicFlag_Integer | BasicFlag_Float | BasicFlag_Complex | BasicFlag_Quaternion,
|
||||
BasicFlag_Ordered = BasicFlag_Integer | BasicFlag_Float | BasicFlag_String | BasicFlag_Pointer | BasicFlag_Rune,
|
||||
BasicFlag_OrderedNumeric = BasicFlag_Integer | BasicFlag_Float | BasicFlag_Rune,
|
||||
BasicFlag_ConstantType = BasicFlag_Boolean | BasicFlag_Numeric | BasicFlag_String | BasicFlag_Pointer | BasicFlag_Rune,
|
||||
@@ -342,6 +347,9 @@ gb_global Type basic_types[] = {
|
||||
{Type_Basic, {Basic_complex64, BasicFlag_Complex, 8, STR_LIT("complex64")}},
|
||||
{Type_Basic, {Basic_complex128, BasicFlag_Complex, 16, STR_LIT("complex128")}},
|
||||
|
||||
{Type_Basic, {Basic_quaternion128, BasicFlag_Quaternion, 16, STR_LIT("quaternion128")}},
|
||||
{Type_Basic, {Basic_quaternion256, BasicFlag_Quaternion, 32, STR_LIT("quaternion256")}},
|
||||
|
||||
{Type_Basic, {Basic_int, BasicFlag_Integer, -1, STR_LIT("int")}},
|
||||
{Type_Basic, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, -1, STR_LIT("uint")}},
|
||||
{Type_Basic, {Basic_uintptr, BasicFlag_Integer | BasicFlag_Unsigned, -1, STR_LIT("uintptr")}},
|
||||
@@ -377,6 +385,7 @@ gb_global Type basic_types[] = {
|
||||
{Type_Basic, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, 0, STR_LIT("untyped integer")}},
|
||||
{Type_Basic, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, 0, STR_LIT("untyped float")}},
|
||||
{Type_Basic, {Basic_UntypedComplex, BasicFlag_Complex | BasicFlag_Untyped, 0, STR_LIT("untyped complex")}},
|
||||
{Type_Basic, {Basic_UntypedQuaternion, BasicFlag_Quaternion | BasicFlag_Untyped, 0, STR_LIT("untyped quaternion")}},
|
||||
{Type_Basic, {Basic_UntypedString, BasicFlag_String | BasicFlag_Untyped, 0, STR_LIT("untyped string")}},
|
||||
{Type_Basic, {Basic_UntypedRune, BasicFlag_Integer | BasicFlag_Untyped, 0, STR_LIT("untyped rune")}},
|
||||
{Type_Basic, {Basic_UntypedNil, BasicFlag_Untyped, 0, STR_LIT("untyped nil")}},
|
||||
@@ -412,6 +421,9 @@ gb_global Type *t_f64 = &basic_types[Basic_f64];
|
||||
gb_global Type *t_complex64 = &basic_types[Basic_complex64];
|
||||
gb_global Type *t_complex128 = &basic_types[Basic_complex128];
|
||||
|
||||
gb_global Type *t_quaternion128 = &basic_types[Basic_quaternion128];
|
||||
gb_global Type *t_quaternion256 = &basic_types[Basic_quaternion256];
|
||||
|
||||
gb_global Type *t_int = &basic_types[Basic_int];
|
||||
gb_global Type *t_uint = &basic_types[Basic_uint];
|
||||
gb_global Type *t_uintptr = &basic_types[Basic_uintptr];
|
||||
@@ -446,6 +458,7 @@ gb_global Type *t_untyped_bool = &basic_types[Basic_UntypedBool];
|
||||
gb_global Type *t_untyped_integer = &basic_types[Basic_UntypedInteger];
|
||||
gb_global Type *t_untyped_float = &basic_types[Basic_UntypedFloat];
|
||||
gb_global Type *t_untyped_complex = &basic_types[Basic_UntypedComplex];
|
||||
gb_global Type *t_untyped_quaternion = &basic_types[Basic_UntypedQuaternion];
|
||||
gb_global Type *t_untyped_string = &basic_types[Basic_UntypedString];
|
||||
gb_global Type *t_untyped_rune = &basic_types[Basic_UntypedRune];
|
||||
gb_global Type *t_untyped_nil = &basic_types[Basic_UntypedNil];
|
||||
@@ -472,6 +485,7 @@ gb_global Type *t_type_info_integer = nullptr;
|
||||
gb_global Type *t_type_info_rune = nullptr;
|
||||
gb_global Type *t_type_info_float = nullptr;
|
||||
gb_global Type *t_type_info_complex = nullptr;
|
||||
gb_global Type *t_type_info_quaternion = nullptr;
|
||||
gb_global Type *t_type_info_any = nullptr;
|
||||
gb_global Type *t_type_info_typeid = nullptr;
|
||||
gb_global Type *t_type_info_string = nullptr;
|
||||
@@ -496,6 +510,7 @@ gb_global Type *t_type_info_integer_ptr = nullptr;
|
||||
gb_global Type *t_type_info_rune_ptr = nullptr;
|
||||
gb_global Type *t_type_info_float_ptr = nullptr;
|
||||
gb_global Type *t_type_info_complex_ptr = nullptr;
|
||||
gb_global Type *t_type_info_quaternion_ptr = nullptr;
|
||||
gb_global Type *t_type_info_any_ptr = nullptr;
|
||||
gb_global Type *t_type_info_typeid_ptr = nullptr;
|
||||
gb_global Type *t_type_info_string_ptr = nullptr;
|
||||
@@ -924,6 +939,13 @@ bool is_type_complex(Type *t) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool is_type_quaternion(Type *t) {
|
||||
t = core_type(t);
|
||||
if (t->kind == Type_Basic) {
|
||||
return (t->Basic.flags & BasicFlag_Quaternion) != 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool is_type_f32(Type *t) {
|
||||
t = core_type(t);
|
||||
if (t->kind == Type_Basic) {
|
||||
@@ -1063,12 +1085,15 @@ bool is_type_simple_compare(Type *t) {
|
||||
|
||||
Type *base_complex_elem_type(Type *t) {
|
||||
t = core_type(t);
|
||||
if (is_type_complex(t)) {
|
||||
if (t->kind == Type_Basic) {
|
||||
switch (t->Basic.kind) {
|
||||
// case Basic_complex32: return t_f16;
|
||||
case Basic_complex64: return t_f32;
|
||||
case Basic_complex128: return t_f64;
|
||||
case Basic_UntypedComplex: return t_untyped_float;
|
||||
// case Basic_complex32: return t_f16;
|
||||
case Basic_complex64: return t_f32;
|
||||
case Basic_complex128: return t_f64;
|
||||
case Basic_quaternion128: return t_f32;
|
||||
case Basic_quaternion256: return t_f64;
|
||||
case Basic_UntypedComplex: return t_untyped_float;
|
||||
case Basic_UntypedQuaternion: return t_untyped_float;
|
||||
}
|
||||
}
|
||||
GB_PANIC("Invalid complex type");
|
||||
@@ -1818,6 +1843,7 @@ Type *default_type(Type *type) {
|
||||
case Basic_UntypedInteger: return t_int;
|
||||
case Basic_UntypedFloat: return t_f64;
|
||||
case Basic_UntypedComplex: return t_complex128;
|
||||
case Basic_UntypedQuaternion: return t_quaternion256;
|
||||
case Basic_UntypedString: return t_string;
|
||||
case Basic_UntypedRune: return t_rune;
|
||||
}
|
||||
@@ -2358,6 +2384,8 @@ i64 type_align_of_internal(Type *t, TypePath *path) {
|
||||
|
||||
case Basic_complex64: case Basic_complex128:
|
||||
return type_size_of_internal(t, path) / 2;
|
||||
case Basic_quaternion128: case Basic_quaternion256:
|
||||
return type_size_of_internal(t, path) / 4;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user