In [1]:
include("program.jl")
Out[1]:
set_cordic_iterations (generic function with 1 method)
In [2]:
using Plots
using Random
using Distributions

plotly()
Out[2]:
Plots.PlotlyBackend()
In [3]:
# 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
In [4]:
# porównianie na sin(2), cos(2)
sin(2.0)
Out[4]:
0.9092974268256817
In [5]:
taylor_sin(2.0, 0.0)
Out[5]:
(0.9092974268256817, -0.0)
In [6]:
cordic_sin(2.0)
Out[6]:
0.9092974280938506
In [7]:
cos(2)
Out[7]:
-0.4161468365471424
In [8]:
taylor_cos(2.0, 0.0)
Out[8]:
(-0.41614683654714246, -0.0)
In [9]:
cordic_cos(2.0)
Out[9]:
-0.4161468353122473
In [10]:
# porównianie na sin(10 + 10i)
sin(10 + 10im)
Out[10]:
-5991.431207677988 - 9240.89014825243im
In [11]:
taylor_sin(10, 10)
Out[11]:
(-5991.431207678, -9240.890148252452)
In [12]:
# 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
Out[12]:
rel_error (generic function with 1 method)
In [13]:
# Funkcje użyte w wykresach błędów od liczby iteracji:
In [14]:
# 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
Out[14]:
taylor_error_of_iterations (generic function with 1 method)
In [15]:
# 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
Out[15]:
cordic_error_of_iterations (generic function with 1 method)
In [16]:
# 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
Out[16]:
taylor_error_of_iterations2 (generic function with 1 method)
In [17]:
X = 1:20
Out[17]:
1:20
In [18]:
# Przykładowe błędy w zależności od liczby iteracji
# obrazują jak szybko zbiega metoda:
In [19]:
plot(taylor_error_of_iterations, X, title="Taylor relative error calculating sin(100+100i)", xguide = "iterations", yguide = "relative error")
Out[19]:
Plots.jl
In [20]:
plot(taylor_error_of_iterations2, X, title="Taylor relative error calculating sin(100)", xguide = "iterations", yguide = "relative error")
Out[20]:
Plots.jl
In [21]:
plot(cordic_error_of_iterations, X, title="CORDIC relative error calculating sin(100)", xguide = "iterations", yguide = "relative error")
Out[21]:
Plots.jl
In [22]:
# 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
Out[22]:
rel_error_cordic (generic function with 1 method)
In [23]:
function rel_error_taylor(x)
   return rel_error(sin(x), taylor_sin(x, 0.0)[1]) 
end
Out[23]:
rel_error_taylor (generic function with 1 method)
In [24]:
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]
Out[24]:
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
In [33]:
# Błąd względny obliczania sinusa Cordicem na przedziale (0, 6.3)
plot(OX, res_cordic, xguide = "x", yguide = "relative error", label = "cordic_sin")
Out[33]:
Plots.jl
In [34]:
# 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")
Out[34]:
Plots.jl
In [27]:
# Poniżej znajdują się funkcje testujące, na podstawie których powstała Tabela 2 w sprawozdaniu
In [28]:
TESTS = 100000000

Random.seed!(12345)
Out[28]:
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)
In [29]:
# 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)
Out[29]:
taylor_test_error_real (generic function with 3 methods)
In [30]:
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)
Out[30]:
taylor_test_error_complex (generic function with 3 methods)
In [31]:
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)
Out[31]:
cordic_test_error (generic function with 3 methods)
In [32]:
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)
Out[32]:
taylor_without_reduction_test_error (generic function with 3 methods)