### ----------------------------------------------------
### -- Rat::Precise
### -- Licenses: Artistic-2.0
### -- Authors: Steve Schulze (thundergnat)
### -- File: t/01-rat.t
### ----------------------------------------------------
use Test;
use Rat::Precise;

plan 153;

can-ok( Rat, 'precise', 'Rat can .precise');

# Testing terminating powers of 2 denominators
is( (.5**0).precise, '1', 'Testing .5**0');
is( (.5**1).precise, '0.5', 'Testing .5**1');
is( (.5**2).precise, '0.25', 'Testing .5**2');
is( (.5**3).precise, '0.125', 'Testing .5**3');
is( (.5**4).precise, '0.0625', 'Testing .5**4');
is( (.5**5).precise, '0.03125', 'Testing .5**5');
is( (.5**6).precise, '0.015625', 'Testing .5**6');
is( (.5**7).precise, '0.0078125', 'Testing .5**7');
is( (.5**8).precise, '0.00390625', 'Testing .5**8');
is( (.5**9).precise, '0.001953125', 'Testing .5**9');
is((.5**10).precise, '0.0009765625', 'Testing .5**10');
is((.5**11).precise, '0.00048828125', 'Testing .5**11');
is((.5**12).precise, '0.000244140625', 'Testing .5**12');
is((.5**13).precise, '0.0001220703125', 'Testing .5**13');
is((.5**14).precise, '0.00006103515625', 'Testing .5**14');
is((.5**15).precise, '0.000030517578125', 'Testing .5**15');
is((.5**16).precise, '0.0000152587890625', 'Testing .5**16');
is((.5**17).precise, '0.00000762939453125', 'Testing .5**17');
is((.5**18).precise, '0.000003814697265625', 'Testing .5**18');
is((.5**19).precise, '0.0000019073486328125', 'Testing .5**19');
is((.5**20).precise, '0.00000095367431640625', 'Testing .5**20');
is((.5**21).precise, '0.000000476837158203125', 'Testing .5**21');
is((.5**22).precise, '0.0000002384185791015625', 'Testing .5**22');
is((.5**23).precise, '0.00000011920928955078125', 'Testing .5**23');
is((.5**24).precise, '0.000000059604644775390625', 'Testing .5**24');
is((.5**25).precise, '0.0000000298023223876953125', 'Testing .5**25');
is((.5**26).precise, '0.00000001490116119384765625', 'Testing .5**26');
is((.5**27).precise, '0.000000007450580596923828125', 'Testing .5**27');
is((.5**28).precise, '0.0000000037252902984619140625', 'Testing .5**28');
is((.5**29).precise, '0.00000000186264514923095703125', 'Testing .5**29');
is((.5**30).precise, '0.000000000931322574615478515625', 'Testing .5**30');
is((.5**31).precise, '0.0000000004656612873077392578125', 'Testing .5**31');
is((.5**32).precise, '0.00000000023283064365386962890625', 'Testing .5**32');
is((.5**33).precise, '0.000000000116415321826934814453125', 'Testing .5**33');
is((.5**34).precise, '0.0000000000582076609134674072265625', 'Testing .5**34');
is((.5**35).precise, '0.00000000002910383045673370361328125', 'Testing .5**35');
is((.5**36).precise, '0.000000000014551915228366851806640625', 'Testing .5**36');
is((.5**37).precise, '0.0000000000072759576141834259033203125', 'Testing .5**37');
is((.5**38).precise, '0.00000000000363797880709171295166015625', 'Testing .5**38');
is((.5**39).precise, '0.000000000001818989403545856475830078125', 'Testing .5**39');
is((.5**40).precise, '0.0000000000009094947017729282379150390625', 'Testing .5**40');
is((.5**41).precise, '0.00000000000045474735088646411895751953125', 'Testing .5**41');
is((.5**42).precise, '0.000000000000227373675443232059478759765625', 'Testing .5**42');
is((.5**43).precise, '0.0000000000001136868377216160297393798828125', 'Testing .5**43');
is((.5**44).precise, '0.00000000000005684341886080801486968994140625', 'Testing .5**44');
is((.5**45).precise, '0.000000000000028421709430404007434844970703125', 'Testing .5**45');
is((.5**46).precise, '0.0000000000000142108547152020037174224853515625', 'Testing .5**46');
is((.5**47).precise, '0.00000000000000710542735760100185871124267578125', 'Testing .5**47');
is((.5**48).precise, '0.000000000000003552713678800500929355621337890625', 'Testing .5**48');
is((.5**49).precise, '0.0000000000000017763568394002504646778106689453125', 'Testing .5**49');
is((.5**50).precise, '0.00000000000000088817841970012523233890533447265625', 'Testing .5**50');
is((.5**51).precise, '0.000000000000000444089209850062616169452667236328125', 'Testing .5**51');
is((.5**52).precise, '0.0000000000000002220446049250313080847263336181640625', 'Testing .5**52');
is((.5**53).precise, '0.00000000000000011102230246251565404236316680908203125', 'Testing .5**53');
is((.5**54).precise, '0.000000000000000055511151231257827021181583404541015625', 'Testing .5**54');
is((.5**55).precise, '0.0000000000000000277555756156289135105907917022705078125', 'Testing .5**55');
is((.5**56).precise, '0.00000000000000001387778780781445675529539585113525390625', 'Testing .5**56');
is((.5**57).precise, '0.000000000000000006938893903907228377647697925567626953125', 'Testing .5**57');
is((.5**58).precise, '0.0000000000000000034694469519536141888238489627838134765625', 'Testing .5**58');
is((.5**59).precise, '0.00000000000000000173472347597680709441192448139190673828125', 'Testing .5**59');
is((.5**60).precise, '0.000000000000000000867361737988403547205962240695953369140625', 'Testing .5**60');
is((.5**61).precise, '0.0000000000000000004336808689942017736029811203479766845703125', 'Testing .5**61');
is((.5**62).precise, '0.00000000000000000021684043449710088680149056017398834228515625', 'Testing .5**62');
is((.5**63).precise, '0.000000000000000000108420217248550443400745280086994171142578125', 'Testing .5**63');

