int test2() { const char str[] = "y=26*2/2+x*30/(20*1)"; mapper_expr e = mapper_expr_new_from_string(str, 0, 0, 1); printf("\nParsing %s\n", str); if (!e) { printf("Test FAILED.\n"); return 1; } #ifdef DEBUG printexpr("Parser returned: ", e); #endif printf("\n"); int inp, outp; inp = 3; mapper_expr_evaluate(e, &inp, &outp); printf("Evaluate with x=%d: %d (expected: %d)\n", inp, outp, 26*2/2+inp*30/(20*1)); inp = 321; mapper_expr_evaluate(e, &inp, &outp); printf("Evaluate with x=%d: %d (expected: %d)\n", inp, outp, 26*2/2+inp*30/(20*1)); mapper_expr_free(e); return 0; }
int main() { const char str[] = "y=26*2/2+log10(pi)+2.*pow(2,1*(3+7*.1)*1.1+x{0}[0])*3*4+cos(2.)"; //const char str[] = "y=x?1:2"; int input_history_size, output_history_size; mapper_expr e = mapper_expr_new_from_string(str, 'f', 'f', 1, 1, &input_history_size, &output_history_size); printf("Parsing %s\n", str); if (!e) { printf("Test FAILED.\n"); return 1; } #ifdef DEBUG printexpr("Parser returned: ", e); #endif printf("\n"); float inp = 3.0, outp; // create signal_history structures mapper_signal_history_t inh, outh; inh.type = 'f'; inh.size = 1; inh.length = 1; inh.value = &inp; inh.timetag = calloc(1, sizeof(mapper_timetag_t)); inh.position = 0; outh.type = 'f'; outh.size = 1; outh.length = 1; outh.value = &outp; outh.timetag = calloc(1, sizeof(mapper_timetag_t)); outh.position = -1; int iterations = 1000000; int results = 0; double then = get_current_time(); printf("Calculate expression %i times... ", iterations); while (iterations--) { results += mapper_expr_evaluate(e, &inh, &outh); } double now = get_current_time(); printf("%f seconds.\n", now-then); if (results) { printf("Evaluate with x=%f: %f (expected: %f)\n", inp, outp, 26*2/2+log10f(M_PI)+2.f*powf(2,1*(3+7*.1f)*1.1f+inp)*3*4+cosf(2.0f)); } else printf("NO results.\n"); mapper_expr_free(e); free(inh.timetag); free(outh.timetag); return 0; }
void mapper_connection_set_mode_expression(mapper_connection c, const char *expr) { int input_history_size, output_history_size; if (replace_expression_string(c, expr, &input_history_size, &output_history_size)) return; c->props.mode = MO_EXPRESSION; reallocate_connection_histories(c, input_history_size, output_history_size); /* Special case: if we are the receiver and the new expression * evaluates to a constant we can update immediately. */ /* TODO: should call handler for all instances updated * through this connection. */ mapper_signal sig = c->parent->signal; if (!sig->props.is_output && mapper_expr_constant_output(c->expr) && !c->props.send_as_instance) { int index = 0; mapper_timetag_t now; mapper_clock_now(&sig->device->admin->clock, &now); if (!sig->id_maps[0].instance) index = msig_get_instance_with_local_id(sig, 0, 1, &now); if (index < 0) return; mapper_signal_instance si = sig->id_maps[index].instance; // evaluate expression mapper_signal_history_t h; h.type = sig->props.type; h.value = si->value; h.position = -1; h.length = sig->props.length; h.size = 1; char typestring[h.length]; mapper_expr_evaluate(c->expr, 0, &c->expr_vars[si->index], &h, typestring); // call handler if it exists if (sig->handler) sig->handler(sig, &sig->props, 0, si->value, 1, &now); } }
int test1() { const char str[] = "y=26*2/2+log10(pi)+2.*pow(2,1*(3+7*.1)*1.1+x{-6*2+12})*3*4+cos(2.)"; mapper_expr e = mapper_expr_new_from_string(str, 1, 1, 1); printf("Parsing %s\n", str); if (!e) { printf("Test FAILED.\n"); return 1; } #ifdef DEBUG printexpr("Parser returned: ", e); #endif printf("\n"); float inp, outp; inp = 3.0; mapper_expr_evaluate(e, &inp, &outp); printf("Evaluate with x=%f: %f (expected: %f)\n", inp, outp, 26*2/2+log10f(M_PI)+2.f*powf(2,1*(3+7*.1f)*1.1f+inp)*3*4+cosf(2.0f)); mapper_expr_free(e); return 0; }
int mapper_connection_perform(mapper_connection connection, mapper_signal_history_t *from, mapper_signal_history_t **expr_vars, mapper_signal_history_t *to, char *typestring) { int changed = 0, i; int vector_length = from->length < to->length ? from->length : to->length; if (connection->props.muted) return 0; /* If the destination type is unknown, we can't do anything * intelligent here -- even bypass mode might screw up if we * assume the types work out. */ if (connection->props.dest_type != 'f' && connection->props.dest_type != 'i' && connection->props.dest_type != 'd') { return 0; } if (!connection->props.mode || connection->props.mode == MO_BYPASS) { /* Increment index position of output data structure. */ to->position = (to->position + 1) % to->size; if (connection->props.src_type == connection->props.dest_type) { memcpy(msig_history_value_pointer(*to), msig_history_value_pointer(*from), mapper_type_size(to->type) * vector_length); memset(msig_history_value_pointer(*to) + mapper_type_size(to->type) * vector_length, 0, (to->length - vector_length) * mapper_type_size(to->type)); } else if (connection->props.src_type == 'f') { float *vfrom = msig_history_value_pointer(*from); if (connection->props.dest_type == 'i') { int *vto = msig_history_value_pointer(*to); for (i = 0; i < vector_length; i++) { vto[i] = (int)vfrom[i]; } for (; i < to->length; i++) { vto[i] = 0; } } else if (connection->props.dest_type == 'd') { double *vto = msig_history_value_pointer(*to); for (i = 0; i < vector_length; i++) { vto[i] = (double)vfrom[i]; } for (; i < to->length; i++) { vto[i] = 0; } } } else if (connection->props.src_type == 'i') { int *vfrom = msig_history_value_pointer(*from); if (connection->props.dest_type == 'f') { float *vto = msig_history_value_pointer(*to); for (i = 0; i < vector_length; i++) { vto[i] = (float)vfrom[i]; } for (; i < to->length; i++) { vto[i] = 0; } } else if (connection->props.dest_type == 'd') { double *vto = msig_history_value_pointer(*to); for (i = 0; i < vector_length; i++) { vto[i] = (double)vfrom[i]; } for (; i < to->length; i++) { vto[i] = 0; } } } else if (connection->props.src_type == 'd') { double *vfrom = msig_history_value_pointer(*from); if (connection->props.dest_type == 'i') { int *vto = msig_history_value_pointer(*to); for (i = 0; i < vector_length; i++) { vto[i] = (int)vfrom[i]; } for (; i < to->length; i++) { vto[i] = 0; } } else if (connection->props.dest_type == 'f') { float *vto = msig_history_value_pointer(*to); for (i = 0; i < vector_length; i++) { vto[i] = (float)vfrom[i]; } for (; i < to->length; i++) { vto[i] = 0; } } } for (i = 0; i < vector_length; i++) { typestring[i] = to->type; } return 1; } else if (connection->props.mode == MO_EXPRESSION || connection->props.mode == MO_LINEAR) { die_unless(connection->expr!=0, "Missing expression.\n"); return (mapper_expr_evaluate(connection->expr, from, expr_vars, to, typestring)); } else if (connection->props.mode == MO_CALIBRATE) { /* Increment index position of output data structure. */ to->position = (to->position + 1) % to->size; if (!connection->props.src_min) { connection->props.src_min = malloc(connection->props.src_length * mapper_type_size(connection->props.src_type)); } if (!connection->props.src_max) { connection->props.src_max = malloc(connection->props.src_length * mapper_type_size(connection->props.src_type)); } /* If calibration mode has just taken effect, first data * sample sets source min and max */ if (connection->props.src_type == 'f') { float *v = msig_history_value_pointer(*from); float *src_min = (float*)connection->props.src_min; float *src_max = (float*)connection->props.src_max; if (!connection->calibrating) { for (i = 0; i < from->length; i++) { src_min[i] = v[i]; src_max[i] = v[i]; } connection->calibrating = 1; changed = 1; } else { for (i = 0; i < from->length; i++) { if (v[i] < src_min[i]) { src_min[i] = v[i]; changed = 1; } if (v[i] > src_max[i]) { src_max[i] = v[i]; changed = 1; } } } } else if (connection->props.src_type == 'i') { int *v = msig_history_value_pointer(*from); int *src_min = (int*)connection->props.src_min; int *src_max = (int*)connection->props.src_max; if (!connection->calibrating) { for (i = 0; i < from->length; i++) { src_min[i] = v[i]; src_max[i] = v[i]; } connection->calibrating = 1; changed = 1; } else { for (i = 0; i < from->length; i++) { if (v[i] < src_min[i]) { src_min[i] = v[i]; changed = 1; } if (v[i] > src_max[i]) { src_max[i] = v[i]; changed = 1; } } } } else if (connection->props.src_type == 'd') { double *v = msig_history_value_pointer(*from); double *src_min = (double*)connection->props.src_min; double *src_max = (double*)connection->props.src_max; if (!connection->calibrating) { for (i = 0; i < from->length; i++) { src_min[i] = v[i]; src_max[i] = v[i]; } connection->calibrating = 1; changed = 1; } else { for (i = 0; i < from->length; i++) { if (v[i] < src_min[i]) { src_min[i] = v[i]; changed = 1; } if (v[i] > src_max[i]) { src_max[i] = v[i]; changed = 1; } } } } if (changed) { mapper_connection_set_mode_linear(connection); /* Stay in calibrate mode. */ connection->props.mode = MO_CALIBRATE; } if (connection->expr) return (mapper_expr_evaluate(connection->expr, from, expr_vars, to, typestring)); else return 0; } return 1; }
int mapper_connection_perform(mapper_connection connection, mapper_signal sig, mapper_signal_value_t *from_value, mapper_signal_value_t *to_value) { int changed = 0; float f = 0; if (connection->props.muted) return 0; /* If the destination type is unknown, we can't do anything * intelligent here -- even bypass mode might screw up if we * assume the types work out. */ if (connection->props.dest_type != 'f' && connection->props.dest_type != 'i') { return 0; } if (!connection->props.mode || connection->props.mode == MO_BYPASS) { if (connection->props.src_type == connection->props.dest_type) *to_value = *from_value; else if (connection->props.src_type == 'f' && connection->props.dest_type == 'i') to_value->i32 = (int)from_value->f; else if (connection->props.src_type == 'i' && connection->props.dest_type == 'f') to_value->f = (float)from_value->i32; } else if (connection->props.mode == MO_EXPRESSION || connection->props.mode == MO_LINEAR) { die_unless(connection->expr!=0, "Missing expression.\n"); *to_value = mapper_expr_evaluate(connection->expr, from_value); } else if (connection->props.mode == MO_CALIBRATE) { if (connection->props.src_type == 'f') f = from_value->f; else if (connection->props.src_type == 'i') f = (float)from_value->i32; /* If calibration mode has just taken effect, first data * sample sets source min and max */ if (!connection->calibrating) { connection->props.range.src_min = f; connection->props.range.src_max = f; connection->props.range.known |= CONNECTION_RANGE_SRC_MIN | CONNECTION_RANGE_SRC_MAX; connection->calibrating = 1; changed = 1; } else { if (f < connection->props.range.src_min) { connection->props.range.src_min = f; connection->props.range.known |= CONNECTION_RANGE_SRC_MIN; changed = 1; } if (f > connection->props.range.src_max) { connection->props.range.src_max = f; connection->props.range.known |= CONNECTION_RANGE_SRC_MAX; changed = 1; } } if (changed) { mapper_connection_set_linear_range(connection, sig, &connection->props.range); /* Stay in calibrate mode. */ connection->props.mode = MO_CALIBRATE; } if (connection->expr) *to_value = mapper_expr_evaluate(connection->expr, from_value); } return 1; }
int parse_and_eval(int expectation) { // clear output arrays int i; for (i = 0; i < DEST_ARRAY_LEN; i++) { dest_int[i] = 0; dest_float[i] = 0.0f; dest_double[i] = 0.0; } eprintf("***************** Expression %d *****************\n", expression_count++); eprintf("Parsing string '%s'\n", str); e = mapper_expr_new_from_string(str, num_sources, src_types, src_lengths, outh.type, outh.length); if (!e) { eprintf("Parser FAILED.\n"); goto fail; } for (i = 0; i < num_sources; i++) { inh[i].size = mapper_expr_input_history_size(e, i); } outh.size = mapper_expr_output_history_size(e); if (mapper_expr_num_variables(e) > MAX_VARS) { eprintf("Maximum variables exceeded.\n"); goto fail; } // reallocate variable value histories for (i = 0; i < e->num_variables; i++) { eprintf("user_var[%d]: %p\n", i, &user_vars[i]); mhist_realloc(&user_vars[i], e->variables[i].history_size, sizeof(double), 0); } user_vars_p = user_vars; #ifdef DEBUG if (verbose) { char str[128]; snprintf(str, 128, "Parser returned %d tokens:", e->length); printexpr(str, e); } #endif token_count += e->length; eprintf("Try evaluation once... "); if (!mapper_expr_evaluate(e, inh_p, &user_vars_p, &outh, &tt_in, typestring)) { eprintf("FAILED.\n"); goto fail; } eprintf("OK\n"); then = current_time(); eprintf("Calculate expression %i times... ", iterations); i = iterations-1; while (i--) { mapper_expr_evaluate(e, inh_p, &user_vars_p, &outh, &tt_in, typestring); } now = current_time(); eprintf("%g seconds.\n", now-then); total_elapsed_time += now-then; if (verbose) { printf("Got: "); print_value(typestring, outh.length, outh.value, outh.position); printf(" \n"); } else printf("."); mapper_expr_free(e); return expectation != EXPECT_SUCCESS; fail: return expectation != EXPECT_FAILURE; }
static void collapse_expr_to_left(exprnode* plhs, exprnode rhs, int constant_folding) { // track whether any variable references int refvar = 0; int is_float = 0; // find trailing operator on right hand side exprnode rhs_last = rhs; if (rhs->tok.type == TOK_VAR) refvar = 1; while (rhs_last->next) { if (rhs_last->tok.type == TOK_VAR) refvar = 1; rhs_last = rhs_last->next; } // find pointer to insertion place: // - could be a function that needs args, // - otherwise assume it's before the trailing operator exprnode *plhs_last = plhs; if ((*plhs_last)->tok.type == TOK_VAR) refvar = 1; while ((*plhs_last)->next) { if ((*plhs_last)->tok.type == TOK_VAR) refvar = 1; plhs_last = &(*plhs_last)->next; } // insert float coersion if sides disagree on type token_t coerce; coerce.type = TOK_TOFLOAT; is_float = (*plhs_last)->is_float || rhs_last->is_float; if ((*plhs_last)->is_float && !rhs_last->is_float) { rhs_last = rhs_last->next = exprnode_new(&coerce, 1); } else if (!(*plhs_last)->is_float && rhs_last->is_float) { exprnode e = exprnode_new(&coerce, 1); e->next = (*plhs_last); (*plhs_last) = e; plhs_last = &e->next; e->next->is_float = 1; } // insert the list before the trailing op of left hand side rhs_last->next = (*plhs_last); (*plhs_last) = rhs; // if there were no variable references, then expression is // constant, so evaluate it immediately if (constant_folding && !refvar) { struct _mapper_expr e; e.node = *plhs; mapper_signal_value_t v = mapper_expr_evaluate(&e, 0); exprnode_free((*plhs)->next); (*plhs)->next = 0; (*plhs)->is_float = is_float; if (is_float) { (*plhs)->tok.type = TOK_FLOAT; (*plhs)->tok.f = v.f; } else { (*plhs)->tok.type = TOK_INT; (*plhs)->tok.i = v.i32; } } }