From 99c80e01b193c045c55b6a607f483285896e0c06 Mon Sep 17 00:00:00 2001 From: Tamas Gal <himself@tamasgal.com> Date: Wed, 31 Mar 2021 12:37:27 +0200 Subject: [PATCH] Add fallback sources from Jpp --- jpp/JIO/JBufferedIO.hh | 231 +++ jpp/JIO/JFileStreamIO.hh | 129 ++ jpp/JIO/JObjectBinaryIO.hh | 47 + jpp/JIO/JSerialisable.hh | 193 +++ jpp/JIO/JStreamIO.hh | 125 ++ jpp/JLang/JAbstractObjectStatus.hh | 51 + jpp/JLang/JAbstractPointer.hh | 133 ++ jpp/JLang/JAssert.hh | 31 + jpp/JLang/JBinaryIO.hh | 61 + jpp/JLang/JBool.hh | 348 ++++ jpp/JLang/JCC.hh | 17 + jpp/JLang/JClass.hh | 220 +++ jpp/JLang/JClonable.hh | 77 + jpp/JLang/JComparable.hh | 311 ++++ jpp/JLang/JEquals.hh | 142 ++ jpp/JLang/JException.hh | 673 ++++++++ jpp/JLang/JForwardIterator.hh | 116 ++ jpp/JLang/JLangToolkit.hh | 333 ++++ jpp/JLang/JManip.hh | 716 +++++++++ jpp/JLang/JMemory.hh | 120 ++ jpp/JLang/JNullType.hh | 22 + jpp/JLang/JObjectID.hh | 157 ++ jpp/JLang/JObjectIO.hh | 141 ++ jpp/JLang/JPointer.hh | 140 ++ jpp/JLang/JSTDTypes.hh | 29 + jpp/JLang/JSharedCounter.hh | 98 ++ jpp/JLang/JSharedPointer.hh | 211 +++ jpp/JLang/JSinglePointer.hh | 113 ++ jpp/JLang/JStorage.hh | 98 ++ jpp/JLang/JType.hh | 37 + jpp/JLang/JVectorize.hh | 193 +++ jpp/JLang/JVoid.hh | 26 + jpp/JLang/gzstream.h | 229 +++ jpp/JMath/JCalculator.hh | 93 ++ jpp/JMath/JConstants.hh | 31 + jpp/JMath/JLimits.hh | 126 ++ jpp/JMath/JMath.hh | 591 +++++++ jpp/JMath/JMathSupportkit.hh | 231 +++ jpp/JMath/JZero.hh | 108 ++ jpp/JPhysics/JConstants.hh | 188 +++ jpp/JPhysics/JGeant_t.hh | 140 ++ jpp/JPhysics/JGeanz.hh | 194 +++ jpp/JPhysics/JNPETable.hh | 216 +++ jpp/JPhysics/JNPE_t.hh | 288 ++++ jpp/JPhysics/JPDFTable.hh | 308 ++++ jpp/JPhysics/JPDFToolkit.hh | 322 ++++ jpp/JPhysics/JPDFTransformer.hh | 1289 +++++++++++++++ jpp/JPhysics/JPDFTypes.hh | 201 +++ jpp/JPhysics/JPDF_t.hh | 383 +++++ jpp/JTools/JAbstractCollection.hh | 88 ++ jpp/JTools/JAbstractMultiMap.hh | 62 + jpp/JTools/JArray.hh | 1265 +++++++++++++++ jpp/JTools/JAssembler.hh | 40 + jpp/JTools/JCollection.hh | 836 ++++++++++ jpp/JTools/JConstantFunction1D.hh | 206 +++ jpp/JTools/JConstants.hh | 22 + jpp/JTools/JDistance.hh | 55 + jpp/JTools/JElement.hh | 611 +++++++ jpp/JTools/JFunction1D_t.hh | 380 +++++ jpp/JTools/JFunctional.hh | 394 +++++ jpp/JTools/JFunctionalMap.hh | 220 +++ jpp/JTools/JFunctionalMap_t.hh | 204 +++ jpp/JTools/JGarbageCollection.hh | 68 + jpp/JTools/JGrid.hh | 185 +++ jpp/JTools/JGridCollection.hh | 111 ++ jpp/JTools/JGridMap.hh | 70 + jpp/JTools/JHermiteSpline.hh | 706 +++++++++ jpp/JTools/JHistogram.hh | 234 +++ jpp/JTools/JHistogramMap.hh | 144 ++ jpp/JTools/JMap.hh | 126 ++ jpp/JTools/JMapCollection.hh | 23 + jpp/JTools/JMapList.hh | 149 ++ jpp/JTools/JMappableCollection.hh | 118 ++ jpp/JTools/JMultiFunction.hh | 354 +++++ jpp/JTools/JMultiHistogram.hh | 135 ++ jpp/JTools/JMultiKey.hh | 537 +++++++ jpp/JTools/JMultiMap.hh | 1669 ++++++++++++++++++++ jpp/JTools/JMultiMapTransformer.hh | 341 ++++ jpp/JTools/JMultiPair.hh | 328 ++++ jpp/JTools/JPair.hh | 234 +++ jpp/JTools/JPolint.hh | 1215 ++++++++++++++ jpp/JTools/JQuadrature.hh | 546 +++++++ jpp/JTools/JQuantiles.hh | 360 +++++ jpp/JTools/JRange.hh | 718 +++++++++ jpp/JTools/JResult.hh | 1043 ++++++++++++ jpp/JTools/JResultTransformer.hh | 87 + jpp/JTools/JSet.hh | 163 ++ jpp/JTools/JSpline.hh | 865 ++++++++++ jpp/JTools/JToolsToolkit.hh | 352 +++++ jpp/JTools/JTransformableMultiFunction.hh | 294 ++++ jpp/JTools/JTransformableMultiHistogram.hh | 176 +++ jpp/JTools/JTransformer.hh | 36 + jpp/Jeep/JeepToolkit.hh | 371 +++++ jpp/README.md | 4 + 94 files changed, 26422 insertions(+) create mode 100644 jpp/JIO/JBufferedIO.hh create mode 100644 jpp/JIO/JFileStreamIO.hh create mode 100644 jpp/JIO/JObjectBinaryIO.hh create mode 100644 jpp/JIO/JSerialisable.hh create mode 100644 jpp/JIO/JStreamIO.hh create mode 100644 jpp/JLang/JAbstractObjectStatus.hh create mode 100644 jpp/JLang/JAbstractPointer.hh create mode 100644 jpp/JLang/JAssert.hh create mode 100644 jpp/JLang/JBinaryIO.hh create mode 100644 jpp/JLang/JBool.hh create mode 100644 jpp/JLang/JCC.hh create mode 100644 jpp/JLang/JClass.hh create mode 100644 jpp/JLang/JClonable.hh create mode 100644 jpp/JLang/JComparable.hh create mode 100644 jpp/JLang/JEquals.hh create mode 100644 jpp/JLang/JException.hh create mode 100644 jpp/JLang/JForwardIterator.hh create mode 100644 jpp/JLang/JLangToolkit.hh create mode 100644 jpp/JLang/JManip.hh create mode 100644 jpp/JLang/JMemory.hh create mode 100644 jpp/JLang/JNullType.hh create mode 100644 jpp/JLang/JObjectID.hh create mode 100644 jpp/JLang/JObjectIO.hh create mode 100644 jpp/JLang/JPointer.hh create mode 100644 jpp/JLang/JSTDTypes.hh create mode 100644 jpp/JLang/JSharedCounter.hh create mode 100644 jpp/JLang/JSharedPointer.hh create mode 100644 jpp/JLang/JSinglePointer.hh create mode 100644 jpp/JLang/JStorage.hh create mode 100644 jpp/JLang/JType.hh create mode 100644 jpp/JLang/JVectorize.hh create mode 100644 jpp/JLang/JVoid.hh create mode 100644 jpp/JLang/gzstream.h create mode 100644 jpp/JMath/JCalculator.hh create mode 100644 jpp/JMath/JConstants.hh create mode 100644 jpp/JMath/JLimits.hh create mode 100644 jpp/JMath/JMath.hh create mode 100644 jpp/JMath/JMathSupportkit.hh create mode 100644 jpp/JMath/JZero.hh create mode 100644 jpp/JPhysics/JConstants.hh create mode 100644 jpp/JPhysics/JGeant_t.hh create mode 100644 jpp/JPhysics/JGeanz.hh create mode 100644 jpp/JPhysics/JNPETable.hh create mode 100644 jpp/JPhysics/JNPE_t.hh create mode 100644 jpp/JPhysics/JPDFTable.hh create mode 100644 jpp/JPhysics/JPDFToolkit.hh create mode 100644 jpp/JPhysics/JPDFTransformer.hh create mode 100644 jpp/JPhysics/JPDFTypes.hh create mode 100644 jpp/JPhysics/JPDF_t.hh create mode 100644 jpp/JTools/JAbstractCollection.hh create mode 100644 jpp/JTools/JAbstractMultiMap.hh create mode 100644 jpp/JTools/JArray.hh create mode 100644 jpp/JTools/JAssembler.hh create mode 100644 jpp/JTools/JCollection.hh create mode 100644 jpp/JTools/JConstantFunction1D.hh create mode 100644 jpp/JTools/JConstants.hh create mode 100644 jpp/JTools/JDistance.hh create mode 100644 jpp/JTools/JElement.hh create mode 100644 jpp/JTools/JFunction1D_t.hh create mode 100644 jpp/JTools/JFunctional.hh create mode 100644 jpp/JTools/JFunctionalMap.hh create mode 100644 jpp/JTools/JFunctionalMap_t.hh create mode 100644 jpp/JTools/JGarbageCollection.hh create mode 100644 jpp/JTools/JGrid.hh create mode 100644 jpp/JTools/JGridCollection.hh create mode 100644 jpp/JTools/JGridMap.hh create mode 100644 jpp/JTools/JHermiteSpline.hh create mode 100644 jpp/JTools/JHistogram.hh create mode 100644 jpp/JTools/JHistogramMap.hh create mode 100644 jpp/JTools/JMap.hh create mode 100644 jpp/JTools/JMapCollection.hh create mode 100644 jpp/JTools/JMapList.hh create mode 100644 jpp/JTools/JMappableCollection.hh create mode 100644 jpp/JTools/JMultiFunction.hh create mode 100644 jpp/JTools/JMultiHistogram.hh create mode 100644 jpp/JTools/JMultiKey.hh create mode 100644 jpp/JTools/JMultiMap.hh create mode 100644 jpp/JTools/JMultiMapTransformer.hh create mode 100644 jpp/JTools/JMultiPair.hh create mode 100644 jpp/JTools/JPair.hh create mode 100644 jpp/JTools/JPolint.hh create mode 100644 jpp/JTools/JQuadrature.hh create mode 100644 jpp/JTools/JQuantiles.hh create mode 100644 jpp/JTools/JRange.hh create mode 100644 jpp/JTools/JResult.hh create mode 100644 jpp/JTools/JResultTransformer.hh create mode 100644 jpp/JTools/JSet.hh create mode 100644 jpp/JTools/JSpline.hh create mode 100644 jpp/JTools/JToolsToolkit.hh create mode 100644 jpp/JTools/JTransformableMultiFunction.hh create mode 100644 jpp/JTools/JTransformableMultiHistogram.hh create mode 100644 jpp/JTools/JTransformer.hh create mode 100644 jpp/Jeep/JeepToolkit.hh create mode 100644 jpp/README.md diff --git a/jpp/JIO/JBufferedIO.hh b/jpp/JIO/JBufferedIO.hh new file mode 100644 index 0000000..864c003 --- /dev/null +++ b/jpp/JIO/JBufferedIO.hh @@ -0,0 +1,231 @@ +#ifndef __JIO__JBUFFEREDIO__ +#define __JIO__JBUFFEREDIO__ + +#include <algorithm> +#include <cstring> + +#include "JLang/JSinglePointer.hh" +#include "JIO/JSerialisable.hh" + + +/** + * \author mdejong + */ + +namespace JIO {} +namespace JPP { using namespace JIO; } + +namespace JIO { + + + /** + * Buffered binary input. + * This class implements the JReader interface. + */ + class JBufferedReader : + public JReader + { + public: + /** + * Constructor. + * Note that this object owns the reader pointed to. + * + * \param __in pointer to reader + * \param __size size of internal buffer + */ + JBufferedReader(JReader* __in, const int __size = 1048576) : + in(__in) + { + size = std::max(__size, 1024); + buffer = new char[size]; + + pos = 0; + ls = 0; + eof = true; + } + + + /** + * Destructor. + */ + ~JBufferedReader() + { + delete [] buffer; + } + + + /** + * Status of reader. + * + * \return status of this reader + */ + virtual bool getStatus() const override + { + return in->getStatus() || !eof; + } + + + /** + * Clear status of reader. + */ + virtual void clear() override + { + in->clear(); + } + + + /** + * Read byte array. + * + * \param zbuf pointer to byte array + * \param n number of bytes + * \return number of bytes + */ + virtual int read(char* zbuf, int n) override + { + for (int i = 0; i != n; ) { + + int m = n - i; + + if (m > ls - pos) { + + memmove(buffer, buffer + pos, ls - pos); + + ls -= pos; + pos = 0; + ls += in->read(buffer + ls, size - ls); + + if (m > ls) { + + if (ls == 0) { + + eof = true; + + return n - i; + } + + m = ls; + } + } + + memcpy(zbuf + i, buffer + pos, m); + + i += m; + pos += m; + } + + eof = false; + + return n; + } + + + protected: + JLANG::JSinglePointer<JReader> in; + + char* buffer; //!< internal buffer + int size; //!< size of internal buffer + int pos; //!< pointer to begin of available data + int ls; //!< pointer to end of available data + bool eof; //!< end of file + }; + + + /** + * Buffered binary output. + * This class implements the JWriter interface. + */ + class JBufferedWriter : + public JWriter + { + public: + /** + * Constructor. + * Note that this object owns the writer pointed to. + * + * \param __out pointer to writer + * \param __size size of internal buffer + */ + JBufferedWriter(JWriter* __out, const int __size = 1048576) : + out(__out) + { + size = std::max(__size, 1024); + buffer = new char[size]; + + pos = 0; + } + + + /** + * Destructor. + */ + ~JBufferedWriter() + { + flush(); + + delete [] buffer; + } + + + /** + * Status of writer. + * + * \return status of this writer + */ + virtual bool getStatus() const override + { + return (bool) *out; + } + + + /** + * Write byte array. + * + * \param zbuf pointer to byte array + * \param n number of bytes + * \return number of bytes + */ + virtual int write(const char* zbuf, int n) override + { + for (int i = 0; i != n; ) { + + int m = n - i; + + if (m > size - pos) { + + flush(); + + if (m > size - pos) { + m = size - pos; + } + } + + memcpy(buffer + pos, zbuf + i, m); + + i += m; + pos += m; + } + + return n; + } + + + /** + * Write internal data to output. + */ + void flush() + { + pos -= out->write(buffer, pos); + } + + + protected: + JLANG::JSinglePointer<JWriter> out; + + char* buffer; //!< internal buffer + int size; //!< size of internal buffer + int pos; //!< pointer to end of buffered data + }; +} + +#endif diff --git a/jpp/JIO/JFileStreamIO.hh b/jpp/JIO/JFileStreamIO.hh new file mode 100644 index 0000000..f6640de --- /dev/null +++ b/jpp/JIO/JFileStreamIO.hh @@ -0,0 +1,129 @@ +#ifndef __JIO__JFILESTREAMIO__ +#define __JIO__JFILESTREAMIO__ + +#include <fstream> + +#include "JIO/JStreamIO.hh" +#include "JIO/JBufferedIO.hh" + + +/** + * \author mdejong + */ + +namespace JIO {} +namespace JPP { using namespace JIO; } + +namespace JIO { + + /** + * Binary buffered file input. + */ + class JFileStreamReader : + public std::ifstream, + public JBufferedReader + { + public: + + using JAbstractObjectStatus::operator bool; + using JAbstractObjectStatus::operator!; + using JReader::operator>>; + + + /** + * Default constructor. + */ + JFileStreamReader() : + std::ifstream(), + JBufferedReader(new JStreamReader(static_cast<std::ifstream&>(*this))) + {} + + + /** + * Constructor. + * + * \param file_name file name + * \param size size of internal buffer + */ + JFileStreamReader(const char* file_name, + const int size = 1048576) : + std::ifstream (), + JBufferedReader(new JStreamReader(static_cast<std::ifstream&>(*this)), size) + { + open(file_name); + } + + + /** + * Open file. + * + * \param file_name file name + */ + void open(const char* file_name) + { + static_cast<std::ifstream*>(this)->open(file_name, std::ios::binary); + } + }; + + + /** + * Binary buffered file output. + */ + class JFileStreamWriter : + public std::ofstream, + public JBufferedWriter + { + public: + + using JAbstractObjectStatus::operator bool; + using JAbstractObjectStatus::operator!; + using JWriter::operator<<; + + + /** + * Default constructor. + */ + JFileStreamWriter() : + std::ofstream(), + JBufferedWriter(new JStreamWriter(static_cast<std::ofstream&>(*this))) + {} + + + /** + * Constructor. + * + * \param file_name file name + * \param size size of internal buffer + */ + JFileStreamWriter(const char* file_name, + const int size = 1048576) : + std::ofstream(), + JBufferedWriter(new JStreamWriter(static_cast<std::ofstream&>(*this)), size) + { + open(file_name); + } + + + /** + * Open file. + * + * \param file_name file name + */ + void open(const char* file_name) + { + static_cast<std::ofstream*>(this)->open(file_name, std::ios::binary); + } + + + /** + * Close file. + */ + void close() + { + static_cast<JBufferedWriter*>(this)->flush(); + static_cast<std::ofstream*> (this)->close(); + } + }; +} + +#endif diff --git a/jpp/JIO/JObjectBinaryIO.hh b/jpp/JIO/JObjectBinaryIO.hh new file mode 100644 index 0000000..619492b --- /dev/null +++ b/jpp/JIO/JObjectBinaryIO.hh @@ -0,0 +1,47 @@ +#ifndef __JIO__JOBJECTBINARYIO__ +#define __JIO__JOBJECTBINARYIO__ + +#include "JLang/JObjectIO.hh" +#include "JIO/JFileStreamIO.hh" + + +/** + * \author mdejong + */ + +namespace JIO {} +namespace JPP { using namespace JIO; } + +namespace JIO { + + /** + * Auxiliary base class for storing and loading a single object to and from a binary file, respectively. + * The implementation of this functionality is based on a static cast of + * the given template parameter (known as "curiously recurring template pattern"). + */ + template<class T> + struct JObjectBinaryIO { + /** + * Load from input file. + * + * \param file_name file name + */ + void load(const char* file_name) + { + JLANG::load<JFileStreamReader>(file_name, static_cast<T&>(*this)); + } + + + /** + * Store to output file. + * + * \param file_name file name + */ + void store(const char* file_name) const + { + JLANG::store<JFileStreamWriter>(file_name, static_cast<const T&>(*this)); + } + }; +} + +#endif diff --git a/jpp/JIO/JSerialisable.hh b/jpp/JIO/JSerialisable.hh new file mode 100644 index 0000000..e72fa05 --- /dev/null +++ b/jpp/JIO/JSerialisable.hh @@ -0,0 +1,193 @@ +#ifndef __JIO__JSERIALISABLE__ +#define __JIO__JSERIALISABLE__ + +#include "JLang/JBinaryIO.hh" +#include "JLang/JObjectID.hh" +#include "JLang/JAbstractObjectStatus.hh" + + +/** + * \author mdejong + */ + +/** + * Auxiliary classes and methods for binary I/O. + */ +namespace JIO {} +namespace JPP { using namespace JIO; } + +namespace JIO { + + using JLANG::JBinaryInput; + using JLANG::JBinaryOutput; + using JLANG::JAbstractObjectStatus; + + class JReader; //!< Forward declaration of binary input. + class JWriter; //!< Forward declaration of binary output. + + + /** + * Interface class for a data structure with binary I/O. + */ + class JSerialisable { + public: + /** + * Virtual destructor. + */ + virtual ~JSerialisable() + {} + + + /** + * Read from input. + * + * \param in JReader + * \return JReader + */ + virtual JReader& read(JReader& in) = 0; + + + /** + * Write to output. + * + * \param out JWriter + * \return JWriter + */ + virtual JWriter& write(JWriter& out) const = 0; + }; + + + /** + * Interface for binary input. + */ + class JReader : + public JLANG::JBinaryInput, + public JLANG::JAbstractObjectStatus + { + public: + /** + * Clear status of reader. + */ + virtual void clear() + {} + + + /** + * Read serialisable data object. + * + * \param object serialisable data object + * \return JReader + */ + JReader& operator>>(JSerialisable& object) + { + return object.read(*this); + } + + + JReader& operator>>(bool& value) { read((char*) &value, sizeof(bool)); return *this; } + JReader& operator>>(char& value) { read((char*) &value, sizeof(char)); return *this; } + JReader& operator>>(unsigned char& value) { read((char*) &value, sizeof(unsigned char)); return *this; } + JReader& operator>>(short& value) { read((char*) &value, sizeof(short)); return *this; } + JReader& operator>>(unsigned short& value) { read((char*) &value, sizeof(unsigned short)); return *this; } + JReader& operator>>(int& value) { read((char*) &value, sizeof(int)); return *this; } + JReader& operator>>(unsigned int& value) { read((char*) &value, sizeof(unsigned int)); return *this; } + JReader& operator>>(long int& value) { read((char*) &value, sizeof(long int)); return *this; } + JReader& operator>>(unsigned long int& value) { read((char*) &value, sizeof(unsigned long int)); return *this; } + JReader& operator>>(long long int& value) { read((char*) &value, sizeof(long long int)); return *this; } + JReader& operator>>(unsigned long long int& value) { read((char*) &value, sizeof(unsigned long long int)); return *this; } + JReader& operator>>(float& value) { read((char*) &value, sizeof(float)); return *this; } + JReader& operator>>(double& value) { read((char*) &value, sizeof(double)); return *this; } + JReader& operator>>(long double& value) { read((char*) &value, sizeof(long double)); return *this; } + JReader& operator>>(JLANG::JObjectID& value) { return (*this) >> value.getID(); } + + + /** + * Read object. + * + * \param object object + * \return this reader + */ + inline JReader& load(JSerialisable& object) + { + return object.read(*this); + } + + + /** + * Read object. + * + * \param object object + * \return this reader + */ + template<class T> + inline JReader& load(T& object) + { + return *this >> object; + } + }; + + + /** + * Interface for binary output. + */ + class JWriter : + public JLANG::JBinaryOutput, + public JLANG::JAbstractObjectStatus + { + public: + /** + * Write serialisable data object. + * + * \param object serialisable data object + * \return JWriter + */ + JWriter& operator<<(const JSerialisable& object) + { + return object.write(*this); + } + + + JWriter& operator<<(const bool& value) { write((const char*) &value, sizeof(bool)); return *this; } + JWriter& operator<<(const char& value) { write((const char*) &value, sizeof(char)); return *this; } + JWriter& operator<<(const unsigned char& value) { write((const char*) &value, sizeof(unsigned char)); return *this; } + JWriter& operator<<(const short& value) { write((const char*) &value, sizeof(short)); return *this; } + JWriter& operator<<(const unsigned short& value) { write((const char*) &value, sizeof(unsigned short)); return *this; } + JWriter& operator<<(const int& value) { write((const char*) &value, sizeof(int)); return *this; } + JWriter& operator<<(const unsigned int& value) { write((const char*) &value, sizeof(unsigned int)); return *this; } + JWriter& operator<<(const long int& value) { write((const char*) &value, sizeof(long int)); return *this; } + JWriter& operator<<(const unsigned long int& value) { write((const char*) &value, sizeof(unsigned long int)); return *this; } + JWriter& operator<<(const long long int& value) { write((const char*) &value, sizeof(long long int)); return *this; } + JWriter& operator<<(const unsigned long long int& value) { write((const char*) &value, sizeof(unsigned long long int)); return *this; } + JWriter& operator<<(const float& value) { write((const char*) &value, sizeof(float)); return *this; } + JWriter& operator<<(const double& value) { write((const char*) &value, sizeof(double)); return *this; } + JWriter& operator<<(const long double& value) { write((const char*) &value, sizeof(long double)); return *this; } + JWriter& operator<<(const JLANG::JObjectID& value) { return (*this) << value.getID(); } + + + /** + * Write object. + * + * \param object object + * \return this writer + */ + inline JWriter& store(const JSerialisable& object) + { + return object.write(*this); + } + + + /** + * Write object. + * + * \param object object + * \return this writer + */ + template<class T> + inline JWriter& store(const T& object) + { + return *this << object; + } + }; +} + +#endif diff --git a/jpp/JIO/JStreamIO.hh b/jpp/JIO/JStreamIO.hh new file mode 100644 index 0000000..afc7775 --- /dev/null +++ b/jpp/JIO/JStreamIO.hh @@ -0,0 +1,125 @@ +#ifndef __JIO__JSTREAMIO__ +#define __JIO__JSTREAMIO__ + +#include <istream> +#include <ostream> + +#include "JIO/JSerialisable.hh" + + +/** + * \author mdejong + */ + +namespace JIO {} +namespace JPP { using namespace JIO; } + +namespace JIO { + + + /** + * Binary input based on std::istream. + * This class implements the JReader interface. + */ + class JStreamReader : + public JReader + { + public: + /** + * Constructor. + * + * \param __in input stream + */ + JStreamReader(std::istream& __in) : + in(__in) + {} + + + /** + * Status of reader. + * + * \return status of this reader + */ + virtual bool getStatus() const override + { + return (bool) in; + } + + + /** + * Clear status of reader. + */ + virtual void clear() override + { + in.clear(); + } + + + /** + * Read byte array. + * + * \param buffer pointer to byte array + * \param length number of bytes + * \return number of bytes read + */ + virtual int read(char* buffer, const int length) override + { + in.read(buffer, length); + + return in.gcount(); + } + + protected: + std::istream& in; + }; + + + /** + * Binary output based on std::ostream. + * This class implements the JWriter interface. + */ + class JStreamWriter : + public JWriter + { + public: + /** + * Constructor. + * + * \param __out output stream + */ + JStreamWriter(std::ostream& __out) : + out(__out) + {} + + + /** + * Status of writer. + * + * \return status of this writer + */ + virtual bool getStatus() const override + { + return (bool) out; + } + + + /** + * Write byte array. + * + * \param buffer pointer to byte array + * \param length number of bytes + * \return number of bytes written + */ + virtual int write(const char* buffer, const int length) override + { + out.write(buffer, length); + + return length; + } + + protected: + std::ostream& out; + }; +} + +#endif diff --git a/jpp/JLang/JAbstractObjectStatus.hh b/jpp/JLang/JAbstractObjectStatus.hh new file mode 100644 index 0000000..bc683ec --- /dev/null +++ b/jpp/JLang/JAbstractObjectStatus.hh @@ -0,0 +1,51 @@ +#ifndef __JLANG__JABSTRACTOBJECTSTATUS__ +#define __JLANG__JABSTRACTOBJECTSTATUS__ + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + /** + * Interface for status of object.\n + * This interface implements: + * - type conversion operator <tt>bool ()</tt>; and + * - negate operator <tt>!</tt>. + */ + struct JAbstractObjectStatus { + /** + * Get status of object. + * + * \return status of this object + */ + virtual bool getStatus() const = 0; + + + /** + * Type conversion operator. + * + * \return status of this object + */ + operator bool() const + { + return this->getStatus(); + } + + + /** + * Negated status of this object. + * + * \return negated status of this object + */ + bool operator!() const + { + return !(this->getStatus()); + } + }; +} + +#endif diff --git a/jpp/JLang/JAbstractPointer.hh b/jpp/JLang/JAbstractPointer.hh new file mode 100644 index 0000000..5fcda7b --- /dev/null +++ b/jpp/JLang/JAbstractPointer.hh @@ -0,0 +1,133 @@ +#ifndef __JLANG__JABSTRACTPOINTER__ +#define __JLANG__JABSTRACTPOINTER__ + +#include <cstdlib> + +#include "JLang/JException.hh" +#include "JLang/JEquals.hh" + + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + + /** + * Template interface for pointer to object(s). + */ + template<class JClass_t> + class JAbstractPointer : + public JEquals< JAbstractPointer<JClass_t> > + { + protected: + /** + * Default constructor. + */ + JAbstractPointer() + {} + + + public: + /** + * Virtual destructor. + */ + virtual ~JAbstractPointer() + {} + + + /** + * Equals. + * The equality is evaluated by comparison of the internal pointers. + * + * \param object abstract pointer + * \return true if equals; else false + */ + virtual bool equals(const JAbstractPointer& object) const + { + return this->get() == object.get(); + } + + + /** + * Get pointer. + * + * \return pointer to object + */ + virtual JClass_t* get() const = 0; + + + /** + * Set pointer. + * + * \param p pointer to object + */ + virtual void set(JClass_t* p) = 0; + + + /** + * Reset pointer. + */ + virtual void reset() = 0; + + + /** + * Check validity of pointer. + * + * \return true if pointer not null; else false + */ + bool is_valid() const + { + return this->get() != NULL; + } + + + /** + * Reset pointer. + * + * \param p pointer to object + */ + void reset(JClass_t* p) + { + if (this->get() != p) { + + this->reset(); + + if (p != NULL) { + this->set(p); + } + } + } + + + /** + * Smart pointer operator. + * + * \return pointer to object + */ + JClass_t* operator->() const + { + if (!is_valid()) + throw JNullPointerException("JAbstractPointer::operator->()"); + else + return this->get(); + } + + + /** + * Type conversion operator. + * + * \return pointer to object + */ + operator JClass_t*() const + { + return this->get(); + } + }; +} + +#endif diff --git a/jpp/JLang/JAssert.hh b/jpp/JLang/JAssert.hh new file mode 100644 index 0000000..78e69fd --- /dev/null +++ b/jpp/JLang/JAssert.hh @@ -0,0 +1,31 @@ +#ifndef __JLANG__JASSERT__ +#define __JLANG__JASSERT__ + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + /** + * Generation of compiler error. + */ + template<bool> + struct JAssert; + + /** + * Implementation of valid assertion. + */ + template<> + struct JAssert<true> + { + static const bool value = true; + }; +} + +#define STATIC_CHECK(expr) { JLANG::JAssert<expr>(); } + +#endif diff --git a/jpp/JLang/JBinaryIO.hh b/jpp/JLang/JBinaryIO.hh new file mode 100644 index 0000000..ab678dc --- /dev/null +++ b/jpp/JLang/JBinaryIO.hh @@ -0,0 +1,61 @@ +#ifndef __JLANG__JBINARYIO__ +#define __JLANG__JBINARYIO__ + + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + + /** + * Interface for binary input. + */ + class JBinaryInput { + public: + /** + * Virtual destructor. + */ + virtual ~JBinaryInput() + {} + + + /** + * Read byte array. + * + * \param buffer pointer to byte array + * \param length number of bytes + * \return number of bytes read + */ + virtual int read(char* buffer, const int length) = 0; + }; + + + /** + * Interface for binary output. + */ + class JBinaryOutput { + public: + /** + * Virtual destructor. + */ + virtual ~JBinaryOutput() + {} + + + /** + * Write byte array. + * + * \param buffer pointer to byte array + * \param length number of bytes + * \return number of bytes written + */ + virtual int write(const char* buffer, const int length) = 0; + }; +} + +#endif diff --git a/jpp/JLang/JBool.hh b/jpp/JLang/JBool.hh new file mode 100644 index 0000000..d50ed8a --- /dev/null +++ b/jpp/JLang/JBool.hh @@ -0,0 +1,348 @@ +#ifndef __JLANG__JBOOL__ +#define __JLANG__JBOOL__ + + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + + /** + * Auxiliary template class for type bool. + * This class can be used for boolean expressions at compile time. + */ + template<bool __value__> + struct JBool + { + /** + * Type definition of bool value. + */ + typedef JBool<__value__> bool_type; + + + /** + * Default construcor. + */ + JBool() + {} + + + /** + * Value. + */ + static const bool value = __value__; + + + /** + * Type conversion operator. + * + * \return value + */ + operator bool() const + { + return value; + } + + + /** + * Make logical NOT. + * + * \return logical NOT + */ + static JBool<!value> c_not() + { + return JBool<!value>(); + } + + + /** + * Make logical EQUALS. + * + * \return logical EQUALS + */ + template<bool option> + static JBool<value == option> c_equals() + { + return JBool<value == option>(); + } + + + /** + * Make logical EQUALS. + * + * \param object value + * \return logical EQUALS + */ + template<bool option> + static JBool<value == option> c_equals(const JBool<option>& object) + { + return bool_type::c_equals<option>(); + } + + + /** + * Make logical AND. + * + * \return logical AND + */ + template<bool option> + static JBool<value && option> c_and() + { + return JBool<value && option>(); + } + + + /** + * Make logical AND. + * + * \param object value + * \return logical AND + */ + template<bool option> + static JBool<value && option> c_and(const JBool<option>& object) + { + return bool_type::c_and<option>(); + } + + + /** + * Make logical OR. + * + * \return logical OR + */ + template<bool option> + static JBool<value || option> c_or() + { + return JBool<value || option>(); + } + + + /** + * Make logical OR. + * + * \param object value + * \return logical OR + */ + template<bool option> + static JBool<value || option> c_or(const JBool<option>& object) + { + return bool_type::c_or<option>(); + } + + + /** + * Make logical XOR. + * + * \return logical XOR + */ + template<bool option> + static JBool<value != option> c_xor() + { + return JBool<value != option>(); + } + + + /** + * Make logical XOR. + * + * \param object value + * \return logical XOR + */ + template<bool option> + static JBool<value != option> c_xor(const JBool<option>& object) + { + return bool_type::c_xor<option>(); + } + + + /** + * Make logical SWITCH. + * If value is true, select first, else select second. + * + * \return logical SWITCH + */ + template<bool __first__, bool __second__> + static JBool<(value && __first__) || (!value && __second__)> c_switch() + { + return JBool<(value && __first__) || (!value && __second__)>(); + } + + + /** + * Make logical SWITCH. + * If value is true, select first, else select second. + * + * \param first first value + * \param second second value + * \return logical SWITCH + */ + template<bool __first__, bool __second__> + static JBool<(value && __first__) || (!value && __second__)> c_switch(const JBool<__first__>& first, + const JBool<__second__>& second) + { + return bool_type::c_switch<__first__, __second__>(); + } + }; + + + /** + * Make logical NOT. + * + * \param value value + * \return logical NOT + */ + template<bool __value__> + static JBool<!__value__> c_not(const JBool<__value__>& value) + { + return value.c_not(); + } + + + /** + * Make logical EQUALS. + * + * \param first first value + * \param second second value + * \return logical EQUALS + */ + template<bool __first__, bool __second__> + inline JBool<__first__ == __second__> c_equals(const JBool<__first__>& first, + const JBool<__second__>& second) + { + return first.c_equals(second); + } + + + /** + * Make logical AND. + * + * \param first first value + * \param second second value + * \return logical AND + */ + template<bool __first__, bool __second__> + inline JBool<__first__ == __second__> c_and(const JBool<__first__>& first, + const JBool<__second__>& second) + { + return first.c_and(second); + } + + + /** + * Make logical OR. + * + * \param first first value + * \param second second value + * \return logical OR + */ + template<bool __first__, bool __second__> + inline JBool<__first__ == __second__> c_or(const JBool<__first__>& first, + const JBool<__second__>& second) + { + return first.c_or(second); + } + + + /** + * Make logical XOR. + * + * \param first first value + * \param second second value + * \return logical XOR + */ + template<bool __first__, bool __second__> + inline JBool<__first__ == __second__> c_xor(const JBool<__first__>& first, + const JBool<__second__>& second) + { + return first.c_xor(second); + } + + + typedef JBool<true> JTRUE; //!< True type + typedef JBool<false> JFALSE; //!< False type + + static const JTRUE JTrue_t; //!< True value + static const JFALSE JFalse_t; //!< False value + + + /** + * Type definition of logical EQUALS. + */ + template<class JFirst_t, class JSecond_t> + struct EQUALS; + + /** + * Template specialisation for logical EQUALS. + */ + template<bool first, bool second> + struct EQUALS< JBool<first>, JBool<second> > : + public JBool<first == second> + {}; + + + /** + * Type definition of logical NOT. + */ + template<class T> + struct NOT; + + /** + * Template specialisation for logical NOT. + */ + template<bool __value__> + struct NOT< JBool<__value__> > : + public JBool<!__value__> + {}; + + + /** + * Type definition of logical AND. + */ + template<class JFirst_t, class JSecond_t> + struct AND; + + /** + * Template specialisation for logical AND. + */ + template<bool first, bool second> + struct AND< JBool<first>, JBool<second> > : + public JBool<first && second> + {}; + + + /** + * Type definition of logical OR. + */ + template<class JFirst_t, class JSecond_t> + struct OR; + + /** + * Template specialisation for logical OR. + */ + template<bool first, bool second> + struct OR< JBool<first>, JBool<second> > : + public JBool<first || second> + {}; + + + /** + * Type definition of logical XOR. + */ + template<class JFirst_t, class JSecond_t> + struct XOR; + + /** + * Template specialisation for logical XOR. + */ + template<bool first, bool second> + struct XOR< JBool<first>, JBool<second> > : + public JBool<first != second> + {}; +} + +#endif diff --git a/jpp/JLang/JCC.hh b/jpp/JLang/JCC.hh new file mode 100644 index 0000000..5e19830 --- /dev/null +++ b/jpp/JLang/JCC.hh @@ -0,0 +1,17 @@ +#ifndef __JLANG_JCC__ +#define __JLANG_JCC__ + +//#include "RVersion.h" + +/** + * \file + * Compiler version dependent expressions, macros, etc. + * \author mdejong + */ + +//#if __GNUC__ == 4 && __GNUC_MINOR__ < 6 +//#endif +//#if ROOT_VERSION_CODE < ROOT_VERSION(6,0,0) +//#endif + +#endif diff --git a/jpp/JLang/JClass.hh b/jpp/JLang/JClass.hh new file mode 100644 index 0000000..67a4c8f --- /dev/null +++ b/jpp/JLang/JClass.hh @@ -0,0 +1,220 @@ +#ifndef __JLANG__JCLASS__ +#define __JLANG__JCLASS__ + + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + + /** + * Data structure for primitive types. + */ + template<class T> + struct JPrimitive { + + typedef const T argument_type; + + enum { is_primitive = true }; + }; + + + /** + * Data structure for method argument types. + */ + template<class T> + struct JArgument { + + typedef const T& argument_type; + + enum { is_primitive = false }; + }; + + + /** + * Specialisations of JArgument for primitive types. + */ + template<> struct JArgument<bool> : public JPrimitive<bool> {}; + template<> struct JArgument<char> : public JPrimitive<char> {}; + template<> struct JArgument<unsigned char> : public JPrimitive<unsigned char> {}; + template<> struct JArgument<short> : public JPrimitive<short> {}; + template<> struct JArgument<unsigned short> : public JPrimitive<unsigned short> {}; + template<> struct JArgument<int> : public JPrimitive<int> {}; + template<> struct JArgument<unsigned int> : public JPrimitive<unsigned int> {}; + template<> struct JArgument<long int> : public JPrimitive<long int> {}; + template<> struct JArgument<unsigned long int> : public JPrimitive<unsigned long int> {}; + template<> struct JArgument<long long int> : public JPrimitive<long long int> {}; + template<> struct JArgument<unsigned long long int> : public JPrimitive<unsigned long long int> {}; + template<> struct JArgument<float> : public JPrimitive<float> {}; + template<> struct JArgument<double> : public JPrimitive<double> {}; + template<> struct JArgument<long double> : public JPrimitive<long double> {}; + + + /** + * Data structure to check whether given data type is an iterator. + */ + template<class T> + struct is_iterator { + + static T make(); + + typedef void* buffer[2]; + + static buffer& test(...); //!< any type + template<class R> static typename R::iterator_category* test(R); //!< iterator + template<class R> static void* test(R *); //!< pointer + + static const bool value = sizeof(test(make())) == sizeof(void *); + }; + + + /** + * Template for generic class types. + */ + template<class T> + struct JClass { + + typedef typename JArgument<T>::argument_type argument_type; + typedef T value_type; + typedef value_type& reference_type; + typedef value_type* pointer_type; + + enum { is_primitive = JArgument<T>::is_primitive }; + enum { is_reference = false }; + enum { is_pointer = false }; + enum { is_constant = false }; + }; + + + /** + * Specialisation of JClass for const class types. + */ + template<class T> + struct JClass<const T> { + + typedef typename JArgument<T>::argument_type argument_type; + typedef T value_type; + typedef const value_type& reference_type; + typedef const value_type* pointer_type; + + enum { is_primitive = JArgument<T>::is_primitive }; + enum { is_reference = false }; + enum { is_pointer = false }; + enum { is_constant = true }; + }; + + + /** + * Specialisation of JClass for reference class types. + */ + template<class T> + struct JClass<T&> { + + typedef T& argument_type; + typedef T value_type; + typedef value_type& reference_type; + typedef value_type* pointer_type; + + enum { is_primitive = JArgument<T>::is_primitive }; + enum { is_reference = true }; + enum { is_pointer = false }; + enum { is_constant = false }; + }; + + + /** + * Specialisation of JClass for const reference class types. + */ + template<class T> + struct JClass<const T&> { + + typedef const T& argument_type; + typedef T value_type; + typedef const value_type& reference_type; + typedef const value_type* pointer_type; + + enum { is_primitive = JArgument<T>::is_primitive }; + enum { is_reference = true }; + enum { is_pointer = false }; + enum { is_constant = true }; + }; + + + /** + * Specialisation of JClass for pointer class types. + */ + template<class T> + struct JClass<T*> { + + typedef T* argument_type; + typedef T value_type; + typedef value_type*& reference_type; + typedef value_type* pointer_type; + + enum { is_primitive = JArgument<T>::is_primitive }; + enum { is_reference = false }; + enum { is_pointer = true }; + enum { is_constant = false }; + }; + + + /** + * Specialisation of JClass for const pointer class types. + */ + template<class T> + struct JClass<const T*> { + + typedef const T* argument_type; + typedef T value_type; + typedef const value_type*& reference_type; + typedef const value_type* pointer_type; + + enum { is_primitive = JArgument<T>::is_primitive }; + enum { is_reference = false }; + enum { is_pointer = true }; + enum { is_constant = true }; + }; + + + /** + * Specialisation of JClass for pointer class types. + */ + template<class T> + struct JClass<T*&> { + + typedef T*& argument_type; + typedef T value_type; + typedef value_type*& reference_type; + typedef value_type* pointer_type; + + enum { is_primitive = JArgument<T>::is_primitive }; + enum { is_reference = true }; + enum { is_pointer = true }; + enum { is_constant = false }; + }; + + + /** + * Specialisation of JClass for const pointer class types. + */ + template<class T> + struct JClass<const T*&> { + + typedef const T*& argument_type; + typedef T value_type; + typedef const value_type*& reference_type; + typedef const value_type* pointer_type; + + enum { is_primitive = JArgument<T>::is_primitive }; + enum { is_reference = true }; + enum { is_pointer = true }; + enum { is_constant = true }; + }; +} + +#endif diff --git a/jpp/JLang/JClonable.hh b/jpp/JLang/JClonable.hh new file mode 100644 index 0000000..681b381 --- /dev/null +++ b/jpp/JLang/JClonable.hh @@ -0,0 +1,77 @@ +#ifndef __JLANG__JCLONABLE__ +#define __JLANG__JCLONABLE__ + +#include "JLang/JNullType.hh" + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + + /** + * Template class for object cloning. + */ + template<class JClonable_t, class JDerived_t = JNullType> + struct JClonable; + + + /** + * Template specialisation to define base class for interface of object cloning. + */ + template<class JClonable_t> + struct JClonable<JClonable_t, JNullType> + { + /** + * Type definition of return value of method clone(). + */ + typedef JClonable_t* clone_type; + + + /** + * Virtual destructor. + */ + virtual ~JClonable() + {} + + + /** + * Get clone of this object. + * + * \return pointer to newly created object + */ + virtual clone_type clone() const = 0; + }; + + + /** + * Template specialisation to define base class for implementation of object cloning. + * + * This class derives from the specified clonable class and implements the method clone. + */ + template<class JClonable_t, class JDerived_t> + struct JClonable : + public JClonable_t + { + + typedef typename JClonable<JClonable_t>::clone_type clone_type; + + + /** + * Get clone of this object. + * + * \return pointer to newly created object + */ + virtual clone_type clone() const override + { + return new JDerived_t(static_cast<const JDerived_t&>(*this)); + } + }; +} + + +#endif diff --git a/jpp/JLang/JComparable.hh b/jpp/JLang/JComparable.hh new file mode 100644 index 0000000..f2ee43d --- /dev/null +++ b/jpp/JLang/JComparable.hh @@ -0,0 +1,311 @@ +#ifndef __JLANG__JCOMPARABLE__ +#define __JLANG__JCOMPARABLE__ + +#include "JLang/JNullType.hh" +#include "JLang/JClass.hh" + + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + + /** + * Template definition of auxiliary base class for comparison of data structures. + * + * The various specialisations of this class implement the operators <tt> < > <= >= == != </tt>. + */ + template<class JFirst_t, class JSecond_t = JNullType> + struct JComparable; + + + /** + * General purpose specialisation of class JComparable for any data type. + * + * The template parameter should have the corresponding member method: + * <pre> + * bool less(const JClass_t&) const; + * </pre> + * + * This class uses in-class friend operators (see Barton-Nackman trick). + */ + template<class JClass_t> + struct JComparable<JClass_t, JNullType> + { + /** + * Less than operator. + * + * \param first first object + * \param second second object + * \return true if first object is less than second object; else false + */ + friend bool operator<(const JClass_t& first, + const JClass_t& second) + { + return first.less(second); + } + + + /** + * Greater than operator. + * + * \param first first object + * \param second second object + * \return true if first object is greater than second object; else false + */ + friend bool operator>(const JClass_t& first, + const JClass_t& second) + { + return second.less(first); + } + + + /** + * Less than or equal operator. + * + * \param first first object + * \param second second object + * \return true if first object is less than or equal to second object; else false + */ + friend bool operator<=(const JClass_t& first, + const JClass_t& second) + { + return !second.less(first); + } + + + /** + * Greater than or equal operator. + * + * \param first first object + * \param second second object + * \return true if first object is greater than or equal to second object; else false + */ + friend bool operator>=(const JClass_t& first, + const JClass_t& second) + { + return !first.less(second); + } + + + /** + * Equal operator. + * + * \param first first object + * \param second second object + * \return true if two objects are equal; else false + */ + friend bool operator==(const JClass_t& first, + const JClass_t& second) + { + return !first.less(second) && !second.less(first); + } + + + /** + * Not equal operator. + * + * \param first first object + * \param second second object + * \return true if two objects are not equal; else false + */ + friend bool operator!=(const JClass_t& first, + const JClass_t& second) + { + return first.less(second) || second.less(first); + } + }; + + + /** + * Specialisation of class JComparable for two data types. + * + * The first template parameter should have the corresponding member methods: + * <pre> + * bool less(const JSecond_t&) const; + * bool more(const JSecond_t&) const; + * </pre> + * where <tt>JFirst_t</tt> andd <tt>JSecond_t</tt> refers to the first and second template parameter, respectively. + * The second template parameter may be a primitive data type. + * This class uses in-class friend operators (see Barton-Nackman trick). + */ + template<class JFirst_t, class JSecond_t> + struct JComparable + { + /** + * Less than operator. + * + * \param first first object + * \param second second object + * \return true if first object is less than second object; else false + */ + friend bool operator<(const JFirst_t& first, + typename JClass<JSecond_t>::argument_type second) + { + return first.less(second); + } + + + /** + * Less than operator. + * + * \param first first object + * \param second second object + * \return true if first object is less than second object; else false + */ + friend bool operator<(typename JClass<JSecond_t>::argument_type first, + const JFirst_t& second) + { + return second.more(first); + } + + + /** + * Greater than operator. + * + * \param first first object + * \param second second object + * \return true if first object is greater than second object; else false + */ + friend bool operator>(const JFirst_t& first, + typename JClass<JSecond_t>::argument_type second) + { + return first.more(second); + } + + + /** + * Greater than operator. + * + * \param first first object + * \param second second object + * \return true if first object is greater than second object; else false + */ + friend bool operator>(typename JClass<JSecond_t>::argument_type first, + const JFirst_t& second) + { + return second.less(first); + } + + + /** + * Less than or equal operator. + * + * \param first first object + * \param second second object + * \return true if first object is less than or equal to second object; else false + */ + friend bool operator<=(const JFirst_t& first, + typename JClass<JSecond_t>::argument_type second) + { + return !first.more(second); + } + + + /** + * Less than or equal operator. + * + * \param first first object + * \param second second object + * \return true if first object is less than or equal to second object; else false + */ + friend bool operator<=(typename JClass<JSecond_t>::argument_type first, + const JFirst_t& second) + { + return second.more(first); + } + + + /** + * Greater than or equal operator. + * + * \param first first object + * \param second second object + * \return true if first object is greater than or equal to second object; else false + */ + friend bool operator>=(const JFirst_t& first, + typename JClass<JSecond_t>::argument_type second) + { + return !first.less(second); + } + + + /** + * Greater than or equal operator. + * + * \param first first object + * \param second second object + * \return true if first object is greater than or equal to second object; else false + */ + friend bool operator>=(typename JClass<JSecond_t>::argument_type first, + const JFirst_t& second) + + { + return second.less(first); + } + + + /** + * Equal operator. + * + * \param first first object + * \param second second object + * \return true if two objects are equal; else false + */ + friend bool operator==(const JFirst_t& first, + typename JClass<JSecond_t>::argument_type second) + { + return !first.less(second) && !first.more(second); + } + + + /** + * Equal operator. + * + * \param first first object + * \param second second object + * \return true if two objects are equal; else false + */ + friend bool operator==(typename JClass<JSecond_t>::argument_type first, + const JFirst_t& second) + + { + return !second.less(first) && !second.more(first); + } + + + /** + * Not equal operator. + * + * \param first first object + * \param second second object + * \return true if two objects are not equal; else false + */ + friend bool operator!=(const JFirst_t& first, + typename JClass<JSecond_t>::argument_type second) + { + return first.less(second) || first.more(second); + } + + + /** + * Not equal operator. + * + * \param first first object + * \param second second object + * \return true if two objects are not equal; else false + */ + friend bool operator!=(typename JClass<JSecond_t>::argument_type first, + const JFirst_t& second) + { + return second.less(first) || second.more(first); + } + }; +} + +#endif diff --git a/jpp/JLang/JEquals.hh b/jpp/JLang/JEquals.hh new file mode 100644 index 0000000..67d9888 --- /dev/null +++ b/jpp/JLang/JEquals.hh @@ -0,0 +1,142 @@ +#ifndef __JLANG__JEQUALS__ +#define __JLANG__JEQUALS__ + +#include "JLang/JNullType.hh" +#include "JLang/JClass.hh" + + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + + /** + * Template definition of auxiliary base class for comparison of data structures. + * + * The various specialisations of this class implement the operators <tt> == != </tt>. + */ + template<class JFirst_t, class JSecond_t = JNullType> + struct JEquals; + + + /** + * General purpose specialisation of class JEquals for any data type. + * + * The template parameter should have the corresponding member method: + * <pre> + * bool equals(const JClass_t&) const; + * </pre> + * + * This class uses in-class friend operators (see Barton-Nackman trick). + */ + template<class JClass_t> + struct JEquals<JClass_t, JNullType> + { + /** + * Equal operator. + * + * \param first first object + * \param second second object + * \return true if two objects are equal; else false + */ + friend bool operator==(const JClass_t& first, + const JClass_t& second) + { + return first.equals(second); + } + + + /** + * Not equal operator. + * + * \param first first object + * \param second second object + * \return true if two objects are not equal; else false + */ + friend bool operator!=(const JClass_t& first, + const JClass_t& second) + { + return !first.equals(second); + } + }; + + + /** + * Specialisation of class JEquals for two data types. + * + * The first template parameter should have the corresponding member methods: + * <pre> + * bool equals(const JFirst_t&) const; + * bool equals(const JSecond_t&) const; + * </pre> + * where <tt>JFirst_t</tt> and <tt>JSecond_t</tt> refer to the first and second template parameter, respectively. + * The second template parameter may be a primitive data type. + * This class uses in-class friend operators (see Barton-Nackman trick). + */ + template<class JFirst_t, class JSecond_t> + struct JEquals : + public JEquals<JFirst_t> + { + /** + * Equal operator. + * + * \param first first object + * \param second second object + * \return true if two objects are equal; else false + */ + friend bool operator==(const JFirst_t& first, + typename JClass<JSecond_t>::argument_type second) + { + return first.equals(second); + } + + + /** + * Equal operator. + * + * \param first first object + * \param second second object + * \return true if two objects are equal; else false + */ + friend bool operator==(typename JClass<JSecond_t>::argument_type first, + const JFirst_t& second) + { + return second.equals(first); + } + + + /** + * Not equal operator. + * + * \param first first object + * \param second second object + * \return true if two objects are not equal; else false + */ + friend bool operator!=(const JFirst_t& first, + typename JClass<JSecond_t>::argument_type second) + { + return !first.equals(second); + } + + + /** + * Not equal operator. + * + * \param first first object + * \param second second object + * \return true if two objects are not equal; else false + */ + friend bool operator!=(typename JClass<JSecond_t>::argument_type first, + const JFirst_t& second) + { + return !second.equals(first); + } + }; +} + +#endif diff --git a/jpp/JLang/JException.hh b/jpp/JLang/JException.hh new file mode 100644 index 0000000..5892627 --- /dev/null +++ b/jpp/JLang/JException.hh @@ -0,0 +1,673 @@ +#ifndef __JLANG__JEXCEPTION__ +#define __JLANG__JEXCEPTION__ + +#include <exception> +#include <string> +#include <ostream> +#include <sstream> + + +/** + * \file + * Exceptions. + * \author mdejong + */ +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + /** + * General exception + */ + class JException : public std::exception { + public: + /** + * Constructor. + * + * \param error error message + */ + JException(const std::string& error) : + std::exception(), + buffer(error) + {} + + + /** + * Destructor. + */ + ~JException() throw() + {} + + + /** + * Get error message. + * + * \return error message + */ + virtual const char* what() const throw() override + { + return buffer.c_str(); + } + + + /** + * Print error message of JException. + * + * \param out output stream + * \param exception exception + */ + friend inline std::ostream& operator<<(std::ostream& out, const JException& exception) + { + return out << exception.what(); + } + + + /** + * Get output stream for conversion of exception. + * + * Note that the ostream is emptied before use. + * + * \return ostream + */ + static inline std::ostream& getOstream() + { + static std::ostringstream buffer; + + buffer.str(""); + + return buffer; + } + + private: + const std::string buffer; + }; + + + /** + * Exception for accessing an index in a collection that is outside of its range. + */ + class JIndexOutOfRange : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JIndexOutOfRange(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for accessing an invalid pointer. + */ + class JPointerException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JPointerException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for a functional operation. + */ + class JFunctionalException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JFunctionalException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for an empty collection. + */ + class JEmptyCollection : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JEmptyCollection(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for accessing a value in a collection that is outside of its range. + */ + class JValueOutOfRange : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JValueOutOfRange(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for parsing value. + */ + class JParseError : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JParseError(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for missing value. + */ + class JNoValue : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JNoValue(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for null pointer operation. + */ + class JNullPointerException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JNullPointerException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for cast operation. + */ + class JCastException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JCastException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for numerical precision error. + */ + class JNumericalPrecision : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JNumericalPrecision(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for division by zero. + */ + class JDivisionByZero : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JDivisionByZero(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for failure of memory allocation. + */ + class JMallocException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JMallocException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for failure of memory allocation. + */ + class JNewException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JNewException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for I/O. + */ + class JIOException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JIOException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for opening of file. + */ + class JFileOpenException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JFileOpenException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for reading of file. + */ + class JFileReadException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JFileReadException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for end of file. + */ + class JEndOfFile : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JEndOfFile(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for opening of pipe. + */ + class JPipeOpenException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JPipeOpenException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for select call. + */ + class JSelectException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JSelectException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for socket. + */ + class JSocketException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JSocketException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for ControlHost. + */ + class JControlHostException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JControlHostException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for socket channel. + */ + class JSocketChannelException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JSocketChannelException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for creation of fork. + */ + class JForkException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JForkException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for system call. + */ + class JSystemException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JSystemException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception when parsing a value. + */ + class JParserException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JParserException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception when parsing a value. + */ + class JPropertiesException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JPropertiesException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for missing entry in dictionary. + */ + class JDictionaryEntryNotFound : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JDictionaryEntryNotFound(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for duplicate entry in dictionary. + */ + class JDictionaryDuplicateEntry : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JDictionaryDuplicateEntry(const std::string& error) : + JException(error) + {} + }; + + + /** + * Run time exception. + */ + class JRunTimeException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JRunTimeException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Exception for absence of type information. + */ + class JTypeInformationException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JTypeInformationException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Protocol exception. + */ + class JProtocolException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JProtocolException(const std::string& error) : + JException(error) + {} + }; + + + /** + * Database exception. + */ + class JDatabaseException : + public JException + { + public: + /** + * Constructor. + * + * \param error error message + */ + JDatabaseException(const std::string& error) : + JException(error) + {} + }; +} + +/** + * Marco for throwing exception with std::ostream compatible message. + * + * \param JException_t exception + * \param A message + */ +#ifndef THROW +#define THROW(JException_t, A) do { throw JException_t(static_cast<std::ostringstream&>(JLANG::JException::getOstream() << __FILE__ << ':' << __LINE__ << std::endl << A).str()); } while(0) +#endif + +#endif diff --git a/jpp/JLang/JForwardIterator.hh b/jpp/JLang/JForwardIterator.hh new file mode 100644 index 0000000..642584e --- /dev/null +++ b/jpp/JLang/JForwardIterator.hh @@ -0,0 +1,116 @@ +#ifndef __JLANG__JFORWARDITERATOR__ +#define __JLANG__JFORWARDITERATOR__ + +#include <cstddef> + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + /** + * Template interface for method bool increment(). + * This interface implements the pre-fix and post-fix operators <tt>++</tt>. + */ + template<class T> + class JForwardIterator { + public: + /** + * Virtual destructor. + */ + virtual ~JForwardIterator() + {} + + + /** + * Increment iterator. + * + * \return this iterator + */ + T& operator++() + { + this->increment(); + + return static_cast<T&>(*this); + } + + + /** + * Increment iterator. + * + * \return previous iterator + */ + T operator++(int) + { + const T tmp(static_cast<const T&>(*this)); + + this->increment(); + + return tmp; + } + + + /** + * Advance iterator. + * + * \param offset offset + * \return iterator + */ + T& operator+=(const size_t offset) + { + this->increment(offset); + + return static_cast<T&>(*this); + } + + + /** + * Advance operator. + * + * \param object iterator + * \param offset offset + * \return iterator + */ + friend inline T operator+(const T& object, const size_t offset) + { + T tmp(object); + + tmp.increment(offset); + + return tmp; + } + + + /** + * Increment iterator. + * + * \return true if incremented; else false + */ + virtual bool increment() = 0; + + + /** + * Increment iterator. + * + * \param offset offset + * \return true if incremented; else false + */ + virtual bool increment(const size_t offset) + { + size_t i = 0; + + while (i != offset && this->increment()) { + ++i; + } + + return i == offset; + } + }; +} + +#endif + diff --git a/jpp/JLang/JLangToolkit.hh b/jpp/JLang/JLangToolkit.hh new file mode 100644 index 0000000..a9abcf2 --- /dev/null +++ b/jpp/JLang/JLangToolkit.hh @@ -0,0 +1,333 @@ +#ifndef __JLANG__JLANGTOOLKIT__ +#define __JLANG__JLANGTOOLKIT__ + +#include <string> +#include <sstream> +#include <iterator> +#include <ctype.h> + + +/** + * \author mdejong + */ + +/** + * Auxiliary classes and methods for language specific functionality. + */ +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + using std::size_t; + + + /** + * Get size of c-array. + * + * \param array array + * \return size + */ + template<class T, size_t N> + inline size_t getSize(T (&array)[N]) + { + return N; + } + + + /** + * Check if two objects are indentical. + * + * \param first first object + * \param second second object + * \return true if addresses are equal; else false + */ + template<class JFirst_t, class JSecond_t> + inline bool is_identical(JFirst_t& first, JSecond_t& second) + { + return (void*) &first == (void*) &second; + } + + + /** + * Check if string is an integer.\n + * + * \param buffer input string + * \return true if integer; else false + */ + inline bool is_integer(const std::string& buffer) + { + using namespace std; + + for (string::const_iterator i = buffer. begin(); i != buffer.end(); ++i) { + if (!isdigit(*i)) { + return false; + } + } + + return !buffer.empty(); + } + + + /** + * Trim string.\n + * Returns a copy of the string, with leading and trailing white spaces omitted. + * + * \param buffer input string + * \return modified string + */ + inline std::string trim(const std::string& buffer) + { + using namespace std; + + string::const_iterator p = buffer. begin(); + string::const_reverse_iterator q = buffer.rbegin(); + + while (p != q.base() && isspace(*p)) { ++p; } + while (p != q.base() && isspace(*q)) { ++q; } + + return string(p,q.base()); + } + + + /** + * Trim string.\n + * Returns a copy of the string, with leading and trailing target characters omitted. + * + * \param buffer input string + * \param c strip character + * \return modified string + */ + inline std::string trim(const std::string& buffer, const char c) + { + using namespace std; + + string::const_iterator p = buffer. begin(); + string::const_reverse_iterator q = buffer.rbegin(); + + while (p != q.base() && *p == c) { ++p; } + while (p != q.base() && *q == c) { ++q; } + + return string(p,q.base()); + } + + + /** + * Replace tokens in string.\n + * Returns a copy of the string, with all occurences of <tt>target</tt> replaced by <tt>replacement</tt>. + * + * \param input input string + * \param target target string + * \param replacement replacement string + * \return modified string + */ + inline std::string replace(const std::string& input, const std::string& target, const std::string& replacement) + { + using namespace std; + + string buffer = input; + + for (size_t i = buffer.find(target); i != string::npos; i = buffer.find(target,i)) { + buffer.replace(buffer.begin() + i, buffer.begin() + i + target.length(), replacement); + } + + return buffer; + } + + + /** + * Replace characters in string.\n + * Returns a copy of the string, with all occurences of <tt>target</tt> replaced by <tt>replacement</tt>. + * + * \param input input string + * \param target target character + * \param replacement replacement character + * \return modified string + */ + inline std::string replace(const std::string& input, const char target, const char replacement) + { + using namespace std; + + string buffer = input; + + for (string::iterator i = buffer.begin(); i != buffer.end(); ++i) { + if (*i == target) { + *i = replacement; + } + } + + return buffer; + } + + + /** + * Trim string.\n + * Returns a copy of the string, with leading and trailing target characters omitted. + * + * \param buffer input string + * \param target strip character(s) + * \return modified string + */ + inline std::string trim(const std::string& buffer, const std::string& target) + { + using namespace std; + + string::const_iterator p = buffer. begin(); + string::const_reverse_iterator q = buffer.rbegin(); + + while (p != q.base() && target.find(*p) != string::npos) { ++p; } + while (p != q.base() && target.find(*q) != string::npos) { ++q; } + + return string(p,q.base()); + } + + + /** + * Convert value to string. + * + * \param value value + * \return string + */ + template<class T> + inline std::string to_string(const T& value) + { + using namespace std; + + ostringstream os; + + os << value; + + return os.str(); + } + + + /** + * Convert string to value. + * + * \param input string + * \return value + */ + template<class T> + inline T to_value(const std::string& input) + { + using namespace std; + + T value; + + istringstream(input) >> value; + + return value; + } + + + /** + * Convert all character to upper case. + * + * \param value value + * \return string + */ + inline std::string to_upper(const std::string& value) + { + using namespace std; + + string buffer(value); + + for (string::iterator i = buffer.begin(); i != buffer.end(); ++i) { + *i = toupper(*i); + } + + return buffer; + } + + + /** + * Convert all character to lower case. + * + * \param value value + * \return string + */ + inline std::string to_lower(const std::string& value) + { + using namespace std; + + string buffer(value); + + for (string::iterator i = buffer.begin(); i != buffer.end(); ++i) { + *i = tolower(*i); + } + + return buffer; + } + + + /** + * Count number of white space separated tokens. + * + * \param buffer input string + * \return number of tokens + */ + inline size_t get_number_of_tokens(const std::string& buffer) + { + using namespace std; + + istringstream is(buffer); + + return distance(istream_iterator<string>(is), istream_iterator<string>()); + } + + + /** + * Check quotation. + * + * \param value value + * \return true if quoted; else false + */ + inline bool is_single_quoted(const std::string& value) + { + return (value.size() > 1 && *value.begin() == '\'' && *value.rbegin() == '\''); + } + + + /** + * Check quotation. + * + * \param value value + * \return true if quoted; else false + */ + inline bool is_double_quoted(const std::string& value) + { + return (value.size() > 1 && *value.begin() == '\"' && *value.rbegin() == '\"'); + } + + + /** + * Quote string. + * + * \param value value + * \return string + */ + inline std::string single_quote(const std::string& value) + { + if (!is_single_quoted(value)) + return "\'" + value + "\'"; + else + return value; + } + + + /** + * Quote string. + * + * \param value value + * \return string + */ + inline std::string double_quote(const std::string& value) + { + if (!is_double_quoted(value)) + return "\"" + value + "\""; + else + return value; + } +} + +#endif diff --git a/jpp/JLang/JManip.hh b/jpp/JLang/JManip.hh new file mode 100644 index 0000000..a4b2193 --- /dev/null +++ b/jpp/JLang/JManip.hh @@ -0,0 +1,716 @@ +#ifndef __JLANG_JMANIP__ +#define __JLANG_JMANIP__ + +#include <string> +#include <ostream> +#include <sstream> +#include <iomanip> + + +/** + * \file + * I/O manipulators. + * \author mdejong + */ +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + /** + * Get index for user I/O manipulation. + * + * \return index + */ + inline int getIndex() + { + static const int index = std::ios_base::xalloc(); + + return index; + } + + + /** + * Print options. + */ + enum JPrintOption_t { + SHORT_PRINT = 1, //!< short print + MEDIUM_PRINT = 2, //!< medium print + LONG_PRINT = 3 //!< long print + }; +} + + +/** + * Get print option. + * + * \param out output stream + * \return print option + */ +inline int getPrintOption(std::ostream& out) +{ + return out.iword(JLANG::getIndex()); +} + + +/** + * Set print option. + * + * \param out output stream + * \param option print option + */ +inline void setPrintOption(std::ostream& out, const int option) +{ + out.iword(JLANG::getIndex()) = option; +} + + +/** + * Get short print option. + * + * \param out output stream + * \return true if short print option is on; else false + */ +inline bool getShortprint(std::ostream& out) +{ + return getPrintOption(out) == JLANG::SHORT_PRINT; +} + + +/** + * Set short print option. + * + * \param out output stream + */ +inline void setShortprint(std::ostream& out) +{ + return setPrintOption(out, JLANG::SHORT_PRINT); +} + + +/** + * Get medium print option. + * + * \param out output stream + * \return true if medium print option is on; else false + */ +inline bool getMediumprint(std::ostream& out) +{ + return getPrintOption(out) == JLANG::MEDIUM_PRINT; +} + + +/** + * Set medium print option. + * + * \param out output stream + */ +inline void setMediumprint(std::ostream& out) +{ + return setPrintOption(out, JLANG::MEDIUM_PRINT); +} + + +/** + * Get long print option. + * + * \param out output stream + * \return true if long print option is on; else false + */ +inline bool getLongprint(std::ostream& out) +{ + return getPrintOption(out) == JLANG::LONG_PRINT; +} + + +/** + * Set long print option. + * + * \param out output stream + */ +inline void setLongprint(std::ostream& out) +{ + return setPrintOption(out, JLANG::LONG_PRINT); +} + + +/** + * Set short printing. + * + * \param out output stream + * \return output stream + */ +inline std::ostream& shortprint(std::ostream& out) +{ + setShortprint(out); + + return out; +} + + +/** + * Set medium printing. + * + * \param out output stream + * \return output stream + */ +inline std::ostream& mediumprint(std::ostream& out) +{ + setMediumprint(out); + + return out; +} + + +/** + * Set long printing. + * + * \param out output stream + * \return output stream + */ +inline std::ostream& longprint(std::ostream& out) +{ + setLongprint(out); + + return out; +} + + +/** + * Print newline character. + * + * \param out output stream + * \return output stream + */ +inline std::ostream& newline(std::ostream& out) +{ + return out << '\n'; +} + + +/** + * Print white space character. + * + * \param out output stream + * \return output stream + */ +inline std::ostream& whitespace(std::ostream& out) +{ + return out << ' '; +} + + +/** + * Print tab character. + * + * \param out output stream + * \return output stream + */ +inline std::ostream& tab(std::ostream& out) +{ + return out << '\t'; +} + + +/** + * Rewind character. + * + * \param out output stream + * \return output stream + */ +inline std::ostream& rewind(std::ostream& out) +{ + return (out << '\r').flush(); +} + + +/** + * Auxiliary data structure for alignment of data. + */ +struct WIDTH { + /** + * Constructor. + * + * \param width width + */ + WIDTH(const int width) + { + this->width = width; + } + + + /** + * Format specifier. + * + * \param out output stream + * \param format format + * \return output stream + */ + friend inline std::ostream& operator<<(std::ostream& out, const WIDTH& format) + { + using namespace std; + + return out << setw(format.width); + } + + int width; +}; + + +/** + * Auxiliary data structure for alignment of data. + */ +struct LEFT : + public WIDTH +{ + /** + * Constructor. + * + * \param width width + */ + LEFT(const int width) : + WIDTH(width) + {} + + + /** + * Format specifier. + * + * \param out output stream + * \param format format + * \return output stream + */ + friend inline std::ostream& operator<<(std::ostream& out, const LEFT& format) + { + using namespace std; + + return out << setw(format.width) << left; + } +}; + + +/** + * Auxiliary data structure for alignment of data. + */ +struct RIGHT : + public WIDTH +{ + /** + * Constructor. + * + * \param width width + */ + RIGHT(const int width) : + WIDTH(width) + {} + + + /** + * Format specifier. + * + * \param out output stream + * \param format format + * \return output stream + */ + friend inline std::ostream& operator<<(std::ostream& out, const RIGHT& format) + { + using namespace std; + + return out << setw(format.width) << right; + } +}; + + +/** + * Auxiliary data structure for sequence of same character. + */ +struct FILL : + public WIDTH +{ + /** + * Constructor. + * + * \param width width + * \param fill fill character + */ + FILL(const int width = 0, + const char fill = ' ') : + WIDTH(width) + { + this->fill = fill; + } + + + /** + * Format specifier. + * + * \param out output stream + * \param format format + * \return output stream + */ + friend inline std::ostream& operator<<(std::ostream& out, const FILL& format) + { + using namespace std; + + return out << setfill(format.fill) << setw(format.width); + } + + char fill; +}; + + +/** + * Auxiliary data structure for alignment of data. + */ +struct CENTER : + public WIDTH +{ +protected: + /** + * Auxiliary class for format center. + */ + struct JCenter : + public WIDTH + { + /** + * Constructor. + * + * \param out output stream + * \param format format center + */ + JCenter(std::ostream& out, const WIDTH& format) : + WIDTH(format), + out (out) + {} + + + /** + * Write value to output stream. + * + * \param value value + * \return this JCenter + */ + template<class T> + std::ostream& operator<<(const T& value) + { + using namespace std; + + ostringstream os; + + os.copyfmt(out); + + os << value; + + const int w = this->width - os.str().size(); + const char c = this->out.fill(); + + if (w > 0) + return this->out << FILL(w/2) << ' ' << os.str() << FILL((w+1)/2) << ' ' << setfill(c); + else + return this->out << os.str(); + } + + private: + std::ostream& out; + }; + +public: + /** + * Constructor. + * + * \param width width + */ + CENTER(const int width) : + WIDTH(width) + {} + + + /** + * Format specifier. + * + * \param out output stream + * \param format format + * \return output stream + */ + friend inline JCenter operator<<(std::ostream& out, const CENTER& format) + { + return JCenter(out, format); + } +}; + + +/** + * Auxiliary data structure for floating point format specification. + */ +struct FIXED : + public WIDTH +{ + /** + * Constructor. + * + * \param width width + * \param precision precision + */ + FIXED(const int width, + const int precision) : + WIDTH(width) + { + this->precision = precision; + } + + + /** + * Format specifier. + * + * \param out output stream + * \param format format + * \return output stream + */ + friend inline std::ostream& operator<<(std::ostream& out, const FIXED& format) + { + using namespace std; + + return out << fixed << right << setw(format.width) << setprecision(format.precision); + } + + int precision; +}; + + +/** + * Auxiliary data structure for floating point format specification. + */ +struct SCIENTIFIC : + public WIDTH +{ + /** + * Constructor. + * + * \param width width + * \param precision precision + */ + SCIENTIFIC(const int width, + const int precision) : + WIDTH(width) + { + this->precision = precision; + } + + + /** + * Format specifier. + * + * \param out output stream + * \param format format + * \return output stream + */ + friend inline std::ostream& operator<<(std::ostream& out, const SCIENTIFIC& format) + { + using namespace std; + + return out << scientific << right << setw(format.width) << setprecision(format.precision); + } + + int precision; +}; + + +/** + * Data structure for format specifications. + */ +struct JFormat_t { + + typedef std::ios_base::fmtflags fmtflags; + + /** + * Default constructor. + */ + JFormat_t() : + width (0), + precision(0), + flags (), + fill (' ') + {} + + + /** + * Constructor. + * + * \param width width + * \param precision precision + * \param flags flags + * \param fill fill character + */ + JFormat_t(const int width, + const int precision = 0, + const fmtflags flags = fmtflags(), + const char fill = ' ') : + width (width), + precision(precision), + flags (flags), + fill (fill) + {} + + + /** + * Constructor. + * + * \param out output stream + */ + JFormat_t(std::ostream& out) + { + get(out); + } + + + /** + * Check validity of this manipulator. + * + * \return true if valid; else false + */ + inline bool is_valid() const + { + return (width > 0); + } + + + /** + * Get format specificaton from given output stream. + * + * \param out output stream + */ + void get(std::ostream& out) + { + this->width = out.width(); + this->precision = out.precision(); + this->flags = out.flags(); + this->fill = out.fill(); + } + + + /** + * Put format specificaton to given output stream. + * + * \param out output stream + */ + void put(std::ostream& out) const + { + out.width (this->width); + out.precision(this->precision); + out.flags (this->flags); + out.fill (this->fill); + } + + + /** + * Format specifier. + * + * \param out output stream + * \param format format + * \return output stream + */ + friend inline std::ostream& operator<<(std::ostream& out, const JFormat_t& format) + { + format.put(out); + + return out; + } + + int width; + int precision; + fmtflags flags; + char fill; +}; + + +/** + * Auxiliary class to temporarily define format specifications. + * + * The format specification of the output stream in use will be restored when this object is destroyed. + */ +struct JFormat : + public JFormat_t +{ + /** + * Constructor. + * + * \param out output stream + */ + JFormat(std::ostream& out) : + JFormat_t(), + out (out), + format (out) + {} + + + /** + * Constructor. + * + * \param out output stream + * \param format format + */ + JFormat(std::ostream& out, const JFormat_t& format) : + JFormat_t(format), + out (out), + format (out) + {} + + + /** + * Destructor. + */ + ~JFormat() + { + format.put(out); + } + +private: + std::ostream& out; + const JFormat_t format; +}; + + +/** + * Get format for given type. + * + * \return format + */ +template<class T> +inline JFormat_t& getFormat() +{ + static JFormat_t manip; + + return manip; +} + + +/** + * Get format for given type. + * + * \param format default format + * \return actual format + */ +template<class T> +inline JFormat_t getFormat(const JFormat_t& format) +{ + const JFormat_t& buffer = getFormat<T>(); + + if (buffer.is_valid()) + return buffer; + else + return format; +} + + +/** + * Set format for given type. + * + * \param format format + */ +template<class T> +inline void setFormat(const JFormat_t& format) +{ + getFormat<T>() = format; +} + +#endif diff --git a/jpp/JLang/JMemory.hh b/jpp/JLang/JMemory.hh new file mode 100644 index 0000000..8d9f622 --- /dev/null +++ b/jpp/JLang/JMemory.hh @@ -0,0 +1,120 @@ +#ifndef __JLANG__JMEMORY__ +#define __JLANG__JMEMORY__ + +#include <stdlib.h> + + +/** + * \file + * + * Base class for memory management. + * \author mdejong + */ +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + + /** + * Memory management class for create/release policy based on new/delete. + */ + template<class JClass_t> + class JNew { + public: + /** + * Create object in memory. + * + * \return pointer to data + */ + static inline JClass_t* create() + { + return new JClass_t(); + } + + + /** + * Release memory. + * + * \param p pointer to data + */ + static inline void release(JClass_t* p) + { + delete p; + } + }; + + + /** + * Memory management class for create/release policy based on new []/delete []. + */ + template<class JClass_t> + class JNewCArray { + public: + /** + * Create array of objects in memory. + * + * \param size number of elements + * \return pointer to data + */ + static inline JClass_t* create(const unsigned int size) + { + return new JClass_t[size]; + } + + + /** + * Release memory. + * + * \param p pointer to data + */ + static inline void release(JClass_t* p) + { + delete [] p; + } + }; + + + /** + * Memory management class for create/release policy based on malloc()/free(). + */ + template<class JClass_t> + class JMalloc { + public: + /** + * Create object in memory. + * + * \return pointer to data + */ + static inline JClass_t* create() + { + return (JClass_t*) malloc(sizeof(JClass_t)); + } + + + /** + * Create array of objects in memory. + * + * \param size number of elements + * \return pointer to data + */ + static inline JClass_t* create(const unsigned int size) + { + return (JClass_t*) malloc(size * sizeof(JClass_t)); + } + + + /** + * Release memory. + * + * \param p pointer to data + */ + static inline void release(JClass_t* p) + { + free((void*) p); + } + }; +} + + +#endif diff --git a/jpp/JLang/JNullType.hh b/jpp/JLang/JNullType.hh new file mode 100644 index 0000000..05b1da9 --- /dev/null +++ b/jpp/JLang/JNullType.hh @@ -0,0 +1,22 @@ +#ifndef __JLANG__JNULLTYPE__ +#define __JLANG__JNULLTYPE__ + + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + + /** + * Auxiliary class for no type definition. + * This class can be used to terminate a type list, define a default template argument, etc. + */ + struct JNullType {}; +} + +#endif diff --git a/jpp/JLang/JObjectID.hh b/jpp/JLang/JObjectID.hh new file mode 100644 index 0000000..2c77a87 --- /dev/null +++ b/jpp/JLang/JObjectID.hh @@ -0,0 +1,157 @@ +#ifndef __JLANG__JOBJECTID__ +#define __JLANG__JOBJECTID__ + +#include <istream> +#include <ostream> + +#include "JLang/JComparable.hh" + + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + /** + * Auxiliary class for object identification. + */ + class JObjectID : + public JComparable<JObjectID>, + public JComparable<JObjectID, int> + { + public: + /** + * Default constructor. + */ + JObjectID() : + __id(-1) + {} + + + /** + * Constructor. + * + * \param id identifier + */ + JObjectID(const int id) : + __id(id) + {} + + + /** + * Get identifier. + * + * \return identifier + */ + int getID() const + { + return __id; + } + + + /** + * Get identifier. + * + * \return identifier + */ + int& getID() + { + return __id; + } + + + /** + * Set identifier. + * + * \param id identifier + */ + void setID(const int id) + { + this->__id = id; + } + + + /** + * Less than method. + * + * \param object object identifier + * \return true if this identifier less than given identifier; else false + */ + inline bool less(const JObjectID& object) const + { + return this->getID() < object.getID(); + } + + + /** + * Less than method. + * + * \param id identifier + * \return true if this identifier less than given identifier; else false + */ + inline bool less(const int id) const + { + return this->getID() < id; + } + + + /** + * More than method. + * + * \param id identifier + * \return true if this identifier greater than given identifier; else false + */ + inline bool more(const int id) const + { + return this->getID() > id; + } + + + /** + * Read object identifier from input. + * + * \param in input stream + * \param object object identifier + * \return input stream + */ + friend inline std::istream& operator>>(std::istream& in, JObjectID& object) + { + return in >> object.__id; + } + + + /** + * Write object identifier to output. + * + * \param out output stream + * \param object object identifier + * \return output stream + */ + friend inline std::ostream& operator<<(std::ostream& out, const JObjectID& object) + { + return out << object.__id; + } + + protected: + int __id; + }; + + + /** + * Get undefined object identifier. + * + * \return undefined object identifier + */ + inline const JObjectID& getUndefinedObjectID() + { + static JObjectID id; + + return id; + } +} + +#endif diff --git a/jpp/JLang/JObjectIO.hh b/jpp/JLang/JObjectIO.hh new file mode 100644 index 0000000..c10939a --- /dev/null +++ b/jpp/JLang/JObjectIO.hh @@ -0,0 +1,141 @@ +#ifndef __JLANG__JOBJECTIO__ +#define __JLANG__JOBJECTIO__ + +#include <fstream> + +#include "JLang/JType.hh" +#include "JLang/JException.hh" + + +/** + * \file + * + * General methods for loading and storing a single object from and to a file, respectively. + * \author mdejong + */ +namespace JLANG {} +namespace JPP { using namespace JLANG; } + + +namespace JLANG { + + /** + * Get error status of reader. + * + * \param reader reader + * \return true if error; else false + */ + template<class JReader_t> + inline bool getError(const JReader_t& reader) + { + return !reader; + } + + + /** + * Get error status of reader. + * + * \param reader reader + * \return true if error; else false + */ + inline bool getError(const std::ifstream& reader) + { + return reader.bad() || (reader.fail() && !reader.eof()); + } + + + /** + * Load object from input file. + * + * \param file_name file name + * \param object object to be read + */ + template<class JReader_t, class T> + inline void load(const char* file_name, T& object) + { + load(file_name, object, JType<JReader_t>()); + } + + + /** + * Store object to output file. + * + * \param file_name file name + * \param object object to be written + */ + template<class JWriter_t, class T> + inline void store(const char* file_name, const T& object) + { + store(file_name, object, JType<JWriter_t>()); + } + + + /** + * Load object from input file. + * + * This method makes use of the STD protocol for the given type reader, namely: + * <pre> + * JReader_t in(file_name); + * + * in >> object; + * + * in.close(); + * </pre> + * This method should be overloaded if the type reader requires a different protocol. + * + * \param file_name file name + * \param object object to be read + * \param type reader type + */ + template<class JReader_t, class T> + inline void load(const char* file_name, T& object, JType<JReader_t> type) + { + JReader_t in(file_name); + + if (!in) { + THROW(JFileOpenException, "Error opening file: " << file_name); + } + + in >> object; + + if (getError(in)) { + THROW(JFileReadException, "Error reading file: " << file_name); + } + + in.close(); + } + + + /** + * Store object to output file. + * + * This method makes use of the STD protocol for the given type writer, namely: + * <pre> + * JWriter_t out(file_name); + * + * out << object; + * + * out.close(); + * </pre> + * This method should be overloaded if the type writer requires a different protocol. + * + * \param file_name file name + * \param object object to be written + * \param type writer type + */ + template<class JWriter_t, class T> + inline void store(const char* file_name, const T& object, JType<JWriter_t> type) + { + JWriter_t out(file_name); + + if (!out) { + THROW(JFileOpenException, "Error opening file: " << file_name); + } + + out << object; + + out.close(); + } +} + +#endif diff --git a/jpp/JLang/JPointer.hh b/jpp/JLang/JPointer.hh new file mode 100644 index 0000000..3d05654 --- /dev/null +++ b/jpp/JLang/JPointer.hh @@ -0,0 +1,140 @@ +#ifndef __JLANG__JPOINTER__ +#define __JLANG__JPOINTER__ + +#include "JLang/JAbstractPointer.hh" + + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + /** + * Template implementation of class that holds pointer to object(s). + * + * This class implements the JAbstractPointer interface. + */ + template<class JClass_t> + class JPointer : + public JAbstractPointer<JClass_t> + { + public: + + using JAbstractPointer<JClass_t>::set; + using JAbstractPointer<JClass_t>::reset; + + /** + * Default constructor. + */ + JPointer() : + __p(NULL) + {} + + + /** + * Constructor. + * + * \param p pointer to object + */ + JPointer(JClass_t* p) : + __p(p) + {} + + + /** + * Constructor. + * + * \param pointer pointer to object + */ + template<class T> + JPointer(JPointer<T> pointer) : + __p(pointer.get()) + {} + + + /** + * Get pointer. + * + * \return pointer to object + */ + virtual JClass_t* get() const override + { + return this->__p; + } + + + /** + * Set pointer. + * + * \param p pointer to object + */ + virtual void set(JClass_t* p) override + { + this->__p = p; + } + + + /** + * Reset pointer. + */ + virtual void reset() override + { + this->__p = NULL; + } + + + /** + * Set pointer. + * + * \param pointer pointer to object + */ + template<class T> + void set(const JPointer<T>& pointer) + { + this->set(pointer.get()); + } + + + /** + * Reset pointer. + * + * \param pointer pointer to object + */ + template<class T> + void reset(const JPointer<T>& pointer) + { + this->reset(pointer.get()); + } + + + /** + * Get rereference to internal pointer. + * + * \return reference to internal pointer + */ + JClass_t* const& getReference() const + { + return __p; + } + + + /** + * Get rereference to internal pointer. + * + * \return reference to internal pointer + */ + JClass_t* & getReference() + { + return __p; + } + + protected: + JClass_t* __p; //!< pointer to object + }; +} + +#endif diff --git a/jpp/JLang/JSTDTypes.hh b/jpp/JLang/JSTDTypes.hh new file mode 100644 index 0000000..9811aaa --- /dev/null +++ b/jpp/JLang/JSTDTypes.hh @@ -0,0 +1,29 @@ +#ifndef __JLANG__JSTDTYPES__ +#define __JLANG__JSTDTYPES__ + +/** + * \file + * + * Forward declarations of STD containers. + * \author mdejong + */ + +namespace std { + template<class JElement_t, class JAllocator_t> class vector; + template<class JElement_t, class JComparator_t, class JAllocator_t> class set; + template<class JElement_t, class JComparator_t, class JAllocator_t> class multiset; + template<class JFirst_t, class JSecond_t> class pair; + template<class JKey_t, class JValue_t, class JComparator_t, class JAllocator_t> class map; + template<class JKey_t, class JValue_t, class JComparator_t, class JAllocator_t> class multimap; + template<class Category, class T, class Distance, class Pointer, class Reference> struct iterator; +#ifdef _GLIBCXX_USE_CXX11_ABI + inline namespace __cxx11 { + template<class JElement_t, class JAllocator_t> class list; + } +#else + template<class JElement_t, class JAllocator_t> class list; +#endif +} + +#endif + diff --git a/jpp/JLang/JSharedCounter.hh b/jpp/JLang/JSharedCounter.hh new file mode 100644 index 0000000..54bddba --- /dev/null +++ b/jpp/JLang/JSharedCounter.hh @@ -0,0 +1,98 @@ +#ifndef __JLANG__JSHAREDCOUNTER__ +#define __JLANG__JSHAREDCOUNTER__ + +#include <cstdlib> + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + + /** + * Shared counter. + */ + class JSharedCounter + { + public: + /** + * Default constructor. + */ + JSharedCounter() : + counter(NULL) + {} + + + /** + * Initialise counter. + */ + void initialise() + { + detach(); + + counter = new int(1); + } + + + /** + * Attach this counter to given shared counter object. + * + * \param object shared counter + */ + void attach(const JSharedCounter& object) + { + detach(); + + counter = object.counter; + + if (counter != NULL) { + ++(*counter); + } + } + + + /** + * Detach. + * + * \return true if counter at zero; else false + */ + bool detach() + { + if (counter != NULL) { + + if (--(*counter) == 0) { + + delete counter; + + counter = NULL; + + return true; + } + + counter = NULL; + } + + return false; + } + + + /** + * Get count + * + * \return count + */ + const int getCount() + { + return (counter != NULL ? *counter : 0); + } + + protected: + int* counter; + }; +} + +#endif diff --git a/jpp/JLang/JSharedPointer.hh b/jpp/JLang/JSharedPointer.hh new file mode 100644 index 0000000..f0d6fae --- /dev/null +++ b/jpp/JLang/JSharedPointer.hh @@ -0,0 +1,211 @@ +#ifndef __JLANG__JSHAREDPOINTER__ +#define __JLANG__JSHAREDPOINTER__ + +#include "JLang/JSharedCounter.hh" +#include "JLang/JMemory.hh" +#include "JLang/JStorage.hh" + + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + + /** + * The template JSharedPointer class can be used to share a pointer to an object. + * The object pointed to is deleted when the shared counter is zero, + * i.e.\ when no-one shares the object. + * It is possible to create a container with shared pointers. + * The first template argument refers to the data type pointed to + * and the second to the memory management policy. + */ + template<class JClass_t, template<class> class JMemory_t = JNew> + class JSharedPointer : + public JSharedCounter, + public JStorage<JClass_t, JMemory_t> + { + public: + + typedef JPointer<JClass_t> pointer_type; + typedef JStorage<JClass_t, JMemory_t> storage_type; + + using JAbstractPointer<JClass_t>::reset; + + + /** + * Default constructor. + */ + JSharedPointer() + {} + + + /** + * Copy constructor. + * The reference counter of the shared object is incremented by one. + * + * \param object shared pointer + */ + JSharedPointer(const JSharedPointer& object) + { + if (object.is_valid()) { + this->set(object); + } + } + + + /** + * Assignment constructor. + * If the pointer is valid, the reference counter of the shared object pointed to + * is initialised to one. + * + * \param p pointer to derived class object + */ + template<class JDerived_t> + JSharedPointer(JDerived_t* p) + { + if (p != NULL) { + this->set(p); + } + } + + + /** + * Destructor. + * The reference counter is decremented by one and + * the object pointed to is deleted when the reference counter is zero. + */ + ~JSharedPointer() + { + if (this->detach()) { + storage_type::reset(); + } + } + + + /** + * Get shared pointer. + * + * \return this shared pointer + */ + const JSharedPointer& getSharedPointer() const + { + return static_cast<const JSharedPointer&>(*this); + } + + + /** + * Get shared pointer. + * + * \return this shared pointer + */ + JSharedPointer& getSharedPointer() + { + return static_cast<JSharedPointer&>(*this); + } + + + /** + * Set shared pointer. + * + * \param object shared pointer + */ + void setSharedPointer(const JSharedPointer& object) + { + if (this->get() != object.get()) { + + this->reset(); + + if (object.is_valid()) { + this->set(object); + } + } + } + + + /** + * Assignment operator. + * The reference counter is decremented by one and + * the object pointed to previously is deleted when its reference counter is zero. + * The reference counter of the shared object is incremented by one. + * + * \param object shared pointer + * \return this shared pointer + */ + JSharedPointer& operator=(const JSharedPointer& object) + { + this->setSharedPointer(object); + + return *this; + } + + + /** + * Assignment operator. + * The reference counter is decremented by one and + * the object pointed to previously is deleted when its reference counter is zero. + * If the pointer is valid, the reference counter of the shared object pointed to + * is initialised to one. + * + * \param p pointer to derived class object + * \return this shared pointer + */ + template<class JDerived_t> + JSharedPointer& operator=(JDerived_t* p) + { + this->reset(p); + + return *this; + } + + + /** + * Reset pointer. + * The reference counter is decremented by one and + * the object pointed to previously is deleted when its reference counter is zero. + */ + virtual void reset() override + { + if (this->detach()) { + storage_type::reset(); + } + + pointer_type::reset(); + } + + + protected: + /** + * Set pointer. + * The reference counter of the shared object pointed to is incremented by one. + * + * \param object shared pointer + */ + void set(const JSharedPointer& object) + { + pointer_type::set(object.get()); + + this->attach(object); + } + + + /** + * Set pointer. + * The reference counter of the shared object pointed to is initialised to one. + * + * \param p pointer to derived class object + */ + virtual void set(JClass_t* p) override + { + pointer_type::set(p); + + this->initialise(); + } + }; +} + +#endif diff --git a/jpp/JLang/JSinglePointer.hh b/jpp/JLang/JSinglePointer.hh new file mode 100644 index 0000000..1832951 --- /dev/null +++ b/jpp/JLang/JSinglePointer.hh @@ -0,0 +1,113 @@ +#ifndef __JLANG__JSINGLEPOINTER__ +#define __JLANG__JSINGLEPOINTER__ + +#include "JLang/JStorage.hh" + + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + /** + * The template JSinglePointer class can be used to hold a pointer to an object. + * The object pointed to is deleted at destruction. + * It is possible to create a container with single pointers. + * The first template argument refers to the data type pointed to + * and the second to the memory management policy. + */ + template<class JClass_t, template<class> class JMemory_t = JNew> + class JSinglePointer : + public JStorage<JClass_t, JMemory_t> + { + public: + + /** + * Default constructor. + */ + JSinglePointer() + {} + + + /** + * Copy constructor. + * The ownership of the object pointed to is transferred to this single pointer. + * + * \param object single pointer + */ + JSinglePointer(const JSinglePointer& object) + { + this->set(object.get()); + + const_cast<JSinglePointer&>(object).set(NULL); + } + + + /** + * Constructor. + * + * \param p pointer to object + */ + JSinglePointer(JClass_t* p) + { + this->set(p); + } + + + /** + * Destructor. + */ + ~JSinglePointer() + { + this->reset(); + } + + + /** + * Assignment operator. + * The object pointed to previously is deleted. + * The ownership of the object pointed to is transferred to this single pointer. + * + * \param object single pointer + * \return this single pointer + */ + JSinglePointer& operator=(const JSinglePointer& object) + { + if (this->get() != object.get()) { + + this->reset(); + + if (object.is_valid()) { + + this->set(object.get()); + + const_cast<JSinglePointer&>(object).set(NULL); + } + } + + return *this; + } + + + /** + * Assignment operator. + * The object pointed to previously is deleted. + * + * \param p pointer to derived class object + * \return this single pointer + */ + template<class JDerived_t> + JSinglePointer& operator=(JDerived_t* p) + { + this->reset(p); + + return *this; + } + }; +} + +#endif diff --git a/jpp/JLang/JStorage.hh b/jpp/JLang/JStorage.hh new file mode 100644 index 0000000..159996e --- /dev/null +++ b/jpp/JLang/JStorage.hh @@ -0,0 +1,98 @@ +#ifndef __JLANG__JSTORAGE__ +#define __JLANG__JSTORAGE__ + +#include "JLang/JPointer.hh" +#include "JLang/JMemory.hh" + + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + /** + * Template storage class. + * This class extends the JPointer class with storage capabilities. + * The first template argument refers to the data type pointed to + * and the second (optional argument) to the memory management policy (see e.g.\ JMemory.hh). + * The method create() can be used to allocate memory; + * the method reset() releases the allocated memory. + */ + template<class JClass_t, template<class> class JMemory_t = JNew> + class JStorage : + public JPointer <JClass_t>, + public JMemory_t<JClass_t> + { + public: + + typedef JPointer <JClass_t> pointer_type; + typedef JMemory_t<JClass_t> memory_type; + + using pointer_type::reset; + + + /** + * Reset pointer. + * The allocated memory is released. + */ + virtual void reset() override + { + if (this->is_valid()) { + this->release(); + } + + pointer_type::reset(); + } + + + /** + * Recreate object in memory. + * A new object is created if no memory is allocated yet, + * else the previously created object is maintained. + */ + void recreate() + { + if (!this->is_valid()) { + this->set(memory_type::create()); + } + } + + + /** + * Create object in memory. + * The memory allocated by a previously created object will be released. + */ + void create() + { + this->reset(memory_type::create()); + } + + + /** + * Create array of objects in memory. + * The memory allocated by previously created objects will be released. + * + * \param size number of elements + */ + void create(const unsigned int size) + { + this->reset(memory_type::create(size)); + } + + + protected: + /** + * Release memory. + */ + void release() + { + memory_type::release(this->get()); + } + }; +} + +#endif diff --git a/jpp/JLang/JType.hh b/jpp/JLang/JType.hh new file mode 100644 index 0000000..6a547c4 --- /dev/null +++ b/jpp/JLang/JType.hh @@ -0,0 +1,37 @@ +#ifndef __JLANG__JTYPE__ +#define __JLANG__JTYPE__ + + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + /** + * Auxiliary class for a type holder. + * This class can be used to transfer a template class to a method argument. + */ + template<class T> + struct JType { + + typedef T data_type; + }; + + + /** + * Get type. + * + * \return type + */ + template<class T> + inline JType<T> getType() + { + return JType<T>(); + } +} + +#endif diff --git a/jpp/JLang/JVectorize.hh b/jpp/JLang/JVectorize.hh new file mode 100644 index 0000000..f99038f --- /dev/null +++ b/jpp/JLang/JVectorize.hh @@ -0,0 +1,193 @@ +#ifndef __JLANG__JVECTORIZE__ +#define __JLANG__JVECTORIZE__ + +#include <vector> +#include <iterator> + +#include "JLang/JSTDTypes.hh" +#include "JLang/JClass.hh" + + +/** + * \file + * Auxiliary methods to convert data members or return values of member methods of a set of objects to a single vector. + * \author mdejong + */ +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + /** + * Auxiliary data structure for return type of make methods. + */ + template<class JElement_t, class JAllocator_t = std::allocator<JElement_t> > + struct array_type : + public std::vector<JElement_t, JAllocator_t> + {}; + + + /** + * Method to create array of values. + * + * \param array c-array of values + * \return data + */ + template<class JValue_t, size_t N> + inline const array_type<JValue_t>& make_array(const JValue_t (&array)[N]) + { + static array_type<JValue_t> buffer; + + buffer.resize(N); + + for (size_t i = 0; i != N; ++i) { + buffer[i] = array[i]; + } + + return buffer; + } + + + /** + * Method to create array of values. + * + * \param __begin begin of data + * \param __end end of data + * \return data + */ + template<class T> + inline const array_type<typename std::iterator_traits<T>::value_type>& make_array(T __begin, T __end) + { + static array_type<typename std::iterator_traits<T>::value_type> buffer; + + buffer.assign(__begin, __end); + + return buffer; + } + + + /** + * Method to create array of values of data member. + * + * \param __begin begin of data + * \param __end end of data + * \param value pointer to data member + * \return data + */ + template<class T, class JType_t, class JValue_t> + inline const array_type<typename JClass<JValue_t>::value_type>& make_array(T __begin, T __end, JValue_t const JType_t::*value) + { + static array_type<typename JClass<JValue_t>::value_type> buffer; + + buffer.clear(); + + for (T __p = __begin; __p != __end; ++__p) { + buffer.push_back(*__p.*value); + } + + return buffer; + } + + + /** + * Method to create array of return values of member method. + * + * \param __begin begin of data + * \param __end end of data + * \param function pointer to member method + * \return data + */ + template<class T, class JType_t, class JValue_t> + inline const array_type<typename JClass<JValue_t>::value_type>& make_array(T __begin, T __end, JValue_t (JType_t::*function)() const) + { + static array_type<typename JClass<JValue_t>::value_type> buffer; + + buffer.clear(); + + for (T __p = __begin; __p != __end; ++__p) { + buffer.push_back((*__p.*function)()); + } + + return buffer; + } + + + /** + * Method to create array of keys of map. + * + * \param data data + * \return data + */ + template<class JKey_t, class JValue_t, class JComparator_t, class JAllocator_t> + inline const array_type<JKey_t>& get_keys(const std::map<JKey_t, JValue_t, JComparator_t, JAllocator_t>& data) + { + return make_array(data.begin(), data.end(), &std::map<JKey_t, JValue_t, JComparator_t, JAllocator_t>::value_type::first); + } + + + /** + * Method to create array of values of map. + * + * \param data data + * \return data + */ + template<class JKey_t, class JValue_t, class JComparator_t, class JAllocator_t> + inline const array_type<JValue_t>& get_values(const std::map<JKey_t, JValue_t, JComparator_t, JAllocator_t>& data) + { + return make_array(data.begin(), data.end(), &std::map<JKey_t, JValue_t, JComparator_t, JAllocator_t>::value_type::second); + } + + + /** + * Method to exclude outliers from already sorted data.\n + * Note that the part after the returned iterator will be overwritten. + * + * \param __begin begin of data + * \param __end end of data + * \param value pointer to data member, + * \param comparator comparison method + * \return end of sorted data + */ + template<class T, class JResult_t, class JComparator_t> + T make_set(T __begin, + T __end, + JResult_t std::iterator_traits<T>::value_type::*value, + const JComparator_t& comparator) + + { + T p2 = __begin; + T p0 = p2++; + T p1 = p2++; + + if (p0 == __end) { return p0; } + if (p1 == __end) { return p1; } + + if (p2 == __end) { + if (comparator((*p0).*value, (*p1).*value)) + return p2; + else + return p0; + } + + for ( ; p2 != __end; ++p2) { + + if (comparator((*p0).*value, (*p1).*value)) { + if (comparator((*p1).*value, (*p2).*value)) { + *(++p0) = *p1; + *(++p1) = *p2; + } else if (comparator((*p0).*value, (*p2).*value)) { + *p1 = *p2; + } + } else { + if (comparator((*p2).*value, (*p0).*value)) { + *p0 = *p1; + } + *p1 = *p2; + } + } + + return ++p1; + } +} + +#endif diff --git a/jpp/JLang/JVoid.hh b/jpp/JLang/JVoid.hh new file mode 100644 index 0000000..f9888ac --- /dev/null +++ b/jpp/JLang/JVoid.hh @@ -0,0 +1,26 @@ +#ifndef __JLANG__JVOID__ +#define __JLANG__JVOID__ + + +/** + * \author mdejong + */ + +namespace JLANG {} +namespace JPP { using namespace JLANG; } + +namespace JLANG { + + + /** + * Auxiliary class for void type definition. + * This class can be used to evaluate the validity of a type definition. + */ + template<class T> + struct JVoid + { + typedef void type; + }; +} + +#endif diff --git a/jpp/JLang/gzstream.h b/jpp/JLang/gzstream.h new file mode 100644 index 0000000..4b40bbc --- /dev/null +++ b/jpp/JLang/gzstream.h @@ -0,0 +1,229 @@ +/** + * \author mdejong + */ + +// ============================================================================ +// gzstream, C++ iostream classes wrapping the zlib compression library. +// Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// ============================================================================ +// +// File : gzstream.h +// Revision : $Revision: 1.5 $ +// Revision_date : $Date: 2002/04/26 23:30:15 $ +// Author(s) : Deepak Bandyopadhyay, Lutz Kettner +// +// Standard streambuf implementation following Nicolai Josuttis, "The +// Standard C++ Library". +// ============================================================================ + +#ifndef GZSTREAM_H +#define GZSTREAM_H 1 + +// standard C++ with new header file names and std:: namespace +#include <iostream> +#include <fstream> +#include <zlib.h> +#include <string> +#include <string.h> + +#ifdef GZSTREAM_NAMESPACE +namespace GZSTREAM_NAMESPACE { +#endif + +// ---------------------------------------------------------------------------- +// Internal classes to implement gzstream. See below for user classes. +// ---------------------------------------------------------------------------- + +class gzstreambuf : public std::streambuf { +private: + static const int bufferSize = 47+256; // size of data buff + // totals 512 bytes under g++ for igzstream at the end. + + gzFile file; // file handle for compressed file + char buffer[bufferSize]; // data buffer + char opened; // open/close state of stream + int mode; // I/O mode + + + int flush_buffer() { + // Separate the writing of the buffer from overflow() and + // sync() operation. + int w = pptr() - pbase(); + if ( gzwrite( file, pbase(), w) != w) + return EOF; + pbump( -w); + return w; + } +public: + gzstreambuf() : opened(0) { + setp( buffer, buffer + (bufferSize-1)); + setg( buffer + 4, // beginning of putback area + buffer + 4, // read position + buffer + 4); // end position + // ASSERT: both input & output capabilities will not be used together + } + int is_open() const { return opened; } + + ~gzstreambuf() { close(); } + gzstreambuf* open( const char* name, int open_mode) { + if ( is_open()) + return (gzstreambuf*)0; + mode = open_mode; + // no append nor read/write mode + if ((mode & std::ios::ate) || (mode & std::ios::app) + || ((mode & std::ios::in) && (mode & std::ios::out))) + return (gzstreambuf*)0; + char fmode[10]; + char* fmodeptr = fmode; + if ( mode & std::ios::in) + *fmodeptr++ = 'r'; + else if ( mode & std::ios::out) + *fmodeptr++ = 'w'; + *fmodeptr++ = 'b'; + *fmodeptr = '\0'; + file = gzopen( name, fmode); + if (file == 0) + return (gzstreambuf*)0; + opened = 1; + setg( buffer + 4, // beginning of putback area + buffer + 4, // read position + buffer + 4); // end position + return this; + } + + gzstreambuf * close() { + if ( is_open()) { + sync(); + opened = 0; + if ( gzclose( file) == Z_OK) + return this; + } + return (gzstreambuf*)0; + } + + virtual int underflow() { // used for input buffer only + if ( gptr() && ( gptr() < egptr())) + return * reinterpret_cast<unsigned char *>( gptr()); + + if ( ! (mode & std::ios::in) || ! opened) + return EOF; + // Josuttis' implementation of inbuf + int n_putback = gptr() - eback(); + if ( n_putback > 4) + n_putback = 4; + memcpy( buffer + (4 - n_putback), gptr() - n_putback, n_putback); + + int num = gzread( file, buffer+4, bufferSize-4); + if (num <= 0) // ERROR or EOF + return EOF; + + // reset buffer pointers + setg( buffer + (4 - n_putback), // beginning of putback area + buffer + 4, // read position + buffer + 4 + num); // end of buffer + + // return next character + return * reinterpret_cast<unsigned char *>( gptr()); + } + + virtual int overflow( int c=EOF) { // used for output buffer only + if ( ! ( mode & std::ios::out) || ! opened) + return EOF; + if (c != EOF) { + *pptr() = c; + pbump(1); + } + if ( flush_buffer() == EOF) + return EOF; + return c; + } + + virtual int sync() { + // Changed to use flush_buffer() instead of overflow( EOF) + // which caused improper behavior with std::endl and flush(), + // bug reported by Vincent Ricard. + if ( pptr() && pptr() > pbase()) { + if ( flush_buffer() == EOF) + return -1; + } + return 0; + } +}; + +class gzstreambase : virtual public std::ios { +protected: + gzstreambuf buf; +public: + + gzstreambase() { init(&buf); } + gzstreambase( const char* name, int mode) { + init( &buf); + open( name, mode); + } + ~gzstreambase() { + buf.close(); + } + void open( const char* name, int open_mode) { + if ( ! buf.open( name, open_mode)) + clear( rdstate() | std::ios::badbit); + } + + void close() { + if ( buf.is_open()) { + if ( ! buf.close()) + clear( rdstate() | std::ios::badbit ); + else + clear(); + } + } + gzstreambuf* rdbuf() { return &buf; } + bool is_open() const { return buf.is_open(); } +}; + +// ---------------------------------------------------------------------------- +// User classes. Use igzstream and ogzstream analogously to ifstream and +// ofstream respectively. They read and write files based on the gz* +// function interface of the zlib. Files are compatible with gzip compression. +// ---------------------------------------------------------------------------- + +class igzstream : public gzstreambase, public std::istream { +public: + igzstream() : std::istream( &buf) {} + igzstream( const char* name, int open_mode = std::ios::in) + : gzstreambase( name, open_mode), std::istream( &buf) {} + void open( const char* name, int open_mode = std::ios::in) { + gzstreambase::open( name, open_mode); + } +}; + +class ogzstream : public gzstreambase, public std::ostream { +public: + ogzstream() : std::ostream( &buf) {} + ogzstream( const char* name, int mode = std::ios::out) + : gzstreambase( name, mode), std::ostream( &buf) {} + void open( const char* name, int open_mode = std::ios::out) { + gzstreambase::open( name, open_mode); + } +}; + +#ifdef GZSTREAM_NAMESPACE +} // namespace GZSTREAM_NAMESPACE +#endif + +#endif // GZSTREAM_H +// ============================================================================ +// EOF // diff --git a/jpp/JMath/JCalculator.hh b/jpp/JMath/JCalculator.hh new file mode 100644 index 0000000..836eeb6 --- /dev/null +++ b/jpp/JMath/JCalculator.hh @@ -0,0 +1,93 @@ +#ifndef __JMATH__JCALCULATOR__ +#define __JMATH__JCALCULATOR__ + + +/** + * \author mdejong + */ + +namespace JMATH {} +namespace JPP { using namespace JMATH; } + +namespace JMATH { + + /** + * Auxiliary class for arithmetic operations on objects. + */ + template<class T, int N = 0> + struct JCalculator : + public T // object + { + /** + * Set calculator value. + * + * \param value value + * \return this calculator + */ + JCalculator& set(const T& value) + { + static_cast<T&>(*this) = value; + + return *this; + } + + static JCalculator calculator; // calculator + }; + + + /** + * Calculator. + */ + template<class T, int N> + JCalculator<T,N> JCalculator<T,N>::calculator; + + + /** + * Product evaluation of objects. + * + * \param first first object + * \param second second object + * \return calculator + */ + template<class T> + inline const JCalculator<T, 1>& operator*(const T& first, const T& second) + { + JCalculator<T, 1>::calculator.mul(first, second); + + return JCalculator<T, 1>::calculator; + } + + + /** + * Recursive product evaluation of objects. + * + * \param first first object + * \param second second object + * \return calculator + */ + template<class T, int N> + inline const JCalculator<T, N+1>& operator*(const T& first, const JCalculator<T, N>& second) + { + JCalculator<T, N+1>::calculator.mul(first, second); + + return JCalculator<T, N+1>::calculator; + } + + + /** + * Recursive product evaluation of objects. + * + * \param first first object + * \param second second object + * \return calculator + */ + template<class T, int N> + inline const JCalculator<T, N+1>& operator*(const JCalculator<T, N>& first, const T& second) + { + JCalculator<T, N+1>::calculator.mul(first, second); + + return JCalculator<T, N+1>::calculator; + } +} + +#endif diff --git a/jpp/JMath/JConstants.hh b/jpp/JMath/JConstants.hh new file mode 100644 index 0000000..5ae6452 --- /dev/null +++ b/jpp/JMath/JConstants.hh @@ -0,0 +1,31 @@ +#ifndef __JMATH__JCONSTANTS__ +#define __JMATH__JCONSTANTS__ + +#include <math.h> + + +/** + * \file + * Mathematical constants. + * \author mdejong + */ +namespace JMATH {} +namespace JPP { using namespace JMATH; } + +namespace JMATH { + + /** + * Mathematical constants. + */ + static const double PI = acos(-1.0); //!< pi + static const double EULER = 0.577215664901533; //!< Euler number + + /** + * Computing quantities. + */ + static const long long int KILOBYTE = 1024; //! Number of bytes in a kilo-byte + static const long long int MEGABYTE = KILOBYTE*KILOBYTE; //! Number of bytes in a mega-byte + static const long long int GIGABYTE = MEGABYTE*KILOBYTE; //! Number of bytes in a giga-byte +} + +#endif diff --git a/jpp/JMath/JLimits.hh b/jpp/JMath/JLimits.hh new file mode 100644 index 0000000..cebfe3e --- /dev/null +++ b/jpp/JMath/JLimits.hh @@ -0,0 +1,126 @@ +#ifndef __JMATH__JLIMITS__ +#define __JMATH__JLIMITS__ + +#include <limits> + +/** + * \file + * + * Definition of minimum and maximum values for any class. + * \author mdejong + */ +namespace JMATH {} +namespace JPP { using namespace JMATH; } + +namespace JMATH { + + /** + * Auxiliary class for minimum and maximum values for any class. + */ + template<class T, bool __is_specialized__ = std::numeric_limits<T>::is_specialized> + struct JLimits; + + + /** + * Template spacialisation of JMATH::JLimits for numerical values. + */ + template<class T> + struct JLimits<T, true> { + /** + * Get minimum possible value. + * + * \return minimum possible value + */ + static T min() + { + return std::numeric_limits<T>::min(); + } + + + /** + * Get maximum possible value. + * + * \return maximum possible value + */ + static T max() + { + return std::numeric_limits<T>::max(); + } + + static const bool is_specialized = true; + }; + + + /** + * Template spacialisation of JMATH::JRandom for other data types. + * + * The given template class should provide for the methods: + * <pre> + * static T %min(); + * static T %max(); + * </pre> + */ + template<class T> + struct JLimits<T, false> { + /** + * Get minimum possible value. + * + * \return minimum possible value + */ + static T min() + { + return T::min(); + } + + + /** + * Get maximum possible value. + * + * \return maximum possible value + */ + static T max() + { + return T::max(); + } + + static const bool is_specialized = false; + }; + + + /** + * Get minimum possible value. + * + * \return minimum possible value + */ + template<> + inline float JLimits<float, true>::min() + { + return std::numeric_limits<float>::lowest(); + } + + + /** + * Get minimum possible value. + * + * \return minimum possible value + */ + template<> + inline double JLimits<double, true>::min() + { + return std::numeric_limits<double>::lowest(); + } + + + /** + * Get minimum possible value. + * + * \return minimum possible value + */ + template<> + inline long double JLimits<long double, true>::min() + { + return std::numeric_limits<long double>::lowest(); + } +} + +#endif diff --git a/jpp/JMath/JMath.hh b/jpp/JMath/JMath.hh new file mode 100644 index 0000000..8c37cc9 --- /dev/null +++ b/jpp/JMath/JMath.hh @@ -0,0 +1,591 @@ +#ifndef __JMATH__ +#define __JMATH__ + +#include <cmath> +#include <iterator> + +#include "JLang/JNullType.hh" +#include "JLang/JClass.hh" +#include "JLang/JBool.hh" +#include "JLang/JVectorize.hh" +#include "JLang/JException.hh" +#include "JMath/JZero.hh" +#include "JMath/JCalculator.hh" + + +/** + * \file + * + * Base class for data structures with artithmetic capabilities. + * \author mdejong + */ +namespace JMATH {} +namespace JPP { using namespace JMATH; } + +namespace JGEOMETRY3D { class JQuaternion3D; } + +namespace JMATH { + + using JLANG::JNullType; + using JLANG::array_type; + using JLANG::JDivisionByZero; + + + /** + * Power \f$x^y\f$. + * + * \param x value + * \param y power + * \return result + */ + template<class T> + inline T pow(const T& x, const double y); + + + /** + * Auxiliary class to hide data type specific methods. + */ + struct JMath_t { + /** + * Friend declaration of global method. + */ + template<class T> + friend T JMATH::pow(const T&, const double y); + + private: + /** + * Power \f$x^y\f$. + * This method corresponds to primitive data types. + * + * \param x value + * \param y power + * \param option true + * \return result + */ + template<class T> + static inline T pow(const T& x, const double y, const JLANG::JBool<true> option) + { + return std::pow(x, y); + } + + + /** + * Power \f$x^y\f$. + * Power. + * This method corresponds to non-primitive data types. + * + * \param x value + * \param y power + * \param option false + * \return result + */ + template<class T> + static inline T pow(const T& x, const double y, const JLANG::JBool<false> option) + { + return T(x).pow(y); + } + }; + + + /** + * Power \f$x^y\f$. + * + * \param x value + * \param y power + * \return result + */ + template<class T> + inline T pow(const T& x, const double y) + { + using namespace JPP; + + return JMath_t::pow(x, y, JBool<JClass<T>::is_primitive>()); + } + + + /** + * Auxiliary base class for aritmetic operations of derived class types. + */ + template<class JFirst_t, class JSecond_t = JNullType> + struct JMath; + + + /** + * Template base class for data structures with arithmetic capabilities. + * + * This class provides for the operators <tt> - += -= *= /= + - * / </tt>.\n + * To this end, the template parameter should privide for the corresponding member methods: + * <pre> + * T& negate(); + * T& add(const T& object); + * T& sub(const T& object); + * T& mul(const double factor); + * T& div(const double factor); + * </pre> + * + * This class also provides for the object multiplication operators <tt>*= *</tt>.\n + * To this end, the template parameter should then also provide for the member method: + * <pre> + * T& mul(const T&, const T&); + * </pre> + * + * This class adds interpolation functionality.\n + * This class uses in-class friend operators (see Barton-Nackman trick). + */ + template<class T> + struct JMath<T, JNullType> { + /** + * Affirm operator. + * + * \param object this object + * \return affirmed object + */ + friend T operator+(const T& object) + { + return T(object); + } + + + /** + * Negate operator. + * + * \param object this object + * \return negated object + */ + friend T operator-(const T& object) + { + return T(object).negate(); + } + + + /** + * Add object. + * + * \param object this object + * \param value value + * \return this object + */ + friend T& operator+=(T& object, const T& value) + { + return object.add(value); + } + + + /** + * Subtract object. + * + * \param object this object + * \param value value + * \return this object + */ + friend T& operator-=(T& object, const T& value) + { + return object.sub(value); + } + + + /** + * Scale object. + * + * \param object this object + * \param factor factor + * \return this object + */ + friend T& operator*=(T& object, const double factor) + { + return object.mul(factor); + } + + + /** + * Scale object. + * + * \param object this object + * \param factor factor + * \return this object + */ + friend T& operator/=(T& object, const double factor) + { + return object.div(factor); + } + + + /** + * Add objects. + * + * \param first first object + * \param second second object + * \return result object + */ + friend T operator+(const T& first, const T& second) + { + return JCalculator<T>::calculator.set(first).add(second); + } + + + /** + * Subtract objects. + * + * \param first first object + * \param second second object + * \return result object + */ + friend T operator-(const T& first, const T& second) + { + return JCalculator<T>::calculator.set(first).sub(second); + } + + + /** + * Scale object. + * + * \param object object + * \param factor factor + * \return object + */ + friend T operator*(const T& object, const double factor) + { + return JCalculator<T>::calculator.set(object).mul(factor); + } + + + /** + * Scale object. + * + * \param factor factor + * \param object object + * \return object + */ + friend T operator*(const double factor, const T& object) + { + return JCalculator<T>::calculator.set(object).mul(factor); + } + + + /** + * Scale object. + * + * \param object object + * \param factor factor + * \return object + */ + friend T operator/(const T& object, const double factor) + { + return JCalculator<T>::calculator.set(object).div(factor); + } + + + /** + * Multiply with object. + * + * \param object object + * \return result object + */ + T& mul(const T& object) + { + return static_cast<T&>(*this) = JCalculator<T>::calculator.mul(static_cast<const T&>(*this), object); + } + + + /** + * Multiply with object. + * + * \param first first object + * \param second second object + * \return result object + */ + friend T& operator*=(T& first, const T& second) + { + return first.mul(second); + } + + + /** + * Multiply objects. + * + * \param first first object + * \param second second object + * \return calculator + */ + friend const JCalculator<T, 1>& operator*(const T& first, const T& second) + { + JCalculator<T, 1>::calculator.mul(first, second); + + return JCalculator<T, 1>::calculator; + } + + + /** + * Interpolation between objects. + * The result is equal to <tt>*this = (1 - alpha) * (*this) + (alpha) * (object)</tt>. + * + * \param object object + * \param alpha interpolation factor <tt>[0, 1]</tt> + * \return this object + */ + T& interpolate(const T& object, const double alpha) + { + static_cast<T*>(this)->mul(1.0 - alpha); + static_cast<T*>(this)->add(T(object).mul(alpha)); + + return static_cast<T&>(*this); + } + }; + + + /** + * Specialisation of JMath for two data types. + * + * This class provides for the object multiplication operators <tt>*= *</tt>. + * The template parameter should then have the member method: + * <pre> + * JFirst_t& mul(const JFirst_t&, const JSecond_t&); + * </pre> + * where <tt>JFirst_t</tt> and <tt>JSecond_t</tt> refer to the first and second template parameter, respectively. + * + * This class uses in-class friend operators (see Barton-Nackman trick). + */ + template<class JFirst_t, class JSecond_t> + struct JMath + { + /** + * Multiply with object. + * + * \param object object + * \return result object + */ + JFirst_t& mul(const JSecond_t& object) + { + return static_cast<JFirst_t&>(*this) = JCalculator<JFirst_t>::calculator.mul(static_cast<const JFirst_t&>(*this), object); + } + + + /** + * Multiply with object. + * + * \param first first object + * \param second second object + * \return result object + */ + friend JFirst_t& operator*=(JFirst_t& first, const JSecond_t& second) + { + return first.mul(second); + } + + + /** + * Multiply objects. + * + * \param first first object + * \param second second object + * \return result object + */ + friend JFirst_t operator*(const JFirst_t& first, const JSecond_t& second) + { + return JFirst_t(first).mul(second); + } + }; + + + /** + * Interpolation between objects. + * The result is equal to <tt>result = (1 - alpha) * (first) + (alpha) * (second)</tt>. + * + * \param first first object + * \param second second object + * \param alpha interpolation factor <tt>[0, 1]</tt> + * \return result + */ + template<class T> + inline T interpolate(const T& first, + const T& second, + const double alpha) + { + return T(first).interpolate(second, alpha); + } + + + /** + * Auxiliary class to determine average of set of values. + */ + template<class JValue_t> + struct JAverage { + /** + * Default constructor. + */ + JAverage() : + value (getZero<JValue_t>()), + weight(0.0) + {} + + + /** + * Constructor. + * + * \param __begin begin of data + * \param __end end of data + */ + template<class T> + JAverage(T __begin, T __end) : + value (getZero<JValue_t>()), + weight(0.0) + { + for (T i = __begin; i != __end; ++i) { + value += (*i); + weight += 1.0; + } + } + + + /** + * Reset. + */ + void reset() + { + this->value = getZero<JValue_t>(); + this->weight = 0.0; + } + + + /** + * Type conversion operator. + * + * \return value + */ + operator JValue_t () const + { + if (weight != 0.0) + return value * (1.0 / weight); + else + THROW(JDivisionByZero, "Invalid weight."); + } + + + /** + * Put value. + * + * \param value value + * \param w weight + */ + void put(const JValue_t& value, const double w = 1.0) + { + this->value += value; + this->weight += w; + } + + private: + JValue_t value; + double weight; + }; + + + /** + * Template definition so that compiler error is generated if implementation is missing (see JEigen3D.hh). + */ + template<> + class JAverage<JGEOMETRY3D::JQuaternion3D>; + + + /** + * Get average. + * + * \param __begin begin of data + * \param __end end of data + * \return average value + */ + template<class T> + typename std::iterator_traits<T>::value_type getAverage(T __begin, T __end) + { + typedef typename std::iterator_traits<T>::value_type value_type; + + return JAverage<value_type>(__begin, __end); + } + + + /** + * Get average. + * + * \param array c-array of values + * \return average value + */ + template<class JValue_t, size_t N> + inline JValue_t getAverage(const JValue_t (&array)[N]) + { + typedef JValue_t value_type; + + return JAverage<value_type>((const value_type*) array, (const value_type*) array + N); + } + + + /** + * Get average. + * + * \param buffer input data + * \return average value + */ + template<class JElement_t, class JAllocator_t> + JElement_t getAverage(const array_type<JElement_t, JAllocator_t>& buffer) + { + return JAverage<JElement_t>(buffer.begin(), buffer.end()); + } + + + /** + * Get average. + * + * \param __begin begin of data + * \param __end end of data + * \param value default value + * \return average value + */ + template<class T> + typename std::iterator_traits<T>::value_type getAverage(T __begin, T __end, typename std::iterator_traits<T>::value_type value) + { + try { + return getAverage(__begin, __end); + } + catch(const std::exception&) { + return value; + } + } + + + /** + * Get average. + * + * \param array c-array of values + * \param value default value + * \return average value + */ + template<class JValue_t, size_t N> + inline JValue_t getAverage(const JValue_t (&array)[N], typename JLANG::JClass<JValue_t>::argument_type value) + { + try { + return getAverage(array); + } + catch(const std::exception&) { + return value; + } + } + + + /** + * Get average. + * + * \param buffer input data + * \param value default value + * \return average value + */ + template<class JElement_t, class JAllocator_t> + JElement_t getAverage(const array_type<JElement_t, JAllocator_t>& buffer, typename JLANG::JClass<JElement_t>::argument_type value) + { + try { + return getAverage(buffer); + } + catch(const std::exception&) { + return value; + } + } +} + +#endif diff --git a/jpp/JMath/JMathSupportkit.hh b/jpp/JMath/JMathSupportkit.hh new file mode 100644 index 0000000..cfba6ad --- /dev/null +++ b/jpp/JMath/JMathSupportkit.hh @@ -0,0 +1,231 @@ +#ifndef __JMATHSUPPORTKIT__ +#define __JMATHSUPPORTKIT__ + +#include <limits> +#include <cmath> + +#include "JMath/JConstants.hh" +#include "JLang/JException.hh" + + +/** + * \file + * + * Auxiliary methods for mathematics. + * \author mdejong + */ + +namespace JMATH {} +namespace JPP { using namespace JMATH; } + +namespace JMATH { + + using JLANG::JValueOutOfRange; + + + /** + * Gauss function (normalised to 1 at x = 0). + * + * \param x x + * \param sigma sigma + * \return function value + */ + inline double gauss(const double x, const double sigma) + { + const double u = x / sigma; + + if (fabs(u) < 10.0) + return exp(-0.5*u*u); + else + return 0.0; + } + + + /** + * Gauss function (normalised to 1 at x = x0). + * + * \param x x + * \param x0 central value + * \param sigma sigma + * \return function value + */ + inline double gauss(const double x, const double x0, const double sigma) + { + return gauss(x - x0, sigma); + } + + + /** + * Normalised Gauss function. + * + * \param x x + * \param sigma sigma + * \return function value + */ + inline double Gauss(const double x, const double sigma) + { + return gauss(x, sigma) / sqrt(2.0*PI) / sigma; + } + + + /** + * Normalised Gauss function. + * + * \param x x + * \param x0 central value + * \param sigma sigma + * \return function value + */ + inline double Gauss(const double x, const double x0, const double sigma) + { + return Gauss(x - x0, sigma); + } + + + /** + * Incomplete gamma function. + * + * \param a a + * \param x x + * \return function value + */ + inline double Gamma(const double a, const double x) + { + using namespace std; + + const int max = 100; + + if (x < 0.0) { THROW(JValueOutOfRange, "x < 0 " << x); } + if (a <= 0.0) { THROW(JValueOutOfRange, "a <= 0 " << a); } + + const double gln = lgamma(a); + + if (x < a + 1.0) { + + if (x <= 0.0) { + THROW(JValueOutOfRange, "x <= 0 " << x); + } + + double ap = a; + double sum = 1.0 /a; + double del = sum; + + for (int i = 1; i != max; ++i) { + + ap += 1.0; + del *= x/ap; + sum += del; + + if (fabs(del) < fabs(sum)*numeric_limits<double>::epsilon()) { + return sum*exp(-x + a*log(x) - gln); + } + } + + } else { + + double b = x + 1.0 - a; + double c = numeric_limits<double>::epsilon() / numeric_limits<double>::min(); + double d = 1.0 / b; + double h = d; + + for (int i = 1; i != max; ++i) { + + const double an = -i * (i-a); + + b += 2.0; + d = an*d + b; + + if (fabs(d) < numeric_limits<double>::min()) { + d = numeric_limits<double>::min(); + } + + c = b + an/c; + + if (fabs(c) < numeric_limits<double>::min()) { + c = numeric_limits<double>::min(); + } + + d = 1.0/d; + + const double del = d*c; + + h *= del; + + if (fabs(del - 1.0) < numeric_limits<double>::epsilon()) { + return 1.0 - exp(-x + a*log(x) - gln) * h; + } + } + + THROW(JValueOutOfRange, "a " << a); + } + + return 0.0; + } + + + /** + * Legendre polynome. + * + * \param n degree + * \param x x + * \return function value + */ + inline double legendre(const unsigned int n, const double x) + { + switch (n) { + + case 0: + return 1.0; + + case 1: + return x; + + default: + { + double p0; + double p1 = 1.0; + double p2 = x; + + for (unsigned int i = 2; i <= n; ++i) { + p0 = p1; + p1 = p2; + p2 = ((2*i-1) * x*p1 - (i-1) * p0) / i; + } + + return p2; + } + } + } + + + /** + * Binomial function. + * + * \param n n + * \param k k + * \return function value + */ + inline double binomial(const int n, const int k) + { + if (k == 0 || n == k) { + return 1.0; + } + + if (n <= 0 || k < 0 || n < k) { + return 0.0; + } + + const int k1 = std::min(k, n - k); + const int k2 = n - k1; + + double value = k2 + 1; + + for (int i = k1; i != 1; --i) { + value *= (double) (k2 + i) / (double) i; + } + + return value; + } +} + +#endif diff --git a/jpp/JMath/JZero.hh b/jpp/JMath/JZero.hh new file mode 100644 index 0000000..501348e --- /dev/null +++ b/jpp/JMath/JZero.hh @@ -0,0 +1,108 @@ +#ifndef __JMATH__JZERO__ +#define __JMATH__JZERO__ + +/** + * \file + * + * Definition of zero value for any class. + * \author mdejong + */ +namespace JMATH {} +namespace JPP { using namespace JMATH; } + +namespace JMATH { + + /** + * Get zero value for a given data type. + * + * The default implementation of this method returns an object which + * is created with the default constructor. + * This method should be specialised if this value does not correspond + * to the equivalent of a zero result. + * + * \return zero + */ + template<class T> + inline T getZero() + { + return T(); + } + + + /** + * Get zero value for <tt>bool</tt>. + * + * \return false + */ + template<> inline bool getZero<bool>() + { + return false; + } + + + /** + * Get zero value for <tt>float</tt>. + * + * \return zero + */ + template<> inline float getZero<float>() + { + return float(0.0); + } + + + /** + * Get zero value for <tt>double</tt>. + * + * \return zero + */ + template<> + inline double getZero<double>() + { + return double(0.0); + } + + + /** + * Get zero value for <tt>long double</tt>. + * + * \return zero + */ + template<> + inline long double getZero<long double>() + { + return (long double)(0.0); + } + + + /** + * Auxiliary class to assign zero value. + */ + struct JZero { + /** + * Default constructor. + */ + JZero() + {} + + + /** + * Type conversion operator. + * + * \return zero + */ + template<class T> + operator T() const + { + return getZero<T>(); + } + }; + + + /** + * Function object to assign zero value. + */ + static const JZero zero; +} + +#endif diff --git a/jpp/JPhysics/JConstants.hh b/jpp/JPhysics/JConstants.hh new file mode 100644 index 0000000..1dbebf2 --- /dev/null +++ b/jpp/JPhysics/JConstants.hh @@ -0,0 +1,188 @@ +#ifndef __JPHYSICS__JCONSTANTS__ +#define __JPHYSICS__JCONSTANTS__ + +#include <math.h> + +#include "JMath/JConstants.hh" + + +/** + * \file + * Physics constants. + * \author mdejong + */ +namespace JPHYSICS {} +namespace JPP { using namespace JPHYSICS; } + +namespace JPHYSICS { + + using JMATH::PI; + using JMATH::EULER; + + /** + * Physics constants. + */ + static const double C = 0.299792458; //!< Speed of light in vacuum [m/ns] + static const double C_INVERSE = 1.0/C; //!< Inverse speed of light in vacuum [ns/m] + static const double AVOGADRO = 6.0221415e23; //!< Avogadro's number [gr^-1] + static const double H = 4.13566733e-15; //!< Planck constant [eV s] + static const double HBAR = H/(2*PI); //!< Planck constant [eV s] + static const double HBARC = HBAR*C*1.0e9; //!< Planck constant [eV m] + static const double ALPHA_ELECTRO_MAGNETIC = 1.0/137.036; //!< Electro-Magnetic coupling constant + static const double THETA_MCS = 13.6e-3; //!< Multiple Coulomb scattering constant [GeV] + + /** + * Fixed environment values. + */ + static const double DENSITY_SEA_WATER = 1.038; //!< Density of sea water [g/cm^3] + static const double DENSITY_ROCK = 2.65; //!< Density of rock [g/cm^3] + static const double SALINITY_SEA_WATER = 0.035; //!< Salinity of sea water + static const double INDEX_OF_REFRACTION_WATER = 1.3800851282; //!< Average index of refraction of water corresponding to the group velocity + static const double X0_WATER_M = 0.36; //!< Radiation length pure water [m] + + /** + * Derived quantities of optical medium. + */ + static const double TAN_THETA_C_WATER = sqrt((INDEX_OF_REFRACTION_WATER - 1.0) * (INDEX_OF_REFRACTION_WATER + 1.0)); //!< Average tangent corresponding to the group velocity + static const double COS_THETA_C_WATER = 1.0 / INDEX_OF_REFRACTION_WATER; //!< Average cosine corresponding to the group velocity + static const double SIN_THETA_C_WATER = TAN_THETA_C_WATER * COS_THETA_C_WATER; //!< Average sine corresponding to the group velocity + static const double KAPPA_WATER = 0.96; //!< Average R-dependence of arrival time of Cherenkov light + + /** + * Particle masses. + * Note that the neutrino masses are set to zero. + */ + static const double MASS_PHOTON = 0.0; //!< photon mass [GeV] + + static const double MASS_ELECTRON_NEUTRINO = 0.0; //!< electron neutrino mass [GeV] + static const double MASS_MUON_NEUTRINO = 0.0; //!< muon neutrino mass [GeV] + static const double MASS_TAU_NEUTRINO = 0.0; //!< tau neutrino mass [GeV] + + static const double MASS_ELECTRON = 0.510998946e-3; //!< electron mass [GeV] + static const double MASS_MUON = 0.1056583745; //!< muon mass [GeV] + static const double MASS_TAU = 1.77682; //!< tau mass [GeV] + + static const double MASS_NEUTRAL_PION = 0.1349766; //!< pi_0 mass [GeV] + static const double MASS_CHARGED_PION = 0.13957018; //!< pi^+/- mass [GeV] + static const double MASS_NEUTRAL_KAON = 0.497614; //!< K_0 mass [GeV] + static const double MASS_CHARGED_KAON = 0.493677; //!< K^+/- mass [GeV] + static const double MASS_NEUTRAL_RHO = 0.77526; //!< rho_0 mass [GeV] + static const double MASS_CHARGED_RHO = 0.77511; //!< rho^+/- mass [GeV] + static const double MASS_NEUTRAL_D = 1.86483; //!< D_0 mass [GeV] + static const double MASS_CHARGED_D = 1.86965; //!< D^+/- mass [GeV] + static const double MASS_CHARGED_D_S = 1.96834; //!< D_s^+/- mass [GeV] + + static const double MASS_PROTON = 0.9382720813; //!< proton mass [GeV] + static const double MASS_NEUTRON = 0.9395654133; //!< neutron mass [GeV] + static const double MASS_DELTA_1232 = 1.232; //!< Delta (1232) mass [GeV] + static const double MASS_LAMBDA = 1.115683; //!< Lambda mass [GeV] + static const double MASS_NEUTRAL_SIGMA = 1.192642; //!< Sigma_0 mass [GeV] + static const double MASS_CHARGED_SIGMA = 1.18937; //!< Sigma^+/- mass [GeV] + static const double MASS_NEUTRAL_XI = 1.31486; //!< Xi_0 mass [GeV] + static const double MASS_CHARGED_XI = 1.32171; //!< Xi^+/- mass [GeV] + static const double MASS_CHARGED_OMEGA = 1.67245; //!< Omega^+/- mass [GeV] + static const double MASS_CHARGED_LAMBDA_C = 2.28646; //!< Lambda_c^+/- mass [GeV] + static const double MASS_DOUBLYCHARGED_SIGMA_C = 2.45397; //!< Sigma_c^++/-- mass [GeV] + static const double MASS_CHARGED_SIGMA_C = 2.4529; //!< Sigma_c^+/- mass [GeV] + static const double MASS_NEUTRAL_SIGMA_C = 2.45375; //!< Sigma_c_0 mass [GeV] + static const double MASS_CHARGED_XI_C = 2.46793; //!< Xi_c^+/- mass [GeV] + static const double MASS_NEUTRAL_XI_C = 2.47091; //!< Xi_c_0 mass [GeV] + static const double MASS_NEUTRAL_OMEGA_C = 2.6952; //!< Omega_c_0 mass [GeV] + static const double MASS_NEUTRAL_B = 5.27958; //!< B_0 mass [GeV] + static const double MASS_CHARGED_B = 5.27926; //!< B^+/- mass [GeV] + static const double MASS_NEUTRAL_B_S = 5.36677; //!< B_s^0 mass [GeV] + static const double MASS_NEUTRAL_LAMBDA_B = 5.6194; //!< Lambda_b^0 mass [GeV] + static const double MASS_NEUTRAL_XI_B = 5.7878; //!< Xi_b^0 mass [GeV] + static const double MASS_CHARGED_XI_B = 5.7911; //!< Xi_b^+/- mass [GeV] + static const double MASS_CHARGED_OMEGA_B = 6.071; //!< Omega_b^+/- mass [GeV] + static const double MASS_CHARGED_B_C = 6.2756; //!< B_c^+/- mass [GeV] + + /** + * Get speed of light. + * + * return speed of light [m/ns] + */ + inline const double getSpeedOfLight() + { + return C; + } + + + /** + * Get inverse speed of light. + * + * return inverse speed of light [ns/m] + */ + inline const double getInverseSpeedOfLight() + { + return C_INVERSE; + } + + + /** + * Get average index of refraction of water corresponding to group velocity. + * + * \return index of refraction + */ + inline double getIndexOfRefraction() + { + return INDEX_OF_REFRACTION_WATER; + } + + + /** + * Get average index of refraction of water corresponding to phase velocity. + * + * \return index of refraction + */ + inline double getIndexOfRefractionPhase() + { + return 1.35; + } + + + /** + * Get average tangent of Cherenkov angle of water corresponding to group velocity. + * + * \return tan(theta_C) + */ + inline double getTanThetaC() + { + return TAN_THETA_C_WATER; + } + + + /** + * Get average cosine of Cherenkov angle of water corresponding to group velocity. + * + * \return cos(theta_C) + */ + inline double getCosThetaC() + { + return COS_THETA_C_WATER; + } + + + /** + * Get average sine of Cherenkov angle of water corresponding to group velocity. + * + * \return sin(theta_C) + */ + inline double getSinThetaC() + { + return SIN_THETA_C_WATER; + } + + + /** + * Get average R-dependence of arrival time of Cherenkov light (a.k.a. kappa). + * + * \return kappa + */ + inline double getKappaC() + { + return KAPPA_WATER; + } +} + +#endif diff --git a/jpp/JPhysics/JGeant_t.hh b/jpp/JPhysics/JGeant_t.hh new file mode 100644 index 0000000..1f9db60 --- /dev/null +++ b/jpp/JPhysics/JGeant_t.hh @@ -0,0 +1,140 @@ +#ifndef __JPHYSICS__JGEANT_T__ +#define __JPHYSICS__JGEANT_T__ + +#include "JTools/JFunction1D_t.hh" +#include "JIO/JSerialisable.hh" + +/** + * \file + * Base class for photon emission profile EM-shower. + * \author mdejong + */ + +namespace JPHYSICS {} +namespace JPP { using namespace JPHYSICS; } + +namespace JPHYSICS { + + using JIO::JReader; + using JIO::JWriter; + + typedef JTOOLS::JGridPolint1Function1D_t JGeantFunction1D_t; + + + /** + * Base class for the probability density function of photon emission from EM-shower + * as a function of the index of refraction and the cosine of the emission angle. + * + * The implementation of this function is based on a linear interpolation of tabulated values. + * In this, a linear approximation of the dependence of the normalisation constant on + * the index of refraction is assumed. This assumption is valid to within 10^-3. + */ + class JGeant_t : + public JGeantFunction1D_t + { + public: + /** + * Default constructor. + */ + JGeant_t() + {} + + + /** + * Number of photons from EM-shower as a function of emission angle. + * The integral over full solid angle is normalised to one. + * + * \param n index of refraction + * \param ct cosine angle of emmision + * \return d^2P/dcos()dphi + */ + double operator()(const double n, + const double ct) const + { + const double y = JGeantFunction1D_t::operator()(ct - 1.0/n); + + return y * (a0 - a1*n); + } + + + /** + * Integral number of photons from EM-shower between two emission angles. + * The integral over full solid angle is normalised to one. + * + * \param n index of refraction + * \param xmin minimal cosine angle of emmision + * \param xmax maximal cosine angle of emmision + * \return dnpe/dphi + */ + double operator()(const double n, + const double xmin, + const double xmax) const + { + const double x_min = std::max(xmin - 1.0/n, buffer. begin()->getX()); + const double x_max = std::min(xmax - 1.0/n, buffer.rbegin()->getX()); + + const double y = buffer(x_max) - buffer(x_min); + + return y * (a0 - a1*n); + } + + + /** + * Read geant from input. + * + * \param in reader + * \param geant geant + * \return reader + */ + friend inline JReader& operator>>(JReader& in, JGeant_t& geant) + { + in >> geant.a0; + in >> geant.a1; + in >> static_cast<JGeantFunction1D_t&>(geant); + + geant.compile(); + + return in; + } + + + /** + * Write geant to output. + * + * \param out writer + * \param geant geant + * \return writer + */ + friend inline JWriter& operator<<(JWriter& out, const JGeant_t& geant) + { + out << geant.a0; + out << geant.a1; + out << static_cast<const JGeantFunction1D_t&>(geant); + + return out; + } + + + protected: + /** + * Function compilation. + */ + virtual void do_compile() override + { + JGeantFunction1D_t::do_compile(); + + buffer.clear(); + + JTOOLS::integrate(*this, buffer); + + buffer.compile(); + } + + + double a0; //!< offset of the normalisation dependence + double a1; //!< slope of the normalisation dependence + JGeantFunction1D_t buffer; + }; +} + +#endif diff --git a/jpp/JPhysics/JGeanz.hh b/jpp/JPhysics/JGeanz.hh new file mode 100644 index 0000000..8eb29d7 --- /dev/null +++ b/jpp/JPhysics/JGeanz.hh @@ -0,0 +1,194 @@ +#ifndef __JPHYSICS__JGEANZ__ +#define __JPHYSICS__JGEANZ__ + +#include <cmath> + +#include "JMath/JMathSupportkit.hh" + +/** + * \file + * Longitudinal emission profile EM-shower. + * \author mdejong + */ + +namespace JPHYSICS {} +namespace JPP { using namespace JPHYSICS; } + +namespace JPHYSICS { + + /** + * Function object for longitudinal profile of EM-shower. + * + * + * \f[P(z) \propto z^{a-1} \times e^{-z/b}\f] + * + * where: \f[a = a_{0} + a_{1} \times \ln(E)\f] + * + * The parametrisation is taken from reference: + * C. Kopper, "Performance Studies for the KM3NeT Neutrino Telescope.", + * PhD thesis, University of Erlangen. + */ + class JGeanz { + public: + /** + * constructor + * \param __a0 power term (constant) + * \param __a1 power term (E dependence) + * \param __b expontial slope + */ + JGeanz(const double __a0, + const double __a1, + const double __b) : + a0(__a0), + a1(__a1), + b (__b), + Emin(exp(-a0/a1)) + {} + + + /** + * Probability Density Function + * + * \param E EM-shower energy [GeV] + * \param z z position of light emission point relative to vertex location (z >= 0) [m] + * \return dP/dz + */ + double getProbability(const double E, + const double z) const + { + if (E > Emin) { + + const double a = a0 + a1 * log(E); + const double y = pow(z,a-1.0) * exp(-z/b) / (pow(b,a) * std::tgamma(a)); + + return y; + } + + if (z <= getMinimalShowerSize()) + return 1.0 / getMinimalShowerSize(); + else + return 0.0; + } + + + /** + * Probability Density Function + * + * \param E EM-shower energy [GeV] + * \param z z position of light emission point relative to vertex location (z >= 0) [m] + * \return dP/dz + */ + double operator()(const double E, + const double z) const + { + return getProbability(E, z); + } + + + /** + * Integral of PDF (starting from 0). + * + * \param E EM-shower energy [GeV] + * \param z z position [m] (>= 0) + * \return dP + */ + double getIntegral(const double E, + const double z) const + { + if (E > Emin) { + + const double a = a0 + a1 * log(E); + const double x = z / b; + const double y = JMATH::Gamma(a,x); + + return y; + } + + if (z <= getMinimalShowerSize()) + return z / getMinimalShowerSize(); + else + return 1.0; + } + + + /** + * Get shower length for a given integrated probability. + * + * \param E EM-shower energy [GeV] + * \param P integrated probability [0,1] + * \param eps relative precision + * \return shower length [m] + */ + double getLength(const double E, + const double P, + const double eps = 1.0e-3) const + { + double zmin = 0.0; // [m] + double zmax = 30.0; // [m] + + if (E > Emin) { + + const double Q = P * (1.0 - eps); + + for (int i = 100; i != 0; --i) { + + const double z = 0.5 * (zmin + zmax); + const double p = getIntegral(E, z); + + if (fabs(p-Q) < p*eps) { + return z; + } + + if (p > P) + zmax = z; + else + zmin = z; + } + + return 0.5 * (zmin + zmax); + + } else + + return 0.0; + } + + /** + * Get depth of shower maximum + * + * \param E EM-shower energy[GeV] + * \return depth of maximum [m] + */ + + double getMaximum(const double E) const + { + const double a = a0 + a1 * log(E); + + return (a-1)*b; + } + + + /** + * Get minimal shower size. + * + * \return size [m] + */ + static double getMinimalShowerSize() + { + return 1e-6; + } + + protected: + const double a0; + const double a1; + const double b; + const double Emin; + }; + + + /** + * Function object for longitudinal EM-shower profile + */ + static const JGeanz geanz(1.85, 0.62, 0.54); +} + +#endif diff --git a/jpp/JPhysics/JNPETable.hh b/jpp/JPhysics/JNPETable.hh new file mode 100644 index 0000000..59d57ae --- /dev/null +++ b/jpp/JPhysics/JNPETable.hh @@ -0,0 +1,216 @@ +#ifndef __JPHYSICS__JNPETABLE__ +#define __JPHYSICS__JNPETABLE__ + +#include "JLang/JSharedPointer.hh" +#include "JLang/JException.hh" + +#include "JTools/JConstantFunction1D.hh" +#include "JTools/JMultiFunction.hh" +#include "JTools/JTransformableMultiFunction.hh" +#include "JTools/JToolsToolkit.hh" + + +/** + * \author mdejong + */ + +namespace JPHYSICS {} +namespace JPP { using namespace JPHYSICS; } + +namespace JPHYSICS { + + using JTOOLS::JConstantFunction1D; + using JTOOLS::JMapList; + using JTOOLS::JMultiFunction; + using JTOOLS::JMultiMapTransformer; + using JTOOLS::JTransformableMultiFunction; + + + /** + * Custom class for integrated values of the PDF of the arrival time of Cherenkov light. + * + * This class provides for the number of photo-electrons as a function + * of the leading <tt>(n - 1)</tt> parameter values. + */ + template<class JArgument_t, + class JResult_t, + class JMaplist_t, + class JDistance_t = JTOOLS::JDistance<JArgument_t> > + class JNPETable : + public JMultiFunction<JConstantFunction1D<JArgument_t, JResult_t>, + JMaplist_t, + JDistance_t> + { + public: + + typedef JMultiFunction<JConstantFunction1D<JArgument_t, JResult_t>, + JMaplist_t, + JDistance_t> multifunction_t; + + using multifunction_t::NUMBER_OF_DIMENSIONS; + + typedef JConstantFunction1D<JArgument_t, JResult_t> function_type; + typedef typename multifunction_t::map_type map_type; + + typedef typename multifunction_t::value_type value_type; + typedef typename multifunction_t::argument_type argument_type; + typedef typename multifunction_t::supervisor_type supervisor_type; + + typedef typename multifunction_t::abscissa_type abscissa_type; + typedef typename multifunction_t::ordinate_type ordinate_type; + typedef typename multifunction_t::result_type result_type; + + typedef typename multifunction_t::const_iterator const_iterator; + typedef typename multifunction_t::const_reverse_iterator const_reverse_iterator; + typedef typename multifunction_t::iterator iterator; + typedef typename multifunction_t::reverse_iterator reverse_iterator; + + typedef typename multifunction_t::super_iterator super_iterator; + typedef typename multifunction_t::super_const_iterator super_const_iterator; + + typedef JMultiMapTransformer<NUMBER_OF_DIMENSIONS, argument_type> transformer_type; + + + /** + * Default constructor. + */ + JNPETable() : + transformer(transformer_type::getClone()) + {} + + + /** + * Constructor. + * + * \param input multi-dimensional PDF + */ + template<class JPDF_t, class JPDFMaplist_t, class JPDFDistance_t> + JNPETable(const JTransformableMultiFunction<JPDF_t, JPDFMaplist_t, JPDFDistance_t>& input) : + transformer(transformer_type::getClone()) + { + using namespace JTOOLS; + + typedef JTransformableMultiFunction<JPDF_t, JPDFMaplist_t, JPDFDistance_t> JTransformableMultiFunction_t; + typedef JMultiKey<JTransformableMultiFunction_t::NUMBER_OF_DIMENSIONS - 1, argument_type> JMultiKey_t; + typedef typename JTransformableMultiFunction_t::transformer_type transformer_type; + + + this->transformer.reset(input.transformer->clone()); + + for (typename JTransformableMultiFunction_t::super_const_iterator i = input.super_begin(); i != input.super_end(); ++i) { + + const JMultiKey_t& key = (*i).getKey(); + const JPDF_t& value = (*i).getValue(); + + const typename transformer_type::array_type array(key); + + const double V = getIntegral(value); + const argument_type z = input.transformer->getXn(array, 1.0) - input.transformer->getXn(array, 0.0); + + this->insert(key, function_type(z*V)); + } + + this->compile(); + } + + + /** + * Add NPE table. + * + * Note that the summation is made via iteration of the elements in this multidimensional table. + * + * \param input NPE table + */ + void add(const JNPETable& input) + { + using namespace JTOOLS; + + for (super_iterator i = this->super_begin(); i != this->super_end(); ++i) { + + map_type& f1 = (*i).getValue(); + + for (typename map_type::iterator j = f1.begin(); j != f1.end(); ++j) { + + try { + + const JArray<NUMBER_OF_DIMENSIONS, argument_type> buffer((*i).getKey(), j->getX()); + + const double npe = get_value(input.evaluate(buffer.data())); + const double W = this->transformer->getWeight(buffer); + + j->getY() += npe/W; + } + catch(JLANG::JException& error) {} + } + } + } + + + /** + * Get number of photo-electrons. + * + * \param args comma separated argument list + * \return number of photo-electrons + */ + template<class ...Args> + result_type operator()(const Args& ...args) const + { + this->buffer.set(args...); + + return this->evaluate(this->buffer.data()); + } + + + /** + * Recursive function value evaluation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const override + { + for (int i = 0; i != NUMBER_OF_DIMENSIONS; ++i) { + this->buffer[i] = pX[i]; + } + + const double W = transformer->getWeight(buffer); + const result_type npe = multifunction_t::evaluate(buffer.data()); + + return W * npe; + } + + + /** + * Application of weight function. + * + * \param transformer function transformer + */ + void transform(const transformer_type& transformer) + { + using namespace JTOOLS; + + for (super_iterator i = this->super_begin(); i != this->super_end(); ++i) { + + map_type& f1 = (*i).getValue(); + + for (typename map_type::iterator j = f1.begin(); j != f1.end(); ++j) { + + const JArray<NUMBER_OF_DIMENSIONS, argument_type> array((*i).getKey(), j->getX()); + + j->getY() *= this->transformer->getWeight(array) / transformer.getWeight(array); + } + } + + this->transformer.reset(transformer.clone()); + this->compile(); + } + + + JLANG::JSharedPointer<transformer_type> transformer; + + protected: + mutable JTOOLS::JArray<NUMBER_OF_DIMENSIONS, argument_type> buffer; + }; +} + +#endif diff --git a/jpp/JPhysics/JNPE_t.hh b/jpp/JPhysics/JNPE_t.hh new file mode 100644 index 0000000..6a3c9b8 --- /dev/null +++ b/jpp/JPhysics/JNPE_t.hh @@ -0,0 +1,288 @@ + +#include "JLang/JException.hh" +#include "JTools/JCollection.hh" +#include "JTools/JMap.hh" +#include "JTools/JGridMap.hh" +#include "JTools/JMapList.hh" +#include "JTools/JSpline.hh" +#include "JTools/JPolint.hh" +#include "JTools/JElement.hh" +#include "JPhysics/JNPETable.hh" +#include "JPhysics/JPDFTable.hh" +#include "JPhysics/JPDFToolkit.hh" +#include "JPhysics/JPDFTypes.hh" +#include "JPhysics/JGeanz.hh" +#include "JMath/JZero.hh" + + +/** + * \file + * + * Auxiliary data structure for muon PDF. + * \author mdejong + */ +struct JMuonNPE_t { + + typedef JPP::JMAPLIST<JPP::JPolint1FunctionalMap, + JPP::JPolint1FunctionalGridMap, + JPP::JPolint1FunctionalGridMap>::maplist JNPEMaplist_t; + typedef JPP::JNPETable<double, double, JNPEMaplist_t> JNPE_t; + + + /** + * Constructor. + * + * The PDF file descriptor should contain the wild card character JPHYSICS::WILD_CARD.\n + * + * \param fileDescriptor PDF file descriptor + */ + JMuonNPE_t(const std::string& fileDescriptor) + { + using namespace std; + using namespace JPP; + + const JPDFType_t pdf_t[] = { DIRECT_LIGHT_FROM_MUON, + SCATTERED_LIGHT_FROM_MUON, + DIRECT_LIGHT_FROM_EMSHOWERS, + SCATTERED_LIGHT_FROM_EMSHOWERS }; + + const int N = sizeof(pdf_t) / sizeof(pdf_t[0]); + + typedef JPP::JSplineFunction1D<JSplineElement2D<double, double>, + JCollection, + double> JFunction1D_t; + typedef JPDFTable<JFunction1D_t, JNPEMaplist_t> JPDF_t; + + + const JNPE_t::JSupervisor supervisor(new JNPE_t::JDefaultResult(zero)); + + for (int i = 0; i != N; ++i) { + + JPDF_t pdf; + + const string file_name = getFilename(fileDescriptor, pdf_t[i]); + + cout << "loading PDF from file " << file_name << "... " << flush; + + pdf.load(file_name.c_str()); + + cout << "OK" << endl; + + pdf.setExceptionHandler(supervisor); + + if (!is_bremsstrahlung(pdf_t[i])) + Y1.push_back(JNPE_t(pdf)); + else + YB.push_back(JNPE_t(pdf)); + } + + // Add PDFs + + cout << "adding PDFs... " << flush; + + Y1[1].add(Y1[0]); Y1.erase(Y1.begin()); + YB[1].add(YB[0]); YB.erase(YB.begin()); + + cout << "OK" << endl; + } + + + /** + * Get PDF. + * + * The orientation of the PMT should be defined according this <a href="https://common.pages.km3net.de/jpp/JPDF.PDF">documentation</a>.\n + * In this, the zenith and azimuth angles are limited to \f[\left[0, \pi\right]\f]. + * + * \param E muon energy at minimum distance of approach [GeV] + * \param R minimum distance of approach [m] + * \param theta PMT zenith angle [rad] + * \param phi PMT azimuth angle [rad] + * \return number of photo-electrons + */ + double calculate(const double E, + const double R, + const double theta, + const double phi) const + { + using namespace JPP; + + const double yA = getNPE(Y1, R, theta, phi); + const double yB = getNPE(YB, R, theta, phi); + + if (E >= MASS_MUON * INDEX_OF_REFRACTION_WATER) + return yA + E * yB; + else + return 0.0; + } + +private: + std::vector<JNPE_t> Y1; //!< light from muon + std::vector<JNPE_t> YB; //!< light from EM showers + + /** + * Get number of photo-electrons. + * + * \param NPE NPE tables + * \param R distance between muon and PMT [m] + * \param theta zenith angle orientation PMT [rad] + * \param phi azimuth angle orientation PMT [rad] + * \return number of photo-electrons + */ + static inline double getNPE(const std::vector<JNPE_t>& NPE, + const double R, + const double theta, + const double phi) + { + using namespace std; + using namespace JPP; + + double npe = 0.0; + + for (vector<JNPE_t>::const_iterator i = NPE.begin(); i != NPE.end(); ++i) { + + if (R <= i->getXmax()) { + + try { + + const double y = get_value((*i)(std::max(R, i->getXmin()), theta, phi)); + + if (y > 0.0) { + npe += y; + } + } + catch(const exception& error) { + cerr << error.what() << endl; + } + } + } + + return npe; + } +}; + + +/** + * Auxiliary data structure for shower PDF. + */ +struct JShowerNPE_t { + + typedef JPP::JMAPLIST<JPP::JPolint1FunctionalMap, + JPP::JPolint1FunctionalMap, + JPP::JPolint1FunctionalGridMap, + JPP::JPolint1FunctionalGridMap>::maplist JNPEMaplist_t; + typedef JPP::JNPETable<double, double, JNPEMaplist_t> JNPE_t; + + + /** + * Constructor. + * + * The PDF file descriptor should contain the wild card character JPHYSICS::WILD_CARD.\n + * + * \param fileDescriptor PDF file descriptor + * \param numberOfPoints number of points for shower elongation + */ + JShowerNPE_t(const std::string& fileDescriptor, + const int numberOfPoints = 0) : + numberOfPoints(numberOfPoints) + { + using namespace std; + using namespace JPP; + + const JPDFType_t pdf_t[] = { SCATTERED_LIGHT_FROM_EMSHOWER, + DIRECT_LIGHT_FROM_EMSHOWER }; + + const int N = sizeof(pdf_t) / sizeof(pdf_t[0]); + + typedef JPP::JSplineFunction1D<JSplineElement2D<double, double>, + JCollection, + double> JFunction1D_t; + typedef JPDFTable<JFunction1D_t, JNPEMaplist_t> JPDF_t; + + + const JNPE_t::JSupervisor supervisor(new JNPE_t::JDefaultResult(zero)); + + for (int i = 0; i != N; ++i) { + + const string file_name = getFilename(fileDescriptor, pdf_t[i]); + + cout << "loading input from file " << file_name << "... " << flush; + + JPDF_t pdf; + + pdf.load(file_name.c_str()); + + pdf.setExceptionHandler(supervisor); + + if (npe.empty()) + npe = JNPE_t(pdf); + else + npe.add(JNPE_t(pdf)); + + F[i] = JNPE_t(pdf); + + cout << "OK" << endl; + } + } + + + /** + * Get PDF. + * + * The orientation of the PMT should be defined according this <a href="https://common.pages.km3net.de/jpp/JPDF.PDF">documentation</a>.\n + * In this, the zenith and azimuth angles are limited to \f[\left[0, \pi\right]\f]. + * + * \param E shower energy at minimum distance of approach [GeV] + * \param D distance [m] + * \param cd cosine emission angle + * \param theta PMT zenith angle [rad] + * \param phi PMT azimuth angle [rad] + * \return hypothesis value + */ + double calculate(const double E, + const double D, + const double cd, + const double theta, + const double phi) const + { + using namespace std; + using namespace JPP; + + double Y = 0.0; + + if (numberOfPoints > 0) { + + const double W = 1.0 / (double) numberOfPoints; + + for (int i = 0; i != numberOfPoints; ++i) { + + const double z = geanz.getLength(E, (i + 0.5) / (double) numberOfPoints); + + const double __D = sqrt(D*D - 2.0*(D*cd)*z + z*z); + const double __cd = (D * cd - z) / __D; + + try { + Y += W * npe (__D, __cd, theta, phi); + } + catch(const exception& error) { + //cerr << error.what() << endl; + } + } + + } else { + + try { + Y = npe(D, cd, theta, phi); + } + catch(const exception& error) { + //cerr << error.what() << endl; + } + } + + return E * Y; + } + +private: + int numberOfPoints; + JNPE_t npe; //!< PDF for shower + JNPE_t F[2]; //!< PDF for shower +}; diff --git a/jpp/JPhysics/JPDFTable.hh b/jpp/JPhysics/JPDFTable.hh new file mode 100644 index 0000000..73670e2 --- /dev/null +++ b/jpp/JPhysics/JPDFTable.hh @@ -0,0 +1,308 @@ +#ifndef __JPHYSICS__JPDFTABLE__ +#define __JPHYSICS__JPDFTABLE__ + +#include <cmath> + +#include "JIO/JObjectBinaryIO.hh" +#include "JTools/JTransformableMultiFunction.hh" +#include "JTools/JQuantiles.hh" +#include "JTools/JSet.hh" +#include "JTools/JRange.hh" +#include "JPhysics/JConstants.hh" +#include "JPhysics/JPDFTransformer.hh" + + +/** + * \author mdejong + */ + +namespace JPHYSICS {} +namespace JPP { using namespace JPHYSICS; } + +namespace JPHYSICS { + + using JIO::JSerialisable; + using JIO::JReader; + using JIO::JWriter; + using JIO::JObjectBinaryIO; + using JTOOLS::JTransformableMultiFunction; + using JTOOLS::JTransformableMultiHistogram; + using JTOOLS::JRange; + + + /** + * Multi-dimensional PDF table for arrival time of Cherenkov light. + */ + template<class JFunction1D_t, + class JMaplist_t, + class JDistance_t = JTOOLS::JDistance<typename JFunction1D_t::argument_type> > + class JPDFTable : + public JTransformableMultiFunction<JFunction1D_t, JMaplist_t, JDistance_t>, + public JSerialisable, + public JObjectBinaryIO< JPDFTable<JFunction1D_t, JMaplist_t, JDistance_t> > + { + public: + + typedef JTransformableMultiFunction<JFunction1D_t, JMaplist_t, JDistance_t> transformablemultifunction_type; + + typedef typename transformablemultifunction_type::argument_type argument_type; + typedef typename transformablemultifunction_type::result_type result_type; + typedef typename transformablemultifunction_type::value_type value_type; + + typedef typename transformablemultifunction_type::multimap_type multimap_type; + typedef typename transformablemultifunction_type::transformer_type transformer_type; + + enum { NUMBER_OF_DIMENSIONS = transformablemultifunction_type::NUMBER_OF_DIMENSIONS }; + + typedef typename transformablemultifunction_type::super_const_iterator super_const_iterator; + typedef typename transformablemultifunction_type::super_iterator super_iterator; + typedef typename transformablemultifunction_type::function_type function_type; + + using transformablemultifunction_type::insert; + + + /** + * Default constructor. + */ + JPDFTable() : + transformablemultifunction_type() + {} + + + /** + * Constructor. + * + * \param input multi-dimensional function + */ + template<class JPDF_t, class JPDFMaplist_t, class JPDFDistance_t> + JPDFTable(const JTransformableMultiFunction<JPDF_t, JPDFMaplist_t, JPDFDistance_t>& input) : + transformablemultifunction_type(input) + {} + + + /** + * Constructor. + * + * \param input multi-dimensional histogram + */ + template<class JHistogram1D_t, class JHistogramMaplist_t, class JHistogramDistance_t> + JPDFTable(const JTransformableMultiHistogram<JHistogram1D_t, JHistogramMaplist_t, JHistogramDistance_t>& input) : + transformablemultifunction_type(input) + {} + + + /** + * Blur PDF. + * + * The arrival times of Cherenkov light are smeared according to a Gaussian distribution + * with the specified width (i.e.\ TTS) using Gauss-Hermite integration. + * An exception is made when the time range according the specified quantile is + * smaller than the specified width (TTS) of the Gaussian distribution. + * In that case, the resulting PDF is a Gaussian distribution with the specified width (TTS) + * and normalisation according to the integral value of the input PDF. + * A smooth transition is imposed between the normal regime and this exeption. + * + * \param TTS TTS [ns] + * \param numberOfPoints number of points for Gauss-Hermite integration + * \param epsilon precision + * \param quantile quantile + */ + void blur(const double TTS, + const int numberOfPoints = 25, + const double epsilon = 1.0e-10, + const double quantile = 0.99) + { + using namespace std; + using namespace JTOOLS; + + typedef typename transformer_type::array_type array_type; + + const JGaussHermite engine(numberOfPoints, epsilon); + + for (super_iterator i = this->super_begin(); i != this->super_end(); ++i) { + + const array_type array = (*i).getKey(); + function_type& f1 = (*i).getValue(); + + if (!f1.empty()) { + + const typename function_type::supervisor_type& supervisor = f1.getSupervisor(); + + const JMultiMapGetTransformer<NUMBER_OF_DIMENSIONS - 1, value_type> get(*(this->transformer), array); + const JMultiMapPutTransformer<NUMBER_OF_DIMENSIONS - 1, value_type> put(*(this->transformer), array); + + f1.transform(get); + f1.compile(); + + const JQuantiles Q(f1, quantile); + + // abscissa + + JSet<double> X; + + for (JGaussHermite::const_iterator j = engine.begin(); j != engine.end(); ++j) { + X.insert(Q.getX() + TTS*sqrt(2.0)*j->getX()); + } + + for (typename function_type::const_iterator j = f1.begin(); j != f1.end(); ++j) { + + if (j->getX() - TTS < X.getXmin()) { + X.insert(j->getX() - TTS); + } + + if (j->getX() + TTS > X.getXmax()) { + X.insert(j->getX() + TTS); + } + } + + + const double W = gauss(Q.getUpperLimit() - Q.getLowerLimit(), TTS); + + function_type buffer; + + for (JSet<double>::const_iterator x = X.begin(); x != X.end(); ++x) { + + double y = 0.0; + + for (JGaussHermite::const_iterator j = engine.begin(); j != engine.end(); ++j) { + + const double u = j->getX(); + const double v = j->getY() / sqrt(PI); + const double w = get_value(f1(*x + u*TTS*sqrt(2.0))); + + y += v * w; + } + + buffer[*x] = W * Q.getIntegral() * Gauss(*x - Q.getX(), TTS) + (1.0 - W) * y; + } + + buffer.transform(put); + buffer.compile(); + + f1 = buffer; + + f1.setExceptionHandler(supervisor); + } + } + } + + + /** + * Compresses PDF to given abscissa range. + * + * \param range abscissa range + */ + void compress(const JRange<typename function_type::abscissa_type>& range) + { + for (super_iterator i = this->super_begin(); i != this->super_end(); ++i) { + + function_type& f1 = i.getValue(); + + typename function_type::iterator p = f1.lower_bound(range.getLowerLimit()); + + f1.function_type::container_type::erase(f1.begin(), p); + + typename function_type::iterator q = f1.lower_bound(range.getUpperLimit()); + + f1.function_type::container_type::erase(++q, f1.end()); + } + + this->compile(); + } + + + /** + * Read from input. + * + * \param in reader + * \return reader + */ + virtual JReader& read(JReader& in) override + { + if (in >> static_cast<transformablemultifunction_type&>(*this)) { + + // read optional transformer + + JPDFTransformer<NUMBER_OF_DIMENSIONS - 1, argument_type> buffer; + + if (buffer.read(in)) { + + this->transformer.reset(buffer.clone()); + + } else { + + in.clear(); + + this->transformer.reset(transformer_type::getClone()); + } + } + + this->compile(); + + return in; + } + + + /** + * Write from input. + * + * \param out writer + * \return writer + */ + virtual JWriter& write(JWriter& out) const override + { + out << static_cast<const transformablemultifunction_type&>(*this); + + this->transformer->write(out); + + return out; + } + + protected: + /** + * Gauss function (normalised to 1 at x = 0). + * + * \param x x + * \param sigma sigma + * \return function value + */ + static double gauss(const double x, const double sigma) + { + const double u = x / sigma; + + if (fabs(u) < 10.0) + return exp(-0.5*u*u); + else + return 0.0; + } + + + /** + * Normalised Gauss function. + * + * \param x x + * \param sigma sigma + * \return function value + */ + static double Gauss(const double x, const double sigma) + { + return gauss(x, sigma) / sqrt(2.0*JTOOLS::PI) / sigma; + } + + + /** + * Normalised Gauss function. + * + * \param x x + * \param x0 central value + * \param sigma sigma + * \return function value + */ + static double Gauss(const double x, const double x0, const double sigma) + { + return Gauss(x - x0, sigma); + } + }; +} + +#endif diff --git a/jpp/JPhysics/JPDFToolkit.hh b/jpp/JPhysics/JPDFToolkit.hh new file mode 100644 index 0000000..23a3586 --- /dev/null +++ b/jpp/JPhysics/JPDFToolkit.hh @@ -0,0 +1,322 @@ +#ifndef __JPHYSICS__JPDFTOOLKIT__ +#define __JPHYSICS__JPDFTOOLKIT__ + +#include <vector> +#include <cmath> + +#include "JLang/JCC.hh" +#include "JPhysics/JConstants.hh" +#include "JTools/JFunction1D_t.hh" +#include "JIO/JSerialisable.hh" + +/** + * \file + * Auxiliary methods for PDF calculations. + * \author mdejong + */ + +namespace JPHYSICS {} +namespace JPP { using namespace JPHYSICS; } + +namespace JPHYSICS { + + using JIO::JReader; + using JIO::JWriter; + using JTOOLS::JGridPolint0Function1D_t; + using JTOOLS::JGridSplineFunction1D_t; + + + /** + * Get minimal wavelength for PDF evaluations. + * + * \return wavelength of light [nm] + */ + inline double getMinimalWavelength() + { + return 300.0; + } + + + /** + * Get maximal wavelength for PDF evaluations. + * + * \return wavelength of light [nm] + */ + inline double getMaximalWavelength() + { + return 700.0; + } + + + /** + * Number of Cherenkov photons per unit track length and per unit wavelength. + * + * \param lambda wavelength of light [nm] + * \param n index of refraction + * \return number of photons per unit track length and per unit wavelength [m^-1 nm^-1] + */ + inline double cherenkov(const double lambda, + const double n) + { + const double x = n*lambda; + + return 1.0e9 * 2 * PI * ALPHA_ELECTRO_MAGNETIC * (n*n - 1.0) / (x*x); + } + + + /** + * Equivalent EM-shower energy due to delta-rays per unit muon track length. + * + * Internal parameters are obtained with application [script] JDeltaRays[.sh]. + * + * \param E muon energy [GeV] + * \return equivalent energy loss [GeV/m] + */ + inline double getDeltaRaysFromMuon(const double E) + { + static const double a = 3.186e-01; + static const double b = 3.384e-01; + static const double c = -2.759e-02; + static const double d = 1.630e-03; + static const double Emin = 0.13078; // [GeV] + + if (E > Emin) { + + const double x = log10(E); // + const double y = a + x*(b + x*(c + x*(d))); // [MeV g^-1 cm^2] + + return y * DENSITY_SEA_WATER * 1.0e-1; // [GeV/m] + } + + return 0.0; + } + + + /** + * Equivalent EM-shower energy due to delta-rays per unit tau track length. + * + * Internal parameters are obtained with application [script] JDeltaRays[.sh]. + * + * \param E tau energy [GeV] + * \return equivalent energy loss [GeV/m] + */ + inline double getDeltaRaysFromTau(const double E) + { + static const double a = -2.374e-01; + static const double b = 5.143e-01; + static const double c = -4.213e-02; + static const double d = 1.804e-03; + static const double Emin = 2.19500; // [GeV] + + if (E > Emin) { + + const double x = log10(E); // + const double y = a + x*(b + x*(c + x*(d))); // [MeV g^-1 cm^2] + + return y * DENSITY_SEA_WATER * 1.0e-1; // [GeV/m] + } + + return 0.0; + } + + + /** + * Rayleigh cross section. + * + * \param n index of refraction + * \param lambda wavelength of light [nm] + * \return cross section [cm^2] + */ + inline const double getRayleighCrossSection(const double n, + const double lambda) + { + static const double d = 0.36; // size of H2O molecule [nm] + static const double U = PI*PI*PI*PI*PI*2.0/3.0; + static const double V = d*d*d*d*d*d; + + const double W = (n*n - 1.0) / (n*n + 2.0); + const double sigma = 1.0e-14 * U*V*W*W / (lambda*lambda*lambda*lambda); // [cm^2] + + return sigma; + } + + + /** + * Rayleigh scattering length. + * + * \param n index of refraction + * \param lambda wavelength of light [nm] + * \return scattering length [m] + */ + inline const double getRayleighScatteringLength(const double n, + const double lambda) + { + static const double amu = 18.01528; // H20 mass in Atomic mass units + + const double sigma = getRayleighCrossSection(n, lambda); + const double ls = 1.0e-2 / (DENSITY_SEA_WATER * AVOGADRO * sigma / amu); // [m] + + return ls; + } + + + /** + * Absorption length of pure water. + * + * CITATION: + * Jonasz M. 2007. Absorption coefficient of water: Data sources (www.tpdsci.com/Tpc/AbsCfOfWaterDat.php). + * In: Top. Part. Disp. Sci. (www.tpdsci.com). + * + * DATA FROM: + * Wozniak B., Wozniak S. B., Tyszka K., Ostrowska M., Majchrowski R., Ficek D., Dera J. 2005. + * Modelling the light absorption properties of particulate matter forming organic particles suspended in seawater. Part 2. + * Modelling results. Oceanologia 47, 621-662. + * see also + * Wozniak B., Dera J. 2007. + * Light absorption in sea water. Springer, Berlin, 456 pp. (see p. 62) + * + * NOTES: + * As stated by the data authors, the data are based on measurement results obtained by various authors + * (interpolated by a linear approximation where applicable): + * Wavelength Reference + * - 200-335 nm Smith R.C., Baker K.S. 1981. Optical properties of the clearest natural waters (200-800 nm). Appl. Opt. 20, 177-184. + * - 340-370 nm Sogandares F.M., Fry, E.S. 1997. Absorption spectrum (340 -640 nm) of pure water. I. Photothermal measurements Appl. Opt. 36, 8699-8709. + * - 380-700 nm Pope R.M., Fry E.S. 1997. Absorption spectrum (380 -700 nm) of pure water. II. Integrating cavity measurements. Appl. Opt. 36, 8710-8723 + */ + class JAbsorptionLengthOfPureWater : + public JGridSplineFunction1D_t + { + public: + JAbsorptionLengthOfPureWater() + { + // wave- absorption + // length coefficient + // [um] [1/m] + (*this)[0.200e3] = 3.07; + (*this)[0.205e3] = 2.53; + (*this)[0.210e3] = 1.99; + (*this)[0.215e3] = 1.65; + (*this)[0.220e3] = 1.31; + (*this)[0.225e3] = 1.1185; + (*this)[0.230e3] = 0.927; + (*this)[0.235e3] = 0.8235; + (*this)[0.240e3] = 0.72; + (*this)[0.245e3] = 0.6395; + (*this)[0.250e3] = 0.559; + (*this)[0.255e3] = 0.508; + (*this)[0.260e3] = 0.457; + (*this)[0.265e3] = 0.415; + (*this)[0.270e3] = 0.373; + (*this)[0.275e3] = 0.3305; + (*this)[0.280e3] = 0.288; + (*this)[0.285e3] = 0.2515; + (*this)[0.290e3] = 0.215; + (*this)[0.295e3] = 0.178; + (*this)[0.300e3] = 0.141; + (*this)[0.305e3] = 0.123; + (*this)[0.310e3] = 0.105; + (*this)[0.315e3] = 0.0947; + (*this)[0.320e3] = 0.0844; + (*this)[0.325e3] = 0.0761; + (*this)[0.330e3] = 0.0678; + (*this)[0.335e3] = 0.06195; + (*this)[0.340e3] = 0.0325; + (*this)[0.345e3] = 0.02645; + (*this)[0.350e3] = 0.0204; + (*this)[0.355e3] = 0.018; + (*this)[0.360e3] = 0.0156; + (*this)[0.365e3] = 0.0135; + (*this)[0.370e3] = 0.0114; + (*this)[0.375e3] = 0.011385; + (*this)[0.380e3] = 0.01137; + (*this)[0.385e3] = 0.00941; + (*this)[0.390e3] = 0.00851; + (*this)[0.395e3] = 0.00813; + (*this)[0.400e3] = 0.00663; + (*this)[0.405e3] = 0.0053; + (*this)[0.410e3] = 0.00473; + (*this)[0.415e3] = 0.00444; + (*this)[0.420e3] = 0.00454; + (*this)[0.425e3] = 0.00478; + (*this)[0.430e3] = 0.00495; + (*this)[0.435e3] = 0.0053; + (*this)[0.440e3] = 0.00635; + (*this)[0.445e3] = 0.00751; + (*this)[0.450e3] = 0.00922; + (*this)[0.455e3] = 0.00962; + (*this)[0.460e3] = 0.00979; + (*this)[0.465e3] = 0.01011; + (*this)[0.470e3] = 0.0106; + (*this)[0.475e3] = 0.0114; + (*this)[0.480e3] = 0.0127; + (*this)[0.485e3] = 0.0136; + (*this)[0.490e3] = 0.015; + (*this)[0.495e3] = 0.0173; + (*this)[0.500e3] = 0.0204; + (*this)[0.505e3] = 0.0256; + (*this)[0.510e3] = 0.0325; + (*this)[0.515e3] = 0.0396; + (*this)[0.520e3] = 0.0409; + (*this)[0.525e3] = 0.0417; + (*this)[0.530e3] = 0.0434; + (*this)[0.535e3] = 0.0452; + (*this)[0.540e3] = 0.0474; + (*this)[0.545e3] = 0.0511; + (*this)[0.550e3] = 0.0565; + (*this)[0.555e3] = 0.0596; + (*this)[0.560e3] = 0.0619; + (*this)[0.565e3] = 0.0642; + (*this)[0.570e3] = 0.0695; + (*this)[0.575e3] = 0.0772; + (*this)[0.580e3] = 0.0896; + (*this)[0.585e3] = 0.11; + (*this)[0.590e3] = 0.1351; + (*this)[0.595e3] = 0.1672; + (*this)[0.600e3] = 0.2224; + (*this)[0.605e3] = 0.2577; + (*this)[0.610e3] = 0.2644; + (*this)[0.615e3] = 0.2678; + (*this)[0.620e3] = 0.2755; + (*this)[0.625e3] = 0.2834; + (*this)[0.630e3] = 0.2916; + (*this)[0.635e3] = 0.3012; + (*this)[0.640e3] = 0.3108; + (*this)[0.645e3] = 0.325; + (*this)[0.650e3] = 0.34; + (*this)[0.655e3] = 0.371; + (*this)[0.660e3] = 0.41; + (*this)[0.665e3] = 0.429; + (*this)[0.670e3] = 0.439; + (*this)[0.675e3] = 0.448; + (*this)[0.680e3] = 0.465; + (*this)[0.685e3] = 0.486; + (*this)[0.690e3] = 0.516; + (*this)[0.695e3] = 0.559; + (*this)[0.700e3] = 0.624; + + compile(); + } + + + /** + * Absorption length of pure water. + * + * \param lambda wavelength of light [nm] + * \return absorption length [m] + */ + double operator()(const double lambda) const + { + const double y = JGridSplineFunction1D_t::operator()(lambda); + + return 1.0 / y; + } + }; + + + /** + * Function object for absorption length of pure water. + */ + static const JAbsorptionLengthOfPureWater getAbsorptionLengthOfPureWater; +} + +#endif diff --git a/jpp/JPhysics/JPDFTransformer.hh b/jpp/JPhysics/JPDFTransformer.hh new file mode 100644 index 0000000..59422f3 --- /dev/null +++ b/jpp/JPhysics/JPDFTransformer.hh @@ -0,0 +1,1289 @@ +#ifndef __JPHYSICS__JPDFTRANSFORMER__ +#define __JPHYSICS__JPDFTRANSFORMER__ + +#include <cmath> + +#include "JLang/JCC.hh" +#include "JIO/JSerialisable.hh" +#include "JPhysics/JConstants.hh" +#include "JTools/JMultiMapTransformer.hh" +#include "JTools/JFunction1D_t.hh" +#include "JTools/JGrid.hh" +#include "JPhysics/JGeant_t.hh" + + +/** + * \author mdejong + */ + +namespace JPHYSICS {} +namespace JPP { using namespace JPHYSICS; } + +namespace JPHYSICS { + + using JIO::JReader; + using JIO::JWriter; + using JTOOLS::JMultiMapTransformer; + + + /** + * Transformer for the 1D probability density function (PDF) of the time response of a PMT to a muon. + * + * PDFs are evaluated by interpolation for: + * -# distance of closest approach of the muon to the PMT [m] + * -# arrival time [ns] + * + * The evaluation of the weights is based on: + * -# effective attenuation length + */ + template<class JArgument_t> + class JPDFTransformer_t : + public JMultiMapTransformer<1, JArgument_t> + { + public: + + typedef JMultiMapTransformer<1, JArgument_t> JMultiMapTransformer_t; + + typedef typename JMultiMapTransformer_t::clone_type clone_type; + typedef typename JMultiMapTransformer_t::argument_type argument_type; + typedef typename JMultiMapTransformer_t::const_array_type const_array_type; + + using JMultiMapTransformer_t::getWeight; + + /** + * Get shortest distance of approach. + * + * \return distance [m] + */ + static double getRmin() + { + return 0.01; + } + + + /** + * Default constructor. + */ + JPDFTransformer_t() : + ln (0.0), + alpha(0), + kmin (0.0), + kmax (0.0) + {} + + + /** + * Constructor. + * + * \param ln Effective attenuation length [m] + * \param alpha Distance dependence (power term) + * \param kmin Minimal kappa + * \param kmax Maximal kappa + */ + JPDFTransformer_t(const double ln, + const int alpha, + const double kmin, + const double kmax) : + ln (ln), + alpha(alpha), + kmin (kmin), + kmax (kmax) + {} + + + /** + * Clone object. + * + * \return pointer to newly created transformer + */ + virtual clone_type clone() const override + { + return new JPDFTransformer_t(*this); + } + + + /** + * Evaluate arrival time. + * + * \param buffer {R_m} + * \param xn old t_ns + * \return new t_ns + */ + virtual argument_type putXn(const_array_type& buffer, const argument_type xn) const override + { + using namespace JTOOLS; + + const double R = buffer[0]; + + double x = xn; + + const double t0 = R * getTanThetaC() * getInverseSpeedOfLight(); + const double t1 = R * kmin * getInverseSpeedOfLight(); + + x -= t1 - t0; + + if (kmax > kmin) { + x /= R * (kmax - kmin) * getInverseSpeedOfLight(); + } + + return x; + } + + + /** + * Evaluate arrival time. + * + * \param buffer {R_m} + * \param xn old t_ns + * \return new t_ns + */ + virtual argument_type getXn(const_array_type& buffer, const argument_type xn) const override + { + using namespace JTOOLS; + + const double R = buffer[0]; + + double x = xn; + + if (kmax > kmin) { + x *= R * (kmax - kmin) * getInverseSpeedOfLight(); + } + + const double t0 = R * getTanThetaC() * getInverseSpeedOfLight(); + const double t1 = R * kmin * getInverseSpeedOfLight(); + + x += t1 - t0; + + return x; + } + + + /** + * Weight function. + * + * \param buffer {R_m} + * \return weight + */ + virtual double getWeight(const_array_type& buffer) const override + { + using namespace JTOOLS; + + const double R = buffer[0]; + + const double n = getIndexOfRefraction(); + const double ct0 = 1.0 / n; + const double st0 = sqrt((1.0 + ct0)*(1.0 - ct0)); + + const double d = sqrt(getRmin()*getRmin() + R*R) / st0; + + return exp(-d/ln) / pow(d,alpha); + } + + + /** + * Read PDF transformer from input. + * + * \param in reader + * \return reader + */ + virtual JReader& read(JReader& in) override + { + in >> ln; + in >> alpha; + in >> kmin; + in >> kmax; + + return in; + } + + + /** + * Write PDF transformer to output. + * + * \param out writer + * \return writer + */ + virtual JWriter& write(JWriter& out) const override + { + out << ln; + out << alpha; + out << kmin; + out << kmax; + + return out; + } + + + /** + * Print PDF transformer to output stream. + * + * \param out output stream + * \return output stream + */ + std::ostream& print(std::ostream& out) const + { + using namespace std; + + out << "Effective attenuation length [m] " << ln << endl; + out << "Distance dependence (power term) " << alpha << endl; + out << "Minimal kappa " << kmin << endl; + out << "Maximal kappa " << kmax << endl; + + return out; + } + + + double ln; //!< Effective attenuation length [m] + int alpha; //!< Distance dependence (power term) + double kmin; //!< minimal kappa + double kmax; //!< maximal kappa + }; + + + /** + * Transformer for the 1D probability density function (PDF) of the time response of a PMT due to a point source. + * + * PDFs are evaluated by interpolation for: + * -# distance between point source and PMT [m] + * -# arrival time [ns] + * + * The evaluation of the weights is based on: + * -# effective attenuation length + */ + template<class JArgument_t> + class JPD0Transformer_t : + public JMultiMapTransformer<1, JArgument_t> + { + public: + + typedef JMultiMapTransformer<1, JArgument_t> JMultiMapTransformer_t; + + typedef typename JMultiMapTransformer_t::clone_type clone_type; + typedef typename JMultiMapTransformer_t::argument_type argument_type; + typedef typename JMultiMapTransformer_t::const_array_type const_array_type; + + using JMultiMapTransformer_t::getWeight; + + /** + * Get shortest distance. + * + * \return distance [m] + */ + static double getDmin() + { + return 0.01; + } + + + /** + * Default constructor. + */ + JPD0Transformer_t() : + ln (0.0), + alpha(0), + kmin (0.0), + kmax (0.0) + {} + + + /** + * Constructor. + * + * \param ln Effective attenuation length [m] + * \param alpha Distance dependence (power term) + * \param kmin Minimal kappa + * \param kmax Maximal kappa + */ + JPD0Transformer_t(const double ln, + const int alpha, + const double kmin, + const double kmax) : + ln (ln), + alpha(alpha), + kmin (kmin), + kmax (kmax) + {} + + + /** + * Clone object. + * + * \return pointer to newly created transformer + */ + virtual clone_type clone() const override + { + return new JPD0Transformer_t(*this); + } + + + /** + * Evaluate arrival time. + * + * \param buffer {D_m} + * \param xn old t_ns + * \return new t_ns + */ + virtual argument_type putXn(const_array_type& buffer, const argument_type xn) const override + { + using namespace JTOOLS; + + const double D = buffer[0]; + + double x = xn; + + const double t0 = D * getIndexOfRefraction() * getInverseSpeedOfLight(); + const double t1 = D * kmin * getInverseSpeedOfLight(); + + x -= t1 - t0; + + if (kmax > kmin) { + x /= D * (kmax - kmin) * getInverseSpeedOfLight(); + } + + return x; + } + + + /** + * Evaluate arrival time. + * + * \param buffer {D_m} + * \param xn old t_ns + * \return new t_ns + */ + virtual argument_type getXn(const_array_type& buffer, const argument_type xn) const override + { + using namespace JTOOLS; + + const double D = buffer[0]; + + double x = xn; + + if (kmax > kmin) { + x *= D * (kmax - kmin) * getInverseSpeedOfLight(); + } + + const double t0 = D * getIndexOfRefraction() * getInverseSpeedOfLight(); + const double t1 = D * kmin * getInverseSpeedOfLight(); + + x += t1 - t0; + + return x; + } + + + /** + * Weight function. + * + * \param buffer {D_m} + * \return weight + */ + virtual double getWeight(const_array_type& buffer) const override + { + using namespace JTOOLS; + + const double D = buffer[0]; + + const double d = sqrt(getDmin()*getDmin() + D*D); + + return exp(-d/ln) / pow(d,alpha); + } + + + /** + * Read PDF transformer from input. + * + * \param in reader + * \return reader + */ + virtual JReader& read(JReader& in) override + { + in >> ln; + in >> alpha; + in >> kmin; + in >> kmax; + + return in; + } + + + /** + * Write PDF transformer to output. + * + * \param out writer + * \return writer + */ + virtual JWriter& write(JWriter& out) const override + { + out << ln; + out << alpha; + out << kmin; + out << kmax; + + return out; + } + + + /** + * Print PDF transformer to output stream. + * + * \param out output stream + * \return output stream + */ + std::ostream& print(std::ostream& out) const + { + using namespace std; + + out << "Effective attenuation length [m] " << ln << endl; + out << "Distance dependence (power term) " << alpha << endl; + out << "Minimal kappa " << kmin << endl; + out << "Maximal kappa " << kmax << endl; + + return out; + } + + + double ln; //!< Effective attenuation length [m] + int alpha; //!< Distance dependence (power term) + double kmin; //!< minimal kappa + double kmax; //!< maximal kappa + }; + + + /** + * Transformer for the 2D probability density function (PDF) of the time response of a PMT due to an EM shower. + * + * PDFs are evaluated by interpolation for: + * -# distance between EM shower and PMT [m] + * -# cosine angle EM shower direction and EM shower - PMT position + * -# arrival time [ns] + * + * The evaluation of the weights is based on: + * -# effective attenuation length + * -# emission profile of the photons + */ + template<class JArgument_t> + class JPDGTransformer_t : + public JMultiMapTransformer<2, JArgument_t> + { + public: + + typedef JPD0Transformer_t <JArgument_t> JFunction1DTransformer_t; + typedef JMultiMapTransformer<2, JArgument_t> JMultiMapTransformer_t; + + typedef typename JMultiMapTransformer_t::clone_type clone_type; + typedef typename JMultiMapTransformer_t::argument_type argument_type; + typedef typename JMultiMapTransformer_t::const_array_type const_array_type; + + using JMultiMapTransformer_t::getWeight; + + + /** + * Default constructor. + */ + JPDGTransformer_t() : + transformer(), + getShowerProbability() + {} + + + /** + * Constructor. + * + * \param ln Effective attenuation length [m] + * \param alpha Distance dependence (power term) + * \param kmin Minimal kappa + * \param kmax Maximal kappa + * \param geant Function photon emission from EM-shower + * \param bmin Baseline photon emission from EM-shower + */ + JPDGTransformer_t(const double ln, + const int alpha, + const double kmin, + const double kmax, + const JGeant_t& geant, + const double bmin) : + transformer(ln, alpha, kmin, kmax), + getShowerProbability(geant) + { + getShowerProbability.add(bmin); + getShowerProbability.compile(); + } + + + /** + * Clone object. + * + * \return pointer to newly created transformer + */ + virtual clone_type clone() const override + { + return new JPDGTransformer_t(*this); + } + + + /** + * Evaluate arrival time. + * + * \param buffer {D_m, cd} + * \param xn old t_ns + * \return new t_ns + */ + virtual argument_type putXn(const_array_type& buffer, const argument_type xn) const override + { + return transformer.putXn(buffer, xn); + } + + + /** + * Evaluate arrival time. + * + * \param buffer {D_m, cd} + * \param xn old t_ns + * \return new t_ns + */ + virtual argument_type getXn(const_array_type& buffer, const argument_type xn) const override + { + return transformer.getXn(buffer, xn); + } + + + /** + * Weight function. + * + * \param buffer {D_m, cd} + * \return weight + */ + virtual double getWeight(const_array_type& buffer) const override + { + using namespace JTOOLS; + + //const double D = buffer[0]; + const double cd = buffer[1]; + + return transformer.getWeight(buffer) * getShowerProbability(getIndexOfRefractionPhase(), cd); + } + + + /** + * Read PDF transformer from input. + * + * \param in reader + * \return reader + */ + virtual JReader& read(JReader& in) override + { + in >> transformer; + in >> getShowerProbability; + + return in; + } + + + /** + * Write PDF transformer to output. + * + * \param out writer + * \return writer + */ + virtual JWriter& write(JWriter& out) const override + { + out << transformer; + out << getShowerProbability; + + return out; + } + + + /** + * Print PDF transformer to output stream. + * + * \param out output stream + * \return output stream + */ + std::ostream& print(std::ostream& out) const + { + return transformer.print(out); + } + + + JFunction1DTransformer_t transformer; + JGeant_t getShowerProbability; + }; + + + /** + * Template definition of transformer of the probability density function (PDF) of the time response of a PMT.\n + * The actual implementation follows from the number of dimensions. + */ + template<unsigned int N, class JArgument_t> + class JPDFTransformer; + + + /** + * Template specialisation of transformer of the 2D probability density function (PDF) of the time response of a PMT due to a bright point. + * + * PDFs are evaluated by interpolation for: + * -# distance between bright point and PMT [m] + * -# cosine PMT angle + * -# arrival time [ns] + * + * The evaluation of the weights is based on: + * -# effective attenuation length + */ + template<class JArgument_t> + class JPDFTransformer<2, JArgument_t> : + public JMultiMapTransformer<2, JArgument_t> + { + public: + + typedef JPD0Transformer_t <JArgument_t> JFunction1DTransformer_t; + typedef JMultiMapTransformer<2, JArgument_t> JMultiMapTransformer_t; + + typedef typename JMultiMapTransformer_t::clone_type clone_type; + typedef typename JMultiMapTransformer_t::argument_type argument_type; + typedef typename JMultiMapTransformer_t::const_array_type const_array_type; + + + /** + * Default constructor. + */ + JPDFTransformer() : + transformer() + {} + + + /** + * Constructor. + * + * \param ln Effective attenuation length [m] + * \param alpha Distance dependence (power term) + * \param kmin Minimal kappa + * \param kmax Maximal kappa + */ + JPDFTransformer(const double ln, + const int alpha, + const double kmin, + const double kmax) : + transformer(ln, alpha, kmin, kmax) + {} + + + /** + * Clone object. + * + * \return pointer to newly created transformer + */ + virtual clone_type clone() const override + { + return new JPDFTransformer(*this); + } + + + /** + * Evaluate arrival time. + * + * \param buffer {D_m, ct} + * \param xn old t_ns + * \return new t_ns + */ + virtual argument_type putXn(const_array_type& buffer, const argument_type xn) const override + { + return transformer.putXn(buffer, xn); + } + + + /** + * Evaluate arrival time. + * + * \param buffer {D_m, ct} + * \param xn old t_ns + * \return new t_ns + */ + virtual argument_type getXn(const_array_type& buffer, const argument_type xn) const override + { + return transformer.getXn(buffer, xn); + } + + + /** + * Weight function. + * + * \param buffer {D_m, ct} + * \return weight + */ + virtual double getWeight(const_array_type& buffer) const override + { + return transformer.getWeight(buffer); + } + + + /** + * Read PDF transformer from input. + * + * \param in reader + * \return reader + */ + virtual JReader& read(JReader& in) override + { + in >> transformer; + + return in; + } + + + /** + * Write PDF transformer to output. + * + * \param out writer + * \return writer + */ + virtual JWriter& write(JWriter& out) const override + { + out << transformer; + + return out; + } + + + /** + * Print PDF transfomer to output stream. + * + * \param out output stream + * \return output stream + */ + std::ostream& print(std::ostream& out) const + { + return transformer.print(out); + } + + + JFunction1DTransformer_t transformer; + }; + + + /** + * Template specialisation of transformer of the 3D probability density function (PDF) of the time response of a PMT due to a muon. + * + * PDFs are evaluated by interpolation for: + * -# distance of closest approach of the muon to the PMT [m] + * -# zenith angle of the PMT + * -# azimuthal angle of the PMT + * -# arrival time [ns] + * + * The evaluation of the weights is based on: + * -# effective attenuation length + * -# angular acceptance of PMT + */ + template<class JArgument_t> + class JPDFTransformer<3, JArgument_t> : + public JMultiMapTransformer<3, JArgument_t> + { + public: + + typedef JPDFTransformer_t <JArgument_t> JFunction1DTransformer_t; + typedef JMultiMapTransformer<3, JArgument_t> JMultiMapTransformer_t; + + typedef typename JMultiMapTransformer_t::clone_type clone_type; + typedef typename JMultiMapTransformer_t::argument_type argument_type; + typedef typename JMultiMapTransformer_t::const_array_type const_array_type; + + typedef JTOOLS::JGridPolint1Function1D_t JFunction1D_t; + + using JMultiMapTransformer_t::getWeight; + + + /** + * Default constructor. + */ + JPDFTransformer() : + transformer(), + getAngularAcceptance() + {} + + + /** + * Constructor. + * + * \param ln Effective attenuation length [m] + * \param alpha Distance dependence (power term) + * \param kmin Minimal kappa + * \param kmax Maximal kappa + * \param pmt Function angular acceptance of PMT + * \param amin Baseline angular acceptance of PMT + */ + template<class T> + JPDFTransformer(const double ln, + const int alpha, + const double kmin, + const double kmax, + T pmt, + const double amin) : + transformer(ln, alpha, kmin, kmax), + getAngularAcceptance() + { + getAngularAcceptance.configure(JTOOLS::make_grid(1000, -1.0, +1.0), pmt); + getAngularAcceptance.add(amin); + getAngularAcceptance.compile(); + getAngularAcceptance.setExceptionHandler(new JFunction1D_t::JDefaultResult(0.0)); + } + + + /** + * Clone object. + * + * \return pointer to newly created transformer + */ + virtual clone_type clone() const override + { + return new JPDFTransformer(*this); + } + + + /** + * Evaluate arrival time. + * + * \param buffer {R_m, theta, phi} + * \param xn old t_ns + * \return new t_ns + */ + virtual argument_type putXn(const_array_type& buffer, const argument_type xn) const override + { + return transformer.putXn(buffer, xn); + } + + + /** + * Evaluate arrival time. + * + * \param buffer {R_m, theta, phi} + * \param xn old t_ns + * \return new t_ns + */ + virtual argument_type getXn(const_array_type& buffer, const argument_type xn) const override + { + return transformer.getXn(buffer, xn); + } + + + /** + * Weight function. + * + * \param buffer {R_m, theta, phi} + * \return weight + */ + virtual double getWeight(const_array_type& buffer) const override + { + using namespace JTOOLS; + + //const double R = buffer[0]; + const double theta = buffer[1]; + const double phi = buffer[2]; + + const double n = getIndexOfRefraction(); + const double ct0 = 1.0 / n; + const double st0 = sqrt((1.0 + ct0)*(1.0 - ct0)); + + const double px = sin(theta)*cos(phi); + //const double py = sin(theta)*sin(phi); + const double pz = cos(theta); + + const double ct = st0*px + ct0*pz; + + return transformer.getWeight(buffer) * getAngularAcceptance(ct); + } + + + /** + * Read PDF transformer from input. + * + * \param in reader + * \return reader + */ + virtual JReader& read(JReader& in) override + { + in >> transformer; + in >> getAngularAcceptance; + + getAngularAcceptance.compile(); + + return in; + } + + + /** + * Write PDF transformer to output. + * + * \param out writer + * \return writer + */ + virtual JWriter& write(JWriter& out) const override + { + out << transformer; + out << getAngularAcceptance; + + return out; + } + + + /** + * Print PDF transformer to output stream. + * + * \param out output stream + * \return output stream + */ + std::ostream& print(std::ostream& out) const + { + return transformer.print(out); + } + + + JFunction1DTransformer_t transformer; + JFunction1D_t getAngularAcceptance; + }; + + + /** + * Template specialisation of transformer of the 4D probability density function (PDF) of the time response of a PMT due to an EM shower. + * + * PDFs are evaluated by interpolation for: + * -# distance between EM shower and PMT [m] + * -# cosine angle EM shower direction and EM shower - PMT position + * -# zenith angle of the PMT + * -# azimuthal angle of the PMT + * -# arrival time [ns] + * + * The evaluation of the weights is based on: + * -# effective attenuation length + * -# emission profile of the photons + * -# angular acceptance of PMT + */ + template<class JArgument_t> + class JPDFTransformer<4, JArgument_t> : + public JMultiMapTransformer<4, JArgument_t> + { + public: + + typedef JPDGTransformer_t <JArgument_t> JFunction2DTransformer_t; + typedef JMultiMapTransformer<4, JArgument_t> JMultiMapTransformer_t; + + typedef typename JMultiMapTransformer_t::clone_type clone_type; + typedef typename JMultiMapTransformer_t::argument_type argument_type; + typedef typename JMultiMapTransformer_t::const_array_type const_array_type; + + typedef JTOOLS::JGridPolint1Function1D_t JFunction1D_t; + + using JMultiMapTransformer_t::getWeight; + + + /** + * Default constructor. + */ + JPDFTransformer() : + transformer(), + getAngularAcceptance() + {} + + + /** + * Constructor. + * + * \param ln Effective attenuation length [m] + * \param alpha Distance dependence (power term) + * \param kmin Minimal kappa + * \param kmax Maximal kappa + * \param geant Function photon emission from EM-shower + * \param bmin Baseline photon emission from EM-shower + * \param pmt Function angular acceptance of PMT + * \param amin Baseline angular acceptance of PMT + */ + template<class T> + JPDFTransformer(const double ln, + const int alpha, + const double kmin, + const double kmax, + const JGeant_t& geant, + const double bmin, + T pmt, + const double amin) : + transformer(ln, alpha, kmin, kmax, geant, bmin), + getAngularAcceptance() + { + getAngularAcceptance.configure(JTOOLS::make_grid(1000, -1.0, +1.0), pmt); + getAngularAcceptance.add(amin); + getAngularAcceptance.compile(); + getAngularAcceptance.setExceptionHandler(new JFunction1D_t::JDefaultResult(0.0)); + } + + + /** + * Clone object. + * + * \return pointer to newly created transformer + */ + virtual clone_type clone() const override + { + return new JPDFTransformer(*this); + } + + + /** + * Evaluate arrival time. + * + * \param buffer {D_m, cd, theta, phi} + * \param xn old t_ns + * \return new t_ns + */ + virtual argument_type putXn(const_array_type& buffer, const argument_type xn) const override + { + return transformer.putXn(buffer, xn); + } + + + /** + * Evaluate arrival time. + * + * \param buffer {D_m, cd, theta, phi} + * \param xn old t_ns + * \return new t_ns + */ + virtual argument_type getXn(const_array_type& buffer, const argument_type xn) const override + { + return transformer.getXn(buffer, xn); + } + + + /** + * Weight function. + * + * \param buffer {D_m, cd, theta, phi} + * \return weight + */ + virtual double getWeight(const_array_type& buffer) const override + { + const double cd = buffer[1]; + const double theta = buffer[2]; + const double phi = buffer[3]; + + const double ct0 = cd; + const double st0 = sqrt((1.0 + ct0)*(1.0 - ct0)); + + const double px = sin(theta)*cos(phi); + //const double py = sin(theta)*sin(phi); + const double pz = cos(theta); + + const double ct = st0*px + ct0*pz; + + return transformer.getWeight(buffer) * getAngularAcceptance(ct); + } + + + /** + * Read PDF transformer from input. + * + * \param in reader + * \return reader + */ + virtual JReader& read(JReader& in) override + { + in >> transformer; + in >> getAngularAcceptance; + + getAngularAcceptance.compile(); + + return in; + } + + + /** + * Write PDF transformer to output. + * + * \param out writer + * \return writer + */ + virtual JWriter& write(JWriter& out) const override + { + out << transformer; + out << getAngularAcceptance; + + return out; + } + + + /** + * Print PDF transfomer to output stream. + * + * \param out output stream + * \return output stream + */ + std::ostream& print(std::ostream& out) const + { + return transformer.print(out); + } + + + JFunction2DTransformer_t transformer; + JFunction1D_t getAngularAcceptance; + }; + + + /** + * Template specialisation of transformer of the 5D probability density function (PDF) of the time response of a PMT due to an EM shower. + * + * PDFs are evaluated by interpolation for: + * -# energy of the EM shower + * -# distance between EM shower and PMT [m] + * -# cosine angle EM shower direction and EM shower - PMT position + * -# zenith angle of the PMT + * -# azimuthal angle of the PMT + * -# arrival time [ns] + * + * The evaluation of the weights is based on: + * -# energy of the EM shower + * -# effective attenuation length + * -# emission profile of the photons + * -# angular acceptance of PMT + */ + template<class JArgument_t> + class JPDFTransformer<5, JArgument_t> : + public JMultiMapTransformer<5, JArgument_t> + { + public: + + typedef JPDFTransformer <4, JArgument_t> JFunction4DTransformer_t; + typedef JMultiMapTransformer<5, JArgument_t> JMultiMapTransformer_t; + + typedef typename JMultiMapTransformer_t::clone_type clone_type; + typedef typename JMultiMapTransformer_t::argument_type argument_type; + typedef typename JMultiMapTransformer_t::const_array_type const_array_type; + + + /** + * Default constructor. + */ + JPDFTransformer() : + transformer() + {} + + + /** + * Constructor. + * + * \param ln Effective attenuation length [m] + * \param alpha Distance dependence (power term) + * \param kmin Minimal kappa + * \param kmax Maximal kappa + * \param geant Function photon emission from EM-shower + * \param bmin Baseline photon emission from EM-shower + * \param pmt Function angular acceptance of PMT + * \param amin Baseline angular acceptance of PMT + */ + + template<class T> + JPDFTransformer(const double ln, + const int alpha, + const double kmin, + const double kmax, + const JGeant_t& geant, + const double bmin, + T pmt, + const double amin) : + transformer(ln, alpha, kmin, kmax, geant, bmin, pmt, amin) + {} + + + /** + * Clone object. + * + * \return pointer to newly created transformer + */ + virtual clone_type clone() const override + { + return new JPDFTransformer(*this); + } + + + /** + * Evaluate arrival time. + * + * \param buffer {E_GeV, D_m, cd, theta, phi} + * \param xn old t_ns + * \return new t_ns + */ + virtual argument_type putXn(const_array_type& buffer, const argument_type xn) const override + { + return transformer.putXn(buffer.pop_front(), xn); + } + + + /** + * Evaluate arrival time. + * + * \param buffer {E_GeV, D_m, cd, theta, phi} + * \param xn old t_ns + * \return new t_ns + */ + virtual argument_type getXn(const_array_type& buffer, const argument_type xn) const override + { + return transformer.getXn(buffer.pop_front(), xn); + } + + + /** + * Weight function. + * + * \param buffer {E_GeV, D_m, cd, theta, phi} + * \return weight + */ + virtual double getWeight(const_array_type& buffer) const override + { + const double E = buffer[0]; + + return transformer.getWeight(buffer.pop_front()) / E; + } + + + /** + * Read PDF transformer from input. + * + * \param in reader + * \return reader + */ + virtual JReader& read(JReader& in) override + { + in >> transformer; + + return in; + } + + + /** + * Write PDF transformer to output. + * + * \param out writer + * \return writer + */ + virtual JWriter& write(JWriter& out) const override + { + out << transformer; + + return out; + } + + + /** + * Print PDF transfomer to output stream. + * + * \param out output stream + * \return output stream + */ + std::ostream& print(std::ostream& out) const + { + return transformer.print(out); + } + + JFunction4DTransformer_t transformer; + }; +} + +#endif diff --git a/jpp/JPhysics/JPDFTypes.hh b/jpp/JPhysics/JPDFTypes.hh new file mode 100644 index 0000000..8c71d47 --- /dev/null +++ b/jpp/JPhysics/JPDFTypes.hh @@ -0,0 +1,201 @@ +#ifndef __JPHYSICS__JPDFTYPES__ +#define __JPHYSICS__JPDFTYPES__ + +#include <string> +#include <sstream> + +#include "JLang/JException.hh" +#include "Jeep/JeepToolkit.hh" + +/** + * \file + * + * Numbering scheme for PDF types. + * \author mdejong + */ +namespace JPHYSICS {} +namespace JPP { using namespace JPHYSICS; } + +namespace JPHYSICS { + + using JLANG::JException; + + + /** + * PDF types + */ + enum JPDFType_t { + + DIRECT_LIGHT_FROM_MUON = 1, //!< direct light from muon + SCATTERED_LIGHT_FROM_MUON = 2, //!< scattered light from muon + + DIRECT_LIGHT_FROM_EMSHOWERS = 3, //!< direct light from EM showers + SCATTERED_LIGHT_FROM_EMSHOWERS = 4, //!< scattered light from EM showers + + DIRECT_LIGHT_FROM_DELTARAYS = 5, //!< direct light from delta-rays + SCATTERED_LIGHT_FROM_DELTARAYS = 6, //!< scattered light from delta-rays + + SCATTERED_LIGHT_FROM_MUON_5D = 12, //!< scattered light from muon + + DIRECT_LIGHT_FROM_EMSHOWER = 13, //!< direct light from EM shower + SCATTERED_LIGHT_FROM_EMSHOWER = 14, //!< scattered light from EM shower + + //DIRECT_LIGHT_FROM_SHOWER = 15, //!< direct + scattered light from HADRONIC shower + + DIRECT_LIGHT_FROM_BRIGHT_POINT = 23, //!< direct light from bright point + SCATTERED_LIGHT_FROM_BRIGHT_POINT = 24, //!< scattered light from bright point + + LIGHT_FROM_MUON = 1001, //!< direct and scattered light from muon + LIGHT_FROM_EMSHOWERS = 1003, //!< direct and scattered light from EM showers + LIGHT_FROM_DELTARAYS = 1005, //!< direct and scattered light from delta-rays + LIGHT_FROM_EMSHOWER = 1013, //!< direct and scattered light from EM shower + LIGHT_FROM_BRIGTH_POINT = 1023 //!< direct and scattered light from brigth point + }; + + + static const char WILD_CARD = '%'; //!< wild card character for file name substitution + + + /** + * Get PDF label. + * + * \param pdf PDF type + * \return PDF label + */ + inline std::string getLabel(const JPDFType_t pdf) + { + std::ostringstream os; + + os << pdf; + + return os.str(); + } + + + /** + * Get PDF type. + * + * \param file_name file name + * \return PDF type (-1 in case of error) + */ + inline int getPDFType(const std::string& file_name) + { + using namespace std; + + static const char* digits = "0123456789"; + + int type = -1; + + string buffer = JEEP::getFilename(file_name); + + string::size_type pos = buffer.find_first_of(digits); + + if (pos != string::npos) { + + string::size_type len = buffer.substr(pos).find_first_not_of(digits); + + istringstream(buffer.substr(pos, len)) >> type; + } + + return type; + } + + + /** + * Check wild card. + * + * \param file_name file name + * \return true if wild card present; else false + */ + inline bool hasWildCard(const std::string& file_name) + { + return (file_name.find(WILD_CARD) != std::string::npos); + } + + + /** + * Get PDF file name. + * + * The input file name should contain the wild card character WILD_CARD + * which will be replaced by the label corresponding to the given PDF type. + * + * \param file_name input file name + * \param pdf PDF type + * \return output file name + */ + inline std::string getFilename(const std::string& file_name, + const JPDFType_t pdf) + { + using namespace std; + + string buffer = file_name; + + string::size_type pos = buffer.find(WILD_CARD); + + if (pos == string::npos) { + throw JException(string("Method getFilename(): Missing wild card character \'") + WILD_CARD + "\'."); + } + + return buffer.replace(pos, 1, getLabel(pdf)); + } + + + /** + * Test if given PDF type corresponds to Cherenkov light from muon. + * + * \param pdf PDF type + * \return true if PDF corresponds to muon; else false + */ + inline bool is_muon(const int pdf) + { + return (pdf == DIRECT_LIGHT_FROM_MUON || + pdf == SCATTERED_LIGHT_FROM_MUON || + pdf == LIGHT_FROM_MUON); + } + + + /** + * Test if given PDF type corresponds to Cherenkov light from Bremsstrahlung. + * + * \param pdf PDF type + * \return true if PDF corresponds to Bremsstrahlung; else false + */ + inline bool is_bremsstrahlung(const int pdf) + { + return (pdf == DIRECT_LIGHT_FROM_EMSHOWERS || + pdf == SCATTERED_LIGHT_FROM_EMSHOWERS || + pdf == LIGHT_FROM_EMSHOWERS); + } + + + /** + * Test if given PDF type corresponds to Cherenkov light from delta-rays. + * + * \param pdf PDF type + * \return true if PDF corresponds to delta-rays; else false + */ + inline bool is_deltarays(const int pdf) + { + return (pdf == DIRECT_LIGHT_FROM_DELTARAYS || + pdf == SCATTERED_LIGHT_FROM_DELTARAYS || + pdf == LIGHT_FROM_DELTARAYS); + } + + + /** + * Test if given PDF type corresponds to scattered light. + * + * \param pdf PDF type + * \return true if PDF corresponds to scattered light; else false + */ + inline bool is_scattered(const int pdf) + { + return (pdf == SCATTERED_LIGHT_FROM_MUON || + pdf == SCATTERED_LIGHT_FROM_EMSHOWERS || + pdf == SCATTERED_LIGHT_FROM_DELTARAYS || + pdf == SCATTERED_LIGHT_FROM_MUON_5D || + pdf == SCATTERED_LIGHT_FROM_EMSHOWER); + } +} + +#endif diff --git a/jpp/JPhysics/JPDF_t.hh b/jpp/JPhysics/JPDF_t.hh new file mode 100644 index 0000000..bfc0ff2 --- /dev/null +++ b/jpp/JPhysics/JPDF_t.hh @@ -0,0 +1,383 @@ +#include "JLang/JException.hh" +#include "JTools/JCollection.hh" +#include "JTools/JMap.hh" +#include "JTools/JGridMap.hh" +#include "JTools/JMapList.hh" +#include "JTools/JSpline.hh" +#include "JTools/JPolint.hh" +#include "JTools/JElement.hh" +#include "JTools/JResult.hh" +#include "JPhysics/JPDFTable.hh" +#include "JPhysics/JPDFToolkit.hh" +#include "JPhysics/JPDFTypes.hh" +#include "JMath/JZero.hh" + + +/** + * \file + * + * Auxiliary data structure for muon PDF. + * \author mdejong + */ + +/** + * Auxiliary data structure for muon PDF. + */ +struct JPDF { + + typedef JPP::JSplineFunction1D<JPP::JSplineElement2S<double, double>, + JPP::JCollection, + JPP::JResultPDF<double> > JFunction1D_t; + + typedef JPP::JMAPLIST<JPP::JPolint1FunctionalMap, + JPP::JPolint0FunctionalGridMap, + JPP::JPolint0FunctionalGridMap>::maplist JPDFMaplist_t; + typedef JPP::JPDFTable<JFunction1D_t, JPDFMaplist_t> JPDF_t; + typedef JFunction1D_t::result_type result_type; + + + /** + * Constructor. + * + * The <tt>TTS</tt> corresponds to the additional time smearing applied to the PDFs. + * + * \param file_name file name + * \param TTS TTS [ns] + * \param numberOfPoints number of points for Gauss-Hermite integration of TTS + * \param epsilon precision for Gauss-Hermite integration of TTS + */ + JPDF(const std::string& file_name, + const double TTS, + const int numberOfPoints = 25, + const double epsilon = 1.0e-10) + { + using namespace std; + using namespace JPP; + + const JPDF_t::JSupervisor supervisor(new JPDF_t::JDefaultResult(zero)); + + cout << "loading input from file " << file_name << "... " << flush; + + pdf.load(file_name.c_str()); + + pdf.setExceptionHandler(supervisor); + + cout << "OK" << endl; + + type = getPDFType(file_name); + + if (TTS > 0.0) { + + cout << "bluring PDFs... " << flush; + + pdf.blur(TTS, numberOfPoints, epsilon); + + cout << "OK" << endl; + + } else if (TTS < 0.0) { + + THROW(JValueOutOfRange, "Illegal value of TTS [ns]: " << TTS); + } + } + + + /** + * Get PDF. + * + * The orientation of the PMT should be defined according this <a href="https://common.pages.km3net.de/jpp/JPDF.PDF">documentation</a>.\n + * In this, the zenith and azimuth angles are limited to \f[\left[0, \pi\right]\f]. + * + * \param E muon energy at minimum distance of approach [GeV] + * \param R minimum distance of approach [m] + * \param theta PMT zenith angle [rad] + * \param phi PMT azimuth angle [rad] + * \param t1 arrival time relative to Cherenkov hypothesis [ns] + * \return hypothesis value + */ + result_type calculate(const double E, + const double R, + const double theta, + const double phi, + const double t1) const + { + using namespace JPP; + + result_type h1 = pdf(R, theta, phi, t1); + + if (is_bremsstrahlung(type)) { + h1 *= E; + } else if (is_deltarays(type)) { + h1 *= getDeltaRaysFromMuon(E); + } + + // safety measures + + if (h1.f <= 0.0) { + h1.f = 0.0; + h1.fp = 0.0; + } + + if (h1.v <= 0.0) { + h1.v = 0.0; + } + + return h1; + } + + JPDF_t pdf; //!< PDF + int type; //!< PDF type +}; + + +/** + * Auxiliary data structure for muon PDF. + */ +struct JMuonPDF_t { + + typedef JPP::JSplineFunction1D<JPP::JSplineElement2S<double, double>, + JPP::JCollection, + JPP::JResultPDF<double> > JFunction1D_t; + + typedef JPP::JMAPLIST<JPP::JPolint1FunctionalMap, + JPP::JPolint0FunctionalGridMap, + JPP::JPolint0FunctionalGridMap>::maplist JPDFMaplist_t; + typedef JPP::JPDFTable<JFunction1D_t, JPDFMaplist_t> JPDF_t; + typedef JFunction1D_t::result_type result_type; + + + /** + * Constructor. + * + * The PDF file descriptor should contain the wild card character JPHYSICS::WILD_CARD.\n + * The <tt>TTS</tt> corresponds to the additional time smearing applied to the PDFs. + * + * \param fileDescriptor PDF file descriptor + * \param TTS TTS [ns] + * \param numberOfPoints number of points for Gauss-Hermite integration of TTS + * \param epsilon precision for Gauss-Hermite integration of TTS + */ + JMuonPDF_t(const std::string& fileDescriptor, + const double TTS, + const int numberOfPoints = 25, + const double epsilon = 1.0e-10) + { + using namespace std; + using namespace JPP; + + const JPDFType_t pdf_t[] = { DIRECT_LIGHT_FROM_MUON, + SCATTERED_LIGHT_FROM_MUON, + DIRECT_LIGHT_FROM_EMSHOWERS, + SCATTERED_LIGHT_FROM_EMSHOWERS, + DIRECT_LIGHT_FROM_DELTARAYS, + SCATTERED_LIGHT_FROM_DELTARAYS }; + + const int N = sizeof(pdf_t) / sizeof(pdf_t[0]); + + JPDF_t pdf[N]; + + const JPDF_t::JSupervisor supervisor(new JPDF_t::JDefaultResult(zero)); + + for (int i = 0; i != N; ++i) { + + const string file_name = getFilename(fileDescriptor, pdf_t[i]); + + cout << "loading input from file " << file_name << "... " << flush; + + pdf[i].load(file_name.c_str()); + + pdf[i].setExceptionHandler(supervisor); + + cout << "OK" << endl; + } + + // Add PDFs + + cout << "adding PDFs... " << flush; + + pdfA = pdf[1]; pdfA.add(pdf[0]); + pdfB = pdf[3]; pdfB.add(pdf[2]); + pdfC = pdf[5]; pdfC.add(pdf[4]); + + cout << "OK" << endl; + + if (TTS > 0.0) { + + cout << "bluring PDFs... " << flush; + + pdfA.blur(TTS, numberOfPoints, epsilon); + pdfB.blur(TTS, numberOfPoints, epsilon); + pdfC.blur(TTS, numberOfPoints, epsilon); + + cout << "OK" << endl; + + } else if (TTS < 0.0) { + + THROW(JValueOutOfRange, "Illegal value of TTS [ns]: " << TTS); + } + } + + + /** + * Get PDF. + * + * The orientation of the PMT should be defined according this <a href="https://common.pages.km3net.de/jpp/JPDF.PDF">documentation</a>.\n + * In this, the zenith and azimuth angles are limited to \f[\left[0, \pi\right]\f]. + * + * \param E muon energy at minimum distance of approach [GeV] + * \param R minimum distance of approach [m] + * \param theta PMT zenith angle [rad] + * \param phi PMT azimuth angle [rad] + * \param t1 arrival time relative to Cherenkov hypothesis [ns] + * \return hypothesis value + */ + result_type calculate(const double E, + const double R, + const double theta, + const double phi, + const double t1) const + { + using namespace JPP; + + result_type h1 = (pdfA(R, theta, phi, t1) + + pdfB(R, theta, phi, t1) * E + + pdfC(R, theta, phi, t1) * getDeltaRaysFromMuon(E)); + + // safety measures + + if (h1.f <= 0.0) { + h1.f = 0.0; + h1.fp = 0.0; + } + + if (h1.v <= 0.0) { + h1.v = 0.0; + } + + return h1; + } + + JPDF_t pdfA; //!< PDF for minimum ionisong particle + JPDF_t pdfB; //!< PDF for average energy losses + JPDF_t pdfC; //!< PDF for delta-rays +}; + + +/** + * Auxiliary data structure for shower PDF. + */ +struct JShowerPDF_t { + + typedef JPP::JSplineFunction1D<JPP::JSplineElement2S<double, double>, + JPP::JCollection, + JPP::JResultPDF<double> > JFunction1D_t; + + typedef JPP::JMAPLIST<JPP::JPolint1FunctionalMap, + JPP::JPolint1FunctionalMap, + JPP::JPolint0FunctionalGridMap, + JPP::JPolint0FunctionalGridMap>::maplist JPDFMaplist_t; + typedef JPP::JPDFTable<JFunction1D_t, JPDFMaplist_t> JPDF_t; + typedef JFunction1D_t::result_type result_type; + + + /** + * Constructor. + * + * The PDF file descriptor should contain the wild card character JPHYSICS::WILD_CARD.\n + * The <tt>TTS</tt> corresponds to the additional time smearing applied to the PDFs. + * + * \param fileDescriptor PDF file descriptor + * \param TTS TTS [ns] + * \param numberOfPoints number of points for Gauss-Hermite integration of TTS + * \param epsilon precision for Gauss-Hermite integration of TTS + */ + JShowerPDF_t(const std::string& fileDescriptor, + const double TTS, + const int numberOfPoints = 25, + const double epsilon = 1.0e-10) + { + using namespace std; + using namespace JPP; + + const JPDFType_t pdf_t[] = { SCATTERED_LIGHT_FROM_EMSHOWER, + DIRECT_LIGHT_FROM_EMSHOWER }; + + const int N = sizeof(pdf_t) / sizeof(pdf_t[0]); + + const JPDF_t::JSupervisor supervisor(new JPDF_t::JDefaultResult(zero)); + + for (int i = 0; i != N; ++i) { + + const string file_name = getFilename(fileDescriptor, pdf_t[i]); + + cout << "loading input from file " << file_name << "... " << flush; + + JPDF_t pdf; + + pdf.load(file_name.c_str()); + + pdf.setExceptionHandler(supervisor); + + if (pdfA.empty()) + pdfA = pdf; + else + pdfA.add(pdf); + + cout << "OK" << endl; + } + + if (TTS > 0.0) { + + cout << "bluring PDFs... " << flush; + + pdfA.blur(TTS, numberOfPoints, epsilon); + + cout << "OK" << endl; + + } else if (TTS < 0.0) { + + THROW(JValueOutOfRange, "Illegal value of TTS [ns]: " << TTS); + } + } + + + /** + * Get PDF. + * + * The orientation of the PMT should be defined according this <a href="https://common.pages.km3net.de/jpp/JPDF.PDF">documentation</a>.\n + * In this, the zenith and azimuth angles are limited to \f[\left[0, \pi\right]\f]. + * + * \param E shower energy at minimum distance of approach [GeV] + * \param D distance [m] + * \param cd cosine emission angle + * \param theta PMT zenith angle [rad] + * \param phi PMT azimuth angle [rad] + * \param t1 arrival time relative to Cherenkov hypothesis [ns] + * \return hypothesis value + */ + result_type calculate(const double E, + const double D, + const double cd, + const double theta, + const double phi, + const double t1) const + { + using namespace JPP; + + result_type h1 = pdfA(D, cd, theta, phi, t1) * E; + + // safety measures + + if (h1.f <= 0.0) { + h1.f = 0.0; + h1.fp = 0.0; + } + + if (h1.v <= 0.0) { + h1.v = 0.0; + } + + return h1; + } + + JPDF_t pdfA; //!< PDF for shower +}; diff --git a/jpp/JTools/JAbstractCollection.hh b/jpp/JTools/JAbstractCollection.hh new file mode 100644 index 0000000..0145837 --- /dev/null +++ b/jpp/JTools/JAbstractCollection.hh @@ -0,0 +1,88 @@ +#ifndef __JTOOLS__JABSTRACTCOLLECTION__ +#define __JTOOLS__JABSTRACTCOLLECTION__ + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + /** + * Abstract interface for abscissa values of a collection of elements. + */ + template<class JAbscissa_t> + struct JAbstractCollection { + + typedef JAbscissa_t abscissa_type; + + + /** + * Virtual destructor. + */ + virtual ~JAbstractCollection() + {} + + + /** + * Get number of elements. + * + * \return number of elements + */ + virtual int getSize() const = 0; + + + /** + * Get abscissa value. + * + * \param index index + * \return abscissa value + */ + virtual abscissa_type getX(int index) const = 0; + + + /** + * Get minimal abscissa value. + * + * \return abscissa value + */ + virtual abscissa_type getXmin() const = 0; + + + /** + * Get maximal abscissa value. + * + * \return abscissa value + */ + virtual abscissa_type getXmax() const = 0; + + + /** + * Test whether abstract collections are equal. + * + * \param collection abstract collection + * \return true if collections are equals; else false + */ + bool is_equal(const JAbstractCollection& collection) const + { + if (this->getSize() == collection.getSize()) { + + for (int i = 0; i != this->getSize(); ++i) { + + if (this->getX(i) != collection.getX(i)) { + return false; + } + } + + return true; + } + + return false; + } + }; +} + +#endif diff --git a/jpp/JTools/JAbstractMultiMap.hh b/jpp/JTools/JAbstractMultiMap.hh new file mode 100644 index 0000000..66d70f3 --- /dev/null +++ b/jpp/JTools/JAbstractMultiMap.hh @@ -0,0 +1,62 @@ +#ifndef __JTOOLS__JABSTRACTMULTIMAP__ +#define __JTOOLS__JABSTRACTMULTIMAP__ + +#include "JTools/JAbstractCollection.hh" +#include "JTools/JMultiKey.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + /** + * Abstract interface for abscissa values of a multidimensional map. + * + * The template parameters refer to the dimension of the multimap and + * the data type of the abscissa values, respectively. + */ + template<unsigned int N, class JAbscissa_t> + struct JAbstractMultiMap : + public virtual JAbstractMultiMap<N - 1, JAbscissa_t> + { + typedef JAbscissa_t abscissa_type; + typedef JMultiKey<N - 1, abscissa_type> key_type; + + using JAbstractMultiMap<N - 1, JAbscissa_t>::operator(); + + + /** + * Virtual destructor. + */ + virtual ~JAbstractMultiMap() + {} + + + /** + * Get abscissa values as a function of given key. + * + * \param key key + * \return abscissa values + */ + virtual const JAbstractCollection<abscissa_type>& operator()(const key_type& key) const = 0; + }; + + + /** + * Terminator class of recursive class JAbstractMultiMap. + * This class provides for dummy implementations of interface methods. + */ + template<class JAbscissa_t> + struct JAbstractMultiMap<0, JAbscissa_t> + { + protected: + void operator()() const {} + }; +} + +#endif diff --git a/jpp/JTools/JArray.hh b/jpp/JTools/JArray.hh new file mode 100644 index 0000000..383b87a --- /dev/null +++ b/jpp/JTools/JArray.hh @@ -0,0 +1,1265 @@ +#ifndef __JTOOLS__JARRAY__ +#define __JTOOLS__JARRAY__ + +#include <istream> +#include <ostream> +#include <iterator> +#include <algorithm> + +#include "JIO/JSerialisable.hh" +#include "JTools/JMultiKey.hh" +#include "JMath/JMath.hh" +#include "JLang/JAssert.hh" +#include "JLang/JClass.hh" +#include "JLang/JException.hh" +#include "JLang/JEquals.hh" +#include "JLang/JManip.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JIO::JReader; + using JIO::JWriter; + using JMATH::JMath; + using JLANG::JEquals; + using JLANG::JIndexOutOfRange; + + + /** + * One dimensional array of template objects with fixed length.\n + * The internal data structure consists of a standard C-array. + */ + template<unsigned int N, class T> + class JArray : + public JMath < JArray<N,T> >, + public JEquals< JArray<N,T> > + { + public: + + typedef const T* const_pointer; + typedef T* pointer; + typedef const T* const_iterator; + typedef T* iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef T& reference; + typedef const T& const_reference; + typedef unsigned int size_type; + typedef typename JLANG::JClass<T>::argument_type argument_type; + + + /** + * Default constructor. + */ + JArray() + {} + + + /** + * Copy constructor. + * + * \param array array + */ + template<unsigned int M> + JArray(const JArray<M, T>& array) + { + STATIC_CHECK(M >= N); + + std::copy_n(array.data(), N, this->data()); + } + + + /** + * Copy constructor. + * + * \param array array + */ + template<unsigned int M> + JArray(const JArray<M, const T>& array) + { + STATIC_CHECK(M >= N); + + std::copy_n(array.data(), N, this->data()); + } + + + /** + * Copy constructor. + * + * \param p pointer to data + */ + JArray(const T* p) + { + std::copy_n(p, N, this->data()); + } + + + /** + * Copy constructor. + * + * \param key multi-dimensional key + */ + JArray(const JMultiKey<N, T>& key) + { + assign(key); + } + + + /** + * Copy constructor. + * + * \param key multi-dimensional key + */ + JArray(const JMultiKey<N, const T>& key) + { + assign(key); + } + + + /** + * Append constructor. + * + * \param array array + * \param value value + */ + JArray(const JArray<N-1, T>& array, argument_type value) + { + std::copy_n(array.data(), N-1, this->data()); + + this->buffer[N-1] = value; + } + + + /** + * Append constructor. + * + * \param array array + * \param value value + */ + JArray(const JArray<N-1, const T>& array, argument_type value) + { + std::copy_n(array.data(), N-1, this->data()); + + this->buffer[N-1] = value; + } + + + /** + * Append constructor. + * + * \param key multi-dimensional key + * \param value value + */ + JArray(const JMultiKey<N-1, T>& key, argument_type value) + { + assign(key, value); + } + + + /** + * Append constructor. + * + * \param key multi-dimensional key + * \param value value + */ + JArray(const JMultiKey<N-1, const T>& key, argument_type value) + { + assign(key, value); + } + + + /** + * Initialise constructor. + * + * \param value first value + * \param args remaining values + */ + template<class ...Args> + JArray(argument_type value, const Args& ...args) + { + set(value, args...); + } + + + /** + * Set array. + * + * \param args values + */ + template<class ...Args> + JArray& set(const Args& ...args) + { + STATIC_CHECK(N == sizeof...(Args)); + + __set__(0, args...); + + return *this; + } + + + const_iterator begin() const { return buffer; } //!< get iterator to begin of data + const_iterator end() const { return buffer + N; } //!< get iterator to end of data + + + iterator begin() { return buffer; } //!< get iterator to begin of data + iterator end() { return buffer + N; } //!< get iterator to end of data + + + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } //!< get reverse iterator to begin of data + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } //!< get reverse iterator to begin of data + + + reverse_iterator rbegin() { return reverse_iterator(end()); } //!< get reverse iterator to begin of data + reverse_iterator rend() { return reverse_iterator(begin()); } //!< get reverse iterator to end of data + + + /** + * Get element at given index. + * + * \param index index + * \return element + */ + const_reference operator[](int index) const + { + return buffer[index]; + } + + + /** + * Get element at given index. + * + * \param index index + * \return element + */ + reference operator[](int index) + { + return buffer[index]; + } + + + /** + * Get element at given index. + * + * \param index index + * \return element at index + */ + const_reference at(int index) const + { + if (index >= 0 && index < N) + return buffer[index]; + else + throw JIndexOutOfRange("JArray<>::at()"); + } + + + /** + * Get element at given index. + * + * \param index index + * \return element at index + */ + reference at(int index) + { + if (index >= 0 && index < N) + return buffer[index]; + else + throw JIndexOutOfRange("JArray<>::at()"); + } + + + /** + * Get pointer to data. + * + * \return pointer to data + */ + const_pointer data() const + { + return buffer; + } + + + /** + * Get pointer to data. + * + * \return pointer to data + */ + pointer data() + { + return buffer; + } + + + /** + * Get size of data. + * + * \return size of data + */ + static size_type size() + { + return N; + } + + + /** + * Make a copy in which the first element is removed. + * + * \return array + */ + JArray<N-1, T> pop_front() const + { + return JArray<N-1, T>(&buffer[1]); + } + + + /** + * Make a copy in which the last element is removed. + * + * \return array + */ + JArray<N-1, T> pop_back() const + { + return JArray<N-1, T>(buffer); + } + + + /** + * Negate array. + * + * \return this array + */ + JArray& negate() + { + for (int i = 0; i != N; ++i) { + buffer[i] = -buffer[i]; + } + + return *this; + } + + + /** + * Add array. + * + * \param array array + * \return this array + */ + JArray& add(const JArray& array) + { + for (int i = 0; i != N; ++i) { + buffer[i] += array[i]; + } + + return *this; + } + + + /** + * Subtract array. + * + * \param array array + * \return this array + */ + JArray& sub(const JArray& array) + { + for (int i = 0; i != N; ++i) { + buffer[i] -= array[i]; + } + + return *this; + } + + + /** + * Scale array. + * + * \param factor multiplication factor + * \return this array + */ + JArray& mul(const double factor) + { + for (int i = 0; i != N; ++i) { + buffer[i] *= factor; + } + + return *this; + } + + + /** + * Scale array. + * + * \param factor division factor + * \return this array + */ + JArray& div(const double factor) + { + for (int i = 0; i != N; ++i) { + buffer[i] /= factor; + } + + return *this; + } + + + /** + * Check equality. + * + * \param array array + * \return true if arrays are equal; else false + */ + bool equals(const JArray<N, T>& array) const + { + for (int i = 0; i != N; ++i) { + if (buffer[i] != array[i]) { + return false; + } + } + + return true; + } + + + /** + * Read array from input stream. + * + * \param in input stream + * \param array array + * \return input stream + */ + friend inline std::istream& operator>>(std::istream& in, JArray& array) + { + for (iterator i = array.begin(); i != array.end(); ++i) { + in >> *i; + } + + return in; + } + + + /** + * Write array to output stream. + * + * \param out output stream + * \param array array + * \return output stream + */ + friend inline std::ostream& operator<<(std::ostream& out, const JArray& array) + { + for (const_iterator i = array.begin(); i != array.end(); ++i) { + out << ' ' << SCIENTIFIC(12,5) << *i; + } + + return out; + } + + + /** + * Read array from input. + * + * \param in reader + * \param buffer array + * \return reader + */ + friend inline JReader& operator>>(JReader& in, JArray& buffer) + { + for (iterator i = buffer.begin(); i != buffer.end(); ++i) { + in >> *i; + } + + return in; + } + + + /** + * Write array to output. + * + * \param out writer + * \param buffer array + * \return writer + */ + friend inline JWriter& operator<<(JWriter& out, const JArray& buffer) + { + for (const_iterator i = buffer.begin(); i != buffer.end(); ++i) { + out << *i; + } + + return out; + } + + protected: + + T buffer[N]; + + + /** + * Recursive method for setting array. + * + * \param i index + * \param x value at given index + * \param args remaining values + */ + template<class ...Args> + void __set__(const int i, const argument_type x, const Args& ...args) + { + this->buffer[i] = x; + + __set__(i + 1, args...); + } + + + /** + * Termination method for setting array. + * + * \param i index + */ + void __set__(const int i) const + {} + + + /** + * Recursive method for setting array. + * + * \param key multi-dimensional key + */ + template<unsigned int M> + void assign(const JMultiKey<M, T>& key) + { + buffer[N-M] = key.first; + + assign(key.second); + } + + + /** + * Recursive method for setting array. + * + * \param key multi-dimensional key + */ + template<unsigned int M> + void assign(const JMultiKey<M, const T>& key) + { + buffer[N-M] = key.first; + + assign(key.second); + } + + + /** + * Termination method for setting array. + * + * \param key one-dimensional key + */ + void assign(const JMultiKey<1, T>& key) + { + buffer[N-1] = key.first; + } + + + /** + * Termination method for setting array. + * + * \param key one-dimensional key + */ + void assign(const JMultiKey<1, const T>& key) + { + buffer[N-1] = key.first; + } + + + /** + * Recursive method for setting array. + * + * \param key multi-dimensional key + * \param value value + */ + template<unsigned int M> + void assign(const JMultiKey<M, T>& key, argument_type value) + { + buffer[N-M-1] = key.first; + + assign(key.second, value); + } + + + /** + * Recursive method for setting array. + * + * \param key multi-dimensional key + * \param value value + */ + template<unsigned int M> + void assign(const JMultiKey<M, const T>& key, argument_type value) + { + buffer[N-M-1] = key.first; + + assign(key.second, value); + } + + + /** + * Termination method for setting array. + * + * \param key one-dimensional key + * \param value value + */ + void assign(const JMultiKey<1, T>& key, argument_type value) + { + buffer[N-2] = key.first; + buffer[N-1] = value; + } + + + /** + * Termination method for setting array. + * + * \param key one-dimensional key + * \param value value + */ + void assign(const JMultiKey<1, const T>& key, argument_type value) + { + buffer[N-2] = key.first; + buffer[N-1] = value; + } + }; + + + /** + * One dimensional array of template objects with fixed length. + * The internal data structure consists of a standard C-array. + */ + template<class T> + class JArray<1, T> : + public JMath < JArray<1,T> >, + public JEquals< JArray<1,T> > + { + public: + + static const unsigned int N = 1; + + typedef const T* const_pointer; + typedef T* pointer; + typedef const T* const_iterator; + typedef T* iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef T& reference; + typedef const T& const_reference; + typedef unsigned int size_type; + typedef typename JLANG::JClass<T>::argument_type argument_type; + + + /** + * Default constructor. + */ + JArray() + {} + + + /** + * Copy constructor. + * + * \param array array + */ + template<unsigned int M> + JArray(const JArray<M, T>& array) + { + buffer[0] = array[0]; + } + + + /** + * Copy constructor. + * + * \param array array + */ + template<unsigned int M> + JArray(const JArray<M, const T>& array) + { + buffer[0] = array[0]; + } + + + /** + * Copy constructor. + * + * \param p pointer to data + */ + JArray(const T* p) + { + buffer[0] = p[0]; + } + + + /** + * Copy constructor. + * + * \param key multi-dimensional key + */ + JArray(const JMultiKey<1, T>& key) + { + buffer[0] = key.first; + } + + + /** + * Copy constructor. + * + * \param key multi-dimensional key + */ + JArray(const JMultiKey<1, const T>& key) + { + buffer[0] = key.first; + } + + + /** + * Initialise constructor. + * + * \param x value; + */ + JArray(argument_type x) + { + buffer[0] = x; + } + + + const_iterator begin() const { return buffer; } //!< get iterator to begin of data + const_iterator end() const { return buffer + N; } //!< get iterator to end of data + + + iterator begin() { return buffer; } //!< get iterator to begin of data + iterator end() { return buffer + N; } //!< get iterator to end of data + + + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } //!< get reverse iterator to begin of data + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } //!< get reverse iterator to begin of data + + + reverse_iterator rbegin() { return reverse_iterator(end()); } //!< get reverse iterator to begin of data + reverse_iterator rend() { return reverse_iterator(begin()); } //!< get reverse iterator to end of data + + + /** + * Get element at given index. + * + * \param index index + * \return element + */ + const_reference operator[](int index) const + { + return buffer[index]; + } + + + /** + * Get element at given index. + * + * \param index index + * \return element + */ + reference operator[](int index) + { + return buffer[index]; + } + + + /** + * Get element at given index. + * + * \param index index + * \return element at index + */ + const_reference at(int index) const + { + if (index >= 0 && index < N) + return buffer[index]; + else + throw JIndexOutOfRange("JArray<>::at()"); + } + + + /** + * Get element at given index. + * + * \param index index + * \return element at index + */ + reference at(int index) + { + if (index >= 0 && index < N) + return buffer[index]; + else + throw JIndexOutOfRange("JArray<>::at()"); + } + + + /** + * Get pointer to data. + * + * \return pointer to data + */ + const_pointer data() const + { + return buffer; + } + + + /** + * Get pointer to data. + * + * \return pointer to data + */ + pointer data() + { + return buffer; + } + + + /** + * Get size of data. + * + * \return size of data + */ + static size_type size() + { + return N; + } + + + /** + * Negate array. + * + * \return this array + */ + JArray& negate() + { + buffer[0] = -buffer[0]; + + return *this; + } + + + /** + * Add array. + * + * \param array array + * \return this array + */ + JArray& add(const JArray& array) + { + buffer[0] += array[0]; + + return *this; + } + + + /** + * Subtract array. + * + * \param array array + * \return this array + */ + JArray& sub(const JArray& array) + { + buffer[0] -= array[0]; + + return *this; + } + + + /** + * Scale array. + * + * \param factor multiplication factor + * \return this array + */ + JArray& mul(const double factor) + { + buffer[0] *= factor; + + return *this; + } + + + /** + * Scale array. + * + * \param factor division factor + * \return this array + */ + JArray& div(const double factor) + { + buffer[0] /= factor; + + return *this; + } + + + /** + * Check equality. + * + * \param array array + * \return true if arrays are equal; else false + */ + bool equals(const JArray<N, T>& array) const + { + return buffer[0] == array[0]; + } + + + /** + * Read array from input stream. + * + * \param in input stream + * \param array array + * \return input stream + */ + friend inline std::istream& operator>>(std::istream& in, JArray& array) + { + for (iterator i = array.begin(); i != array.end(); ++i) { + in >> *i; + } + + return in; + } + + + /** + * Write array to output stream. + * + * \param out output stream + * \param array array + * \return output stream + */ + friend inline std::ostream& operator<<(std::ostream& out, const JArray& array) + { + for (const_iterator i = array.begin(); i != array.end(); ++i) { + out << ' ' << SCIENTIFIC(12,5) << *i; + } + + return out; + } + + + /** + * Read array from input. + * + * \param in reader + * \param buffer array + * \return reader + */ + friend inline JReader& operator>>(JReader& in, JArray& buffer) + { + return in >> buffer[0]; + } + + + /** + * Write array to output. + * + * \param out writer + * \param buffer array + * \return writer + */ + friend inline JWriter& operator<<(JWriter& out, const JArray& buffer) + { + return out << buffer[0]; + } + + protected: + T buffer[1]; + }; + + + /** + * One dimensional read-only array of template objects with fixed length. + * The internal data structure consists of a simple C-pointer to the actual data. + * The user should ensure that the data are persistent. + */ + template<unsigned int N, class T> + class JArray<N, const T> { + public: + + friend class JArray<N + 1, const T>; + + typedef const T* const_pointer; + typedef const T* const_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef const T& const_reference; + typedef unsigned int size_type; + + + /** + * Copy constructor. + * + * \param array array + */ + template<unsigned int M> + JArray(const JArray<M, T>& array) : + p(array.data()) + { + STATIC_CHECK(M >= N); + } + + + /** + * Copy constructor. + * + * \param array array + */ + template<unsigned int M> + JArray(const JArray<M, const T>& array) : + p(array.data()) + { + STATIC_CHECK(M >= N); + } + + + const_iterator begin() const { return p; } //!< get iterator to begin of data + const_iterator end() const { return p + N; } //!< get iterator to end of data + + + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } //!< get reverse iterator to begin of data + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } //!< get reverse iterator to end of data + + + /** + * Get element at given index. + * + * \param index index + * \return element at index + */ + const_reference operator[](int index) const + { + return p[index]; + } + + + /** + * Get element at given index. + * + * \param index index + * \return element at index + */ + const_reference at(int index) const + { + if (index >= 0 && index < N) + return p[index]; + else + throw JIndexOutOfRange("JArray<>::at()"); + } + + + /** + * Get pointer to data. + * + * \return pointer to data + */ + const_pointer data() const + { + return p; + } + + + /** + * Get size of data. + * + * \return size of data + */ + static size_type size() + { + return N; + } + + + /** + * Make a copy in which the first element is removed. + * + * \return array + */ + JArray<N-1, const T> pop_front() const + { + return JArray<N-1, const T>(p + 1); + } + + + /** + * Make a copy in which the last element is removed. + * + * \return array + */ + JArray<N-1, const T> pop_back() const + { + return JArray<N-1, const T>(p); + } + + + /** + * Write array to output. + * + * \param out writer + * \param buffer array + * \return writer + */ + friend inline JWriter& operator<<(JWriter& out, const JArray& buffer) + { + for (const_iterator i = buffer.begin(); i != buffer.end(); ++i) { + out << *i; + } + + return out; + } + + protected: + + const_pointer p; + + /** + * Constructor. + * + * \param __p pointer to data + */ + JArray(const T* __p) : + p(__p) + {} + }; + + + /** + * One dimensional read-only array of template objects with fixed length. + * The internal data structure consists of a simple C-pointer to the actual data. + * The user should ensure that the data are persistent. + */ + template<class T> + class JArray<1, const T> { + public: + + static const unsigned int N = 1; + + friend class JArray<N + 1, const T>; + + typedef const T* const_pointer; + typedef const T* const_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef const T& const_reference; + typedef unsigned int size_type; + + + /** + * Copy constructor. + * + * \param array array + */ + template<unsigned int M> + JArray(const JArray<M, T>& array) : + p(array.data()) + { + STATIC_CHECK(M >= N); + } + + + /** + * Copy constructor. + * + * \param array array + */ + template<unsigned int M> + JArray(const JArray<M, const T>& array) : + p(array.data()) + { + STATIC_CHECK(M >= N); + } + + + const_iterator begin() const { return p; } //!< get iterator to begin of data + const_iterator end() const { return p + N; } //!< get iterator to end of data + + + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } //!< get reverse iterator to begin of data + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } //!< get reverse iterator to end of data + + + /** + * Get element at given index. + * + * \param index index + * \return element at index + */ + const_reference operator[](int index) const + { + return p[index]; + } + + + /** + * Get element at given index. + * + * \param index index + * \return element at index + */ + const_reference at(int index) const + { + if (index >= 0 && index < N) + return p[index]; + else + throw JIndexOutOfRange("JArray<>::at()"); + } + + + /** + * Get pointer to data. + * + * \return pointer to data + */ + const_pointer data() const + { + return p; + } + + + /** + * Get size of data. + * + * \return size of data + */ + static size_type size() + { + return N; + } + + + /** + * Write array to output. + * + * \param out writer + * \param buffer array + * \return writer + */ + friend inline JWriter& operator<<(JWriter& out, const JArray& buffer) + { + return out << buffer[0]; + } + + protected: + + const_pointer p; + + /** + * Constructor. + * + * \param __p pointer to data + */ + JArray(const T* __p) : + p(__p) + {} + }; +} + +#endif diff --git a/jpp/JTools/JAssembler.hh b/jpp/JTools/JAssembler.hh new file mode 100644 index 0000000..25768e3 --- /dev/null +++ b/jpp/JTools/JAssembler.hh @@ -0,0 +1,40 @@ +#ifndef __JTOOLS__JASSEMBLER__ +#define __JTOOLS__JASSEMBLER__ + +#include "JLang/JVoid.hh" + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JLANG::JVoid; + + + /** + * Auxiliary class to check whether given template is a collection, + * i.e.\ has a defined type <tt>collection_type</tt>. + */ + template<class T, class JType_t = void> + struct JAssembler + { + static const bool is_collection = false; + }; + + + /** + * Template specialisation of class JAssembler for classes + * with a defined type <tt>collection_type</tt>. + */ + template<class T> + struct JAssembler<T, typename JVoid<typename T::collection_type>::type> + { + static const bool is_collection = true; + }; +} + +#endif diff --git a/jpp/JTools/JCollection.hh b/jpp/JTools/JCollection.hh new file mode 100644 index 0000000..a366cc3 --- /dev/null +++ b/jpp/JTools/JCollection.hh @@ -0,0 +1,836 @@ +#ifndef __JTOOLS__JCOLLECTION__ +#define __JTOOLS__JCOLLECTION__ + +#include <vector> +#include <cmath> +#include <limits> +#include <algorithm> + +#include "JLang/JClass.hh" +#include "JLang/JException.hh" +#include "JLang/JLangToolkit.hh" +#include "JMath/JZero.hh" +#include "JMath/JMath.hh" +#include "JIO/JSerialisable.hh" +#include "JTools/JDistance.hh" +#include "JTools/JTransformer.hh" +#include "JTools/JMappableCollection.hh" +#include "JTools/JAbstractCollection.hh" + +/** + * \file + * + * General purpose class for a collection of sorted elements. + * \author mdejong + */ +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JMATH::JMath; + using JIO::JReader; + using JIO::JWriter; + using JLANG::JValueOutOfRange; + using JLANG::JClass; + using JLANG::JException; + + + /** + * General purpose class for collection of elements, see: + \htmlonly + <a href="JTools.PDF";>Collection of elements.</a> + \endhtmlonly + * + * This class implements the JMappableCollection and JAbstractCollection interfaces. + * + * The data type of the elements of the collection should have the following policy + * type definition and member methods. + * <pre> + * typedef \<abscissa type\> abscissa_type; + * typedef \<ordinate type\> ordinate_type; + * + * (constructor)(abscissa_type, ordinate_type); + * + * abscissa_type %getX() const; + * ordinate_type %getY() const; + * ordinate_type& %getY(); + * </pre> + * + * The elements in a collection are sorted according to their abscissa values and + * the given distance operator. + * The distance operator constitues a binary method returning the distance between + * two abscissa values; The default distance operator is JDistance. + * + * For the binary I/O of a collection of elements, the data structure of the elements + * should provide for an implementation of the following operators: + * <pre> + * JReader& operator>>(JReader& in); + * JWriter& operator<<(JWriter& out); + * </pre> + */ + template<class JElement_t, class JDistance_t = JDistance<typename JElement_t::abscissa_type> > + class JCollection : + public std::vector<JElement_t>, + public JMappableCollection<typename JElement_t::abscissa_type, + typename JElement_t::ordinate_type>, + public JAbstractCollection<typename JElement_t::abscissa_type>, + public JMath< JCollection<JElement_t, JDistance_t> > + { + public: + + typedef typename JElement_t::abscissa_type abscissa_type; + typedef typename JElement_t::ordinate_type ordinate_type; + typedef JElement_t value_type; + typedef JDistance_t distance_type; + + typedef JCollection<JElement_t, JDistance_t> collection_type; + + typedef std::vector<value_type> container_type; + + typedef typename container_type::const_iterator const_iterator; + typedef typename container_type::const_reverse_iterator const_reverse_iterator; + typedef typename container_type::iterator iterator; + typedef typename container_type::reverse_iterator reverse_iterator; + + typedef JCollectionElementTransformer<value_type> transformer_type; + typedef std::pair<const_iterator, bool> pair_type; + + using JMappableCollection<abscissa_type, ordinate_type>::operator[]; + + + /** + * Auxiliary class for ordering of objects in the collection by their abscissa values. + */ + struct JComparator { + /** + * Comparison of elements. + * + * \param first first element + * \param second second element + * \return true if first element less than second element; else false + */ + inline bool operator()(const JElement_t& first, + const JElement_t& second) const + { + return this->getDistance(first.getX(), second.getX()) > 0.0; + } + + + /** + * Comparison of element and abscissa value. + * + * \param element element + * \param x abscissa value + * \return true if element less than abscissa value; else false + */ + inline bool operator()(const JElement_t& element, typename JClass<abscissa_type>::argument_type x) const + { + return this->getDistance(element.getX(), x) > 0.0; + } + + + /** + * Function object for distance evaluation. + */ + JDistance_t getDistance; + }; + + + /** + * Default constructor. + */ + JCollection() + {} + + + /** + * Clear. + */ + virtual void clear() override + { + container_type::clear(); + } + + + /** + * Get ordinate value. + * + * \param x abscissa value + * \return ordinate value + */ + virtual const ordinate_type& get(typename JClass<abscissa_type>::argument_type x) const override + { + const_iterator i = this->lower_bound(x); + + if (i == this->end() || this->getDistance(x, i->getX()) > distance_type::precision) { + THROW(JValueOutOfRange, "Invalid abscissa value " << x); + } + + return i->getY(); + } + + + /** + * Get ordinate value. + * + * \param x abscissa value + * \return ordinate value + */ + virtual ordinate_type& get(typename JClass<abscissa_type>::argument_type x) override + { + iterator i = this->lower_bound(x); + + if (i == this->end() || this->getDistance(x, i->getX()) > distance_type::precision) { + i = container_type::insert(i, value_type(x, ordinate_type())); + } + + return i->getY(); + } + + + /** + * Get number of elements. + * + * \return number of elements + */ + virtual int getSize() const override + { + return (int) this->size(); + } + + + /** + * Get abscissa value. + * + * \param index index + * \return abscissa value + */ + virtual abscissa_type getX(int index) const override + { + return this->at(index).getX(); + } + + + /** + * Get minimal abscissa value. + * + * \return abscissa value + */ + virtual abscissa_type getXmin() const override + { + return this->begin()->getX(); + } + + + /** + * Get maximal abscissa value. + * + * \return abscissa value + */ + virtual abscissa_type getXmax() const override + { + return this->rbegin()->getX(); + } + + + + /** + * Get ordinate value. + * + * \param index index + * \return ordinate value + */ + const ordinate_type& getY(int index) const + { + return this->at(index).getY(); + } + + + /** + * Get ordinate value. + * + * \param index index + * \return ordinate value + */ + ordinate_type& getY(int index) + { + return this->at(index).getY(); + } + + + /** + * Transform collection. + * + * \param transformer element transformer + */ + void transform(const transformer_type& transformer) + { + collection_type buffer; + + this->swap(buffer); + + for (const_iterator i = buffer.begin(); i != buffer.end(); ++i) { + this->insert(transformer(*i)); + } + } + + + /** + * Sort elements. + */ + void sort() + { + std::sort(this->begin(), this->end(), compare); + } + + + /** + * Get first position of element <tt>i</tt>, where <tt>x >= i->getX()</tt>. + * + * \param x abscissa value + * \return position of corresponding element + */ + const_iterator lower_bound(typename JClass<abscissa_type>::argument_type x) const + { + return std::lower_bound(this->begin(), this->end(), x, compare); + } + + + /** + * Get first position of element <tt>i</tt>, where <tt>x >= i->getX()</tt>. + * + * \param x abscissa value + * \return position of corresponding element + */ + iterator lower_bound(typename JClass<abscissa_type>::argument_type x) + { + return std::lower_bound(this->begin(), this->end(), x, compare); + } + + + /** + * Insert element. + * + * \param element element + * \return (iterator, status), where status is true if inserted; else false + */ + pair_type insert(const value_type& element) + { + iterator i = this->lower_bound(element.getX()); + + if (i == this->end() || this->getDistance(element.getX(), i->getX()) > 0.0) + return pair_type(container_type::insert(i, element), true); + else + return pair_type(this->end(), false); + } + + + /** + * Configure collection. + * + * \param bounds abscissa values + */ + void configure(const JAbstractCollection<abscissa_type>& bounds) + { + configure(bounds, JMATH::getZero<ordinate_type>()); + } + + + /** + * Configure collection. + * + * \param bounds abscissa values + * \param value ordinate value + */ + void configure(const JAbstractCollection<abscissa_type>& bounds, + typename JClass<ordinate_type>::argument_type value) + { + this->resize(bounds.getSize()); + + for (iterator i = this->begin(); i != this->end(); ++i) { + + const abscissa_type x = bounds.getX(std::distance(this->begin(),i)); + + *i = value_type(x,value); + } + } + + + /** + * Configure collection. + * + * \param bounds abscissa values + * \param function function + */ + template<class JFunction1D_t> + void configure(const JAbstractCollection<abscissa_type>& bounds, + const JFunction1D_t& function) + { + using namespace JLANG; + + collection_type* out = (is_identical(*this, function) ? new collection_type() : this); + + for (int i = 0; i != bounds.getSize(); ++i) { + + const abscissa_type x = bounds.getX(i); + + out->put(x, function(x)); + } + + if (is_identical(*this, function)) { + + this->swap(*out); + + delete out; + } + } + + + /** + * Test whether collections are compatible. + * + * \param collection collection + * \return true if collections are compatible; else false + */ + bool is_compatible(const JCollection& collection) const + { + if (this->empty() || collection.empty()) { + + return true; + + } else { + + const double precision = JDistance<abscissa_type>::precision; + + const_iterator p = this->begin(); + const_iterator q = collection.begin(); + + if (getDistance(p->getX(), q->getX()) > precision) { + + do { + ++p; + } while (p != this->end() && getDistance(p->getX(), q->getX()) > precision); + + } else if (getDistance(q->getX(), p->getX()) > precision) { + + do { + ++q; + } while (q != collection.end() && getDistance(q->getX(), p->getX()) > precision); + } + + for ( ; p != this->end() && q != collection.end(); ++p, ++q) { + if (fabs(getDistance(p->getX(), q->getX())) > precision) { + return false; + } + } + + return true; + } + } + + + /** + * Negate collection. + * + * \return this collection + */ + JCollection& negate() + { + for (iterator i = this->begin(); i != this->end(); ++i) { + i->getY() = -i->getY(); + } + + return *this; + } + + + /** + * Add collection. + * + * \param collection collection + * \return this collection + */ + JCollection& add(const JCollection& collection) + { + if (!collection.empty()) { + + if (this->empty()) { + + for (const_iterator i = collection.begin(); i != collection.end(); ++i) { + this->put(i->getX(), +i->getY()); + } + + } else if (this->is_compatible(collection)) { + + const double precision = JDistance<abscissa_type>::precision; + + iterator p = this->begin(); + const_iterator q = collection.begin(); + + if (getDistance(p->getX(), q->getX()) > precision) { + + do { + ++p; + } while (p != this->end() && getDistance(p->getX(), q->getX()) > precision); + + } else if (getDistance(q->getX(), p->getX()) > precision) { + + do { + ++q; + } while (q != collection.end() && getDistance(q->getX(), p->getX()) > precision); + } + + const_iterator i = q; + + for ( ; p != this->end() && i != collection.end(); ++p, ++i) { + p->getY() += i->getY(); + } + + for ( ; i != collection.end(); ++i) { + this->put(i->getX(), +i->getY()); + } + + for (i = collection.begin(); i != q; ++i) { + this->put(i->getX(), +i->getY()); + } + } + } + + return *this; + } + + + /** + * Subtract collection. + * + * \param collection collection + * \return this collection + */ + JCollection& sub(const JCollection& collection) + { + if (!collection.empty()) { + + if (this->empty()) { + + for (const_iterator i = collection.begin(); i != collection.end(); ++i) { + this->put(i->getX(), -i->getY()); + } + + } else if (this->is_compatible(collection)) { + + const double precision = JDistance<abscissa_type>::precision; + + iterator p = this->begin(); + const_iterator q = collection.begin(); + + if (getDistance(p->getX(), q->getX()) > precision) { + + do { + ++p; + } while (p != this->end() && getDistance(p->getX(), q->getX()) > precision); + + } else if (getDistance(q->getX(), p->getX()) > precision) { + + do { + ++q; + } while (q != collection.end() && getDistance(q->getX(), p->getX()) > precision); + } + + const_iterator i = q; + + for ( ; p != this->end() && i != collection.end(); ++p, ++i) { + p->getY() -= i->getY(); + } + + for ( ; i != collection.end(); ++i) { + this->put(i->getX(), -i->getY()); + } + + for (i = collection.begin(); i != q; ++i) { + this->put(i->getX(), -i->getY()); + } + + } else { + + throw JException("JCollection::add() collections incompatible."); + } + } + + return *this; + } + + + /** + * Scale contents. + * + * \param value multiplication factor + * \return this collection + */ + JCollection& mul(const double value) + { + for (iterator i = this->begin(); i != this->end(); ++i) { + i->getY() *= value; + } + + return *this; + } + + + /** + * Scale contents. + * + * \param value division factor + * \return this collection + */ + JCollection& div(const double value) + { + for (iterator i = this->begin(); i != this->end(); ++i) { + i->getY() /= value; + } + + return *this; + } + + + /** + * Add offset. + * + * \param value offset + * \return this collection + */ + JCollection& add(typename JClass<ordinate_type>::argument_type value) + { + for (iterator i = this->begin(); i != this->end(); ++i) { + i->getY() += value; + } + + return *this; + } + + + /** + * Subtract offset. + * + * \param value offset + * \return this collection + */ + JCollection& sub(typename JClass<ordinate_type>::argument_type value) + { + for (iterator i = this->begin(); i != this->end(); ++i) { + i->getY() -= value; + } + + return *this; + } + + + /** + * Add function. + * + * \param function function + * \return this collection + */ + template<class JFunction1D_t> + JCollection& add(const JFunction1D_t& function) + { + for (iterator i = this->begin(); i != this->end(); ++i) { + i->getY() += function(i->getX()); + } + + return *this; + } + + + /** + * Subtract function. + * + * \param function function + * \return this collection + */ + template<class JFunction1D_t> + JCollection& sub(const JFunction1D_t& function) + { + for (iterator i = this->begin(); i != this->end(); ++i) { + i->getY() -= function(i->getX()); + } + + return *this; + } + + + /** + * Add offset to collaction. + * + * \param collection collection + * \param value offset + * \return collection + */ + friend JCollection& operator+=(JCollection& collection, typename JClass<ordinate_type>::argument_type value) + { + return collection.add(value); + } + + + /** + * Subtract offset from collaction. + * + * \param collection collection + * \param value offset + * \return collection + */ + friend JCollection& operator-=(JCollection& collection, typename JClass<ordinate_type>::argument_type value) + { + return collection.sub(value); + } + + + /** + * Add function. + * + * \param collection collection + * \param function function + * \return this collection + */ + template<class JFunction1D_t> + friend JCollection& operator+=(JCollection& collection, const JFunction1D_t& function) + { + return collection.add(function); + } + + + /** + * Subtract function. + * + * \param collection collection + * \param function function + * \return this collection + */ + template<class JFunction1D_t> + friend JCollection& operator-=(JCollection& collection, const JFunction1D_t& function) + { + return collection.sub(function); + } + + + /** + * Read collection from input. + * + * \param in reader + * \param collection collection + * \return reader + */ + friend inline JReader& operator>>(JReader& in, JCollection& collection) + { + int n; + + in >> n; + + collection.resize(n); + + for (typename JCollection::iterator i = collection.begin(); i != collection.end(); ++i) { + in >> *i; + } + + return in; + } + + + /** + * Write collection to output. + * + * \param out writer + * \param collection collection + * \return writer + */ + friend inline JWriter& operator<<(JWriter& out, const JCollection& collection) + { + const int n = collection.size(); + + out << n; + + for (typename JCollection::const_iterator i = collection.begin(); i != collection.end(); ++i) { + out << *i; + } + + return out; + } + + + /** + * Get comparator. + * + * \return comparator + */ + const JComparator& getComparator() const + { + return compare; + } + + + /** + * Function object for distance evaluation. + */ + JDistance_t getDistance; + + + protected: + /** + * Function object for comparison. + */ + JComparator compare; + + + /** + * Resize collection + * + * \param size size + */ + void resize(typename container_type::size_type size) + { + container_type::resize(size); + } + + private: + void erase(); + void push_back(); + void pop_back(); + }; + + + /** + * Conversion of data points to integral values. + * + * The integration is based on the trapezoidal rule applied to the input data points. + * + * \param input collection + * \param output mappable collection + * \return integral + */ + template<class JElement_t, + class JDistance_t> + inline typename JElement_t::ordinate_type + integrate(const JCollection<JElement_t, JDistance_t>& input, typename JMappable<JElement_t>::map_type& output) + { + typedef typename JElement_t::ordinate_type ordinate_type; + typedef typename JCollection<JElement_t, JDistance_t>::const_iterator const_iterator; + + ordinate_type V(JMATH::zero); + + if (input.getSize() > 1) { + + output.put(input.begin()->getX(), V); + + for (const_iterator j = input.begin(), i = j++; j != input.end(); ++i, ++j) { + + V += 0.5 * input.getDistance(i->getX(), j->getX()) * (i->getY() + j->getY()); + + output.put(j->getX(), V); + } + } + + return V; + } +} + +#endif diff --git a/jpp/JTools/JConstantFunction1D.hh b/jpp/JTools/JConstantFunction1D.hh new file mode 100644 index 0000000..8ee9e14 --- /dev/null +++ b/jpp/JTools/JConstantFunction1D.hh @@ -0,0 +1,206 @@ +#ifndef __JCONSTANTFUNCTION1D__ +#define __JCONSTANTFUNCTION1D__ + +#include "JIO/JSerialisable.hh" +#include "JTools/JFunctional.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JIO::JReader; + using JIO::JWriter; + + /** + * Template implementation of function object in one dimension returning a constant value. + * + * This class implements the JFunction1D interface. + */ + template<class JArgument_t, class JResult_t> + class JConstantFunction1D : + public JFunction1D<JArgument_t, JResult_t> + { + public: + + typedef JFunction1D<JArgument_t, JResult_t> function_type; + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + + + /** + * Default constructor. + */ + JConstantFunction1D() : + function_type(), + __y() + {} + + + /** + * Constructor. + * + * \param y value + */ + JConstantFunction1D(const result_type y) : + function_type(), + __y(y) + {} + + + /** + * Constructor. + * + * \param y zero + */ + JConstantFunction1D(const JMATH::JZero& y) : + function_type(), + __y(y) + {} + + + /** + * Add offset. + * + * \param value offset + */ + JConstantFunction1D& add(typename JLANG::JClass<result_type>::argument_type value) + { + __y += value; + + return *this; + } + + + /** + * Subtract offset. + * + * \param value offset + */ + JConstantFunction1D& sub(typename JLANG::JClass<result_type>::argument_type value) + { + __y -= value; + + return *this; + } + + + /** + * Scale contents. + * + * \param value multiplication factor + */ + JConstantFunction1D& mul(const double value) + { + __y *= value; + + return *this; + } + + + /** + * Scale contents. + * + * \param value division factor + */ + JConstantFunction1D& div(const double value) + { + __y /= value; + + return *this; + } + + + /** + * Add function. + * + * \param function function + */ + JConstantFunction1D& add(const JConstantFunction1D& function) + { + __y += function.getY(); + + return *this; + } + + + /** + * Subtract function. + * + * \param function function + */ + JConstantFunction1D& sub(const JConstantFunction1D& function) + { + __y -= function.getY(); + + return *this; + } + + + /** + * Function value. + * + * \return function value + */ + result_type getY() const + { + return __y; + } + + + /** + * Function value evaluation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const override + { + return __y; + } + + + /** + * Read function from input. + * + * \param in reader + * \param function function + * \return reader + */ + friend inline JReader& operator>>(JReader& in, JConstantFunction1D& function) + { + return in >> function.__y; + } + + + /** + * Write function to output. + * + * \param out writer + * \param function function + * \return writer + */ + friend inline JWriter& operator<<(JWriter& out, const JConstantFunction1D& function) + { + return out << function.__y; + } + + + protected: + /** + * Function compilation. + */ + virtual void do_compile() override + {} + + private: + result_type __y; + }; +} + +#endif diff --git a/jpp/JTools/JConstants.hh b/jpp/JTools/JConstants.hh new file mode 100644 index 0000000..351227a --- /dev/null +++ b/jpp/JTools/JConstants.hh @@ -0,0 +1,22 @@ +#ifndef __JTOOLS__JCONSTANTS__ +#define __JTOOLS__JCONSTANTS__ + +#include <math.h> + +#include "JMath/JConstants.hh" + +/** + * \file + * Constants. + * \author mdejong + */ +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JMATH::PI; + using JMATH::EULER; +} + +#endif diff --git a/jpp/JTools/JDistance.hh b/jpp/JTools/JDistance.hh new file mode 100644 index 0000000..8ba53f4 --- /dev/null +++ b/jpp/JTools/JDistance.hh @@ -0,0 +1,55 @@ +#ifndef __JTOOLS__JDISTANCE__ +#define __JTOOLS__JDISTANCE__ + +#include <limits> + +#include "JLang/JClass.hh" + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + /** + * Template class for distance evaluation. + * + * This class should be specialised for data types when the distance + * between two values is not equal to the arithmetic minus operation. + */ + template<class JAbscissa_t> + struct JDistance { + + typedef typename JLANG::JClass<JAbscissa_t>::argument_type argument_type; + + + /** + * Get distance between values. + * + * The distance should be negative, zero or positive if the first value + * is respectively larger, equal or smaller compared to the second value. + * + * \param first first value + * \param second second value + * \return distance + */ + inline double operator()(argument_type first, argument_type second) const + { + return second - first; + } + + static double precision; + }; + + + /** + * Default precision. + */ + template<class JAbscissa_t> + double JDistance<JAbscissa_t>::precision = std::numeric_limits<double>::min(); +} + +#endif diff --git a/jpp/JTools/JElement.hh b/jpp/JTools/JElement.hh new file mode 100644 index 0000000..693a28d --- /dev/null +++ b/jpp/JTools/JElement.hh @@ -0,0 +1,611 @@ +#ifndef __JTOOLS__JELEMENT__ +#define __JTOOLS__JELEMENT__ + +#include <cmath> + +#include "JMath/JZero.hh" +#include "JMath/JMath.hh" +#include "JLang/JClass.hh" +#include "JIO/JSerialisable.hh" + + +/** + * \file + * + * The elements in a collection are sorted according to their abscissa values and a given distance operator. + * These elements should have the following type definitions and member methods: + * <pre> + * typedef \<abscissa type\> abscissa_type; + * typedef \<ordinate type\> ordinate_type; + * + * constructor(); + * constructor(abscissa_type, ordinate_type); + * + * abscissa_type getX() const; + * const ordinate_type& getY() const; + * ordinate_type& getY(); + * </pre> + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JIO::JReader; + using JIO::JWriter; + using JMATH::JMath; + using JMATH::getZero; + + + /** + * 2D Element. + */ + template<class JAbscissa_t, class JOrdinate_t> + struct JElement2D { + + typedef JAbscissa_t abscissa_type; + typedef JOrdinate_t ordinate_type; + + + /** + * Default constructor. + */ + JElement2D() : + __x(getZero<abscissa_type>()), + __y(getZero<ordinate_type>()) + {} + + + /** + * Constructor. + * + * \param x abscissa value + * \param y ordinate value + */ + JElement2D(typename JLANG::JClass<abscissa_type>::argument_type x, + typename JLANG::JClass<ordinate_type>::argument_type y) : + __x(x), + __y(y) + {} + + + /** + * Get abscissa value. + * + * \return abscissa value + */ + abscissa_type getX() const + { + return __x; + } + + + /** + * Get ordinate value. + * + * \return ordinate value + */ + const ordinate_type& getY() const + { + return __y; + } + + + /** + * Get ordinate value. + * + * \return ordinate value + */ + ordinate_type& getY() + { + return __y; + } + + + /** + * Read element from input. + * + * \param in reader + * \param element element + * \return reader + */ + friend inline JReader& operator>>(JReader& in, JElement2D& element) + { + in >> element.__x; + in >> element.__y; + + return in; + } + + + /** + * Write element to output. + * + * \param out writer + * \param element element + * \return writer + */ + friend inline JWriter& operator<<(JWriter& out, const JElement2D& element) + { + out << element.__x; + out << element.__y; + + return out; + } + + + protected: + abscissa_type __x; + ordinate_type __y; + }; + + + /** + * 2D Element for spline interpolations. + * + * Note that the internal data members needed for the calculation + * of the 2nd derivatives are not subject to I/O, i.e.\ the I/O of + * this class is identical to that of the JElement2D class. + */ + template<class JAbscissa_t, class JOrdinate_t> + struct JSplineElement2D : + public JElement2D<JAbscissa_t, JOrdinate_t> + { + + typedef JElement2D<JAbscissa_t, JOrdinate_t> element_type; + typedef typename element_type::abscissa_type abscissa_type; + typedef typename element_type::ordinate_type ordinate_type; + + + /** + * Default constructor. + */ + JSplineElement2D() : + element_type(), + __u(getZero<ordinate_type>()) + {} + + + /** + * Constructor. + * + * \param x abscissa value + * \param y ordinate value + */ + JSplineElement2D(typename JLANG::JClass<abscissa_type>::argument_type x, + typename JLANG::JClass<ordinate_type>::argument_type y) : + element_type(x, y), + __u(getZero<ordinate_type>()) + {} + + + /** + * Get derivative. + * + * \return derivative + */ + ordinate_type getU() const + { + return __u; + } + + + /** + * Set derivative. + * + * \param u derivative + */ + void setU(typename JLANG::JClass<ordinate_type>::argument_type u) + { + __u= u; + } + + + protected: + ordinate_type __u; + }; + + + /** + * 2D Element for spline interpolations. + * + * Note that the internal data members needed for the calculation + * of the integral values are not subject to I/O, i.e.\ the I/O of + * this class is identical to that of the JElement2D class. + */ + template<class JAbscissa_t, class JOrdinate_t> + struct JSplineElement2S : + public JSplineElement2D<JAbscissa_t, JOrdinate_t> + { + + typedef JSplineElement2D<JAbscissa_t, JOrdinate_t> element_type; + typedef typename element_type::abscissa_type abscissa_type; + typedef typename element_type::ordinate_type ordinate_type; + + + /** + * Default constructor. + */ + JSplineElement2S() : + element_type(), + __v(getZero<ordinate_type>()) + {} + + + /** + * Constructor. + * + * \param x abscissa value + * \param y ordinate value + */ + JSplineElement2S(typename JLANG::JClass<abscissa_type>::argument_type x, + typename JLANG::JClass<ordinate_type>::argument_type y) : + element_type(x, y), + __v(getZero<ordinate_type>()) + {} + + + /** + * Get integral. + * + * \return integral + */ + ordinate_type getIntegral() const + { + return __v; + } + + + /** + * Set integral. + * + * \param v integral + */ + void setIntegral(typename JLANG::JClass<ordinate_type>::argument_type v) + { + __v = v; + } + + + protected: + ordinate_type __v; + }; + + + /** + * 2D Element for polynomial interpolations. + * + * Note that the internal data members needed for the calculation + * of the integral values are not subject to I/O, i.e.\ the I/O of + * this class is identical to that of the JElement2D class. + */ + template<class JAbscissa_t, class JOrdinate_t> + struct JPolintElement2S : + public JElement2D<JAbscissa_t, JOrdinate_t> + { + + typedef JElement2D<JAbscissa_t, JOrdinate_t> element_type; + typedef typename element_type::abscissa_type abscissa_type; + typedef typename element_type::ordinate_type ordinate_type; + + + /** + * Default constructor. + */ + JPolintElement2S() : + element_type(), + __v(getZero<ordinate_type>()) + {} + + + /** + * Constructor. + * + * \param x abscissa value + * \param y ordinate value + */ + JPolintElement2S(typename JLANG::JClass<abscissa_type>::argument_type x, + typename JLANG::JClass<ordinate_type>::argument_type y) : + element_type(x, y), + __v(getZero<ordinate_type>()) + {} + + + /** + * Get integral. + * + * \return integral + */ + ordinate_type getIntegral() const + { + return __v; + } + + + /** + * Set integral. + * + * \param v integral + */ + void setIntegral(typename JLANG::JClass<ordinate_type>::argument_type v) + { + __v = v; + } + + + protected: + ordinate_type __v; + }; + + + /** + * 2D Binned element. + * + * Note that the internal data members needed for the calculation + * of the bin center are not subject to I/O, i.e.\ the I/O of + * this class is identical to that of the JElement2D class. + */ + template<class JAbscissa_t, class JOrdinate_t> + struct JBin2D : + public JElement2D<JAbscissa_t, JOrdinate_t>, + public JMath< JBin2D<JAbscissa_t, JOrdinate_t> > + { + + typedef JElement2D<JAbscissa_t, JOrdinate_t> element_type; + typedef typename element_type::abscissa_type abscissa_type; + typedef typename element_type::ordinate_type ordinate_type; + + + /** + * Default constructor. + */ + JBin2D() : + element_type(), + __z (getZero<ordinate_type>()), + __w2(getZero<ordinate_type>()) + {} + + + /** + * Constructor. + * + * \param x abscissa value + * \param y ordinate value + */ + JBin2D(typename JLANG::JClass<abscissa_type>::argument_type x, + typename JLANG::JClass<ordinate_type>::argument_type y) : + element_type(x,y), + __z (getZero<ordinate_type>()), + __w2(getZero<ordinate_type>()) + {} + + + /** + * Add abscissa value. + * + * \param x abscissa value + * \param w weight + */ + void fill(typename JLANG::JClass<abscissa_type>::argument_type x, + typename JLANG::JClass<ordinate_type>::argument_type w) + { + this->__y += w; + this->__z += w * x; + this->__w2 += w * w; + } + + + /** + * Get bin center. + * + * \return center + */ + abscissa_type getBinCenter() const + { + if (this->__y != 0) + return this->__z / this->__y; + else + return this->__x; + } + + + /** + * Get bin content. + * + * \return content + */ + ordinate_type getBinContent() const + { + return this->__y; + } + + + /** + * Get bin error. + * + * \return error + */ + ordinate_type getBinError() const + { + return sqrt(this->__w2); + } + + + /** + * Add bin. + * + * \param bin bin + * \return this bin + */ + JBin2D& add(const JBin2D& bin) + { + this->__y += bin.__y; + this->__z += bin.__zl; + this->__w2 += bin.__w2; + + return *this; + } + + + /** + * Scale contents. + * + * \param value multiplication factor + * \return this bin + */ + JBin2D& mul(const double value) + { + this->__y *= value; + this->__z *= value; + this->__w2 *= value*value; + + return *this; + } + + + /** + * Scale contents. + * + * \param value division factor + * \return this bin + */ + JBin2D& div(const double value) + { + this->__y /= value; + this->__z /= value; + this->__w2 /= value*value; + + return *this; + } + + + protected: + ordinate_type __z; + ordinate_type __w2; + }; + + + /** + * 3D Element. + */ + template<class JAbscissa_t, class JOrdinate_t> + struct JElement3D { + + typedef JAbscissa_t abscissa_type; + typedef JOrdinate_t ordinate_type; + + + /** + * Default constructor. + */ + JElement3D() : + __x(getZero<abscissa_type>()), + __y(getZero<abscissa_type>()), + __z(getZero<ordinate_type>()) + {} + + + /** + * Constructor. + * + * \param x abscissa value + * \param y abscissa value + * \param z ordinate value + */ + JElement3D(typename JLANG::JClass<abscissa_type>::argument_type x, + typename JLANG::JClass<abscissa_type>::argument_type y, + typename JLANG::JClass<ordinate_type>::argument_type z) : + __x(x), + __y(y), + __z(z) + {} + + + /** + * Get abscissa value. + * + * \return abscissa value + */ + abscissa_type getX() const + { + return __x; + } + + + /** + * Get abscissa value. + * + * \return abscissa value + */ + abscissa_type getY() const + { + return __y; + } + + + /** + * Get ordinate value. + * + * \return ordinate value + */ + const ordinate_type& getZ() const + { + return __y; + } + + + /** + * Get ordinate value. + * + * \return ordinate value + */ + ordinate_type& getZ() + { + return __y; + } + + + /** + * Read element from input. + * + * \param in reader + * \param element element + * \return reader + */ + friend inline JReader& operator>>(JReader& in, JElement3D& element) + { + in >> element.__x; + in >> element.__y; + in >> element.__z; + + return in; + } + + + /** + * Write element to output. + * + * \param out writer + * \param element element + * \return writer + */ + friend inline JWriter& operator<<(JWriter& out, const JElement3D& element) + { + out << element.__x; + out << element.__y; + out << element.__z; + + return out; + } + + + protected: + abscissa_type __x; + abscissa_type __y; + ordinate_type __z; + }; +} + +#endif diff --git a/jpp/JTools/JFunction1D_t.hh b/jpp/JTools/JFunction1D_t.hh new file mode 100644 index 0000000..07329eb --- /dev/null +++ b/jpp/JTools/JFunction1D_t.hh @@ -0,0 +1,380 @@ +#ifndef __JFUNCTION1D_T__ +#define __JFUNCTION1D_T__ + +#include "JTools/JElement.hh" +#include "JTools/JCollection.hh" +#include "JTools/JGridCollection.hh" +#include "JTools/JSpline.hh" +#include "JTools/JHermiteSpline.hh" +#include "JTools/JPolint.hh" +#include "JTools/JResult.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + + /** + * Type definition of a spline interpolation based on a JGridCollection. + */ + template<class JElement_t, class JDistance_t = JDistance<typename JElement_t::abscissa_type> > + struct JGridSplineFunction1D : + public JSplineFunction1D<JElement_t, JGridCollection, JDistance_t> + {}; + + + /** + * Type definition of a spline interpolation method based on a JCollection with double result type. + */ + struct JSplineFunction1D_t : + public JSplineFunction1D<JSplineElement2D<double, double>, JCollection, double> + {}; + + + /** + * Type definition of a spline interpolation method based on a JCollection with JResultDerivative result type. + */ + struct JSplineFunction1H_t : + public JSplineFunction1D<JSplineElement2S<double, double>, JCollection, JResultDerivative<double> > + {}; + + + /** + * Type definition of a spline interpolation method based on a JCollection with JResultPDF result type. + */ + struct JSplineFunction1S_t : + public JSplineFunction1D<JSplineElement2S<double, double>, JCollection, JResultPDF<double> > + {}; + + + /** + * Type definition of a spline interpolation based on a JGridCollection with result type double. + */ + struct JGridSplineFunction1D_t : + public JSplineFunction1D<JSplineElement2D<double, double>, JGridCollection, double> + {}; + + + /** + * Type definition of a spline interpolation based on a JGridCollection with JResultDerivative result type. + */ + struct JGridSplineFunction1H_t : + public JSplineFunction1D<JSplineElement2S<double, double>, JGridCollection, JResultDerivative<double> > + {}; + + + /** + * Type definition of a spline interpolation based on a JGridCollection with JResultPDF result type. + */ + struct JGridSplineFunction1S_t : + public JSplineFunction1D<JSplineElement2S<double, double>, JGridCollection, JResultPDF<double> > + {}; + + + /** + * Type definition of a spline interpolation based on a JGridCollection. + */ + template<class JElement_t, class JDistance_t = JDistance<typename JElement_t::abscissa_type> > + struct JGridHermiteSplineFunction1D : + public JHermiteSplineFunction1D<JElement_t, JGridCollection, JDistance_t> + {}; + + + /** + * Type definition of a spline interpolation method based on a JCollection with double result type. + */ + struct JHermiteSplineFunction1D_t : + public JHermiteSplineFunction1D<JSplineElement2D<double, double>, JCollection, double> + {}; + + + /** + * Type definition of a spline interpolation method based on a JCollection with JResultDerivative result type. + */ + struct JHermiteSplineFunction1H_t : + public JHermiteSplineFunction1D<JSplineElement2S<double, double>, JCollection, JResultDerivative<double> > + {}; + + + /** + * Type definition of a spline interpolation method based on a JCollection with JResultPDF result type. + */ + struct JHermiteSplineFunction1S_t : + public JHermiteSplineFunction1D<JSplineElement2S<double, double>, JCollection, JResultPDF<double> > + {}; + + + /** + * Type definition of a spline interpolation based on a JGridCollection with result type double. + */ + struct JGridHermiteSplineFunction1D_t : + public JHermiteSplineFunction1D<JSplineElement2D<double, double>, JGridCollection, double> + {}; + + + /** + * Type definition of a spline interpolation based on a JGridCollection with JResultDerivative result type. + */ + struct JGridHermiteSplineFunction1H_t : + public JHermiteSplineFunction1D<JSplineElement2S<double, double>, JGridCollection, JResultDerivative<double> > + {}; + + + /** + * Type definition of a zero degree polynomial interpolation. + */ + template<class JElement_t, class JDistance_t = JDistance<typename JElement_t::abscissa_type> > + struct JPolint0Function1D : + public JPolintFunction1D<0, JElement_t, JCollection, JDistance_t> + {}; + + + /** + * Type definition of a 1st degree polynomial interpolation. + */ + template<class JElement_t, class JDistance_t = JDistance<typename JElement_t::abscissa_type> > + struct JPolint1Function1D : + public JPolintFunction1D<1, JElement_t, JCollection, JDistance_t> + {}; + + + /** + * Type definition of a 2nd degree polynomial interpolation. + */ + template<class JElement_t, class JDistance_t = JDistance<typename JElement_t::abscissa_type> > + struct JPolint2Function1D : + public JPolintFunction1D<2, JElement_t, JCollection, JDistance_t> + {}; + + + /** + * Type definition of a 3rd degree polynomial interpolation. + */ + template<class JElement_t, class JDistance_t = JDistance<typename JElement_t::abscissa_type> > + struct JPolint3Function1D : + public JPolintFunction1D<3, JElement_t, JCollection, JDistance_t> + {}; + + + /** + * Polynomial interpolation method with result type double. + */ + template<int N> + struct JPolintFunction1D_t : + public JPolintFunction1D<N, JElement2D<double, double>, JCollection, double> + {}; + + + /** + * Type definition of a zero degree polynomial interpolation with result type double. + */ + struct JPolint0Function1D_t : + public JPolintFunction1D_t<0> + {}; + + + /** + * Type definition of a 1st degree polynomial interpolation with result type double. + */ + struct JPolint1Function1D_t : + public JPolintFunction1D_t<1> + {}; + + + /** + * Type definition of a 2nd degree polynomial interpolation with result type double. + */ + struct JPolint2Function1D_t : + public JPolintFunction1D_t<2> + {}; + + + /** + * Type definition of a 3rd degree polynomial interpolation with result type double. + */ + struct JPolint3Function1D_t : + public JPolintFunction1D_t<3> + {}; + + + /** + * Polynomial interpolation method with result type JResultDerivative. + */ + template<int N> + struct JPolintFunction1H_t : + public JPolintFunction1D<N, JElement2D<double, double>, JCollection, JResultDerivative<double> > + {}; + + + /** + * Type definition of a 1st degree polynomial interpolation with result type JResultDerivative. + */ + struct JPolint1Function1H_t : + public JPolintFunction1H_t<1> + {}; + + + /** + * Type definition of a 2nd degree polynomial interpolation with result type JResultDerivative. + */ + struct JPolint2Function1H_t : + public JPolintFunction1H_t<2> + {}; + + + /** + * Type definition of a 3rd degree polynomial interpolation with result type JResultDerivative. + */ + struct JPolint3Function1H_t : + public JPolintFunction1H_t<3> + {}; + + + /** + * Polynomial interpolation method with result type JResultPDF. + */ + template<int N> + struct JPolintFunction1S_t : + public JPolintFunction1D<N, JPolintElement2S<double, double>, JCollection, JResultPDF<double> > + {}; + + + /** + * Type definition of a 1st degree polynomial interpolation with result type JResultPDF. + */ + struct JPolint1Function1S_t : + public JPolintFunction1S_t<1> + {}; + + + /** + * Type definition of a 2nd degree polynomial interpolation with result type JResultPDF. + */ + struct JPolint2Function1S_t : + public JPolintFunction1S_t<2> + {}; + + + /** + * Type definition of a 3rd degree polynomial interpolation with result type JResultPDF. + */ + struct JPolint3Function1S_t : + public JPolintFunction1S_t<3> + {}; + + + /** + * Polynomial interpolation method based on a JGridCollection with result type double. + */ + template<int N> + struct JGridPolintFunction1D_t : + public JPolintFunction1D<N, JElement2D<double, double>, JGridCollection, double> + {}; + + + /** + * Type definition of a zero degree polynomial interpolation based on a JGridCollection with result type double. + */ + struct JGridPolint0Function1D_t : + public JGridPolintFunction1D_t<0> + {}; + + + /** + * Type definition of a 1st degree polynomial interpolation based on a JGridCollection with result type double. + */ + struct JGridPolint1Function1D_t : + public JGridPolintFunction1D_t<1> + {}; + + + /** + * Type definition of a 2nd degree polynomial interpolation based on a JGridCollection with result type double. + */ + struct JGridPolint2Function1D_t : + public JGridPolintFunction1D_t<2> + {}; + + + /** + * Type definition of a 3rd degree polynomial interpolation based on a JGridCollection with result type double. + */ + struct JGridPolint3Function1D_t : + public JGridPolintFunction1D_t<3> + {}; + + + /** + * Polynomial interpolation method based on a JGridCollection with result type JResultDerivative. + */ + template<int N> + struct JGridPolintFunction1H_t : + public JPolintFunction1D<N, JElement2D<double, double>, JGridCollection, JResultDerivative<double> > + {}; + + + /** + * Type definition of a 1st degree polynomial interpolation with result type JResultDerivative. + */ + struct JGridPolint1Function1H_t : + public JGridPolintFunction1H_t<2> + {}; + + + + /** + * Type definition of a 2nd degree polynomial interpolation with result type JResultDerivative. + */ + struct JGridPolint2Function1H_t : + public JGridPolintFunction1H_t<2> + {}; + + + /** + * Type definition of a 3rd degree polynomial interpolation with result type JResultDerivative. + */ + struct JGridPolint3Function1H_t : + public JGridPolintFunction1H_t<3> + {}; + + + /** + * Polynomial interpolation method with result type JResultPDF. + */ + template<int N> + struct JGridPolintFunction1S_t : + public JPolintFunction1D<N, JPolintElement2S<double, double>, JGridCollection, JResultPDF<double> > + {}; + + + /** + * Type definition of a 1st degree polynomial interpolation with result type JResulPDF. + */ + struct JGridPolint1Function1S_t : + public JGridPolintFunction1S_t<1> + {}; + + + /** + * Type definition of a 2nd degree polynomial interpolation with result type JResulPDF. + */ + struct JGridPolint2Function1S_t : + public JGridPolintFunction1S_t<2> + {}; + + + /** + * Type definition of a 3rd degree polynomial interpolation with result type JResulPDF. + */ + struct JGridPolint3Function1S_t : + public JGridPolintFunction1S_t<3> + {}; +} + +#endif diff --git a/jpp/JTools/JFunctional.hh b/jpp/JTools/JFunctional.hh new file mode 100644 index 0000000..5b0c005 --- /dev/null +++ b/jpp/JTools/JFunctional.hh @@ -0,0 +1,394 @@ +#ifndef __JTOOLS__JFUNCTIONAL__ +#define __JTOOLS__JFUNCTIONAL__ + +#include "JLang/JSharedPointer.hh" +#include "JLang/JNullType.hh" +#include "JLang/JException.hh" +#include "JLang/JVoid.hh" +#include "JLang/JClass.hh" +#include "JMath/JZero.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JLANG::JClass; + using JLANG::JException; + using JLANG::JNullType; + using JLANG::JVoid; + using JLANG::JSharedPointer; + + + /** + * Template definition of function object interface. + */ + template<class JArgument_t = JNullType, class JResult_t = JNullType> + class JFunctional; + + + /** + * Template specialisation of compilable function object. + */ + template<> + class JFunctional<JNullType, JNullType> + { + protected: + /** + * Function compilation. + */ + virtual void do_compile() = 0; + + + public: + /** + * Virtual destructor. + */ + virtual ~JFunctional() + {} + + + /** + * Function compilation. + */ + void compile() + { + do_compile(); + } + }; + + + /** + * Template definition of recursive function value evaluation. + */ + template<class JArgument_t, class JResult_t> + class JFunctional : + public virtual JFunctional<JNullType, JNullType> + { + protected: + /** + * Default constructor. + */ + JFunctional() : + JFunctional<JNullType, JNullType>(), + supervisor(JSupervisor::getInstance()) + {} + + public: + + class JSupervisor; + + typedef JArgument_t argument_type; + typedef JResult_t result_type; + typedef JFunctional<argument_type, result_type> functional_type; + typedef JSupervisor supervisor_type; + + + /** + * Recursive function value evaluation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const = 0; + + + /** + * Recursive function value evaluation. + * + * \param function function + * \param pX pointer to abscissa values + */ + static result_type getValue(const JFunctional& function, + const argument_type* pX) + { + return function.evaluate(pX); + } + + + /** + * Termination of recursive function value evaluation. + * + * \param value result + * \param pX pointer to abscissa values + */ + static typename JClass<result_type>::argument_type + getValue(typename JClass<result_type>::argument_type value, + const argument_type* pX) + { + return value; + } + + + /** + * Exception handler for functional object. + */ + struct JExceptionHandler + { + /** + * Default constructor. + */ + JExceptionHandler() + {} + + + /** + * Virtual destructor. + */ + virtual ~JExceptionHandler() + {} + + + /** + * Implementation of exception handler. + * This implementation throws the exception. + * + * \param error error + */ + virtual result_type action(const JException& error) const + { + throw error; + } + }; + + + /** + * Exception handler for functional object using default result. + */ + struct JDefaultResult : + public JExceptionHandler + { + /** + * Constructor. + * + * \param value default result in case of exception + */ + JDefaultResult(const result_type value) : + JExceptionHandler(), + defaultResult(value) + {} + + + /** + * Constructor. + * + * \param value default result in case of exception + */ + JDefaultResult(const JMATH::JZero& value) : + JExceptionHandler(), + defaultResult() + {} + + + /** + * Implementation of exception handler. + * This implementation returns the default value. + * + * \param error error + * \return default value + */ + virtual result_type action(const JException& error) const override + { + return defaultResult; + } + + private: + result_type defaultResult; + }; + + + /** + * Place holder for exception handler. + */ + class JSupervisor : + public JSharedPointer<JExceptionHandler> + { + + typedef JSharedPointer<JExceptionHandler> supervisor_type; + + public: + /** + * Default constructor. + */ + JSupervisor() : + supervisor_type(new JExceptionHandler()) + {} + + + /** + * Constructor + * + * \param exception_handler pointer to exception handler + */ + JSupervisor(JExceptionHandler* exception_handler) : + supervisor_type(exception_handler) + {} + + + /** + * Get reference to unique instance of this class object. + * + * \return supervisor + */ + static const JSupervisor& getInstance() + { + static const JSupervisor supervisor; + + return supervisor; + } + + + /** + * Set exception handler of given functional object. + * + * \param function function + * \return this supervisor + */ + const JSupervisor& operator()(functional_type& function) const + { + function.setExceptionHandler(*this); + + return *this; + } + }; + + + /** + * Get supervisor. + * + * \return supervisor + */ + JSupervisor getSupervisor() const + { + return supervisor; + } + + + /** + * Get exception handler. + * + * \return exception handler + */ + const JExceptionHandler& getExceptionHandler() const + { + return *supervisor; + } + + + /** + * Set the supervisor for handling of exceptions. + * + * \param supervisor supervisor + */ + void setExceptionHandler(const JSupervisor& supervisor) + { + this->supervisor = supervisor; + } + + + protected: + JSupervisor supervisor; + }; + + + /** + * Template definition of function object interface in multidimensions. + */ + template<class JArgument_t, class JResult_t> + struct JFunction : + public virtual JFunctional<JArgument_t, JResult_t> + { + typedef JFunctional<JArgument_t, JResult_t> functional_type; + typedef typename functional_type::argument_type argument_type; + typedef typename functional_type::result_type result_type; + }; + + + /** + * Template definition of function object interface in one dimension. + * This class provides for the standard function operator <tt>()</tt>. + */ + template<class JArgument_t, class JResult_t> + struct JFunction1D : + public JFunction<JArgument_t, JResult_t> + { + enum { NUMBER_OF_DIMENSIONS = 1 }; + + typedef JFunctional<JArgument_t, JResult_t> functional_type; + typedef typename functional_type::argument_type argument_type; + typedef typename functional_type::result_type result_type; + + + /** + * Function value evaluation. + * + * \param x argument value + * \return function value + */ + result_type operator()(const argument_type x) const + { + return this->evaluate(&x); + } + }; + + + /** + * Functional object compiler. + */ + struct JCompiler { + /** + * Default constructor. + */ + JCompiler() + {} + + + /** + * Compile function. + * + * \param function function + * \return this compiler + */ + const JCompiler& operator()(JFunctional<>& function) const + { + function.compile(); + + return *this; + } + }; + + + /** + * Function object for functional object compilation. + */ + static const JCompiler compiler; + + + /** + * Auxiliary class to evaluate result type. + * The result type is the actual data type. + */ + template<class JClass_t, class JResultType_t = void> + struct JResultType { + + typedef JClass_t result_type; + }; + + + /** + * Auxiliary class to evaluate result type. + * The result type is the result type of the function object. + */ + template<class JClass_t> + struct JResultType<JClass_t, typename JVoid<typename JClass_t::result_type>::type> { + + typedef typename JClass_t::result_type result_type; + }; +} + +#endif diff --git a/jpp/JTools/JFunctionalMap.hh b/jpp/JTools/JFunctionalMap.hh new file mode 100644 index 0000000..52ae939 --- /dev/null +++ b/jpp/JTools/JFunctionalMap.hh @@ -0,0 +1,220 @@ +#ifndef __JTOOLS__JFUNCTIONALMAP__ +#define __JTOOLS__JFUNCTIONALMAP__ + +#include "JTools/JFunctionalMap_t.hh" +#include "JTools/JSpline.hh" +#include "JTools/JPolint.hh" +#include "JTools/JCollection.hh" +#include "JTools/JGridCollection.hh" +#include "JTools/JElement.hh" +#include "JTools/JDistance.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + + /** + * Auxiliary class to define corresponding one-dimensional function interpolator <tt>function_type</tt>. + */ + template<template<class JKey_t, class JValue_t, class JDistance_t> class JFunctionalMap_t> + struct JFunctionalMap; + + + /** + * Specialisation of JFunctionalMap for JSplineFunctionalMap. + */ + template<> + struct JFunctionalMap<JSplineFunctionalMap> + { + /** + * Corresponding one-dimensional function interpolator. + */ + template<class JAbscissa_t, + class JOrdinate_t, + class JResult_t, + class JDistance_t = JDistance<JAbscissa_t> > + struct function_type : + public JSplineFunction1D<JSplineElement2D<JAbscissa_t, JOrdinate_t>, JCollection, JResult_t, JDistance_t> + {}; + }; + + + /** + * Specialisation of JFunctionalMap for JSplineFunctionalGridMap. + */ + template<> + struct JFunctionalMap<JSplineFunctionalGridMap> + { + /** + * Corresponding one-dimensional function interpolator. + */ + template<class JAbscissa_t, + class JOrdinate_t, + class JResult_t, + class JDistance_t = JDistance<JAbscissa_t> > + struct function_type : + public JSplineFunction1D<JSplineElement2D<JAbscissa_t, JOrdinate_t>, JGridCollection, JResult_t, JDistance_t> + {}; + }; + + + /** + * Specialisation of JFunctionalMap for JPolint0FunctionalMap. + */ + template<> + struct JFunctionalMap<JPolint0FunctionalMap> + { + /** + * Corresponding one-dimensional function interpolator. + */ + template<class JAbscissa_t, + class JOrdinate_t, + class JResult_t, + class JDistance_t = JDistance<JAbscissa_t> > + struct function_type : + public JPolintFunction1D<0, JElement2D<JAbscissa_t, JOrdinate_t>, JCollection, JResult_t, JDistance_t> + {}; + }; + + + /** + * Specialisation of JFunctionalMap for JPolint1FunctionalMap. + */ + template<> + struct JFunctionalMap<JPolint1FunctionalMap> + { + /** + * Corresponding one-dimensional function interpolator. + */ + template<class JAbscissa_t, + class JOrdinate_t, + class JResult_t, + class JDistance_t = JDistance<JAbscissa_t> > + struct function_type : + public JPolintFunction1D<1, JElement2D<JAbscissa_t, JOrdinate_t>, JCollection, JResult_t, JDistance_t> + {}; + }; + + + /** + * Specialisation of JFunctionalMap for JPolint2FunctionalMap. + */ + template<> + struct JFunctionalMap<JPolint2FunctionalMap> + { + /** + * Corresponding one-dimensional function interpolator. + */ + template<class JAbscissa_t, + class JOrdinate_t, + class JResult_t, + class JDistance_t = JDistance<JAbscissa_t> > + struct function_type : + public JPolintFunction1D<2, JElement2D<JAbscissa_t, JOrdinate_t>, JCollection, JResult_t, JDistance_t> + {}; + }; + + + /** + * Specialisation of JFunctionalMap for JPolint3FunctionalMap. + */ + template<> + struct JFunctionalMap<JPolint3FunctionalMap> + { + /** + * Corresponding one-dimensional function interpolator. + */ + template<class JAbscissa_t, + class JOrdinate_t, + class JResult_t, + class JDistance_t = JDistance<JAbscissa_t> > + struct function_type : + public JPolintFunction1D<3, JElement2D<JAbscissa_t, JOrdinate_t>, JCollection, JResult_t, JDistance_t> + {}; + }; + + + /** + * Specialisation of JFunctionalMap for JPolint0FunctionalGridMap. + */ + template<> + struct JFunctionalMap<JPolint0FunctionalGridMap> + { + /** + * Corresponding one-dimensional function interpolator. + */ + template<class JAbscissa_t, + class JOrdinate_t, + class JResult_t, + class JDistance_t = JDistance<JAbscissa_t> > + struct function_type : + public JPolintFunction1D<0, JElement2D<JAbscissa_t, JOrdinate_t>, JGridCollection, JResult_t, JDistance_t> + {}; + }; + + + /** + * Specialisation of JFunctionalMap for JPolint1FunctionalGridMap. + */ + template<> + struct JFunctionalMap<JPolint1FunctionalGridMap> + { + /** + * Corresponding one-dimensional function interpolator. + */ + template<class JAbscissa_t, + class JOrdinate_t, + class JResult_t, + class JDistance_t = JDistance<JAbscissa_t> > + struct function_type : + public JPolintFunction1D<1, JElement2D<JAbscissa_t, JOrdinate_t>, JGridCollection, JResult_t, JDistance_t> + {}; + }; + + + /** + * Specialisation of JFunctionalMap for JPolint2FunctionalGridMap. + */ + template<> + struct JFunctionalMap<JPolint2FunctionalGridMap> + { + /** + * Corresponding one-dimensional function interpolator. + */ + template<class JAbscissa_t, + class JOrdinate_t, + class JResult_t, + class JDistance_t = JDistance<JAbscissa_t> > + struct function_type : + public JPolintFunction1D<2, JElement2D<JAbscissa_t, JOrdinate_t>, JGridCollection, JResult_t, JDistance_t> + {}; + }; + + + /** + * Specialisation of JFunctionalMap for JPolint3FunctionalGridMap. + */ + template<> + struct JFunctionalMap<JPolint3FunctionalGridMap> + { + /** + * Corresponding one-dimensional function interpolator. + */ + template<class JAbscissa_t, + class JOrdinate_t, + class JResult_t, + class JDistance_t = JDistance<JAbscissa_t> > + struct function_type : + public JPolintFunction1D<3, JElement2D<JAbscissa_t, JOrdinate_t>, JGridCollection, JResult_t, JDistance_t> + {}; + }; +} + +#endif diff --git a/jpp/JTools/JFunctionalMap_t.hh b/jpp/JTools/JFunctionalMap_t.hh new file mode 100644 index 0000000..bf0ae84 --- /dev/null +++ b/jpp/JTools/JFunctionalMap_t.hh @@ -0,0 +1,204 @@ +#ifndef __JFUNCTIONALMAP_T__ +#define __JFUNCTIONALMAP_T__ + +#include "JTools/JDistance.hh" +#include "JTools/JMap.hh" +#include "JTools/JGridMap.hh" +#include "JTools/JPolint.hh" +#include "JTools/JSpline.hh" +#include "JTools/JResult.hh" + + +/** + * \file + * + * Various implementations of functional maps. + * \author mdejong + */ +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + + /** + * Type definition of a spline interpolation based on a JMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JSplineFunctionalMap : + public JSplineMap<JKey_t, JValue_t, JMap, typename JResultType<JValue_t>::result_type, JDistance_t> + {}; + + + /** + * Type definition of a spline interpolation based on a JGridMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JSplineFunctionalGridMap : + public JSplineMap<JKey_t, JValue_t, JGridMap, typename JResultType<JValue_t>::result_type, JDistance_t> + {}; + + + /** + * Type definition of a zero degree polynomial interpolation based on a JMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JPolint0FunctionalMap : + public JPolintMap<0, JKey_t, JValue_t, JMap, typename JResultType<JValue_t>::result_type, JDistance_t> + {}; + + + /** + * Type definition of a 1st degree polynomial interpolation based on a JMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JPolint1FunctionalMap : + public JPolintMap<1, JKey_t, JValue_t, JMap, typename JResultType<JValue_t>::result_type, JDistance_t> + {}; + + + /** + * Type definition of a 2nd degree polynomial interpolation based on a JMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JPolint2FunctionalMap : + public JPolintMap<2, JKey_t, JValue_t, JMap, typename JResultType<JValue_t>::result_type, JDistance_t> + {}; + + + /** + * Type definition of a 3rd degree polynomial interpolation based on a JMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JPolint3FunctionalMap : + public JPolintMap<3, JKey_t, JValue_t, JMap, typename JResultType<JValue_t>::result_type, JDistance_t> + {}; + + + /** + * Type definition of a zero degree polynomial interpolation based on a JGridMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JPolint0FunctionalGridMap : + public JPolintMap<0, JKey_t, JValue_t, JGridMap, typename JResultType<JValue_t>::result_type, JDistance_t> + {}; + + + /** + * Type definition of a 1st degree polynomial interpolation based on a JGridMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JPolint1FunctionalGridMap : + public JPolintMap<1, JKey_t, JValue_t, JGridMap, typename JResultType<JValue_t>::result_type, JDistance_t> + {}; + + + /** + * Type definition of a 2nd degree polynomial interpolation based on a JGridMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JPolint2FunctionalGridMap : + public JPolintMap<2, JKey_t, JValue_t, JGridMap, typename JResultType<JValue_t>::result_type, JDistance_t> + {}; + + + /** + * Type definition of a 3rd degree polynomial interpolation based on a JGridMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JPolint3FunctionalGridMap : + public JPolintMap<3, JKey_t, JValue_t, JGridMap, typename JResultType<JValue_t>::result_type, JDistance_t> + {}; + + + /** + * Type definition of a spline interpolation based on a JMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JSplineFunctionalMapH : + public JSplineMap<JKey_t, JValue_t, JMap, JResultDerivative<typename JResultType<JValue_t>::result_type>, JDistance_t> + {}; + + + /** + * Type definition of a spline interpolation based on a JGridMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JSplineFunctionalGridMapH : + public JSplineMap<JKey_t, JValue_t, JGridMap, JResultDerivative<typename JResultType<JValue_t>::result_type>, JDistance_t> + {}; + + + /** + * Type definition of a zero degree polynomial interpolation based on a JMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JPolint0FunctionalMapH : + public JPolintMap<0, JKey_t, JValue_t, JMap, JResultDerivative<typename JResultType<JValue_t>::result_type>, JDistance_t> + {}; + + + /** + * Type definition of a 1st degree polynomial interpolation based on a JMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JPolint1FunctionalMapH : + public JPolintMap<1, JKey_t, JValue_t, JMap, JResultDerivative<typename JResultType<JValue_t>::result_type>, JDistance_t> + {}; + + + /** + * Type definition of a 2nd degree polynomial interpolation based on a JMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JPolint2FunctionalMapH : + public JPolintMap<2, JKey_t, JValue_t, JMap, JResultDerivative<typename JResultType<JValue_t>::result_type>, JDistance_t> + {}; + + + /** + * Type definition of a 3rd degree polynomial interpolation based on a JMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JPolint3FunctionalMapH : + public JPolintMap<3, JKey_t, JValue_t, JMap, JResultDerivative<typename JResultType<JValue_t>::result_type>, JDistance_t> + {}; + + + /** + * Type definition of a zero degree polynomial interpolation based on a JGridMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JPolint0FunctionalGridMapH : + public JPolintMap<0, JKey_t, JValue_t, JGridMap, JResultDerivative<typename JResultType<JValue_t>::result_type>, JDistance_t> + {}; + + + /** + * Type definition of a 1st degree polynomial interpolation based on a JGridMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JPolint1FunctionalGridMapH : + public JPolintMap<1, JKey_t, JValue_t, JGridMap, JResultDerivative<typename JResultType<JValue_t>::result_type>, JDistance_t> + {}; + + + /** + * Type definition of a 2nd degree polynomial interpolation based on a JGridMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JPolint2FunctionalGridMapH : + public JPolintMap<2, JKey_t, JValue_t, JGridMap, JResultDerivative<typename JResultType<JValue_t>::result_type>, JDistance_t> + {}; + + + /** + * Type definition of a 3rd degree polynomial interpolation based on a JGridMap implementation. + */ + template<class JKey_t, class JValue_t, class JDistance_t = JDistance<JKey_t> > + struct JPolint3FunctionalGridMapH : + public JPolintMap<3, JKey_t, JValue_t, JGridMap, JResultDerivative<typename JResultType<JValue_t>::result_type>, JDistance_t> + {}; +} + +#endif diff --git a/jpp/JTools/JGarbageCollection.hh b/jpp/JTools/JGarbageCollection.hh new file mode 100644 index 0000000..3fe8ae1 --- /dev/null +++ b/jpp/JTools/JGarbageCollection.hh @@ -0,0 +1,68 @@ +#ifndef __JTOOLS__JGARBAGECOLLACTION__ +#define __JTOOLS__JGARBAGECOLLACTION__ + +#include "JTools/JMappableCollection.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + /** + * Garbage collection. + * + * This class implements the JMappableCollection interface but does nothing. + */ + template<class JKey_t, class JValue_t> + class JGarbageCollection : + public JMappableCollection<JKey_t, JValue_t> + { + public: + + typedef JMappableCollection<JKey_t, JValue_t> mappablecollection_type; + + typedef typename mappablecollection_type::key_type key_type; + typedef typename mappablecollection_type::mapped_type mapped_type; + + + /** + * Clear. + */ + virtual void clear() override + {} + + + /** + * Get mapped value. + * + * \param key key + * \return value + */ + virtual const mapped_type& get(typename JLANG::JClass<key_type>::argument_type key) const override + { + return value; + } + + + /** + * Get mapped value. + * + * \param key key + * \return value + */ + virtual mapped_type& get(typename JLANG::JClass<key_type>::argument_type key) override + { + return value; + } + + private: + mapped_type value; + }; +} + +#endif diff --git a/jpp/JTools/JGrid.hh b/jpp/JTools/JGrid.hh new file mode 100644 index 0000000..aeb6b45 --- /dev/null +++ b/jpp/JTools/JGrid.hh @@ -0,0 +1,185 @@ +#ifndef __JTOOLS__JGRID__ +#define __JTOOLS__JGRID__ + +#include <istream> +#include <ostream> + +#include "JTools/JAbstractCollection.hh" +#include "JLang/JClass.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JLANG::JClass; + + template<class JElement_t, class JDistance_t> + class JCollection; + + + /** + * Simple data structure for an abstract collection of equidistant abscissa values. + * + * This class implements the JAbstractCollection interface. + */ + template<class JAbscissa_t> + struct JGrid : + public JAbstractCollection<JAbscissa_t> + { + typedef typename JAbstractCollection<JAbscissa_t>::abscissa_type abscissa_type; + + + /** + * Default constructor. + */ + JGrid() : + size(0), + xmin(), + xmax() + {} + + + /** + * Constructor. + * + * \param nx number of elements + * \param Xmin lower limit + * \param Xmax upper limit + */ + JGrid(const int nx, + const abscissa_type Xmin, + const abscissa_type Xmax) : + size(nx), + xmin(Xmin), + xmax(Xmax) + {} + + + /** + * Get number of elements. + * + * \return number of elements + */ + virtual int getSize() const override + { + return size; + } + + + /** + * Get abscissa value. + * + * \param index index + * \return abscissa value + */ + virtual abscissa_type getX(int index) const override + { + return xmin + index * ((xmax - xmin) / (size - 1)); + } + + + /** + * Get minimal abscissa value. + * + * \return abscissa value + */ + virtual abscissa_type getXmin() const override + { + return xmin; + } + + + /** + * Get maximal abscissa value. + * + * \return abscissa value + */ + virtual abscissa_type getXmax() const override + { + return xmax; + } + + + /** + * Get index of given abscissa value. + * + * \param x abscissa value + * \return index + */ + int getIndex(typename JClass<abscissa_type>::argument_type x) const + { + return (int) ((size - 1) * (x - xmin) / (xmax - xmin)); + } + + + /** + * Configure collection. + * + * \param collection collection + * \return this grid + */ + template<class JElement_t, class JDistance_t> + const JGrid& operator()(JCollection<JElement_t, JDistance_t>& collection) const + { + collection.configure(*this); + + return *this; + } + + + /** + * Read grid from input. + * + * \param in input stream + * \param grid grid + * \return input stream + */ + friend inline std::istream& operator>>(std::istream& in, JGrid<JAbscissa_t>& grid) + { + return in >> grid.size >> grid.xmin >> grid.xmax; + } + + + /** + * Write grid to output. + * + * \param out output stream + * \param grid grid + * \return output stream + */ + friend inline std::ostream& operator<<(std::ostream& out, const JGrid<JAbscissa_t>& grid) + { + return out << grid.size << ' ' << grid.xmin << ' ' << grid.xmax; + } + + protected: + int size; + abscissa_type xmin; + abscissa_type xmax; + }; + + + /** + * Helper method for JGrid. + * + * \param nx number of elements + * \param Xmin lower limit + * \param Xmax upper limit + * \return grid + */ + template<class JAbscissa_t> + inline JGrid<JAbscissa_t> make_grid(const int nx, + const JAbscissa_t Xmin, + const JAbscissa_t Xmax) + { + return JGrid<JAbscissa_t>(nx, Xmin, Xmax); + } +} + +#endif diff --git a/jpp/JTools/JGridCollection.hh b/jpp/JTools/JGridCollection.hh new file mode 100644 index 0000000..1f702b2 --- /dev/null +++ b/jpp/JTools/JGridCollection.hh @@ -0,0 +1,111 @@ +#ifndef __JTOOLS__JGRIDCOLLECTION__ +#define __JTOOLS__JGRIDCOLLECTION__ + +#include "JLang/JClass.hh" +#include "JTools/JCollection.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JLANG::JClass; + + + /** + * General purpose class for collection of equidistant elements. + * + * For a collection with equidistant elements, the index of the nearest element can directly be computed + * based on the minimal abscissa value, the maximal abscissa value and the number of elements in the collection. + * The lower_bound methods are re-implemented in this class which otherwise simply derives from JCollection. + * + * For convenience, the implementation of the standard map operator <tt>[]</tt> of the JCollection class is maintained. + */ + template<class JElement_t, class JDistance_t = JDistance<typename JElement_t::abscissa_type> > + class JGridCollection : + public JCollection<JElement_t, JDistance_t> + { + public: + + typedef JCollection<JElement_t, JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef typename collection_type::pair_type pair_type; + + + /** + * Default constructor. + */ + JGridCollection() + {} + + + /** + * Get index of given abscissa value. + * + * For values within the range of this collection, the index starts at zero and ends at number of elements minus one. + * Note that the index could be less than zero or larger than (or equal to) the number of elements, + * if the given abscissa value is outside the range of this collection. + * + * \param x abscissa value + * \return index + */ + int getIndex(typename JClass<abscissa_type>::argument_type x) const + { + return (int) ((this->size() - 1) * (x - this->begin()->getX()) / (this->rbegin()->getX() - this->begin()->getX())); + } + + + /** + * Get first position of element <tt>i</tt>, where <tt>x >= i->getX()</tt>. + * + * \param x abscissa value + * \return position of corresponding element + */ + const_iterator lower_bound(typename JClass<abscissa_type>::argument_type x) const + { + const int index = getIndex(x) + 1; + + if (index <= 0) + return this->begin(); + else if (index >= (int) this->size()) + return this->end(); + else + return this->begin() + index; + } + + + /** + * Get first position of element <tt>i</tt>, where <tt>x >= i->getX()</tt>. + * + * \param x abscissa value + * \return position of corresponding element + */ + iterator lower_bound(typename JClass<abscissa_type>::argument_type x) + { + const int index = getIndex(x) + 1; + + if (index <= 0) + return this->begin(); + else if (index >= (int) this->size()) + return this->end(); + else + return this->begin() + index; + } + }; +} + +#endif diff --git a/jpp/JTools/JGridMap.hh b/jpp/JTools/JGridMap.hh new file mode 100644 index 0000000..61b04fe --- /dev/null +++ b/jpp/JTools/JGridMap.hh @@ -0,0 +1,70 @@ +#ifndef __JTOOLS__JGRIDMAP__ +#define __JTOOLS__JGRIDMAP__ + +#include "JTools/JGridCollection.hh" +#include "JTools/JMapCollection.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + + /** + * Map of equidistant pair-wise elements. + * + * The key_type and mapped_type refer to the pair-wise element of this map, respectively. + */ + template<class JKey_t, + class JValue_t, + class JDistance_t = JDistance<JKey_t> > + class JGridMap : + public JGridCollection<JElement2D<JKey_t, JValue_t>, JDistance_t> + { + public: + + typedef JKey_t key_type; + typedef JValue_t mapped_type; + + typedef JGridCollection<JElement2D<JKey_t, JValue_t>, JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + + /** + * Default constructor. + */ + JGridMap() + {} + }; + + + /** + * Specialisation of JMapCollection for JGridMap. + */ + template<> + struct JMapCollection<JGridMap> { + /** + * Collection of elements. + */ + template<class JElement_t, + class JDistance_t = JDistance<typename JElement_t::abscissa_type> > + struct collection_type : + public JGridCollection<JElement_t, JDistance_t> + {}; + }; +} + +#endif diff --git a/jpp/JTools/JHermiteSpline.hh b/jpp/JTools/JHermiteSpline.hh new file mode 100644 index 0000000..e908e0a --- /dev/null +++ b/jpp/JTools/JHermiteSpline.hh @@ -0,0 +1,706 @@ +#ifndef __JTOOLS__JHERMITESPLINE__ +#define __JTOOLS__JHERMITESPLINE__ + +#include <utility> +#include <cmath> + +#include "JMath/JZero.hh" +#include "JLang/JException.hh" +#include "JLang/JClass.hh" +#include "JTools/JFunctional.hh" +#include "JTools/JDistance.hh" +#include "JTools/JResult.hh" +#include "JTools/JMapCollection.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JLANG::JNoValue; + using JLANG::JDivisionByZero; + using JLANG::JFunctionalException; + using JLANG::JValueOutOfRange; + + + /** + * Template base class spline interpolations. + * + * This class implements the JFunctional interface. + * + * Note that the data structure of the elements in the collection should have the additional methods: + * <pre> + * ordinate_type getU() const; + * void setU(ordinate_type u); + * </pre> + * to get and set the derivatives, respectively. + * + * Note that -by default- the compilation is for a monotonous interpolation. + */ + template<class JElement_t, template<class, class> class JCollection_t, class JDistance_t> + class JHermiteSplineCollection : + public JCollection_t<JElement_t, JDistance_t>, + public virtual JFunctional<> + { + public: + + typedef JCollection_t<JElement_t, JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + using JFunctional<>::compile; + + + /** + * Determination of derivatives. + * + * \param monotone monotone + */ + void compile(const bool monotone) + { + using namespace std; + + if (this->size() >= 2u) { + + { + iterator j = this->begin(), i = j++; + + i->setU((j->getY() - i->getY()) / this->getDistance(i->getX(), j->getX())); + } + + { + reverse_iterator j = this->rbegin(), i = j++; + + i->setU((j->getY() - i->getY()) / this->getDistance(i->getX(), j->getX())); + } + + for (iterator k = this->begin(), i = k++, j = k++; k != this->end(); ++i, ++j, ++k) { + j->setU(0.5 * ((j->getY() - i->getY()) / this->getDistance(i->getX(), j->getX()) + + (k->getY() - j->getY()) / this->getDistance(j->getX(), k->getX()))); + } + + if (monotone) { + + for (iterator j = this->begin(), i = j++; j != this->end(); ++i, ++j) { + if (i->getY() == j->getY()) { + j->setU(JMATH::zero); + } + } + + for (iterator j = this->begin(), i = j++; j != this->end(); ++i, ++j) { + + const ordinate_type u = (j->getY() - i->getY()) / this->getDistance(i->getX(), j->getX()); + const ordinate_type w = (i->getU()*i->getU() + j->getU()*j->getU()); + + if (w > 9.0*u*u) { + + const ordinate_type v = 3.0*u/sqrt(w); + + i->setU(v*i->getU()); + j->setU(v*j->getU()); + } + } + } + } + } + + + protected: + + static abscissa_type h00 (abscissa_type t) { return (1.0 + 2*t) * (1.0 - t) * (1.0 - t); } + static abscissa_type h10 (abscissa_type t) { return t * (1.0 - t) * (1.0 - t); } + static abscissa_type h01 (abscissa_type t) { return t * t * (3.0 - 2*t); } + static abscissa_type h11 (abscissa_type t) { return t * t * (t - 1.0); } + + static abscissa_type h00p(abscissa_type t) { return 6 * t * (t - 1.0); } + static abscissa_type h10p(abscissa_type t) { return t * (3*t - 4.0) + 1.0; } + static abscissa_type h01p(abscissa_type t) { return 6 * t * (1.0 -t); } + static abscissa_type h11p(abscissa_type t) { return t * (3*t - 2.0); } + + static abscissa_type H00 (abscissa_type t) { return t * (t * t * (0.5*t - 1.0) + 1.0); } + static abscissa_type H10 (abscissa_type t) { return t * t * (t * (0.25*t - 2.0/3.0) + 0.5); } + static abscissa_type H01 (abscissa_type t) { return t * t * t * (1.0 - 0.5*t); } + static abscissa_type H11 (abscissa_type t) { return t * t * t * (0.25*t - 1.0/3.0); } + + + /** + * Default constructor. + */ + JHermiteSplineCollection() + {} + + + /** + * Determination of derivatives. + */ + virtual void do_compile() override + { + compile(true); + } + }; + + + /** + * Template definition for functional collection with spline interpolation. + */ + template<class JElement_t, + template<class, class> class JCollection_t, + class JResult_t, + class JDistance_t> + class JHermiteSplineFunction; + + + /** + * Template specialisation for functional collection with spline interpolation. + */ + template<class JElement_t, template<class, class> class JCollection_t, class JDistance_t> + class JHermiteSplineFunction<JElement_t, + JCollection_t, + typename JResultType<typename JElement_t::ordinate_type>::result_type, + JDistance_t> : + public JHermiteSplineCollection<JElement_t, JCollection_t, JDistance_t>, + public JFunction<typename JElement_t::abscissa_type, + typename JResultType<typename JElement_t::ordinate_type>::result_type> + { + public: + + typedef JHermiteSplineCollection<JElement_t, JCollection_t, JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef typename JResultType<ordinate_type>::result_type data_type; + typedef JFunction<abscissa_type, data_type> function_type; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::JExceptionHandler exceptionhandler_type; + + + /** + * Default constructor. + */ + JHermiteSplineFunction() + {} + + + /** + * Recursive interpolation method implementation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const override + { + if (this->size() <= 1u) { + return this->getExceptionHandler().action(JFunctionalException("JHermiteSplineFunction<>::evaluate() not enough data.")); + } + + const argument_type x = *pX; + + const_iterator p = this->lower_bound(x); + + if ((p == this->begin() && this->getDistance(x, (p++)->getX()) > distance_type::precision) || + (p == this->end() && this->getDistance((--p)->getX(), x) > distance_type::precision)) { + + return this->getExceptionHandler().action(JValueOutOfRange("JHermiteSplineFunction::evaluate() x out of range.")); + } + + const_iterator q = p--; + + const double dx = this->getDistance(p->getX(), q->getX()); + const double t = this->getDistance(p->getX(), x) / dx; + + return h00(t)*p->getY() + h10(t)*p->getU()*dx + h01(t)*q->getY() + h11(t)*q->getU()*dx; + } + + protected: + + using collection_type::h00; + using collection_type::h10; + using collection_type::h01; + using collection_type::h11; + }; + + + /** + * Template specialisation for spline interpolation method with returning JResultDerivative data structure. + */ + template<class JElement_t, template<class, class> class JCollection_t, class JDistance_t> + class JHermiteSplineFunction<JElement_t, + JCollection_t, + JResultDerivative<typename JResultType<typename JElement_t::ordinate_type>::result_type>, + JDistance_t> : + public JHermiteSplineCollection<JElement_t, JCollection_t, JDistance_t>, + public JFunction<typename JElement_t::abscissa_type, + JResultDerivative<typename JResultType<typename JElement_t::ordinate_type>::result_type> > + { + public: + + typedef JHermiteSplineCollection<JElement_t, JCollection_t, JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef typename JResultType<ordinate_type>::result_type data_type; + typedef JFunction<abscissa_type, JResultDerivative<data_type> > function_type; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::JExceptionHandler exceptionhandler_type; + + + /** + * Default constructor. + */ + JHermiteSplineFunction() + {} + + + /** + * Recursive interpolation method implementation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const override + { + if (this->size() <= 1u) { + return this->getExceptionHandler().action(JFunctionalException("JHermiteSplineFunction<>::evaluate() not enough data.")); + } + + const argument_type x = *pX; + + const_iterator p = this->lower_bound(x); + + + if ((p == this->begin() && this->getDistance(x, (p++)->getX()) > distance_type::precision) || + (p == this->end() && this->getDistance((--p)->getX(), x) > distance_type::precision)) { + + return this->getExceptionHandler().action(JValueOutOfRange("JHermiteSplineFunction::evaluate() x out of range.")); + } + + const_iterator q = p--; + + const double dx = this->getDistance(p->getX(), q->getX()); + const double t = this->getDistance(p->getX(), x) / dx; + + result.f = h00 (t)*p->getY() + h10 (t)*p->getU()*dx + h01 (t)*q->getY() + h11 (t)*q->getU()*dx; + result.fp = h00p(t)*p->getY()/dx + h10p(t)*p->getU() + h01p(t)*q->getY()/dx + h11p(t)*q->getU(); + + return result; + } + + + protected: + + using collection_type::h00; + using collection_type::h10; + using collection_type::h01; + using collection_type::h11; + + using collection_type::h00p; + using collection_type::h10p; + using collection_type::h01p; + using collection_type::h11p; + + private: + mutable result_type result; + }; + + + /** + * Template specialisation for spline interpolation method with returning JResultPDF data structure. + * + * Note that the data structure of the elements in the collection should have the additional methods: + * <pre> + * ordinate_type getIntegral() const; + * void setIntegral(ordinate_type v); + * </pre> + * to get and set the integral values, respectively. + */ + template<class JElement_t, template<class, class> class JCollection_t, class JDistance_t> + class JHermiteSplineFunction<JElement_t, + JCollection_t, + JResultPDF<typename JResultType<typename JElement_t::ordinate_type>::result_type>, + JDistance_t> : + public JHermiteSplineCollection<JElement_t, JCollection_t, JDistance_t>, + public JFunction<typename JElement_t::abscissa_type, + JResultPDF<typename JResultType<typename JElement_t::ordinate_type>::result_type> > + { + public: + + typedef JHermiteSplineCollection<JElement_t, JCollection_t, JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef typename JResultType<ordinate_type>::result_type data_type; + typedef JFunction<abscissa_type, JResultPDF<data_type> > function_type; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::JExceptionHandler exceptionhandler_type; + + + /** + * Default constructor. + */ + JHermiteSplineFunction() + {} + + + /** + * Recursive interpolation method implementation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const override + { + if (this->size() <= 1u) { + return this->getExceptionHandler().action(JFunctionalException("JHermiteSplineFunction<>::evaluate() not enough data.")); + } + + const argument_type x = *pX; + + const_iterator p = this->lower_bound(x); + + if (p == this->begin() && this->getDistance(x, (p++)->getX()) > distance_type::precision) { + + try { + + result = this->getExceptionHandler().action(JValueOutOfRange("JHermiteSplineFunction1D<>::operator() x < xmin.")); + + // overwrite integral values + + result.v = 0; + result.V = this->rbegin()->getIntegral(); + + } catch(const JValueOutOfRange& exception) { + throw exception; + } + + return result; + + } else if (p == this->end() && this->getDistance((--p)->getX(), x) > distance_type::precision) { + + try { + + result = this->getExceptionHandler().action(JValueOutOfRange("JHermiteSplineFunction1D<>::operator() x > xmax.")); + + // overwrite integral values + + result.v = this->rbegin()->getIntegral(); + result.V = this->rbegin()->getIntegral(); + + } catch(const JValueOutOfRange& exception) { + throw exception; + } + + return result; + } + + const_iterator q = p--; + + const double dx = this->getDistance(p->getX(), q->getX()); + const double t = this->getDistance(p->getX(), x) / dx; + + result.f = h00 (t)*p->getY() + h10 (t)*p->getU()*dx + h01 (t)*q->getY() + h11 (t)*q->getU()*dx; + result.fp = h00p(t)*p->getY()/dx + h10p(t)*p->getU() + h01p(t)*q->getY()/dx + h11p(t)*q->getU(); + result.v = (p->getIntegral() + + (H00 (t)*p->getY() + H10 (t)*p->getU()*dx + H01 (t)*q->getY() + H11 (t)*q->getU()*dx)*dx); + result.V = this->rbegin()->getIntegral(); + + return result; + } + + + protected: + + using collection_type::h00; + using collection_type::h10; + using collection_type::h01; + using collection_type::h11; + + using collection_type::h00p; + using collection_type::h10p; + using collection_type::h01p; + using collection_type::h11p; + + using collection_type::H00; + using collection_type::H10; + using collection_type::H01; + using collection_type::H11; + + /** + * Determination of derivatives. + */ + virtual void do_compile() override + { + if (!this->empty()) { + + collection_type::do_compile(); + + this->begin()->setIntegral(JMATH::zero); + + for (iterator j = this->begin(), i = j++; j != this->end(); ++i, ++j) { + + const double dx = this->getDistance(i->getX(), j->getX()); + const ordinate_type y = i->getY() + j->getY(); + const ordinate_type z = i->getU() - j->getU(); + + const ordinate_type v = dx * 0.50 * y; + const ordinate_type w = dx * 1.00 * z*dx/12.0; + + j->setIntegral(i->getIntegral() + v + w); + } + } + } + + private: + mutable result_type result; + }; + + + /** + * Template class for spline interpolation in 1D + * + * This class implements the JFunction1D interface. + */ + template<class JElement_t, + template<class, class> class JCollection_t, + class JResult_t = typename JElement_t::ordinate_type, + class JDistance_t = JDistance<typename JElement_t::abscissa_type> > + class JHermiteSplineFunction1D : + public JHermiteSplineFunction<JElement_t, JCollection_t, JResult_t, JDistance_t>, + public JFunction1D<typename JElement_t::abscissa_type, JResult_t> + { + public: + + typedef JHermiteSplineCollection<JElement_t, JCollection_t, JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef JFunction1D<abscissa_type, JResult_t> function_type; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::JExceptionHandler exceptionhandler_type; + + + /** + * Default contructor. + */ + JHermiteSplineFunction1D() + {} + }; + + + /** + * Functional map with spline interpolation. + */ + template<class JKey_t, + class JValue_t, + template<class, class, class> class JMap_t, + class JResult_t, + class JDistance_t = JDistance<JKey_t> > + class JHermiteSplineMap : + public JMap_t<JKey_t, JValue_t, JDistance_t>, + public JFunction<JKey_t, JResult_t> + { + public: + + typedef JMap_t<JKey_t, JValue_t, JDistance_t> collection_type; + typedef JFunction<JKey_t, JResult_t> function_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::JExceptionHandler exceptionhandler_type; + + typedef typename JResultType<ordinate_type>::result_type data_type; + typedef JHermiteSplineFunction1D<JSplineElement2D<argument_type, data_type>, + JMapCollection<JMap_t>::template collection_type, + result_type> JHermiteSplineFunction1D_t; + + + /** + * Default constructor. + */ + JHermiteSplineMap() + {} + + + /** + * Recursive interpolation method implementation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const override + { + const argument_type x = *pX; + + ++pX; // next argument value + + const_iterator p = this->begin(); + + for (typename JHermiteSplineFunction1D_t::iterator q = buffer.begin(); q != buffer.end(); ++q, ++p) { + q->getY() = JFunction<argument_type, data_type>::getValue(p->getY(), pX); + } + + buffer.compile(); + + return buffer(x); + } + + + private: + /** + * Function compilation. + */ + virtual void do_compile() override + { + buffer.clear(); + + for (iterator i = this->begin(); i != this->end(); ++i) { + buffer.put(i->getX(), data_type()); + } + } + + + mutable JHermiteSplineFunction1D_t buffer; + }; + + + /** + * Conversion of data points to integral values. + * + * The integration includes the use of 2nd derivatives of the data points of the input spline interpolating function. + * + * \param input collection + * \param output mappable collection + * \return integral + */ + template<class JElement_t, + template<class, class> class JCollection_t, + class JResult_t, + class JDistance_t> + inline typename JElement_t::ordinate_type + integrate(const JHermiteSplineFunction1D<JElement_t, JCollection_t, JResult_t, JDistance_t>& input, + typename JMappable<JElement_t>::map_type& output) + { + typedef typename JElement_t::ordinate_type ordinate_type; + typedef typename JHermiteSplineFunction1D<JElement_t, JCollection_t, JResult_t, JDistance_t>::const_iterator const_iterator; + + ordinate_type V(JMATH::zero); + + if (input.getSize() > 1) { + + output.put(input.begin()->getX(), V); + + for (const_iterator j = input.begin(), i = j++; j != input.end(); ++i, ++j) { + + const double dx = input.getDistance(i->getX(), j->getX()); + const ordinate_type y = i->getY() + j->getY(); + const ordinate_type z = i->getU() - j->getU(); + + const ordinate_type v = dx * 0.50 * y; + const ordinate_type w = dx * 1.00 * z*dx/12.0; + + V += v + w; + + output.put(j->getX(), V); + } + } + + return V; + } + + + /** + * Conversion of data points to integral values. + * + * The integration directly uses the integral values of the input spline interpolating function. + * + * \param input collection + * \param output mappable collection + * \return integral + */ + template<class JElement_t, + template<class, class> class JCollection_t, + class JDistance_t> + inline typename JElement_t::ordinate_type + integrate(const JHermiteSplineFunction1D<JElement_t, JCollection_t, JResultPDF<typename JElement_t::ordinate_type>, JDistance_t>& input, + typename JMappable<JElement_t>::map_type& output) + { + typedef typename JElement_t::ordinate_type ordinate_type; + typedef JResultPDF<ordinate_type> result_type; + typedef typename JHermiteSplineFunction1D<JElement_t, JCollection_t, result_type, JDistance_t>::const_iterator const_iterator; + + if (input.getSize() > 1) { + + for (const_iterator i = input.begin(); i != input.end(); ++i) { + output.put(i->getX(), i->getIntegral()); + } + + return input.rbegin()->getIntegral(); + } + + return JMATH::zero; + } +} + +#endif diff --git a/jpp/JTools/JHistogram.hh b/jpp/JTools/JHistogram.hh new file mode 100644 index 0000000..224f5e6 --- /dev/null +++ b/jpp/JTools/JHistogram.hh @@ -0,0 +1,234 @@ +#ifndef __JTOOLS__JHISTOGRAM__ +#define __JTOOLS__JHISTOGRAM__ + +#include "JLang/JClass.hh" +#include "JMath/JZero.hh" +#include "JIO/JSerialisable.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JIO::JReader; + using JIO::JWriter; + + + /** + * Template definition of histogram object interface. + * This class also comprises auxiliary data. + */ + template<class JAbscissa_t, class JContents_t> + class JHistogram + { + protected: + /** + * Default constructor. + */ + JHistogram() : + underflow(JMATH::zero), + overflow (JMATH::zero), + integral (JMATH::zero) + {} + + + public: + + typedef JAbscissa_t abscissa_type; + typedef JContents_t contents_type; + + + /** + * Virtual destructor. + */ + virtual ~JHistogram() + {} + + + /** + * Histogram filling. + * + * \param pX pointer to abscissa values + * \param w weight + */ + virtual void evaluate(const abscissa_type* pX, + typename JLANG::JClass<contents_type>::argument_type w) = 0; + + + /** + * Add histogram. + * + * \param histogram histogram + * \return this histogram + */ + JHistogram& add(const JHistogram& histogram) + { + this->underflow += histogram.underflow; + this->overflow += histogram.overflow; + this->integral += histogram.integral; + + return *this; + } + + + /** + * Subtract histogram. + * + * \param histogram histogram + * \return this histogram + */ + JHistogram& sub(const JHistogram& histogram) + { + this->underflow -= histogram.underflow; + this->overflow -= histogram.overflow; + this->integral -= histogram.integral; + + return *this; + } + + + /** + * Scale histogram. + * + * \param value multiplication factor + * \return this histogram + */ + JHistogram& mul(const double value) + { + this->underflow *= value; + this->overflow *= value; + this->integral *= value; + + return *this; + } + + + /** + * Scale histogram. + * + * \param value division factor + * \return this histogram + */ + JHistogram& div(double value) + { + this->underflow /= value; + this->overflow /= value; + this->integral /= value; + + return *this; + } + + + /** + * Get contents below lower limit. + * + * \return contents + */ + const contents_type& getUnderflow() const + { + return underflow; + } + + + /** + * Get contents above upper limit. + * + * \return contents + */ + const contents_type& getOverflow() const + { + return overflow; + } + + + /** + * Get contents above upper limit. + * + * \return contents + */ + const contents_type& getIntegral() const + { + return integral; + } + + + /** + * Read histogram from input. + * + * \param in reader + * \param object histogram + * \return reader + */ + friend inline JReader& operator>>(JReader& in, JHistogram& object) + { + in >> object.underflow; + in >> object.overflow; + in >> object.integral; + + return in; + } + + + /** + * Write histogram to output. + * + * \param out writer + * \param object histogram + * \return writer + */ + friend inline JWriter& operator<<(JWriter& out, const JHistogram& object) + { + out << object.underflow; + out << object.overflow; + out << object.integral; + + return out; + } + + + protected: + contents_type underflow; + contents_type overflow; + contents_type integral; + }; + + + /** + * Functional histogram cumulator. + */ + struct JCumulator { + /** + * Default constructor. + */ + JCumulator() + {} + + + /** + * Compile function. + * + * \param function function + * \return this cumulator + */ + template<class JHistogram_t> + const JCumulator& operator()(JHistogram_t& function) const + { + function.cumlative(); + + return *this; + } + }; + + + /** + * Function object for functional object compilation. + */ + static const JCumulator cumulator; +} + +#endif diff --git a/jpp/JTools/JHistogramMap.hh b/jpp/JTools/JHistogramMap.hh new file mode 100644 index 0000000..56efe4a --- /dev/null +++ b/jpp/JTools/JHistogramMap.hh @@ -0,0 +1,144 @@ +#ifndef __JTOOLS__JHISTOGRAMMAP__ +#define __JTOOLS__JHISTOGRAMMAP__ + +#include "JLang/JClass.hh" +#include "JTools/JHistogram.hh" +#include "JTools/JDistance.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + + /** + * Histogram map. + * + * This class implements the JHistogram interface. + */ + template<class JAbscissa_t, + class JContents_t, + template<class, class, class> class JMap_t, + class JDistance_t = JDistance<JAbscissa_t> > + class JHistogramMap : + public JMap_t<JAbscissa_t, JContents_t, JDistance_t>, + public JHistogram<JAbscissa_t, typename JContents_t::contents_type> + { + public: + + typedef JMap_t<JAbscissa_t, JContents_t, JDistance_t> collection_type; + typedef JHistogram<JAbscissa_t, typename JContents_t::contents_type> histogram_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + //typedef typename histogram_type::abscissa_type abscissa_type; + typedef typename histogram_type::contents_type contents_type; + + + /** + * Default constructor. + */ + JHistogramMap() + {} + + + /** + * Fill histogram. + * + * \param pX pointer to abscissa values + * \param w weight + */ + virtual void evaluate(const abscissa_type* pX, + typename JLANG::JClass<contents_type>::argument_type w) + { + const abscissa_type x = *pX; + + iterator p = this->lower_bound(x); + + this->integral += w; + + if (p == this->begin()) + this->underflow += w; + else if (p == this->end()) + this->overflow += w; + else + (--p)->getY().evaluate(++pX, w); + } + + + /** + * Scale contents. + * + * \param factor multiplication factor + * \return this histogram + */ + JHistogramMap& mul(typename JLANG::JClass<contents_type>::argument_type factor) + { + collection_type::mul(factor); + histogram_type ::mul(factor); + + return *this; + } + + + /** + * Scale contents. + * + * \param factor division factor + * \return this histogram + */ + JHistogramMap& div(typename JLANG::JClass<contents_type>::argument_type factor) + { + collection_type::div(factor); + histogram_type ::div(factor); + + return *this; + } + + + /** + * Read histogram map from input. + * + * \param in reader + * \param object histogram map + * \return reader + */ + friend inline JReader& operator>>(JReader& in, JHistogramMap& object) + { + in >> static_cast<histogram_type&> (object); + in >> static_cast<collection_type&>(object); + + return in; + } + + + /** + * Write histogram map to output. + * + * \param out writer + * \param object histogram map + * \return writer + */ + friend inline JWriter& operator<<(JWriter& out, const JHistogramMap& object) + { + out << static_cast<const histogram_type&> (object); + out << static_cast<const collection_type&>(object); + + return out; + } + }; +} + +#endif diff --git a/jpp/JTools/JMap.hh b/jpp/JTools/JMap.hh new file mode 100644 index 0000000..72a077c --- /dev/null +++ b/jpp/JTools/JMap.hh @@ -0,0 +1,126 @@ +#ifndef __JTOOLS__JMAP__ +#define __JTOOLS__JMAP__ + +#include "JTools/JCollection.hh" +#include "JTools/JMapCollection.hh" +#include "JTools/JElement.hh" +#include "JMath/JMath.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JMATH::JMath; + + + /** + * Map of pair-wise elements. + * + * The key_type and mapped_type refer to the pair-wise element of this map, respectively. + */ + template<class JKey_t, + class JValue_t, + class JDistance_t = JDistance<JKey_t> > + class JMap : + public JCollection<JElement2D<JKey_t, JValue_t>, JDistance_t>, + public JMath< JMap<JKey_t, JValue_t, JDistance_t> > + { + public: + + typedef JKey_t key_type; + typedef JValue_t mapped_type; + + typedef JCollection<JElement2D<JKey_t, JValue_t>, JDistance_t> container_type; + + typedef typename container_type::const_iterator const_iterator; + typedef typename container_type::const_reverse_iterator const_reverse_iterator; + typedef typename container_type::iterator iterator; + typedef typename container_type::reverse_iterator reverse_iterator; + + + /** + * Default constructor. + */ + JMap() + {} + + + /** + * Add map. + * + * \param map map + * \return this map + */ + JMap& add(const JMap& map) + { + static_cast<container_type&>(*this).add(static_cast<const container_type&>(map)); + + return *this; + } + + + /** + * Subtract map. + * + * \param map map + * \return this map + */ + JMap& sub(const JMap& map) + { + static_cast<container_type&>(*this).sub(static_cast<const container_type&>(map)); + + return *this; + } + + + /** + * Scale contents. + * + * \param value multiplication factor + * \return this map + */ + JMap& mul(const double value) + { + static_cast<container_type&>(*this).mul(value); + + return *this; + } + + /** + * Scale contents. + * + * \param value division factor + * \return this map + */ + JMap& div(const double value) + { + static_cast<container_type&>(*this).div(value); + + return *this; + } + }; + + + /** + * Specialisation of JMapCollection for JMap. + */ + template<> + struct JMapCollection<JMap> { + /** + * Collection of elements. + */ + template<class JElement_t, + class JDistance_t = JDistance<typename JElement_t::abscissa_type> > + struct collection_type : + public JCollection<JElement_t, JDistance_t> + {}; + }; +} + +#endif diff --git a/jpp/JTools/JMapCollection.hh b/jpp/JTools/JMapCollection.hh new file mode 100644 index 0000000..cf55747 --- /dev/null +++ b/jpp/JTools/JMapCollection.hh @@ -0,0 +1,23 @@ +#ifndef __JTOOLS__JMAPCOLLECTION__ +#define __JTOOLS__JMAPCOLLECTION__ + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + /** + * Template class to define the corresponding JCollection for a given template JMap. + * + * This class should be specialised for each map type so that the implementation + * of an interpolation method based on a collection can directly be transferred to a map. + */ + template<template<class, class, class> class JMap_t> + struct JMapCollection; +} + +#endif diff --git a/jpp/JTools/JMapList.hh b/jpp/JTools/JMapList.hh new file mode 100644 index 0000000..6559dab --- /dev/null +++ b/jpp/JTools/JMapList.hh @@ -0,0 +1,149 @@ +#ifndef __JTOOLS__JMAPLIST__ +#define __JTOOLS__JMAPLIST__ + +#include "JLang/JNullType.hh" +#include "JTools/JDistance.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JLANG::JNullType; + + + /** + * Map list. + */ + template<template<class, class, class> class JHead_t, class JTail_t = JNullType> + struct JMapList + { + typedef JMapList<JHead_t, typename JTail_t::head_list> head_list; //!< first N-1 maps + typedef typename JTail_t::tail_type tail_type; //!< last map + }; + + + /** + * Terminator class of map list. + */ + template<template<class, class, class> class JHead_t> + struct JMapList<JHead_t, JNullType> + { + typedef JNullType head_list; //!< first N-1 maps + typedef JMapList<JHead_t> tail_type; //!< last map + }; + + + /** + * Length of map list. + */ + template<class JMaplist_t> struct JMapLength {}; + + + /** + * Recursive length of map list. + */ + template<template<class, class, class> class JHead_t, class JTail_t> + struct JMapLength< JMapList<JHead_t, JTail_t> > + { + enum { value = 1 + JMapLength<JTail_t>::value }; + }; + + + /** + * Terminator class of length of map list. + */ + template<template<class, class, class> class JHead_t> + struct JMapLength< JMapList<JHead_t, JNullType> > + { + enum { value = 1 }; + }; + + + /** + * Auxiliary class for no map definition. + * This class can be used to terminate a map list, define a default template argument, etc. + */ + template<class JKey_t, + class JValue_t, + class JDistance_t = JDistance<JKey_t> > + struct JNullMap {}; + + + /** + * Auxiliary class for recursive map list generation. + * This class accepts up to 26 map types. + */ + template<template<class, class, class> class A = JNullMap, + template<class, class, class> class B = JNullMap, + template<class, class, class> class C = JNullMap, + template<class, class, class> class D = JNullMap, + template<class, class, class> class E = JNullMap, + template<class, class, class> class F = JNullMap, + template<class, class, class> class G = JNullMap, + template<class, class, class> class H = JNullMap, + template<class, class, class> class I = JNullMap, + template<class, class, class> class J = JNullMap, + template<class, class, class> class K = JNullMap, + template<class, class, class> class L = JNullMap, + template<class, class, class> class M = JNullMap, + template<class, class, class> class N = JNullMap, + template<class, class, class> class O = JNullMap, + template<class, class, class> class P = JNullMap, + template<class, class, class> class Q = JNullMap, + template<class, class, class> class R = JNullMap, + template<class, class, class> class S = JNullMap, + template<class, class, class> class T = JNullMap, + template<class, class, class> class U = JNullMap, + template<class, class, class> class V = JNullMap, + template<class, class, class> class W = JNullMap, + template<class, class, class> class X = JNullMap, + template<class, class, class> class Y = JNullMap, + template<class, class, class> class Z = JNullMap> + struct JMAPLIST + { + typedef JMapList<A, typename JMAPLIST<B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z>::maplist> maplist; //!< Map list + }; + + + /** + * Template specialisation to terminate recursive map list generation. + */ + template<template<class, class, class> class A> + struct JMAPLIST<A, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap, + JNullMap> + { + typedef JMapList<A> maplist; //!< Map list + }; +} + +#endif diff --git a/jpp/JTools/JMappableCollection.hh b/jpp/JTools/JMappableCollection.hh new file mode 100644 index 0000000..3a67c49 --- /dev/null +++ b/jpp/JTools/JMappableCollection.hh @@ -0,0 +1,118 @@ +#ifndef __JTOOLS__JMAPPABLECOLLECTION__ +#define __JTOOLS__JMAPPABLECOLLECTION__ + +#include "JLang/JClass.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JLANG::JClass; + + + /** + * Template interface definition for associative collection of elements. + * The concrete associative collection should implement the following methods. + * <pre> + * void clear(); + * + * mapped_type& get(key_type key); + * </pre> + * This class implements the operator <tt>[key_type key]</tt> and method <tt>put(key_type key, mapped_type value)</tt>. + */ + template<class JKey_t, class JValue_t> + struct JMappableCollection + { + + typedef JKey_t key_type; + typedef JValue_t mapped_type; + + /** + * Virtual destructor. + */ + virtual ~JMappableCollection() + {} + + + /** + * Clear. + */ + virtual void clear() = 0; + + + /** + * Get mapped value. + * + * \param key key + * \return value + */ + virtual const mapped_type& get(typename JClass<key_type>::argument_type key) const = 0; + + + /** + * Get mapped value. + * + * \param key key + * \return value + */ + virtual mapped_type& get(typename JClass<key_type>::argument_type key) = 0; + + + /** + * Get mapped value. + * + * \param key key + * \return value + */ + const mapped_type& operator[](typename JClass<key_type>::argument_type key) const + { + return get(key); + } + + + /** + * Get mapped value. + * + * \param key key + * \return value + */ + mapped_type& operator[](typename JClass<key_type>::argument_type key) + { + return get(key); + } + + + /** + * Put pair-wise element (key,value) into collection. + * + * \param key key + * \param value value + */ + void put(typename JClass<key_type> ::argument_type key, + typename JClass<mapped_type>::argument_type value) + { + get(key) = value; + } + }; + + + /** + * Auxiliary class to define JMappableCollection for given template. + */ + template<class T> + struct JMappable { + /** + * Type definition of JMappableCollection. + */ + typedef JMappableCollection<typename T::abscissa_type, + typename T::ordinate_type> map_type; + }; +} + +#endif diff --git a/jpp/JTools/JMultiFunction.hh b/jpp/JTools/JMultiFunction.hh new file mode 100644 index 0000000..715fed8 --- /dev/null +++ b/jpp/JTools/JMultiFunction.hh @@ -0,0 +1,354 @@ +#ifndef __JTOOLS__JMULTIFUNCTION__ +#define __JTOOLS__JMULTIFUNCTION__ + +#include "JTools/JMultiMap.hh" +#include "JTools/JFunctional.hh" +#include "JTools/JConstantFunction1D.hh" +#include "JTools/JArray.hh" +#include "JTools/JMultiHistogram.hh" +#include "JTools/JHistogramMap.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + /** + * Multidimensional interpolation method. + * + * The template parameters respectively refer to: + * -# function object used for the lowest dimension(s); + * -# list of functional maps used for the higher dimension(s); and + * -# distance operator. + * + * The number of dimensions of this function object is equal to the length of + * the given map list plus the extra dimensions of the first function object. + * When converting a multidimensional histogram to a multidimensional function for + * subsequent interpolations, the function object used for the lowest dimension(s) + * is treated as a probability density function. + */ + template<class JFunction_t, + class JMaplist_t, + class JDistance_t = JDistance<typename JFunction_t::argument_type> > + class JMultiFunction : + public JMultiMap<typename JFunction_t::argument_type, JFunction_t, JMaplist_t, JDistance_t> + { + public: + + typedef JMultiMap<typename JFunction_t::argument_type, + JFunction_t, + JMaplist_t, + JDistance_t> multimap_type; + + enum { NUMBER_OF_DIMENSIONS = JMapLength<JMaplist_t>::value + JFunction_t::NUMBER_OF_DIMENSIONS }; + + typedef JFunction_t function_type; + + typedef typename JFunction_t::value_type value_type; + typedef typename JFunction_t::argument_type argument_type; + typedef typename JFunction_t::supervisor_type supervisor_type; + + typedef typename multimap_type::abscissa_type abscissa_type; + typedef typename multimap_type::ordinate_type ordinate_type; + typedef typename multimap_type::result_type result_type; + + typedef typename multimap_type::const_iterator const_iterator; + typedef typename multimap_type::const_reverse_iterator const_reverse_iterator; + typedef typename multimap_type::iterator iterator; + typedef typename multimap_type::reverse_iterator reverse_iterator; + + typedef typename multimap_type::super_iterator super_iterator; + typedef typename multimap_type::super_const_iterator super_const_iterator; + + using multimap_type::insert; + + + /** + * Default constructor. + */ + JMultiFunction() + {} + + + /** + * Constructor. + * + * \param input multidimensional input + */ + template<class T> + JMultiFunction(const T& input) + { + insert(input); + + this->compile(); + } + + + /** + * Get multidimensional function. + * + * \return this multidimensional function + */ + const JMultiFunction& getMultiFunction() const + { + return static_cast<const JMultiFunction&>(*this); + } + + + /** + * Get multidimensional function. + * + * \return this multidimensional function + */ + JMultiFunction& getMultiFunction() + { + return static_cast<JMultiFunction&>(*this); + } + + + /** + * Insert multidimensional input. + * + * \param input multidimensional function + */ + template<class JPDF_t, class JPDFMaplist_t, class JPDFDistance_t> + void insert(const JMultiFunction<JPDF_t, JPDFMaplist_t, JPDFDistance_t>& input) + { + copy(input, *this); + } + + + /** + * Insert multidimensional input. + * + * \param input multidimensional histogram + */ + template<class JHistogram_t, class JHistogramMaplist_t, class JHistogramDistance_t> + void insert(const JMultiHistogram<JHistogram_t, JHistogramMaplist_t, JHistogramDistance_t>& input) + { + this->insert(JMultiKey<0, argument_type>(), input); + } + + + /** + * Compilation. + */ + void compile() + { + this->for_each(compiler); + + for (super_iterator i = this->super_begin(); i != this->super_end(); ++i) { + (*i).getValue().compile(); + } + } + + + /** + * Set the supervisor for handling of exceptions. + * + * \param supervisor supervisor + */ + void setExceptionHandler(const supervisor_type& supervisor) + { + this->for_each(supervisor); + + for (super_iterator i = this->super_begin(); i != this->super_end(); ++i) { + (*i).getValue().setExceptionHandler(supervisor); + } + } + + + /** + * Multi-dimensional interpolation method call. + * + * \param args comma seperated list of abscissa values + * \return function value + */ + template<class ...Args> + result_type operator()(const Args& ...args) const + { + return this->evaluate(JArray<NUMBER_OF_DIMENSIONS, argument_type>(args...).data()); + } + + + protected: + /** + * Insert multidimensional histogram at multidimensional key. + * + * \param key multidimensional key + * \param input multidimensional histogram + */ + template<unsigned int N, + class __JAbscissa_t, + class __JContents_t, + template<class, class, class> class __JMap_t, + class __JDistance_t> + void insert(const JMultiKey<N, argument_type>& key, + const JHistogramMap<__JAbscissa_t, __JContents_t, __JMap_t, __JDistance_t>& input) + { + if (input.size() > 1) { + + for (typename JHistogramMap<__JAbscissa_t, __JContents_t, __JMap_t, __JDistance_t>::const_iterator j = input.begin(), i = j++; j != input.end(); ++i, ++j) { + + const argument_type x = 0.5 * (i->getX() + j->getX()); + + insert(JMultiKey<N+1, argument_type>(key, x), i->getY()); + } + } + } + + + /** + * Convert one-dimensional histogram to PDF and insert result at given multidimensional key. + * + * \param key multidimensional key + * \param input histogram + */ + template<class __JValue_t> + void insert(const JMultiKey<JMapLength<JMaplist_t>::value, argument_type>& key, + const __JValue_t& input) + { + JFunction_t buffer; + + makePDF(input, buffer); + + multimap_type::insert(key, buffer); + } + }; + + + /** + * Template specialisation of JMultiFunction for a JConstantFunction. + * The primary 2D function is reduced to a 1D function. + */ + template<class JArgument_t, + class JResult_t, + template<class, class, class> class JMap_t, + class JDistance_t> + class JMultiFunction<JConstantFunction1D<JArgument_t, JResult_t>, JMapList<JMap_t>, JDistance_t> : + public JMap_t<JArgument_t, JResult_t, JDistance_t>, + public JFunction1D<JArgument_t, JResult_t> + { + public: + + typedef JMap_t<JArgument_t, JResult_t, JDistance_t> multimap_type; + + typedef typename multimap_type::abscissa_type abscissa_type; + typedef typename multimap_type::ordinate_type ordinate_type; + + typedef typename multimap_type::argument_type argument_type; + typedef typename multimap_type::result_type result_type; + + typedef typename multimap_type::const_iterator const_iterator; + typedef typename multimap_type::const_reverse_iterator const_reverse_iterator; + typedef typename multimap_type::iterator iterator; + typedef typename multimap_type::reverse_iterator reverse_iterator; + + typedef JConstantFunction1D<JArgument_t, JResult_t> function_type; + typedef JMap_t<JArgument_t, JResult_t, JDistance_t> map_type; + + enum { NUMBER_OF_DIMENSIONS = 1 }; + + using multimap_type::insert; + + + /** + * Insert element. + * + * \param key multidimensional key + * \param function function + */ + void insert(const JMultiKey<1, abscissa_type>& key, const function_type& function) + { + this->insert(key.first, function.getY()); + } + }; + + + /** + * Template specialisation of JMultiFunction for a JConstantFunction. + * The number of dimensions of the primary function is reduced by one. + */ + template<class JArgument_t, + class JResult_t, + class JMaplist_t, + class JDistance_t> + class JMultiFunction<JConstantFunction1D<JArgument_t, JResult_t>, JMaplist_t, JDistance_t> : + public JMultiFunction<JMultiFunction<JConstantFunction1D<JArgument_t, JResult_t>, + typename JMaplist_t::tail_type, + JDistance_t>, + typename JMaplist_t::head_list, + JDistance_t> + { + public: + + typedef JMultiFunction<JMultiFunction<JConstantFunction1D<JArgument_t, JResult_t>, + typename JMaplist_t::tail_type, + JDistance_t>, + typename JMaplist_t::head_list, + JDistance_t> multifunction_type; + + typedef typename multifunction_type::multimap_type multimap_type; + + typedef typename multimap_type::abscissa_type abscissa_type; + typedef typename multimap_type::ordinate_type ordinate_type; + + typedef typename multimap_type::argument_type argument_type; + typedef typename multimap_type::result_type result_type; + + typedef typename multimap_type::const_iterator const_iterator; + typedef typename multimap_type::const_reverse_iterator const_reverse_iterator; + typedef typename multimap_type::iterator iterator; + typedef typename multimap_type::reverse_iterator reverse_iterator; + + typedef typename multimap_type::super_iterator super_iterator; + typedef typename multimap_type::super_const_iterator super_const_iterator; + + typedef JConstantFunction1D<JArgument_t, JResult_t> function_type; + typedef JMultiFunction<JConstantFunction1D<JArgument_t, JResult_t>, + typename JMaplist_t::tail_type, + JDistance_t> map_type; + + enum { NUMBER_OF_DIMENSIONS = JMapLength<JMaplist_t>::value }; + + using multimap_type::insert; + + + /** + * Insert element. + * + * \param key multidimensional key + * \param function function + */ + void insert(const JMultiKey<NUMBER_OF_DIMENSIONS, abscissa_type>& key, const function_type& function) + { + this->get(key.front()).put(key.back(), function.getY()); + } + }; + + + /** + * Conversion of multidimensional histogram to multidimensional function. + * + * \param input multidimensional histogram + * \param output multidimensional function + */ + template<class JHistogram_t, + class JHistogramMaplist_t, + class JHistogramDistance_t, + class JFunction_t, + class JFunctionMaplist_t, + class JFunctionDistance_t> + inline void makePDF(const JMultiHistogram<JHistogram_t, JHistogramMaplist_t, JHistogramDistance_t>& input, + JMultiFunction<JFunction_t, JFunctionMaplist_t, JFunctionDistance_t>& output) + { + output.insert(input); + } +} + +#endif diff --git a/jpp/JTools/JMultiHistogram.hh b/jpp/JTools/JMultiHistogram.hh new file mode 100644 index 0000000..f24c238 --- /dev/null +++ b/jpp/JTools/JMultiHistogram.hh @@ -0,0 +1,135 @@ +#ifndef __JTOOLS__JMULTIHISTOGRAM__ +#define __JTOOLS__JMULTIHISTOGRAM__ + +#include "JTools/JMultiMap.hh" +#include "JTools/JHistogram.hh" +#include "JTools/JArray.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + + /** + * Multidimensional histogram. + * + * The template parameters respectively refer to: + * -# histogram object used for the lowest dimension(s); + * -# list of histogram maps used for the higher dimension(s); and + * -# distance operator. + * + * The number of dimensions of this histogram object is equal to the length of + * the given map list plus the extra dimensions of the first histogram object. + */ + template<class JHistogram_t, + class JMaplist_t, + class JDistance_t = JDistance<typename JHistogram_t::abscissa_type> > + class JMultiHistogram : + public JMultiMap<typename JHistogram_t::abscissa_type, JHistogram_t, JMaplist_t, JDistance_t> + { + public: + + typedef JMultiMap<typename JHistogram_t::abscissa_type, + JHistogram_t, + JMaplist_t, + JDistance_t> multimap_type; + + enum { NUMBER_OF_DIMENSIONS = JMapLength<JMaplist_t>::value + JHistogram_t::NUMBER_OF_DIMENSIONS }; + + typedef typename multimap_type::abscissa_type abscissa_type; + typedef typename multimap_type::ordinate_type ordinate_type; + + typedef typename multimap_type::const_iterator const_iterator; + typedef typename multimap_type::const_reverse_iterator const_reverse_iterator; + typedef typename multimap_type::iterator iterator; + typedef typename multimap_type::reverse_iterator reverse_iterator; + + typedef typename multimap_type::super_iterator super_iterator; + typedef typename multimap_type::super_const_iterator super_const_iterator; + + typedef typename JHistogram_t::contents_type contents_type; + + + /** + * Default constructor. + */ + JMultiHistogram() + {} + + + /** + * Get multidimensional histogram. + * + * \return this multidimensional histogram + */ + const JMultiHistogram& getMultiHistogram() const + { + return static_cast<const JMultiHistogram&>(*this); + } + + + /** + * Get multidimensional histogram. + * + * \return this multidimensional histogram + */ + JMultiHistogram& getMultiHistogram() + { + return static_cast<JMultiHistogram&>(*this); + } + + + /** + * Multi-dimensional fill method call. + * + * \param args comma seperated list of abscissa values and weight + */ + template<class ...Args> + void fill(const Args& ...args) + { + __fill__(0, args...); + } + + + protected: + /** + * Recursive method for filling histogram. + * + * \param i index + * \param x0 value at given index + * \param x1 value at following index + * \param args remaining values and weight + */ + template<class ...Args> + void __fill__(const int i, const abscissa_type x0, const abscissa_type x1, const Args& ...args) + { + this->buffer[i] = x0; + + __fill__(i + 1, x1, args...); + } + + /** + * Termination method for filling histogram. + * + * \param i index + * \param x value at given index + * \param w weight + */ + virtual void __fill__(const int i, const abscissa_type x, const contents_type w) + { + this->buffer[i] = x; + + this->evaluate(this->buffer.data(), w); + } + + mutable JArray<NUMBER_OF_DIMENSIONS, abscissa_type> buffer; + }; +} + +#endif diff --git a/jpp/JTools/JMultiKey.hh b/jpp/JTools/JMultiKey.hh new file mode 100644 index 0000000..419ad0a --- /dev/null +++ b/jpp/JTools/JMultiKey.hh @@ -0,0 +1,537 @@ +#ifndef __JTOOLS__JMULTIKEY__ +#define __JTOOLS__JMULTIKEY__ + +#include <istream> +#include <ostream> +#include <utility> +#include <cmath> + +#include "JLang/JClass.hh" +#include "JLang/JException.hh" +#include "JLang/JComparable.hh" +#include "JLang/JManip.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JLANG::JComparable; + using JLANG::JClass; + + + /** + * \cond NEVER + * Forward declaration of template JMultiKey class. + * \endcond + */ + template<unsigned int N, class JKey_t> + class JMultiKey; + + + namespace { + /** + * Auxiliary class for copying between const and non-const key types. + */ + template<unsigned int N, class JKey_t> + struct JArgument { + typedef const JMultiKey<N, const JKey_t>& argument_type; + }; + + + template<unsigned int N, class JKey_t> + struct JArgument<N, const JKey_t> { + typedef const JMultiKey<N, JKey_t>& argument_type; + }; + } + + + /** + * Multidimensional key. + * + * This class reproduces the key of a multidimensional map. + * The individual data members can be accessed as, e.g: + * <pre> + * JMultiKey<3, key_type> key; + * + * key[[.second].second].first; + * </pre> + */ + template<unsigned int N, class JKey_t> + class JMultiKey : + public std::pair<JKey_t, JMultiKey<N-1, JKey_t> >, + public JComparable< JMultiKey<N, JKey_t> > + { + public: + + typedef JKey_t key_type; + typedef JMultiKey<N-1, JKey_t> mapped_type; + typedef std::pair<key_type, mapped_type> pair; + + + /** + * Default constructor. + */ + JMultiKey() : + pair() + {} + + + /** + * Constructor. + * The secondary key is appended to the end of the primary keys. + * + * \param __first primary keys + * \param __second secondary key + */ + JMultiKey(typename JClass<mapped_type>::argument_type __first, + typename JClass<key_type> ::argument_type __second) : + pair(__first.first, mapped_type(__first.second, __second)) + {} + + + /** + * Constructor. + * The primary key is inserted at the start of the secondary keys. + * + * \param __first primary key + * \param __second secondary keys + */ + JMultiKey(typename JClass<key_type> ::argument_type __first, + typename JClass<mapped_type>::argument_type __second) : + pair(__first, __second) + {} + + + /** + * Copy constructor. + * + * \param key key + */ + JMultiKey(typename JArgument<N, JKey_t>::argument_type key) : + pair(key.first, key.second) + {} + + + /** + * Less than method. + * + * \param key key + * \return true if this key less than given key; else false + */ + bool less(const JMultiKey<N, JKey_t>& key) const + { + if (this->first == key.first) + return this->second.less(key.second); + else + return this->first < key.first; + } + + + /** + * Get length squared. + * + * \return square of length + */ + double getLengthSquared() const + { + return this->first*this->first + this->second.getLengthSquared(); + } + + + /** + * Get length. + * + * \return length + */ + double getLength() const + { + return sqrt(this->getLengthSquared()); + } + + + /** + * Get frontend key. + * + * \return frontend key + */ + JMultiKey<N-1, JKey_t> front() const + { + return JMultiKey<N-1, JKey_t>(this->first, this->second.front()); + } + + + /** + * Get backend key. + * + * \return backend key + */ + key_type back() const + { + return this->second.back(); + } + + + /** + * Read key from input. + * + * \param in input stream + * \param key key + * \return input stream + */ + friend inline std::istream& operator>>(std::istream& in, JMultiKey<N, JKey_t>& key) + { + in >> key.first; + in >> key.second; + + return in; + } + + + /** + * Write key to output. + * + * \param out output stream + * \param key key + * \return output stream + */ + friend inline std::ostream& operator<<(std::ostream& out, const JMultiKey<N, JKey_t>& key) + { + const JFormat format(out, getFormat< JMultiKey<N, JKey_t> >(JFormat_t(9, 3, std::ios::fixed | std::ios::showpos))); + + out << format << key.first; + out << ' '; + out << key.second; + + return out; + } + }; + + + /** + * Two-dimensional key. + */ + template<class JKey_t> + class JMultiKey<2, JKey_t> : + public std::pair<JKey_t, JMultiKey<1, JKey_t> >, + public JComparable< JMultiKey<2, JKey_t> > + { + public: + + typedef JKey_t key_type; + typedef JMultiKey<1, JKey_t> mapped_type; + typedef std::pair<key_type, mapped_type> pair; + + + /** + * Default constructor. + */ + JMultiKey() : + pair() + {} + + + /** + * Constructor. + * The secondary key is appended to the end of the primary key. + * + * \param __first primary key + * \param __second secondary key + */ + JMultiKey(typename JClass<mapped_type>::argument_type __first, + typename JClass<key_type> ::argument_type __second) : + pair(__first.first, __second) + {} + + + /** + * Constructor. + * The primary key is inserted at the start of the secondary key. + * + * \param __first primary key + * \param __second secondary key + */ + JMultiKey(typename JClass<key_type> ::argument_type __first, + typename JClass<mapped_type>::argument_type __second) : + pair(__first, __second.first) + {} + + + /** + * Copy constructor. + * + * \param key key + */ + JMultiKey(typename JArgument<2, JKey_t>::argument_type key) : + pair(key.first, key.second) + {} + + + /** + * Less than method. + * + * \param key key + * \return true if this key less than given key; else false + */ + bool less(const JMultiKey<2, JKey_t>& key) const + { + if (this->first == key.first) + return this->second.less(key.second); + else + return this->first < key.first; + } + + + /** + * Get length squared. + * + * \return square of length + */ + double getLengthSquared() const + { + return this->first*this->first + this->second.getLengthSquared(); + } + + + /** + * Get length. + * + * \return length + */ + double getLength() const + { + return sqrt(this->getLengthSquared()); + } + + + /** + * Get frontend key. + * + * \return frontend key + */ + JMultiKey<1, JKey_t> front() const + { + return JMultiKey<1, JKey_t>(this->first); + } + + + /** + * Get backend key. + * + * \return backend key + */ + key_type back() const + { + return this->second.back(); + } + + + /** + * Read key from input. + * + * \param in input stream + * \param key key + * \return input stream + */ + friend inline std::istream& operator>>(std::istream& in, JMultiKey<2, JKey_t>& key) + { + in >> key.first; + in >> key.second; + + return in; + } + + + /** + * Write key to output. + * + * \param out output stream + * \param key key + * \return output stream + */ + friend inline std::ostream& operator<<(std::ostream& out, const JMultiKey<2, JKey_t>& key) + { + const JFormat format(out, getFormat< JMultiKey<2, JKey_t> >(JFormat_t(9, 3, std::ios::fixed | std::ios::showpos))); + + out << format << key.first; + out << ' '; + out << key.second; + + return out; + } + }; + + + /** + * One-dimensional key. + */ + template<class JKey_t> + class JMultiKey<1, JKey_t> : + public JComparable< JMultiKey<1, JKey_t> > + { + public: + + typedef JKey_t key_type; + typedef JMultiKey<0, JKey_t> mapped_type; + + + /** + * Default constructor. + */ + JMultiKey() : + first() + {} + + + /** + * Constructor. + * The secondary key is appended to the end of the primary key. + * + * \param __first primary key + * \param __second secondary key + */ + JMultiKey(typename JClass<mapped_type>::argument_type __first, + typename JClass<key_type> ::argument_type __second) : + first(__second) + {} + + + /** + * Constructor. + * The primary key is inserted at the start of the secondary key. + * + * \param __first primary key + * \param __second secondary key + */ + JMultiKey(typename JClass<key_type> ::argument_type __first, + typename JClass<mapped_type>::argument_type __second) : + first(__first) + {} + + + /** + * Constructor. + * + * \param __first key + */ + JMultiKey(typename JClass<key_type>::argument_type __first) : + first(__first) + {} + + + /** + * Copy constructor. + * + * \param key key + */ + JMultiKey(typename JArgument<1, JKey_t>::argument_type key) : + first(key.first) + {} + + + /** + * Less than method. + * + * \param key key + * \return true if this key less than given key; else false + */ + bool less(const JMultiKey<1, JKey_t>& key) const + { + return this->first < key.first; + } + + + /** + * Get length squared. + * + * \return square of length + */ + double getLengthSquared() const + { + return this->first*this->first; + } + + + /** + * Get length. + * + * \return length + */ + double getLength() const + { + return sqrt(this->getLengthSquared()); + } + + + /** + * Get backend key. + * + * \return backend key + */ + key_type back() const + { + return this->first; + } + + + /** + * Read key from input. + * + * \param in input stream + * \param key key + * \return input stream + */ + friend inline std::istream& operator>>(std::istream& in, JMultiKey<1, JKey_t>& key) + { + in >> key.first; + + return in; + } + + + /** + * Write key to output. + * + * \param out output stream + * \param key key + * \return output stream + */ + friend inline std::ostream& operator<<(std::ostream& out, const JMultiKey<1, JKey_t>& key) + { + const JFormat format(out, getFormat< JMultiKey<1, JKey_t> >(JFormat_t(9, 3, std::ios::fixed | std::ios::showpos))); + + out << format << key.first; + + return out; + } + + + key_type first; + }; + + + /** + * Empty key. + */ + template<class JKey_t> + class JMultiKey<0, JKey_t> + { + public: + + typedef JKey_t key_type; + + + /** + * Default constructor. + */ + JMultiKey() + {} + }; +} + +#endif diff --git a/jpp/JTools/JMultiMap.hh b/jpp/JTools/JMultiMap.hh new file mode 100644 index 0000000..d1ff254 --- /dev/null +++ b/jpp/JTools/JMultiMap.hh @@ -0,0 +1,1669 @@ +#ifndef __JTOOLS__JMULTIMAP__ +#define __JTOOLS__JMULTIMAP__ + +#include "JLang/JSinglePointer.hh" +#include "JLang/JEquals.hh" +#include "JLang/JForwardIterator.hh" + +#include "JTools/JDistance.hh" +#include "JTools/JPair.hh" +#include "JTools/JMultiPair.hh" +#include "JTools/JMapList.hh" +#include "JTools/JAbstractMultiMap.hh" +#include "JTools/JMultiKey.hh" +#include "JMath/JMath.hh" + + +/** + * \file + * + * JMultiMap is a general purpose multidimensional map based on a type list of maps. + * \author mdejong + */ +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JMATH::JMath; + using JLANG::JEquals; + using JLANG::JForwardIterator; + + + /** + * Multidimensional map. + * + * The first template parameter refers to the data type of the (multidimensional) key; + * the second to the data type of the overall mapped value; + * the third to the list of maps used; and + * the fourth to the distance operator. + * + * In addition to the standard STL iterators, there is a + * super_[const_[reverse_]]iterator for linear access to the multidimensional map. + * The access from the super_iterator to the actual elements in the multidimensional map + * is handeld via a the standard dereference and pointer operators yielding + * a multidimensional key (see JTOOLS::JMultiKey) or pair (see JTOOLS::JMultiPair), respectively. + */ + template<class JAbscissa_t, + class JOrdinate_t, + class JMaplist_t, + class JDistance_t = JDistance<JAbscissa_t> > + class JMultiMap; + + + /** + * Template specialisation of JMultiMap for map list with at least one map. + */ + template<class JAbscissa_t, + class JOrdinate_t, + template<class, class, class> class JHead_t, + class JTail_t, + class JDistance_t> + class JMultiMap<JAbscissa_t, JOrdinate_t, JMapList<JHead_t, JTail_t>, JDistance_t> : + public JHead_t<JAbscissa_t, JMultiMap<JAbscissa_t, JOrdinate_t, JTail_t, JDistance_t>, JDistance_t>, + public JMath< JMultiMap<JAbscissa_t, JOrdinate_t, JMapList<JHead_t, JTail_t>, JDistance_t> > + { + public: + + enum { NUMBER_OF_DIMENSIONS = JMapLength< JMapList<JHead_t, JTail_t> >::value }; + + typedef JHead_t<JAbscissa_t, + JMultiMap<JAbscissa_t, JOrdinate_t, JTail_t, JDistance_t>, + JDistance_t> map_type; + + typedef JAbscissa_t abscissa_type; + typedef JOrdinate_t ordinate_type; + + typedef typename map_type::key_type key_type; + typedef typename map_type::mapped_type mapped_type; + typedef typename map_type::value_type value_type; + + typedef typename map_type::const_iterator const_iterator; + typedef typename map_type::const_reverse_iterator const_reverse_iterator; + typedef typename map_type::iterator iterator; + typedef typename map_type::reverse_iterator reverse_iterator; + + using map_type::insert; + using map_type::configure; + using map_type::get; + + + /** + * Default constructor. + */ + JMultiMap() + {} + + + /** + * Add map. + * + * \param map multimap + * \return this multimap + */ + JMultiMap& add(const JMultiMap& map) + { + static_cast<map_type&>(*this).add(static_cast<const map_type&>(map)); + + return *this; + } + + + /** + * Subtract map. + * + * \param map multimap + * \return this multimap + */ + JMultiMap& sub(const JMultiMap& map) + { + static_cast<map_type&>(*this).sub(static_cast<const map_type&>(map)); + + return *this; + } + + + /** + * Scale contents. + * + * \param value multiplication factor + * \return this multimap + */ + JMultiMap& mul(const double value) + { + static_cast<map_type&>(*this).mul(value); + + return *this; + } + + /** + * Scale contents. + * + * \param value division factor + * \return this multimap + */ + JMultiMap& div(const double value) + { + static_cast<map_type&>(*this).div(value); + + return *this; + } + + + /** + * Function application to each element of this multimap. + * + * \param function function + * \return function + */ + template<class JFunction_t> + void for_each(const JFunction_t& function) + { + function(*this); + + for (iterator i = this->begin(); i != this->end(); ++i) { + i->getY().for_each(function); + } + } + + + /** + * Configure multidimensional map. + * + * \param bounds multidimensional bounds + */ + void configure(const JAbstractMultiMap<NUMBER_OF_DIMENSIONS, abscissa_type>& bounds) + { + this->configure(JMultiKey<0, abscissa_type>(), bounds); + } + + + /** + * Configure multidimensional map. + * + * \param key multidimensional key + * \param bounds multidimensional bounds + */ + template<unsigned int N, unsigned int M> + void configure(const JMultiKey<M, abscissa_type>& key, const JAbstractMultiMap<N, abscissa_type>& bounds) + { + this->configure(bounds(key)); + + for (iterator i = this->begin(); i != this->end(); ++i) { + i->getY().configure(JMultiKey<M+1, abscissa_type>(key,i->getX()), bounds); + } + } + + + class super_const_iterator; // forward declaration + + + /** + * Multidimensional iterator. + */ + class super_iterator : + public JEquals <super_iterator>, + public JForwardIterator<super_iterator> + { + + friend class JMultiMap; + friend class super_const_iterator; + + public: + + typedef int difference_type; + typedef JPair<const key_type&, typename mapped_type::super_iterator&> value_type; + typedef JLANG::JSinglePointer<value_type> pointer; + typedef JMultiPair<NUMBER_OF_DIMENSIONS, const JAbscissa_t, JOrdinate_t&> reference; + typedef std::forward_iterator_tag iterator_category; + typedef JMultiKey <NUMBER_OF_DIMENSIONS, const JAbscissa_t> multikey_type; + + /** + * Default constructor. + */ + super_iterator() + {} + + + /** + * Smart pointer operator. + * + * \return pointer to pair of iterators + */ + pointer operator->() + { + return pointer(new value_type(i->getX(), second)); + } + + + /** + * Dereference operator. + * + * \return multidimensional pair + */ + reference operator*() + { + return reference(i->getX(), *second); + } + + + /** + * Equality of super iterator. + * + * \param cursor super iterator + * \return true if equal; else false + */ + virtual bool equals(const super_iterator& cursor) const + { + return i == cursor.i && (i == range.second || second.equals(cursor.second)); + } + + + /** + * Increment super_iterator. + * + * \return true if valid; else false + */ + virtual bool increment() override + { + if (!second.increment()) { + + while (++i != range.second) { + + second = i->getY().super_begin(); + + if (second != i->getY().super_end()) { + break; + } + } + } + + return i != range.second; + } + + + /** + * Get multi-dimensional key. + * + * \return key + */ + multikey_type getKey() const + { + return multikey_type(i->getX(), second.getKey()); + } + + + /** + * Get value. + * + * \return value + */ + JOrdinate_t& getValue() + { + return second.getValue(); + } + + + private: + /** + * Constructor. + * + * \param __begin begin of data + * \param __end end of data + */ + super_iterator(iterator __begin, + iterator __end) : + range(__begin, __end) + { + for (i = range.first; i != range.second; ++i) { + + second = i->getY().super_begin(); + + if (second != i->getY().super_end()) { + break; + } + } + } + + + std::pair<iterator, iterator> range; + iterator i; + typename mapped_type::super_iterator second; + }; + + + /** + * Multidimensional const_iterator. + */ + class super_const_iterator : + public JEquals <super_const_iterator>, + public JForwardIterator<super_const_iterator> + { + + friend class JMultiMap; + + public: + + typedef int difference_type; + typedef JPair<const key_type&, typename mapped_type::super_const_iterator&> value_type; + typedef JLANG::JSinglePointer<value_type> pointer; + typedef JMultiPair<NUMBER_OF_DIMENSIONS, const JAbscissa_t, const JOrdinate_t&> reference; + typedef std::forward_iterator_tag iterator_category; + typedef JMultiKey <NUMBER_OF_DIMENSIONS, const JAbscissa_t> multikey_type; + + + /** + * Default constructor. + */ + super_const_iterator() + {} + + + /** + * Copy constructor. + * + * \param cursor super_iterator + */ + super_const_iterator(super_iterator cursor) : + range (cursor.range), + i (cursor.i), + second(cursor.second) + {} + + + /** + * Smart pointer operator. + * + * \return pointer to pair of iterators + */ + pointer operator->() + { + return pointer(new value_type(i->getX(), second)); + } + + + /** + * Dereference operator. + * + * \return multidimensional pair + */ + reference operator*() + { + return reference(i->getX(), *second); + } + + + /** + * Equality of super iterator. + * + * \param cursor super iterator + * \return true if equal; else false + */ + virtual bool equals(const super_const_iterator& cursor) const + { + return i == cursor.i && (i == range.second || second.equals(cursor.second)); + } + + + /** + * Increment super_iterator. + * + * \return true if valid; else false + */ + virtual bool increment() override + { + if (!second.increment()) { + + while (++i != range.second) { + + second = i->getY().super_begin(); + + if (second != i->getY().super_end()) { + break; + } + } + } + + return i != range.second; + } + + + /** + * Get multi-dimensional key. + * + * \return key + */ + multikey_type getKey() const + { + return multikey_type(i->getX(), second.getKey()); + } + + + /** + * Get value. + * + * \return value + */ + const JOrdinate_t& getValue() + { + return second.getValue(); + } + + + private: + /** + * Constructor. + * + * \param __begin begin of data + * \param __end end of data + */ + super_const_iterator(const_iterator __begin, + const_iterator __end) : + range(__begin, __end) + { + for (i = range.first; i != range.second; ++i) { + + second = i->getY().super_begin(); + + if (second != i->getY().super_end()) { + break; + } + } + } + + + std::pair<const_iterator, const_iterator> range; + const_iterator i; + typename mapped_type::super_const_iterator second; + }; + + + class super_const_reverse_iterator; // forward declaration + + + /** + * Multidimensional reverse iterator. + */ + class super_reverse_iterator : + public JEquals <super_reverse_iterator>, + public JForwardIterator<super_reverse_iterator> + { + + friend class JMultiMap; + friend class super_const_reverse_iterator; + + public: + + typedef int difference_type; + typedef JPair<const key_type&, typename mapped_type::super_reverse_iterator&> value_type; + typedef JLANG::JSinglePointer<value_type> pointer; + typedef JMultiPair<NUMBER_OF_DIMENSIONS, const JAbscissa_t, JOrdinate_t&> reference; + typedef std::forward_iterator_tag iterator_category; + typedef JMultiKey <NUMBER_OF_DIMENSIONS, const JAbscissa_t> multikey_type; + + + /** + * Default constructor. + */ + super_reverse_iterator() + {} + + + /** + * Smart pointer operator. + * + * \return pointer to pair of iterators + */ + pointer operator->() + { + return pointer(new value_type(i->getX(), second)); + } + + + /** + * Dereference operator. + * + * \return multidimensional pair + */ + reference operator*() + { + return reference(i->getX(), *second); + } + + + /** + * Equality of super reverse iterator. + * + * \param cursor super reverse iterator + * \return true if equal; else false + */ + virtual bool equals(const super_reverse_iterator& cursor) const + { + return i == cursor.i && (i == range.second || second.equals(cursor.second)); + } + + + /** + * Increment super_iterator. + * + * \return true if valid; else false + */ + virtual bool increment() override + { + if (!second.increment()) { + + while (++i != range.second) { + + second = i->getY().super_rbegin(); + + if (!second.equals(i->getY().super_rend())) { + break; + } + } + } + + return i != range.second; + } + + + /** + * Get multi-dimensional key. + * + * \return key + */ + multikey_type getKey() const + { + return multikey_type(i->getX(), second.getKey()); + } + + + /** + * Get value. + * + * \return value + */ + JOrdinate_t& getValue() + { + return second.getValue(); + } + + + private: + /** + * Constructor. + * + * \param __begin reverse begin of data + * \param __end reverse end of data + */ + super_reverse_iterator(reverse_iterator __begin, + reverse_iterator __end) : + range(__begin, __end) + { + for (i = range.first; i != range.second; ++i) { + + second = i->getY().super_rbegin(); + + if (!second.equals(i->getY().super_rend())) { + break; + } + } + } + + + std::pair<reverse_iterator, reverse_iterator> range; + reverse_iterator i; + typename mapped_type::super_reverse_iterator second; + }; + + + /** + * Multidimensional const_reverse_iterator. + */ + class super_const_reverse_iterator : + public JEquals <super_const_reverse_iterator>, + public JForwardIterator<super_const_reverse_iterator> + { + + friend class JMultiMap; + + public: + + typedef int difference_type; + typedef JPair<const key_type&, typename mapped_type::super_const_reverse_iterator&> value_type; + typedef JLANG::JSinglePointer<value_type> pointer; + typedef JMultiPair<NUMBER_OF_DIMENSIONS, const JAbscissa_t, const JOrdinate_t&> reference; + typedef std::forward_iterator_tag iterator_category; + typedef JMultiKey <NUMBER_OF_DIMENSIONS, const JAbscissa_t> multikey_type; + + + /** + * Default constructor. + */ + super_const_reverse_iterator() + {} + + + /** + * Copy constructor. + * + * \param cursor super_iterator + */ + super_const_reverse_iterator(super_reverse_iterator cursor) : + range (cursor.range), + i (cursor.i), + second(cursor.second) + {} + + + /** + * Smart pointer operator. + * + * \return pointer to pair of iterators + */ + pointer operator->() + { + return pointer(new value_type(i->getX(), second)); + } + + + /** + * Dereference operator. + * + * \return multidimensional pair + */ + reference operator*() + { + return reference(i->getX(), *second); + } + + + /** + * Equality of super reverse iterator. + * + * \param cursor super reverse iterator + * \return true if equal; else false + */ + virtual bool equals(const super_const_reverse_iterator& cursor) const + { + return i == cursor.i && (i == range.second || second.equals(cursor.second)); + } + + + /** + * Increment super_iterator. + * + * \return true if valid; else false + */ + virtual bool increment() override + { + if (!second.increment()) { + + while (++i != range.second) { + + second = i->getY().super_rbegin(); + + if (second != i->getY().super_rend()) { + break; + } + } + } + + return i != range.second; + } + + + /** + * Get multi-dimensional key. + * + * \return key + */ + multikey_type getKey() const + { + return multikey_type(i->getX(), second.getKey()); + } + + + /** + * Get value. + * + * \return value + */ + const JOrdinate_t& getValue() + { + return second.getValue(); + } + + + private: + /** + * Constructor. + * + * \param __begin begin of data + * \param __end end of data + */ + super_const_reverse_iterator(const_reverse_iterator __begin, + const_reverse_iterator __end) : + range(__begin, __end) + { + for (i = range.first; i != range.second; ++i) { + + second = i->getY().super_rbegin(); + + if (second != i->getY().super_rend()) { + break; + } + } + } + + + std::pair<const_reverse_iterator, const_reverse_iterator> range; + const_reverse_iterator i; + typename mapped_type::super_const_reverse_iterator second; + }; + + + /** + * Get super_iterator to begin of data. + * + * \return super iterator + */ + super_const_iterator super_begin() const + { + return super_const_iterator(this->begin(), this->end()); + } + + + /** + * Get super_reverse_iterator to reverse begin of data + * + * \return super reverse iterator + */ + super_const_reverse_iterator super_rbegin() const + { + return super_const_reverse_iterator(this->rbegin(), this->rend()); + } + + + /** + * Get super_iterator to end of data. + * + * \return super iterator + */ + super_const_iterator super_end() const + { + return super_const_iterator(this->end(), this->end()); + } + + + /** + * Get super_reverse_iterator to end of data. + * + * \return super reverse iterator + */ + super_const_reverse_iterator super_rend() const + { + return super_const_reverse_iterator(this->rend(), this->rend()); + } + + + /** + * Get super_iterator to begin of data. + * + * \return super iterator + */ + super_iterator super_begin() + { + return super_iterator(this->begin(), this->end()); + } + + + /** + * Get super_reverse_iterator to begin of data. + * + * \return super iterator + */ + super_reverse_iterator super_rbegin() + { + return super_reverse_iterator(this->rbegin(), this->rend()); + } + + + /** + * Get super_iterator to end of data. + * + * \return super iterator + */ + super_iterator super_end() + { + return super_iterator(this->end(), this->end()); + } + + + /** + * Get super_reverse_iterator to end of data. + * + * \return super iterator + */ + super_reverse_iterator super_rend() + { + return super_reverse_iterator(this->rend(), this->rend()); + } + + + /** + * Get value. + * + * \param key multidimensional key + * \return value + */ + ordinate_type& get(const JMultiKey<NUMBER_OF_DIMENSIONS, abscissa_type>& key) + { + return this->get(key.first).get(key.second); + } + + + /** + * Insert element. + * + * \param key multidimensional key + * \param value value + */ + void insert(const JMultiKey<NUMBER_OF_DIMENSIONS, abscissa_type>& key, const ordinate_type& value) + { + (*this)[key.first].insert(key.second, value); + } + + + /** + * Insert element. + * + * \param value multidimensional pair + */ + void insert(const JMultiPair<NUMBER_OF_DIMENSIONS, abscissa_type, ordinate_type>& value) + { + (*this)[value.first].insert(value.second); + } + + + /** + * Insert element. + * + * \param value multidimensional iterator value + */ + void insert(const typename super_iterator::reference& value) + { + (*this)[value.first].insert(value.second); + } + + + /** + * Insert element. + * + * \param value multidimensional iterator value + */ + void insert(const typename super_const_iterator::reference& value) + { + (*this)[value.first].insert(value.second); + } + }; + + + /** + * Terminator class of recursive JMultiMap class. + */ + template<class JAbscissa_t, + class JOrdinate_t, + template<class, class, class> class JHead_t, + class JDistance_t> + class JMultiMap<JAbscissa_t, JOrdinate_t, JMapList<JHead_t, JLANG::JNullType>, JDistance_t> : + public JHead_t<JAbscissa_t, JOrdinate_t, JDistance_t>, + public JMath< JMultiMap<JAbscissa_t, JOrdinate_t, JMapList<JHead_t, JLANG::JNullType>, JDistance_t> > + { + public: + + enum { NUMBER_OF_DIMENSIONS = 1 }; + + typedef JHead_t<JAbscissa_t, JOrdinate_t, JDistance_t> map_type; + + typedef JAbscissa_t abscissa_type; + typedef JOrdinate_t ordinate_type; + + typedef typename map_type::key_type key_type; + typedef typename map_type::mapped_type mapped_type; + typedef typename map_type::value_type value_type; + + typedef typename map_type::const_iterator const_iterator; + typedef typename map_type::const_reverse_iterator const_reverse_iterator; + + typedef typename map_type::iterator iterator; + typedef typename map_type::reverse_iterator reverse_iterator; + + using map_type::insert; + using map_type::configure; + using map_type::get; + + + /** + * Default constructor. + */ + JMultiMap() + {} + + + /** + * Add map. + * + * \param map multimap + * \return this multimap + */ + JMultiMap& add(const JMultiMap& map) + { + static_cast<map_type&>(*this).add(static_cast<const map_type&>(map)); + + return *this; + } + + + /** + * Subtract map. + * + * \param map multimap + * \return this multimap + */ + JMultiMap& sub(const JMultiMap& map) + { + static_cast<map_type&>(*this).sub(static_cast<const map_type&>(map)); + + return *this; + } + + + /** + * Scale contents. + * + * \param value multiplication factor + * \return this multimap + */ + JMultiMap& mul(const double value) + { + static_cast<map_type&>(*this).mul(value); + + return *this; + } + + /** + * Scale contents. + * + * \param value division factor + * \return this multimap + */ + JMultiMap& div(const double value) + { + static_cast<map_type&>(*this).div(value); + + return *this; + } + + + /** + * Termination of function application. + * + * \param function function + * \return function + */ + template<class JFunction_t> + void for_each(const JFunction_t& function) + { + function(*this); + } + + + /** + * Configure multidimensional map. + * + * \param bounds multidimensional bounds + */ + void configure(const JAbstractMultiMap<NUMBER_OF_DIMENSIONS, abscissa_type>& bounds) + { + this->configure(JMultiKey<0, abscissa_type>(), bounds); + } + + + /** + * Configure multidimensional map. + * + * \param key multidimensional key + * \param bounds multidimensional bounds + */ + template<unsigned int N, unsigned int M> + void configure(const JMultiKey<M, abscissa_type>& key, const JAbstractMultiMap<N, abscissa_type>& bounds) + { + this->configure(bounds(key)); + } + + + class super_const_iterator; // forward declaration + + + /** + * Terminator class of multidimensional iterator. + */ + class super_iterator : + public JEquals <super_iterator>, + public JForwardIterator<super_iterator> + { + + friend class JMultiMap; + friend class super_const_iterator; + + public: + + typedef size_t difference_type; + typedef JPair<const key_type&, mapped_type&> value_type; + typedef JLANG::JSinglePointer<value_type> pointer; + typedef JMultiPair<1, const JAbscissa_t, JOrdinate_t&> reference; + typedef std::forward_iterator_tag iterator_category; + typedef JMultiKey <1, const JAbscissa_t> multikey_type; + + + /** + * Default constructor. + */ + super_iterator() + {} + + + /** + * Smart pointer operator. + * + * \return pointer to pair of iterators + */ + pointer operator->() + { + return pointer(new value_type(i->getX(), i->getY())); + } + + + /** + * Dereference operator. + * + * \return multidimensional pair + */ + reference operator*() + { + return reference(i->getX(), i->getY()); + } + + + /** + * Equality of super iterator. + * + * \param cursor super iterator + * \return true if equal; else false + */ + virtual bool equals(const super_iterator& cursor) const + { + return i == cursor.i; + } + + + /** + * Increment super_iterator. + * + * \return true if valid; else false + */ + virtual bool increment() override + { + return ++i != range.second; + } + + + /** + * Get multi-dimensional key. + * + * \return key + */ + multikey_type getKey() const + { + return multikey_type(i->getX()); + } + + + /** + * Get value. + * + * \return value + */ + JOrdinate_t& getValue() + { + return i->getY(); + } + + private: + /** + * Constructor. + * + * \param __begin begin of data + * \param __end end of data + */ + super_iterator(iterator __begin, + iterator __end) : + range(__begin, __end), + i (__begin) + {} + + + std::pair<iterator, iterator> range; + iterator i; + }; + + + /** + * Terminator class of multidimensional const_iterator. + */ + class super_const_iterator : + public JEquals <super_const_iterator>, + public JForwardIterator<super_const_iterator> + { + + friend class JMultiMap; + + public: + + typedef size_t difference_type; + typedef JPair<const key_type&, const mapped_type&> value_type; + typedef JLANG::JSinglePointer<value_type> pointer; + typedef JMultiPair<1, const JAbscissa_t, const JOrdinate_t&> reference; + typedef std::forward_iterator_tag iterator_category; + typedef JMultiKey <1, const JAbscissa_t> multikey_type; + + + /** + * Default constructor. + */ + super_const_iterator() + {} + + + /** + * Copy constructor. + * + * \param cursor super_iterator + */ + super_const_iterator(super_iterator cursor) : + range(cursor.range), + i (cursor.i) + {} + + + /** + * Smart pointer operator. + * + * \return pointer to pair of iterators + */ + pointer operator->() + { + return pointer(new value_type(i->getX(), i->getY())); + } + + + /** + * Dereference operator. + * + * \return multidimensional pair + */ + reference operator*() + { + return reference(i->getX(), i->getY()); + } + + + /** + * Equality of super iterator. + * + * \param cursor super iterator + * \return true if equal; else false + */ + virtual bool equals(const super_const_iterator& cursor) const + { + return i == cursor.i; + } + + + /** + * Increment super_iterator. + * + * \return true if valid; else false + */ + virtual bool increment() override + { + return ++i != range.second; + } + + + /** + * Get multi-dimensional key. + * + * \return key + */ + multikey_type getKey() const + { + return multikey_type(i->getX()); + } + + + /** + * Get value. + * + * \return value + */ + const JOrdinate_t& getValue() + { + return i->getY(); + } + + private: + /** + * Constructor. + * + * \param __begin begin of data + * \param __end end of data + */ + super_const_iterator(const_iterator __begin, + const_iterator __end) : + range(__begin, __end), + i (__begin) + {} + + + std::pair<const_iterator, const_iterator> range; + const_iterator i; + }; + + + class super_const_reverse_iterator; // forward declaration + + + /** + * Terminator class of multidimensional reverse iterator. + */ + class super_reverse_iterator : + public JEquals <super_iterator>, + public JForwardIterator<super_iterator> + { + + friend class JMultiMap; + friend class super_const_reverse_iterator; + + public: + + typedef size_t difference_type; + typedef JPair<const key_type&, mapped_type&> value_type; + typedef JLANG::JSinglePointer<value_type> pointer; + typedef JMultiPair<1, const JAbscissa_t, JOrdinate_t&> reference; + typedef std::forward_iterator_tag iterator_category; + typedef JMultiKey <1, const JAbscissa_t> multikey_type; + + + /** + * Default constructor. + */ + super_reverse_iterator() + {} + + + /** + * Smart pointer operator. + * + * \return pointer to pair of reverse iterators + */ + pointer operator->() + { + return pointer(new value_type(i->getX(), i->getY())); + } + + + /** + * Dereference operator. + * + * \return multidimensional pair + */ + reference operator*() + { + return reference(i->getX(), i->getY()); + } + + + /** + * Equality of super reverse iterator. + * + * \param cursor super reverse iterator + * \return true if equal; else false + */ + virtual bool equals(const super_reverse_iterator& cursor) const + { + return i == cursor.i; + } + + + /** + * Increment super_reverse_iterator. + * + * \return true if valid; else false + */ + virtual bool increment() override + { + return ++i != range.second; + } + + + /** + * Get multi-dimensional key. + * + * \return key + */ + multikey_type getKey() const + { + return multikey_type(i->getX()); + } + + + /** + * Get value. + * + * \return value + */ + JOrdinate_t& getValue() + { + return i->getY(); + } + + private: + /** + * Constructor. + * + * \param __begin begin of data + * \param __end end of data + */ + super_reverse_iterator(reverse_iterator __begin, + reverse_iterator __end) : + range(__begin, __end), + i (__begin) + {} + + + std::pair<reverse_iterator, reverse_iterator> range; + reverse_iterator i; + }; + + + /** + * Terminator class of multidimensional const_iterator. + */ + class super_const_reverse_iterator : + public JEquals <super_const_reverse_iterator>, + public JForwardIterator<super_const_reverse_iterator> + { + + friend class JMultiMap; + + public: + + typedef size_t difference_type; + typedef JPair<const key_type&, const mapped_type&> value_type; + typedef JLANG::JSinglePointer<value_type> pointer; + typedef JMultiPair<1, const JAbscissa_t, const JOrdinate_t&> reference; + typedef std::forward_iterator_tag iterator_category; + typedef JMultiKey <1, const JAbscissa_t> multikey_type; + + + /** + * Default constructor. + */ + super_const_reverse_iterator() + {} + + + /** + * Copy constructor. + * + * \param cursor super_iterator + */ + super_const_reverse_iterator(super_reverse_iterator cursor) : + range(cursor.range), + i (cursor.i) + {} + + + /** + * Smart pointer operator. + * + * \return pointer to pair of iterators + */ + pointer operator->() + { + return pointer(new value_type(i->getX(), i->getY())); + } + + + /** + * Dereference operator. + * + * \return multidimensional pair + */ + reference operator*() + { + return reference(i->getX(), i->getY()); + } + + + /** + * Equality of super reverse iterator. + * + * \param cursor super reverse iterator + * \return true if equal; else false + */ + virtual bool equals(const super_const_reverse_iterator& cursor) const + { + return i == cursor.i; + } + + + /** + * Increment super_iterator. + * + * \return true if valid; else false + */ + virtual bool increment() override + { + return ++i != range.second; + } + + + /** + * Get multi-dimensional key. + * + * \return key + */ + multikey_type getKey() const + { + return multikey_type(i->getX()); + } + + + /** + * Get value. + * + * \return value + */ + const JOrdinate_t& getValue() + { + return i->getY(); + } + + private: + /** + * Constructor. + * + * \param __begin begin of data + * \param __end end of data + */ + super_const_reverse_iterator(const_reverse_iterator __begin, + const_reverse_iterator __end) : + range(__begin, __end), + i (__begin) + {} + + + std::pair<const_reverse_iterator, const_reverse_iterator> range; + const_reverse_iterator i; + }; + + + /** + * Get super_iterator to begin of data. + * + * \return super_iterator + */ + super_const_iterator super_begin() const + { + return super_const_iterator(this->begin(), this->end()); + } + + + /** + * Get super_reverse_iterator to reverse begin of data. + * + * \return super_reverse_iterator + */ + super_const_reverse_iterator super_rbegin() const + { + return super_const_reverse_iterator(this->rbegin(), this->rend()); + } + + + /** + * Get super_iterator to end of data. + * + * \return super_iterator + */ + super_const_iterator super_end() const + { + return super_const_iterator(this->end(), this->end()); + } + + + /** + * Get super_reverse_iterator to reverse end of data. + * + * \return super_reverse_iterator + */ + super_const_reverse_iterator super_rend() const + { + return super_const_reverse_iterator(this->rend(), this->rend()); + } + + + /** + * Get super_iterator to begin of data. + * + * \return super_iterator + */ + super_iterator super_begin() + { + return super_iterator(this->begin(), this->end()); + } + + + /** + * Get super_reverse_iterator to reverse begin of data. + * + * \return super_reverse_iterator + */ + super_reverse_iterator super_rbegin() + { + return super_reverse_iterator(this->rbegin(), this->rend()); + } + + + /** + * Get super_iterator to end of data. + * + * \return super_iterator + */ + super_iterator super_end() + { + return super_iterator(this->end(), this->end()); + } + + + /** + * Get super_reverse_iterator to end of data. + * + * \return super_reverse_iterator + */ + super_reverse_iterator super_rend() + { + return super_reverse_iterator(this->rend(), this->rend()); + } + + + /** + * Get value. + * + * \param key multidimensional key + * \return value + */ + ordinate_type& get(const JMultiKey<1, abscissa_type>& key) + { + return get(key.first); + } + + + /** + * Insert element. + * + * \param key multidimensional key + * \param value value + */ + void insert(const JMultiKey<1, JAbscissa_t>& key, const JOrdinate_t& value) + { + insert(value_type(key.first, value)); + } + + + /** + * Insert element. + * + * \param value multidimensional pair + */ + void insert(const JMultiPair<1, JAbscissa_t, JOrdinate_t>& value) + { + insert(value_type(value.first, value.second)); + } + + + /** + * Insert element. + * + * \param value multidimensional iterator value + */ + void insert(const typename super_iterator::reference& value) + { + insert(value_type(value.first, value.second)); + } + + + /** + * Insert element. + * + * \param value multidimensional iterator value + */ + void insert(const typename super_const_iterator::reference& value) + { + insert(value_type(value.first, value.second)); + } + }; +} + +#endif diff --git a/jpp/JTools/JMultiMapTransformer.hh b/jpp/JTools/JMultiMapTransformer.hh new file mode 100644 index 0000000..50dc1e1 --- /dev/null +++ b/jpp/JTools/JMultiMapTransformer.hh @@ -0,0 +1,341 @@ +#ifndef __JTOOLS__JMULTIMAPTRANSFORMER__ +#define __JTOOLS__JMULTIMAPTRANSFORMER__ + +#include "JLang/JClonable.hh" +#include "JIO/JSerialisable.hh" +#include "JTools/JArray.hh" +#include "JTools/JTransformer.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JLANG::JClonable; + using JIO::JSerialisable; + using JIO::JReader; + using JIO::JWriter; + + + /** + * Interface for weight application and coordinate transformation of function. + * + * The template parameters refer to the dimension of the map and the data type of the argument, respectively. + * + * This class extends the JClonable and JSerialisable interfacea. + */ + template<unsigned int N, class JArgument_t> + class JMultiMapTransformer : + public JClonable< JMultiMapTransformer<N, JArgument_t> >, + public JSerialisable + { + public: + + typedef JMultiMapTransformer<N, JArgument_t> multimaptransformer_type; + + typedef typename JClonable<multimaptransformer_type>::clone_type clone_type; + typedef JArgument_t argument_type; + typedef JArray<N, argument_type> array_type; + typedef const JArray<N, const argument_type> const_array_type; + + + /** + * Evaluate xn value as a function of {x0, ..., xn-1} + * + * \param buffer x0 - xn-1 values + * \param xn xn value + * \return xn value + */ + virtual argument_type putXn(const_array_type& buffer, const argument_type xn) const = 0; + + + /** + * Evaluate xn value as a function of {x0, ..., xn-1} + * + * \param buffer x0 - xn-1 values + * \param xn xn value + * \return xn value + */ + virtual argument_type getXn(const_array_type& buffer, const argument_type xn) const = 0; + + + /** + * Weight function. + * + * \param buffer x0 - xn-1 values + * \return weight + */ + virtual double getWeight(const_array_type& buffer) const = 0; + + + /** + * Weight function. + * + * \param x first abscissa values + * \param args comma seperated list of remaining abscissa values + * \return weight + */ + template<class ...Args> + double getWeight(const argument_type x, const Args& ...args) const + { + return getWeight(array_type(x, args...)); + } + + + /** + * Default implementation of weight application and coordinate transformation of function. + */ + class JMultiMapDefaultTransformer; + + + /** + * Get default transformer. + * + * \return default transformer + */ + static const JMultiMapTransformer& getDefaultTransformer() + { + static const JMultiMapDefaultTransformer transformer; + + return transformer; + } + + + /** + * Get clone of default transformer. + * + * \return pointer to newly created transformer + */ + static JMultiMapTransformer* getClone() + { + return new JMultiMapDefaultTransformer(); + } + }; + + + /** + * Default implementation of weight application and coordinate transformation of function. + * + * The coordiniate transformation has no effect and the weight is equal to one. + * + * This class implements the JMultiMapTransformer, JClonable and JSerialisable interfaces. + */ + template<unsigned int N, class JArgument_t> + class JMultiMapTransformer<N, JArgument_t>::JMultiMapDefaultTransformer : + public JMultiMapTransformer<N, JArgument_t> + { + public: + + /** + * Default constructor. + */ + JMultiMapDefaultTransformer() + {} + + + /** + * Clone object. + * + * \return pointer to newly created transformer + */ + virtual clone_type clone() const override + { + return new JMultiMapDefaultTransformer(*this); + } + + + /** + * Evaluate xn value as a function of {x0, ..., xn-1} + * + * \param buffer x0 - xn-1 values + * \param xn xn value + * \return xn value + */ + virtual argument_type putXn(const_array_type& buffer, const argument_type xn) const override + { + return xn; + } + + + /** + * Evaluate xn value as a function of {x0, ..., xn-1} + * + * \param buffer x0 - xn-1 values + * \param xn xn value + * \return xn value + */ + virtual argument_type getXn(const_array_type& buffer, const argument_type xn) const override + { + return xn; + } + + + /** + * Weight function. + * + * \param buffer x0 - xn-1 values + * \return weight + */ + virtual double getWeight(const_array_type& buffer) const override + { + return 1.0; + } + + + /** + * Read from input. + * + * This method reads nothing. + * + * \param in reader + * \return reader + */ + virtual JReader& read(JReader& in) override + { + return in; + } + + + /** + * Write to output. + * + * This method writes nothing. + * + * \param out writer + * \return writer + */ + virtual JWriter& write(JWriter& out) const override + { + return out; + } + }; + + + /** + * Auxiliary class to convert JMultiMapTransformer to JCollectionElementTransformer. + * + * This class implements the JCollectionElementTransformer interface. + */ + template<unsigned int N, class JElement_t> + class JMultiMapPutTransformer : + public JCollectionElementTransformer<JElement_t> + { + public: + + typedef typename JElement_t::abscissa_type abscissa_type; + typedef typename JElement_t::ordinate_type ordinate_type; + + typedef JMultiMapTransformer<N, abscissa_type> transformer_type; + + typedef typename transformer_type::const_array_type const_array_type; + + + /** + * Constructor. + * + * \param __transformer multidimensional map transformer + * \param __buffer x0 - xn-1 values + */ + JMultiMapPutTransformer(const transformer_type& __transformer, + const_array_type& __buffer) : + transformer(__transformer), + buffer (__buffer), + W(transformer.getWeight(buffer)) + {} + + + /** + * Transform element. + * + * \param element input element + * \return output element + */ + virtual JElement_t operator()(const JElement_t& element) const override + { + return JElement_t(transformer.putXn(buffer, element.getX()), element.getY() / W); + } + + private: + const transformer_type& transformer; + const_array_type buffer; + const double W; + }; + + + /** + * Auxiliary class to convert JMultiMapTransformer to JCollectionElementTransformer. + * + * This class implements the JCollectionElementTransformer interface. + */ + template<unsigned int N, class JElement_t> + class JMultiMapGetTransformer : + public JCollectionElementTransformer<JElement_t> + { + public: + + typedef typename JElement_t::abscissa_type abscissa_type; + typedef typename JElement_t::ordinate_type ordinate_type; + + typedef JMultiMapTransformer<N, abscissa_type> transformer_type; + + typedef typename transformer_type::const_array_type const_array_type; + + + /** + * Constructor. + * + * \param __transformer multidimensional map transformer + * \param __buffer x0 - xn-1 values + */ + JMultiMapGetTransformer(const transformer_type& __transformer, + const_array_type& __buffer) : + transformer(__transformer), + buffer (__buffer), + W(transformer.getWeight(buffer)) + {} + + + /** + * Transform element. + * + * \param element input element + * \return output element + */ + virtual JElement_t operator()(const JElement_t& element) const override + { + return JElement_t(transformer.getXn(buffer, element.getX()), element.getY() * W); + } + + private: + const transformer_type& transformer; + const_array_type buffer; + const double W; + }; + + + /** + * Abstract interface for transformable multidimensional map. + * + * The template parameters refer to the dimension of the map and the data type of the argument, respectively. + */ + template<unsigned int N, class JArgument_t> + struct JTransformable + { + typedef JArgument_t argument_type; + typedef JMultiMapTransformer<N, argument_type> transformer_type; + + /** + * Application of transformation. + * + * \param transformer function transformer + */ + virtual void transform(const transformer_type& transformer) = 0; + }; +} + +#endif diff --git a/jpp/JTools/JMultiPair.hh b/jpp/JTools/JMultiPair.hh new file mode 100644 index 0000000..87bf9bb --- /dev/null +++ b/jpp/JTools/JMultiPair.hh @@ -0,0 +1,328 @@ +#ifndef __JTOOLS__JMULTIPAIR__ +#define __JTOOLS__JMULTIPAIR__ + +#include "JTools/JMultiKey.hh" +#include "JLang/JClass.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + /** + * Multidimensional pair. + * + * This class reproduces the element of a multidimensional map. + * The individual data members can be accessed as: + * <pre> + * JMultiPair<3, key_type, mapped_type> pair; + * + * pair[[.second].second].first; + * pair[[.second].second].second; + * </pre> + */ + template<unsigned int N, class JKey_t, class JValue_t> + class JMultiPair + { + public: + + typedef JKey_t key_type; + typedef JValue_t value_type; + typedef JMultiPair<N-1, key_type, value_type> mapped_type; + typedef typename JLANG::JClass<value_type>::reference_type reference_type; + typedef JMultiKey<N, key_type> multikey_type; + + + /** + * Default constructor. + */ + JMultiPair() : + first (), + second() + {} + + + /** + * Constructor. + * The primary key is inserted at the start of the secondary keys. + * + * \param __first primary key + * \param __second secondary keys and value + */ + JMultiPair(typename JClass<key_type> ::argument_type __first, + typename JClass<mapped_type>::argument_type __second) : + first (__first), + second(__second) + {} + + + /** + * Constructor. + * The secondary key is appended to the end of the primary keys. + * + * \param __first primary keys and value + * \param __second secondary key + */ + JMultiPair(typename JClass<mapped_type>::argument_type __first, + typename JClass<key_type> ::argument_type __second) : + first (__first.first), + second(mapped_type(__first.second, __second)) + {} + + + /** + * Constructor. + * + * \param key multidimensional key + * \param value value + */ + JMultiPair(typename JClass<multikey_type>::argument_type key, + typename JClass<value_type> ::argument_type value) : + first (key.first), + second(mapped_type(key.second, value)) + {} + + + /** + * Get multidimensional key. + * + * \return multidimensional key + */ + multikey_type getKey() const + { + return multikey_type(this->first, this->second.getKey()); + } + + + /** + * Get value. + * + * \return value + */ + reference_type getValue() + { + return this->second.getValue(); + } + + + /** + * Get value. + * + * \return value + */ + const reference_type getValue() const + { + return this->second.getValue(); + } + + + key_type first; + mapped_type second; + }; + + + /** + * Two-dimensional pair. + */ + template<class JKey_t, class JValue_t> + class JMultiPair<2, JKey_t, JValue_t> + { + public: + + typedef JKey_t key_type; + typedef JValue_t value_type; + typedef JMultiPair<1, key_type, value_type> mapped_type; + typedef typename JClass<value_type>::reference_type reference_type; + typedef JMultiKey<2, key_type> multikey_type; + + + /** + * Default constructor. + */ + JMultiPair() : + first (), + second() + {} + + + /** + * Constructor. + * The primary key is inserted at the start of the secondary key. + * + * \param __first primary key + * \param __second secondary key and value + */ + JMultiPair(typename JClass<key_type> ::argument_type __first, + typename JClass<mapped_type>::argument_type __second) : + first (__first), + second(__second) + {} + + + /** + * Constructor. + * The secondary key is appended to the end of the primary key. + * + * \param __first primary keys and value + * \param __second secondary key + */ + JMultiPair(typename JClass<mapped_type>::argument_type __first, + typename JClass<key_type> ::argument_type __second) : + first (__first.first), + second(mapped_type(__second, __first.second)) + {} + + + /** + * Constructor. + * + * \param key multidimensional key + * \param value value + */ + JMultiPair(typename JClass<multikey_type>::argument_type key, + typename JClass<value_type> ::argument_type value) : + first (key.first), + second(mapped_type(key.second, value)) + {} + + + /** + * Get multidimensional key. + * + * \return multidimensional key + */ + multikey_type getKey() const + { + return multikey_type(this->first, this->second.getKey()); + } + + + /** + * Get value. + * + * \return value + */ + reference_type getValue() + { + return this->second.getValue(); + } + + + /** + * Get value. + * + * \return value + */ + const reference_type getValue() const + { + return this->second.getValue(); + } + + + key_type first; + mapped_type second; + }; + + + /** + * One-dimensional pair. + */ + template<class JKey_t, class JValue_t> + class JMultiPair<1, JKey_t, JValue_t> + { + public: + + typedef JKey_t key_type; + typedef JValue_t value_type; + typedef JValue_t mapped_type; + typedef typename JClass<value_type>::reference_type reference_type; + typedef JMultiKey<1, key_type> multikey_type; + + + /** + * Default constructor. + */ + JMultiPair() : + first (), + second() + {} + + + /** + * Constructor. + * + * \param __first key + * \param __second value + */ + JMultiPair(typename JClass<key_type> ::argument_type __first, + typename JClass<value_type>::argument_type __second) : + first (__first), + second(__second) + {} + + + /** + * Constructor. + * + * \param key multidimensional key + * \param value value + */ + JMultiPair(typename JClass<multikey_type>::argument_type key, + typename JClass<value_type> ::argument_type value) : + first (key.first), + second(value) + {} + + + /** + * Get multidimensional key. + * + * \return multidimensional key + */ + multikey_type getKey() const + { + return JMultiKey<1, key_type>(this->first); + } + + + /** + * Get value. + * + * \return value + */ + reference_type getValue() + { + return this->second; + } + + + /** + * Get value. + * + * \return value + */ + const reference_type getValue() const + { + return this->second; + } + + + key_type first; + mapped_type second; + }; + + + /** + * Empty pair. + */ + template<class JKey_t, class JValue_t> + class JMultiPair<0, JKey_t, JValue_t> + {}; +} + +#endif diff --git a/jpp/JTools/JPair.hh b/jpp/JTools/JPair.hh new file mode 100644 index 0000000..af16632 --- /dev/null +++ b/jpp/JTools/JPair.hh @@ -0,0 +1,234 @@ +#ifndef __JTOOLS__JPAIR__ +#define __JTOOLS__JPAIR__ + +#include <istream> +#include <ostream> + +#include "JLang/JClass.hh" +#include "JIO/JSerialisable.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JIO::JReader; + using JIO::JWriter; + + + /** + * Template specialisation for a pair of values. + */ + template<class JKey_t, class JValue_t> + class JPair + { + public: + + typedef JKey_t key_type; + typedef JValue_t mapped_type; + + + /** + * Default constructor. + */ + JPair() : + first (), + second() + {} + + + /** + * Constructor. + * + * \param key JKey_t + * \param value JValue_t + */ + JPair(typename JLANG::JClass<key_type> ::argument_type key, + typename JLANG::JClass<mapped_type>::argument_type value) : + first (key), + second(value) + {} + + + /** + * Read pair from input. + * + * \param in input stream + * \param pair pair + * \return input stream + */ + friend inline std::istream& operator>>(std::istream& in, JPair<JKey_t, JValue_t>& pair) + { + in >> pair.first; + in >> pair.second; + + return in; + } + + + /** + * Write pair to output. + * + * \param out output stream + * \param pair pair + * \return output stream + */ + friend inline std::ostream& operator<<(std::ostream& out, const JPair<JKey_t, JValue_t>& pair) + { + out << pair.first; + out << ' '; + out << pair.second; + + return out; + } + + + /** + * Read pair from input. + * + * \param in reader + * \param pair pair + * \return reader + */ + friend inline JReader& operator>>(JReader& in, JPair<JKey_t, JValue_t>& pair) + { + in >> pair.first; + in >> pair.second; + + return in; + } + + + /** + * Write pair to output. + * + * \param out writer + * \param pair pair + * \return writer + */ + friend inline JWriter& operator<<(JWriter& out, const JPair<JKey_t, JValue_t>& pair) + { + out << pair.first; + out << pair.second; + + return out; + } + + + const key_type& getKey() const { return this->first; } + const mapped_type& getValue() const { return this->second; } + + mapped_type& getValue() { return this->second; } + + JKey_t first; + JValue_t second; + }; + + + /** + * Template specialisation for a pair of references. + */ + template<class JKey_t, class JValue_t> + class JPair<JKey_t&, JValue_t&> + { + public: + + typedef JKey_t key_type; + typedef JValue_t mapped_type; + + + /** + * Constructor. + * + * \param key JKey_t + * \param value JValue_t + */ + JPair(key_type& key, + mapped_type& value) : + first (key), + second(value) + {} + + const key_type& getKey() const { return this->first; } + const mapped_type& getValue() const { return this->second; } + + key_type& getKey() { return this->first; } + mapped_type& getValue() { return this->second; } + + JKey_t& first; + JValue_t& second; + }; + + + /** + * Template specialisation for a mixed pair of const and non-const references. + */ + template<class JKey_t, class JValue_t> + class JPair<const JKey_t&, JValue_t&> + { + public: + + typedef JKey_t key_type; + typedef JValue_t mapped_type; + + + /** + * Constructor. + * + * \param key JKey_t + * \param value JValue_t + */ + JPair(const key_type& key, + mapped_type& value) : + first (key), + second(value) + {} + + const key_type& getKey() const { return this->first; } + const mapped_type& getValue() const { return this->second; } + + mapped_type& getValue() { return this->second; } + + const JKey_t& first; + JValue_t& second; + }; + + + /** + * Template specialisation for a pair of const references. + */ + template<class JKey_t, class JValue_t> + class JPair<const JKey_t&, const JValue_t&> + { + public: + + typedef JKey_t key_type; + typedef JValue_t mapped_type; + + + /** + * Constructor. + * + * \param key JKey_t + * \param value JValue_t + */ + JPair(const key_type& key, + const mapped_type& value) : + first (key), + second(value) + {} + + const key_type& getKey() const { return this->first; } + const mapped_type& getValue() const { return this->second; } + + const JKey_t& first; + const JValue_t& second; + }; +} + +#endif diff --git a/jpp/JTools/JPolint.hh b/jpp/JTools/JPolint.hh new file mode 100644 index 0000000..d843fa3 --- /dev/null +++ b/jpp/JTools/JPolint.hh @@ -0,0 +1,1215 @@ +#ifndef __JTOOLS__JPOLINT__ +#define __JTOOLS__JPOLINT__ + +#include <cmath> +#include <iterator> +#include <algorithm> + +#include "JLang/JException.hh" +#include "JLang/JAssert.hh" +#include "JLang/JBool.hh" +#include "JTools/JFunctional.hh" +#include "JTools/JDistance.hh" +#include "JTools/JResult.hh" +#include "JTools/JElement.hh" +#include "JTools/JMapCollection.hh" +#include "JTools/JQuadrature.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JLANG::JException; + using JLANG::JFunctionalException; + using JLANG::JNumericalPrecision; + using JLANG::JValueOutOfRange; + + + /** + * Template definition for functional collection with polynomial interpolation. + */ + template<unsigned int N, + class JElement_t, + template<class, class> class JCollection_t, + class JResult_t, + class JDistance_t> + class JPolintFunction; + + + /** + * Template specialisation for functional collection with polynomial interpolation. + * + * Polynomial interpolation code is taken from reference: + * Numerical Recipes in C++, W.H. Press, S.A. Teukolsky, W.T. Vetterling and B.P. Flannery, + * Cambridge University Press. + */ + template<unsigned int N, class JElement_t, template<class, class> class JCollection_t, class JDistance_t> + class JPolintFunction<N, + JElement_t, + JCollection_t, + typename JResultType<typename JElement_t::ordinate_type>::result_type, + JDistance_t> : + public JCollection_t<JElement_t, JDistance_t>, + public JFunction<typename JElement_t::abscissa_type, + typename JResultType<typename JElement_t::ordinate_type>::result_type> + { + public: + + typedef JCollection_t<JElement_t, JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef typename JResultType<ordinate_type>::result_type data_type; + typedef JFunction<abscissa_type, data_type> function_type; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::JExceptionHandler exceptionhandler_type; + + + /** + * Default constructor. + */ + JPolintFunction() + {} + + + /** + * Recursive interpolation method implementation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const override + { + if (this->size() <= 1u) { + return this->getExceptionHandler().action(JFunctionalException("JPolintFunction<>::evaluate() not enough data.")); + } + + const argument_type x = *pX; + + const_iterator p = this->lower_bound(x); + + if ((p == this->begin() && this->getDistance(x, (p++)->getX()) > distance_type::precision) || + (p == this->end() && this->getDistance((--p)->getX(), x) > distance_type::precision)) { + return this->getExceptionHandler().action(JValueOutOfRange("JPolintFunction::evaluate() x out of range.")); + } + + ++pX; // next argument value + + + const int n = std::min((int) (N + 1), (int) this->size()); // number of points to interpolate + + for (int i = n/2; i != 0 && p != this->end(); --i, ++p) {} // move p to begin of data + for (int i = n ; i != 0 && p != this->begin(); --i, --p) {} + + + int j = 0; + + for (int i = 0; i != n; ++p, ++i) { + + u[i] = this->getDistance(x, p->getX()); + v[i] = function_type::getValue(p->getY(), pX); + w[i] = v[i]; + + if (fabs(u[i]) < fabs(u[j])) { + j = i; + } + } + + + result_type y = v[j]; + + --j; + + for (int m = 1; m != n; ++m) { + + for (int i = 0; i != n-m; ++i) { + + const double ho = u[ i ]; + const double hp = u[i+m]; + const double dx = ho - hp; + + v[i] = v[i+1]; + v[i] -= w[ i ]; + w[i] = v[ i ]; + + v[i] *= ho/dx; + w[i] *= hp/dx; + } + + if (2*(j+1) < n - m) + y += v[j+1]; + else + y += w[j--]; + } + + return y; + } + + protected: + /** + * Function compilation. + */ + virtual void do_compile() override + {} + + + private: + mutable double u[N+1]; + mutable result_type v[N+1]; + mutable result_type w[N+1]; + }; + + + /** + * Template specialisation for zero-degree polynomial interpolation method.\n + * The interpolation is based on a simple lookup table. + */ + template<class JElement_t, template<class, class> class JCollection_t, class JDistance_t> + class JPolintFunction<0, + JElement_t, + JCollection_t, + typename JResultType<typename JElement_t::ordinate_type>::result_type, + JDistance_t> : + public JCollection_t<JElement_t, JDistance_t>, + public JFunction<typename JElement_t::abscissa_type, + typename JResultType<typename JElement_t::ordinate_type>::result_type> + { + public: + + typedef JCollection_t<JElement_t, JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef typename JResultType<ordinate_type>::result_type data_type; + typedef JFunction<abscissa_type, data_type> function_type; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::JExceptionHandler exceptionhandler_type; + + + /** + * Default constructor. + */ + JPolintFunction() + {} + + + /** + * Recursive interpolation method implementation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const override + { + if (this->size() <= 1u) { + return this->getExceptionHandler().action(JFunctionalException("JPolintFunction<>::evaluate() not enough data.")); + } + + const argument_type x = *pX; + + const_iterator p = this->lower_bound(x); + + if ((p == this->begin() && this->getDistance(x, (p++)->getX()) > distance_type::precision) || + (p == this->end() && this->getDistance((--p)->getX(), x) > distance_type::precision)) { + + return this->getExceptionHandler().action(JValueOutOfRange("JPolintFunction::evaluate() x out of range.")); + } + + ++pX; // next argument value + + + const_iterator q = p--; + + if (q == this->begin() || this->getDistance(x, q->getX()) < this->getDistance(p->getX(), x)) + return function_type::getValue(q->getY(), pX); + else + return function_type::getValue(p->getY(), pX); + } + + protected: + /** + * Function compilation. + */ + virtual void do_compile() override + {} + }; + + + /** + * Template specialisation for first-degree polynomial interpolation method.\n + * The interpolation is based on a simple linear interpolation. + */ + template<class JElement_t, template<class, class> class JCollection_t, class JDistance_t> + class JPolintFunction<1, + JElement_t, + JCollection_t, + typename JResultType<typename JElement_t::ordinate_type>::result_type, + JDistance_t> : + public JCollection_t<JElement_t, JDistance_t>, + public JFunction<typename JElement_t::abscissa_type, + typename JResultType<typename JElement_t::ordinate_type>::result_type> + { + public: + + typedef JCollection_t<JElement_t, JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef typename JResultType<ordinate_type>::result_type data_type; + typedef JFunction<abscissa_type, data_type> function_type; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::JExceptionHandler exceptionhandler_type; + + + /** + * Default constructor. + */ + JPolintFunction() + {} + + + /** + * Recursive interpolation method implementation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const override + { + if (this->size() <= 1u) { + return this->getExceptionHandler().action(JFunctionalException("JPolintFunction<>::evaluate() not enough data.")); + } + + const argument_type x = *pX; + + const_iterator p = this->lower_bound(x); + + if ((p == this->begin() && this->getDistance(x, (p++)->getX()) > distance_type::precision) || + (p == this->end() && this->getDistance((--p)->getX(), x) > distance_type::precision)) { + + return this->getExceptionHandler().action(JValueOutOfRange("JPolintFunction::evaluate() x out of range.")); + } + + ++pX; // next argument value + + + const_iterator q = p--; + + const double dx = this->getDistance(p->getX(), q->getX()); + const double a = this->getDistance(x, q->getX()) / dx; + const double b = 1.0 - a; + + ya = function_type::getValue(p->getY(), pX); + yb = function_type::getValue(q->getY(), pX); + + ya *= a; + yb *= b; + + ya += yb; + + return ya; + } + + protected: + /** + * Function compilation. + */ + virtual void do_compile() override + {} + + + private: + mutable result_type ya; + mutable result_type yb; + }; + + + /** + * Template specialisation for polynomial interpolation method with returning JResultPDF data structure. + * + * Note that the data structure of the elements in the collection should have the additional methods: + * <pre> + * ordinate_type getIntegral() const; + * void setIntegral(ordinate_type v); + * </pre> + * to get and set the integral values, respectively. + */ + template<unsigned int N, class JElement_t, template<class, class> class JCollection_t, class JDistance_t> + class JPolintFunction<N, + JElement_t, + JCollection_t, + JResultPDF<typename JResultType<typename JElement_t::ordinate_type>::result_type>, + JDistance_t> : + public JCollection_t<JElement_t, JDistance_t>, + public JFunction<typename JElement_t::abscissa_type, + JResultPDF<typename JResultType<typename JElement_t::ordinate_type>::result_type> > + { + public: + + typedef JCollection_t<JElement_t, JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef typename JResultType<ordinate_type>::result_type data_type; + typedef JFunction<abscissa_type, JResultPDF<data_type> > function_type; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::JExceptionHandler exceptionhandler_type; + + using JFunctional<>::compile; + + + /** + * Default contructor. + */ + JPolintFunction() + {} + + + /** + * Recursive interpolation method implementation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const override + { + if (this->size() <= 1u) { + return this->getExceptionHandler().action(JFunctionalException("JPolintFunction<>::evaluate() not enough data.")); + } + + const argument_type x = *pX; + + const_iterator p = this->lower_bound(x); + + if (p == this->begin() && this->getDistance(x, (p++)->getX()) > distance_type::precision) { + + try { + + result = this->getExceptionHandler().action(JValueOutOfRange("JPolintFunction<>::operator() x < xmin.")); + + // overwrite integral values + + result.v = 0; + result.V = this->rbegin()->getIntegral(); + + } catch(const JValueOutOfRange& exception) { + throw exception; + } + + return result; + + } else if (p == this->end() && this->getDistance((--p)->getX(), x) > distance_type::precision) { + + try { + + result = this->getExceptionHandler().action(JValueOutOfRange("JPolintFunction<>::operator() x > xmax.")); + + // overwrite integral values + + result.v = this->rbegin()->getIntegral(); + result.V = this->rbegin()->getIntegral(); + + } catch(const JValueOutOfRange& exception) { + throw exception; + } + + return result; + } + + ++pX; // next argument value + + { + const int n = std::min((int) (N + 1), (int) this->size()); // number of points to interpolate + + for (int i = n/2; i != 0 && p != this->end(); --i, ++p) {} // move p to begin of data + for (int i = n ; i != 0 && p != this->begin(); --i, --p) {} + + + int j = 0; + + for (int i = 0; i != n; ++p, ++i) { + + u[i] = this->getDistance(x, p->getX()); + + w[i][0] = v[i][0] = JFunctional<argument_type, data_type>::getValue(p->getY(), pX); + w[i][1] = v[i][1] = JMATH::zero; + w[i][2] = v[i][2] = p->getIntegral(); + + if (fabs(u[i]) < fabs(u[j])) { + j = i; + } + } + + + result.f = v[j][0]; + result.fp = v[j][1]; + result.v = v[j][2]; + result.V = this->rbegin()->getIntegral(); + + --j; + + for (int m = 1; m != n; ++m) { + + for (int i = 0; i != n-m; ++i) { + + const double ho = u[ i ]; + const double hp = u[i+m]; + const double dx = ho - hp; + + for (int k = 0; k != 3; ++k) { + r[k] = (v[i+1][k] - w[i][k]) / dx; + } + + v[i][0] = ho * r[0]; + w[i][0] = hp * r[0]; + v[i][1] = ho * r[1] - r[0]; + w[i][1] = hp * r[1] - r[0]; + v[i][2] = ho * r[2]; + w[i][2] = hp * r[2]; + } + + if (2*(j+1) < n - m) { + + result.f += v[j+1][0]; + result.fp += v[j+1][1]; + result.v += v[j+1][2]; + + } else { + + result.f += w[j][0]; + result.fp += w[j][1]; + result.v += w[j][2]; + + --j; + } + } + } + + return result; + } + + protected: + /** + * Function compilation. + */ + virtual void do_compile() override + { + ordinate_type V(JMATH::zero); + + if (this->getSize() > 1) { + + const JGaussLegendre engine(N); + + this->begin()->setIntegral(V); + + for (iterator j = this->begin(), i = j++; j != this->end(); ++i, ++j) { + + const abscissa_type xmin = i->getX(); + const abscissa_type xmax = j->getX(); + + for (JGaussLegendre::const_iterator m = engine.begin(); m != engine.end(); ++m) { + + const abscissa_type x = 0.5 * (xmax + xmin + m->getX() * (xmax - xmin)); + const ordinate_type v = 0.5 * (xmax - xmin) * m->getY() * get_value(this->evaluate(&x)); + + V += v; + } + + j->setIntegral(V); + } + } + } + + + mutable double u[N+1]; + mutable data_type v[N+1][3]; + mutable data_type w[N+1][3]; + mutable data_type r[3]; + + mutable result_type result; + }; + + + /** + * Template definition of base class for polynomial interpolations with polynomial result. + */ + template<unsigned int N, + class JElement_t, + template<class, class> class JCollection_t, + class JResult_t, + class JDistance_t> + class JPolintCollection; + + + /** + * Template base class for polynomial interpolations with polynomial result. + * + * This class partially implements the JFunctional interface. + */ + template<unsigned int N, class JElement_t, template<class, class> class JCollection_t, class JDistance_t, unsigned int M> + class JPolintCollection<N, + JElement_t, + JCollection_t, + JResultPolynome<M, typename JResultType<typename JElement_t::ordinate_type>::result_type>, + JDistance_t> : + public JCollection_t<JElement_t, JDistance_t>, + public virtual JFunctional<>, + private JLANG::JAssert<M <= N> + { + public: + + typedef JCollection_t<JElement_t, JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef typename JResultType<ordinate_type>::result_type data_type; + typedef JFunction<abscissa_type, JResultPolynome<M, data_type> > function_type; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + + using JFunctional<>::compile; + + + /** + * Default contructor. + */ + JPolintCollection() + {} + + + /** + * Recursive interpolation method implementation. + * + * \param pX pointer to abscissa values + * \return function value + */ + result_type evaluate(const argument_type* pX) const + { + if (this->size() <= N) { + THROW(JFunctionalException, "JPolintFunction<>::evaluate() not enough data."); + } + + const argument_type x = *pX; + + const_iterator p = this->lower_bound(x); + + if ((p == this->begin() && this->getDistance(x, (p++)->getX()) > distance_type::precision) || + (p == this->end() && this->getDistance((--p)->getX(), x) > distance_type::precision)) { + + THROW(JValueOutOfRange, "JPolintFunction::evaluate() x out of range."); + } + + ++pX; // next argument value + + + const int n = std::min((int) (N + 1), (int) this->size()); // number of points to interpolate + + for (int i = n/2; i != 0 && p != this->end(); --i, ++p) {} // move p to begin of data + for (int i = n ; i != 0 && p != this->begin(); --i, --p) {} + + + int j = 0; + + for (int i = 0; i != n; ++p, ++i) { + + u[i] = this->getDistance(x, p->getX()); + + w[i][0] = v[i][0] = JFunctional<argument_type, data_type>::getValue(p->getY(), pX); + + for (unsigned int k = 1; k != M+1; ++k) { + w[i][k] = v[i][k] = JMATH::zero; + } + + if (fabs(u[i]) < fabs(u[j])) { + j = i; + } + } + + + for (unsigned int k = 0; k != M+1; ++k) { + result.y[k] = v[j][k]; + } + + --j; + + for (int m = 1; m != n; ++m) { + + for (int i = 0; i != n-m; ++i) { + + const double ho = u[ i ]; + const double hp = u[i+m]; + const double dx = ho - hp; + + for (int k = 0; k != M+1; ++k) { + r[k] = (v[i+1][k] - w[i][k]) / dx; + } + + v[i][0] = ho * r[0]; + w[i][0] = hp * r[0]; + + for (int k = 1; k != M+1; ++k) { + v[i][k] = ho * r[k] - k * r[k-1]; + w[i][k] = hp * r[k] - k * r[k-1]; + } + } + + if (2*(j+1) < n - m) { + + for (int k = 0; k != M+1; ++k) { + result.y[k] += v[j+1][k]; + } + + } else { + + for (int k = 0; k != M+1; ++k) { + result.y[k] += w[j][k]; + } + + --j; + } + } + + return result; + } + + protected: + /** + * Function compilation. + */ + virtual void do_compile() override + {} + + + private: + mutable double u[N+1]; + mutable data_type v[N+1][M+1]; + mutable data_type w[N+1][M+1]; + mutable data_type r[M+1]; + + mutable result_type result; + }; + + + /** + * Template specialisation for polynomial interpolation method with returning JResultPolynome data structure. + */ + template<unsigned int N, class JElement_t, template<class, class> class JCollection_t, class JDistance_t, unsigned int M> + class JPolintFunction<N, + JElement_t, + JCollection_t, + JResultPolynome<M, typename JResultType<typename JElement_t::ordinate_type>::result_type>, + JDistance_t> : + public JPolintCollection<N, + JElement_t, + JCollection_t, + JResultPolynome<M, typename JResultType<typename JElement_t::ordinate_type>::result_type>, + JDistance_t>, + public JFunction<typename JElement_t::abscissa_type, + JResultPolynome<N, typename JResultType<typename JElement_t::ordinate_type>::result_type> > + { + public: + + typedef JPolintCollection<N, + JElement_t, + JCollection_t, + JResultPolynome<M, typename JResultType<typename JElement_t::ordinate_type>::result_type>, + JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef typename JResultType<ordinate_type>::result_type data_type; + typedef JFunction<abscissa_type, JResultPolynome<M, data_type> > function_type; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::JExceptionHandler exceptionhandler_type; + + + /** + * Default contructor. + */ + JPolintFunction() + {} + + + /** + * Recursive interpolation method implementation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const override + { + try { + return collection_type::evaluate(pX); + } + catch(const JException& error) { + return this->getExceptionHandler().action(error); + } + } + }; + + + /** + * Template specialisation for polynomial interpolation method with returning JResultDerivative data structure. + */ + template<unsigned int N, class JElement_t, template<class, class> class JCollection_t, class JDistance_t> + class JPolintFunction<N, + JElement_t, + JCollection_t, + JResultDerivative<typename JResultType<typename JElement_t::ordinate_type>::result_type>, + JDistance_t> : + public JPolintCollection<N, + JElement_t, + JCollection_t, + JResultPolynome<1, typename JResultType<typename JElement_t::ordinate_type>::result_type>, + JDistance_t>, + public JFunction<typename JElement_t::abscissa_type, + JResultDerivative<typename JResultType<typename JElement_t::ordinate_type>::result_type> > + { + public: + + typedef JPolintCollection<N, + JElement_t, + JCollection_t, + JResultPolynome<1, typename JResultType<typename JElement_t::ordinate_type>::result_type>, + JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef typename JResultType<ordinate_type>::result_type data_type; + typedef JFunction<abscissa_type, JResultDerivative<data_type> > function_type; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::JExceptionHandler exceptionhandler_type; + + using JFunctional<>::compile; + + + /** + * Default contructor. + */ + JPolintFunction() + {} + + + /** + * Recursive interpolation method implementation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const override + { + try { + return collection_type::evaluate(pX); + } + catch(const JException& error) { + return this->getExceptionHandler().action(error); + } + } + }; + + + /** + * Template specialisation for polynomial interpolation method with returning JResultHesse data structure. + */ + template<unsigned int N, class JElement_t, template<class, class> class JCollection_t, class JDistance_t> + class JPolintFunction<N, + JElement_t, + JCollection_t, + JResultHesse<typename JResultType<typename JElement_t::ordinate_type>::result_type>, + JDistance_t> : + public JPolintCollection<N, + JElement_t, + JCollection_t, + JResultPolynome<2, typename JResultType<typename JElement_t::ordinate_type>::result_type>, + JDistance_t>, + public JFunction<typename JElement_t::abscissa_type, + JResultHesse<typename JResultType<typename JElement_t::ordinate_type>::result_type> > + { + public: + + typedef JPolintCollection<N, + JElement_t, + JCollection_t, + JResultPolynome<2, typename JResultType<typename JElement_t::ordinate_type>::result_type>, + JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef typename JResultType<ordinate_type>::result_type data_type; + typedef JFunction<abscissa_type, JResultHesse<data_type> > function_type; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::JExceptionHandler exceptionhandler_type; + + using JFunctional<>::compile; + + + /** + * Default contructor. + */ + JPolintFunction() + {} + + + /** + * Recursive interpolation method implementation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const override + { + try { + return collection_type::evaluate(pX); + } + catch(const JException& error) { + return this->getExceptionHandler().action(error); + } + } + }; + + + /** + * Template class for polynomial interpolation in 1D + * + * This class implements the JFunction1D interface. + */ + template<unsigned int N, + class JElement_t, + template<class, class> class JCollection_t, + class JResult_t = typename JElement_t::ordinate_type, + class JDistance_t = JDistance<typename JElement_t::abscissa_type> > + class JPolintFunction1D : + public JPolintFunction<N, JElement_t, JCollection_t, JResult_t, JDistance_t>, + public JFunction1D<typename JElement_t::abscissa_type, JResult_t> + { + public: + + typedef JCollection_t<JElement_t, JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef JFunction1D<abscissa_type, JResult_t> function_type; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::JExceptionHandler exceptionhandler_type; + + + /** + * Default contructor. + */ + JPolintFunction1D() + {} + }; + + + /** + * \cond NEVER + * Forward declarations. + * \endcond + */ + template<class JAbscissa_t, class JOrdinate_t> + struct JElement2D; + + template<template<class, class, class> class JMap_t> + struct JMapCollection; + + + /** + * Functional map with polynomial interpolation. + */ + template<unsigned int N, + class JKey_t, + class JValue_t, + template<class, class, class> class JMap_t, + class JResult_t, + class JDistance_t = JDistance<JKey_t> > + class JPolintMap : + public JPolintFunction<N, + JElement2D<JKey_t, JValue_t>, + JMapCollection<JMap_t>::template collection_type, + JResult_t, + JDistance_t> + { + public: + + typedef JElement2D<JKey_t, JValue_t> element_type; + typedef JPolintFunction<N, + element_type, + JMapCollection<JMap_t>::template collection_type, + JResult_t, + JDistance_t> JPolintFunction_t; + + typedef typename JPolintFunction_t::abscissa_type abscissa_type; + typedef typename JPolintFunction_t::ordinate_type ordinate_type; + typedef typename JPolintFunction_t::value_type value_type; + typedef typename JPolintFunction_t::distance_type distance_type; + + typedef typename JPolintFunction_t::const_iterator const_iterator; + typedef typename JPolintFunction_t::const_reverse_iterator const_reverse_iterator; + typedef typename JPolintFunction_t::iterator iterator; + typedef typename JPolintFunction_t::reverse_iterator reverse_iterator; + + typedef typename JPolintFunction_t::argument_type argument_type; + typedef typename JPolintFunction_t::result_type result_type; + typedef typename JPolintFunction_t::JExceptionHandler exceptionhandler_type; + + + /** + * Default constructor. + */ + JPolintMap() + {} + }; + + + /** + * Conversion of data points to integral values. + * + * This method transfers the integration to the corresponding specialised function. + * + * \param input collection + * \param output mappable collection + * \return integral + */ + template<unsigned int N, + class JElement_t, + template<class, class> class JCollection_t, + class JResult_t, + class JDistance_t> + inline typename JElement_t::ordinate_type + integrate(const JPolintFunction1D<N, JElement_t, JCollection_t, JResult_t, JDistance_t>& input, + typename JMappable<JElement_t>::map_type& output) + { + return integrate(input, output, JLANG::JBool<N == 0 || N == 1>()); + } + + + /** + * Conversion of data points to integral values. + * + * The integration uses the Gauss-Legendre quadratures with the number of points set + * to the degree of the input polynomial interpolating function. + * + * \param input collection + * \param output mappable collection + * \param option false + * \return integral + */ + template<unsigned int N, + class JElement_t, + template<class, class> class JCollection_t, + class JResult_t, + class JDistance_t> + inline typename JElement_t::ordinate_type + integrate(const JPolintFunction1D<N, JElement_t, JCollection_t, JResult_t, JDistance_t>& input, + typename JMappable<JElement_t>::map_type& output, + const JLANG::JBool<false>& option) + { + typedef typename JElement_t::abscissa_type abscissa_type; + typedef typename JElement_t::ordinate_type ordinate_type; + typedef typename JPolintFunction1D<N, JElement_t, JCollection_t, JResult_t, JDistance_t>::const_iterator const_iterator; + + ordinate_type V(JMATH::zero); + + if (input.getSize() > 1) { + + output.put(input.begin()->getX(), V); + + const JGaussLegendre engine(N); + + for (const_iterator j = input.begin(), i = j++; j != input.end(); ++i, ++j) { + + const abscissa_type xmin = i->getX(); + const abscissa_type xmax = j->getX(); + + for (JGaussLegendre::const_iterator m = engine.begin(); m != engine.end(); ++m) { + + const abscissa_type x = 0.5 * (xmax + xmin + m->getX() * (xmax - xmin)); + const ordinate_type v = 0.5 * (xmax - xmin) * m->getY() * get_value(input(x)); + + V += v; + } + + output.put(xmax, V); + } + } + + return V; + } + + + /** + * Conversion of data points to integral values. + * + * The integration is based on the sum of ordinates of the input data points. + * + * \param input collection + * \param output mappable collection + * \param option true + * \return integral + */ + template<class JElement_t, + template<class, class> class JCollection_t, + class JResult_t, + class JDistance_t> + inline typename JElement_t::ordinate_type + integrate(const JPolintFunction1D<0, JElement_t, JCollection_t, JResult_t, JDistance_t>& input, + typename JMappable<JElement_t>::map_type& output, + const JLANG::JBool<true>& option) + { + typedef typename JElement_t::ordinate_type ordinate_type; + typedef typename JPolintFunction1D<0, JElement_t, JCollection_t, JResult_t, JDistance_t>::const_iterator const_iterator; + + ordinate_type V(JMATH::zero); + + if (input.getSize() > 1) { + + output.put(input.begin()->getX(), V); + + for (const_iterator j = input.begin(), i = j++; j != input.end(); ++i, ++j) { + + V += input.getDistance(i->getX(), j->getX()) * j->getY(); + + output.put(j->getX(), V); + } + } + + return V; + } + + + /** + * Conversion of data points to integral values. + * + * The integration is based on the trapezoidal rule applied to the input data points. + * + * \param input collection + * \param output mappable collection + * \param option true + * \return integral + */ + template<class JElement_t, + template<class, class> class JCollection_t, + class JResult_t, + class JDistance_t> + inline typename JElement_t::ordinate_type + integrate(const JPolintFunction1D<1, JElement_t, JCollection_t, JResult_t, JDistance_t>& input, + typename JMappable<JElement_t>::map_type& output, + const JLANG::JBool<true>& option) + { + typedef typename JElement_t::ordinate_type ordinate_type; + typedef typename JPolintFunction1D<1, JElement_t, JCollection_t, JResult_t, JDistance_t>::const_iterator const_iterator; + + ordinate_type V(JMATH::zero); + + if (input.getSize() > 1) { + + output.put(input.begin()->getX(), V); + + for (const_iterator j = input.begin(), i = j++; j != input.end(); ++i, ++j) { + + V += 0.5 * input.getDistance(i->getX(), j->getX()) * (i->getY() + j->getY()); + + output.put(j->getX(), V); + } + } + + return V; + } +} + +#endif diff --git a/jpp/JTools/JQuadrature.hh b/jpp/JTools/JQuadrature.hh new file mode 100644 index 0000000..c29f1c9 --- /dev/null +++ b/jpp/JTools/JQuadrature.hh @@ -0,0 +1,546 @@ +#ifndef __JTOOLS__JQUADRATURE__ +#define __JTOOLS__JQUADRATURE__ + +#include <cmath> + +#include "JTools/JConstants.hh" +#include "JTools/JElement.hh" +#include "JTools/JCollection.hh" + + +/** + * \file + * + * Auxiliary classes for numerical integration. + * \author mdejong + */ +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + /** + * Type definition of basic element for quadratures. + */ + typedef JElement2D<double, double> JElement2D_t; + + + /** + * Type definition for numerical integration. + * + * \f$\displaystyle \int_{x_1}^{x_2} f(x) dx = \sum_{i=1}^{N} w_i f(x_i) \f$ + * + * The abscissa and ordinate values of the collection can be used + * as abscissa and weight values of the summation to approximately + * determine the integral of the function. + */ + class JQuadrature : + public JCollection<JElement2D_t> + { + public: + /** + * Default constructor. + */ + JQuadrature() + {} + + + /** + * General purpose constructor. + * + * The template argument should correspond to a function requiring two arguments. + * These two arguments should correspond to the lower and upper integration limit, respectively. + * The given function should return the value of the integral between the two integration limits. + * + * \param xmin minimal x + * \param xmax maximal x + * \param nx number of points + * \param integral integral + * \param eps precision + */ + template<class JFunction_t> + JQuadrature(const double xmin, + const double xmax, + const int nx, + JFunction_t integral, + const double eps = 1.0e-4) + { + double Xmin = xmin; + double Xmax = xmax; + + const double Vmin = integral(Xmin, Xmax) / (double) nx; + + for (int i = 0; i != nx; ++i) { + + for (double xmin = Xmin, xmax = Xmax; ; ) { + + const double x = 0.5 * (xmin + xmax); + const double v = integral(Xmin, x); + + if (fabs(Vmin - v) < eps * Vmin || + fabs(xmax - xmin) < eps * (Xmax - Xmin)) { + + const double __x = 0.5 * (Xmin + x); + const double __y = Vmin / integral(__x); + + insert(JElement2D_t(__x,__y)); + + Xmin = x; + xmax = Xmax; + + break; + } + + if (v < Vmin) + xmin = x; + else + xmax = x; + } + } + } + }; + + + /** + * Numerical integrator for <tt>W(x) = 1</tt>. + * + * Gauss-Legendre integration code is taken from reference: + * Numerical Recipes in C++, W.H. Press, S.A. Teukolsky, W.T. Vetterling and B.P. Flannery, + * Cambridge University Press. + */ + class JGaussLegendre : + public JQuadrature + { + public: + /** + * Constructor. + * + * \param n number of points + * \param eps precision + */ + JGaussLegendre(const int n, + const double eps = 1.0e-12) : + JQuadrature() + { + resize(n); + + const int M = (n + 1) / 2; + + double p0, p1, p2, pp; + + for (int i = 0; i < M; ++i) { + + double z = cos(PI * (i+0.75) / (n+0.5)); + double z1; + + do { + + p1 = 0.0; + p2 = 1.0; + + // recurrence relation + + for (int j = 0; j < n; ++j) { + p0 = p1; + p1 = p2; + p2 = ((2*j + 1) * z*p1 - j*p0) / (j+1); + } + + pp = n * (z*p2 - p1) / (z*z - 1.0); + + z1 = z; + z = z1 - p2/pp; + + } while (fabs(z-z1) > eps); + + const double y = 2.0 / ((1.0-z*z)*pp*pp); + + at( i ) = JElement2D_t(-z,y); + at(n-i-1) = JElement2D_t(+z,y); + } + } + }; + + + /** + * Numerical integrator for <tt>W(x) = x^a e^(-x)</tt>. + * + * Gauss-Laguerre integration code is taken from reference: + * Numerical Recipes in C++, W.H. Press, S.A. Teukolsky, W.T. Vetterling and B.P. Flannery, + * Cambridge University Press. + */ + class JGaussLaguerre : + public JQuadrature + { + public: + /** + * Constructor. + * + * \param n number of points + * \param alf power + * \param eps precision + */ + JGaussLaguerre(const int n, + const double alf, + const double eps = 1.0e-12) : + JQuadrature() + { + const int number_of_iterations = 100; + + double z, z1; + double p0, p1, p2, pp; + + for (int i = 0; i < n; ++i) { + + switch (i) { + + case 0: + z = (1.0 + alf) * (3.0 + 0.92*alf) / (1.0 + 2.4*n + 1.8*alf); + break; + + case 1: + z += (15.0 + 6.25*alf) / (1.0 + 0.9*alf + 2.5*n); + break; + + default: + const double ai = i - 1; + z += ((1.0+2.55*ai)/(1.9*ai) + (1.26*ai*alf)/(1.0+3.5*ai)) * (z - at(i-2).getX()) / (1.0 + 0.3*alf); + break; + } + + + int k; + + for (k = 0; k != number_of_iterations; ++k) { + + p1 = 0.0; + p2 = 1.0; + + // recurrence relation + + for (int j = 0; j < n; ++j) { + p0 = p1; + p1 = p2; + p2 = ((2*j + 1 + alf - z) * p1 - (j + alf)*p0) / (j+1); + } + + pp = (n*p2 - (n+alf)*p1) / z; + + z1 = z; + z = z1 - p2/pp; + + if (fabs(z-z1) < eps) + break; + } + + const double y = -tgamma(alf+n) / tgamma((double) n) / (pp*n*p1); + + insert(JElement2D_t(z,y)); + } + } + }; + + + /** + * Numerical integrator for <tt>W(x) = e^-(x^2)</tt>. + * + * Gauss-Hermite integration code is taken from reference: + * Numerical Recipes in C++, W.H. Press, S.A. Teukolsky, W.T. Vetterling and B.P. Flannery, + * Cambridge University Press. + */ + class JGaussHermite : + public JQuadrature + { + public: + /** + * Constructor. + * + * \param n number of points + * \param eps precision + */ + JGaussHermite(const int n, + const double eps = 1.0e-12) : + JQuadrature() + { + resize(n); + + const double pii = 1.0 / pow(PI,0.25); + + const int number_of_iterations = 100; + + const int M = (n + 1) / 2; + + double p0, p1, p2, pp; + double z = 0.0; + double z1; + + for (int i = 0; i < M; ++i) { + + switch (i) { + + case 0: + z = sqrt((double) (2*n+1)) - 1.85575 * pow((double) (2*n+1),-0.16667); + break; + + case 1: + z -= 1.14 * pow((double) n,0.426) / z; + break; + + case 2: + z = 1.86*z + 0.86*at( 0 ).getX(); + break; + + case 3: + z = 1.91*z + 0.91*at( 1 ).getX(); + break; + + default: + z = 2.00*z + 1.00*at(i-2).getX(); + break; + } + + for (int k = 0; k != number_of_iterations; ++k) { + + p1 = 0.0; + p2 = pii; + + // recurrence relation + + for (int j = 0; j < n; ++j) { + p0 = p1; + p1 = p2; + p2 = z * sqrt(2.0/(double) (j+1)) * p1 - sqrt((double) j / (double) (j+1)) * p0; + } + + pp = sqrt((double) (2*n)) * p1; + + z1 = z; + z = z1 - p2/pp; + + if (fabs(z-z1) < eps) + break; + } + + const double y = 2.0 / (pp*pp); + + at( i ) = JElement2D_t(-z,y); + at(n-i-1) = JElement2D_t(+z,y); + } + } + }; + + + /** + * Numerical integrator for <tt>W(x) = (1 + g^2 - 2gx)^a</tt>. + * For this, <tt>g > 0</tt>. + * + * Henyey-Greenstein integration points and weights. + */ + class JHenyeyGreenstein : + public JQuadrature + { + public: + /** + * Constructor. + * + * \param n number of points + * \param g angular dependence parameter + * \param a power + */ + JHenyeyGreenstein(const int n, + const double g, + const double a) : + JQuadrature() + { + const double b = -2*g * (a + 1.0); + const double ai = 1.0 / (a + 1.0); + + const double ymin = pow(1.0 + g, 2*(a + 1.0)) / b; + const double ymax = pow(1.0 - g, 2*(a + 1.0)) / b; + + const double dy = (ymax - ymin) / (n + 1); + + for (double y = ymax - 0.5*dy; y > ymin; y -= dy) { + + const double v = y*b; + const double w = pow(v, ai); + const double x = (1.0 + g*g - w) / (2*g); + const double dx = pow(v, -a*ai)*dy; + + insert(JElement2D_t(x,dx)); + } + } + + + /** + * Constructor. + * + * \param n number of points + * \param g angular dependence parameter + * \param a power + * \param xmin minimal value + * \param xmax maximal value + */ + JHenyeyGreenstein(const int n, + const double g, + const double a, + const double xmin, + const double xmax) : + JQuadrature() + { + const double b = -2*g * (a + 1.0); + const double ai = 1.0 / (a + 1.0); + + const double ymin = pow(1.0 + g*g -2*g*xmin, a + 1.0) / b; + const double ymax = pow(1.0 + g*g -2*g*xmax, a + 1.0) / b; + + const double dy = (ymax - ymin) / (n + 1); + + for (double y = ymax - 0.5*dy; y > ymin; y -= dy) { + + const double v = y*b; + const double w = pow(v, ai); + const double x = (1.0 + g*g - w) / (2*g); + const double dx = pow(v, -a*ai)*dy; + + insert(JElement2D_t(x,dx)); + } + } + + + /** + * Constructor for special case where a = -1. + * + * \param n number of points + * \param g angular dependence parameter + */ + JHenyeyGreenstein(const int n, + const double g) : + JQuadrature() + { + const double dy = 1.0 / (n + 1); + const double gi = log((1.0 + g*g) / (1.0 - g*g)) / (2.0*g); + + for (double y = 1.0 - 0.5*dy; y > 0.0; y -= dy) { + + const double v = -y*2.0*g*gi + log(1.0 + g*g); + const double w = exp(v); + const double x = (1.0 + g*g - w) / (2.0*g); + const double dx = w*gi*dy; + + insert(JElement2D_t(x,dx)); + } + } + }; + + + /** + * Numerical integrator for <tt>W(x) = (1 + g*x*x)</tt>. + * For this, <tt>g > 0</tt>. + * + * Rayleigh integration points and weights. + */ + class JRayleigh : + public JQuadrature + { + public: + /** + * Constructor. + * + * \param n number of points + * \param g angular dependence parameter + */ + JRayleigh(const int n, + const double g) : + JQuadrature() + { + const double dy = 1.0 / (n + 1); + const double gi = 3.0/g + 1.0; + + // t^3 + 3pt + 2q = 0 + + const double p = 1.0/g; + + for (double y = 0.5*dy; y < 1.0; y += dy) { + + const double q = 0.5*gi - gi*y; + + const double b = sqrt(q*q + p*p*p); + const double u = pow(-q + b, 1.0/3.0); + const double v = pow(+q + b, 1.0/3.0); + + const double x = u - v; + const double dx = (u + v) / (3.0*b); + + insert(JElement2D_t(x, dx*gi*dy)); + } + } + }; + + + /** + * Numerical integrator for <tt>W(x) = |x| / sqrt(1 - x*x)</tt> + * + * Co-tangent integration points and weights. + */ + class JCotangent : + public JQuadrature + { + public: + /** + * Constructor. + * + * \param n number of points + */ + JCotangent(const int n) : + JQuadrature() + { + for (double ds = 1.0 / (n/2), sb = 0.5*ds; sb < 1.0; sb += ds) { + + const double cb = sqrt((1.0 + sb)*(1.0 - sb)); + const double dc = ds*sb/cb; + + insert(JElement2D_t(+cb, dc)); + insert(JElement2D_t(-cb, dc)); + } + } + }; + + + /** + * Numerical integrator for <tt>W(x) = |x| / sqrt(1 - x*x), x > 0 </tt> and <tt>W(x) = 1, x <= 0</tt>. + * + * Bi-tangent integration points and weights. + */ + class JBitangent : + public JQuadrature + { + public: + /** + * Constructor. + * + * \param n number of points + */ + JBitangent(const int n) : + JQuadrature() + { + double sb, ds; + double cb = 0.0; + double dc = 0.0; + + for (ds = 1.0 / (n/2), sb = 0.5*ds; sb < 1.0; sb += ds) { + + cb = sqrt((1.0 + sb)*(1.0 - sb)); + dc = ds*sb/cb; + + insert(JElement2D_t(cb, dc)); + } + + for (dc = (cb + 1.0) / (n/2), cb -= 0.5*dc ; cb > -1.0; cb -= dc) { + insert(JElement2D_t(cb, dc)); + } + } + }; +} + +#endif diff --git a/jpp/JTools/JQuantiles.hh b/jpp/JTools/JQuantiles.hh new file mode 100644 index 0000000..024ab4b --- /dev/null +++ b/jpp/JTools/JQuantiles.hh @@ -0,0 +1,360 @@ +#ifndef __JTOOLS__JQUANTILES__ +#define __JTOOLS__JQUANTILES__ + +#include <limits> +#include <cmath> + +#include "JLang/JException.hh" +#include "JTools/JRange.hh" +#include "JTools/JElement.hh" +#include "JTools/JResult.hh" +#include "JTools/JAbstractCollection.hh" +#include "JTools/JToolsToolkit.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JLANG::JException; + using JLANG::JEmptyCollection; + + + /** + * Locate maximum or minimun of function. + * + * Golden section search code is taken from reference: + * Numerical Recipes in C++, W.H. Press, S.A. Teukolsky, W.T. Vetterling and B.P. Flannery, + * Cambridge University Press. + * + * xa < xb < xc + * + * is = +1 -> There is a minimum, i.e: f(xb) < min(f(xa),f(xc)) + * is = -1 -> There is a maximum, i.e: f(xb) > max(f(xa),f(xc)) + * + * \param xa + * \param xb + * \param xc + * \param f function + * \param is sign (+1 -> minimim, -1 -> maximum) + * \param eps relative precision + */ + template<class JFunction1D_t> + double search(const double xa, + const double xb, + const double xc, + const JFunction1D_t& f, + const int is, + const double eps = 1.0e-6) + { + static const double R = 0.61803399; + static const double C = 1.0 - R; + + double x0 = xa; + double x3 = xc; + double x1, x2; + + if (fabs(xc-xb) > fabs(xb-xa)) { + x1 = xb; + x2 = xb + C*(xc-xb); + } else { + x2 = xb; + x1 = xb - C*(xb-xa); + } + + double f1 = is * get_value(f(x1)); + double f2 = is * get_value(f(x2)); + + while (fabs(x3-x0) > eps*(fabs(x1)+fabs(x2))) { + + if (f2 < f1) { + + x0 = x1; + x1 = x2; + x2 = R*x2 + C*x3; + + f1 = f2; + f2 = is * get_value(f(x2)); + + } else { + + x3 = x2; + x2 = x1; + x1 = R*x1 + C*x0; + + f2 = f1; + f1 = is * get_value(f(x1)); + } + } + + if (f1 < f2) + return x1; + else + return x2; + } + + + /** + * Quantile calculator for a given function. + * It is assumed that the function has a single maximum. + */ + class JQuantiles : + public JRange<double> + { + public: + + typedef JAbstractCollection<double> JAbscissa_t; + + /** + * Default constructor. + */ + JQuantiles() : + Xmax(0.0), + Ymax(0.0), + fwhm(0.0), + sum (0.0) + {} + + + /** + * Constructor. + * + * \param f1 functional collection + * \param Q quantile + * \param eps relative precision + */ + template<class JFunction1D_t> + JQuantiles(const JFunction1D_t& f1, + const double Q = 1.0, + const double eps = 1.0e-6) : + Xmax(0.0), + Ymax(0.0), + fwhm(0.0), + sum (0.0) + { + set(f1, Q, eps); + } + + + /** + * Constructor. + * + * \param abscissa abscissa + * \param f1 function + * \param Q quantile + * \param eps relative precision + */ + template<class JFunction1D_t> + JQuantiles(const JAbscissa_t& abscissa, + const JFunction1D_t& f1, + const double Q = 1.0, + const double eps = 1.0e-6) : + Xmax(0.0), + Ymax(0.0), + fwhm(0.0), + sum (0.0) + { + set(abscissa, f1, Q, eps); + } + + + /** + * Set quantiles. + * + * \param f1 functional collection + * \param Q quantile + * \param eps relative precision + */ + template<class JFunction1D_t> + void set(const JFunction1D_t& f1, + const double Q = 1.0, + const double eps = 1.0e-6) + { + typedef typename JFunction1D_t::const_iterator const_iterator; + + if (f1.empty()) { + throw JEmptyCollection("JQuantiles() no data."); + } + + + // maximum + + const_iterator p = f1.begin(); + + for (const_iterator i = f1.begin(); i != f1.end(); ++i) { + if (i->getY() > p->getY()) { + p = i; + } + } + + + // x at maximum + + Xmax = p->getX(); + + if (p != f1.begin()) { + + const double xa = (--p)->getX(); + const double xb = (++p)->getX(); + + if (++p != f1.end()) { + + const double xc = p->getX(); + + Xmax = search(xa, xb, xc, f1, -1, eps); + } + } + + Ymax = get_value(f1(Xmax)); + + + // integral & quantile + + if (Q > 0.0 && Q <= 1.0) { + + JSplineFunction1D<JSplineElement2D<double, double>, JCollection, double> buffer; + + try { + + sum = makeCDF(f1, buffer); + + setLowerLimit(buffer(0.5 * (1.0 - Q))); + setUpperLimit(buffer(0.5 * (1.0 + Q))); + } + catch(const JException& error) { + sum = 0.0; + } + + } else { + + sum = JTOOLS::getIntegral(f1); + + if (Q > 1.0) { + setLowerLimit(f1. begin()->getX()); + setUpperLimit(f1.rbegin()->getX()); + } else if (Q <= 0.0) { + setLowerLimit(Xmax); + setUpperLimit(Xmax); + } + } + + + // FWHM + + fwhm = 0.0; + + for (double xmin = f1.begin()->getX(), xmax = Xmax, v = 0.5*Ymax; ; ) { + + const double x = 0.5 * (xmin + xmax); + const double y = get_value(f1(x)); + + if (fabs(y - v) < eps*v || xmax - xmin < eps) { + fwhm -= x; + break; + } + + if (y > v) + xmax = x; + else + xmin = x; + } + + for (double xmin = Xmax, xmax = f1.rbegin()->getX(), v = 0.5*Ymax; ; ) { + + const double x = 0.5 * (xmin + xmax); + const double y = get_value(f1(x)); + + if (fabs(y - v) < eps*v || xmax - xmin < eps) { + fwhm += x; + break; + } + + if (y > v) + xmin = x; + else + xmax = x; + } + } + + + /** + * Set quantiles. + * + * \param abscissa abscissa + * \param f1 function + * \param Q quantile + * \param eps relative precision + */ + template<class JFunction1D_t> + void set(const JAbscissa_t& abscissa, + const JFunction1D_t& f1, + const double Q = 1.0, + const double eps = 1.0e-6) + { + JSplineFunction1D<JSplineElement2D<double, double>, JCollection, double> buffer; + + buffer.configure(abscissa, f1); + buffer.compile(); + + set(buffer, Q, eps); + } + + + /** + * Get position of maximum. + * + * \return x value at maximum + */ + double getX() const + { + return Xmax; + } + + + /** + * Get value of maximum. + * + * \return y value at maximum + */ + double getY() const + { + return Ymax; + } + + + /** + * Get Full Width at Half Maximum. + * + * \return FWHM + */ + double getFWHM() const + { + return fwhm; + } + + + /** + * Get integral of function. + * + * \return integral + */ + double getIntegral() const + { + return sum; + } + + + protected: + double Xmax; + double Ymax; + double fwhm; + double sum; + }; +} + +#endif diff --git a/jpp/JTools/JRange.hh b/jpp/JTools/JRange.hh new file mode 100644 index 0000000..93ce131 --- /dev/null +++ b/jpp/JTools/JRange.hh @@ -0,0 +1,718 @@ +#ifndef __JTOOLS__JRANGE__ +#define __JTOOLS__JRANGE__ + +#include <cmath> +#include <utility> +#include <functional> + +#include "JLang/JClass.hh" +#include "JLang/JBool.hh" +#include "JLang/JEquals.hh" +#include "JLang/JVectorize.hh" +#include "JTools/JPair.hh" +#include "JMath/JMath.hh" +#include "JMath/JLimits.hh" + + +/** + * \file + * + * Auxiliary class to define a range between two values. + * \author mdejong + */ +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JLANG::JEquals; + using JLANG::array_type; + using JLANG::make_array; + using JMATH::JMath; + + + /** + * Range of values. + */ + template<class T, class JComparator_t = std::less<T> > + class JRange : + public JPair<T,T>, + public JEquals< JRange<T> >, + public JMath < JRange<T> > + { + public: + + typedef std::pair<T,T> pair_type; + typedef JRange<T, JComparator_t> range_type; + typedef typename JLANG::JClass<T>::argument_type argument_type; + + + /** + * Default constructor.\n + * This range corresponds to the maximal possible range. + */ + JRange() : + JPair<T,T>(getMinimum(), getMaximum()) + {} + + + /** + * Constructor. + * + * \param pair pair + */ + JRange(const pair_type& pair) : + JPair<T,T>(pair.first, pair.second) + {} + + + /** + * Constructor. + * + * \param x lower limit + * \param y upper limit + */ + JRange(argument_type x, + argument_type y) : + JPair<T,T>(x, y) + {} + + + /** + * Constructor. + * + * \param x lower and upper limit + */ + JRange(argument_type x) : + JPair<T,T>(x, x) + {} + + + /** + * Constructor.\n + * The arguments could be values or iterators. + * + * \param first first + * \param second second + */ + template<class R> + JRange(R first, R second) : + JPair<T,T>() + { + setRange(first, second); + } + + + /** + * Constructor. + * + * \param buffer input data + */ + template<class JElement_t, class JAllocator_t> + JRange(const array_type<JElement_t, JAllocator_t>& buffer) : + JPair<T,T>() + { + setRange(buffer); + } + + + /** + * Type conversion operator. + * + * \return piar + */ + operator pair_type() const + { + return pair_type(getLowerLimit(), getUpperLimit()); + } + + + /** + * Get range. + * + * \return range + */ + const range_type& getRange() const + { + return static_cast<const range_type&>(*this); + } + + + /** + * Set range. + * + * \param range range + */ + void setRange(const range_type& range) + { + static_cast<range_type&>(*this) = range; + } + + + /** + * Set lower and upper limit. + * + * \param x lower limit + * \param y upper limit + */ + void setRange(argument_type x, argument_type y) + { + this->first = x; + this->second = y; + } + + + /** + * Set range.\n + * The arguments could be values or iterators. + * + * \param first first + * \param second second + */ + template<class R> + void setRange(R first, R second) + { + using namespace JLANG; + + setRange(first, second, JBool<is_iterator<R>::value>()); + } + + + /** + * Set lower and upper limit according to input data. + * + * \param buffer input data + */ + template<class JElement_t, class JAllocator_t> + void setRange(const array_type<JElement_t, JAllocator_t>& buffer) + { + setRange(getMaximum(), getMinimum()); + + for (typename array_type<JElement_t, JAllocator_t>::const_iterator i = buffer.begin(); i != buffer.end(); ++i) { + include(*i); + } + } + + + /** + * Get lower limit. + * + * \return lower limit + */ + T getLowerLimit() const + { + return this->first; + } + + + /** + * Get upper limit. + * + * \return upper limit + */ + T getUpperLimit() const + { + return this->second; + } + + + /** + * Set lower limit. + * + * \param x lower limit + */ + void setLowerLimit(argument_type x) + { + this->first = x; + } + + + /** + * Set upper limit. + * + * \param y upper limit + */ + void setUpperLimit(argument_type y) + { + this->second = y; + } + + + /** + * Fix lower limit. + * + * The range is shifted to the given lower limit. + * + * \param x lower limit + */ + void fixLowerLimit(argument_type x) + { + this->second += x - this->first; + this->first = x; + } + + + /** + * Fix upper limit. + * + * The range is shifted to the given upper limit. + * + * \param y upper limit + */ + void fixUpperLimit(argument_type y) + { + this->first += y - this->second; + this->second = y; + } + + + /** + * Equal method. + * + * \param range range + * \result true if this module range equal to given module range; else false + */ + inline bool equals(const range_type& range) const + { + return (!this->compare(this->getLowerLimit(), range.getLowerLimit()) && + !this->compare(range.getLowerLimit(), this->getLowerLimit()) && + !this->compare(this->getUpperLimit(), range.getUpperLimit()) && + !this->compare(range.getUpperLimit(), this->getUpperLimit())); + } + + + /** + * Get length (difference between upper and lower limit). + * + * \return length + */ + T getLength() const + { + return getUpperLimit() - getLowerLimit(); + } + + + /** + * Set length (difference between upper and lower limit). + * + * \param length length + */ + void setLength(argument_type length) + { + setUpperLimit(getLowerLimit() + length); + } + + + /** + * Check validity of range. + * + * \return true if lower limit less than or equal to upper limit; else false + */ + bool is_valid() const + { + return !compare(getUpperLimit(), getLowerLimit()); + } + + + /** + * Test whether value is inside range. + * + * \param x value + * \return true if lower limit <= value <= upper limit; else false + */ + bool in_range(argument_type x) const + { + return (!compare(x, getLowerLimit()) && + !compare(getUpperLimit(), x)); + } + + + /** + * Test whether value is inside range. + * + * \param x value + * \return true if lower limit <= value <= upper limit; else false + */ + bool operator()(argument_type x) const + { + return in_range(x); + } + + + /** + * Constrain value to range.\n + * This method returns the original value if it is in this range, else + * lower limit if value < lower limit or upper limit if value > upper limit. + * + * \param x value + * \return lower limit <= x <= upper limit + */ + T constrain(argument_type x) const + { + if (compare(x, getLowerLimit())) { return getLowerLimit(); } + if (compare(getUpperLimit(), x)) { return getUpperLimit(); } + + return x; + } + + + /** + * Modulo value with respect to range.\n + * + * \param x value + * \return lower limit <= x <= upper limit + */ + T mod(argument_type x) const + { + if (compare(x, getLowerLimit())) + return x + getLength() * floor((getUpperLimit() - x) / getLength()); + else if (compare(getUpperLimit(), x)) + return x - getLength() * floor((x - getLowerLimit()) / getLength()); + else + return x; + } + + + /** + * Test overlap with given range.\n + * The result is equivalent to join(range).is_valid(). + * + * \param range range + * \return true if there is a non-zero overlap; else false + */ + bool overlap(const range_type& range) const + { + return (compare(getLowerLimit(), range.getUpperLimit()) && + compare(range.getLowerLimit(), getUpperLimit())); + } + + + /** + * Include given value to range.\n + * The new lower limit is the minimim of the original lower limit and given value and\n + * the new upper limit is the maximum of the original upper limit and given value; + * + * \param x value + * \return range + */ + range_type include(argument_type x) + { + if (compare(x, getLowerLimit())) { setLowerLimit(x); } + if (compare(getUpperLimit(), x)) { setUpperLimit(x); } + + return *this; + } + + + /** + * Join ranges.\n + * The new lower limit is the maximim of the two lower limits and\n + * the new upper limit is the minimum of the two upper limits.\n + * This operation results in an equal or smaller range and + * may result in an unphysical range (i.e.\ lower limit > upper limit). + * + * \param range range + */ + range_type& join(const range_type& range) + { + if (compare(getLowerLimit(), range.getLowerLimit())) { setLowerLimit(range.getLowerLimit()); } + if (compare(range.getUpperLimit(), getUpperLimit())) { setUpperLimit(range.getUpperLimit()); } + + return *this; + } + + + /** + * Combine ranges.\n + * The new lower limit is the minimim of the two lower limits and\n + * the new upper limit is the maximum of the two upper limits.\n + * This operation results in an equal or larger range. + * + * \param range range + */ + range_type& combine(const range_type& range) + { + if (compare(range.getLowerLimit(), getLowerLimit())) { setLowerLimit(range.getLowerLimit()); } + if (compare(getUpperLimit(), range.getUpperLimit())) { setUpperLimit(range.getUpperLimit()); } + + return *this; + } + + + /** + * Add offset. + * + * \param x offset + */ + range_type& add(argument_type x) + { + this->first += x; + this->second += x; + + return *this; + } + + + /** + * Subtract offset. + * + * \param x offset + */ + range_type& sub(argument_type x) + { + this->first -= x; + this->second -= x; + + return *this; + } + + + /** + * Add offsets.\n + * The new lower limit is the sum of the two lower limits and\n + * the new upper limit is the sum of the two upper limits. + * + * \param range offset + */ + range_type& add(const range_type& range) + { + this->first += range.getLowerLimit(); + this->second += range.getUpperLimit(); + + return *this; + } + + + /** + * Subtract offsets.\n + * The new lower limit is the difference of the two lower limits and\n + * the new upper limit is the difference of the two upper limits. + * + * \param range offset + */ + range_type& sub(const range_type& range) + { + this->first -= range.getLowerLimit(); + this->second -= range.getUpperLimit(); + + return *this; + } + + + /** + * Multiply range. + * + * \param factor factor + */ + range_type& mul(const double factor) + { + this->first *= factor; + this->second *= factor; + + return *this; + } + + + /** + * Divide range. + * + * \param factor factor + */ + range_type& div(const double factor) + { + this->first /= factor; + this->second /= factor; + + return *this; + } + + + /** + * Get expected number of occurances of given rate within this interval. + * + * \param R rate + * \return expectation value + */ + T getN(const double R) const + { + return R * (getUpperLimit() - getLowerLimit()); + } + + + /** + * Get minimum possible value. + * + * \return minimum possible value + */ + static T getMinimum() + { + return JMATH::JLimits<T>::min(); + } + + + /** + * Get maximum possible value. + * + * \return maximum possible value + */ + static T getMaximum() + { + return JMATH::JLimits<T>::max(); + } + + + /** + * Default range. + * This range corresponds to an unphysical range. + */ + static const JRange<T, JComparator_t> DEFAULT_RANGE; + + + /** + * Function object. + * + * \param first first argument + * \param second second argument + * \return true if first < second; else false + */ + JComparator_t compare; + + protected: + /** + * Set range. + * + * \param first first + * \param second second + * \param option false + */ + template<class R> + void setRange(R first, R second, const JLANG::JBool<false>& option) + { + setRange((argument_type) first, (argument_type) second); + } + + + /** + * Set range. + * + * \param first first + * \param second second + * \param option true + */ + template<class R> + void setRange(R first, R second, const JLANG::JBool<true>& option) + { + setRange(getMaximum(), getMinimum()); + + for (R i = first; i != second; ++i) { + include(*i); + } + } + }; + + + /** + * Default range. + * This range corresponds to an unphysical range. + */ + template<class T, class JComparator_t> + const JRange<T, JComparator_t> JRange<T, JComparator_t>::DEFAULT_RANGE(JRange<T, JComparator_t>::getMaximum(), + JRange<T, JComparator_t>::getMinimum()); + + + /** + * Add ranges.\n + * The new lower limit is the sum of the two lower limits and\n + * the new upper limit is the sum of the two upper limits. + * + * \param first first range + * \param second second range + * \result range + */ + template<class T, class JComparator_t> + inline JRange<T, JComparator_t> operator+(const JRange<T, JComparator_t>& first, const JRange<T, JComparator_t>& second) + { + return JRange<T, JComparator_t>(first).add(second); + } + + + /** + * Subtract ranges.\n + * The new lower limit is the difference of the two lower limits and + * the new upper limit is the difference of the two upper limits. + * + * \param first first range + * \param second second range + * \result range + */ + template<class T, class JComparator_t> + inline JRange<T, JComparator_t> operator-(const JRange<T, JComparator_t>& first, const JRange<T, JComparator_t>& second) + { + return JRange<T, JComparator_t>(first).sub(second); + } + + + /** + * Test overlap between ranges. + * + * \param first first range + * \param second second range + * \return true if there is a non-zero overlap; else false + */ + template<class T, class JComparator_t> + inline bool overlap(const JRange<T, JComparator_t>& first, const JRange<T, JComparator_t>& second) + { + return first.overlap(second); + } + + + /** + * Join ranges.\n + * The new lower limit is the maximim of the two lower limits and\n + * the new upper limit is the minimum of the two upper limits.\n + * This operation results in an equal or smaller range and + * may result in an unphysical range (i.e.\ lower limit > upper limit). + * + * \param first first range + * \param second second range + * \result range + */ + template<class T, class JComparator_t> + inline JRange<T, JComparator_t> join(const JRange<T, JComparator_t>& first, const JRange<T, JComparator_t>& second) + { + return JRange<T, JComparator_t>(first).join(second); + } + + + /** + * Combine ranges.\n + * The new lower limit is the minimim of the two lower limits and\n + * the new upper limit is the maximum of the two upper limits.\n + * This operation results in an equal or larger range. + * + * \param first first range + * \param second second range + * \result range + */ + template<class T, class JComparator_t> + inline JRange<T, JComparator_t> combine(const JRange<T, JComparator_t>& first, const JRange<T, JComparator_t>& second) + { + return JRange<T, JComparator_t>(first).combine(second); + } + + + /** + * Auxiliary method to create range of values. + * + * \param x lower limit + * \param y upper limit + * \return range + */ + template<class T> + inline JRange<T> make_range(T x, T y) + { + return JRange<T>(x,y); + } +} + +#endif diff --git a/jpp/JTools/JResult.hh b/jpp/JTools/JResult.hh new file mode 100644 index 0000000..bd3f3a1 --- /dev/null +++ b/jpp/JTools/JResult.hh @@ -0,0 +1,1043 @@ +#ifndef __JTOOLS__JRESULT__ +#define __JTOOLS__JRESULT__ + +#include <cmath> + +#include "JTools/JRange.hh" +#include "JLang/JClass.hh" +#include "JLang/JAssert.hh" +#include "JMath/JMath.hh" +#include "JMath/JZero.hh" + + +/** + * \file + * + * This include file containes various data structures that + * can be used as specific return types for the interpolating methods. + * These data structures have standard arithmetic capabilities and + * are templated so that they can be expanded in higher dimensions. + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JMATH::JMath; + + + /** + * Data structure for result including value and first derivative of function. + * + * This data structure contains the following data mambers: + * <pre> + * JResultDerivative::f = function value; + * JResultDerivative::fp = first derivative; + * </pre> + * + * This class implements the JMATH::JMath interface. + */ + template<class JResult_t> + struct JResultDerivative : + public JMath< JResultDerivative<JResult_t> > + { + + typedef typename JLANG::JClass<JResult_t>::argument_type argument_type; + + + /** + * Default constructor. + */ + JResultDerivative() : + f (JMATH::zero), + fp (JMATH::zero) + {} + + + /** + * Constructor. + * + * \param f function value + * \param fp first derivative + */ + JResultDerivative(argument_type f, + argument_type fp) : + f (f ), + fp (fp) + {} + + + /** + * Prefix unary minus for function value of PDF. + * + * \return function value of PDF + */ + JResultDerivative& negate() + { + f = -f; + fp = -fp; + + return *this; + } + + + /** + * Addition operator for function value of PDF. + * + * \param value function value of PDF + * \return function value of PDF + */ + JResultDerivative& add(const JResultDerivative& value) + { + f += value.f; + fp += value.fp; + + return *this; + } + + + /** + * Subtraction operator for function value of PDF. + * + * \param value function value of PDF + * \return function value of PDF + */ + JResultDerivative& sub(const JResultDerivative& value) + { + f -= value.f; + fp -= value.fp; + + return *this; + } + + + /** + * Multiplication operator for function value of PDF. + * + * \param value multiplication factor + * \return function value of PDF + */ + JResultDerivative& mul(const double value) + { + f *= value; + fp *= value; + + return *this; + } + + + /** + * Division operator for function value of PDF. + * + * \param value multiplication factor + * \return function value of PDF + */ + JResultDerivative& div(const double value) + { + f /= value; + fp /= value; + + return *this; + } + + + /** + * Get probability.\n + * If the given hit is false (true), the return value corresponds to the Poisson probability + * that zero (one or more) hits occur for the given expectation value JResultDerivative::f. + * + * \param hit hit (or not) + * \return probability + */ + double getP(const bool hit) const + { + if (!hit) + return exp(-f); // probability of 0 hits + else + return 1.0 - getP(false); // probability of 1 or more hits + } + + + /** + * Get chi2. + * The chi2 corresponds to <tt>-log(P)</tt>, where <tt>P</tt> is the probability JResultDerivative::f. + * + * \param hit hit (or not) + * \return chi2 + */ + double getChi2(const bool hit) const + { + if (!hit) + return f; // = -log(getP(false)) + else + return -log(getP(true)); + } + + + /** + * Get derivative of chi2. + * + * \param hit hit (or not) + * \return derivative + */ + double getDerivativeOfChi2(const bool hit) const + { + if (!hit) + return fp; + else + return -fp * getP(false) / getP(true); + } + + + JResult_t f; //!< function value + JResult_t fp; //!< first derivative + }; + + + /** + * Data structure for result including value and first derivative of function. + * + * This data structure contains the following data mambers: + * <pre> + * JResultHesse::f = function value; + * JResultHesse::fp = first derivative; + * JResultHesse::fpp = second derivative; + * </pre> + * + * This class implements the JMATH::JMath interface. + */ + template<class JResult_t> + struct JResultHesse : + public JResultDerivative<JResult_t>, + public JMath< JResultHesse<JResult_t> > + { + + typedef typename JResultDerivative<JResult_t>::argument_type argument_type; + + + /** + * Default constructor. + */ + JResultHesse() : + JResultDerivative<JResult_t>(), + fpp(JMATH::zero) + {} + + + /** + * Constructor. + * + * \param f function value + * \param fp first derivative + * \param fpp second derivative + */ + JResultHesse(argument_type f, + argument_type fp, + argument_type fpp) : + JResultDerivative<JResult_t>(f, fp), + fpp(fpp) + {} + + + /** + * Prefix unary minus for function value of PDF. + * + * \return function value of PDF + */ + JResultHesse& negate() + { + static_cast<JResultDerivative<JResult_t>&>(*this).negate(); + fpp = -fpp; + + return *this; + } + + + /** + * Addition operator for function value of PDF. + * + * \param value function value of PDF + * \return function value of PDF + */ + JResultHesse& add(const JResultHesse& value) + { + static_cast<JResultDerivative<JResult_t>&>(*this).add(value); + fpp += value.fpp; + + return *this; + } + + + /** + * Subtraction operator for function value of PDF. + * + * \param value function value of PDF + * \return function value of PDF + */ + JResultHesse& sub(const JResultHesse& value) + { + static_cast<JResultDerivative<JResult_t>&>(*this).sub(value); + fpp -= value.fpp; + + return *this; + } + + + /** + * Multiplication operator for function value of PDF. + * + * \param value multiplication factor + * \return function value of PDF + */ + JResultHesse& mul(const double value) + { + static_cast<JResultDerivative<JResult_t>&>(*this).mul(value); + fpp *= value; + + return *this; + } + + + /** + * Division operator for function value of PDF. + * + * \param value multiplication factor + * \return function value of PDF + */ + JResultHesse& div(const double value) + { + static_cast<JResultDerivative<JResult_t>&>(*this).div(value); + fpp /= value; + + return *this; + } + + + JResult_t fpp; //!< second derivative + }; + + + /** + * Data structure for result including value, first derivative and integrals of function. + * + * This data structure contains the following data mambers: + * <pre> + * JResultPDF::f = function value; + * JResultPDF::fp = first derivative; + * JResultPDF::v = partial integral; + * JResultPDF::V = complete integral. + * </pre> + * The partial and complete integrals are used to evaluate the probability of the first hit. + * + * This class implements the JMATH::JMath interface. + */ + template<class JResult_t> + struct JResultPDF : + public JMath< JResultPDF<JResult_t> > + { + + typedef typename JLANG::JClass<JResult_t>::argument_type argument_type; + + + /** + * Default constructor. + */ + JResultPDF() : + f (JMATH::zero), + fp(JMATH::zero), + v (JMATH::zero), + V (JMATH::zero) + {} + + + /** + * Constructor. + * + * \param f function value + * \param fp first derivative + * \param v integral <xmin,x] + * \param V integral <xmin,xmax> + */ + JResultPDF(argument_type f, + argument_type fp, + argument_type v, + argument_type V) : + f (f ), + fp(fp), + v (v), + V (V) + {} + + + /** + * Constructor.\n + * This constructor refers to the result of a signal with a constant rate <tt>R</tt> + * to produce an event occuring at the given moment <tt>x</tt> within the fixed range <tt>X</tt>. + * + * \param R rate + * \param x abscissa value + * \param X abscissa range + */ + JResultPDF(argument_type R, + argument_type x, + const JRange<JResult_t>& X) : + f (R), + fp(JMATH::zero), + v (R * (X.constrain(x) - X.getLowerLimit())), + V (R * (X.getUpperLimit() - X.getLowerLimit())) + {} + + + /** + * Prefix unary minus for function value of PDF. + * + * \return function value of PDF + */ + JResultPDF& negate() + { + f = -f; + fp = -fp; + v = -v; + V = -V; + + return *this; + } + + + /** + * Addition operator for function value of PDF. + * + * \param value function value of PDF + * \return function value of PDF + */ + JResultPDF& add(const JResultPDF& value) + { + f += value.f; + fp += value.fp; + v += value.v; + V += value.V; + + return *this; + } + + + /** + * Subtraction operator for function value of PDF. + * + * \param value function value of PDF + * \return function value of PDF + */ + JResultPDF& sub(const JResultPDF& value) + { + f -= value.f; + fp -= value.fp; + v -= value.v; + V -= value.V; + + return *this; + } + + + /** + * Multiplication operator for function value of PDF. + * + * \param value multiplication factor + * \return function value of PDF + */ + JResultPDF& mul(const double value) + { + f *= value; + fp *= value; + v *= value; + V *= value; + + return *this; + } + + + /** + * Division operator for function value of PDF. + * + * \param value division factor + * \return function value of PDF + */ + JResultPDF& div(const double value) + { + f /= value; + fp /= value; + v /= value; + V /= value; + + return *this; + } + + + /** + * Get probability of first hit.\n + * The probability is defined at the moment JResultPDF::f and JResultPDF::v have been evaluated + * and it is normalised to the total interval corresponding to JResultPDF::V. + * + * \return probability + */ + double getP() const + { + return exp(-v) * f / (1.0 - exp(-V)); + } + + + /** + * Get chi2 of first hit.\n + * The chi2 corresponds to <tt>-log(P)</tt>, where <tt>P</tt> is the probability JResultPDF::f. + * + * \return chi2 + */ + double getChi2() const + { + return -log(getP()); + } + + + /** + * Get derivative of chi2 of first hit. + * + * \return derivative + */ + double getDerivativeOfChi2() const + { + return fp/f - f; + } + + + JResult_t f; //!< function value + JResult_t fp; //!< first derivative + JResult_t v; //!< integral <xmin,x] + JResult_t V; //!< integral <xmin,xmax> + }; + + + /** + * Data structure for result including value and <tt>N</tt> derivatives of function. + * + * This data structure contains the following data mambers: + * <pre> + * JResultPolynome::y[0] = function value; + * JResultPolynome::y[i] = ith derivative; + * JResultPolynome::y[N] = Nth derivative; + * </pre> + * + * This class implements the JMATH::JMath interface. + */ + template<unsigned int N, class JResult_t> + struct JResultPolynome : + public JMath< JResultPolynome<N, JResult_t> > + { + + typedef typename JLANG::JClass<JResult_t>::argument_type argument_type; + + static const int NUMBER_OF_POINTS = N + 1; // number of points (starting at 0) + + + /** + * Default constructor. + */ + JResultPolynome() + { + for (int i = 0; i != NUMBER_OF_POINTS; ++i) { + y[i] = JMATH::zero; + } + } + + + /** + * Type conversion operator. + * + * \return result + */ + operator JResultDerivative<JResult_t>() const + { + STATIC_CHECK(NUMBER_OF_POINTS >= 2); + return JResultDerivative<JResult_t>(y[0], y[1]); + } + + + /** + * Type conversion operator. + * + * \return result + */ + operator JResultHesse<JResult_t>() const + { + STATIC_CHECK(NUMBER_OF_POINTS >= 3); + return JResultHesse<JResult_t>(y[0], y[1], y[2]); + } + + + /** + * Prefix unary minus for function value of PDF. + * + * \return function value of PDF + */ + JResultPolynome& negate() + { + for (int i = 0; i != NUMBER_OF_POINTS; ++i) { + y[i] = -y[i]; + } + + return *this; + } + + + /** + * Addition operator for function value of PDF. + * + * \param value function value of PDF + * \return function value of PDF + */ + JResultPolynome& add(const JResultPolynome& value) + { + for (int i = 0; i != NUMBER_OF_POINTS; ++i) { + y[i] += value.y[i]; + } + + return *this; + } + + + /** + * Subtraction operator for function value of PDF. + * + * \param value function value of PDF + * \return function value of PDF + */ + JResultPolynome& sub(const JResultPolynome& value) + { + for (int i = 0; i != NUMBER_OF_POINTS; ++i) { + y[i] -= value.y[i]; + } + + return *this; + } + + + /** + * Multiplication operator for function value of PDF. + * + * \param value multiplication factor + * \return function value of PDF + */ + JResultPolynome& mul(const double value) + { + for (int i = 0; i != NUMBER_OF_POINTS; ++i) { + y[i] *= value; + } + + return *this; + } + + + /** + * Division operator for function value of PDF. + * + * \param value multiplication factor + * \return function value of PDF + */ + JResultPolynome& div(const double value) + { + for (int i = 0; i != NUMBER_OF_POINTS; ++i) { + y[i] /= value; + } + + return *this; + } + + + /** + * Function value. + * + * \param x abscissa value + * \return function value + */ + double getValue(const double x) const + { + double w = 0.0; + double z = 1.0; + + for (int i = 0; i != NUMBER_OF_POINTS; ++i, z *= x / i) { + w += y[i] * z; + } + + return w; + } + + + /** + * Function value. + * + * \param x abscissa value + * \return function value + */ + double operator()(const double x) const + { + return getValue(x); + } + + + JResult_t y[NUMBER_OF_POINTS]; //!< function and derivative values + }; + + + /** + * Auxiliary class to recursively evaluate to a result. + */ + template<class T> + struct JResultEvaluator + { + typedef T result_type; + + /** + * Get function value. + * + * \return result + */ + static result_type get_value(typename JLANG::JClass<T>::argument_type value) + { + return value; + } + + /** + * Get derivative value. + * + * \return result + */ + static result_type get_derivative(typename JLANG::JClass<T>::argument_type value) + { + return value; + } + + /** + * Get partial integral value. + * + * \return result + */ + static result_type get_integral(typename JLANG::JClass<T>::argument_type value) + { + return value; + } + + /** + * Get total integral value. + * + * \return result + */ + static result_type get_total_integral(typename JLANG::JClass<T>::argument_type value) + { + return value; + } + }; + + + /** + * Template specialisation of JResultEvaluator for JResultDerivative. + */ + template<class T> + struct JResultEvaluator< JResultDerivative<T> > + { + typedef typename JResultEvaluator<T>::result_type result_type; + + /** + * Get function value. + * + * \return result + */ + static result_type get_value(const JResultDerivative<T>& value) + { + return JResultEvaluator<T>::get_value(value.f); + } + + /** + * Get derivative value. + * + * \return result + */ + static result_type get_derivative(const JResultDerivative<T>& value) + { + return JResultEvaluator<T>::get_value(value.fp); + } + + /** + * Get partial integral value. + * + * \return result + */ + static result_type get_integral(const JResultDerivative<T>& value) + { + return JMATH::zero; + } + + /** + * Get total integral value. + * + * \return result + */ + static result_type get_total_integral(typename JLANG::JClass<T>::argument_type value) + { + return JMATH::zero; + } + }; + + + /** + * Template specialisation of JResultEvaluator for JResultHesse. + */ + template<class T> + struct JResultEvaluator< JResultHesse<T> > + { + typedef typename JResultEvaluator<T>::result_type result_type; + + /** + * Get function value. + * + * \return result + */ + static result_type get_value(const JResultHesse<T>& value) + { + return JResultEvaluator<T>::get_value(value.f); + } + + /** + * Get derivative value. + * + * \return result + */ + static result_type get_derivative(const JResultHesse<T>& value) + { + return JResultEvaluator<T>::get_value(value.fp); + } + + /** + * Get partial integral value. + * + * \return result + */ + static result_type get_integral(const JResultHesse<T>& value) + { + return JMATH::zero; + } + + /** + * Get total integral value. + * + * \return result + */ + static result_type get_total_integral(typename JLANG::JClass<T>::argument_type value) + { + return JMATH::zero; + } + }; + + + /** + * Template specialisation of JResultEvaluator for JResultPDF. + */ + template<class T> + struct JResultEvaluator< JResultPDF<T> > + { + typedef typename JResultEvaluator<T>::result_type result_type; + + /** + * Get function value. + * + * \return result + */ + static result_type get_value(const JResultPDF<T>& value) + { + return JResultEvaluator<T>::get_value(value.f); + } + + /** + * Get derivative value. + * + * \return result + */ + static result_type get_derivative(const JResultPDF<T>& value) + { + return JResultEvaluator<T>::get_value(value.fp); + } + + /** + * Get partial integral value. + * + * \return result + */ + static result_type get_integral(const JResultPDF<T>& value) + { + return JResultEvaluator<T>::get_value(value.v); + } + + /** + * Get total integral value. + * + * \return result + */ + static result_type get_total_integral(typename JLANG::JClass<T>::argument_type value) + { + return JResultEvaluator<T>::get_value(value.V); + } + }; + + + /** + * Template specialisation of JResultEvaluator for JResultPolynome. + */ + template<unsigned int N, class T> + struct JResultEvaluator< JResultPolynome<N, T> > + { + typedef typename JResultEvaluator<T>::result_type result_type; + + /** + * Get function value. + * + * \return result + */ + static result_type get_value(const JResultPolynome<N, T>& value) + { + return JResultEvaluator<T>::get_value(value.y[0]); + } + + /** + * Get derivative value. + * + * \return result + */ + static result_type get_derivative(const JResultPolynome<N, T>& value) + { + return JResultEvaluator<T>::get_value(value.y[1]); + } + + /** + * Get partial integral value. + * + * \return result + */ + static result_type get_integral(const JResultPolynome<N, T>& value) + { + return JMATH::zero; + } + + /** + * Get total integral value. + * + * \return result + */ + static result_type get_total_integral(typename JLANG::JClass<T>::argument_type value) + { + return JMATH::zero; + } + }; + + + /** + * Template specialisation of JResultEvaluator for JResultPolynome. + */ + template<class T> + struct JResultEvaluator< JResultPolynome<0, T> > + { + typedef typename JResultEvaluator<T>::result_type result_type; + + /** + * Get function value. + * + * \return result + */ + static result_type get_value(const JResultPolynome<0, T>& value) + { + return JResultEvaluator<T>::get_value(value.y[0]); + } + + /** + * Get derivative value. + * + * \return result + */ + static result_type get_derivative(const JResultPolynome<0, T>& value) + { + return JMATH::zero; + } + + /** + * Get partial integral value. + * + * \return result + */ + static result_type get_integral(const JResultPolynome<0, T>& value) + { + return JMATH::zero; + } + + /** + * Get total integral value. + * + * \return result + */ + static result_type get_total_integral(typename JLANG::JClass<T>::argument_type value) + { + return JMATH::zero; + } + }; + + + /** + * Helper method to recursively evaluate a to function value. + * + * \param value result + * \return function value + */ + template<class JResult_t> + inline typename JResultEvaluator<JResult_t>::result_type get_value(const JResult_t& value) + { + return JResultEvaluator<JResult_t>::get_value(value); + } + + + /** + * Helper method to convert function value to derivative value. + * + * \param value result + * \return derivative value + */ + template<class JResult_t> + inline typename JResultEvaluator<JResult_t>::result_type get_derivative(const JResult_t& value) + { + return JResultEvaluator<JResult_t>::get_derivative(value); + } + + + /** + * Helper method to convert function value to partial integral value. + * + * \param value result + * \return partial integral value + */ + template<class JResult_t> + inline typename JResultEvaluator<JResult_t>::result_type get_integral(const JResult_t& value) + { + return JResultEvaluator<JResult_t>::get_integral(value); + } + + + /** + * Helper method to convert function value to total integral value. + * + * \param value result + * \return total integral value + */ + template<class JResult_t> + inline typename JResultEvaluator<JResult_t>::result_type get_total_integral(const JResult_t& value) + { + return JResultEvaluator<JResult_t>::get_total_integral(value); + } +} + +#endif diff --git a/jpp/JTools/JResultTransformer.hh b/jpp/JTools/JResultTransformer.hh new file mode 100644 index 0000000..ea8ac14 --- /dev/null +++ b/jpp/JTools/JResultTransformer.hh @@ -0,0 +1,87 @@ +#ifndef __JTOOLS__JRESULTTRANSFORMER__ +#define __JTOOLS__JRESULTTRANSFORMER__ + +#include "JTools/JMultiMapTransformer.hh" +#include "JTools/JResult.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + /** + * Auxiliary class to handle multidimensional map transformations for given result type. + */ + template<class JResult_t> + struct JResultTransformer { + + typedef JResult_t result_type; + + template<unsigned int N, class JArgument_t> + static result_type transform(const JMultiMapTransformer<N, JArgument_t>& transformer, + typename JMultiMapTransformer<N, JArgument_t>::const_array_type array, + const result_type& result) + { + return result; + } + }; + + + /** + * Auxiliary class to handle multidimensional map transformations for given result type. + */ + template<class JResult_t> + struct JResultTransformer< JResultHesse<JResult_t> > { + + typedef JResultHesse<JResult_t> result_type; + + template<unsigned int N, class JArgument_t> + static result_type transform(const JMultiMapTransformer<N, JArgument_t>& transformer, + typename JMultiMapTransformer<N, JArgument_t>::const_array_type array, + const result_type& result) + { + const JArgument_t z = transformer.getXn(array, 1.0) - transformer.getXn(array, 0.0); + + result_type value(result); + + value.fp /= z; + + return value; + } + }; + + + /** + * Auxiliary class to handle multidimensional map transformations for given result type. + */ + template<class JResult_t> + struct JResultTransformer< JResultPDF<JResult_t> > { + + typedef JResultPDF<JResult_t> result_type; + + template<unsigned int N, class JArgument_t> + static result_type transform(const JMultiMapTransformer<N, JArgument_t>& transformer, + typename JMultiMapTransformer<N, JArgument_t>::const_array_type array, + const result_type& result) + { + typedef JArgument_t argument_type; + + const argument_type z = transformer.getXn(array, 1.0) - transformer.getXn(array, 0.0); + + result_type value(result); + + value.fp /= z; + value.v *= z; + value.V *= z; + + return value; + } + }; +} + +#endif diff --git a/jpp/JTools/JSet.hh b/jpp/JTools/JSet.hh new file mode 100644 index 0000000..b5a90c9 --- /dev/null +++ b/jpp/JTools/JSet.hh @@ -0,0 +1,163 @@ +#ifndef __JTOOLS__JSET__ +#define __JTOOLS__JSET__ + +#include <set> +#include <iterator> + +#include "JTools/JAbstractCollection.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + template<class JElement_t, class JDistance_t> + class JCollection; + + + /** + * Simple data structure for an abstract collection of non-equidistant abscissa values. + * + * This class implements the JAbstractCollection interface. + */ + template<class JAbscissa_t> + struct JSet : + public JAbstractCollection<JAbscissa_t>, + std::set <JAbscissa_t> + { + typedef typename JAbstractCollection<JAbscissa_t>::abscissa_type abscissa_type; + + + /** + * Default constructor. + */ + JSet() + {} + + + /** + * Constructor. + * + * \param collection abstract collection + */ + JSet(const JAbstractCollection<abscissa_type>& collection) + { + for (int i = 0; i != collection.getSize(); ++i) { + this->insert(collection.getX(i)); + } + } + + + /** + * Constructor. + * + * \param __begin begin of abscissa values + * \param __end end of abscissa values + */ + template<class T> + JSet(T __begin, T __end) + { + for (T i = __begin; i != __end; ++i) { + this->insert(*i); + } + } + + + /** + * Get number of elements. + * + * \return number of elements + */ + virtual int getSize() const override + { + return (int) this->size(); + } + + + /** + * Get abscissa value. + * + * \param index index + * \return abscissa value + */ + virtual abscissa_type getX(int index) const override + { + typename std::set<abscissa_type>::const_iterator i = this->begin(); + + std::advance(i, index); + + return *i; + } + + + /** + * Get minimal abscissa value. + * + * \return abscissa value + */ + virtual abscissa_type getXmin() const override + { + return *(this->begin()); + } + + + /** + * Get maximal abscissa value. + * + * \return abscissa value + */ + virtual abscissa_type getXmax() const override + { + return *(this->rbegin()); + } + + + /** + * Configure collection. + * + * \param collection collection + * \return this set + */ + template<class JElement_t, class JDistance_t> + const JSet& operator()(JCollection<JElement_t, JDistance_t>& collection) const + { + collection.configure(*this); + + return *this; + } + }; + + + /** + * Helper method for JSet. + * + * \param __begin begin of abscissa values + * \param __end end of abscissa values + * \return set + */ + template<class T> + inline JSet<typename std::iterator_traits<T>::value_type> make_set(T __begin, T __end) + { + return JSet<typename std::iterator_traits<T>::value_type>(__begin, __end); + } + + + /** + * Helper method for JSet. + * + * \param input abstract collection + * \return set + */ + template<class JAbscissa_t> + inline JSet<JAbscissa_t> make_set(const JAbstractCollection<JAbscissa_t>& input) + { + return JSet<JAbscissa_t>(input); + } +} + +#endif diff --git a/jpp/JTools/JSpline.hh b/jpp/JTools/JSpline.hh new file mode 100644 index 0000000..cfd7843 --- /dev/null +++ b/jpp/JTools/JSpline.hh @@ -0,0 +1,865 @@ +#ifndef __JTOOLS__JSPLINE__ +#define __JTOOLS__JSPLINE__ + +#include <utility> + +#include "JMath/JZero.hh" +#include "JLang/JException.hh" +#include "JLang/JClass.hh" +#include "JTools/JFunctional.hh" +#include "JTools/JDistance.hh" +#include "JTools/JResult.hh" +#include "JTools/JMapCollection.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JLANG::JNoValue; + using JLANG::JDivisionByZero; + using JLANG::JFunctionalException; + using JLANG::JValueOutOfRange; + + + /** + * Auxiliary class to define first derivates of the spline function at the two extrema. + */ + template<class JOrdinate_t> + class JSplineBounds { + public: + + typedef JOrdinate_t ordinate_type; + typedef typename JLANG::JClass<ordinate_type>::argument_type argument_type; + + + /** + * Default constructor. + */ + JSplineBounds() : + fp_at_xmin(false, ordinate_type()), + fp_at_xmax(false, ordinate_type()) + {} + + + /** + * Constructor. + * + * \param fpAtXmin 1st derivative at minimal abscissa value + * \param fpAtXmax 1st derivative at maximal abscissa value + */ + JSplineBounds(argument_type fpAtXmin, + argument_type fpAtXmax) : + fp_at_xmin(true, fpAtXmin), + fp_at_xmax(true, fpAtXmax) + {} + + + /** + * Set first derivative of function at minimal abscissa value. + * + * \param fp 1st derivative + */ + void setFirstDerivativeAtXmin(argument_type fp) + { + fp_at_xmin.first = true; + fp_at_xmin.second = fp; + } + + + /** + * Set first derivative of function at maximal abscissa value. + * + * \param fp 1st derivative + */ + void setFirstDerivativeAtXmax(argument_type fp) + { + fp_at_xmax.first = true; + fp_at_xmax.second = fp; + } + + + /** + * Has first derivative of function at minimal abscissa value. + * + * \return true if 1st derivative is set; else false + */ + const bool& hasFirstDerivativeAtXmin() const + { + return fp_at_xmin.first; + } + + + /** + * Has first derivative of function at maximal abscissa value. + * + * \return true if 1st derivative is set; else false + */ + const bool& hasFirstDerivativeAtXmax() const + { + return fp_at_xmax.first; + } + + + /** + * Get first derivative of function at minimal abscissa value. + * + * \return 1st derivative + */ + ordinate_type getFirstDerivativeAtXmin() const + { + if (fp_at_xmin.first) + return fp_at_xmin.second; + else + throw JNoValue("JSplineBounds: missing 1st derivative."); + } + + + /** + * Get first derivative of function at maximal abscissa value. + * + * \return 1st derivative + */ + ordinate_type getFirstDerivativeAtXmax() const + { + if (fp_at_xmax.first) + return fp_at_xmax.second; + else + throw JNoValue("JSplineBounds: missing 1st derivative."); + } + + protected: + std::pair<bool, ordinate_type> fp_at_xmin; + std::pair<bool, ordinate_type> fp_at_xmax; + }; + + + /** + * Helper method for JSplineBounds. + * + * \param fpAtXmin 1st derivative at minimal abscissa value + * \param fpAtXmax 1st derivative at maximal abscissa value + * \return spline bounds + */ + template<class JOrdinate_t> + inline JSplineBounds<JOrdinate_t> make_spline_bounds(const JOrdinate_t fpAtXmin, + const JOrdinate_t fpAtXmax) + { + return JSplineBounds<JOrdinate_t>(fpAtXmin, fpAtXmax); + } + + + /** + * Template base class for spline interpolations. + * + * This class partially implements the JFunctional interface. + * + * Note that the data structure of the elements in the collection should have the additional methods: + * <pre> + * ordinate_type getU() const; + * void setU(ordinate_type u); + * </pre> + * to get and set the second derivatives, respectively. + * + * Spline interpolation code is taken from reference: + * Numerical Recipes in C++, W.H. Press, S.A. Teukolsky, W.T. Vetterling and B.P. Flannery, + * Cambridge University Press. + */ + template<class JElement_t, template<class, class> class JCollection_t, class JDistance_t> + class JSplineCollection : + public JCollection_t<JElement_t, JDistance_t>, + public virtual JFunctional<> + { + public: + + typedef JCollection_t<JElement_t, JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + using JFunctional<>::compile; + + + /** + * Determination of second derivatives with specified bounds. + * + * \param bounds 1st derivatives at two extrema. + */ + void compile(const JSplineBounds<ordinate_type>& bounds) + { + const int numberOfElements = this->size(); + + using namespace std; + + if (numberOfElements > 2) { + + std::vector<double> buffer(numberOfElements); + + if (bounds.hasFirstDerivativeAtXmin()) { + + iterator j = this->begin(); + iterator i = j++; + + const double dx = this->getDistance(i->getX(), j->getX()); + const ordinate_type dy = (j->getY() - i->getY()); + + buffer[0] = -0.5; + + i->setU((3.0/dx) * (dy/dx - bounds.getFirstDerivativeAtXmin())); + + } else { + + buffer[0] = 0.0; + + this->begin()->setU(JMATH::zero); + } + + int index = 1; + + for (iterator k = this->begin(), i = k++, j = k++; k != this->end(); ++i, ++j, ++k, ++index) { + + const abscissa_type x1 = i->getX(); + const abscissa_type x2 = j->getX(); + const abscissa_type x3 = k->getX(); + + const ordinate_type& y1 = i->getY(); + const ordinate_type& y2 = j->getY(); + const ordinate_type& y3 = k->getY(); + + const double sig = this->getDistance(x1, x2) / this->getDistance(x1, x3); + const double h = sig * buffer[index-1] + 2.0; + + buffer[index] = (sig - 1.0) / h; + + j->setU((y3 - y2) / this->getDistance(x2, x3) - + (y2 - y1) / this->getDistance(x1, x2)); + + j->setU((6.0 * j->getU() / this->getDistance(x1, x3) - sig * i->getU()) / h); + } + + + if (bounds.hasFirstDerivativeAtXmax()) { + + reverse_iterator j = this->rbegin(); + reverse_iterator i = j++; + + index = numberOfElements - 2; + + const double dx = this->getDistance(i->getX(), j->getX()); + const ordinate_type dy = (j->getY() - i->getY()); + + i->setU((3.0/dx) * (bounds.getFirstDerivativeAtXmax() - dy/dx)); + + i->setU((i->getU() - 0.5*j->getU()) / (0.5*buffer[index] + 1.0)); + + } else { + + this->rbegin()->setU(JMATH::zero); + } + + + reverse_iterator j = this->rbegin(); + reverse_iterator i = j++; + + index = numberOfElements - 2; + + for ( ; j != this->rend(); ++i, ++j, --index) { + j->setU(j->getU() + i->getU() * buffer[index]); + } + + } else { + + for (iterator i = this->begin(); i != this->end(); ++i) { + i->setU(JMATH::zero); + } + } + } + + + protected: + /** + * Default constructor. + */ + JSplineCollection() + {} + + + /** + * Determination of second derivatives with no bounds. + */ + virtual void do_compile() override + { + compile(JSplineBounds<ordinate_type>()); + } + }; + + + /** + * Template definition for functional collection with spline interpolation. + */ + template<class JElement_t, + template<class, class> class JCollection_t, + class JResult_t, + class JDistance_t> + class JSplineFunction; + + + /** + * Template specialisation for functional collection with spline interpolation. + */ + template<class JElement_t, template<class, class> class JCollection_t, class JDistance_t> + class JSplineFunction<JElement_t, + JCollection_t, + typename JResultType<typename JElement_t::ordinate_type>::result_type, + JDistance_t> : + public JSplineCollection<JElement_t, JCollection_t, JDistance_t>, + public JFunction<typename JElement_t::abscissa_type, + typename JResultType<typename JElement_t::ordinate_type>::result_type> + { + public: + + typedef JSplineCollection<JElement_t, JCollection_t, JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef typename JResultType<ordinate_type>::result_type data_type; + typedef JFunction<abscissa_type, data_type> function_type; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::JExceptionHandler exceptionhandler_type; + + + /** + * Default constructor. + */ + JSplineFunction() + {} + + + /** + * Recursive interpolation method implementation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const override + { + if (this->size() <= 1u) { + return this->getExceptionHandler().action(JFunctionalException("JSplineFunction<>::evaluate() not enough data.")); + } + + const argument_type x = *pX; + + const_iterator p = this->lower_bound(x); + + if ((p == this->begin() && this->getDistance(x, (p++)->getX()) > distance_type::precision) || + (p == this->end() && this->getDistance((--p)->getX(), x) > distance_type::precision)) { + + return this->getExceptionHandler().action(JValueOutOfRange("JSplineFunction::evaluate() x out of range.")); + } + + const_iterator q = p--; + + const double dx = this->getDistance(p->getX(), q->getX()); + const double a = this->getDistance(x, q->getX()) / dx; + const double b = 1.0 - a; + + return a * p->getY() + b * q->getY() + - a*b * ((a + 1.0)*p->getU() + (b + 1.0)*q->getU()) * dx*dx/6; + } + }; + + + /** + * Template specialisation for spline interpolation method with returning JResultDerivative data structure. + */ + template<class JElement_t, template<class, class> class JCollection_t, class JDistance_t> + class JSplineFunction<JElement_t, + JCollection_t, + JResultDerivative<typename JResultType<typename JElement_t::ordinate_type>::result_type>, + JDistance_t> : + public JSplineCollection<JElement_t, JCollection_t, JDistance_t>, + public JFunction<typename JElement_t::abscissa_type, + JResultDerivative<typename JResultType<typename JElement_t::ordinate_type>::result_type> > + { + public: + + typedef JSplineCollection<JElement_t, JCollection_t, JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef typename JResultType<ordinate_type>::result_type data_type; + typedef JFunction<abscissa_type, JResultDerivative<data_type> > function_type; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::JExceptionHandler exceptionhandler_type; + + using JFunctional<>::compile; + + + /** + * Default constructor. + */ + JSplineFunction() + {} + + + /** + * Recursive interpolation method implementation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const override + { + if (this->size() <= 1u) { + return this->getExceptionHandler().action(JFunctionalException("JSplineFunction<>::evaluate() not enough data.")); + } + + const argument_type x = *pX; + + const_iterator p = this->lower_bound(x); + + + if ((p == this->begin() && this->getDistance(x, (p++)->getX()) > distance_type::precision) || + (p == this->end() && this->getDistance((--p)->getX(), x) > distance_type::precision)) { + + return this->getExceptionHandler().action(JValueOutOfRange("JSplineFunction::evaluate() x out of range.")); + } + + const_iterator q = p--; + + const double dx = this->getDistance(p->getX(), q->getX()); + const double a = this->getDistance(x, q->getX()) / dx; + const double b = 1.0 - a; + + result.f = a * p->getY() + b * q->getY() + - a*b * ((a + 1.0)*p->getU() + (b + 1.0)*q->getU()) * dx*dx/6; + + result.fp = (q->getY() - p->getY() + (p->getU()*(1.0 - 3*a*a) - + q->getU()*(1.0 - 3*b*b)) * dx*dx/6) / dx; + + return result; + } + + + private: + mutable result_type result; + }; + + + /** + * Template specialisation for spline interpolation method with returning JResultPDF data structure. + * + * Note that the data structure of the elements in the collection should have the additional methods: + * <pre> + * ordinate_type getIntegral() const; + * void setIntegral(ordinate_type v); + * </pre> + * to get and set the integral values, respectively. + */ + template<class JElement_t, template<class, class> class JCollection_t, class JDistance_t> + class JSplineFunction<JElement_t, + JCollection_t, + JResultPDF<typename JResultType<typename JElement_t::ordinate_type>::result_type>, + JDistance_t> : + public JSplineCollection<JElement_t, JCollection_t, JDistance_t>, + public JFunction<typename JElement_t::abscissa_type, + JResultPDF<typename JResultType<typename JElement_t::ordinate_type>::result_type> > + { + public: + + typedef JSplineCollection<JElement_t, JCollection_t, JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef typename JResultType<ordinate_type>::result_type data_type; + typedef JFunction<abscissa_type, JResultPDF<data_type> > function_type; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::JExceptionHandler exceptionhandler_type; + + using JFunctional<>::compile; + + + /** + * Default constructor. + */ + JSplineFunction() + {} + + + /** + * Determination of second derivatives with specified bounds. + * + * \param bounds 1st derivatives at two extrema. + */ + void compile(const JSplineBounds<ordinate_type>& bounds) + { + if (this->size() >= 2u) { + + collection_type::compile(bounds); + + this->begin()->setIntegral(JMATH::zero); + + for (iterator j = this->begin(), i = j++; j != this->end(); ++i, ++j) { + + const double dx = this->getDistance(i->getX(), j->getX()); + const ordinate_type y = i->getY() + j->getY(); + const ordinate_type z = i->getU() + j->getU(); + + const ordinate_type v = dx * 0.50 * y; + const ordinate_type w = dx * 0.25 * z*dx*dx/6; + + j->setIntegral(i->getIntegral() + v - w); + } + } + } + + + /** + * Recursive interpolation method implementation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const override + { + if (this->size() <= 1u) { + return this->getExceptionHandler().action(JFunctionalException("JSplineFunction<>::evaluate() not enough data.")); + } + + const argument_type x = *pX; + + const_iterator p = this->lower_bound(x); + + if (p == this->begin() && this->getDistance(x, (p++)->getX()) > distance_type::precision) { + + try { + + result = this->getExceptionHandler().action(JValueOutOfRange("JSplineFunction<>::operator() x < xmin.")); + + // overwrite integral values + + result.v = 0; + result.V = this->rbegin()->getIntegral(); + + } catch(const JValueOutOfRange& exception) { + throw exception; + } + + return result; + + } else if (p == this->end() && this->getDistance((--p)->getX(), x) > distance_type::precision) { + + try { + + result = this->getExceptionHandler().action(JValueOutOfRange("JSplineFunction<>::operator() x > xmax.")); + + // overwrite integral values + + result.v = this->rbegin()->getIntegral(); + result.V = this->rbegin()->getIntegral(); + + } catch(const JValueOutOfRange& exception) { + throw exception; + } + + return result; + } + + const_iterator q = p--; + + const double dx = this->getDistance(p->getX(), q->getX()); + const double a = this->getDistance(x, q->getX()) / dx; + const double b = 1.0 - a; + + result.f = a * p->getY() + b * q->getY() + - a*b * ((a + 1.0)*p->getU() + (b + 1.0)*q->getU()) * dx*dx/6; + + result.fp = (q->getY() - p->getY() + (p->getU()*(1.0 - 3*a*a) - + q->getU()*(1.0 - 3*b*b)) * dx*dx/6) / dx; + + result.v = p->getIntegral() + + 0.5*dx * (p->getY() - 0.5*p->getU()*dx*dx/6) + - 0.5*dx * ((a*a*p->getY() - b*b*q->getY()) + + (p->getU() * a*a*(0.5*a*a - 1.0) - + q->getU() * b*b*(0.5*b*b - 1.0)) * dx*dx/6); + + result.V = this->rbegin()->getIntegral(); + + return result; + } + + + protected: + /** + * Determination of second derivatives with no bounds. + */ + virtual void do_compile() override + { + compile(JSplineBounds<ordinate_type>()); + } + + + private: + mutable result_type result; + }; + + + /** + * Template class for spline interpolation in 1D + * + * This class implements the JFunction1D interface. + */ + template<class JElement_t, + template<class, class> class JCollection_t, + class JResult_t = typename JElement_t::ordinate_type, + class JDistance_t = JDistance<typename JElement_t::abscissa_type> > + class JSplineFunction1D : + public JSplineFunction<JElement_t, JCollection_t, JResult_t, JDistance_t>, + public JFunction1D<typename JElement_t::abscissa_type, JResult_t> + { + public: + + typedef JSplineCollection<JElement_t, JCollection_t, JDistance_t> collection_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef JFunction1D<abscissa_type, JResult_t> function_type; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::JExceptionHandler exceptionhandler_type; + + + /** + * Default contructor. + */ + JSplineFunction1D() + {} + }; + + + /** + * \cond NEVER + * Forward declarations. + * \endcond + */ + template<class JAbscissa_t, class JOrdinate_t> + struct JSplineElement2D; + + template<template<class, class, class> class JMap_t> + struct JMapCollection; + + + /** + * Functional map with spline interpolation. + */ + template<class JKey_t, + class JValue_t, + template<class, class, class> class JMap_t, + class JResult_t, + class JDistance_t = JDistance<JKey_t> > + class JSplineMap : + public JMap_t<JKey_t, JValue_t, JDistance_t>, + public JFunction<JKey_t, JResult_t> + { + public: + + typedef JMap_t<JKey_t, JValue_t, JDistance_t> collection_type; + typedef JFunction<JKey_t, JResult_t> function_type; + + typedef typename collection_type::abscissa_type abscissa_type; + typedef typename collection_type::ordinate_type ordinate_type; + typedef typename collection_type::value_type value_type; + typedef typename collection_type::distance_type distance_type; + + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::const_reverse_iterator const_reverse_iterator; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::reverse_iterator reverse_iterator; + + typedef typename function_type::argument_type argument_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::JExceptionHandler exceptionhandler_type; + + typedef typename JResultType<ordinate_type>::result_type data_type; + typedef JSplineFunction1D<JSplineElement2D<argument_type, data_type>, + JMapCollection<JMap_t>::template collection_type, + result_type> JSplineFunction1D_t; + + + /** + * Default constructor. + */ + JSplineMap() + {} + + + /** + * Recursive interpolation method implementation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const override + { + const argument_type x = *pX; + + ++pX; // next argument value + + const_iterator p = this->begin(); + + for (typename JSplineFunction1D_t::iterator q = buffer.begin(); q != buffer.end(); ++q, ++p) { + q->getY() = JFunction<argument_type, data_type>::getValue(p->getY(), pX); + } + + buffer.compile(); + + return buffer(x); + } + + + private: + /** + * Function compilation. + */ + virtual void do_compile() override + { + buffer.clear(); + + for (iterator i = this->begin(); i != this->end(); ++i) { + buffer.put(i->getX(), data_type()); + } + } + + + mutable JSplineFunction1D_t buffer; + }; + + + /** + * Conversion of data points to integral values. + * + * The integration includes the use of 2nd derivatives of the data points of the input spline interpolating function. + * + * \param input collection + * \param output mappable collection + * \return integral + */ + template<class JElement_t, + template<class, class> class JCollection_t, + class JResult_t, + class JDistance_t> + inline typename JElement_t::ordinate_type + integrate(const JSplineFunction1D<JElement_t, JCollection_t, JResult_t, JDistance_t>& input, + typename JMappable<JElement_t>::map_type& output) + { + typedef typename JElement_t::ordinate_type ordinate_type; + typedef typename JSplineFunction1D<JElement_t, JCollection_t, JResult_t, JDistance_t>::const_iterator const_iterator; + + ordinate_type V(JMATH::zero); + + if (input.getSize() > 1) { + + output.put(input.begin()->getX(), V); + + for (const_iterator j = input.begin(), i = j++; j != input.end(); ++i, ++j) { + + const double dx = input.getDistance(i->getX(), j->getX()); + const ordinate_type y = i->getY() + j->getY(); + const ordinate_type z = i->getU() + j->getU(); + const ordinate_type v = dx * 0.50 * y; + const ordinate_type w = dx * 0.25 * z*dx*dx/6; + + V += v - w; + + output.put(j->getX(), V); + } + } + + return V; + } + + + /** + * Conversion of data points to integral values. + * + * The integration directly uses the integral values of the input spline interpolating function. + * + * \param input collection + * \param output mappable collection + * \return integral + */ + template<class JElement_t, + template<class, class> class JCollection_t, + class JDistance_t> + inline typename JElement_t::ordinate_type + integrate(const JSplineFunction1D<JElement_t, JCollection_t, JResultPDF<typename JElement_t::ordinate_type>, JDistance_t>& input, + typename JMappable<JElement_t>::map_type& output) + { + typedef typename JElement_t::ordinate_type ordinate_type; + typedef JResultPDF<ordinate_type> result_type; + typedef typename JSplineFunction1D<JElement_t, JCollection_t, result_type, JDistance_t>::const_iterator const_iterator; + + if (input.getSize() > 1) { + + for (const_iterator i = input.begin(); i != input.end(); ++i) { + output.put(i->getX(), i->getIntegral()); + } + + return input.rbegin()->getIntegral(); + } + + return JMATH::zero; + } +} + +#endif diff --git a/jpp/JTools/JToolsToolkit.hh b/jpp/JTools/JToolsToolkit.hh new file mode 100644 index 0000000..6b81ae5 --- /dev/null +++ b/jpp/JTools/JToolsToolkit.hh @@ -0,0 +1,352 @@ +#ifndef __JTOOLS__JTOOLSTOOLKIT__ +#define __JTOOLS__JTOOLSTOOLKIT__ + +#include "JLang/JException.hh" +#include "JLang/JBool.hh" +#include "JMath/JZero.hh" +#include "JTools/JAssembler.hh" +#include "JTools/JElement.hh" +#include "JTools/JCollection.hh" +#include "JTools/JGarbageCollection.hh" +#include "JTools/JMultiFunction.hh" +#include "JTools/JMultiHistogram.hh" +#include "JTools/JFunctionalMap.hh" + + +/** + * \file + * + * This include file contains various recursive methods to operate on multi-dimensional collections. + * \author mdejong + */ +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +/** + * Auxiliary classes and methods for multi-dimensional interpolations and histograms. + */ +namespace JTOOLS { + + using JLANG::JException; + using JLANG::JEmptyCollection; + using JLANG::JDivisionByZero; + using JLANG::JBool; + + + /** + * Conversion of data points to cumulative probability distribition (CDF). + * + * Note that the data type of the input container should be preserved + * so that the corresponding method <tt>integrate()</tt> is used. + * + * \param input collection + * \param output mappable collection + * \param eps minimal step size + * \return integral value + */ + template<class JContainer_t, + class JKey_t, + class JValue_t> + inline typename JContainer_t::ordinate_type + makeCDF(const JContainer_t& input, + JMappableCollection<JKey_t, JValue_t>& output, + const typename JContainer_t::ordinate_type eps = JMATH::zero) + { + typedef typename JContainer_t::ordinate_type ordinate_type; + typedef typename JContainer_t::abscissa_type abscissa_type; + typedef JElement2D<abscissa_type, ordinate_type> element_type; + typedef JCollection<element_type> buffer_type; + + + if (input.getSize() > 1) { + + buffer_type buffer; + + const ordinate_type V = integrate(input, buffer); + + if (V == ordinate_type(JMATH::zero)) { + THROW(JDivisionByZero, "Method makeCDF(): integral equals zero."); + } + + output.clear(); + + typename buffer_type::const_iterator i = buffer.begin(); + + for ( ; i != buffer.end() && i->getY() <= 0.5 * eps * V; ++i) {} + + if (i != buffer.end()) { + + // force first point at (0, ymin) + + JKey_t x = 0.0; + JValue_t y = i->getX(); + + output.put(x, y); + + JKey_t xmax = x; + JValue_t ymax = y; + + for (++i; i != buffer.end(); ++i) { + + x = i->getY() / V; + y = i->getX(); + + if (x > xmax) { + + ymax = y; + + if (x > xmax + eps) { + + output.put(x, y); + + xmax = x; + } + } + } + + // force last point at (1, ymax) + + x = 1.0; + y = ymax; + + output.put(x,y); + + } else { + THROW(JDivisionByZero, "Method makeCDF(): no remaining data."); + } + + return V; + + } else { + THROW(JEmptyCollection, "Method makeCDF(): not sufficient input data."); + } + } + + + /** + * Get integral of input data points. + * + * \param input input data + * \return integral value + */ + template<class JContainer_t> + inline typename JContainer_t::ordinate_type getIntegral(const JContainer_t& input) + { + JGarbageCollection<typename JContainer_t::abscissa_type, typename JContainer_t::ordinate_type> garbage; + + return integrate(input, garbage); + } + + + /** + * Auxiliary method to get integral of input data points. + * + * \param input input data + * \return integral value + */ + template<class JFunction_t, + template<class, class, class> class JMap_t, + class JTail_t> + inline typename JFunction_t::ordinate_type + getIntegral(const JMultiMap<typename JFunction_t::abscissa_type, JFunction_t, JMapList<JMap_t, JTail_t>, typename JFunction_t::distance_type>& input) + { + typedef typename JFunction_t::abscissa_type abscissa_type; + typedef typename JFunction_t::ordinate_type ordinate_type; + typedef typename JFunction_t::distance_type distance_type; + typedef typename JFunctionalMap<JMap_t>::template function_type<abscissa_type, + ordinate_type, + ordinate_type, + distance_type> buffer_type; + typedef JMultiMap<abscissa_type, JFunction_t, JMapList<JMap_t, JTail_t>, distance_type> multimap_type; + + static buffer_type buffer; + + buffer.configure(input); + + typename buffer_type::iterator out = buffer.begin(); + + for (typename multimap_type::const_iterator in = input.begin(); in != input.end(); ++in, ++out) { + out->getY() = getIntegral(in->getY()); + } + + buffer.compile(); + + return getIntegral(buffer); + } + + + /** + * Get integral of input data points. + * + * \param input input data + * \return integral value + */ + template<class JFunction_t, + template<class, class, class> class JMap_t, + class JTail_t> + inline typename JFunction_t::ordinate_type + getIntegral(const JMultiFunction<JFunction_t, JMapList<JMap_t, JTail_t>, typename JFunction_t::distance_type>& input) + { + typedef typename JFunction_t::abscissa_type abscissa_type; + typedef typename JFunction_t::ordinate_type ordinate_type; + typedef typename JFunction_t::distance_type distance_type; + typedef typename JFunctionalMap<JMap_t>::template function_type<abscissa_type, + ordinate_type, + ordinate_type, + distance_type> buffer_type; + typedef JMultiFunction<JFunction_t, JMapList<JMap_t, JTail_t>, distance_type> multifunction_type; + + buffer_type buffer; + + for (typename multifunction_type::const_iterator i = input.begin(); i != input.end(); ++i) { + buffer.put(i->getX(), getIntegral(i->getY())); + } + + buffer.compile(); + + return getIntegral(buffer); + } + + + /** + * Reset value. + * + * The value is set to (the equivalent of) zero, see method JMATH::getZero. + * + * \param value value + */ + template<class T> + inline void reset(T& value) + { + value = JMATH::getZero<T>(); + } + + + /** + * Recursive reset of collection. + * + * \param collection collection + */ + template<class JElement_t, class JDistance_t> + inline void reset(JCollection<JElement_t, JDistance_t>& collection) + { + typedef typename JCollection<JElement_t, JDistance_t>::iterator iterator; + + for (iterator i = collection.begin(); i != collection.end(); ++i) { + reset(i->getY()); + } + } + + + /** + * Copy of input to output. + * + * The output value is set to the input value. + * + * \param input input + * \param output output + */ + template<class T> + inline void copy(const T& input, T& output) + { + output = input; + } + + + /** + * Recursive copy of input collection to output collection. + * + * \param input input + * \param output output + */ + template<class JElement_t, class JDistance_t, class JKey_t, class JValue_t> + inline void copy(const JCollection<JElement_t, JDistance_t>& input, JMappableCollection<JKey_t, JValue_t>& output) + { + typedef typename JCollection<JElement_t, JDistance_t>::const_iterator const_iterator; + + output.clear(); + + for (const_iterator i = input.begin(); i != input.end(); ++i) { + copy(i->getY(), output.get(i->getX())); + } + } + + + /** + * Configuration of value. + * + * This is a fall-back method; it does nothing. + * + * \param value value + * \param bounds bounds + * \param option false + */ + template<class T, class JAbscissa_t> + inline void configure(const T& value, const JAbstractCollection<JAbscissa_t>& bounds, JBool<false> option) + {} + + + /** + * Recursive configuration of collection. + * + * \param collection collection + * \param bounds bounds + * \param option true + */ + template<class JElement_t, class JDistance_t> + inline void configure(JCollection<JElement_t, JDistance_t>& collection, + const JAbstractCollection<typename JElement_t::abscissa_type>& bounds, + JBool<true> option = JBool<true>()) + { + typedef typename JCollection<JElement_t, JDistance_t>::iterator iterator; + typedef typename JCollection<JElement_t, JDistance_t>::ordinate_type ordinate_type; + + collection.configure(bounds); + + for (iterator i = collection.begin(); i != collection.end(); ++i) { + configure(i->getY(), bounds, JBool<JAssembler<ordinate_type>::is_collection>()); + } + } + + + /** + * Accumulation of value. + * + * This is a fall-back method; it does nothing. + * + * \param value value + * \param option false + */ + template<class T> + inline void accumulate(T& value, JBool<false> option) + {} + + + /** + * Recursive accumulation of collection. + * + * \param collection collection + * \param option true + */ + template<class JElement_t, class JDistance_t> + inline void accumulate(JCollection<JElement_t, JDistance_t>& collection, JBool<true> option = JBool<true>()) + { + typedef typename JCollection<JElement_t, JDistance_t>::iterator iterator; + typedef typename JCollection<JElement_t, JDistance_t>::ordinate_type ordinate_type; + + for (iterator i = collection.begin(); i != collection.end(); ++i) { + accumulate(i->getY(), JBool<JAssembler<ordinate_type>::is_collection>()); + } + + if (collection.getSize() > 1) { + + for (iterator j = collection.begin(), i = j++; j != collection.end(); ++i, ++j) { + j->getY() += i->getY(); + } + + reset(collection.begin()->getY()); + } + } +} + +#endif diff --git a/jpp/JTools/JTransformableMultiFunction.hh b/jpp/JTools/JTransformableMultiFunction.hh new file mode 100644 index 0000000..125547e --- /dev/null +++ b/jpp/JTools/JTransformableMultiFunction.hh @@ -0,0 +1,294 @@ +#ifndef __JTOOLS__JTRANSFORMABLEMULTIFUNCTION__ +#define __JTOOLS__JTRANSFORMABLEMULTIFUNCTION__ + +#include "JIO/JSerialisable.hh" +#include "JLang/JSharedPointer.hh" + +#include "JTools/JMultiFunction.hh" +#include "JTools/JMultiMapTransformer.hh" +#include "JTools/JFunctional.hh" +#include "JTools/JArray.hh" +#include "JTools/JResultTransformer.hh" +#include "JTools/JTransformableMultiHistogram.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JIO::JReader; + using JIO::JWriter; + + + /** + * Transformable multidimensional function. + * + * This class implements the JTransformable interface. + */ + template<class JFunction_t, + class JMaplist_t, + class JDistance_t = JDistance<typename JFunction_t::argument_type> > + class JTransformableMultiFunction : + public JMultiFunction<JFunction_t, JMaplist_t, JDistance_t>, + public JTransformable<JMapLength<JMaplist_t>::value, typename JFunction_t::argument_type> + { + public: + + typedef JMultiFunction<JFunction_t, + JMaplist_t, + JDistance_t> multifunction_type; + + enum { NUMBER_OF_DIMENSIONS = multifunction_type::NUMBER_OF_DIMENSIONS }; + + typedef JFunction_t function_type; + + typedef typename multifunction_type::value_type value_type; + typedef typename multifunction_type::argument_type argument_type; + typedef typename multifunction_type::supervisor_type supervisor_type; + + typedef typename multifunction_type::abscissa_type abscissa_type; + typedef typename multifunction_type::ordinate_type ordinate_type; + typedef typename multifunction_type::result_type result_type; + + typedef typename multifunction_type::const_iterator const_iterator; + typedef typename multifunction_type::const_reverse_iterator const_reverse_iterator; + typedef typename multifunction_type::iterator iterator; + typedef typename multifunction_type::reverse_iterator reverse_iterator; + + typedef typename multifunction_type::super_iterator super_iterator; + typedef typename multifunction_type::super_const_iterator super_const_iterator; + + typedef JMultiMapTransformer<JMapLength<JMaplist_t>::value, argument_type> transformer_type; + typedef typename transformer_type::array_type array_type; + + using multifunction_type::insert; + + + /** + * Default constructor. + */ + JTransformableMultiFunction() : + transformer(transformer_type::getClone()) + {} + + + /** + * Constructor. + * + * \param input multidimensional input + */ + template<class T> + JTransformableMultiFunction(const T& input) + { + insert(input); + + this->compile(); + } + + + /** + * Get transformable multidimensional function. + * + * \return this transformable multidimensional function + */ + const JTransformableMultiFunction& getTransformableMultiFunction() const + { + return static_cast<const JTransformableMultiFunction&>(*this); + } + + + /** + * Get transformable multidimensional function. + * + * \return this transformable multidimensional function + */ + JTransformableMultiFunction& getTransformableMultiFunction() + { + return static_cast<JTransformableMultiFunction&>(*this); + } + + + /** + * Insert multidimensional input. + * + * \param input multidimensional function + */ + template<class JPDF_t, class JPDFMaplist_t, class JPDFDistance_t> + void insert(const JTransformableMultiFunction<JPDF_t, JPDFMaplist_t, JPDFDistance_t>& input) + { + this->transformer.reset(input.transformer->clone()); + + multifunction_type::insert(input); + } + + + /** + * Insert multidimensional input. + * + * \param input multidimensional histogram + */ + template<class JHistogram_t, class JHistogramMaplist_t, class JHistogramDistance_t> + void insert(const JTransformableMultiHistogram<JHistogram_t, JHistogramMaplist_t, JHistogramDistance_t>& input) + { + this->transformer.reset(input.transformer->clone()); + + multifunction_type::insert(input); + } + + + /** + * Add function. + * + * Note that the summation is made via iteration of the elements in this multidimensional function. + * + * \param input multidimensional function + */ + template<class JMultiFunction_t> + void add(const JMultiFunction_t& input) + { + for (super_iterator i = this->super_begin(); i != this->super_end(); ++i) { + + const array_type array = (*i).getKey(); + function_type& f1 = (*i).getValue(); + + if (!f1.empty()) { + + const JMultiMapGetTransformer<NUMBER_OF_DIMENSIONS - 1, value_type> get(*(this->transformer), array); + const JMultiMapPutTransformer<NUMBER_OF_DIMENSIONS - 1, value_type> put(*(this->transformer), array); + + f1.transform(get); + + for (typename function_type::iterator j = f1.begin(); j != f1.end(); ++j) { + + const JArray<NUMBER_OF_DIMENSIONS, argument_type> buffer(array, j->getX()); + + j->getY() += get_value(input.evaluate(buffer.data())); + } + + f1.transform(put); + f1.compile(); + } + } + } + + + /** + * Multidimensional interpolation method call. + * + * \param args comma seperated list of abscissa values + * \return function value + */ + template<class ...Args> + result_type operator()(const Args& ...args) const + { + return this->evaluate(this->buffer.set(args...).data()); + } + + + /** + * Recursive function value evaluation. + * + * \param pX pointer to abscissa values + * \return function value + */ + virtual result_type evaluate(const argument_type* pX) const override + { + for (int i = 0; i != NUMBER_OF_DIMENSIONS; ++i) { + this->buffer[i] = pX[i]; + } + + this->buffer[NUMBER_OF_DIMENSIONS - 1] = transformer->putXn(this->buffer, this->buffer[NUMBER_OF_DIMENSIONS - 1]); + + const result_type y = multifunction_type::evaluate(this->buffer.data()); + const double W = transformer->getWeight(this->buffer); + + return JResultTransformer<result_type>::transform(*transformer, this->buffer, y) * W; + } + + + /** + * Application of weight function and coordinate transformation. + * + * \param transformer function transformer + */ + virtual void transform(const transformer_type& transformer) override + { + for (super_iterator i = this->super_begin(); i != this->super_end(); ++i) { + + const array_type array = (*i).getKey(); + function_type& function = (*i).getValue(); + + const JMultiMapGetTransformer<NUMBER_OF_DIMENSIONS - 1, value_type> get(*(this->transformer), array); + const JMultiMapPutTransformer<NUMBER_OF_DIMENSIONS - 1, value_type> put( transformer, array); + + function.transform(get); + function.transform(put); + } + + this->transformer.reset(transformer.clone()); + this->compile(); + } + + + /** + * Read transformable multidimensional function. + * + * \param in reader + * \param object transformable multidimensional function. + * \return reader + */ + friend inline JReader& operator>>(JReader& in, JTransformableMultiFunction& object) + { + in >> static_cast<multifunction_type&>(object); + + return object.transformer->read(in); + } + + + /** + * Write transformable multidimensional function. + * + * \param out writer + * \param object transformable multidimensional function + * \return writer + */ + friend inline JWriter& operator<<(JWriter& out, const JTransformableMultiFunction& object) + { + out << static_cast<const multifunction_type&>(object); + + return object.transformer->write(out); + } + + + JLANG::JSharedPointer<transformer_type> transformer; + + private: + mutable JArray<NUMBER_OF_DIMENSIONS, argument_type> buffer; + }; + + + /** + * Conversion of multidimensional histogram to multidimensional function. + * + * \param input multidimensional histogram + * \param output multidimensional function + */ + template<class JHistogram_t, + class JHistogramMaplist_t, + class JHistogramDistance_t, + class JFunction_t, + class JFunctionMaplist_t, + class JFunctionDistance_t> + inline void makePDF(const JTransformableMultiHistogram<JHistogram_t, JHistogramMaplist_t, JHistogramDistance_t>& input, + JTransformableMultiFunction<JFunction_t, JFunctionMaplist_t, JFunctionDistance_t>& output) + { + output.insert(input); + } +} + +#endif diff --git a/jpp/JTools/JTransformableMultiHistogram.hh b/jpp/JTools/JTransformableMultiHistogram.hh new file mode 100644 index 0000000..5f3a32c --- /dev/null +++ b/jpp/JTools/JTransformableMultiHistogram.hh @@ -0,0 +1,176 @@ +#ifndef __JTOOLS__JTRANSFORMABLEMULTIHISTOGRAM__ +#define __JTOOLS__JTRANSFORMABLEMULTIHISTOGRAM__ + +#include "JIO/JSerialisable.hh" +#include "JLang/JSharedPointer.hh" + +#include "JTools/JMultiMap.hh" +#include "JTools/JMultiHistogram.hh" +#include "JTools/JMultiMapTransformer.hh" +#include "JTools/JArray.hh" +#include "JIO/JSerialisable.hh" + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + using JIO::JReader; + using JIO::JWriter; + + + /** + * Transformable multidimensional histogram. + * + * This class implements the JTransformable interface. + */ + template<class JHistogram_t, + class JMaplist_t, + class JDistance_t = JDistance<typename JHistogram_t::abscissa_type> > + class JTransformableMultiHistogram : + public JMultiHistogram<JHistogram_t, JMaplist_t, JDistance_t>, + public JTransformable<JMapLength<JMaplist_t>::value, typename JHistogram_t::abscissa_type> + { + public: + + typedef JMultiHistogram<JHistogram_t, + JMaplist_t, + JDistance_t> JMultiHistogram_t; + + enum { NUMBER_OF_DIMENSIONS = JMultiHistogram_t::NUMBER_OF_DIMENSIONS }; + + typedef JHistogram_t histogram_type; + + typedef typename histogram_type::contents_type contents_type; + typedef typename histogram_type::value_type value_type; + + typedef typename JMultiHistogram_t::abscissa_type abscissa_type; + typedef typename JMultiHistogram_t::ordinate_type ordinate_type; + + typedef typename JMultiHistogram_t::const_iterator const_iterator; + typedef typename JMultiHistogram_t::const_reverse_iterator const_reverse_iterator; + typedef typename JMultiHistogram_t::iterator iterator; + typedef typename JMultiHistogram_t::reverse_iterator reverse_iterator; + + typedef typename JMultiHistogram_t::super_iterator super_iterator; + typedef typename JMultiHistogram_t::super_const_iterator super_const_iterator; + + typedef JMultiMapTransformer<JMapLength<JMaplist_t>::value, abscissa_type> transformer_type; + typedef typename transformer_type::array_type array_type; + + + /** + * Default constructor. + */ + JTransformableMultiHistogram() : + transformer(transformer_type::getClone()) + {} + + + /** + * Get transformable multidimensional histogram. + * + * \return this transformable multidimensional histogram + */ + const JTransformableMultiHistogram& getTransformableMultiHistogram() const + { + return static_cast<const JTransformableMultiHistogram&>(*this); + } + + + /** + * Get transformable multidimensional histogram. + * + * \return this transformable multidimensional histogram + */ + JTransformableMultiHistogram& getTransformableMultiHistogram() + { + return static_cast<JTransformableMultiHistogram&>(*this); + } + + + /** + * Application of weight function and coordinate transformation. + * + * \param transformer function transformer + */ + virtual void transform(const transformer_type& transformer) override + { + typedef typename transformer_type::array_type array_type; + + for (super_iterator i = this->super_begin(); i != this->super_end(); ++i) { + + const array_type array = (*i).getKey(); + histogram_type& histogram = (*i).getValue(); + + const JMultiMapGetTransformer<NUMBER_OF_DIMENSIONS - 1, value_type> get(*(this->transformer), array); + const JMultiMapPutTransformer<NUMBER_OF_DIMENSIONS - 1, value_type> put( transformer, array); + + histogram.transform(get); + histogram.transform(put); + } + + this->transformer.reset(transformer.clone()); + } + + + /** + * Read transformable multidimensional histogram. + * + * \param in reader + * \param object transformable multidimensional histogram. + * \return reader + */ + friend inline JReader& operator>>(JReader& in, JTransformableMultiHistogram& object) + { + in >> static_cast<JMultiHistogram_t&>(object); + + return object.transformer->read(in); + } + + + /** + * Write transformable multidimensional histogram. + * + * \param out writer + * \param object transformable multidimensional histogram + * \return writer + */ + friend inline JWriter& operator<<(JWriter& out, const JTransformableMultiHistogram& object) + { + out << static_cast<const JMultiHistogram_t&>(object); + + return object.transformer->write(out); + } + + + JLANG::JSharedPointer<transformer_type> transformer; + + protected: + /** + * Termination method for filling histogram. + * + * \param i index + * \param x abscissa value + * \param w weight + */ + virtual void __fill__(const int i, const abscissa_type x, const contents_type w) override + { + this->buffer[NUMBER_OF_DIMENSIONS - 1] = transformer->putXn(this->buffer, this->buffer[NUMBER_OF_DIMENSIONS - 1]); + + const double z = transformer->putXn(this->buffer, 1.0) - transformer->putXn(this->buffer, 0.0); + const double W = transformer->getWeight(this->buffer); + + this->evaluate(this->buffer.begin(), w * z / W); + + this->evaluate(this->buffer.begin(), w); + } + }; +} + +#endif diff --git a/jpp/JTools/JTransformer.hh b/jpp/JTools/JTransformer.hh new file mode 100644 index 0000000..37b29e5 --- /dev/null +++ b/jpp/JTools/JTransformer.hh @@ -0,0 +1,36 @@ +#ifndef __JTOOLS__JTRANSFORMER__ +#define __JTOOLS__JTRANSFORMER__ + + +/** + * \author mdejong + */ + +namespace JTOOLS {} +namespace JPP { using namespace JTOOLS; } + +namespace JTOOLS { + + /** + * Interface for transformation of collection of elements. + */ + template<class JElement_t> + struct JCollectionElementTransformer { + /** + * Virtual destructor. + */ + virtual ~JCollectionElementTransformer() + {} + + + /** + * Transform element. + * + * \param element input element + * \return output element + */ + virtual JElement_t operator()(const JElement_t& element) const = 0; + }; +} + +#endif diff --git a/jpp/Jeep/JeepToolkit.hh b/jpp/Jeep/JeepToolkit.hh new file mode 100644 index 0000000..01e5412 --- /dev/null +++ b/jpp/Jeep/JeepToolkit.hh @@ -0,0 +1,371 @@ +#ifndef __JEEP__JEEPTOOLKIT__ +#define __JEEP__JEEPTOOLKIT__ + +#include <string> +#include <fstream> +#include <sstream> +#include <cstdlib> +#include <map> + +#include "JLang/gzstream.h" + + +/** + * \file + * + * Auxiliary methods for handling file names, type names and environment. + * \author mdejong + */ + +/** + * General puprpose classes and methods. + */ +namespace JEEP {} +namespace JPP { using namespace JEEP; } + +namespace JEEP { + + /** + * Nick names of environment variables. + */ + static const char* const LD_LIBRARY_PATH = "LD_LIBRARY_PATH"; //!< library file paths + static const char* const PATH = "PATH"; //!< binary file paths + static const char* const SHELL = "SHELL"; //!< SHELL + static const char* const JPP_PAGES = "JPP_PAGES"; //!< Jpp document pages + + static const char PATHNAME_SEPARATOR = '/'; //!< path name separator + static const char PATHLIST_SEPARATOR = ':'; //!< path list separator + static const char FILENAME_SEPARATOR = '.'; //!< file name separator + static const char* const TYPENAME_SEPARATOR = "::"; //!< type name separator + static const char PROTOCOL_SEPARATOR = ':'; //!< protocol separator + + + /** + * Strip leading and trailing white spaces from file name. + * + * \param file_name file name + * \return file name + */ + inline std::string strip(const std::string& file_name) + { + using namespace std; + + string::const_iterator p = file_name. begin(); + string::const_reverse_iterator q = file_name.rbegin(); + + for ( ; p != file_name.end() && q != file_name.rend() && isspace(*p); ++p) {} + for ( ; p != file_name.end() && q != file_name.rend() && isspace(*q); ++q) {} + + return string(p,q.base()); + } + + + /** + * Get file name extension, i.e.\ part after last JEEP::FILENAME_SEPARATOR if any. + * + * \param file_name file name + * \return extension (excluding separator) + */ + inline std::string getFilenameExtension(const std::string& file_name) + { + using namespace std; + + const size_t pos = file_name.rfind(FILENAME_SEPARATOR); + + if (pos != string::npos) + return file_name.substr(pos + 1); + else + return ""; + } + + + /** + * Get file name part, i.e.\ part after last JEEP::PATHNAME_SEPARATOR if any. + * + * \param file_name file name + * \return file name part (excluding separator) + */ + inline std::string getFilename(const std::string& file_name) + { + using namespace std; + + const string buffer = strip(file_name); + const size_t pos = buffer.rfind(PATHNAME_SEPARATOR); + + if (pos != string::npos) + return buffer.substr(pos + 1); + else + return buffer; + } + + + /** + * Get path, i.e.\ part before last JEEP::PATHNAME_SEPARATOR if any. + * + * \param file_name file name + * \return path (including separator) + */ + inline std::string getPath(const std::string& file_name) + { + using namespace std; + + const string buffer = strip(file_name); + const size_t pos = buffer.rfind(PATHNAME_SEPARATOR); + + if (pos != string::npos) + return buffer.substr(0, pos + 1); + else + return ""; + } + + + /** + * Get full path, i.e.\ add JEEP::PATHNAME_SEPARATOR if necessary. + * + * \param path path + * \return path (including separator) + */ + inline std::string getFullPath(const std::string& path) + { + using namespace std; + + const string buffer = strip(path); + + if (buffer.empty() || *buffer.rbegin() == PATHNAME_SEPARATOR) { + + return buffer; + + } else { + + return buffer + PATHNAME_SEPARATOR; + } + } + + + /** + * Compose full file name and introduce JEEP::PATHNAME_SEPARATOR if needed. + * + * \param path path + * \param file_name file name + * \return file name + */ + inline std::string getFilename(const std::string& path, const std::string& file_name) + { + using namespace std; + + const string buffer = getFullPath(path); + + if (buffer.empty()) + return strip(file_name); + else + return buffer + strip(file_name); + } + + + /** + * Get selected path from environment variable for given file name. + * + * The environment variable is parsed according character JEEP::PATHLIST_SEPARATOR. + * The first path in which a file exists with the given file name is returned. + * If no existing file is found, an empty path is returned. + * + * \param variable environment variable + * \param file_name file name + * \return path + */ + inline std::string getPath(const std::string& variable, const std::string& file_name) + { + using namespace std; + + string path = ""; + + if (!file_name.empty() && file_name[0] != PATHNAME_SEPARATOR) { + + const string buffer(getenv(variable.c_str())); + + if (!buffer.empty()) { + + size_t pos = 0, len; + + do { + + len = buffer.substr(pos).find(PATHLIST_SEPARATOR); + path = buffer.substr(pos,len); + + } while (!ifstream(getFilename(path, file_name).c_str()).good() && len != string::npos && (pos += len + 1) != buffer.length()); + } + } + + if (ifstream(getFilename(path, file_name).c_str()).good()) + return path; + else + return ""; + } + + + /** + * Get full file name (see JEEP::getPath). + * + * \param variable environment variable + * \param file_name file name + * \return file name + */ + inline std::string getFullFilename(const std::string& variable, const std::string& file_name) + { + return getFilename(getPath(variable, file_name), file_name); + } + + + /** + * Get name space, i.e.\ part before JEEP::TYPENAME_SEPARATOR. + * + * \param type_name type name + * \return name space (possibly empty) + */ + inline std::string getNamespace(const std::string& type_name) + { + using namespace std; + + const size_t pos = type_name.rfind(TYPENAME_SEPARATOR); + + if (pos != string::npos) + return type_name.substr(0, pos); + else + return ""; + } + + + /** + * Get type name, i.e.\ part after JEEP::TYPENAME_SEPARATOR. + * + * \param type_name type name + * \return class name + */ + inline std::string getClassname(const std::string& type_name) + { + using namespace std; + + const size_t pos = type_name.rfind(TYPENAME_SEPARATOR); + + if (pos != string::npos) + return type_name.substr(pos + 2); + else + return type_name; + } + + + /** + * Get protocol, i.e.\ part before first JEEP::PROTOCOL_SEPARATOR if any. + * + * \param file_name file name + * \return protocol (excluding separator) + */ + inline std::string getProtocol(const std::string& file_name) + { + using namespace std; + + const size_t pos = file_name.find(PROTOCOL_SEPARATOR); + + if (pos != string::npos) + return file_name.substr(0, pos); + else + return ""; + } + + + /** + * Get URL of document pages. + * + * \return URL + */ + inline std::string getURL() + { + const char* const url = getenv(JPP_PAGES); + + return std::string(url != NULL ? url : ""); + } + + + /** + * Open file. + * + * \param file_name file name + * \return pointer to input stream + */ + template<class T> + inline T* open(const std::string& file_name); + + + /** + * Open file. + * + * \param file_name file name + * \return pointer to input stream + */ + template<> + inline std::istream* open(const std::string& file_name) + { + using namespace std; + using namespace JPP; + + if (getFilenameExtension(file_name) == "gz") + return new igzstream(file_name.c_str()); + else if (getFilenameExtension(file_name) == "txt") + return new ifstream (file_name.c_str()); + else + return NULL; + } + + + /** + * Open file. + * + * \param file_name file name + * \return pointer to output stream + */ + template<> + inline std::ostream* open(const std::string& file_name) + { + using namespace std; + using namespace JPP; + + if (getFilenameExtension(file_name) == "gz") + return new ogzstream(file_name.c_str()); + else if (getFilenameExtension(file_name) == "txt") + return new ofstream (file_name.c_str()); + else + return NULL; + } + + + /** + * Close file. + * + * \param pf pointer to file stream + */ + inline void close(std::istream* pf) + { + using namespace std; + using namespace JPP; + + if (dynamic_cast<ifstream*> (pf) != NULL) { dynamic_cast<ifstream*> (pf)->close(); return; } + if (dynamic_cast<igzstream*>(pf) != NULL) { dynamic_cast<igzstream*>(pf)->close(); return; } + } + + + /** + * Close file. + * + * \param pf pointer to file stream + */ + inline void close(std::ostream* pf) + { + using namespace std; + using namespace JPP; + + if (dynamic_cast<ofstream*> (pf) != NULL) { dynamic_cast<ofstream*> (pf)->close(); return; } + if (dynamic_cast<ogzstream*>(pf) != NULL) { dynamic_cast<ogzstream*>(pf)->close(); return; } + } +} + +#endif diff --git a/jpp/README.md b/jpp/README.md new file mode 100644 index 0000000..36b6d2c --- /dev/null +++ b/jpp/README.md @@ -0,0 +1,4 @@ +# Jpp + +The following source files were taken from Jpp version v14.1.0-40-ge37bef90a +and are used for testing and as fallback if no Jpp environment is loaded. -- GitLab