00001
00002
00003
00004 #include "var.h"
00005 #include "common.h"
00006 #include "ast.h"
00007
00008 #include <stdlib.h>
00009 #include <algorithm>
00010 #include <memory>
00011
00012 using namespace std;
00013
00014
00015 bool VariableUser::is_dependent_on(int idx,
00016 vector<Variable*> const &variables) const
00017 {
00018 v_foreach (int, i, var_idx)
00019 if (*i == idx || variables[*i]->is_dependent_on(idx, variables))
00020 return true;
00021 return false;
00022 }
00023
00024 void VariableUser::set_var_idx(vector<Variable*> const &variables)
00025 {
00026 const int n = varnames.size();
00027 var_idx.resize(n);
00028 for (int v = 0; v < n; ++v) {
00029 bool found = false;
00030 for (int i = 0; i < size(variables); ++i) {
00031 if (varnames[v] == variables[i]->name) {
00032 var_idx[v] = i;
00033 found = true;
00034 break;
00035 }
00036 }
00037 if (!found)
00038 throw ExecuteError("Undefined variable: $" + varnames[v]);
00039 }
00040 }
00041
00042 int VariableUser::get_max_var_idx()
00043 {
00044 if (var_idx.empty())
00045 return -1;
00046 else
00047 return *max_element(var_idx.begin(), var_idx.end());
00048 }
00049
00050 std::string VariableUser::get_debug_idx_info() const
00051 {
00052 string r = prefix + name + ": ";
00053 assert(varnames.size() == var_idx.size());
00054 for (size_t i = 0; i != varnames.size(); ++i)
00055 r += varnames[i] + "/" + S(var_idx[i]) + " ";
00056 return r;
00057 }
00058
00059
00060
00061
00062 Variable::Variable(string const &name, int nr)
00063 : VariableUser(name, "$"),
00064 nr_(nr), original_(NULL)
00065 {
00066 assert(!name.empty());
00067 if (nr_ != -2) {
00068 ParMult pm;
00069 pm.p = nr_;
00070 pm.mult = 1;
00071 recursive_derivatives_.push_back(pm);
00072 }
00073 }
00074
00075
00076 Variable::Variable(string const &name, vector<string> const &vars,
00077 vector<OpTree*> const &op_trees)
00078 : VariableUser(name, "$", vars),
00079 nr_(-1), derivatives_(vars.size()), op_trees_(op_trees), original_(NULL)
00080 {
00081 assert(!name.empty());
00082 }
00083
00084 Variable::~Variable()
00085 {
00086 purge_all_elements(op_trees_);
00087 }
00088
00089 void Variable::set_var_idx(vector<Variable*> const& variables)
00090 {
00091 VariableUser::set_var_idx(variables);
00092 if (nr_ == -1) {
00093
00094 assert(var_idx.size() + 1 == op_trees_.size());
00095 vm_.clear_data();
00096 int n = op_trees_.size() - 1;
00097 for (int i = 0; i < n; ++i) {
00098 add_bytecode_from_tree(op_trees_[i], var_idx, vm_);
00099 vm_.append_code(OP_PUT_DERIV);
00100 vm_.append_code(i);
00101 }
00102 add_bytecode_from_tree(op_trees_.back(), var_idx, vm_);
00103
00104 }
00105 }
00106
00107 string Variable::get_formula(vector<realt> const ¶meters) const
00108 {
00109 assert(nr_ >= -1);
00110 vector<string> vn;
00111 v_foreach (string, i, varnames)
00112 vn.push_back("$" + *i);
00113 return nr_ == -1 ? get_op_trees().back()->str(&vn)
00114 : "~" + eS(parameters[nr_]);
00115 }
00116
00117 void Variable::recalculate(vector<Variable*> const &variables,
00118 vector<realt> const ¶meters)
00119 {
00120 if (nr_ >= 0) {
00121 assert (nr_ < (int) parameters.size());
00122 value_ = parameters[nr_];
00123 assert(derivatives_.empty());
00124 }
00125 else if (nr_ == -1) {
00126 value_ = run_code_for_variable(vm_, variables, derivatives_);
00127 recursive_derivatives_.clear();
00128 for (int i = 0; i < size(derivatives_); ++i) {
00129 Variable *v = variables[var_idx[i]];
00130 v_foreach (ParMult, j, v->recursive_derivatives()) {
00131 recursive_derivatives_.push_back(*j);
00132 recursive_derivatives_.back().mult *= derivatives_[i];
00133 }
00134 }
00135 }
00136 else if (nr_ == -2) {
00137 if (original_) {
00138 value_ = original_->value_;
00139 recursive_derivatives_ = original_->recursive_derivatives_;
00140 }
00141 }
00142 else
00143 assert(0);
00144 }
00145
00146 void Variable::erased_parameter(int k)
00147 {
00148 if (nr_ != -1 && nr_ > k)
00149 --nr_;
00150 for (vector<ParMult>::iterator i = recursive_derivatives_.begin();
00151 i != recursive_derivatives_.end(); ++i)
00152 if (i->p > k)
00153 -- i->p;
00154 }
00155
00156 bool Variable::is_constant() const
00157 {
00158 return nr_ == -1 && op_trees_.back()->op == 0;
00159 }
00160