CORDIC: Difference between revisions
m
→{{header|Phix}}: use pygments
(Add Java implementation) |
m (→{{header|Phix}}: use pygments) |
||
(2 intermediate revisions by 2 users not shown) | |||
Line 549:
</pre>
=={{header|jq}}==
'''Adapted from [[#Wren|Wren]]'''
{{works with|jq}}
'''Works with gojq, the Go implementation of jq'''
'''Preliminaries'''
<syntaxhighlight lang="jq">
# like while/2 but emit the final term rather than the first one
def whilst(cond; update):
def _whilst:
if cond then update | (., _whilst) else empty end;
_whilst;
# Simplistic approach to rounding:
def round($ndec): pow(10;$ndec) as $p | . * $p | round / $p;
def lpad($len): tostring | ($len - length) as $l | (" " * $l) + .;
</syntaxhighlight>
'''The task'''
<syntaxhighlight lang="jq">
# The following are pre-computed to avoid using atan and sqrt functions.
def angles: [
0.78539816339745, 0.46364760900081, 0.24497866312686, 0.12435499454676,
0.06241880999596, 0.03123983343027, 0.01562372862048, 0.00781234106010,
0.00390623013197, 0.00195312251648, 0.00097656218956, 0.00048828121119,
0.00024414062015, 0.00012207031189, 0.00006103515617, 0.00003051757812,
0.00001525878906, 0.00000762939453, 0.00000381469727, 0.00000190734863,
0.00000095367432, 0.00000047683716, 0.00000023841858, 0.00000011920929,
0.00000005960464, 0.00000002980232, 0.00000001490116, 0.00000000745058
];
def kvalues: [
0.70710678118655, 0.63245553203368, 0.61357199107790, 0.60883391251775,
0.60764825625617, 0.60735177014130, 0.60727764409353, 0.60725911229889,
0.60725447933256, 0.60725332108988, 0.60725303152913, 0.60725295913894,
0.60725294104140, 0.60725293651701, 0.60725293538591, 0.60725293510314,
0.60725293503245, 0.60725293501477, 0.60725293501035, 0.60725293500925,
0.60725293500897, 0.60725293500890, 0.60725293500889, 0.60725293500888
];
def PI: (1 | atan * 4);
def radians: . * PI / 180;
def Cordic($alpha; $n):
PI as $PI
| (if (($alpha / (2 * $PI))|floor % 2 == 1) then 1 else -1 end) as $newsgn
| if ($alpha < -$PI/2)
then Cordic($alpha + $PI; $n) | map(. * $newsgn)
elif ($alpha > $PI/2)
then Cordic($alpha - $PI; $n) | map(. * $newsgn)
else kvalues[ [$n-1, (kvalues|length-1)] | min] as $kn
| reduce angles[0:$n][] as $atan ({ theta: 0, x: 1, y: 0, pow2: 1};
(if .theta < $alpha then 1 else -1 end) as $sigma
| .theta += $sigma * $atan
| .x as $t
| .x = (.x - $sigma * .y * .pow2)
| .y = (.y + $sigma * $t * .pow2)
| .pow2 /= 2 )
| [.x * $kn, .y * $kn]
end;
def example:
def format: map(round(8) | lpad(11)) | join(" ");
" x sin(x) diff. sine cos(x) diff. cosine",
({ th: -90 }
| whilst (.th <= 90;
(.th | radians) as $thr
| Cordic($thr; 24) as [ $cos, $sin ]
| .out = [.th, $sin, $sin - ($thr|sin), $cos, $cos - ($thr|cos) ]
| .th += 15 )
| .out
| format),
"\n x(rads) sin(x) diff. sine cos(x) diff. cosine",
((-9, 0, 1.5, 6) as $thr
| Cordic($thr; 24) as [$cos, $sin]
| [$thr, $sin, $sin - ($thr|sin), $cos, $cos - ($thr|cos)]
| format) ;
example
</syntaxhighlight>
'''Invocation:''' jq -ncr -f cordic.jq
{{output}}
<pre>
x sin(x) diff. sine cos(x) diff. cosine
-90 -1 0 -7e-08 -7e-08
-75 -0.96592585 -3e-08 0.25881895 -9e-08
-60 -0.86602545 -5e-08 0.49999992 -8e-08
-45 -0.70710684 -6e-08 0.70710672 -6e-08
-30 -0.49999992 8e-08 0.86602545 5e-08
-15 -0.25881895 9e-08 0.96592585 3e-08
0 7e-08 7e-08 1 -0
15 0.25881895 -9e-08 0.96592585 3e-08
30 0.49999992 -8e-08 0.86602545 5e-08
45 0.70710684 6e-08 0.70710672 -6e-08
60 0.86602545 5e-08 0.49999992 -8e-08
75 0.96592585 3e-08 0.25881895 -9e-08
90 1 -0 -7e-08 -7e-08
x(rads) sin(x) diff. sine cos(x) diff. cosine
-9 -0.41211842 6e-08 -0.91113029 -3e-08
0 7e-08 7e-08 1 -0
1.5 0.99749499 0 0.07073719 -2e-08
6 -0.27941552 -2e-08 0.96017028 -1e-08
</pre>
=={{header|Julia}}==
Line 828 ⟶ 936:
=={{header|Phix}}==
{{trans|Wren}}
<!--
<syntaxhighlight lang="phix">
with javascript_semantics
constant angles = {
0.78539816339745, 0.46364760900081, 0.24497866312686, 0.12435499454676,
0.06241880999596, 0.03123983343027, 0.01562372862048, 0.00781234106010,
0.00390623013197, 0.00195312251648, 0.00097656218956, 0.00048828121119,
0.00024414062015, 0.00012207031189, 0.00006103515617, 0.00003051757812,
0.00001525878906, 0.00000762939453, 0.00000381469727, 0.00000190734863,
0.00000095367432, 0.00000047683716, 0.00000023841858, 0.00000011920929,
0.00000005960464, 0.00000002980232, 0.00000001490116, 0.00000000745058}
constant kvalues = {
0.70710678118655, 0.63245553203368, 0.61357199107790, 0.60883391251775,
0.60764825625617, 0.60735177014130, 0.60727764409353, 0.60725911229889,
0.60725447933256, 0.60725332108988, 0.60725303152913, 0.60725295913894,
0.60725294104140, 0.60725293651701, 0.60725293538591, 0.60725293510314,
0.60725293503245, 0.60725293501477, 0.60725293501035, 0.60725293500925,
0.60725293500897, 0.60725293500890, 0.60725293500889, 0.60725293500888}
function cordic(atom alpha, integer n)
bool sgn = +1
while alpha < -PI/2 do alpha += PI sgn *= -1 end while
while alpha > PI/2 do alpha -= PI sgn *= -1 end while
atom kn = sgn * kvalues[min(n,length(kvalues))],
atan, theta = 0, x = 1, y = 0, pow2 = 1
for i=1 to n do
atan = iff(i<=length(angles)?angles[i]:atan/2)
-- atom sigma = iff(theta <= alpha ? 1 : -1), t = x -- (matches Julia)
theta += sigma * atan
x -= sigma * y * pow2
y += sigma * t * pow2
pow2 /= 2
end for
return {x * kn, y * kn}
end function
constant fmh = "%n x(%s) sin(x) diff.sine cos(x) diff.cosine\n",
fmt = "%+6.1f %+.8f (%+.8f) %+.8f (%+.8f)\n"
printf(1,fmh,{false,"deg"})
for theta = -90 to 90 by 15 do
atom r = theta*PI/180,
{c,s} = cordic(r,24)
printf(1,fmt,{theta,s,s-sin(r),c,c-cos(r)})
end for
printf(1,fmh,{true,"rad"})
for r in {-9, 0, 1.5, 6} do
atom {c,s} = cordic(r, 24)
printf(1,fmt,{r,s,s-sin(r),c,c-cos(r)})
end for
</syntaxhighlight>
{{out}}
As noted above in the commented out line, and mentioned in the Wren entry, testing for <= flips the sign of sin(0).
Line 903 ⟶ 1,012:
</pre>
=={{header|Python}}==
{{trans|C}}
<syntaxhighlight lang="python">
# CORDIC.py by Xing216
from math import pi, sin, cos, floor
angles = [
0.78539816339745, 0.46364760900081, 0.24497866312686, 0.12435499454676,
0.06241880999596, 0.03123983343027, 0.01562372862048, 0.00781234106010,
0.00390623013197, 0.00195312251648, 0.00097656218956, 0.00048828121119,
0.00024414062015, 0.00012207031189, 0.00006103515617, 0.00003051757812,
0.00001525878906, 0.00000762939453, 0.00000381469727, 0.00000190734863,
0.00000095367432, 0.00000047683716, 0.00000023841858, 0.00000011920929,
0.00000005960464, 0.00000002980232, 0.00000001490116, 0.00000000745058
]
kvalues = [
0.70710678118655, 0.63245553203368, 0.61357199107790, 0.60883391251775,
0.60764825625617, 0.60735177014130, 0.60727764409353, 0.60725911229889,
0.60725447933256, 0.60725332108988, 0.60725303152913, 0.60725295913894,
0.60725294104140, 0.60725293651701, 0.60725293538591, 0.60725293510314,
0.60725293503245, 0.60725293501477, 0.60725293501035, 0.60725293500925,
0.60725293500897, 0.60725293500890, 0.60725293500889, 0.60725293500888
]
radians = lambda degrees: (degrees * pi) / 180
def Cordic(alpha, n, c_cos, c_sin):
i, ix, sigma = 0, 0, 0
kn, x, y, atn, t, theta = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
pow2 = 1.0
newsgn = 1 if floor(alpha / (2.0 * pi)) % 2 == 1 else -1
if alpha < -pi/2.0 or alpha > pi/2.0:
if alpha < 0:
Cordic(alpha + pi, n, x, y)
else:
Cordic(alpha - pi, n, x, y)
c_cos = x * newsgn
c_sin = y * newsgn
return c_cos, c_sin
ix = n - 1
if ix > 23: ix = 23
kn = kvalues[ix]
x = 1
y = 0
for i in range(n):
atn = angles[i]
sigma = 1 if theta < alpha else -1
theta += sigma * atn
t = x
x -= sigma * y * pow2
y += sigma * t * pow2
pow2 /= 2.0
c_cos = x * kn
c_sin = y * kn
return c_cos, c_sin
def main():
i, th = 0, 0
thr, c_cos, c_sin = 0.0, 0.0, 0.0
angles = [-9.0, 0.0, 1.5, 6.0]
print(" x sin(x) diff. sine cos(x) diff. cosine")
for th in range(-90,91,15):
thr = radians(th)
c_cos, c_sin = Cordic(thr, 24, c_cos, c_sin)
sin_diff = c_sin - sin(thr)
cos_diff = c_cos - cos(thr)
print(f"{th:+03}.0° {c_sin:+.8f} ({sin_diff:+.8f}) {c_cos:+.8f} ({cos_diff:+.8f})")
print("\nx(rads) sin(x) diff. sine cos(x) diff. cosine")
for i in range(4):
thr = angles[i]
c_cos, c_sin = Cordic(thr, 24, c_cos, c_sin)
sin_diff = c_sin - sin(thr)
cos_diff = c_cos - cos(thr)
print(f"{thr:+4.1f} {c_sin:+.8f} ({c_sin - sin(thr):+.8f}) {c_cos:+.8f} ({c_cos - cos(thr):+.8f})")
if __name__ in "__main__":
main()
</syntaxhighlight>
{{out}}
<pre>
x sin(x) diff. sine cos(x) diff. cosine
-90.0° -1.00000000 (+0.00000000) -0.00000007 (-0.00000007)
-75.0° -0.96592585 (-0.00000003) +0.25881895 (-0.00000009)
-60.0° -0.86602545 (-0.00000005) +0.49999992 (-0.00000008)
-45.0° -0.70710684 (-0.00000006) +0.70710672 (-0.00000006)
-30.0° -0.49999992 (+0.00000008) +0.86602545 (+0.00000005)
-15.0° -0.25881895 (+0.00000009) +0.96592585 (+0.00000003)
+00.0° +0.00000007 (+0.00000007) +1.00000000 (-0.00000000)
+15.0° +0.25881895 (-0.00000009) +0.96592585 (+0.00000003)
+30.0° +0.49999992 (-0.00000008) +0.86602545 (+0.00000005)
+45.0° +0.70710684 (+0.00000006) +0.70710672 (-0.00000006)
+60.0° +0.86602545 (+0.00000005) +0.49999992 (-0.00000008)
+75.0° +0.96592585 (+0.00000003) +0.25881895 (-0.00000009)
+90.0° +1.00000000 (-0.00000000) -0.00000007 (-0.00000007)
x(rads) sin(x) diff. sine cos(x) diff. cosine
-9.0 -0.00000000 (+0.41211849) -0.00000000 (+0.91113026)
+0.0 +0.00000007 (+0.00000007) +1.00000000 (-0.00000000)
+1.5 +0.99749499 (+0.00000000) +0.07073719 (-0.00000002)
+6.0 -0.00000000 (+0.27941550) -0.00000000 (-0.96017029)
</pre>
=={{header|Raku}}==
{{trans|XPL0}}
|