]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/math/FGFunction.cpp
Sync. w. JSBSim CVS.
[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 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9 INCLUDES
10 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
11
12 #include <stdio.h>
13
14 #include "FGFunction.h"
15 #include "FGTable.h"
16 #include "FGPropertyValue.h"
17 #include "FGRealValue.h"
18
19 namespace JSBSim {
20
21 static const char *IdSrc = "$Id$";
22 static const char *IdHdr = ID_FUNCTION;
23
24 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
25 CLASS IMPLEMENTATION
26 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
27
28 FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, string prefix)
29                                       : PropertyManager(propMan), Prefix(prefix)
30 {
31   int i;
32   Element* element;
33   string operation, property_name;
34   int size = el->GetNumElements();
35   cached = false;
36   cachedValue = -HUGE_VAL;
37
38   Name = el->GetAttributeValue("name");
39   operation = el->GetName();
40   if (operation == string("function")) {
41     Type = eTopLevel;
42     bind();
43   } else if (operation == string("product")) {
44     Type = eProduct;
45   } else if (operation == string("difference")) {
46     Type = eDifference;
47   } else if (operation == string("sum")) {
48     Type = eSum;
49   } else if (operation == string("quotient")) {
50     Type = eQuotient;
51   } else if (operation == string("pow")) {
52     Type = ePow;
53   } else if (operation == string("abs")) {
54     Type = eAbs;
55   } else if (operation == string("sin")) {
56     Type = eSin;
57   } else if (operation == string("cos")) {
58     Type = eCos;
59   } else if (operation == string("tan")) {
60     Type = eTan;
61   } else if (operation == string("asin")) {
62     Type = eASin;
63   } else if (operation == string("acos")) {
64     Type = eACos;
65   } else if (operation == string("atan")) {
66     Type = eATan;
67   } else if (operation == string("atan2")) {
68     Type = eATan2;
69   } else if (operation != string("description")) {
70     cerr << "Bad operation " << operation << " detected in configuration file" << endl;
71   }
72
73   element = el->GetElement();
74   while (element) {
75     operation = element->GetName();
76
77     // data types
78     if (operation == string("property")) {
79       property_name = element->GetDataLine();
80       FGPropertyManager* newNode = PropertyManager->GetNode(property_name);
81       if (newNode == 0) {
82         cerr << "The property " << property_name << " is undefined." << endl;
83         abort();
84       } else {
85         Parameters.push_back(new FGPropertyValue( newNode ));
86       }
87     } else if (operation == string("value")) {
88       Parameters.push_back(new FGRealValue(element->GetDataAsNumber()));
89     } else if (operation == string("table")) {
90       Parameters.push_back(new FGTable(PropertyManager, element));
91     // operations
92     } else if (operation == string("product") ||
93                operation == string("difference") ||
94                operation == string("sum") ||
95                operation == string("quotient") ||
96                operation == string("pow") ||
97                operation == string("abs") ||
98                operation == string("sin") ||
99                operation == string("cos") ||
100                operation == string("tan") ||
101                operation == string("asin") ||
102                operation == string("acos") ||
103                operation == string("atan") ||
104                operation == string("atan2"))
105     {
106       Parameters.push_back(new FGFunction(PropertyManager, element));
107     } else if (operation != string("description")) {
108       cerr << "Bad operation " << operation << " detected in configuration file" << endl;
109     }
110     element = el->GetNextElement();
111   }
112
113   Debug(0);
114 }
115
116 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
117
118 FGFunction::~FGFunction(void)
119 {
120   string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
121   PropertyManager->Untie(tmp);
122 }
123
124 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
125
126 void FGFunction::cacheValue(bool cache)
127 {
128   cached = false; // Must set cached to false prior to calling GetValue(), else
129                   // it will _never_ calculate the value;
130   if (cache) {
131     cachedValue = GetValue();
132     cached = true;
133   }
134 }
135
136 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
137
138 double FGFunction::GetValue(void) const
139 {
140   int i;
141
142   if (cached) return cachedValue;
143
144   double temp = Parameters[0]->GetValue();
145
146   switch (Type) {
147   case eTopLevel:
148     break;
149   case eProduct:
150     for (i=1;i<Parameters.size();i++) temp *= Parameters[i]->GetValue();
151     break;
152   case eDifference:
153     for (i=1;i<Parameters.size();i++) temp -= Parameters[i]->GetValue();
154     break;
155   case eSum:
156     for (i=1;i<Parameters.size();i++) temp += Parameters[i]->GetValue();
157     break;
158   case eQuotient:
159     temp /= Parameters[1]->GetValue();
160     break;
161   case ePow:
162     temp = pow(temp,Parameters[1]->GetValue());
163     break;
164   case eAbs:
165     temp = fabs(temp);
166     break;
167   case eSin:
168     temp = sin(temp);
169     break;
170   case eCos:
171     temp = cos(temp);
172     break;
173   case eTan:
174     temp = tan(temp);
175     break;
176   case eACos:
177     temp = acos(temp);
178     break;
179   case eASin:
180     temp = asin(temp);
181     break;
182   case eATan:
183     temp = atan(temp);
184     break;
185   case eATan2:
186     temp = atan2(temp, Parameters[1]->GetValue());
187     break;
188   default:
189     cerr << "Unknown function operation type" << endl;
190     break;
191   }
192
193   return temp;
194 }
195
196 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
197
198 string FGFunction::GetValueAsString(void) const
199 {
200   char buffer[20];
201   string value;
202
203   sprintf(buffer,"%9.6f",GetValue());
204   value = string(buffer);
205   return value;
206 }
207
208 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
209
210 void FGFunction::bind(void)
211 {
212   if ( !Name.empty() ) {
213     string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
214     PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
215   }
216 }
217
218 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
219 //    The bitmasked value choices are as follows:
220 //    unset: In this case (the default) JSBSim would only print
221 //       out the normally expected messages, essentially echoing
222 //       the config files as they are read. If the environment
223 //       variable is not set, debug_lvl is set to 1 internally
224 //    0: This requests JSBSim not to output any messages
225 //       whatsoever.
226 //    1: This value explicity requests the normal JSBSim
227 //       startup messages
228 //    2: This value asks for a message to be printed out when
229 //       a class is instantiated
230 //    4: When this value is set, a message is displayed when a
231 //       FGModel object executes its Run() method
232 //    8: When this value is set, various runtime state variables
233 //       are printed out periodically
234 //    16: When set various parameters are sanity checked and
235 //       a message is printed out when they go out of bounds
236
237 void FGFunction::Debug(int from)
238 {
239   if (debug_lvl <= 0) return;
240
241   if (debug_lvl & 1) { // Standard console startup message output
242     if (from == 0) { // Constructor
243       if (Type == eTopLevel)
244         cout << "    Function: " << Name << endl;
245     }
246   }
247   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
248     if (from == 0) cout << "Instantiated: FGGroundReactions" << endl;
249     if (from == 1) cout << "Destroyed:    FGGroundReactions" << endl;
250   }
251   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
252   }
253   if (debug_lvl & 8 ) { // Runtime state variables
254   }
255   if (debug_lvl & 16) { // Sanity checking
256   }
257   if (debug_lvl & 64) {
258     if (from == 0) { // Constructor
259       cout << IdSrc << endl;
260       cout << IdHdr << endl;
261     }
262   }
263 }
264
265 }