From ad7c84a500e59c1b546b301e64ef00d2faaa26c6 Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Fri, 21 Aug 2020 00:53:13 +0530 Subject: [PATCH 01/18] Introduce CAPI with bare minimum skeleton code --- README.md | 35 +++++++++++++++++++++++++++++++++++ capi/CMakeLists.txt | 35 +++++++++++++++++++++++++++++++++++ capi/include/meos/meos_c.h | 18 ++++++++++++++++++ capi/source/meos_c.cpp | 24 ++++++++++++++++++++++++ 4 files changed, 112 insertions(+) create mode 100644 capi/CMakeLists.txt create mode 100644 capi/include/meos/meos_c.h create mode 100644 capi/source/meos_c.cpp diff --git a/README.md b/README.md index 7f35995..b492558 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,41 @@ Minimalistic C++ app example: [https://github.com/adonmo/meos-cpp-example](https C++ API Reference: [https://adonmo.github.io/meos/](https://adonmo.github.io/meos/) +## C + +MEOS can also be accessed from C. + +Here is an example code on how to do this: + +```c +#include "meos/meos_c.h" +#include + +int main(int argc, char* argv[]) { + struct TBox* tbox = newTBox(12.34, 56.78); + double xmin = TBox_xmin(tbox); + printf("%lf\n", xmin); + deleteTBox(tbox); +} +``` +To compile the above code, you would need `libmeos_c.so`. If you do not have it, build it first by running: +```sh +cmake -B build/capi -S capi +cmake --build build/capi +``` + +After saving the above file as `main.c`, run the following commands to build and run it: + +```sh +gcc -I//capi/include -c main.c -o main.o +g++ -L//build/capi main.o -l:libmeos_c.so -o main +LD_LIBRARY_PATH=//build/capi ./main +``` +If you see the following output, you have succesfully used MEOS from C! +``` +12.340000 +``` + ## Contributing Issues and pull requests are welcome. diff --git a/capi/CMakeLists.txt b/capi/CMakeLists.txt new file mode 100644 index 0000000..eb140a8 --- /dev/null +++ b/capi/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +project( + meos_c + LANGUAGES CXX +) + +# ---- Dependencies ---- + +include(../cmake/CPM.cmake) + +CPMAddPackage( + NAME libmeos + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/.. +) + +# ---- Create library ---- + +file(GLOB_RECURSE headers CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h") +file(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp") +add_library(meos_c SHARED ${headers} ${sources}) +target_link_libraries(meos_c libmeos) + +if(MSVC) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) +endif() + +# being a cross-platform target, we enforce standards conformance on MSVC +target_compile_options(meos_c PUBLIC "$<$:/permissive->") + +target_include_directories(meos_c + PUBLIC + $ + $ +) diff --git a/capi/include/meos/meos_c.h b/capi/include/meos/meos_c.h new file mode 100644 index 0000000..2e76fa1 --- /dev/null +++ b/capi/include/meos/meos_c.h @@ -0,0 +1,18 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct TBox TBox; + +TBox *newTBox(double const xmin, double const xmax); + +double TBox_xmin(TBox *tbox); +double TBox_xmax(TBox *tbox); + +void deleteTBox(TBox *v); + +#ifdef __cplusplus +} +#endif diff --git a/capi/source/meos_c.cpp b/capi/source/meos_c.cpp new file mode 100644 index 0000000..98ac930 --- /dev/null +++ b/capi/source/meos_c.cpp @@ -0,0 +1,24 @@ +#include + +#include + +extern "C" { +TBox *newTBox(double const xmin, double const xmax) { + return reinterpret_cast(new meos::TBox(xmin, xmax)); +} + +double TBox_xmin(TBox *tbox) { + auto t = reinterpret_cast(tbox); + return t->xmin(); +} + +double TBox_xmax(TBox *tbox) { + auto t = reinterpret_cast(tbox); + return t->xmax(); +} + +void deleteTBox(TBox *tbox) { + auto t = reinterpret_cast(tbox); + delete t; +} +} From e345b2b7e05eb3181d6387e55ff6e3d47ca1016b Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Thu, 10 Sep 2020 12:40:51 +0530 Subject: [PATCH 02/18] Implement atPeriod - in TSeq and TSeqSet --- include/meos/types/temporal/TSequence.hpp | 4 + include/meos/types/temporal/TSequenceSet.hpp | 3 + include/meos/types/temporal/Temporal.hpp | 11 ++ include/meos/types/time/Period.hpp | 2 + source/types/temporal/TSequence.cpp | 158 +++++++++++++++++++ source/types/temporal/TSequenceSet.cpp | 47 ++++++ source/types/time/Period.cpp | 26 +++ test/source/types/temporal/tsequenceset.cpp | 22 +++ 8 files changed, 273 insertions(+) diff --git a/include/meos/types/temporal/TSequence.hpp b/include/meos/types/temporal/TSequence.hpp index 91524a4..13c3b62 100644 --- a/include/meos/types/temporal/TSequence.hpp +++ b/include/meos/types/temporal/TSequence.hpp @@ -62,6 +62,7 @@ template class TSequence : public TemporalSet *shift_impl(duration_ms const timedelta) const override; bool intersectsTimestamp(time_point const datetime) const override; bool intersectsPeriod(Period const period) const override; + TSequence atPeriod(Period const &period) const; std::istream &read(std::istream &in, bool with_interp = true, bool with_srid = true); std::ostream &write(std::ostream &os, bool with_interp = true, bool with_srid = true) const; @@ -110,6 +111,9 @@ template class TSequence : public TemporalSet *clone_impl() const override { return new TSequence(*this); }; + + TInstant atTimestamp(time_point t) const; + int findTimestamp(time_point t) const; }; typedef TSequence TBoolSeq; diff --git a/include/meos/types/temporal/TSequenceSet.hpp b/include/meos/types/temporal/TSequenceSet.hpp index fd9bf20..4e17e5c 100644 --- a/include/meos/types/temporal/TSequenceSet.hpp +++ b/include/meos/types/temporal/TSequenceSet.hpp @@ -93,6 +93,7 @@ template class TSequenceSet TSequenceSet *shift_impl(duration_ms const timedelta) const override; bool intersectsTimestamp(time_point const datetime) const override; bool intersectsPeriod(Period const period) const override; + TSequenceSet atPeriod(Period const &period) const; std::istream &read(std::istream &in); std::ostream &write(std::ostream &os) const; @@ -137,6 +138,8 @@ template class TSequenceSet std::ostream &write_internal(std::ostream &os) const; TSequenceSet *clone_impl() const override { return new TSequenceSet(*this); }; + + int findTimestamp(time_point t) const; }; typedef TSequenceSet TBoolSeqSet; diff --git a/include/meos/types/temporal/Temporal.hpp b/include/meos/types/temporal/Temporal.hpp index 445834f..5103a15 100644 --- a/include/meos/types/temporal/Temporal.hpp +++ b/include/meos/types/temporal/Temporal.hpp @@ -133,6 +133,17 @@ template class Temporal */ bool intersectsPeriodSet(PeriodSet const periodset) const; + /** + * @brief Restrict to a period + * @code + * TFloatSeqSet t("{[1@2012-01-01, 3@2012-01-03), [3@2012-01-04, 1@2012-01-06)}"); + * Period p("[2012-01-02,2012-01-05)"); + * + * t.atPeriod(p); // + * @endcode + */ + // virtual BaseType atPeriod(Period period) const = 0; + private: virtual Temporal *clone_impl() const = 0; diff --git a/include/meos/types/time/Period.hpp b/include/meos/types/time/Period.hpp index f44c1fb..6829fbf 100644 --- a/include/meos/types/time/Period.hpp +++ b/include/meos/types/time/Period.hpp @@ -43,7 +43,9 @@ class Period { duration_ms timespan() const; std::unique_ptr shift(duration_ms const timedelta) const; bool overlap(Period const &period) const; + bool contains(Period const &period) const; bool contains_timestamp(time_point const timestamp) const; + Period intersection(Period const &period) const; friend bool operator==(Period const &lhs, Period const &rhs); friend bool operator!=(Period const &lhs, Period const &rhs); diff --git a/source/types/temporal/TSequence.cpp b/source/types/temporal/TSequence.cpp index c253128..fb3b25b 100644 --- a/source/types/temporal/TSequence.cpp +++ b/source/types/temporal/TSequence.cpp @@ -298,6 +298,164 @@ template bool TSequence::intersectsPeriod(Period c return this->period().overlap(period); } +template +TSequence TSequence::atPeriod(Period const &period) const { + Period inter = this->period().intersection(period); + auto interp = this->interpolation(); + + /* Intersecting period is instantaneous */ + if (inter.lower() == inter.upper()) { + set> instants; + TInstant instant = this->atTimestamp(inter.lower()); + instants.insert(instant); + return TSequence(instants); + } + + int n = this->findTimestamp(inter.lower()); + + /* If the lower bound of the intersecting period is exclusive */ + if (n == -1) n = 0; + set> instants; + + /* Compute the value at the beginning of the intersecting period */ + TInstant inst1 = this->instantN(n); + TInstant inst2 = this->instantN(n + 1); + instants.insert(at_timestamp1(inst1, inst2, interp, inter.lower())); + for (size_t i = n + 2; i < this->m_instants.size(); i++) { + /* If the end of the intersecting period is between inst1 and inst2 */ + if (inst1.getTimestamp() <= inter.upper() && inter.upper() <= inst2.getTimestamp()) break; + + inst1 = inst2; + inst2 = this->instantN(i); + /* If the intersecting period contains inst1 */ + if (inter.lower() <= inst1.getTimestamp() && inst1.getTimestamp() <= inter.upper()) + instants.insert(inst1); + } + + /* The last two values of sequences with step interpolation and + * exclusive upper bound must be equal */ + if (interp == Interpolation::Linear || inter.upper_inc()) + instants.insert(at_timestamp1(inst1, inst2, interp, inter.upper())); + else { + auto value = instants.rbegin()->getValue(); + instants.insert(TInstant(value, inter.upper())); + } + + /* Since by definition the sequence is normalized it is not necessary to + * normalize the projection of the sequence to the period */ + TSequence result(instants, inter.lower_inc(), inter.upper_inc(), interp); + return result; +} + +template int TSequence::findTimestamp(time_point t) const { + int first = 0; + int const seq_size = this->m_instants.size(); + int last = seq_size - 2; + int middle = (first + last) / 2; + while (first <= last) { + TInstant inst1 = this->instantN(middle); + TInstant inst2 = this->instantN(middle + 1); + bool lower_inc = (middle == 0) ? this->period().lower_inc() : true; + bool upper_inc = (middle == seq_size - 2) ? this->period().upper_inc() : false; + if ((inst1.getTimestamp() < t && t < inst2.getTimestamp()) + || (lower_inc && inst1.getTimestamp() == t) || (upper_inc && inst2.getTimestamp() == t)) + return middle; + if (t <= inst1.getTimestamp()) + last = middle - 1; + else + first = middle + 1; + middle = (first + last) / 2; + } + return -1; +} + +/** + * Returns a point interpolated from the geometry/geography segment with + * respect to the fraction of its total length. + * + * @param[in] start,end Points defining the segment + * @param[in] ratio Float between 0 and 1 representing the fraction of the + * total length of the segment where the point must be located + */ +GeomPoint geoseg_interpolate_point(GeomPoint start, GeomPoint end, double ratio) { + int srid = start.srid(); + // TODO add support for geodetic + // bool geodetic = start.geodetic(); + GeomPoint p(start.x() + ((end.x() - start.x()) * ratio), + start.y() + ((end.y() - start.y()) * ratio), srid); + return p; +} + +template BaseType value_at_timestamp1(TInstant const & /*inst1*/, + TInstant const & /*inst2*/, + Interpolation /*interpolation*/, + time_point /*t*/) { + // Check template specializations for double and GeomPoint + throw invalid_argument("Unsupported base type for function"); +} + +template <> float value_at_timestamp1(TInstant const &inst1, TInstant const &inst2, + Interpolation interpolation, time_point t) { + auto start = inst1.getValue(); + auto end = inst2.getValue(); + /* Constant segment or t is equal to lower bound or step interpolation */ + if (start == end || inst1.getTimestamp() == t + || (interpolation != Interpolation::Linear && t < inst2.getTimestamp())) + return start; + + /* t is equal to upper bound */ + if (inst2.getTimestamp() == t) return end; + + /* Interpolation for types with linear interpolation */ + auto duration1 = t - inst1.getTimestamp(); + auto duration2 = inst2.getTimestamp() - inst1.getTimestamp(); + float ratio = ((float)duration1.count()) / duration2.count(); + return start + (end - start) * ratio; +} + +template <> GeomPoint value_at_timestamp1(TInstant const &inst1, + TInstant const &inst2, + Interpolation interpolation, time_point t) { + auto start = inst1.getValue(); + auto end = inst2.getValue(); + /* Constant segment or t is equal to lower bound or step interpolation */ + if (start == end || inst1.getTimestamp() == t + || (interpolation != Interpolation::Linear && t < inst2.getTimestamp())) + return start; + + /* t is equal to upper bound */ + if (inst2.getTimestamp() == t) return end; + + /* Interpolation for types with linear interpolation */ + auto duration1 = t - inst1.getTimestamp(); + auto duration2 = inst2.getTimestamp() - inst1.getTimestamp(); + double ratio = duration1 / duration2; + return geoseg_interpolate_point(start, end, ratio); +} + +template +TInstant at_timestamp1(TInstant const &inst1, TInstant const &inst2, + Interpolation interpolation, time_point t) { + auto value = value_at_timestamp1(inst1, inst2, interpolation, t); + return TInstant(value, t); +} + +template +TInstant TSequence::atTimestamp(time_point t) const { + /* Bounding box test */ + if (!this->period().contains_timestamp(t)) + throw invalid_argument("Specified timestamp does not overlap with this sequence"); + + /* Instantaneous sequence */ + if (this->m_instants.size() == 1) return this->startInstant(); + + /* General case */ + int n = this->findTimestamp(t); + TInstant inst1 = this->instantN(n); + TInstant inst2 = this->instantN(n + 1); + return at_timestamp1(inst1, inst2, this->interpolation(), t); +} + template istream &TSequence::read_internal(istream &in, bool with_interp) { char c; diff --git a/source/types/temporal/TSequenceSet.cpp b/source/types/temporal/TSequenceSet.cpp index fd806d9..6aa92c1 100644 --- a/source/types/temporal/TSequenceSet.cpp +++ b/source/types/temporal/TSequenceSet.cpp @@ -337,6 +337,53 @@ bool TSequenceSet::intersectsPeriod(Period const period) const { return false; } +template +TSequenceSet TSequenceSet::atPeriod(Period const &period) const { + int loc = this->findTimestamp(period.lower()); + int const seq_size = this->m_sequences.size(); + if (loc >= seq_size) { + throw invalid_argument("no value at specified period"); + } + TSequence seq; + set> sequences; + for (int i = loc; i < seq_size; i++) { + seq = this->sequenceN(i); + auto seq_period = seq.period(); + if (period.contains(seq_period)) { + sequences.insert(seq); + } else if (period.overlap(seq_period)) { + sequences.insert(seq.atPeriod(period)); + } + if ((period.upper() < seq_period.upper()) + || ((period.upper() == seq_period.upper()) && seq_period.upper_inc())) { + break; + } + } + if (sequences.size() == 0) { + throw invalid_argument("no value at specified period"); + } + return TSequenceSet(sequences); +} + +template int TSequenceSet::findTimestamp(time_point t) const { + int first = 0, middle = 0, last = this->m_sequences.size() - 1; + TSequence seq; + while (first <= last) { + middle = (first + last) / 2; + seq = this->sequenceN(middle); + Period p = seq.period(); + if (p.contains_timestamp(t)) { + return middle; + } + if (t <= p.lower()) + last = middle - 1; + else + first = middle + 1; + } + if (t >= seq.period().upper()) middle++; + return middle; +} + template istream &TSequenceSet::read_internal(istream &in) { char c; diff --git a/source/types/time/Period.cpp b/source/types/time/Period.cpp index 5d0601c..f4c996c 100644 --- a/source/types/time/Period.cpp +++ b/source/types/time/Period.cpp @@ -84,12 +84,38 @@ bool Period::overlap(Period const &period) const { : period.upper_inc() && this->lower_inc(); } +bool Period::contains(Period const &period) const { + bool c1 = this->lower() < period.lower(); + bool c2 = this->upper() > period.upper(); + if ((c1 || (this->lower() == period.lower() && (this->lower_inc() || !period.lower_inc()))) + && (c2 || (this->upper() == period.upper() && (this->upper_inc() || !period.upper_inc())))) { + return true; + } + return false; +} + bool Period::contains_timestamp(time_point const timestamp) const { return ((this->lower() < timestamp && timestamp < this->upper()) || (this->lower_inc() && this->lower() == timestamp) || (this->upper_inc() && this->upper() == timestamp)); } +Period Period::intersection(Period const &other) const { + /* Bounding box test */ + if (!this->overlap(other)) + throw invalid_argument("Specified period does not overlap with this period"); + + time_point lower = max(this->lower(), other.lower()); + time_point upper = min(this->upper(), other.upper()); + bool lower_inc = this->lower() == other.lower() + ? this->lower_inc() && other.lower_inc() + : (lower == this->lower() ? this->lower_inc() : other.lower_inc()); + bool upper_inc = this->upper() == other.upper() + ? this->upper_inc() && other.upper_inc() + : (upper == this->upper() ? this->upper_inc() : other.upper_inc()); + return Period(lower, upper, lower_inc, upper_inc); +} + int Period::compare(Period const &other) const { if (lower() < other.lower()) return -1; diff --git a/test/source/types/temporal/tsequenceset.cpp b/test/source/types/temporal/tsequenceset.cpp index 2d43487..438b1a4 100644 --- a/test/source/types/temporal/tsequenceset.cpp +++ b/test/source/types/temporal/tsequenceset.cpp @@ -576,3 +576,25 @@ TEST_CASE("interpolation is maintained in sequences", "[tsequenceset]") { REQUIRE(seq.interpolation() == Interpolation::Stepwise); } } + +TEST_CASE("atPeriod", "[tsequenceset]") { + SECTION("no overlap at sequence level") { + TFloatSeqSet seqset("{[1@2012-01-02, 3@2012-01-03), [3@2012-01-04, 1@2012-01-06)}"); + Period period("[2012-01-01,2012-01-07)"); + TFloatSeqSet result = seqset.atPeriod(period); + + stringstream output; + output << result; + REQUIRE(output.str() == "{[1@2012-01-02T00:00:00+0000, 3@2012-01-03T00:00:00+0000), [3@2012-01-04T00:00:00+0000, 1@2012-01-06T00:00:00+0000)}"); + } + + SECTION("overlap at sequence level") { + TFloatSeqSet seqset("{[1@2012-01-01, 3@2012-01-03), [3@2012-01-04, 1@2012-01-06)}"); + Period period("[2012-01-02,2012-01-05)"); + TFloatSeqSet result = seqset.atPeriod(period); + + stringstream output; + output << result; + REQUIRE(output.str() == "{[2@2012-01-02T00:00:00+0000, 3@2012-01-03T00:00:00+0000), [3@2012-01-04T00:00:00+0000, 2@2012-01-05T00:00:00+0000)}"); + } +} From e971e11062614ab324dcd7c2aec6684e6534994f Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Tue, 15 Sep 2020 12:40:19 +0530 Subject: [PATCH 03/18] C API: Expose TFloatSeqSet's atPeriod function --- capi/include/meos/meos_c.h | 23 ++++++++++++++++- capi/source/meos_c.cpp | 51 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/capi/include/meos/meos_c.h b/capi/include/meos/meos_c.h index 2e76fa1..341bc0b 100644 --- a/capi/include/meos/meos_c.h +++ b/capi/include/meos/meos_c.h @@ -1,17 +1,38 @@ #pragma once +#include + #ifdef __cplusplus extern "C" { #endif typedef struct TBox TBox; +typedef struct Period Period; +typedef struct TFloatSeqSet TFloatSeqSet; + +// TBox TBox *newTBox(double const xmin, double const xmax); double TBox_xmin(TBox *tbox); double TBox_xmax(TBox *tbox); -void deleteTBox(TBox *v); +void deleteTBox(TBox *tbox); + +// Period + +Period *newPeriod(char *serialized); + +void deletePeriod(Period *period); + +// TFloatSeqSet + +TFloatSeqSet *newTFloatSeqSet(char *serialized); + +TFloatSeqSet *TFloatSeqSet_atPeriod(TFloatSeqSet *tfloatseqset, Period *period); +unsigned char *TFloatSeqSet_str(TFloatSeqSet *tfloatseqset, size_t *size); + +void deleteTFloatSeqSet(TFloatSeqSet *tfloatseqset); #ifdef __cplusplus } diff --git a/capi/source/meos_c.cpp b/capi/source/meos_c.cpp index 98ac930..0e35819 100644 --- a/capi/source/meos_c.cpp +++ b/capi/source/meos_c.cpp @@ -1,8 +1,15 @@ #include +#include #include +#include +#include +#include extern "C" { + +// TBox + TBox *newTBox(double const xmin, double const xmax) { return reinterpret_cast(new meos::TBox(xmin, xmax)); } @@ -21,4 +28,48 @@ void deleteTBox(TBox *tbox) { auto t = reinterpret_cast(tbox); delete t; } + +// Period + +Period *newPeriod(char *serialized) { + return reinterpret_cast(new meos::Period(serialized)); +} + +void deletePeriod(Period *period) { + auto t = reinterpret_cast(period); + delete t; +} + +// TFloatSeqSet + +TFloatSeqSet *newTFloatSeqSet(char *serialized) { + return reinterpret_cast(new meos::TFloatSeqSet(serialized)); +} + +TFloatSeqSet *TFloatSeqSet_atPeriod(TFloatSeqSet *tfloatseqset, Period *period) { + auto t = reinterpret_cast(tfloatseqset); + auto p = reinterpret_cast(period); + auto r = t->atPeriod(*p); + return reinterpret_cast(new meos::TFloatSeqSet(r)); +} + +// Remember to free the result! +unsigned char *TFloatSeqSet_str(TFloatSeqSet *tfloatseqset, size_t *size) { + auto t = reinterpret_cast(tfloatseqset); + std::stringstream output; + output << *t; + auto s = output.str(); + const std::size_t len = s.length(); + unsigned char *result = static_cast(malloc(len)); + if (result) { + std::memcpy(result, s.c_str(), len); + *size = len; + } + return result; +} + +void deleteTFloatSeqSet(TFloatSeqSet *tfloatseqset) { + auto t = reinterpret_cast(tfloatseqset); + delete t; +} } From b5c712a5b85e74ed62c0015743856f8cf4597808 Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Tue, 15 Sep 2020 12:40:49 +0530 Subject: [PATCH 04/18] C API: packageProject in CMake --- capi/CMakeLists.txt | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/capi/CMakeLists.txt b/capi/CMakeLists.txt index eb140a8..9e77d8e 100644 --- a/capi/CMakeLists.txt +++ b/capi/CMakeLists.txt @@ -2,8 +2,13 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR) project( meos_c - LANGUAGES CXX + LANGUAGES C CXX ) +# Get version from VERSION file instead of hardcoding here +# This is so that we can maintain a single version across C/C++ and Python +file(STRINGS ../VERSION LIBMEOS_VERSION) +set(PROJECT_VERSION ${LIBMEOS_VERSION}) +message(STATUS "MEOS: v${LIBMEOS_VERSION}") # ---- Dependencies ---- @@ -33,3 +38,15 @@ target_include_directories(meos_c $ $ ) + +message(${PROJECT_SOURCE_DIR}/include) + +packageProject( + NAME ${PROJECT_NAME} + VERSION ${PROJECT_VERSION} + BINARY_DIR ${PROJECT_BINARY_DIR} + INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include + INCLUDE_DESTINATION include/${PROJECT_NAME}-${PROJECT_VERSION} + VERSION_HEADER "${VERSION_HEADER_LOCATION}" + DEPENDENCIES "" +) From ce2dadb4c51d68dfd7c28d534990548d0072934a Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Wed, 16 Sep 2020 10:29:52 +0530 Subject: [PATCH 05/18] C API: namespace all C functions and types --- README.md | 6 +++--- capi/include/meos/meos_c.h | 26 +++++++++++++------------- capi/source/meos_c.cpp | 29 +++++++++++++++-------------- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index b492558..0c17637 100644 --- a/README.md +++ b/README.md @@ -123,10 +123,10 @@ Here is an example code on how to do this: #include int main(int argc, char* argv[]) { - struct TBox* tbox = newTBox(12.34, 56.78); - double xmin = TBox_xmin(tbox); + struct MEOS_TBox* tbox = MEOS_newTBox(12.34, 56.78); + double xmin = MEOS_TBox_xmin(tbox); printf("%lf\n", xmin); - deleteTBox(tbox); + MEOS_deleteTBox(tbox); } ``` To compile the above code, you would need `libmeos_c.so`. If you do not have it, build it first by running: diff --git a/capi/include/meos/meos_c.h b/capi/include/meos/meos_c.h index 341bc0b..dc212a5 100644 --- a/capi/include/meos/meos_c.h +++ b/capi/include/meos/meos_c.h @@ -6,33 +6,33 @@ extern "C" { #endif -typedef struct TBox TBox; -typedef struct Period Period; -typedef struct TFloatSeqSet TFloatSeqSet; +typedef struct MEOS_TBox MEOS_TBox; +typedef struct MEOS_Period MEOS_Period; +typedef struct MEOS_TFloatSeqSet MEOS_TFloatSeqSet; // TBox -TBox *newTBox(double const xmin, double const xmax); +MEOS_TBox *MEOS_newTBox(double const xmin, double const xmax); -double TBox_xmin(TBox *tbox); -double TBox_xmax(TBox *tbox); +double MEOS_TBox_xmin(MEOS_TBox *tbox); +double MEOS_TBox_xmax(MEOS_TBox *tbox); -void deleteTBox(TBox *tbox); +void MEOS_deleteTBox(MEOS_TBox *tbox); // Period -Period *newPeriod(char *serialized); +MEOS_Period *MEOS_newPeriod(char *serialized); -void deletePeriod(Period *period); +void MEOS_deletePeriod(MEOS_Period *period); // TFloatSeqSet -TFloatSeqSet *newTFloatSeqSet(char *serialized); +MEOS_TFloatSeqSet *MEOS_newTFloatSeqSet(char *serialized); -TFloatSeqSet *TFloatSeqSet_atPeriod(TFloatSeqSet *tfloatseqset, Period *period); -unsigned char *TFloatSeqSet_str(TFloatSeqSet *tfloatseqset, size_t *size); +MEOS_TFloatSeqSet *MEOS_TFloatSeqSet_atPeriod(MEOS_TFloatSeqSet *tfloatseqset, MEOS_Period *period); +unsigned char *MEOS_TFloatSeqSet_str(MEOS_TFloatSeqSet *tfloatseqset, size_t *size); -void deleteTFloatSeqSet(TFloatSeqSet *tfloatseqset); +void MEOS_deleteTFloatSeqSet(MEOS_TFloatSeqSet *tfloatseqset); #ifdef __cplusplus } diff --git a/capi/source/meos_c.cpp b/capi/source/meos_c.cpp index 0e35819..b6f79e7 100644 --- a/capi/source/meos_c.cpp +++ b/capi/source/meos_c.cpp @@ -10,51 +10,52 @@ extern "C" { // TBox -TBox *newTBox(double const xmin, double const xmax) { - return reinterpret_cast(new meos::TBox(xmin, xmax)); +MEOS_TBox *MEOS_newTBox(double const xmin, double const xmax) { + return reinterpret_cast(new meos::TBox(xmin, xmax)); } -double TBox_xmin(TBox *tbox) { +double MEOS_TBox_xmin(MEOS_TBox *tbox) { auto t = reinterpret_cast(tbox); return t->xmin(); } -double TBox_xmax(TBox *tbox) { +double MEOS_TBox_xmax(MEOS_TBox *tbox) { auto t = reinterpret_cast(tbox); return t->xmax(); } -void deleteTBox(TBox *tbox) { +void MEOS_deleteTBox(MEOS_TBox *tbox) { auto t = reinterpret_cast(tbox); delete t; } // Period -Period *newPeriod(char *serialized) { - return reinterpret_cast(new meos::Period(serialized)); +MEOS_Period *MEOS_newPeriod(char *serialized) { + return reinterpret_cast(new meos::Period(serialized)); } -void deletePeriod(Period *period) { +void MEOS_deletePeriod(MEOS_Period *period) { auto t = reinterpret_cast(period); delete t; } // TFloatSeqSet -TFloatSeqSet *newTFloatSeqSet(char *serialized) { - return reinterpret_cast(new meos::TFloatSeqSet(serialized)); +MEOS_TFloatSeqSet *MEOS_newTFloatSeqSet(char *serialized) { + return reinterpret_cast(new meos::TFloatSeqSet(serialized)); } -TFloatSeqSet *TFloatSeqSet_atPeriod(TFloatSeqSet *tfloatseqset, Period *period) { +MEOS_TFloatSeqSet *MEOS_TFloatSeqSet_atPeriod(MEOS_TFloatSeqSet *tfloatseqset, + MEOS_Period *period) { auto t = reinterpret_cast(tfloatseqset); auto p = reinterpret_cast(period); auto r = t->atPeriod(*p); - return reinterpret_cast(new meos::TFloatSeqSet(r)); + return reinterpret_cast(new meos::TFloatSeqSet(r)); } // Remember to free the result! -unsigned char *TFloatSeqSet_str(TFloatSeqSet *tfloatseqset, size_t *size) { +unsigned char *MEOS_TFloatSeqSet_str(MEOS_TFloatSeqSet *tfloatseqset, size_t *size) { auto t = reinterpret_cast(tfloatseqset); std::stringstream output; output << *t; @@ -68,7 +69,7 @@ unsigned char *TFloatSeqSet_str(TFloatSeqSet *tfloatseqset, size_t *size) { return result; } -void deleteTFloatSeqSet(TFloatSeqSet *tfloatseqset) { +void MEOS_deleteTFloatSeqSet(MEOS_TFloatSeqSet *tfloatseqset) { auto t = reinterpret_cast(tfloatseqset); delete t; } From 8aa3c093c6898c1520096a8bb50b385a72580224 Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Sat, 19 Sep 2020 19:51:29 +0530 Subject: [PATCH 06/18] C API: Add MEOS_Period_str function --- capi/include/meos/meos_c.h | 2 ++ capi/source/meos_c.cpp | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/capi/include/meos/meos_c.h b/capi/include/meos/meos_c.h index dc212a5..5d07a49 100644 --- a/capi/include/meos/meos_c.h +++ b/capi/include/meos/meos_c.h @@ -23,6 +23,8 @@ void MEOS_deleteTBox(MEOS_TBox *tbox); MEOS_Period *MEOS_newPeriod(char *serialized); +unsigned char *MEOS_Period_str(MEOS_Period *period, size_t *size); + void MEOS_deletePeriod(MEOS_Period *period); // TFloatSeqSet diff --git a/capi/source/meos_c.cpp b/capi/source/meos_c.cpp index b6f79e7..9a0b793 100644 --- a/capi/source/meos_c.cpp +++ b/capi/source/meos_c.cpp @@ -35,6 +35,21 @@ MEOS_Period *MEOS_newPeriod(char *serialized) { return reinterpret_cast(new meos::Period(serialized)); } +// Remember to free the result! +unsigned char *MEOS_Period_str(MEOS_Period *period, size_t *size) { + auto t = reinterpret_cast(period); + std::stringstream output; + output << *t; + auto s = output.str(); + const std::size_t len = s.length(); + unsigned char *result = static_cast(malloc(len)); + if (result) { + std::memcpy(result, s.c_str(), len); + *size = len; + } + return result; +} + void MEOS_deletePeriod(MEOS_Period *period) { auto t = reinterpret_cast(period); delete t; From 5a0862404e54bbdac2706ad09fb670b6e604f119 Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Sat, 19 Sep 2020 20:38:05 +0530 Subject: [PATCH 07/18] C API: Simplify str functions --- capi/include/meos/meos_c.h | 4 ++-- capi/source/meos_c.cpp | 14 ++++++-------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/capi/include/meos/meos_c.h b/capi/include/meos/meos_c.h index 5d07a49..804f277 100644 --- a/capi/include/meos/meos_c.h +++ b/capi/include/meos/meos_c.h @@ -23,7 +23,7 @@ void MEOS_deleteTBox(MEOS_TBox *tbox); MEOS_Period *MEOS_newPeriod(char *serialized); -unsigned char *MEOS_Period_str(MEOS_Period *period, size_t *size); +char *MEOS_Period_str(MEOS_Period *period); void MEOS_deletePeriod(MEOS_Period *period); @@ -32,7 +32,7 @@ void MEOS_deletePeriod(MEOS_Period *period); MEOS_TFloatSeqSet *MEOS_newTFloatSeqSet(char *serialized); MEOS_TFloatSeqSet *MEOS_TFloatSeqSet_atPeriod(MEOS_TFloatSeqSet *tfloatseqset, MEOS_Period *period); -unsigned char *MEOS_TFloatSeqSet_str(MEOS_TFloatSeqSet *tfloatseqset, size_t *size); +char *MEOS_TFloatSeqSet_str(MEOS_TFloatSeqSet *tfloatseqset); void MEOS_deleteTFloatSeqSet(MEOS_TFloatSeqSet *tfloatseqset); diff --git a/capi/source/meos_c.cpp b/capi/source/meos_c.cpp index 9a0b793..4f4b3a8 100644 --- a/capi/source/meos_c.cpp +++ b/capi/source/meos_c.cpp @@ -36,16 +36,15 @@ MEOS_Period *MEOS_newPeriod(char *serialized) { } // Remember to free the result! -unsigned char *MEOS_Period_str(MEOS_Period *period, size_t *size) { +char *MEOS_Period_str(MEOS_Period *period) { auto t = reinterpret_cast(period); std::stringstream output; output << *t; auto s = output.str(); const std::size_t len = s.length(); - unsigned char *result = static_cast(malloc(len)); + char *result = new char[len + 1]; if (result) { - std::memcpy(result, s.c_str(), len); - *size = len; + std::strcpy(result, s.c_str()); } return result; } @@ -70,16 +69,15 @@ MEOS_TFloatSeqSet *MEOS_TFloatSeqSet_atPeriod(MEOS_TFloatSeqSet *tfloatseqset, } // Remember to free the result! -unsigned char *MEOS_TFloatSeqSet_str(MEOS_TFloatSeqSet *tfloatseqset, size_t *size) { +char *MEOS_TFloatSeqSet_str(MEOS_TFloatSeqSet *tfloatseqset) { auto t = reinterpret_cast(tfloatseqset); std::stringstream output; output << *t; auto s = output.str(); const std::size_t len = s.length(); - unsigned char *result = static_cast(malloc(len)); + char *result = new char[len + 1]; if (result) { - std::memcpy(result, s.c_str(), len); - *size = len; + std::strcpy(result, s.c_str()); } return result; } From de4204679054322d32eeea9b126f9330efab4e5c Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Wed, 23 Sep 2020 22:36:59 +0530 Subject: [PATCH 08/18] C API: More Period constructors --- capi/include/meos/meos_c.h | 6 ++++++ capi/source/meos_c.cpp | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/capi/include/meos/meos_c.h b/capi/include/meos/meos_c.h index 804f277..c122ba8 100644 --- a/capi/include/meos/meos_c.h +++ b/capi/include/meos/meos_c.h @@ -1,6 +1,7 @@ #pragma once #include +#include #ifdef __cplusplus extern "C" { @@ -21,7 +22,12 @@ void MEOS_deleteTBox(MEOS_TBox *tbox); // Period +// Constructor with a string MEOS_Period *MEOS_newPeriod(char *serialized); +// Constructor with two timestamps +MEOS_Period *MEOS_newPeriod_TT(time_t lower, time_t upper); +// Constructor with two timestamps and two boolean bounds +MEOS_Period *MEOS_newPeriod_TTBB(time_t lower, time_t upper, bool lower_inc, bool upper_inc); char *MEOS_Period_str(MEOS_Period *period); diff --git a/capi/source/meos_c.cpp b/capi/source/meos_c.cpp index 4f4b3a8..587c791 100644 --- a/capi/source/meos_c.cpp +++ b/capi/source/meos_c.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -35,6 +36,18 @@ MEOS_Period *MEOS_newPeriod(char *serialized) { return reinterpret_cast(new meos::Period(serialized)); } +MEOS_Period *MEOS_newPeriod_TT(time_t lower, time_t upper) { + return reinterpret_cast( + new meos::Period(std::chrono::system_clock::from_time_t(lower), + std::chrono::system_clock::from_time_t(upper))); +} + +MEOS_Period *MEOS_newPeriod_TTBB(time_t lower, time_t upper, bool lower_inc, bool upper_inc) { + return reinterpret_cast( + new meos::Period(std::chrono::system_clock::from_time_t(lower), + std::chrono::system_clock::from_time_t(upper), lower_inc, upper_inc)); +} + // Remember to free the result! char *MEOS_Period_str(MEOS_Period *period) { auto t = reinterpret_cast(period); From 8021d253543ce974f8e3cae8bb012ae7697bbe17 Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Wed, 23 Sep 2020 23:48:12 +0530 Subject: [PATCH 09/18] C API: More TFloatSeqSet constructors --- capi/include/meos/meos_c.h | 15 ++++++++++++++- capi/source/meos_c.cpp | 25 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/capi/include/meos/meos_c.h b/capi/include/meos/meos_c.h index c122ba8..d51a709 100644 --- a/capi/include/meos/meos_c.h +++ b/capi/include/meos/meos_c.h @@ -7,10 +7,16 @@ extern "C" { #endif -typedef struct MEOS_TBox MEOS_TBox; typedef struct MEOS_Period MEOS_Period; +typedef struct MEOS_TBox MEOS_TBox; +typedef struct MEOS_TFloatSeq MEOS_TFloatSeq; typedef struct MEOS_TFloatSeqSet MEOS_TFloatSeqSet; +enum MEOS_Interpolation { + MEOS_Interpolation_Stepwise, + MEOS_Interpolation_Linear, +}; + // TBox MEOS_TBox *MEOS_newTBox(double const xmin, double const xmax); @@ -35,7 +41,14 @@ void MEOS_deletePeriod(MEOS_Period *period); // TFloatSeqSet +// Constructor with a string MEOS_TFloatSeqSet *MEOS_newTFloatSeqSet(char *serialized); +// Constructor with a set of sequences and interpolation +MEOS_TFloatSeqSet *MEOS_newTFloatSeqSet_SI(MEOS_TFloatSeq **sequences, int count, + MEOS_Interpolation interpolation); +// Constructor with a set of sequences as strings and interpolation +MEOS_TFloatSeqSet *MEOS_newTFloatSeqSet_SsI(char **sequences, int count, + MEOS_Interpolation interpolation); MEOS_TFloatSeqSet *MEOS_TFloatSeqSet_atPeriod(MEOS_TFloatSeqSet *tfloatseqset, MEOS_Period *period); char *MEOS_TFloatSeqSet_str(MEOS_TFloatSeqSet *tfloatseqset); diff --git a/capi/source/meos_c.cpp b/capi/source/meos_c.cpp index 587c791..c1750d4 100644 --- a/capi/source/meos_c.cpp +++ b/capi/source/meos_c.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -73,6 +74,30 @@ MEOS_TFloatSeqSet *MEOS_newTFloatSeqSet(char *serialized) { return reinterpret_cast(new meos::TFloatSeqSet(serialized)); } +MEOS_TFloatSeqSet *MEOS_newTFloatSeqSet_SI(MEOS_TFloatSeq **sequences, int count, + MEOS_Interpolation interpolation) { + std::set s; + for (size_t i = 0; i < count; i++) { + auto seq = reinterpret_cast(sequences[i]); + s.insert(*seq); + } + auto interp = interpolation == MEOS_Interpolation_Linear ? meos::Interpolation::Linear + : meos::Interpolation::Stepwise; + return reinterpret_cast(new meos::TFloatSeqSet(s, interp)); +} + +MEOS_TFloatSeqSet *MEOS_newTFloatSeqSet_SsI(char **sequences, int count, + MEOS_Interpolation interpolation) { + std::set s; + for (size_t i = 0; i < count; i++) { + meos::TFloatSeq seq(sequences[i]); + s.insert(seq); + } + auto interp = interpolation == MEOS_Interpolation_Linear ? meos::Interpolation::Linear + : meos::Interpolation::Stepwise; + return reinterpret_cast(new meos::TFloatSeqSet(s, interp)); +} + MEOS_TFloatSeqSet *MEOS_TFloatSeqSet_atPeriod(MEOS_TFloatSeqSet *tfloatseqset, MEOS_Period *period) { auto t = reinterpret_cast(tfloatseqset); From b612c57fecaa8ec8c1d4dbe137d77aa90f9ba75a Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Thu, 24 Sep 2020 10:12:20 +0530 Subject: [PATCH 10/18] C API: TFloatSeq --- capi/include/meos/meos_c.h | 34 +++++++++++++++++--- capi/source/meos_c.cpp | 63 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 8 deletions(-) diff --git a/capi/include/meos/meos_c.h b/capi/include/meos/meos_c.h index d51a709..e29edb2 100644 --- a/capi/include/meos/meos_c.h +++ b/capi/include/meos/meos_c.h @@ -9,15 +9,18 @@ extern "C" { typedef struct MEOS_Period MEOS_Period; typedef struct MEOS_TBox MEOS_TBox; +typedef struct MEOS_TFloatInst MEOS_TFloatInst; typedef struct MEOS_TFloatSeq MEOS_TFloatSeq; typedef struct MEOS_TFloatSeqSet MEOS_TFloatSeqSet; -enum MEOS_Interpolation { +typedef enum { MEOS_Interpolation_Stepwise, MEOS_Interpolation_Linear, -}; +} MEOS_Interpolation; -// TBox +/***************************************************************************** + * TBox + *****************************************************************************/ MEOS_TBox *MEOS_newTBox(double const xmin, double const xmax); @@ -26,7 +29,9 @@ double MEOS_TBox_xmax(MEOS_TBox *tbox); void MEOS_deleteTBox(MEOS_TBox *tbox); -// Period +/***************************************************************************** + * Period + *****************************************************************************/ // Constructor with a string MEOS_Period *MEOS_newPeriod(char *serialized); @@ -39,7 +44,26 @@ char *MEOS_Period_str(MEOS_Period *period); void MEOS_deletePeriod(MEOS_Period *period); -// TFloatSeqSet +/***************************************************************************** + * TFloatSeq + *****************************************************************************/ + +// Constructor with a string +MEOS_TFloatSeq *MEOS_newTFloatSeq(char *serialized); +// Constructor with a set of instants, two boolean bounds and interpolation +MEOS_TFloatSeq *MEOS_newTFloatSeq_IBBI(MEOS_TFloatInst **instants, int count, bool lower_inc, + bool upper_inc, MEOS_Interpolation interpolation); +// Constructor with a set of instants as strings, two boolean bounds and interpolation +MEOS_TFloatSeq *MEOS_newTFloatSeq_IsBBI(char **instants, int count, bool lower_inc, bool upper_inc, + MEOS_Interpolation interpolation); + +char *MEOS_TFloatSeq_str(MEOS_TFloatSeq *tfloatseqset); + +void MEOS_deleteTFloatSeq(MEOS_TFloatSeq *tfloatseqset); + +/***************************************************************************** + * TFloatSeqSet + *****************************************************************************/ // Constructor with a string MEOS_TFloatSeqSet *MEOS_newTFloatSeqSet(char *serialized); diff --git a/capi/source/meos_c.cpp b/capi/source/meos_c.cpp index c1750d4..c8b3f80 100644 --- a/capi/source/meos_c.cpp +++ b/capi/source/meos_c.cpp @@ -10,7 +10,9 @@ extern "C" { -// TBox +/***************************************************************************** + * TBox + *****************************************************************************/ MEOS_TBox *MEOS_newTBox(double const xmin, double const xmax) { return reinterpret_cast(new meos::TBox(xmin, xmax)); @@ -31,7 +33,9 @@ void MEOS_deleteTBox(MEOS_TBox *tbox) { delete t; } -// Period +/***************************************************************************** + * Period + *****************************************************************************/ MEOS_Period *MEOS_newPeriod(char *serialized) { return reinterpret_cast(new meos::Period(serialized)); @@ -68,7 +72,60 @@ void MEOS_deletePeriod(MEOS_Period *period) { delete t; } -// TFloatSeqSet +/***************************************************************************** + * TFloatSeq + *****************************************************************************/ + +MEOS_TFloatSeq *MEOS_newTFloatSeq(char *serialized) { + return reinterpret_cast(new meos::TFloatSeq(serialized)); +} + +MEOS_TFloatSeq *MEOS_newTFloatSeq_IBBI(MEOS_TFloatInst **instants, int count, bool lower_inc, + bool upper_inc, MEOS_Interpolation interpolation) { + std::set s; + for (size_t i = 0; i < count; i++) { + auto inst = reinterpret_cast(instants[i]); + s.insert(*inst); + } + auto interp = interpolation == MEOS_Interpolation_Linear ? meos::Interpolation::Linear + : meos::Interpolation::Stepwise; + return reinterpret_cast(new meos::TFloatSeq(s, lower_inc, upper_inc, interp)); +} + +MEOS_TFloatSeq *MEOS_newTFloatSeq_IsBBI(char **instants, int count, bool lower_inc, bool upper_inc, + MEOS_Interpolation interpolation) { + std::set s; + for (size_t i = 0; i < count; i++) { + meos::TFloatInst inst(instants[i]); + s.insert(inst); + } + auto interp = interpolation == MEOS_Interpolation_Linear ? meos::Interpolation::Linear + : meos::Interpolation::Stepwise; + return reinterpret_cast(new meos::TFloatSeq(s, lower_inc, upper_inc, interp)); +} + +// Remember to free the result! +char *MEOS_TFloatSeq_str(MEOS_TFloatSeq *tfloatseq) { + auto t = reinterpret_cast(tfloatseq); + std::stringstream output; + output << *t; + auto s = output.str(); + const std::size_t len = s.length(); + char *result = new char[len + 1]; + if (result) { + std::strcpy(result, s.c_str()); + } + return result; +} + +void MEOS_deleteTFloatSeq(MEOS_TFloatSeq *tfloatseq) { + auto t = reinterpret_cast(tfloatseq); + delete t; +} + +/***************************************************************************** + * TFloatSeqSet + *****************************************************************************/ MEOS_TFloatSeqSet *MEOS_newTFloatSeqSet(char *serialized) { return reinterpret_cast(new meos::TFloatSeqSet(serialized)); From c0208daf9807d04c99901c86da471a441df26500 Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Thu, 24 Sep 2020 10:28:38 +0530 Subject: [PATCH 11/18] C API: TFloatInst --- capi/include/meos/meos_c.h | 17 +++++++++++++++-- capi/source/meos_c.cpp | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/capi/include/meos/meos_c.h b/capi/include/meos/meos_c.h index e29edb2..fab9b23 100644 --- a/capi/include/meos/meos_c.h +++ b/capi/include/meos/meos_c.h @@ -44,6 +44,19 @@ char *MEOS_Period_str(MEOS_Period *period); void MEOS_deletePeriod(MEOS_Period *period); +/***************************************************************************** + * TFloatInst + *****************************************************************************/ + +// Constructor with a string +MEOS_TFloatInst *MEOS_newTFloatInst(char *serialized); +// Constructor with a value and timestamp +MEOS_TFloatInst *MEOS_newTFloatInst_VT(float value, time_t timestamp); + +char *MEOS_TFloatInst_str(MEOS_TFloatInst *tfloatinst); + +void MEOS_deleteTFloatInst(MEOS_TFloatInst *tfloatinst); + /***************************************************************************** * TFloatSeq *****************************************************************************/ @@ -57,9 +70,9 @@ MEOS_TFloatSeq *MEOS_newTFloatSeq_IBBI(MEOS_TFloatInst **instants, int count, bo MEOS_TFloatSeq *MEOS_newTFloatSeq_IsBBI(char **instants, int count, bool lower_inc, bool upper_inc, MEOS_Interpolation interpolation); -char *MEOS_TFloatSeq_str(MEOS_TFloatSeq *tfloatseqset); +char *MEOS_TFloatSeq_str(MEOS_TFloatSeq *tfloatseq); -void MEOS_deleteTFloatSeq(MEOS_TFloatSeq *tfloatseqset); +void MEOS_deleteTFloatSeq(MEOS_TFloatSeq *tfloatseq); /***************************************************************************** * TFloatSeqSet diff --git a/capi/source/meos_c.cpp b/capi/source/meos_c.cpp index c8b3f80..6833809 100644 --- a/capi/source/meos_c.cpp +++ b/capi/source/meos_c.cpp @@ -72,6 +72,38 @@ void MEOS_deletePeriod(MEOS_Period *period) { delete t; } +/***************************************************************************** + * TFloatInst + *****************************************************************************/ + +MEOS_TFloatInst *MEOS_newTFloatInst(char *serialized) { + return reinterpret_cast(new meos::TFloatInst(serialized)); +} + +MEOS_TFloatInst *MEOS_newTFloatInst_VT(float value, time_t timestamp) { + return reinterpret_cast( + new meos::TFloatInst(value, std::chrono::system_clock::from_time_t(timestamp))); +} + +// Remember to free the result! +char *MEOS_TFloatInst_str(MEOS_TFloatInst *tfloatinst) { + auto t = reinterpret_cast(tfloatinst); + std::stringstream output; + output << *t; + auto s = output.str(); + const std::size_t len = s.length(); + char *result = new char[len + 1]; + if (result) { + std::strcpy(result, s.c_str()); + } + return result; +} + +void MEOS_deleteTFloatInst(MEOS_TFloatInst *tfloatinst) { + auto t = reinterpret_cast(tfloatinst); + delete t; +} + /***************************************************************************** * TFloatSeq *****************************************************************************/ From 782424982ac398672c0308fd8c44cb9e88a2bfa2 Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Fri, 25 Sep 2020 11:23:31 +0530 Subject: [PATCH 12/18] C API: Implement MEOS_TFloatSeqSet_sequences --- capi/include/meos/meos_c.h | 1 + capi/source/meos_c.cpp | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/capi/include/meos/meos_c.h b/capi/include/meos/meos_c.h index fab9b23..37ccde4 100644 --- a/capi/include/meos/meos_c.h +++ b/capi/include/meos/meos_c.h @@ -87,6 +87,7 @@ MEOS_TFloatSeqSet *MEOS_newTFloatSeqSet_SI(MEOS_TFloatSeq **sequences, int count MEOS_TFloatSeqSet *MEOS_newTFloatSeqSet_SsI(char **sequences, int count, MEOS_Interpolation interpolation); +MEOS_TFloatSeq **MEOS_TFloatSeqSet_sequences(MEOS_TFloatSeqSet *tfloatseqset, int *count); MEOS_TFloatSeqSet *MEOS_TFloatSeqSet_atPeriod(MEOS_TFloatSeqSet *tfloatseqset, MEOS_Period *period); char *MEOS_TFloatSeqSet_str(MEOS_TFloatSeqSet *tfloatseqset); diff --git a/capi/source/meos_c.cpp b/capi/source/meos_c.cpp index 6833809..442f8a5 100644 --- a/capi/source/meos_c.cpp +++ b/capi/source/meos_c.cpp @@ -187,6 +187,19 @@ MEOS_TFloatSeqSet *MEOS_newTFloatSeqSet_SsI(char **sequences, int count, return reinterpret_cast(new meos::TFloatSeqSet(s, interp)); } +MEOS_TFloatSeq **MEOS_TFloatSeqSet_sequences(MEOS_TFloatSeqSet *tfloatseqset, int *count) { + auto t = reinterpret_cast(tfloatseqset); + auto r = t->sequences(); + *count = r.size(); + MEOS_TFloatSeq **sequences = new MEOS_TFloatSeq *[*count]; + size_t i = 0; + for (auto const &it : r) { + auto x = new meos::TFloatSeq(it); + sequences[i++] = reinterpret_cast(x); + } + return sequences; +} + MEOS_TFloatSeqSet *MEOS_TFloatSeqSet_atPeriod(MEOS_TFloatSeqSet *tfloatseqset, MEOS_Period *period) { auto t = reinterpret_cast(tfloatseqset); From 14d03b1fd875138a08f3b8f0d697c420120fe270 Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Fri, 25 Sep 2020 11:28:33 +0530 Subject: [PATCH 13/18] C API: Implement MEOS_TFloatSeq_instants --- capi/include/meos/meos_c.h | 1 + capi/source/meos_c.cpp | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/capi/include/meos/meos_c.h b/capi/include/meos/meos_c.h index 37ccde4..a54459e 100644 --- a/capi/include/meos/meos_c.h +++ b/capi/include/meos/meos_c.h @@ -70,6 +70,7 @@ MEOS_TFloatSeq *MEOS_newTFloatSeq_IBBI(MEOS_TFloatInst **instants, int count, bo MEOS_TFloatSeq *MEOS_newTFloatSeq_IsBBI(char **instants, int count, bool lower_inc, bool upper_inc, MEOS_Interpolation interpolation); +MEOS_TFloatInst **MEOS_TFloatSeq_instants(MEOS_TFloatSeq *tfloatseq, int *count); char *MEOS_TFloatSeq_str(MEOS_TFloatSeq *tfloatseq); void MEOS_deleteTFloatSeq(MEOS_TFloatSeq *tfloatseq); diff --git a/capi/source/meos_c.cpp b/capi/source/meos_c.cpp index 442f8a5..18fb450 100644 --- a/capi/source/meos_c.cpp +++ b/capi/source/meos_c.cpp @@ -136,6 +136,19 @@ MEOS_TFloatSeq *MEOS_newTFloatSeq_IsBBI(char **instants, int count, bool lower_i return reinterpret_cast(new meos::TFloatSeq(s, lower_inc, upper_inc, interp)); } +MEOS_TFloatInst **MEOS_TFloatSeq_instants(MEOS_TFloatSeq *tfloatseq, int *count) { + auto t = reinterpret_cast(tfloatseq); + auto r = t->instants(); + *count = r.size(); + MEOS_TFloatInst **instants = new MEOS_TFloatInst *[*count]; + size_t i = 0; + for (auto const &it : r) { + auto x = new meos::TFloatInst(it); + instants[i++] = reinterpret_cast(x); + } + return instants; +} + // Remember to free the result! char *MEOS_TFloatSeq_str(MEOS_TFloatSeq *tfloatseq) { auto t = reinterpret_cast(tfloatseq); From 371601bdb904f881569713732e39e64072166dc3 Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Fri, 25 Sep 2020 11:34:15 +0530 Subject: [PATCH 14/18] C API: Implement MEOS_TFloatSeq_lower_inc and MEOS_TFloatSeq_upper_inc --- capi/include/meos/meos_c.h | 2 ++ capi/source/meos_c.cpp | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/capi/include/meos/meos_c.h b/capi/include/meos/meos_c.h index a54459e..b932922 100644 --- a/capi/include/meos/meos_c.h +++ b/capi/include/meos/meos_c.h @@ -70,6 +70,8 @@ MEOS_TFloatSeq *MEOS_newTFloatSeq_IBBI(MEOS_TFloatInst **instants, int count, bo MEOS_TFloatSeq *MEOS_newTFloatSeq_IsBBI(char **instants, int count, bool lower_inc, bool upper_inc, MEOS_Interpolation interpolation); +bool MEOS_TFloatSeq_lower_inc(MEOS_TFloatSeq *tfloatseq); +bool MEOS_TFloatSeq_upper_inc(MEOS_TFloatSeq *tfloatseq); MEOS_TFloatInst **MEOS_TFloatSeq_instants(MEOS_TFloatSeq *tfloatseq, int *count); char *MEOS_TFloatSeq_str(MEOS_TFloatSeq *tfloatseq); diff --git a/capi/source/meos_c.cpp b/capi/source/meos_c.cpp index 18fb450..b34aeb1 100644 --- a/capi/source/meos_c.cpp +++ b/capi/source/meos_c.cpp @@ -136,6 +136,16 @@ MEOS_TFloatSeq *MEOS_newTFloatSeq_IsBBI(char **instants, int count, bool lower_i return reinterpret_cast(new meos::TFloatSeq(s, lower_inc, upper_inc, interp)); } +bool MEOS_TFloatSeq_lower_inc(MEOS_TFloatSeq *tfloatseq) { + auto t = reinterpret_cast(tfloatseq); + return t->lower_inc(); +} + +bool MEOS_TFloatSeq_upper_inc(MEOS_TFloatSeq *tfloatseq) { + auto t = reinterpret_cast(tfloatseq); + return t->upper_inc(); +} + MEOS_TFloatInst **MEOS_TFloatSeq_instants(MEOS_TFloatSeq *tfloatseq, int *count) { auto t = reinterpret_cast(tfloatseq); auto r = t->instants(); From 3fbbeed122944e3bfbb72fa5e4b4056765e2388c Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Fri, 25 Sep 2020 12:15:55 +0530 Subject: [PATCH 15/18] C API: Implement MEOS_TFloatSeq_interpolation --- capi/include/meos/meos_c.h | 1 + capi/source/meos_c.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/capi/include/meos/meos_c.h b/capi/include/meos/meos_c.h index b932922..490c090 100644 --- a/capi/include/meos/meos_c.h +++ b/capi/include/meos/meos_c.h @@ -72,6 +72,7 @@ MEOS_TFloatSeq *MEOS_newTFloatSeq_IsBBI(char **instants, int count, bool lower_i bool MEOS_TFloatSeq_lower_inc(MEOS_TFloatSeq *tfloatseq); bool MEOS_TFloatSeq_upper_inc(MEOS_TFloatSeq *tfloatseq); +MEOS_Interpolation MEOS_TFloatSeq_interpolation(MEOS_TFloatSeq *tfloatseq); MEOS_TFloatInst **MEOS_TFloatSeq_instants(MEOS_TFloatSeq *tfloatseq, int *count); char *MEOS_TFloatSeq_str(MEOS_TFloatSeq *tfloatseq); diff --git a/capi/source/meos_c.cpp b/capi/source/meos_c.cpp index b34aeb1..043e78a 100644 --- a/capi/source/meos_c.cpp +++ b/capi/source/meos_c.cpp @@ -146,6 +146,12 @@ bool MEOS_TFloatSeq_upper_inc(MEOS_TFloatSeq *tfloatseq) { return t->upper_inc(); } +MEOS_Interpolation MEOS_TFloatSeq_interpolation(MEOS_TFloatSeq *tfloatseq) { + auto t = reinterpret_cast(tfloatseq); + return t->interpolation() == meos::Interpolation::Linear ? MEOS_Interpolation_Linear + : MEOS_Interpolation_Stepwise; +} + MEOS_TFloatInst **MEOS_TFloatSeq_instants(MEOS_TFloatSeq *tfloatseq, int *count) { auto t = reinterpret_cast(tfloatseq); auto r = t->instants(); From 8ddefd6378283fb62b717b5b589fac948084e377 Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Fri, 25 Sep 2020 12:58:17 +0530 Subject: [PATCH 16/18] C API: Implement MEOS_TFloatInst_value and MEOS_TFloatInst_timestamp --- capi/include/meos/meos_c.h | 2 ++ capi/source/meos_c.cpp | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/capi/include/meos/meos_c.h b/capi/include/meos/meos_c.h index 490c090..46f65ff 100644 --- a/capi/include/meos/meos_c.h +++ b/capi/include/meos/meos_c.h @@ -53,6 +53,8 @@ MEOS_TFloatInst *MEOS_newTFloatInst(char *serialized); // Constructor with a value and timestamp MEOS_TFloatInst *MEOS_newTFloatInst_VT(float value, time_t timestamp); +float MEOS_TFloatInst_value(MEOS_TFloatInst *tfloatinst); +time_t MEOS_TFloatInst_timestamp(MEOS_TFloatInst *tfloatinst); char *MEOS_TFloatInst_str(MEOS_TFloatInst *tfloatinst); void MEOS_deleteTFloatInst(MEOS_TFloatInst *tfloatinst); diff --git a/capi/source/meos_c.cpp b/capi/source/meos_c.cpp index 043e78a..950c6fd 100644 --- a/capi/source/meos_c.cpp +++ b/capi/source/meos_c.cpp @@ -85,6 +85,16 @@ MEOS_TFloatInst *MEOS_newTFloatInst_VT(float value, time_t timestamp) { new meos::TFloatInst(value, std::chrono::system_clock::from_time_t(timestamp))); } +float MEOS_TFloatInst_value(MEOS_TFloatInst *tfloatinst) { + auto t = reinterpret_cast(tfloatinst); + return t->getValue(); +} + +time_t MEOS_TFloatInst_timestamp(MEOS_TFloatInst *tfloatinst) { + auto t = reinterpret_cast(tfloatinst); + return std::chrono::system_clock::to_time_t(t->getTimestamp()); +} + // Remember to free the result! char *MEOS_TFloatInst_str(MEOS_TFloatInst *tfloatinst) { auto t = reinterpret_cast(tfloatinst); From 03a6791f678e20793173206f03e24f2c61bfa512 Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Thu, 1 Oct 2020 12:44:41 +0530 Subject: [PATCH 17/18] TSequence: Modify comaprision logic to compare intants first --- source/types/temporal/TSequence.cpp | 27 ++++++++++++------------ test/source/types/temporal/tsequence.cpp | 4 ++-- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/source/types/temporal/TSequence.cpp b/source/types/temporal/TSequence.cpp index fb3b25b..25a0576 100644 --- a/source/types/temporal/TSequence.cpp +++ b/source/types/temporal/TSequence.cpp @@ -182,30 +182,31 @@ int TSequence::compare_internal(Temporal const &other) const } TSequence const *that = dynamic_cast const *>(&other); - // Compare number of instants - if (this->m_instants.size() < that->m_instants.size()) return -1; - if (this->m_instants.size() > that->m_instants.size()) return 1; - - // Compare bounds - // [ < (, ) < ] - if ((this->m_lower_inc && !that->m_lower_inc) || (!this->m_upper_inc && that->m_upper_inc)) - return -1; - // ( > [, ] > ) - if ((that->m_lower_inc && !this->m_lower_inc) || (!that->m_upper_inc && this->m_upper_inc)) - return 1; // Compare instant by instant auto lhs_instants = this->instants(); auto rhs_instants = that->instants(); auto lhs = lhs_instants.begin(); auto rhs = rhs_instants.begin(); - while (lhs != lhs_instants.end()) { + while (lhs != lhs_instants.end() && rhs != rhs_instants.end()) { if (*lhs < *rhs) return -1; if (*lhs > *rhs) return 1; lhs++; rhs++; } + // Compare number of instants + if (this->m_instants.size() < that->m_instants.size()) return -1; + if (this->m_instants.size() > that->m_instants.size()) return 1; + + // Compare bounds + // [ < (, ) < ] + if ((this->m_lower_inc && !that->m_lower_inc) || (!this->m_upper_inc && that->m_upper_inc)) + return -1; + // ( > [, ] > ) + if ((that->m_lower_inc && !this->m_lower_inc) || (!that->m_upper_inc && this->m_upper_inc)) + return 1; + // Compare Interpolation if (this->interpolation() < that->interpolation()) return -1; if (this->interpolation() > that->interpolation()) return 1; @@ -308,7 +309,7 @@ TSequence TSequence::atPeriod(Period const &period) const { set> instants; TInstant instant = this->atTimestamp(inter.lower()); instants.insert(instant); - return TSequence(instants); + return TSequence(instants, true, true, interp); } int n = this->findTimestamp(inter.lower()); diff --git a/test/source/types/temporal/tsequence.cpp b/test/source/types/temporal/tsequence.cpp index e6d7719..e2a717e 100644 --- a/test/source/types/temporal/tsequence.cpp +++ b/test/source/types/temporal/tsequence.cpp @@ -216,8 +216,8 @@ TEMPLATE_TEST_CASE("TSequence comparision operators", "[tsequence]", int, float) SECTION("lhs < rhs") { SECTION("different sizes") { set> lhs_instants = { - TInstant(4, unix_time_point(2012, 1, 4)), - TInstant(5, unix_time_point(2012, 1, 5)), + TInstant(1, unix_time_point(2012, 1, 1)), + TInstant(2, unix_time_point(2012, 1, 2)), }; TSequence lhs(lhs_instants, true, false); set> rhs_instants = { From 8e7f62b9a9b2b9b3a85bf620d081391a37acde1f Mon Sep 17 00:00:00 2001 From: B Krishna Chaitanya Date: Wed, 7 Oct 2020 16:03:29 +0530 Subject: [PATCH 18/18] C API: Optimize through the usage of range constructor --- capi/source/meos_c.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/capi/source/meos_c.cpp b/capi/source/meos_c.cpp index 950c6fd..a3a4fe3 100644 --- a/capi/source/meos_c.cpp +++ b/capi/source/meos_c.cpp @@ -124,11 +124,11 @@ MEOS_TFloatSeq *MEOS_newTFloatSeq(char *serialized) { MEOS_TFloatSeq *MEOS_newTFloatSeq_IBBI(MEOS_TFloatInst **instants, int count, bool lower_inc, bool upper_inc, MEOS_Interpolation interpolation) { - std::set s; + meos::TFloatInst *insts = new meos::TFloatInst[count]; for (size_t i = 0; i < count; i++) { - auto inst = reinterpret_cast(instants[i]); - s.insert(*inst); + insts[i] = *reinterpret_cast(instants[i]); } + std::set s(insts, insts + count); auto interp = interpolation == MEOS_Interpolation_Linear ? meos::Interpolation::Linear : meos::Interpolation::Stepwise; return reinterpret_cast(new meos::TFloatSeq(s, lower_inc, upper_inc, interp)); @@ -204,11 +204,11 @@ MEOS_TFloatSeqSet *MEOS_newTFloatSeqSet(char *serialized) { MEOS_TFloatSeqSet *MEOS_newTFloatSeqSet_SI(MEOS_TFloatSeq **sequences, int count, MEOS_Interpolation interpolation) { - std::set s; + meos::TFloatSeq *seqs = new meos::TFloatSeq[count]; for (size_t i = 0; i < count; i++) { - auto seq = reinterpret_cast(sequences[i]); - s.insert(*seq); + seqs[i] = *reinterpret_cast(sequences[i]); } + std::set s(seqs, seqs + count); auto interp = interpolation == MEOS_Interpolation_Linear ? meos::Interpolation::Linear : meos::Interpolation::Stepwise; return reinterpret_cast(new meos::TFloatSeqSet(s, interp));