# Testing terminating powers of 5 denominators
is( (.2**1).precise, '0.2', 'Testing .2**1');
is( (.2**2).precise, '0.04', 'Testing .2**2');
is( (.2**3).precise, '0.008', 'Testing .2**3');
is( (.2**4).precise, '0.0016', 'Testing .2**4');
is( (.2**5).precise, '0.00032', 'Testing .2**5');
is( (.2**6).precise, '0.000064', 'Testing .2**6');
is( (.2**7).precise, '0.0000128', 'Testing .2**7');
is( (.2**8).precise, '0.00000256', 'Testing .2**8');
is( (.2**9).precise, '0.000000512', 'Testing .2**9');
is((.2**10).precise, '0.0000001024', 'Testing .2**10');
is((.2**11).precise, '0.00000002048', 'Testing .2**11');
is((.2**12).precise, '0.000000004096', 'Testing .2**12');
is((.2**13).precise, '0.0000000008192', 'Testing .2**13');
is((.2**14).precise, '0.00000000016384', 'Testing .2**14');
is((.2**15).precise, '0.000000000032768', 'Testing .2**15');
is((.2**16).precise, '0.0000000000065536', 'Testing .2**16');
is((.2**17).precise, '0.00000000000131072', 'Testing .2**17');
is((.2**18).precise, '0.000000000000262144', 'Testing .2**18');
is((.2**19).precise, '0.0000000000000524288', 'Testing .2**19');
is((.2**20).precise, '0.00000000000001048576', 'Testing .2**20');
is((.2**21).precise, '0.000000000000002097152', 'Testing .2**21');
is((.2**22).precise, '0.0000000000000004194304', 'Testing .2**22');
is((.2**23).precise, '0.00000000000000008388608', 'Testing .2**23');
is((.2**24).precise, '0.000000000000000016777216', 'Testing .2**24');
is((.2**25).precise, '0.0000000000000000033554432', 'Testing .2**25');
is((.2**26).precise, '0.00000000000000000067108864', 'Testing .2**26');
is((.2**27).precise, '0.000000000000000000134217728', 'Testing .2**27');


