bool matrix_3x3_square_to_quad(const float dx0, const float dy0, const float dx1, const float dy1, const float dx3, const float dy3, const float dx2, const float dy2, math_matrix_3x3 *mat) { float ax = dx0 - dx1 + dx2 - dx3; float ay = dy0 - dy1 + dy2 - dy3; if (float_is_zero(ax) && float_is_zero(ay)) { /* affine case */ matrix_3x3_inits(mat, dx1 - dx0, dy1 - dy0, 0, dx2 - dx1, dy2 - dy1, 0, dx0, dy0, 1); } else { float a, b, c, d, e, f, g, h; float ax1 = dx1 - dx2; float ax2 = dx3 - dx2; float ay1 = dy1 - dy2; float ay2 = dy3 - dy2; /* determinants */ float gtop = ax * ay2 - ax2 * ay; float htop = ax1 * ay - ax * ay1; float bottom = ax1 * ay2 - ax2 * ay1; if (!bottom) return false; g = gtop / bottom; h = htop / bottom; a = dx1 - dx0 + g * dx1; b = dx3 - dx0 + h * dx3; c = dx0; d = dy1 - dy0 + g * dy1; e = dy3 - dy0 + h * dy3; f = dy0; matrix_3x3_inits(mat, a, d, g, b, e, h, c, f, 1.f); } return true; }
bool matrix_3x3_invert(math_matrix_3x3 *mat) { float det = matrix_3x3_determinant(mat); if (float_is_zero(det)) return false; matrix_3x3_adjoint(mat); matrix_3x3_divide_scalar(mat, det); return true; }
node_t* node_optimize2(node_t*n, bool*again) { int t,num; switch(node_get_opcode(n)) { case opcode_node_block: for(t=0;t<n->num_children;t++) { if(n->child[t]->type == &node_nop) { node_remove_child(n, t--); } } break; case opcode_node_in: /* convert a in [x] to a == x */ if(node_is_array(n->child[1]) && n->child[1]->value.a->size == 1) { node_t*new_node = node_new(&node_equals, n->parent); node_t*constant = node_new_with_args(&node_constant, n->child[1]->value.a->entries[0]); node_append_child(new_node, n->child[0]); node_append_child(new_node, constant); node_destroy_self(n); return new_node; } break; case opcode_node_mul: /* convert a * 1.0 or 1.0 * a to a */ if(n->child[1]->type == &node_float && float_is_one(n->child[1]->value.f)) { node_t*new_node = n->child[0]; node_destroy(n->child[1]); node_destroy_self(n); return new_node; } if(n->child[0]->type == &node_float && float_is_one(n->child[0]->value.f)) { node_t*new_node = n->child[1]; node_destroy(n->child[0]); node_destroy_self(n); return new_node; } /* convert a * 0.0 or 0.0 * a to 0.0 */ if(n->child[0]->type == &node_float && float_is_zero(n->child[0]->value.f)) { node_t*new_node = n->child[0]; node_destroy(n->child[1]); node_destroy_self(n); return new_node; } if(n->child[1]->type == &node_float && float_is_zero(n->child[1]->value.f)) { node_t*new_node = n->child[1]; node_destroy(n->child[0]); node_destroy_self(n); return new_node; } break; case opcode_node_sub: /* convert a - 0.0 to a */ if(n->child[1]->type == &node_float && float_is_zero(n->child[1]->value.f)) { node_t*new_node = n->child[0]; node_destroy_self(n); return new_node; } break; case opcode_node_div: /* convert a / 1.0 to a */ if(n->child[1]->type == &node_float && float_is_one(n->child[1]->value.f)) { node_t*new_node = n->child[0]; node_destroy_self(n); return new_node; } break; case opcode_node_add: /* convert a + 0.0 to a */ num = 0; for(t=0;t<n->num_children;t++) { node_set_child(n, num, n->child[t]); if(n->child[t]->type != &node_float || !float_is_zero(n->child[t]->value.f)) { num++; } } if(!num) { node_set_child(n, num++, node_new_with_args(&node_float, 0.0)); } n->num_children = num; if(num==1) { node_t*new_node = n->child[0]; node_destroy_self(n); return new_node; } break; case opcode_node_if: /* convert if c then a else a to a */ if(node_equals_node(n->child[1], n->child[2])) { node_t*new_node = n->child[1]; node_destroy_self(n); return new_node; } break; case opcode_node_setlocal: /* convert setlocal i getlocal i to nop */ if(n->child[0]->type == &node_getlocal) { if(n->child[0]->value.i == n->value.i) { node_t*new_node = node_new(&node_nop, n->parent); node_destroy(n); *again = true; return new_node; } } break; } for(t=0;t<n->num_children;t++) { node_set_child(n, t, node_optimize2(n->child[t], again)); } return n; }