aboutsummaryrefslogtreecommitdiff
path: root/semestr-3/anm/cordic/cordic.jl
diff options
context:
space:
mode:
Diffstat (limited to 'semestr-3/anm/cordic/cordic.jl')
-rw-r--r--semestr-3/anm/cordic/cordic.jl81
1 files changed, 81 insertions, 0 deletions
diff --git a/semestr-3/anm/cordic/cordic.jl b/semestr-3/anm/cordic/cordic.jl
new file mode 100644
index 0000000..9509fb2
--- /dev/null
+++ b/semestr-3/anm/cordic/cordic.jl
@@ -0,0 +1,81 @@
+using Printf
+
+global ITERATIONS = 30
+global CORDIC_MUL_POW = 30
+global CORDIC_MUL = 2.0^CORDIC_MUL_POW
+global CORDIC_ATANS
+global CORDIC_F
+global CORDIC_F_INV
+
+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]
+CORDIC_F = 1768195363
+CORDIC_F_INV = 652032874
+
+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
+
+function preprocess_scaling_factor(iterations)
+ # @printf("Preprocessing scaling factor, %d iterations\n", iterations)
+ CORDIC_F = 1.0
+ for i in 0:iterations
+ CORDIC_F *= sqrt(1. + 1. / Float64(BigInt(2)^(2 * i)))
+ end
+ # @printf("Scaling factor: %.16f\n", F)
+ @printf("CORDIC_F = %d\nCORDIC_F_INV = %d\n", round(CORDIC_F * CORDIC_MUL), round(CORDIC_MUL / CORDIC_F))
+end
+
+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
+ for i in 0:(iterations - 1)
+ println(X, " ", Y)
+
+ 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
+
+ println(X, " ", Y)
+ return (Float64(X) / CORDIC_MUL, Float64(Y) / CORDIC_MUL)
+end
+
+# works only for real numbers
+function approx_sin(x, y)
+ return (approx_trig(x, ITERATIONS)[2], 0)
+end
+
+# works only for real numbers
+function approx_cos(x, y)
+ return (approx_trig(x, ITERATIONS)[1], 0)
+end
+
+function main()
+ println("Preprocessing CORDIC constants.")
+ preprocess_atan(CORDIC_MUL_POW)
+ preprocess_scaling_factor(CORDIC_MUL_POW)
+end