You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

108 lines
2.8KB

  1. #pragma once
  2. #include <assert.h>
  3. #include <map>
  4. template <typename T> class NonUniformLookupTable;
  5. template <typename T>
  6. class NonUniformLookupTableParams
  7. {
  8. public:
  9. friend NonUniformLookupTable<T>;
  10. int size() const
  11. {
  12. return (int) entries.size();
  13. }
  14. private:
  15. class Entry
  16. {
  17. public:
  18. T x;
  19. T y;
  20. T a;
  21. };
  22. using container = std::map<T, Entry>;
  23. bool isFinalized = false;
  24. container entries;
  25. };
  26. template <typename T>
  27. class NonUniformLookupTable
  28. {
  29. public:
  30. NonUniformLookupTable() = delete;
  31. static void addPoint(NonUniformLookupTableParams<T>& params, T x, T y);
  32. static void finalize(NonUniformLookupTableParams<T>& params);
  33. static T lookup(NonUniformLookupTableParams<T>& params, T x);
  34. };
  35. template <typename T>
  36. inline void NonUniformLookupTable<T>::addPoint(NonUniformLookupTableParams<T>& params, T x, T y)
  37. {
  38. using Entry = typename NonUniformLookupTableParams<T>::Entry;
  39. Entry e;
  40. e.x = x;
  41. e.y = y;
  42. params.entries.insert(std::pair<T, Entry>(x, e));
  43. }
  44. template <typename T>
  45. inline void NonUniformLookupTable<T>::finalize(NonUniformLookupTableParams<T>& params)
  46. {
  47. assert(!params.isFinalized);
  48. using iterator = typename std::map<T, typename NonUniformLookupTableParams<T>::Entry>::iterator;
  49. iterator it;
  50. //typename std::map<T, typename NonUniformLookupTableParams<T>::Entry>::iterator it;
  51. for (it = params.entries.begin(); it != params.entries.end(); ++it) {
  52. iterator it_next = it;
  53. ++it_next;
  54. // Will now generate a line segment from this entry to the next
  55. if (it_next == params.entries.end()) {
  56. it->second.a = 0;
  57. } else {
  58. T a = (it_next->second.y - it->second.y) / (it_next->second.x - it->second.x);
  59. it->second.a = a;
  60. }
  61. }
  62. params.isFinalized = true;
  63. }
  64. template <typename T>
  65. inline T NonUniformLookupTable<T>::lookup(NonUniformLookupTableParams<T>& params, T x)
  66. {
  67. assert(params.isFinalized);
  68. assert(!params.entries.empty());
  69. auto lb_init = params.entries.lower_bound(x);
  70. auto lb = lb_init;
  71. if (lb == params.entries.end()) {
  72. return params.entries.rbegin()->second.y;
  73. }
  74. if (x >= lb->second.x) {
  75. // this could only happen if we hit equal
  76. } else {
  77. // added this case to keep mac from crashing, as we were trying to decrement begin()
  78. if (lb == params.entries.begin()) {
  79. return lb_init->second.y;
  80. }
  81. --lb;
  82. if (lb == params.entries.end()) {
  83. // I thing now that above is fixed this won't happen?
  84. assert(false);
  85. return lb_init->second.y;
  86. }
  87. }
  88. // Now that we have the right entry, interpolate.
  89. T ret = lb->second.a * (x - lb->second.x) + lb->second.y;
  90. return ret;
  91. }