/* //paragraph [1] Title: [{\Large \bf \begin{center}] [\end{center}}] //paragraph [10] Footnote: [{\footnote{] [}}] //[ue] [\"u] //[ae] [\"a] //[TOC] [\tableofcontents] [1] TemporalUnitAlgebra - Implementing Units-Operators May 2006, initial version implemented by Thomas Fischer for diploma thesis with Prof. Dr. G[ue]ting, Fachbereich Informatik, Feruniversit[ae]t Hagen. July 2006, Christian D[ue]ntgen: The so far implemented operators do not suffice to model typical queries using the compact unit representation ~moving(T)~ with relations of units. Instead, we also need variants of spatiotemporal operators that process streams of units. Instead of implementing them directly, we will fake them using the set wrapper-operators ~use~ on the native single-unit operators. The ~use~ operators passes single values to an operator one-by-one value and collects all returned values/streams of values in a flat stream of values. This does not work for some binary predicates, like equal, but one could implement an ordered pairwise comparison here. It may be useful, to have some operators consuming a stream of units and returning an aggregated vale, as e.g. initial, final, present, never, always. December 2006, Christian D[ue]ntgen: Moved class functions for unit types to where they belong (ie. ~TemporalAlgebra~). ---- State Operator/Signatures OK makemvalue (**) stream (tuple ([x1:t1,xi:uT,..,xn:tn])) --> mT OK the_mvalue (**) stream uT --> mT OK get_duration periods --> duration OK point2d periods --> point OK queryrect2d instant --> rect OK circle point x real x int --> region OK uint2ureal: uint --> ureal the_unit: For T in {bool, int, string, region*} *: Crashed for T=region OK point point instant instant bool bool --> upoint OK ipoint ipoint bool bool --> upoint OK real real real bool instant instant bool bool --> ureal OK iT duration bool bool --> uT OK T instant instant bool bool --> uT the_ivalue: For T in {bool, int, string, real, point, region} OK (instant T) --> iT OK isempty U --> bool (for U in kind UNIT) OK trajectory upoint --> line OK velocity mpoint --> mpoint OK velocity upoint --> upoint OK derivable mreal --> mbool OK derivable ureal --> ubool OK derivative mreal --> mreal OK derivative ureal --> ureal OK speed mpoint [ x geoid ] --> mreal OK speed upoint [ x geoid ] --> ureal passes: For T in {bool, int, string, point}: OK + uT x T --> bool OK + ureal x real --> bool n/a + uregion x region --> bool OK + deftime (**) uT --> periods OK + atinstant (**) uT x instant --> iT OK + atperiods (**) uT x periods --> (stream uT) OK + Initial (**) uT --> iT OK Initial (**) (stream uT) --> iT OK + final (**) uT --> iT OK final (**) (stream uT) --> iT OK + present (**) uT x instant --> bool OK + present (**) uT x periods --> bool n/a present (stream uT) x instant --> bool (use use2/present) n/a present (stream uT) x periods --> bool (use use2/present) atmax: For T in {bool, int, real, string}: OK + uT --> (stream uT) atmin: For T in {bool, int, real, string}: OK + uT --> (stream uT) at: For T in {bool, int, string, point, region*} OK + uT x T --> (stream uT) as intersection: uT x T OK ureal x real --> (stream ureal) as intersection: ureal x real OK + upoint x region --> (stream upoint) as intersection: upoint x region distance: T in {int, point} OK - uT x uT --> ureal OK ? uT x T --> ureal OK ? T x uT --> ureal OK + ureal x ureal --> (stream ureal) OK + ureal x real --> (stream ureal) OK + real x ureal --> (stream ureal) OK + abs: ureal --> (stream ureal) OK + abs: uint --> uint intersection: For T in {bool, int, string}: OK + uT x uT --> (stream uT) OK + uT x T --> (stream uT) same as at: uT x T OK + T x uT --> (stream uT) same as at: uT x T OK + ureal x real --> (stream ureal) same as at: ureal x real OK + real x ureal --> (stream ureal) same as at: ureal x real OK - upoint x point --> (stream upoint) same as at: upoint x point OK - point x upoint --> (stream upoint) same as at: upoint x point OK - upoint x upoint --> (stream upoint) OK + upoint x line --> (stream upoint) OK + line x upoint --> (stream upoint) OK + ureal x ureal --> (stream ureal) OK + upoint x uregion --> (stream upoint) same as at: upoint x uregion OK - uregion x upoint --> (stream upoint) OK - upoint x region --> (stream upoint) same as: at: upoint x region OK - region x upoint --> (stream upoint) n/a + upoint x points --> (stream upoint) n/a + points x upoint --> (stream upoint) Pre - uregion x region --> (stream uregion) Pre - region x uregion --> (stream uregion) OK + no_components: uT --> uint OK + and, or: ubool x ubool --> ubool OK + bool x ubool --> ubool OK + ubool x bool --> ubool ==, ##, <<, >>, <<==, >>==: For T in {bool, int, string, real, point, region} Test+ uT x uT --> bool =, #, <, >, <=, >=: T in {bool, int, string, real} OK + uT x uT --> (stream ubool) OK + T x uT --> (stream ubool) OK + T x uT --> (stream ubool) OK + upoint x upoint --> (stream ubool) for {=,#} only OK + point x upoint --> (stream ubool) for {=,#} only OK + upoint x point --> (stream ubool) for {=,#} only pre + uregion x uregion --> (stream ubool) for {=,#} only n/a + region x uregion --> (stream ubool) for {=,#} only n/a + uregion x region --> (stream ubool) for {=,#} only OK + not: ubool --> ubool inside: OK + upoint x uregion --> (stream ubool) pre + upoint x line --> (stream ubool) n/a + upoint x points --> (stream ubool) n/a + uregion x points --> (stream ubool) n/a + mdirection: upoint --> ureal n/a + mheading: upoint --> ureal n/a + area: uregion --> ureal see TemporalLiftedAlgebra OK + sometimes: ( ubool) --> bool OK (stream ubool) --> bool OK + never: ( ubool) --> bool OK (stream ubool) --> bool OK + always: ( ubool) --> bool OK (stream ubool) --> bool OK length: (upoint [geoid]) --> real COMMENTS: (*): These operators have been implemented for T in {bool, int, real, point} (**): These operators have been implemented for T in {bool, int, real, point, string, region} Key to STATE of implementation: OK : Operator has been implemented and fully tested (OK): Operator has been implemented and partially tested Test: Operator has been implemented, but tests have not been done ERR : Operator produces errors Pre : Operator has not been functionally implemented, but stubs (dummy code) exist n/a : Neither functionally nor dummy code exists for this ones + : Equivalent exists for according mType - : Does nor exist for according mType ? : It is unclear, whether it exists or not ---- */ /* August 2006, Christian D[ue]ntgen: Added missing checks for ~undefined~ argument values to all value mapping functions. The functions will now return ~undefined~ result values for these cases. Changed structure of the file to become ordered by operators rather than by typemapping, valuemapping etc. This makes the file easier to extend. September 2009 Simone Jandt: Changed TU\_VM\_ComparePredicateValue\_UReal to use new member function CompUReal of UReal. */ /* 0. Bug-List ---- (none known) Key: (C): system crash (R): Wrong result ---- */ /* [TOC] 1 Overview This file contains the implementation of the unit operators and helping operators for indexing instant values in R-trees. 2 Defines, includes, and constants */ #include #include #include #include #include #include "TemporalUnitAlgebra.h" #include "NestedList.h" #include "QueryProcessor.h" #include "AlgebraManager.h" #include "Algebra.h" #include "StandardTypes.h" #include "Algebras/Spatial/SpatialAlgebra.h" #include "Algebras/Geoid/Geoid.h" #include "Algebras/Relation-C++/RelationAlgebra.h" #include "Algebras/Temporal/TemporalAlgebra.h" #include "Algebras/TemporalExt/TemporalExtAlgebra.h" #include "Algebras/MovingRegion/MovingRegionAlgebra.h" #include "Algebras/Rectangle/RectangleAlgebra.h" #include "PolySolver.h" #include "ListUtils.h" #include "Symbols.h" #include "Stream.h" #include "GenericTC.h" #include "Algebras/Temporal/RefinementStream.h" #include "Algebras/TemporalLifted/TemporalLiftedAlgebra.h" #include "DateTime.h" extern NestedList* nl; extern QueryProcessor* qp; extern AlgebraManager* am; // #define TUA_DEBUG namespace temporalalgebra{ /* 2.1 Definition of some constants and auxiliary functions */ // const double MAXDOUBLE = std::numeric_limits::max(); // const double MINDOUBLE = std::numeric_limits::min(); /* 2.2 Auxiliary output functions */ // make a string from a numeric value std::string TUn2s(const double& i) { std::stringstream ss; std::string str; ss << i; ss >> str; return str; } // make a string representation from a time interval std::string TUPrintTimeInterval( Interval iv ) { std::string Result; if (iv.lc) Result += "["; else Result += "]"; Result += iv.start.ToString(); Result += ", "; Result += iv.end.ToString(); if (iv.rc) Result += "]"; else Result += "["; return Result; } // make a string representation from a point std::string TUPrintPoint( const Point& p ) { std::string Result; if ( p.IsDefined() ) Result = "( def : "; else Result = "( undef: "; Result += TUn2s(p.GetX()); Result += "/"; Result += TUn2s(p.GetY()); Result += " )"; return Result; } // make a string representation from an upoint value std::string TUPrintUPoint( const UPoint& upoint ) { std::string Result; if ( upoint.IsDefined() ) Result = "( def : "; else Result = "( undef: "; Result += TUPrintTimeInterval(upoint.timeInterval); Result += ", "; Result += TUPrintPoint(upoint.p0); Result += ", "; Result += TUPrintPoint(upoint.p1); Result +=" )"; Result += ((Attribute*)(&upoint))->AttrDelete2string(); return Result; } // make a string representation from an ureal value std::string TUPrintUReal( UReal* ureal ) { std::string Result; if ( ureal->IsDefined() ) Result = "( def : "; else Result = "( undef: "; Result += TUPrintTimeInterval(ureal->timeInterval); Result += ", "; Result += TUn2s(ureal->a); Result += ", "; Result += TUn2s(ureal->b); Result += ", "; Result += TUn2s(ureal->c); if (ureal->r) Result += ", true )"; else Result +=", false )"; Result += ureal->AttrDelete2string(); return Result; } /* 3 Auxiliary Functions */ /* Auxiliary Method ~TU\_GetMidwayInstant~ Returns the instant at the middle of the interval defined by ~start~ and ~end~. */ Instant TU_GetMidwayInstant(const Instant &start, const Instant &end) { datetime::DateTime result(datetime::instanttype); result = start + ((end - start) / 2); return result; } /* 4 General Selection functions A selection function is quite similar to a type mapping function. The only difference is that it doesn't return a type but the index of a value mapping function within the operator's ~ValueMapping~ array, being able to deal with the respective combination of input parameter types. Non-overloaded opertors (having only one single signature) do not need a selection function or a ValueMapping array. Note that a selection function does not need to check the correctness of argument types; it has already been checked by the type mapping function that it is applied to correct arguments. Only some more general selection functions are listed here. More of them can be found in the operator implementation section below. 4.1 Selection function ~UnitSimpleSelect~ Is used for the ~deftime~,~atinstant~,~atperiods~ operations. */ int UnitSimpleSelect( ListExpr args ) { ListExpr T = nl->First( args ); if( nl->SymbolValue( T ) == UBool::BasicType() ) return 0; if( nl->SymbolValue( T ) == UInt::BasicType() ) return 1; if( nl->SymbolValue( T ) == UReal::BasicType() ) return 2; if( nl->SymbolValue( T ) == UPoint::BasicType() ) return 3; if( nl->SymbolValue( T ) == UString::BasicType() ) return 4; if( nl->SymbolValue( T ) == URegion::BasicType() ) return 5; return -1; // This point should never be reached } /* 4.2 Selection function ~UnitCombinedUnitStreamSelect~ This extended version of ~UnitSimpleSelect~ can map (unit) as well as (stream unit): */ int UnitCombinedUnitStreamSelect( ListExpr args ) { ListExpr arg1 = nl->First( args ); if (nl->IsAtom( arg1 ) ) { if( nl->SymbolValue( arg1 ) == UBool::BasicType() ) return 0; if( nl->SymbolValue( arg1 ) == UInt::BasicType() ) return 1; if( nl->SymbolValue( arg1 ) == UReal::BasicType() ) return 2; if( nl->SymbolValue( arg1 ) == UPoint::BasicType() ) return 3; if( nl->SymbolValue( arg1 ) == UString::BasicType() ) return 4; if( nl->SymbolValue( arg1 ) == URegion::BasicType() ) return 5; } if( Stream::checkType(arg1)){ if( nl->IsEqual( nl->Second(arg1), UBool::BasicType() ) ) return 6; if( nl->IsEqual( nl->Second(arg1), UInt::BasicType() ) ) return 7; if( nl->IsEqual( nl->Second(arg1), UReal::BasicType() ) ) return 8; if( nl->IsEqual( nl->Second(arg1), UPoint::BasicType() ) ) return 9; if( nl->IsEqual( nl->Second(arg1), UString::BasicType() ) ) return 10; if( nl->IsEqual( nl->Second(arg1), URegion::BasicType() ) ) return 11; } return -1; // This point should never be reached } /* 5 Implementation of Algebra Operators 5.1 Operator ~speed~ 5.1.1 Type mapping function for ~speed~ Type mapping for ~speed~ is ---- upoint [ x geoid ] --> ureal mpoint [ x geoid ] --> mreal ---- */ ListExpr TypeMapSpeed( ListExpr args ) { int noargs = nl->ListLength( args ); std::string errmsg = "Expected ( {upoint|mpoint} [ x geoid ] )."; if( (noargs < 1) || (noargs >2) ) { return listutils::typeError(errmsg +" 1"); } if( (noargs==2) && !listutils::isSymbol(nl->Second(args), Geoid::BasicType()) ){ return listutils::typeError(errmsg +" 2"); } ListExpr first = nl->First(args); if( listutils::isSymbol(first, UPoint::BasicType()) ) { return nl->SymbolAtom( UReal::BasicType() ); } if( listutils::isSymbol(first, MPoint::BasicType()) ) { return nl->SymbolAtom( MReal::BasicType() ); } return listutils::typeError(errmsg +" 3"); } /* 5.1.2 Value mapping for operator ~speed~ */ int MPointSpeed(Word* args, Word& result, int message, Word& local, Supplier s) { result = (qp->ResultStorage( s )); MReal *res = (MReal*)result.addr; MPoint *input = (MPoint*)args[0].addr; Geoid* g = 0; res->Clear(); if ( !input->IsDefined() ){ res->SetDefined(false); return 0; } if( qp->GetNoSons(s)==2 ){ g = static_cast(args[1].addr); if(!g->IsDefined()){ res->SetDefined(false); return 0; } } // call member function: input->MSpeed( *res, g ); return 0; } int UnitPointSpeed(Word* args,Word& result,int message,Word& local,Supplier s) { result = qp->ResultStorage( s ); UReal *res = (UReal*)result.addr; UPoint *input = (UPoint*)args[0].addr; Geoid* g = 0; if ( !input->IsDefined() ){ res->SetDefined(false); return 0; } if( qp->GetNoSons(s)==2 ){ // using (LON,LAT) and Geoid g = static_cast(args[1].addr); if(!g->IsDefined()){ res->SetDefined(false); return 0; } } input->USpeed( *res, g ); return 0; } /* 5.1.3 Specification for operator ~speed~ */ const std::string TemporalSpecSpeed = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( mpoint [x geoid] -> mreal\n" "upoint [x geoid] -> ureal" "speed( Obj [, Geoid] )" "Returns the scalar speed of a spatio-temporal object Obj in " "unit/s. If Geoid is used, coordinates in Obj are expected to be geographic " "(LON,LAT) coordinates and velocity is calculated in accordance to the geoid. " "Otherwise metric (X,Y) coordinates are assumed." "query speed(mp1) ) )"; /* 5.1.4 Selection Function of operator ~speed~ */ int SpeedSelect( ListExpr args ) { ListExpr arg1 = nl->First( args ); if( nl->SymbolValue( arg1 ) == MPoint::BasicType() ) return 0; if( nl->SymbolValue( arg1 ) == UPoint::BasicType() ) return 1; return -1; // This point should never be reached } ValueMapping temporalspeedmap[] = { MPointSpeed, UnitPointSpeed }; /* 5.1.5 Definition of operator ~speed~ */ Operator temporalspeed( "speed", TemporalSpecSpeed, 2, temporalspeedmap, SpeedSelect, TypeMapSpeed); /* 5.2 Operator ~queryrect2d~ 5.2.1 Type Mapping for ~queryresct2d~ Type mapping for ~queryrect2d~ is ---- instant [->] rect ---- */ ListExpr InstantTypeMapQueryrect2d( ListExpr args ) { if ( nl->ListLength( args ) == 1 ) { ListExpr arg1 = nl->First( args ); if( nl->IsEqual( arg1, Instant::BasicType() ) ) return nl->SymbolAtom( Rectangle<2>::BasicType() ); } return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.2.2 Value Mapping for ~queryrect2d~ */ int Queryrect2d(Word* args, Word& result, int message, Word& local, Supplier s) { const unsigned dim = 2; double min[dim], max[dim]; double timevalue; double mininst, maxinst; Instant* Inv = (Instant*)args[0].addr; datetime::DateTime tmpinst; tmpinst.ToMinimum(); mininst = tmpinst.ToDouble(); tmpinst.ToMaximum(); maxinst = tmpinst.ToDouble(); result = qp->ResultStorage( s ); if (Inv->IsDefined()) // Inv is defined: create rect2 { timevalue = Inv->ToDouble(); min[0] = mininst; // x1 min[1] = timevalue; // x2 max[0] = timevalue; // y1 max[1] = maxinst; // y2 Rectangle* rect = new Rectangle(true, min, max); ((Rectangle*)result.addr)->CopyFrom(rect); delete rect; } else // Inv is undefined: return mininst^4 { min[0] = mininst; min[1] = mininst; max[0] = mininst; max[1] = mininst; Rectangle* rect = new Rectangle(false, min, max); ((Rectangle*)result.addr)->CopyFrom(rect); delete rect; } return 0; } /* 5.2.3 Specification for operator ~queryrect2d~ */ const std::string TemporalSpecQueryrect2d = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( (instant) -> rect" "queryrect2d( _ )" "Translate an instant object to a rect object to query against " "a periods object translated to a point using operator 'point2d'. The " "undef instant is mapped to rect mininst^4" "query queryrect2d(instant) ) )"; /* 5.2.4 Selection Function of operator ~queryrect2d~ Not necessary. */ /* 5.2.5 Definition of operator ~queryrect2d~ */ Operator temporalunitqueryrect2d( "queryrect2d", TemporalSpecQueryrect2d, Queryrect2d, Operator::SimpleSelect, InstantTypeMapQueryrect2d); /* 5.3 Operator ~point2d~ 5.3.1 Type Mapping for ~point2d~ Type mapping for ~point2d~ is ---- periods [->] point ---- */ ListExpr PeriodsTypeMapPoint2d( ListExpr args ) { if ( nl->ListLength( args ) == 1 ) { ListExpr arg1 = nl->First( args ); if( nl->IsEqual( arg1, Periods::BasicType() ) ) return nl->SymbolAtom( Point::BasicType() ); } return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.3.2 Value Mapping for ~point2d~ */ int Point2d( Word* args, Word& result, int message, Word& local, Supplier s ) { double X, Y; Instant sup, inf; result = qp->ResultStorage( s ); Periods* range = (Periods*)args[0].addr; if ( !range->IsDefined() ) ((Point*)result.addr)->SetDefined( false ); else { X = 0; Y = 0; if( !range->IsEmpty() ) { Interval intv1, intv2; range->Get( 0, intv1 ); range->Get( range->GetNoComponents()-1, intv2 ); sup = intv1.end; inf = intv2.start; Y = sup.ToDouble(); // Derives the maximum of all intervals. X = inf.ToDouble(); // Derives the minimum of all intervals. ((Point*)result.addr)->Set(X,Y); // Returns the calculated point. ((Point*)result.addr)->SetDefined(true); } else { // empty periods -> set to (mininstant, mininstant) ((Point*)result.addr)->SetDefined( false ); } } return 0; } /* 5.3.3 Specification for operator ~point2d~ */ const std::string TemporalSpecPoint2d = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( (periods) -> point" "point2d( _ )" "Translates a periods value to a point value representing " "the period's total deftime interval. The empty periods value " "is mapped to the undefined point." "query point2d(periods) ) )"; /* 5.3.4 Selection Function of operator ~point2d~ Not necessary. */ /* 5.3.5 Definition of operator ~point2d~ */ Operator temporalunitpoint2d( "point2d", TemporalSpecPoint2d, Point2d, Operator::SimpleSelect, PeriodsTypeMapPoint2d); /* 5.4 Operator ~get\_duration~ 5.4.1 Type Mapping for ~get\_duration~ Type mapping for ~get\_duration~ is ---- periods [->] duration ---- */ ListExpr PeriodsTypeMapGetDuration( ListExpr args ) { if ( nl->ListLength( args ) == 1 ) { ListExpr arg1 = nl->First( args ); if( nl->IsEqual( arg1, Periods::BasicType() ) ) return nl->SymbolAtom( Duration::BasicType() ); } return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.4.2 Value Mapping for ~get\_duration~ */ int GetDuration( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); Periods* range = (Periods*)args[0].addr; datetime::DateTime* Res = ((datetime::DateTime*)result.addr); *Res = datetime::DateTime(0, 0, datetime::durationtype); if ( !range->IsDefined() ) ((datetime::DateTime*)result.addr)->SetDefined( false ); else { Res->SetDefined(true); if( !range->IsEmpty() ) { Interval intv; for( int i = 0; i < range->GetNoComponents(); i++ ) { range->Get( i, intv ); *Res += (intv.end - intv.start); } } } return 0; } /* 5.4.3 Specification for operator ~get\_duration~ */ const std::string TemporalSpecGetDuration = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( (periods) -> duration" "get_duration( _ )" "Return the duration in spanned by a periods value " "as a duration value." "query get_duration(periods) ) )"; /* 5.4.4 Selection Function of operator ~get\_duration~ Not necessary. */ /* 5.4.5 Definition of operator ~get\_duration~ */ Operator temporalunitget_duration( "get_duration", TemporalSpecGetDuration, GetDuration, Operator::SimpleSelect, PeriodsTypeMapGetDuration ); /* 5.5 Operators ~makemvalue~, ~the\_mvalue~ This operators create a moving object type mT from a stream of unit type objects uT. The operator does not expect the stream to be ordered by their timeintervals. Also, undefined units are allowed (but will be ignored). If the stream contains amindst 2 units with overlapping timeIntervals, the operator might crash. If the stream is empty, the result will be an empty mT. 5.5.1 Type Mapping for ~makemvalue~, ~the\_mvalue~ Type mapping for ~makemvalue~ is ---- stream (tuple ([x1:t1,x1:ubool,..,[xn:tn))) -> mbool APPEND (i ti) stream (tuple ([x1:t1,x1:uint,..,[xn:tn))) -> mint APPEND (i ti) stream (tuple ([x1:t1,x1:ureal,..,[xn:tn))) -> mreal APPEND (i ti) stream (tuple ([x1:t1,x1:upoint,..,[xn:tn))) -> mpoint APPEND (i ti) stream (tuple ([x1:t1,x1:ustring,..,[xn:tn))) -> mstring APPEND (i ti) NOT YET AVAILABLE DUE TO ERRORS: stream (tuple ([x1:t1,x1:uregion,..,[xn:tn))) -> mregion APPEND (i ti) ---- For ~the\_mvalue~, it is ---- the_mvalue: (stream uT) --> mT ---- */ ListExpr TU_TM_themvalue( ListExpr args ) { std::string errmsg = "Expected (stream T), where T " "in{ubool,uint,upoint,ustring}"; if(nl->ListLength(args) != 1){ return listutils::typeError(errmsg); } if(!listutils::isDATAStream(nl->First(args))){ return listutils::typeError(errmsg); } ListExpr elemtype = nl->Second(nl->First(args)); if(listutils::isSymbol(elemtype,UBool::BasicType())){ return nl->SymbolAtom( MBool::BasicType() ); } if(listutils::isSymbol(elemtype,UInt::BasicType())){ return nl->SymbolAtom( MInt::BasicType() ); } if(listutils::isSymbol(elemtype,UString::BasicType())){ return nl->SymbolAtom( MString::BasicType() ); } if(listutils::isSymbol(elemtype,UReal::BasicType())){ return nl->SymbolAtom( MReal::BasicType() ); } if(listutils::isSymbol(elemtype,UPoint::BasicType())){ return nl->SymbolAtom( MPoint::BasicType() ); } // if(listutils::isSymbol(elemtype,URegion::BasicType())){ // return nl->SymbolAtom( MRegion::BasicType() ); // } return listutils::typeError(errmsg); } ListExpr the_mvalue2TM(ListExpr args){ std::string err = "stream(UT) , T in {bool. int, real, " "string, point} expected"; if(!nl->HasLength(args,1)){ return listutils::typeError(err); } ListExpr a = nl->First(args); if(Stream::checkType(a)) return nl->SymbolAtom(MBool::BasicType()); if(Stream::checkType(a)) return nl->SymbolAtom(MInt::BasicType()); if(Stream::checkType(a)) return nl->SymbolAtom(MString::BasicType()); if(Stream::checkType(a)) return nl->SymbolAtom(MReal::BasicType()); if(Stream::checkType(a)) return nl->SymbolAtom(MPoint::BasicType()); return listutils::typeError(err); } ListExpr MovingTypeMapMakemvalue( ListExpr args ) { ListExpr first, second, rest, listn, lastlistn, first2, second2, firstr, listfull, attrtype; int j; std::string argstr, argstr2, attrname, inputtype, inputname, fulllist; //check the list length. if(nl->ListLength(args)!=2){ return listutils::typeError("two arguments expected"); } first = nl->First(args); nl->WriteToString(argstr, first); // check the structure of the list. if( !listutils::isTupleStream(first) ) { ErrorReporter::ReportError("Operator makemvalue expects as first argument " "a tuplestream, but gets '" + argstr + "'."); return nl->TypeError(); } // check the given parameter second = nl->Second(args); nl->WriteToString(argstr, second); if(argstr == Symbol::TYPEERROR()){ return listutils::typeError("invalid attrname" + argstr); } // inputname represented the name of the given attribute nl->WriteToString(inputname, second); rest = nl->Second(nl->Second(first)); listn = nl->OneElemList(nl->First(rest)); lastlistn = listn; firstr = nl->First(rest); rest = nl->Rest(rest); first2 = nl->First(firstr); second2 = nl->Second(firstr); nl->WriteToString(attrname, first2); nl->WriteToString(argstr2, second2); // compare with the attributes in the relation if (attrname == inputname) inputtype = argstr2; // save from the detected attribute the type while (!(nl->IsEmpty(rest))) { lastlistn = nl->Append(lastlistn,nl->First(rest)); firstr = nl->First(rest); rest = nl->Rest(rest); first2 = nl->First(firstr); second2 = nl->Second(firstr); nl->WriteToString(attrname, first2); nl->WriteToString(argstr2, second2); // compare with the attributes in the relation if (attrname == inputname) inputtype = argstr2; // save from the detected attribute the type } rest = second; listfull = listn; nl->WriteToString(fulllist, listfull); if(inputtype==""){ return listutils::typeError("attribute not found"); } if((inputtype != UBool::BasicType()) && (inputtype != UInt::BasicType()) && (inputtype != UReal::BasicType()) && (inputtype != UPoint::BasicType()) && (inputtype != UString::BasicType()) ) { return listutils::typeError("attr type not in {ubool, uint," " ustring, ureal, upoint"); } attrname = nl->SymbolValue(second); j = FindAttribute(nl->Second(nl->Second(first)), attrname, attrtype); assert( j !=0 ); if( inputtype == UPoint::BasicType() ) attrtype = nl->SymbolAtom( MPoint::BasicType() ) ; if( inputtype == UBool::BasicType() ) attrtype = nl->SymbolAtom( MBool::BasicType() ); if( inputtype == UReal::BasicType() ) attrtype = nl->SymbolAtom( MReal::BasicType() ); if( inputtype == UInt::BasicType() ) attrtype = nl->SymbolAtom( MInt::BasicType() ); if( inputtype == UString::BasicType() ) attrtype = nl->SymbolAtom( MString::BasicType() ); //if( inputtype == URegion::BasicType() ) // attrtype = nl->SymbolAtom( MRegion::BasicType()); return nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()), nl->TwoElemList(nl->IntAtom(j), nl->StringAtom(nl->SymbolValue(attrtype))), attrtype); // Appending the number of the attribute in the relation is very important, // because in the other case we can't work with it in the value function. } /* 5.5.2 Value Mapping for ~makemvalue~, ~the\_mvalue~ */ template int MappingMakemvalue(Word* args,Word& result,int message, Word& local,Supplier s) { Mapping* m; Unit* unit; Word currentTupleWord; assert(args[2].addr != 0); // assert existence of input assert(args[3].addr != 0); // assert existence of input int attributeIndex = ((CcInt*)args[2].addr)->GetIntval() - 1; qp->Open(args[0].addr); qp->Request(args[0].addr, currentTupleWord); result = qp->ResultStorage(s); m = (Mapping*) result.addr; m->Clear(); m->SetDefined( true ); m->StartBulkLoad(); while ( qp->Received(args[0].addr) ) // get all tuples { Tuple* currentTuple = (Tuple*)currentTupleWord.addr; Attribute* currentAttr = (Attribute*)currentTuple-> GetAttribute(attributeIndex); if(currentAttr == 0) { cout << endl << "ERROR in " << __PRETTY_FUNCTION__ << ": received Nullpointer!" << endl; assert( false ); } else if(currentAttr->IsDefined()) { unit = static_cast(currentAttr); m->Add( *unit ); } else { std::cerr << endl << __PRETTY_FUNCTION__ << ": Dropping undef unit. " << endl; } currentTuple->DeleteIfAllowed(); qp->Request(args[0].addr, currentTupleWord); } m->EndBulkLoad( true, true ); // force Mapping to sort the units qp->Close(args[0].addr); // and mark invalid Mapping as undefined return 0; } template int UCompare( const void *a, const void *b ) { Unit *unita = new ((void*)a) Unit, *unitb = new ((void*)b) Unit; int cmp= unita->Compare(unitb); return cmp; } template int MappingMakemvaluePlain(Word* args,Word& result,int message, Word& local,Supplier s) { Word currentUnit; Unit* unit1; Instant lastInst(datetime::instanttype, 0); bool lastRC= false; DbArray allUnits(0); qp->Open(args[0].addr); qp->Request(args[0].addr, currentUnit); result = qp->ResultStorage(s); Mapping* m = static_cast(result.addr); m->Clear(); m->SetDefined( true ); while ( qp->Received(args[0].addr) ) { // get all tuples unit1 = static_cast(currentUnit.addr); if(unit1 == 0) { cout << endl << __PRETTY_FUNCTION__ << ": Received Nullpointer!" << endl; assert( false ); } else if(unit1->IsDefined()) { allUnits.Append(*unit1); } else { std::cerr << endl << __PRETTY_FUNCTION__ << ": Dropping undef unit " << endl; } unit1->DeleteIfAllowed(); qp->Request(args[0].addr, currentUnit); } qp->Close(args[0].addr); if(allUnits.Size() == 0) return 0; allUnits.Sort( UCompare ); Unit unit2; allUnits.Get(0, unit2); lastInst= unit2.timeInterval.start; for(int i=0; i< allUnits.Size(); ++i) { allUnits.Get(i, unit2); if(unit2.timeInterval.start > lastInst || ((unit2.timeInterval.start == lastInst) && !(unit2.timeInterval.lc && lastRC) )) { m->MergeAdd( unit2 ); lastInst= unit2.timeInterval.end; lastRC= unit2.timeInterval.rc; } } return 0; } template int the_mvalue2VM1(Word* args, Word& result, int message, Word& local, Supplier s){ result = qp->ResultStorage(s); Mapping* res = (Mapping*)result.addr; res->Clear(); res->StartBulkLoad(); res->SetDefined(true); Stream stream(args[0]); Unit* unit; stream.open(); unit = stream.request(); Unit* lastUnit = 0; while(unit){ if(unit->IsDefined()){ if(lastUnit==0){ // first Unit res->MergeAdd(*unit); lastUnit = unit; } else { // not the first unit if((unit->timeInterval.start > lastUnit->timeInterval.end) || ( (unit->timeInterval.start == lastUnit->timeInterval.end) && (!unit->timeInterval.lc || !lastUnit->timeInterval.rc))){ // case : unit starts after lastUnit res->MergeAdd(*unit); lastUnit->DeleteIfAllowed(); lastUnit = unit; } else if(((unit->timeInterval.end) < (lastUnit->timeInterval.end)) || ((unit->timeInterval.end ==lastUnit->timeInterval.end) && (!unit->timeInterval.rc || lastUnit->timeInterval.rc))) { // no part of the unit if after the last unit // ignore this unit unit->DeleteIfAllowed(); } else { // unit overlaps lastUnit, but is longer than lastUnit Interval iv = unit->timeInterval; iv.start = lastUnit->timeInterval.end; iv.lc = !lastUnit->timeInterval.rc; Unit nUnit(true); unit->AtInterval(iv,nUnit); res->MergeAdd(nUnit); lastUnit->DeleteIfAllowed(); lastUnit = unit;; } } } // unit is defined unit = stream.request(); } if(lastUnit){ lastUnit->DeleteIfAllowed(); } stream.close(); res->EndBulkLoad(false); return 0; } // here comes the version for mregion, where URegion has a rather // ugly implementation and thus needs a specialized treatment! int MappingMakemvalue_movingregion(Word* args,Word& result,int message, Word& local,Supplier s) { MRegion* m; Word currentTupleWord; assert(args[2].addr != 0); // assert existence of input assert(args[3].addr != 0); // assert existence of input int attributeIndex = ((CcInt*)args[2].addr)->GetIntval() - 1; qp->Open(args[0].addr); qp->Request(args[0].addr, currentTupleWord); result = qp->ResultStorage(s); m = (MRegion*) result.addr; m->Clear(); m->SetDefined( true ); m->StartBulkLoad(); while ( qp->Received(args[0].addr) ) // get all tuples { Tuple* currentTuple = (Tuple*)currentTupleWord.addr; URegion* currentUnit = static_cast(currentTuple-> GetAttribute(attributeIndex)); if(currentUnit == 0) { cout << endl << __PRETTY_FUNCTION__ << ": Received Nullpointer!"<< endl; assert( false ); } else if(currentUnit->IsDefined()) { m->AddURegion( *currentUnit ); } else { std::cerr << endl << __PRETTY_FUNCTION__ << ": Dropping undef URegion " << endl; } currentTuple->DeleteIfAllowed(); qp->Request(args[0].addr, currentTupleWord); } m->EndBulkLoad( true, true ); // force Mapping to sort the units qp->Close(args[0].addr); // and mark invalid Mapping as undefined return 0; } int MappingMakemvalue_movingregionPlain(Word* args,Word& result,int message, Word& local,Supplier s) { MRegion* m; URegion* unit; Word currentUnit; qp->Open(args[0].addr); qp->Request(args[0].addr, currentUnit); result = qp->ResultStorage(s); m = (MRegion*) result.addr; m->Clear(); m->SetDefined( true ); m->StartBulkLoad(); while ( qp->Received(args[0].addr) ) // get all tuples { unit = (URegion*) currentUnit.addr; if(unit == 0) { cout << endl << __PRETTY_FUNCTION__ << ":received Nullpointer!" << endl; assert( false ); } else if(unit->IsDefined()) { m->AddURegion( *unit ); } else { std::cerr << endl << __PRETTY_FUNCTION__ << ": Dropping undef URegion " << endl; } unit->DeleteIfAllowed(); qp->Request(args[0].addr, currentUnit); } m->EndBulkLoad( true, true ); // force Mapping to sort the units qp->Close(args[0].addr); // and mark invalid Mapping as undefined return 0; } /* 5.5.3 Specification for operators ~makemvalue~, ~the\_mvalue~ */ const std::string TemporalSpecMakemvalue = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( For T in {bool, int, string, real, point, region*}:\n" "((stream (tuple ((x1 t1)...(xn tn))) (uT)))-> mT\n" "*: Not yet available" "_ makemvalue[ _ ]" "Create a moving object from a (not necessarily sorted) " "tuple stream containing a unit type attribute. " "No two unit timeintervals may overlap. Undefined units are " "allowed and will be ignored. A stream with less than 1 defined " "unit will result in an 'empty' moving object, not in an 'undef'." "query units(zug5) transformstream makemvalue[elem] ) )"; const std::string TemporalSpecThemvalue = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( For T in {bool, int, string, real, point, region*}:\n" "(stream uT) -> mT\n" "*: Not yet available" "_ the_mvalue" "Create a moving object from a (not necessarily sorted) " "object stream containing units. If two unit time intervals overlap, the unit " "that starts first is kept in the result, and the unit that starts later is " "ignored. Undefined units are allowed and will be ignored. A stream with less " "than 1 defined unit will result in an 'empty' moving object, not in an " "'undef'." "query units(zug5) the_mvalue ) )"; const std::string the_mvalue2Spec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( For T in {bool, int, string, real, point}:\n" "(stream uT) -> mT\n" "" "_ the_mvalue2" "Create a moving object from a sorted " "object stream containing units. " "Two units may overlap in time. The second unit will be shortened. " "" "query units(zug5) the_mvalue2 ) )"; /* 5.5.4 Selection Function of operators ~makemvalue~, ~the\_mvalue~ */ int ThemvalueSelect( ListExpr args ) { std::string argstr; nl->WriteToString(argstr, args); if ( argstr == "((stream ubool))" ) return 0; if ( argstr == "((stream uint))" ) return 1; if ( argstr == "((stream ustring))" ) return 2; if ( argstr == "((stream ureal))" ) return 3; if ( argstr == "((stream upoint))" ) return 4; if ( argstr == "((stream uregion))" ) return 5; return -1; // This point should never be reached } int the_mvalue2Select( ListExpr args ) { ListExpr t = nl->Second(nl->First(args)); if(UBool::checkType(t)) return 0; if(UInt::checkType(t)) return 1; if(UString::checkType(t)) return 2; if(UReal::checkType(t)) return 3; if(UPoint::checkType(t)) return 4; return -1; } int MakemvalueSelect( ListExpr args ) { ListExpr first, second, rest, listn, lastlistn, first2, second2, firstr; std::string argstr, argstr2, attrname, inputtype, inputname; first = nl->First(args); second = nl->Second(args); nl->WriteToString(argstr, first); nl->WriteToString(inputname, second); rest = nl->Second(nl->Second(first)); listn = nl->OneElemList(nl->First(rest)); lastlistn = listn; firstr = nl->First(rest); rest = nl->Rest(rest); first2 = nl->First(firstr); second2 = nl->Second(firstr); nl->WriteToString(attrname, first2); nl->WriteToString(argstr2, second2); if (attrname == inputname) inputtype = argstr2; while (!(nl->IsEmpty(rest))) { lastlistn = nl->Append(lastlistn,nl->First(rest)); firstr = nl->First(rest); rest = nl->Rest(rest); first2 = nl->First(firstr); second2 = nl->Second(firstr); nl->WriteToString(attrname, first2); nl->WriteToString(argstr2, second2); if (attrname == inputname) inputtype = argstr2; } if( inputtype == UBool::BasicType() ) return 0; if( inputtype == UInt::BasicType() ) return 1; if( inputtype == UString::BasicType() ) return 2; if( inputtype == UReal::BasicType() ) return 3; if( inputtype == UPoint::BasicType() ) return 4; if( inputtype == URegion::BasicType() ) return 5; return -1; // This point should never be reached } ValueMapping temporalmakemvaluemap[] = { MappingMakemvalue, MappingMakemvalue, MappingMakemvalue, MappingMakemvalue, MappingMakemvalue, MappingMakemvalue_movingregion} ; ValueMapping temporalthemvaluemap[] = { MappingMakemvaluePlain, MappingMakemvaluePlain, MappingMakemvaluePlain, MappingMakemvaluePlain, MappingMakemvaluePlain, MappingMakemvalue_movingregionPlain }; ValueMapping the_mvalue2VM[] = { the_mvalue2VM1, the_mvalue2VM1, the_mvalue2VM1, the_mvalue2VM1, the_mvalue2VM1 }; /* 5.5.5 Definition of operators ~makemvalue~, ~the\-mvalue~ */ Operator temporalunitmakemvalue( "makemvalue", TemporalSpecMakemvalue, 6, temporalmakemvaluemap, MakemvalueSelect, MovingTypeMapMakemvalue ); Operator temporalunitthemvalue( "the_mvalue", TemporalSpecThemvalue, 6, temporalthemvaluemap, ThemvalueSelect, TU_TM_themvalue ); Operator the_mvalue2( "the_mvalue2", the_mvalue2Spec, 5, the_mvalue2VM, the_mvalue2Select, the_mvalue2TM); /* 5.6 Operator ~trajectory~ 5.6.1 Type Mapping for ~trajectory~ */ ListExpr UnitTrajectoryTypeMap( ListExpr args ) { if ( nl->ListLength( args ) == 1 ) { ListExpr arg1 = nl->First( args ); if( nl->IsEqual( arg1, UPoint::BasicType() ) ) return nl->SymbolAtom( Line::BasicType() ); } return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.6.2 Value Mapping for ~trajectory~ */ int UnitPointTrajectory(Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); Line *line = ((Line*)result.addr); UPoint *upoint = ((UPoint*)args[0].addr); line->Clear(); // clear result if ( upoint->IsDefined() ){ line->SetDefined( true ); upoint->UTrajectory( *line ); // call memberfunction } else { line->SetDefined( false ); } return 0; } /* 5.6.3 Specification for operator ~trajectory~ */ const std::string TemporalSpecTrajectory = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( upoint -> line" "trajectory( _ )" "get the trajectory of the corresponding" "unit point object. Static upoint objects " "yield empty line objects, on undef argument, it returns undef." "trajectory( up1 ) ) )"; /* 5.6.4 Selection Function of operator ~trajectory~ Not necessary. */ /* 5.6.5 Definition of operator ~trajectory~ */ Operator temporalunittrajectory( "trajectory", TemporalSpecTrajectory, UnitPointTrajectory, Operator::SimpleSelect, UnitTrajectoryTypeMap ); /* 5.7 Operator ~deftime~ 5.7.1 Type Mapping for ~deftime~ */ ListExpr UnitTypeMapPeriods( ListExpr args ) { if ( nl->ListLength( args ) == 1 ) { ListExpr arg1 = nl->First( args ); if( nl->IsEqual( arg1, UBool::BasicType() ) || nl->IsEqual( arg1, UInt::BasicType() ) || nl->IsEqual( arg1, UReal::BasicType() ) || nl->IsEqual( arg1, UPoint::BasicType() ) || nl->IsEqual( arg1, UString::BasicType() ) || nl->IsEqual( arg1, URegion::BasicType() ) ) return nl->SymbolAtom( Periods::BasicType() ); } return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.7.2 Value Mapping for ~deftime~ */ template int MappingUnitDefTime( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); Periods* r = ((Periods*) result.addr); Unit* m = ((Unit*) args[0].addr); r->Clear(); if ( !m->IsDefined() ) r->SetDefined( false ); else { r->SetDefined( true ); r->StartBulkLoad(); r->Add( m->timeInterval ); r->EndBulkLoad( false ); } return 0; } /* 5.7.3 Specification for operator ~deftime~ */ const std::string TemporalSpecDefTime = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( uT -> periods \n" "(for T in {bool, int, real, string, point, region})" "deftime( _ )" "get the definition time for the " " unit data objects." "deftime( up1 ) ) )"; /* 5.7.4 Selection Function of operator ~deftime~ Uses ~UnitSimpleSelect~. */ ValueMapping temporalunitdeftimemap[] = { MappingUnitDefTime, MappingUnitDefTime, MappingUnitDefTime, MappingUnitDefTime, MappingUnitDefTime, MappingUnitDefTime}; /* 5.7.5 Definition of operator ~deftime~ */ Operator temporalunitdeftime( "deftime", TemporalSpecDefTime, 6, temporalunitdeftimemap, UnitSimpleSelect, UnitTypeMapPeriods ); /* 5.8 Operator ~atinstant~ 5.8.1 Type Mapping for ~atinstant~ */ ListExpr UnitInstantTypeMapIntime( ListExpr args ) { if ( nl->ListLength( args ) == 2 ) { ListExpr arg1 = nl->First( args ), arg2 = nl->Second( args ); if( nl->IsEqual( arg2, Instant::BasicType() ) ) { if( nl->IsEqual( arg1, UBool::BasicType() ) ) return nl->SymbolAtom( IBool::BasicType() ); if( nl->IsEqual( arg1, UInt::BasicType() ) ) return nl->SymbolAtom( IInt::BasicType() ); if( nl->IsEqual( arg1, UReal::BasicType() ) ) return nl->SymbolAtom( IReal::BasicType() ); if( nl->IsEqual( arg1, UPoint::BasicType() ) ) return nl->SymbolAtom( IPoint::BasicType() ); if( nl->IsEqual( arg1, UString::BasicType() ) ) return nl->SymbolAtom( IString::BasicType() ); if( nl->IsEqual( arg1, URegion::BasicType() ) ) return nl->SymbolAtom( IRegion::BasicType() ); } } return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.8.2 Value Mapping for ~atinstant~ */ template int MappingUnitAtInstant( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); Intime* pResult = (Intime*)result.addr; Mapping* posUnit = ((Mapping*)args[0].addr); Instant* t = ((Instant*)args[1].addr); if ( !t->IsDefined() || !posUnit->IsDefined() ) { pResult->SetDefined( false ); } else if( posUnit->timeInterval.Contains(*t) ) { posUnit->TemporalFunction( *t, pResult->value ); pResult->instant = *t; pResult->SetDefined( true ); } else { // instant not contained by deftime interval pResult->SetDefined( false ); } return 0; } /* 5.8.3 Specification for operator ~atinstant~ */ const std::string TemporalSpecAtInstant = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( (uT instant) -> iT\n" "(T in {bool, int, real, string, point, region})" "_ atinstant _ " "From a unit type, get the Intime value corresponding to " "the given instant." "upoint1 atinstant instant1 ) )"; /* 5.8.4 Selection Function of operator ~atinstant~ Uses ~UnitSimpleSelect~. */ ValueMapping temporalunitatinstantmap[] = {MappingUnitAtInstant, MappingUnitAtInstant, MappingUnitAtInstant, MappingUnitAtInstant, MappingUnitAtInstant, MappingUnitAtInstant}; /* 5.8.5 Definition of operator ~atinstant~ */ Operator temporalunitatinstant( "atinstant", TemporalSpecAtInstant, 6, temporalunitatinstantmap, UnitSimpleSelect, UnitInstantTypeMapIntime ); /* 5.9 Operator ~atperiods~ 5.9.1 Type Mapping for ~atperiods~ */ ListExpr UnitPeriodsTypeMap( ListExpr args ) { ListExpr arg1, arg2; std::string argstr; if ( nl->ListLength( args ) != 2 ) { ErrorReporter::ReportError("Operator atperiods expects " "a list of length 2."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } arg1 = nl->First( args ); arg2 = nl->Second( args ); nl->WriteToString(argstr, arg2); if ( !( nl->IsEqual( arg2, Periods::BasicType() ) ) ) { ErrorReporter::ReportError("Operator atperiods expects a second argument" " of type 'periods' but gets '" + argstr + "'."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } if( nl->IsAtom( arg1 ) ) { if( nl->IsEqual( arg1, UBool::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UBool::BasicType())); if( nl->IsEqual( arg1, UInt::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UInt::BasicType())); if( nl->IsEqual( arg1, UReal::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UReal::BasicType())); if( nl->IsEqual( arg1, UPoint::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UPoint::BasicType())); if( nl->IsEqual( arg1, UString::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UString::BasicType())); if( nl->IsEqual( arg1, URegion::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(URegion::BasicType())); nl->WriteToString(argstr, arg1); ErrorReporter::ReportError("Operator atperiods expects a first argument " "of type T in {ubool, uint, ureal, upoint, " "ustring, uregion} but gets a '" + argstr + "'."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } if(!Stream::checkType(arg1)){ return listutils::typeError("Operator atperiods expects as first " "argument a list with structure 'T' or " "'stream(T)', T in {ubool, uint, ureal, " "upoint, ustring, ureagion} but gets a " "list with structure '" + argstr + "'."); } if( nl->IsEqual( nl->Second(arg1), UBool::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UBool::BasicType())); if( nl->IsEqual( nl->Second(arg1), UInt::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UInt::BasicType())); if( nl->IsEqual( nl->Second(arg1), UReal::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UReal::BasicType())); if( nl->IsEqual( nl->Second(arg1), UPoint::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UPoint::BasicType())); if( nl->IsEqual( nl->Second(arg1), UString::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UString::BasicType())); if( nl->IsEqual( nl->Second(arg1), URegion::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(URegion::BasicType())); nl->WriteToString(argstr, nl->Second(arg1)); ErrorReporter::ReportError("Operator atperiods expects a type " "(stream T); T in {ubool, uint, ureal, upoint, " "ustring, uregion} but gets '(stream " + argstr + ")'."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.9.2 Value Mapping for ~atperiods~ */ struct AtPeriodsLocalInfo { Word uWord; // the address of the unit value Word pWord; // the adress of the periods value int j; // save the number of the interval }; /* Variant 1: first argument is a scalar value */ template int MappingUnitAtPeriods( Word* args, Word& result, int message, Word& local, Supplier s ) { AtPeriodsLocalInfo *localinfo; Interval interval; Alpha *unit; Alpha r(true); Periods* periods; switch( message ) { case OPEN: // #ifdef TUA_DEBUG // cout << "\nMappingUnitAtPeriods: OPEN" << endl; // #endif localinfo = new AtPeriodsLocalInfo; localinfo->uWord = args[0]; localinfo->pWord = args[1]; localinfo->j = 0; local.setAddr(localinfo); return 0; case REQUEST: // #ifdef TUA_DEBUG // cout << "\nMappingUnitAtPeriods: REQUEST" << endl; // #endif if( local.addr == 0 ) return CANCEL; localinfo = (AtPeriodsLocalInfo *)local.addr; unit = (Alpha*)localinfo->uWord.addr; periods = (Periods*)localinfo->pWord.addr; if( !unit->IsDefined() || !periods->IsDefined() || periods->IsEmpty() ) { result.setAddr(0); return CANCEL; } // #ifdef TUA_DEBUG // cout << " Unit's timeInterval u=" // << TUPrintTimeInterval( unit->timeInterval ) << endl; // #endif if( localinfo->j >= periods->GetNoComponents() ) { result.setAddr(0); // #ifdef TUA_DEBUG // cout << "Maquery train7 inside train7sectionsppingUnitAtPeriods: " // << "REQUEST finished: CANCEL (1)" // << endl; // #endif return CANCEL; } periods->Get( localinfo->j, interval ); localinfo->j++; // #ifdef TUA_DEBUG // cout << " Probing timeInterval p =" // << TUPrintTimeInterval(interval) // << endl; // #endif while( interval.Before( unit->timeInterval ) && localinfo->j < periods->GetNoComponents() ) { // forward to first candidate interval periods->Get(localinfo->j, interval); localinfo->j++; // #ifdef TUA_DEBUG // cout << " Probing timeInterval=" // << TUPrintTimeInterval(interval) // << endl; // if (interval.Before( unit->timeInterval )) // cout << " p is before u" << endl; // if (localinfo->j < periods->GetNoComponents()) // cout << " j < #Intervals" << endl; // #endif } if( unit->timeInterval.Before( interval ) ) { // interval after unit-deftime --> finished result.addr = 0; // #ifdef TUA_DEBUG // cout << "MappingUnitAtPeriods: REQUEST finished: CANCEL (2)" // << endl; // #endif return CANCEL; } if(unit->timeInterval.Intersects( interval )) { // interval intersectd unit's deftime --> produce result // create unit restricted to interval unit->AtInterval( interval, r ); Alpha* aux = new Alpha( r ); result.setAddr( aux ); // #ifdef TUA_DEBUG // cout << " Result interval=" // << TUPrintTimeInterval(aux->timeInterval) // << endl; // cout << " Result defined=" << aux->IsDefined() // << endl; // cout << "MappingUnitAtPeriods: REQUEST finished: YIELD" // << endl; // #endif return YIELD; } if( localinfo->j >= periods->GetNoComponents() ) { // Passed last interval --> finished result.addr = 0; // #ifdef TUA_DEBUG // cout << "MappingUnitAtPeriods: REQUEST finished: CANCEL (3)" // << endl; // #endif return CANCEL; } result.setAddr(0 ); cout << "MappingUnitAtPeriods: REQUEST finished: CANCEL (4)" << endl; cout << "Intervals should overlap: " << endl; cout << " Unit's timeInterval = "; TUPrintTimeInterval(unit->timeInterval); cout << " Current Period's interval = "; TUPrintTimeInterval(interval); cout << endl; assert( false ); return CANCEL; // should not happen case CLOSE: if( local.addr != 0 ) { delete (AtPeriodsLocalInfo *)local.addr; local.setAddr(Address(0)); } return 0; } // should not happen: return -1; } /* Variant 2: first argument is a stream Implemented on 07/17/2006 by Christian D[ue]ntgen */ struct AtPeriodsLocalInfoUS { Word uWord; // address of the input stream Word pWord; // address of the input periods value int j; // interval counter for within periods }; template int MappingUnitStreamAtPeriods( Word* args, Word& result, int message, Word& local, Supplier s ) { AtPeriodsLocalInfoUS *localinfo; Alpha *unit, *aux; Alpha resultUnit(true); Periods *periods; Interval interval; bool foundUnit = false; switch( message ) { case OPEN: localinfo = new AtPeriodsLocalInfoUS; localinfo->pWord = args[1]; localinfo->j = 0; // init interval counter qp->Open( args[0].addr ); // open stream of units qp->Request( args[0].addr, localinfo->uWord ); // request first unit if ( !( qp->Received( args[0].addr) ) ){ localinfo->uWord.addr = 0; result.addr = 0; return CANCEL; } local.setAddr(localinfo); // pass up link to localinfo return 0; case REQUEST: if ( local.addr == 0 ) return CANCEL; localinfo = (AtPeriodsLocalInfoUS *) local.addr; // restore local data if ( localinfo->uWord.addr == 0 ) { result.addr = 0; return CANCEL; } unit = (Alpha *) localinfo->uWord.addr; if ( localinfo->pWord.addr == 0 ) { result.addr = 0; return CANCEL; } periods = (Periods *) localinfo->pWord.addr; if( !periods->IsDefined() || periods->IsEmpty() ) return CANCEL; // search for a pair of overlapping unit/interval: while (1){ if ( localinfo->j == periods->GetNoComponents() ){// redo first interval localinfo->j = 0; unit->DeleteIfAllowed(); // delete original unit? localinfo->uWord.addr = 0; foundUnit = false; while(!foundUnit){ qp->Request(args[0].addr, localinfo->uWord); // get new unit if( qp->Received( args[0].addr ) ) unit = (Alpha *) localinfo->uWord.addr; else { localinfo->uWord.addr = 0; result.addr = 0; return CANCEL; } // end of unit stream foundUnit = unit->IsDefined(); } } periods->Get(localinfo->j, interval); // get an interval if ( !( interval.Before( unit->timeInterval ) ) && !( unit->timeInterval.Before( interval) ) ) break; // found candidate, break while localinfo->j++; // next interval, loop } // We have an interval overlapping the unit's interval now // Return unit restricted to overlapping part of both intervals if (!unit->timeInterval.Intersects( interval) ){ // This may not happen! cout << __FILE__ << __LINE__ << __PRETTY_FUNCTION__ << ": Intervals do not overlap, but should do so:" << endl; cout << " Unit's timeInterval = "; TUPrintTimeInterval(unit->timeInterval); cout << endl << " Current Period's interval = "; TUPrintTimeInterval(interval); cout << endl; assert(false); } unit->AtInterval( interval, resultUnit); // intersect unit and interval aux = new Alpha( resultUnit ); result.setAddr( aux ); localinfo->j++; // increase interval counter return YIELD; case CLOSE: if ( local.addr != 0 ) { qp->Close( args[0].addr ); localinfo = (AtPeriodsLocalInfoUS *) local.addr; if ( localinfo->uWord.addr != 0 ) { unit = (Alpha *) localinfo->uWord.addr; unit->DeleteIfAllowed(); // delete remaining original unit } delete (AtPeriodsLocalInfoUS *)localinfo; local.setAddr(Address(0)); } return 0; } // end switch return -1; // should never be reached } // end MappingUnitStreamAtPeriods /* 5.9.3 Specification for operator ~atperiods~ */ const std::string TemporalSpecAtPeriods = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\") " "( For T in {int, bool, real, string, point, region}:\n" "(uT periods) -> stream uT\n" "((stream uT) periods) -> stream uT" "_ atperiods _ " "restrict the movement to the given" " periods." "upoint1 atperiods thehour(2003,11,11,8)\n" "sfeed(upoint1) atperiods thehour(2003,11,11,8)) )"; /* 5.9.4 Selection Function of operator ~atperiods~ Uses ~UnitCombinedUnitStreamSelect~. */ ValueMapping temporalunitatperiodsmap[] = { MappingUnitAtPeriods, MappingUnitAtPeriods, MappingUnitAtPeriods, MappingUnitAtPeriods, MappingUnitAtPeriods, MappingUnitAtPeriods, MappingUnitStreamAtPeriods, MappingUnitStreamAtPeriods, MappingUnitStreamAtPeriods, MappingUnitStreamAtPeriods, MappingUnitStreamAtPeriods, MappingUnitStreamAtPeriods }; /* 5.9.5 Definition of operator ~atperiods~ */ Operator temporalunitatperiods( "atperiods", TemporalSpecAtPeriods, 12, temporalunitatperiodsmap, UnitCombinedUnitStreamSelect, UnitPeriodsTypeMap ); /* 5.10 Operators ~initial~ and ~final~ 5.10.1 Type Mapping for ~initial~ and ~final~ Signatures ---- For T in {bool, int, real, string, point, region}: ( uT) --> iT (stream uT) --> iT ---- */ ListExpr UnitTypeMapIntime( ListExpr args ) { ListExpr t; if ( nl->ListLength( args ) == 1 ) { if (nl->IsAtom(nl->First(args))) t = nl->First( args ); else if (nl->ListLength(nl->First(args))==2 && nl->IsEqual(nl->First(nl->First(args)), Symbol::STREAM())) t = nl->Second(nl->First(args)); else { ErrorReporter::ReportError ("Operator initial/final expects a (stream T)" "for T in {bool,int,real,string,point,region}"); return nl->SymbolAtom( Symbol::TYPEERROR() ); } if( nl->IsEqual( t, UBool::BasicType() ) ) return nl->SymbolAtom( IBool::BasicType() ); if( nl->IsEqual( t, UInt::BasicType() ) ) return nl->SymbolAtom( IInt::BasicType() ); if( nl->IsEqual( t, UReal::BasicType() ) ) return nl->SymbolAtom( IReal::BasicType() ); if( nl->IsEqual( t, UPoint::BasicType() ) ) return nl->SymbolAtom( IPoint::BasicType() ); if( nl->IsEqual( t, UString::BasicType() ) ) return nl->SymbolAtom( IString::BasicType() ); if( nl->IsEqual( t, URegion::BasicType() ) ) return nl->SymbolAtom( IRegion::BasicType() ); } else ErrorReporter::ReportError ("Operator initial/final expects a list of length one, " "containing a value of one type 'T' with T in " "{bool,int,real,string,point,region}"); return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.10.2 Value Mapping for ~initial~ and ~final~ */ // first come the value mappings for (UNIT) argument template int MappingUnitInitial( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); Unit* unit = ((Unit*)args[0].addr); Intime* res = ((Intime*)result.addr); if( !unit->IsDefined() || !(unit->timeInterval.start.IsDefined()) ) res->SetDefined( false ); else { unit->TemporalFunction( unit->timeInterval.start, res->value, true ); res->instant.CopyFrom( &unit->timeInterval.start ); res->SetDefined( true ); } return 0; } template int MappingUnitFinal( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); Unit *unit = ((Unit*)args[0].addr); Intime *res = ((Intime*)result.addr); if( !unit->IsDefined() || !(unit->timeInterval.end.IsDefined()) ) res->SetDefined( false ); else { unit->TemporalFunction( unit->timeInterval.end, res->value, true ); res->instant.CopyFrom( &unit->timeInterval.end ); res->SetDefined( true ); } return 0; } //now, we give the value mappings for (stream UNIT) argument // Mode=0 for initial, Mode=1 for final template int MappingUnitStreamInstantFinal( Word* args, Word& result, int message, Word& local, Supplier s ) { assert(Mode>=0 && Mode<=1); result = qp->ResultStorage( s ); Word elem; Unit *U = 0, *SavedUnit = 0; Intime *I = ((Intime*)result.addr); qp->Open(args[0].addr); // get first elem from stream qp->Request(args[0].addr, elem); // get first elem from stream while ( qp->Received(args[0].addr) ) // there is a element from the stream { U = (Unit*) elem.addr; if ( U->IsDefined() ) { if (SavedUnit == 0) SavedUnit = U; else { if(Mode == 0) { // initial-mode if ( U->timeInterval.start < SavedUnit->timeInterval.start) { SavedUnit->DeleteIfAllowed(); SavedUnit = U; } else U->DeleteIfAllowed(); } else // (Mode == 1) { // final-mode if ( U->timeInterval.end > SavedUnit->timeInterval.end) { SavedUnit->DeleteIfAllowed(); SavedUnit = U; } else { U->DeleteIfAllowed(); } } } } else U->DeleteIfAllowed(); qp->Request(args[0].addr, elem); // get next stream elem } qp->Close(args[0].addr); // close the stream // create and return the result if (SavedUnit == 0) I->SetDefined(false); else if(Mode == 0) { // initial-mode SavedUnit->TemporalFunction ( SavedUnit->timeInterval.start, I->value, true ); I->instant.CopyFrom( &SavedUnit->timeInterval.start ); I->SetDefined( true ); SavedUnit->DeleteIfAllowed(); } else // (Mode == 1) { // final-mode SavedUnit->TemporalFunction ( SavedUnit->timeInterval.end, I->value, true ); I->instant.CopyFrom( &SavedUnit->timeInterval.end ); I->SetDefined( true ); SavedUnit->DeleteIfAllowed(); } return 0; } /* 5.10.3 Specification for operator ~initial~ and ~final~ */ const std::string TemporalSpecInitial = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( ( uT) -> iT\n" "(stream uT) -> iT\n" "(T in {bool, int, real, string, point, region})" "initial( _ )" "From a unit type (or a stream of units), get the " "intime value corresponding to the (overall) initial instant." "initial( upoint1 ) ) )"; const std::string TemporalSpecFinal = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( ) uT) -> iT\n" "(stream uT) -> iT\n" "(T in {bool, int, real, string, point, region})" "final( _ )" "get the intime value corresponding " "to the (overall) final instant of the (stream of) unit." "final( upoint1 ) ) )"; /* 5.10.4 Selection Function of operator ~initial~ and ~final~ Using ~UnitCombinedUnitStreamSelect~. */ ValueMapping temporalunitinitialmap[] = { MappingUnitInitial, MappingUnitInitial, MappingUnitInitial, MappingUnitInitial, MappingUnitInitial, MappingUnitInitial, MappingUnitStreamInstantFinal, MappingUnitStreamInstantFinal, MappingUnitStreamInstantFinal, MappingUnitStreamInstantFinal, MappingUnitStreamInstantFinal, MappingUnitStreamInstantFinal }; ValueMapping temporalunitfinalmap[] = { MappingUnitFinal, MappingUnitFinal, MappingUnitFinal, MappingUnitFinal, MappingUnitFinal, MappingUnitFinal, MappingUnitStreamInstantFinal, MappingUnitStreamInstantFinal, MappingUnitStreamInstantFinal, MappingUnitStreamInstantFinal, MappingUnitStreamInstantFinal, MappingUnitStreamInstantFinal }; /* 5.10.5 Definition of operator ~initial~ and ~final~ */ Operator temporalunitinitial ( "initial", TemporalSpecInitial, 12, temporalunitinitialmap, UnitCombinedUnitStreamSelect, UnitTypeMapIntime ); Operator temporalunitfinal ( "final", TemporalSpecFinal, 12, temporalunitfinalmap, UnitCombinedUnitStreamSelect, UnitTypeMapIntime ); /* 5.11 Operator ~present~ 5.11.1 Type Mapping for ~present~ */ ListExpr UnitInstantPeriodsTypeMapBool( ListExpr args ) { if ( nl->ListLength( args ) == 2 ) { ListExpr arg1 = nl->First( args ), arg2 = nl->Second( args ); if( nl->IsEqual( arg2, Instant::BasicType() ) || nl->IsEqual( arg2, Periods::BasicType() ) ) { if( nl->IsEqual( arg1, UBool::BasicType() ) || nl->IsEqual( arg1, UInt::BasicType() ) || nl->IsEqual( arg1, UReal::BasicType() ) || nl->IsEqual( arg1, UPoint::BasicType()) || nl->IsEqual( arg1, UString::BasicType()) || nl->IsEqual( arg1, URegion::BasicType()) ) return nl->SymbolAtom( CcBool::BasicType() ); } } return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.11.2 Value Mapping for ~present~ */ template int MappingUnitPresent_i( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); Unit *m = ((Unit*)args[0].addr); Instant* inst = ((Instant*)args[1].addr); Instant t1 = *inst; if ( !inst->IsDefined() || !m->IsDefined() ) ((CcBool *)result.addr)->Set( false, false ); else ((CcBool *)result.addr)->Set( true, m->timeInterval.Contains(t1) ); return 0; } template int MappingUnitPresent_p( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); Unit *m = ((Unit*)args[0].addr); Periods* periods = ((Periods*)args[1].addr); if ( !m->IsDefined() || !periods->IsDefined() || periods->IsEmpty() ) { ((CcBool *)result.addr)->Set( false, false ); return 0; } // create a periods containing the smallest superinterval // of all intervals within the periods value. Periods deftime( 1 ); deftime.Clear(); deftime.SetDefined( true ); deftime.StartBulkLoad(); deftime.Add( m->timeInterval ); deftime.EndBulkLoad( false ); ((CcBool *)result.addr)->Set( true, periods->Intersects( deftime ) ); return 0; } /* 5.11.3 Specification for operator ~present~ */ const std::string TemporalSpecPresent = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( ({m|u}T instant) -> bool\n" "({m|u}T periods) -> bool\n" "(T in {bool, int, real, string, point, region)" "_ present _ " "whether the moving/unit object is present at the" " given instant or period. For an empty or undefines periods value, " "the result is undefined." "mpoint1 present instant1 ) )"; /* 5.11.4 Selection Function of operator ~present~ */ int UnitInstantPeriodsSelect( ListExpr args ) { ListExpr arg1 = nl->First( args ), arg2 = nl->Second( args ); // instant versions: if( nl->SymbolValue( arg1 ) == UBool::BasicType() && nl->SymbolValue( arg2 ) == Instant::BasicType() ) return 0; if( nl->SymbolValue( arg1 ) == UInt::BasicType() && nl->SymbolValue( arg2 ) == Instant::BasicType() ) return 1; if( nl->SymbolValue( arg1 ) == UReal::BasicType() && nl->SymbolValue( arg2 ) == Instant::BasicType() ) return 2; if( nl->SymbolValue( arg1 ) == UPoint::BasicType() && nl->SymbolValue( arg2 ) == Instant::BasicType() ) return 3; if( nl->SymbolValue( arg1 ) == UString::BasicType() && nl->SymbolValue( arg2 ) == Instant::BasicType() ) return 4; if( nl->SymbolValue( arg1 ) == URegion::BasicType() && nl->SymbolValue( arg2 ) == Instant::BasicType() ) return 5; // periods versions: if( nl->SymbolValue( arg1 ) == UBool::BasicType() && nl->SymbolValue( arg2 ) == Periods::BasicType() ) return 6; if( nl->SymbolValue( arg1 ) == UInt::BasicType() && nl->SymbolValue( arg2 ) == Periods::BasicType() ) return 7; if( nl->SymbolValue( arg1 ) == UReal::BasicType() && nl->SymbolValue( arg2 ) == Periods::BasicType() ) return 8; if( nl->SymbolValue( arg1 ) == UPoint::BasicType() && nl->SymbolValue( arg2 ) == Periods::BasicType() ) return 9; if( nl->SymbolValue( arg1 ) == UString::BasicType() && nl->SymbolValue( arg2 ) == Periods::BasicType() ) return 10; if( nl->SymbolValue( arg1 ) == URegion::BasicType() && nl->SymbolValue( arg2 ) == Periods::BasicType() ) return 11; return -1; // This point should never be reached } ValueMapping temporalunitpresentmap[] = { MappingUnitPresent_i, MappingUnitPresent_i, MappingUnitPresent_i, MappingUnitPresent_i, MappingUnitPresent_i, MappingUnitPresent_i, MappingUnitPresent_p, MappingUnitPresent_p, MappingUnitPresent_p, MappingUnitPresent_p, MappingUnitPresent_p, MappingUnitPresent_p }; /* 5.11.5 Definition of operator ~present~ */ Operator temporalunitpresent( "present", TemporalSpecPresent, 12, temporalunitpresentmap, UnitInstantPeriodsSelect, UnitInstantPeriodsTypeMapBool); /* 5.12 Operator ~passes~ 5.12.1 Type Mapping for ~passes~ */ ListExpr UnitBaseTypeMapBool( ListExpr args ) { ListExpr arg1, arg2; if( nl->ListLength( args ) == 2 ) { arg1 = nl->First( args ); arg2 = nl->Second( args ); if( ((nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, Point::BasicType() ))) ) return nl->SymbolAtom( CcBool::BasicType() ); if( ((nl->IsEqual( arg1, UInt::BasicType() ) && nl->IsEqual( arg2, CcInt::BasicType() ))) ) return nl->SymbolAtom( CcBool::BasicType() ); if( ((nl->IsEqual( arg1, UBool::BasicType() ) && nl->IsEqual( arg2, CcBool::BasicType() ))) ) return nl->SymbolAtom( CcBool::BasicType() ); if( ((nl->IsEqual( arg1, UReal::BasicType() ) && nl->IsEqual( arg2, CcReal::BasicType() ))) ) return nl->SymbolAtom( CcBool::BasicType() ); if( ((nl->IsEqual( arg1, UString::BasicType() ) && nl->IsEqual( arg2, CcString::BasicType() ))) ) return nl->SymbolAtom( CcBool::BasicType() ); if( ((nl->IsEqual( arg1, URegion::BasicType() ) && nl->IsEqual( arg2, Point::BasicType() ))) ) return nl->SymbolAtom( CcBool::BasicType() ); if( ((nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, Region::BasicType() ))) ) return nl->SymbolAtom( CcBool::BasicType() ); if( ((nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, Rectangle<2>::BasicType() ))) ) return nl->SymbolAtom( CcBool::BasicType() ); } return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.12.2 Value Mapping for ~passes~ */ template int MappingUnitPasses( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); Mapping *m = ((Mapping*)args[0].addr); Alpha* val = ((Alpha*)args[1].addr); if( !val->IsDefined() || !m->IsDefined() ) ((CcBool *)result.addr)->Set( false, false ); else ((CcBool *)result.addr)->Set( true, m->Passes( *val ) ); return 0; } /* 5.12.3 Specification for operator ~passes~ */ const std::string TemporalSpecPasses = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( (uT T) -> bool\n" "for T in {bool, int, real*, string, point, region*}\n" "(*): Not yet implemented" "_ passes _ " "whether the object unit passes the given" " value." "upoint1 passes point1 ) )"; /* 5.12.4 Selection Function of operator ~passes~ */ int TUPassesSelect( ListExpr args ) { ListExpr arg1 = nl->First( args ), arg2 = nl->Second( args ); if( nl->SymbolValue( arg1 ) == UBool::BasicType() && nl->SymbolValue( arg2 ) == CcBool::BasicType() ) return 0; if( nl->SymbolValue( arg1 ) == UInt::BasicType() && nl->SymbolValue( arg2 ) == CcInt::BasicType() ) return 1; if( nl->SymbolValue( arg1 ) == UReal::BasicType() && nl->SymbolValue( arg2 ) == CcReal::BasicType() ) return 2; if( nl->SymbolValue( arg1 ) == UPoint::BasicType() && nl->SymbolValue( arg2 ) == Point::BasicType() ) return 3; if( nl->SymbolValue( arg1 ) == UString::BasicType() && nl->SymbolValue( arg2 ) == CcString::BasicType() ) return 4; if( nl->SymbolValue( arg1 ) == URegion::BasicType() && nl->SymbolValue( arg2 ) == Region::BasicType() ) return 5; if( nl->SymbolValue( arg1 ) == UPoint::BasicType() && nl->SymbolValue( arg2 ) == Region::BasicType() ) return 6; if( nl->SymbolValue( arg1 ) == UPoint::BasicType() && nl->SymbolValue( arg2 ) == Rectangle<2>::BasicType() ) return 7; return -1; // This point should never be reached } ValueMapping temporalunitpassesmap[] = { MappingUnitPasses, //0 MappingUnitPasses, //1 MappingUnitPasses, //2 MappingUnitPasses, //3 MappingUnitPasses, //4 MappingUnitPasses, //5 MappingUnitPasses, //6 MappingUnitPasses >}; //7 /* 5.12.5 Definition of operator ~passes~ */ Operator temporalunitpasses( "passes", TemporalSpecPasses, 8, temporalunitpassesmap, TUPassesSelect, UnitBaseTypeMapBool); /* 5.16 Operator ~velocity~ Type mapping for ~velocity~ is ---- mpoint -> mpoint upoint -> upoint ---- */ ListExpr TypeMapVelocity( ListExpr args ) { ListExpr arg1; if( nl->ListLength( args ) == 1 ) { arg1 = nl->First( args ); if( nl->IsEqual( arg1, MPoint::BasicType() ) ) return nl->SymbolAtom( MPoint::BasicType() ); if( nl->IsEqual( arg1, UPoint::BasicType() ) ) return nl->SymbolAtom( UPoint::BasicType() ); } return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.16.2 Value Mapping for ~velocity~ */ int MPointVelocity(Word* args, Word& result, int message, Word& local, Supplier s) { result = (qp->ResultStorage( s )); MPoint *res = (MPoint*) result.addr; MPoint *input = (MPoint*)args[0].addr; input->MVelocity( *res ); return 0; } int UnitPointVelocity(Word* args, Word& result, int message, Word& local, Supplier s) { result = (qp->ResultStorage( s )); UPoint *input = (UPoint*)args[0].addr; UPoint *res = (UPoint*)result.addr; input->UVelocity( *res ); return 0; } /* 5.16.3 Specification for operator ~velocity~ */ const std::string TemporalSpecVelocity= "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( mpoint -> mpoint\n" "upoint -> upoint" "velocity ( Obj ) " "describes the vector of the vectorial velocity " "of the given temporal spatial object Obj (i.e. the " "componentwise speed in unit/s a vector). An undefined argument yields an " "undefined result value" "velocity (mpoint) ) )"; /* 5.16.4 Selection Function of operator ~velocity~ */ int VelocitySelect( ListExpr args ) { ListExpr arg1 = nl->First( args ); if( nl->SymbolValue( arg1 ) == MPoint::BasicType()) return 0; if( nl->SymbolValue( arg1 ) == UPoint::BasicType()) return 1; return -1; // This point should never be reached } ValueMapping temporalvelocitymap[] = { MPointVelocity, UnitPointVelocity }; /* 5.16.5 Definition of operator ~velocity~ */ Operator temporalvelocity( "velocity", TemporalSpecVelocity, 2, temporalvelocitymap, VelocitySelect, TypeMapVelocity); /* 5.17 Operator ~derivable~ 5.17.1 Type Mapping for ~derivable~ Type mapping for ~derivable~ is ---- mreal -> mbool ---- */ ListExpr TypeMapDerivable( ListExpr args ) { ListExpr arg1; if( nl->ListLength( args ) == 1 ) { arg1 = nl->First( args ); if( nl->IsEqual( arg1, MReal::BasicType() ) ) return nl->SymbolAtom( MBool::BasicType() ); if( nl->IsEqual( arg1, UReal::BasicType() ) ) return nl->SymbolAtom( UBool::BasicType() ); } return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.17.2 Value Mapping for ~derivable~ */ int MPointDerivable( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); MReal* value = (MReal*)args[0].addr; MBool* res = ((MBool*)result.addr); UReal uReal; CcBool b; res->Clear(); if ( !value->IsDefined() ) res->SetDefined(false); else { res->SetDefined(true); res->StartBulkLoad(); for( int i = 0; i < value->GetNoComponents(); i++ ) { value->Get( i, uReal ); // Load a real unit. // FALSE means in this case that a real unit describes a quadratic // polynomial. A derivation is possible and the operator returns TRUE. if (uReal.r == false) b.Set(true,true); else b.Set(true,false); UBool boolvalue(uReal.timeInterval,b); res->MergeAdd( boolvalue ); } res->EndBulkLoad( false ); } return 0; } int UnitPointDerivable( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); UReal* uReal = (UReal*)args[0].addr; UBool* res = ((UBool*)result.addr); CcBool b; if (uReal->IsDefined()) { res->SetDefined(true); res->timeInterval = uReal->timeInterval; if (uReal->r == false) b.Set(true,true); else b.Set(true,false); UBool boolvalue(uReal->timeInterval,b); res->CopyFrom(&boolvalue); } else res->SetDefined( false ); return 0; } /* 5.17.3 Specification for operator ~derivable~ */ const std::string TemporalSpecDerivable= "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( mreal -> mbool\n" "ureal -> ubool" "derivable ( _ ) " "Returns a moving/unit bool decribing the " "derivability of the moving/unit real over time." "derivable (mreal) ) )"; /* 5.17.4 Selection Function of operator ~derivable~ */ int DerivableSelect( ListExpr args ) { ListExpr arg1 = nl->First( args ); if( nl->SymbolValue( arg1 ) == MReal::BasicType()) return 0; if( nl->SymbolValue( arg1 ) == UReal::BasicType()) return 1; return -1; // This point should never be reached } ValueMapping temporalderivablemap[] = { MPointDerivable, UnitPointDerivable }; /* 5.17.5 Definition of operator ~derivable~ */ Operator temporalderivable( "derivable", TemporalSpecDerivable, 2, temporalderivablemap, DerivableSelect, TypeMapDerivable); /* 5.18 Operator ~derivative~ 5.18.1 Type Mapping for ~derivative~ Type mapping for ~derivative~ is ---- mreal -> mreal ---- */ ListExpr TypeMapDerivative( ListExpr args ) { ListExpr arg1; if( nl->ListLength( args ) == 1 ) { arg1 = nl->First( args ); if( nl->IsEqual( arg1, MReal::BasicType() ) ) return nl->SymbolAtom( MReal::BasicType() ); if( nl->IsEqual( arg1, UReal::BasicType() ) ) return nl->SymbolAtom( UReal::BasicType() ); } return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.18.2 Value Mapping for ~derivative~ */ int MPointDerivative( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); MReal* m = ((MReal*)args[0].addr); MReal* pResult = ((MReal*)result.addr); UReal unitin; UReal unitout(true); pResult->Clear(); if( !m->IsDefined() ){ pResult->SetDefined( false ); return 0; } pResult->SetDefined( true ); pResult->StartBulkLoad(); for(int i=0;iGetNoComponents();i++) { m->Get(i, unitin); assert( unitin.IsDefined() ); if(!unitin.r) { unitout.a = 0.; unitout.b = 2*unitin.a; unitout.c = unitin.b; unitout.r = false; unitout.timeInterval = unitin.timeInterval; pResult->MergeAdd(unitout); } } pResult->EndBulkLoad( false ); return 0; } int UnitPointDerivative( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); UReal *Unit = (UReal*)args[0].addr; UReal *res = (UReal*)result.addr; if (Unit->IsDefined() && !Unit->r) { res->timeInterval = Unit->timeInterval; res->a = 0; res->b = 2 * Unit->a; res->c = Unit->b; res->r = Unit->r; res->SetDefined(true); } else // Unit is undefined { datetime::DateTime t = datetime::DateTime(datetime::instanttype); res->timeInterval = Interval(t,t,true,true); res->a = 0; res->b = 0; res->c = 0; res->r = false; res->SetDefined(false); } return 0; } /* 5.18.3 Specification for operator ~derivative~ */ const std::string TemporalSpecDerivative= "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( {m|u}real -> {m|u}real" "derivative ( _ ) " "Determine the derivative" " of a mreal/ureal value." "derivable (mreal) ) )"; /* 5.18.4 Selection Function of operator ~deriavtive~ Uses ~DerivableSelect~. */ ValueMapping temporalderivativemap[] = { MPointDerivative, UnitPointDerivative }; /* 5.18.5 Definition of operator ~derivative~ */ Operator temporalderivative( "derivative", TemporalSpecDerivative, 2, temporalderivativemap, DerivableSelect, TypeMapDerivative); /* 5.19 Operator ~sfeed~ Moved to ~StreamAlgebra~ and renamed it to ~feed~. */ /* 5.20 Operator ~suse~ Moved to ~StreamAlgebra~ and renamed it to ~use~ resp. ~use2~. */ /* 5.21 Operator ~distance~ The operator calculates the minimum distance between two units of base types ~int~ or ~point~. The distance is always a non-negative ~ureal~ value. ---- For T in {int, point} distance: uT x uT -> ureal uT x T -> ureal T x uT -> ureal ureal x ureal -> (stream ureal) real x ureal -> (stream ureal) ureal x real -> (stream ureal) ---- 5.21.1 Type mapping function for ~distance~ typemapping appends the argument number of the argument containing the unitvalue (either 0 or 1). */ ListExpr TypeMapTemporalUnitDistance( ListExpr args ) { ListExpr first, second; std::string outstr1, outstr2; if ( nl->IsAtom( args ) || nl->ListLength( args ) != 2 ) { nl->WriteToString(outstr1, args); ErrorReporter::ReportError("Operator distance expects a list of " "length two, but gets '" + outstr1 + "'."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } first = nl->First(args); second = nl->Second(args); // check for compatibility of arguments if( !nl->IsAtom(first) || !nl->IsAtom(second) ) { nl->WriteToString(outstr1, first); nl->WriteToString(outstr2, second); ErrorReporter::ReportError("Operator distance expects as arguments " "lists of length one, but gets '" + outstr1 + "' and '" + outstr2 + "'."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } if( nl->IsEqual(first, UPoint::BasicType()) && nl->IsEqual(second, UPoint::BasicType()) ) { return nl->SymbolAtom(UReal::BasicType()); } if( nl->IsEqual(first, UPoint::BasicType()) && nl->IsEqual(second, Point::BasicType()) ) { return nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()), nl->OneElemList(nl->IntAtom(0)), nl->SymbolAtom( UReal::BasicType() )); } if( nl->IsEqual(first, Point::BasicType()) && nl->IsEqual(second, UPoint::BasicType()) ) { return nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()), nl->OneElemList(nl->IntAtom(1)), nl->SymbolAtom( UReal::BasicType() )); } if( nl->IsEqual(first, UInt::BasicType()) && nl->IsEqual(second, UInt::BasicType()) ) { return nl->SymbolAtom(UReal::BasicType()); } if( nl->IsEqual(first, UInt::BasicType()) && nl->IsEqual(second, CcInt::BasicType()) ) { return nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()), nl->OneElemList(nl->IntAtom(0)), nl->SymbolAtom( UReal::BasicType() )); } if( nl->IsEqual(first, CcInt::BasicType()) && nl->IsEqual(second, UInt::BasicType()) ) { return nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()), nl->OneElemList(nl->IntAtom(1)), nl->SymbolAtom( UReal::BasicType() )); } if( nl->IsEqual(first, UReal::BasicType()) && nl->IsEqual(second, UReal::BasicType()) ) { return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UReal::BasicType() )); } if( nl->IsEqual(first, UReal::BasicType()) && nl->IsEqual(second, CcReal::BasicType()) ) { return nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()), nl->OneElemList(nl->IntAtom(0)), nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UReal::BasicType() ))); } if( nl->IsEqual(first, CcReal::BasicType()) && nl->IsEqual(second, UReal::BasicType()) ) { return nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()), nl->OneElemList(nl->IntAtom(1)), nl->TwoElemList( nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UReal::BasicType() ))); } nl->WriteToString(outstr1, first); nl->WriteToString(outstr2, second); ErrorReporter::ReportError("Operator distance found wrong argument " "configuration '" + outstr1 + "' and '" + outstr2 + "'."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.21.2 Value mapping for operator ~distance~ */ /* (a1) Value mapping for ---- (upoint upoint) -> ureal ---- */ int TUDistance_UPoint_UPoint( Word* args, Word& result, int message, Word& local, Supplier s ) { Interval iv; // Word a1, a2; UPoint *u1, *u2; result = qp->ResultStorage( s ); UReal* res = (UReal*) result.addr; u1 = (UPoint*)(args[0].addr); u2 = (UPoint*)(args[1].addr); if (!u1->IsDefined() || !u2->IsDefined() || !u1->timeInterval.Intersects( u2->timeInterval ) ) { // return undefined ureal res->SetDefined( false ); } else { // get intersection of deftime intervals #ifdef TUA_DEBUG cout << __PRETTY_FUNCTION__ << ":" << endl << " iv1=" << TUPrintTimeInterval(u1->timeInterval) << endl << " iv2=" << TUPrintTimeInterval(u2->timeInterval) << endl; #endif u1->timeInterval.Intersection( u2->timeInterval, iv ); #ifdef TUA_DEBUG cout << __PRETTY_FUNCTION__ << ": iv=" << TUPrintTimeInterval(iv) << endl; #endif // calculate result u1->Distance( *u2, *res ); res->SetDefined( true ); } // pass on result return 0; } /* (a2) value mapping for ---- (upoint point) -> ureal (point upoint) -> ureal ---- */ int TUDistance_UPoint_Point( Word* args, Word& result, int message, Word& local, Supplier s ) { Word thePoint, theUPoint; result = qp->ResultStorage( s ); UReal* res = static_cast(result.addr); // get argument configuration int argConfDescriptor2; argConfDescriptor2 = ((CcInt*)args[2].addr)->GetIntval(); if (argConfDescriptor2 == 0) { theUPoint = args[0]; thePoint = args[1]; } else if (argConfDescriptor2 == 1) { theUPoint = args[1]; thePoint = args[0]; } else { cout << "\nWrong argument configuration in " << __PRETTY_FUNCTION__ << ": argConfDescriptor2=" << argConfDescriptor2 << endl; assert( false ); return 0; } UPoint* up = static_cast(theUPoint.addr); Point* p = static_cast(thePoint.addr); up->Distance( *p, *res); return 0; } /* (b1) value mapping for ---- (uint uint) -> ureal ---- */ int TUDistance_UInt_UInt( Word* args, Word& result, int message, Word& local, Supplier s ) { Interval iv; double c1, c2, c; result = qp->ResultStorage( s ); UReal* res = static_cast(result.addr); UInt* u1 = static_cast(args[0].addr); UInt* u2 = static_cast(args[1].addr); if (!u1->IsDefined() || !u2->IsDefined() || !u1->timeInterval.Intersects( u2->timeInterval ) ) { // return undefined ureal res->SetDefined( false ); } else { // get intersection of deftime intervals u1->timeInterval.Intersection( u2->timeInterval, iv ); // calculate result // (as the result is constant, no translation step is required) c1 = static_cast(u2->constValue.GetIntval()); c2 = static_cast(u2->constValue.GetIntval()); c = fabs(c1 - c2); *res = UReal(iv, 0, 0, c, false); res->SetDefined( true ); } // pass on result return 0; } /* (b2) value mapping for ---- ((uint int) -> ureal) and ((int uint) -> ureal) ---- */ int TUDistance_UInt_Int( Word* args, Word& result, int message, Word& local, Supplier s ) { Word ii, ui; int argConfDescriptor2; UInt *u; CcInt *i; double c1, c2, c; // get argument configuration argConfDescriptor2 = ((CcInt*)args[2].addr)->GetIntval(); if (argConfDescriptor2 == 0) { ui = args[0]; ii = args[1]; } else if (argConfDescriptor2 == 1) { ui = args[1]; ii = args[0]; } else { cout << "\nWrong argument configuration in " << "'TUDistance_UInt_Int'. argConfDescriptor2=" << argConfDescriptor2 << endl; return 0; } result = qp->ResultStorage( s ); u = (UInt*)(ui.addr); i = (CcInt*)(ii.addr); if (!u->IsDefined() || !i->IsDefined() ) { // return undefined ureal ((UReal*)(result.addr))->SetDefined( false ); } else { // calculate result // (as the result is constant, no translation step is required) c1 = (double) u->constValue.GetIntval(); c2 = (double) i->GetIntval(); c = fabs(c1 - c2); *((UReal*)(result.addr)) = UReal(u->timeInterval, 0, 0, c, false); ((UReal*)(result.addr))->SetDefined( true ); } // pass on result return 0; } /* (c2) value mapping for ---- ((ureal ureal) -> (stream ureal)) ---- */ struct TUDistanceLocalInfo { bool finished; int NoOfResults; int NoOfResultsDelivered; std::vector resultVector; }; int TUDistance_UReal_UReal( Word* args, Word& result, int message, Word& local, Supplier s ) { UReal *u1, *u2, utemp(true); TUDistanceLocalInfo *localinfo = 0; result = qp->ResultStorage( s ); switch( message ) { case OPEN: u1 = (UReal*)(args[0].addr); u2 = (UReal*)(args[1].addr); localinfo = new TUDistanceLocalInfo; local.setAddr(localinfo); localinfo->finished = true; localinfo->NoOfResults = 0; localinfo->NoOfResultsDelivered = 0; localinfo->resultVector.clear(); if (!u1->IsDefined() || !u2->IsDefined() || u1->r || u2->r ) { // return empty stream return 0; } else { // calculate results localinfo->NoOfResults = u1->Distance(*u2, localinfo->resultVector); localinfo->finished = (localinfo->NoOfResults <= 0); return 0; } case REQUEST: if(local.addr == 0) return CANCEL; localinfo = (TUDistanceLocalInfo*) local.addr; if( localinfo->finished || localinfo->NoOfResultsDelivered >= localinfo->NoOfResults ) { localinfo->finished = true; return CANCEL; } result.setAddr( localinfo->resultVector[localinfo->NoOfResultsDelivered].Clone() ); localinfo->NoOfResultsDelivered++; return YIELD; case CLOSE: if(local.addr != 0) { localinfo = (TUDistanceLocalInfo*) local.addr; delete localinfo; local.setAddr(Address(0)); } return 0; } return 0; } /* (c2) value mapping for ---- ((ureal real) -> (stream ureal)) and ((real ureal) -> (stream ureal)) ---- */ int TUDistance_UReal_Real( Word* args, Word& result, int message, Word& local, Supplier s ) { Word ii, ui; int argConfDescriptor2; UReal *u, utemp(true); CcReal *i; TUDistanceLocalInfo *localinfo = 0; result = qp->ResultStorage( s ); switch( message ) { case OPEN: // get argument configuration argConfDescriptor2 = ((CcInt*)args[2].addr)->GetIntval(); if (argConfDescriptor2 == 0) { ui = args[0]; ii = args[1]; } else if (argConfDescriptor2 == 1) { ui = args[1]; ii = args[0]; } else { cout << "\nWrong argument configuration in " << "'TUDistance_UReal_Real'. argConfDescriptor2=" << argConfDescriptor2 << endl; return 0; } u = (UReal*)(ui.addr); i = (CcReal*)(ii.addr); localinfo = new TUDistanceLocalInfo; local.setAddr(localinfo); localinfo->finished = true; localinfo->NoOfResults = 0; localinfo->NoOfResultsDelivered = 0; localinfo->resultVector.clear(); if (!u->IsDefined() || !i->IsDefined() || u->r ) { // return empty stream return 0; } else { // calculate result utemp = UReal(u->timeInterval, u->a, u->b, (u->c - i->GetRealval() ), false); localinfo->NoOfResults = utemp.Abs(localinfo->resultVector); localinfo->finished = (localinfo->NoOfResults <= 0); return 0; } case REQUEST: if(local.addr != 0) localinfo = (TUDistanceLocalInfo*) local.addr; else return CANCEL; if( localinfo->finished || localinfo->NoOfResultsDelivered >= localinfo->NoOfResults ) { localinfo->finished = true; return CANCEL; } result.setAddr( localinfo->resultVector[localinfo->NoOfResultsDelivered].Clone() ); localinfo->NoOfResultsDelivered++; return YIELD; case CLOSE: if(local.addr != 0) { localinfo = (TUDistanceLocalInfo*) local.addr; delete localinfo; local.setAddr(Address(0)); } return 0; } return 0; } /* 5.21.3 Specification for operator ~distance~ */ const std::string TemporalSpecDistance = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "(" "For T in {point, int}:\n" "(uT uT) -> ureal\n" "(uT T) -> ureal\n" "( T uT) -> ureal\n" "(ureal ureal) -> (stream ureal)\n" "(ureal real) -> (stream ureal)\n" "( real ureal) -> (stream ureal)" "distance( _, _)" "Calculates the distance of both arguments, " "whereof at least one is a unittype, " "as a 'ureal' value. For the ureal signatures, all " "radix-flags must be FALSE, otherwise the result is " "empty." "distance(upoint1,point1)" ") )"; /* 5.21.4 Selection Function of operator ~distance~ */ ValueMapping temporalunitdistancemap[] = { TUDistance_UPoint_UPoint, // 0 TUDistance_UPoint_Point, TUDistance_UInt_UInt, TUDistance_UInt_Int, TUDistance_UReal_UReal, TUDistance_UReal_Real // 5 }; int temporalunitDistanceSelect( ListExpr args ) { ListExpr first = nl->First(args); ListExpr second = nl->Second(args); if( nl->IsEqual(first, UPoint::BasicType()) && nl->IsEqual(second, UPoint::BasicType()) ) return 0; else if( nl->IsEqual(first, UPoint::BasicType()) && nl->IsEqual(second, Point::BasicType()) ) return 1; else if( nl->IsEqual(first, Point::BasicType()) && nl->IsEqual(second, UPoint::BasicType()) ) return 1; else if( nl->IsEqual(first, UInt::BasicType()) && nl->IsEqual(second, UInt::BasicType()) ) return 2; else if( nl->IsEqual(first, UInt::BasicType()) && nl->IsEqual(second, CcInt::BasicType()) ) return 3; else if( nl->IsEqual(first, CcInt::BasicType()) && nl->IsEqual(second, UInt::BasicType()) ) return 3; else if( nl->IsEqual(first, UReal::BasicType()) && nl->IsEqual(second, UReal::BasicType()) ) return 4; else if( nl->IsEqual(first, UReal::BasicType()) && nl->IsEqual(second, CcReal::BasicType()) ) return 5; else if( nl->IsEqual(first, CcReal::BasicType()) && nl->IsEqual(second, UReal::BasicType()) ) return 5; else cout << "\nERROR in temporalunitDistanceSelect!" << endl; return -1; } /* 5.21.5 Definition of operator ~distance~ */ Operator temporalunitdistance( "distance", TemporalSpecDistance, 6, temporalunitdistancemap, temporalunitDistanceSelect, TypeMapTemporalUnitDistance); /* 5.22 Operator ~atmax~ From a given unit ~u~, the operator creates a stream of units that are restrictions of ~u~ to the periods where it reaches its maximum value. ---- For T in {int, real} atmax: uT --> (stream uT) ---- 5.22.1 Type mapping function for ~atmax~ */ ListExpr UnitBaseTypeMapAtmax( ListExpr args ) { ListExpr arg1; if( nl->ListLength( args ) == 1 ) { arg1 = nl->First( args ); if( nl->IsEqual( arg1, UBool::BasicType() ) ) return nl->SymbolAtom( UBool::BasicType() ); if( nl->IsEqual( arg1, UInt::BasicType() ) ) return nl->SymbolAtom( UInt::BasicType() ); if( nl->IsEqual( arg1, UString::BasicType() ) ) return nl->SymbolAtom( UString::BasicType() ); // for ureal, atmax/atmin will return a stream of ureals! if( nl->IsEqual( arg1, UReal::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UReal::BasicType() )); } return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.22.2 Value mapping for operator ~atmax~ */ struct AtExtrURealLocalInfo { int NoOfResults; int ResultsDelivered; std::vector resultUnitVector; }; int atmaxUReal( Word* args, Word& result, int message, Word& local, Supplier s ) { AtExtrURealLocalInfo *sli; UReal *ureal; result = qp->ResultStorage( s ); switch (message) { case OPEN : ureal = (UReal*)(args[0].addr); #ifdef TUA_DEBUG cout << " Argument ureal value: " << TUPrintUReal(ureal) << endl << " 1" << endl; #endif sli = new AtExtrURealLocalInfo; sli->resultUnitVector.clear(); sli->NoOfResults = 0; sli->ResultsDelivered = 0; local.setAddr(sli); if ( !ureal->IsDefined() ) { // ureal undefined // -> return empty stream sli->NoOfResults = 0; #ifdef TUA_DEBUG cout << " ureal undef: no solution" << endl; #endif return 0; } sli->NoOfResults = ureal->AtMax(sli->resultUnitVector); return 0; case REQUEST : if (local.addr == 0) return CANCEL; sli = (AtExtrURealLocalInfo*) local.addr; if (sli->NoOfResults <= sli->ResultsDelivered) return CANCEL; result.setAddr( sli->resultUnitVector[sli->ResultsDelivered].Clone() ); #ifdef TUA_DEBUG cout << " delivered result[" << sli->ResultsDelivered+1 << "/" << sli->NoOfResults<< "]=" << TUPrintUReal((UReal*)(result.addr)) << endl; #endif sli->ResultsDelivered++; return YIELD; case CLOSE : if (local.addr != 0) { sli = (AtExtrURealLocalInfo*) local.addr; // for(unsigned int i=0; i< sli->resultUnitVector.size(); i++) // sli->resultUnitVector[i].DeleteIfAllowed(); delete sli; local.setAddr(Address(0)); } return 0; } // end switch return 0; // should not be reached } template int atmaxUConst( Word* args, Word& result, int message, Word& local, Supplier s ) { ConstTemporalUnit* arg = static_cast*>(args[0].addr); result = qp->ResultStorage( s ); // This operator is not very interesting. It implements // the atmax operator for constant unit types, like uint, ustring or ubool. // In fact, it returns just a copy of the argument. ConstTemporalUnit* res = static_cast*>(result.addr); res->CopyFrom(arg); return 0; } /* 5.22.3 Specification for operator ~atmax~ */ const std::string TemporalSpecAtmax = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" ) " "(" "For T in {int, bool, string}:\n" "uT -> uT\n" "ureal -> (stream ureal)" "atmax( _ )" "Restricts a the unittype value to the time where " "it takes it's maximum value.\n" "Observe, that for type 'ureal', the result is a '(stream ureal)' " "rather than a 'ureal'!" "atmax( ureal1 )" ") )"; /* 5.22.4 Selection Function of operator ~atmax~ */ ValueMapping temporalunitatmaxmap[] = { atmaxUConst, atmaxUConst, atmaxUConst, atmaxUReal }; int temporalunitAtmaxSelect( ListExpr args ) { ListExpr arg1; if( nl->ListLength( args ) == 1 ) { arg1 = nl->First( args ); if( nl->IsEqual( arg1, UBool::BasicType() ) ) return 0; if( nl->IsEqual( arg1, UInt::BasicType() ) ) return 1; if( nl->IsEqual( arg1, UString::BasicType() ) ) return 2; if( nl->IsEqual( arg1, UReal::BasicType() ) ) return 3; } cout << "\ntemporalunitAtmaxSelect: Wrong type!" << endl; return -1; } /* 5.22.5 Definition of operator ~atmax~ */ Operator temporalunitatmax( "atmax", TemporalSpecAtmax, 4, temporalunitatmaxmap, temporalunitAtmaxSelect, UnitBaseTypeMapAtmax); /* 5.23 Operator ~atmin~ From a given unit ~u~, the operator creates a stream of units that are restrictions of ~u~ to the periods where it reaches its minimum value. ---- For T in {int, real} atmin: uT --> (stream uT) ---- 5.23.1 Type mapping function for ~atmin~ Uses typemapping ~UnitBaseTypeMapAtmax~ intended for related operator ~atmax~ */ /* 5.23.2 Value mapping for operator ~atmin~ */ int atminUReal( Word* args, Word& result, int message, Word& local, Supplier s ) { AtExtrURealLocalInfo *sli; UReal *ureal; result = qp->ResultStorage( s ); switch (message) { case OPEN : ureal = (UReal*)(args[0].addr); #ifdef TUA_DEBUG cout << " Argument ureal value: " << TUPrintUReal(ureal) << endl << " 1" << endl; #endif sli = new AtExtrURealLocalInfo; sli->resultUnitVector.clear(); sli->NoOfResults = 0; sli->ResultsDelivered = 0; local.setAddr(sli); if ( !ureal->IsDefined() ) { // ureal undefined // -> return empty stream sli->NoOfResults = 0; #ifdef TUA_DEBUG cout << " ureal undef: no solution" << endl; #endif return 0; } sli->NoOfResults = ureal->AtMin(sli->resultUnitVector); return 0; case REQUEST : if (local.addr == 0) return CANCEL; sli = (AtExtrURealLocalInfo*) local.addr; if (sli->NoOfResults <= sli->ResultsDelivered) return CANCEL; result.setAddr( sli->resultUnitVector[sli->ResultsDelivered].Clone() ); #ifdef TUA_DEBUG cout << " delivered result[" << sli->ResultsDelivered+1 << "/" << sli->NoOfResults<< "]=" << TUPrintUReal((UReal*)(result.addr)) << endl; #endif sli->ResultsDelivered++; return YIELD; case CLOSE : if (local.addr != 0) { sli = (AtExtrURealLocalInfo*) local.addr; // for(unsigned int i=0; i< sli->resultUnitVector.size(); i++) // sli->resultUnitVector[i].DeleteIfAllowed(); delete sli; local.setAddr(Address(0)); } return 0; } // end switch return 0; // should not be reached } template int atminUConst( Word* args, Word& result, int message, Word& local, Supplier s ) { ConstTemporalUnit* arg = static_cast*>(args[0].addr); result = qp->ResultStorage( s ); // This operator is not very interesting. It implements // the atmin operator for constant unit types, like uint, ustring or ubool. // In fact, it returns just a copy of the argument. ConstTemporalUnit* res = static_cast*>(result.addr); res->CopyFrom(arg); return 0; } /* 5.23.3 Specification for operator ~atmin~ */ const std::string TemporalSpecAtmin = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" ) " "(" "For T in {int, bool, string}:\n" "uT -> uT\n" "ureal -> (stream ureal)" "atmin( _ )" "Restricts a the unittype value to the time where " "it takes it's minimum value.\n" "Observe, that for type 'ureal', the result is a '(stream ureal)' " "rather than a 'ureal'!" "atmin( ureal1 )" ") )"; /* 5.23.4 Selection Function of operator ~atmin~ Uses selection function ~temporalunitAtmaxSelect~. */ ValueMapping temporalunitatminmap[] = { atminUConst, atminUConst, atminUConst, atminUReal }; /* 5.23.5 Definition of operator ~atmin~ */ Operator temporalunitatmin( "atmin", TemporalSpecAtmin, 4, temporalunitatminmap, temporalunitAtmaxSelect, UnitBaseTypeMapAtmax); /* 5.24 Operator ~saggregate~ Moved to ~StreamAlgebra~ and remaned it to ~aggregateS~ */ /* 5.25 Operator ~abs~ The operator returns the absolute function derived from the input ureal or uint. */ /* 5.25.1 Type mapping function for ~abs~ The operator has signature ---- abs: ureal --> (stream ureal) abs: uint --> uint ---- */ ListExpr TU_TM_Abs( ListExpr args ) { ListExpr first; std::string outstr1, outstr2; if ( nl->IsAtom( args ) || nl->ListLength( args ) != 1 ) { nl->WriteToString(outstr1, args); ErrorReporter::ReportError("Operator abs expects a list of " "length one, but gets '" + outstr1 + "'."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } first = nl->First(args); if( nl->IsEqual(first, UInt::BasicType()) ) { return nl->SymbolAtom(UInt::BasicType()); } if( nl->IsEqual(first, UReal::BasicType()) ) { return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UReal::BasicType() )); } nl->WriteToString(outstr1, first); ErrorReporter::ReportError("Operator abs found wrong argument " + outstr1 + "'."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.25.2 Value mapping for operator ~abs~ */ // value mapping for uint --> uint int TU_VM_Abs_UInt( Word* args, Word& result, int message, Word& local, Supplier s ) { Word a1; UInt *u1; long c1, c; result = qp->ResultStorage( s ); a1 = args[0]; u1 = (UInt*)(a1.addr); if ( !u1->IsDefined() ) { // return undefined ureal ((UInt*)(result.addr))->SetDefined( false ); } else { c1 = (long) u1->constValue.GetIntval(); c = std::abs(c1); ((UInt*)(result.addr))->timeInterval = u1->timeInterval; ((UInt*)(result.addr))->SetDefined( true ); ((UInt*)(result.addr))->constValue.Set(true,c); } return 0; } struct TUAbsLocalInfo { bool finished; int NoOfResults; int NoOfResultsDelivered; std::vector resultVector; }; // value mapping for ureal --> (stream ureal) int TU_VM_Abs_UReal( Word* args, Word& result, int message, Word& local, Supplier s ) { TUAbsLocalInfo *sli; Word u1; UReal *uv1; Interval iv; switch( message ) { case OPEN: sli = new TUAbsLocalInfo; local.setAddr(sli); sli->resultVector.clear(); sli->finished = true; sli->NoOfResults = 0; sli->NoOfResultsDelivered = 0; u1 = args[0]; uv1 = (UReal*) (u1.addr); if ( uv1->IsDefined() ) { sli->NoOfResults = uv1->Abs(sli->resultVector); sli->finished = ( sli->NoOfResults <= 0 ); } return 0; case REQUEST: if(local.addr == 0) { return CANCEL; } sli = (TUAbsLocalInfo*) local.addr; if(sli->finished) { return CANCEL; } if(sli->NoOfResultsDelivered < sli->NoOfResults) { result.setAddr( sli->resultVector[sli->NoOfResultsDelivered].Clone() ); sli->NoOfResultsDelivered++; return YIELD; } sli->finished = true; return CANCEL; case CLOSE: if (local.addr != 0) { sli = (TUAbsLocalInfo*) local.addr; delete sli; local.setAddr(Address(0)); } return 0; } // end switch return 0; } /* 5.24.3 Specification for operator ~abs~ */ const std::string TU_Spec_Abs = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( uint -> uint\n" "ureal -> (stream ureal)" "abs( _ )" "Return the argument's absolute value." "query speed(mp1) ) )"; /* 5.25.4 Selection Function of operator ~abs~ */ int TU_Select_Abs( ListExpr args ) { ListExpr arg1 = nl->First( args ); if( nl->SymbolValue( arg1 ) == UInt::BasicType() ) return 0; if( nl->SymbolValue( arg1 ) == UReal::BasicType() ) return 1; return -1; // This point should never be reached } ValueMapping temporalunit_abs_map[] = { TU_VM_Abs_UInt, TU_VM_Abs_UReal }; /* 5.25.5 Definition of operator ~abs~ */ Operator temporalunitabs( "abs", TU_Spec_Abs, 2, temporalunit_abs_map, TU_Select_Abs, TU_TM_Abs); /* 5.26 Operator ---- intersection: For T in {bool, int, string}: OK uT x uT --> (stream uT) OK uT x T --> (stream uT) OK T x uT --> (stream uT) (OK) ureal x real --> (stream ureal) (OK) real x ureal --> (stream ureal) Pre ureal x ureal --> (stream ureal) OK upoint x point --> (stream upoint) same as at: upoint x point OK point x upoint --> (stream upoint) same as at: upoint x point OK upoint x upoint --> (stream upoint) OK upoint x line --> (stream upoint) OK line x upoint --> (stream upoint) OK upoint x region --> (stream upoint) OK region x upoint --> (stream upoint) OK upoint x uregion --> (stream upoint) OK uregion x upoint --> (stream upoint) ---- A. (T mT) [->] mT and (mT T) -> mT B. (mT mT) [->] mT The operator always returns a stream of units (to handle both, empty and set valued results). 1. For all types of arguments, we return an empty stream, if both timeIntervals don't overlap. 2. Now, the algorithms depends on the actual dataype: Then, for ~constant temporal units~ (ubool, uint, ustring), the operator restricts two unit values with equal values to the intersection of both time intervals, or otherwise (if the const values are nit equal) returns an empty stream. For ~ureal~, we test whether the functions of both units are equal, for we can pass its restriction to the intersection of deftimes then (resp. create an empty stream). Otherwise, we restrict both arguments' deftimes to their intersection. Then we calculate the minimum and maximum value for both arguments with respect to the restricted deftime. If both ranges don't overlap, we return an empty stream. Otherwise, we compute the intersection points (1 or 2) and return them as the result - or an UNDEFINED value, if the result is not represeantable as a ureal value. For ~upoint~, we interpret the units as straight lines. If both are parallel, return the empty stream. If both are identical, Otherwise calculate the intersection point ~S~. From ~S~, calculate the instants $t_{u1}$ and $t_{u2}$. If both coincide, return that point if within the common timeInterval, otherwise the empty stream. C. (upoint line) [->] (stream upoint) and (line upoint) [->] (stream upoint) */ /* 5.26.1 Type mapping function for ~intersection~ */ ListExpr TemporalUnitIntersectionTypeMap( ListExpr args ) { ListExpr arg1, arg2; std::string argstr1 = "", argstr2 = ""; if( nl->ListLength( args ) == 2 ) { arg1 = nl->First( args ); arg2 = nl->Second( args ); // First case: uT uT -> stream uT if (nl->Equal( arg1, arg2 )) { if( nl->IsEqual( arg1, UBool::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UBool::BasicType() )); if( nl->IsEqual( arg1, UInt::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UInt::BasicType() )); if( nl->IsEqual( arg1, UReal::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UReal::BasicType() )); if( nl->IsEqual( arg1, UPoint::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UPoint::BasicType() )); if( nl->IsEqual( arg1, UString::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UString::BasicType() )); } // Second case: uT T -> stream uT if( nl->IsEqual( arg1, UBool::BasicType() ) && nl->IsEqual( arg2, CcBool::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UBool::BasicType() )); if( nl->IsEqual( arg1, UInt::BasicType() ) && nl->IsEqual( arg2, CcInt::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UInt::BasicType() )); if( nl->IsEqual( arg1, UReal::BasicType() ) && nl->IsEqual( arg2, CcReal::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UReal::BasicType() )); if( nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, Point::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UPoint::BasicType() )); if( nl->IsEqual( arg1, UString::BasicType() ) && nl->IsEqual( arg2, CcString::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UString::BasicType() )); // Third case: T uT -> stream uT if( nl->IsEqual( arg1, CcBool::BasicType() ) && nl->IsEqual( arg2, UBool::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UBool::BasicType() )); if( nl->IsEqual( arg1, CcInt::BasicType() ) && nl->IsEqual( arg2, UInt::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UInt::BasicType() )); if( nl->IsEqual( arg1, CcReal::BasicType() ) && nl->IsEqual( arg2, UReal::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UReal::BasicType() )); if( nl->IsEqual( arg1, Point::BasicType() ) && nl->IsEqual( arg2, UPoint::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UPoint::BasicType() )); if( nl->IsEqual( arg1, CcString::BasicType() ) && nl->IsEqual( arg2, UString::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UString::BasicType() )); // Fourth case: upoint line -> stream upoint if( nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, Line::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UPoint::BasicType() )); // Fifth case: line upoint -> stream upoint if( nl->IsEqual( arg1, Line::BasicType() ) && nl->IsEqual( arg2, UPoint::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UPoint::BasicType() )); // Sixth case: upoint uregion -> stream upoint if( nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, URegion::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UPoint::BasicType() )); // Eighth case: uregion upoint -> stream upoint if( nl->IsEqual( arg1, URegion::BasicType() ) && nl->IsEqual( arg2, UPoint::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UPoint::BasicType() )); // Ninth case: upoint region -> stream upoint if( nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, Region::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UPoint::BasicType() )); // Tenth case: region upoint -> stream upoint if( nl->IsEqual( arg1, Region::BasicType() ) && nl->IsEqual( arg2, UPoint::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UPoint::BasicType() )); // Error case: nl->WriteToString(argstr1, arg1); nl->WriteToString(argstr2, arg2); ErrorReporter::ReportError( "Operator intersection expects argumentlist (T,T), (uT,T), (T,uT), " "where T in {ubool, uint, ureal, ustring, upoint}\n or a combination " "of {upoint,line}, {upoint,uregion}, {upoint,region}.\n" "The passed arguments have types '"+ argstr1 +"' and '" + argstr2 + "'."); } else { // Error case: ErrorReporter::ReportError( "Operator intersection expects argumentlist (T,T), (uT,T), (T,uT), " "where T in {ubool, uint, ureal, ustring, upoint}\n or a combination of" " {upoint,line}, {upoint,uregion}, {upoint,region}.\n"); } return nl->SymbolAtom(Symbol::TYPEERROR()); } /* 5.26.2 Value mapping for operator ~intersection~ */ struct TUIntersectionLocalInfo { bool finished; int NoOfResults; int NoOfResultsDelivered; Word resultValues[2]; // Used if at most 2 results can occur std::vector resultValues2; // Used if more than 2 results may occur MPoint *mpoint; // Used for upoint x lines }; // value mapping for constant units (uT uT) -> (stream uT) template int temporalUnitIntersection_CU_CU( Word* args, Word& result, int message, Word& local, Supplier s ) { TUIntersectionLocalInfo *sli; Word u1, u2; T *uv1, *uv2; Interval iv; // test for overlapping intervals switch( message ) { case OPEN: #ifdef TUA_DEBUG cout << "temporalUnitIntersection_CU_CU: received OPEN" << endl; #endif sli = new TUIntersectionLocalInfo; sli->finished = true; sli->NoOfResults = 0; sli->NoOfResultsDelivered = 0; u1 = args[0]; u2 = args[1]; uv1 = (T*) (u1.addr); uv2 = (T*) (u2.addr); if ( uv1->IsDefined() && uv2->IsDefined() && uv1->timeInterval.Intersects( uv2->timeInterval ) && uv1->EqualValue(*uv2) ) { // get intersection of deftime intervals uv1->timeInterval.Intersection( uv2->timeInterval, iv ); #ifdef TUA_DEBUG cout << " iv=" << TUPrintTimeInterval( iv ) << endl; #endif // store result (sli->resultValues[sli->NoOfResults]).setAddr( uv1->Clone() ); ((T*)(sli->resultValues[sli->NoOfResults].addr))->timeInterval = iv; sli->NoOfResults++; sli->finished = false; #ifdef TUA_DEBUG cout << " added result" << endl; #endif }// else: no result local.setAddr(sli); #ifdef TUA_DEBUG cout << "temporalUnitIntersection_CU_CU: finished OPEN" << endl; #endif return 0; case REQUEST: #ifdef TUA_DEBUG cout << "temporalUnitIntersection_CU_CU: received REQUEST" << endl; #endif if(local.addr == 0) { #ifdef TUA_DEBUG cout << "temporalUnitIntersection_CU_CU: CANCEL (1)" << endl; #endif return CANCEL; } sli = (TUIntersectionLocalInfo*) local.addr; if(sli->finished) { #ifdef TUA_DEBUG cout << "temporalUnitIntersection_CU_CU: CANCEL (2)" << endl; #endif return CANCEL; } if(sli->NoOfResultsDelivered < sli->NoOfResults) { result.setAddr( ((T*) (sli->resultValues[sli->NoOfResultsDelivered].addr))->Clone() ); ((T*)(sli->resultValues[sli->NoOfResultsDelivered].addr)) ->DeleteIfAllowed(); sli->NoOfResultsDelivered++; #ifdef TUA_DEBUG cout << "temporalUnitIntersection_CU_CU: YIELD" << endl; #endif return YIELD; } sli->finished = true; #ifdef TUA_DEBUG cout << "temporalUnitIntersection_CU_CU: CANCEL (3)" << endl; #endif return CANCEL; case CLOSE: if (local.addr != 0) { sli = (TUIntersectionLocalInfo*) local.addr; while(sli->NoOfResultsDelivered < sli->NoOfResults) { ((T*)(sli->resultValues[sli->NoOfResultsDelivered].addr)) ->DeleteIfAllowed(); sli->NoOfResultsDelivered++; } delete sli; local.setAddr(Address(0)); } return 0; } // end switch return 0; } // value mapping for constant units (uT T) -> (stream uT) // and ( T uT) -> (stream uT) template int temporalUnitIntersection_CU_C( Word* args, Word& result, int message, Word& local, Supplier s ) { TUIntersectionLocalInfo *sli; Word u1, u2; UT *uv1; T *uv2; Interval iv; // test for overlapping intervals switch( message ) { case OPEN: #ifdef TUA_DEBUG cout << "temporalUnitIntersection_CU_C: received OPEN" << endl; #endif sli = new TUIntersectionLocalInfo; sli->finished = true; sli->NoOfResults = 0; sli->NoOfResultsDelivered = 0; // get arguments, such that u1 is the unit type // and u2 is the simple type if (uargindex == 0) { u1 = args[0]; u2 = args[1]; } else { u1 = args[1]; u2 = args[0];} #ifdef TUA_DEBUG cout << " uargindex =" << uargindex << endl; #endif uv1 = (UT*) (u1.addr); uv2 = (T*) (u2.addr); if ( uv1->IsDefined() && uv2->IsDefined() && (uv1->constValue.Compare( uv2 ) == 0 ) ) { // store result (sli->resultValues[sli->NoOfResults]).setAddr( uv1->Clone() ); sli->NoOfResults++; sli->finished = false; #ifdef TUA_DEBUG cout << " Added Result" << endl; #endif }// else: no result local.setAddr(sli); #ifdef TUA_DEBUG cout << "temporalUnitIntersection_CU_C: finished OPEN" << endl; #endif return 0; case REQUEST: #ifdef TUA_DEBUG cout << "temporalUnitIntersection_CU_C: received REQUEST" << endl; #endif if(local.addr == 0) { #ifdef TUA_DEBUG cout << "temporalUnitIntersection_CU_C: finished REQUEST: " << "CANCEL (1)" << endl; #endif return CANCEL; } sli = (TUIntersectionLocalInfo*) local.addr; if(sli->finished) { #ifdef TUA_DEBUG cout << "temporalUnitIntersection_CU_C: finished REQUEST: " << "CANCEL (2)" << endl; #endif return CANCEL; } if(sli->NoOfResultsDelivered < sli->NoOfResults) { result.setAddr( ((UT*) (sli->resultValues[sli->NoOfResultsDelivered].addr))->Clone() ); ((UT*)(sli->resultValues[sli->NoOfResultsDelivered].addr)) ->DeleteIfAllowed(); sli->NoOfResultsDelivered++; #ifdef TUA_DEBUG cout << "temporalUnitIntersection_CU_C: finished REQUEST: " << "YIELD" << endl; #endif return YIELD; } sli->finished = true; #ifdef TUA_DEBUG cout << "temporalUnitIntersection_CU_C: finished REQUEST: " << "CANCEL (3)" << endl; #endif return CANCEL; case CLOSE: if (local.addr != 0) { sli = (TUIntersectionLocalInfo*) local.addr; while(sli->NoOfResultsDelivered < sli->NoOfResults) { ((UT*)(sli->resultValues[sli->NoOfResultsDelivered].addr)) ->DeleteIfAllowed(); sli->NoOfResultsDelivered++; } delete sli; local.setAddr(Address(0)); } return 0; } // end switch return 0; } /* Value mapping for ureal We will calculate the intersection points (time instants) of both ureal functions. Therefore, we need to distinguish 2 different cases: 1. $ureal_1.r = ureal_2.r$ Then, we have to solve the equation \[ (a_1-a_2)t^2 + (b_1-b_2)t + (c_1-c_2) = 0 \] With $a\neq 0$, this computes to \[ t_{1,2} = \frac{-(b_1-b_2) \pm \sqrt{(b_1-b_2)^2 - 4(a_1-a_2)(c_1-c_2)}} {2(a_1-a_2)} \] And depending on the value of $D = (b_1-b_2)^2 - 4(a_1-a_2)(c_1-c_2)$, we will have 0 ($D<0$), 1 ($D=0$) or 2 ($D>0$) solutions. 2. $ureal_1.r \neq ureal2_.r$ Then we have to solve the equation \[ {a_1}^2 t^4 + 2 a_1 b_1 t^3 + (2 a_1 c_1 + {b_1}^2 - a_2) t^2 + (2 b_1 c_1 - b_2) t - c_2 = 0 \] where $x_1$ stands for parameters from the ~ureal~ value that does have $r = false$, $x_2$ for the parameters of the ~ureal~ value with $r = true$. */ struct MappingUnitIntersection_rLocalInfo { bool finished; int NoOfResults; // total number of results int ResultsDelivered; // number of results already delivered std::vector resvector; // the results }; int temporalUnitIntersection_ureal_ureal( Word* args, Word& result, int message, Word& local, Supplier s ) { MappingUnitIntersection_rLocalInfo *localinfo; UReal *ureal1, *ureal2; Word a0, a1; Periods result_times(2); switch (message) { case OPEN : localinfo = new MappingUnitIntersection_rLocalInfo; local.setAddr(localinfo); localinfo->finished = true; localinfo->resvector.clear(); localinfo->NoOfResults = 0; localinfo->ResultsDelivered = 0; // initialize arguments, such that a0 always contains the UReal // and a1 the CcReal a0 = args[0]; a1 = args[1]; ureal1 = (UReal*)(a0.addr); ureal2 = (UReal*)(a1.addr); if ( !ureal1->IsDefined() || !ureal2->IsDefined() ) { // some input is undefined -> return empty stream return 0; } // call int UReal::PeriodsAtEqual( UReal& other, Periods& times) localinfo->NoOfResults = ureal1->PeriodsAtEqual( *ureal2, result_times); // cout << "temporalUnitIntersection_ureal_ureal(): NoOfResults=" // << localinfo->NoOfResults << endl; localinfo->finished = (localinfo->NoOfResults <= 0); for(int i=0; iNoOfResults; i++) { // create result vector UReal unit(true); Interval iv; // cout << "temporalUnitIntersection_ureal_ureal(): Processing interval " // << i << endl; result_times.Get(i, iv); if( iv.start == iv.end ) { // simplify result to constant datetime::DateTime T(datetime::durationtype); T = iv.start - ureal1->timeInterval.start; double t = T.ToDouble(); double value = ureal1->a*t*t + ureal1->b*t + ureal1->c; value = ureal1->r ? sqrt(value) : value; unit = UReal(iv, 0.0, 0.0, value, false); } else ureal1->AtInterval(iv, unit); localinfo->resvector.push_back(unit); // cout << "temporalUnitIntersection_ureal_ureal(): Added unit "; // unit.Print(cout); cout << endl; } localinfo->finished = ( localinfo->NoOfResults <= 0 ); // cout << "temporalUnitIntersection_ureal_ureal(): NoOfResults=" // << localinfo->NoOfResults << endl // << "temporalUnitIntersection_ureal_ureal(): finished=" // << localinfo->finished << endl; return 0; case REQUEST : if (local.addr == 0) return CANCEL; localinfo = (MappingUnitIntersection_rLocalInfo*) local.addr; if (localinfo->finished) return CANCEL; if ( localinfo->NoOfResults <= localinfo->ResultsDelivered ) { localinfo->finished = true; return CANCEL; } result = SetWord(localinfo->resvector[localinfo->ResultsDelivered].Clone()); localinfo->ResultsDelivered++; return YIELD; case CLOSE : if (local.addr != 0) { localinfo = (MappingUnitIntersection_rLocalInfo*) local.addr; delete localinfo; local.setAddr(Address(0)); } return 0; } // end switch // should not be reached return 0; } // value mapping for constant units (uT T) -> (stream uT) // and ( T uT) -> (stream uT) template int temporalUnitIntersection_ureal_real( Word* args, Word& result, int message, Word& local, Supplier s ) { MappingUnitIntersection_rLocalInfo *localinfo; UReal *uinput; CcReal *value; Word a0, a1; switch (message) { case OPEN : localinfo = new MappingUnitIntersection_rLocalInfo; local.setAddr(localinfo); localinfo->finished = true; localinfo->NoOfResults = 0; localinfo->ResultsDelivered = 0; // initialize arguments, such that a0 always contains the UReal // and a1 the CcReal if (uargindex == 0) { a0 = args[0]; a1 = args[1]; } else { a0 = args[1]; a1 = args[0]; } uinput = (UReal*)(a0.addr); value = (CcReal*)(a1.addr); if ( !uinput->IsDefined() || !value->IsDefined() ) { // some input is undefined -> return empty stream localinfo->NoOfResults = 0; localinfo->finished = true; return 0; } // call UReal::AtValue(CcReal value, vector& result) localinfo->NoOfResults = uinput->AtValue(*value, localinfo->resvector); localinfo->finished = (localinfo->NoOfResults <= 0); return 0; case REQUEST : if (local.addr == 0) return CANCEL; localinfo = (MappingUnitIntersection_rLocalInfo*) local.addr; if (localinfo->finished) return CANCEL; if ( localinfo->NoOfResults <= localinfo->ResultsDelivered ) { localinfo->finished = true; return CANCEL; } result = SetWord(localinfo->resvector[localinfo->ResultsDelivered].Clone()); localinfo->ResultsDelivered++; return YIELD; case CLOSE : if (local.addr != 0) { localinfo = (MappingUnitIntersection_rLocalInfo*) local.addr; delete localinfo; local.setAddr(Address(0)); } return 0; } // end switch // should not be reached return 0; } /* value mapping for ---- (upoint upoint) -> (stream upoint) ---- */ int temporalUnitIntersection_upoint_upoint( Word* args, Word& result, int message, Word& local, Supplier s ) { TUIntersectionLocalInfo *sli; Word u1, u2; UPoint *uv1, *uv2, *res; // test for overlapping intervals switch( message ) { case OPEN: #ifdef TUA_DEBUG cout << "temporalUnitIntersection_upoint_upoint: received OPEN" << endl; #endif sli = new TUIntersectionLocalInfo; sli->finished = true; sli->NoOfResults = 0; sli->NoOfResultsDelivered = 0; local.setAddr(sli); u1 = args[0]; u2 = args[1]; uv1 = (UPoint*) (u1.addr); uv2 = (UPoint*) (u2.addr); res = new UPoint( false ); uv1->Intersection(*uv2, *res); if ( res->IsDefined() && res->timeInterval.Inside(uv1->timeInterval) && res->timeInterval.Inside(uv2->timeInterval) ) { // 2nd and 3rd condition guarantees, that results on "open borders" // are filtered out (sli->resultValues[sli->NoOfResults]).setAddr( res ); sli->NoOfResults++; sli->finished = false; } else delete( res ); #ifdef TUA_DEBUG cout << "temporalUnitIntersection_upoint_upoint: finished OPEN (6)" << endl; #endif return 0; case REQUEST: #ifdef TUA_DEBUG cout << "temporalUnitIntersection_upoint_upoint: received REQUEST" << endl; #endif if(local.addr == 0) { #ifdef TUA_DEBUG cout << "temporalUnitIntersection_upoint_upoint: CANCEL (1)" << endl; #endif return CANCEL; } sli = (TUIntersectionLocalInfo*) local.addr; if(sli->finished) { #ifdef TUA_DEBUG cout << "temporalUnitIntersection_upoint_upoint: CANCEL (2)" << endl; #endif return CANCEL; } #ifdef TUA_DEBUG cout << " NoOfResults=" << sli->NoOfResults << endl << " NoOfResultsDelivered=" << sli->NoOfResultsDelivered << endl; #endif if(sli->NoOfResultsDelivered < sli->NoOfResults) { result.setAddr( ((UPoint*) (sli->resultValues[sli->NoOfResultsDelivered].addr))->Clone() ); ((UPoint*)(sli->resultValues[sli->NoOfResultsDelivered].addr)) ->DeleteIfAllowed(); sli->NoOfResultsDelivered++; #ifdef TUA_DEBUG cout << "temporalUnitIntersection_upoint_upoint: YIELD" << endl; #endif return YIELD; } sli->finished = true; #ifdef TUA_DEBUG cout << "temporalUnitIntersection_upoint_upoint: CANCEL (3)" << endl; #endif return CANCEL; case CLOSE: if (local.addr != 0) { sli = (TUIntersectionLocalInfo*) local.addr; while(sli->NoOfResultsDelivered < sli->NoOfResults) { ((UPoint*)(sli->resultValues[sli->NoOfResultsDelivered].addr)) ->DeleteIfAllowed(); sli->NoOfResultsDelivered++; } delete sli; local.setAddr(0); } return 0; } // end switch return 0; } /* value mapping for (upoint point) -> (stream upoint) and (point upoint) -> (stream upoint) is identical with at: (upoint point) -> (stream upoint). We just add switches for both signatures and the stream framework */ template int temporalUnitIntersection_upoint_point( Word* args, Word& result, int message, Word& local, Supplier s ) { TUIntersectionLocalInfo *sli; Word a0, a1; UPoint *unit, pResult(true); Point *val; switch( message ) { case OPEN: sli = new TUIntersectionLocalInfo; sli->finished = true; sli->NoOfResults = 0; sli->NoOfResultsDelivered = 0; local.setAddr(sli); if (uargindex == 0) { a0 = args[0]; a1 = args[1]; } else { a0 = args[1]; a1 = args[0]; } unit = ((UPoint*)a0.addr); val = ((Point*) a1.addr); if ( !unit->IsDefined() || !val->IsDefined() ) return 0; if (unit->At( *val, pResult )) { pResult.SetDefined(true); pResult.timeInterval.start.SetDefined(true); pResult.timeInterval.end.SetDefined(true); (sli->resultValues[sli->NoOfResults]).setAddr( pResult.Clone() ); sli->NoOfResults++; sli->finished = false; } return 0; case REQUEST: if(local.addr == 0) return CANCEL; sli = (TUIntersectionLocalInfo*) local.addr; if(sli->finished) return CANCEL; if(sli->NoOfResultsDelivered < sli->NoOfResults) { result.setAddr( ((UPoint*) (sli->resultValues[sli->NoOfResultsDelivered].addr))->Clone() ); ((UPoint*)(sli->resultValues[sli->NoOfResultsDelivered].addr)) ->DeleteIfAllowed(); sli->NoOfResultsDelivered++; return YIELD; } sli->finished = true; return CANCEL; case CLOSE: if (local.addr != 0) { sli = (TUIntersectionLocalInfo*) local.addr; while(sli->NoOfResultsDelivered < sli->NoOfResults) { ((UPoint*)(sli->resultValues[sli->NoOfResultsDelivered].addr)) ->DeleteIfAllowed(); sli->NoOfResultsDelivered++; } delete sli; local.setAddr(0); } return 0; } // end switch return 0; } /* Value mapping for ---- intersection: (upoint line) -> (stream upoint) (line upoint) -> (stream upoint) ---- Method ~TUUPointInsideLine~ Copied from TempralLiftedAlgebra calculates the periods where the given UPoint lies inside the given Line. It returns the existing intervals in a Periods-Object. */ static void TUUPointInsideLine(UPoint *u, Line& ln, Periods& pResult) { #ifdef TUA_DEBUG cout<<"MPointLineInside called"<IsDefined() || !ln.IsDefined() ){ pResult.SetDefined( false ); return; } pResult.SetDefined( true ); HalfSegment l; const UPoint* up = (UPoint*) u; Periods* period = new Periods(0); Periods* between = new Periods(0); Point pt; Interval newper; //part of the result #ifdef TUA_DEBUG cout << "up = " << *up << endl; #endif for( int n = 0; n < ln.Size(); n++) { Instant t; ln.Get(n, l); #ifdef TUA_DEBUG cout << "up = " << *up << endl; cout << "ln: Segment # "<< n << " l = " << l << endl; #endif if (l.GetRightPoint().GetX() == l.GetDomPoint().GetX() && l.GetRightPoint().GetY() == l.GetDomPoint().GetY()) { #ifdef TUA_DEBUG cout<<"right point is dominating -> continue"<p0.GetX() && l.GetRightPoint().GetX() < up->p1.GetX()) || (l.GetLeftPoint().GetX() > up->p0.GetX() && l.GetLeftPoint().GetX() > up->p1.GetX()) || (l.GetRightPoint().GetY() < up->p0.GetY() && l.GetRightPoint().GetY() < up->p1.GetY() && (l.GetLeftPoint().GetY() < up->p0.GetY() && l.GetLeftPoint().GetY() < up->p1.GetY())) || (l.GetRightPoint().GetY() > up->p0.GetY() && l.GetRightPoint().GetY() > up->p1.GetY() && (l.GetLeftPoint().GetY() > up->p0.GetY() && l.GetLeftPoint().GetY() > up->p1.GetY()))) { #ifdef TUA_DEBUG cout<<"Bounding Boxes not crossing!"<p1.GetX() == up->p0.GetX(); if(!vup){ aup = (up->p1.GetY() - up->p0.GetY()) / (up->p1.GetX() - up->p0.GetX()); bup = up->p0.GetY() - up->p0.GetX() * aup; #ifdef TUA_DEBUG cout<<"aup: "<p1.GetX() != l.GetLeftPoint().GetX()){ #ifdef TUA_DEBUG cout<<"elements are vertical but not at same line"<p1.GetY() < l.GetLeftPoint().GetY() && up->p0.GetY() < l.GetLeftPoint().GetY()){ #ifdef TUA_DEBUG cout<<"uPoint lower as linesegment"<p1.GetY() > l.GetRightPoint().GetY() && up->p0.GetY() > l.GetRightPoint().GetY()){ #ifdef TUA_DEBUG cout<<"uPoint higher as linesegment"<p0.GetY() <= l.GetLeftPoint().GetY() && up->p1.GetY() >= l.GetLeftPoint().GetY()){ #ifdef TUA_DEBUG cout<<"uPoint starts below linesegemet"<p0.GetY()) / (up->p1.GetY() - up->p0.GetY()) * (up->timeInterval.end.ToDouble() - up->timeInterval.start.ToDouble()) + up->timeInterval.start.ToDouble()); t.SetType(datetime::instanttype); #ifdef TUA_DEBUG cout<<"t "<timeInterval.start == t) ? up->timeInterval.lc : true; } if(up->p1.GetY() <= l.GetLeftPoint().GetY() && up->p0.GetY() >= l.GetLeftPoint().GetY()){ #ifdef TUA_DEBUG cout<<"uPoint ends below linesegemet"<p0.GetY()) / (up->p1.GetY() - up->p0.GetY()) * (up->timeInterval.end.ToDouble() - up->timeInterval.start.ToDouble()) + up->timeInterval.start.ToDouble()); t.SetType(datetime::instanttype); #ifdef TUA_DEBUG cout<<"t "<timeInterval.end == t) ? up->timeInterval.rc : true; } if(up->p0.GetY() <= l.GetRightPoint().GetY() && up->p1.GetY() >= l.GetRightPoint().GetY()){ #ifdef TUA_DEBUG cout<<"uPoint ends above linesegemet"<p0.GetY()) / (up->p1.GetY() - up->p0.GetY()) * (up->timeInterval.end.ToDouble() - up->timeInterval.start.ToDouble()) + up->timeInterval.start.ToDouble()); t.SetType(datetime::instanttype); #ifdef TUA_DEBUG cout<<"t "<timeInterval.end == t) ? up->timeInterval.rc : true; } if(up->p1.GetY() <= l.GetRightPoint().GetY() && up->p0.GetY() >= l.GetRightPoint().GetY()){ #ifdef TUA_DEBUG cout<<"uPoint starts above linesegemet"<p0.GetY()) / (up->p1.GetY() - up->p0.GetY()) * (up->timeInterval.end.ToDouble() - up->timeInterval.start.ToDouble()) + up->timeInterval.start.ToDouble()); t.SetType(datetime::instanttype); #ifdef TUA_DEBUG cout<<"t "<timeInterval.start == t) ? up->timeInterval.lc : true; } if (up->p0.GetY() <= l.GetRightPoint().GetY() && up->p0.GetY() >= l.GetLeftPoint().GetY()){ #ifdef TUA_DEBUG cout<<"uPoint starts inside linesegemet"<timeInterval.start; newper.lc = up->timeInterval.lc; } if( up->p1.GetY() <= l.GetRightPoint().GetY() && up->p1.GetY() >= l.GetLeftPoint().GetY()){ #ifdef TUA_DEBUG cout<<"uPoint ends inside linesegemet"<timeInterval.end; newper.rc = up->timeInterval.rc; } if(newper.start == newper.end && (!newper.lc || !newper.rc)){ #ifdef TUA_DEBUG cout<<"not an interval"<p0.GetX()) / (up->p1.GetX() - up->p0.GetX()) * (up->timeInterval.end.ToDouble() - up->timeInterval.start.ToDouble()) + up->timeInterval.start.ToDouble()); t.SetType(datetime::instanttype); #ifdef TUA_DEBUG cout<<"t "<timeInterval.start == t && !up->timeInterval.lc) || (up->timeInterval.end == t && !up->timeInterval.rc)) continue; if(up->timeInterval.start > t|| up->timeInterval.end < t){ #ifdef TUA_DEBUG cout<<"up outside line"<TemporalFunction(t, pt); if( pt.GetX() < l.GetLeftPoint().GetX() || pt.GetX() > l.GetRightPoint().GetX() || (pt.GetY() < l.GetLeftPoint().GetY() && pt.GetY() < l.GetRightPoint().GetY()) || (pt.GetY() > l.GetLeftPoint().GetY() && pt.GetY() > l.GetRightPoint().GetY())){ #ifdef TUA_DEBUG cout<<"pt outside up!"<p1.GetY() != up->p0.GetY()) { t.ReadFrom((up->p0.GetX() * al + bl - up->p0.GetY()) / (up->p1.GetY() - up->p0.GetY()) * (up->timeInterval.end.ToDouble() - up->timeInterval.start.ToDouble()) + up->timeInterval.start.ToDouble()); t.SetType(datetime::instanttype); #ifdef TUA_DEBUG cout<<"t "<timeInterval.start == t && !up->timeInterval.lc) || (up->timeInterval.end == t && !up->timeInterval.rc)){ #ifdef TUA_DEBUG cout<<"continue"<timeInterval.start > t|| up->timeInterval.end < t){ #ifdef TUA_DEBUG cout<<"up outside line"<TemporalFunction(t, pt); if( pt.GetX() < l.GetLeftPoint().GetX() || pt.GetX() > l.GetRightPoint().GetX() || (pt.GetY() < l.GetLeftPoint().GetY() && pt.GetY() < l.GetRightPoint().GetY()) || (pt.GetY() > l.GetLeftPoint().GetY() && pt.GetY() > l.GetRightPoint().GetY())){ #ifdef TUA_DEBUG cout<<"pt outside up!"<p1.GetX() + bl == up->p1.GetY()){ #ifdef TUA_DEBUG cout<<"Point lies on line"<timeInterval; } else { #ifdef TUA_DEBUG cout<<"continue 2"<p0.GetX() <= l.GetLeftPoint().GetX() && up->p1.GetX() >= l.GetLeftPoint().GetX()){ #ifdef TUA_DEBUG cout<<"uPoint starts left of linesegment"<p0.GetX()) / (up->p1.GetX() - up->p0.GetX()) * (up->timeInterval.end.ToDouble() - up->timeInterval.start.ToDouble()) + up->timeInterval.start.ToDouble()); t.SetType(datetime::instanttype); #ifdef TUA_DEBUG cout<<"t "<timeInterval.start == t) ? up->timeInterval.lc : true; } if(up->p1.GetX() <= l.GetLeftPoint().GetX() && up->p0.GetX() >= l.GetLeftPoint().GetX()){ #ifdef TUA_DEBUG cout<<"uPoint ends left of linesegment"<p0.GetX()) / (up->p1.GetX() - up->p0.GetX()) * (up->timeInterval.end.ToDouble() - up->timeInterval.start.ToDouble()) + up->timeInterval.start.ToDouble()); t.SetType(datetime::instanttype); #ifdef TUA_DEBUG cout<<"t "<timeInterval.end == t) ? up->timeInterval.rc : true; } if(up->p0.GetX() <= l.GetRightPoint().GetX() && up->p1.GetX() >= l.GetRightPoint().GetX()){ #ifdef TUA_DEBUG cout<<"uPoint ends right of linesegment"<p0.GetX()) / (up->p1.GetX() - up->p0.GetX()) * (up->timeInterval.end.ToDouble() - up->timeInterval.start.ToDouble()) + up->timeInterval.start.ToDouble()); t.SetType(datetime::instanttype); #ifdef TUA_DEBUG cout<<"t "<timeInterval.end == t) ? up->timeInterval.rc : true; } if(up->p1.GetX() <= l.GetRightPoint().GetX() && up->p0.GetX() >= l.GetRightPoint().GetX()){ #ifdef TUA_DEBUG cout<<"uPoint starts right of linesegment"<p0.GetX()) / (up->p1.GetX() - up->p0.GetX()) * (up->timeInterval.end.ToDouble() - up->timeInterval.start.ToDouble()) + up->timeInterval.start.ToDouble()); t.SetType(datetime::instanttype); #ifdef TUA_DEBUG cout<<"t "<timeInterval.start == t) ? up->timeInterval.lc : true; } if(up->p0.GetX() <= l.GetRightPoint().GetX() && up->p0.GetX() >= l.GetLeftPoint().GetX()){ #ifdef TUA_DEBUG cout<<"uPoint starts inside linesegment"<timeInterval.start; newper.lc = up->timeInterval.lc; } if(up->p1.GetX() <= l.GetRightPoint().GetX() && up->p1.GetX() >= l.GetLeftPoint().GetX()){ #ifdef TUA_DEBUG cout<<"uPoint ends inside linesegment"<timeInterval.end; newper.rc = up->timeInterval.rc; } if(newper.start == newper.end && (!newper.lc || !newper.rc)){ #ifdef TUA_DEBUG cout<<"not an interval"<p0.GetX()) / (up->p1.GetX() - up->p0.GetX()) * (up->timeInterval.end.ToDouble() - up->timeInterval.start.ToDouble()) + up->timeInterval.start.ToDouble()); t.SetType(datetime::instanttype); if((up->timeInterval.start == t && !up->timeInterval.lc) || (up->timeInterval.end == t && !up->timeInterval.rc)){ #ifdef TUA_DEBUG cout<<"continue"<timeInterval.start > t|| up->timeInterval.end < t){ #ifdef TUA_DEBUG cout<<"up outside line"<TemporalFunction(t, pt); if( pt.GetX() < l.GetLeftPoint().GetX() || pt.GetX() > l.GetRightPoint().GetX() || (pt.GetY() < l.GetLeftPoint().GetY() && pt.GetY() < l.GetRightPoint().GetY()) || (pt.GetY() > l.GetLeftPoint().GetY() && pt.GetY() > l.GetRightPoint().GetY())){ #ifdef TUA_DEBUG cout<<"pt outside up!"<Clear(); period->StartBulkLoad(); period->Add(newper); period->EndBulkLoad(false); if (!pResult.IsEmpty()) { between->Clear(); period->Union(pResult, *between); pResult.Clear(); pResult.CopyFrom(between); } else{ pResult.CopyFrom(period); } } // end for each segment delete between; delete period; } /* Method ~TUCompletePeriods2MPoint~ Copied from TempralLiftedAlgebra Completes a Periods-value to a MPoint-value. For this it adds the starting and end points. */ static void TUCompletePeriods2MPoint(UPoint* u, Periods* pResult, MPoint* endResult){ #ifdef TUA_DEBUG cout<<"TUCompletePeriods2MPoint called"<Clear(); if( !u->IsDefined() || !pResult->IsDefined() ){ endResult->SetDefined( false ); return; } endResult->SetDefined( true ); const UPoint* up = (UPoint*) u; Interval per; UPoint newUp(true); Point pt; int m = 0; bool pfinished = (pResult->GetNoComponents() == 0); endResult->StartBulkLoad(); for ( int i = 0; i < 1; i++) { if(!up->IsDefined()) continue; #ifdef TUA_DEBUG cout<<"*up = "<< *up <Get(m, per); #ifdef TUA_DEBUG cout<<"per "<timeInterval.end < per.start || (up->timeInterval.end == per.start && !up->timeInterval.rc && per.lc))) { #ifdef TUA_DEBUG cout<<"per not totally after up"<timeInterval.start < per.start || (up->timeInterval.start == per.start && up->timeInterval.lc && !per.lc)) { #ifdef TUA_DEBUG cout<<"up starts before per"<timeInterval.start; newUp.timeInterval.lc = up->timeInterval.lc; } while(true) { if(up->timeInterval.end < per.end || (up->timeInterval.end == per.end && per.rc && !up->timeInterval.rc)) { #ifdef TUA_DEBUG cout<<"per ends after up (break)"<timeInterval.end; newUp.timeInterval.rc = up->timeInterval.rc; up->TemporalFunction(newUp.timeInterval.start, pt, true); newUp.p0 = pt; up->TemporalFunction(newUp.timeInterval.end, pt, true); newUp.p1 = pt; #ifdef TUA_DEBUG cout<<"Add3 ("<("<Add(newUp); break; } else { #ifdef TUA_DEBUG cout<<"per ends inside up"<TemporalFunction(newUp.timeInterval.start, pt, true); newUp.p0 = pt; up->TemporalFunction(newUp.timeInterval.end, pt, true); newUp.p1 = pt; #ifdef TUA_DEBUG cout<<"Add4 ("<("<Add(newUp); } if(m == pResult->GetNoComponents() - 1){ #ifdef TUA_DEBUG cout<<"last per"<Get(++m, per); #ifdef TUA_DEBUG cout<<"per "<timeInterval.end || (per.start == up->timeInterval.end && up->timeInterval.rc && per.rc))){ #ifdef TUA_DEBUG cout<<"next per starts in same up"< finish up"<EndBulkLoad(false); } /* The value mapping function: */ template int temporalUnitIntersection_upoint_line( Word* args, Word& result, int message, Word& local, Supplier s ) { TUIntersectionLocalInfo *sli; Word a0, a1; UPoint res(true); UPoint *u; Line *l; Periods *p; UPoint cu; switch( message ) { case OPEN: #ifdef TUA_DEBUG cout << "temporalUnitIntersection_upoint_line<" << uargindex << ">: Received OPEN" << endl; #endif p = new Periods(10); sli = new TUIntersectionLocalInfo; sli->finished = true; sli->NoOfResults = 0; sli->NoOfResultsDelivered = 0; sli->mpoint = new MPoint(10); local.setAddr(sli); // initialize arguments, such that a0 always contains the upoint // and a1 the line #ifdef TUA_DEBUG cout << " uargindex=" << uargindex << endl; #endif if (uargindex == 0) { a0 = args[0]; a1 = args[1]; } else { a0 = args[1]; a1 = args[0]; } u = (UPoint*)(a0.addr); l = (Line*)(a1.addr); // test for definedness if ( !u->IsDefined() || !l->IsDefined() || l->IsEmpty() ) { #ifdef TUA_DEBUG cout << " Undef/Empty arg -> Empty Result" << endl << endl; #endif // nothing to do } else { TUUPointInsideLine(u, *l, *p); // get intersecting timeintervals TUCompletePeriods2MPoint(u, p, sli->mpoint); // create upoints sli->NoOfResults = sli->mpoint->GetNoComponents(); sli->finished = (sli->NoOfResults <= 0); #ifdef TUA_DEBUG cout << " " << sli->NoOfResults << " result units" << endl << endl; #endif } delete p; #ifdef TUA_DEBUG cout << "temporalUnitIntersection_upoint_line: Finished OPEN" << endl; #endif return 0; case REQUEST: if(local.addr == 0) return CANCEL; sli = (TUIntersectionLocalInfo*) local.addr; if(sli->finished) return CANCEL; if(sli->NoOfResultsDelivered < sli->NoOfResults) { sli->mpoint->Get(sli->NoOfResultsDelivered, cu); result.setAddr( cu.Clone() ); sli->NoOfResultsDelivered++; return YIELD; } sli->finished = true; return CANCEL; case CLOSE: if (local.addr != 0) { sli = (TUIntersectionLocalInfo*) local.addr; delete sli->mpoint; delete sli; local.setAddr(0); } return 0; } // end switch return 0; } // for (upoint uregion) -> (stream upoint) (with <0, true>) // (uregion upoint) -> (stream upoint) (with <1, true>) // (upoint region) -> (stream upoint) (with <0, false>) // (region upoint) -> (stream upoint) (with <1, false>) // template int temporalUnitIntersection_upoint_uregion( Word* args, Word& result, int message, Word& local, Supplier s ) { // This implementation uses class function // MRegion::Intersection(MPoint& mp, MPoint& res) // by creating a single-unit MRegion and a single-unit MPoint // This is not very clever, but is comparable to the implementation found in // the MovingRegionAlgebra. TUIntersectionLocalInfo *sli; Word a0, a1; UPoint *u = 0; URegion *r = 0; Region *f = 0; MPoint *mp_tmp; MRegion *mr_tmp; UPoint cu; switch( message ) { case OPEN: #ifdef TUA_DEBUG std::cerr << "temporalUnitIntersection_upoint_uregion<" << uargindex << ", " << regionismoving << ">: Received OPEN" << endl; #endif sli = new TUIntersectionLocalInfo; sli->finished = true; sli->NoOfResults = 0; sli->NoOfResultsDelivered = 0; sli->mpoint = new MPoint(10); local.setAddr(sli); // initialize arguments, such that a0 always contains the upoint // and a1 the uregion/region #ifdef TUA_DEBUG std::cerr << " uargindex=" << uargindex << endl; #endif if (uargindex == 0) { a0 = args[0]; a1 = args[1]; } else if (uargindex == 1) { a0 = args[1]; a1 = args[0]; } else { std::cerr << "temporalUnitIntersection_upoint_uregion<" << uargindex << ", " << regionismoving << ">: WRONG uargindex!" << endl; return -1; } u = (UPoint*)(a0.addr); if ( regionismoving ) r = (URegion*)(a1.addr); else f = (Region*) (a1.addr); // test for definedness if ( !u->IsDefined() || ( regionismoving && !r->IsDefined()) || (!regionismoving && !f->IsDefined()) ) { #ifdef TUA_DEBUG std::cerr << " Undef arg -> Empty Result" << endl << endl; #endif // nothing to do } else { mp_tmp = new MPoint(1); // create temporary MPoint mp_tmp->SetDefined(true); mp_tmp->Add(*u); // create temporary MRegion if ( regionismoving ) { // case (upoint x uregion): from a URegion mr_tmp = new MRegion(1); mr_tmp->SetDefined(true); mr_tmp->AddURegion(*r); //mr_tmp.EndBulkLoad(); assert( mr_tmp->IsDefined() ); } else { // case (upoint x region): from (MPoint,Region) mr_tmp = new MRegion(*mp_tmp, *f); assert( mr_tmp->IsDefined() ); } mr_tmp->Intersection(*mp_tmp, *(sli->mpoint)); // get and save result; delete mp_tmp; delete mr_tmp; sli->NoOfResults = sli->mpoint->GetNoComponents(); sli->finished = (sli->NoOfResults <= 0); #ifdef TUA_DEBUG std::cerr << " " << sli->NoOfResults << " result units" << endl << endl; #endif } #ifdef TUA_DEBUG std::cerr << "temporalUnitIntersection_upoint_uregion: Finished OPEN" << endl; #endif return 0; case REQUEST: #ifdef TUA_DEBUG std::cerr << "temporalUnitIntersection_upoint_uregion<" << uargindex << ", " << regionismoving << ">: Received REQUEST" << endl; #endif if(local.addr == 0) { #ifdef TUA_DEBUG std::cerr << "temporalUnitIntersection_upoint_uregion<" << uargindex << ", " << regionismoving << ">: Finished REQUEST (1)" << endl; #endif return CANCEL; } sli = (TUIntersectionLocalInfo*) local.addr; if(sli->finished) { #ifdef TUA_DEBUG std::cerr << "temporalUnitIntersection_upoint_uregion<" << uargindex << ", " << regionismoving << ">: Finished REQUEST (2)" << endl; #endif return CANCEL; } if(sli->NoOfResultsDelivered < sli->NoOfResults) { sli->mpoint->Get(sli->NoOfResultsDelivered, cu); result.setAddr( cu.Clone() ); sli->NoOfResultsDelivered++; #ifdef TUA_DEBUG std::cerr << "temporalUnitIntersection_upoint_uregion<" << uargindex << ", " << regionismoving << ">: Finished REQUEST (YIELD)" << endl; #endif return YIELD; } sli->finished = true; #ifdef TUA_DEBUG std::cerr << "temporalUnitIntersection_upoint_uregion<" << uargindex << ", " << regionismoving << ">: Finished REQUEST (3)" << endl; #endif return CANCEL; case CLOSE: #ifdef TUA_DEBUG std::cerr << "temporalUnitIntersection_upoint_uregion<" << uargindex << ", " << regionismoving << ">: Received CLOSE" << endl; #endif if (local.addr != 0) { sli = (TUIntersectionLocalInfo*) local.addr; delete sli->mpoint; delete sli; local.setAddr(0); } #ifdef TUA_DEBUG std::cerr << "temporalUnitIntersection_upoint_uregion<" << uargindex << ", " << regionismoving << ">: Finished CLOSE" << endl; #endif return 0; } // end switch std::cerr << "temporalUnitIntersection_upoint_uregion<" << uargindex << ", " << regionismoving << ">: Received UNKNOWN COMMAND" << endl; return 0; } // For signatures // (upoint region) -> (stream upoint) (with <0>) // (region upoint) -> (stream upoint) (with <1>) struct TUIntersectionUPointRegionLocalInfo { TUIntersectionUPointRegionLocalInfo() : finished(true), NoOfResults(0), NoOfResultsDelivered(0) { results.clear(); } ~TUIntersectionUPointRegionLocalInfo() {} bool finished; int NoOfResults; int NoOfResultsDelivered; std::vector results; }; template int temporalUnitIntersection_upoint_region( Word* args, Word& result, int message, Word& local, Supplier s ) { TUIntersectionUPointRegionLocalInfo *sli = static_cast(local.addr); Word a0, a1; UPoint *u = 0; Region *r = 0; UPoint cu; switch( message ) { case OPEN: if(sli){ delete sli; } sli = new TUIntersectionUPointRegionLocalInfo; local.setAddr(sli); // initialize arguments, such that a0 always contains the upoint // and a1 the uregion/region if (uargindex == 0) { a0 = args[0]; a1 = args[1]; } else if (uargindex == 1) { a0 = args[1]; a1 = args[0]; } else { std::cerr << __PRETTY_FUNCTION__ << ": WRONG uargindex!" << endl; return -1; } u = static_cast(a0.addr); r = static_cast(a1.addr); // test for definedness if ( u->IsDefined() && r->IsDefined() ){ if(u->AtRegion(r, sli->results)) { sli->NoOfResults = sli->results.size(); sli->finished = (sli->NoOfResults <= 0); } else { std::cerr << __PRETTY_FUNCTION__ << ": INFO: UPoint::AtRegion failed!" << endl; } } return 0; case REQUEST: if( !sli || sli->finished || (sli->NoOfResultsDelivered >= sli->NoOfResults) ){ sli->finished = true; return CANCEL; } else { result.setAddr(sli->results[sli->NoOfResultsDelivered].Clone()); sli->NoOfResultsDelivered++; return YIELD; } case CLOSE: if (sli) { delete sli; local.setAddr(0); } return 0; } // end switch std::cerr << __PRETTY_FUNCTION__ << ": Received UNKNOWN COMMAND" << endl; return 0; } template int temporalUnitIntersection_uregion_region( Word* args, Word& result, int message, Word& local, Supplier s ) { std::cerr << "temporalUnitIntersection_uregion_region(): Not yet Implemented!" << endl; return 0; } /* 5.26.3 Specification for operator ~intersection~ */ const std::string TemporalUnitIntersectionSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" ) " "(" "For T in {bool, int, real, string, point}:\n" "(uT uT) -> (stream uT)*\n" "(uT T) -> (stream uT)\n" "( T uT) -> (stream uT)\n" "(line upoint) -> (stream upoint)\n" "(upoint line) -> (stream upoint)\n" "(upoint uregion) -> (stream upoint)\n" "(uregion upoint) -> (stream upoint)\n" "(upoint region) -> (stream upoint)\n" "(region upoint) -> (stream upoint)\n" "(*): Not yet implemented for T = real" "intersection(_, _)" "Returns the intersection of two unit datatype values " "or of a unit datatype and its corrosponding simple datatype " "as a stream of that unit datatype." "query intersection(upoint1, upoint2) count" ") )"; /* 5.26.4 Selection Function of operator ~intersection~ */ ValueMapping temporalunitintersectionmap[] = { temporalUnitIntersection_CU_CU, // 0 temporalUnitIntersection_CU_CU, temporalUnitIntersection_ureal_ureal, temporalUnitIntersection_upoint_upoint, temporalUnitIntersection_CU_CU, temporalUnitIntersection_CU_C, // 5 temporalUnitIntersection_CU_C, temporalUnitIntersection_ureal_real<0>, temporalUnitIntersection_upoint_point<0>, temporalUnitIntersection_CU_C, temporalUnitIntersection_CU_C, // 10 temporalUnitIntersection_CU_C, temporalUnitIntersection_ureal_real<1>, temporalUnitIntersection_upoint_point<1>, temporalUnitIntersection_CU_C, temporalUnitIntersection_upoint_line<0>, // 15 temporalUnitIntersection_upoint_line<1>, temporalUnitIntersection_upoint_uregion<0, true>, temporalUnitIntersection_upoint_uregion<1, true>, temporalUnitIntersection_upoint_region<0>, temporalUnitIntersection_upoint_region<1> // 20 }; int temporalunitIntersectionSelect( ListExpr args ) { ListExpr arg1 = nl->First(args); ListExpr arg2 = nl->Second(args); if( nl->IsEqual( arg1, UBool::BasicType() ) && nl->IsEqual( arg2, UBool::BasicType()) ) return 0; if( nl->IsEqual( arg1, UInt::BasicType() ) && nl->IsEqual( arg2, UInt::BasicType() ) ) return 1; if( nl->IsEqual( arg1, UReal::BasicType() ) && nl->IsEqual( arg2, UReal::BasicType() ) ) return 2; if( nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, UPoint::BasicType() ) ) return 3; if( nl->IsEqual( arg1, UString::BasicType() ) && nl->IsEqual( arg2, UString::BasicType() ) ) return 4; if( nl->IsEqual( arg1, UBool::BasicType() ) && nl->IsEqual( arg2, CcBool::BasicType() )) return 5; if( nl->IsEqual( arg1, UInt::BasicType() ) && nl->IsEqual( arg2, CcInt::BasicType() )) return 6; if( nl->IsEqual( arg1, UReal::BasicType() ) && nl->IsEqual( arg2, CcReal::BasicType() )) return 7; if( nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, Point::BasicType() ) ) return 8; if( nl->IsEqual( arg1, UString::BasicType() ) && nl->IsEqual( arg2, CcString::BasicType() )) return 9; if( nl->IsEqual( arg2, UBool::BasicType() ) && nl->IsEqual( arg1, CcBool::BasicType() )) return 10; if( nl->IsEqual( arg2, UInt::BasicType() ) && nl->IsEqual( arg1, CcInt::BasicType() )) return 11; if( nl->IsEqual( arg2, UReal::BasicType() ) && nl->IsEqual( arg1, CcReal::BasicType() )) return 12; if( nl->IsEqual( arg2, UPoint::BasicType() ) && nl->IsEqual( arg1, Point::BasicType() )) return 13; if( nl->IsEqual( arg2, UString::BasicType() ) && nl->IsEqual( arg1, UString::BasicType() )) return 14; if( nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, Line::BasicType() )) return 15; if( nl->IsEqual( arg1, Line::BasicType() ) && nl->IsEqual( arg2, UPoint::BasicType() ) ) return 16; if( nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, URegion::BasicType() ) ) return 17; if( nl->IsEqual( arg1, URegion::BasicType() ) && nl->IsEqual( arg2, UPoint::BasicType() ) ) return 18; if( nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, Region::BasicType() ) ) return 19; if( nl->IsEqual( arg1, Region::BasicType() ) && nl->IsEqual( arg2, UPoint::BasicType() ) ) return 20; std::cerr << "ERROR: Unmatched case in temporalunitIntersectionSelect" << endl; std::string argstr; nl->WriteToString(argstr, args); std::cerr << " Argumets = '" << argstr << "'." << endl; return -1; } /* 5.26.5 Definition of operator ~intersection~ */ Operator temporalunitintersection( "intersection", TemporalUnitIntersectionSpec, 21, temporalunitintersectionmap, temporalunitIntersectionSelect, TemporalUnitIntersectionTypeMap); /* 5.13 Operator ~at~ The operator restricts a unit type to the interval, where it's value is equal to a given value. For base types ~bool~, ~int~ and ~point~, the result will be only a single unit, but for base type ~real~, there may be two units, as ~ureal~ is represented by a quadratic polynomial function (or it's radical). 5.13.1 Type Mapping for ~at~ ---- at: For T in {bool, int, string, point, region*} OK + uT x T --> uT OK ureal x real --> (stream ureal) OK + upoint x region --> (stream upoint) upoint x rect --> upoint (*): Not yet implemented ---- */ ListExpr TemporalUnitAtTypeMapUnit( ListExpr args ) { ListExpr arg1, arg2; if( nl->ListLength( args ) == 2 ) { arg1 = nl->First( args ); arg2 = nl->Second( args ); #ifdef TUA_DEBUG cout << "\nTemporalUnitAtTypeMapUnit: 0" << endl; #endif if( nl->IsEqual( arg1, UBool::BasicType() ) && nl->IsEqual( arg2, CcBool::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UBool::BasicType() )); if( nl->IsEqual( arg1, UInt::BasicType() ) && nl->IsEqual( arg2, CcInt::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UInt::BasicType() )); if( nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, Point::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UPoint::BasicType() )); // for ureal, _ at _ will return a stream of ureals! if( nl->IsEqual( arg1, UReal::BasicType() ) && nl->IsEqual( arg2, CcReal::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UReal::BasicType() )); if( nl->IsEqual( arg1, UString::BasicType() ) && nl->IsEqual( arg2, CcString::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UString::BasicType() )); if( nl->IsEqual( arg1, URegion::BasicType() ) && nl->IsEqual( arg2, Region::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( URegion::BasicType() )); if( nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, Region::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UPoint::BasicType() )); if( nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, Rectangle<2>::BasicType() ) ) return nl->SymbolAtom( UPoint::BasicType() ); } #ifdef TUA_DEBUG cout << "\nTemporalUnitAtTypeMapUnit: 1" << endl; #endif return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.13.2 Value Mapping for ~at~ Instead of implementing dedicated value mappings, we use those for operator ~intersection~ except for "upoint x rect". */ int AtUpR(Word* args, Word& result, int message, Word& local, Supplier s) { result = qp->ResultStorage(s); UPoint* arg1 = static_cast(args[0].addr); Rectangle<2>* arg2 = static_cast*>(args[1].addr); UPoint* res = static_cast(result.addr); arg1->At(*arg2,*res); return 0; } /* 5.13.3 Specification for operator ~at~ */ const std::string TemporalSpecAt = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( For T in {bool, int, string, point, region*}:\n" "(uT T ) -> (stream uT)\n" "(ureal real ) -> (stream ureal)\n" "(upoint region) -> (stream upoint)\n" "(upoint rect) -> upoint\n" "(*): Not yet implemented" "_ at _ " "restrict the movement to the times " "where the equality occurs.\n" "Observe, that the result is always a " "'(stream UNIT)' rather than a 'UNIT'! except for upoint x rect" "upoint1 at point1 the_mvalue ) )"; /* 5.13.4 Selection Function of operator ~at~ */ int TUSelectAt( ListExpr args ) { ListExpr arg1 = nl->First( args ), arg2 = nl->Second( args ); if( nl->SymbolValue( arg1 ) == UBool::BasicType() && nl->SymbolValue( arg2 ) == CcBool::BasicType() ) return 0; if( nl->SymbolValue( arg1 ) == UInt::BasicType() && nl->SymbolValue( arg2 ) == CcInt::BasicType() ) return 1; if( nl->SymbolValue( arg1 ) == UReal::BasicType() && nl->SymbolValue( arg2 ) == CcReal::BasicType() ) return 2; if( nl->SymbolValue( arg1 ) == UPoint::BasicType() && nl->SymbolValue( arg2 ) == Point::BasicType() ) return 3; if( nl->SymbolValue( arg1 ) == UString::BasicType() && nl->SymbolValue( arg2 ) == CcString::BasicType() ) return 4; if( nl->SymbolValue( arg1 ) == URegion::BasicType() && nl->SymbolValue( arg2 ) == Region::BasicType() ) return 5; if( nl->SymbolValue( arg1 ) == UPoint::BasicType() && nl->SymbolValue( arg2 ) == Region::BasicType() ) return 6; if( nl->SymbolValue( arg1 ) == UPoint::BasicType() && nl->SymbolValue( arg2 ) == Rectangle<2>::BasicType() ) return 7; return -1; // This point should never be reached } ValueMapping temporalunitatmap[] = { temporalUnitIntersection_CU_C< UBool, CcBool, 0 >, //0 temporalUnitIntersection_CU_C< UInt, CcInt, 0 >, //1 temporalUnitIntersection_ureal_real<0>, //2 temporalUnitIntersection_upoint_point<0>, //3 temporalUnitIntersection_CU_C< UString, CcString, 0 >, //4 temporalUnitIntersection_uregion_region<0>, //5 temporalUnitIntersection_upoint_region<0>, //6 AtUpR}; //7 /* 5.13.5 Definition of operator ~at~ */ Operator temporalunitat( "at", TemporalSpecAt, 8, temporalunitatmap, TUSelectAt, TemporalUnitAtTypeMapUnit ); /* 5.31 Operator ~no\_components~ Return the number of components (units) contained by the object. For unit types, the result is either undef (for undef values) or a const unit with value=1 (otherwise). ---- n/a + no_components: (uT) --> uint ---- */ /* 5.31.1 Type mapping function for ~no\_components~ */ static ListExpr TUNoComponentsTypeMap(ListExpr args) { if (nl->ListLength(args) == 1) { if (nl->IsEqual(nl->First(args), UBool::BasicType())) return nl->SymbolAtom(UInt::BasicType()); if (nl->IsEqual(nl->First(args), UInt::BasicType())) return nl->SymbolAtom(UInt::BasicType()); if (nl->IsEqual(nl->First(args), UReal::BasicType())) return nl->SymbolAtom(UInt::BasicType()); if (nl->IsEqual(nl->First(args), UString::BasicType())) return nl->SymbolAtom(UInt::BasicType()); if (nl->IsEqual(nl->First(args), UPoint::BasicType())) return nl->SymbolAtom(UInt::BasicType()); if (nl->IsEqual(nl->First(args), URegion::BasicType())) return nl->SymbolAtom(UInt::BasicType()); } return nl->SymbolAtom(Symbol::TYPEERROR()); } /* 5.31.2 Value mapping for operator ~no\_components~ */ template int TUNoComponentsValueMap(Word* args, Word& result, int message, Word& local, Supplier s) { result = (qp->ResultStorage( s )); UInt *res = (UInt*)result.addr; T *input = (T*)args[0].addr; if ( input->IsDefined() ) { res->SetDefined(true); res->timeInterval.CopyFrom(input->timeInterval); res->constValue.Set(true,1); } else { res->SetDefined(false); res->constValue.Set(true,0); } return 0; } /* 5.31.3 Specification for operator ~no\_components~ */ const std::string TUNoComponentsSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( For T in {bool, int, real, point, region}:\n" "(uT) -> uint" "no_components( _ )" "Returns an undef uint for undef unit, an uint with the " "argument's deftime and value '1' otherwise." "query no_components([const uint value undef])" ") )"; /* 5.31.4 Selection Function of operator ~no\_components~ Uses ~UnitSimpleSelect( ListExpr args )~ */ ValueMapping temporalunitNoComponentsvaluemap[] = { TUNoComponentsValueMap, TUNoComponentsValueMap, TUNoComponentsValueMap, TUNoComponentsValueMap, TUNoComponentsValueMap, TUNoComponentsValueMap}; /* 5.31.5 Definition of operator ~no\_components~ */ Operator temporalunitnocomponents ( "no_components", TUNoComponentsSpec, 6, temporalunitNoComponentsvaluemap, UnitSimpleSelect, TUNoComponentsTypeMap ); /* 5.32 Operator ~isempty~ The operator returns TRUE, if the unit is undefined, otherwise it returns FALSE. It will never return an undefined result! ---- For U in kind UNIT and U in kind DATA: isempty U --> bool ---- */ /* 5.32.1 Type mapping function for ~isempty~ */ ListExpr TUIsemptyTypeMap( ListExpr args ) { ListExpr arg1; ListExpr errorInfo = nl->OneElemList(nl->SymbolAtom(Symbol::ERRORS())); if ( ( nl->ListLength(args) == 1 ) && ( nl->IsAtom(nl->First(args) ) ) ) { arg1 = nl->First(args); if( am->CheckKind(Kind::UNIT(), arg1, errorInfo) ) return nl->SymbolAtom(CcBool::BasicType()); } ErrorReporter::ReportError("Operator isempty expects a list of length one, " "containing a value of type 'U' with U in " "kind UNIT."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.32.2 Value mapping for operator ~isempty~ */ int TUIsemptyValueMap( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); Attribute* val = ((Attribute*)args[0].addr); ((CcBool *)result.addr)->Set( true, !val->IsDefined() ); return 0; } /* 5.32.3 Specification for operator ~isempty~ */ const std::string TUIsemptySpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( For U in kind UNIT:\n" "U -> bool" "isempty( _ )" "The operator returns TRUE, if the unit is undefined, " "otherwise it returns FALSE. It will never return an " "undefined result!" "query isempty([const uint value undef])" ") )"; /* 5.32.4 Selection Function of operator ~isempty~ Simple selection is used, as there is only one value mapping function. */ ValueMapping temporalunitIsemptyvaluemap[] = { TUIsemptyValueMap }; /* 5.32.5 Definition of operator ~isempty~ */ Operator temporalunitisempty ( "isempty", TUIsemptySpec, 1, temporalunitIsemptyvaluemap, Operator::SimpleSelect, TUIsemptyTypeMap ); /* 5.33 Operator ~not~ Negates an ubool. ---- not: ubool --> ubool ---- */ /* 5.33.1 Type mapping function for ~not~ */ ListExpr TUNotTypeMap( ListExpr args ) { if ( nl->ListLength( args ) == 1 ) { ListExpr arg1 = nl->First( args ); if( nl->IsEqual( arg1, UBool::BasicType() ) ) return nl->SymbolAtom( UBool::BasicType() ); } return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.33.2 Value mapping for operator ~not~ */ int TUNotValueMap(Word* args, Word& result, int message, Word& local, Supplier s) { result = (qp->ResultStorage( s )); UBool *res = (UBool*) result.addr; UBool *input = (UBool*)args[0].addr; if(!input->IsDefined()){ res->SetDefined( false ); } else { res->SetDefined( true ); res->CopyFrom(input); res->constValue.Set(res->constValue.IsDefined(), !(res->constValue.GetBoolval())); } return 0; } /* 5.33.3 Specification for operator ~not~ */ const std::string TUNotSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( ubool -> ubool" "not( _ )" "The operator returns the logical complement of " "its argument. Undef argument resullts in an undef result." "" "query not([const ubool value ((\"2010-11-11\" " "\"2011-01-03\" TRUE FALSE) TRUE)])" ") )"; /* 5.33.4 Selection Function of operator ~not~ We use simple selection: */ ValueMapping temporalunitNotvaluemap[] = { TUNotValueMap }; /* 5.33.5 Definition of operator ~not~ */ Operator temporalunitnot ( "not", TUNotSpec, 1, temporalunitNotvaluemap, Operator::SimpleSelect, TUNotTypeMap ); /* 5.34 Operators ~and~ and ~or~ These operators perform the binary conjunction/disjunction for ubool (and bool): ---- and, or: ubool x ubool -> ubool bool x ubool -> ubool ubool x bool -> ubool ---- */ /* 5.34.1 Type mapping function for ~and~ and ~or~ We implement a genric function for binary boolean functions here: */ ListExpr TUBinaryBoolFuncTypeMap( ListExpr args ) { if( nl->ListLength( args ) == 2 ) { ListExpr arg1 = nl->First( args ); ListExpr arg2 = nl->Second( args ); // First case: ubool ubool -> ubool if ( nl->IsEqual( arg1, UBool::BasicType() ) && nl->IsEqual( arg2, UBool::BasicType() ) ) return nl->SymbolAtom(UBool::BasicType()); // Second case: ubool bool -> ubool if( nl->IsEqual( arg1, UBool::BasicType() ) && nl->IsEqual( arg2, CcBool::BasicType()) ) return nl->SymbolAtom(UBool::BasicType()); // Third case: bool ubool -> ubool if( nl->IsEqual( arg1, CcBool::BasicType() ) && nl->IsEqual( arg2, UBool::BasicType()) ) return nl->SymbolAtom(UBool::BasicType()); // Error case: std::string argstr1, argstr2; nl->WriteToString(argstr1, arg1); nl->WriteToString(argstr2, arg2); ErrorReporter::ReportError( "Binary booleon operator expects any combination of {bool, ubool} " "as arguments, but the passed arguments have types '"+ argstr1 + "' and '" + argstr2 + "'."); } else { ErrorReporter::ReportError( "Binary booleon operator expects any combination of {bool, ubool} " "as arguments."); } return nl->SymbolAtom(Symbol::TYPEERROR()); } /* 5.34.2 Value mapping for operators ~and~ and ~or~ */ template int TUAndValueMap(Word* args, Word& result, int message, Word& local, Supplier s) { assert( (ArgConf>=0) && (ArgConf<=2)); result = (qp->ResultStorage( s )); UBool *res = (UBool*) result.addr; UBool *u1, *u2; CcBool *cb; Interval iv; if(ArgConf == 0) // case: ubool x ubool -> ubool { u1 = (UBool*) args[0].addr; u2 = (UBool*) args[1].addr; if (!u1->IsDefined() || !u2->IsDefined() || !u1->timeInterval.Intersects( u2->timeInterval) ) res->SetDefined( false ); else { u1->timeInterval.Intersection( u2->timeInterval, iv ); res->SetDefined( true ); res->timeInterval = iv; res->constValue.Set( u1->constValue.IsDefined() && u2->constValue.IsDefined(), u1->constValue.GetBoolval() && u2->constValue.GetBoolval()); } return 0; } else if(ArgConf == 1) // case: ubool x bool -> ubool { u1 = (UBool*)args[0].addr; cb = (CcBool*)args[1].addr; } else if(ArgConf == 2) // case: bool x ubool -> ubool { u1 = (UBool*)args[1].addr; cb = (CcBool*)args[0].addr; } if (!u1->IsDefined() || !cb->IsDefined()) res->SetDefined( false ); else { res->CopyFrom(u1); res->constValue.Set(u1->constValue.IsDefined(), u1->constValue.GetBoolval() && cb->GetBoolval() ); } return 0; } template int TUOrValueMap(Word* args, Word& result, int message, Word& local, Supplier s) { assert( (ArgConf>=0) && (ArgConf<=2)); result = (qp->ResultStorage( s )); UBool *res = (UBool*) result.addr; UBool *u1, *u2; CcBool *cb; Interval iv; if(ArgConf == 0) // case: ubool x ubool -> ubool { u1 = (UBool*) args[0].addr; u2 = (UBool*) args[1].addr; if (!u1->IsDefined() || !u2->IsDefined() || !u1->timeInterval.Intersects( u2->timeInterval) ) res->SetDefined( false ); else { u1->timeInterval.Intersection( u2->timeInterval, iv ); res->SetDefined( true ); res->timeInterval = iv; res->constValue.Set( u1->constValue.IsDefined() && u2->constValue.IsDefined(), u1->constValue.GetBoolval() || u2->constValue.GetBoolval()); } return 0; } else if(ArgConf == 1) // case: ubool x bool -> ubool { u1 = (UBool*)args[0].addr; cb = (CcBool*)args[1].addr; } else if(ArgConf == 2) // case: bool x ubool -> ubool { u1 = (UBool*)args[1].addr; cb = (CcBool*)args[0].addr; } if (!u1->IsDefined() || !cb->IsDefined()) res->SetDefined( false ); else { res->CopyFrom(u1); res->constValue.Set(u1->constValue.IsDefined(), u1->constValue.GetBoolval() || cb->GetBoolval() ); } return 0; } /* 5.34.3 Specification for operators ~and~ and ~or~ */ const std::string TUAndSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( (ubool ubool) -> ubool\n" "(ubool bool) -> ubool\n" "( bool ubool) -> ubool" "_ and _" "The operator returns the logical conjunction of its " "arguments, restricted to their common deftime. Any undefined " "argument or non-overlapping intervals result in an " "undefined result." "" "query [const ubool value ((\"2010-11-11\" " "\"2011-01-03\" TRUE FALSE) TRUE)] and [const ubool value " "((\"2011-01-01\"2012-09-17\" FALSE TRUE) TRUE)]" ") )"; const std::string TUOrSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( (ubool ubool) -> ubool\n" "(ubool bool) -> ubool\n" "( bool ubool) -> ubool" "_ or _" "The operator returns the logical disjunction of its " "arguments, restricted to their common deftime. Any undefined " "argument or non-overlapping intervals result in an " "undefined result." "" "query [const ubool value ((\"2010-11-11\" " "\"2011-01-03\" TRUE FALSE) TRUE)] or [const ubool value " "((\"2011-01-01\"2012-09-17\" FALSE TRUE) TRUE)]" ") )"; /* 5.34.4 Selection Function of operators ~and~ and ~or~ */ int TUBinaryBoolFuncSelect( ListExpr args ) { ListExpr arg1 = nl->First( args ), arg2 = nl->Second( args ); if( nl->SymbolValue( arg1 ) == UBool::BasicType() && nl->SymbolValue( arg2 ) == UBool::BasicType() ) return 0; if( nl->SymbolValue( arg1 ) == UBool::BasicType() && nl->SymbolValue( arg2 ) == CcBool::BasicType() ) return 1; if( nl->SymbolValue( arg1 ) == CcBool::BasicType() && nl->SymbolValue( arg2 ) == UBool::BasicType() ) return 2; return -1; // This point should never be reached } ValueMapping temporalunitAndValuemap[] = { TUAndValueMap<0>, TUAndValueMap<1>, TUAndValueMap<2> }; ValueMapping temporalunitOrValuemap[] = { TUOrValueMap<0>, TUOrValueMap<1>, TUOrValueMap<2> }; /* 5.34.5 Definition of operators ~and~ and ~or~ */ Operator temporalunitand ( "and", TUAndSpec, 3, temporalunitAndValuemap, TUBinaryBoolFuncSelect, TUBinaryBoolFuncTypeMap ); Operator temporalunitor ( "or", TUOrSpec, 3, temporalunitOrValuemap, TUBinaryBoolFuncSelect, TUBinaryBoolFuncTypeMap ); /* 5.35 Operator ~ComparePredicates~ Here, we implement the binary comparison operators/predicates for (uT uT). The predicates are: ---- == (equality), ## (unequality), << (smaller than), >> (bigger than), <<== (smaller than or equal to), >>== (bigger than or equal to). ---- The operators use the internal ~Compare~ function, which implements an ordering on the elements, but does not need to respect intuitive operator semantics (e.g. in case ureal). They compare whole units as such. They do NOT compare the values! WARNING: Do not confuse this operators with the ~CompareValuePredicates~, which compare the values. ---- =, #, <, >, <=, >=: For T in {int, bool, real, string, point, region} n/a + uT x uT --> bool ---- */ /* 5.35.1 Type mapping function for ~ComparePredicates~ */ ListExpr TUComparePredicatesTypeMap( ListExpr args ) { if( nl->ListLength( args ) == 2 ) { ListExpr arg1 = nl->First( args ); ListExpr arg2 = nl->Second( args ); if (nl->Equal( arg1, arg2 )) { if( (nl->IsEqual( arg1, UBool::BasicType() ) ) || (nl->IsEqual( arg1, UInt::BasicType() ) ) || (nl->IsEqual( arg1, UString::BasicType() ) ) || (nl->IsEqual( arg1, UReal::BasicType() ) ) || (nl->IsEqual( arg1, URegion::BasicType() ) ) || (nl->IsEqual( arg1, UPoint::BasicType() ) ) ) return nl->SymbolAtom( CcBool::BasicType() ); } std::string argstr1, argstr2; nl->WriteToString(argstr1, arg1); nl->WriteToString(argstr2, arg2); ErrorReporter::ReportError( "Compare Operator (one of ==, ##, <<, >>, , <<==, >>==) expects " "two arguments of type 'uT', where T in {bool, int, real, " "string, point, region}./nThe passed arguments have types '" + argstr1 +"' and '" + argstr2 + "'."); } else { // Error case: ErrorReporter::ReportError( "Compare Operator (one of ==, ##, <<, >>, , <<==, >>==) expects " "two arguments of type 'uT', where T in {bool, int, real, " "string, point, region}./n"); } return nl->SymbolAtom(Symbol::TYPEERROR()); } /* 5.35.2 Value mapping for operator ~ComparePredicates~ template parameter ~OPType~ gives the character of the operator: ---- 0 =, 1 #, 2 <, 3 >, 4 <=, 5 >=- ---- */ template int TUComparePredicatedValueMap(Word* args, Word& result, int message, Word& local, Supplier s) { assert( (OpType>=0) && (OpType<=5)); result = (qp->ResultStorage( s )); CcBool *res = (CcBool*) result.addr; Attribute *u1, *u2; int p1; u1 = (Attribute*)args[0].addr; u2 = (Attribute*)args[1].addr; p1 = u1->Compare(u2); switch (OpType) { case 0: // is_equal res->Set(true, (p1 == 0)); return 0; case 1: // is_not_equal res->Set(true, (p1 != 0)); return 0; case 2: // less_than res->Set(true, (p1 == -1)); return 0; case 3: // bigger_than res->Set(true, (p1 == 1)); return 0; case 4: // less_or_equal res->Set(true, (p1 < 1) ); return 0; case 5: // bigger_or_equal res->Set(true, (p1 > -1)); return 0; } res->Set(false, false); return -1; // should not happen } /* 5.35.3 Specification for operator ~ComparePredicates~ */ const std::string TUEqSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( (uT uT) -> bool\n" "_ == _" "The operator checks if the internal ordering predicate " "holds for both arguments." "query [const ubool value ((\"2010-11-11\" " "\"2011-01-03\" TRUE FALSE) TRUE)] == [const ubool value " "((\"2011-01-01\" \"2012-09-17\" FALSE TRUE) TRUE)]" ") )"; const std::string TUNEqSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( (uT uT) -> bool\n" "_ ## _" "The operator checks if the internal ordering predicate " "holds for both arguments." "query [const ubool value ((\"2010-11-11\" " "\"2011-01-03\" TRUE FALSE) TRUE)] ## [const ubool value " "((\"2011-01-01\" \"2012-09-17\" FALSE TRUE) TRUE)]" ") )"; const std::string TULtSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( (uT uT) -> bool\n" "_ << _" "The operator checks if the internal ordering predicate " "holds for both arguments." "query [const ubool value ((\"2010-11-11\" " "\"2011-01-03\" TRUE FALSE) TRUE)] << [const ubool value " "((\"2011-01-01\" \"2012-09-17\" FALSE TRUE) TRUE)]" ") )"; const std::string TUBtSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( (uT uT) -> bool\n" "_ >> _" "The operator checks if the internal ordering predicate " "holds for both arguments." "query [const ubool value ((\"2010-11-11\" " "\"2011-01-03\" TRUE FALSE) TRUE)] >> [const ubool value " "((\"2011-01-01\" \"2012-09-17\" FALSE TRUE) TRUE)]" ") )"; const std::string TULtEqSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( (uT uT) -> bool\n" "_ <<== _" "The operator checks if the internal ordering predicate " "holds for both arguments." "query [const ubool value ((\"2010-11-11\" " "\"2011-01-03\" TRUE FALSE) TRUE)] <<== [const ubool value " "((\"2011-01-01\" \"2012-09-17\" FALSE TRUE) TRUE)]" ") )"; const std::string TUBtEqSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( (uT uT) -> bool\n" "_ >>== _" "The operator checks if the internal ordering predicate " "holds for both arguments." "query [const ubool value ((\"2010-11-11\" " "\"2011-01-03\" TRUE FALSE) TRUE)] >>== [const ubool value " "((\"2011-01-01\" \"2012-09-17\" FALSE TRUE) TRUE)]" ") )"; /* 5.35.4 Selection Function of operator ~ComparePredicates~ We can use Operator::SimpleSelect: */ /* 5.35.5 Definition of operator ~ComparePredicates~ */ Operator temporalunitisequal ( "==", TUEqSpec, TUComparePredicatedValueMap<0>, Operator::SimpleSelect, TUComparePredicatesTypeMap ); Operator temporalunitisnotequal ( "##", TUNEqSpec, TUComparePredicatedValueMap<1>, Operator::SimpleSelect, TUComparePredicatesTypeMap ); Operator temporalunitsmaller ( "<<", TULtSpec, TUComparePredicatedValueMap<2>, Operator::SimpleSelect, TUComparePredicatesTypeMap ); Operator temporalunitbigger ( ">>", TUBtSpec, TUComparePredicatedValueMap<3>, Operator::SimpleSelect, TUComparePredicatesTypeMap ); Operator temporalunitsmallereq ( "<<==", TULtEqSpec, TUComparePredicatedValueMap<4>, Operator::SimpleSelect, TUComparePredicatesTypeMap ); Operator temporalunitbiggereq ( ">>==", TUBtEqSpec, TUComparePredicatedValueMap<5>, Operator::SimpleSelect, TUComparePredicatesTypeMap ); /* 5.36 Operator ~uint2ureal~ This operator creates an ureal value from an uint value ---- uint --> ureal ---- */ /* 5.36.1 Type mapping function for ~uint2ureal~ */ ListExpr TUuint2urealTypeMap( ListExpr args ) { if( nl->ListLength( args ) == 1 ) { ListExpr arg1 = nl->First( args ); if( nl->IsEqual( arg1, UInt::BasicType() ) ) return nl->SymbolAtom(UReal::BasicType()); // Error case: std::string argstr1; nl->WriteToString(argstr1, arg1); ErrorReporter::ReportError( "Operator uint2ureal expects an argument of type 'uint', " "but the passed argument has type '"+ argstr1 + "'."); } else { ErrorReporter::ReportError( "Operator uint2ureal expects an argument of type 'uint'."); } return nl->SymbolAtom(Symbol::TYPEERROR()); } /* 5.36.2 Value mapping for operator ~uint2ureal~ */ int TUuint2urealValueMap(Word* args, Word& result, int message, Word& local, Supplier s) { result = (qp->ResultStorage( s )); UReal *res = (UReal*) result.addr; UInt *u1; u1 = (UInt*)args[0].addr; res->SetDefined(u1->IsDefined()); if ( u1->IsDefined() ) { res->timeInterval.CopyFrom(u1->timeInterval); res->a = 0.0; res->b = 0.0; res->c = u1->constValue.GetIntval(); res->r = false; } return 0; } /* 5.36.3 Specification for operator ~uint2ureal~ */ const std::string TUuint2urealSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( uint -> ureal\n" "uint2ureal( _ )" "The operator creates a ureal value from an uint value." "query uint2ureal([const uint value ((\"2010-11-11\" " "\"2011-01-03\" TRUE FALSE) -5.4)])" ") )"; /* 5.36.4 Selection Function of operator ~uint2ureal~ We use Operator::SimpleSelect here. */ /* 5.36.5 Definition of operator ~uint2ureal~ */ Operator temporalunituint2ureal ( "uint2ureal", TUuint2urealSpec, TUuint2urealValueMap, Operator::SimpleSelect, TUuint2urealTypeMap ); /* 5.37 Operator ---- inside: OK + upoint x uregion --> (stream ubool) OK + upoint x line --> (stream ubool) pre + upoint x points --> (stream ubool) pre + uregion x points --> (stream ubool) ---- */ /* 5.37.1 Type mapping function for ~inside~ */ ListExpr TemporalUnitInsideTypeMap( ListExpr args ) { ListExpr arg1, arg2; std::string argstr; if( nl->ListLength( args ) == 2 ) { arg1 = nl->First( args ); arg2 = nl->Second( args ); if( nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, URegion::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UBool::BasicType() )); if( nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, Line::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UBool::BasicType() )); if( nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, Points::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UBool::BasicType() )); if( nl->IsEqual( arg1, URegion::BasicType() ) && nl->IsEqual( arg2, Points::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UBool::BasicType() )); } // Error case: nl->WriteToString(argstr, args); ErrorReporter::ReportError( "Operator inside expects a list of length two with a certain signature. " "But it gets '" + argstr + "'."); return nl->SymbolAtom(Symbol::TYPEERROR()); } /* 5.37.2 Value mapping for operator ~inside~ */ struct TUInsideLocalInfo { bool finished; int NoOfResults; int NoOfResultsDelivered; MBool *mbool; // Used to store results }; // case upoint x uregion --> (stream ubool) int temporalUnitInside_up_ur( Word* args, Word& result, int message, Word& local, Supplier s ) { // This implementation uses class-function // void MRegion::Inside(MPoint& mp, MBool& res) TUInsideLocalInfo *sli; Word a0, a1; UPoint *u; URegion *r; UBool cu; switch( message ) { case OPEN: #ifdef TUA_DEBUG std::cerr << "temporalUnitInside_up_ur: Received OPEN" << endl; #endif sli = new TUInsideLocalInfo; sli->finished = true; sli->NoOfResults = 0; sli->NoOfResultsDelivered = 0; sli->mbool = new MBool(10); local.setAddr(sli); // initialize arguments, such that a0 always contains the upoint // and a1 the uregion a0 = args[0]; a1 = args[1]; u = (UPoint*)(a0.addr); r = (URegion*)(a1.addr); // test for definedness if ( !u->IsDefined() || !r->IsDefined() ) { #ifdef TUA_DEBUG std::cerr << " Undef arg -> Empty Result" << endl << endl; #endif // nothing to do } else { MPoint mp_tmp(1); mp_tmp.Clear(); // create temporary MPoint mp_tmp.SetDefined( true ); mp_tmp.Add(*u); MRegion mr_tmp(1); mr_tmp.Clear(); // create temporary MRegion mr_tmp.SetDefined( true ); mr_tmp.AddURegion(*r); mr_tmp.Inside(mp_tmp, *(sli->mbool)); // get and save result; sli->NoOfResults = sli->mbool->GetNoComponents(); sli->finished = (sli->NoOfResults <= 0); #ifdef TUA_DEBUG std::cerr << " " << sli->NoOfResults << " result units" << endl << endl; #endif } #ifdef TUA_DEBUG std::cerr << "temporalUnitInside_up_ur: Finished OPEN" << endl; #endif return 0; case REQUEST: #ifdef TUA_DEBUG std::cerr << "temporalUnitInside_up_ur: Received REQUEST"<< endl; #endif if(local.addr == 0) { #ifdef TUA_DEBUG std::cerr << "temporalUnitInside_up_ur: Finished REQUEST (1)" << endl; #endif return CANCEL; } sli = (TUInsideLocalInfo*) local.addr; if(sli->finished) { #ifdef TUA_DEBUG std::cerr << "temporalUnitInside_up_ur: Finished REQUEST (2)"<< endl; #endif return CANCEL; } if(sli->NoOfResultsDelivered < sli->NoOfResults) { sli->mbool->Get(sli->NoOfResultsDelivered, cu); result.setAddr( cu.Clone() ); sli->NoOfResultsDelivered++; #ifdef TUA_DEBUG std::cerr << "temporalUnitInside_up_ur: " << "Finished REQUEST (YIELD)" << endl; #endif return YIELD; } sli->finished = true; #ifdef TUA_DEBUG std::cerr << "temporalUnitInside_up_ur: Finished REQUEST (3)"<< endl; #endif return CANCEL; case CLOSE: #ifdef TUA_DEBUG std::cerr << "temporalUnitInside_up_ur: Received CLOSE"<< endl; #endif if (local.addr != 0) { sli = (TUInsideLocalInfo*) local.addr; delete sli->mbool; delete sli; local.setAddr(0); } #ifdef TUA_DEBUG std::cerr << "temporalUnitInside_up_ur: Finished CLOSE"<< endl; #endif return 0; } // end switch std::cerr << "temporalUnitInside_up_ur: Received UNKNOWN COMMAND" << endl; return 0; } // case upoint x line --> (stream ubool) int temporalUnitInside_up_l( Word* args, Word& result, int message, Word& local, Supplier s ) { cout << "\nATTENTION: temporalUnitInside_up_l " << "not yet implemented!" << endl; assert( false ); return 0; } // case upoint x points --> (stream ubool) int temporalUnitInside_up_pts( Word* args, Word& result, int message, Word& local, Supplier s ) { cout << "\nATTENTION: temporalUnitInside_up_pts " << "not yet implemented!" << endl; assert( false ); return 0; } // case uregion x points --> (stream ubool) int temporalUnitInside_ur_pts( Word* args, Word& result, int message, Word& local, Supplier s ) { cout << "\nATTENTION: temporalUnitInside_ur_pts " << "not yet implemented!" << endl; assert( false ); return 0; } /* 5.37.3 Specification for operator ~inside~ */ const std::string TemporalUnitInsideSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" ) " "(" "" "(upoint uregion) -> (stream ubool)\n" "(upoint line) -> (stream ubool)*\n" "(upoint points) -> (stream ubool)*\n" "(uregion points) -> (stream ubool)*\n" "(*): Not yet implemented" "_ inside _" "Returns a stream of ubool indicating, whether the first " "object is fully included by the second one." "query upoint1 inside uregion1 count" ") )"; /* 5.37.4 Selection Function of operator ~inside~ */ ValueMapping temporalunitinsidemap[] = { temporalUnitInside_up_ur, temporalUnitInside_up_l, temporalUnitInside_up_pts, temporalUnitInside_ur_pts }; int temporalunitInsideSelect( ListExpr args ) { ListExpr arg1 = nl->First(args); ListExpr arg2 = nl->Second(args); if( nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, URegion::BasicType()) ) return 0; if( nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, Line::BasicType() ) ) return 1; if( nl->IsEqual( arg1, UPoint::BasicType() ) && nl->IsEqual( arg2, Points::BasicType() ) ) return 2; if( nl->IsEqual( arg1, URegion::BasicType() ) && nl->IsEqual( arg2, Points::BasicType() ) ) return 3; std::cerr << "ERROR: Unmatched case in temporalunitInsideSelect" << endl; std::string argstr; nl->WriteToString(argstr, args); std::cerr << " Argumets = '" << argstr << "'." << endl; return -1; } /* 5.37.5 Definition of operator ~inside~ */ Operator temporalunitinside( "inside", TemporalUnitInsideSpec, 4, temporalunitinsidemap, temporalunitInsideSelect, TemporalUnitInsideTypeMap); /* 5.38 Operator ~sometimes~ ---- sometimes: ( ubool) --> bool (stream ubool) --> bool ---- */ /* 5.38.1 Type mapping function for ~sometimes~ */ ListExpr TemporalUnitBoolAggrTypeMap( ListExpr args ) { ListExpr t; std::string argstr; if ( nl->ListLength( args ) == 1 ) { if (nl->IsAtom(nl->First(args))) t = nl->First( args ); else if (nl->ListLength(nl->First(args))==2 && nl->IsEqual(nl->First(nl->First(args)), Symbol::STREAM())) t = nl->Second(nl->First(args)); else { ErrorReporter::ReportError ("Operator sometimes/always/never expects a (stream ubool)" "or (ubool)."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } if( nl->IsEqual( t, UBool::BasicType() ) ) return nl->SymbolAtom( CcBool::BasicType() ); } nl->WriteToString(argstr, args); ErrorReporter::ReportError ("Operator sometimes/always/never expects a list of length one, " "having list structure (ubool) or (stream ubool), but it gets '" + argstr + "'."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.38.2 Value mapping for operator ~sometimes~ */ int TemporalUnitSometimes_streamubool( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); CcBool *res = (CcBool*) result.addr; Word elem; UBool *U; bool found = false; qp->Open(args[0].addr); // open input stream qp->Request(args[0].addr, elem); // get first elem from stream while ( !found && qp->Received(args[0].addr) ) { U = (UBool*) elem.addr; if ( U->IsDefined() && U->constValue.GetBoolval() ){ found = true; } else { qp->Request(args[0].addr, elem); } U->DeleteIfAllowed(); } qp->Close(args[0].addr); // close the stream // create and return the result res->Set( true, found ); return 0; } int TemporalUnitSometimes_ubool( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); CcBool *res = (CcBool*) result.addr; UBool *U = (UBool*) args[0].addr; res->Set( true, ( U->IsDefined() && U->constValue.GetBoolval() ) ); return 0; } /* 5.38.3 Specification for operator ~sometimes~ */ const std::string TemporalUnitSometimesSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" ) " "(" "" "ubool -> bool\n" "(stream ubool) -> bool\n" "" "sometimes( _ )" "Returns 'true', iff the ubool/stream of ubool is 'true'" "at least once, otherwise 'false'. Never returns 'undef' itself." "query sometimes(ubool1)" ") )"; /* 5.38.4 Selection Function of operator ~sometimes~ */ int TemporalUnitBoolAggrSelect( ListExpr args ) { ListExpr arg1 = nl->First( args ); return UBool::checkType(arg1)?0:1; } ValueMapping TemporalUnitSometimesMap[] = { TemporalUnitSometimes_ubool, TemporalUnitSometimes_streamubool, }; /* 5.38.5 Definition of operator ~sometimes~ */ Operator temporalunitsometimes( "sometimes", TemporalUnitSometimesSpec, 2, TemporalUnitSometimesMap, TemporalUnitBoolAggrSelect, TemporalUnitBoolAggrTypeMap); /* 5.38 Operator ~never~ ---- never: ( ubool) --> bool (stream ubool) --> bool ---- */ /* 5.39.1 Type mapping function for ~never~ Using ~TemporalUnitBoolAggrTypeMap~ */ /* 5.39.2 Value mapping for operator ~never~localinfo */ int TemporalUnitNever_streamubool( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); CcBool *res = (CcBool*) result.addr; Word elem; UBool *U; bool found = true; qp->Open(args[0].addr); // open input stream qp->Request(args[0].addr, elem); // get first elem from stream while ( found && qp->Received(args[0].addr) ) { U = (UBool*) elem.addr; if ( U->IsDefined() && U->constValue.GetBoolval() ) found = false; else qp->Request(args[0].addr, elem); U->DeleteIfAllowed(); } qp->Close(args[0].addr); // close the stream // create and return the result res->Set( true, found ); return 0; } int TemporalUnitNever_ubool( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); CcBool *res = (CcBool*) result.addr; UBool *U = (UBool*) args[0].addr; res->Set( true, ( !U->IsDefined() || !U->constValue.GetBoolval() ) ); return 0; } /* 5.39.3 Specification for operator ~never~ */ const std::string TemporalUnitNeverSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" ) " "(" "" "ubool -> bool\n" "(stream ubool) -> bool\n" "" "never( _ )" "Returns 'true', iff the ubool/stream does never take value 'true', " "otherwise 'false'. Never returns 'undef'." "query never(ubool1)" ") )"; /* 5.39.4 Selection Function of operator ~never~ Using ~TemporalUnitBoolAggrSelect~ */ ValueMapping TemporalUnitNeverMap[] = { TemporalUnitNever_ubool, TemporalUnitNever_streamubool, }; /* 5.39.5 Definition of operator ~never~ */ Operator temporalunitnever( "never", TemporalUnitNeverSpec, 2, TemporalUnitNeverMap, TemporalUnitBoolAggrSelect, TemporalUnitBoolAggrTypeMap); /* 5.40 Operator ~always~ ---- always: ( ubool) --> bool (stream ubool) --> bool ---- */ /* 5.40.1 Type mapping function for ~always~ Using ~TemporalUnitBoolAggrTypeMap~ */ /* 5.40.2 Value mapping for operator ~always~ */ int TemporalUnitAlways_streamubool( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); CcBool *res = (CcBool*) result.addr; Word elem; UBool *U; bool found = true; qp->Open(args[0].addr); // open input stream qp->Request(args[0].addr, elem); // get first elem from stream while ( found && qp->Received(args[0].addr) ) { U = (UBool*) elem.addr; if ( U->IsDefined() && !U->constValue.GetBoolval() ) found = false; else qp->Request(args[0].addr, elem); U->DeleteIfAllowed(); } qp->Close(args[0].addr); // close the stream // create and return the result res->Set( true, found ); return 0; } int TemporalUnitAlways_ubool( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); CcBool *res = (CcBool*) result.addr; UBool *U = (UBool*) args[0].addr; res->Set( true, ( U->IsDefined() && U->constValue.GetBoolval() ) ); return 0; } /* 5.40.3 Specification for operator ~always~ */ const std::string TemporalUnitAlwaysSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" ) " "(" "" "ubool -> bool\n" "(stream ubool) -> bool" "" "always( _ )" "Returns 'false', iff the ubool/stream takes value 'false' " "at least once, otherwise 'true'. Never returns 'undef'." "query never(ubool1)" ") )"; /* 5.40.4 Selection Function of operator ~always~ Using ~TemporalUnitBoolAggrSelect~ */ ValueMapping TemporalUnitAlwaysMap[] = { TemporalUnitAlways_ubool, TemporalUnitAlways_streamubool, }; /* 5.40.5 Definition of operator ~always~ */ Operator temporalunitalways( "always", TemporalUnitAlwaysSpec, 2, TemporalUnitAlwaysMap, TemporalUnitBoolAggrSelect, TemporalUnitBoolAggrTypeMap); /* 5.41 Operator ~the\_unit~ ---- the_unit: For T in {bool, int, string} point point instant instant bool bool --> upoint ipoint ipoint bool bool --> upoint real real real bool instant instant bool bool --> ureal iT duration bool bool --> uT T instant instant bool bool --> uT ---- */ /* 5.41.1 Type mapping function for ~the\_unit~ */ ListExpr TU_TM_TheUnit( ListExpr args ) { if (nl->Equal(args , nl->SixElemList(nl->SymbolAtom(Point::BasicType()), nl->SymbolAtom(Point::BasicType()), nl->SymbolAtom(Instant::BasicType()), nl->SymbolAtom(Instant::BasicType()), nl->SymbolAtom(CcBool::BasicType()), nl->SymbolAtom(CcBool::BasicType())))){ return nl->SymbolAtom( UPoint::BasicType() ); } if (nl->Equal(args , nl->FourElemList(nl->SymbolAtom(IPoint::BasicType()), nl->SymbolAtom(IPoint::BasicType()), nl->SymbolAtom(CcBool::BasicType()), nl->SymbolAtom(CcBool::BasicType())))){ return nl->SymbolAtom( UPoint::BasicType() ); } if(nl->Equal(args ,nl->Cons( nl->SymbolAtom(CcReal::BasicType()), nl->Cons( nl->SymbolAtom(CcReal::BasicType()), nl->SixElemList(nl->SymbolAtom(CcReal::BasicType()), nl->SymbolAtom(CcBool::BasicType()), nl->SymbolAtom(Instant::BasicType()), nl->SymbolAtom(Instant::BasicType()), nl->SymbolAtom(CcBool::BasicType()), nl->SymbolAtom(CcBool::BasicType())))))){ return nl->SymbolAtom( UReal::BasicType() ); } if (nl->Equal(args , nl->FiveElemList(nl->SymbolAtom(CcBool::BasicType()), nl->SymbolAtom(Instant::BasicType()), nl->SymbolAtom(Instant::BasicType()), nl->SymbolAtom(CcBool::BasicType()), nl->SymbolAtom(CcBool::BasicType())))){ return nl->SymbolAtom( UBool::BasicType() ); } if (nl->Equal(args , nl->FourElemList(nl->SymbolAtom(IBool::BasicType()), nl->SymbolAtom(Duration::BasicType()), nl->SymbolAtom(CcBool::BasicType()), nl->SymbolAtom(CcBool::BasicType())))){ return nl->SymbolAtom( UBool::BasicType() ); } if (nl->Equal(args , nl->FiveElemList(nl->SymbolAtom(CcInt::BasicType()), nl->SymbolAtom(Instant::BasicType()), nl->SymbolAtom(Instant::BasicType()), nl->SymbolAtom(CcBool::BasicType()), nl->SymbolAtom(CcBool::BasicType())))){ return nl->SymbolAtom( UInt::BasicType() ); } if (nl->Equal(args , nl->FourElemList(nl->SymbolAtom(IInt::BasicType()), nl->SymbolAtom(Duration::BasicType()), nl->SymbolAtom(CcBool::BasicType()), nl->SymbolAtom(CcBool::BasicType())))){ return nl->SymbolAtom( UInt::BasicType() ); } if (nl->Equal(args , nl->FiveElemList(nl->SymbolAtom(CcString::BasicType()), nl->SymbolAtom(Instant::BasicType()), nl->SymbolAtom(Instant::BasicType()), nl->SymbolAtom(CcBool::BasicType()), nl->SymbolAtom(CcBool::BasicType())))){ return nl->SymbolAtom( UString::BasicType() ); } if (nl->Equal(args , nl->FourElemList(nl->SymbolAtom(IString::BasicType()), nl->SymbolAtom(Duration::BasicType()), nl->SymbolAtom(CcBool::BasicType()), nl->SymbolAtom(CcBool::BasicType())))){ return nl->SymbolAtom( UString::BasicType() ); } if (nl->Equal(args, nl->TwoElemList(nl->SymbolAtom(CcString::BasicType()), nl->SymbolAtom(SecInterval::BasicType())))) { return nl->SymbolAtom(UString::BasicType()); } if (nl->Equal(args, nl->TwoElemList(nl->SymbolAtom(CcInt::BasicType()), nl->SymbolAtom(SecInterval::BasicType())))) { return nl->SymbolAtom(UInt::BasicType()); } if (nl->Equal(args, nl->TwoElemList(nl->SymbolAtom(CcBool::BasicType()), nl->SymbolAtom(SecInterval::BasicType())))) { return nl->SymbolAtom(UBool::BasicType()); } if (nl->Equal(args, nl->FiveElemList(nl->SymbolAtom(CcReal::BasicType()), nl->SymbolAtom(CcReal::BasicType()), nl->SymbolAtom(CcReal::BasicType()), nl->SymbolAtom(CcBool::BasicType()), nl->SymbolAtom(SecInterval::BasicType())))) { return nl->SymbolAtom(UReal::BasicType()); } if (nl->Equal(args, nl->ThreeElemList(nl->SymbolAtom(Point::BasicType()), nl->SymbolAtom(Point::BasicType()), nl->SymbolAtom(SecInterval::BasicType())))) { return nl->SymbolAtom(UPoint::BasicType()); } return listutils::typeError( "Operator 'the_unit' expects a list with structure\n" "'(point point instant instant bool bool)', or \n" "'(ipoint ipoint bool bool)', or \n" "'(real real real bool instant instant bool bool)', or\n" "'(T instant instant bool bool)', or \n" "'(iT duration bool bool)'\n for T in {bool, int, string}, or\n" "'(T interval)' for T in {bool, int, string}, or\n" "'(real real real bool interval)', or\n" "'(point point interval)'"); } /* 5.41.2 Value mapping for operator ~the\_unit~ */ // point point instant instant bool bool --> ubool int TU_VM_TheUnit_ppiibb(Word* args, Word& result, int message, Word& local, Supplier s) { result = (qp->ResultStorage( s )); UPoint *res = (UPoint*)result.addr; Point *p1 = (Point*)args[0].addr; Point *p2 = (Point*)args[1].addr; Instant *i1 = (Instant*)args[2].addr; Instant *i2 = (Instant*)args[3].addr; CcBool *cl = (CcBool*)args[4].addr; CcBool *cr = (CcBool*)args[5].addr; bool clb, crb; // Test arguments for definedness if ( !p1->IsDefined() || !p2->IsDefined() || !i1->IsDefined() || !i2->IsDefined() || !cl->IsDefined() || !cr->IsDefined() ) { res->SetDefined( false ); return 0; } clb = cl->GetBoolval(); crb = cr->GetBoolval(); if ( ( (*i1 == *i2) && (!clb || !crb) ) || ( i1->Adjacent(i2) && !(clb || crb) ) ) // illegal interval setting { res->SetDefined( false ); return 0; } if ( *i1 < *i2 ) // sort instants { Interval interval( *i1, *i2, clb, crb ); *res = UPoint( interval, *p1, *p2 ); } else { Interval interval( *i2, *i1, clb, crb ); *res = UPoint( interval, *p2, *p1 ); } return 0; } // ipoint ipoint bool bool --> upoint int TU_VM_TheUnit_ipipbb(Word* args, Word& result, int message, Word& local, Supplier s) { result = (qp->ResultStorage( s )); UPoint *res = (UPoint*)result.addr; Intime *ip1 = (Intime *)args[0].addr; Intime *ip2 = (Intime *)args[1].addr; CcBool *cl = (CcBool*)args[2].addr; CcBool *cr = (CcBool*)args[3].addr; bool clb, crb; // Test arguments for definedness if ( !ip1->IsDefined() || !ip2->IsDefined() || !cl->IsDefined() || !cr->IsDefined() ) { res->SetDefined( false ); return 0; } clb = cl->GetBoolval(); crb = cr->GetBoolval(); if ( ( (ip1->instant == ip2->instant) && (!clb || !crb) ) || ( ip1->instant.Adjacent(&ip2->instant) && !(clb || crb) ) ) // illegal interval setting { res->SetDefined( false ); return 0; } if ( ip1->instant < ip2->instant ) // sort instants { Interval interval( ip1->instant, ip2->instant, clb, crb ); *res = UPoint( interval, ip1->value, ip2->value ); } else { Interval interval( ip2->instant, ip1->instant, clb, crb ); *res = UPoint( interval, ip2->value, ip1->value ); } return 0; } // real real real bool instant instant bool bool -> ubool int TU_VM_TheUnit_rrrbiibb(Word* args, Word& result, int message, Word& local, Supplier s) { result = (qp->ResultStorage( s )); UReal *res = (UReal*)result.addr; CcReal *a = (CcReal*)args[0].addr; CcReal *b = (CcReal*)args[1].addr; CcReal *c = (CcReal*)args[2].addr; CcBool *r = (CcBool*)args[3].addr; Instant *i1 = (Instant*)args[4].addr; Instant *i2 = (Instant*)args[5].addr; CcBool *cl = (CcBool*)args[6].addr; CcBool *cr = (CcBool*)args[7].addr; bool clb, crb; // Test arguments for definedness if ( !a->IsDefined() || !b->IsDefined() || !c->IsDefined() || !r->IsDefined() || !i1->IsDefined() || !i2->IsDefined() || !cl->IsDefined() || !cr->IsDefined() ) { res->SetDefined( false ); return 0; } clb = cl->GetBoolval(); crb = cr->GetBoolval(); if ( ( (*i1 == *i2) && (!clb || !crb) ) || ( i1->Adjacent(i2) && !(clb || crb) ) )// illegal interval setting { res->SetDefined( false ); return 0; } if ( *i1 < *i2 ) // sort instants { Interval interval( *i1, *i2, clb, crb ); *res = UReal( interval, a->GetRealval(), b->GetRealval(), c->GetRealval(), r->GetBoolval() ); } else { Interval interval( *i2, *i1, clb, crb ); *res = UReal( interval, a->GetRealval(), b->GetRealval(), c->GetRealval(), r->GetBoolval() ); }; return 0; } // template for constant unit types: // iT duration bool bool -> uT template int TU_VM_TheUnit_iTdbb(Word* args, Word& result, int message, Word& local, Supplier s) { result = (qp->ResultStorage( s )); ConstTemporalUnit *res = (ConstTemporalUnit *)result.addr; Intime *ip = (Intime *)args[0].addr; datetime::DateTime *dur = (datetime::DateTime*) args[1].addr; CcBool *cl = (CcBool*)args[2].addr; CcBool *cr = (CcBool*)args[3].addr; bool clb, crb; // Test arguments for definedness if ( !ip->IsDefined() || !dur->IsDefined() || !cl->IsDefined() || !cr->IsDefined() ) { res->SetDefined( false ); return 0; } clb = cl->GetBoolval(); crb = cr->GetBoolval(); assert(dur->GetType() == datetime::durationtype); if ( ( (*dur == datetime::DateTime(0,0,datetime::durationtype)) && (!clb || !crb) ) || ( (*dur == datetime::DateTime(0,1,datetime::durationtype)) && !( clb || crb) ) ) // illegal interval setting { res->SetDefined( false ); return 0; } Interval interval( ip->instant, ip->instant+(*dur), clb, crb ); *res = ConstTemporalUnit( interval, ip->value ); return 0; } // template for constant unit types: // T instant instant bool bool -> uT template int TU_VM_TheUnit_Tiibb(Word* args, Word& result, int message, Word& local, Supplier s) { result = (qp->ResultStorage( s )); ConstTemporalUnit *res = static_cast *>(result.addr); T *value = static_cast(args[0].addr); Instant *i1 = static_cast(args[1].addr); Instant *i2 = static_cast(args[2].addr); CcBool *cl = static_cast(args[3].addr); CcBool *cr = static_cast(args[4].addr); bool clb, crb; // Test arguments for definedness if ( !value->IsDefined() || !i1->IsDefined() || !i2->IsDefined() || !cl->IsDefined() || !cr->IsDefined() ) { res->SetDefined( false ); return 0; } clb = cl->GetBoolval(); crb = cr->GetBoolval(); if ( ( (*i1 == *i2) && (!clb || !crb) ) || ( i1->Adjacent(i2) && !(clb || crb) ) ) { // illegal interval setting res->SetDefined( false ); return 0; } if ( *i1 < *i2 ) {// sort instants Interval interval( *i1, *i2, clb, crb ); *res = ConstTemporalUnit( interval, *value ); } else { Interval interval( *i2, *i1, clb, crb ); *res = ConstTemporalUnit( interval, *value ); } return 0; } // template for constant unit types: // T x interval --> uT template int TU_VM_TheUnit_Tiv(Word* args, Word& result, int message, Word& local, Supplier s) { result = qp->ResultStorage(s); ConstTemporalUnit *res = static_cast *>(result.addr); T *value = static_cast(args[0].addr); SecInterval *iv = static_cast(args[1].addr); if (!value->IsDefined() || !iv->IsDefined()) { res->SetDefined(false); return 0; } *res = ConstTemporalUnit(*iv, *value); return 0; } // real real real bool interval -> ubool int TU_VM_TheUnit_rrrbiv(Word* args, Word& result, int message, Word& local, Supplier s) { result = qp->ResultStorage(s); UReal *res = (UReal*)result.addr; CcReal *a = (CcReal*)args[0].addr; CcReal *b = (CcReal*)args[1].addr; CcReal *c = (CcReal*)args[2].addr; CcBool *r = (CcBool*)args[3].addr; SecInterval *iv = (SecInterval*)args[4].addr; if (!a->IsDefined() || !b->IsDefined() || !c->IsDefined() || !r->IsDefined() || !iv->IsDefined()) { res->SetDefined(false); return 0; } *res = UReal(*iv, a->GetRealval(), b->GetRealval(), c->GetRealval(), r->GetBoolval()); return 0; } // point point interval --> ubool int TU_VM_TheUnit_ppiv(Word* args, Word& result, int message, Word& local, Supplier s) { result = qp->ResultStorage(s); UPoint *res = (UPoint*)result.addr; Point *p1 = (Point*)args[0].addr; Point *p2 = (Point*)args[1].addr; SecInterval *iv = (SecInterval*)args[2].addr; if (!p1->IsDefined() || !p2->IsDefined() || !iv->IsDefined()) { res->SetDefined(false); return 0; } *res = UPoint(*iv, *p1, *p2); return 0; } /* 5.41.3 Specification for operator ~the\_unit~ */ const std::string TU_Spec_TheUnit = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" ) " "(" "For T in {bool, int, string}:\n" "point x point x instant x instant x bool x bool --> upoint\n" "ipoint x ipoint x bool x bool --> upoint\n" "real x real x real x bool x instant x instant x bool x bool --> ureal\n" "iT x duration x bool x bool --> uT\n" "T x instant x instant x bool x bool --> uT\n" "T x interval --> uT\n" "real x real x real x bool x interval --> ureal\n" "point x point x interval --> upoint\n" "" "the_unit( pstart, pend, tstart, tend, cl, cr )\n" "the_unit( ip1, ip2, cl, cr )\n" "the_unit( a, b, c, r, tstart, tend, cl, cr )" "Creates a unit value from the argument list. The instants/ipoints" "/(point/instant)-pairs will be sorted automatically." "query the_unit(point1, point2, instant1, instant2, bool1, bool2)" "" ") )"; /* 5.41.4 Selection Function of operator ~the\_unit~ */ int TU_Select_TheUnit( ListExpr args ) { std::string argstr; nl->WriteToString(argstr, args); if (argstr == "(point point instant instant bool bool)") return 0; if (argstr == "(ipoint ipoint bool bool)") return 1; if (argstr == "(real real real bool instant instant bool bool)") return 2; if (argstr == "(bool instant instant bool bool)") return 3; if (argstr == "(ibool duration bool bool)") return 4; if (argstr == "(int instant instant bool bool)") return 5; if (argstr == "(iint duration bool bool)") return 6; if (argstr == "(string instant instant bool bool)") return 7; if (argstr == "(istring duration bool bool)") return 8; if (argstr == "(string interval)") return 9; if (argstr == "(int interval)") return 10; if (argstr == "(bool interval)") return 11; if (argstr == "(real real real bool interval)") return 12; if (argstr == "(point point interval)") return 13; return -1; // should not be reached! } ValueMapping TU_VMMap_TheUnit[] = { TU_VM_TheUnit_ppiibb, //0 TU_VM_TheUnit_ipipbb, TU_VM_TheUnit_rrrbiibb, //2 TU_VM_TheUnit_Tiibb, TU_VM_TheUnit_iTdbb, //4 TU_VM_TheUnit_Tiibb, TU_VM_TheUnit_iTdbb, //6 TU_VM_TheUnit_Tiibb, TU_VM_TheUnit_iTdbb, //8 TU_VM_TheUnit_Tiv, TU_VM_TheUnit_Tiv, //10 TU_VM_TheUnit_Tiv, TU_VM_TheUnit_rrrbiv, //12 TU_VM_TheUnit_ppiv}; /* 5.41.5 Definition of operator ~the\_unit~ */ Operator temporalunittheupoint( "the_unit", TU_Spec_TheUnit, 14, TU_VMMap_TheUnit, TU_Select_TheUnit, TU_TM_TheUnit); /* 5.42 Operator ~the\_ivalue~ This operator creates an intime value from an instant and a value. ---- the_ivalue: For T in {bool, int, string, real, point, region} OK (instant T) --> iT ---- */ /* 5.42.1 Type mapping function for ~the\_ivalue~ */ ListExpr TU_TM_TheIvalue( ListExpr args ) { if( (nl->ListLength(args)==2) && (listutils::isSymbol(nl->First(args),Instant::BasicType())) ){ ListExpr second = nl->Second(args); if (listutils::isSymbol(second, CcBool::BasicType()) ){ return nl->SymbolAtom( IBool::BasicType() ); } if (listutils::isSymbol(second, CcInt::BasicType()) ){ return nl->SymbolAtom( IInt::BasicType() ); } if (listutils::isSymbol(second, CcString::BasicType()) ){ return nl->SymbolAtom( IString::BasicType() ); } if (listutils::isSymbol(second, CcReal::BasicType()) ){ return nl->SymbolAtom( IReal::BasicType() ); } if (listutils::isSymbol(second, Point::BasicType()) ){ return nl->SymbolAtom( IPoint::BasicType() ); } if (listutils::isSymbol(second, Region::BasicType()) ){ return nl->SymbolAtom( IRegion::BasicType() ); } } return listutils::typeError( "Operator 'the_ivalue' expects a list with structure " "'(instant T)', " "for T in {bool, int, string, real, point, region}."); } /* 5.42.2 Value mapping for operator ~the\_ivalue~ */ template int TU_VM_TheIvalue(Word* args, Word& result, int message, Word& local, Supplier s) { result = (qp->ResultStorage( s )); Intime *res = (Intime *) result.addr; Instant *inst = (datetime::DateTime*) args[0].addr; T *value = (T*) args[1].addr; *res = Intime(*inst, *value); return 0; } /* 5.42.3 Specification for operator ~the\_ivalue~ */ const std::string TU_Spec_TheIvalue = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" ) " "(" "For T in {bool, int, string, real, point, region}:\n" "instant T --> iT" "" "the_ivalue( instant, value )" "Creates an intime value from the argument list. " "An undef 'instant' argument results in an undef result." "query the_ivalue(instant1, point1)" "" ") )"; /* 5.42.4 Selection Function of operator ~the\_ivalue~ */ int TU_Select_TheIvalue( ListExpr args ) { std::string argstr; nl->WriteToString(argstr, args); if (argstr == "(instant bool)") return 0; if (argstr == "(instant int)") return 1; if (argstr == "(instant string)") return 2; if (argstr == "(instant real)") return 3; if (argstr == "(instant point)") return 4; if (argstr == "(instant region)") return 5; return -1; // should not be reached! } ValueMapping TU_VMMap_TheIvalue[] = { TU_VM_TheIvalue, TU_VM_TheIvalue, TU_VM_TheIvalue, TU_VM_TheIvalue, TU_VM_TheIvalue, TU_VM_TheIvalue }; /* 5.42.5 Definition of operator ~the\_ivalue~ */ Operator temporalunittheivalue( "the_ivalue", TU_Spec_TheIvalue, 6, TU_VMMap_TheIvalue, TU_Select_TheIvalue, TU_TM_TheIvalue); /* 5.41 Operator ~ComparePredicateValues~ Here, we implement the binary comparison operators/predicates for (uT uT). The predicates are ---- = (equality), # (unequality), < (smaller than), > (bigger than), <= (smaller than or equal to), >= (bigger than or equal to). ---- The operators compare the values for each instant of time, so they will return a (stream ubool) for the intersection of the arguments' deftimes. WARNING: Do not confuse this operators with the ~ComparePredicates~, which compare the units as such, but not the temporal functions. ---- =, #, <, >, <=, >=: For T in {int, bool, real, string, point*, region*} (*): {#, =} only Test + uT x uT --> (stream ubool) Test + uT x T --> (stream ubool) (**) Test + T x uT --> (stream ubool) +(**) (**): Not for T = region ---- */ /* 5.43.1 Type mapping function for ~ComparePredicateValues~ */ ListExpr TUCompareValuePredicatesTypeMap( ListExpr args ) { if( nl->ListLength( args ) == 2 ) { ListExpr arg1, arg2; arg1 = nl->First( args ); arg2 = nl->Second( args ); if (nl->Equal( arg1, arg2 )) { if( (nl->IsEqual( arg1, UBool::BasicType() ) ) || (nl->IsEqual( arg1, UInt::BasicType() ) ) || (nl->IsEqual( arg1, UReal::BasicType() ) ) || (nl->IsEqual( arg1, UString::BasicType() ) ) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UBool::BasicType() )); } else if ( ((nl->IsEqual( arg1, UBool::BasicType() )) && (nl->IsEqual( arg2, CcBool::BasicType() ))) || ((nl->IsEqual( arg1, UInt::BasicType() )) && (nl->IsEqual( arg2, CcInt::BasicType() ))) || ((nl->IsEqual( arg1, UReal::BasicType() )) && (nl->IsEqual( arg2, CcReal::BasicType() ))) || ((nl->IsEqual( arg1, UString::BasicType() )) && (nl->IsEqual( arg2, CcString::BasicType() ))) || ((nl->IsEqual( arg1, CcBool::BasicType() )) && (nl->IsEqual( arg2, UBool::BasicType() ))) || ((nl->IsEqual( arg1, CcInt::BasicType() )) && (nl->IsEqual( arg2, UInt::BasicType() ))) || ((nl->IsEqual( arg1, CcReal::BasicType() )) && (nl->IsEqual( arg2, UReal::BasicType() ))) || ((nl->IsEqual( arg1, CcString::BasicType() )) && (nl->IsEqual( arg2, UString::BasicType() ))) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UBool::BasicType() )); } // Error case: ErrorReporter::ReportError( "CompareTemporalValueOperator (one of <, >, <=, >=) " "expects two arguments of types '(uT x uT)', '(T x uT)', or '(uT x T)', " "where T in {bool, int, real, string}."); return nl->SymbolAtom(Symbol::TYPEERROR()); } ListExpr TUCompareValueEqPredicatesTypeMap( ListExpr args ) { if( nl->ListLength( args ) == 2 ) { ListExpr arg1, arg2; arg1 = nl->First( args ); arg2 = nl->Second( args ); if (nl->Equal( arg1, arg2 )) { if( (nl->IsEqual( arg1, UBool::BasicType() ) ) || (nl->IsEqual( arg1, UInt::BasicType() ) ) || (nl->IsEqual( arg1, UReal::BasicType() ) ) || (nl->IsEqual( arg1, UString::BasicType() ) || (nl->IsEqual( arg1, UPoint::BasicType() ) ) || (nl->IsEqual( arg1, URegion::BasicType() ) ) ) ) return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UBool::BasicType() )); } std::string argstr; nl->WriteToString(argstr, args); if (argstr == "(bool ubool)" || argstr == "(ubool bool)" || argstr == "(int uint)" || argstr == "(unit int)" || argstr == "(string ustring)" || argstr == "(ustring string)" || argstr == "(real ureal)" || argstr == "(ureal real)" || argstr == "(point upoint)" || argstr == "(upoint point)") return nl->TwoElemList(nl->SymbolAtom( Symbol::STREAM() ), nl->SymbolAtom( UBool::BasicType() )); } // Error case: ErrorReporter::ReportError( "CompareTemporalValueOperator (one of =, #) " "expects two arguments of " "type 'uT x uT', 'T x uT' or 'uT x T', where T in " "{bool, int, real, string, point}, or (uregion x uregion). "); return nl->SymbolAtom(Symbol::TYPEERROR()); } /* 5.43.2 Value mapping for operator ~ComparePredicateValues~ */ template int TU_VM_ComparePredicateValue_Const(Word* args, Word& result, int message, Word& local, Supplier s) { assert( (opcode >= 0) && (opcode <= 5)); ConstTemporalUnit *u1 = (ConstTemporalUnit *) args[0].addr; ConstTemporalUnit *u2 = (ConstTemporalUnit *) args[1].addr; bool *finished; Interval iv; int p1; bool compresult = false; switch( message ) { case OPEN: finished = new bool(false); // local.setAddr(finished); return 0; case REQUEST: if( local.addr == 0 ) return CANCEL; finished = (bool*) local.addr; if ( *finished ) return CANCEL; if ( !u1->IsDefined() || !u2->IsDefined() ) { *finished = true; return CANCEL; } if (!u1->timeInterval.Intersects(u2->timeInterval) ) { *finished = true; return CANCEL; } u1->timeInterval.Intersection(u2->timeInterval, iv); p1 = u1->constValue.Compare( &u2->constValue ); switch (opcode) { case 0: // is_equal compresult = (p1 == 0); break; case 1: // is_not_equal compresult = (p1 != 0); break; case 2: // less_than compresult = (p1 == -1); break; case 3: // bigger_than compresult = (p1 == 1); break; case 4: // less_or_equal compresult = (p1 < 1); break; case 5: // bigger_or_equal compresult = (p1 > -1); break; } // end switch (opcode) result.setAddr( new ConstTemporalUnit(iv, CcBool(true, compresult) ) ); *finished = true; // only one result! return YIELD; case CLOSE: if( local.addr != 0 ) { finished = (bool*) local.addr; delete finished; local.setAddr(0); } return 0; } // end switch (message) return -1; // should not be reached } template int TU_VM_ComparePredicateValue_Const_T(Word* args, Word& result, int message, Word& local, Supplier s) { assert( (opcode >= 0) && (opcode <= 5)); assert( (unit_arg >=0) && (unit_arg <=1)); ConstTemporalUnit *u1; T *u2; if (unit_arg == 0) { u1 = (ConstTemporalUnit *) args[0].addr; u2 = (T*) args[1].addr; } else // (unit_arg == 1) { u1 = (ConstTemporalUnit *) args[1].addr; u2 = (T*) args[0].addr; } bool *finished; Interval iv; int p1; bool compresult = false; switch( message ) { case OPEN: finished = new bool(false); // local.setAddr(finished); return 0; case REQUEST: if( local.addr == 0 ) return CANCEL; finished = (bool*) local.addr; if ( *finished ) return CANCEL; if ( !u1->IsDefined() || !u2->IsDefined() ) { *finished = true; return CANCEL; } if(unit_arg == 0) p1 = u1->constValue.Compare( u2 ); else p1 = u2->Compare( &(u1->constValue) ); switch (opcode) { case 0: // is_equal compresult = (p1 == 0); break; case 1: // is_not_equal compresult = (p1 != 0); break; case 2: // less_than compresult = (p1 == -1); break; case 3: // bigger_than compresult = (p1 == 1); break; case 4: // less_or_equal compresult = (p1 < 1); break; case 5: // bigger_or_equal compresult = (p1 > -1); break; } // end switch (opcode) result.setAddr( new ConstTemporalUnit(u1->timeInterval, CcBool(true, compresult) ) ); *finished = true; // only one result! return YIELD; case CLOSE: if( local.addr != 0 ) { finished = (bool*) local.addr; delete finished; local.setAddr(0); } return 0; } // end switch (message) return -1; // should not be reached } struct TUCompareValueLocalInfo { bool finished; int NoOfResults; int NoOfResultsDelivered; MBool *intersectionBool; }; template int TU_VM_ComparePredicateValue_UPoint(Word* args, Word& result, int message, Word& local, Supplier s) { assert( (opcode >= 0) && (opcode <= 1)); UPoint *u1 = (UPoint*) args[0].addr; UPoint *u2 = (UPoint*) args[1].addr; UPoint uinters(true); UBool cu; TUCompareValueLocalInfo *localinfo; Interval iv, ivBefore, ivInters, ivAfter; switch( message ) { case OPEN: { localinfo = new TUCompareValueLocalInfo(); localinfo->finished = true; localinfo->NoOfResults = 0; localinfo->NoOfResultsDelivered = 0; localinfo->intersectionBool = new MBool(5); local.setAddr(localinfo); if ( !u1->IsDefined() || !u2->IsDefined() ) { return 0; } // fill up the result RefinementStream rs(u1,u2); int pos1; int pos2; Interval iv; bool compValue = opcode==0?true:false; while(rs.hasNext()){ rs.getNext(iv,pos1,pos2); if(pos1==0 && pos2==0){ // the common time interval if exists Point p1_start(true); Point p1_end(true); Point p2_start(true); Point p2_end(true); u1->TemporalFunction(iv.start,p1_start,true); u1->TemporalFunction(iv.end,p1_end,true); u2->TemporalFunction(iv.start,p2_start,true); u2->TemporalFunction(iv.end,p2_end,true); computeMEquality(iv, p1_start, p1_end, p2_start, p2_end, *(localinfo->intersectionBool), compValue); } } localinfo->NoOfResults = localinfo->intersectionBool->GetNoComponents(); localinfo->finished = localinfo->NoOfResults == 0; } return 0; case REQUEST: if( local.addr == 0 ) { return CANCEL; } localinfo = (TUCompareValueLocalInfo*) local.addr; if ( localinfo->finished ){ return CANCEL; } if ( localinfo->NoOfResultsDelivered >= localinfo->NoOfResults) { localinfo->finished = true; return CANCEL; } localinfo->intersectionBool->Get(localinfo->NoOfResultsDelivered, cu); result.setAddr( cu.Clone() ); localinfo->NoOfResultsDelivered++; return YIELD; case CLOSE: if( local.addr != 0 ) { localinfo = (TUCompareValueLocalInfo*) local.addr; delete localinfo->intersectionBool; delete localinfo; local.setAddr(0); } return 0; } // end switch (message) return -1; // should not be reached } template int TU_VM_ComparePredicateValue_UPoint_Point(Word* args, Word& result, int message, Word& local, Supplier s) { assert( (opcode >= 0) && (opcode <= 1)); assert( (unit_arg >= 0) && (unit_arg <= 1)); UPoint *u1; Point *p; if(unit_arg == 0) { u1 = (UPoint*) args[0].addr; p = (Point*) args[1].addr; } else{ u1 = (UPoint*) args[1].addr; p = (Point*) args[0].addr; } UPoint *u2, uinters(true); UBool cu; TUCompareValueLocalInfo *localinfo; Interval iv, ivBefore, ivInters, ivAfter; bool compresult = false; switch( message ) { case OPEN: localinfo = new TUCompareValueLocalInfo; localinfo->finished = true; localinfo->NoOfResults = 0; localinfo->NoOfResultsDelivered = 0; localinfo->intersectionBool = new MBool(5); local.setAddr(localinfo); if ( !u1->IsDefined()) // || !u2->IsDefined() ) { // std::cerr << "Undef input" << endl; return 0; } iv = u1->timeInterval; u2 = new UPoint(iv, *p, *p); u1->Intersection(*u2, uinters); delete u2; ivInters = uinters.timeInterval; compresult = (opcode == 0) ? uinters.IsDefined() : !uinters.IsDefined(); if ( !uinters.IsDefined() || ( uinters.IsDefined() && !uinters.timeInterval.Inside(ivInters)) ) {// no intersection or intersection outside common interval: // result unit spans common interval totally // cout << "No intersection in: "; iv.Print(cout); cout << endl; localinfo->intersectionBool->Add(UBool(iv,CcBool(true,compresult))); localinfo->NoOfResults++; localinfo->finished = false; return 0; } if( uinters.IsDefined() && iv.start == ivInters.start && iv.end == ivInters.end ) {// only one resultunit // cout << "Complete intersection: "; ivInters.Print(cout); cout << endl; localinfo->intersectionBool->Add( ConstTemporalUnit(ivInters, CcBool(true, compresult)) ); localinfo->NoOfResults++; localinfo->finished = false; return 0; } if ( uinters.IsDefined() ) {// possibly more than 1 resultunit if ( (iv.start < ivInters.start) || ( (iv.start == ivInters.start) && iv.lc && !ivInters.lc && ivInters.Inside(iv) ) ) {// result before intersection interval ivBefore=Interval(iv.start,ivInters.start, iv.lc,!ivInters.lc); // cout << "Before intersection: "; ivBefore.Print(cout); cout << endl; localinfo->intersectionBool->Add( ConstTemporalUnit(ivBefore, CcBool(true, !compresult)) ); localinfo->NoOfResults++; localinfo->finished = false; } if ( ivInters.Inside(iv) ) { // result at intersection interval // UPoint::Intersection(...) will also return a result being on the // limit of an open interval. Therefore, we need the second condition! // cout << "At intersection: "; ivInters.Print(cout); cout << endl; localinfo->intersectionBool->Add( ConstTemporalUnit(ivInters, CcBool(true, compresult)) ); localinfo->NoOfResults++; localinfo->finished = false; } if ( (iv.end > ivInters.end) || ( (iv.end == ivInters.end) && iv.rc && !ivInters.rc && ivInters.Inside(iv) ) ) {// result after intersection interval ivAfter = Interval(ivInters.end,iv.end,!ivInters.rc,iv.rc); // cout << "After intersection: "; ivAfter.Print(cout); cout << endl; localinfo->intersectionBool->Add( ConstTemporalUnit(ivAfter, CcBool(true, !compresult)) ); localinfo->NoOfResults++; localinfo->finished = false; } } return 0; case REQUEST: if( local.addr == 0 ) return CANCEL; localinfo = (TUCompareValueLocalInfo*) local.addr; if ( localinfo->finished ) return CANCEL; if ( localinfo->NoOfResultsDelivered >= localinfo->NoOfResults) { localinfo->finished = true; return CANCEL; } localinfo->intersectionBool->Get(localinfo->NoOfResultsDelivered, cu); result.setAddr( cu.Clone() ); localinfo->NoOfResultsDelivered++; return YIELD; case CLOSE: if( local.addr != 0 ) { localinfo = (TUCompareValueLocalInfo*) local.addr; delete localinfo->intersectionBool; delete localinfo; local.setAddr(0); } return 0; } // end switch (message) return -1; // should not be reached } /* Implementation changed after ~CompUReal~ became memberfunction of UReal. Simone */ template int TU_VM_ComparePredicateValue_UReal(Word* args, Word& result, int message, Word& local, Supplier s) { UReal *u1 = (UReal*) args[0].addr; UReal *u2 = (UReal*) args[1].addr; TUCompareValueLocalInfo *localinfo; UBool cu; std::vector res; switch (message) { case OPEN: localinfo = new TUCompareValueLocalInfo; local.setAddr(localinfo); localinfo->finished = true; localinfo->NoOfResults = 0; localinfo->NoOfResultsDelivered = 0; localinfo->intersectionBool = new MBool(5); localinfo->intersectionBool->Clear(); if ( !u1->IsDefined() || !u2->IsDefined() || !u1->timeInterval.Intersects(u2->timeInterval) ) { // no result // cout << "TU_VM_ComparePredicateValue_UReal: No Result." << endl; return 0; } // common deftime --> some result exists u1->CompUReal(*u2, opcode, res); localinfo->intersectionBool->StartBulkLoad(); for (size_t i = 0;i < res.size();i++) { localinfo->intersectionBool->MergeAdd(res[i]); } res.clear(); localinfo->intersectionBool->EndBulkLoad(true); localinfo->NoOfResults = localinfo->intersectionBool->GetNoComponents(); localinfo->finished = ( localinfo->NoOfResults <= 0 ); return 0; case REQUEST: if (local.addr == 0) return CANCEL; localinfo = (TUCompareValueLocalInfo*) local.addr; if (localinfo->finished) return CANCEL; if (localinfo->NoOfResultsDelivered >= localinfo->NoOfResults) { localinfo->finished = true; return CANCEL; } localinfo->intersectionBool->Get(localinfo->NoOfResultsDelivered, cu); result.setAddr( cu.Clone() ); localinfo->NoOfResultsDelivered++; return YIELD; case CLOSE: if( local.addr != 0 ) { localinfo = (TUCompareValueLocalInfo*) local.addr; delete localinfo->intersectionBool; delete localinfo; local.setAddr(0); } } return -1; } template int TU_VM_ComparePredicateValue_UReal_CcReal(Word* args, Word& result, int message, Word& local, Supplier s) { assert(opcode>=0 && opcode<=5); assert(unit_arg>=0 && unit_arg <=1); UReal *u1; CcReal *r; if(unit_arg == 0) { u1 = (UReal*) args[0].addr; r = (CcReal*) args[1].addr; } else { u1 = (UReal*) args[1].addr; r = (CcReal*) args[0].addr; } UBool cu; UBool newunit(true); TUCompareValueLocalInfo *localinfo; Interval iv(datetime::DateTime(0,0,datetime::instanttype), datetime::DateTime(0,0,datetime::instanttype), false, false), ivnew(datetime::DateTime(0,0,datetime::instanttype), datetime::DateTime(0,0,datetime::instanttype), false, false); Interval actIntv; Instant start(datetime::instanttype), end(datetime::instanttype), testInst(datetime::instanttype); Periods *eqPeriods; int i, numEq, cmpres; bool compresult, lc; CcReal fccr1(true, 0.0), fccr2(true,0.0); switch (message) { case OPEN: localinfo = new TUCompareValueLocalInfo; local.setAddr(localinfo); localinfo->finished = true; localinfo->NoOfResults = 0; localinfo->NoOfResultsDelivered = 0; localinfo->intersectionBool = new MBool(5); localinfo->intersectionBool->Clear(); if ( !u1->IsDefined() || !r->IsDefined() ) { // no result // cout << "TU_VM_ComparePredicateValue_UReal: No Result." << endl; return 0; } iv = u1->timeInterval; eqPeriods = new Periods(4); u1->PeriodsAtVal(r->GetRealval(), *eqPeriods);// only intervals of length numEq = eqPeriods->GetNoComponents();// 1 instant herein (start==end) // cout << " numEq=" << numEq << endl; if ( numEq == 0 ) { // special case: no equality -> only one result unit // cout << "TU_VM_ComparePredicateValue_UReal: Single Result." << endl; testInst = TU_GetMidwayInstant(iv.start, iv.end); u1->TemporalFunction(testInst, fccr1, false); fccr2 = *r; if(unit_arg == 0) cmpres = fccr1.Compare( &fccr2 ); else cmpres = fccr2.Compare( &fccr1 ); compresult = ( (opcode == 0 && cmpres == 0) || // == (opcode == 1 && cmpres != 0) || // # (opcode == 2 && cmpres < 0) || // < (opcode == 3 && cmpres > 0) || // > (opcode == 4 && cmpres <= 0) || // <= (opcode == 5 && cmpres >= 0) );// >= newunit = UBool(iv, CcBool(true, compresult)); localinfo->intersectionBool->StartBulkLoad(); localinfo->intersectionBool->Add(newunit); localinfo->intersectionBool->EndBulkLoad(); localinfo->NoOfResults++; localinfo->finished = false; delete eqPeriods; return 0; } // case: numEq > 0, at least one instant of equality // iterate the Periods and create result units // UBool::MergeAdd() will merge units with common value // for <= and >= // cout << "TU_VM_ComparePredicateValue_UReal: Multiple Results." << endl; localinfo->intersectionBool->StartBulkLoad(); start = iv.start; // the ending instant for the next interval lc = iv.lc; i = 0; // counter for instants of equality eqPeriods->Get(i, actIntv); // handle special case: first equality in first instant if (start == actIntv.start) { // cout << "TU_VM_ComparePredicateValue_UReal: Handling start..."; if (iv.lc) { // cout << " required." << endl; u1->TemporalFunction(u1->timeInterval.start, fccr1, false); fccr2 = *r; if(unit_arg == 0) cmpres = fccr1.Compare( &fccr2 ); else cmpres = fccr2.Compare( &fccr1 ); compresult = ( (opcode == 0 && cmpres == 0) || (opcode == 1 && cmpres != 0) || (opcode == 2 && cmpres < 0) || (opcode == 3 && cmpres > 0) || (opcode == 4 && cmpres <= 0) || (opcode == 5 && cmpres >= 0) ); ivnew = Interval(start, start, true, true); newunit = UBool(ivnew, CcBool(true, compresult)); localinfo->intersectionBool->Add(newunit); // cout << "TU_VM_ComparePredicateValue_UReal: Added initial" // << i << endl; lc = false; } // else: equal instant not in interval! // else // cout << " not required." << endl; i++; } while ( i < numEq ) { // cout << "TU_VM_ComparePredicateValue_UReal: Pass i=" << i << endl; eqPeriods->Get(i, actIntv); // if(actIntv.start != actIntv.end) // { // cout << "Something's wrong with actIntv!" << endl; // } end = actIntv.start; // cout << " start=" << start.ToString() // << " end=" << end.ToString() << endl; ivnew = Interval(start, end, lc, false); testInst = TU_GetMidwayInstant(start, end); u1->TemporalFunction(testInst, fccr1, false); fccr2 = *r; if(unit_arg == 0) cmpres = fccr1.Compare( &fccr2 ); else cmpres = fccr2.Compare( &fccr1 ); compresult = ( (opcode == 0 && cmpres == 0) || (opcode == 1 && cmpres != 0) || (opcode == 2 && cmpres < 0) || (opcode == 3 && cmpres > 0) || (opcode == 4 && cmpres <= 0) || (opcode == 5 && cmpres >= 0) ); newunit = UBool(ivnew, CcBool(true, compresult)); localinfo->intersectionBool->MergeAdd(newunit); // cout << "TU_VM_ComparePredicateValue_UReal: Added regular" << i << endl; if ( !(end == iv.end) || iv.rc ) { // cout << "TU_VM_ComparePredicateValue_UReal: rc==true" << endl; ivnew = Interval(end, end, true, true); compresult = (opcode == 0 || opcode == 4 || opcode == 5); newunit = UBool(ivnew, CcBool(true, compresult)); localinfo->intersectionBool->MergeAdd(newunit); } start = end; i++; lc = false; } if ( start < iv.end ) { // handle teq[numEq-1] < iv.end ivnew = Interval(start, iv.end, false, iv.rc); testInst = TU_GetMidwayInstant(start, iv.end); u1->TemporalFunction(testInst, fccr1, false); fccr2 = *r; if(unit_arg == 0) cmpres = fccr1.Compare( &fccr2 ); else cmpres = fccr2.Compare( &fccr1 ); compresult = ( (opcode == 0 && cmpres == 0) || (opcode == 1 && cmpres != 0) || (opcode == 2 && cmpres < 0) || (opcode == 3 && cmpres > 0) || (opcode == 4 && cmpres <= 0) || (opcode == 5 && cmpres >= 0) ); newunit = UBool(ivnew, CcBool(true, compresult)); localinfo->intersectionBool->MergeAdd(newunit); // cout << "TU_VM_ComparePredicateValue_UReal: Added final res" // << i << endl; } localinfo->intersectionBool->EndBulkLoad(true); localinfo->NoOfResults = localinfo->intersectionBool->GetNoComponents(); localinfo->finished = ( localinfo->NoOfResults <= 0 ); delete eqPeriods; return 0; case REQUEST: if (local.addr == 0) return CANCEL; localinfo = (TUCompareValueLocalInfo*) local.addr; if (localinfo->finished) return CANCEL; if (localinfo->NoOfResultsDelivered >= localinfo->NoOfResults) { localinfo->finished = true; return CANCEL; } localinfo->intersectionBool->Get(localinfo->NoOfResultsDelivered, cu); result.setAddr( cu.Clone() ); localinfo->NoOfResultsDelivered++; return YIELD; case CLOSE: if( local.addr != 0 ) { localinfo = (TUCompareValueLocalInfo*) local.addr; delete localinfo->intersectionBool; delete localinfo; local.setAddr(0); } } return -1; } template int TU_VM_ComparePredicateValue_URegion(Word* args, Word& result, int message, Word& local, Supplier s) { // URegion *u1 = (URegion*) args[0].addr; // URegion *u2 = (URegion*) args[1].addr; std::cerr << "TU_VM_ComparePredicateValue_URegion() not yet implemented!" << endl; return -1; // should not be reached } /* 5.43.3 Specification for operator ~ComparePredicateValues~ */ const std::string TUEqVSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( For T in {bool, int, string, real, point, region}\n" "(uT uT) -> (stream ubool)\n" "(uT T) -> (stream ubool)\n" "( T uT) -> (stream ubool)" "_ = _" "The operator returns the value of the temporal predicate." "query [const ubool value ((\"2010-11-11\" " "\"2011-01-03\" TRUE FALSE) TRUE)] = [const ubool value " "((\"2011-01-01\"2012-09-17\" FALSE TRUE) TRUE)] the_mvalue" ") )"; const std::string TUNEqVSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( For T in {bool, int, string, real, point, region}\n" "(uT uT) -> (stream ubool)\n" "(uT T) -> (stream ubool)\n" "( T uT) -> (stream ubool)" "_ # _" "The operator returns the value of the temporal predicate." "query [const ubool value ((\"2010-11-11\" " "\"2011-01-03\" TRUE FALSE) TRUE)] # [const ubool value " "((\"2011-01-01\" \"2012-09-17\" FALSE TRUE) TRUE)] the_mvalue" ") )"; const std::string TULtVSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( For T in {bool, int, string, real}\n" "(uT uT) -> (stream ubool)\n" "(uT T) -> (stream ubool)\n" "( T uT) -> (stream ubool)" "_ < _" "The operator returns the value of the temporal predicate." "query [const ubool value ((\"2010-11-11\" " "\"2011-01-03\" TRUE FALSE) TRUE)] < [const ubool value " "((\"2011-01-01\" \"2012-09-17\" FALSE TRUE) TRUE)] the_mvalue" ") )"; const std::string TUBtVSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( For T in {bool, int, string, real}\n" "(uT uT) -> (stream ubool)\n" "(uT T) -> (stream ubool)\n" "( T uT) -> (stream ubool)" "_ > _" "The operator returns the value of the temporal predicate." "query [const ubool value ((\"2010-11-11\" " "\"2011-01-03\" TRUE FALSE) TRUE)] > [const ubool value " "((\"2011-01-01\" \"2012-09-17\" FALSE TRUE) TRUE)] the_mvalue" ") )"; const std::string TULtEqVSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( For T in {bool, int, string, real}\n" "(uT uT) -> (stream ubool)\n" "(uT T) -> (stream ubool)\n" "( T uT) -> (stream ubool)" "_ <= _" "The operator returns the value of the temporal predicate." "query [const ubool value ((\"2010-11-11\" " "\"2011-01-03\" TRUE FALSE) TRUE)] <= [const ubool value " "((\"2011-01-01\" \"2012-09-17\" FALSE TRUE) TRUE)] the_mvalue" ") )"; const std::string TUBtEqVSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( For T in {bool, int, string, real}\n" "(uT uT) -> (stream ubool)\n" "(uT T) -> (stream ubool)\n" "( T uT) -> (stream ubool)" "_ >= _" "The operator returns the value of the temporal predicate." "query [const ubool value ((\"2010-11-11\" " "\"2011-01-03\" TRUE FALSE) TRUE)] >= [const ubool value " "((\"2011-01-01\" \"2012-09-17\" FALSE TRUE) TRUE)] the_mvalue" ") )"; /* 5.43.4 Selection Function of operator ~ComparePredicateValues~ */ template int TU_Select_ComparePredicateValue ( ListExpr args ) { std::string argstr; nl->WriteToString(argstr, args); if (argstr == "(ubool ubool)") return 0 + opcode; if (argstr == "(uint uint)") return 6 + opcode; if (argstr == "(ustring ustring)") return 12 + opcode; if (argstr == "(ureal ureal)") return 18 + opcode; if (argstr == "(upoint upoint)") return 24 + opcode; if (argstr == "(uregion uregion)") return 26 + opcode; if (argstr == "(bool ubool)") return 28 + opcode; if (argstr == "(ubool bool)") return 34 + opcode; if (argstr == "(int uint)") return 40 + opcode; if (argstr == "(unit int)") return 46 + opcode; if (argstr == "(string ustring)") return 52 + opcode; if (argstr == "(ustring string)") return 58 + opcode; if (argstr == "(real ureal)") return 64 + opcode; if (argstr == "(ureal real)") return 70 + opcode; if (argstr == "(point upoint)") return 76 + opcode; if (argstr == "(upoint point)") return 78 + opcode; return -1; // should not be reached! } ValueMapping TU_VMMap_ComparePredicateValue[] = { TU_VM_ComparePredicateValue_Const, // 0 TU_VM_ComparePredicateValue_Const, TU_VM_ComparePredicateValue_Const, TU_VM_ComparePredicateValue_Const, TU_VM_ComparePredicateValue_Const, TU_VM_ComparePredicateValue_Const, // 5 TU_VM_ComparePredicateValue_Const, // 6 TU_VM_ComparePredicateValue_Const, TU_VM_ComparePredicateValue_Const, TU_VM_ComparePredicateValue_Const, TU_VM_ComparePredicateValue_Const, TU_VM_ComparePredicateValue_Const, // 11 TU_VM_ComparePredicateValue_Const, // 12 TU_VM_ComparePredicateValue_Const, TU_VM_ComparePredicateValue_Const, TU_VM_ComparePredicateValue_Const, TU_VM_ComparePredicateValue_Const, TU_VM_ComparePredicateValue_Const, // 17 TU_VM_ComparePredicateValue_UReal<0>, // 18 TU_VM_ComparePredicateValue_UReal<1>, TU_VM_ComparePredicateValue_UReal<2>, TU_VM_ComparePredicateValue_UReal<3>, TU_VM_ComparePredicateValue_UReal<4>, TU_VM_ComparePredicateValue_UReal<5>, // 23 TU_VM_ComparePredicateValue_UPoint<0>, // 24 TU_VM_ComparePredicateValue_UPoint<1>, // 25 TU_VM_ComparePredicateValue_URegion<0>, // 26 TU_VM_ComparePredicateValue_URegion<1>, // 27 TU_VM_ComparePredicateValue_Const_T,// 28 TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T,//34 TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T,// 40 TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T,// 46 TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T,// 52 TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T,// 58 TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_Const_T, TU_VM_ComparePredicateValue_UReal_CcReal<0,1>, // 64 TU_VM_ComparePredicateValue_UReal_CcReal<1,1>, TU_VM_ComparePredicateValue_UReal_CcReal<2,1>, TU_VM_ComparePredicateValue_UReal_CcReal<3,1>, TU_VM_ComparePredicateValue_UReal_CcReal<4,1>, TU_VM_ComparePredicateValue_UReal_CcReal<5,1>, TU_VM_ComparePredicateValue_UReal_CcReal<0,0>, // 70 TU_VM_ComparePredicateValue_UReal_CcReal<1,0>, TU_VM_ComparePredicateValue_UReal_CcReal<2,0>, TU_VM_ComparePredicateValue_UReal_CcReal<3,0>, TU_VM_ComparePredicateValue_UReal_CcReal<4,0>, TU_VM_ComparePredicateValue_UReal_CcReal<5,0>, // 75 TU_VM_ComparePredicateValue_UPoint_Point<0,1>, // 76 TU_VM_ComparePredicateValue_UPoint_Point<1,1>, // 77 TU_VM_ComparePredicateValue_UPoint_Point<0,0>, // 78 TU_VM_ComparePredicateValue_UPoint_Point<1,0> // 79 }; /* 5.43.5 Definition of operator ~ComparePredicateValues~ */ Operator temporalunitvalisequal ( "=", TUEqVSpec, 80, TU_VMMap_ComparePredicateValue, TU_Select_ComparePredicateValue<0>, TUCompareValueEqPredicatesTypeMap ); Operator temporalunitvalisnotequal ( "#", TUNEqVSpec, 80, TU_VMMap_ComparePredicateValue, TU_Select_ComparePredicateValue<1>, TUCompareValueEqPredicatesTypeMap ); Operator temporalunitvalsmaller ( "<", TULtVSpec, 80, TU_VMMap_ComparePredicateValue, TU_Select_ComparePredicateValue<2>, TUCompareValuePredicatesTypeMap ); Operator temporalunitvalbigger ( ">", TUBtVSpec, 80, TU_VMMap_ComparePredicateValue, TU_Select_ComparePredicateValue<3>, TUCompareValuePredicatesTypeMap ); Operator temporalunitvalsmallereq ( "<=", TULtEqVSpec, 80, TU_VMMap_ComparePredicateValue, TU_Select_ComparePredicateValue<4>, TUCompareValuePredicatesTypeMap ); Operator temporalunitvalbiggereq ( ">=", TUBtEqVSpec, 80, TU_VMMap_ComparePredicateValue, TU_Select_ComparePredicateValue<5>, TUCompareValuePredicatesTypeMap ); /* 5.44 Operator ~length~ Calculate the spatial length of the movement. ---- length: upoint --> real ---- */ /* 5.44.1 Type mapping function for ~length~ ---- upoint [ x geoid ] --> real ---- */ ListExpr TUTypeMapLength( ListExpr args ) { std::string errmsg = "Expected (upoint) or (upoint x geoid)."; int noargs = nl->ListLength(args); if((noargs<1) || (noargs>2)){ return listutils::typeError(errmsg); } if(!listutils::isSymbol(nl->First(args),UPoint::BasicType())){ return listutils::typeError(errmsg); } if( (noargs==2) && (!listutils::isSymbol(nl->Second(args),Geoid::BasicType())) ){ return listutils::typeError(errmsg); } return nl->SymbolAtom(CcReal::BasicType()); } /* 5.44.2 Value mapping for operator ~length~ */ int TUUnitLength(Word* args,Word& result,int message,Word& local,Supplier s) { result = qp->ResultStorage( s ); CcReal *res = (CcReal*)result.addr; UPoint *input = (UPoint*)args[0].addr; if(qp->GetNoSons(s)==2){ // variant using (LON,LAT)-coordinates Geoid* g = static_cast(args[1].addr); if(!g->IsDefined()){ res->Set(false, 0.0); return 0; } input->Length(*g, *res); } else { // normal variant using (X,Y)-coordinates input->Length( *res ); } return 0; } /* 5.44.3 Specification for operator ~length~ */ const std::string TULengthSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( upoint [ x geoid ] -> real" " length( Up [, Geoid ] )" "The operator returns the distance of the unit's initial and final" "position. If the optional parameter Geoid is not used, spatial " "coordinates are interpreted as metric (X,Y)-pairs, otherwise as " "geographic (LON,LAT)-coordinates relative to the passed geoid." "query units(Trains feed extract[Trip]) use[fun(U:upoint) " "length(U)] transformstream sum[elem]" ") )"; /* 5.44.4 Selection Function of operator ~length~ none - uses simpleselect */ /* 5.44.5 Definition of operator ~length~ */ Operator temporalunitlength( "length", TULengthSpec, TUUnitLength, Operator::SimpleSelect, TUTypeMapLength); /* 5.45 Operator ~canmeet~ The predicate predictes whether two mpoint objects will become close to eachother (in terms of a given distance threshold), within a given time duration assuming that they keep the speed and direction of the given two upoints. */ /* 5.45.1 Type mapping function for ~canmeet~ */ ListExpr TypeMapTemporalUnitCanMeet( ListExpr args ) { ListExpr upoint1, upoint2, distance, duration; std::string outstr; if ( nl->IsAtom( args ) || nl->ListLength( args ) != 4 ) { nl->WriteToString(outstr, args); ErrorReporter::ReportError("Operator canmeet expects a list of " "length four, but gets '" + outstr + "'."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } upoint1 = nl->First(args); upoint2 = nl->Second(args); distance = nl->Third(args); duration = nl->Fourth(args); // check for compatibility of arguments if( !nl->IsAtom(upoint1) || !nl->IsEqual(upoint1, UPoint::BasicType())) { nl->WriteToString(outstr, upoint1); ErrorReporter::ReportError("Operator canmeet expects upoint as a first " "argument, but gets '" + outstr + "'."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } if( !nl->IsAtom(upoint2) || !nl->IsEqual(upoint2, UPoint::BasicType())) { nl->WriteToString(outstr, upoint2); ErrorReporter::ReportError("Operator canmeet expects upoint as a second " "argument, but gets '" + outstr + "'."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } if( !nl->IsAtom(distance) || !nl->IsEqual(distance, CcReal::BasicType())) { nl->WriteToString(outstr, distance); ErrorReporter::ReportError("Operator canmeet expects real as a third " "argument, but gets '" + outstr + "'."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } if( !nl->IsAtom(duration) || !nl->IsEqual(duration, Duration::BasicType())) { nl->WriteToString(outstr, duration); ErrorReporter::ReportError("Operator canmeet expects duration as a " "fourth " "argument, but gets '" + outstr + "'."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } return nl->SymbolAtom( CcBool::BasicType() ); } /* 5.45.2 Value mapping for operator ~canmeet~ */ int TUCanMeet( Word* args, Word& result, int message, Word& local, Supplier s ) { bool debugme=false; Interval iv; // Word a1, a2; UPoint *u1, *u2; CcReal* distThreshold; Instant* timeThreshold; result = qp->ResultStorage( s ); CcBool* res = (CcBool*) result.addr; u1 = (UPoint*)(args[0].addr); u2 = (UPoint*)(args[1].addr); distThreshold = (CcReal*)(args[2].addr); timeThreshold = (Instant*)(args[3].addr); double tThresholdMin=0, tThresholdMax=0; if (!u1->IsDefined() || !u2->IsDefined() || !distThreshold->IsDefined() || ! timeThreshold->IsDefined()) { // return undefined ureal res->SetDefined( false ); } else { // calculate result res->SetDefined( true ); // 1- Extend the two upoints so that their time intervals are equal UPoint u1ex(*u1), u2ex(*u2); Point newPoint; if(u1->timeInterval.start < u2->timeInterval.start) //extend u2 backward { tThresholdMin = u2->timeInterval.start.ToDouble(); u2->TemporalFunction(u1->timeInterval.start, newPoint, true); u2ex.timeInterval.start = u1->timeInterval.start; u2ex.p0 = newPoint; } else //extend u1 backward { tThresholdMin = u1->timeInterval.start.ToDouble(); u1->TemporalFunction(u2->timeInterval.start, newPoint, true); u1ex.timeInterval.start = u2->timeInterval.start; u1ex.p0 = newPoint; } if(u1->timeInterval.end < u2->timeInterval.end) //extend u1 forward { tThresholdMax = u2->timeInterval.end.ToDouble() + timeThreshold->ToDouble(); u1->TemporalFunction(u2->timeInterval.end, newPoint, true); u1ex.timeInterval.end = u2->timeInterval.end; u1ex.p1 = newPoint; } else //extend u2 forward { tThresholdMax = u1->timeInterval.end.ToDouble() + timeThreshold->ToDouble(); u2->TemporalFunction(u1->timeInterval.end, newPoint, true); u2ex.timeInterval.end = u1->timeInterval.end; u2ex.p1 = newPoint; } // 2- Compute the distance between the two extended units UReal dist(0); u1ex.Distance( u2ex, dist ); if(debugme) dist.Print(std::cerr); // 3- Compute the time when the distance reaches the distThreshould double c= dist.c - ((dist.r)? distThreshold->GetRealval() * distThreshold->GetRealval(): distThreshold->GetRealval()); double coeff = (dist.b * dist.b) - (4 * dist.a * c); if(coeff < 0) { res->Set(true, false); return 0; } coeff = sqrt(coeff); double t1= ((dist.b * -1) + coeff )/ (2 * dist.a); double t2= ((dist.b * -1) - coeff )/ (2 * dist.a); double intervalStart= u1ex.timeInterval.start.ToDouble(); if( (t1 + intervalStart) > tThresholdMin && (t1 + intervalStart) < tThresholdMax) res->Set(true, true); else if( (t2 + intervalStart) > tThresholdMin && (t2 + intervalStart) < tThresholdMax) res->Set(true, true); else res->Set(true, false); } // pass on result return 0; } /* 5.45.3 Specification for operator ~canmeet~ */ const std::string TemporalSpecCanMeet = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "(" "( upoint upoint real duration) -> bool" "canmeet( _, _, _, _)" " The predicate predictes whether two upoint objects will become close" " to eachother (in terms of the given distance threshold), within the given " " time duration, assuming that they keep their speed and direction." "canmeet(upoint1,upoint2, 50.0, now() + create_duration(0, 5000))" "" ") )"; /* 5.45.5 Definition of operator ~canmeet~ */ Operator temporalunitcanmeet( "canmeet", TemporalSpecCanMeet, TUCanMeet, Operator::SimpleSelect, TypeMapTemporalUnitCanMeet); /* 5.46 Operator ~when~ 5.46.1 Type Mapping for ~when~ */ ListExpr UnitWhenTypeMap( ListExpr args ) { ListExpr arg1, arg2; std::string argstr; if ( nl->ListLength( args ) != 2 ) { ErrorReporter::ReportError("Operator when expects a list of length 2."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } arg1 = nl->First( args ); arg2 = nl->Second( args ); nl->WriteToString(argstr, arg2); if ( !( nl->IsEqual( arg2, MBool::BasicType() ) ) ) { ErrorReporter::ReportError("Operator when expects a second argument" " of type " + MBool::BasicType() + " but gets '" + argstr + "'."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } if( nl->IsAtom( arg1 ) ) { if( nl->IsEqual( arg1, UBool::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UBool::BasicType())); if( nl->IsEqual( arg1, UInt::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UInt::BasicType())); if( nl->IsEqual( arg1, UReal::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UReal::BasicType())); if( nl->IsEqual( arg1, UPoint::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UPoint::BasicType())); if( nl->IsEqual( arg1, UString::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UString::BasicType())); nl->WriteToString(argstr, arg1); ErrorReporter::ReportError("Operator when expects a first argument " "of type T in {ubool, uint, ureal, upoint, " "ustring, uregion} but gets a '" + argstr + "'."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } if(!Stream::checkType(arg1)){ return listutils::typeError("Operator when expects as first " "argument a list with structure 'T' or " "'stream(T)', T in {ubool, uint, ureal, " "upoint, ustring, ureagion} but gets a " "list with structure '" + argstr + "'."); } if( nl->IsEqual( nl->Second(arg1), UBool::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UBool::BasicType())); if( nl->IsEqual( nl->Second(arg1), UInt::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UInt::BasicType())); if( nl->IsEqual( nl->Second(arg1), UReal::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UReal::BasicType())); if( nl->IsEqual( nl->Second(arg1), UPoint::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UPoint::BasicType())); if( nl->IsEqual( nl->Second(arg1), UString::BasicType() ) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(UString::BasicType())); nl->WriteToString(argstr, nl->Second(arg1)); ErrorReporter::ReportError("Operator when expects a type " "(stream T); T in {ubool, uint, ureal, upoint, " "ustring, uregion} but gets '(stream " + argstr + ")'."); return nl->SymbolAtom( Symbol::TYPEERROR() ); } /* 5.46.2 Value Mapping for ~atperiods~ */ struct WhenLocalInfo { Word uWord; // the address of the unit value Word pWord; // the adress of the periods value int j; // save the number of the interval }; /* Variant 1: first argument is a scalar value */ template int MappingUnitWhen( Word* args, Word& result, int message, Word& local, Supplier s ) { AtPeriodsLocalInfo *localinfo; Interval interval; Alpha *unit; Alpha r(true); Periods* periods; switch( message ) { case OPEN: { // #ifdef TUA_DEBUG // cout << "\nMappingUnitAtPeriods: OPEN" << endl; // #endif Periods* p= new Periods(0); MBool* mb= static_cast(args[1].addr); CcBool tru(true, true); MBool mbTrue(0); mb->At(tru, mbTrue); mbTrue.DefTime(*p); localinfo = new AtPeriodsLocalInfo; localinfo->uWord = args[0]; localinfo->pWord = SetWord(p); localinfo->j = 0; local.setAddr(localinfo); return 0; }break; case REQUEST: { // #ifdef TUA_DEBUG // cout << "\nMappingUnitAtPeriods: REQUEST" << endl; // #endif if( local.addr == 0 ) return CANCEL; localinfo = (AtPeriodsLocalInfo *)local.addr; unit = (Alpha*)localinfo->uWord.addr; periods = (Periods*)localinfo->pWord.addr; if( !unit->IsDefined() || !periods->IsDefined() || periods->IsEmpty() ) { result.setAddr(0); return CANCEL; } // #ifdef TUA_DEBUG // cout << " Unit's timeInterval u=" // << TUPrintTimeInterval( unit->timeInterval ) << endl; // #endif if( localinfo->j >= periods->GetNoComponents() ) { result.setAddr(0); // #ifdef TUA_DEBUG // cout << "Maquery train7 inside train7sectionsppingUnitAtPeriods: " // << "REQUEST finished: CANCEL (1)" // << endl; // #endif return CANCEL; } periods->Get( localinfo->j, interval ); localinfo->j++; // #ifdef TUA_DEBUG // cout << " Probing timeInterval p =" // << TUPrintTimeInterval(interval) // << endl; // #endif while( interval.Before( unit->timeInterval ) && localinfo->j < periods->GetNoComponents() ) { // forward to first candidate interval periods->Get(localinfo->j, interval); localinfo->j++; // #ifdef TUA_DEBUG // cout << " Probing timeInterval=" // << TUPrintTimeInterval(interval) // << endl; // if (interval.Before( unit->timeInterval )) // cout << " p is before u" << endl; // if (localinfo->j < periods->GetNoComponents()) // cout << " j < #Intervals" << endl; // #endif } if( unit->timeInterval.Before( interval ) ) { // interval after unit-deftime --> finished result.addr = 0; // #ifdef TUA_DEBUG // cout << "MappingUnitAtPeriods: REQUEST finished: CANCEL (2)" // << endl; // #endif return CANCEL; } if(unit->timeInterval.Intersects( interval )) { // interval intersectd unit's deftime --> produce result // create unit restricted to interval unit->AtInterval( interval, r ); Alpha* aux = new Alpha( r ); result.setAddr( aux ); // #ifdef TUA_DEBUG // cout << " Result interval=" // << TUPrintTimeInterval(aux->timeInterval) // << endl; // cout << " Result defined=" << aux->IsDefined() // << endl; // cout << "MappingUnitAtPeriods: REQUEST finished: YIELD" // << endl; // #endif return YIELD; } if( localinfo->j >= periods->GetNoComponents() ) { // Passed last interval --> finished result.addr = 0; // #ifdef TUA_DEBUG // cout << "MappingUnitAtPeriods: REQUEST finished: CANCEL (3)" // << endl; // #endif return CANCEL; } result.setAddr(0 ); cout << "MappingUnitWhen: REQUEST finished: CANCEL (4)" << endl; cout << "Intervals should overlap: " << endl; cout << " Unit's timeInterval = "; TUPrintTimeInterval(unit->timeInterval); cout << " Current Period's interval = "; TUPrintTimeInterval(interval); cout << endl; assert( false ); return CANCEL; // should not happen }break; case CLOSE: { if( local.addr != 0 ) { AtPeriodsLocalInfo *li= static_cast(local.addr); Periods* p = static_cast(li->pWord.addr); delete p; delete li; local.setAddr(Address(0)); } return 0; } } // should not happen: return -1; } /* Variant 2: first argument is a stream */ struct WhenLocalInfoUS { Word uWord; // address of the input stream Word pWord; // address of the input periods value int j; // interval counter for within periods }; template int MappingUnitStreamWhen( Word* args, Word& result, int message, Word& local, Supplier s ) { AtPeriodsLocalInfoUS *localinfo; Alpha *unit, *aux; Alpha resultUnit(true); Periods *periods; Interval interval; bool foundUnit = false; switch( message ) { case OPEN: { Periods* p= new Periods(0); MBool* mb= static_cast(args[1].addr); CcBool tru(true, true); MBool mbTrue(0); mb->At(tru, mbTrue); mbTrue.DefTime(*p); localinfo = new AtPeriodsLocalInfoUS; localinfo->pWord = p; localinfo->j = 0; // init interval counter qp->Open( args[0].addr ); // open stream of units qp->Request( args[0].addr, localinfo->uWord ); // request first unit if ( !( qp->Received( args[0].addr) ) ){ localinfo->uWord.addr = 0; result.addr = 0; return CANCEL; } local.setAddr(localinfo); // pass up link to localinfo return 0; }break; case REQUEST: { if ( local.addr == 0 ) return CANCEL; localinfo = (AtPeriodsLocalInfoUS *) local.addr; // restore local data if ( localinfo->uWord.addr == 0 ) { result.addr = 0; return CANCEL; } unit = (Alpha *) localinfo->uWord.addr; if ( localinfo->pWord.addr == 0 ) { result.addr = 0; return CANCEL; } periods = (Periods *) localinfo->pWord.addr; if( !periods->IsDefined() || periods->IsEmpty() ) return CANCEL; // search for a pair of overlapping unit/interval: while (1){ if ( localinfo->j == periods->GetNoComponents() ){// redo first interval localinfo->j = 0; unit->DeleteIfAllowed(); // delete original unit? localinfo->uWord.addr = 0; foundUnit = false; while(!foundUnit){ qp->Request(args[0].addr, localinfo->uWord); // get new unit if( qp->Received( args[0].addr ) ) unit = (Alpha *) localinfo->uWord.addr; else { localinfo->uWord.addr = 0; result.addr = 0; return CANCEL; } // end of unit stream foundUnit = unit->IsDefined(); } } periods->Get(localinfo->j, interval); // get an interval if ( !( interval.Before( unit->timeInterval ) ) && !( unit->timeInterval.Before( interval) ) ) break; // found candidate, break while localinfo->j++; // next interval, loop } // We have an interval overlapping the unit's interval now // Return unit restricted to overlapping part of both intervals if (!unit->timeInterval.Intersects( interval) ){ // This may not happen! cout << __FILE__ << __LINE__ << __PRETTY_FUNCTION__ << ": Intervals do not overlap, but should do so:" << endl; cout << " Unit's timeInterval = "; TUPrintTimeInterval(unit->timeInterval); cout << endl << " Current Period's interval = "; TUPrintTimeInterval(interval); cout << endl; assert(false); } unit->AtInterval( interval, resultUnit); // intersect unit and interval aux = new Alpha( resultUnit ); result.setAddr( aux ); localinfo->j++; // increase interval counter return YIELD; }break; case CLOSE: { if ( local.addr != 0 ) { qp->Close( args[0].addr ); localinfo = (AtPeriodsLocalInfoUS *) local.addr; if ( localinfo->uWord.addr != 0 ) { unit = (Alpha *) localinfo->uWord.addr; unit->DeleteIfAllowed(); // delete remaining original unit } Periods* p = static_cast(localinfo->pWord.addr); delete p; delete (AtPeriodsLocalInfoUS *)localinfo; local.setAddr(Address(0)); } return 0; } } // end switch return -1; // should never be reached } // end MappingUnitStreamAtPeriods /* 5.46.3 Specification for operator ~atperiods~ */ const std::string TemporalSpecWhen = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\") " "( For T in {int, bool, real, string, point, region}:\n" "(uT periods) -> stream uT\n" "((stream uT) periods) -> stream uT" "_ when[_] " "restrict the movement to the times on which the given mbool is true." "" "units(mpoint1) when[speed(mpoint1) > 20.0] ) )"; /* 5.46.4 Value map of operator ~when~ */ ValueMapping temporalunitwhenmap[] = { MappingUnitWhen, MappingUnitWhen, MappingUnitWhen, MappingUnitWhen, MappingUnitWhen, MappingUnitStreamWhen, MappingUnitStreamWhen, MappingUnitStreamWhen, MappingUnitStreamWhen, MappingUnitStreamWhen }; /* 5.46.4 Selection Function of operator ~when~ */ int WhenSelect( ListExpr args ) { ListExpr arg1 = nl->First( args ); if (nl->IsAtom( arg1 ) ) { if( nl->SymbolValue( arg1 ) == UBool::BasicType() ) return 0; if( nl->SymbolValue( arg1 ) == UInt::BasicType() ) return 1; if( nl->SymbolValue( arg1 ) == UReal::BasicType() ) return 2; if( nl->SymbolValue( arg1 ) == UPoint::BasicType() ) return 3; if( nl->SymbolValue( arg1 ) == UString::BasicType() ) return 4; } if( Stream:: checkType(arg1)){ if( nl->IsEqual( nl->Second(arg1), UBool::BasicType() ) ) return 5; if( nl->IsEqual( nl->Second(arg1), UInt::BasicType() ) ) return 6; if( nl->IsEqual( nl->Second(arg1), UReal::BasicType() ) ) return 7; if( nl->IsEqual( nl->Second(arg1), UPoint::BasicType() ) ) return 8; if( nl->IsEqual( nl->Second(arg1), UString::BasicType() ) ) return 9; } return -1; // This point should never be reached } /* 5.46.6 Definition of operator ~when~ */ Operator temporalunitwhen( "when", TemporalSpecWhen, 10, temporalunitwhenmap, WhenSelect, UnitWhenTypeMap ); /* 5.47.1 Operator atRect Value Mapping */ int atRectUVM( Word* args, Word& result, int message, Word& local, Supplier s ){ UPoint* up = (UPoint*) args[0].addr; Rectangle<2>* rect = (Rectangle<2>*) args[1].addr; result = qp->ResultStorage(s); UPoint* res = (UPoint*) result.addr; up->At(*rect,*res); return 0; } /* 5.47.2 Operator atRect Type Mapping Signature is: upoint x rect -> upoint */ ListExpr atRectUTM(ListExpr args){ std::string err ="upoint x rect expected"; if(!nl->HasLength(args,2)){ return listutils::typeError(err + " (wrong number of arguments)"); } if(!UPoint::checkType(nl->First(args)) || !Rectangle<2>::checkType(nl->Second(args))){ return listutils::typeError(err); } return nl->SymbolAtom(UPoint::BasicType()); } /* 5.47.3 Specification */ const std::string atRectUSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) " "( upoint x rect -> upoint " " up atRect r " "Restricts the upoint up to the part inside r " "" "query getunit(train7, 1) atRect bbox(thecenter)" ") )"; /* 5.47.4 Definition of operator atRect */ Operator atRectU( "atRect", atRectUSpec, atRectUVM, Operator::SimpleSelect, atRectUTM); /* 5.47 Operator ~contains~ ---- Secinterval x SecInterval -> bool Secinterval x Periods -> bool Periods x SecInterval -> bool Periods x Periods -> bool ---- */ /* 5.47.1 Class ~SecInterval~ */ const std::string SecInterval::BasicType() { return "interval"; } const bool SecInterval::checkType(const ListExpr type) { return listutils::isSymbol(type, BasicType()); } bool SecInterval::CheckKind(ListExpr type, ListExpr& errorInfo) { return checkType(type); } size_t SecInterval::Sizeof() const { return 2 * sizeof(Instant) + 2 * sizeof(CcBool); } int SecInterval::Compare(const Attribute* attr) const { SecInterval* si = (SecInterval*) attr; if(!IsDefined()) { return si->IsDefined()? -1 : 0; } if(!si->IsDefined()){ return 1; } return Interval::CompareTo(*si); } std::ostream& SecInterval::Print(std::ostream &os) const { os << (lc?"[":"("); start.Print(os) << ", "; end.Print(os) << (rc?"]":")"); return os; } bool SecInterval::Adjacent(const Attribute* attr) const { if(!IsDefined() || !attr->IsDefined()) return false; return Interval::Adjacent(*((Interval*)attr)); } SecInterval* SecInterval::Clone() const { SecInterval* i = new SecInterval(*this); return i; } size_t SecInterval::HashValue() const { return (this->start).HashValue() + (this->end).HashValue(); } void SecInterval::CopyFrom(const Attribute *attr) { *this = *((SecInterval*)attr); } void SecInterval::WriteTo(char *dest) { strcpy(dest, ToString().c_str()); } std::string SecInterval::ToString() { std::string result = "(" + start.ToString() + " " + end.ToString() + " " + (lc ? "TRUE" : "FALSE") + " " + (rc ? "TRUE" : "FALSE") + ")"; return result; } ListExpr SecInterval::ToListExpr(const ListExpr typeInfo) const{ if(IsDefined()) return nl->FourElemList(start.ToListExpr(false), end.ToListExpr(false), nl->BoolAtom(lc), nl->BoolAtom(rc)); else return nl->SymbolAtom(Symbol::UNDEFINED()); } SmiSize SecInterval::SizeOfChars() { std::string key = this->ToString(); return (SmiSize)key.length(); } bool SecInterval::ReadFrom(const ListExpr instance, const ListExpr typeInfo){ if(listutils::isSymbolUndefined(instance)){ SetDefined(false); return true; } if(!nl->HasLength(instance,4)) return false; datetime::DateTime s(datetime::instanttype); datetime::DateTime e(datetime::instanttype); bool lc; bool rc; if (!s.ReadFrom(nl->First(instance), false) || !e.ReadFrom(nl->Second(instance), false)) return false; ListExpr Lc = nl->Third(instance); if (nl->AtomType(Lc) != BoolType) return false; else lc = nl->BoolValue(Lc); ListExpr Rc = nl->Fourth(instance); if (nl->AtomType(Rc) != BoolType) return false; else rc = nl->BoolValue(Rc); return Set(s,e,lc,rc); } bool SecInterval::Set(const datetime::DateTime& s, const datetime::DateTime& e, const bool lc, const bool rc) { if ((s < e) || ((s == e) && lc && rc)) { SetDefined(true); this->start = s; this->end = e; this->lc = lc; this->rc = rc; return true; } return false; } bool SecInterval::Set(const Interval* iinst) { return Set(iinst->start, iinst->end, iinst->lc, iinst->rc); } bool SecInterval::SetStart(const datetime::DateTime& s, const bool lc) { if ((s < this->end) || ((s == this->end) && lc && this->rc)) { this->start = s; this->lc = lc; return true; } return false; } bool SecInterval::SetEnd(const datetime::DateTime& e, const bool rc) { if ((this->start < e) || ((this->start == e) && rc && this->lc)) { this->end = e; this->rc = rc; return true; } return false; } ListExpr SecInterval::Property(){ return (nl->TwoElemList( nl->FiveElemList( nl->StringAtom("Signature"), nl->StringAtom("Example Type List"), nl->StringAtom("List Rep"), nl->StringAtom("Example List"), nl->StringAtom("Remarks")), nl->FiveElemList( nl->StringAtom("-> SecInterval"), nl->StringAtom(SecInterval::BasicType()), nl->StringAtom("(start end leftclosed rightclosed)"), nl->TextAtom ("2004-4-12-8:03:32.645 2011-07-01-08:55:22.000 TRUE FALSE"), nl->StringAtom("This type represents an interval")))); } const bool SecInterval::Contains(const Periods& per) const{ if (!IsDefined() || !per.IsDefined()) return false; int no = per.GetNoComponents(); if (!no) return true; Interval firstIv, lastIv; per.Get(0, firstIv); per.Get(no - 1, lastIv); return Interval::Contains(firstIv) && Interval::Contains(lastIv); } const bool SecInterval::Contains(const Interval& si) const{ if(!IsDefined()) return false; return Interval::Contains(si); } /* 5.47.2 Type mapping function for ~contains~ */ ListExpr containsTM(ListExpr args) { if (nl->ListLength(args) != 2) { ErrorReporter::ReportError("Exactly two arguments required."); return nl->SymbolAtom(Symbol::TYPEERROR()); } if (!SecInterval::checkType(nl->First(args)) && !Periods::checkType(nl->First(args))) { ErrorReporter::ReportError ("1st argument requires type interval or periods."); return nl->SymbolAtom(Symbol::TYPEERROR()); } if (!SecInterval::checkType(nl->First(args)) && !Periods::checkType(nl->First(args))) { ErrorReporter::ReportError ("2nd argument requires type interval or periods."); return nl->SymbolAtom(Symbol::TYPEERROR()); } return nl->SymbolAtom(CcBool::BasicType()); } /* 5.47.3 Value mapping for operator ~contains~ */ template int containsVM(Word* args, Word& result, int message, Word& local, Supplier s){ C1* arg1 = static_cast(args[0].addr); C2* arg2 = static_cast(args[1].addr); result = qp->ResultStorage(s); CcBool* res = (CcBool*)result.addr; if(!arg1->IsDefined() || !arg2->IsDefined()) res->SetDefined(false); else res->Set(true, arg1->Contains(*arg2)); return 0; } /* 5.47.4 Value mapping array for operator ~contains~ */ ValueMapping containsvm[] = {containsVM, containsVM, containsVM, containsVM}; GenTC interval; /* 5.47.5 Specification for operator ~contains~ */ const std::string ContainsSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\") " "( periods x periods -> bool" "_ contains _ " "decides whether the first argument contains the second" "p1 contains p2) )"; /* 5.47.6 Selection Function of operator ~contains~ */ int containsSelect(ListExpr args) { if (SecInterval::checkType(nl->First(args)) && SecInterval::checkType(nl->Second(args))) return 0; else if (Periods::checkType(nl->First(args)) && SecInterval::checkType(nl->Second(args))) return 1; else if (SecInterval::checkType(nl->First(args)) && Periods::checkType(nl->Second(args))) return 2; else if (Periods::checkType(nl->First(args)) && Periods::checkType(nl->Second(args))) return 3; else return -1; } /* 5.47.7 Definition of operator ~contains~ */ Operator temporalcontains("contains", ContainsSpec, 4, containsvm, containsSelect, containsTM); /* 5.48 Operator ~swapcoord~ ---- mpoint -> mpoint ---- */ /* 5.48.1 Type mapping function for ~swapcoord~ */ ListExpr swapcoordTM(ListExpr args) { if (nl->ListLength(args) != 1) { return listutils::typeError("Exactly one argument required."); } if (!MPoint::checkType(nl->First(args))) { return listutils::typeError("Type mpoint required."); } return nl->SymbolAtom(MPoint::BasicType()); } /* 5.48.2 Value mapping function for operator ~swapcoord~ */ int swapcoordVM(Word* args, Word& result, int message, Word& local, Supplier s){ MPoint* source = static_cast(args[0].addr); result = qp->ResultStorage(s); MPoint* res = (MPoint*)result.addr; if (!source->IsDefined()) { res->SetDefined(false); return 0; } res->SetDefined(true); res->Clear(); UPoint up(1); Point p0, p1; for (int i = 0; i < source->GetNoComponents(); i++) { source->Get(i, up); p0.Set(up.p0.GetY(), up.p0.GetX()); p1.Set(up.p1.GetY(), up.p1.GetX()); p0.SetDefined(true); p1.SetDefined(true); up.p0 = p0; up.p1 = p1; res->MergeAdd(up); } return 0; } /* 5.48.3 Specification for operator ~swapcoord~ */ const std::string swapcoordSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\") " "( mpoint -> mpoint" "swapcoord( _ )" "swaps the x and y coordinates of an mpoint" "swapcoord(mpoint1)) )"; /* 5.48.4 Definition of operator ~swapcoord~ */ Operator temporalswapcoord("swapcoord", swapcoordSpec, swapcoordVM, Operator::SimpleSelect, swapcoordTM); /* 5.49 Operator ~getInterval~ This operator computes bounding interval of a moving object. */ ListExpr getIntervalTM(ListExpr args){ if(!nl->HasLength(args,1)){ return listutils::typeError("one arg expected"); } ListExpr a = nl->First(args); if( !MString::checkType(a) && !MRegion::checkType(a) && !MReal::checkType(a) && !MPoint::checkType(a) && !MInt::checkType(a) && !MBool::checkType(a) && !Periods::checkType(a) && !UString::checkType(a) && !URegion::checkType(a) && !UReal::checkType(a) && !UPoint::checkType(a) && !UInt::checkType(a) && !UBool::checkType(a)){ return listutils::typeError("unsupported type found"); } return listutils::basicSymbol(); } template int getIntervalVM_Unit(Word* args, Word& result, int message, Word& local, Supplier s){ A* arg = (A*) args[0].addr; result=qp->ResultStorage(s); SecInterval* res = (SecInterval*) result.addr; if(!arg->IsDefined()){ res->SetDefined(false); return 0; } (*res) = arg->timeInterval; return 0; } int getIntervalVM_Periods(Word* args, Word& result, int message, Word& local, Supplier s){ Periods* arg = (Periods*) args[0].addr; result=qp->ResultStorage(s); SecInterval* res = (SecInterval*) result.addr; if(!arg->IsDefined() || arg->GetNoComponents()<1){ res->SetDefined(false); return 0; } Interval iv(false); arg->Get(0,iv); (*res) = iv; if(arg->GetNoComponents()==1){ return 0; } arg->Get(arg->GetNoComponents()-1, iv); res->SetEnd(iv.end, iv.rc); return 0; } template int getIntervalVM_Moving(Word* args, Word& result, int message, Word& local, Supplier s){ A* arg = (A*) args[0].addr; result = qp->ResultStorage(s); typedef typename A::unittype U; SecInterval* res = (SecInterval*) result.addr; if(!arg->IsDefined() || arg->GetNoComponents()<1){ res->SetDefined(false); return 0; } U unit(false); arg->Get(0,unit); (*res) = unit.timeInterval; if(arg->GetNoComponents()==1){ return 0; } arg->Get(arg->GetNoComponents()-1, unit); res->SetEnd(unit.timeInterval.end, unit.timeInterval.rc); return 0; } ValueMapping getIntervalVM[] = { getIntervalVM_Unit, getIntervalVM_Unit, getIntervalVM_Unit, getIntervalVM_Unit, getIntervalVM_Unit, getIntervalVM_Unit, getIntervalVM_Periods, getIntervalVM_Moving, getIntervalVM_Moving, getIntervalVM_Moving, getIntervalVM_Moving, getIntervalVM_Moving, getIntervalVM_Moving }; int getIntervalSelect(ListExpr args){ ListExpr a = nl->First(args); if(UString::checkType(a) ) return 0; if(URegion::checkType(a) ) return 1; if(UReal::checkType(a) ) return 2; if(UPoint::checkType(a) ) return 3; if(UInt::checkType(a) ) return 4; if(UBool::checkType(a) ) return 5; if(Periods::checkType(a) ) return 6; if(MString::checkType(a) ) return 7; if(MRegion::checkType(a) ) return 8; if(MReal::checkType(a) ) return 9; if(MPoint::checkType(a) ) return 10; if(MInt::checkType(a) ) return 11; if(MBool::checkType(a) ) return 12; return -1; } OperatorSpec getIntervalSpec( "uX, uX -> interval, " "X in {string, region, real, int, boll, point, periods}", "getInterval(_)", "Computes the time interval (boxed).", "query getInterval(train1)" ); Operator getIntervalOp( "getInterval", getIntervalSpec.getStr(), 13, getIntervalVM, getIntervalSelect, getIntervalTM ); /* 6 Creating the Algebra */ class TemporalUnitAlgebra : public Algebra { public: TemporalUnitAlgebra() : Algebra() { AddTypeConstructor(&interval); interval.AssociateKind("DATA"); AddOperator( &temporalunitmakemvalue ); AddOperator( &temporalunitthemvalue ); AddOperator( &the_mvalue2 ); AddOperator( &temporalunitqueryrect2d ); AddOperator( &temporalunitpoint2d ); AddOperator( &temporalunitisempty ); AddOperator( &temporalunitdeftime ); AddOperator( &temporalunitpresent ); AddOperator( &temporalunitinitial ); AddOperator( &temporalunitfinal ); AddOperator( &temporalunitatinstant ); AddOperator( &temporalunitatperiods ); AddOperator( &temporalunitwhen ); AddOperator( &temporalunitat ); AddOperator( &temporalunitatmax ); AddOperator( &temporalunitatmin ); AddOperator( &temporalunitintersection ); AddOperator( &temporalunitinside ); AddOperator( &temporalunitpasses ); AddOperator( &temporalunitget_duration ); AddOperator( &temporalunittrajectory ); AddOperator( &temporalunitdistance ); AddOperator( &temporalunitabs ); AddOperator( &temporalspeed ); AddOperator( &temporalvelocity ); AddOperator( &temporalderivable ); AddOperator( &temporalderivative ); AddOperator( &temporalunitnocomponents ); AddOperator( &temporalunitnot ); AddOperator( &temporalunitand ); AddOperator( &temporalunitor ); AddOperator( &temporalunitsometimes ); AddOperator( &temporalunitnever ); AddOperator( &temporalunitalways ); AddOperator( &temporalunitisequal ); AddOperator( &temporalunitisnotequal ); AddOperator( &temporalunitsmaller ); AddOperator( &temporalunitbigger ); AddOperator( &temporalunitsmallereq ); AddOperator( &temporalunitbiggereq ); AddOperator( &temporalunitvalisequal ); AddOperator( &temporalunitvalisnotequal ); AddOperator( &temporalunitvalsmaller ); AddOperator( &temporalunitvalbigger ); AddOperator( &temporalunitvalsmallereq ); AddOperator( &temporalunitvalbiggereq ); AddOperator( &temporalunituint2ureal ); AddOperator( &temporalunittheupoint ); AddOperator( &temporalunittheivalue ); AddOperator( &temporalunitlength ); AddOperator( &temporalunitcanmeet); AddOperator( &atRectU); AddOperator(&temporalcontains); AddOperator(&temporalswapcoord); AddOperator(&getIntervalOp); } ~TemporalUnitAlgebra() {}; }; } // end of namespace temporalalgebra /* 7 Initialization Each algebra module needs an initialization function. The algebra manager has a reference to this function if this algebra is included in the list of required algebras, thus forcing the linker to include this module. The algebra manager invokes this function to get a reference to the instance of the algebra class and to provide references to the global nested list container (used to store constructor, type, operator and object information) and to the query processor. The function has a C interface to make it possible to load the algebra dynamically at runtime. */ extern "C" Algebra* InitializeTemporalUnitAlgebra( NestedList* nlRef, QueryProcessor* qpRef ) { nl = nlRef; qp = qpRef; return (new temporalalgebra::TemporalUnitAlgebra()); }