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 ©); 00499 00502 virtual ~LUT(); 00503 00506 LUT<N, X> const &operator=(LUT<N, X> const ©); 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 ©); 00705 LUT<1, X> const &operator=(LUT<1, X> const ©); 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. |