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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
use warnings;
use strict;
use Math::MPFR qw(:mpfr);
my $t = 11;
print "1..$t\n";
eval {require Math::LongDouble;};
my $mant_dig = Math::MPFR::_LDBL_MANT_DIG(); # expected to be either 64 or 106
my $ldbl_dig = Math::MPFR::_LDBL_DIG();
my $def_prec = 6 + $mant_dig;
unless($@ || $Math::LongDouble::VERSION < 0.02) {
Rmpfr_set_default_prec($def_prec);
my($ld_1, $ld_2) = (Math::LongDouble->new('1.123'), Math::LongDouble->new());
my $fr_plus6 = Math::MPFR->new();
my $fr_true = Rmpfr_init2($mant_dig);
my ($man, $exp);
Rmpfr_set_LD($fr_plus6, $ld_1, MPFR_RNDN);
Rmpfr_get_LD($ld_2, $fr_plus6, MPFR_RNDN);
if($ld_1 && $ld_1 == $ld_2) {print "ok 1\n"}
else {
warn "\$ld_1: $ld_1\n\$ld_2: $ld_2\n";
print "not ok 1\n";
}
# The following binary strings represent the mantissa for 1e-37 (for varous precisions)
# Precision = 112 or 70:
my $str_plus6 = $mant_dig == 106
? '1000100000011100111010100001010001010100010111000111010101110101011111100101000011010110010000010111011111011010'
: '1000100000011100111010100001010001010100010111000111010101110101100000';
# Precision = 106 or 64 (but derived from the relevant above representation).
my $m_plus6_to_actual = $mant_dig == 106
? '1000100000011100111010100001010001010100010111000111010101110101011111100101000011010110010000010111011111'
: '1000100000011100111010100001010001010100010111000111010101110110';
# Precision = 106 or 64 (actual correct 106/64-bit representation).
my $m_actual = $mant_dig == 106
? '1000100000011100111010100001010001010100010111000111010101110101011111100101000011010110010000010111011111'
: '1000100000011100111010100001010001010100010111000111010101110101';
my $ld_check = Math::LongDouble->new('1e-37');
Rmpfr_set_str($fr_plus6, '1@-37', 10, MPFR_RNDN);
Rmpfr_set_str($fr_true, '1@-37', 10, MPFR_RNDN);
($man, $exp) = Rmpfr_deref2($fr_true, 2, $mant_dig, MPFR_RNDN);
print "\$man:\n$man\n\n";
#####################################################
# $ld_2, derived from $fr_true should == $ld_check #
#####################################################
Rmpfr_get_LD($ld_2, $fr_true, MPFR_RNDN);
$man = get_man($ld_2);
if($man eq ('1.' . ('0' x ($ldbl_dig - 1)))) {print "ok 2\n"}
else {
warn "\n\$man: $man\n";
print "not ok 2\n";
}
if($ld_check == $ld_2) {print "ok 3\n"}
else {
warn "\n\$ld_check: $ld_check\n\$ld_2: $ld_2\n";
print "not ok 3\n";
}
$man = get_manp($ld_2, $ldbl_dig + 1);
if($man eq ('9.' . ('9' x $ldbl_dig))) {print "ok 4\n"}
else {
warn "\n\$man: $man\n";
print "not ok 4\n";
}
#####################################################
# $ld_2, derived from $fr_plus6 should != $ld_check #
#####################################################
Rmpfr_get_LD($ld_2, $fr_plus6, MPFR_RNDN);
$man = get_man($ld_2);
if($man eq ('1.' . ('0' x ($ldbl_dig - 1)))) {print "ok 5\n"}
else {
warn "\n\$man: $man\n";
print "not ok 5\n";
}
if($ld_check != $ld_2) {print "ok 6\n"}
else {
warn "\n\$ld_check: $ld_check\n\$ld_2: $ld_2\n";
print "not ok 6\n";
}
$man = get_manp($ld_2, 19);
if($man eq '1.000000000000000000') {print "ok 7\n"}
else {
warn "\n\$man: $man\n";
print "not ok 7\n";
}
##################################################################################
# Mantissa of $fr_plus6, rounded to $mant_dig bits should eq $m_plus6_to_actual #
##################################################################################
($man, $exp) = Rmpfr_deref2($fr_plus6, 2, $mant_dig, MPFR_RNDN);
if($man eq $m_plus6_to_actual) {print "ok 8\n"}
else {
warn "\n\$man: $man\n $m_plus6_to_actual\n";
print "not ok 8\n";
}
####################################################################
# $mant_dig-bit mantissa of $fr_true should eq $m_actual #
####################################################################
($man, $exp) = Rmpfr_deref2($fr_true, 2, $mant_dig, MPFR_RNDN);
if($man eq $m_actual) {print "ok 9\n"}
else {
warn "\n\$man: $man\n\$m_actual: $m_actual\n";
print "not ok 9\n";
}
Rmpfr_set_str($fr_plus6, $str_plus6, 2, MPFR_RNDN);
##################################################################################
# Mantissa of $fr_plus6, rounded to $mant_dig bits should eq $m_plus6_to_actual #
##################################################################################
($man, $exp) = Rmpfr_deref2($fr_plus6, 2, $mant_dig, MPFR_RNDN);
if($man eq $m_plus6_to_actual) {print "ok 10\n"}
else {
warn "\n\$man: $man\n $m_plus6_to_actual\n";
print "not ok 10\n";
}
Rmpfr_set_str($fr_true, $str_plus6, 2, MPFR_RNDN);
#################################################################################
# Mantissa of $fr_true, rounded to $mant_dig bits should eq $m_plus6_to_actual #
#################################################################################
($man, $exp) = Rmpfr_deref2($fr_true, 2, $mant_dig, MPFR_RNDN);
if($man eq $m_plus6_to_actual) {print "ok 11\n"}
else {
warn "\n\$man: $man\n $m_plus6_to_actual\n";
print "not ok 11\n";
}
}
else {
warn "\nSkipping all tests - couldn't load Math-LongDouble-0.02 (or later)\n";
for(1 .. $t) {print "ok $_\n"}
}
sub get_man {
return (split /e/i, Math::LongDouble::LDtoSTR($_[0]))[0];
}
sub get_manp {
return (split /e/i, Math::LongDouble::LDtoSTRP($_[0], $_[1]))[0];
}
|