summaryrefslogtreecommitdiff
path: root/src/tibfunction.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tibfunction.c')
-rw-r--r--src/tibfunction.c381
1 files changed, 190 insertions, 191 deletions
diff --git a/src/tibfunction.c b/src/tibfunction.c
index d2085f5..b1d59fc 100644
--- a/src/tibfunction.c
+++ b/src/tibfunction.c
@@ -1,6 +1,6 @@
/*
* libtib - Read, write, and evaluate TI BASIC programs
- * Copyright (C) 2015-2016 Delwink, LLC
+ * Copyright (C) 2015-2017 Delwink, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -30,267 +30,266 @@
struct registry_node
{
- int key;
- tib_Function f;
+ int key;
+ tib_Function f;
};
struct registry
{
- size_t len;
- struct registry_node *nodes;
+ size_t len;
+ struct registry_node *nodes;
};
static gsl_rng *rng = NULL;
-static struct registry registry =
- {
- .len = 0,
- .nodes = NULL
- };
+static struct registry registry = {
+ .len = 0,
+ .nodes = NULL
+};
static TIB *
-func_paren (const struct tib_expr *expr)
+func_paren(const struct tib_expr *expr)
{
- return tib_eval (expr);
+ return tib_eval(expr);
}
static int
-split_number_args (const struct tib_expr *expr, int num_params, ...)
+split_number_args(const struct tib_expr *expr, int num_params, ...)
{
- const int *beg, *end;
- int rc = 0, numpar = 0;
- va_list ap;
-
- va_start (ap, num_params);
- for (beg = expr->data, end = beg; end < expr->data + expr->len; ++end)
- {
- if (tib_is_func (*end))
- {
- ++numpar;
- }
- else if (')' == *end)
- {
- if (--numpar < 0)
- {
- rc = TIB_ESYNTAX;
- break;
- }
- }
- else if (0 == numpar &&
- (',' == *end || end + 1 == expr->data + expr->len))
- {
- if (num_params-- == 0)
- {
- rc = TIB_EARGNUM;
- break;
- }
-
- int start = beg - expr->data, stop = end - expr->data;
- if (end + 1 == expr->data + expr->len)
- ++stop;
-
- struct tib_expr arg;
- tib_subexpr (&arg, expr, start, stop);
-
- TIB *t = tib_eval (&arg);
- if (!t)
- {
- rc = tib_errno;
- break;
- }
-
- if (tib_type (t) != TIB_TYPE_COMPLEX)
- {
- tib_decref (t);
- tib_errno = TIB_ETYPE;
- break;
- }
-
- gsl_complex *out = va_arg (ap, gsl_complex *);
- *out = tib_complex_value (t);
- tib_decref (t);
-
- beg = end + 1;
- }
- }
- va_end (ap);
-
- return rc;
+ const int *beg, *end;
+ int rc = 0, numpar = 0;
+ va_list ap;
+
+ va_start(ap, num_params);
+ for (beg = expr->data, end = beg; end < expr->data + expr->len; ++end)
+ {
+ if (tib_is_func(*end))
+ {
+ ++numpar;
+ }
+ else if (')' == *end)
+ {
+ if (--numpar < 0)
+ {
+ rc = TIB_ESYNTAX;
+ break;
+ }
+ }
+ else if (0 == numpar &&
+ (',' == *end || end + 1 == expr->data + expr->len))
+ {
+ if (num_params-- == 0)
+ {
+ rc = TIB_EARGNUM;
+ break;
+ }
+
+ int start = beg - expr->data, stop = end - expr->data;
+ if (end + 1 == expr->data + expr->len)
+ ++stop;
+
+ struct tib_expr arg;
+ tib_subexpr(&arg, expr, start, stop);
+
+ TIB *t = tib_eval(&arg);
+ if (!t)
+ {
+ rc = tib_errno;
+ break;
+ }
+
+ if (tib_type(t) != TIB_TYPE_COMPLEX)
+ {
+ tib_decref(t);
+ tib_errno = TIB_ETYPE;
+ break;
+ }
+
+ gsl_complex *out = va_arg(ap, gsl_complex *);
+ *out = tib_complex_value(t);
+ tib_decref(t);
+
+ beg = end + 1;
+ }
+ }
+ va_end(ap);
+
+ return rc;
}
static TIB *
-single_parameter_function (const struct tib_expr *expr,
- gsl_complex (*f) (gsl_complex))
+single_parameter_function(const struct tib_expr *expr,
+ gsl_complex(*f)(gsl_complex))
{
- gsl_complex z;
+ gsl_complex z;
- tib_errno = split_number_args (expr, 1, &z);
- if (tib_errno)
- return NULL;
+ tib_errno = split_number_args(expr, 1, &z);
+ if (tib_errno)
+ return NULL;
- z = f (z);
- return tib_new_complex (GSL_REAL (z), GSL_IMAG (z));
+ z = f(z);
+ return tib_new_complex(GSL_REAL(z), GSL_IMAG(z));
}
static TIB *
-func_sin (const struct tib_expr *expr)
+func_sin(const struct tib_expr *expr)
{
- return single_parameter_function (expr, gsl_complex_sin);
+ return single_parameter_function(expr, gsl_complex_sin);
}
static TIB *
-func_cos (const struct tib_expr *expr)
+func_cos(const struct tib_expr *expr)
{
- return single_parameter_function (expr, gsl_complex_cos);
+ return single_parameter_function(expr, gsl_complex_cos);
}
static TIB *
-func_tan (const struct tib_expr *expr)
+func_tan(const struct tib_expr *expr)
{
- return single_parameter_function (expr, gsl_complex_tan);
+ return single_parameter_function(expr, gsl_complex_tan);
}
static int
-is_int (gsl_complex z)
+is_int(gsl_complex z)
{
- return GSL_IMAG (z) == 0 && fmod (GSL_REAL (z), 1.0) == 0;
+ return GSL_IMAG(z) == 0 && fmod(GSL_REAL(z), 1.0) == 0;
}
static TIB *
-func_randint (const struct tib_expr *expr)
+func_randint(const struct tib_expr *expr)
{
- int len = expr->len, num_commas = 0;
-
- for (int i = 0; i < len; ++i)
- {
- if (',' == expr->data[i])
- {
- if (++num_commas > 2)
- break;
- }
- }
-
- if (num_commas != 2)
- {
- tib_errno = TIB_EARGNUM;
- return NULL;
- }
-
- gsl_complex min, max, count;
- tib_errno = split_number_args (expr, 3, &min, &max, &count);
- if (tib_errno)
- return NULL;
-
- if (!(is_int (min) && is_int (max) && is_int (count))
- || GSL_REAL (count) < 0)
- return NULL;
-
- double diff = GSL_REAL (max) - GSL_REAL (min);
-
- len = (unsigned int) GSL_REAL (count);
- gsl_complex vals[len];
-
- for (int i = 0; i < len; ++i)
- {
- GSL_SET_COMPLEX (&vals[i], (double) gsl_rng_get (rng), 0);
-
- while (GSL_REAL (vals[i]) < GSL_REAL (min))
- GSL_SET_REAL (&vals[i], GSL_REAL (vals[i]) + diff);
- while (GSL_REAL (vals[i]) > GSL_REAL (max))
- GSL_SET_REAL (&vals[i], GSL_REAL (vals[i]) - diff);
- }
-
- return tib_new_list (vals, len);
+ int len = expr->len, num_commas = 0;
+
+ for (int i = 0; i < len; ++i)
+ {
+ if (',' == expr->data[i])
+ {
+ if (++num_commas > 2)
+ break;
+ }
+ }
+
+ if (num_commas != 2)
+ {
+ tib_errno = TIB_EARGNUM;
+ return NULL;
+ }
+
+ gsl_complex min, max, count;
+ tib_errno = split_number_args(expr, 3, &min, &max, &count);
+ if (tib_errno)
+ return NULL;
+
+ if (!(is_int(min) && is_int(max) && is_int(count))
+ || GSL_REAL(count) < 0)
+ return NULL;
+
+ double diff = GSL_REAL(max) - GSL_REAL(min);
+
+ len = (unsigned int) GSL_REAL(count);
+ gsl_complex vals[len];
+
+ for (int i = 0; i < len; ++i)
+ {
+ GSL_SET_COMPLEX(&vals[i], (double) gsl_rng_get(rng), 0);
+
+ while (GSL_REAL(vals[i]) < GSL_REAL(min))
+ GSL_SET_REAL(&vals[i], GSL_REAL(vals[i]) + diff);
+
+ while (GSL_REAL(vals[i]) > GSL_REAL(max))
+ GSL_SET_REAL(&vals[i], GSL_REAL(vals[i]) - diff);
+ }
+
+ return tib_new_list(vals, len);
}
int
-tib_registry_init ()
+tib_registry_init()
{
- int rc;
+ int rc;
- if (registry.nodes != NULL || rng != NULL)
- tib_registry_free ();
+ if (registry.nodes != NULL || rng != NULL)
+ tib_registry_free();
- rng = gsl_rng_alloc (gsl_rng_taus2);
- if (NULL == rng)
- return TIB_EALLOC;
+ rng = gsl_rng_alloc(gsl_rng_taus2);
+ if (NULL == rng)
+ return TIB_EALLOC;
- gsl_rng_set (rng, (unsigned long) time (NULL));
+ gsl_rng_set(rng, (unsigned long) time(NULL));
-#define ADD(K,F) rc = tib_registry_add (K, F); if (rc) goto fail;
+#define ADD(K,F) rc = tib_registry_add(K, F); if (rc) goto fail;
- ADD ('(', func_paren);
- ADD (TIB_CHAR_SIN, func_sin);
- ADD (TIB_CHAR_COS, func_cos);
- ADD (TIB_CHAR_TAN, func_tan);
- ADD (TIB_CHAR_RANDINT, func_randint);
+ ADD('(', func_paren);
+ ADD(TIB_CHAR_SIN, func_sin);
+ ADD(TIB_CHAR_COS, func_cos);
+ ADD(TIB_CHAR_TAN, func_tan);
+ ADD(TIB_CHAR_RANDINT, func_randint);
#undef ADD
fail:
- if (rc)
- tib_registry_free ();
+ if (rc)
+ tib_registry_free();
- return rc;
+ return rc;
}
void
-tib_registry_free ()
+tib_registry_free()
{
- if (registry.nodes)
- free (registry.nodes);
- if (rng)
- gsl_rng_free (rng);
-
- registry.len = 0;
- registry.nodes = NULL;
- rng = NULL;
+ if (registry.nodes)
+ free(registry.nodes);
+ if (rng)
+ gsl_rng_free(rng);
+
+ registry.len = 0;
+ registry.nodes = NULL;
+ rng = NULL;
}
int
-tib_registry_add (int key, tib_Function f)
+tib_registry_add(int key, tib_Function f)
{
- struct registry_node *old = registry.nodes;
-
- ++registry.len;
- registry.nodes = realloc (registry.nodes,
- registry.len * sizeof (struct registry_node));
- if (NULL == registry.nodes)
- {
- registry.nodes = old;
- --registry.len;
- return TIB_EALLOC;
- }
-
- struct registry_node new =
- {
- .key = key,
- .f = f
- };
-
- registry.nodes[registry.len - 1] = new;
- return 0;
+ struct registry_node *old = registry.nodes;
+
+ ++registry.len;
+ registry.nodes = realloc(registry.nodes,
+ registry.len * sizeof(struct registry_node));
+ if (NULL == registry.nodes)
+ {
+ registry.nodes = old;
+ --registry.len;
+ return TIB_EALLOC;
+ }
+
+ struct registry_node new = {
+ .key = key,
+ .f = f
+ };
+
+ registry.nodes[registry.len - 1] = new;
+ return 0;
}
bool
-tib_is_func (int key)
+tib_is_func(int key)
{
- size_t i;
- for (i = 0; i < registry.len; ++i)
- if (key == registry.nodes[i].key)
- return true;
+ size_t i;
+ for (i = 0; i < registry.len; ++i)
+ if (key == registry.nodes[i].key)
+ return true;
- return false;
+ return false;
}
TIB *
-tib_call (int key, const struct tib_expr *expr)
+tib_call(int key, const struct tib_expr *expr)
{
- size_t i;
- for (i = 0; i < registry.len; ++i)
- if (key == registry.nodes[i].key)
- return registry.nodes[i].f (expr);
+ size_t i;
+ for (i = 0; i < registry.len; ++i)
+ if (key == registry.nodes[i].key)
+ return registry.nodes[i].f(expr);
- tib_errno = TIB_EBADFUNC;
- return NULL;
+ tib_errno = TIB_EBADFUNC;
+ return NULL;
}