diff --git a/libc3/complex.c b/libc3/complex.c
index efb1170..2126fda 100644
--- a/libc3/complex.c
+++ b/libc3/complex.c
@@ -79,7 +79,6 @@ s_complex * complex_mul (const s_complex *a, const s_complex *b,
s_complex * complex_new (void)
{
s_complex *c;
- assert(src);
c = calloc(1, sizeof(s_complex));
if (! c) {
err_puts("complex_new_copy: failed to allocate memory");
diff --git a/libc3/integer.c b/libc3/integer.c
index a5c0904..0f6254c 100644
--- a/libc3/integer.c
+++ b/libc3/integer.c
@@ -372,10 +372,16 @@ bool integer_is_negative (const s_integer *i)
return i->mp_int.sign == MP_NEG;
}
+bool integer_is_positive (const s_integer *i)
+{
+ assert(i);
+ return i->mp_int.used && i->mp_int.sign != MP_NEG;
+}
+
bool integer_is_zero (const s_integer *i)
{
assert(i);
- return (i->mp_int.used == 0);
+ return ! i->mp_int.used;
}
s_integer * integer_lcm (const s_integer *a, const s_integer *b,
@@ -606,6 +612,12 @@ s_tag * integer_sqrt (const s_integer *a, s_tag *dest)
sw r;
assert(a);
assert(dest);
+ if (integer_is_negative(a)) {
+ // FIXME
+ err_puts("integer_sqrt: not implemented");
+ assert(! "integer_sqrt: not implemented");
+ return NULL;
+ }
dest->type = TAG_INTEGER;
integer_init(&dest->data.integer);
if ((r = mp_sqrt(&a->mp_int, &dest->data.integer.mp_int)) != MP_OKAY) {
@@ -617,6 +629,26 @@ s_tag * integer_sqrt (const s_integer *a, s_tag *dest)
return dest;
}
+s_integer * integer_sqrt_positive (const s_integer *a, s_integer *dest)
+{
+ sw r;
+ assert(a);
+ assert(dest);
+ if (integer_is_negative(a)) {
+ err_puts("integer_sqrt_positive: negative argument");
+ assert(! "integer_sqrt_positive: negative argument");
+ return NULL;
+ }
+ integer_init(dest);
+ if ((r = mp_sqrt(&a->mp_int, &dest->mp_int)) != MP_OKAY) {
+ err_write_1("integer_sqrt_positive: ");
+ err_puts(mp_error_to_string(r));
+ assert(! "integer_sqrt_positive: mp_sqrt");
+ return NULL;
+ }
+ return dest;
+}
+
s_integer * integer_sub (const s_integer *a, const s_integer *b,
s_integer *dest)
{
diff --git a/libc3/integer.h b/libc3/integer.h
index 2ed5228..034e3ce 100644
--- a/libc3/integer.h
+++ b/libc3/integer.h
@@ -19,8 +19,6 @@
#ifndef LIBC3_INTEGER_H
#define LIBC3_INTEGER_H
-#include <stdarg.h>
-#include <stdio.h>
#include "types.h"
#define MP_IS_ZERO(a) ((a)->used == 0)
@@ -86,6 +84,7 @@ s_integer * integer_neg (const s_integer *a, s_integer *dest);
s_integer * integer_pow (const s_integer *a, const s_integer *b,
s_integer *dest);
s_tag * integer_sqrt (const s_integer *a, s_tag *dest);
+s_integer * integer_sqrt_positive (const s_integer *a, s_integer *dest);
s_integer * integer_sub (const s_integer *a, const s_integer *b,
s_integer *dest);
@@ -97,6 +96,7 @@ s_integer * integer_new_copy (const s_integer *a);
uw integer_bits (const s_integer *i);
uw integer_bytes (const s_integer *i);
bool integer_is_negative (const s_integer *i);
+bool integer_is_positive (const s_integer *i);
bool integer_is_zero (const s_integer *i);
f32 integer_to_f32 (const s_integer *i);
f64 integer_to_f64 (const s_integer *i);
diff --git a/libc3/ratio.c b/libc3/ratio.c
index 6130e48..7c05e52 100644
--- a/libc3/ratio.c
+++ b/libc3/ratio.c
@@ -19,6 +19,27 @@
#include "buf_inspect.h"
#include "compare.h"
#include "integer.h"
+#include "ratio.h"
+
+s_ratio * ratio_add (const s_ratio *a, const s_ratio *b,
+ s_ratio *dest)
+{
+ s_integer i;
+ s_integer j;
+ assert(a);
+ assert(b);
+ assert(dest);
+ assert(integer_is_positive(&a->denominator));
+ assert(integer_is_positive(&b->denominator));
+ integer_mul(&a->numerator, &b->denominator, &i);
+ integer_mul(&b->numerator, &a->denominator, &j);
+ integer_add(&i, &j, &dest->numerator);
+ integer_mul(&a->denominator, &b->denominator,
+ &dest->denominator);
+ integer_clean(&i);
+ integer_clean(&j);
+ return dest;
+}
void ratio_clean (s_ratio *r)
{
@@ -27,6 +48,20 @@ void ratio_clean (s_ratio *r)
integer_clean(&r->denominator);
}
+s_ratio * ratio_div (const s_ratio *a, const s_ratio *b,
+ s_ratio *dest)
+{
+ assert(a);
+ assert(b);
+ assert(dest);
+ assert(! integer_is_zero(&b->numerator));
+ assert(integer_is_positive(&a->denominator));
+ assert(integer_is_positive(&b->denominator));
+ integer_mul(&a->numerator, &b->denominator, &dest->numerator);
+ integer_mul(&a->denominator, &b->numerator, &dest->denominator);
+ return dest;
+}
+
s_ratio * ratio_init (s_ratio *dest)
{
sw r;
@@ -38,41 +73,18 @@ s_ratio * ratio_init (s_ratio *dest)
return dest;
}
-s_ratio * ratio_init_integer (s_ratio *r, s_integer *numerator, s_integer *denominator)
-{
- assert(numerator);
- assert(denominator);
- assert(r);
-
- integer_init_copy(&r->numerator, numerator);
- integer_init_copy(&r->denominator, denominator);
-
- return r;
-}
-
s_ratio * ratio_init_1 (s_ratio *r, const char *p)
{
- assert(r);
- assert(p);
-
s_integer numerator;
s_integer denominator;
+ assert(r);
+ assert(p);
integer_init_1(&numerator, p);
integer_init_u64(&denominator, 1);
ratio_init_integer(r, &numerator, &denominator);
return r;
}
-s_ratio * ratio_init_zero (s_ratio *r)
-{
- assert(r);
-
- integer_init_zero(&r->numerator);
- integer_init(&r->denominator);
- integer_set_u64(&r->denominator, 1);
- return r;
-}
-
s_ratio * ratio_init_copy (s_ratio *dest, const s_ratio *src)
{
assert(src);
@@ -84,11 +96,33 @@ s_ratio * ratio_init_copy (s_ratio *dest, const s_ratio *src)
return dest;
}
+s_ratio * ratio_init_integer (s_ratio *r, s_integer *numerator, s_integer *denominator)
+{
+ assert(numerator);
+ assert(denominator);
+ assert(r);
+ integer_init_copy(&r->numerator, numerator);
+ integer_init_copy(&r->denominator, denominator);
+ return r;
+}
+
+s_ratio * ratio_init_zero (s_ratio *r)
+{
+ assert(r);
+ integer_init_zero(&r->numerator);
+ integer_init(&r->denominator);
+ integer_set_u64(&r->denominator, 1);
+ return r;
+}
+
s_str * ratio_inspect (const s_ratio *src, s_str *dest)
{
s_buf buf;
sw r;
sw size;
+ assert(src);
+ assert(dest);
+ assert(integer_is_positive(&src->denominator));
size = buf_inspect_ratio_size(src);
if (size <= 0)
return NULL;
@@ -108,22 +142,31 @@ s_str * ratio_inspect (const s_ratio *src, s_str *dest)
return buf_to_str(&buf, dest);
}
-s_ratio * ratio_add (const s_ratio *a, const s_ratio *b,
+bool ratio_is_negative (const s_ratio *r)
+{
+ assert(r);
+ assert(integer_is_positive(&r->denominator));
+ return integer_is_negative(&r->numerator);
+}
+
+bool ratio_is_zero (const s_ratio *r)
+{
+ assert(r);
+ assert(integer_is_positive(&r->denominator));
+ return integer_is_zero(&r->numerator);
+}
+
+s_ratio * ratio_mul (const s_ratio *a, const s_ratio *b,
s_ratio *dest)
{
assert(a);
assert(b);
assert(dest);
- assert(!integer_is_zero(&a->denominator));
- assert(!integer_is_zero(&b->denominator));
-
- s_integer temp1, temp2;
- integer_mul(&a->numerator, &b->denominator, &temp1);
- integer_mul(&b->numerator, &a->denominator, &temp2);
- integer_add(&temp1, &temp2, &dest->numerator);
+ assert(integer_is_positive(&a->denominator));
+ assert(integer_is_positive(&b->denominator));
+ integer_mul(&a->numerator, &b->numerator, &dest->numerator);
integer_mul(&a->denominator, &b->denominator,
&dest->denominator);
-
return dest;
}
@@ -132,7 +175,7 @@ s_ratio * ratio_neg (const s_ratio *r, s_ratio *dest)
s_ratio tmp = {0};
assert(r);
assert(dest);
- assert(! integer_is_zero(&r->denominator));
+ assert(integer_is_positive(&r->denominator));
if (! integer_neg(&r->numerator, &tmp.numerator))
return NULL;
if (! integer_init_copy(&tmp.denominator, &r->denominator)) {
@@ -143,26 +186,30 @@ s_ratio * ratio_neg (const s_ratio *r, s_ratio *dest)
return dest;
}
-s_ratio * ratio_sub (const s_ratio *a, const s_ratio *b,
- s_ratio *dest)
+s_tag * ratio_sqrt (const s_ratio *r, s_tag *dest)
{
- assert(a);
- assert(b);
+ s_ratio tmp = {0};
+ assert(r);
assert(dest);
- assert(!integer_is_zero(&a->denominator));
- assert(!integer_is_zero(&b->denominator));
-
- s_integer temp1, temp2;
- integer_mul(&a->numerator, &b->denominator, &temp1);
- integer_mul(&b->numerator, &a->denominator, &temp2);
- integer_sub(&temp1, &temp2, &dest->numerator);
- integer_mul(&a->denominator, &b->denominator,
- &dest->denominator);
-
+ assert(integer_is_positive(&r->denominator));
+ if (ratio_is_negative(r)) {
+ // FIXME
+ err_puts("ratio_sqrt: not implemented");
+ assert(! "ratio_sqrt: not implemented");
+ return NULL;
+ }
+ if (! integer_sqrt_positive(&r->numerator, &tmp.numerator))
+ return NULL;
+ if (! integer_sqrt_positive(&r->denominator, &tmp.denominator)) {
+ integer_clean(&tmp.numerator);
+ return NULL;
+ }
+ dest->type = TAG_RATIO;
+ dest->data.ratio = tmp;
return dest;
}
-s_ratio * ratio_mul (const s_ratio *a, const s_ratio *b,
+s_ratio * ratio_sub (const s_ratio *a, const s_ratio *b,
s_ratio *dest)
{
assert(a);
@@ -171,35 +218,16 @@ s_ratio * ratio_mul (const s_ratio *a, const s_ratio *b,
assert(!integer_is_zero(&a->denominator));
assert(!integer_is_zero(&b->denominator));
- integer_mul(&a->numerator, &b->numerator, &dest->numerator);
+ s_integer temp1, temp2;
+ integer_mul(&a->numerator, &b->denominator, &temp1);
+ integer_mul(&b->numerator, &a->denominator, &temp2);
+ integer_sub(&temp1, &temp2, &dest->numerator);
integer_mul(&a->denominator, &b->denominator,
&dest->denominator);
return dest;
}
-s_ratio * ratio_div (const s_ratio *a, const s_ratio *b,
- s_ratio *dest)
-{
- assert(a);
- assert(b);
- assert(dest);
- assert(!integer_is_zero(&b->numerator));
- assert(!integer_is_zero(&a->denominator));
- assert(!integer_is_zero(&b->denominator));
-
- integer_mul(&a->numerator, &b->denominator, &dest->numerator);
- integer_mul(&a->denominator, &b->numerator, &dest->denominator);
-
- return dest;
-}
-
-bool ratio_is_zero (const s_ratio *r)
-{
- assert(r);
- return integer_is_zero(&r->numerator);
-}
-
f32 ratio_to_f32(const s_ratio *r)
{
assert(r);
@@ -222,24 +250,24 @@ f64 ratio_to_f64(const s_ratio *r)
return numerator / denominator;
}
-sw ratio_to_sw (const s_ratio *r)
+s8 ratio_to_s8 (const s_ratio *r)
{
assert(r);
assert(!integer_is_zero(&r->denominator));
- sw numerator = integer_to_sw(&r->numerator);
- sw denominator = integer_to_sw(&r->denominator);
+ s8 numerator = integer_to_s8(&r->numerator);
+ s8 denominator = integer_to_s8(&r->denominator);
return numerator / denominator;
}
-s64 ratio_to_s64 (const s_ratio *r)
+s16 ratio_to_s16 (const s_ratio *r)
{
assert(r);
assert(!integer_is_zero(&r->denominator));
- s64 numerator = integer_to_s64(&r->numerator);
- s64 denominator = integer_to_s64(&r->denominator);
+ s16 numerator = integer_to_s16(&r->numerator);
+ s16 denominator = integer_to_s16(&r->denominator);
return numerator / denominator;
}
@@ -255,46 +283,46 @@ s32 ratio_to_s32 (const s_ratio *r)
return numerator / denominator;
}
-s16 ratio_to_s16 (const s_ratio *r)
+s64 ratio_to_s64 (const s_ratio *r)
{
assert(r);
assert(!integer_is_zero(&r->denominator));
- s16 numerator = integer_to_s16(&r->numerator);
- s16 denominator = integer_to_s16(&r->denominator);
+ s64 numerator = integer_to_s64(&r->numerator);
+ s64 denominator = integer_to_s64(&r->denominator);
return numerator / denominator;
}
-s8 ratio_to_s8 (const s_ratio *r)
+sw ratio_to_sw (const s_ratio *r)
{
assert(r);
assert(!integer_is_zero(&r->denominator));
- s8 numerator = integer_to_s8(&r->numerator);
- s8 denominator = integer_to_s8(&r->denominator);
+ sw numerator = integer_to_sw(&r->numerator);
+ sw denominator = integer_to_sw(&r->denominator);
return numerator / denominator;
}
-uw ratio_to_uw (const s_ratio *r)
+u8 ratio_to_u8 (const s_ratio *r)
{
assert(r);
assert(!integer_is_zero(&r->denominator));
- uw numerator = integer_to_uw(&r->numerator);
- uw denominator = integer_to_uw(&r->denominator);
+ u8 numerator = integer_to_u8(&r->numerator);
+ u8 denominator = integer_to_u8(&r->denominator);
return numerator / denominator;
}
-u64 ratio_to_u64 (const s_ratio *r)
+u16 ratio_to_u16 (const s_ratio *r)
{
assert(r);
assert(!integer_is_zero(&r->denominator));
- u64 numerator = integer_to_u64(&r->numerator);
- u64 denominator = integer_to_u64(&r->denominator);
+ u16 numerator = integer_to_u16(&r->numerator);
+ u16 denominator = integer_to_u16(&r->denominator);
return numerator / denominator;
}
@@ -310,24 +338,24 @@ u32 ratio_to_u32 (const s_ratio *r)
return numerator / denominator;
}
-u16 ratio_to_u16 (const s_ratio *r)
+u64 ratio_to_u64 (const s_ratio *r)
{
assert(r);
assert(!integer_is_zero(&r->denominator));
- u16 numerator = integer_to_u16(&r->numerator);
- u16 denominator = integer_to_u16(&r->denominator);
+ u64 numerator = integer_to_u64(&r->numerator);
+ u64 denominator = integer_to_u64(&r->denominator);
return numerator / denominator;
}
-u8 ratio_to_u8 (const s_ratio *r)
+uw ratio_to_uw (const s_ratio *r)
{
assert(r);
assert(!integer_is_zero(&r->denominator));
- u8 numerator = integer_to_u8(&r->numerator);
- u8 denominator = integer_to_u8(&r->denominator);
+ uw numerator = integer_to_uw(&r->numerator);
+ uw denominator = integer_to_uw(&r->denominator);
return numerator / denominator;
}
diff --git a/libc3/ratio.h b/libc3/ratio.h
index e75f90b..1f4aff2 100644
--- a/libc3/ratio.h
+++ b/libc3/ratio.h
@@ -34,6 +34,7 @@ s_ratio * ratio_new_copy (const s_ratio *a);
/* Observers. */
s_str * ratio_inspect (const s_ratio *src, s_str *dest);
+bool ratio_is_negative (const s_ratio *r);
bool ratio_is_zero (const s_ratio *r);
f32 ratio_to_f32 (const s_ratio *r);
f64 ratio_to_f64 (const s_ratio *r);
diff --git a/libc3/s.c.in b/libc3/s.c.in
index 7c81583..acc9f7e 100644
--- a/libc3/s.c.in
+++ b/libc3/s.c.in
@@ -12,6 +12,7 @@
*/
/* Gen from s.h.in BITS=_BITS$ bits=_bits$ */
#include "assert.h"
+#include <math.h>
#include <stdlib.h>
#include "integer.h"
#include "tag.h"
@@ -97,6 +98,11 @@ s_bits$ * s_bits$_random (s_bits$ *s)
s_tag * s_bits$_sqrt (const s_bits$ x, s_tag *dest)
{
assert(dest);
+ if (x < 0) {
+ // FIXME
+ //dest->type = TAG_COMPLEX;
+ return NULL;
+ }
dest->type = TAG_S_BITS$;
dest->data.s_bits$ = (s_bits$) sqrtl((long double) x);
return dest;
diff --git a/libc3/s16.c b/libc3/s16.c
index b26af01..ac15af4 100644
--- a/libc3/s16.c
+++ b/libc3/s16.c
@@ -12,6 +12,7 @@
*/
/* Gen from s.h.in BITS=16 bits=16 */
#include "assert.h"
+#include <math.h>
#include <stdlib.h>
#include "integer.h"
#include "tag.h"
@@ -93,3 +94,16 @@ s16 * s16_random (s16 *s)
arc4random_buf(s, sizeof(s16));
return s;
}
+
+s_tag * s16_sqrt (const s16 x, s_tag *dest)
+{
+ assert(dest);
+ if (x < 0) {
+ // FIXME
+ //dest->type = TAG_COMPLEX;
+ return NULL;
+ }
+ dest->type = TAG_S16;
+ dest->data.s16 = (s16) sqrtl((long double) x);
+ return dest;
+}
diff --git a/libc3/s32.c b/libc3/s32.c
index 37e8bc0..18f87a8 100644
--- a/libc3/s32.c
+++ b/libc3/s32.c
@@ -12,6 +12,7 @@
*/
/* Gen from s.h.in BITS=32 bits=32 */
#include "assert.h"
+#include <math.h>
#include <stdlib.h>
#include "integer.h"
#include "tag.h"
@@ -93,3 +94,16 @@ s32 * s32_random (s32 *s)
arc4random_buf(s, sizeof(s32));
return s;
}
+
+s_tag * s32_sqrt (const s32 x, s_tag *dest)
+{
+ assert(dest);
+ if (x < 0) {
+ // FIXME
+ //dest->type = TAG_COMPLEX;
+ return NULL;
+ }
+ dest->type = TAG_S32;
+ dest->data.s32 = (s32) sqrtl((long double) x);
+ return dest;
+}
diff --git a/libc3/s64.c b/libc3/s64.c
index 9309c1d..4a346d6 100644
--- a/libc3/s64.c
+++ b/libc3/s64.c
@@ -12,6 +12,7 @@
*/
/* Gen from s.h.in BITS=64 bits=64 */
#include "assert.h"
+#include <math.h>
#include <stdlib.h>
#include "integer.h"
#include "tag.h"
@@ -93,3 +94,16 @@ s64 * s64_random (s64 *s)
arc4random_buf(s, sizeof(s64));
return s;
}
+
+s_tag * s64_sqrt (const s64 x, s_tag *dest)
+{
+ assert(dest);
+ if (x < 0) {
+ // FIXME
+ //dest->type = TAG_COMPLEX;
+ return NULL;
+ }
+ dest->type = TAG_S64;
+ dest->data.s64 = (s64) sqrtl((long double) x);
+ return dest;
+}
diff --git a/libc3/s8.c b/libc3/s8.c
index b0a037a..8e16717 100644
--- a/libc3/s8.c
+++ b/libc3/s8.c
@@ -12,6 +12,7 @@
*/
/* Gen from s.h.in BITS=8 bits=8 */
#include "assert.h"
+#include <math.h>
#include <stdlib.h>
#include "integer.h"
#include "tag.h"
@@ -93,3 +94,16 @@ s8 * s8_random (s8 *s)
arc4random_buf(s, sizeof(s8));
return s;
}
+
+s_tag * s8_sqrt (const s8 x, s_tag *dest)
+{
+ assert(dest);
+ if (x < 0) {
+ // FIXME
+ //dest->type = TAG_COMPLEX;
+ return NULL;
+ }
+ dest->type = TAG_S8;
+ dest->data.s8 = (s8) sqrtl((long double) x);
+ return dest;
+}
diff --git a/libc3/sw.c b/libc3/sw.c
index a645c86..b8a53bc 100644
--- a/libc3/sw.c
+++ b/libc3/sw.c
@@ -12,6 +12,7 @@
*/
/* Gen from s.h.in BITS=W bits=w */
#include "assert.h"
+#include <math.h>
#include <stdlib.h>
#include "integer.h"
#include "tag.h"
@@ -93,3 +94,16 @@ sw * sw_random (sw *s)
arc4random_buf(s, sizeof(sw));
return s;
}
+
+s_tag * sw_sqrt (const sw x, s_tag *dest)
+{
+ assert(dest);
+ if (x < 0) {
+ // FIXME
+ //dest->type = TAG_COMPLEX;
+ return NULL;
+ }
+ dest->type = TAG_SW;
+ dest->data.sw = (sw) sqrtl((long double) x);
+ return dest;
+}