// Copyright ©2017 The Gonum Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package plot import ( "math" "reflect" "testing" ) var talbotLinHanrahanTests = []struct { dMin, dMax float64 want int containment int wantValues []float64 wantStep float64 wantMagnitude int }{ // Expected values confirmed against R reference implementation. { dMin: -1.9846500878911073, dMax: 0.4370974820125605, want: 3, containment: free, wantValues: []float64{-2, -1, 0}, wantStep: 1, wantMagnitude: 0, }, { dMin: -1.9846500878911073, dMax: 0.4370974820125605, want: 3, containment: containData, wantValues: []float64{-2, -1, 0, 1}, wantStep: 1, wantMagnitude: 0, }, { dMin: -1.985e-15, dMax: 0.4371e-15, want: 3, containment: free, wantValues: []float64{-1.985e-15, -7.739500000000001e-16, 4.3709999999999994e-16}, wantStep: 1.21105e-15, wantMagnitude: -16, }, { dMin: -1.985e-15, dMax: 0.4371e-15, want: 3, containment: containData, wantValues: []float64{-1.985e-15, -7.739500000000001e-16, 4.3709999999999994e-16}, wantStep: 1.21105e-15, wantMagnitude: -16, }, { dMin: -1.985e15, dMax: 0.4371e15, want: 3, containment: free, wantValues: []float64{-2e+15, -1e+15, 0}, wantStep: 1, wantMagnitude: 15, }, { dMin: -1.985e15, dMax: 0.4371e15, want: 3, containment: containData, wantValues: []float64{-2e+15, -1e+15, 0, 1e+15}, wantStep: 1, wantMagnitude: 15, }, { dMin: dlamchP * 20, dMax: dlamchP * 50, want: 3, containment: free, wantValues: []float64{4.440892098500626e-15, 7.771561172376096e-15, 1.1102230246251565e-14}, wantStep: 3.3306690738754696e-15, wantMagnitude: -15, }, { dMin: dlamchP * 20, dMax: dlamchP * 50, want: 3, containment: containData, wantValues: []float64{4.440892098500626e-15, 7.771561172376096e-15, 1.1102230246251565e-14}, wantStep: 3.3306690738754696e-15, wantMagnitude: -15, }, { dMin: math.MaxFloat64 / 4, dMax: math.MaxFloat64 / 3, want: 3, containment: free, wantValues: []float64{4.4942328371557893e+307, 5.243271643348421e+307, 5.992310449541053e+307}, wantStep: 7.490388061926317e+306, wantMagnitude: 307, }, { dMin: math.MaxFloat64 / 4, dMax: math.MaxFloat64 / 3, want: 3, containment: containData, wantValues: []float64{4.4942328371557893e+307, 5.243271643348421e+307, 5.992310449541053e+307}, wantStep: 7.490388061926317e+306, wantMagnitude: 307, }, { dMin: 0.00010, dMax: 0.00015, want: 3, containment: free, wantValues: []float64{0.0001, 0.000125, 0.00015000000000000001}, wantStep: 2.5, wantMagnitude: -5, }, { dMin: 0.00010, dMax: 0.00015, want: 3, containment: containData, wantValues: []float64{0.0001, 0.000125, 0.00015000000000000001}, wantStep: 2.5, wantMagnitude: -5, }, { dMin: 555.6545, dMax: 21800.9875, want: 3, containment: free, wantValues: []float64{0, 10000, 20000}, wantStep: 1, wantMagnitude: 4, }, { dMin: 555.6545, dMax: 21800.9875, want: 3, containment: containData, wantValues: []float64{0, 12000, 24000}, wantStep: 12, wantMagnitude: 3, }, { dMin: 555.6545, dMax: 27800.9875, want: 3, containment: free, wantValues: []float64{0, 10000, 20000, 30000}, wantStep: 1, wantMagnitude: 4, }, { dMin: 555.6545, dMax: 27800.9875, want: 3, containment: containData, wantValues: []float64{0, 10000, 20000, 30000}, wantStep: 1, wantMagnitude: 4, }, { dMin: 55.6545, dMax: 1555.9875, want: 3, containment: free, wantValues: []float64{0, 500, 1000, 1500}, wantStep: 5, wantMagnitude: 2, }, { dMin: 55.6545, dMax: 1555.9875, want: 3, containment: containData, wantValues: []float64{0, 800, 1600}, wantStep: 8, wantMagnitude: 2, }, { dMin: 3.096916 - 0.125, dMax: 3.096916 + 0.125, want: 3, containment: free, wantValues: []float64{3, 3.1, 3.2}, wantStep: 1, wantMagnitude: -1, }, { dMin: 3.096916 - 0.125, dMax: 3.096916 + 0.125, want: 3, containment: containData, wantValues: []float64{2.9499999999999997, 3.0999999999999996, 3.2499999999999996}, wantStep: 15, wantMagnitude: -2, }, // The following fails in the reference implementation with a // warning of "probable complete loss of accuracy in modulus". { dMin: 99.99999999999996, dMax: 100, want: 3, containment: free, wantValues: []float64{99.99999999999996, 99.99999999999997, 100}, wantStep: 2, wantMagnitude: -14, }, } func TestTalbotLinHanrahan(t *testing.T) { for _, test := range talbotLinHanrahanTests { values, step, _, magnitude := talbotLinHanrahan(test.dMin, test.dMax, test.want, test.containment, nil, nil, nil) if !reflect.DeepEqual(values, test.wantValues) { t.Errorf("unexpected values for dMin=%g, dMax=%g, want=%d, containment=%d:\ngot: %v\nwant:%v", test.dMin, test.dMax, test.want, test.containment, values, test.wantValues) } if step != test.wantStep { t.Errorf("unexpected step for dMin=%g, dMax=%g, want=%d, containment=%d: got:%v want:%v", test.dMin, test.dMax, test.want, test.containment, step, test.wantStep) } if magnitude != test.wantMagnitude { t.Errorf("unexpected magnitude for dMin=%g, dMax=%g, want=%d, containment=%d: got:%d want:%d", test.dMin, test.dMax, test.want, test.containment, magnitude, test.wantMagnitude) } if test.containment == containData { f := math.Pow10(-magnitude) if test.containment == containData && (test.dMin*f < values[0]*f || values[len(values)-1]*f < test.dMax*f) { t.Errorf("unexpected values for containment dMin=%g, dMax=%g, want=%d not containment:\ngot: %v\nwant:%v", test.dMin, test.dMax, test.want, values, test.wantValues) } } } }