pow.t 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. #!perl -T
  2. use 5.006;
  3. use strict;
  4. use warnings;
  5. use Test::More;
  6. plan tests => 159;
  7. use Math::AnyNum;
  8. my $int1 = Math::AnyNum->new(3);
  9. my $int2 = Math::AnyNum->new(-4);
  10. #################################################################
  11. # integer
  12. my $r = $int1**$int1;
  13. is("$r", "27");
  14. $r = $int1->ipow($int1);
  15. is("$r", "27");
  16. $r = $int1**4;
  17. is("$r", "81");
  18. $r = $int1->ipow(4);
  19. is("$r", "81");
  20. $r = 4**$int1;
  21. is("$r", "64");
  22. $r = $int2**$int1;
  23. is("$r", "-64");
  24. $r = $int2**2;
  25. is("$r", "16");
  26. $r = $int1**$int2;
  27. ok($r == 1 / ($int1**abs($int2)));
  28. $r = $int1->ipow($int2);
  29. is("$r", "0");
  30. $r = $int2->ipow($int1);
  31. is("$r", "-64");
  32. $r = $int2->ipow(2);
  33. is("$r", "16");
  34. $r = (-$int1)**($int2);
  35. ok($r == 1 / ($int1**abs($int2)));
  36. $r = (-$int1)**($int2 - 1);
  37. ok($r == -(1 / ($int1**abs($int2 - 1))));
  38. $r = $int2**(-$int1);
  39. is("$r", "-1/64");
  40. $r = $int2**(-$int1 + 1);
  41. is("$r", "1/16");
  42. #################################################################
  43. # float + int
  44. my $float1 = Math::AnyNum->new(3.45);
  45. my $float2 = Math::AnyNum->new(-5.67);
  46. $r = $float1**$int1;
  47. is("$r", "41.063625");
  48. $r = $float1**$int2;
  49. like("$r", qr/^0\.00705868/);
  50. $r = $float1**$float2;
  51. like("$r", qr/^0\.0008924/);
  52. $r = $float2**$int1;
  53. is("$r", "-182.284263");
  54. $r = $float2**$int2;
  55. like("$r", qr/^0\.00096753/);
  56. $r = $float2**abs($int2);
  57. is("$r", "1033.55177121");
  58. $r = $float1**4;
  59. is("$r", "141.66950625");
  60. $r = $float2**2;
  61. is("$r", "32.1489");
  62. $r = $float2**3;
  63. is("$r", "-182.284263");
  64. $r = $float1**2.34;
  65. like("$r", qr/^18\.13412823/);
  66. $r = $float2**2.25;
  67. like("$r", qr/^35\.078974175.*?\+35\.078974175.*?i\z/);
  68. $r = 3**$float1;
  69. like("$r", qr/^44\.2658011/);
  70. $r = 1.23**$float2;
  71. like("$r", qr/^0\.309198955/);
  72. $r = 0**$float2;
  73. is(lc("$r"), 'inf');
  74. $r = Math::AnyNum->new(0)**$int2;
  75. is(lc("$r"), 'inf');
  76. $r = Math::AnyNum->new(0)**$int1;
  77. is("$r", "0");
  78. $r = 0**($int2 - 1);
  79. is(lc("$r"), 'inf');
  80. {
  81. my $n = Math::AnyNum->new('12.6');
  82. $n = $n->pow('3.45');
  83. like("$n", qr/^6255\.735538995494576076354865979491381\d*\z/);
  84. }
  85. {
  86. my $n = Math::AnyNum->new('12.6');
  87. $n = $n->pow('3.45');
  88. like("$n", qr/^6255\.735538995494576076354865979491381\d*\z/);
  89. }
  90. {
  91. my $n = Math::AnyNum->new('12.6');
  92. $n = $n->ipow('3.45');
  93. is("$n", "1728");
  94. }
  95. ##############################################################
  96. # special values
  97. # See: https://en.wikipedia.org/wiki/NaN#Operations_generating_NaN
  98. {
  99. use Math::AnyNum qw(:overload);
  100. # AnyNum
  101. is(0**0, 1);
  102. is(0**Inf, 0);
  103. is(0**(-Inf), Inf);
  104. is(ref(0**0), 'Math::AnyNum'); # make sure we're getting AnyNum objects
  105. is(1**Inf, 1);
  106. is((-1)**Inf, 1);
  107. is(1**(-Inf), 1);
  108. is((-1)**(-Inf), 1);
  109. is(Inf**0, 1);
  110. is((-Inf)**0, 1);
  111. is((-Inf)**2, Inf);
  112. is((-Inf)**3, -Inf);
  113. is((-Inf)**2.3, 'Inf+NaNi');
  114. is(Inf**2.3, Inf);
  115. is(Inf**-2.3, 0);
  116. is((-Inf)**-3, 0);
  117. is(Inf**Inf, Inf);
  118. is((-Inf)**Inf, Inf);
  119. is((-Inf)**(-Inf), 0);
  120. is(Inf**(-Inf), 0);
  121. is(100**(-Inf), 0);
  122. is((-100)**(-Inf), 0);
  123. is(((0**(1 / 0))**0), 1);
  124. is(0->root(0)->pow(0), 1);
  125. is((Inf)**(1 / (-12)), 0);
  126. is((-Inf)**(1 / (-12)), 0);
  127. is((Inf)**(1 / (2)), Inf);
  128. is((-Inf)**(1 / (2)), 'Inf+NaNi');
  129. is((Inf)**(1 / (Inf)), 1);
  130. is((-Inf)**(1 / (Inf)), 1);
  131. is((Inf)**(1 / (-Inf)), 1);
  132. is((-Inf)**(1 / (-Inf)), 1);
  133. # Scalar
  134. is("1"**Inf, 1);
  135. is("-1"**Inf, 1);
  136. is("1"**(-Inf), 1);
  137. is("-1"**(-Inf), 1);
  138. is(Inf**"0", 1);
  139. is((-Inf)**"0", 1);
  140. is((-Inf)**"2", Inf);
  141. is((-Inf)**"3", -Inf);
  142. is((-Inf)**"2.3", 'Inf+NaNi');
  143. is(Inf**"2.3", Inf);
  144. is(Inf**"-2.3", 0);
  145. is((-Inf)**"-3", 0);
  146. is("100"**(-Inf), 0);
  147. is("-100"**(-Inf), 0);
  148. is(((0**(1 / 0))**"0"), 1);
  149. is((("0"**(1 / 0))**"0"), 1);
  150. is(0->root("0")->pow("0"), 1);
  151. is((Inf)**("1" / (Inf)), 1);
  152. is((-Inf)**("1" / (Inf)), 1);
  153. is((Inf)**("1" / (-Inf)), 1);
  154. is((-Inf)**("1" / (-Inf)), 1);
  155. }
  156. {
  157. my $mone = Math::AnyNum->new(-1);
  158. my $one = Math::AnyNum->new(1);
  159. my $zero = Math::AnyNum->new(0);
  160. my $inf = Math::AnyNum->inf;
  161. my $ninf = Math::AnyNum->ninf;
  162. # NEGATIVE INFINITY
  163. is($ninf**$inf, $inf);
  164. is($ninf**$ninf, $zero);
  165. is($ninf**$zero, $one);
  166. is($ninf**$one, $ninf);
  167. is($ninf**$mone, $zero); # actually -0.0
  168. is($ninf->ipow($inf), 'NaN'); # should be Inf?
  169. is($ninf->ipow($ninf), 'NaN'); # should be 0?
  170. is($ninf->ipow($zero), 'NaN'); # should be 1?
  171. is($ninf->ipow($one), 'NaN'); # should be -Inf?
  172. is($ninf->ipow($mone), 'NaN'); # should be 0?
  173. # MINUS ONE
  174. is($mone**$inf, $one);
  175. is($mone**$ninf, $one);
  176. is($mone**$zero, $one);
  177. is($mone**$one, $mone);
  178. is($mone**$mone, $mone);
  179. is($mone->ipow($inf), 'NaN'); # should be 1?
  180. is($mone->ipow($ninf), 'NaN'); # should be 1?
  181. is($mone->ipow($zero), $one);
  182. is($mone->ipow($one), $mone);
  183. is($mone->ipow($mone), $mone);
  184. # ZERO
  185. is($zero**$inf, $zero);
  186. is($zero**$ninf, $inf);
  187. is($zero**$zero, $one);
  188. is($zero**$one, $zero);
  189. is($zero**$mone, $inf);
  190. is($zero->ipow($inf), 'NaN'); # should be 0?
  191. is($zero->ipow($ninf), 'NaN'); # should be Inf?
  192. is($zero->ipow($zero), $one);
  193. is($zero->ipow($one), $zero);
  194. is($zero->ipow($mone), $inf);
  195. # ONE
  196. is($one**$inf, $one);
  197. is($one**$ninf, $one);
  198. is($one**$zero, $one);
  199. is($one**$one, $one);
  200. is($one**$mone, $one);
  201. is($one->ipow($inf), 'NaN'); # should be 1?
  202. is($one->ipow($ninf), 'NaN'); # should be 1?
  203. is($one->ipow($zero), $one);
  204. is($one->ipow($one), $one);
  205. is($one->ipow($mone), $one);
  206. # POSITIVE INFINITY
  207. is($inf**$inf, $inf);
  208. is($inf**$ninf, $zero);
  209. is($inf**$zero, $one);
  210. is($inf**$one, $inf);
  211. is($inf**$mone, $zero);
  212. is($inf->ipow($inf), 'NaN'); # should be Inf?
  213. is($inf->ipow($ninf), 'NaN'); # should be 0?
  214. is($inf->ipow($zero), 'NaN'); # should be 1?
  215. is($inf->ipow($one), 'NaN'); # should be Inf?
  216. is($inf->ipow($mone), 'NaN'); # should be 0?
  217. # Make sure the constants are the same
  218. is($inf, Math::AnyNum->inf);
  219. is($ninf, Math::AnyNum->ninf);
  220. is($zero, Math::AnyNum->zero);
  221. is($one, Math::AnyNum->one);
  222. is($mone, Math::AnyNum->mone);
  223. }
  224. ##############################################################
  225. # special integer truncations
  226. is(Math::AnyNum->new(-3)->ipow(-5), -1);
  227. is(Math::AnyNum->new(-3)->ipow(Math::AnyNum->new(-5)), -1);
  228. is(Math::AnyNum->new(-3)->ipow(-4), 0);
  229. is(Math::AnyNum->new(-3)->ipow($int2), 0);
  230. is(Math::AnyNum->new(-1)->ipow(-5), -1);
  231. is(Math::AnyNum->new(-1)->ipow(Math::AnyNum->new(-5)), -1);
  232. is(Math::AnyNum->new(-1)->ipow(-4), 1);
  233. is(Math::AnyNum->new(-1)->ipow($int2), 1);
  234. ##############################################################
  235. # pow + int truncation
  236. is(Math::AnyNum->new(-3)->pow(-5)->int, 0);
  237. is(Math::AnyNum->new(-3)->pow(Math::AnyNum->new(-5))->int, 0);
  238. is(Math::AnyNum->new(-3)->pow(-4)->int, 0);
  239. is(Math::AnyNum->new(-3)->pow($int2)->int, 0);
  240. is(Math::AnyNum->new(-1)->pow(-5)->int, -1);
  241. is(Math::AnyNum->new(-1)->pow(Math::AnyNum->new(-5))->int, -1);
  242. is(Math::AnyNum->new(-1)->pow(-4)->int, 1);
  243. is(Math::AnyNum->new(-1)->pow($int2)->int, 1);