Mercurial > hg > octave-nkf
diff src/pt-cbinop.cc @ 7800:5861b95e9879
support for compound operators, implement trans_mul, mul_trans, herm_mul and mul_herm
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Wed, 07 May 2008 16:33:15 +0200 |
parents | |
children | 3100283874d7 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/src/pt-cbinop.cc @@ -0,0 +1,158 @@ +/* + +Copyright (C) 2008 Jaroslav Hajek + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +<http://www.gnu.org/licenses/>. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "error.h" +#include "oct-obj.h" +#include "ov.h" +#include "pt-cbinop.h" +#include "pt-bp.h" +#include "pt-unop.h" +#include "pt-walk.h" + +// If a tree expression is a transpose or hermitian transpose, return +// the argument and corresponding operator. + +static octave_value::unary_op +strip_trans_herm (tree_expression *&exp) +{ + if (exp->is_unary_expression ()) + { + tree_unary_expression *uexp = + dynamic_cast<tree_unary_expression *> (exp); + + octave_value::unary_op op = uexp->op_type (); + + if (op == octave_value::op_transpose + || op == octave_value::op_hermitian) + exp = uexp->operand (); + else + op = octave_value::unknown_unary_op; + + return op; + } + else + return octave_value::unknown_unary_op; +} + +// Possibly convert multiplication to trans_mul, mul_trans, herm_mul, +// or mul_herm. + +static octave_value::compound_binary_op +simplify_mul_op (tree_expression *&a, tree_expression *&b) +{ + octave_value::compound_binary_op retop; + octave_value::unary_op opa = strip_trans_herm (a); + + if (opa == octave_value::op_hermitian) + retop = octave_value::op_herm_mul; + else if (opa == octave_value::op_transpose) + retop = octave_value::op_trans_mul; + else + { + octave_value::unary_op opb = strip_trans_herm (b); + + if (opb == octave_value::op_hermitian) + retop = octave_value::op_mul_herm; + else if (opb == octave_value::op_transpose) + retop = octave_value::op_mul_trans; + else + retop = octave_value::unknown_compound_binary_op; + } + + return retop; +} + +tree_binary_expression * +maybe_compound_binary_expression (tree_expression *a, tree_expression *b, + int l, int c, octave_value::binary_op t) +{ + tree_expression *ca = a, *cb = b; + octave_value::compound_binary_op ct; + + switch (t) + { + case octave_value::op_mul: + ct = simplify_mul_op (ca, cb); + break; + + default: + ct = octave_value::unknown_compound_binary_op; + break; + } + + tree_binary_expression *ret = (ct == octave_value::unknown_compound_binary_op) + ? new tree_binary_expression (a, b, l, c, t) + : new tree_compound_binary_expression (a, b, l, c, t, ca, cb, ct); + + return ret; +} + + +octave_value +tree_compound_binary_expression::rvalue (void) +{ + octave_value retval; + + MAYBE_DO_BREAKPOINT; + + if (error_state) + return retval; + + if (op_lhs) + { + octave_value a = op_lhs->rvalue (); + + if (error_state) + eval_error (); + else if (a.is_defined () && op_rhs) + { + octave_value b = op_rhs->rvalue (); + + if (error_state) + eval_error (); + else if (b.is_defined ()) + { + retval = ::do_binary_op (etype, a, b); + + if (error_state) + { + retval = octave_value (); + eval_error (); + } + } + else + eval_error (); + } + else + eval_error (); + } + else + eval_error (); + + return retval; +} + +