1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
#include <cassert>
using namespace std;
//--------------------------------------
struct TempResponse // Basic data structure
{
double kelvin;
double mV;
double sensitivity;
};
//--------------------------------------
istream &operator >> ( istream &in, TempResponse &tr ) // Read one data item
{
double V;
in >> tr.kelvin >> V >> tr.sensitivity;
tr.mV = 1000 * V; // Conversion V to mV
return in;
}
//--------------------------------------
vector<TempResponse> getData( istream &in ) // Read data from any input stream
{
vector<TempResponse> result;
string line;
TempResponse tr;
while ( getline( in, line ) )
{
stringstream ss( line );
if ( ss >> tr ) result.push_back( tr );
}
return result;
}
//--------------------------------------
// Interpolate (NOT use closest).
// Independent variable x, dependent variable y
// Use MEMBER POINTERS to specify these; see https://en.cppreference.com/w/cpp/language/pointer
// NOTE: must be sorted by whatever is x
double interpolate( const vector<TempResponse> &data, double TempResponse::* x, double TempResponse::* y, double xValue )
{
auto ip = lower_bound( data.begin(), data.end(), xValue, [ x ]( TempResponse a, double b ){ return a.*x < b; } );
// No extrapolation beyond data limits
if ( ip == data.end () ) return data.back ().*y;
if ( ip == data.begin() ) return data.front().*y;
// Otherwise, linear interpolation
auto im = ip - 1;
double slope = ( (*ip).*y - (*im).*y ) / ( (*ip).*x - (*im).*x ); // dY/dX
return (*im).*y + slope * ( xValue - (*im).*x ); // Y0 + (dY/dX) * ( X - X0 )
}
//--------------------------------------
int main()
{
// Get data
// ifstream in( "data.dat" ); assert( in ); // Data file ...
stringstream in( " \n" // ... or fudged for demonstration
"Temp. Voltage Sensitivity \n"
"(Kelvin) (Volts) (milliVolts/Kelvin)\n"
" \n"
"1.4 1.644290 -12.5 \n"
"1.5 1.642990 -13.6 \n"
"1.6 1.641570 -14.8 \n"
"1.7 1.640030 -16.0 \n"
"1.8 1.638370 -17.1 \n" );
vector<TempResponse> data = getData( in );
cout << "Data read" << '\n' << "T" << '\t' << "mV" << '\t' << "sensitivity (mV)" << '\n';
for ( TempResponse tr : data ) cout << tr.kelvin << '\t' << tr.mV << '\t' << tr.sensitivity << '\n';
cout << '\n';
// Do some interpolation: temperature to voltage
cout << "Temperature as independent variable" << '\n' << "T" << '\t' << "mV" << '\n';
sort( data.begin(), data.end(), []( TempResponse a, TempResponse b ){ return a.kelvin < b.kelvin; } );
double Tvalues[] = { 1.0, 1.425, 1.65, 1.9 };
for ( double T : Tvalues ) cout << T << '\t' << interpolate( data, &TempResponse::kelvin, &TempResponse::mV, T ) << '\n';
cout << '\n';
// Do some interpolation: voltage to temperature
cout << "milliVolts as independent variable" << '\n' << "mV" << "\t" << "T" << '\n';
sort( data.begin(), data.end(), []( TempResponse a, TempResponse b ){ return a.mV < b.mV; } );
double mVvalues[] = { 1630.0, 1642.0, 1648.0 };
for ( double mV : mVvalues ) cout << mV << '\t' << interpolate( data, &TempResponse::mV, &TempResponse::kelvin, mV ) << '\n';
cout << '\n';
}
//--------------------------------------
| |