]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/math/FGFunction.cpp
sync. with JSBSim v. 2.0
[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       Parameters.push_back(new FGPropertyValue(PropertyManager->GetNode(property_name)));
81     } else if (operation == string("value")) {
82       Parameters.push_back(new FGRealValue(element->GetDataAsNumber()));
83     } else if (operation == string("table")) {
84       Parameters.push_back(new FGTable(PropertyManager, element));
85     // operations
86     } else if (operation == string("product") ||
87                operation == string("difference") ||
88                operation == string("sum") ||
89                operation == string("quotient") ||
90                operation == string("pow") ||
91                operation == string("abs") ||
92                operation == string("sin") ||
93                operation == string("cos") ||
94                operation == string("tan") ||
95                operation == string("asin") ||
96                operation == string("acos") ||
97                operation == string("atan") ||
98                operation == string("atan2"))
99     {
100       Parameters.push_back(new FGFunction(PropertyManager, element));
101     } else if (operation != string("description")) {
102       cerr << "Bad operation " << operation << " detected in configuration file" << endl;
103     }
104     element = el->GetNextElement();
105   }
106
107   Debug(0);
108 }
109
110 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
111
112 FGFunction::~FGFunction(void)
113 {
114   string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
115   PropertyManager->Untie(tmp);
116 }
117
118 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
119
120 void FGFunction::cacheValue(bool cache)
121 {
122   cached = false; // Must set cached to false prior to calling GetValue(), else
123                   // it will _never_ calculate the value;
124   if (cache) {
125     cachedValue = GetValue();
126     cached = true;
127   }
128 }
129
130 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
131
132 double FGFunction::GetValue(void) const
133 {
134   int i;
135
136   if (cached) return cachedValue;
137
138   double temp = Parameters[0]->GetValue();
139
140   switch (Type) {
141   case eTopLevel:
142     break;
143   case eProduct:
144     for (i=1;i<Parameters.size();i++) temp *= Parameters[i]->GetValue();
145     break;
146   case eDifference:
147     for (i=1;i<Parameters.size();i++) temp -= Parameters[i]->GetValue();
148     break;
149   case eSum:
150     for (i=1;i<Parameters.size();i++) temp += Parameters[i]->GetValue();
151     break;
152   case eQuotient:
153     temp /= Parameters[1]->GetValue();
154     break;
155   case ePow:
156     temp = pow(temp,Parameters[1]->GetValue());
157     break;
158   case eAbs:
159     temp = abs(temp);
160     break;
161   case eSin:
162     temp = sin(temp);
163     break;
164   case eCos:
165     temp = cos(temp);
166     break;
167   case eTan:
168     temp = tan(temp);
169     break;
170   case eACos:
171     temp = acos(temp);
172     break;
173   case eASin:
174     temp = asin(temp);
175     break;
176   case eATan:
177     temp = atan(temp);
178     break;
179   case eATan2:
180     temp = atan2(temp, Parameters[1]->GetValue());
181     break;
182   default:
183     cerr << "Unknown function operation type" << endl;
184     break;
185   }
186
187   return temp;
188 }
189
190 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
191
192 string FGFunction::GetValueAsString(void) const
193 {
194   char buffer[20];
195   string value;
196
197   sprintf(buffer,"%9.6f",GetValue());
198   value = string(buffer);
199   return value;
200 }
201
202 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
203
204 void FGFunction::bind(void)
205 {
206   string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
207   PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
208 }
209
210 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
211 //    The bitmasked value choices are as follows:
212 //    unset: In this case (the default) JSBSim would only print
213 //       out the normally expected messages, essentially echoing
214 //       the config files as they are read. If the environment
215 //       variable is not set, debug_lvl is set to 1 internally
216 //    0: This requests JSBSim not to output any messages
217 //       whatsoever.
218 //    1: This value explicity requests the normal JSBSim
219 //       startup messages
220 //    2: This value asks for a message to be printed out when
221 //       a class is instantiated
222 //    4: When this value is set, a message is displayed when a
223 //       FGModel object executes its Run() method
224 //    8: When this value is set, various runtime state variables
225 //       are printed out periodically
226 //    16: When set various parameters are sanity checked and
227 //       a message is printed out when they go out of bounds
228
229 void FGFunction::Debug(int from)
230 {
231   if (debug_lvl <= 0) return;
232
233   if (debug_lvl & 1) { // Standard console startup message output
234     if (from == 0) { // Constructor
235       if (Type == eTopLevel)
236         cout << "    Function: " << Name << endl;
237     }
238   }
239   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
240     if (from == 0) cout << "Instantiated: FGGroundReactions" << endl;
241     if (from == 1) cout << "Destroyed:    FGGroundReactions" << endl;
242   }
243   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
244   }
245   if (debug_lvl & 8 ) { // Runtime state variables
246   }
247   if (debug_lvl & 16) { // Sanity checking
248   }
249   if (debug_lvl & 64) {
250     if (from == 0) { // Constructor
251       cout << IdSrc << endl;
252       cout << IdHdr << endl;
253     }
254   }
255 }
256
257 }