Skip to content

Instantly share code, notes, and snippets.

@NiklasRosenstein
Last active February 9, 2016 21:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NiklasRosenstein/d0dd73ad81ca46e0daf2 to your computer and use it in GitHub Desktop.
Save NiklasRosenstein/d0dd73ad81ca46e0daf2 to your computer and use it in GitHub Desktop.
C++11 floating-point interpolation class with a convenient function to statically create an instance.
// Copyright (c) 2016 Niklas Rosenstein
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <iostream>
#include <cmath>
#include <cstring>
/*!
* Utility class to interpolate by a floating-point value in the
* range [0..1] in an arbitrary set of constraint values. You can
* easily create interpolators using the #make() static method.
*/
template <typename... Args>
struct Interpolator
{
int count;
double values[sizeof...(Args)];
Interpolator(Args... args)
: count(sizeof...(Args))
{
static_assert(sizeof...(Args) >= 2, "need at least 2 arguments");
// XXX Is there a way to initialize the array in the member initialization
// list? `values({ static_cast<double>(args)... })` does not work.
double const values[sizeof...(Args)] = { static_cast<double>(args)... };
memcpy(this->values, values, sizeof(double) * sizeof...(Args));
}
inline double operator () (double x) const
{
if (x <= 0.0) {
return values[0];
}
else if (x >= 1.0) {
return values[count - 1];
}
else {
x *= (count - 1);
int const left = int(x);
x = fmod(x, 1.0);
return values[left] * (1.0 - x) + values[left + 1] * x;
}
}
};
/*!
* Factory function to create an #Interpolator object.
*/
template <typename... Args>
Interpolator<Args...> make_interpolator(Args... args)
{
return Interpolator<Args...>(args...);
}
int main()
{
auto it = make_interpolator(8, 64, 512);
for (double x = 0.0; x <= 1.0; x += 0.1)
std::cout << x << ": " << it(x) << "\n";
it = make_interpolator(100, 200, 900);
for (double x = 0.0; x <= 1.0; x += 0.1)
std::cout << x << ": " << it(x) << "\n";
return 0;
}
@NiklasRosenstein
Copy link
Author

Output

0: 8
0.1: 19.2
0.2: 30.4
0.3: 41.6
0.4: 52.8
0.5: 64
0.6: 153.6
0.7: 243.2
0.8: 332.8
0.9: 422.4
1: 512
0: 100
0.1: 120
0.2: 140
0.3: 160
0.4: 180
0.5: 200
0.6: 340
0.7: 480
0.8: 620
0.9: 760
1: 900

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment