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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pt-cbinop.cc	Wed May 07 16:33:15 2008 +0200
@@ -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;
+}
+
+