rsl-interpolation 0.1.18

A re-write of GSL's Interpolation Routines in Rust.
Documentation
use crate::Bicubic;
use crate::Interpolation2d;
use crate::interp2d::Interp2dType;
use crate::tests::XYZTable;
use crate::tests::test_interp2d;
use crate::tests::test_interp2d_extra;
use crate::{Accelerator, Cache};

#[test]
fn test_type_fields() {
    let _ = <Bicubic as Interp2dType<f64>>::name(&Bicubic);
    let _ = <Bicubic as Interp2dType<f64>>::min_size(&Bicubic);
}

/// Linear case
#[test]
fn gsl_test_bicubic1() {
    let xa = [0.0, 1.0, 2.0, 3.0];
    let ya = [0.0, 1.0, 2.0, 3.0];
    #[rustfmt::skip]
    let za = [
        1.0, 1.1, 1.2, 1.3,
        1.1, 1.2, 1.3, 1.4,
        1.2, 1.3, 1.4, 1.5,
        1.3, 1.4, 1.5, 1.6,
    ];

    let xtest = [1.0, 1.5, 2.0];
    let ytest = [1.0, 1.5, 2.0];
    let ztest = [1.2, 1.3, 1.4];

    let data_table = XYZTable {
        x: &xa,
        y: &ya,
        z: &za,
    };

    let test_e_table = XYZTable {
        x: &xtest,
        y: &ytest,
        z: &ztest,
    };

    let interp = Bicubic.build(&xa, &ya, &za).unwrap();
    test_interp2d(data_table, test_e_table, interp);
}

/// Nonlinear case
#[test]
fn gsl_test_bicubic2() {
    let xa = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
    let ya = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];

    /* least common multiple of x and y */
    #[rustfmt::skip]
    let za = [
        1.0,  2.0,  3.0,  4.0,  5.0,  6.0,  7.0,  8.0,
        2.0,  2.0,  6.0,  4.0, 10.0,  6.0, 14.0,  8.0,
        3.0,  6.0,  3.0, 12.0, 15.0,  6.0, 21.0, 24.0,
        4.0,  4.0, 12.0,  4.0, 20.0, 12.0, 28.0,  8.0,
        5.0, 10.0, 15.0, 20.0,  5.0, 30.0, 35.0, 40.0,
        6.0,  6.0,  6.0, 12.0, 30.0,  6.0, 42.0, 24.0,
        7.0, 14.0, 21.0, 28.0, 35.0, 42.0,  7.0, 56.0,
        8.0,  8.0, 24.0,  8.0, 40.0, 24.0, 56.0,  8.0,
    ];
    let xtest = [1.4, 2.3, 4.7, 3.3, 7.5, 6.6, 5.1];
    let ytest = [1.0, 1.8, 1.9, 2.5, 2.7, 4.1, 3.3];

    /* results computed using GSL 1D cubic interpolation twice */
    let ztest = [
        1.4,
        3.11183531264736,
        8.27114315792559,
        5.03218982537718,
        22.13230634702637,
        23.63206834997871,
        17.28553080971182,
    ];

    let data_table = XYZTable {
        x: &xa,
        y: &ya,
        z: &za,
    };

    let test_e_table = XYZTable {
        x: &xtest,
        y: &ytest,
        z: &ztest,
    };

    let interp = Bicubic.build(&xa, &ya, &za).unwrap();
    test_interp2d(data_table, test_e_table, interp);
}

