]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/math/FGFunction.cpp
Clean up header file use of iostream and "using" declarations
[flightgear.git] / src / FDM / JSBSim / math / FGFunction.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3 Module: FGFunction.cpp
4 Author: Jon Berndt
5 Date started: 8/25/2004
6 Purpose: Stores various parameter types for functions
7
8  ------------- Copyright (C) 2004  Jon S. Berndt (jsb@hal-pc.org) -------------
9
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
13  version.
14
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
18  details.
19
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.
23
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.
26
27 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
28 INCLUDES
29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
30
31 #include <stdio.h>
32 #include <iostream>
33
34 #include "FGFunction.h"
35 #include "FGTable.h"
36 #include "FGPropertyValue.h"
37 #include "FGRealValue.h"
38
39 namespace JSBSim {
40
41 static const char *IdSrc = "$Id$";
42 static const char *IdHdr = ID_FUNCTION;
43
44 using std::cerr;
45 using std::cout;
46
47 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
48 CLASS IMPLEMENTATION
49 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
50
51 FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, string prefix)
52                                       : PropertyManager(propMan), Prefix(prefix)
53 {
54   Element* element;
55   string operation, property_name;
56   int size = el->GetNumElements();
57   cached = false;
58   cachedValue = -HUGE_VAL;
59
60   Name = el->GetAttributeValue("name");
61   operation = el->GetName();
62
63   if (operation == string("function")) {
64     Type = eTopLevel;
65   } else if (operation == string("product")) {
66     Type = eProduct;
67   } else if (operation == string("difference")) {
68     Type = eDifference;
69   } else if (operation == string("sum")) {
70     Type = eSum;
71   } else if (operation == string("quotient")) {
72     Type = eQuotient;
73   } else if (operation == string("pow")) {
74     Type = ePow;
75   } else if (operation == string("abs")) {
76     Type = eAbs;
77   } else if (operation == string("sin")) {
78     Type = eSin;
79   } else if (operation == string("exp")) {
80     Type = eExp;
81   } else if (operation == string("cos")) {
82     Type = eCos;
83   } else if (operation == string("tan")) {
84     Type = eTan;
85   } else if (operation == string("asin")) {
86     Type = eASin;
87   } else if (operation == string("acos")) {
88     Type = eACos;
89   } else if (operation == string("atan")) {
90     Type = eATan;
91   } else if (operation == string("atan2")) {
92     Type = eATan2;
93   } else if (operation != string("description")) {
94     cerr << "Bad operation " << operation << " detected in configuration file" << endl;
95   }
96
97   element = el->GetElement();
98   if (!element) {
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;
104     cerr << reset;
105     exit(-2);
106   }
107   
108   while (element) {
109     operation = element->GetName();
110
111     // data types
112     if (operation == string("property")) {
113       property_name = element->GetDataLine();
114       FGPropertyManager* newNode = PropertyManager->GetNode(property_name);
115       if (newNode == 0) {
116         cerr << "The property " << property_name << " is undefined." << endl;
117         abort();
118       } else {
119         Parameters.push_back(new FGPropertyValue( newNode ));
120       }
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));
125     // operations
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"))
140     {
141       Parameters.push_back(new FGFunction(PropertyManager, element));
142     } else if (operation != string("description")) {
143       cerr << "Bad operation " << operation << " detected in configuration file" << endl;
144     }
145     element = el->GetNextElement();
146   }
147
148   bind(); // Allow any function to save its value
149
150   Debug(0);
151 }
152
153 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
154
155 FGFunction::~FGFunction(void)
156 {
157   if (!Name.empty()) {
158     string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
159     PropertyManager->Untie(tmp);
160   }
161
162   for (unsigned int i=0; i<Parameters.size(); i++) {
163     delete Parameters[i];
164   }
165 }
166
167 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
168
169 void FGFunction::cacheValue(bool cache)
170 {
171   cached = false; // Must set cached to false prior to calling GetValue(), else
172                   // it will _never_ calculate the value;
173   if (cache) {
174     cachedValue = GetValue();
175     cached = true;
176   }
177 }
178
179 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180
181 double FGFunction::GetValue(void) const
182 {
183   unsigned int i;
184
185   if (cached) return cachedValue;
186
187   double temp = Parameters[0]->GetValue();
188
189   switch (Type) {
190   case eTopLevel:
191     break;
192   case eProduct:
193     for (i=1;i<Parameters.size();i++) {
194       temp *= Parameters[i]->GetValue();
195     }
196     break;
197   case eDifference:
198     for (i=1;i<Parameters.size();i++) {
199       temp -= Parameters[i]->GetValue();
200     }
201     break;
202   case eSum:
203     for (i=1;i<Parameters.size();i++) {
204       temp += Parameters[i]->GetValue();
205     }
206     break;
207   case eQuotient:
208     temp /= Parameters[1]->GetValue();
209     break;
210   case ePow:
211     temp = pow(temp,Parameters[1]->GetValue());
212     break;
213   case eExp:
214     temp = exp(temp);
215     break;
216   case eAbs:
217     temp = fabs(temp);
218     break;
219   case eSin:
220     temp = sin(temp);
221     break;
222   case eCos:
223     temp = cos(temp);
224     break;
225   case eTan:
226     temp = tan(temp);
227     break;
228   case eACos:
229     temp = acos(temp);
230     break;
231   case eASin:
232     temp = asin(temp);
233     break;
234   case eATan:
235     temp = atan(temp);
236     break;
237   case eATan2:
238     temp = atan2(temp, Parameters[1]->GetValue());
239     break;
240   default:
241     cerr << "Unknown function operation type" << endl;
242     break;
243   }
244
245   return temp;
246 }
247
248 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
249
250 string FGFunction::GetValueAsString(void) const
251 {
252   char buffer[20];
253   string value;
254
255   sprintf(buffer,"%9.6f",GetValue());
256   value = string(buffer);
257   return value;
258 }
259
260 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261
262 void FGFunction::bind(void)
263 {
264   if ( !Name.empty() ) {
265     string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
266     PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
267   }
268 }
269
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
277 //       whatsoever.
278 //    1: This value explicity requests the normal JSBSim
279 //       startup messages
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
288
289 void FGFunction::Debug(int from)
290 {
291   if (debug_lvl <= 0) return;
292
293   if (debug_lvl & 1) { // Standard console startup message output
294     if (from == 0) { // Constructor
295       if (Type == eTopLevel)
296         cout << "    Function: " << Name << endl;
297     }
298   }
299   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
300     if (from == 0) cout << "Instantiated: FGFunction" << endl;
301     if (from == 1) cout << "Destroyed:    FGFunction" << endl;
302   }
303   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
304   }
305   if (debug_lvl & 8 ) { // Runtime state variables
306   }
307   if (debug_lvl & 16) { // Sanity checking
308   }
309   if (debug_lvl & 64) {
310     if (from == 0) { // Constructor
311       cout << IdSrc << endl;
312       cout << IdHdr << endl;
313     }
314   }
315 }
316
317 }