9#ifndef PRINTLINES_ALLOWED
10#define PRINTLINES_ALLOWED 0
15static const char *FNAME =
"kest_expression.c";
20#define KEST_EXPRESSION_CONST(x) { \
21 .type = KEST_EXPR_CONST, \
22 .val = {.val_float = x}, \
68 return "TYPE_UNKNOWN";
145 if (!ret_val && strcmp(expr->
val.
ref_name,
"e") == 0)
148 if (!ret_val && strcmp(expr->
val.
ref_name,
"sample_rate") == 0)
178 goto detect_constants_finish;
189 goto detect_constants_finish;
203 goto detect_constants_finish;
206 for (
int i = 0; ret_val && i < arity; i++)
210 ret_val = ret_val && sub_expr_cst;
214detect_constants_finish:
228 kest_parameter_pll *current;
242 goto expr_compute_return;
254 goto expr_compute_return;
260 goto expr_compute_return;
268 goto expr_compute_return;
275 goto expr_compute_return;
281 goto expr_compute_return;
283 else if (strcmp(expr->
val.
ref_name,
"sample_rate") == 0)
287 goto expr_compute_return;
292 KEST_PRINTF(
"Error evaluating expression \"%s\": expression refers to non-constant \"%s\", but no scope given!\n",
295 goto expr_compute_return;
302 KEST_PRINTF(
"Error evaluating expression \"%s\": expression refers to non-constant \"%s\", but it isn't found in scope!\n",
305 goto expr_compute_return;
311 ret_val = kest_expression_evaluate_rec(ref->
val.
expr, scope, depth + 1);
317 KEST_PRINTF(
"Error evaluating expression \"%s\": expression refers to non-constant \"%s\", but it is NULL!\n",
330 KEST_PRINTF(
"Error evaluating expression \"%s\": expression refers to non-constant \"%s\", but it is NULL!\n",
341 KEST_PRINTF(
"Error evaluating expression \"%s\": expression refers to non-constant \"%s\", but it has unrecognised type %d!\n",
347 goto expr_compute_return;
352 KEST_PRINTF(
"Error evaluating expression (%p): expression has arity > 0, but has no sub-expressions!\n",
355 goto expr_compute_return;
361 ret_val = -(kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1));
365 ret_val = (kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1) + kest_expression_evaluate_rec(expr->
val.
sub_exprs[1], scope, depth + 1));
369 ret_val = kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1) - kest_expression_evaluate_rec(expr->
val.
sub_exprs[1], scope, depth + 1);
373 ret_val = kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1) * kest_expression_evaluate_rec(expr->
val.
sub_exprs[1], scope, depth + 1);
377 x = kest_expression_evaluate_rec(expr->
val.
sub_exprs[1], scope, depth + 1);
379 if (fabsf(x) < 1e-20)
383 goto expr_compute_return;
386 ret_val = kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1) / x;
390 ret_val = fabs(kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1));
397 ret_val = sqrt(kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1));
401 ret_val = exp(kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1));
405 ret_val = log(kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1));
409 ret_val = pow(kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1),
410 kest_expression_evaluate_rec(expr->
val.
sub_exprs[1], scope, depth + 1));
413 ret_val = sin(kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1));
417 ret_val = sinh(kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1));
421 ret_val = asin(kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1));
425 ret_val = cos(kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1));
429 ret_val = cosh(kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1));
433 ret_val = acos(kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1));
437 ret_val = tan(kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1));
441 ret_val = tanh(kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1));
445 ret_val = atan(kest_expression_evaluate_rec(expr->
val.
sub_exprs[0], scope, depth + 1));
459 float ret_val = kest_expression_evaluate_rec(expr, scope, 0);
488 for (
int i = 0; i < arity; i++)
517 if (!result)
return NULL;
526 if (!rhs)
return NULL;
530 if (!lhs)
return NULL;
532 lhs->
type = unary_type;
550 if (!arg_1 || !arg_2)
return NULL;
554 if (!bin)
return NULL;
556 bin->
type = binary_type;
576 if (!ref_name)
return NULL;
580 if (!result)
return NULL;
639 kest_parameter_pll *current;
643 #ifdef KEST_BOUNDS_CHECK_VERBOSE
647 float p1, p2, p3, p4;
672 #ifdef KEST_BOUNDS_CHECK_VERBOSE
673 KEST_PRINTF(
"[Depth: %d] Expression is constant (and cached!), with known value %.3f.\n", depth, expr->
cached_val);
681 #ifdef KEST_BOUNDS_CHECK_VERBOSE
690 #ifdef KEST_BOUNDS_CHECK_VERBOSE
691 KEST_PRINTF(
"[Depth: %d] Expression is a reference, to \"%s\". Therefore we must compute its range.\n", depth, expr->
val.
ref_name ? expr->
val.
ref_name :
"(NULL)");
695 #ifdef KEST_BOUNDS_CHECK_VERBOSE
696 KEST_PRINTF(
"[Depth: %d] The referenced value is a constant,", depth);
702 #ifdef KEST_BOUNDS_CHECK_VERBOSE
710 KEST_PRINTF(
"Error estimating expression (%p): expression refers to non-constant \"%s\", but no scope given!\n",
720 KEST_PRINTF(
"Error estimating expression (%p): expression refers to non-constant \"%s\", but it isn't found in scope!\n",
729 #ifdef KEST_BOUNDS_CHECK_VERBOSE
730 KEST_PRINTF(
"[Depth: %d] The referred quantity is an expression, so we recurse and compute its range!\n", depth);
738 #ifdef KEST_BOUNDS_CHECK_VERBOSE
739 KEST_PRINTF(
"The reference is to a parameter, but, ultimately, it turned up NULL!\n");
745 #ifdef KEST_BOUNDS_CHECK_VERBOSE
746 KEST_PRINTF(
"[Depth: %d] The reference is to a parameter. We compute its range.\n", depth);
750 ret.
a = kest_expression_evaluate_rec(ref->
val.
param->
min_expr, scope, depth + 1);
758 ret.
b = kest_expression_evaluate_rec(ref->
val.
param->
max_expr, scope, depth + 1);
765 #ifdef KEST_BOUNDS_CHECK_VERBOSE
766 KEST_PRINTF(
"[Depth: %d] Obtained parameter range [%.4f, %.4f].\n", depth, ret.
a, ret.
b);
772 KEST_PRINTF(
"Error evaluating expression (%p): expression refers to non-constant \"%s\", but it has unrecognised type %d!\n",
795 #ifdef KEST_BOUNDS_CHECK_VERBOSE
796 KEST_PRINTF(
"[Depth: %d] The expression has top-level arity %d; therefore we recurse and compute ranges of its top-level sub-expressions.\n", depth, arity);
813 if (x_int.
a < 0) ret.
a = 0;
814 else ret.
a = sqrt(x_int.
a);
816 if (x_int.
b < 0) ret.
b = 0;
817 else ret.
b = sqrt(x_int.
b);
825 ret.
a = log(x_int.
a);
830 ret.
b = log(x_int.
b);
837 else if (x_int.
a > 1)
840 ret.
a = asin(x_int.
a);
844 else if (x_int.
b > 1)
847 ret.
b = asin(x_int.
b);
852 if (x_int.
b < -1) ret.
a = M_PI;
853 else if (x_int.
b > 1) ret.
a = 0.0f;
854 else ret.
a = acos(x_int.
b);
856 if (x_int.
b < -1) ret.
b = M_PI;
857 else if (x_int.
b > 1) ret.
b = 0.0f;
858 else ret.
b = acos(x_int.
b);
885 if (x_int.
b > 0) ret.
a = 0.0;
886 else ret.
a = x_int.
b * x_int.
b;
890 ret.
a = x_int.
a * x_int.
a;
893 p1 = x_int.
a * x_int.
a;
894 p2 = x_int.
b * x_int.
b;
896 if (p2 > p1) ret.
b = p2;
904 if (x_int.
b > 0) ret.
a = 1.0;
905 else ret.
a = cosh(x_int.
b);
909 ret.
a = cosh(x_int.
a);
915 if (p2 > p1) ret.
b = p2;
923 if (x_int.
b > 0) ret.
a = 0.0;
924 else ret.
a = -x_int.
b;
934 if (p2 > p1) ret.
b = p2;
940 p1 = x_int.
a * y_int.
a;
941 p2 = x_int.
a * y_int.
b;
942 p3 = x_int.
b * y_int.
a;
943 p4 = x_int.
b * y_int.
b;
963 if (y_int.
a <= 0.0f && 0.0f <= y_int.
b)
966 if (x_int.
a > 0.0f || x_int.
b < 0.0f)
976 else if (x_int.
a == 0.0f && x_int.
b == 0.0f)
1004 if (y_int.
a < 0.0f && y_int.
a > -1e-20f) y_int.
a = -1e-20f;
1005 if (y_int.
a > 0.0f && y_int.
a < 1e-20f) y_int.
a = 1e-20f;
1007 if (y_int.
b < 0.0f && y_int.
b > -1e-20f) y_int.
b = -1e-20f;
1008 if (y_int.
b > 0.0f && y_int.
b < 1e-20f) y_int.
b = 1e-20f;
1010 y_int_d.
a = (fabsf(y_int.
a) < 1e-20) ? FLT_MAX : 1.0 / y_int.
a;
1011 y_int_d.
b = (fabsf(y_int.
b) < 1e-20) ? FLT_MAX : 1.0 / y_int.
b;
1013 p1 = x_int.
a * y_int_d.
a;
1014 p2 = x_int.
a * y_int_d.
b;
1015 p3 = x_int.
b * y_int_d.
a;
1016 p4 = x_int.
b * y_int_d.
b;
1044 if (x_int.
a == 0 && x_int.
b == 0)
1050 p1 = pow(x_int.
a, y_int.
a);
1051 p2 = pow(x_int.
a, y_int.
b);
1052 p3 = pow(x_int.
b, y_int.
a);
1053 p4 = pow(x_int.
b, y_int.
b);
1077 x_int.
a = x_int.
a + (0.5*M_PI);
1078 x_int.
b = x_int.
b + (0.5*M_PI);
1082 if (x_int.
b - x_int.
a > (2.0*M_PI))
1094 k = (int)ceilf((x_int.
a + (0.5*M_PI)) / (2.0*M_PI));
1101 if (-(0.5*M_PI) + k * (2.0*M_PI) <= x_int.
b)
1116 if (p2 < p1) ret.
a = p2;
1121 k = (int)ceilf((x_int.
a - (0.5*M_PI)) / (2.0*M_PI));
1123 if ((0.5*M_PI) + k * (2.0*M_PI) <= x_int.
b)
1135 if (p2 > p1) ret.
b = p2;
1145 if (x_int.
b - x_int.
a >= M_PI)
1157 k = (int)ceilf((x_int.
a - (0.5*M_PI)) / (2.0*M_PI));
1159 if ((0.5*M_PI) + k * (2.0*M_PI) <= x_int.
b)
1165 k = (int)ceilf((x_int.
a + M_PI/2) / (2.0*M_PI));
1167 if (-(0.5*M_PI) + k * (2.0*M_PI) <= x_int.
b)
1198 #ifdef KEST_BOUNDS_CHECK_VERBOSE
1260 const char *str_ptr;
1264 goto kest_expr_print_end;
1270 goto kest_expr_print_end;
1282 buf_pos = strlen(buf);
1288 buf[buf_pos++] =
'(';
if (buf_len < buf_pos + 1)
goto kest_expr_print_end;
1289 buf[buf_pos++] =
'n';
if (buf_len < buf_pos + 1)
goto kest_expr_print_end;
1290 buf[buf_pos++] =
'u';
if (buf_len < buf_pos + 1)
goto kest_expr_print_end;
1291 buf[buf_pos++] =
'l';
if (buf_len < buf_pos + 1)
goto kest_expr_print_end;
1292 buf[buf_pos++] =
'l';
if (buf_len < buf_pos + 1)
goto kest_expr_print_end;
1293 buf[buf_pos++] =
')';
1297 while (expr->
val.
ref_name[buf_pos] != 0 && buf_pos < buf_len)
1309 buf[buf_pos++] =
'-';
if (buf_len < buf_pos + 1)
goto kest_expr_print_end;
1313 goto bracketed_unary_sub_expr;
1322 while (str_ptr[buf_pos] != 0 && buf_pos < buf_len)
1324 buf[buf_pos] = str_ptr[buf_pos];
1328 if (buf_len < buf_pos + 1)
goto kest_expr_print_end;
1330 goto bracketed_unary_sub_expr;
1334 buf[buf_pos++] =
'(';
if (buf_len < buf_pos + 1)
goto kest_expr_print_end;
1336 if (buf_len < buf_pos + 1)
goto kest_expr_print_end;
1339 for (
int i = 0; str_ptr[i] != 0 && buf_pos < buf_len; i++)
1340 buf[buf_pos++] = str_ptr[i];
1342 if (buf_len < buf_pos + 1)
goto kest_expr_print_end;
1345 if (buf_len < buf_pos + 1)
goto kest_expr_print_end;
1346 buf[buf_pos++] =
')';
1350 buf[buf_pos++] =
'|';
if (buf_len < buf_pos + 1)
goto kest_expr_print_end;
1352 if (buf_len < buf_pos + 1)
goto kest_expr_print_end;
1353 buf[buf_pos++] =
'|';
1357 goto kest_expr_print_end;
1358bracketed_unary_sub_expr:
1359 buf[buf_pos++] =
'(';
if (buf_len < buf_pos + 1)
goto kest_expr_print_end;
1361 if (buf_len < buf_pos + 1)
goto kest_expr_print_end;
1362 buf[buf_pos++] =
')';
void kest_free(void *ptr)
void * kest_alloc(size_t size)
char * kest_strndup(const char *str, size_t n)
kest_expr_scope_entry * kest_expr_scope_fetch(kest_expr_scope *scope, const char *name)
#define KEST_SCOPE_ENTRY_TYPE_PARAM
#define KEST_SCOPE_ENTRY_TYPE_EXPR
#define KEST_SCOPE_ENTRY_TYPE_SETTING
kest_interval kest_interval__b(float b)
kest_expression kest_expression_zero
int kest_expression_detect_constants(kest_expression *expr)
kest_interval kest_expression_compute_range_rec(kest_expression *expr, kest_expr_scope *scope, int depth)
const char * kest_expression_infix_operator_string(kest_expression *expr)
kest_expression kest_expression_int_max
int kest_expression_form(kest_expression *expr)
int kest_expression_references_param(kest_expression *expr, kest_parameter *param)
kest_expression * new_m_expression_reference(char *ref_name)
kest_expression * new_m_expression_const(float v)
kest_interval kest_interval_a_(float a)
int kest_expression_is_constant(kest_expression *expr)
kest_interval kest_expression_compute_range(kest_expression *expr, kest_expr_scope *scope)
int kest_expression_detect_constants_rec(kest_expression *expr, int depth)
kest_expression kest_expression_standard_gain_min
kest_expression kest_expression_pi
kest_expression kest_expression_freq_max
kest_expression kest_expression_sample_rate
int kest_expression_print_rec(kest_expression *expr, char *buf, int buf_len, int depth)
const char * kest_expression_function_string(kest_expression *expr)
int kest_expression_arity(kest_expression *expr)
char * kest_expression_type_to_str(int type)
#define KEST_EXPRESSION_CONST(x)
int kest_expression_print(kest_expression *expr)
kest_interval kest_interval_real_line()
kest_expression kest_expression_standard_gain_max
kest_expression * new_m_expression_unary(int unary_type, kest_expression *rhs)
kest_expression kest_expression_one
int kest_expression_references_param_rec(kest_expression *expr, kest_parameter *param, int depth)
const char * kest_expression_to_string(kest_expression *expr)
float kest_expression_evaluate(kest_expression *expr, kest_expr_scope *scope)
kest_expression kest_expression_int_min
kest_expression kest_expression_minus_one
kest_expression * new_m_expression_binary(int binary_type, kest_expression *arg_1, kest_expression *arg_2)
kest_interval kest_interval_singleton(float v)
kest_interval kest_interval_ab(float a, float b)
kest_expression kest_expression_e
kest_expression kest_expression_const(float v)
int kest_expression_refers_constant(kest_expression *expr)
#define KEST_EXPR_FORM_UNARY_OP
#define KEST_EXPR_REC_MAX_DEPTH
#define KEST_EXPR_FORM_UNARY_FN
#define KEST_EXPR_FORM_INFIX_OP
#define KEST_EXPR_FORM_ATOMIC
#define KEST_EXPR_TYPE_MAX_VAL
#define KEST_EXPR_FORM_NORM
#define KEST_FPGA_SAMPLE_RATE
#define KEST_FPGA_DATA_WIDTH
#define IMPLEMENT_LINKED_PTR_LIST(X)
#define IMPLEMENT_PTR_LIST(X)
#define KEST_STANDARD_GAIN_MIN
#define KEST_STANDARD_GAIN_MAX
struct kest_expression * expr
struct kest_parameter * param
struct kest_setting * setting
union kest_expr_scope_entry::@246374331353003302125051026062066243300031256272 val
union kest_expression::@166010055114121035173062362142367362353107353142 val
struct kest_expression ** sub_exprs
struct kest_expression * min_expr
const char * name_internal
struct kest_expression * max_expr