/// Nonlinear case non-square
/// This function contributed by Andrew W. Steiner <awsteiner@gmail.com>
#[test]
fn gsl_test_bicubic3() {
    let xa = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0];
    let ya = [1.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0];
    #[rustfmt::skip]
    let za = [
        1.0,  2.0,  3.0,  4.0,  5.0,  6.0,  7.0,  8.0,  9.0, 10.0,
        2.0,  2.0,  6.0,  4.0, 10.0,  6.0, 14.0,  8.0, 11.0, 12.0,
        3.0,  6.0,  3.0, 12.0, 15.0,  6.0, 21.0, 24.0, 13.0, 14.0,
        4.0,  4.0, 12.0,  4.0, 20.0, 12.0, 28.0,  8.0, 15.0, 16.0,
        5.0, 10.0, 15.0, 20.0,  5.0, 30.0, 35.0, 40.0, 17.0, 18.0,
        6.0,  6.0,  6.0, 12.0, 30.0,  6.0, 42.0, 24.0, 19.0, 20.0,
        7.0, 14.0, 21.0, 28.0, 35.0, 42.0,  7.0, 56.0, 21.0, 22.0,
        8.0,  8.0, 24.0,  8.0, 40.0, 24.0, 56.0,  8.0, 23.0, 24.0,
    ];

    let xtest = [1.4, 2.3, 9.7, 3.3, 9.5, 6.6, 5.1];
    let ytest = [1.0, 1.8, 1.9, 2.5, 2.7, 4.1, 3.3];

    // results computed using GSL 1D cubic interpolation twice
    let ztest = [
        1.4,
        2.46782030941187003,
        10.7717721621846465,
        4.80725067958096375,
        11.6747032398627297,
        11.2619968682970111,
        9.00168877916872567,
    ];

    let data_table = XYZTable {
        x: &xa,
        y: &ya,
        z: &za,
    };

    let test_e_table = XYZTable {
        x: &xtest,
        y: &ytest,
        z: &ztest,
    };

    let interp = Bicubic.build(&xa, &ya, &za).unwrap();
    test_interp2d(data_table, test_e_table, interp);
}