is(Rat.new( 1,1).precise(25), '1', 'Testing digits parameter 1/1');
is(Rat.new( 1,2).precise(25), '0.5', 'Testing digits parameter 1/2');
is(Rat.new( 1,3).precise(25), '0.3333333333333333333333333', 'Testing digits parameter 1/3');
is(Rat.new( 1,4).precise(25), '0.25', 'Testing digits parameter 1/4');
is(Rat.new( 1,5).precise(25), '0.2', 'Testing digits parameter 1/5');
is(Rat.new( 1,6).precise(25), '0.1666666666666666666666667', 'Testing digits parameter 1/6');
is(Rat.new( 1,7).precise(25), '0.1428571428571428571428571', 'Testing digits parameter 1/7');
is(Rat.new( 1,8).precise(25), '0.125', 'Testing digits parameter 1/8');
is(Rat.new( 1,9).precise(25), '0.1111111111111111111111111', 'Testing digits parameter 1/9');
is(Rat.new(1,10).precise(25), '0.1', 'Testing digits parameter 1/10');
is(Rat.new(1,11).precise(25), '0.0909090909090909090909091', 'Testing digits parameter 1/11');
is(Rat.new(1,12).precise(25), '0.0833333333333333333333333', 'Testing digits parameter 1/12');
is(Rat.new(1,13).precise(25), '0.0769230769230769230769231', 'Testing digits parameter 1/13');
is(Rat.new(1,14).precise(25), '0.0714285714285714285714286', 'Testing digits parameter 1/14');
is(Rat.new(1,15).precise(25), '0.0666666666666666666666667', 'Testing digits parameter 1/15');
is(Rat.new(1,16).precise(25), '0.0625', 'Testing digits parameter 1/16');
is(Rat.new(1,17).precise(25), '0.0588235294117647058823529', 'Testing digits parameter 1/17');
is(Rat.new(1,18).precise(25), '0.0555555555555555555555556', 'Testing digits parameter 1/18');
is(Rat.new(1,19).precise(25), '0.0526315789473684210526316', 'Testing digits parameter 1/19');
is(Rat.new(1,20).precise(25), '0.05', 'Testing digits parameter 1/20');
is(Rat.new(1,21).precise(25), '0.047619047619047619047619', 'Testing digits parameter 1/21');
is(Rat.new(1,22).precise(25), '0.0454545454545454545454545', 'Testing digits parameter 1/22');
is(Rat.new(1,23).precise(25), '0.0434782608695652173913043', 'Testing digits parameter 1/23');
is(Rat.new(1,24).precise(25), '0.0416666666666666666666667', 'Testing digits parameter 1/24');
is(Rat.new(1,25).precise(25), '0.04', 'Testing digits parameter 1/25');

