#include <vector>
#include <algorithm>
#include <memory>
#include <iostream>

template<typename T>
T interpolate(uint16_t factor, const T& from, const T& to)
{
    return T(double(from) + double(factor) * (double(to) - double(from)) / double(0xFFFF));
}

template<typename T>
void test(const T& from, const T& to)
{
    for(uint16_t t = 0; t < 0xFFFF; t += 0xFFFF / 5)
    {
        const T& r = interpolate(t, from, to);
        std::cout << "interpolate(" << t << ", " << from << ", " << to << ") = " << r << "\n";
    }
    
    {
        const uint16_t t = 0xFFFF;
        const T& r = interpolate(t, from, to);
        std::cout << "interpolate(" << t << ", " << from << ", " << to << ") = " << r << "\n";
    }
}

template<typename T>
void test_lims()
{
    const T lowest = std::numeric_limits<T>::lowest();
    const T max = std::numeric_limits<T>::max();
    test(lowest, max);
    test(max, lowest);
}

int main()
{
    test(0, 10);
    test(-25, 33);
    test(1, 2);
    test(1, 1);
    test(1, 0);
    test(1, -1);
    test(-1, 1);
    test(-1, -1);

    test<int8_t>('0', '9');
    test<int8_t>('A', 'Z');
    test<uint8_t>('0', '9');
    test<uint8_t>('A', 'Z');
    
    test_lims<int16_t>();
    test_lims<uint16_t>();
    test_lims<int32_t>();
    test_lims<uint32_t>();
}
