Note that you might need to change the 2.22044604925031e-16 constant to 2 ULPs 
(4.44089209850063e-16) in order to get around some pathological rounding cases.

It probably will not be noticeable faster since you are only saving a few 
machine cycles per iteration.  It might be noticeable unless you are running 
the calculation thousands or millions of times. 

-- 
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.

>-----Original Message-----
>From: sqlite-users <sqlite-users-boun...@mailinglists.sqlite.org> On
>Behalf Of Bart Smissaert
>Sent: Friday, 18 October, 2019 16:48
>To: SQLite mailing list <sqlite-users@mailinglists.sqlite.org>
>Subject: Re: [sqlite] Standard deviation last x entries
>
>> However, to optimize the calculation the following is more efficient
>
>I tested it, but didn't find it any faster.
>Naming makes it a lot clearer though.
>
>RBS
>
>On Fri, Oct 18, 2019 at 10:56 PM Keith Medcalf <kmedc...@dessus.com>
>wrote:
>
>>
>> We are calculating the square root using Newtons Method of successive
>> approximation
>>
>> https://pages.mtu.edu/~shene/COURSES/cs201/NOTES/chap04/sqrt.html
>>
>> (x>0)*(y+x/y)/2 yi
>>
>> is computing the new guess of the square root of x based on the last
>guess
>> y and calling that calculation yi (the AS keyword is omitted).  The
>(x>0)
>> part is to make sure that x is always a positive number otherwise the
>new
>> guess will be 0.  This means that the attempt to find the square root
>of a
>> negative number (or 0) will always return 0 for each of two iterations
>thus
>> meeting the stop condition because abs(0 - 0) is less than any positive
>> number.
>>
>> To use a CTE with better named variables one would use:
>>
>> with guesses(findRootOf, guessRoot, iteration)
>>   as (
>>          select ?, 1.0, 1
>>       union all
>>          select findRootOf, (findRootOf > 0) * (guessRoot + findRootOf
>/
>> guessRoot) / 2.0 as newGuess, iteration + 1
>>            from guesses
>>           where abs(newGuess - guessRoot) > 1e-12
>>           limit 32
>>      )
>>   select guessRoot
>>     from guesses
>> order by iteration desc
>>    limit 1;
>>
>> However, to optimize the calculation the following is more efficient
>> (since it only calculates the new guess once each iteration, and
>computes
>> to the limit of precision).  We are substituting calculating the guess
>> twice and its difference from a constant (9 operations) with computing
>the
>> actual precision (6 operations):
>>
>> with guesses(findRootOf, guessRoot, iteration)
>>   as (
>>          select ?, 1.0, 1
>>       union all
>>          select findRootOf, (findRootOf > 0) * (guessRoot + findRootOf
>/
>> guessRoot) / 2.0, iteration + 1
>>            from guesses
>>           where abs(guessRoot*guessRoot - findRootOf) >
>> (2.22044604925031e-16 * FindRootOf)
>>           limit 32
>>      )
>>   select guessRoot
>>     from guesses
>> order by iteration desc
>>    limit 1;
>>
>> where 2.22044604925031e-16 is the epsilon of IEEE754 double precision
>> floating point numbers (the limit of computational precision in the
>last
>> binary place)
>>
>> --
>> The fact that there's a Highway to Hell but only a Stairway to Heaven
>says
>> a lot about anticipated traffic volume.
>>
>> >-----Original Message-----
>> >From: sqlite-users <sqlite-users-boun...@mailinglists.sqlite.org> On
>> >Behalf Of Bart Smissaert
>> >Sent: Friday, 18 October, 2019 14:55
>> >To: SQLite mailing list <sqlite-users@mailinglists.sqlite.org>
>> >Subject: Re: [sqlite] Standard deviation last x entries
>> >
>> >Hi Olaf,
>> >
>> >Could you tell me what this is doing:
>> >
>> >,(x>0)*(y+x/y)/2 yi
>> >
>> >Especially the yi after the 2
>> >How does the yi relate to the preceding bit?
>> >
>> >RBS
>> >
>> >
>> >
>> >On Fri, Oct 18, 2019 at 8:26 PM Olaf Schmidt <n...@vbrichclient.com>
>wrote:
>> >
>> >> Am 18.10.2019 um 19:45 schrieb Bart Smissaert:
>> >>
>> >> > Regarding:
>> >> >
>> >> > With r(s2, s, i) As (Select 2, 1, 1 Union All
>> >> >     Select s2, (s2>0)*(s+s2/s)*.5, i+1 From r Where Abs(s2-
>s*s)>1e-12
>> >> > Limit 32
>> >> > ) Select s From r Order By i Desc Limit 1
>> >> >
>> >> > How would this work if I wanted to update all the values in a
>table
>> >> column
>> >> > to have the square root?
>> >>
>> >> Well, as with any other (single-value-returning) Sub-Select
>> >> (which was enclosed in parentheses)...
>> >>
>> >> E.g.
>> >>       "Update MyTable Set MyCol = (Select 1)"
>> >> would update MyCol with the value 1 across the whole table...
>> >>
>> >> Same thing basically (only "a bit larger") with a CTE-based
>> >> "Single-Value-SubSelect"...
>> >>
>> >> BTW, I've updated and tuned the thing a bit (which should now
>> >> offer more precision, and ~20% more performance as well):
>> >>
>> >> With  r (x, y, i) As (
>> >>    Select ?, 1, 1  Union All
>> >>    Select x,(x>0)*(y+x/y)/2 yi,i+1 From r Where Abs(yi-y)>1e-12
>Limit
>> >32
>> >> ) Select y From r Order By i Desc Limit 1
>> >>
>> >> Note the question-marked "Parameter" for the "squared Input-Value"
>> >> (in the first Select Statement of the CTEs triple).
>> >>
>> >> Integrated into an Update-Query it could look this way:
>> >>
>> >> Update MyTable Set MySquareRoot = ( -- SubSelect-Opening-Paren...
>> >>   With  r (x, y, i) As (
>> >>     Select MySquaredValue, 1, 1  Union All
>> >>     Select x,(x>0)*(y+x/y)/2 yi,i+1 From r Where Abs(yi-y)>1e-12
>Limit
>> >32
>> >>   ) Select y From r Order By i Desc Limit 1
>> >> ) -- SubSelect-Closing-Paren...
>> >>
>> >> HTH
>> >>
>> >> Olaf
>> >>
>> >> _______________________________________________
>> >> sqlite-users mailing list
>> >> sqlite-users@mailinglists.sqlite.org
>> >> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>> >>
>> >_______________________________________________
>> >sqlite-users mailing list
>> >sqlite-users@mailinglists.sqlite.org
>> >http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>>
>>
>>
>> _______________________________________________
>> sqlite-users mailing list
>> sqlite-users@mailinglists.sqlite.org
>> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>>
>_______________________________________________
>sqlite-users mailing list
>sqlite-users@mailinglists.sqlite.org
>http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users



_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to