The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/env perl
use strict;
use warnings;

use Test::More;
use Math::Prime::Util::GMP qw/lambertw/;

my $extra = defined $ENV{EXTENDED_TESTING} && $ENV{EXTENDED_TESTING};

# gp: \p 47   for(s=1,20,print(lambertw(s/10)))
my @lambertw_pos = (qw/
0.09127652716086226429989572142317956865311922405
0.16891597349910956511647490370581839872844691351
0.23675531078855931687136699131310225298500760689
0.29716775067313854677972696224702134190445810155
0.35173371124919582602490930092995106517146421552
0.40156363678707259466266645379468368662300271601
0.44747025926965500617391369569828820651642372589
0.49006785880157985805409310369058536690518633813
0.52983296563343441213336643954546304857788132270
0.56714329040978387299996866221035554975381578719
0.60230368332423955208141907724781646834018621903
0.63556401636486979588897480666234039281174569563
0.66713184636145511027696303054764416118395622349
0.69718159736485477728463015090916650398040286448
0.72586135776622625704868939927630687970616284950
0.75329800360236163905533048094198675280489216776
0.77960112253110087767947544014073352010915631650
0.80486606240915653539311916942960487067684752791
0.82917633026584003370043580096721870716384212825
0.85260550201372549134647241469531746689845330015 /);

# mpu 'say Math::Prime::Util::GMP::lambertw(-$_/100,60) for 1..36;'
my @lambertw_neg = (qw/
-.010101527198538753272920187671386239736709039934752358772907
-.020412444055807667259736053907495480041586124956473882211299
-.030942794982848179397910380656115249172758969601628633107179
-.041703408436484473898727338125539767862560100379397457601264
-.052705983551546347959956506179157212894276743965923951598612
-.063963189356172510195294981801688674563926410493711618670952
-.075488778865792205919339159557966811535249322283339165083946
-.087297720861579924040919758660273139926487733500100982854449
-.099406352804544814743535671867866210578206253549365520218783
-.111832559158962964833569456820265842272645362291265863329690
-.124595980455726657756666719621079053135793152710793891521622
-.137718259795895797448508164728412292161457597778234624620631
-.151223335286407083128449581782332753827082968266648724409332
-.165137789266952660984667476981335345353363106097517166766420
-.179491268347984733616995619377229799755123368660617667934835
-.194316992550129530626780651886669951304286727951478697660929
-.209652377677375752685411045492259182117234133891279509923664
-.225539803158920852052247756445805821494725010063047182583317
-.242027569001518737785833894572663806870009909839476525157284
-.259171101819073745056651950215406705713588339700893703221839
-.277034493696194227740540864940868823319654245584378425221794
-.295692493013839673188241480334100976626740236332783148583977
-.315233120146138643576596973887403298103005446463709766170537
-.335761164788902751728680758230526223662054745950766593456372
-.357402956181388903068811104055904753316590555076012043627620
-.380313020330171115830396535587815630136987739456240325380691
-.404683621605071865364325005647866585793186609324244936619702
-.430758874527112757916530656841372138819645982270515538512158
-.458856413481802088194570741325926714770279841019865124786075
-.489402227180214969036231251996293368923410006016359034511466
-.522989949627320353102183624081467090128630010624958933652258
-.560489483078455574363484050411654565701879066488752753655891
-.603266649755133050529005017751062680519867283347993925372013
-.653694501269089483159799753113833884316246499410359482443376
-.716638816456073850588169800003865040611057570138505526161434
-.806084315970817778285521361620992001997459968346671301630487 /);

plan tests => 1
            + 1
            + 2
            + 1 + 9 + 1
            + 0;

# Zero
like(lambertw(0),qr/^(0|0\.0*|\.0+)$/,"LambertW(0) = 0");

# Small near 0
is_deeply( [map { lambertw($_/10,47) } 1 .. 20],
           [ map { my $v=$_; $v =~ s/^0\./\./; $v; } @lambertw_pos ],
           "LambertW(0.1, 0.2, ..., 2.0) with 47 digits" );

# Large
is(lambertw(567.88,200),
   '4.7779074500898520857566786498941386921081437132046838176277373693328027204872327756806561733378322233740589247715164285350377396936983330158336745859018884955805599964831794364022417460679608626400255',
   "LambertW(567.88,200)");
is(lambertw(1e6,200),
   '11.383358086140052622000156781585004289033774706018865121432386106268986107680188677977093154937176497608379627334858730713524631040595012365827453723027024771329429880161761665512493723379590114648319',
   "LambertW(1e6,200)");

# Negative
is_deeply( [map { lambertw(-$_/100,60) } 1 .. 36],
           \@lambertw_neg,
           "LambertW(-0.01, -0.02, ..., -0.36) with 60 digits" );

is(lambertw(-0.367,60),"-.932399184747928483716466190879357208467147999295610926409585", "LambertW(-1/e 3 dig)");
is(lambertw(-0.3678,60),"-.979360714957828477476184443488648168605594922954737936799275", "LambertW(-1/e 4 dig)");
is(lambertw(-0.36787,60),"-.992852729821537244347936437425679636289281963248559781988806", "LambertW(-1/e 5 dig)");
is(lambertw(-0.367879,60), "-.998452103780727259318294980306402273168568357748510198614929",, "LambertW(-1/e 6 dig)");
is(lambertw(-0.3678794,60), "-.999526966607568126260639553879986677897888242792523379259623", "LambertW(-1/e 7 dig)");
is(lambertw(-0.36787944,60), "-.999920198484083397218223112707340646977607183717479410260892", "LambertW(-1/e 8 dig)");
is(lambertw(-0.367879441,60), "-.999969470700548827401043484208206713552686883880847602595116", "LambertW(-1/e 9 dig)");
is(lambertw(-0.3678794411,60), "-.999980292244517017881635617805970344624605830260329876659669", "LambertW(-1/e 10 dig)");
is(lambertw(-0.36787944117,60), "-.999997199775271588621133996800710268311896978469564842091958", "LambertW(-1/e 11 dig)");

is(lambertw("-0.3678794411714423215955237701614608674458111310317678345078368016974614957",100), "-.9999999999999999999999999999999999995059345801068083846704911383511891531411739090792786439206362436", "LambertW(-1/e 73 dig)");