<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
		>
<channel>
	<title>Comments on: Calculating Sines</title>
	<atom:link href="http://programmingpraxis.com/2010/01/12/calculating-sines/feed/" rel="self" type="application/rss+xml" />
	<link>http://programmingpraxis.com/2010/01/12/calculating-sines/</link>
	<description>A collection of etudes, updated weekly, for the education and enjoyment of the savvy programmer</description>
	<lastBuildDate>Mon, 28 May 2012 03:30:45 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
	<item>
		<title>By: ardnew</title>
		<link>http://programmingpraxis.com/2010/01/12/calculating-sines/#comment-3730</link>
		<dc:creator><![CDATA[ardnew]]></dc:creator>
		<pubDate>Fri, 07 Oct 2011 16:44:38 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1875#comment-3730</guid>
		<description><![CDATA[oops, usage says to provide input in degrees, but that should be radians]]></description>
		<content:encoded><![CDATA[<p>oops, usage says to provide input in degrees, but that should be radians</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: ardnew</title>
		<link>http://programmingpraxis.com/2010/01/12/calculating-sines/#comment-3729</link>
		<dc:creator><![CDATA[ardnew]]></dc:creator>
		<pubDate>Fri, 07 Oct 2011 16:40:38 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1875#comment-3729</guid>
		<description><![CDATA[like Matías Giovannini, i went for the purely iterative implementations

[sourcecode lang=&quot;perl&quot;]
use strict;
use warnings;

our $ABSTOL = 0.0000000001;
our $PI2    = 6.28318530717958648;

#
# evaluates the taylor expansion of sin(x) by
# first performing range reduction, and then
# updating the numerator, denominator, and 
# partial sum at each iteration.
#
sub taylor_sine
{  
  my $x = shift;
  
  # sine is periodic, so map domain to [-x, x]
  $x -= int($x / $PI2) * $PI2;

  # local vars  
  my ($s, $t, $n, $d, $k) = 
     ($x,  0, $x,  1,  1);
    
  do
  {
    # save previous term
    $t = $s;
    
    # update numerator and denominator
    $n *= $x * $x;
    $d *= ++$k;
    $d *= ++$k;
    
    # divide (odd) iterator by 2 and check if odd
    if (($k &gt;&gt; 1) &amp; 1) { $s -= $n / $d }
                  else { $s += $n / $d }
    
  }  
  until abs($t - $s) &lt;= $ABSTOL;
  
  return $s;
}

#
# iteratively calculates sin(x) through the triple
# angle formula, first performing range reduction
#
# MUCH faster than the recursive implementation
#
sub triple_sine
{
  my $x = shift;  
  
  # sine is periodic, so map domain to [-x, x]
  $x -= int($x / $PI2) * $PI2;
  
  # recursion depth counter
  my $n = 0;
  
  # find our base case
  while (abs($x) &gt; $ABSTOL and ++$n)
  {
    $x /= 3;    
  }
  
  # evaluate back up our expression tree
  while ($n--)
  {
    $x = 3 * $x - 4 * $x * $x * $x;
  }
  
  return $x;
}

die &quot;\nusage:\n\t\tperl $0 &lt;degrees&gt;\n&quot;
  unless scalar @ARGV and $ARGV[0] =~ /^[-0-9.]+$/;

printf(&quot;\ntaylor_sine(%f) = %4.12f\n&quot;, $ARGV[0], 
  taylor_sine($ARGV[0]));
  
printf(&quot;\ntriple_sine(%f) = %4.12f\n&quot;, $ARGV[0], 
  triple_sine($ARGV[0]));
[/sourcecode]]]></description>
		<content:encoded><![CDATA[<p>like Matías Giovannini, i went for the purely iterative implementations</p>
<pre class="brush: perl;">
use strict;
use warnings;

our $ABSTOL = 0.0000000001;
our $PI2    = 6.28318530717958648;

#
# evaluates the taylor expansion of sin(x) by
# first performing range reduction, and then
# updating the numerator, denominator, and 
# partial sum at each iteration.
#
sub taylor_sine
{  
  my $x = shift;
  
  # sine is periodic, so map domain to [-x, x]
  $x -= int($x / $PI2) * $PI2;

  # local vars  
  my ($s, $t, $n, $d, $k) = 
     ($x,  0, $x,  1,  1);
    
  do
  {
    # save previous term
    $t = $s;
    
    # update numerator and denominator
    $n *= $x * $x;
    $d *= ++$k;
    $d *= ++$k;
    
    # divide (odd) iterator by 2 and check if odd
    if (($k &gt;&gt; 1) &amp; 1) { $s -= $n / $d }
                  else { $s += $n / $d }
    
  }  
  until abs($t - $s) &lt;= $ABSTOL;
  
  return $s;
}

#
# iteratively calculates sin(x) through the triple
# angle formula, first performing range reduction
#
# MUCH faster than the recursive implementation
#
sub triple_sine
{
  my $x = shift;  
  
  # sine is periodic, so map domain to [-x, x]
  $x -= int($x / $PI2) * $PI2;
  
  # recursion depth counter
  my $n = 0;
  
  # find our base case
  while (abs($x) &gt; $ABSTOL and ++$n)
  {
    $x /= 3;    
  }
  
  # evaluate back up our expression tree
  while ($n--)
  {
    $x = 3 * $x - 4 * $x * $x * $x;
  }
  
  return $x;
}

die &quot;\nusage:\n\t\tperl $0 &lt;degrees&gt;\n&quot;
  unless scalar @ARGV and $ARGV[0] =~ /^[-0-9.]+$/;

printf(&quot;\ntaylor_sine(%f) = %4.12f\n&quot;, $ARGV[0], 
  taylor_sine($ARGV[0]));
  
printf(&quot;\ntriple_sine(%f) = %4.12f\n&quot;, $ARGV[0], 
  triple_sine($ARGV[0]));
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: Graham</title>
		<link>http://programmingpraxis.com/2010/01/12/calculating-sines/#comment-3063</link>
		<dc:creator><![CDATA[Graham]]></dc:creator>
		<pubDate>Sat, 21 May 2011 03:05:08 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1875#comment-3063</guid>
		<description><![CDATA[My &lt;code&gt;sin_taylor()&lt;/code&gt; works quite well, but my recursive &lt;code&gt;sin_limit&lt;/code&gt;runs into numerical trouble if epsilon is too small...
[sourcecode lang=&quot;python&quot;]
#!/usr/bin/env python

from __future__ import division
from itertools import count, takewhile
from operator import mul

def factorial(n):
    return reduce(mul, xrange(2, n + 1), 1)

def sin_taylor(x, eps):
    a = lambda k: pow(x, 2 * k + 1) / factorial(2 * k + 1)
    return sum(pow(-1, k) * a(k) for k in takewhile(lambda k: a(k) &gt; eps,
        count()))

def sin_limit(x, eps):
    #Loses accuracy if eps &lt; 1e-6...
    if x &lt; eps:
        return eps
    else:
        return 3 * sin_limit(x / 3, eps) - 4 * pow(sin_limit(x / 3, eps), 3)
[/sourcecode]]]></description>
		<content:encoded><![CDATA[<p>My <code>sin_taylor()</code> works quite well, but my recursive <code>sin_limit</code>runs into numerical trouble if epsilon is too small&#8230;</p>
<pre class="brush: python;">
#!/usr/bin/env python

from __future__ import division
from itertools import count, takewhile
from operator import mul

def factorial(n):
    return reduce(mul, xrange(2, n + 1), 1)

def sin_taylor(x, eps):
    a = lambda k: pow(x, 2 * k + 1) / factorial(2 * k + 1)
    return sum(pow(-1, k) * a(k) for k in takewhile(lambda k: a(k) &gt; eps,
        count()))

def sin_limit(x, eps):
    #Loses accuracy if eps &lt; 1e-6...
    if x &lt; eps:
        return eps
    else:
        return 3 * sin_limit(x / 3, eps) - 4 * pow(sin_limit(x / 3, eps), 3)
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: David</title>
		<link>http://programmingpraxis.com/2010/01/12/calculating-sines/#comment-2755</link>
		<dc:creator><![CDATA[David]]></dc:creator>
		<pubDate>Mon, 28 Mar 2011 03:15:41 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1875#comment-2755</guid>
		<description><![CDATA[Version in Factor.  Interesting that the Taylor series is minimally accurate to the given precision (1e-7), but the recursive version is much more precise than our minimum of 1e-7.  Probably the case as for values that small sin x ~= x.

[sourcecode lang=&quot;text&quot;]
USING: kernel math math.constants math.libm locals
       arrays sequences lists lists.lazy ;
IN: sines

CONSTANT: epsilon 1e-7

: normalize-theta  ( x -- x )
    [let 1 :&gt; sign!
      dup 0 &lt;
        [ -1 *  -1 sign! ]  when

      pi 2 *  fmod

      dup pi &gt;
        [ 2 pi * - ] when

      sign *
    ] ;


! create the lazy list of taylor terms (not so simple :)

: numerators  ( x -- lazy-list )
    dup 2array  [ first2
                  over *
                  over *
                  -1 *
                  2array
                ] lfrom-by  [ second ] lazy-map ;

: denominators  ( -- lazy-list )
    { 1 1 }  [ first2
               [ 1 + ] dip over *
               [ 1 + ] dip over *
               2array
             ] lfrom-by  [ second ] lazy-map ;

: taylor-terms ( x -- lazy-list )
    numerators denominators lzip [ first2 / ] lazy-map ;

: taylor-sine ( x -- x )
   &gt;float normalize-theta taylor-terms  [ abs epsilon &lt; ] luntil  0 [ + ] foldl ;


! sin x = 3 sin (x/3) - 4 sin^3 (x/3)

: sine  ( x -- x )
    dup abs epsilon &gt;
      [ 3.0 / sine [ 3 * ] [ dup sq * 4 * ] bi - ]          
    when ;
[/sourcecode]

Session:

[sourcecode lang=&quot;text&quot;]

( scratchpad ) pi 4 / sin .
0.7071067811865475
( scratchpad ) pi 4 / sine .
0.7071067811865475
( scratchpad ) pi 4 / taylor-sine .
0.7071067811796195
( scratchpad ) 1 sin .
0.8414709848078965
( scratchpad ) 1 sine .
0.8414709848078971
( scratchpad ) 1 taylor-sine .
0.841470984648068
( scratchpad ) 100 sin .
-0.5063656411097588
( scratchpad ) 100 sine .
-0.5063656411096491
( scratchpad ) 100 taylor-sine .
-0.5063656411334029
( scratchpad ) pi 1.5 * sin .
-1.0
( scratchpad ) pi 1.5 * sine .
-1.0
( scratchpad ) pi 1.5 * taylor-sine .
-1.00000000066278
( scratchpad ) 
[/sourcecode]]]></description>
		<content:encoded><![CDATA[<p>Version in Factor.  Interesting that the Taylor series is minimally accurate to the given precision (1e-7), but the recursive version is much more precise than our minimum of 1e-7.  Probably the case as for values that small sin x ~= x.</p>
<pre class="brush: plain;">
USING: kernel math math.constants math.libm locals
       arrays sequences lists lists.lazy ;
IN: sines

CONSTANT: epsilon 1e-7

: normalize-theta  ( x -- x )
    [let 1 :&gt; sign!
      dup 0 &lt;
        [ -1 *  -1 sign! ]  when

      pi 2 *  fmod

      dup pi &gt;
        [ 2 pi * - ] when

      sign *
    ] ;


! create the lazy list of taylor terms (not so simple :)

: numerators  ( x -- lazy-list )
    dup 2array  [ first2
                  over *
                  over *
                  -1 *
                  2array
                ] lfrom-by  [ second ] lazy-map ;

: denominators  ( -- lazy-list )
    { 1 1 }  [ first2
               [ 1 + ] dip over *
               [ 1 + ] dip over *
               2array
             ] lfrom-by  [ second ] lazy-map ;

: taylor-terms ( x -- lazy-list )
    numerators denominators lzip [ first2 / ] lazy-map ;

: taylor-sine ( x -- x )
   &gt;float normalize-theta taylor-terms  [ abs epsilon &lt; ] luntil  0 [ + ] foldl ;


! sin x = 3 sin (x/3) - 4 sin^3 (x/3)

: sine  ( x -- x )
    dup abs epsilon &gt;
      [ 3.0 / sine [ 3 * ] [ dup sq * 4 * ] bi - ]          
    when ;
</pre>
<p>Session:</p>
<pre class="brush: plain;">

( scratchpad ) pi 4 / sin .
0.7071067811865475
( scratchpad ) pi 4 / sine .
0.7071067811865475
( scratchpad ) pi 4 / taylor-sine .
0.7071067811796195
( scratchpad ) 1 sin .
0.8414709848078965
( scratchpad ) 1 sine .
0.8414709848078971
( scratchpad ) 1 taylor-sine .
0.841470984648068
( scratchpad ) 100 sin .
-0.5063656411097588
( scratchpad ) 100 sine .
-0.5063656411096491
( scratchpad ) 100 taylor-sine .
-0.5063656411334029
( scratchpad ) pi 1.5 * sin .
-1.0
( scratchpad ) pi 1.5 * sine .
-1.0
( scratchpad ) pi 1.5 * taylor-sine .
-1.00000000066278
( scratchpad ) 
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: Mike</title>
		<link>http://programmingpraxis.com/2010/01/12/calculating-sines/#comment-1146</link>
		<dc:creator><![CDATA[Mike]]></dc:creator>
		<pubDate>Sat, 10 Apr 2010 00:34:48 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1875#comment-1146</guid>
		<description><![CDATA[Python:

[sourcecode lang=&quot;python&quot;]

def reduce_range( x ):
    sign,x = (1, x) if x &gt;= 0 else (-1, -x)
    
    if x &gt;= 2*pi: x -= int(x/2/pi) * pi
    if x &gt; pi: x = x - 2*pi
    
    return x if sign&gt;0 else -x


def sin_taylor( x, eps=1.0e-7 ):
    x = reduce_range( x )        
    x2 = x*x
    sinx = 0
    num, den, k, sign = ( float( x ), 1.0, 3.0, 1 )
    
    while True:
        delta = num / den
        sinx += sign * delta

        if delta &lt; eps: break

        num, den, k, sign = ( num * x2, den*k*(k-1), k+2, -sign )

    return sinx

def sin_3angle( x, eps=1e-7 ):

    def _3angle( x ):
        if x &lt; eps:
            return x
        else:
            f = _3angle( x/3.0 )
            return f * ( 3 - 4*f*f )

    return _3angle( reduce_range( x ) )

[/sourcecode]]]></description>
		<content:encoded><![CDATA[<p>Python:</p>
<pre class="brush: python;">

def reduce_range( x ):
    sign,x = (1, x) if x &gt;= 0 else (-1, -x)
    
    if x &gt;= 2*pi: x -= int(x/2/pi) * pi
    if x &gt; pi: x = x - 2*pi
    
    return x if sign&gt;0 else -x


def sin_taylor( x, eps=1.0e-7 ):
    x = reduce_range( x )        
    x2 = x*x
    sinx = 0
    num, den, k, sign = ( float( x ), 1.0, 3.0, 1 )
    
    while True:
        delta = num / den
        sinx += sign * delta

        if delta &lt; eps: break

        num, den, k, sign = ( num * x2, den*k*(k-1), k+2, -sign )

    return sinx

def sin_3angle( x, eps=1e-7 ):

    def _3angle( x ):
        if x &lt; eps:
            return x
        else:
            f = _3angle( x/3.0 )
            return f * ( 3 - 4*f*f )

    return _3angle( reduce_range( x ) )

</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: Norsetto&#39;s Journal</title>
		<link>http://programmingpraxis.com/2010/01/12/calculating-sines/#comment-919</link>
		<dc:creator><![CDATA[Norsetto&#39;s Journal]]></dc:creator>
		<pubDate>Fri, 15 Jan 2010 16:05:35 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1875#comment-919</guid>
		<description><![CDATA[[...] dabbling with haskell in the recent days. My first semi-serious attempt was inspired by a prompt at programming praxis. The code I concocted is as follows (I guess it would ashame any serious haskell programmer, if you [...]]]></description>
		<content:encoded><![CDATA[<p>[...] dabbling with haskell in the recent days. My first semi-serious attempt was inspired by a prompt at programming praxis. The code I concocted is as follows (I guess it would ashame any serious haskell programmer, if you [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Erik Schulz</title>
		<link>http://programmingpraxis.com/2010/01/12/calculating-sines/#comment-915</link>
		<dc:creator><![CDATA[Erik Schulz]]></dc:creator>
		<pubDate>Thu, 14 Jan 2010 00:07:47 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1875#comment-915</guid>
		<description><![CDATA[Here is a version written in F#.

http://pastie.org/777280]]></description>
		<content:encoded><![CDATA[<p>Here is a version written in F#.</p>
<p><a href="http://pastie.org/777280" rel="nofollow">http://pastie.org/777280</a></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Erik Schulz</title>
		<link>http://programmingpraxis.com/2010/01/12/calculating-sines/#comment-914</link>
		<dc:creator><![CDATA[Erik Schulz]]></dc:creator>
		<pubDate>Thu, 14 Jan 2010 00:06:01 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1875#comment-914</guid>
		<description><![CDATA[the comment section ate my code ...]]></description>
		<content:encoded><![CDATA[<p>the comment section ate my code &#8230;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Erik Schulz</title>
		<link>http://programmingpraxis.com/2010/01/12/calculating-sines/#comment-913</link>
		<dc:creator><![CDATA[Erik Schulz]]></dc:creator>
		<pubDate>Thu, 14 Jan 2010 00:03:28 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1875#comment-913</guid>
		<description><![CDATA[A version written in F#.

let epsilon = 1e-7
let pi = 3.141592654

let sin (x:float) = 
    let rec series sum f d v k2 =
        let next = f * d / float v
        if abs(next) &lt; epsilon then
            sum + next
        else
            series (sum + next) (-f) (d * x * x) (v  * (k2 + 1) * (k2 + 2)) (k2 + 2)
    series 0.0 1.0 1.0 1 1

let rec sin&#039; x =
    if abs(x)  float
val sin&#039; : float -&gt; float

&gt; sin 1.0;;
val it : float = 0.8414709846
&gt; sin&#039; 1.0;;
val it : float = 0.8414709848]]></description>
		<content:encoded><![CDATA[<p>A version written in F#.</p>
<p>let epsilon = 1e-7<br />
let pi = 3.141592654</p>
<p>let sin (x:float) =<br />
    let rec series sum f d v k2 =<br />
        let next = f * d / float v<br />
        if abs(next) &lt; epsilon then<br />
            sum + next<br />
        else<br />
            series (sum + next) (-f) (d * x * x) (v  * (k2 + 1) * (k2 + 2)) (k2 + 2)<br />
    series 0.0 1.0 1.0 1 1</p>
<p>let rec sin&#039; x =<br />
    if abs(x)  float<br />
val sin&#8217; : float -&gt; float</p>
<p>&gt; sin 1.0;;<br />
val it : float = 0.8414709846<br />
&gt; sin&#8217; 1.0;;<br />
val it : float = 0.8414709848</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: programmingpraxis</title>
		<link>http://programmingpraxis.com/2010/01/12/calculating-sines/#comment-912</link>
		<dc:creator><![CDATA[programmingpraxis]]></dc:creator>
		<pubDate>Wed, 13 Jan 2010 13:49:40 +0000</pubDate>
		<guid isPermaLink="false">http://programmingpraxis.com/?p=1875#comment-912</guid>
		<description><![CDATA[Manish:  Fixed.  My fault, not Bill&#039;s.]]></description>
		<content:encoded><![CDATA[<p>Manish:  Fixed.  My fault, not Bill&#8217;s.</p>
]]></content:encoded>
	</item>
</channel>
</rss>

