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)
51 string operation, property_name;
52 int size = el->GetNumElements();
54 cachedValue = -HUGE_VAL;
56 Name = el->GetAttributeValue("name");
57 operation = el->GetName();
59 if (operation == string("function")) {
61 } else if (operation == string("product")) {
63 } else if (operation == string("difference")) {
65 } else if (operation == string("sum")) {
67 } else if (operation == string("quotient")) {
69 } else if (operation == string("pow")) {
71 } else if (operation == string("abs")) {
73 } else if (operation == string("sin")) {
75 } else if (operation == string("exp")) {
77 } else if (operation == string("cos")) {
79 } else if (operation == string("tan")) {
81 } else if (operation == string("asin")) {
83 } else if (operation == string("acos")) {
85 } else if (operation == string("atan")) {
87 } else if (operation == string("atan2")) {
89 } else if (operation != string("description")) {
90 cerr << "Bad operation " << operation << " detected in configuration file" << endl;
93 element = el->GetElement();
95 cerr << fgred << highint << endl;
96 cerr << " No element was specified as an argument to the \"" << operation << "\" operation" << endl;
97 cerr << " This can happen when, for instance, a cos operation is specified and a " << endl;
98 cerr << " property name is given explicitly, but is not placed within a" << endl;
99 cerr << " <property></property> element tag pair." << endl;
105 operation = element->GetName();
108 if (operation == string("property")) {
109 property_name = element->GetDataLine();
110 FGPropertyManager* newNode = PropertyManager->GetNode(property_name);
112 cerr << "The property " << property_name << " is undefined." << endl;
115 Parameters.push_back(new FGPropertyValue( newNode ));
117 } else if (operation == string("value")) {
118 Parameters.push_back(new FGRealValue(element->GetDataAsNumber()));
119 } else if (operation == string("table")) {
120 Parameters.push_back(new FGTable(PropertyManager, element));
122 } else if (operation == string("product") ||
123 operation == string("difference") ||
124 operation == string("sum") ||
125 operation == string("quotient") ||
126 operation == string("pow") ||
127 operation == string("exp") ||
128 operation == string("abs") ||
129 operation == string("sin") ||
130 operation == string("cos") ||
131 operation == string("tan") ||
132 operation == string("asin") ||
133 operation == string("acos") ||
134 operation == string("atan") ||
135 operation == string("atan2"))
137 Parameters.push_back(new FGFunction(PropertyManager, element));
138 } else if (operation != string("description")) {
139 cerr << "Bad operation " << operation << " detected in configuration file" << endl;
141 element = el->GetNextElement();
144 bind(); // Allow any function to save its value
149 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
151 FGFunction::~FGFunction(void)
154 string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
155 PropertyManager->Untie(tmp);
158 for (unsigned int i=0; i<Parameters.size(); i++) {
159 delete Parameters[i];
163 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
165 void FGFunction::cacheValue(bool cache)
167 cached = false; // Must set cached to false prior to calling GetValue(), else
168 // it will _never_ calculate the value;
170 cachedValue = GetValue();
175 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
177 double FGFunction::GetValue(void) const
181 if (cached) return cachedValue;
183 double temp = Parameters[0]->GetValue();
189 for (i=1;i<Parameters.size();i++) {
190 temp *= Parameters[i]->GetValue();
194 for (i=1;i<Parameters.size();i++) {
195 temp -= Parameters[i]->GetValue();
199 for (i=1;i<Parameters.size();i++) {
200 temp += Parameters[i]->GetValue();
204 temp /= Parameters[1]->GetValue();
207 temp = pow(temp,Parameters[1]->GetValue());
234 temp = atan2(temp, Parameters[1]->GetValue());
237 cerr << "Unknown function operation type" << endl;
244 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246 string FGFunction::GetValueAsString(void) const
251 sprintf(buffer,"%9.6f",GetValue());
252 value = string(buffer);
256 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
258 void FGFunction::bind(void)
260 if ( !Name.empty() ) {
261 string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
262 PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
266 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
267 // The bitmasked value choices are as follows:
268 // unset: In this case (the default) JSBSim would only print
269 // out the normally expected messages, essentially echoing
270 // the config files as they are read. If the environment
271 // variable is not set, debug_lvl is set to 1 internally
272 // 0: This requests JSBSim not to output any messages
274 // 1: This value explicity requests the normal JSBSim
276 // 2: This value asks for a message to be printed out when
277 // a class is instantiated
278 // 4: When this value is set, a message is displayed when a
279 // FGModel object executes its Run() method
280 // 8: When this value is set, various runtime state variables
281 // are printed out periodically
282 // 16: When set various parameters are sanity checked and
283 // a message is printed out when they go out of bounds
285 void FGFunction::Debug(int from)
287 if (debug_lvl <= 0) return;
289 if (debug_lvl & 1) { // Standard console startup message output
290 if (from == 0) { // Constructor
291 if (Type == eTopLevel)
292 cout << " Function: " << Name << endl;
295 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
296 if (from == 0) cout << "Instantiated: FGFunction" << endl;
297 if (from == 1) cout << "Destroyed: FGFunction" << endl;
299 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
301 if (debug_lvl & 8 ) { // Runtime state variables
303 if (debug_lvl & 16) { // Sanity checking
305 if (debug_lvl & 64) {
306 if (from == 0) { // Constructor
307 cout << IdSrc << endl;
308 cout << IdHdr << endl;