02-pow.t 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. #!perl -T
  2. use 5.006;
  3. use strict;
  4. use warnings;
  5. use Test::More;
  6. plan tests => 116;
  7. use Sidef;
  8. my $o = 'Sidef::Types::Number::Number';
  9. my $int1 = $o->new(3);
  10. my $int2 = $o->new(-4);
  11. my $inf = $o->inf;
  12. my $nan = $o->nan;
  13. my $ninf = $o->ninf;
  14. sub re($) {
  15. qr/^\Q$_[0]\E\z/;
  16. }
  17. #################################################################
  18. # integer
  19. my $r = $int1->pow($int1);
  20. is("$r", "27");
  21. $r = $int1->ipow($int1);
  22. is("$r", "27");
  23. $r = $int2->pow($int1);
  24. is("$r", "-64");
  25. $r = $int1->pow($int2);
  26. ok($r eq $int1->pow($int2->abs)->inv);
  27. $r = $int1->ipow($int2);
  28. is("$r", "0");
  29. $r = $int2->ipow($int1);
  30. is("$r", "-64");
  31. $r = $int1->neg->pow($int2);
  32. ok($r eq ($int1->pow($int2->abs)->inv));
  33. $r = $int1->neg->pow($int2->dec);
  34. ok($r eq $int1->pow($int2->dec->abs)->inv->neg);
  35. $r = $int2->pow($int1->neg);
  36. is($r->as_rat->get_value, "-1/64");
  37. $r = $int2->pow($int1->neg->inc);
  38. is($r->as_frac->get_value, "1/16");
  39. #################################################################
  40. # float + int
  41. my $float1 = $o->new(3.45)->float;
  42. my $float2 = $o->new(-5.67)->float;
  43. $r = $float1->pow($int1);
  44. is("$r", "41.063625");
  45. $r = $float1->pow($int2);
  46. like("$r", qr/^0\.00705868/);
  47. $r = $float1->pow($float2);
  48. like("$r", qr/^0\.0008924/);
  49. $r = $float2->pow($int1);
  50. is("$r", "-182.284263");
  51. $r = $float2->pow($int2);
  52. like("$r", qr/^0\.00096753/);
  53. $r = $float2->pow($int2->abs);
  54. is("$r", "1033.55177121");
  55. $r = $float2->pow($o->new("4.23"));
  56. is(ref($r), 'Sidef::Types::Number::Number');
  57. like("$r", qr/^1155\.531831861.*?\s*\+\s*1018\.7383470368.*?i\z/);
  58. $r = $o->new(0)->pow($int2);
  59. is(ref($r), 'Sidef::Types::Number::Number');
  60. is(lc("$r"), 'inf');
  61. $r = $o->new(0)->pow($int1);
  62. is("$r", "0");
  63. ##############################################################
  64. # special values
  65. # See: https://en.wikipedia.org/wiki/$nan#Operations_generating_$nan
  66. {
  67. my $one = $o->new('1');
  68. my $mone = $o->new('-1');
  69. my $zero = $o->new('0');
  70. is($zero->pow($inf), $zero);
  71. is($zero->pow($ninf), $inf);
  72. is($zero->pow($zero), $one);
  73. is($one->pow($inf), $one);
  74. is($mone->pow($inf), $one);
  75. is($one->pow($ninf), $one);
  76. is($mone->pow($ninf), $one);
  77. is($inf->pow($zero), $one);
  78. is(($ninf)->pow($zero), $one);
  79. is(($ninf)->pow($o->new(2)), $inf);
  80. is(($ninf)->pow($o->new(3)), $ninf);
  81. is($inf->pow($o->new(2.3)), $inf);
  82. is($inf->pow($o->new(-2.3)), $zero);
  83. is(($ninf)->pow($o->new(-3)), $zero);
  84. is($inf->pow($inf), $inf);
  85. is(($ninf)->pow($inf), $inf);
  86. is(($ninf)->pow($ninf), $zero);
  87. is($inf->pow($ninf), $zero);
  88. is($o->new(100)->pow($ninf), $zero);
  89. is($o->new(-100)->pow($ninf), $zero);
  90. is((($zero->pow($inf))->pow($zero)), $one);
  91. is($zero->root($zero)->pow($zero), $one);
  92. is(($inf)->pow($one->div($o->new(-12))), $zero);
  93. is(($ninf)->pow($o->new(-12)->inv), $zero);
  94. is(($inf)->pow($o->new(2)->inv), $inf);
  95. is(($inf)->pow($one->div($inf)), $one);
  96. is(($ninf)->pow($inf->inv), $one);
  97. is(($inf)->pow($one->div($ninf)), $one);
  98. is(($ninf)->pow($ninf->inv), $one);
  99. # NEGATIVE INFINITY
  100. is($ninf->pow($inf), $inf);
  101. is($ninf->pow($ninf), $zero);
  102. is($ninf->pow($zero), $one);
  103. is($ninf->pow($one), $ninf);
  104. is($ninf->pow($mone), $zero); # actually -0.0
  105. # MINUS ONE
  106. is($mone->pow($inf), $one);
  107. is($mone->pow($ninf), $one);
  108. is($mone->pow($zero), $one);
  109. is($mone->pow($one), $mone);
  110. is($mone->pow($mone), $mone);
  111. # ZERO
  112. is($zero->pow($inf), $zero);
  113. is($zero->pow($ninf), $inf);
  114. is($zero->pow($zero), $one);
  115. is($zero->pow($one), $zero);
  116. is($zero->pow($mone), $inf);
  117. # ONE
  118. is($one->pow($inf), $one);
  119. is($one->pow($ninf), $one);
  120. is($one->pow($zero), $one);
  121. is($one->pow($one), $one);
  122. is($one->pow($mone), $one);
  123. # POSITIVE INFINITY
  124. is($inf->pow($inf), $inf);
  125. is($inf->pow($ninf), $zero);
  126. is($inf->pow($zero), $one);
  127. is($inf->pow($one), $inf);
  128. is($inf->pow($mone), $zero);
  129. # Make sure the constants are the same
  130. is($inf, $o->inf);
  131. is($ninf, $o->ninf);
  132. is($zero, $o->new(0));
  133. is($one, $o->new(1));
  134. is($mone, $o->new(-1));
  135. ##############################################################
  136. # special integer flooring
  137. is($o->new(-3)->ipow($o->new(-5)), $mone);
  138. is($o->new(-3)->ipow($o->new(-4)), $zero);
  139. is($o->new(-1)->ipow($o->new(-5)), $mone);
  140. is($o->new(-1)->ipow($o->new(-4)), $one);
  141. ##############################################################
  142. # pow + floor
  143. is($o->new(-3)->pow($o->new(-5))->floor, $mone);
  144. is($o->new(-3)->pow($o->new(-4))->floor, $zero);
  145. is($o->new(-1)->pow($o->new(-5))->floor, $mone);
  146. is($o->new(-1)->pow($o->new(-4))->floor, $one);
  147. ##############################################################
  148. # pow + int truncation
  149. is($o->new(-3)->pow($o->new(-5))->int, $zero);
  150. is($o->new(-3)->pow($o->new(-4))->int, $zero);
  151. is($o->new(-1)->pow($o->new(-5))->int, $mone);
  152. is($o->new(-1)->pow($o->new(-4))->int, $one);
  153. }
  154. ##############################################################
  155. # real test
  156. {
  157. sub round_nth {
  158. my ($orig, $nth) = @_;
  159. my $n = $orig->abs;
  160. my $p = $o->new(10)->pow($nth);
  161. $n = $n->mul($p);
  162. $n = $n->add($o->new(0.5));
  163. if ($n->is_int and $n->is_odd) {
  164. $n = $n->sub($o->new(0.5));
  165. }
  166. $n = $n->int;
  167. $n = $n->div($p);
  168. $n = $n->neg if ($orig->is_neg);
  169. return $n;
  170. }
  171. my @tests = (
  172. # original | rounded | places
  173. [+1.6, +2, 0],
  174. [+1.5, +2, 0],
  175. [+1.4, +1, 0],
  176. [+0.6, +1, 0],
  177. [+0.5, 0, 0],
  178. [+0.4, 0, 0],
  179. [-0.4, 0, 0],
  180. [-0.5, 0, 0],
  181. [-0.6, -1, 0],
  182. [-1.4, -1, 0],
  183. [-1.5, -2, 0],
  184. [-1.6, -2, 0],
  185. [3.016, 3.02, 2],
  186. [3.013, 3.01, 2],
  187. [3.015, 3.02, 2],
  188. [3.045, 3.04, 2],
  189. [3.04501, 3.05, 2],
  190. [-1234.555, -1000, -3],
  191. [-1234.555, -1200, -2],
  192. [-1234.555, -1230, -1],
  193. [-1234.555, -1235, 0],
  194. [-1234.555, -1234.6, 1],
  195. [-1234.555, -1234.56, 2],
  196. [-1234.555, -1234.555, 3],
  197. );
  198. foreach my $pair (@tests) {
  199. my ($n, $expected, $places) = @$pair;
  200. my $rounded = round_nth($o->new($n), $o->new($places));
  201. is($rounded->eq($o->new($expected)), Sidef::Types::Bool::Bool::TRUE);
  202. }
  203. }