]> git.mxchange.org Git - flightgear.git/blobdiff - src/FDM/JSBSim/math/FGFunction.cpp
Merge branch 'vivian/trainz'
[flightgear.git] / src / FDM / JSBSim / math / FGFunction.cpp
index 304575a62bdb505ca0f31c41ca7b2d477bad4cd5..e45e6d9aa23c1a14181e4a9371fb2f2f9ad9e44b 100755 (executable)
@@ -5,7 +5,7 @@ Author: Jon Berndt
 Date started: 8/25/2004
 Purpose: Stores various parameter types for functions
 
- ------------- Copyright (C) 2004  Jon S. Berndt (jsb@hal-pc.org) -------------
+ ------------- Copyright (C) 2004  Jon S. Berndt (jon@jsbsim.org) -------------
 
  This program is free software; you can redistribute it and/or modify it under
  the terms of the GNU Lesser General Public License as published by the Free Software
@@ -28,69 +28,125 @@ Purpose: Stores various parameter types for functions
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#include <stdio.h>
-#include <iostream>
-
+#include <sstream>
+#include <iomanip>
+#include <cstdlib>
+#include <cmath>
 #include "FGFunction.h"
 #include "FGTable.h"
 #include "FGPropertyValue.h"
 #include "FGRealValue.h"
+#include "input_output/FGXMLElement.h"
+#include "input_output/FGPropertyManager.h"
+
+using namespace std;
 
 namespace JSBSim {
 
 static const char *IdSrc = "$Id$";
 static const char *IdHdr = ID_FUNCTION;
 
-using std::cerr;
-using std::cout;
-
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS IMPLEMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, string prefix)
+FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& prefix)
                                       : PropertyManager(propMan), Prefix(prefix)
 {
   Element* element;
   string operation, property_name;
-  int size = el->GetNumElements();
   cached = false;
   cachedValue = -HUGE_VAL;
+  invlog2val = 1.0/log10(2.0);
+
+  property_string = "property";
+  value_string = "value";
+  table_string = "table";
+  p_string = "p";
+  v_string = "v";
+  t_string = "t";
+
+  function_string = "function";
+  description_string = "description";
+  sum_string = "sum";
+  difference_string = "difference";
+  product_string = "product";
+  quotient_string = "quotient";
+  pow_string = "pow";
+  exp_string = "exp";
+  log2_string = "log2";
+  ln_string = "ln";
+  log10_string = "log10";
+  abs_string = "abs";
+  sin_string = "sin";
+  cos_string = "cos";
+  tan_string = "tan";
+  asin_string = "asin";
+  acos_string = "acos";
+  atan_string = "atan";
+  atan2_string = "atan2";
+  min_string = "min";
+  max_string = "max";
+  avg_string = "avg";
+  fraction_string = "fraction";
+  mod_string = "mod";
+  random_string = "random";
+  integer_string = "integer";
 
   Name = el->GetAttributeValue("name");
   operation = el->GetName();
 
-  if (operation == string("function")) {
+  if (operation == function_string) {
     Type = eTopLevel;
-  } else if (operation == string("product")) {
+  } else if (operation == product_string) {
     Type = eProduct;
-  } else if (operation == string("difference")) {
+  } else if (operation == difference_string) {
     Type = eDifference;
-  } else if (operation == string("sum")) {
+  } else if (operation == sum_string) {
     Type = eSum;
-  } else if (operation == string("quotient")) {
+  } else if (operation == quotient_string) {
     Type = eQuotient;
-  } else if (operation == string("pow")) {
+  } else if (operation == pow_string) {
     Type = ePow;
-  } else if (operation == string("abs")) {
+  } else if (operation == log2_string) {
+    Type = eLog2;
+  } else if (operation == ln_string) {
+    Type = eLn;
+  } else if (operation == log10_string) {
+    Type = eLog10;
+  } else if (operation == abs_string) {
     Type = eAbs;
-  } else if (operation == string("sin")) {
+  } else if (operation == sin_string) {
     Type = eSin;
-  } else if (operation == string("exp")) {
+  } else if (operation == exp_string) {
     Type = eExp;
-  } else if (operation == string("cos")) {
+  } else if (operation == cos_string) {
     Type = eCos;
-  } else if (operation == string("tan")) {
+  } else if (operation == tan_string) {
     Type = eTan;
-  } else if (operation == string("asin")) {
+  } else if (operation == asin_string) {
     Type = eASin;
-  } else if (operation == string("acos")) {
+  } else if (operation == acos_string) {
     Type = eACos;
-  } else if (operation == string("atan")) {
+  } else if (operation == atan_string) {
     Type = eATan;
-  } else if (operation == string("atan2")) {
+  } else if (operation == atan2_string) {
     Type = eATan2;
-  } else if (operation != string("description")) {
+  } else if (operation == min_string) {
+    Type = eMin;
+  } else if (operation == max_string) {
+    Type = eMax;
+  } else if (operation == avg_string) {
+    Type = eAvg;
+  } else if (operation == fraction_string) {
+    Type = eFrac;
+  } else if (operation == integer_string) {
+    Type = eInteger;
+  } else if (operation == mod_string) {
+    Type = eMod;
+  } else if (operation == random_string) {
+    Type = eRandom;
+  } else if (operation != description_string) {
     cerr << "Bad operation " << operation << " detected in configuration file" << endl;
   }
 
@@ -109,7 +165,7 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, string prefix)
     operation = element->GetName();
 
     // data types
-    if (operation == string("property")) {
+    if (operation == property_string || operation == p_string) {
       property_name = element->GetDataLine();
       FGPropertyManager* newNode = PropertyManager->GetNode(property_name);
       if (newNode == 0) {
@@ -118,28 +174,38 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, string prefix)
       } else {
         Parameters.push_back(new FGPropertyValue( newNode ));
       }
-    } else if (operation == string("value")) {
+    } else if (operation == value_string || operation == v_string) {
       Parameters.push_back(new FGRealValue(element->GetDataAsNumber()));
-    } else if (operation == string("table")) {
+    } else if (operation == table_string || operation == t_string) {
       Parameters.push_back(new FGTable(PropertyManager, element));
     // operations
-    } else if (operation == string("product") ||
-               operation == string("difference") ||
-               operation == string("sum") ||
-               operation == string("quotient") ||
-               operation == string("pow") ||
-               operation == string("exp") ||
-               operation == string("abs") ||
-               operation == string("sin") ||
-               operation == string("cos") ||
-               operation == string("tan") ||
-               operation == string("asin") ||
-               operation == string("acos") ||
-               operation == string("atan") ||
-               operation == string("atan2"))
+    } else if (operation == product_string ||
+               operation == difference_string ||
+               operation == sum_string ||
+               operation == quotient_string ||
+               operation == pow_string ||
+               operation == exp_string ||
+               operation == log2_string ||
+               operation == ln_string ||
+               operation == log10_string ||
+               operation == abs_string ||
+               operation == sin_string ||
+               operation == cos_string ||
+               operation == tan_string ||
+               operation == asin_string ||
+               operation == acos_string ||
+               operation == atan_string ||
+               operation == atan2_string ||
+               operation == min_string ||
+               operation == max_string ||
+               operation == fraction_string ||
+               operation == integer_string ||
+               operation == mod_string ||
+               operation == random_string ||
+               operation == avg_string )
     {
       Parameters.push_back(new FGFunction(PropertyManager, element));
-    } else if (operation != string("description")) {
+    } else if (operation != description_string) {
       cerr << "Bad operation " << operation << " detected in configuration file" << endl;
     }
     element = el->GetNextElement();
