[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Implementation of log(x) for SPARC32
- To: shlomif(at-nospam)techst02.technion.ac.il
- Subject: Re: Implementation of log(x) for SPARC32
- From: "Ehud Karni" <ehud(at-nospam)unix.simonwiesel.co.il>
- Date: Tue, 25 Dec 2001 14:23:19 +0200
- Cc: nyh(at-nospam)math.technion.ac.il, linux-il(at-nospam)linux.org.il
- Delivered-To: linux.org.il-linux-il@linux.org.il
- In-reply-to: <Pine.GSO.4.33.0112251318490.4261-100000@techst02.technion.ac.il>(message from Shlomi Fish on Tue, 25 Dec 2001 13:23:20 +0200 (IST))
- Organization: Mivtach-Simon Insurance agencies
- References: <Pine.GSO.4.33.0112251318490.4261-100000@techst02.technion.ac.il>
- Reply-to: ehud(at-nospam)unix.simonwiesel.co.il
- Sender: linux-il-bounce(at-nospam)cs.huji.ac.il
On Tue, 25 Dec 2001 13:23:20 +0200 (IST), Shlomi Fish <shlomif@techst02.technion.ac.il> wrote:
>
> FYI, I eventually gave up and coded a logarithm function in perl:
>
> #################
> #!/usr/bin/perl
>
> use strict;
>
> my $e_const = exp(1);
> my $e_const_reci = (1/$e_const);
>
> my $number = shift || 516;
>
> printf("%.80lf\n", mylog($number));
> printf("%.80lf\n", log($number));
>
> sub mylog
> {
> my $number = shift;
> my $exp_base = 0;
> while ($number > 2)
> {
> $number *= $e_const_reci;
> $exp_base++;
> }
> $number -= 1;
> my $x_times_n = $number;
> my $result = 0;
> for(my $a = 1; $a < 28 ; $a++)
> {
> if ($a & 0x1)
> {
> $result += $x_times_n/$a;
> }
> else
> {
> $result -= $x_times_n/$a;
> }
> $x_times_n *= $number;
> #printf("%i: %.80lf\n", $a, $result);
> }
> return $result+$exp_base;
> }
> #####################################
>
> Works like a charm with exactly the same accuracy. I'm going to convert it
> to C, and by this I will have a truly portable log() implementation for
> the kernel.
>
> IMO, someone should port stuff like a large part of glibc as well as STL,
> etc to the kernel. That would make the lives of programmers much easier
> because they won't have to reinvent the wheel times and again.
May I suggest a small improvement ?
You are using the Taylor series for ln(1+X).
It is better to use the series for ln((1+X)/(1-X)) which is
2*(X+X**3/3+X**5/5+..X**(2n-1)/(2n-1)...)
There is no sign change and it needs half the numbers of terms.
If you have T [between 0.5 and 2] and you do T=(1+X)/(1-X), you'll get
X=(T-1)/(T+1) which gives you an |X| < 0.334. This will converge very
quickly (for 14 decimal digits precision you need only 15 iterations)
Ehud.
--
Ehud Karni Tel: +972-3-7966-561 /"\
Mivtach - Simon Fax: +972-3-7966-667 \ / ASCII Ribbon Campaign
Insurance agencies (USA) voice mail and X Against HTML Mail
http://www.mvs.co.il FAX: 1-815-5509341 / \
mailto:ehud@unix.simonwiesel.co.il Better Safe Than Sorry
=================================================================
To unsubscribe, send mail to linux-il-request@linux.org.il with
the word "unsubscribe" in the message body, e.g., run the command
echo unsubscribe | mail linux-il-request@linux.org.il