<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wikidot="http://www.wikidot.com/rss-namespace">

	<channel>
		<title>How to implement natural log?</title>
		<link>http://tibasicdev.wikidot.com/forum/t-8987164/how-to-implement-natural-log</link>
		<description>Posts in the discussion thread &quot;How to implement natural log?&quot;</description>
				<copyright></copyright>
		<lastBuildDate>Fri, 15 May 2026 13:55:33 +0000</lastBuildDate>
		
					<item>
				<guid>http://tibasicdev.wikidot.com/forum/t-8987164#post-4076239</guid>
				<title>Re: How to implement natural log?</title>
				<link>http://tibasicdev.wikidot.com/forum/t-8987164/how-to-implement-natural-log#post-4076239</link>
				<description></description>
				<pubDate>Tue, 04 Dec 2018 23:54:19 +0000</pubDate>
				<wikidot:authorName>Xeda Elnara</wikidot:authorName>				<wikidot:authorUserId>595803</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>I take that back, I had totally forgotten about the algorithm using theta functions! <a href="https://maths-people.anu.edu.au/~brent/pd/RNC7t.pdf">This</a> is a good reference for algorithms, from which you can derive some quality algorithms.<br /> For a straight-forward example, as long as inputs are bigger than roughly 2.45, then the calculators precision will be exhausted with this algorithm:</p> <div class="code"> <pre><code>1/Ans→Q 2(Q+Q^9+Q^25→P 1+2(Q^4+Q^16→Q 2PAns→A P²+Q²→G While e-5&lt;abs(A-Ans A→B .5(A+B→A √(BG→G End π/(A+G)</code></pre></div> <br /> To make it roughly 30% faster: <div class="code"> <pre><code>1/Ans→Q Q²²→A Ans²→B Ans²→C 2Q(1+B+BC→P 1+2(A+C→Q 2PAns→A P²+Q²→G While e-5&lt;abs(A-Ans A→B .5(A+B→A √(BG→G End π/(A+G)</code></pre></div> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://tibasicdev.wikidot.com/forum/t-8987164#post-4076207</guid>
				<title>Re: How to implement natural log?</title>
				<link>http://tibasicdev.wikidot.com/forum/t-8987164/how-to-implement-natural-log#post-4076207</link>
				<description></description>
				<pubDate>Tue, 04 Dec 2018 22:25:15 +0000</pubDate>
				<wikidot:authorName>Xeda Elnara</wikidot:authorName>				<wikidot:authorUserId>595803</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>To corroborate lirtosiast, to my knowledge it is just a version of the CORDIC or BKM algorithm that is used.</p> <p>I've implemented them using my own variant of the BKM algorithm in assembly and BASIC. For computing the natural log, you take advantage of log identities : <span class="math-inline">$log(x\cdot y)=log(x)+log(y)$</span> and <span class="math-inline">$log(1) = 0$</span>. Keep in mind that these apply for any base and for complex values.</p> <p>If you can find some sequence so that:<br /> <span class="math-inline">$x\cdot a_{0}\cdot a_{1} \cdot a_{2}\dots =1$</span>,</p> <p>then you have that:<br /> <span class="math-inline">$log(x\cdot a_{0}\cdot a_{1} \cdot a_{2}\dots) =log(1)$</span>,</p> <p>but that means:<br /> <span class="math-inline">$log(x)+log(a_{0})+log(a_{1})+log(a_{2})+\dots) = 0$</span>,</p> <p>and so :<br /> <span class="math-inline">$log(x)=-log(a_{0})-log(a_{1})-log(a_{2})-\dots)$</span>.</p> <p>The trick is then to use range reduction to get <span class="math-inline">$x$</span> into an acceptable range like [1,2) and use a precomputed table of values of the form <span class="math-inline">$log(1+d_{i}2^{-i})$</span>. Then during the loop you just multiply <span class="math-inline">$x$</span> by <span class="math-inline">$1+d_{i}2^{-i}$</span></p> <p>The example with real numbers is easier, so let's do an example with that. I want to find the log base 2 of 42. Using range reduction, <span class="math-inline">$log_{2}(42)=log_{2}(2^{5}\cdot 1.3125) = 5+log_{2}(1.3125)$</span> The goal then is to drive 1.3125 toward 1, so let's start:</p> <p>1.3125 needs to be driven toward 1 via multiplication. Ideally, we would multiply by 1/1.3125=.76190476&#8230; but our table doesn't hold that value. Our table does, however, have 1-2<sup>-2</sup> = .75.</p> <p>x=.75x =&gt; x=1.3125*.75 = .984375<br /> Excellent, now we subtract <span class="math-inline">$log_{2}(1-2^{-2})$</span> from our accumulator.<br /> acc=acc-<span class="math-inline">$log_{2}(1-2^{-2})$</span> =&gt; 5&#8212;.415037499&#8230; = 5.415037499&#8230;</p> <p>Next iteration. 1/x is now roughly 1.01587301&#8230;. That is awfully close to 1+2<sup>-6</sup> which is in our table.<br /> x=x+x/64 =&gt; x=.999755859&#8230;<br /> Now we subtract <span class="math-inline">$log_{2}(1-2^{-6})$</span> from our accumulator.<br /> acc=acc-<span class="math-inline">$log_{2}(1+2^{-6})$</span> =&gt; 5.3926696&#8230;</p> <p>I would like to point out that here we already have a few digits of accuracy.</p> <p>Next iteration. 1/x is now roughly 1.00024414&#8230;. That is awfully close to 1+2<sup>-12</sup> which is in our table.<br /> x=x+x/2<sup>12</sup> =&gt; x=.999999940&#8230;<br /> Now we subtract <span class="math-inline">$log_{2}(1-2^{-12})$</span> from our accumulator.<br /> acc=acc-<span class="math-inline">$log_{2}(1+2^{-12})$</span> =&gt; 5.39231750&#8230;</p> <p>For comparison, the actual value is <span style="text-decoration: underline;">5.392317</span>42&#8230;</p> <p>For a more in-depth analysis on this algorithm, looking at efficiency, take a look at <a href="https://www.omnimaga.org/math-and-science/computing-logarithms/">this</a>.</p> <hr /> <p>Now what if you want to compute from scratch (like if you don't have the table built yet) ? In a case like that, you'll find that the series expansion is slow as heck, even on fast computers, let alone our puny Z80 calculator. Well for that, the best way I have found is to use the Arithmetic Geometric Mean algorithm, or Carslon's accelerated Borchardt-Gauss algorithm. AGM is a bit easier to code general-purpose, so here is a BASIC program. Note that I take advantage of some tricks to optimize this further (ex. I only calculate the AGM to 5 digits precision, knowing that the next iteration will roughly double, so the final iteration is just (A+G)/2)</p> <div class="code"> <pre><code>Ans→X 1→A 2^-18/X→G While e-5&lt;abs(A-G A→B .5(A+B→A √(BG→G End π/(A+G)-20ln(2</code></pre></div> <br /> Now that is cool and all, but how do you calculate that ln(2) at the bottom? Well for that one we have a fast sum that generates roughly one base 10 digit per iteration:<br /> <span class="math-inline">$ln(2)\approx\frac{2}{3}\sum_{k=0}^{9}{\frac{9^{-k}}{2k+1}}$</span> <hr /> <p>Here is another algorithm I came up with based on <a href="http://www.ams.org/journals/mcom/1972-26-118/S0025-5718-1972-0307438-2/S0025-5718-1972-0307438-2.pdf">this</a> paper. It assumes <span class="math-inline">$x\in [.5,2]$</span> with the ideal range being <span class="math-inline">$x\in [\frac{\sqrt2}{2},\sqrt2]$</span></p> <div class="code"> <pre><code>a=.5(1+x) g=.5(a+x/a) ;half precision divide g=.5(g+x/g) ;full precision divide b=a a=(a+g)/2 c=.5(a+g) g=.5(c+a*g/c) ;full precision divide c=a b = a-b/4 a=(a+g)/2 c = a-c/4-b/16 return (x-1)(1-1/4)(1-1/16)/c</code></pre></div> <p>Rendered into fairly optimzed BASIC:</p> <div class="code"> <pre><code>Ans→X .5(1+Ans→A √(X→G .5(A+Ans 28Ans-C16+A+32√(GAns (X-1)45/Ans</code></pre></div> <hr /> <p><strong>EDIT:</strong> I also wanted to point out that you don't need to compute logs in order to change base. Here is an example that probably isn't the most optimized :</p> <div class="code"> <pre><code>int(abs(Ans→X &quot;0→Str1 If not(X Return While X .5int(X→X sub(&quot;01&quot;,1+fPart(Ans)2,1)+Str1→Str1 End sub(Str1,2,length(Str1)-2→Str1</code></pre></div> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://tibasicdev.wikidot.com/forum/t-8987164#post-4076130</guid>
				<title>Re: How to implement natural log?</title>
				<link>http://tibasicdev.wikidot.com/forum/t-8987164/how-to-implement-natural-log#post-4076130</link>
				<description></description>
				<pubDate>Tue, 04 Dec 2018 20:16:36 +0000</pubDate>
				<wikidot:authorName>Xeda Elnara</wikidot:authorName>				<wikidot:authorUserId>595803</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>I use spasm, which I compiled in such a way as to be able to sign applications and probably OSes. For programs and appvars, there is no signing needed.</p> <p>If your compiler doesn't do signing, you can likely output to a .hex file and then use rabbitsign to perform the app signing.</p> <p>As an example, to compile Grammer, I just use:</p> <div class="code"> <pre><code>spasm grammer.z80 grammer.8xk</code></pre></div> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://tibasicdev.wikidot.com/forum/t-8987164#post-4069421</guid>
				<title>Re: How to implement natural log?</title>
				<link>http://tibasicdev.wikidot.com/forum/t-8987164/how-to-implement-natural-log#post-4069421</link>
				<description></description>
				<pubDate>Tue, 27 Nov 2018 18:47:25 +0000</pubDate>
				<wikidot:authorName>lirtosiast</wikidot:authorName>				<wikidot:authorUserId>2005367</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>Sorry, I don't actually know assembly. You're probably better off asking on another forum. :)</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://tibasicdev.wikidot.com/forum/t-8987164#post-4069403</guid>
				<title>Re: How to implement natural log?</title>
				<link>http://tibasicdev.wikidot.com/forum/t-8987164/how-to-implement-natural-log#post-4069403</link>
				<description></description>
				<pubDate>Tue, 27 Nov 2018 18:20:36 +0000</pubDate>
				<wikidot:authorName>Deoxal</wikidot:authorName>				<wikidot:authorUserId>4178723</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>Thanks for the link. I have a couple of questions though about assemblers and the OS though:</p> <ol> <li>Do you use Brass, Spasm, or something else for assembling code?</li> <li>What programs do you use to create and sign .8xk, .8xu and .8xv files or can the assembler do it automatically?</li> <li>Do you need to create a .bin to convert to an .8xu?</li> <li>What dissembler do you use?</li> </ol> <p>Thanks (;</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://tibasicdev.wikidot.com/forum/t-8987164#post-4068844</guid>
				<title>Re: How to implement natural log?</title>
				<link>http://tibasicdev.wikidot.com/forum/t-8987164/how-to-implement-natural-log#post-4068844</link>
				<description></description>
				<pubDate>Tue, 27 Nov 2018 04:22:40 +0000</pubDate>
				<wikidot:authorName>lirtosiast</wikidot:authorName>				<wikidot:authorUserId>2005367</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p><a href="https://www.cemetech.net/forum/viewtopic.php?t=11187">https://www.cemetech.net/forum/viewtopic.php?t=11187</a> says the CORDIC algorithm is used. It seems tricky to implement in BCD, and I don't know the details.</p> <p>From looking at disassembly of the OS once, I know ln( is calculated by taking the result from log( and multiplying by a hardcoded ln(10). This is reflected in the fact that ln( is slower by a multiplication.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://tibasicdev.wikidot.com/forum/t-8987164#post-4068567</guid>
				<title>How to implement natural log?</title>
				<link>http://tibasicdev.wikidot.com/forum/t-8987164/how-to-implement-natural-log#post-4068567</link>
				<description></description>
				<pubDate>Mon, 26 Nov 2018 19:14:16 +0000</pubDate>
				<wikidot:authorName>Deoxal</wikidot:authorName>				<wikidot:authorUserId>4178723</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>I wrote this code to convert a number from decimal to binary, but it wouldn't work for 16 and 512 because of round off error. Adding <strong>round(</strong> fixed my issue, but now I want to dig deeper.</p> <div class="collapsible-block"> <div class="collapsible-block-folded"><a class="collapsible-block-link" href="javascript:;">+&nbsp;Show&nbsp;Code</a></div> <div class="collapsible-block-unfolded" style="display:none"> <div class="collapsible-block-unfolded-link"><a class="collapsible-block-link" href="javascript:;">-&nbsp;Hide&nbsp;Code</a></div> <div class="collapsible-block-content"> <div class="code"> <pre><code>Input &quot;X=&quot;,X iPart(abs(X→X &quot;M→Str1 If not(X Then &quot;0→Str1 Disp Str1 Return End iPart(logBASE(X,2→A // This is the line I was looking for the last hour For(A,A,0,­1 X-2^A→B If B≥0 Then Str1+&quot;1→Str1 B→X Else Str1+&quot;0→Str1 End End sub(Str1,2,length(Str1)-1→Str1 Disp Str1</code></pre></div> </div> </div> </div> <br /> So now I want to know how TI implemented logarithms and other functions and how to make my own versions. I've looked at the <a href="http://tibasicdev.wikidot.com/ln">ln</a> page, but there isn't anything there about how it's calculated. I'm familiar with Taylor series, Newton's Method, and Halley's method but I don't know how to use them correctly or if any of those would work for complex values.
				 	]]>
				</content:encoded>							</item>
				</channel>
</rss>