]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/math/FGFunction.cpp
Sync. w. JSB CVS as of 15/01/2007
[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
33 #include "FGFunction.h"
34 #include "FGTable.h"
35 #include "FGPropertyValue.h"
36 #include "FGRealValue.h"
37
38 namespace JSBSim {
39
40 static const char *IdSrc = "$Id$";
41 static const char *IdHdr = ID_FUNCTION;
42
43 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
44 CLASS IMPLEMENTATION
45 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
46
47 FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, string prefix)
48                                       : PropertyManager(propMan), Prefix(prefix)
49 {
50   int i;
51   Element* element;
52   string operation, property_name;
53   int size = el->GetNumElements();
54   cached = false;
55   cachedValue = -HUGE_VAL;
56
57   Name = el->GetAttributeValue("name");
58   operation = el->GetName();
59
60   if (operation == string("function")) {
61     Type = eTopLevel;
62   } else if (operation == string("product")) {
63     Type = eProduct;
64   } else if (operation == string("difference")) {
65     Type = eDifference;
66   } else if (operation == string("sum")) {
67     Type = eSum;
68   } else if (operation == string("quotient")) {
69     Type = eQuotient;
70   } else if (operation == string("pow")) {
71     Type = ePow;
72   } else if (operation == string("abs")) {
73     Type = eAbs;
74   } else if (operation == string("sin")) {
75     Type = eSin;
76   } else if (operation == string("exp")) {
77     Type = eExp;
78   } else if (operation == string("cos")) {
79     Type = eCos;
80   } else if (operation == string("tan")) {
81     Type = eTan;
82   } else if (operation == string("asin")) {
83     Type = eASin;
84   } else if (operation == string("acos")) {
85     Type = eACos;
86   } else if (operation == string("atan")) {
87     Type = eATan;
88   } else if (operation == string("atan2")) {
89     Type = eATan2;
90   } else if (operation != string("description")) {
91     cerr << "Bad operation " << operation << " detected in configuration file" << endl;
92   }
93
94   element = el->GetElement();
95   while (element) {
96     operation = element->GetName();
97
98     // data types
99     if (operation == string("property")) {
100       property_name = element->GetDataLine();
101       FGPropertyManager* newNode = PropertyManager->GetNode(property_name);
102       if (newNode == 0) {
103         cerr << "The property " << property_name << " is undefined." << endl;
104         abort();
105       } else {
106         Parameters.push_back(new FGPropertyValue( newNode ));
107       }
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));
112     // operations
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"))
127     {
128       Parameters.push_back(new FGFunction(PropertyManager, element));
129     } else if (operation != string("description")) {
130       cerr << "Bad operation " << operation << " detected in configuration file" << endl;
131     }
132     element = el->GetNextElement();
133   }
134
135   bind(); // Allow any function to save its value
136
137   Debug(0);
138 }
139
140 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
141
142 FGFunction::~FGFunction(void)
143 {
144   if (!Name.empty()) {
145     string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
146     PropertyManager->Untie(tmp);
147   }
148
149   for (int i=0; i<Parameters.size(); i++) {
150     delete Parameters[i];
151   }
152 }
153
154 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
155
156 void FGFunction::cacheValue(bool cache)
157 {
158   cached = false; // Must set cached to false prior to calling GetValue(), else
159                   // it will _never_ calculate the value;
160   if (cache) {
161     cachedValue = GetValue();
162     cached = true;
163   }
164 }
165
166 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
167
168 double FGFunction::GetValue(void) const
169 {
170   int i;
171
172   if (cached) return cachedValue;
173
174   double temp = Parameters[0]->GetValue();
175
176   switch (Type) {
177   case eTopLevel:
178     break;
179   case eProduct:
180     for (i=1;i<Parameters.size();i++) temp *= Parameters[i]->GetValue();
181     break;
182   case eDifference:
183     for (i=1;i<Parameters.size();i++) temp -= Parameters[i]->GetValue();
184     break;
185   case eSum:
186     for (i=1;i<Parameters.size();i++) temp += Parameters[i]->GetValue();
187     break;
188   case eQuotient:
189     temp /= Parameters[1]->GetValue();
190     break;
191   case ePow:
192     temp = pow(temp,Parameters[1]->GetValue());
193     break;
194   case eExp:
195     temp = exp(temp);
196     break;
197   case eAbs:
198     temp = fabs(temp);
199     break;
200   case eSin:
201     temp = sin(temp);
202     break;
203   case eCos:
204     temp = cos(temp);
205     break;
206   case eTan:
207     temp = tan(temp);
208     break;
209   case eACos:
210     temp = acos(temp);
211     break;
212   case eASin:
213     temp = asin(temp);
214     break;
215   case eATan:
216     temp = atan(temp);
217     break;
218   case eATan2:
219     temp = atan2(temp, Parameters[1]->GetValue());
220     break;
221   default:
222     cerr << "Unknown function operation type" << endl;
223     break;
224   }
225
226   return temp;
227 }
228
229 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
230
231 string FGFunction::GetValueAsString(void) const
232 {
233   char buffer[20];
234   string value;
235
236   sprintf(buffer,"%9.6f",GetValue());
237   value = string(buffer);
238   return value;
239 }
240
241 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242
243 void FGFunction::bind(void)
244 {
245   if ( !Name.empty() ) {
246     string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
247     PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
248   }
249 }
250
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
258 //       whatsoever.
259 //    1: This value explicity requests the normal JSBSim
260 //       startup messages
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
269
270 void FGFunction::Debug(int from)
271 {
272   if (debug_lvl <= 0) return;
273
274   if (debug_lvl & 1) { // Standard console startup message output
275     if (from == 0) { // Constructor
276       if (Type == eTopLevel)
277         cout << "    Function: " << Name << endl;
278     }
279   }
280   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
281     if (from == 0) cout << "Instantiated: FGFunction" << endl;
282     if (from == 1) cout << "Destroyed:    FGFunction" << endl;
283   }
284   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
285   }
286   if (debug_lvl & 8 ) { // Runtime state variables
287   }
288   if (debug_lvl & 16) { // Sanity checking
289   }
290   if (debug_lvl & 64) {
291     if (from == 0) { // Constructor
292       cout << IdSrc << endl;
293       cout << IdHdr << endl;
294     }
295   }
296 }
297
298 }