@@ -154,14 +220,7 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, string prefix)
 
 FGFunction::~FGFunction(void)
 {
-  if (!Name.empty()) {
-    string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
-    PropertyManager->Untie(tmp);
-  }
-
-  for (unsigned int i=0; i<Parameters.size(); i++) {
-    delete Parameters[i];
-  }
+  for (unsigned int i=0; i<Parameters.size(); i++) delete Parameters[i];
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -181,6 +240,7 @@ void FGFunction::cacheValue(bool cache)
 double FGFunction::GetValue(void) const
 {
   unsigned int i;
+  double scratch;
 
   if (cached) return cachedValue;
 
@@ -213,6 +273,18 @@ double FGFunction::GetValue(void) const
   case eExp:
     temp = exp(temp);
     break;
+  case eLog2:
+    if (temp > 0.00) temp = log10(temp)*invlog2val;
+    else temp = -HUGE_VAL;
+    break;
+  case eLn:
+    if (temp > 0.00) temp = log(temp);
+    else temp = -HUGE_VAL;
+    break;
+  case eLog10:
+    if (temp > 0.00) temp = log10(temp);
+    else temp = -HUGE_VAL;
+    break;
   case eAbs:
     temp = fabs(temp);
     break;
@@ -237,6 +309,35 @@ double FGFunction::GetValue(void) const
   case eATan2:
     temp = atan2(temp, Parameters[1]->GetValue());
     break;
+  case eMod:
+    temp = ((int)temp) % ((int) Parameters[1]->GetValue());
+    break;
+  case eMin:
+    for (i=1;i<Parameters.size();i++) {
+      if (Parameters[i]->GetValue() < temp) temp = Parameters[i]->GetValue();
+    }    
+    break;
+  case eMax:
+    for (i=1;i<Parameters.size();i++) {
+      if (Parameters[i]->GetValue() > temp) temp = Parameters[i]->GetValue();
+    }    
+    break;
+  case eAvg:
+    for (i=1;i<Parameters.size();i++) {
+      temp += Parameters[i]->GetValue();
+    }
+    temp /= Parameters.size();
+    break;
+  case eFrac:
+    temp = modf(temp, &scratch);
+    break;
+  case eInteger:
+    modf(temp, &scratch);
+    temp = scratch;
+    break;
+  case eRandom:
+    temp = GaussianRandomNumber();
+    break;
   default:
     cerr << "Unknown function operation type" << endl;
     break;
@@ -249,12 +350,10 @@ double FGFunction::GetValue(void) const
 
 string FGFunction::GetValueAsString(void) const
 {
-  char buffer[20];
-  string value;
+  ostringstream buffer;
 
-  sprintf(buffer,"%9.6f",GetValue());
-  value = string(buffer);
-  return value;
+  buffer << setw(9) << setprecision(6) << GetValue();
+  return buffer.str();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -262,7 +361,12 @@ string FGFunction::GetValueAsString(void) const
 void FGFunction::bind(void)
 {
   if ( !Name.empty() ) {
-    string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
+    string tmp;
+    if (Prefix.empty())
+      tmp  = PropertyManager->mkPropertyName(Name, false); // Allow upper case
+    else
+      tmp  = PropertyManager->mkPropertyName(Prefix + "/" + Name, false); // Allow upper case
+
     PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
   }
 }