#define NATIVE_MODULE "$math"
#include <math.h>
#include "ext_math.h"
#include "list.h"
module_t ext_math_module = {NO, NULL, NO, NULL};
static int check_one_vector(cList *l1, Int *len_ret)
{
Int i,len;
len=list_length(l1);
for (i=0; i<len; i++) {
if (list_elem(l1,i)->type != FLOAT)
THROW((type_id, "Arguments must be lists of floats."))
}
*len_ret=len;
RETURN_TRUE;
}
static int check_vectors(cList *l1, cList *l2, Int *len_ret)
{
Int i,len;
len=list_length(l1);
if (list_length(l2)!=len)
THROW((range_id, "Arguments are not of the same length."))
for (i=0; i<len; i++) {
if (list_elem(l1,i)->type != FLOAT)
THROW((type_id, "Arguments must be lists of floats."))
if (list_elem(l2,i)->type != FLOAT)
THROW((type_id, "Arguments must be lists of floats."))
}
*len_ret=len;
RETURN_TRUE;
}
NATIVE_METHOD(minor) {
Int i,len;
cList *l,*l1,*l2;
INIT_2_ARGS(LIST,LIST);
l1=LIST1;
l2=LIST2;
if (!check_vectors (l1,l2,&len))
RETURN_FALSE;
l=list_new(len);
l->len=len;
for (i=0; i<len; i++) {
Float p,q;
p=list_elem(l1,i)->u.fval;
q=list_elem(l2,i)->u.fval;
list_elem(l,i)->type=FLOAT;
list_elem(l,i)->u.fval=p<q ? p : q;
}
CLEAN_RETURN_LIST(l);
}
NATIVE_METHOD(major) {
Int i,len;
cList *l,*l1,*l2;
INIT_2_ARGS(LIST,LIST);
l1=LIST1;
l2=LIST2;
if (!check_vectors (l1,l2,&len))
RETURN_FALSE;
l=list_new(len);
l->len=len;
for (i=0; i<len; i++) {
Float p,q;
p=list_elem(l1,i)->u.fval;
q=list_elem(l2,i)->u.fval;
list_elem(l,i)->type=FLOAT;
list_elem(l,i)->u.fval=p>q ? p : q;
}
CLEAN_RETURN_LIST(l);
}
NATIVE_METHOD(add) {
Int i,len;
cList *l,*l1,*l2;
INIT_2_ARGS(LIST,LIST);
l1=LIST1;
l2=LIST2;
if (!check_vectors (l1,l2,&len))
RETURN_FALSE;
l=list_new(len);
l->len=len;
for (i=0; i<len; i++) {
Float p,q;
p=list_elem(l1,i)->u.fval;
q=list_elem(l2,i)->u.fval;
list_elem(l,i)->type=FLOAT;
list_elem(l,i)->u.fval=p+q;
}
CLEAN_RETURN_LIST(l);
}
NATIVE_METHOD(sub) {
Int i,len;
cList *l,*l1,*l2;
INIT_2_ARGS(LIST,LIST);
l1=LIST1;
l2=LIST2;
if (!check_vectors (l1,l2,&len))
RETURN_FALSE;
l=list_new(len);
l->len=len;
for (i=0; i<len; i++) {
Float p,q;
p=list_elem(l1,i)->u.fval;
q=list_elem(l2,i)->u.fval;
list_elem(l,i)->type=FLOAT;
list_elem(l,i)->u.fval=p-q;
}
CLEAN_RETURN_LIST(l);
}
NATIVE_METHOD(dot) {
Int i,len;
cList *l1,*l2;
Float s;
INIT_2_ARGS(LIST,LIST);
l1=LIST1;
l2=LIST2;
if (!check_vectors (l1,l2,&len))
RETURN_FALSE;
for (s=0.0,i=0; i<len; i++) {
Float p,q;
p=list_elem(l1,i)->u.fval;
q=list_elem(l2,i)->u.fval;
s+=p*q;
}
CLEAN_RETURN_FLOAT(s);
}
NATIVE_METHOD(distance) {
Int i,len;
cList *l1,*l2;
Float s;
INIT_2_ARGS(LIST,LIST);
l1=LIST1;
l2=LIST2;
if (!check_vectors (l1,l2,&len))
RETURN_FALSE;
for (s=0.0,i=0; i<len; i++) {
Float p,q,d;
p=list_elem(l1,i)->u.fval;
q=list_elem(l2,i)->u.fval;
d=p-q;
s+=d*d;
}
CLEAN_RETURN_FLOAT(sqrt(s));
}
NATIVE_METHOD(cross) {
Int len;
cList *l,*l1,*l2;
cData *f,*f1,*f2;
INIT_2_ARGS(LIST,LIST);
l1=LIST1;
l2=LIST2;
if (!check_vectors (l1,l2,&len))
RETURN_FALSE;
if (len!=3)
THROW((range_id,"The vectors are not of length 3."))
l=list_new(len);
l->len=len;
f=list_elem(l,0);
f1=list_elem(l1,0);
f2=list_elem(l2,0);
f[0].type=f[1].type=f[2].type=FLOAT;
f[0].u.fval=f1[1].u.fval*f2[2].u.fval-f1[2].u.fval*f2[1].u.fval;
f[1].u.fval=f1[2].u.fval*f2[0].u.fval-f1[0].u.fval*f2[2].u.fval;
f[2].u.fval=f1[0].u.fval*f2[1].u.fval-f1[1].u.fval*f2[0].u.fval;
CLEAN_RETURN_LIST(l);
}
NATIVE_METHOD(scale) {
Int i,len;
cList *l,*l1;
Float f;
INIT_2_ARGS(FLOAT,LIST);
l1=LIST2;
f=FLOAT1;
if (!check_one_vector (l1,&len))
RETURN_FALSE;
l=list_new(len);
l->len=len;
for (i=0; i<len; i++) {
Float p;
p=list_elem(l1,i)->u.fval;
list_elem(l,i)->type=FLOAT;
list_elem(l,i)->u.fval=p*f;
}
CLEAN_RETURN_LIST(l);
}
NATIVE_METHOD(is_lower) {
Int i,len;
cList *l1,*l2;
INIT_2_ARGS(LIST,LIST);
l1=LIST1;
l2=LIST2;
if (!check_vectors (l1,l2,&len))
RETURN_FALSE;
for (i=0; i<len; i++) {
Float p,q;
p=list_elem(l1,i)->u.fval;
q=list_elem(l2,i)->u.fval;
if (p>=q) {
CLEAN_RETURN_INTEGER(0);
}
}
CLEAN_RETURN_INTEGER(1);
}
NATIVE_METHOD(transpose) {
Int i,len,len1;
cList *l,*l1;
cData *e,*o;
INIT_1_ARG(LIST);
l1=LIST1;
len=list_length(l1);
if (!len) {
l1=list_dup(l1);
CLEAN_RETURN_LIST(l1);
}
e=list_elem(l1,0);
for (i=0; i<len; i++) {
if (e[i].type!=LIST)
THROW((type_id,"The argument must be a list of lists."))
}
len1=list_length(e[0].u.list);
if (!len1) {
l1=list_dup(e[0].u.list);
CLEAN_RETURN_LIST(l1);
}
for (i=1; i<len; i++) {
if (list_length(e[i].u.list)!=len1)
THROW((range_id,"All sublists must be of the same length"))
}
l=list_new(len1);
l->len=len1;
o=list_elem(l,0);
for (i=0; i<len1; i++) {
cList *l2;
cData *k;
Int j;
l2=list_new(len);
l2->len=len;
o[i].type=LIST;
o[i].u.list=l2;
k=list_elem(l2,0);
for (j=0; j<len; j++)
data_dup(&k[j],list_elem(e[j].u.list,i));
}
CLEAN_RETURN_LIST(l);
}