require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb')) require File.dirname(__FILE__) + '/../lib/flt/math' class TestTrig < Minitest::Test def setup @data = {} Dir[File.join(File.dirname(__FILE__), "data/trigtest/*.txt")].each do |fn| if File.basename(fn) =~ /\A([a-z]+)(\d+)_(\d+)_([a-z]+)\.txt\Z/ method = $1.to_sym radix = $2.to_i prec = $3.to_i angle = $4.to_sym num_class = Flt::Num[radix] @data[radix] ||= {} @data[radix][angle] ||= {} @data[radix][angle][prec] ||= {} @data[radix][angle][prec][method] = File.read(fn).split("\n").map do |line| line.split.map{|x| num_class.Num(x, :base=>radix)} end end end BinNum.context = BinNum::IEEEDoubleContext end def trig_test_data_present?(radix, angle) present = @data && @data[radix] && @data[radix][angle] skip unless present present end def check(f, radix=10, angle=:rad) if trig_test_data_present?(radix, angle) class_num = Num[radix] @data[radix][angle].keys.each do |prec| class_num.context(:precision=>prec, :angle=>angle) do class_num.context.traps[DecNum::DivisionByZero] = false data = @data[radix][angle][prec][f] data.each do |x, result| msg = "#{f}(#{x})==#{result}\ninput: #{x.to_int_scale.inspect} [#{radix} #{angle} #{prec}]" assert_equal result, class_num::Math.send(f, x), msg end end end end end def check_relaxed(f, radix=10, angle=:rad, ulps=1) if trig_test_data_present?(radix, angle) class_num = Num[radix] @data[radix][angle].keys.each do |prec| class_num.context(:precision=>prec, :angle=>angle) do class_num.context.traps[DecNum::DivisionByZero] = false data = @data[radix][angle][prec][f] unless data.nil? data.each do |x, result| y = class_num::Math.send(f, x) if result.special? assert_equal result, y, "#{f}(#{x})==#{result} [#{radix} #{angle} #{prec}]" else err_ulps = (y-result).abs/result.ulp msg = "#{f}(#{x})==#{result} to within #{ulps} ulps; error: #{err_ulps} ulps (#{y})\ninput: #{x.to_int_scale.inspect} [#{radix} #{angle} #{prec}]" assert err_ulps<=ulps, msg end end else skip "Missing data for radix #{radix.inspect} angle #{angle.inspect} prec #{prec.inspect} #{f.inspect}" end end end end end def check_bin(f) if trig_test_data_present?(2, :rad) class_num = BinNum @data[2][:rad].keys.each do |prec| class_num.context do #class_num.context.traps[DecNum::DivisionByZero] = false data = @data[2][:rad][53][f] data.each do |x, result| x = class_num.Num(x) result = ::Math.send(f, x.to_f) assert_equal result, class_num::Math.send(f, x), "#{f}(#{x})==#{result} [bin]" end end end end end def test_data_present if @data.empty? skip "No data for trigonometry tests. Generate it with tst/generate_trig_data.rb" end end def test_sin check :sin, 10, :rad end def test_cos check :cos, 10, :rad end def test_tan check_relaxed :tan, 10, :rad end def test_asin check_relaxed :asin, 10, :rad end def test_acos check_relaxed :acos, 10, :rad end def test_atan check_relaxed :atan, 10, :rad end def test_sin_deg check_relaxed :sin, 10, :deg end def test_cos_deg check_relaxed :cos, 10, :deg end def test_tan_deg check_relaxed :tan, 10, :deg end def test_asin_deg check_relaxed :asin, 10, :deg end def test_acos_deg check_relaxed :acos, 10, :deg end def test_atan_deg check_relaxed :atan, 10, :deg end def test_sin_bin check_relaxed :sin, 2, :rad end def test_cos_bin check_relaxed :cos, 2, :rad end def test_tan_bin check_relaxed :tan, 2, :rad end def test_asin_bin check_relaxed :asin, 2, :rad end def test_acos_bin check_relaxed :acos, 2, :rad end def test_atan_bin check_relaxed :atan, 2, :rad end # def test_bin # check_bin :sin # end end