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 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
34 #include "FGFunction.h"
36 #include "FGPropertyValue.h"
37 #include "FGRealValue.h"
41 static const char *IdSrc = "$Id$";
42 static const char *IdHdr = ID_FUNCTION;
47 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
49 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
51 FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, string prefix)
52 : PropertyManager(propMan), Prefix(prefix)
55 string operation, property_name;
56 int size = el->GetNumElements();
58 cachedValue = -HUGE_VAL;
60 Name = el->GetAttributeValue("name");
61 operation = el->GetName();
63 if (operation == string("function")) {
65 } else if (operation == string("product")) {
67 } else if (operation == string("difference")) {
69 } else if (operation == string("sum")) {
71 } else if (operation == string("quotient")) {
73 } else if (operation == string("pow")) {
75 } else if (operation == string("abs")) {
77 } else if (operation == string("sin")) {
79 } else if (operation == string("exp")) {
81 } else if (operation == string("cos")) {
83 } else if (operation == string("tan")) {
85 } else if (operation == string("asin")) {
87 } else if (operation == string("acos")) {
89 } else if (operation == string("atan")) {
91 } else if (operation == string("atan2")) {
93 } else if (operation != string("description")) {
94 cerr << "Bad operation " << operation << " detected in configuration file" << endl;
97 element = el->GetElement();
99 cerr << fgred << highint << endl;
100 cerr << " No element was specified as an argument to the \"" << operation << "\" operation" << endl;
101 cerr << " This can happen when, for instance, a cos operation is specified and a " << endl;
102 cerr << " property name is given explicitly, but is not placed within a" << endl;
103 cerr << " <property></property> element tag pair." << endl;
109 operation = element->GetName();
112 if (operation == string("property")) {
113 property_name = element->GetDataLine();
114 FGPropertyManager* newNode = PropertyManager->GetNode(property_name);
116 cerr << "The property " << property_name << " is undefined." << endl;
119 Parameters.push_back(new FGPropertyValue( newNode ));
121 } else if (operation == string("value")) {
122 Parameters.push_back(new FGRealValue(element->GetDataAsNumber()));
123 } else if (operation == string("table")) {
124 Parameters.push_back(new FGTable(PropertyManager, element));
126 } else if (operation == string("product") ||
127 operation == string("difference") ||
128 operation == string("sum") ||
129 operation == string("quotient") ||
130 operation == string("pow") ||
131 operation == string("exp") ||
132 operation == string("abs") ||
133 operation == string("sin") ||
134 operation == string("cos") ||
135 operation == string("tan") ||
136 operation == string("asin") ||
137 operation == string("acos") ||
138 operation == string("atan") ||
139 operation == string("atan2"))
141 Parameters.push_back(new FGFunction(PropertyManager, element));
142 } else if (operation != string("description")) {
143 cerr << "Bad operation " << operation << " detected in configuration file" << endl;
145 element = el->GetNextElement();
148 bind(); // Allow any function to save its value
153 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
155 FGFunction::~FGFunction(void)
158 string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
159 PropertyManager->Untie(tmp);
162 for (unsigned int i=0; i<Parameters.size(); i++) {
163 delete Parameters[i];
167 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
169 void FGFunction::cacheValue(bool cache)
171 cached = false; // Must set cached to false prior to calling GetValue(), else
172 // it will _never_ calculate the value;
174 cachedValue = GetValue();
179 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
181 double FGFunction::GetValue(void) const
185 if (cached) return cachedValue;
187 double temp = Parameters[0]->GetValue();
193 for (i=1;i<Parameters.size();i++) {
194 temp *= Parameters[i]->GetValue();
198 for (i=1;i<Parameters.size();i++) {
199 temp -= Parameters[i]->GetValue();
203 for (i=1;i<Parameters.size();i++) {
204 temp += Parameters[i]->GetValue();
208 temp /= Parameters[1]->GetValue();
211 temp = pow(temp,Parameters[1]->GetValue());
238 temp = atan2(temp, Parameters[1]->GetValue());
241 cerr << "Unknown function operation type" << endl;
248 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250 string FGFunction::GetValueAsString(void) const
255 sprintf(buffer,"%9.6f",GetValue());
256 value = string(buffer);
260 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
262 void FGFunction::bind(void)
264 if ( !Name.empty() ) {
265 string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
266 PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
270 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271 // The bitmasked value choices are as follows:
272 // unset: In this case (the default) JSBSim would only print
273 // out the normally expected messages, essentially echoing
274 // the config files as they are read. If the environment
275 // variable is not set, debug_lvl is set to 1 internally
276 // 0: This requests JSBSim not to output any messages
278 // 1: This value explicity requests the normal JSBSim
280 // 2: This value asks for a message to be printed out when
281 // a class is instantiated
282 // 4: When this value is set, a message is displayed when a
283 // FGModel object executes its Run() method
284 // 8: When this value is set, various runtime state variables
285 // are printed out periodically
286 // 16: When set various parameters are sanity checked and
287 // a message is printed out when they go out of bounds
289 void FGFunction::Debug(int from)
291 if (debug_lvl <= 0) return;
293 if (debug_lvl & 1) { // Standard console startup message output
294 if (from == 0) { // Constructor
295 if (Type == eTopLevel)
296 cout << " Function: " << Name << endl;
299 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
300 if (from == 0) cout << "Instantiated: FGFunction" << endl;
301 if (from == 1) cout << "Destroyed: FGFunction" << endl;
303 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
305 if (debug_lvl & 8 ) { // Runtime state variables
307 if (debug_lvl & 16) { // Sanity checking
309 if (debug_lvl & 64) {
310 if (from == 0) { // Constructor
311 cout << IdSrc << endl;
312 cout << IdHdr << endl;