diff --git a/lib/c3/0.1/complex.facts b/lib/c3/0.1/complex.facts
index 613354c..386ac1c 100644
--- a/lib/c3/0.1/complex.facts
+++ b/lib/c3/0.1/complex.facts
@@ -2,4 +2,4 @@
version: 1}
replace {Complex, :is_a, :module}
replace {Complex, :symbol, Complex.cast}
-replace {Complex.cast, :cfn, cfn Complex "complex_new_cast" (Tag)}
+replace {Complex.cast, :cfn, cfn Complex "pcomplex_init_cast" (Result, Tag)}
diff --git a/libc3/complex.h b/libc3/complex.h
index 4d2aeff..425a8a4 100644
--- a/libc3/complex.h
+++ b/libc3/complex.h
@@ -13,8 +13,6 @@
#ifndef LIBC3_COMPLEX_H
#define LIBC3_COMPLEX_H
-#include <stdarg.h>
-#include <stdio.h>
#include "types.h"
/* Stack-allocation compatible functions, call complex_clean
@@ -53,10 +51,11 @@ s_complex * complex_mul (const s_complex *a, const s_complex *b,
s_complex * complex_sub (const s_complex *a, const s_complex *b,
s_complex *dest);
-/* Constructors, call complex_delete after use. */
+/* Heap-allocation functions, call complex_delete after use. */
void complex_delete (s_complex *c);
s_complex * complex_new (void);
s_complex * complex_new_add (const s_complex *a, const s_complex *b);
+s_complex * complex_new_cast (const s_tag *src);
s_complex * complex_new_div (const s_complex *a, const s_complex *b);
s_complex * complex_new_mul (const s_complex *a, const s_complex *b);
s_complex * complex_new_sub (const s_complex *a, const s_complex *b);
diff --git a/libc3/pcomplex.c b/libc3/pcomplex.c
new file mode 100644
index 0000000..f677199
--- /dev/null
+++ b/libc3/pcomplex.c
@@ -0,0 +1,57 @@
+/* c3
+ * Copyright 2022-2024 kmx.io <contact@kmx.io>
+ *
+ * Permission is hereby granted to use this software granted the above
+ * copyright notice and this permission paragraph are included in all
+ * copies and substantial portions of this software.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
+ * PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
+ * AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+#include "assert.h"
+#include "complex.h"
+#include "pcomplex.h"
+
+void pcomplex_clean (s_complex **p)
+{
+ assert(p);
+ complex_delete(*p);
+}
+
+s_complex ** pcomplex_init (s_complex **p)
+{
+ s_complex *tmp = NULL;
+ assert(p);
+ tmp = complex_new();
+ if (! tmp)
+ return NULL;
+ *p = tmp;
+ return p;
+}
+
+s_complex ** pcomplex_init_cast (s_complex **p, const s_tag *src)
+{
+ s_complex *tmp = NULL;
+ assert(p);
+ assert(src);
+ tmp = complex_new_cast(src);
+ if (! tmp)
+ return NULL;
+ *p = tmp;
+ return p;
+}
+
+s_complex ** pcomplex_init_copy (s_complex **p,
+ const s_complex * const *src)
+{
+ s_complex *tmp = NULL;
+ assert(p);
+ assert(src);
+ tmp = complex_new_copy(*src);
+ if (! tmp)
+ return NULL;
+ *p = tmp;
+ return p;
+}
diff --git a/libc3/pcomplex.h b/libc3/pcomplex.h
new file mode 100644
index 0000000..9797078
--- /dev/null
+++ b/libc3/pcomplex.h
@@ -0,0 +1,26 @@
+/* c3
+ * Copyright 2022-2024 kmx.io <contact@kmx.io>
+ *
+ * Permission is hereby granted to use this software granted the above
+ * copyright notice and this permission paragraph are included in all
+ * copies and substantial portions of this software.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
+ * PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
+ * AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+#ifndef LIBC3_PCOMPLEX_H
+#define LIBC3_PCOMPLEX_H
+
+#include "types.h"
+
+/* Stack-allocation compatible functions, call pcomplex_clean
+ after use. */
+void pcomplex_clean (s_complex **p);
+s_complex ** pcomplex_init (s_complex **p);
+s_complex ** pcomplex_init_cast (s_complex **p, const s_tag *src);
+s_complex ** pcomplex_init_copy (s_complex **p,
+ const s_complex * const *src);
+
+#endif /* LIBC3_COMPLEX_H */
diff --git a/libc3/tag.c b/libc3/tag.c
index 2dbd76c..35aa5d5 100644
--- a/libc3/tag.c
+++ b/libc3/tag.c
@@ -21,7 +21,6 @@
#include "call.h"
#include "cfn.h"
#include "compare.h"
-#include "complex.h"
#include "env.h"
#include "fn.h"
#include "frame.h"
@@ -30,6 +29,7 @@
#include "integer.h"
#include "list.h"
#include "map.h"
+#include "pcomplex.h"
#include "ptr.h"
#include "ptr_free.h"
#include "quote.h"
@@ -140,24 +140,24 @@ void tag_clean (s_tag *tag)
{
assert(tag);
switch (tag->type) {
- case TAG_ARRAY: array_clean(&tag->data.array); break;
- case TAG_BLOCK: block_clean(&tag->data.block); break;
- case TAG_CALL: call_clean(&tag->data.call); break;
- case TAG_CFN: cfn_clean(&tag->data.cfn); break;
- case TAG_COMPLEX: complex_delete(tag->data.complex); break;
- case TAG_FN: fn_clean(&tag->data.fn); break;
- case TAG_INTEGER: integer_clean(&tag->data.integer); break;
- case TAG_LIST: list_delete_all(tag->data.list); break;
- case TAG_MAP: map_clean(&tag->data.map); break;
- case TAG_PTR_FREE: ptr_free_clean(&tag->data.ptr); break;
- case TAG_QUOTE: quote_clean(&tag->data.quote); break;
- case TAG_RATIO: ratio_clean(&tag->data.ratio); break;
- case TAG_STR: str_clean(&tag->data.str); break;
- case TAG_STRUCT: struct_clean(&tag->data.struct_); break;
+ case TAG_ARRAY: array_clean(&tag->data.array); break;
+ case TAG_BLOCK: block_clean(&tag->data.block); break;
+ case TAG_CALL: call_clean(&tag->data.call); break;
+ case TAG_CFN: cfn_clean(&tag->data.cfn); break;
+ case TAG_COMPLEX: pcomplex_clean(&tag->data.complex); break;
+ case TAG_FN: fn_clean(&tag->data.fn); break;
+ case TAG_INTEGER: integer_clean(&tag->data.integer); break;
+ case TAG_LIST: list_delete_all(tag->data.list); break;
+ case TAG_MAP: map_clean(&tag->data.map); break;
+ case TAG_PTR_FREE: ptr_free_clean(&tag->data.ptr); break;
+ case TAG_QUOTE: quote_clean(&tag->data.quote); break;
+ case TAG_RATIO: ratio_clean(&tag->data.ratio); break;
+ case TAG_STR: str_clean(&tag->data.str); break;
+ case TAG_STRUCT: struct_clean(&tag->data.struct_); break;
case TAG_STRUCT_TYPE: struct_type_clean(&tag->data.struct_type);
- break;
- case TAG_TUPLE: tuple_clean(&tag->data.tuple); break;
- case TAG_UNQUOTE: unquote_clean(&tag->data.unquote); break;
+ break;
+ case TAG_TUPLE: tuple_clean(&tag->data.tuple); break;
+ case TAG_UNQUOTE: unquote_clean(&tag->data.unquote); break;
case TAG_BOOL:
case TAG_CHARACTER:
case TAG_F32:
@@ -339,7 +339,8 @@ s_tag * tag_init_copy (s_tag *tag, const s_tag *src)
cfn_init_copy(&tag->data.cfn, &src->data.cfn);
break;
case TAG_COMPLEX:
- tag->data.complex = complex_new_copy(src->data.complex);
+ pcomplex_init_copy(&tag->data.complex,
+ (const s_complex * const *) &src->data.complex);
break;
case TAG_FN:
fn_init_copy(&tag->data.fn, &src->data.fn);
@@ -348,7 +349,8 @@ s_tag * tag_init_copy (s_tag *tag, const s_tag *src)
integer_init_copy(&tag->data.integer, &src->data.integer);
break;
case TAG_LIST:
- list_init_copy(&tag->data.list, (const s_list **) &src->data.list);
+ list_init_copy(&tag->data.list,
+ (const s_list * const *) &src->data.list);
break;
case TAG_MAP:
map_init_copy(&tag->data.map, &src->data.map);
@@ -700,7 +702,7 @@ bool tag_to_const_pointer (const s_tag *tag, const s_sym *type,
case TAG_CALL: *dest = &tag->data.call; return true;
case TAG_CFN: *dest = &tag->data.cfn; return true;
case TAG_CHARACTER: *dest = &tag->data.character; return true;
- case TAG_COMPLEX: *dest = tag->data.complex; return true;
+ case TAG_COMPLEX: *dest = &tag->data.complex; return true;
case TAG_F32: *dest = &tag->data.f32; return true;
case TAG_F64: *dest = &tag->data.f64; return true;
case TAG_F128: *dest = &tag->data.f128; return true;
@@ -791,7 +793,7 @@ bool tag_to_ffi_pointer (s_tag *tag, const s_sym *type, void **dest)
goto invalid_cast;
case TAG_COMPLEX:
if (type == &g_sym_Complex) {
- *dest = tag->data.complex;
+ *dest = &tag->data.complex;
return true;
}
goto invalid_cast;
@@ -838,9 +840,10 @@ bool tag_to_ffi_pointer (s_tag *tag, const s_sym *type, void **dest)
}
goto invalid_cast;
case TAG_RATIO:
- if (type == sym_1("Ratio") ||
- type == sym_1("ratio"))
+ if (type == &g_sym_Ratio) {
+ *dest = &tag->data.ratio;
return true;
+ }
goto invalid_cast;
case TAG_SW:
if (type == &g_sym_Sw) {
@@ -1031,7 +1034,7 @@ bool tag_to_pointer (s_tag *tag, const s_sym *type, void **dest)
case TAG_CALL: *dest = &tag->data.call; return true;
case TAG_CFN: *dest = &tag->data.cfn; return true;
case TAG_CHARACTER: *dest = &tag->data.character; return true;
- case TAG_COMPLEX: *dest = tag->data.complex; return true;
+ case TAG_COMPLEX: *dest = &tag->data.complex; return true;
case TAG_F32: *dest = &tag->data.f32; return true;
case TAG_F64: *dest = &tag->data.f64; return true;
case TAG_F128: *dest = &tag->data.f128; return true;