-
Notifications
You must be signed in to change notification settings - Fork 34
/
logarithmic_root_mpfr.pl
executable file
·67 lines (47 loc) · 1.61 KB
/
logarithmic_root_mpfr.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#!/usr/bin/perl
# Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 17 September 2016
# Website: https://github.com/trizen
# Logarithmic root of n.
# Solves c = x^x, where "c" is known.
# (based on Newton's method for nth-root)
# Example: 100 = x^x
# x = lgrt(100)
# x =~ 3.59728502354042
# The function is defined in real numbers for any value >= 0.7
use 5.010;
use strict;
use warnings;
use Math::MPFR;
my $PREC = 128; # can be tweaked
my $ROUND = Math::MPFR::MPFR_RNDN();
sub lgrt {
my ($c) = @_;
if (ref($c) ne 'Math::MPFR') {
my $n = Math::MPFR::Rmpfr_init2($PREC);
Math::MPFR::Rmpfr_set_str($n, "$c", 10, $ROUND);
$c = $n;
}
my $p = Math::MPFR::Rmpfr_init2($PREC);
Math::MPFR::Rmpfr_ui_pow_ui($p, 10, $PREC >> 2, $ROUND);
Math::MPFR::Rmpfr_ui_div($p, 1, $p, $ROUND);
my $d = Math::MPFR::Rmpfr_init2($PREC);
Math::MPFR::Rmpfr_log($d, $c, $ROUND);
my $x = Math::MPFR::Rmpfr_init2($PREC);
Math::MPFR::Rmpfr_set_ui($x, 1, $ROUND);
my $y = Math::MPFR::Rmpfr_init2($PREC);
Math::MPFR::Rmpfr_set_ui($y, 0, $ROUND);
my $tmp = Math::MPFR::Rmpfr_init2($PREC);
while (1) {
Math::MPFR::Rmpfr_sub($tmp, $x, $y, $ROUND);
Math::MPFR::Rmpfr_cmpabs($tmp, $p) <= 0 and last;
Math::MPFR::Rmpfr_set($y, $x, $ROUND);
Math::MPFR::Rmpfr_log($tmp, $x, $ROUND);
Math::MPFR::Rmpfr_add_ui($tmp, $tmp, 1, $ROUND);
Math::MPFR::Rmpfr_add($x, $x, $d, $ROUND);
Math::MPFR::Rmpfr_div($x, $x, $tmp, $ROUND);
}
$x;
}
say lgrt(100); # 3.597285023540417505497652251782286069146