00001
00002
00003
00004
00005
00006 #include "info.h"
00007 #include <string>
00008 #include <vector>
00009 #include <ctype.h>
00010 #include <string.h>
00011
00012 #include <xylib/xylib.h>
00013 #include <boost/version.hpp>
00014 #ifdef HAVE_LUALIB_H
00015 extern "C" {
00016 #include <lua.h>
00017 }
00018 #endif
00019
00020 #include "logic.h"
00021 #include "func.h"
00022 #include "tplate.h"
00023 #include "data.h"
00024 #include "fit.h"
00025 #include "ast.h"
00026 #include "model.h"
00027 #include "guess.h"
00028 #include "cparser.h"
00029 #include "eparser.h"
00030 #include "lexer.h"
00031 #include "ui.h"
00032 #include "runner.h"
00033
00034 using namespace std;
00035
00036 namespace {
00037
00038
00039 string& gnuplotize_formula(string& formula)
00040 {
00041 replace_all(formula, "^", "**");
00042 replace_words(formula, "ln", "log");
00043
00044 string::size_type pos = 0;
00045 while ((pos = formula.find('/', pos)) != string::npos) {
00046 ++pos;
00047 if (!isdigit(formula[pos]))
00048 continue;
00049 while (pos < formula.length() && isdigit(formula[pos]))
00050 ++pos;
00051 if (pos == formula.length())
00052 formula += ".";
00053 else if (pos != '.')
00054 formula.insert(pos, ".");
00055 }
00056 return formula;
00057 }
00058
00059 string info_compiler()
00060 {
00061 return
00062 "Build system type: "
00063 #ifdef CONFIGURE_BUILD
00064 CONFIGURE_BUILD
00065 #else
00066 "UNKNOWN"
00067 #endif
00068
00069 "\nConfigured with: "
00070 #ifdef CONFIGURE_ARGS
00071 CONFIGURE_ARGS
00072 #else
00073 "UNKNOWN"
00074 #endif
00075
00076 "\nCompiler: "
00077 #if defined(__GNUC__)
00078 "GCC"
00079 #elif defined(_MSC_VER)
00080 "MS VC++"
00081 #else
00082 "UNKNOWN"
00083 #endif
00084
00085 "\nCompiler version: "
00086 #ifdef __VERSION__
00087 __VERSION__
00088 #else
00089 "UNKNOWN"
00090 #endif
00091
00092 "\nCompilation date: " __DATE__
00093 "\nBoost version: " + S(BOOST_VERSION / 100000)
00094 + "." + S(BOOST_VERSION / 100 % 1000)
00095 + "." + S(BOOST_VERSION % 100)
00096 + "\nxylib version: " + xylib_get_version()
00097 #ifdef HAVE_LUALIB_H
00098 + "\n" LUA_RELEASE
00099 #endif
00100 ;
00101 }
00102
00103 string get_variable_info(const Ftk* F, const Variable* v)
00104 {
00105 string s = "$" + v->name + " = " + v->get_formula(F->parameters()) + " = "
00106 + F->settings_mgr()->format_double(v->get_value());
00107 const RealRange& d = v->domain;
00108 if (!d.from_inf() || !d.to_inf())
00109 s += " [" + (d.from_inf() ? S("") : S(d.from)) + " : "
00110 + (d.to_inf() ? S("") : S(d.to)) + "]";
00111 if (v->is_auto_delete())
00112 s += " [auto]";
00113 return s;
00114 }
00115
00116
00117 void info_functions(const Ftk* F, const string& name, string& result)
00118 {
00119 if (!contains_element(name, '*')) {
00120 const Function *f = F->find_function(name);
00121 result += f->get_basic_assignment();
00122 }
00123 else {
00124 v_foreach (Function*, i, F->functions())
00125 if (match_glob((*i)->name.c_str(), name.c_str()))
00126 result += (result.empty() ? "" : "\n")
00127 + (*i)->get_basic_assignment();
00128 }
00129 }
00130
00131 void info_variables(const Ftk* F, const string& name, string& result)
00132 {
00133 if (!contains_element(name, '*')) {
00134 const Variable* var = F->find_variable(name);
00135 result += get_variable_info(F, var);
00136 }
00137 else {
00138 v_foreach (Variable*, i, F->variables())
00139 if (match_glob((*i)->name.c_str(), name.c_str()))
00140 result += (result.empty() ? "" : "\n")
00141 + get_variable_info(F, *i);
00142 }
00143 }
00144
00145 void info_func_type(const Ftk* F, const string& functype, string& result)
00146 {
00147 const Tplate* tp = F->get_tpm()->get_tp(functype);
00148 if (tp == NULL)
00149 result += "undefined";
00150 else {
00151 result += tp->as_formula();
00152 if (!tp->op_trees.empty()) {
00153 vector<string> args = tp->fargs;
00154 args.push_back("x");
00155 result += "\n = " + tp->op_trees.back()->str(&args);
00156 }
00157 }
00158 }
00159
00160 string info_func_props(const Ftk* F, const string& name)
00161 {
00162 const Function* f = F->find_function(name);
00163 string s = f->tp()->as_formula();
00164 for (int i = 0; i < f->get_vars_count(); ++i) {
00165 Variable const* v = F->get_variable(f->get_var_idx(i));
00166 s += "\n" + f->get_param(i) + " = " + get_variable_info(F, v);
00167 }
00168 realt a;
00169 const vector<string>& fargs = f->tp()->fargs;;
00170 if (f->get_center(&a) && !contains_element(fargs, string("center")))
00171 s += "\nCenter: " + S(a);
00172 if (f->get_height(&a) && !contains_element(fargs, string("height")))
00173 s += "\nHeight: " + S(a);
00174 if (f->get_fwhm(&a) && !contains_element(fargs, string("fwhm")))
00175 s += "\nFWHM: " + S(a);
00176 if (f->get_area(&a) && !contains_element(fargs, string("area")))
00177 s += "\nArea: " + S(a);
00178 v_foreach (string, i, f->get_other_prop_names())
00179 s += "\n" + *i + ": " + S(f->get_other_prop(*i));
00180 return s;
00181 }
00182
00183
00184 void info_history(const Ftk* F, const Token& t1, const Token& t2,
00185 string& result)
00186 {
00187 const vector<UserInterface::Cmd>& cmds = F->get_ui()->cmds();
00188 int from = 0, to = cmds.size();
00189 if (t1.type == kTokenExpr) {
00190 from = iround(t1.value.d);
00191 if (from < 0)
00192 from += cmds.size();
00193 }
00194 if (t2.type == kTokenExpr) {
00195 to = iround(t2.value.d);
00196 if (to < 0)
00197 to += cmds.size();
00198 }
00199 if (from < 0 || to > (int) cmds.size())
00200 throw ExecuteError("wrong history range");
00201 for (int i = from; i < to; ++i)
00202 result += cmds[i].str() + "\n";
00203 }
00204
00205
00206 void info_guess(const Ftk* F, int ds, const RealRange& range, string& result)
00207 {
00208 if (range.from >= range.to)
00209 result += "invalid range";
00210 else {
00211 int lb = F->get_data(ds)->get_lower_bound_ac(range.from);
00212 int rb = F->get_data(ds)->get_upper_bound_ac(range.to);
00213 Guess g(F->get_settings());
00214 g.initialize(F->get_dm(ds), lb, rb, -1);
00215 boost::array<double,4> peak_v = g.estimate_peak_parameters();
00216 for (int i = 0; i != 4; ++i)
00217 result += (i != 0 ? ", " : "")
00218 + Guess::peak_traits[i] + ": " + S(peak_v[i]);
00219 result += "\n";
00220 boost::array<double,3> lin_v = g.estimate_linear_parameters();
00221 for (int i = 0; i != 3; ++i)
00222 result += (i != 0 ? ", " : "")
00223 + Guess::linear_traits[i] + ": " + S(lin_v[i]);
00224 }
00225 }
00226
00227 void save_models(const Ftk* F, string& r, bool commented_defines)
00228 {
00229 r += "# ------------ (un)defines ------------";
00230 TplateMgr default_tpm;
00231 default_tpm.add_builtin_types(F->get_ui()->parser());
00232 v_foreach (Tplate::Ptr, i, default_tpm.tpvec()) {
00233 const Tplate* t = F->get_tpm()->get_tp((*i)->name);
00234 if (t == NULL || t->as_formula() != (*i)->as_formula())
00235 r += "\nundefine " + (*i)->name;
00236 }
00237 v_foreach (Tplate::Ptr, i, F->get_tpm()->tpvec()) {
00238 string formula = (*i)->as_formula();
00239 const Tplate* t = default_tpm.get_tp((*i)->name);
00240 if (t == NULL || t->as_formula() != formula)
00241 r += "\ndefine " + formula;
00242 else if (commented_defines)
00243 r += "\n# define " + formula;
00244 }
00245 r += "\n\n# ------------ variables and functions ------------";
00246
00247
00248
00249 v_foreach (Variable*, i, F->variables())
00250 r += "\n$" + (*i)->name + " = " + (*i)->get_formula(F->parameters());
00251 r += "\n";
00252 v_foreach (Function*, i, F->functions())
00253 r +="\n" + (*i)->get_basic_assignment();
00254 r += "\n\n# ------------ models ------------";
00255 for (int i = 0; i != F->get_dm_count(); ++i) {
00256 const Model* model = F->get_model(i);
00257 const vector<string>& ff = model->get_ff().names;
00258 if (!ff.empty())
00259 r += "\n@" + S(i) + ": F = %" + join_vector(ff, " + %");
00260 vector<string> const& zz = model->get_zz().names;
00261 if (!zz.empty())
00262 r += "\n@" + S(i) + ": Z = %" + join_vector(zz, " + %");
00263 }
00264 }
00265
00266 void save_state(const Ftk* F, string& r)
00267 {
00268 if (!r.empty())
00269 r += "\n";
00270 r += fityk_version_line + S(". Created: ") + time_now();
00271 r += "\nset verbosity = -1 #the rest of the file is not shown";
00272 r += "\nset autoplot = 0";
00273 r += "\nreset";
00274 r += "\n# ------------ settings ------------";
00275
00276 vector<string> e = F->settings_mgr()->get_key_list("");
00277 v_foreach(string, i, e) {
00278 if (*i == "autoplot" || *i == "verbosity")
00279 continue;
00280 string v = F->settings_mgr()->get_as_string(*i);
00281 r += "\nset " + *i + " = " + (v.empty() ? "''" : v);
00282 }
00283 r += "\n";
00284 r += "\n# ------------ datasets ------------";
00285 for (int i = 0; i != F->get_dm_count(); ++i) {
00286 const Data* data = F->get_data(i);
00287 if (i != 0)
00288 r += "\n@+ = 0";
00289 r += "\nuse @" + S(i);
00290 r += "\ntitle = '" + data->get_title() + "'";
00291 int m = data->points().size();
00292 r += "\nM=" + S(m);
00293 r += "\nX=" + eS(data->get_x_max()) + "# =max(x), prevents sorting.";
00294 for (int j = 0; j != m; ++j) {
00295 const Point& p = data->points()[j];
00296 string idx = "[" + S(j) + "]=";
00297 r += "\nX" + idx + eS(p.x) +
00298 ", Y" + idx + eS(p.y) +
00299 ", S" + idx + eS(p.sigma) +
00300 ", A" + idx + (p.is_active ? "1" : "0");
00301 }
00302 r += "\n";
00303 }
00304 r += "\n\n";
00305 save_models(F, r, true);
00306 r += "\n";
00307 r += "\nplot " + F->view.str();
00308 r += "\nuse @" + S(F->default_dm());
00309 r += "\nset autoplot = " + F->settings_mgr()->get_as_string("autoplot");
00310 r += "\nset verbosity = " + F->settings_mgr()->get_as_string("verbosity");
00311 }
00312
00313 static
00314 string format_error_info(const Ftk* F, const vector<realt>& errors)
00315 {
00316 string s;
00317 const SettingsMgr *sm = F->settings_mgr();
00318 const vector<realt>& pp = F->parameters();
00319 assert(pp.size() == errors.size());
00320 const Fit* fit = F->get_fit();
00321 for (size_t i = 0; i != errors.size(); ++i) {
00322 if (fit->is_param_used(i)) {
00323 realt err = errors[i];
00324 s += "\n$" + F->find_variable_handling_param(i)->name
00325 + " = " + sm->format_double(pp[i])
00326 + " +- " + (err == 0. ? string("??") : sm->format_double(err));
00327 }
00328 }
00329 return s;
00330 }
00331
00332 int eval_one_info_arg(const Ftk* F, int ds, const vector<Token>& args, int n,
00333 string& result)
00334 {
00335 int ret = 0;
00336 if (args[n].type == kTokenLname) {
00337 const string word = args[n].as_string();
00338
00339
00340 if (word == "version")
00341 result += "Fityk " VERSION;
00342 else if (word == "compiler")
00343 result += info_compiler();
00344 else if (word == "variables")
00345 for (size_t i = 0; i < F->variables().size(); ++i)
00346 result += (i > 0 ? " $" : "$") + F->get_variable(i)->name;
00347 else if (word == "types")
00348 v_foreach (Tplate::Ptr, i, F->get_tpm()->tpvec())
00349 result += (*i)->name + " ";
00350 else if (word == "functions")
00351 for (size_t i = 0; i < F->functions().size(); ++i)
00352 result += (i > 0 ? " %" : "%") + F->get_function(i)->name;
00353 else if (word == "dataset_count")
00354 result += S(F->get_dm_count());
00355 else if (word == "view")
00356 result += F->view.str();
00357 else if (word == "fit_history")
00358 result += F->get_fit_container()->param_history_info();
00359 else if (word == "filename") {
00360 result += F->get_data(ds)->get_filename();
00361 }
00362 else if (word == "title") {
00363 result += F->get_data(ds)->get_title();
00364 }
00365 else if (word == "data") {
00366 result += F->get_data(ds)->get_info();
00367 }
00368 else if (word == "formula")
00369 result += F->get_model(ds)->get_formula(false);
00370 else if (word == "gnuplot_formula") {
00371 string formula = F->get_model(ds)->get_formula(false);
00372 result += gnuplotize_formula(formula);
00373 }
00374 else if (word == "simplified_formula")
00375 result += F->get_model(ds)->get_formula(true);
00376 else if (word == "simplified_gnuplot_formula") {
00377 string formula = F->get_model(ds)->get_formula(true);
00378 result += gnuplotize_formula(formula);
00379 }
00380 else if (word == "models") {
00381 save_models(F, result, false);
00382 }
00383 else if (word == "state") {
00384 save_state(F, result);
00385 }
00386 else if (word == "peaks") {
00387 vector<realt> no_errors;
00388 result += F->get_model(ds)->get_peak_parameters(no_errors);
00389 }
00390 else if (word == "peaks_err") {
00391
00392 DataAndModel* dm = const_cast<DataAndModel*>(F->get_dm(ds));
00393 vector<DataAndModel*> dms(1, dm);
00394 vector<realt> errors = F->get_fit()->get_standard_errors(dms);
00395 result += F->get_model(ds)->get_peak_parameters(errors);
00396 }
00397 else if (word == "history_summary")
00398 result += F->get_ui()->get_history_summary();
00399
00400 else if (word == "set") {
00401 if (args[n+1].type == kTokenLname) {
00402 string key = args[n+1].as_string();
00403 result += F->settings_mgr()->get_as_string(key) + "\ntype: "
00404 + F->settings_mgr()->get_type_desc(key);
00405 }
00406 else {
00407 result += "Available options:";
00408 vector<string> e = F->settings_mgr()->get_key_list("");
00409 v_foreach(string, i, e)
00410 result += "\n " + *i
00411 + " <" + F->settings_mgr()->get_type_desc(*i)
00412 + "> = " + F->settings_mgr()->get_as_string(*i);
00413 }
00414 ++ret;
00415 }
00416
00417
00418 else if (word == "history") {
00419 info_history(F, args[n+1], args[n+2], result);
00420 ret += 2;
00421 }
00422 else if (word == "guess") {
00423 RealRange range = args2range(args[n+1], args[n+2]);
00424 info_guess(F, ds, range, result);
00425 ret += 2;
00426 }
00427
00428
00429 else if (word == "fit" || word == "errors" || word == "cov" ||
00430 word == "confidence") {
00431 double level = 0.;
00432 if (word == "confidence") {
00433 level = args[n+1].value.d;
00434 if (level <= 0 || level >= 100)
00435 throw ExecuteError("confidence level outside of (0,100)");
00436 ++n;
00437 ++ret;
00438 }
00439 vector<DataAndModel*> v;
00440 while (args[n+1].type == kTokenDataset) {
00441 int k = args[n+1].value.i;
00442 DataAndModel* dm = const_cast<DataAndModel*>(F->get_dm(k));
00443 v.push_back(dm);
00444 ++n;
00445 ++ret;
00446 }
00447 assert(args[n+1].type == kTokenNop);
00448 ++ret;
00449 if (v.empty()) {
00450 DataAndModel* dm = const_cast<DataAndModel*>(F->get_dm(ds));
00451 v.push_back(dm);
00452 }
00453 if (word == "fit")
00454 result += F->get_fit()->get_goodness_info(v);
00455 else if (word == "errors") {
00456 result += "Standard errors:";
00457 vector<realt> errors = F->get_fit()->get_standard_errors(v);
00458 result += format_error_info(F, errors);
00459 }
00460 else if (word == "confidence") {
00461 result += S(level) + "% confidence intervals:";
00462 vector<realt> limits =
00463 F->get_fit()->get_confidence_limits(v, level);
00464 result += format_error_info(F, limits);
00465 }
00466 else
00467 result += F->get_fit()->get_cov_info(v);
00468 }
00469
00470
00471 else if (word == "refs") {
00472 string name = Lexer::get_string(args[n+1]);
00473 vector<string> refs = F->get_variable_references(name);
00474 result += join_vector(refs, ", ");
00475 ++ret;
00476 }
00477
00478
00479 else if (word == "prop") {
00480 string name = Lexer::get_string(args[n+1]);
00481 result += info_func_props(F, name);
00482 ++ret;
00483 }
00484 }
00485
00486
00487 else if (args[n].type == kTokenCname)
00488 info_func_type(F, args[n].as_string(), result);
00489
00490
00491 else if (args[n].type == kTokenFuncname)
00492 info_functions(F, Lexer::get_string(args[n]), result);
00493
00494
00495 else if (args[n].type == kTokenVarname)
00496 info_variables(F, Lexer::get_string(args[n]), result);
00497
00498
00499 else if ((args[n].type == kTokenUletter &&
00500 (*args[n].str == 'F' || *args[n].str == 'Z'))
00501 || args[n].type == kTokenDataset) {
00502 int k = ds;
00503 if (args[n].type == kTokenDataset) {
00504 k = args[n].value.i;
00505 ++n;
00506 ++ret;
00507 }
00508 const Model* model = F->get_model(k);
00509 char fz = *args[n].str;
00510 if (is_index(n+1, args) && args[n+1].type == kTokenExpr) {
00511 ++ret;
00512 int idx = iround(args[n+1].value.d);
00513 const string& name = model->get_func_name(fz, idx);
00514 const Function *f = F->find_function(name);
00515 result += f->get_basic_assignment();
00516 }
00517 else {
00518 const vector<string>& names = model->get_fz(fz).names;
00519 if (!names.empty())
00520 result += "%" + join_vector(names, " + %");
00521 }
00522 }
00523 ++ret;
00524 return ret;
00525 }
00526
00527 void eval_one_print_arg(const Ftk* F, int ds, const Token& t, string& result)
00528 {
00529 if (t.type == kTokenString)
00530 result += Lexer::get_string(t);
00531 else if (t.type == kTokenExpr)
00532 result += F->settings_mgr()->format_double(t.value.d);
00533 else if (t.as_string() == "filename")
00534 result += F->get_data(ds)->get_filename();
00535 else if (t.as_string() == "title")
00536 result += F->get_data(ds)->get_title();
00537 else
00538 assert(0);
00539 }
00540
00541 int eval_print_args(const Ftk* F, int ds, const vector<Token>& args, int len,
00542 string& result)
00543 {
00544
00545 string sep = " ";
00546 if (args[0].type == kTokenNop) {
00547 for (int n = 1; n < len; ++n) {
00548 if (n != 1)
00549 result += sep;
00550 eval_one_print_arg(F, ds, args[n], result);
00551 }
00552 }
00553 else {
00554 vector<ExpressionParser> expr_parsers(args.size() + 1, F);
00555 for (int i = 0; i < len; ++i)
00556 if (args[i].type == kTokenExpr) {
00557 Lexer lex(args[i].str);
00558 expr_parsers[i].parse_expr(lex, ds);
00559 }
00560 const vector<Point>& points = F->get_data(ds)->points();
00561 for (int k = 0; k != (int) points.size(); ++k) {
00562 if (args[0].type == kTokenExpr) {
00563 double cond = expr_parsers[0].calculate(k, points);
00564 if (fabs(cond) < 0.5)
00565 continue;
00566 }
00567 if (!result.empty())
00568 result += "\n";
00569 for (int n = 1; n < len; ++n) {
00570 if (n != 1)
00571 result += sep;
00572 if (args[n].type == kTokenExpr) {
00573 double value = expr_parsers[n].calculate(k, points);
00574 result += F->settings_mgr()->format_double(value);
00575 }
00576 else
00577 eval_one_print_arg(F, ds, args[n], result);
00578 }
00579 }
00580 }
00581 return len;
00582 }
00583
00584 }
00585
00586 int eval_info_args(const Ftk* F, int ds, const vector<Token>& args, int len,
00587 string& result)
00588 {
00589 int n = 0;
00590 while (n < len) {
00591 if (!result.empty())
00592 result += "\n";
00593 n += eval_one_info_arg(F, ds, args, n, result);
00594 }
00595 if (len == 0) {
00596 result += "Available arguments:\n";
00597 const char** arg = info_args;
00598 while (*arg != NULL) {
00599 result += *arg + S(" ");
00600 ++arg;
00601 }
00602 result += "%* $* AnyFunctionT";
00603 }
00604 return n;
00605 }
00606
00607 void command_redirectable(const Ftk* F, int ds,
00608 CommandType cmd, const vector<Token>& args)
00609 {
00610 string info;
00611 int len = args.size();
00612 bool redir = (len >= 2 && (args[len-2].type == kTokenGT ||
00613 args[len-2].type == kTokenAppend));
00614 int n_args = redir ? len - 2 : len;
00615 if (cmd == kCmdInfo)
00616 eval_info_args(F, ds, args, n_args, info);
00617 else
00618 eval_print_args(F, ds, args, n_args, info);
00619 if (!redir) {
00620 int max_screen_info_length = 2048;
00621 int more = (int) info.length() - max_screen_info_length;
00622 if (more > 0) {
00623 info.resize(max_screen_info_length);
00624 info += "\n[... " + S(more) + " characters more...]";
00625 }
00626 F->rmsg(info);
00627 }
00628 else {
00629 assert(args.back().type == kTokenFilename ||
00630 args.back().type == kTokenString);
00631 string filename = Lexer::get_string(args.back());
00632 const char* mode = args[len-2].type == kTokenGT ? "w" : "a";
00633 FILE *f = fopen(filename.c_str(), mode);
00634 if (!f)
00635 throw ExecuteError("Can't open file: " + filename);
00636 fprintf(f, "%s\n", info.c_str());
00637 fclose(f);
00638 }
00639 }
00640
00641 void command_debug(const Ftk* F, int ds, const Token& key, const Token& rest)
00642 {
00643
00644 string r;
00645 string word = key.as_string();
00646
00647 if (word == "parse") {
00648 Parser parser(const_cast<Ftk*>(F));
00649 try {
00650 Lexer lex(rest.str);
00651 while (parser.parse_statement(lex))
00652 r += parser.get_statements_repr();
00653 }
00654 catch (fityk::SyntaxError& e) {
00655 r += string("ERR: ") + e.what();
00656 }
00657 }
00658
00659 else if (word == "lex") {
00660 Lexer lex(rest.str);
00661 for (Token t = lex.get_token(); t.type != kTokenNop; t =lex.get_token())
00662 r += token2str(t) + "\n";
00663 }
00664
00665 else if (word == "expr") {
00666 Lexer lex(rest.str);
00667 try {
00668 ExpressionParser parser(F);
00669 parser.parse_expr(lex, -1);
00670 r += vm2str(parser.vm());
00671 }
00672 catch (fityk::SyntaxError& e) {
00673 r += "ERROR at " + S(lex.scanned_chars()) + ": " + e.what();
00674 }
00675 if (lex.peek_token().type != kTokenNop)
00676 r += "\nnext token: " + token2str(lex.peek_token());
00677 }
00678
00679 else if (word == "der") {
00680 get_derivatives_str(rest.str, r);
00681 }
00682
00683
00684 else if (word == "rd") {
00685 for (int i = 0; i < size(F->variables()); ++i) {
00686 Variable const* var = F->get_variable(i);
00687 r += "$" + var->name + ": ";
00688 v_foreach (Variable::ParMult, i, var->recursive_derivatives())
00689 r += "p" + S(i->p) + "=$"
00690 + F->find_variable_handling_param(i->p)->name
00691 + " *" + S(i->mult) + " ";
00692 r += "\n";
00693 }
00694 }
00695
00696
00697 else if (word == "idx") {
00698 for (size_t i = 0; i != F->functions().size(); ++i)
00699 r += S(i) + ": " + F->get_function(i)->get_debug_idx_info() + "\n";
00700 for (size_t i = 0; i != F->variables().size(); ++i)
00701 r += S(i) + ": " + F->get_variable(i)->get_debug_idx_info() + "\n";
00702 }
00703
00704
00705 else if (word == "df") {
00706 Lexer lex(rest.str);
00707 ExpressionParser ep(F);
00708 ep.parse_expr(lex, ds);
00709 realt x = ep.calculate();
00710 const Model* model = F->get_model(ds);
00711 vector<realt> symb = model->get_symbolic_derivatives(x);
00712 vector<realt> num = model->get_numeric_derivatives(x, 1e-4);
00713 assert (symb.size() == num.size());
00714 int n = symb.size() - 1;
00715 r += "F(" + S(x) + ")=" + S(model->value(x));
00716 for (int i = 0; i < n; ++i) {
00717 if (is_neq(symb[i], 0) || is_neq(num[i], 0))
00718 r += "\ndF / d$" + F->find_variable_handling_param(i)->name
00719 + " = (symb.) " + S(symb[i]) + " = (num.) " + S(num[i]);
00720 }
00721 r += "\ndF / dx = (symb.) " + S(symb[n]) + " = (num.) " + S(num[n]);
00722 }
00723
00724
00725 else if (key.type == kTokenFuncname) {
00726 const Function* f = F->find_function(Lexer::get_string(key));
00727 r += f->get_bytecode();
00728 }
00729
00730
00731 else if (key.type == kTokenVarname) {
00732 const Variable* v = F->find_variable(Lexer::get_string(key));
00733 vector<string> vn;
00734 v_foreach (string, i, v->get_varnames())
00735 vn.push_back("$" + *i);
00736 for (int i = 0; i < v->get_vars_count(); ++i) {
00737 string formula = v->get_op_trees()[i]->str(&vn);
00738 double value = v->get_derivative(i);
00739 if (i != 0)
00740 r += "\n";
00741 r += "d($" + v->name + ")/d($" + v->get_var_name(i) + "): "
00742 + formula + " == " + F->settings_mgr()->format_double(value);
00743 }
00744 }
00745
00746
00747 else if (word == "glob") {
00748 Lexer lex(rest.str);
00749 string pattern = lex.get_filename_token().as_string();
00750 Token t;
00751 while ((t = lex.get_filename_token()).type != kTokenNop) {
00752 string s = t.as_string();
00753 if (match_glob(s.c_str(), pattern.c_str()))
00754 r += s + " ";
00755 }
00756 }
00757
00758 else
00759 r += "unexpected arg: " + word;
00760 F->rmsg(r);
00761 }
00762
00763 void parse_and_eval_info(Ftk *F, const string& s, int dataset,
00764 string& result)
00765 {
00766 Lexer lex(s.c_str());
00767 Parser parser(F);
00768 vector<Token> args;
00769 parser.parse_info_args(lex, args);
00770 if (lex.peek_token().type != kTokenNop)
00771 lex.throw_syntax_error("unexpected argument");
00772 eval_info_args(F, dataset, args, args.size(), result);
00773 }
00774