From 9477dbe667f250ecd23f8fc0d56b942191526421 Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Thu, 25 Feb 2021 14:42:55 +0100 Subject: Stare semestry, niepoukladane --- Semestr 3/anm/pracowniaPOP/prog/program.jl | 273 +++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 Semestr 3/anm/pracowniaPOP/prog/program.jl (limited to 'Semestr 3/anm/pracowniaPOP/prog/program.jl') diff --git a/Semestr 3/anm/pracowniaPOP/prog/program.jl b/Semestr 3/anm/pracowniaPOP/prog/program.jl new file mode 100644 index 0000000..d75f82b --- /dev/null +++ b/Semestr 3/anm/pracowniaPOP/prog/program.jl @@ -0,0 +1,273 @@ +using Printf + +# stałe dla CORDIC'A +global C_ITERATIONS = 30 +global CORDIC_MUL_POW = 30 +global CORDIC_MUL = 2.0^CORDIC_MUL_POW +global CORDIC_ATANS = [843314857, 497837829, 263043837, 133525159, 67021687, 33543516, 16775851, + 8388437, 4194283, 2097149, 1048576, 524288, 262144, 131072, 65536, 32768, 16384, 8192, 4096, + 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2] +global CORDIC_F = 1768195363 +global CORDIC_F_INV = 652032874 + +# stałe dla obliczania szeregiem Taylora +global T_ITERATIONS = 15 +global HYPERBOLIC_MAX = 1 + +# liczenie szeregu Taylora +function series(x, parity, change_sign, iterations) + res = zero(x) + elem = one(x) + if parity == 1 + elem = x + end + i = parity + 1 + while i <= 2*iterations + parity + res += elem + elem *= change_sign*x*x/(i*(i+1)) + i += 2 + end + return res +end + +# generyczna funkcja stosująca wzory redukcyjne, licząca sin(x) +# za pomocą podanych funkcji sin_fun, cos_fun +function gen_sin(x, iterations, sin_fun, cos_fun) + # sin(-x) = sin(x) + if x < 0 + return -gen_sin(-x, iterations, sin_fun, cos_fun) + end + x = mod2pi(x) + # sin(π + x) = -sin(x) + if x > pi + return -gen_sin(x-pi, iterations, sin_fun, cos_fun) + end + # sin(π/2 + x) = cos(x) + if x > pi/2 + return gen_cos(x-pi/2, iterations, sin_fun, cos_fun) + end + # sin(π/2 - x) = cos(x) + if x > pi/4 + return gen_cos(pi/2-x, iterations, sin_fun, cos_fun) + end + return sin_fun(x, iterations) +end + +# generyczna funkcja stosująca wzory redukcyjne, licząca cos(x) +# za pomocą podanych funkcji sin_fun, cos_fun +function gen_cos(x, iterations, sin_fun, cos_fun) + # cos(-x) = cos(x) + if x < 0 + return gen_cos(-x, iterations, sin_fun, cos_fun) + end + x = mod2pi(x) + # cos(π + x) = -cos(x) + if x > pi + return -gen_cos(x-pi, iterations, sin_fun, cos_fun) + end + # cos(π/2 + x) = -sin(x) + if x > pi/2 + return -gen_sin(x-pi/2, iterations, sin_fun, cos_fun) + end + # cos(π/2 - x) = sin(x) + if x > pi/4 + return gen_sin(pi/2-x, iterations, sin_fun, cos_fun) + end + return cos_fun(x, iterations) +end + +# sin dla liczb rzeczywistych [Taylor] +function real_sin(r, iterations) + return series(r, 1, -1, iterations) +end + +# cos dla liczb rzeczywistych [Taylor] +function real_cos(r, iterations) + return series(r, 0, -1, iterations) +end + +# sinh [Taylor] +function real_sinh(r, iterations) + # sinh(1000) jest za duży by reprezentować go we Float64 + if r > 1000 + return Inf + end + if r < -1000 + return -Inf + end + if r == 0 + return Float64(0) + end + # dla dużych liczb korzystamy ze wzoru: + # sinh(2r) = 2 * cosh(r) * sinh(r) + if abs(r) > HYPERBOLIC_MAX + return 2*real_sinh(r/2, iterations)*real_cosh(r/2, iterations) + end + return series(r, 1, 1, iterations) +end + +# cosh [Taylor] +function real_cosh(r, iterations) + # cosh(1000) jest za duży by reprezentować go we Float64 + if abs(r) > 1000 + return Inf + end + if r == 1 + return Float64(1) + end + # dla dużych liczb korzystamy ze wzoru: + # cosh(2r) = cosh(r)^2 + sinh(r)^2 + if abs(r) > HYPERBOLIC_MAX + s = real_sinh(r/2, iterations) + c = real_cosh(r/2, iterations) + return s*s+c*c + end + return series(r, 0, 1, iterations) +end + +# sin dla liczb zespolonych [Taylor] +function complex_sin(a, b, iterations) + # sin(a + bi) = sin(a) * cosh(b) + i(cos(a) * sinh(b)) + return (gen_sin(a, iterations, real_sin, real_cos)*real_cosh(b, iterations), + gen_cos(a, iterations, real_sin, real_cos)*real_sinh(b, iterations)) +end + +# cos dla liczb zespolonych [Taylor] +function complex_cos(a, b, iterations) + # cos(a + bi) = cos(a) * cosh(b) - i(sin(a) * sinh(b)) + return (real_cos(a, iterations)*real_cosh(b, iterations), + -real_sin(a, iterations)*real_sinh(b, iterations)) +end + +# funkcja sin dla użytkownika [Taylor] +function taylor_sin(a, b) + return complex_sin(a, b, T_ITERATIONS) +end + +# funkcja cos dla użytkownika [Taylor] +function taylor_cos(a, b) + return complex_cos(a, b, T_ITERATIONS) +end + +# funkcja sinh dla użytkownika [Taylor] +function taylor_sinh(r) + return real_sinh(r, T_ITERATIONS) +end + +# funkcja cosh dla użytkownika [Taylor] +function taylor_cosh(r) + return real_cosh(r, T_ITERATIONS) +end + +# preprocesing [CORDIC] +function preprocess_atan(iterations) + global CORDIC_MUL + atan2pow = Array{Float64}(undef, iterations) + @printf("CORDIC_ATANS = [") + for i in 1:iterations + atan2pow[i] = round(atan(1.0 / Float64(BigInt(2)^(i - 1))) * CORDIC_MUL) + @printf("%d", atan2pow[i]) + if i < iterations + @printf(", ") + end + end + @printf("]\n") +end + + +# preprocesing [CORDIC] +function preprocess_scaling_factor(iterations) + CORDIC_F = 1.0 + for i in 0:iterations + CORDIC_F *= sqrt(1. + 1. / Float64(BigInt(2)^(2 * i))) + end + @printf("CORDIC_F = %d\nCORDIC_F_INV = %d\n", round(CORDIC_F * CORDIC_MUL), round(CORDIC_MUL / CORDIC_F)) +end + + +# funkcja licząca zarówno cosx oraz sinx algorytmem CORDIC +function approx_trig(x, iterations) + global CORDIC_ATANS + global CORDIC_F_INV + X = CORDIC_F_INV + Y = 0 + Z = round(x * CORDIC_MUL) + s = 1 + # Proces iteracyjny algorytmu CORDIC + for i in 0:(iterations - 1) + tempX = X + if Z == 0 + break + end + if Z >= 0 + X -= s * (Y >> i) + Y += s * (tempX >> i) + Z -= s * CORDIC_ATANS[i + 1] + else + X += s * (Y >> i) + Y -= s * (tempX >> i) + Z += s * CORDIC_ATANS[i + 1] + end + end + + return (Float64(X) / CORDIC_MUL, Float64(Y) / CORDIC_MUL) +end + +# wyciąganie sin z approx_trig [CORDIC] +function approx_sin(x, iterations) + return approx_trig(x, iterations)[2] +end + + +# wyciąganie cos z approx_trig [CORDIC] +function approx_cos(x, iterations) + return approx_trig(x, iterations)[1] +end + +# funkcja sin dla użytkownika [CORDIC] +function cordic_sin(x) + return gen_sin(x, C_ITERATIONS, approx_sin, approx_cos) +end + +# funkcja cos dla użytkownika [CORDIC] +function cordic_cos(x) + return gen_cos(x, C_ITERATIONS, approx_sin, approx_cos) +end + +# uruchamianie preprocesingu [CORDIC] +# funkcja wypisuje kod w języku Julia na ekran, który potem po prostu wkleiliśmy do pliku źródłowego +# oblicza stałe potrzebne do obliczania funkcji trygonometrycznych metodą CORDIC +function preprocess_cordic() + println("Preprocessing CORDIC constants.") + preprocess_atan(CORDIC_MUL_POW) + preprocess_scaling_factor(CORDIC_MUL_POW) +end + +# sinh bez stosowania wzorów redukcyjnych [Taylor] +function sinh_no_reduction(x, iterations) + return series(x, 1, 1, iterations) +end + +# cosh bez stosowania wzorów redukcyjnych [Taylor] +function cosh_no_reduction(x, iterations) + return series(x, 0, 1, iterations) +end + +# sin bez stosowania wzorów redukcyjnych [Taylor] +function taylor_sin_no_reduction(x, y) + # sin(a + bi) = sin(a) * cosh(b) + i(cos(a) * sinh(b)) + # wykonujemy odpowiednio (10a + 10), (10b + 10) iteracji - szereg Tylora + # powinien dobrze przybliżać funkcje trygonometryczne dla takiej liczby wyrazów + return (real_sin(x, 10*round(x)+10) * cosh_no_reduction(y, 10*round(y)+10), + real_cos(x, 10*round(x)+10) * sinh_no_reduction(y, 10*round(y)+10)) +end + +# zmiana liczby iteracji [Taylor] +function set_taylor_iterations(x) + global T_ITERATIONS = x +end + +# zmiana liczby iteracji [CORDIC] +function set_cordic_iterations(x) + global C_ITERATIONS = x +end \ No newline at end of file -- cgit v1.2.3