is(Rat.new( 1,1).precise(25, :z), '1.0000000000000000000000000', 'Testing digits with :z flag parameter 1/1');
is(Rat.new( 1,2).precise(25, :z), '0.5000000000000000000000000', 'Testing digits with :z flag parameter 1/2');
is(Rat.new( 1,3).precise(25, :z), '0.3333333333333333333333333', 'Testing digits with :z flag parameter 1/3');
is(Rat.new( 1,4).precise(25, :z), '0.2500000000000000000000000', 'Testing digits with :z flag parameter 1/4');
is(Rat.new( 1,5).precise(25, :z), '0.2000000000000000000000000', 'Testing digits with :z flag parameter 1/5');
is(Rat.new( 1,6).precise(25, :z), '0.1666666666666666666666667', 'Testing digits with :z flag parameter 1/6');
is(Rat.new( 1,7).precise(25, :z), '0.1428571428571428571428571', 'Testing digits with :z flag parameter 1/7');
is(Rat.new( 1,8).precise(25, :z), '0.1250000000000000000000000', 'Testing digits with :z flag parameter 1/8');
is(Rat.new( 1,9).precise(25, :z), '0.1111111111111111111111111', 'Testing digits with :z flag parameter 1/9');
is(Rat.new(1,10).precise(25, :z), '0.1000000000000000000000000', 'Testing digits with :z flag parameter 1/10');
is(Rat.new(1,11).precise(25, :z), '0.0909090909090909090909091', 'Testing digits with :z flag parameter 1/11');
is(Rat.new(1,12).precise(25, :z), '0.0833333333333333333333333', 'Testing digits with :z flag parameter 1/12');
is(Rat.new(1,13).precise(25, :z), '0.0769230769230769230769231', 'Testing digits with :z flag parameter 1/13');
is(Rat.new(1,14).precise(25, :z), '0.0714285714285714285714286', 'Testing digits with :z flag parameter 1/14');
is(Rat.new(1,15).precise(25, :z), '0.0666666666666666666666667', 'Testing digits with :z flag parameter 1/15');
is(Rat.new(1,16).precise(25, :z), '0.0625000000000000000000000', 'Testing digits with :z flag parameter 1/16');
is(Rat.new(1,17).precise(25, :z), '0.0588235294117647058823529', 'Testing digits with :z flag parameter 1/17');
is(Rat.new(1,18).precise(25, :z), '0.0555555555555555555555556', 'Testing digits with :z flag parameter 1/18');
is(Rat.new(1,19).precise(25, :z), '0.0526315789473684210526316', 'Testing digits with :z flag parameter 1/19');
is(Rat.new(1,20).precise(25, :z), '0.0500000000000000000000000', 'Testing digits with :z flag parameter 1/20');
is(Rat.new(1,21).precise(25, :z), '0.0476190476190476190476190', 'Testing digits with :z flag parameter 1/21');
is(Rat.new(1,22).precise(25, :z), '0.0454545454545454545454545', 'Testing digits with :z flag parameter 1/22');
is(Rat.new(1,23).precise(25, :z), '0.0434782608695652173913043', 'Testing digits with :z flag parameter 1/23');
is(Rat.new(1,24).precise(25, :z), '0.0416666666666666666666667', 'Testing digits with :z flag parameter 1/24');
is(Rat.new(1,25).precise(25, :z), '0.0400000000000000000000000', 'Testing digits with :z flag parameter 1/25');

is((7/1610).precise, '0.0043478260869565', 'Rat returns 16 digits by default');
is((7/1610).precise(26), '0.00434782608695652173913043', 'digits parameter works');
is((7/1610).precise(24), '0.00434782608695652173913', 'non-significant zeros are trimmed');
is((7/1610).precise(24, :z), '0.004347826086956521739130', 'unless the :z parameter is set');
is((7/1610).precise(2), '0', 'degenerate non-significant zeros are trimmed');
is((7/1610).precise(2, :z), '0.00', 'unless the :z parameter is set');
is((7/1610).precise(0), '0', 'zero digits returns integer portion only');

is(Rat.new(999999999,1000000000).precise, '0.999999999','No rounding when not appropriate');
is(Rat.new(999999999,1000000000).precise(8), '1', 'Rounds when appropriate');
is(Rat.new(999999999,1000000000).precise(8, :z), '1.00000000', 'Rounds but preserves zeros');

throws-like({(.5**64).precise}, X::Method::NotFound, 'Overflow to Num fails as expected');

done-testing;


