include("program.jl")
set_cordic_iterations (generic function with 1 method)
using Plots
using Random
using Distributions
plotly()
Plots.PlotlyBackend()
# Zadanie 10, Franiszek malinka, Kacper Solecki
# instrukcja:
# Nasz program udostępnia funkcje
# -> taylor_sin(a, b) - sinus liczby a+bi liczony za pomocą szeregu Taylora
# -> taylor_cos(a, b) - cosinus liczby a+bi liczony za pomocą szeregu Taylora
# -> taylor_sinh(x) - sinus hiperboliczny liczby x liczony za pomocą szeregu Taylora
# -> taylor_cosh(x) - cosinus hiperboliczny liczby x liczony za pomocą szeregu Taylora
# -> cordic_sin(x) - sinus (rzeczywistej) liczby x liczony za pomocą algorytmu Cordic
# -> cordic_cos(x) - cosinus (rzeczywistej) liczby x liczony za pomocą algorytmu Cordic
# porównianie na sin(2), cos(2)
sin(2.0)
0.9092974268256817
taylor_sin(2.0, 0.0)
(0.9092974268256817, -0.0)
cordic_sin(2.0)
0.9092974280938506
cos(2)
-0.4161468365471424
taylor_cos(2.0, 0.0)
(-0.41614683654714246, -0.0)
cordic_cos(2.0)
-0.4161468353122473
# porównianie na sin(10 + 10i)
sin(10 + 10im)
-5991.431207677988 - 9240.89014825243im
taylor_sin(10, 10)
(-5991.431207678, -9240.890148252452)
# w ten sposób liczony jest błąd względny zarówno dla liczb rzeczywistych jak i zespolonych
function rel_error(x, y)
if x == 0
return 0
end
return abs((x-y)/x)
end
rel_error (generic function with 1 method)
# Funkcje użyte w wykresach błędów od liczby iteracji:
# błąd przy liczeniu sin(100 + 100i) szeregiem Taylora przy x iteracjach
function taylor_error_of_iterations(x)
set_taylor_iterations(x)
return rel_error(sin(100+100im), taylor_sin(100, 100)[1] + taylor_sin(100, 100)[2]*im)
end
taylor_error_of_iterations (generic function with 1 method)
# błąd przy liczeniu sin(100) Cordicem przy x iteracjach
function cordic_error_of_iterations(x)
set_cordic_iterations(x)
return rel_error(sin(100), cordic_sin(100.0))
end
cordic_error_of_iterations (generic function with 1 method)
# błąd przy liczeniu sin(100) szeregiem Taylora przy x iteracjach
function taylor_error_of_iterations2(x)
set_taylor_iterations(x)
return rel_error(sin(100), taylor_sin(100.0, 0.0)[1])
end
taylor_error_of_iterations2 (generic function with 1 method)
X = 1:20
1:20
# Przykładowe błędy w zależności od liczby iteracji
# obrazują jak szybko zbiega metoda:
plot(taylor_error_of_iterations, X, title="Taylor relative error calculating sin(100+100i)", xguide = "iterations", yguide = "relative error")
plot(taylor_error_of_iterations2, X, title="Taylor relative error calculating sin(100)", xguide = "iterations", yguide = "relative error")
plot(cordic_error_of_iterations, X, title="CORDIC relative error calculating sin(100)", xguide = "iterations", yguide = "relative error")
# funkcje do kolejnych wykresów, pokaujących błąd względny liczenia sinusa w przedziale [0, 2pi]:
function rel_error_cordic(x)
return rel_error(sin(x), cordic_sin(x))
end
rel_error_cordic (generic function with 1 method)
function rel_error_taylor(x)
return rel_error(sin(x), taylor_sin(x, 0.0)[1])
end
rel_error_taylor (generic function with 1 method)
xs = range(0, stop = 6.3, step = 0.01)
OX = [x for x in xs]
# rysowane zbiory punktów:
res_cordic = [rel_error_cordic(x) for x in xs]
res_taylor = [rel_error_taylor(x) for x in xs]
631-element Array{Real,1}: 0 0.0 0.0 1.1566558078817942e-16 0.0 1.3883571906382453e-16 0.0 0.0 1.7365752302283546e-16 1.5440600601196135e-16 1.3900944467230525e-16 0.0 1.1592625449066459e-16 ⋮ 2.684565604502478e-15 2.839380050077419e-15 3.0367153263107948e-15 3.956085449056853e-15 4.6990042927913394e-15 5.625450115568505e-15 7.319681171152798e-15 1.062538454174323e-14 1.8551186877114254e-14 7.69251100506661e-14 1.2727917079577463e-16 2.0634396850290369e-16
# Błąd względny obliczania sinusa Cordicem na przedziale (0, 6.3)
plot(OX, res_cordic, xguide = "x", yguide = "relative error", label = "cordic_sin")
# Błąd względny obliczania sinusa szeregiem Taylora na przedziale (0, 6.3)
plot(OX, res_taylor, xguide = "x", yguide = "relative error", label = "taylor_sin")
# Poniżej znajdują się funkcje testujące, na podstawie których powstała Tabela 2 w sprawozdaniu
TESTS = 100000000
Random.seed!(12345)
MersenneTwister(UInt32[0x00003039], Random.DSFMT.DSFMT_state(Int32[-870096391, 1072918504, -1812426662, 1073255081, -733866021, 1073404543, 807620846, 1073368448, 1919433844, 1072852359 … -362113007, 1073100625, -166402106, 1073460158, -1907020342, 721295190, -750225566, -1300227565, 382, 0]), [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 … 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], UInt128[0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000 … 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000], 1002, 0)
# wszystkie te funkcje wyglądają bardzo podobnie
function taylor_test_error_real(l::Float64=floatmin(), r::Float64=floatmax())
res = BigFloat(0) # suma błędów względnych
abs_res = BigFloat(0) # suma błędów bezwzględnych
maksi_rel = BigFloat(0) # max bląd względny
maksi_abs = BigFloat(0) # max bląd bezwzględny
for i = 1:TESTS
# losujemy argument z przedziału [l, r]
x = rand(Uniform(l, r))
lib_sin = sin(x)
# sprawdzanie błędu względnego z zerem nie ma sensu
if lib_sin == 0
continue
end
my_sin = taylor_sin(x, 0)
# obliczamy błąd względny względem funkcji bibliotecznej
error = rel_error(lib_sin, my_sin[1])
# obliczamy błąd bezwzględny względem funkcji bibliotecznej
abs_error = abs(my_sin[1] - lib_sin)
# aktualizujemy błędy
res += error
abs_res += abs_error
maksi_rel = max(maksi_rel, error)
maksi_abs = max(maksi_abs, abs_error)
end
return (res/TESTS, maksi_rel, abs_res/TESTS, maksi_abs)
end
# (floatmin(), floatmax()):
# (1.887844299668514797145972383393008309519973773948872165524132116232181033410611e-15,
# 3.16719187748669057932019506480803006098767582443542778491973876953125e-08,
# 1.1794041986528804301572959036155385792454808324691839516162872314453125e-16,
# 8.8817841970012523233890533447265625e-16)
# (-pi/2, pi/2):
# (1.471587646915289673578957365178574707202863924359834292944840261618821841693717e-15,
# 1.1848604479598457485905096801294400510329296594136394560337066650390625e-08,
# 9.765754183892570637182101557852154094518937199609354138374328613281249999999994e-17,
# 5.5511151231257827021181583404541015625e-16)
# (0, 1):
# (8.693695902799099432701533207691913249153884601349429181102457242502623557811573e-17,
# 6.661260307992334044328275268948192015174572739102942797728701407322660088539124e-16,
# 4.293257315426284893844499634951716871000826358795166015624999999999999999999994e-17,
# 4.44089209850062616169452667236328125e-16)
taylor_test_error_real (generic function with 3 methods)
function taylor_test_error_complex(l::Float64=-100.0, r::Float64=100.0)
res = BigFloat(0)
abs_res = BigFloat(0)
maksi_rel = BigFloat(0)
maksi_abs = BigFloat(0)
for i = 1:TESTS
x = rand(Uniform(l, r))
y = rand(Uniform(max(l, -Float64(√(BigFloat(r)*r - BigFloat(x)*x))),
Float64(√(BigFloat(r)*r - BigFloat(x)*x))))
lib_sin = sin(x + y*im)
my_sin = taylor_sin(x, y)
error = rel_error(lib_sin, my_sin[1] + my_sin[2]*im)
abs_error = abs(lib_sin - (my_sin[1] + my_sin[2]*im))
res += error
abs_res += abs_error
maksi_rel = max(maksi_rel, error)
maksi_abs = max(maksi_abs, abs_error)
end
return (res/TESTS, maksi_rel, abs_res/TESTS, maksi_abs)
end
# (-100, 100):
# (4.932205036590292360305897845543684560590114030155004375572792447173773555907229e-15,
# 1.3111008357751143737471652583705182364137709072338111582212150096893310546875e-13,
# 1.688623533003329462861070079404255492323042928202526655997186385923664654746476e+26,
# 5.89784569029861503624382775296e+29)
# (-2pi, 2pi):
# (4.338436856498561167962902801400526155223569336855327458414068651872587652334067e-16,
# 1.48720543982594402760972427363260419015678071019692652043886482715606689453125e-11,
# 1.364745868545483273874507699553481910023596725366415789061836204439613629002538e-14,
# 8.7095846425677781478128738959826782468909289747216462274082005023956298828125e-13)
# (0, 1):
# (1.596935223079780368874812440778376297707878344605454825588075017177200118204992e-16,
# 1.098997011961567777204023105931451003520679665648174250236479565501213073730469e-15,
# 1.124298405324025732059699593805301650508046127888472394113736655893442950571177e-16,
# 1.110569915127177230816030746289393434073728902933275719533412484452128410339355e-15)
taylor_test_error_complex (generic function with 3 methods)
function cordic_test_error(l::Float64=floatmin(), r::Float64=floatmax())
res = BigFloat(0)
abs_res = BigFloat(0)
maksi_rel = BigFloat(0)
maksi_abs = BigFloat(0)
for i = 1:TESTSd
x = rand(Uniform(l, r))
lib_sin = sin(x)
my_sin = cordic_sin(x)
error = rel_error(lib_sin, my_sin)
abs_error = abs(lib_sin - my_sin)
res += error
abs_res += abs_error
if error > maksi_rel
worst_rel = x
end
maksi_rel = max(maksi_rel, error)
maksi_abs = max(maksi_abs, abs_error)
end
return (res/TESTS, maksi_rel, abs_res/TESTS, maksi_abs)
end
# (floatmin(), floatmax()):
# (3.099880824631376815575307358441341907045753361742215192539218280437518515668677e-08,
# 0.457561153670805575988111968399607576429843902587890625,
# 2.459716652636021482355597144179802356154379561203882076370064169168472290039072e-09,
# 0.0006041780891818948617810747236944735050201416015625)
# (-2pi, 2pi):
# (2.769658715752475495709394998775060901506630522496771093654899307916206208091117e-08,
# 0.11834204003306579566778822254491387866437435150146484375,
# 2.532059440779907667675144447194875727078638982803227008844260126352310180664052e-09,
# 0.00552917548107156875403234153054654598236083984375)
# (0, 1):
# (4.176404604808155838824592152607760760141260709650975486490997166423577713345588e-08,
# 0.091828765031669201679420666550868190824985504150390625,
# 2.613683444981852927700279986835644064485650872597943816799670457839965820312493e-09,
# 0.00052619288922584050993691562325693666934967041015625)
cordic_test_error (generic function with 3 methods)
function taylor_without_reduction_test_error(l::Float64=-100.0, r::Float64=100.0)
res = BigFloat(0)
abs_res = BigFloat(0)
maksi_rel = BigFloat(0)
maksi_abs = BigFloat(0)
for i = 1:TESTS
x = rand(Uniform(l, r))
y = rand(Uniform(max(l, -Float64(√(BigFloat(r)*r - BigFloat(x)*x))),
Float64(√(BigFloat(r)*r - BigFloat(x)*x))))
lib_sin = sin(x + y*im)
my_sin = taylor_sin_no_reduction(x, y)
error = rel_error(lib_sin, my_sin[1] + my_sin[2]*im)
abs_error = abs(lib_sin - (my_sin[1] + my_sin[2]*im))
res += error
abs_res += abs_error
maksi_rel = max(maksi_rel, error)
maksi_abs = max(maksi_abs, abs_error)
end
return (res/TESTS, maksi_rel, abs_res/TESTS, maksi_abs)
end
# (-100, 100)
# (4.774091809397734982069398193189465079787514988283523440828527859306283137571149e+23,
# 4.48814142545670189837451264e+26,
# 7.758560481134976967771949796127369173267383351574525337904198599731007318070319e+40,
# 2.20832987186165589366506156220211970162294784e+44)
# (-2pi, 2pi)
# (0.6332711088634405192103194531076134843075526902544601426097735760298574150340518,
# 1.0,
# 23.44057586605533515691829807979128873527513778367553433852055381911453864572971,
# 267.74654227273646256435313262045383453369140625)
# (0, 1)
# (1.589482169544726703219739509256918022523030217883325972454504856003547167066932e-16,
# 1.291897416767691567199962520855285151964115327068161054313577551511116325855255e-15,
# 1.118367257755837281340217148887719929595000777959128862241583039814976641146415e-16,
# 1.115760330918745818020084658567032229219617364690542160587938269600272178649902e-15)
taylor_without_reduction_test_error (generic function with 3 methods)