/// Extra test that includes all derivatives, and iterates through all (x, y) pairs.
#[test]
fn extra_test_bicubic() {
    let xa = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
    let ya = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
    #[rustfmt::skip]
    let za = [
        1.0,  2.0,  3.0,  4.0,  5.0,  6.0,  7.0,  8.0,
        2.0,  2.0,  6.0,  4.0, 10.0,  6.0, 14.0,  8.0,
        3.0,  6.0,  3.0, 12.0, 15.0,  6.0, 21.0, 24.0,
        4.0,  4.0, 12.0,  4.0, 20.0, 12.0, 28.0,  8.0,
        5.0, 10.0, 15.0, 20.0,  5.0, 30.0, 35.0, 40.0,
        6.0,  6.0,  6.0, 12.0, 30.0,  6.0, 42.0, 24.0,
        7.0, 14.0, 21.0, 28.0, 35.0, 42.0,  7.0, 56.0,
        8.0,  8.0, 24.0,  8.0, 40.0, 24.0, 56.0,  8.0,
    ];

    let xtest = [
        1.0000, 1.8750, 2.7500, 3.6250, 4.5000, 5.3750, 6.2500, 7.1250, 8.0000,
    ];
    let ytest = [
        1.0000, 1.8750, 2.7500, 3.6250, 4.5000, 5.3750, 6.2500, 7.1250, 8.0000,
    ];
    #[rustfmt::skip]
    let ztest = [
        1.000000000000000, 1.875000000000000, 2.750000000000000, 3.625000000000000, 4.500000000000000,
        5.375000000000000, 6.250000000000000, 7.125000000000000, 8.000000000000000, 1.875000000000000,
        1.254509243872024, 5.669632661523053, 3.745024334805152, 6.512662913348347, 8.383113706545888,
        7.218120241331311, 13.271999431999280, 6.390372724149760, 2.750000000000000, 5.669632661523053,
        2.950900870271933, 7.883385553541205, 14.305499175057211, 9.549580622954057, 8.072063510921939,
        20.473327141914499, 23.212040535898314, 3.625000000000000, 3.745024334805154, 7.883385553541214,
        4.268219428794188, 14.733204524537509, 15.993533578343033, 9.724122152691743, 26.354800347252240,
        10.684290192373744, 4.500000000000000, 6.512662913348346, 14.305499175057218, 14.733204524537515,
        9.551800238048003, 15.107939500705493, 27.793279899035234, 29.866861897267107, 24.676056338028168,
        5.375000000000000, 8.383113706545888, 9.549580622954055, 15.993533578343037, 15.107939500705497,
        12.124863708355404, 25.983553197888618, 42.453056668299737, 35.097399948471313, 6.250000000000000,
        7.218120241331312, 8.072063510921939, 9.724122152691743, 27.793279899035230, 25.983553197888629,
        13.628168266570457, 34.996623468550816, 30.108381999312954, 7.125000000000000, 13.271999431999280,
        20.473327141914499, 26.354800347252240, 29.866861897267100, 42.453056668299737, 34.996623468550816,
        8.585001196037567, 55.353025163174173, 8.000000000000000, 6.390372724149773, 23.212040535898304,
        10.684290192373755, 24.676056338028165, 35.097399948471313, 30.108381999312950, 55.353025163174166,
        8.000000000000071,
    ];

    #[rustfmt::skip]
    let dxtest = [
        1.000000000000000, -2.275466778454743, 5.083797224744011, -1.259444982914344, 0.543235711071651,
        4.147279261645819, 1.100269646424601, 6.712423784359979, -7.848849192717283, 1.000000000000000,
        2.423536678756426, -0.157425324266119, 2.930401970874926, 5.814087137908174, 2.018974184865698,
        1.118730106001013, 7.650579055277569, 10.178976296805180, 1.000000000000000, 3.769979545027799,
        -1.745992939322312, 2.244361691441426, 7.851374824004148, 3.165607331435293, 0.588180380732618,
        8.115271083270972, 11.792854689110273, 1.000000000000000, -4.188838868044227, 10.445105354630591,
        -3.406434418205000, -5.515115647725247, 7.585411254543290, 7.781990824176535, 5.069465949112084,
        -21.165149433184496, 1.000000000000000, 8.606904509859566, 1.841733364194698, 21.024581201796600,
        -3.013912744761272, -7.929958971463375, 24.776863123266651, 5.693226593068973, 43.317073170731696,
        1.000000000000000, -5.625487227674274, -10.324694047134717, -20.033291130981805, 15.525705865863340,
        5.227119209594348, -29.615289234203736, 18.607609986082483, -26.066557883888716, 1.000000000000000,
        7.541007180346554, 11.549978220263602, 18.669858073896847, 8.771746526047380, 25.006195026342382,
        18.091838975907670, -43.697427593647284, 36.426657506011708, 1.000000000000000, -0.597456202306083,
        9.175994343017793, 0.615993709509895, -3.061658311903370, 3.971131359729886, 10.683115526838263,
        14.334772824796918, -14.148488491927143, 1.000000000000000, -11.498346255160385, 0.106940075320495,
        -27.171728548832334, -7.367694659886503, -14.595262913856530, -13.721400282112626, 73.006368959835712,
        -74.102370319477728,
    ];

    #[rustfmt::skip]
    let dytest = [
        1.000000000000000, 1.000000000000000, 1.000000000000000, 1.000000000000000, 1.000000000000000,
        1.000000000000000, 1.000000000000000, 1.000000000000000, 1.000000000000000, -2.275466778454743,
        2.423536678756424, 3.769979545027809, -4.188838868044223, 8.606904509859564, -5.625487227674274,
        7.541007180346553, -0.597456202306086, -11.498346255160433, 5.083797224744012, -0.157425324266121,
        -1.745992939322312, 10.445105354630545, 1.841733364194682, -10.324694047134717, 11.549978220263608,
        9.175994343017795, 0.106940075320493, -1.259444982914345, 2.930401970874923, 2.244361691441462,
        -3.406434418205006, 21.024581201796583, -20.033291130981802, 18.669858073896847, 0.615993709509892,
        -27.171728548832387, 0.543235711071651, 5.814087137908174, 7.851374824004155, -5.515115647725228,
        -3.013912744761268, 15.525705865863340, 8.771746526047380, -3.061658311903369, -7.367694659886492,
        4.147279261645819, 2.018974184865697, 3.165607331435293, 7.585411254543283, -7.929958971463366,
        5.227119209594353, 25.006195026342393, 3.971131359729885, -14.595262913856537, 1.100269646424601,
        1.118730106001014, 0.588180380732618, 7.781990824176533, 24.776863123266669, -29.615289234203736,
        18.091838975907667, 10.683115526838259, -13.721400282112636, 6.712423784359979, 7.650579055277570,
        8.115271083270972, 5.069465949112085, 5.693226593068973, 18.607609986082480, -43.697427593647284,
        14.334772824796916, 73.006368959835712, -7.848849192717282, 10.178976296805217, 11.792854689110262,
        -21.165149433184453, 43.317073170731668, -26.066557883888709, 36.426657506011736, -14.148488491927152,
        -74.102370319477672,
    ];

    #[rustfmt::skip]
    let dxxtest = [
        0.000000000000000, 0.000000000000002, 0.000000000000007, -0.000000000000002, -0.000000000000004,
        -0.000000000000000, 0.000000000000000, -0.000000000000002, -0.000000000000030, 0.000000000000000,
        10.740579330768384, -11.979937254880303, 9.576793037232617, 12.047660404197773, -4.864697318354564,
        0.042195336174657, 2.144354904954493, 41.206458261765668, 0.000000000000000, -12.520354686095537,
        13.733725575503954, -16.194630301004953, -12.638723443374063, 10.354734368384110, -1.478092271644376,
        -1.977353616115995, -57.506011679835112, 0.000000000000000, 8.639560676395750, 1.492436700237448,
        23.732904084599902, -7.699577488980633, -11.921863917514171, 26.393040080707625, -4.120918950136470,
        46.858124355891420, 0.000000000000000, -1.312195182430910, -15.692447539928647, -13.030946656622994,
        14.825034715334223, -3.296356953771758, -27.802010404923553, 13.498267824267831, -5.408450704225402,
        0.000000000000000, -6.678920589929495, 2.813248449824764, -16.849197737507296, 11.200370982335116,
        23.517590672112718, -21.963790755963199, -22.662943563985532, -33.336997595328157, 0.000000000000000,
        15.671911160807749, 24.763276673735220, 47.128552294998684, -16.792193041450368, 7.562705827043830,
        63.916029766503598, -46.407223728091381, 70.689110271384422, 0.000000000000000, -24.916320120809843,
        -20.729266897593803, -63.514793733353699, -9.842368795390009, -42.437472625340362, -55.781750420459112,
        134.106505451517307, -137.037444177258436, 0.000000000000000, 0.000000000000005, -0.000000000000021,
        0.000000000000011, -0.000000000000021, -0.000000000000007, -0.000000000000054, -0.000000000000078,
        -0.000000000000171,
    ];

    #[rustfmt::skip]
    let dyytest = [
        0.000000000000000, 0.000000000000000, 0.000000000000000, 0.000000000000000, 0.000000000000000,
        0.000000000000000, 0.000000000000000, 0.000000000000000, 0.000000000000000, 0.000000000000005,
        10.740579330768375, -12.520354686095505, 8.639560676395771, -1.312195182430912, -6.678920589929498,
        15.671911160807742, -24.916320120809871, -0.000000000000068, 0.000000000000001, -11.979937254880303,
        13.733725575503939, 1.492436700237377, -15.692447539928690, 2.813248449824757, 24.763276673735227,
        -20.729266897593789, -0.000000000000036, -0.000000000000004, 9.576793037232619, -16.194630301004885,
        23.732904084599909, -13.030946656623051, -16.849197737507314, 47.128552294998684, -63.514793733353720,
        -0.000000000000057, -0.000000000000005, 12.047660404197774, -12.638723443374063, -7.699577488980587,
        14.825034715334215, 11.200370982335105, -16.792193041450378, -9.842368795390012, 0.000000000000018,
        0.000000000000001, -4.864697318354565, 10.354734368384111, -11.921863917514180, -3.296356953771745,
        23.517590672112732, 7.562705827043835, -42.437472625340376, -0.000000000000012, -0.000000000000001,
        0.042195336174659, -1.478092271644376, 26.393040080707625, -27.802010404923553, -21.963790755963213,
        63.916029766503598, -55.781750420459112, -0.000000000000049, -0.000000000000002, 2.144354904954493,
        -1.977353616115995, -4.120918950136469, 13.498267824267829, -22.662943563985536, -46.407223728091381,
        134.106505451517279, -0.000000000000051, 0.000000000000002, 41.206458261765711, -57.506011679835119,
        46.858124355891476, -5.408450704225501, -33.336997595328114, 70.689110271384592, -137.037444177258493,
        0.000000000000057,
    ];

    #[rustfmt::skip]
    let dxytest = [
        -7.056077936058172, 2.881984060271510, 5.668659201566772, -12.204380320220121, 13.588650283617227,
        -8.447867566265959, 8.321696974753483, -5.495343500075117, -22.214510496380608, 2.881984060271510,
        -0.883270936235284, -1.840245677323928, 6.618455950002904, -1.096485104858797, -5.820221076637015,
        5.782916383109787, 5.513694306529366, 1.577548117925467, 5.668659201566776, -1.840245677323935,
        -4.948434279272853, 10.618243231986725, 0.155753826947414, -8.625685402297474, 5.809894187966529,
        6.961170070631264, 2.823844003266004, -12.204380320220121, 6.618455950002900, 10.618243231986831,
        -27.579360815351563, 21.110789158658037, 1.641035939925075, 3.990692265385457, -17.959367143012408,
        -35.993942798145106, 13.588650283617227, -1.096485104858790, 0.155753826947443, 21.110789158658129,
        -58.729030339083948, 57.079034606957634, -15.760490590778481, 9.384529795519096, 59.805757806805104,
        -8.447867566265959, -5.820221076637016, -8.625685402297464, 1.641035939925079, 57.079034606957656,
        -83.337018326730885, 47.341371828259511, 3.581949084879246, -78.375262319533107, 8.321696974753483,
        5.782916383109795, 5.809894187966526, 3.990692265385463, -15.760490590778478, 47.341371828259504,
        -89.149557175184896, 14.183689664912425, 130.263729624102012, -5.495343500075114, 5.513694306529372,
        6.961170070631262, -17.959367143012400, 9.384529795519091, 3.581949084879244, 14.183689664912437,
        -16.191561418457894, -40.732667262297980, -22.214510496380612, 1.577548117925566, 2.823844003266004,
        -35.993942798144978, 59.805757806805033, -78.375262319533050, 130.263729624102069, -40.732667262298023,
        -231.820076561959922,
    ];

    let data_table = XYZTable {
        x: &xa,
        y: &ya,
        z: &za,
    };

    let test_e_table = XYZTable {
        x: &xtest,
        y: &ytest,
        z: &ztest,
    };

    let test_dx_table = XYZTable {
        x: &xtest,
        y: &ytest,
        z: &dxtest,
    };

    let test_dy_table = XYZTable {
        x: &xtest,
        y: &ytest,
        z: &dytest,
    };

    let test_dxx_table = XYZTable {
        x: &xtest,
        y: &ytest,
        z: &dxxtest,
    };

    let test_dyy_table = XYZTable {
        x: &xtest,
        y: &ytest,
        z: &dyytest,
    };

    let test_dxy_table = XYZTable {
        x: &xtest,
        y: &ytest,
        z: &dxytest,
    };

    let interp = Bicubic.build(&xa, &ya, &za).unwrap();
    test_interp2d_extra(
        data_table,
        test_e_table,
        test_dx_table,
        test_dy_table,
        test_dxx_table,
        test_dyy_table,
        test_dxy_table,
        interp,
    );
}

/// Fixes a bug where the uninitialized Cache appears updated the first time it is called.
///
/// If x[0] <= x <= x[1] AND y[0] <= y <= y[0] on the first called, the Cache's acc indices are
/// zero, while all the other fields where NaNs.
///
/// This caused the interpolator to believe that the Cache is updated, causing NaNs to bubble up.
#[test]
fn test_uninit_cache_00eval() {
    let xa = [0.0, 1.0, 2.0, 3.0];
    let ya = [0.0, 1.0, 2.0, 3.0];
    #[rustfmt::skip]
    let za = [
        1.0, 1.1, 1.2, 1.3,
        1.1, 1.2, 1.3, 1.4,
        1.2, 1.3, 1.4, 1.5,
        1.3, 1.4, 1.5, 1.6,
    ];

    let interp = Bicubic.build(&xa, &ya, &za).unwrap();
    let mut xacc = Accelerator::new();
    let mut yacc = Accelerator::new();
    let mut cache = Cache::new();

    let v: f64 = interp
        .eval(&xa, &ya, &za, 0.5, 0.5, &mut xacc, &mut yacc, &mut cache)
        .unwrap();
    assert!(v.is_finite());
}