Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

LUT.h

Go to the documentation of this file.
00001 /* SimData: Data Infrastructure for Simulations
00002  * Copyright (C) 2002 Mark Rose <tm2@stm.lbl.gov>
00003  * 
00004  * This file is part of SimData.
00005  * 
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  * 
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  * 
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019  */
00020 
00021 
00022 #include <SimData/PTS.h>
00023 
00024 #ifdef __PTS_SIM__
00025         // old versions of msvc can't do partial template specialization
00026         #define __SIMDATA_NO_LUT__
00027         #define __SIMDATA_LUT_H__
00028 #endif
00029 
00030 
00031 #ifndef __SIMDATA_LUT_H__
00032 #define __SIMDATA_LUT_H__
00033 
00034 
00045 #include <vector>
00046 #include <iostream>
00047 #include <istream>
00048 #include <cstdio>
00049 #include <cmath>
00050 
00051 
00052 #include <SimData/Archive.h>
00053 #include <SimData/Exception.h>
00054 #include <SimData/BaseType.h>
00055 
00056 
00057 NAMESPACE_SIMDATA
00058 
00059 SIMDATA_EXCEPTION(InterpolationInput);
00060 SIMDATA_EXCEPTION(InterpolationError);
00061 SIMDATA_EXCEPTION(InterpolationIndex);
00062 SIMDATA_EXCEPTION(InterpolationUnpackMismatch);
00063 
00064 
00065 // some simple debugging messages used during initial development
00066 // LUTLOG() can be safely removed when no longer needed
00067 #if 0
00068 #  define __LUTLOG(msg) std::cout << msg << "\n";
00069 #else
00070 #  define __LUTLOG(msg)
00071 #endif
00072 
00073 
00074 
00075 
00076 // forward declaration for lookup table templates
00077 template <int N, typename X>
00078 class LUT;
00079 
00080 
00093 template <int N, typename T>
00094 class VEC {
00095         T m_Vec[N];
00096         T* m_Vp;
00097         int m_N;
00098 
00099         friend class VEC<N+1, T>;
00100 
00104         VEC(T* d): m_Vp(d), m_N(N) {}
00105 
00106 public:
00110         VEC(std::vector<T> const &v): m_Vp(m_Vec), m_N(N) {
00111                 if (v.size() != N) throw InterpolationIndex("VEC::VEC() dimension mismatch");
00112                 for (int i = 0; i < N; i++) {
00113                         m_Vec[i] = v[i];
00114                 }
00115         }
00116 
00120         VEC(T d): m_Vp(m_Vec), m_N(1) { m_Vec[0] = d; }
00121 
00126         VEC(): m_Vp(m_Vec), m_N(0) {}
00127 
00137         VEC<N,T> &set(T d) {
00138                 m_N = 1;
00139                 m_Vp = m_Vec;
00140                 m_Vec[0] = d;
00141                 return *this;
00142         }
00143 
00150         inline VEC<N,T> &operator()(T d) {
00151                 if (m_N >= N) {
00152                         throw InterpolationIndex("VEC() too many coordinates specified");
00153                 }
00154                 m_Vec[m_N++] = d;
00155                 return *this;
00156         }
00163         inline T &operator[](int n) const { 
00164                 if (n < 0 || n >= m_N) {
00165                         throw InterpolationIndex("VEC[] index out of range");
00166                 }
00167                 return m_Vp[n]; 
00168         }
00169 
00175         inline VEC<N-1, T> rest() const {
00176                 if (m_N != N) {
00177                         throw InterpolationIndex("VEC.rest() called for incomplete VEC");
00178                 }
00179                 return VEC<N-1, T>(m_Vp+1);
00180         }
00181 };
00182 
00191 template <typename T>
00192 class VEC<1, T> {
00193 friend class VEC<2, T>;
00194         T m_Vec;
00195         VEC(T *d): m_Vec(*d) {}
00196 public:
00200         VEC(std::vector<T> const &v) {
00201                 if (v.size() != 1) throw InterpolationIndex("VEC::VEC() dimension mismatch");
00202                 m_Vec = v[0];
00203         }
00204         VEC(T d): m_Vec(d) {}
00205         inline void set(T d) { m_Vec = d; }
00206         inline T operator[](int n) const { 
00207                 if (n != 0) {
00208                         throw InterpolationIndex("VEC[] index out of range");
00209                 }
00210                 return m_Vec; 
00211         }
00212 };
00213 
00219 template <typename T>
00220 class VEC<0, T> {
00221         VEC(); // private ctor, not defined
00222 };
00223 
00224 
00248 template <int N, typename T>
00249 class WRAP {
00250         LUT<N,T> const *m_Bind;
00251         VEC<N,T> m_Vec;
00252         int m_N;
00253         T m_Value;
00254 
00255 friend class LUT<N,T>;
00256 
00260         WRAP(LUT<N,T> const *bind, T x): m_Bind(bind), m_Vec(x), m_N(1) {
00261                 m_Value = static_cast<T>(0.0);
00262         }
00263 
00264 public:
00268         inline WRAP<N,T> &operator[](T x);
00269 
00273         inline operator T() const { return m_Value; }
00274 };
00275 
00276 
00282 class SIMDATA_EXPORT Interpolation: public BaseType {
00283 public:
00284         typedef enum { LINEAR, SPLINE } Modes;
00285 
00290         inline bool isInterpolated() const { return m_Interpolated; }
00291 
00292 protected:
00296         Interpolation(): m_Interpolated(false) {}
00297 
00298         inline void checkInterpolated() const {
00299                 if (!isInterpolated()) {
00300                         throw InterpolationError("LUT not interpolated");
00301                 }
00302         }
00303 
00304         inline void checkNotInterpolated() const {
00305                 if (isInterpolated()) {
00306                         throw InterpolationError("LUT already interpolated");
00307                 }
00308         }
00309 
00310         void throwBreakpointOrder() const {
00311                 throw InterpolationInput("Breakpoints must increase monotonically");
00312         }
00313 
00314         void throwInterpolationMode() const {
00315                 throw InterpolationError("Unknown interpolation mode");
00316         }
00317 
00318         bool m_Interpolated;
00319 };
00320 
00321 
00329 template <typename X>
00330 class SIMDATA_EXPORT InterpolationType: public Interpolation {
00331 protected:
00332         X m_X0, m_X1, m_XS;
00333         int m_Limit;
00334 
00335         InterpolationType(): m_X0(0.0), m_X1(0.0), m_XS(0.0), m_Limit(1) {}
00336 
00341         inline void find(X x, int &i, X &f) const {
00342                 x = (x - m_X0) * m_XS;
00343                 i = static_cast<int>(floor(x)); 
00344                 if (i >= m_Limit) {
00345                         i = m_Limit-1;
00346                         f = 1.0;
00347                 } else
00348                 if (i < 0) {
00349                         i = 0;
00350                         f = 0.0;
00351                 } else {
00352                         f = x - i;
00353                 }
00354         }
00355 
00360         void postInterpolation(X x0, X x1, int n);
00361 };
00362 
00363 
00374 template <int N, class X=float>
00375 class Curvature;
00376 
00377 
00378 
00389 template <int N, class X=float>
00390 class SIMDATA_EXPORT LUT: public InterpolationType<X> {
00391         typedef LUT<N-1, X> Y;
00392         typedef std::vector< std::pair<X, Y> > DataVector;
00393         typedef std::vector<Y> TableVector;
00394 
00395         union {
00396                 DataVector *m_Data;
00397                 TableVector *m_Table;
00398         };
00399 
00400         int *m_Ref;
00401 
00402         inline std::pair<X, Y> &data(int n) {
00403                 return (*m_Data)[n];
00404         }
00405 
00406         inline std::pair<X, Y> const &data(int n) const {
00407                 return (*m_Data)[n];
00408         }
00409 
00410         inline int dataSize() const { return m_Data->size(); }
00411 
00412         inline Y &table(int n) {
00413                 return (*m_Table)[n];
00414         }
00415 
00416         inline Y const &table(int n) const {
00417                 return (*m_Table)[n];
00418         }
00419 
00420         inline int tableSize() const { return m_Table->size(); }
00421 
00422         inline void ref() {
00423                 bool inc = false;
00424                 if (isInterpolated()) {
00425                         inc = m_Table != NULL;
00426                 } else {
00427                         inc = m_Data != NULL;
00428                 }
00429                 if (inc) {
00430                         assert(m_Ref);
00431                         *m_Ref += 1;
00432                 }
00433         }
00434 
00435         inline void deref() {
00436                 if (!m_Ref) return;
00437                 *m_Ref -= 1;
00438                 assert(*m_Ref >= 0);
00439                 if (*m_Ref == 0) {
00440                         if (m_Interpolated) {
00441                                 assert(m_Table);
00442                                 __LUTLOG("~TABLE " << int(m_Table));
00443                                 delete m_Table;
00444                                 m_Table = 0;
00445                         } else {
00446                                 assert(m_Data);
00447                                 __LUTLOG("~DATA " << int(m_Data));
00448                                 delete m_Data;
00449                                 m_Data = 0;
00450                         }
00451                         delete m_Ref;
00452                         m_Ref = 0;
00453                 }
00454         }
00455 
00456         inline void substitute(TableVector *_table) {
00457                 assert(!isInterpolated() && _table);
00458                 deref();
00459                 m_Ref = new int(0);
00460                 m_Table = _table;
00461                 ref();
00462         }
00463 
00464         void createData(int n);
00465         void postInterpolation(TableVector *_table);
00466         void interpolateLinear(int n, TableVector *_table);
00467         void computeCurvature(Curvature<N,X> &c);
00468         void interpolateSpline(int n, TableVector *_table);
00469 
00470 friend class LUT<N+1,X>;
00471 private:
00472         // spline interpolation
00473         static void __splineInterpolate(X x, X h, LUT<N,X> const &y0, LUT<N,X> const &y1, 
00474                       Curvature<N,X> const &c0, 
00475                       Curvature<N,X> const &c1, 
00476                       LUT<N,X> &out);
00477 
00478         // 2 LUT parameter version does linear interpolation
00479         void __interpolate(X x, LUT<N,X> const &next, LUT<N,X> &out);
00480         
00481         X __getElement(int n);
00482         void __getDimension(std::vector<int> &dim);
00483 
00484 public:
00486         typedef VEC<N, int> Dim;
00488         typedef VEC<N, X> Vec;
00490         typedef VEC<N, std::vector<X> > Breaks;
00491 
00494         LUT();
00495 
00498         LUT(LUT<N, X> const &copy);
00499 
00502         virtual ~LUT();
00503 
00506         LUT<N, X> const &operator=(LUT<N, X> const &copy);
00507 
00517         void interpolate(Dim const &dim, Interpolation::Modes mode);
00518 
00528         void interpolate(std::vector<int> const &dim, Interpolation::Modes mode);
00529 
00538         X getValue(Vec const &v) const;
00539 
00548         inline X getValue(std::vector<X> const &x) const {
00549                 return getValue(Vec(x));
00550         }
00551 
00552 
00563         inline WRAP<N,X> operator[](X x) const {
00564                 checkInterpolated();
00565                 return WRAP<N,X>(this, x);
00566         }
00567 
00578         void load(std::vector<X> const &values, Breaks const &breaks, int *index = 0);
00579         void load(std::vector<X> const &values, std::vector< std::vector<X> > const &breaks);
00580 
00583         virtual void serialize(Archive&);
00584 
00587         virtual std::string asString() const;
00588 
00591         virtual std::string typeString() const;
00592 };
00593 
00599 template <typename X>
00600 class SIMDATA_EXPORT LUT<1, X>: public InterpolationType<X> {
00601         typedef std::vector< std::pair<X, X> > DataVector;
00602         typedef std::vector<X> TableVector;
00603 
00604         union {
00605                 DataVector *m_Data;
00606                 TableVector *m_Table;
00607         };
00608         int *m_Ref;
00609 
00610         inline std::pair<X, X> &data(int n) {
00611                 return (*m_Data)[n];
00612         }
00613 
00614         inline std::pair<X, X> const &data(int n) const {
00615                 return (*m_Data)[n];
00616         }
00617 
00618         inline int dataSize() const { return m_Data->size(); }
00619 
00620         inline X &table(int n) {
00621                 return (*m_Table)[n];
00622         }
00623 
00624         inline X const &table(int n) const {
00625                 return (*m_Table)[n];
00626         }
00627 
00628         inline int tableSize() const { return m_Table->size(); }
00629 
00630         inline void ref() {
00631                 if (m_Data) {
00632                         assert(m_Ref);
00633                         *m_Ref += 1;
00634                 }
00635         }
00636 
00637         inline void deref() {
00638                 if (!m_Ref) return;
00639                 assert(m_Data);
00640                 *m_Ref -= 1;
00641                 assert(*m_Ref >= 0);
00642                 if (*m_Ref == 0) {
00643                         if (m_Interpolated) {
00644                                 assert(m_Table);
00645                                 __LUTLOG("~TABLE " << int(m_Table));
00646                                 delete m_Table;
00647                                 m_Table = 0;
00648                         } else {
00649                                 assert(m_Data);
00650                                 __LUTLOG("~DATA " << int(m_Data));
00651                                 delete m_Data;
00652                                 m_Data = 0;
00653                         }
00654                         delete m_Ref;
00655                         m_Ref = 0;
00656                 }
00657         }
00658 
00659         inline void substitute(TableVector *_table) {
00660                 assert(!isInterpolated() && _table);
00661                 deref();
00662                 m_Ref = new int(0);
00663                 m_Table = _table;
00664                 ref();
00665         }
00666 
00667         void createData(int n);
00668         void postInterpolation(TableVector *_table);
00669         void interpolateLinear(int n, TableVector *_table);
00670         void interpolateSpline(int n, TableVector *_table);
00671 
00672 friend class LUT<2,X>;
00673 private:
00674 
00675         inline X __getElement(int n) {
00676                 return data(n).second;
00677         }
00678 
00679         inline void __getDimension(std::vector<int> &dim) {
00680                 dim.push_back(dataSize());
00681         }
00682 
00683         // linear interpolation between this and next
00684         void __interpolate(X x, LUT<1,X> const &next, LUT<1,X> &out);
00685 
00686         // spline interpolation 
00687         static void __splineInterpolate(
00688                         X x, X h, 
00689                         LUT<1,X> const &y0, 
00690                         LUT<1,X> const &y1, 
00691                         Curvature<1,X> const &c0, 
00692                         Curvature<1,X> const &c1, 
00693                         LUT<1,X> &out);
00694 
00695 public:
00696         typedef VEC<1, int> Dim;
00697         typedef VEC<1, X> Vec;
00698         typedef VEC<1, std::vector<X> > Breaks;
00699 
00700         inline X __get(int n) const { return data(n).second; }
00701 
00702         LUT();
00703         virtual ~LUT();
00704         LUT(LUT<1, X> const &copy);
00705         LUT<1, X> const &operator=(LUT<1, X> const &copy);
00706 
00707         void interpolate(Dim const &dim, Interpolation::Modes mode);
00708         void interpolate(std::vector<int> const &dim, Interpolation::Modes mode);
00709 
00710         X getValue(Vec const &v) const;
00711 
00712         inline X getValue(std::vector<X> const &x) const {
00713                 return getValue(Vec(x));
00714         }
00715 
00716         inline X operator[](Vec const &v) const {
00717                 return getValue(v);
00718         }
00719 
00720         void load(std::vector<X> const &values, Breaks const &breaks, int *index = 0);
00721         void load(std::vector<X> const &values, std::vector< std::vector<X> > const &breaks);
00722 
00725         virtual void serialize(Archive&);
00726 
00729         virtual std::string asString() const;
00730 
00733         virtual std::string typeString() const;
00734 };
00735 
00739 template <typename X>
00740 class SIMDATA_EXPORT LUT<0, X>: public Interpolation {
00741         LUT();
00742 };
00743 
00744 
00750 template <int N, typename X>
00751 inline WRAP<N,X> &WRAP<N,X>::operator[](X x) {
00752         m_Vec(x);
00753         if (++m_N == N && m_Bind) {
00754                 m_Value = m_Bind->getValue(m_Vec);
00755         }
00756         return *this;
00757 }
00758 
00759 
00766 typedef LUT<1,float> Table1;
00767 
00774 typedef LUT<2,float> Table2;
00775 
00782 typedef LUT<3,float> Table3;
00783 
00784 
00785 NAMESPACE_SIMDATA_END // simdata
00786 
00787 
00788 #endif // __SIMDATA_LUT_H__
00789 

SimData version pre-0.4.0. For more information on SimData, visit the SimData Homepage.

Generated on Tue Oct 14 12:06:38 2003, using Doxygen 1.2.18.

[SF.net]