Files
secondo/Algebras/Periodic/MRealMap.cpp
2026-01-23 17:03:45 +08:00

282 lines
4.9 KiB
C++

/*
3.11 ~MRealMap~
*/
#include <iostream>
#include <string>
#include "NestedList.h"
#include "PeriodicTypes.h"
#include "PeriodicSupport.h"
#include "StandardTypes.h"
extern NestedList* nl;
using namespace std;
using namespace datetime;
namespace periodic{
/*
~Constructor~
*/
MRealMap::MRealMap(){}
/*
~Constructor~
Creates a realmap for the constant value zero.
*/
MRealMap::MRealMap(int dummy){
a = 0.0;
b = 0.0;
c = 0.0;
root=false;
}
/*
~constructor~
This constructor sets the value of this moving real map to the
given values.
*/
MRealMap::MRealMap(double a, double b, double c, bool root){
Set(a,b,c,root);
}
/*
~Copy constructor~
*/
MRealMap::MRealMap(const MRealMap& source){
Equalize(&source);
}
/*
~Destructor~
*/
MRealMap::~MRealMap(){}
/*
~Assignment operator~
*/
MRealMap& MRealMap::operator=(const MRealMap& source){
Equalize(&source);
return *this;
}
/*
~Set~
This function sets this MRealMap to represent the function:
Figure 5: Formula of an Moving Real Map [MRealFormula.eps]
*/
void MRealMap::Set(double a, double b, double c, bool root){
this->a=a;
this->b=b;
this->c=c;
this->root=root;
Unify();
}
/*
~ExtremumAt~
Return the point in time where this Map has its extremum.
If no extremum is present, i.e. if a==0, an undefined
duration value is returned.
*/
DateTime MRealMap::ExtremumAt()const{
DateTime res(instanttype);
if(a==0){
res.SetDefined(false);
return res;
}
res.ReadFrom(-b / (2*a) );
return res;
}
/*
~ReadFrom function~
This function reads the value of this map from a list expression.
If the list does not represent a valid moving real map,
the value of this map remains unchanged and the result will be __false__.
Otherwise, this value is changed to the value given in the list and
__true__ is returned.
*/
bool MRealMap::ReadFrom(ListExpr le){
if(::nl->ListLength(le)!=4)
return false;
double tmpa,tmpb,tmpc;
if(::nl->AtomType(::nl->Fourth(le))!=BoolType)
return false;
bool tmproot=::nl->BoolValue(::nl->Fourth(le));
if(!GetNumeric(::nl->First(le),tmpa))
return false;
if(!GetNumeric(::nl->Second(le),tmpb))
return false;
if(!GetNumeric(::nl->Third(le),tmpc))
return false;
a = tmpa;
b = tmpb;
c = tmpc;
root = tmproot;
Unify();
return true;
}
/*
~ToListExpr~
This function returns the nested list representation of this map.
*/
ListExpr MRealMap::ToListExpr()const{
return ::nl->FourElemList(::nl->RealAtom(a),
::nl->RealAtom(b),
::nl->RealAtom(c),
::nl->BoolAtom(root));
}
/*
~At~
Computes the value of this map for a given instant. Ensure, that the
map is defined at this instant using the ~IsDefinedAt~ function.
*/
double MRealMap::At(const DateTime* duration) const {
double d = duration->ToDouble();
return At(d);
}
/*
~At~
This function may be used for a faster computing of a value of this
map.
*/
double MRealMap::At(const double d) const{
double r1 = (a*d+b)*d+c;
if(root) return sqrt(r1);
return r1;
}
/*
~IsDefinedAt~
This function checks whether this map is defined at the given instant.
*/
bool MRealMap::IsDefinedAt(const DateTime* duration) const {
if(!root) // defined all the time
return true;
double d = duration->ToDouble();
double r1 = (a*d+b)*d+c;
return r1>=0; // defined only if expression under the root is positive
}
/*
~IsDefinedAt~
Returns __true__ if this map is defined for the given value.
*/
bool MRealMap::IsDefinedAt(const double d) const{
if(!root)
return true;
double r1 = (a*d+b)*d+c;
return r1>=0; // defined only if expression under the root is positive
}
/*
~EqualsTo~
This function checks for equality between this map and the argument.
*/
bool MRealMap::EqualsTo(const MRealMap RM2)const{
return a == RM2.a &&
b == RM2.b &&
c == RM2.c &&
root == RM2.root;
}
/*
~Equalize~
If this function is called, the valu of this map is taken from the argument.
*/
void MRealMap::Equalize(const MRealMap* RM){
a = RM->a;
b = RM->b;
c = RM->c;
root = RM->root;
}
/*
~EqualsTo~
This function checks whether the argument is an extension for this map when the
arguments starts __timediff__ later. This means:
[forall] x [in] [R]: this[->]GetValueAt(x+timediff)==RM[->]GetValueAt(x)
*/
bool MRealMap::EqualsTo(const MRealMap& RM, double timediff) const{
if(root!=RM.root)
return false;
return RM.a == a &&
RM.b == 2*a*timediff+b &&
RM.c == timediff*timediff + b*timediff + c;
}
/*
~Unify~
This functions converts this moving real into a unified representation.
*/
void MRealMap::Unify(){
if(!root) return;
if(a==0 && b==0){
c = sqrt(c);
root = false;
return;
}
if(b==0 && c==0){
b=sqrt(a);
a=0;
root=false;
return;
}
}
} // end of namespace periodic