01-number.t 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. #!perl -T
  2. ###############################################################################
  3. use strict;
  4. use warnings;
  5. use Test::More tests => 188;
  6. use Sidef;
  7. sub re($) {
  8. qr/^\Q$_[0]\E\z/;
  9. }
  10. ###############################################################################
  11. # general tests
  12. my $o = 'Sidef::Types::Number::Number';
  13. my $zero = $o->new(0);
  14. my $one = $o->new(1);
  15. my $mone = $o->new(-1);
  16. {
  17. my $x = $o->new(1234);
  18. is("$x", "1234");
  19. $x = $o->new("1234/1");
  20. is("$x", "1234");
  21. $x = $o->new("1234/2");
  22. is("$x", "617");
  23. #$x = $o->new("100/1.0");
  24. #is("$x", "100");
  25. #$x = $o->new("10.0/1.0");
  26. #is("$x", "10");
  27. #$x = $o->new("0.1/10");
  28. #is("$x", "0.01");
  29. #$x = $o->new("0.1/0.1");
  30. #is("$x", "1");
  31. #$x = $o->new("1e2/10");
  32. #is("$x", "10");
  33. #$x = $o->new("5/1e2");
  34. #is("$x", "0.05");
  35. #$x = $o->new("1e2/1e1");
  36. #is("$x", "10");
  37. $x = $o->new("8");
  38. $x = $x->rsft($o->new("32"));
  39. is("$x", "0");
  40. $x = $o->new("112");
  41. $x = $x->rsft($o->new("32"));
  42. is("$x", "0");
  43. $x = $o->new("640");
  44. $x = $x->rsft($o->new("64"));
  45. is("$x", "0");
  46. $x = $o->new("1 / 3");
  47. like($x->as_rat, re '1/3');
  48. $x = $o->new("-1 / 3");
  49. like($x->as_rat, re '-1/3');
  50. $x = $o->new("1 / -3");
  51. like($x->as_rat, re '-1/3');
  52. $x = $o->new("abc");
  53. is("$x", "NaN");
  54. $x = $o->new("inf");
  55. is("$x", "Inf");
  56. $x = $o->new("-inf");
  57. is("$x", "-Inf");
  58. $x = $o->new("1/");
  59. is("$x", "NaN");
  60. $x = $o->new("1/+");
  61. is("$x", "NaN");
  62. $x = $o->new("1/-");
  63. is("$x", "NaN");
  64. $x = $o->new("1/_");
  65. is("$x", "NaN");
  66. $x = $o->new("+");
  67. is("$x", "NaN");
  68. $x = $o->new("-");
  69. is("$x", "NaN");
  70. $x = $o->new("_");
  71. is("$x", "NaN");
  72. $x = $o->new("1_000_000");
  73. is("$x", "1000000");
  74. #$x = $o->new("1/2/3/4/5/6"); # is parsed as: (1 / (2 / (3 / (4 / (5 / 6)))))
  75. #like($x->as_rat, re '5/16');
  76. #$x = $o->new("1/0");
  77. #is("$x", "Inf");
  78. #$x = $o->new("-1/0");
  79. #is("$x", "-Inf");
  80. #$x = $o->new("-h5/0", 36);
  81. #is("$x", "-Inf");
  82. $x = $o->new("ff/f", 16);
  83. is("$x", "17");
  84. $x = $o->new("7e", 16);
  85. is("$x", "126");
  86. $x = $o->new("inf", 36);
  87. is("$x", "24171");
  88. $x = $o->new("-Inf", 36);
  89. is("$x", "-24171");
  90. $x = $o->new("nan", 36);
  91. is("$x", "30191");
  92. # fraction in base 10
  93. $x = $o->new('123/45');
  94. like($x->as_rat, re '41/15');
  95. # fraction in base 36
  96. $x = $o->new("h5/1e", 36);
  97. like($x->as_float, re "12.34");
  98. $x = $o->new("14/1e", 36);
  99. like($x->as_rat, re "4/5");
  100. # base-10 number, converted to another base
  101. $x = $o->new($o->new("1211"), 3);
  102. is("$x", "49");
  103. #$x = $o->new("1/1.2");
  104. #like($x->as_rat, re "5/6");
  105. #$x = $o->new("1.3/1.2");
  106. #like($x->as_rat, re "13/12");
  107. #$x = $o->new("1.2/1");
  108. #like($x->as_rat, re "6/5");
  109. }
  110. ###############################################################################
  111. # general tests
  112. {
  113. like($o->new(2)->sqrt, qr/^1\.414213562/);
  114. like($o->new(100)->log, qr/^4\.605170185/);
  115. like($o->new(10)->exp, qr/^22026\.46579/);
  116. like($o->new(-4.5)->abs->float, qr/^4.5\z/);
  117. like($o->new(-4.5)->float->abs, qr/^4.5\z/);
  118. like($o->new(10)->abs, qr/^10\z/);
  119. like($o->new(2.9)->floor, qr/^2\z/);
  120. like($o->new(2.5)->floor, qr/^2\z/);
  121. like($o->new(2.1)->floor, qr/^2\z/);
  122. like($o->new(2)->floor, qr/^2\z/);
  123. like($o->new(2.9)->ceil, qr/^3\z/);
  124. like($o->new(2.5)->ceil, qr/^3\z/);
  125. like($o->new(2.1)->ceil, qr/^3\z/);
  126. like($o->new(2)->ceil, qr/^2\z/);
  127. like($o->new(2.3)->pow($o->new(5.4)), qr/^89.811/);
  128. like($o->new(1040)->ilog($o->new(2)), qr/^10\z/);
  129. like($o->new(2834)->ilog, qr/^7\z/);
  130. my $x = $o->new(1227);
  131. my $pow = $o->new(42);
  132. my $bint = $x->ipow($pow);
  133. ok($mone->is_pow($o->new(3)));
  134. ok(!($mone->is_pow($o->new(2))));
  135. ok($mone->is_pow($o->new(-3)));
  136. ok(!($mone->is_pow($o->new(-2))));
  137. ok($bint->is_pow($pow));
  138. ok($o->new(-27)->is_pow($o->new(3)));
  139. ok(!($o->new(-25)->is_pow($o->new(2))));
  140. ok(!($o->new(-27)->is_pow($o->new(-3))));
  141. ok($one->is_pow($o->new(3)));
  142. ok($one->is_pow($o->new(-2)));
  143. ok($zero->is_pow($one));
  144. ok($zero->is_pow($o->new(3)));
  145. ok(!($zero->is_pow($zero)));
  146. ok(!($zero->is_pow($o->new(-3))));
  147. ok(!($zero->is_pow($o->new(-4))));
  148. ok(!($zero->is_pow($o->new(-2))));
  149. ok(!($zero->is_pow($zero)));
  150. ok($bint->is_pow($o->new(2)));
  151. ok($bint->is_pow($o->new(3)));
  152. ok(!$bint->is_pow($o->new(4)));
  153. ok(!$bint->is_pow($o->new(5)));
  154. }
  155. ##############################################################################
  156. # Bernoulli numbers
  157. {
  158. my %results = qw(
  159. 0 1
  160. 1 1/2
  161. 2 1/6
  162. 3 0
  163. 4 -1/30
  164. 5 0
  165. 6 1/42
  166. 10 5/66
  167. 12 -691/2730
  168. 20 -174611/330
  169. 22 854513/138
  170. );
  171. #
  172. ## bernfrac()
  173. #
  174. foreach my $i (keys %results) {
  175. my $bn = $o->new($i)->bernfrac->as_rat;
  176. is("$bn", $results{$i});
  177. }
  178. is("${\($o->new(-2)->bernfrac)}", 'NaN'); # make sure we check for even correctly
  179. is($o->new(52)->bernfrac->as_frac->get_value, '-801165718135489957347924991853/1590');
  180. is($o->new(106)->bernfrac->as_frac->get_value, '36373903172617414408151820151593427169231298640581690038930816378281879873386202346572901/642');
  181. #
  182. ## bernreal()
  183. #
  184. my $r = $o->new(10);
  185. is("${\($o->new(-2)->bernreal)}", "NaN"); # check negative values
  186. is($o->new(1)->bernreal->get_value, 0.5);
  187. is($o->new(0)->bernreal->get_value, 1);
  188. is($o->new(3)->bernreal->get_value, 0);
  189. is($o->new(2)->bernreal->as_float($r)->get_value, '0.1666666667');
  190. is($o->new(52)->bernreal->as_float($r)->get_value, '-5.038778101e26');
  191. }
  192. ##############################################################################
  193. my ($x, $y, $z);
  194. $x = $o->new('1/4');
  195. $y = $o->new('1/3');
  196. like(($x->add($y))->as_rat, qr'^7/12\z');
  197. like(($x->mul($y))->as_rat, qr'^1/12\z');
  198. like(($x->div($y))->as_rat, qr'^3/4\z');
  199. $x = $o->new('2/3');
  200. $y = $o->new('3/2');
  201. ok(!($x->gt($y)));
  202. ok($x->lt($y));
  203. ok(!($x->eq($y)));
  204. $x = $o->new('-2/3');
  205. $y = $o->new('3/2');
  206. ok(!($x->gt($y)));
  207. ok($x->lt($y));
  208. ok(!($x->eq($y)));
  209. $x = $o->new('-2/3');
  210. $y = $o->new('-2/3');
  211. ok(!($x->gt($y)));
  212. ok(!($x->lt($y)));
  213. ok($x->eq($y));
  214. $x = $o->new('-2/3');
  215. $y = $o->new('-1/3');
  216. ok(!($x->gt($y)));
  217. ok($x->lt($y));
  218. ok(!($x->eq($y)));
  219. $x = $o->new('-124');
  220. $y = $o->new('-122');
  221. is($x->acmp($y), $o->new(1));
  222. $x = $o->new('-124');
  223. $y = $o->new('-122');
  224. is($x->cmp($y), $o->new(-1));
  225. $x = $o->new('3/7');
  226. $y = $o->new('5/7');
  227. like(($x->add($y))->as_rat, re '8/7');
  228. $x = $o->new('3/7');
  229. $y = $o->new('5/7');
  230. like(($x->mul($y))->as_rat, re '15/49');
  231. $x = $o->new('3/5');
  232. $y = $o->new('5/7');
  233. like(($x->mul($y))->as_rat, re '3/7');
  234. $x = $o->new('3/5');
  235. $y = $o->new('5/7');
  236. like(($x->div($y))->as_rat, re '21/25');
  237. $x = $o->new('43/99');
  238. $y = $o->new('13');
  239. like($x->mod($y)->as_rat, re '7');
  240. like($x->mod($y->rat)->as_rat, re '7');
  241. $x = $o->new('7/4');
  242. $y = $o->new('5/13');
  243. like(($x->mod($y))->as_rat, re '11/52');
  244. $x = $o->new('7/4');
  245. $y = $o->new('5/9');
  246. like(($x->mod($y))->as_rat, re '1/12');
  247. $x = $o->new('-144/9')->sqrt();
  248. is("$x", '4i');
  249. $x = $o->new('144/9')->sqrt();
  250. is("$x", '4');
  251. $x = $o->new('3/4');
  252. my $n = 'numerator';
  253. my $d = 'denominator';
  254. my $num = $x->$n;
  255. my $den = $x->$d;
  256. is("$num", 3);
  257. is("$den", 4);
  258. ##############################################################################
  259. # mixed arguments
  260. like($o->new('3/7')->add($o->new(1))->as_rat, re '10/7');
  261. like($o->new('3/10')->add($o->new(1.1))->as_rat, re '7/5');
  262. like($o->new('3/7')->sub($o->new(1))->as_rat, re '-4/7');
  263. like($o->new('3/10')->sub($o->new('1.1'))->as_rat, re '-4/5');
  264. like($o->new('3/7')->mul($o->new(1))->as_rat, re '3/7');
  265. like($o->new('3/10')->mul($o->new('1.1'))->as_rat, re '33/100');
  266. like($o->new('3/7')->div($o->new(1))->as_rat, re '3/7');
  267. like($o->new('3/10')->div($o->new('1.1'))->as_rat, re '3/11');
  268. ##############################################################################
  269. # pow
  270. $x = $o->new('2/1')->pow($o->new('3'));
  271. is("$x", '8');
  272. $x = $o->new('1/2')->pow($o->new('3'));
  273. is($x->as_frac->get_value, '1/8');
  274. #is("$x", '1/8');
  275. is("$x", '0.125');
  276. $x = $o->new('1/3')->pow($o->new('4'));
  277. is($x->as_frac->get_value, '1/81');
  278. #is("$x", '1/81');
  279. $x = $o->new('2/3')->pow($o->new(4));
  280. is($x->as_frac->get_value, '16/81');
  281. #is("$x", "16/81");
  282. $x = $o->new('2/3')->pow($o->new('5/3'));
  283. like("$x", qr/^0\.50876188557925/);
  284. ##############################################################################
  285. # fac
  286. $x = $o->new('1');
  287. $x->fac();
  288. is("$x", '1');
  289. my @fac = qw(1 1 2 6 24 120);
  290. for (my $i = 0 ; $i < 6 ; $i++) {
  291. $x = $o->new("$i/1")->fac();
  292. like($x, re $fac[$i]);
  293. }
  294. # test for $self->bnan() vs. $x->bnan();
  295. $x = $o->new('-1')->fac;
  296. is("$x", 'NaN');
  297. ##############################################################################
  298. # inc/dec
  299. $x = $o->new('3/2');
  300. like($x->inc()->as_rat, re '5/2');
  301. $x = $o->new('15/6');
  302. like($x->dec()->as_rat, re '3/2');
  303. ##############################################################################
  304. # bsqrt
  305. $x = $o->new('144');
  306. like($x->sqrt(), re '12');
  307. $x = $o->new('144/16');
  308. like($x->sqrt(), re '3');
  309. ##############################################################################
  310. # floor/ceil
  311. $x = $o->new('-7/7');
  312. like($x->$n(), re '-1');
  313. like($x->$d(), re '1');
  314. $x = $o->new('-7/7')->floor();
  315. like($x->$n(), re '-1');
  316. like($x->$d(), re '1');
  317. $x = $o->new('49/4');
  318. like($x->floor(), re '12');
  319. $x = $o->new('49/4');
  320. like($x->ceil(), re '13');
  321. ##############################################################################
  322. # root(), log(), powmod() and invmod()
  323. $x = $o->new(2)->pow($o->new(32));
  324. $y = $o->new(4);
  325. $z = $o->new(3);
  326. like($x->root($y), re '256');
  327. is(ref($x->root($y)), $o);
  328. like($x->powmod($y, $z), re '1');
  329. is(ref($x->powmod($y, $z)), $o);
  330. $x = $o->new(8);
  331. $y = $o->new(5033);
  332. $z = $o->new(4404);
  333. is($x->invmod($y), $z);
  334. is(ref($x->invmod($y)), $o);
  335. # square root with exact result
  336. $x = $o->new('1.44');
  337. like($x->root($o->new(2)), re "1.2");
  338. # log with exact result
  339. $x = $o->new('256.1');
  340. like($x->log($o->new(2)), qr/^8.0005634/);
  341. $x = $o->new(144);
  342. like($x->root($o->new('2')), re '12');
  343. $x = $o->new(12 * 12 * 12);
  344. like($x->root($o->new('3')), re '12');
  345. ##############################################################################
  346. # as_float()
  347. $x = $o->new('1/2');
  348. my $f = $x->as_float();
  349. like($x->as_rat, re '1/2');
  350. like($f, re '0.5');
  351. $x = $o->new('2/3');
  352. $f = $x->as_float($o->new(5));
  353. like($x->as_rat, re '2/3');
  354. like($f, re '0.66667');
  355. ##############################################################################
  356. # int()
  357. $x = $o->new('5/2');
  358. is(int($x), '2', '5/2 converted to integer');
  359. $x = $o->new('-1/2');
  360. is(int($x), '0', '-1/2 converted to integer');
  361. ##############################################################################
  362. # as_hex(), as_bin(), as_oct()
  363. $x = $o->new('8/8');
  364. like($x->as_hex(), re '1');
  365. like($x->as_bin(), re '1');
  366. like($x->as_oct(), re '1');
  367. $x = $o->new('80/8');
  368. like($x->as_hex(), re 'a');
  369. like($x->as_bin(), re '1010');
  370. like($x->as_oct(), re '12');
  371. ##############################################################################
  372. # shift_left(), shift_right()
  373. $x = $o->new(5);
  374. $y = $o->new(7);
  375. like($x->shift_left($y), re '640');
  376. like($x->shift_left($o->new(50)), re '5629499534213120');
  377. like($x->shift_left($o->new(62)), re '23058430092136939520');
  378. like($zero->shift_left($o->new(5)), re '0');
  379. like($one->shift_left($o->new(64)), re '18446744073709551616');
  380. like($one->shift_left($o->new(65)), re '36893488147419103232');
  381. like($mone->shift_left($x), re '-32');
  382. like($mone->shift_left($y), re '-128');
  383. like($x->shift_left($mone), re '2');
  384. like($y->shift_left($mone), re '3');
  385. like($x->shift_right($mone), re '10');
  386. like($y->shift_right($mone), re '14');
  387. like($zero->shift_right($o->new(5)), re '0');
  388. like($y->shift_right($x), re '0');
  389. like($x->shift_right($y), re '0');
  390. like($o->new('12312631237')->shift_right($o->new(10)), re '12024053');
  391. $x = $o->new('12312631237999999999123');
  392. like($x->shift_right($o->new(9)), re '24048107886718749998');
  393. like($x->shift_right($o->new(10)), re '12024053943359374999');
  394. ##############################################################################
  395. # done
  396. 1;