1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5 Date started: 8/25/2004
6 Purpose: Stores various parameter types for functions
8 ------------- Copyright (C) 2004 Jon S. Berndt (jsb@hal-pc.org) -------------
10 This program is free software; you can redistribute it and/or modify it under
11 the terms of the GNU Lesser General Public License as published by the Free Software
12 Foundation; either version 2 of the License, or (at your option) any later
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
20 You should have received a copy of the GNU Lesser General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22 Place - Suite 330, Boston, MA 02111-1307, USA.
24 Further information about the GNU Lesser General Public License can also be found on
25 the world wide web at http://www.gnu.org.
27 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
33 #include "FGFunction.h"
35 #include "FGPropertyValue.h"
36 #include "FGRealValue.h"
40 static const char *IdSrc = "$Id$";
41 static const char *IdHdr = ID_FUNCTION;
43 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
45 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
47 FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, string prefix)
48 : PropertyManager(propMan), Prefix(prefix)
52 string operation, property_name;
53 int size = el->GetNumElements();
55 cachedValue = -HUGE_VAL;
57 Name = el->GetAttributeValue("name");
58 operation = el->GetName();
60 if (operation == string("function")) {
62 } else if (operation == string("product")) {
64 } else if (operation == string("difference")) {
66 } else if (operation == string("sum")) {
68 } else if (operation == string("quotient")) {
70 } else if (operation == string("pow")) {
72 } else if (operation == string("abs")) {
74 } else if (operation == string("sin")) {
76 } else if (operation == string("exp")) {
78 } else if (operation == string("cos")) {
80 } else if (operation == string("tan")) {
82 } else if (operation == string("asin")) {
84 } else if (operation == string("acos")) {
86 } else if (operation == string("atan")) {
88 } else if (operation == string("atan2")) {
90 } else if (operation != string("description")) {
91 cerr << "Bad operation " << operation << " detected in configuration file" << endl;
94 element = el->GetElement();
96 operation = element->GetName();
99 if (operation == string("property")) {
100 property_name = element->GetDataLine();
101 FGPropertyManager* newNode = PropertyManager->GetNode(property_name);
103 cerr << "The property " << property_name << " is undefined." << endl;
106 Parameters.push_back(new FGPropertyValue( newNode ));
108 } else if (operation == string("value")) {
109 Parameters.push_back(new FGRealValue(element->GetDataAsNumber()));
110 } else if (operation == string("table")) {
111 Parameters.push_back(new FGTable(PropertyManager, element));
113 } else if (operation == string("product") ||
114 operation == string("difference") ||
115 operation == string("sum") ||
116 operation == string("quotient") ||
117 operation == string("pow") ||
118 operation == string("exp") ||
119 operation == string("abs") ||
120 operation == string("sin") ||
121 operation == string("cos") ||
122 operation == string("tan") ||
123 operation == string("asin") ||
124 operation == string("acos") ||
125 operation == string("atan") ||
126 operation == string("atan2"))
128 Parameters.push_back(new FGFunction(PropertyManager, element));
129 } else if (operation != string("description")) {
130 cerr << "Bad operation " << operation << " detected in configuration file" << endl;
132 element = el->GetNextElement();
135 bind(); // Allow any function to save its value
140 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142 FGFunction::~FGFunction(void)
145 string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
146 PropertyManager->Untie(tmp);
149 for (int i=0; i<Parameters.size(); i++) {
150 delete Parameters[i];
154 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
156 void FGFunction::cacheValue(bool cache)
158 cached = false; // Must set cached to false prior to calling GetValue(), else
159 // it will _never_ calculate the value;
161 cachedValue = GetValue();
166 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
168 double FGFunction::GetValue(void) const
172 if (cached) return cachedValue;
174 double temp = Parameters[0]->GetValue();
180 for (i=1;i<Parameters.size();i++) temp *= Parameters[i]->GetValue();
183 for (i=1;i<Parameters.size();i++) temp -= Parameters[i]->GetValue();
186 for (i=1;i<Parameters.size();i++) temp += Parameters[i]->GetValue();
189 temp /= Parameters[1]->GetValue();
192 temp = pow(temp,Parameters[1]->GetValue());
219 temp = atan2(temp, Parameters[1]->GetValue());
222 cerr << "Unknown function operation type" << endl;
229 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
231 string FGFunction::GetValueAsString(void) const
236 sprintf(buffer,"%9.6f",GetValue());
237 value = string(buffer);
241 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
243 void FGFunction::bind(void)
245 if ( !Name.empty() ) {
246 string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
247 PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
251 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252 // The bitmasked value choices are as follows:
253 // unset: In this case (the default) JSBSim would only print
254 // out the normally expected messages, essentially echoing
255 // the config files as they are read. If the environment
256 // variable is not set, debug_lvl is set to 1 internally
257 // 0: This requests JSBSim not to output any messages
259 // 1: This value explicity requests the normal JSBSim
261 // 2: This value asks for a message to be printed out when
262 // a class is instantiated
263 // 4: When this value is set, a message is displayed when a
264 // FGModel object executes its Run() method
265 // 8: When this value is set, various runtime state variables
266 // are printed out periodically
267 // 16: When set various parameters are sanity checked and
268 // a message is printed out when they go out of bounds
270 void FGFunction::Debug(int from)
272 if (debug_lvl <= 0) return;
274 if (debug_lvl & 1) { // Standard console startup message output
275 if (from == 0) { // Constructor
276 if (Type == eTopLevel)
277 cout << " Function: " << Name << endl;
280 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
281 if (from == 0) cout << "Instantiated: FGFunction" << endl;
282 if (from == 1) cout << "Destroyed: FGFunction" << endl;
284 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
286 if (debug_lvl & 8 ) { // Runtime state variables
288 if (debug_lvl & 16) { // Sanity checking
290 if (debug_lvl & 64) {
291 if (from == 0) { // Constructor
292 cout << IdSrc << endl;
293 cout << IdHdr << endl;