pt-cbinop.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2008-2012 Jaroslav Hajek
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include "error.h"
00028 #include "oct-obj.h"
00029 #include "ov.h"
00030 #include "pt-cbinop.h"
00031 #include "pt-bp.h"
00032 #include "pt-unop.h"
00033 #include "pt-walk.h"
00034 
00035 // If a tree expression is a transpose or hermitian transpose, return
00036 // the argument and corresponding operator.
00037 
00038 static octave_value::unary_op
00039 strip_trans_herm (tree_expression *&exp)
00040 {
00041   if (exp->is_unary_expression ())
00042     {
00043       tree_unary_expression *uexp =
00044         dynamic_cast<tree_unary_expression *> (exp);
00045 
00046       octave_value::unary_op op = uexp->op_type ();
00047 
00048       if (op == octave_value::op_transpose
00049           || op == octave_value::op_hermitian)
00050         exp = uexp->operand ();
00051       else
00052         op = octave_value::unknown_unary_op;
00053 
00054       return op;
00055     }
00056   else
00057     return octave_value::unknown_unary_op;
00058 }
00059 
00060 static octave_value::unary_op
00061 strip_not (tree_expression *&exp)
00062 {
00063   if (exp->is_unary_expression ())
00064     {
00065       tree_unary_expression *uexp =
00066         dynamic_cast<tree_unary_expression *> (exp);
00067 
00068       octave_value::unary_op op = uexp->op_type ();
00069 
00070       if (op == octave_value::op_not)
00071         exp = uexp->operand ();
00072       else
00073         op = octave_value::unknown_unary_op;
00074 
00075       return op;
00076     }
00077   else
00078     return octave_value::unknown_unary_op;
00079 }
00080 
00081 // Possibly convert multiplication to trans_mul, mul_trans, herm_mul,
00082 // or mul_herm.
00083 
00084 static octave_value::compound_binary_op
00085 simplify_mul_op (tree_expression *&a, tree_expression *&b)
00086 {
00087   octave_value::compound_binary_op retop
00088     = octave_value::unknown_compound_binary_op;
00089 
00090   octave_value::unary_op opa = strip_trans_herm (a);
00091 
00092   if (opa == octave_value::op_hermitian)
00093     retop = octave_value::op_herm_mul;
00094   else if (opa == octave_value::op_transpose)
00095     retop = octave_value::op_trans_mul;
00096   else
00097     {
00098       octave_value::unary_op opb = strip_trans_herm (b);
00099 
00100       if (opb == octave_value::op_hermitian)
00101         retop = octave_value::op_mul_herm;
00102       else if (opb == octave_value::op_transpose)
00103         retop = octave_value::op_mul_trans;
00104     }
00105 
00106   return retop;
00107 }
00108 
00109 // Possibly convert left division to trans_ldiv or herm_ldiv.
00110 
00111 static octave_value::compound_binary_op
00112 simplify_ldiv_op (tree_expression *&a, tree_expression *&)
00113 {
00114   octave_value::compound_binary_op retop
00115     = octave_value::unknown_compound_binary_op;
00116 
00117   octave_value::unary_op opa = strip_trans_herm (a);
00118 
00119   if (opa == octave_value::op_hermitian)
00120     retop = octave_value::op_herm_ldiv;
00121   else if (opa == octave_value::op_transpose)
00122     retop = octave_value::op_trans_ldiv;
00123 
00124   return retop;
00125 }
00126 
00127 // Possibly contract and/or with negation.
00128 
00129 static octave_value::compound_binary_op
00130 simplify_and_or_op (tree_expression *&a, tree_expression *&b, octave_value::binary_op op)
00131 {
00132   octave_value::compound_binary_op retop
00133     = octave_value::unknown_compound_binary_op;
00134 
00135   octave_value::unary_op opa = strip_not (a);
00136 
00137   if (opa == octave_value::op_not)
00138     {
00139       if (op == octave_value::op_el_and)
00140         retop = octave_value::op_el_not_and;
00141       else if (op == octave_value::op_el_or)
00142         retop = octave_value::op_el_not_or;
00143     }
00144   else
00145     {
00146       octave_value::unary_op opb = strip_not (b);
00147 
00148       if (opb == octave_value::op_not)
00149         {
00150           if (op == octave_value::op_el_and)
00151             retop = octave_value::op_el_and_not;
00152           else if (op == octave_value::op_el_or)
00153             retop = octave_value::op_el_or_not;
00154         }
00155     }
00156 
00157   return retop;
00158 }
00159 
00160 tree_binary_expression *
00161 maybe_compound_binary_expression (tree_expression *a, tree_expression *b,
00162                                   int l, int c, octave_value::binary_op t)
00163 {
00164   tree_expression *ca = a, *cb = b;
00165   octave_value::compound_binary_op ct;
00166 
00167   switch (t)
00168     {
00169     case octave_value::op_mul:
00170       ct = simplify_mul_op (ca, cb);
00171       break;
00172 
00173     case octave_value::op_ldiv:
00174       ct = simplify_ldiv_op (ca, cb);
00175       break;
00176 
00177     case octave_value::op_el_and:
00178     case octave_value::op_el_or:
00179       ct = simplify_and_or_op (ca, cb, t);
00180       break;
00181 
00182     default:
00183       ct = octave_value::unknown_compound_binary_op;
00184       break;
00185     }
00186 
00187   tree_binary_expression *ret = (ct == octave_value::unknown_compound_binary_op)
00188     ? new tree_binary_expression (a, b, l, c, t)
00189     : new tree_compound_binary_expression (a, b, l, c, t, ca, cb, ct);
00190 
00191   return ret;
00192 }
00193 
00194 octave_value
00195 tree_compound_binary_expression::rvalue1 (int)
00196 {
00197   octave_value retval;
00198 
00199   if (error_state)
00200     return retval;
00201 
00202   if (op_lhs)
00203     {
00204       octave_value a = op_lhs->rvalue1 ();
00205 
00206       if (! error_state && a.is_defined () && op_rhs)
00207         {
00208           octave_value b = op_rhs->rvalue1 ();
00209 
00210           if (! error_state && b.is_defined ())
00211             {
00212               retval = ::do_binary_op (etype, a, b);
00213 
00214               if (error_state)
00215                 retval = octave_value ();
00216             }
00217         }
00218     }
00219 
00220   return retval;
00221 }
00222 
00223 
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines