Examples
...
hello.void
{ v_import("level-00/voidc_target.void");
v_import("level-00/voidc_types.void");
v_import("llvm-c/Core.void");
v_import("llvm-c/TargetMachine.void");
v_import("printf.void");
}
{ triple = LLVMGetDefaultTargetTriple();
tr_v = v_alloca(LLVMTargetRef);
LLVMGetTargetFromTriple(triple, tr_v, 0);
tr = v_load(tr_v);
cpu_name = LLVMGetHostCPUName();
cpu_features = LLVMGetHostCPUFeatures();
target_machine =
LLVMCreateTargetMachine
(
tr,
triple,
cpu_name,
cpu_features,
LLVMCodeGenLevelDefault,
LLVMRelocPIC, //- WTF !?!
LLVMCodeModelDefault
);
LLVMDisposeMessage(cpu_features);
LLVMDisposeMessage(cpu_name);
LLVMDisposeMessage(triple);
//-----------------------------------------------------------------
llvm_ctx = v_target_get_voidc_llvm_ctx();
module = LLVMModuleCreateWithNameInContext("hello_mod", llvm_ctx);
builder = v_target_get_voidc_builder();
int_ = v_type_get_llvm_type(int);
main_ft_ = LLVMFunctionType(int_, 0, 0, false);
main_f = LLVMAddFunction(module, "main", main_ft_);
entry = LLVMAppendBasicBlockInContext(llvm_ctx, main_f, "entry");
LLVMPositionBuilderAtEnd(builder, entry);
typ_ = v_alloca(LLVMTypeRef);
char_ = v_type_get_llvm_type(char);
char_ptr_ = LLVMPointerType(char_, 0);
v_store(char_ptr_, typ_);
printf_ft_ = LLVMFunctionType(int_, typ_, 1, true);
printf_f = LLVMAddFunction(module, "printf", printf_ft_);
str = LLVMBuildGlobalStringPtr(builder, "Hello world!\n", "str");
val = v_alloca(LLVMValueRef);
v_store(str, val);
LLVMBuildCall2(builder, printf_ft_, printf_f, val, 1, "");
null_ = LLVMConstNull(int_);
LLVMBuildRet(builder, null_);
LLVMClearInsertionPosition(builder);
//-----------------------------------------------------------------
msg = LLVMPrintModuleToString(module);
printf("\n%s\n", msg);
LLVMDisposeMessage(msg);
//-----------------------------------------------------------------
LLVMTargetMachineEmitToFile(target_machine,
module,
"hello.o",
LLVMObjectFile,
0);
//-----------------------------------------------------------------
LLVMDisposeModule(module);
LLVMDisposeTargetMachine(target_machine);
}
{ typ = v_alloca(v_type_ptr);
char_ptr = v_pointer_type(char, 0);
v_store(char_ptr, typ);
system_ft = v_function_type(int, typ, 1, false);
v_add_symbol("system", system_ft, 0);
}
{ system("clang hello.o -o hello");
system("bash -c ./hello");
}
...
...
macros_test.void
{ v_import("level-00");
v_import("level-01");
v_import("level-02");
v_import("level-03/intrinsics_derive.void");
v_import("level-03/local_objects.void");
v_import("level-03/heap_objects.void");
v_import("level-03/global_objects.void");
v_import("level-03/coercions.void");
v_import("level-03/namespaces.void");
v_import("level-03/generics_etc.void");
v_import("level-03/generating_ast.void");
v_import("level-03/macros.void");
v_import("printf.void");
}
{ v_enable_level_01();
v_enable_level_02();
voidc_enable_intrinsics_derive();
voidc_enable_local_objects();
voidc_enable_heap_objects();
voidc_enable_global_objects();
voidc_enable_coercions();
voidc_enable_namespaces();
voidc_enable_generics_etc();
voidc_enable_generating_ast();
voidc_enable_macros();
}
//---------------------------------------------------------------------
#define foo: (x, y) = x*y;
{ v = foo(6, 7);
printf("v: %d\n", v);
}
#define bar: (v) = printf("bar: %d\n", v);
{ bar(777);
}
//---------------------------------------------------------------------
#define fact: (n) =
(
#if (n <= 0) 1
#else n * fact(n-1)
#endif
);
{ n = 7;
printf("fact(%d): %d\n", n, fact(n));
}
//---------------------------------------------------------------------
#define fib: (n) =
{
#define fibb: (a, b, m) =
(
#if (m > 0) fibb(b, a+b, m-1)
#else a
#endif
);
fibb(0, 1, n)
};
{ n = 19;
printf("fib(%d): %d\n", n, fib(n));
}
//---------------------------------------------------------------------
#define FOO: (x, y = 40+x) = x + y;
{
printf("FOO(1, 1): %d\n", FOO(1, 1));
printf("FOO(1): %d\n", FOO(1));
}
//---------------------------------------------------------------------
#define (_*_): (s: v_std_string_t, n) ~> v_std_string_t =
{
tmp: &v_std_string_t := {};
str = v_std_string_get(&s);
for (i: &int := 0; i < n; ++i)
{
v_std_string_append(&tmp, str);
}
tmp
};
#define (_.str): (s: *const char) ~> v_std_string_t =
{
tmp: &v_std_string_t := {};
v_std_string_set(&tmp, s);
tmp
};
//{ voidc_verify_jit_module_optimized(true); }
//{ v_debug_print_module(2); }
{ ns = ("Qwe" : *const char).str * 7;
printf("ns: %s\n", v_std_string_get(&ns));
}
#define (_*_): (a: char[4], n) ~> v_std_string_t = (a: *const char).str * n;
{ ns = "Asd" * 8;
printf("ns: %s\n", v_std_string_get(&ns));
}
#define (_.c_str): (s: &v_std_string_t) ~> *char = v_std_string_get(&s);
#define (_.c_str): (s: v_std_string_t) ~> *const char = v_std_string_get(&s);
{ ns = "Zxc" * 9;
printf("ns: %s\n", ns.c_str);
}
#define (_[]): (s: &v_std_string_t, i) ~> &char = s.c_str[i];
#define (_[]): (s: v_std_string_t, i) ~> char = s.c_str[i];
{ ns = "Zxc" * 10;
for (i: &int := 0; i < 10; ++i) printf("ns[%d]: %c\n", i, ns[i]);
}
#define str: (s) = (s: *const char);
{
printf("[%s]\n", (str("Qwerty").str * 5).c_str);
}
//=====================================================================
{ v_import("macros_mod_test.void"); }
//---------------------------------------------------------------------
#do (my.instantiate_list(int),
my.instantiate_list(long))
//---------------------------------------------------------------------
{
l: &my.list(int) := {};
l << 5
<< 6
<< 7
<< 8
<< 9;
for (i: &int := 0, n = l.size; i < n; ++i)
{
printf("l[%d]: %d\n", i, l[i]);
}
l0: my.list(int) = {};
l1 = l0 << 55;
l2 = l1 << 66 << 77;
l3 = l2 << 88 << 99;
ll: &my.list(int)[4] := { l0, l1, l2, l3 };
for (i: &int := 0; i < 4; ++i)
{
for (j: &int := 0, n = ll[i].size; j < n; ++j)
{
printf("ll[%d][%d]: %d\n", i, j, ll[i][j]);
}
}
l.impl; //- WTF !?!?!?!?!?!?!
}
//---------------------------------------------------------------------
#define instantiate_list_plus: (T)
{'unit_defn_list'
(_+_): (a: my.list(T), b: my.list(T)) ~> my.list(T) =
{
tmp: &my.list(T) := a;
for (i: &int := 0, n = b.size; i < n; ++i)
{
tmp << b[i];
}
tmp
};
'unit_defn_list'}
#do (instantiate_list_plus(long))
//{ voidc_verify_jit_module_optimized(true); }
//{ v_debug_print_module(2); }
//---------------------------------------------------------------------
{
a: my.list(long) = { 9, 8, 7, 6, 5 };
b: my.list(long) = { 4, 3 };
l = a + b + { 2, 1, 0 };
for (i: &int := 0, n = l.size; i < n; ++i)
{
printf("l[%d]: %ld\n", i, l[i]);
}
}
macros_mod_test.void
{ v_import("level-00");
v_import("level-01");
v_import("level-02");
v_import("level-03/intrinsics_derive.void");
v_import("level-03/local_objects.void");
v_import("level-03/heap_objects.void");
v_import("level-03/global_objects.void");
v_import("level-03/coercions.void");
v_import("level-03/namespaces.void");
v_import("level-03/generics_etc.void");
v_import("level-03/generating_ast.void");
v_import("level-03/macros.void");
v_import("printf.void");
}
{ v_enable_level_01();
v_enable_level_02();
voidc_enable_intrinsics_derive();
voidc_enable_local_objects();
voidc_enable_heap_objects();
voidc_enable_global_objects();
voidc_enable_coercions();
voidc_enable_namespaces();
voidc_enable_generics_etc();
voidc_enable_generating_ast();
voidc_enable_macros();
}
//---------------------------------------------------------------------
{ q_ref = v_reference_type(v_quark_t, 0);
q = v_quark_ptr_from_string;
v_add_symbol("list_q", q_ref, q("my.list"));
v_add_symbol("q_static_type_t", q_ref, q("v_static_type_t"));
}
//=====================================================================
{ voidc_unit_begin_module("macros_mod_test_module"); }
//---------------------------------------------------------------------
export
namespace my {
//---------------------------------------------------------------------
#define list: (T: v_static_type_t) ~> v_static_type_t = v_generic("my.list", t(T));
//---------------------------------------------------------------------
private
list_op_braces_intrinsic: (aux: *void, vis: *voidc_visitor_t, self: *v_ast_base_t,
arg_ptrs: **v_ast_expr_t, arg_count: unsigned
) ~> void
{
//printf("list_op_braces_intrinsic: start\n");
//defer printf("list_op_braces_intrinsic: stop\n");
tr: &*v_type_t := v_get_result_type();
is_reference = v_type_is_reference(tr);
addr_sp: &unsigned := undef;
if (is_reference)
{
addr_sp := v_type_refptr_get_address_space(tr); //- Sic!
tr := v_type_refptr_get_element_type(tr); //- Sic!
}
vr: &LLVMValueRef := v_get_result_value();
if (vr == 0) vr := v_make_temporary(tr, 0);
list: &v_ast_stmt_list_t :=
{'stmt_list'
my_any: &v_std_any_t := {};
#define my_step: (lst, v)
{'stmt_list'
v_std_any_set_value(&my_any, v);
v_list_append(lst, lst, &my_any);
'stmt_list'}
'stmt_list'};
expr: &v_ast_expr_t[2] := {};
v_ast_make_expr_compiled(expr+0, v_pointer_type(v_util_list_t, 0), vr);
typ = (aux: *v_type_t);
my_step_q = v_quark_from_string("my_step");
stmt: &v_ast_stmt_t := {};
for (i: &int := 0; i < arg_count; ++i)
{
v_reset_result();
v_set_result_type(typ);
v_ast_accept_visitor(arg_ptrs[i], vis);
val = v_get_result_value();
v_ast_make_expr_compiled(expr+1, typ, val);
v_ast_make_stmt_call(&stmt, 0, my_step_q, expr, 2);
v_list_append(&list, &list, &stmt);
}
v_ast_make_stmt_block(&stmt, &list, false);
v_reset_result();
v_ast_accept_visitor(&stmt, vis);
if (is_reference) v_set_result_type(v_reference_type(tr, addr_sp));
else v_set_result_type(tr);
v_set_result_value(vr);
}
//---------------------------------------------------------------------
private
register_list_op_braces_intrinsic: (*void, vis: *voidc_visitor_t, self: *v_ast_base_t) ~> void
{
args = v_ast_expr_call_get_arg_list((self: *v_ast_expr_t));
arg0 = v_list_get_item(args, 0); //- Element type
arg1 = v_list_get_item(args, 1); //- List type
static_type_t = v_find_type_q(q_static_type_t);
v_reset_result();
v_set_result_type(static_type_t);
v_ast_accept_visitor(arg0, vis);
elt = (v_get_result_value() : *v_type_t);
v_reset_result();
v_set_result_type(static_type_t);
v_ast_accept_visitor(arg1, vis);
lst = (v_get_result_value() : *v_type_t);
sstr: &v_std_string_t := {};
v_std_string_set(&sstr, "my.list_op_braces-");
voidc_internal_std_string_append_type(&sstr, elt);
iname = v_std_string_get(&sstr);
v_add_overload("v.op_braces", lst, iname);
v_add_intrinsic(iname, list_op_braces_intrinsic, elt); //- Sic!
}
//---------------------------------------------------------------------
#define instantiate_list: (T)
{'unit_defn_list'
namespace my
{
#do (v_set_implementation_type(list(T), v_util_list_t))
private
namespace v_generic_ns(list_detail, t(T))
{
impl_t = v_get_implementation_type(list(T));
alwaysinline
(_.impl): (s: &list(T)) ~> &impl_t = *(&s : *impl_t);
}
//-------------------------------------------------------------
inlinehint
(v_initialize(_)): (sp: *list(T), N: size_t) ~> void
{
v_initialize(&sp->impl, N);
for (i: &int := 0; i < N; ++i)
{
v_make_list_nil(&sp[i].impl);
}
}
alwaysinline
(v_terminate(_)): (sp: *list(T), N: size_t) ~> void
{
v_terminate(&sp->impl, N);
}
alwaysinline
(v_copy(_)): (dst: *list(T), src: *const list(T), N: size_t) ~> void
{
v_copy(&dst->impl, &src->impl, N);
}
#do (register_list_op_braces(T, list(T)))
//-------------------------------------------------------------
inlinehint
(_[]): (sp: list(T), i: size_t) ~> T
{
a = v_list_get_item(&sp.impl, i);
v_assert(a);
return v_std_any_get_value(T, a);
}
inlinehint
(_<<_): (sp: list(T), v: T) ~> list(T)
{
a: &v_std_any_t := {};
v_std_any_set_value(&a, v);
v_list_append(&v_get_return_value().impl, &sp.impl, &a);
}
inlinehint
(_<<_): (sp: &list(T), v: T) ~> &list(T) =
{
a: &v_std_any_t := {};
v_std_any_set_value(&a, v);
lst = &sp.impl;
v_list_append(lst, lst, &a);
sp
};
alwaysinline
(_.size): (sp: list(T)) ~> size_t = v_list_get_size(&sp.impl);
} //- namespace my
'unit_defn_list'}
//---------------------------------------------------------------------
enable_list_effort: (*void) ~> void
{
v_add_intrinsic("register_list_op_braces", register_list_op_braces_intrinsic, 0);
}
//---------------------------------------------------------------------
} //- namespace my
//=====================================================================
{ voidc_unit_end_module(); }
//---------------------------------------------------------------------
{ v_export_effort(my.enable_list_effort, 0); }
...
...
geometry.void
{ voidc_import("libvoidc.void"); }
{ voidc_make_header("geometry"); }
//---------------------------------------------------------------------
{
v_export_import("cstdio.void");
v_export_import("type_traits.void");
}
//---------------------------------------------------------------------
double = float(64);
fabs: (double) ~> double;
//---------------------------------------------------------------------
#define (_<<_): (f: *FILE, v) ~> *FILE =
{
t = typeof(v);
#if (t.is_reference)
t = t.element_type;
#endif
#if ((t.is_array || t.is_pointer) && t.element_type == char)
fprintf(f, "%s", v);
#else
v.print_to_file(f);
#endif
f
};
//---------------------------------------------------------------------
namespace Geometry
{
//---------------------------------------------------------------------
is_equal: (x: double, y: double) ~> bool;
alwaysinline
is_finite: (x: double) ~> bool = fabs(x) < 1e15; //- ?...
infinity = 1e1000;
det_3: (v: &double[9]) ~> double;
seq_equal: (a: *const double, b: *const double, n: int) ~> bool;
//=====================================================================
//- Vector (2D)
//=====================================================================
struct Vector
{
x: double;
y: double;
};
(_.print_to_file()): (v: Vector, f: *FILE) ~> void;
//---------------------------------------------------------------------
alwaysinline
(_+_): (a: Vector, b: Vector) ~> Vector = {a.x+b.x, a.y+b.y};
alwaysinline
(_-_): (a: Vector, b: Vector) ~> Vector = {a.x-b.x, a.y-b.y};
alwaysinline
(+_): (a: Vector) ~> Vector = a;
alwaysinline
(-_): (a: Vector) ~> Vector = {-a.x, -a.y};
alwaysinline
(_*_): (a: Vector, k: double) ~> Vector = {a.x*k, a.y*k};
alwaysinline
(_*__): (k: double, a: Vector) ~> Vector = {k*a.x, k*a.y};
alwaysinline
(_/_): (a: Vector, k: double) ~> Vector = {a.x/k, a.y/k};
(_==_): (a: Vector, b: Vector) ~> bool;
alwaysinline
(_!=_): (a: Vector, b: Vector) ~> bool = !(a == b);
//---------------------------------------------------------------------
namespace Vector
{
zero: Vector = {0, 0};
unit_x: Vector = {1, 0};
unit_y: Vector = {0, 1};
infinity: Vector = {infinity, infinity};
}
//---------------------------------------------------------------------
alwaysinline
(_.dot()): (a: Vector, b: Vector) ~> double = a.x*b.x + a.y*b.y;
alwaysinline
(_.crs()): (a: Vector, b: Vector) ~> double = a.x*b.y - a.y*b.x;
alwaysinline
(_.is_finite()): (a: Vector) ~> bool = is_finite(a.x) && is_finite(a.y);
//=====================================================================
//- Projective point (2D)
//=====================================================================
struct Point
{
x: double;
y: double;
w: double;
};
//---------------------------------------------------------------------
(_.print_to_file()): (p: Point, f: *FILE) ~> void;
//---------------------------------------------------------------------
alwaysinline
(_+_): (p: Point, v: Vector) ~> Point = {p.x + p.w*v.x, p.y + p.w*v.y, p.w};
#define (_-_): (a: Point, b) =
{
t = typeof(b);
#if (t.is_reference) t = t.element_type; #endif
#if (t == Point)
ret: Vector = {a.x/a.w - b.x/b.w, a.y/a.w - b.y/b.w};
#endif
#if (t == Vector)
ret: Point = {a.x - a.w*b.x, a.y - a.w*b.y, a.w};
#endif
ret
};
//---------------------------------------------------------------------
(_.norm()): (p: &Point) ~> bool;
(_.is_affine()): (p: &Point) ~> bool;
(_==_): (a: &Point, b: &Point) ~> bool;
alwaysinline
(_!=_): (a: &Point, b: &Point) ~> bool = !(a == b);
//---------------------------------------------------------------------
namespace Point
{
zero: Point = {0, 0, 1};
unit_x: Point = {1, 0, 1};
unit_y: Point = {0, 1, 1};
inf_x: Point = {1, 0, 0};
inf_y: Point = {0, 1, 0};
}
//=====================================================================
//- Projective line (2D)
//=====================================================================
struct Line
{
cx: double;
cy: double;
cw: double;
};
//---------------------------------------------------------------------
(_.print_to_file()): (l: Line, f: *FILE) ~> void;
//---------------------------------------------------------------------
alwaysinline
(_+_): (l: Line, v: Vector) ~> Line = {l.cx, l.cy, l.cw - l.cx*v.x - l.cy*v.y};
alwaysinline
(_-_): (l: Line, v: Vector) ~> Line = {l.cx, l.cy, l.cw + l.cx*v.x + l.cy*v.y};
//---------------------------------------------------------------------
(_.norm()): (l: &Line) ~> bool;
(_.is_affine()): (l: &Line) ~> bool;
(_==_): (a: &Line, b: &Line) ~> bool;
alwaysinline
(_!=_): (a: &Line, b: &Line) ~> bool = !(a == b);
//---------------------------------------------------------------------
namespace Line
{
infinity: Line = {0, 0, 1};
abscissa: Line = {0, 1, 0};
ordinate: Line = {1, 0, 0};
}
//=====================================================================
(_.incident()): (l: &Line, p: &Point) ~> bool;
//---------------------------------------------------------------------
alwaysinline
(_&_): (a: Point, b: Point) ~> Line = {a.y*b.w - a.w*b.y, a.w*b.x - a.x*b.w, a.x*b.y - a.y*b.x};
alwaysinline
(_&_): (a: Line, b: Line) ~> Point = {a.cy*b.cw - a.cw*b.cy, a.cw*b.cx - a.cx*b.cw, a.cx*b.cy - a.cy*b.cx};
//=====================================================================
//- Projective transformation (2D)
//=====================================================================
struct Transform
{
double[9];
};
//---------------------------------------------------------------------
(_.print_to_file()): (t: &Transform, f: *FILE) ~> void;
//---------------------------------------------------------------------
(_.norm()): (t: &Transform) ~> bool;
(_.is_regular()): (t: &Transform) ~> bool;
(_.is_affine()): (t: &Transform) ~> bool;
(_==_): (a: &Transform, b: &Transform) ~> bool;
alwaysinline
(_!=_): (a: &Transform, b: &Transform) ~> bool = !(a == b);
//---------------------------------------------------------------------
alwaysinline
(_.det()): (t: &Transform) ~> double = det_3(t[0]);
//---------------------------------------------------------------------
#define (_()): (t: Transform, v) = v.transform_by(t);
//---------------------------------------------------------------------
(_.transform_by()): (v: Vector, t: Transform) ~> Vector;
(_.transform_by()): (p: Point, t: Transform) ~> Point;
(_.transform_by()): (l: Line, t: Transform) ~> Line;
//---------------------------------------------------------------------
(_+_): (t: Transform, v: Vector) ~> Transform;
alwaysinline
(_-_): (t: Transform, v: Vector) ~> Transform = t + -v;
(_*_): (a: Transform, b: Transform) ~> Transform;
(_*__): (k: double, t: Transform) ~> Transform;
(~_): (t: Transform) ~> Transform;
(_/_): (a: Transform, b: Transform) ~> Transform;
//---------------------------------------------------------------------
alwaysinline
(_.scaled()): (t: Transform, k: double) ~> Transform = k * t;
alwaysinline
(_.shifted()): (t: Transform, v: Vector) ~> Transform = t + v;
(_.rotated()): (t: Transform, d: double) ~> Transform;
//---------------------------------------------------------------------
namespace Transform
{
map4: (i1: &Point, i2: &Point, i3: &Point, i4: &Point,
o1: &Point, o2: &Point, o3: &Point, o4: &Point
) ~> Transform;
map3: (i1: &Point, i2: &Point, i3: &Point,
o1: &Point, o2: &Point, o3: &Point
) ~> Transform;
map2: (i1: &Point, i2: &Point,
o1: &Point, o2: &Point
) ~> Transform;
map2_mirror: (i1: &Point, i2: &Point,
o1: &Point, o2: &Point
) ~> Transform;
//------------------------------------------------------
identity: Transform = {{ 1, 0, 0, 0, 1, 0, 0, 0, 1 }};
flip_x: Transform = {{-1, 0, 0, 0, 1, 0, 0, 0, 1 }};
flip_y: Transform = {{ 1, 0, 0, 0,-1, 0, 0, 0, 1 }};
}
//---------------------------------------------------------------------
} //- namespace Geometry
geometry_mod.void
{ v_import("libvoidc.void"); }
{ voidc_make_module("geometry"); }
//---------------------------------------------------------------------
{
v_import("geometry.void");
}
//---------------------------------------------------------------------
sin: (double) ~> double;
cos: (double) ~> double;
M_PI = 3.14159265358979323846264338327950288419716939937510582;
//---------------------------------------------------------------------
namespace Geometry
{
//---------------------------------------------------------------------
EPSILON = 1e-9;
is_equal: (x: double, y: double) ~> bool
{
if (x == y) return true;
size = fabs(x) + fabs(y);
if (size <= EPSILON) return true;
diff = fabs(x - y);
if (diff <= EPSILON) return true;
if (size > 1 && diff/size <= EPSILON) return true;
return false;
}
det_3: (v: &double[9]) ~> double
{
v00 = v[0]; v01 = v[1]; v02 = v[2];
v10 = v[3]; v11 = v[4]; v12 = v[5];
v20 = v[6]; v21 = v[7]; v22 = v[8];
return v00 * (v11*v22 - v12*v21)
- v10 * (v01*v22 - v02*v21)
+ v20 * (v01*v12 - v02*v11);
}
//---------------------------------------------------------------------
seq_equal: (a: *const double, b: *const double, n: int) ~> bool
{
ret: &bool := true;
for (i: &int := 0; i < n; ++i) if (!is_equal( a[i], b[i])) { ret := false; break; }
if (ret) return true;
for (i: &int := 0; i < n; ++i) if (!is_equal(-a[i], b[i])) { return false; }
return true;
}
//=====================================================================
//- Vector (2D)
//=====================================================================
(_.print_to_file()): (v: Vector, f: *FILE) ~> void
{
fprintf(f, "(%g, %g)", v.x, v.y);
}
(_==_): (a: Vector, b: Vector) ~> bool
{
return is_equal(a.x, b.x) && is_equal(a.y, b.y);
}
//=====================================================================
//- Projective point (2D)
//=====================================================================
(_.print_to_file()): (p: Point, f: *FILE) ~> void
{
fprintf(f, "(%g, %g, %g)", p.x, p.y, p.w);
}
//---------------------------------------------------------------------
(_.norm()): (p: &Point) ~> bool
{
pa: &double[3] := {p.x, p.y, p.w};
d: &double := 0;
for (i: &int := 0; i < 3; ++i)
{
if (!is_finite(pa[i])) return false;
if (di = fabs(pa[i]), d < di) d := di;
}
if (d == 0) return false;
if (d == 1) return true;
p.x /= d;
p.y /= d;
p.w /= d;
return true;
}
//---------------------------------------------------------------------
(_.is_affine()): (p: &Point) ~> bool
{
if (!p.norm()) return false;
return fabs(p.w) > EPSILON;
}
//---------------------------------------------------------------------
(_==_): (a: &Point, b: &Point) ~> bool
{
if (!(a.norm() && b.norm())) return false;
sa: &double[] := {a.x, a.y, a.w};
sb: &double[] := {b.x, b.y, b.w};
return seq_equal(sa, sb, 3);
}
//=====================================================================
//- Projective line (2D)
//=====================================================================
(_.print_to_file()): (l: Line, f: *FILE) ~> void
{
fprintf(f, "(%g, %g, %g)", l.cx, l.cy, l.cw);
}
//---------------------------------------------------------------------
(_.norm()): (l: &Line) ~> bool
{
la: &double[3] := {l.cx, l.cy, l.cw};
d: &double := 0;
for (i: &int := 0; i < 3; ++i)
{
if (!is_finite(la[i])) return false;
if (di = fabs(la[i]), d < di) d := di;
}
if (d == 0) return false;
if (d == 1) return true;
l.cx /= d;
l.cy /= d;
l.cw /= d;
return true;
}
//---------------------------------------------------------------------
(_.is_affine()): (l: &Line) ~> bool
{
if (!l.norm()) return false;
return fabs(l.cx) > EPSILON || fabs(l.cy) > EPSILON;
}
//---------------------------------------------------------------------
(_==_): (a: &Line, b: &Line) ~> bool
{
if (!(a.norm() && b.norm())) return false;
sa: &double[] := {a.cx, a.cy, a.cw};
sb: &double[] := {b.cx, b.cy, b.cw};
return seq_equal(sa, sb, 3);
}
//=====================================================================
(_.incident()): (l: &Line, p: &Point) ~> bool
{
l.norm();
p.norm();
return fabs(l.cx*p.x + l.cy*p.y + l.cw*p.w) < EPSILON;
}
//=====================================================================
//- Projective transformation (2D)
//=====================================================================
(_.print_to_file()): (t: &Transform, f: *FILE) ~> void
{
t = t[0];
fprintf(f, "(%g, %g, %g, %g, %g, %g, %g, %g, %g)", t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8]);
}
//---------------------------------------------------------------------
(_.norm()): (t: &Transform) ~> bool
{
t = t[0];
d: &double := 0;
for (i: &int := 0; i < 9; ++i)
{
if (!is_finite(t[i])) return false;
if (di = fabs(t[i]), d < di) d := di;
}
if (d == 0) return false;
if (d == 1) return true;
for (i: &int := 0; i < 9; ++i)
{
t[i] /= d;
}
return true;
}
//---------------------------------------------------------------------
(_.is_regular()): (t: &Transform) ~> bool
{
if (!t.norm()) return false;
return fabs(t.det()) > EPSILON;
}
//---------------------------------------------------------------------
(_.is_affine()): (t: &Transform) ~> bool
{
if (!t.norm()) return false;
t = t[0];
return fabs(t[6]) <= EPSILON &&
fabs(t[7]) <= EPSILON &&
fabs(t[8]) > EPSILON;
}
//---------------------------------------------------------------------
(_==_): (a: &Transform, b: &Transform) ~> bool
{
if (!(a.norm() && b.norm())) return false;
return seq_equal(a[0], b[0], 9);
}
//---------------------------------------------------------------------
(_.transform_by()): (v: Vector, t: Transform) ~> Vector
{
t = t[0];
x = t[0]*v.x + t[1]*v.y + t[2];
y = t[3]*v.x + t[4]*v.y + t[5];
w = t[6]*v.x + t[7]*v.y + t[8];
return { x/w, y/w };
}
(_.transform_by()): (p: Point, t: Transform) ~> Point
{
t = t[0];
x = t[0]*p.x + t[1]*p.y + t[2]*p.w;
y = t[3]*p.x + t[4]*p.y + t[5]*p.w;
w = t[6]*p.x + t[7]*p.y + t[8]*p.w;
return { x, y, w };
}
(_.transform_by()): (l: Line, t: Transform) ~> Line
{
t = t[0];
cx = det_3({ l.cx, t[3], t[6],
l.cy, t[4], t[7],
l.cw, t[5], t[8] });
cy = det_3({ t[0], l.cx, t[6],
t[1], l.cy, t[7],
t[2], l.cw, t[8] });
cw = det_3({ t[0], t[3], l.cx,
t[1], t[4], l.cy,
t[2], t[5], l.cw });
return { cx, cy, cw };
}
//---------------------------------------------------------------------
(_+_): (t: Transform, v: Vector) ~> Transform
{
t = t[0];
xx = t[0] + v.x*t[6];
xy = t[1] + v.x*t[7];
xw = t[2] + v.x*t[8];
yx = t[3] + v.y*t[6];
yy = t[4] + v.y*t[7];
yw = t[5] + v.y*t[8];
wx = t[6];
wy = t[7];
ww = t[8];
return {{ xx, xy, xw,
yx, yy, yw,
wx, wy, ww }};
}
//---------------------------------------------------------------------
(_*_): (a: Transform, b: Transform) ~> Transform
{
a = a[0];
b = b[0];
xx = a[0]*b[0] + a[1]*b[3] + a[2]*b[6];
xy = a[0]*b[1] + a[1]*b[4] + a[2]*b[7];
xw = a[0]*b[2] + a[1]*b[5] + a[2]*b[8];
yx = a[3]*b[0] + a[4]*b[3] + a[5]*b[6];
yy = a[3]*b[1] + a[4]*b[4] + a[5]*b[7];
yw = a[3]*b[2] + a[4]*b[5] + a[5]*b[8];
wx = a[6]*b[0] + a[7]*b[3] + a[8]*b[6];
wy = a[6]*b[1] + a[7]*b[4] + a[8]*b[7];
ww = a[6]*b[2] + a[7]*b[5] + a[8]*b[8];
return {{ xx, xy, xw,
yx, yy, yw,
wx, wy, ww }};
}
(_*__): (k: double, t: Transform) ~> Transform
{
t = t[0];
xx = k*t[0];
xy = k*t[1];
xw = k*t[2];
yx = k*t[3];
yy = k*t[4];
yw = k*t[5];
wx = t[6];
wy = t[7];
ww = t[8];
return {{ xx, xy, xw,
yx, yy, yw,
wx, wy, ww }};
}
//---------------------------------------------------------------------
(~_): (t: Transform) ~> Transform
{
t = t[0];
xx = t[4]*t[8] - t[5]*t[7];
xy = t[2]*t[7] - t[1]*t[8];
xw = t[1]*t[5] - t[2]*t[4];
yx = t[5]*t[6] - t[3]*t[8];
yy = t[0]*t[8] - t[2]*t[6];
yw = t[2]*t[3] - t[0]*t[5];
wx = t[3]*t[7] - t[4]*t[6];
wy = t[1]*t[6] - t[0]*t[7];
ww = t[0]*t[4] - t[1]*t[3];
r: &Transform := {{ xx,xy,xw, yx,yy,yw, wx,wy,ww }};
if (r.det() < 0)
{
r = r[0];
for (i: &int := 0; i < 9; ++i) r[i] := -r[i];
}
return r;
}
//---------------------------------------------------------------------
(_/_): (a: Transform, b: Transform) ~> Transform
{
return a * (~b);
}
//---------------------------------------------------------------------
(_.rotated()): (t: Transform, d: double) ~> Transform
{
a = d * (M_PI/180);
sa = sin(a);
ca = cos(a);
r: Transform = {{ ca, -sa, 0,
sa, ca, 0,
0, 0, 1 }};
return r * t;
}
//---------------------------------------------------------------------
private
map4_util: (o1: &Point, o2: &Point, o3: &Point, o4: &Point) ~> Transform
{
o1.norm();
o2.norm();
o3.norm();
o4.norm();
a1 = det_3({ o4.x, o2.x, o3.x,
o4.y, o2.y, o3.y,
o4.w, o2.w, o3.w });
a2 = det_3({ o1.x, o4.x, o3.x,
o1.y, o4.y, o3.y,
o1.w, o4.w, o3.w });
a3 = det_3({ o1.x, o2.x, o4.x,
o1.y, o2.y, o4.y,
o1.w, o2.w, o4.w });
return {{ o1.x*a1, o2.x*a2, o3.x*a3,
o1.y*a1, o2.y*a2, o3.y*a3,
o1.w*a1, o2.w*a2, o3.w*a3 }};
}
//---------------------------------------------------------------------
Transform.map4: (i1: &Point, i2: &Point, i3: &Point, i4: &Point,
o1: &Point, o2: &Point, o3: &Point, o4: &Point
) ~> Transform
{
t1 = map4_util(i1, i2, i3, i4);
t2 = map4_util(o1, o2, o3, o4);
return t2 / t1;
}
Transform.map3: (i1: &Point, i2: &Point, i3: &Point,
o1: &Point, o2: &Point, o3: &Point
) ~> Transform
{
i4 = i3 + (i2 - i1);
o4 = o3 + (o2 - o1);
return Transform.map4(i1, i2, i3, i4, o1, o2, o3, o4);
}
Transform.map2: (i1: &Point, i2: &Point,
o1: &Point, o2: &Point
) ~> Transform
{
v = i2 - i1; v: Vector = { -v.y, v.x };
i3 = i1 + v;
v = o2 - o1; v: Vector = { -v.y, v.x };
o3 = o1 + v;
return Transform.map3(i1, i2, i3, o1, o2, o3);
}
Transform.map2_mirror: (i1: &Point, i2: &Point,
o1: &Point, o2: &Point
) ~> Transform
{
v = i2 - i1; v: Vector = { -v.y, v.x };
i3 = i1 + v;
v = o2 - o1; v: Vector = { v.y, -v.x };
o3 = o1 + v;
return Transform.map3(i1, i2, i3, o1, o2, o3);
}
//---------------------------------------------------------------------
} //- namespace Geometry
//---------------------------------------------------------------------
{ voidc_emit_module("geometry_mod.o"); }
//---------------------------------------------------------------------
...