test_basic.py 195 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868
  1. # this program corresponds to special.py
  2. ### Means test is not done yet
  3. # E Means test is giving error (E)
  4. # F Means test is failing (F)
  5. # EF Means test is giving error and Failing
  6. #! Means test is segfaulting
  7. # 8 Means test runs forever
  8. ### test_besselpoly
  9. ### test_modfresnelp
  10. ### test_modfresnelm
  11. # test_pbdv_seq
  12. ### test_pbvv_seq
  13. ### test_sph_harm
  14. import functools
  15. import itertools
  16. import operator
  17. import platform
  18. import sys
  19. import warnings
  20. import numpy as np
  21. from numpy import (array, isnan, r_, arange, finfo, pi, sin, cos, tan, exp,
  22. log, zeros, sqrt, asarray, inf, nan_to_num, real, arctan, double,
  23. array_equal)
  24. import pytest
  25. from pytest import raises as assert_raises
  26. from numpy.testing import (assert_equal, assert_array_equal, assert_,
  27. assert_allclose, assert_array_almost_equal_nulp)
  28. from scipy import special
  29. import scipy.special._ufuncs as cephes
  30. from scipy.special import ellipe, ellipk, ellipkm1
  31. from scipy.special import elliprc, elliprd, elliprf, elliprg, elliprj
  32. from scipy.special import softplus
  33. from scipy.special import mathieu_odd_coef, mathieu_even_coef, stirling2
  34. from scipy._lib._util import np_long, np_ulong
  35. from scipy._lib._array_api import xp_assert_close, xp_assert_equal, SCIPY_ARRAY_API
  36. from scipy.special._basic import (
  37. _FACTORIALK_LIMITS_64BITS, _FACTORIALK_LIMITS_32BITS, _is_subdtype
  38. )
  39. from scipy.special._testutils import with_special_errors, \
  40. assert_func_equal, FuncData
  41. from scipy.integrate import quad
  42. import math
  43. native_int = np.int32 if (
  44. sys.platform == 'win32'
  45. or platform.architecture()[0] == "32bit"
  46. ) else np.int64
  47. class TestCephes:
  48. def test_airy(self):
  49. cephes.airy(0)
  50. def test_airye(self):
  51. cephes.airye(0)
  52. def test_binom(self):
  53. n = np.array([0.264, 4, 5.2, 17])
  54. k = np.array([2, 0.4, 7, 3.3])
  55. nk = np.array(np.broadcast_arrays(n[:,None], k[None,:])
  56. ).reshape(2, -1).T
  57. rknown = np.array([[-0.097152, 0.9263051596159367, 0.01858423645695389,
  58. -0.007581020651518199],[6, 2.0214389119675666, 0, 2.9827344527963846],
  59. [10.92, 2.22993515861399, -0.00585728, 10.468891352063146],
  60. [136, 3.5252179590758828, 19448, 1024.5526916174495]])
  61. assert_func_equal(cephes.binom, rknown.ravel(), nk, rtol=1e-13)
  62. # Test branches in implementation
  63. rng = np.random.RandomState(1234)
  64. n = np.r_[np.arange(-7, 30), 1000*rng.rand(30) - 500]
  65. k = np.arange(0, 102)
  66. nk = np.array(np.broadcast_arrays(n[:,None], k[None,:])
  67. ).reshape(2, -1).T
  68. assert_func_equal(cephes.binom,
  69. cephes.binom(nk[:,0], nk[:,1] * (1 + 1e-15)),
  70. nk,
  71. atol=1e-10, rtol=1e-10)
  72. def test_binom_2(self):
  73. # Test branches in implementation
  74. np.random.seed(1234)
  75. n = np.r_[np.logspace(1, 300, 20)]
  76. k = np.arange(0, 102)
  77. nk = np.array(np.broadcast_arrays(n[:,None], k[None,:])
  78. ).reshape(2, -1).T
  79. assert_func_equal(cephes.binom,
  80. cephes.binom(nk[:,0], nk[:,1] * (1 + 1e-15)),
  81. nk,
  82. atol=1e-10, rtol=1e-10)
  83. def test_binom_exact(self):
  84. @np.vectorize
  85. def binom_int(n, k):
  86. n = int(n)
  87. k = int(k)
  88. num = 1
  89. den = 1
  90. for i in range(1, k+1):
  91. num *= i + n - k
  92. den *= i
  93. return float(num/den)
  94. np.random.seed(1234)
  95. n = np.arange(1, 15)
  96. k = np.arange(0, 15)
  97. nk = np.array(np.broadcast_arrays(n[:,None], k[None,:])
  98. ).reshape(2, -1).T
  99. nk = nk[nk[:,0] >= nk[:,1]]
  100. assert_func_equal(cephes.binom,
  101. binom_int(nk[:,0], nk[:,1]),
  102. nk,
  103. atol=0, rtol=0)
  104. def test_binom_nooverflow_8346(self):
  105. # Test (binom(n, k) doesn't overflow prematurely */
  106. dataset = [
  107. (1000, 500, 2.70288240945436551e+299),
  108. (1002, 501, 1.08007396880791225e+300),
  109. (1004, 502, 4.31599279169058121e+300),
  110. (1006, 503, 1.72468101616263781e+301),
  111. (1008, 504, 6.89188009236419153e+301),
  112. (1010, 505, 2.75402257948335448e+302),
  113. (1012, 506, 1.10052048531923757e+303),
  114. (1014, 507, 4.39774063758732849e+303),
  115. (1016, 508, 1.75736486108312519e+304),
  116. (1018, 509, 7.02255427788423734e+304),
  117. (1020, 510, 2.80626776829962255e+305),
  118. (1022, 511, 1.12140876377061240e+306),
  119. (1024, 512, 4.48125455209897109e+306),
  120. (1026, 513, 1.79075474304149900e+307),
  121. (1028, 514, 7.15605105487789676e+307)
  122. ]
  123. dataset = np.asarray(dataset)
  124. FuncData(cephes.binom, dataset, (0, 1), 2, rtol=1e-12).check()
  125. def test_bdtr(self):
  126. assert_equal(cephes.bdtr(1,1,0.5),1.0)
  127. def test_bdtri(self):
  128. assert_equal(cephes.bdtri(1,3,0.5),0.5)
  129. def test_bdtrc(self):
  130. assert_equal(cephes.bdtrc(1,3,0.5),0.5)
  131. def test_bdtrin(self):
  132. assert_equal(cephes.bdtrin(1,0,1),5.0)
  133. def test_bdtrik(self):
  134. cephes.bdtrik(1,3,0.5)
  135. def test_bei(self):
  136. assert_equal(cephes.bei(0),0.0)
  137. def test_beip(self):
  138. assert_equal(cephes.beip(0),0.0)
  139. def test_ber(self):
  140. assert_equal(cephes.ber(0),1.0)
  141. def test_berp(self):
  142. assert_equal(cephes.berp(0),0.0)
  143. def test_besselpoly(self):
  144. assert_equal(cephes.besselpoly(0,0,0),1.0)
  145. def test_cbrt(self):
  146. assert_allclose(cephes.cbrt(1), 1.0, atol=1e-6, rtol=0)
  147. def test_chdtr(self):
  148. assert_equal(cephes.chdtr(1,0),0.0)
  149. def test_chdtrc(self):
  150. assert_equal(cephes.chdtrc(1,0),1.0)
  151. def test_chdtri(self):
  152. assert_equal(cephes.chdtri(1,1),0.0)
  153. def test_chndtrix(self):
  154. assert_equal(cephes.chndtrix(0,1,0),0.0)
  155. def test_cosdg(self):
  156. assert_equal(cephes.cosdg(0),1.0)
  157. def test_cosm1(self):
  158. assert_equal(cephes.cosm1(0),0.0)
  159. def test_cotdg(self):
  160. assert_allclose(cephes.cotdg(45), 1.0, atol=1.5e-7, rtol=0)
  161. def test_dawsn(self):
  162. assert_equal(cephes.dawsn(0),0.0)
  163. assert_allclose(cephes.dawsn(1.23), 0.50053727749081767)
  164. def test_diric(self):
  165. # Test behavior near multiples of 2pi. Regression test for issue
  166. # described in gh-4001.
  167. n_odd = [1, 5, 25]
  168. x = np.array(2*np.pi + 5e-5).astype(np.float32)
  169. assert_allclose(special.diric(x, n_odd), 1.0, atol=1.5e-7, rtol=0)
  170. x = np.array(2*np.pi + 1e-9).astype(np.float64)
  171. assert_allclose(special.diric(x, n_odd), 1.0, atol=1.5e-15, rtol=0)
  172. x = np.array(2*np.pi + 1e-15).astype(np.float64)
  173. assert_allclose(special.diric(x, n_odd), 1.0, atol=1.5e-15, rtol=0)
  174. if hasattr(np, 'float128'):
  175. # No float128 available in 32-bit numpy
  176. x = np.array(2*np.pi + 1e-12).astype(np.float128)
  177. assert_allclose(special.diric(x, n_odd), 1.0, atol=1.5e-19, rtol=0)
  178. n_even = [2, 4, 24]
  179. x = np.array(2*np.pi + 1e-9).astype(np.float64)
  180. assert_allclose(special.diric(x, n_even), -1.0, atol=1.5e-15, rtol=0)
  181. # Test at some values not near a multiple of pi
  182. x = np.arange(0.2*np.pi, 1.0*np.pi, 0.2*np.pi)
  183. octave_result = [0.872677996249965, 0.539344662916632,
  184. 0.127322003750035, -0.206011329583298]
  185. assert_allclose(special.diric(x, 3), octave_result, atol=1.5e-15, rtol=0)
  186. def test_diric_broadcasting(self):
  187. x = np.arange(5)
  188. n = np.array([1, 3, 7])
  189. assert_(special.diric(x[:, np.newaxis], n).shape == (x.size, n.size))
  190. def test_ellipe(self):
  191. assert_equal(cephes.ellipe(1),1.0)
  192. def test_ellipeinc(self):
  193. assert_equal(cephes.ellipeinc(0,1),0.0)
  194. def test_ellipj(self):
  195. cephes.ellipj(0,1)
  196. def test_ellipk(self):
  197. assert_allclose(ellipk(0), pi/2)
  198. def test_ellipkinc(self):
  199. assert_equal(cephes.ellipkinc(0,0),0.0)
  200. def test_erf(self):
  201. assert_equal(cephes.erf(0), 0.0)
  202. def test_erf_symmetry(self):
  203. x = 5.905732037710919
  204. assert_equal(cephes.erf(x) + cephes.erf(-x), 0.0)
  205. def test_erfc(self):
  206. assert_equal(cephes.erfc(0), 1.0)
  207. def test_exp10(self):
  208. assert_allclose(cephes.exp10(2), 100.0, atol=1e-6, rtol=0)
  209. def test_exp2(self):
  210. assert_equal(cephes.exp2(2),4.0)
  211. def test_expm1(self):
  212. assert_equal(cephes.expm1(0),0.0)
  213. assert_equal(cephes.expm1(np.inf), np.inf)
  214. assert_equal(cephes.expm1(-np.inf), -1)
  215. assert_equal(cephes.expm1(np.nan), np.nan)
  216. def test_expm1_complex(self):
  217. expm1 = cephes.expm1
  218. assert_equal(expm1(0 + 0j), 0 + 0j)
  219. assert_equal(expm1(complex(np.inf, 0)), complex(np.inf, 0))
  220. assert_equal(expm1(complex(np.inf, 1)), complex(np.inf, np.inf))
  221. assert_equal(expm1(complex(np.inf, 2)), complex(-np.inf, np.inf))
  222. assert_equal(expm1(complex(np.inf, 4)), complex(-np.inf, -np.inf))
  223. assert_equal(expm1(complex(np.inf, 5)), complex(np.inf, -np.inf))
  224. assert_equal(expm1(complex(1, np.inf)), complex(np.nan, np.nan))
  225. assert_equal(expm1(complex(0, np.inf)), complex(np.nan, np.nan))
  226. assert_equal(expm1(complex(np.inf, np.inf)), complex(np.inf, np.nan))
  227. assert_equal(expm1(complex(-np.inf, np.inf)), complex(-1, 0))
  228. assert_equal(expm1(complex(-np.inf, np.nan)), complex(-1, 0))
  229. assert_equal(expm1(complex(np.inf, np.nan)), complex(np.inf, np.nan))
  230. assert_equal(expm1(complex(0, np.nan)), complex(np.nan, np.nan))
  231. assert_equal(expm1(complex(1, np.nan)), complex(np.nan, np.nan))
  232. assert_equal(expm1(complex(np.nan, 1)), complex(np.nan, np.nan))
  233. assert_equal(expm1(complex(np.nan, np.nan)), complex(np.nan, np.nan))
  234. @pytest.mark.xfail(reason='The real part of expm1(z) bad at these points')
  235. def test_expm1_complex_hard(self):
  236. # The real part of this function is difficult to evaluate when
  237. # z.real = -log(cos(z.imag)).
  238. y = np.array([0.1, 0.2, 0.3, 5, 11, 20])
  239. x = -np.log(np.cos(y))
  240. z = x + 1j*y
  241. # evaluate using mpmath.expm1 with dps=1000
  242. expected = np.array([-5.5507901846769623e-17+0.10033467208545054j,
  243. 2.4289354732893695e-18+0.20271003550867248j,
  244. 4.5235500262585768e-17+0.30933624960962319j,
  245. 7.8234305217489006e-17-3.3805150062465863j,
  246. -1.3685191953697676e-16-225.95084645419513j,
  247. 8.7175620481291045e-17+2.2371609442247422j])
  248. found = cephes.expm1(z)
  249. # this passes.
  250. assert_array_almost_equal_nulp(found.imag, expected.imag, 3)
  251. # this fails.
  252. assert_array_almost_equal_nulp(found.real, expected.real, 20)
  253. def test_fdtr(self):
  254. assert_equal(cephes.fdtr(1, 1, 0), 0.0)
  255. # Computed using Wolfram Alpha: CDF[FRatioDistribution[1e-6, 5], 10]
  256. assert_allclose(cephes.fdtr(1e-6, 5, 10), 0.9999940790193488,
  257. rtol=1e-12)
  258. def test_fdtrc(self):
  259. assert_equal(cephes.fdtrc(1, 1, 0), 1.0)
  260. # Computed using Wolfram Alpha:
  261. # 1 - CDF[FRatioDistribution[2, 1/10], 1e10]
  262. assert_allclose(cephes.fdtrc(2, 0.1, 1e10), 0.27223784621293512,
  263. rtol=1e-12)
  264. def test_fdtri(self):
  265. assert_allclose(cephes.fdtri(1, 1, [0.499, 0.501]),
  266. array([0.9937365, 1.00630298]), rtol=1e-6)
  267. # From Wolfram Alpha:
  268. # CDF[FRatioDistribution[1/10, 1], 3] = 0.8756751669632105666874...
  269. p = 0.8756751669632105666874
  270. assert_allclose(cephes.fdtri(0.1, 1, p), 3, rtol=1e-12)
  271. def test_gh20835(self):
  272. # gh-20835 reported fdtri failing for extreme inputs
  273. dfd, dfn, x = 1, 50000, 29.72591544307521
  274. assert_allclose(cephes.fdtri(dfd, dfn, cephes.fdtr(dfd, dfn, x)), x, rtol=1e-15)
  275. def test_fdtri_mysterious_failure(self):
  276. assert_allclose(cephes.fdtri(1, 1, 0.5), 1)
  277. def test_fdtridfd(self):
  278. assert_equal(cephes.fdtridfd(1,0,0),5.0)
  279. def test_fresnel(self):
  280. assert_equal(cephes.fresnel(0),(0.0,0.0))
  281. def test_gamma(self):
  282. assert_equal(cephes.gamma(5),24.0)
  283. def test_gammainccinv(self):
  284. assert_equal(cephes.gammainccinv(5,1),0.0)
  285. def test_gammaln(self):
  286. cephes.gammaln(10)
  287. def test_gammasgn(self):
  288. vals = np.array(
  289. [-np.inf, -4, -3.5, -2.3, -0.0, 0.0, 1, 4.2, np.inf], np.float64
  290. )
  291. reference = np.array(
  292. [np.nan, np.nan, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0], np.float64
  293. )
  294. assert_array_equal(cephes.gammasgn(vals), reference)
  295. def test_gdtr(self):
  296. assert_equal(cephes.gdtr(1,1,0),0.0)
  297. def test_gdtr_inf(self):
  298. assert_equal(cephes.gdtr(1,1,np.inf),1.0)
  299. def test_gdtrc(self):
  300. assert_equal(cephes.gdtrc(1,1,0),1.0)
  301. def test_gdtria(self):
  302. assert_equal(cephes.gdtria(0,1,1),0.0)
  303. def test_gdtrib(self):
  304. cephes.gdtrib(1,0,1)
  305. # assert_equal(cephes.gdtrib(1,0,1),5.0)
  306. def test_gdtrix(self):
  307. cephes.gdtrix(1,1,.1)
  308. def test_hankel1(self):
  309. cephes.hankel1(1,1)
  310. def test_hankel1e(self):
  311. cephes.hankel1e(1,1)
  312. def test_hankel2(self):
  313. cephes.hankel2(1,1)
  314. def test_hankel2e(self):
  315. cephes.hankel2e(1,1)
  316. def test_hyp1f1(self):
  317. assert_allclose(cephes.hyp1f1(1, 1, 1), exp(1.0), atol=1e-6, rtol=0)
  318. assert_allclose(cephes.hyp1f1(3, 4, -6), 0.026056422099537251095,
  319. atol=1e-6, rtol=0)
  320. cephes.hyp1f1(1,1,1)
  321. def test_hyp2f1(self):
  322. assert_equal(cephes.hyp2f1(1,1,1,0),1.0)
  323. def test_i0(self):
  324. assert_equal(cephes.i0(0),1.0)
  325. def test_i0e(self):
  326. assert_equal(cephes.i0e(0),1.0)
  327. def test_i1(self):
  328. assert_equal(cephes.i1(0),0.0)
  329. def test_i1e(self):
  330. assert_equal(cephes.i1e(0),0.0)
  331. def test_it2i0k0(self):
  332. cephes.it2i0k0(1)
  333. def test_it2j0y0(self):
  334. cephes.it2j0y0(1)
  335. def test_it2struve0(self):
  336. cephes.it2struve0(1)
  337. def test_itairy(self):
  338. cephes.itairy(1)
  339. def test_iti0k0(self):
  340. assert_equal(cephes.iti0k0(0),(0.0,0.0))
  341. def test_itj0y0(self):
  342. assert_equal(cephes.itj0y0(0),(0.0,0.0))
  343. def test_itmodstruve0(self):
  344. assert_equal(cephes.itmodstruve0(0),0.0)
  345. def test_itstruve0(self):
  346. assert_equal(cephes.itstruve0(0),0.0)
  347. def test_iv(self):
  348. assert_equal(cephes.iv(1,0),0.0)
  349. def test_ive(self):
  350. assert_equal(cephes.ive(1,0),0.0)
  351. def test_j0(self):
  352. assert_equal(cephes.j0(0),1.0)
  353. def test_j1(self):
  354. assert_equal(cephes.j1(0),0.0)
  355. def test_jn(self):
  356. assert_equal(cephes.jn(0,0),1.0)
  357. def test_jv(self):
  358. assert_equal(cephes.jv(0,0),1.0)
  359. def test_jve(self):
  360. assert_equal(cephes.jve(0,0),1.0)
  361. def test_k0(self):
  362. cephes.k0(2)
  363. def test_k0e(self):
  364. cephes.k0e(2)
  365. def test_k1(self):
  366. cephes.k1(2)
  367. def test_k1e(self):
  368. cephes.k1e(2)
  369. def test_kei(self):
  370. cephes.kei(2)
  371. def test_keip(self):
  372. assert_equal(cephes.keip(0),0.0)
  373. def test_ker(self):
  374. cephes.ker(2)
  375. def test_kerp(self):
  376. cephes.kerp(2)
  377. def test_kelvin(self):
  378. cephes.kelvin(2)
  379. def test_kn(self):
  380. cephes.kn(1,1)
  381. def test_kolmogi(self):
  382. assert_equal(cephes.kolmogi(1),0.0)
  383. assert_(np.isnan(cephes.kolmogi(np.nan)))
  384. def test_kolmogorov(self):
  385. assert_equal(cephes.kolmogorov(0), 1.0)
  386. def test_kolmogp(self):
  387. assert_equal(cephes._kolmogp(0), -0.0)
  388. def test_kolmogc(self):
  389. assert_equal(cephes._kolmogc(0), 0.0)
  390. def test_kolmogci(self):
  391. assert_equal(cephes._kolmogci(0), 0.0)
  392. assert_(np.isnan(cephes._kolmogci(np.nan)))
  393. def test_kv(self):
  394. cephes.kv(1,1)
  395. def test_kve(self):
  396. cephes.kve(1,1)
  397. def test_log1p(self):
  398. log1p = cephes.log1p
  399. assert_equal(log1p(0), 0.0)
  400. assert_equal(log1p(-1), -np.inf)
  401. assert_equal(log1p(-2), np.nan)
  402. assert_equal(log1p(np.inf), np.inf)
  403. def test_log1p_complex(self):
  404. log1p = cephes.log1p
  405. c = complex
  406. assert_equal(log1p(0 + 0j), 0 + 0j)
  407. assert_equal(log1p(c(-1, 0)), c(-np.inf, 0))
  408. with warnings.catch_warnings():
  409. warnings.filterwarnings(
  410. "ignore", "invalid value encountered in multiply", RuntimeWarning)
  411. assert_allclose(log1p(c(1, np.inf)), c(np.inf, np.pi/2))
  412. assert_equal(log1p(c(1, np.nan)), c(np.nan, np.nan))
  413. assert_allclose(log1p(c(-np.inf, 1)), c(np.inf, np.pi))
  414. assert_equal(log1p(c(np.inf, 1)), c(np.inf, 0))
  415. assert_allclose(log1p(c(-np.inf, np.inf)), c(np.inf, 3*np.pi/4))
  416. assert_allclose(log1p(c(np.inf, np.inf)), c(np.inf, np.pi/4))
  417. assert_equal(log1p(c(np.inf, np.nan)), c(np.inf, np.nan))
  418. assert_equal(log1p(c(-np.inf, np.nan)), c(np.inf, np.nan))
  419. assert_equal(log1p(c(np.nan, np.inf)), c(np.inf, np.nan))
  420. assert_equal(log1p(c(np.nan, 1)), c(np.nan, np.nan))
  421. assert_equal(log1p(c(np.nan, np.nan)), c(np.nan, np.nan))
  422. def test_lpmv(self):
  423. assert_equal(cephes.lpmv(0,0,1),1.0)
  424. def test_mathieu_a_q0(self):
  425. # When q is 0, the exact result is m**2.
  426. m = np.array([1, 2, 5])
  427. assert_equal(cephes.mathieu_a(m, 0), m**2)
  428. # Reference values were computed with Wolfram Alpha:
  429. # MathieuCharacteristicA[m, q]
  430. @pytest.mark.parametrize(
  431. 'm, q, ref',
  432. [(0, 8, -10.6067292355526479852024),
  433. (3, 3/2, 9.19330104768060974047804),
  434. (5, 1/4, 25.0013021454698022809572),
  435. (8, -10, 64.8008910105046444848962)]
  436. )
  437. def test_mathieu_a(self, m, q, ref):
  438. y = cephes.mathieu_a(m, q)
  439. assert_allclose(y, ref, rtol=1e-15)
  440. def test_mathieu_b_q0(self):
  441. # When q is 0, the exact result is m**2.
  442. m = np.array([1, 2, 5])
  443. assert_equal(cephes.mathieu_b(m, 0), m**2)
  444. # Reference values were computed with Wolfram Alpha:
  445. # MathieuCharacteristicB[m, q]
  446. @pytest.mark.parametrize(
  447. 'm, q, ref',
  448. [(1, 15, -22.5130034974234666335),
  449. (5, 3, 25.1870798027185125480),
  450. (9, 1/4, 81.00039062627570760760),
  451. (10, -3, 100.0454683359769326164)]
  452. )
  453. def test_mathieu_b(self, m, q, ref):
  454. y = cephes.mathieu_b(m, q)
  455. assert_allclose(y, ref, rtol=1e-15)
  456. def test_mathieu_cem(self):
  457. assert_equal(cephes.mathieu_cem(1,0,0),(1.0,0.0))
  458. # Test AMS 20.2.27
  459. @np.vectorize
  460. def ce_smallq(m, q, z):
  461. z *= np.pi/180
  462. if m == 0:
  463. # + O(q^2)
  464. return 2**(-0.5) * (1 - .5*q*cos(2*z))
  465. elif m == 1:
  466. # + O(q^2)
  467. return cos(z) - q/8 * cos(3*z)
  468. elif m == 2:
  469. # + O(q^2)
  470. return cos(2*z) - q*(cos(4*z)/12 - 1/4)
  471. else:
  472. # + O(q^2)
  473. return cos(m*z) - q*(cos((m+2)*z)/(4*(m+1)) - cos((m-2)*z)/(4*(m-1)))
  474. m = np.arange(0, 100)
  475. q = np.r_[0, np.logspace(-30, -9, 10)]
  476. assert_allclose(cephes.mathieu_cem(m[:,None], q[None,:], 0.123)[0],
  477. ce_smallq(m[:,None], q[None,:], 0.123),
  478. rtol=1e-14, atol=0)
  479. def test_mathieu_sem(self):
  480. assert_equal(cephes.mathieu_sem(1,0,0),(0.0,1.0))
  481. # Test AMS 20.2.27
  482. @np.vectorize
  483. def se_smallq(m, q, z):
  484. z *= np.pi/180
  485. if m == 1:
  486. # + O(q^2)
  487. return sin(z) - q/8 * sin(3*z)
  488. elif m == 2:
  489. # + O(q^2)
  490. return sin(2*z) - q*sin(4*z)/12
  491. else:
  492. # + O(q^2)
  493. return sin(m*z) - q*(sin((m+2)*z)/(4*(m+1)) - sin((m-2)*z)/(4*(m-1)))
  494. m = np.arange(1, 100)
  495. q = np.r_[0, np.logspace(-30, -9, 10)]
  496. assert_allclose(cephes.mathieu_sem(m[:,None], q[None,:], 0.123)[0],
  497. se_smallq(m[:,None], q[None,:], 0.123),
  498. rtol=1e-14, atol=0)
  499. def test_mathieu_modcem1(self):
  500. assert_equal(cephes.mathieu_modcem1(1,0,0),(0.0,0.0))
  501. def test_mathieu_modcem2(self):
  502. cephes.mathieu_modcem2(1,1,1)
  503. # Test reflection relation AMS 20.6.19
  504. m = np.arange(0, 4)[:,None,None]
  505. q = np.r_[np.logspace(-2, 2, 10)][None,:,None]
  506. z = np.linspace(0, 1, 7)[None,None,:]
  507. y1 = cephes.mathieu_modcem2(m, q, -z)[0]
  508. fr = -cephes.mathieu_modcem2(m, q, 0)[0] / cephes.mathieu_modcem1(m, q, 0)[0]
  509. y2 = (-cephes.mathieu_modcem2(m, q, z)[0]
  510. - 2*fr*cephes.mathieu_modcem1(m, q, z)[0])
  511. assert_allclose(y1, y2, rtol=1e-10)
  512. def test_mathieu_modsem1(self):
  513. assert_equal(cephes.mathieu_modsem1(1,0,0),(0.0,0.0))
  514. def test_mathieu_modsem2(self):
  515. cephes.mathieu_modsem2(1,1,1)
  516. # Test reflection relation AMS 20.6.20
  517. m = np.arange(1, 4)[:,None,None]
  518. q = np.r_[np.logspace(-2, 2, 10)][None,:,None]
  519. z = np.linspace(0, 1, 7)[None,None,:]
  520. y1 = cephes.mathieu_modsem2(m, q, -z)[0]
  521. fr = cephes.mathieu_modsem2(m, q, 0)[1] / cephes.mathieu_modsem1(m, q, 0)[1]
  522. y2 = (cephes.mathieu_modsem2(m, q, z)[0]
  523. - 2*fr*cephes.mathieu_modsem1(m, q, z)[0])
  524. assert_allclose(y1, y2, rtol=1e-10)
  525. def test_mathieu_overflow(self):
  526. # Check that these return NaNs instead of causing a SEGV
  527. assert_equal(cephes.mathieu_cem(10000, 0, 1.3), (np.nan, np.nan))
  528. assert_equal(cephes.mathieu_sem(10000, 0, 1.3), (np.nan, np.nan))
  529. assert_equal(cephes.mathieu_cem(10000, 1.5, 1.3), (np.nan, np.nan))
  530. assert_equal(cephes.mathieu_sem(10000, 1.5, 1.3), (np.nan, np.nan))
  531. assert_equal(cephes.mathieu_modcem1(10000, 1.5, 1.3), (np.nan, np.nan))
  532. assert_equal(cephes.mathieu_modsem1(10000, 1.5, 1.3), (np.nan, np.nan))
  533. assert_equal(cephes.mathieu_modcem2(10000, 1.5, 1.3), (np.nan, np.nan))
  534. assert_equal(cephes.mathieu_modsem2(10000, 1.5, 1.3), (np.nan, np.nan))
  535. def test_mathieu_ticket_1847(self):
  536. # Regression test --- this call had some out-of-bounds access
  537. # and could return nan occasionally
  538. for k in range(60):
  539. v = cephes.mathieu_modsem2(2, 100, -1)
  540. # Values from ACM TOMS 804 (derivate by numerical differentiation)
  541. assert_allclose(v[0], 0.1431742913063671074347, rtol=1e-10)
  542. assert_allclose(v[1], 0.9017807375832909144719, rtol=1e-4)
  543. def test_modfresnelm(self):
  544. cephes.modfresnelm(0)
  545. def test_modfresnelp(self):
  546. cephes.modfresnelp(0)
  547. def test_modstruve(self):
  548. assert_equal(cephes.modstruve(1,0),0.0)
  549. def test_nbdtr(self):
  550. assert_equal(cephes.nbdtr(1,1,1),1.0)
  551. def test_nbdtrc(self):
  552. assert_equal(cephes.nbdtrc(1,1,1),0.0)
  553. def test_nbdtri(self):
  554. assert_equal(cephes.nbdtri(1,1,1),1.0)
  555. def test_nbdtrik(self):
  556. cephes.nbdtrik(1,.4,.5)
  557. def test_nbdtrin(self):
  558. assert_equal(cephes.nbdtrin(1,0,0),5.0)
  559. def test_ncfdtr(self):
  560. assert_equal(cephes.ncfdtr(1,1,1,0),0.0)
  561. def test_ncfdtri(self):
  562. assert_equal(cephes.ncfdtri(1, 1, 1, 0), 0.0)
  563. f = [0.5, 1, 1.5]
  564. p = cephes.ncfdtr(2, 3, 1.5, f)
  565. assert_allclose(cephes.ncfdtri(2, 3, 1.5, p), f)
  566. @pytest.mark.xfail(
  567. reason=(
  568. "ncfdtr uses a Boost math implementation but ncfdtridfd"
  569. "inverts the less accurate cdflib implementation of ncfdtr."
  570. )
  571. )
  572. def test_ncfdtridfd(self):
  573. dfd = [1, 2, 3]
  574. p = cephes.ncfdtr(2, dfd, 0.25, 15)
  575. assert_allclose(cephes.ncfdtridfd(2, p, 0.25, 15), dfd)
  576. @pytest.mark.xfail(
  577. reason=(
  578. "ncfdtr uses a Boost math implementation but ncfdtridfn"
  579. "inverts the less accurate cdflib implementation of ncfdtr."
  580. )
  581. )
  582. def test_ncfdtridfn(self):
  583. dfn = [0.1, 1, 2, 3, 1e4]
  584. p = cephes.ncfdtr(dfn, 2, 0.25, 15)
  585. assert_allclose(cephes.ncfdtridfn(p, 2, 0.25, 15), dfn, rtol=1e-5)
  586. @pytest.mark.xfail(
  587. reason=(
  588. "ncfdtr uses a Boost math implementation but ncfdtrinc"
  589. "inverts the less accurate cdflib implementation of ncfdtr."
  590. )
  591. )
  592. def test_ncfdtrinc(self):
  593. nc = [0.5, 1.5, 2.0]
  594. p = cephes.ncfdtr(2, 3, nc, 15)
  595. assert_allclose(cephes.ncfdtrinc(2, 3, p, 15), nc)
  596. def test_nctdtr(self):
  597. assert_equal(cephes.nctdtr(1,0,0),0.5)
  598. assert_equal(cephes.nctdtr(9, 65536, 45), 0.0)
  599. assert_allclose(cephes.nctdtr(np.inf, 1., 1.), 0.5, atol=1e-4, rtol=0)
  600. assert_(np.isnan(cephes.nctdtr(2., np.inf, 10.)))
  601. assert_allclose(cephes.nctdtr(2., 1., np.inf), 1., atol=1e-6, rtol=0)
  602. assert_(np.isnan(cephes.nctdtr(np.nan, 1., 1.)))
  603. assert_(np.isnan(cephes.nctdtr(2., np.nan, 1.)))
  604. assert_(np.isnan(cephes.nctdtr(2., 1., np.nan)))
  605. def test_nctdtridf(self):
  606. cephes.nctdtridf(1,0.5,0)
  607. def test_nctdtrinc(self):
  608. cephes.nctdtrinc(1,0,0)
  609. def test_nctdtrit(self):
  610. cephes.nctdtrit(.1,0.2,.5)
  611. def test_nrdtrimn(self):
  612. assert_allclose(cephes.nrdtrimn(0.5, 1, 1), 1.0, atol=1e-6, rtol=0)
  613. def test_nrdtrisd(self):
  614. assert_allclose(cephes.nrdtrisd(0.5,0.5,0.5), 0.0,
  615. atol=0, rtol=0)
  616. def test_obl_ang1(self):
  617. cephes.obl_ang1(1,1,1,0)
  618. def test_obl_ang1_cv(self):
  619. result = cephes.obl_ang1_cv(1,1,1,1,0)
  620. assert_allclose(result[0], 1.0, atol=1.5e-7, rtol=0)
  621. assert_allclose(result[1], 0.0, atol=1.5e-7, rtol=0)
  622. def test_obl_cv(self):
  623. assert_equal(cephes.obl_cv(1,1,0),2.0)
  624. def test_obl_rad1(self):
  625. cephes.obl_rad1(1,1,1,0)
  626. def test_obl_rad1_cv(self):
  627. cephes.obl_rad1_cv(1,1,1,1,0)
  628. def test_obl_rad2(self):
  629. cephes.obl_rad2(1,1,1,0)
  630. def test_obl_rad2_cv(self):
  631. cephes.obl_rad2_cv(1,1,1,1,0)
  632. def test_pbdv(self):
  633. assert_equal(cephes.pbdv(1,0),(0.0,1.0))
  634. def test_pbvv(self):
  635. cephes.pbvv(1,0)
  636. def test_pbwa(self):
  637. cephes.pbwa(1,0)
  638. def test_pdtr(self):
  639. val = cephes.pdtr(0, 1)
  640. assert_allclose(val, np.exp(-1), atol=1.5e-7, rtol=0)
  641. # Edge case: m = 0.
  642. val = cephes.pdtr([0, 1, 2], 0)
  643. assert_array_equal(val, [1, 1, 1])
  644. def test_pdtrc(self):
  645. val = cephes.pdtrc(0, 1)
  646. assert_allclose(val, 1 - np.exp(-1), atol=1.5e-7, rtol=0)
  647. # Edge case: m = 0.
  648. val = cephes.pdtrc([0, 1, 2], 0.0)
  649. assert_array_equal(val, [0, 0, 0])
  650. def test_pdtri(self):
  651. with warnings.catch_warnings():
  652. msg = "floating point number truncated to an integer"
  653. warnings.filterwarnings("ignore", msg, RuntimeWarning)
  654. cephes.pdtri(0.5,0.5)
  655. def test_pro_ang1(self):
  656. cephes.pro_ang1(1,1,1,0)
  657. def test_pro_ang1_cv(self):
  658. assert_allclose(cephes.pro_ang1_cv(1, 1, 1, 1, 0), array((1.0, 0.0)),
  659. atol=1.5e-7, rtol=0)
  660. def test_pro_cv(self):
  661. assert_equal(cephes.pro_cv(1,1,0),2.0)
  662. def test_pro_rad1(self):
  663. cephes.pro_rad1(1,1,1,0.1)
  664. def test_pro_rad1_cv(self):
  665. cephes.pro_rad1_cv(1,1,1,1,0)
  666. def test_pro_rad2(self):
  667. cephes.pro_rad2(1,1,1,0)
  668. def test_pro_rad2_cv(self):
  669. cephes.pro_rad2_cv(1,1,1,1,0)
  670. def test_psi(self):
  671. cephes.psi(1)
  672. def test_radian(self):
  673. assert_equal(cephes.radian(0,0,0),0)
  674. def test_rgamma(self):
  675. assert_equal(cephes.rgamma(1),1.0)
  676. def test_round(self):
  677. assert_equal(cephes.round(3.4),3.0)
  678. assert_equal(cephes.round(-3.4),-3.0)
  679. assert_equal(cephes.round(3.6),4.0)
  680. assert_equal(cephes.round(-3.6),-4.0)
  681. assert_equal(cephes.round(3.5),4.0)
  682. assert_equal(cephes.round(-3.5),-4.0)
  683. def test_shichi(self):
  684. cephes.shichi(1)
  685. def test_sici(self):
  686. cephes.sici(1)
  687. s, c = cephes.sici(np.inf)
  688. assert_allclose(s, np.pi * 0.5, atol=1.5e-7, rtol=0)
  689. assert_allclose(c, 0, atol=1.5e-7, rtol=0)
  690. s, c = cephes.sici(-np.inf)
  691. assert_allclose(s, -np.pi * 0.5, atol=1.5e-7, rtol=0)
  692. assert_(np.isnan(c), "cosine integral(-inf) is not nan")
  693. def test_sindg(self):
  694. assert_equal(cephes.sindg(90),1.0)
  695. def test_smirnov(self):
  696. assert_equal(cephes.smirnov(1,.1),0.9)
  697. assert_(np.isnan(cephes.smirnov(1,np.nan)))
  698. def test_smirnovp(self):
  699. assert_equal(cephes._smirnovp(1, .1), -1)
  700. assert_equal(cephes._smirnovp(2, 0.75), -2*(0.25)**(2-1))
  701. assert_equal(cephes._smirnovp(3, 0.75), -3*(0.25)**(3-1))
  702. assert_(np.isnan(cephes._smirnovp(1, np.nan)))
  703. def test_smirnovc(self):
  704. assert_equal(cephes._smirnovc(1,.1),0.1)
  705. assert_(np.isnan(cephes._smirnovc(1,np.nan)))
  706. x10 = np.linspace(0, 1, 11, endpoint=True)
  707. assert_allclose(cephes._smirnovc(3, x10), 1 - cephes.smirnov(3, x10),
  708. atol=1.5e-7, rtol=0)
  709. x4 = np.linspace(0, 1, 5, endpoint=True)
  710. assert_allclose(cephes._smirnovc(4, x4), 1 - cephes.smirnov(4, x4),
  711. atol=1.5e-7, rtol=0)
  712. def test_smirnovi(self):
  713. assert_allclose(cephes.smirnov(1, cephes.smirnovi(1, 0.4)), 0.4,
  714. atol=1.5e-7, rtol=0)
  715. assert_allclose(cephes.smirnov(1, cephes.smirnovi(1, 0.6)), 0.6,
  716. atol=1.5e-7, rtol=0)
  717. assert_(np.isnan(cephes.smirnovi(1,np.nan)))
  718. def test_smirnovci(self):
  719. assert_allclose(cephes._smirnovc(1, cephes._smirnovci(1, 0.4)), 0.4,
  720. atol=1.5e-7, rtol=0)
  721. assert_allclose(cephes._smirnovc(1, cephes._smirnovci(1, 0.6)), 0.6,
  722. atol=1.5e-7, rtol=0)
  723. assert_(np.isnan(cephes._smirnovci(1,np.nan)))
  724. def test_spence(self):
  725. assert_equal(cephes.spence(1),0.0)
  726. def test_stdtr(self):
  727. assert_equal(cephes.stdtr(1,0),0.5)
  728. assert_allclose(cephes.stdtr(1, 1), 0.75, atol=1.5e-7, rtol=0)
  729. assert_allclose(cephes.stdtr(1, 2), 0.852416382349, atol=1.5e-7, rtol=0)
  730. def test_stdtridf(self):
  731. cephes.stdtridf(0.7,1)
  732. def test_stdtrit(self):
  733. cephes.stdtrit(1,0.7)
  734. def test_struve(self):
  735. assert_equal(cephes.struve(0,0),0.0)
  736. def test_tandg(self):
  737. assert_equal(cephes.tandg(45),1.0)
  738. def test_tklmbda(self):
  739. assert_allclose(cephes.tklmbda(1, 1), 1.0, atol=1.5e-7, rtol=0)
  740. def test_y0(self):
  741. cephes.y0(1)
  742. def test_y1(self):
  743. cephes.y1(1)
  744. def test_yn(self):
  745. cephes.yn(1,1)
  746. def test_yv(self):
  747. cephes.yv(1,1)
  748. def test_yve(self):
  749. cephes.yve(1,1)
  750. def test_wofz(self):
  751. z = [complex(624.2,-0.26123), complex(-0.4,3.), complex(0.6,2.),
  752. complex(-1.,1.), complex(-1.,-9.), complex(-1.,9.),
  753. complex(-0.0000000234545,1.1234), complex(-3.,5.1),
  754. complex(-53,30.1), complex(0.0,0.12345),
  755. complex(11,1), complex(-22,-2), complex(9,-28),
  756. complex(21,-33), complex(1e5,1e5), complex(1e14,1e14)
  757. ]
  758. w = [
  759. complex(-3.78270245518980507452677445620103199303131110e-7,
  760. 0.000903861276433172057331093754199933411710053155),
  761. complex(0.1764906227004816847297495349730234591778719532788,
  762. -0.02146550539468457616788719893991501311573031095617),
  763. complex(0.2410250715772692146133539023007113781272362309451,
  764. 0.06087579663428089745895459735240964093522265589350),
  765. complex(0.30474420525691259245713884106959496013413834051768,
  766. -0.20821893820283162728743734725471561394145872072738),
  767. complex(7.317131068972378096865595229600561710140617977e34,
  768. 8.321873499714402777186848353320412813066170427e34),
  769. complex(0.0615698507236323685519612934241429530190806818395,
  770. -0.00676005783716575013073036218018565206070072304635),
  771. complex(0.3960793007699874918961319170187598400134746631,
  772. -5.593152259116644920546186222529802777409274656e-9),
  773. complex(0.08217199226739447943295069917990417630675021771804,
  774. -0.04701291087643609891018366143118110965272615832184),
  775. complex(0.00457246000350281640952328010227885008541748668738,
  776. -0.00804900791411691821818731763401840373998654987934),
  777. complex(0.8746342859608052666092782112565360755791467973338452,
  778. 0.),
  779. complex(0.00468190164965444174367477874864366058339647648741,
  780. 0.0510735563901306197993676329845149741675029197050),
  781. complex(-0.0023193175200187620902125853834909543869428763219,
  782. -0.025460054739731556004902057663500272721780776336),
  783. complex(9.11463368405637174660562096516414499772662584e304,
  784. 3.97101807145263333769664875189354358563218932e305),
  785. complex(-4.4927207857715598976165541011143706155432296e281,
  786. -2.8019591213423077494444700357168707775769028e281),
  787. complex(2.820947917809305132678577516325951485807107151e-6,
  788. 2.820947917668257736791638444590253942253354058e-6),
  789. complex(2.82094791773878143474039725787438662716372268e-15,
  790. 2.82094791773878143474039725773333923127678361e-15)
  791. ]
  792. assert_func_equal(cephes.wofz, w, z, rtol=1e-13)
  793. class TestAiry:
  794. def test_airy(self):
  795. # This tests the airy function to ensure 8 place accuracy in computation
  796. x = special.airy(.99)
  797. assert_allclose(x, array([0.13689066, -0.16050153, 1.19815925, 0.92046818]),
  798. atol=1.5e-8, rtol=0)
  799. x = special.airy(.41)
  800. assert_allclose(x, array([0.25238916, -.23480512, 0.80686202, 0.51053919]),
  801. atol=1.5e-8, rtol=0)
  802. x = special.airy(-.36)
  803. assert_allclose(x, array([0.44508477,-0.23186773,0.44939534,0.48105354]),
  804. atol=1.5e-8, rtol=0)
  805. def test_airye(self):
  806. a = special.airye(0.01)
  807. b = special.airy(0.01)
  808. b1 = [None]*4
  809. for n in range(2):
  810. b1[n] = b[n]*exp(2.0/3.0*0.01*sqrt(0.01))
  811. for n in range(2,4):
  812. b1[n] = b[n]*exp(-abs(real(2.0/3.0*0.01*sqrt(0.01))))
  813. assert_allclose(a, b1, atol=1.5e-6, rtol=0)
  814. def test_bi_zeros(self):
  815. bi = special.bi_zeros(2)
  816. bia = (array([-1.17371322, -3.2710930]),
  817. array([-2.29443968, -4.07315509]),
  818. array([-0.45494438, 0.39652284]),
  819. array([0.60195789, -0.76031014]))
  820. assert_allclose(bi, bia, atol=1.5e-4, rtol=0)
  821. bi = special.bi_zeros(5)
  822. assert_allclose(bi[0], array([-1.173713222709127,
  823. -3.271093302836352,
  824. -4.830737841662016,
  825. -6.169852128310251,
  826. -7.376762079367764]),
  827. atol=1.5e-11, rtol=0)
  828. assert_allclose(bi[1], array([-2.294439682614122,
  829. -4.073155089071828,
  830. -5.512395729663599,
  831. -6.781294445990305,
  832. -7.940178689168587]),
  833. atol=1.5e-10, rtol=0)
  834. assert_allclose(bi[2], array([-0.454944383639657,
  835. 0.396522836094465,
  836. -0.367969161486959,
  837. 0.349499116831805,
  838. -0.336026240133662]),
  839. atol=1.5e-11, rtol=0)
  840. assert_allclose(bi[3], array([0.601957887976239,
  841. -0.760310141492801,
  842. 0.836991012619261,
  843. -0.88947990142654,
  844. 0.929983638568022]),
  845. atol=1.5e-10, rtol=0)
  846. def test_ai_zeros(self):
  847. ai = special.ai_zeros(1)
  848. assert_allclose(ai, (array([-2.33810741]),
  849. array([-1.01879297]),
  850. array([0.5357]),
  851. array([0.7012])),
  852. atol=1.5e-4, rtol=0)
  853. @pytest.mark.fail_slow(5)
  854. def test_ai_zeros_big(self):
  855. z, zp, ai_zpx, aip_zx = special.ai_zeros(50000)
  856. ai_z, aip_z, _, _ = special.airy(z)
  857. ai_zp, aip_zp, _, _ = special.airy(zp)
  858. ai_envelope = 1/abs(z)**(1./4)
  859. aip_envelope = abs(zp)**(1./4)
  860. # Check values
  861. assert_allclose(ai_zpx, ai_zp, rtol=1e-10)
  862. assert_allclose(aip_zx, aip_z, rtol=1e-10)
  863. # Check they are zeros
  864. assert_allclose(ai_z/ai_envelope, 0, atol=1e-10, rtol=0)
  865. assert_allclose(aip_zp/aip_envelope, 0, atol=1e-10, rtol=0)
  866. # Check first zeros, DLMF 9.9.1
  867. assert_allclose(z[:6],
  868. [-2.3381074105, -4.0879494441, -5.5205598281,
  869. -6.7867080901, -7.9441335871, -9.0226508533], rtol=1e-10)
  870. assert_allclose(zp[:6],
  871. [-1.0187929716, -3.2481975822, -4.8200992112,
  872. -6.1633073556, -7.3721772550, -8.4884867340], rtol=1e-10)
  873. @pytest.mark.fail_slow(5)
  874. def test_bi_zeros_big(self):
  875. z, zp, bi_zpx, bip_zx = special.bi_zeros(50000)
  876. _, _, bi_z, bip_z = special.airy(z)
  877. _, _, bi_zp, bip_zp = special.airy(zp)
  878. bi_envelope = 1/abs(z)**(1./4)
  879. bip_envelope = abs(zp)**(1./4)
  880. # Check values
  881. assert_allclose(bi_zpx, bi_zp, rtol=1e-10)
  882. assert_allclose(bip_zx, bip_z, rtol=1e-10)
  883. # Check they are zeros
  884. assert_allclose(bi_z/bi_envelope, 0, atol=1e-10, rtol=0)
  885. assert_allclose(bip_zp/bip_envelope, 0, atol=1e-10, rtol=0)
  886. # Check first zeros, DLMF 9.9.2
  887. assert_allclose(z[:6],
  888. [-1.1737132227, -3.2710933028, -4.8307378417,
  889. -6.1698521283, -7.3767620794, -8.4919488465], rtol=1e-10)
  890. assert_allclose(zp[:6],
  891. [-2.2944396826, -4.0731550891, -5.5123957297,
  892. -6.7812944460, -7.9401786892, -9.0195833588], rtol=1e-10)
  893. class TestAssocLaguerre:
  894. def test_assoc_laguerre(self):
  895. a1 = special.genlaguerre(11,1)
  896. a2 = special.assoc_laguerre(.2,11,1)
  897. assert_allclose(a2, a1(.2), atol=1.5e-8, rtol=0)
  898. a2 = special.assoc_laguerre(1,11,1)
  899. assert_allclose(a2, a1(1), atol=1.5e-8, rtol=0)
  900. class TestBesselpoly:
  901. def test_besselpoly(self):
  902. pass
  903. class TestKelvin:
  904. def test_bei(self):
  905. mbei = special.bei(2)
  906. # This may not be exact.
  907. assert_allclose(mbei, 0.9722916273066613, atol=1.5e-5, rtol=0)
  908. def test_beip(self):
  909. mbeip = special.beip(2)
  910. # This may not be exact.
  911. assert_allclose(mbeip, 0.91701361338403631, atol=1.5e-5, rtol=0)
  912. def test_ber(self):
  913. mber = special.ber(2)
  914. # This may not be exact.
  915. assert_allclose(mber, 0.75173418271380821, atol=1.5e-5, rtol=0)
  916. def test_berp(self):
  917. mberp = special.berp(2)
  918. # This may not be exact.
  919. assert_allclose(mberp, -0.49306712470943909, atol=1.5e-5, rtol=0)
  920. def test_bei_zeros(self):
  921. # Abramowitz & Stegun, Table 9.12
  922. bi = special.bei_zeros(5)
  923. assert_allclose(bi, array([5.02622,
  924. 9.45541,
  925. 13.89349,
  926. 18.33398,
  927. 22.77544]),
  928. atol=1.5e-4, rtol=0)
  929. def test_beip_zeros(self):
  930. bip = special.beip_zeros(5)
  931. assert_allclose(bip, array([3.772673304934953,
  932. 8.280987849760042,
  933. 12.742147523633703,
  934. 17.193431752512542,
  935. 21.641143941167325]),
  936. atol=1.5e-8, rtol=0)
  937. def test_ber_zeros(self):
  938. ber = special.ber_zeros(5)
  939. assert_allclose(ber, array([2.84892,
  940. 7.23883,
  941. 11.67396,
  942. 16.11356,
  943. 20.55463]),
  944. atol=1.5e-4, rtol=0)
  945. def test_berp_zeros(self):
  946. brp = special.berp_zeros(5)
  947. assert_allclose(brp, array([6.03871,
  948. 10.51364,
  949. 14.96844,
  950. 19.41758,
  951. 23.86430]),
  952. atol=1.5e-4, rtol=0)
  953. def test_kelvin(self):
  954. mkelv = special.kelvin(2)
  955. assert_allclose(mkelv, (special.ber(2) + special.bei(2)*1j,
  956. special.ker(2) + special.kei(2)*1j,
  957. special.berp(2) + special.beip(2)*1j,
  958. special.kerp(2) + special.keip(2)*1j),
  959. atol=1.5e-8, rtol=0)
  960. def test_kei(self):
  961. mkei = special.kei(2)
  962. assert_allclose(mkei, -0.20240006776470432, atol=1.5e-5, rtol=0)
  963. def test_keip(self):
  964. mkeip = special.keip(2)
  965. assert_allclose(mkeip, 0.21980790991960536, atol=1.5e-5, rtol=0)
  966. def test_ker(self):
  967. mker = special.ker(2)
  968. assert_allclose(mker, -0.041664513991509472, atol=1.5e-5, rtol=0)
  969. def test_kerp(self):
  970. mkerp = special.kerp(2)
  971. assert_allclose(mkerp, -0.10660096588105264, atol=1.5e-5, rtol=0)
  972. def test_kei_zeros(self):
  973. kei = special.kei_zeros(5)
  974. assert_allclose(kei, array([3.91467,
  975. 8.34422,
  976. 12.78256,
  977. 17.22314,
  978. 21.66464]),
  979. atol=1.5e-4, rtol=0)
  980. def test_keip_zeros(self):
  981. keip = special.keip_zeros(5)
  982. assert_allclose(keip, array([4.93181,
  983. 9.40405,
  984. 13.85827,
  985. 18.30717,
  986. 22.75379]),
  987. atol=1.5e-4, rtol=0)
  988. # numbers come from 9.9 of A&S pg. 381
  989. def test_kelvin_zeros(self):
  990. tmp = special.kelvin_zeros(5)
  991. berz, beiz, kerz, keiz, berpz, beipz, kerpz, keipz = tmp
  992. assert_allclose(berz, array([2.84892,
  993. 7.23883,
  994. 11.67396,
  995. 16.11356,
  996. 20.55463]),
  997. atol=1.5e-4, rtol=0)
  998. assert_allclose(beiz, array([5.02622,
  999. 9.45541,
  1000. 13.89349,
  1001. 18.33398,
  1002. 22.77544]),
  1003. atol=1.5e-4, rtol=0)
  1004. assert_allclose(kerz, array([1.71854,
  1005. 6.12728,
  1006. 10.56294,
  1007. 15.00269,
  1008. 19.44382]),
  1009. atol=1.5e-4, rtol=0)
  1010. assert_allclose(keiz, array([3.91467,
  1011. 8.34422,
  1012. 12.78256,
  1013. 17.22314,
  1014. 21.66464]),
  1015. atol=1.5e-4, rtol=0)
  1016. assert_allclose(berpz, array([6.03871,
  1017. 10.51364,
  1018. 14.96844,
  1019. 19.41758,
  1020. 23.86430]),
  1021. atol=1.5e-4, rtol=0)
  1022. assert_allclose(beipz, array([3.77267,
  1023. # table from 1927 had 3.77320
  1024. # but this is more accurate
  1025. 8.28099,
  1026. 12.74215,
  1027. 17.19343,
  1028. 21.64114]),
  1029. atol=1.5e-4, rtol=0)
  1030. assert_allclose(kerpz, array([2.66584,
  1031. 7.17212,
  1032. 11.63218,
  1033. 16.08312,
  1034. 20.53068]),
  1035. atol=1.5e-4, rtol=0)
  1036. assert_allclose(keipz, array([4.93181,
  1037. 9.40405,
  1038. 13.85827,
  1039. 18.30717,
  1040. 22.75379]),
  1041. atol=1.5e-4, rtol=0)
  1042. def test_ker_zeros(self):
  1043. ker = special.ker_zeros(5)
  1044. assert_allclose(ker, array([1.71854,
  1045. 6.12728,
  1046. 10.56294,
  1047. 15.00269,
  1048. 19.44381]),
  1049. atol=1.5e-4, rtol=0)
  1050. def test_kerp_zeros(self):
  1051. kerp = special.kerp_zeros(5)
  1052. assert_allclose(kerp, array([2.66584,
  1053. 7.17212,
  1054. 11.63218,
  1055. 16.08312,
  1056. 20.53068]),
  1057. atol=1.5e-4, rtol=0)
  1058. class TestBernoulli:
  1059. def test_bernoulli(self):
  1060. brn = special.bernoulli(5)
  1061. assert_allclose(brn, array([1.0000,
  1062. -0.5000,
  1063. 0.1667,
  1064. 0.0000,
  1065. -0.0333,
  1066. 0.0000]),
  1067. atol=1.5e-4, rtol=0)
  1068. class TestBeta:
  1069. """
  1070. Test beta and betaln.
  1071. """
  1072. def test_beta(self):
  1073. assert_equal(special.beta(1, 1), 1.0)
  1074. assert_allclose(special.beta(-100.3, 1e-200), special.gamma(1e-200))
  1075. assert_allclose(special.beta(0.0342, 171), 24.070498359873497,
  1076. rtol=1e-13, atol=0)
  1077. bet = special.beta(2, 4)
  1078. betg = (special.gamma(2)*special.gamma(4))/special.gamma(6)
  1079. assert_allclose(bet, betg, rtol=1e-13)
  1080. def test_beta_inf(self):
  1081. assert_(np.isinf(special.beta(-1, 2)))
  1082. def test_betaln(self):
  1083. assert_equal(special.betaln(1, 1), 0.0)
  1084. assert_allclose(special.betaln(-100.3, 1e-200),
  1085. special.gammaln(1e-200))
  1086. assert_allclose(special.betaln(0.0342, 170), 3.1811881124242447,
  1087. rtol=1e-14, atol=0)
  1088. betln = special.betaln(2, 4)
  1089. bet = log(abs(special.beta(2, 4)))
  1090. assert_allclose(betln, bet, rtol=1e-13)
  1091. class TestBetaInc:
  1092. """
  1093. Tests for betainc, betaincinv, betaincc, betainccinv.
  1094. """
  1095. def test_a1_b1(self):
  1096. # betainc(1, 1, x) is x.
  1097. x = np.array([0, 0.25, 1])
  1098. assert_equal(special.betainc(1, 1, x), x)
  1099. assert_equal(special.betaincinv(1, 1, x), x)
  1100. assert_equal(special.betaincc(1, 1, x), 1 - x)
  1101. assert_equal(special.betainccinv(1, 1, x), 1 - x)
  1102. # Nontrivial expected values computed with mpmath:
  1103. # from mpmath import mp
  1104. # mp.dps = 100
  1105. # p = mp.betainc(a, b, 0, x, regularized=True)
  1106. #
  1107. # or, e.g.,
  1108. #
  1109. # p = 0.25
  1110. # a, b = 0.0342, 171
  1111. # x = mp.findroot(
  1112. # lambda t: mp.betainc(a, b, 0, t, regularized=True) - p,
  1113. # (8e-21, 9e-21),
  1114. # solver='anderson',
  1115. # )
  1116. #
  1117. @pytest.mark.parametrize(
  1118. 'a, b, x, p',
  1119. [(2, 4, 0.3138101704556974, 0.5),
  1120. (0.0342, 171.0, 1e-10, 0.552699169018070910641),
  1121. # gh-3761:
  1122. (0.0342, 171, 8.42313169354797e-21, 0.25),
  1123. # gh-4244:
  1124. (0.0002742794749792665, 289206.03125, 1.639984034231756e-56,
  1125. 0.9688708782196045),
  1126. # gh-12796:
  1127. (4, 99997, 0.0001947841578892121, 0.999995)])
  1128. def test_betainc_and_inverses(self, a, b, x, p):
  1129. p1 = special.betainc(a, b, x)
  1130. assert_allclose(p1, p, rtol=1e-15)
  1131. x1 = special.betaincinv(a, b, p)
  1132. assert_allclose(x1, x, rtol=5e-13)
  1133. a1 = special.btdtria(p, b, x)
  1134. assert_allclose(a1, a, rtol=1e-13)
  1135. b1 = special.btdtrib(a, p, x)
  1136. assert_allclose(b1, b, rtol=1e-13)
  1137. # Expected values computed with mpmath:
  1138. # from mpmath import mp
  1139. # mp.dps = 100
  1140. # p = mp.betainc(a, b, x, 1, regularized=True)
  1141. @pytest.mark.parametrize('a, b, x, p',
  1142. [(2.5, 3.0, 0.25, 0.833251953125),
  1143. (7.5, 13.25, 0.375, 0.43298734645560368593),
  1144. (0.125, 7.5, 0.425, 0.0006688257851314237),
  1145. (0.125, 18.0, 1e-6, 0.72982359145096327654),
  1146. (0.125, 18.0, 0.996, 7.2745875538380150586e-46),
  1147. (0.125, 24.0, 0.75, 3.70853404816862016966e-17),
  1148. (16.0, 0.75, 0.99999999975,
  1149. 5.4408759277418629909e-07),
  1150. # gh-4677 (numbers from stackoverflow question):
  1151. (0.4211959643503401, 16939.046996018118,
  1152. 0.000815296167195521, 1e-7)])
  1153. def test_betaincc_betainccinv(self, a, b, x, p):
  1154. p1 = special.betaincc(a, b, x)
  1155. assert_allclose(p1, p, rtol=5e-15)
  1156. x1 = special.betainccinv(a, b, p)
  1157. assert_allclose(x1, x, rtol=8e-15)
  1158. @pytest.mark.parametrize(
  1159. 'a, b, y, ref',
  1160. [(14.208308325339239, 14.208308325339239, 7.703145458496392e-307,
  1161. 8.566004561846704e-23),
  1162. (14.0, 14.5, 1e-280, 2.9343915006642424e-21),
  1163. (3.5, 15.0, 4e-95, 1.3290751429289227e-28),
  1164. (10.0, 1.25, 2e-234, 3.982659092143654e-24),
  1165. (4.0, 99997.0, 5e-88, 3.309800566862242e-27)]
  1166. )
  1167. def test_betaincinv_tiny_y(self, a, b, y, ref):
  1168. # Test with extremely small y values. This test includes
  1169. # a regression test for an issue in the boost code;
  1170. # see https://github.com/boostorg/math/issues/961
  1171. #
  1172. # The reference values were computed with mpmath. For example,
  1173. #
  1174. # from mpmath import mp
  1175. # mp.dps = 1000
  1176. # a = 14.208308325339239
  1177. # p = 7.703145458496392e-307
  1178. # x = mp.findroot(lambda t: mp.betainc(a, a, 0, t,
  1179. # regularized=True) - p,
  1180. # x0=8.566e-23)
  1181. # print(float(x))
  1182. #
  1183. x = special.betaincinv(a, b, y)
  1184. assert_allclose(x, ref, rtol=1e-14)
  1185. @pytest.mark.parametrize('func', [special.betainc, special.betaincinv,
  1186. special.btdtria, special.btdtrib,
  1187. special.betaincc, special.betainccinv])
  1188. @pytest.mark.parametrize('args', [(-1.0, 2, 0.5), (1.5, -2.0, 0.5),
  1189. (1.5, 2.0, -0.3), (1.5, 2.0, 1.1)])
  1190. def test_betainc_domain_errors(self, func, args):
  1191. with special.errstate(domain='raise'):
  1192. with pytest.raises(special.SpecialFunctionError, match='domain'):
  1193. func(*args)
  1194. @pytest.mark.parametrize(
  1195. "args,expected",
  1196. [
  1197. ((0.0, 0.0, 0.0), np.nan),
  1198. ((0.0, 0.0, 0.5), np.nan),
  1199. ((0.0, 0.0, 1.0), np.nan),
  1200. ((np.inf, np.inf, 0.0), np.nan),
  1201. ((np.inf, np.inf, 0.5), np.nan),
  1202. ((np.inf, np.inf, 1.0), np.nan),
  1203. ((0.0, 1.0, 0.0), 0.0),
  1204. ((0.0, 1.0, 0.5), 1.0),
  1205. ((0.0, 1.0, 1.0), 1.0),
  1206. ((1.0, 0.0, 0.0), 0.0),
  1207. ((1.0, 0.0, 0.5), 0.0),
  1208. ((1.0, 0.0, 1.0), 1.0),
  1209. ((0.0, np.inf, 0.0), 0.0),
  1210. ((0.0, np.inf, 0.5), 1.0),
  1211. ((0.0, np.inf, 1.0), 1.0),
  1212. ((np.inf, 0.0, 0.0), 0.0),
  1213. ((np.inf, 0.0, 0.5), 0.0),
  1214. ((np.inf, 0.0, 1.0), 1.0),
  1215. ((1.0, np.inf, 0.0), 0.0),
  1216. ((1.0, np.inf, 0.5), 1.0),
  1217. ((1.0, np.inf, 1.0), 1.0),
  1218. ((np.inf, 1.0, 0.0), 0.0),
  1219. ((np.inf, 1.0, 0.5), 0.0),
  1220. ((np.inf, 1.0, 1.0), 1.0),
  1221. ]
  1222. )
  1223. def test_betainc_edge_cases(self, args, expected):
  1224. observed = special.betainc(*args)
  1225. assert_equal(observed, expected)
  1226. @pytest.mark.parametrize(
  1227. "args,expected",
  1228. [
  1229. ((0.0, 0.0, 0.0), np.nan),
  1230. ((0.0, 0.0, 0.5), np.nan),
  1231. ((0.0, 0.0, 1.0), np.nan),
  1232. ((np.inf, np.inf, 0.0), np.nan),
  1233. ((np.inf, np.inf, 0.5), np.nan),
  1234. ((np.inf, np.inf, 1.0), np.nan),
  1235. ((0.0, 1.0, 0.0), 1.0),
  1236. ((0.0, 1.0, 0.5), 0.0),
  1237. ((0.0, 1.0, 1.0), 0.0),
  1238. ((1.0, 0.0, 0.0), 1.0),
  1239. ((1.0, 0.0, 0.5), 1.0),
  1240. ((1.0, 0.0, 1.0), 0.0),
  1241. ((0.0, np.inf, 0.0), 1.0),
  1242. ((0.0, np.inf, 0.5), 0.0),
  1243. ((0.0, np.inf, 1.0), 0.0),
  1244. ((np.inf, 0.0, 0.0), 1.0),
  1245. ((np.inf, 0.0, 0.5), 1.0),
  1246. ((np.inf, 0.0, 1.0), 0.0),
  1247. ((1.0, np.inf, 0.0), 1.0),
  1248. ((1.0, np.inf, 0.5), 0.0),
  1249. ((1.0, np.inf, 1.0), 0.0),
  1250. ((np.inf, 1.0, 0.0), 1.0),
  1251. ((np.inf, 1.0, 0.5), 1.0),
  1252. ((np.inf, 1.0, 1.0), 0.0),
  1253. ]
  1254. )
  1255. def test_betaincc_edge_cases(self, args, expected):
  1256. observed = special.betaincc(*args)
  1257. assert_equal(observed, expected)
  1258. @pytest.mark.parametrize('dtype', [np.float32, np.float64])
  1259. def test_gh21426(self, dtype):
  1260. # Test for gh-21426: betaincinv must not return NaN
  1261. a = np.array([5.], dtype=dtype)
  1262. x = np.array([0.5], dtype=dtype)
  1263. result = special.betaincinv(a, a, x)
  1264. assert_allclose(result, x, rtol=10 * np.finfo(dtype).eps)
  1265. @pytest.mark.parametrize("dtype, rtol",
  1266. [(np.float32, 1e-4),
  1267. (np.float64, 1e-15)])
  1268. @pytest.mark.parametrize("a, b, x, reference",
  1269. [(1e-20, 1e-21, 0.5, 0.0909090909090909),
  1270. (1e-15, 1e-16, 0.5, 0.09090909090909091)])
  1271. def test_gh22682(self, a, b, x, reference, dtype, rtol):
  1272. # gh-22682: betainc returned incorrect results for tiny
  1273. # single precision inputs. test that this is resolved
  1274. a = np.array(a, dtype=dtype)
  1275. b = np.array(b, dtype=dtype)
  1276. x = np.array(x, dtype=dtype)
  1277. res = special.betainc(a, b, x)
  1278. assert_allclose(res, reference, rtol=rtol)
  1279. class TestCombinatorics:
  1280. def test_comb(self):
  1281. assert_allclose(special.comb([10, 10], [3, 4]), [120., 210.])
  1282. assert_allclose(special.comb(10, 3), 120.)
  1283. assert_equal(special.comb(10, 3, exact=True), 120)
  1284. assert_equal(special.comb(10, 3, exact=True, repetition=True), 220)
  1285. assert_allclose([special.comb(20, k, exact=True) for k in range(21)],
  1286. special.comb(20, list(range(21))), atol=1e-15)
  1287. ii = np.iinfo(int).max + 1
  1288. assert_equal(special.comb(ii, ii-1, exact=True), ii)
  1289. expected = 100891344545564193334812497256
  1290. assert special.comb(100, 50, exact=True) == expected
  1291. def test_comb_with_np_int64(self):
  1292. n = 70
  1293. k = 30
  1294. np_n = np.int64(n)
  1295. np_k = np.int64(k)
  1296. res_np = special.comb(np_n, np_k, exact=True)
  1297. res_py = special.comb(n, k, exact=True)
  1298. assert res_np == res_py
  1299. def test_comb_zeros(self):
  1300. assert_equal(special.comb(2, 3, exact=True), 0)
  1301. assert_equal(special.comb(-1, 3, exact=True), 0)
  1302. assert_equal(special.comb(2, -1, exact=True), 0)
  1303. assert_equal(special.comb(2, -1, exact=False), 0)
  1304. assert_allclose(special.comb([2, -1, 2, 10], [3, 3, -1, 3]), [0., 0., 0., 120.])
  1305. def test_comb_exact_non_int_error(self):
  1306. msg = "`exact=True`"
  1307. with pytest.raises(ValueError, match=msg):
  1308. special.comb(3.4, 4, exact=True)
  1309. with pytest.raises(ValueError, match=msg):
  1310. special.comb(3, 4.4, exact=True)
  1311. @pytest.mark.parametrize('N', [0, 5, 10])
  1312. @pytest.mark.parametrize('exact', [True, False])
  1313. def test_comb_repetition_k_zero(self, N, exact):
  1314. # Regression test for gh-23867
  1315. # C(n, 0) should always be 1 for n >= 0, regardless of repetition
  1316. actual = special.comb(N, 0, exact=exact, repetition=True)
  1317. assert actual == 1
  1318. assert type(actual) is int if exact else np.float64
  1319. def test_comb_repetition_k_zero_array(self):
  1320. # Test array-like input with exact=False for gh-23867
  1321. N = np.array([0, 5, 10])
  1322. result = special.comb(N, 0, exact=False, repetition=True)
  1323. expected = np.array([1.0, 1.0, 1.0])
  1324. assert_equal(result, expected)
  1325. def test_perm(self):
  1326. assert_allclose(special.perm([10, 10], [3, 4]), [720., 5040.])
  1327. assert_allclose(special.perm(10, 3), 720., atol=1.5e-7, rtol=0)
  1328. assert_equal(special.perm(10, 3, exact=True), 720)
  1329. def test_perm_zeros(self):
  1330. assert_equal(special.perm(2, 3, exact=True), 0)
  1331. assert_equal(special.perm(-1, 3, exact=True), 0)
  1332. assert_equal(special.perm(2, -1, exact=True), 0)
  1333. assert_equal(special.perm(2, -1, exact=False), 0)
  1334. assert_allclose(special.perm([2, -1, 2, 10], [3, 3, -1, 3]), [0., 0., 0., 720.])
  1335. def test_perm_iv(self):
  1336. # currently `exact=True` only support scalars
  1337. with pytest.raises(ValueError, match="scalar integers"):
  1338. special.perm([1, 2], [4, 5], exact=True)
  1339. with pytest.raises(ValueError, match="Non-integer"):
  1340. special.perm(4.6, 6, exact=True)
  1341. with pytest.raises(ValueError, match="Non-integer"):
  1342. special.perm(-4.6, 3, exact=True)
  1343. with pytest.raises(ValueError, match="Non-integer"):
  1344. special.perm(4, -3.9, exact=True)
  1345. with pytest.raises(ValueError, match="Non-integer"):
  1346. special.perm(6.0, 4.6, exact=True)
  1347. class TestTrigonometric:
  1348. def test_cbrt(self):
  1349. cb = special.cbrt(27)
  1350. cbrl = 27**(1.0/3.0)
  1351. assert_allclose(cb, cbrl, atol=1.5e-7, rtol=0)
  1352. def test_cbrtmore(self):
  1353. cb1 = special.cbrt(27.9)
  1354. cbrl1 = 27.9**(1.0/3.0)
  1355. assert_allclose(cb1, cbrl1, atol=1.5e-8, rtol=0)
  1356. def test_cosdg(self):
  1357. cdg = special.cosdg(90)
  1358. cdgrl = cos(pi/2.0)
  1359. assert_allclose(cdg, cdgrl, atol=1.5e-8, rtol=0)
  1360. def test_cosdgmore(self):
  1361. cdgm = special.cosdg(30)
  1362. cdgmrl = cos(pi/6.0)
  1363. assert_allclose(cdgm, cdgmrl, atol=1.5e-8, rtol=0)
  1364. def test_cosm1(self):
  1365. cs = (special.cosm1(0),special.cosm1(.3),special.cosm1(pi/10))
  1366. csrl = (cos(0)-1,cos(.3)-1,cos(pi/10)-1)
  1367. assert_allclose(cs, csrl, atol=1.5e-8, rtol=0)
  1368. def test_cotdg(self):
  1369. ct = special.cotdg(30)
  1370. ctrl = tan(pi/6.0)**(-1)
  1371. assert_allclose(ct, ctrl, atol=1.5e-8, rtol=0)
  1372. def test_cotdgmore(self):
  1373. ct1 = special.cotdg(45)
  1374. ctrl1 = tan(pi/4.0)**(-1)
  1375. assert_allclose(ct1, ctrl1, atol=1.5e-8, rtol=0)
  1376. def test_specialpoints(self):
  1377. assert_allclose(special.cotdg(45), 1.0, atol=1.5e-14, rtol=0)
  1378. assert_allclose(special.cotdg(-45), -1.0, atol=1.5e-14, rtol=0)
  1379. assert_allclose(special.cotdg(90), 0.0, atol=1.5e-14, rtol=0)
  1380. assert_allclose(special.cotdg(-90), 0.0, atol=1.5e-14, rtol=0)
  1381. assert_allclose(special.cotdg(135), -1.0, atol=1.5e-14, rtol=0)
  1382. assert_allclose(special.cotdg(-135), 1.0, atol=1.5e-14, rtol=0)
  1383. assert_allclose(special.cotdg(225), 1.0, atol=1.5e-14, rtol=0)
  1384. assert_allclose(special.cotdg(-225), -1.0, atol=1.5e-14, rtol=0)
  1385. assert_allclose(special.cotdg(270), 0.0, atol=1.5e-14, rtol=0)
  1386. assert_allclose(special.cotdg(-270), 0.0, atol=1.5e-14, rtol=0)
  1387. assert_allclose(special.cotdg(315), -1.0, atol=1.5e-14, rtol=0)
  1388. assert_allclose(special.cotdg(-315), 1.0, atol=1.5e-14, rtol=0)
  1389. assert_allclose(special.cotdg(765), 1.0, atol=1.5e-14, rtol=0)
  1390. def test_sinc(self):
  1391. # the sinc implementation and more extensive sinc tests are in numpy
  1392. assert_array_equal(special.sinc([0]), 1)
  1393. assert_equal(special.sinc(0.0), 1.0)
  1394. def test_sindg(self):
  1395. sn = special.sindg(90)
  1396. assert_equal(sn,1.0)
  1397. def test_sindgmore(self):
  1398. snm = special.sindg(30)
  1399. snmrl = sin(pi/6.0)
  1400. assert_allclose(snm, snmrl, atol=1.5e-8, rtol=0)
  1401. snm1 = special.sindg(45)
  1402. snmrl1 = sin(pi/4.0)
  1403. assert_allclose(snm1, snmrl1, atol=1.5e-8, rtol=0)
  1404. class TestTandg:
  1405. def test_tandg(self):
  1406. tn = special.tandg(30)
  1407. tnrl = tan(pi/6.0)
  1408. assert_allclose(tn, tnrl, atol=1.5e-8, rtol=0)
  1409. def test_tandgmore(self):
  1410. tnm = special.tandg(45)
  1411. tnmrl = tan(pi/4.0)
  1412. assert_allclose(tnm, tnmrl, atol=1.5e-8, rtol=0)
  1413. tnm1 = special.tandg(60)
  1414. tnmrl1 = tan(pi/3.0)
  1415. assert_allclose(tnm1, tnmrl1, atol=1.5e-8, rtol=0)
  1416. def test_specialpoints(self):
  1417. assert_allclose(special.tandg(0), 0.0, atol=1.5e-14, rtol=0)
  1418. assert_allclose(special.tandg(45), 1.0, atol=1.5e-14, rtol=0)
  1419. assert_allclose(special.tandg(-45), -1.0, atol=1.5e-14, rtol=0)
  1420. assert_allclose(special.tandg(135), -1.0, atol=1.5e-14, rtol=0)
  1421. assert_allclose(special.tandg(-135), 1.0, atol=1.5e-14, rtol=0)
  1422. assert_allclose(special.tandg(180), 0.0, atol=1.5e-14, rtol=0)
  1423. assert_allclose(special.tandg(-180), 0.0, atol=1.5e-14, rtol=0)
  1424. assert_allclose(special.tandg(225), 1.0, atol=1.5e-14, rtol=0)
  1425. assert_allclose(special.tandg(-225), -1.0, atol=1.5e-14, rtol=0)
  1426. assert_allclose(special.tandg(315), -1.0, atol=1.5e-14, rtol=0)
  1427. assert_allclose(special.tandg(-315), 1.0, atol=1.5e-14, rtol=0)
  1428. class TestEllip:
  1429. def test_ellipj_nan(self):
  1430. """Regression test for #912."""
  1431. special.ellipj(0.5, np.nan)
  1432. def test_ellipj(self):
  1433. el = special.ellipj(0.2,0)
  1434. rel = [sin(0.2),cos(0.2),1.0,0.20]
  1435. assert_allclose(el, rel, atol=1.5e-13, rtol=0)
  1436. def test_ellipk(self):
  1437. elk = special.ellipk(.2)
  1438. assert_allclose(elk, 1.659623598610528, atol=1.5e-11, rtol=0)
  1439. assert_equal(special.ellipkm1(0.0), np.inf)
  1440. assert_equal(special.ellipkm1(1.0), pi/2)
  1441. assert_equal(special.ellipkm1(np.inf), 0.0)
  1442. assert_equal(special.ellipkm1(np.nan), np.nan)
  1443. assert_equal(special.ellipkm1(-1), np.nan)
  1444. assert_allclose(special.ellipk(-10), 0.7908718902387385)
  1445. def test_ellipkinc(self):
  1446. elkinc = special.ellipkinc(pi/2,.2)
  1447. elk = special.ellipk(0.2)
  1448. assert_allclose(elkinc, elk, atol=1.5e-15, rtol=0)
  1449. alpha = 20*pi/180
  1450. phi = 45*pi/180
  1451. m = sin(alpha)**2
  1452. elkinc = special.ellipkinc(phi,m)
  1453. assert_allclose(elkinc, 0.79398143, atol=1.5e-8, rtol=0)
  1454. # From pg. 614 of A & S
  1455. assert_equal(special.ellipkinc(pi/2, 0.0), pi/2)
  1456. assert_equal(special.ellipkinc(pi/2, 1.0), np.inf)
  1457. assert_equal(special.ellipkinc(pi/2, -np.inf), 0.0)
  1458. assert_equal(special.ellipkinc(pi/2, np.nan), np.nan)
  1459. assert_equal(special.ellipkinc(pi/2, 2), np.nan)
  1460. assert_equal(special.ellipkinc(0, 0.5), 0.0)
  1461. assert_equal(special.ellipkinc(np.inf, 0.5), np.inf)
  1462. assert_equal(special.ellipkinc(-np.inf, 0.5), -np.inf)
  1463. assert_equal(special.ellipkinc(np.inf, np.inf), np.nan)
  1464. assert_equal(special.ellipkinc(np.inf, -np.inf), np.nan)
  1465. assert_equal(special.ellipkinc(-np.inf, -np.inf), np.nan)
  1466. assert_equal(special.ellipkinc(-np.inf, np.inf), np.nan)
  1467. assert_equal(special.ellipkinc(np.nan, 0.5), np.nan)
  1468. assert_equal(special.ellipkinc(np.nan, np.nan), np.nan)
  1469. assert_allclose(special.ellipkinc(0.38974112035318718, 1), 0.4, rtol=1e-14)
  1470. assert_allclose(special.ellipkinc(1.5707, -10), 0.79084284661724946)
  1471. def test_ellipkinc_2(self):
  1472. # Regression test for gh-3550
  1473. # ellipkinc(phi, mbad) was NaN and mvals[2:6] were twice the correct value
  1474. mbad = 0.68359375000000011
  1475. phi = 0.9272952180016123
  1476. m = np.nextafter(mbad, 0)
  1477. mvals = []
  1478. for j in range(10):
  1479. mvals.append(m)
  1480. m = np.nextafter(m, 1)
  1481. f = special.ellipkinc(phi, mvals)
  1482. assert_array_almost_equal_nulp(f, np.full_like(f, 1.0259330100195334), 1)
  1483. # this bug also appears at phi + n * pi for at least small n
  1484. f1 = special.ellipkinc(phi + pi, mvals)
  1485. assert_array_almost_equal_nulp(f1, np.full_like(f1, 5.1296650500976675), 2)
  1486. def test_ellipkinc_singular(self):
  1487. # ellipkinc(phi, 1) has closed form and is finite only for phi in (-pi/2, pi/2)
  1488. xlog = np.logspace(-300, -17, 25)
  1489. xlin = np.linspace(1e-17, 0.1, 25)
  1490. xlin2 = np.linspace(0.1, pi/2, 25, endpoint=False)
  1491. assert_allclose(special.ellipkinc(xlog, 1), np.arcsinh(np.tan(xlog)),
  1492. rtol=1e14)
  1493. assert_allclose(special.ellipkinc(xlin, 1), np.arcsinh(np.tan(xlin)),
  1494. rtol=1e14)
  1495. assert_allclose(special.ellipkinc(xlin2, 1), np.arcsinh(np.tan(xlin2)),
  1496. rtol=1e14)
  1497. assert_equal(special.ellipkinc(np.pi/2, 1), np.inf)
  1498. assert_allclose(special.ellipkinc(-xlog, 1), np.arcsinh(np.tan(-xlog)),
  1499. rtol=1e14)
  1500. assert_allclose(special.ellipkinc(-xlin, 1), np.arcsinh(np.tan(-xlin)),
  1501. rtol=1e14)
  1502. assert_allclose(special.ellipkinc(-xlin2, 1), np.arcsinh(np.tan(-xlin2)),
  1503. rtol=1e14)
  1504. assert_equal(special.ellipkinc(-np.pi/2, 1), np.inf)
  1505. def test_ellipe(self):
  1506. ele = special.ellipe(.2)
  1507. assert_allclose(ele, 1.4890350580958529, atol=1.5e-8, rtol=0)
  1508. assert_equal(special.ellipe(0.0), pi/2)
  1509. assert_equal(special.ellipe(1.0), 1.0)
  1510. assert_equal(special.ellipe(-np.inf), np.inf)
  1511. assert_equal(special.ellipe(np.nan), np.nan)
  1512. assert_equal(special.ellipe(2), np.nan)
  1513. assert_allclose(special.ellipe(-10), 3.6391380384177689)
  1514. def test_ellipeinc(self):
  1515. eleinc = special.ellipeinc(pi/2,.2)
  1516. ele = special.ellipe(0.2)
  1517. assert_allclose(eleinc, ele, atol=1.5e-14, rtol=0)
  1518. # pg 617 of A & S
  1519. alpha, phi = 52*pi/180,35*pi/180
  1520. m = sin(alpha)**2
  1521. eleinc = special.ellipeinc(phi,m)
  1522. assert_allclose(eleinc, 0.58823065, atol=1.5e-8, rtol=0)
  1523. assert_equal(special.ellipeinc(pi/2, 0.0), pi/2)
  1524. assert_equal(special.ellipeinc(pi/2, 1.0), 1.0)
  1525. assert_equal(special.ellipeinc(pi/2, -np.inf), np.inf)
  1526. assert_equal(special.ellipeinc(pi/2, np.nan), np.nan)
  1527. assert_equal(special.ellipeinc(pi/2, 2), np.nan)
  1528. assert_equal(special.ellipeinc(0, 0.5), 0.0)
  1529. assert_equal(special.ellipeinc(np.inf, 0.5), np.inf)
  1530. assert_equal(special.ellipeinc(-np.inf, 0.5), -np.inf)
  1531. assert_equal(special.ellipeinc(np.inf, -np.inf), np.inf)
  1532. assert_equal(special.ellipeinc(-np.inf, -np.inf), -np.inf)
  1533. assert_equal(special.ellipeinc(np.inf, np.inf), np.nan)
  1534. assert_equal(special.ellipeinc(-np.inf, np.inf), np.nan)
  1535. assert_equal(special.ellipeinc(np.nan, 0.5), np.nan)
  1536. assert_equal(special.ellipeinc(np.nan, np.nan), np.nan)
  1537. assert_allclose(special.ellipeinc(1.5707, -10), 3.6388185585822876)
  1538. def test_ellipeinc_2(self):
  1539. # Regression test for gh-3550
  1540. # ellipeinc(phi, mbad) was NaN and mvals[2:6] were twice the correct value
  1541. mbad = 0.68359375000000011
  1542. phi = 0.9272952180016123
  1543. m = np.nextafter(mbad, 0)
  1544. mvals = []
  1545. for j in range(10):
  1546. mvals.append(m)
  1547. m = np.nextafter(m, 1)
  1548. f = special.ellipeinc(phi, mvals)
  1549. assert_array_almost_equal_nulp(f, np.full_like(f, 0.84442884574781019), 2)
  1550. # this bug also appears at phi + n * pi for at least small n
  1551. f1 = special.ellipeinc(phi + pi, mvals)
  1552. assert_array_almost_equal_nulp(f1, np.full_like(f1, 3.3471442287390509), 4)
  1553. class TestEllipCarlson:
  1554. """Test for Carlson elliptic integrals ellipr[cdfgj].
  1555. The special values used in these tests can be found in Sec. 3 of Carlson
  1556. (1994), https://arxiv.org/abs/math/9409227
  1557. """
  1558. def test_elliprc(self):
  1559. assert_allclose(elliprc(1, 1), 1)
  1560. assert elliprc(1, inf) == 0.0
  1561. assert isnan(elliprc(1, 0))
  1562. assert elliprc(1, complex(1, inf)) == 0.0
  1563. args = array([[0.0, 0.25],
  1564. [2.25, 2.0],
  1565. [0.0, 1.0j],
  1566. [-1.0j, 1.0j],
  1567. [0.25, -2.0],
  1568. [1.0j, -1.0]])
  1569. expected_results = array([np.pi,
  1570. np.log(2.0),
  1571. 1.1107207345396 * (1.0-1.0j),
  1572. 1.2260849569072-0.34471136988768j,
  1573. np.log(2.0) / 3.0,
  1574. 0.77778596920447+0.19832484993429j])
  1575. for i, arr in enumerate(args):
  1576. assert_allclose(elliprc(*arr), expected_results[i])
  1577. def test_elliprd(self):
  1578. assert_allclose(elliprd(1, 1, 1), 1)
  1579. assert_allclose(elliprd(0, 2, 1) / 3.0, 0.59907011736779610371)
  1580. assert elliprd(1, 1, inf) == 0.0
  1581. assert np.isinf(elliprd(1, 1, 0))
  1582. assert np.isinf(elliprd(1, 1, complex(0, 0)))
  1583. assert np.isinf(elliprd(0, 1, complex(0, 0)))
  1584. assert isnan(elliprd(1, 1, -np.finfo(np.float64).tiny / 2.0))
  1585. assert isnan(elliprd(1, 1, complex(-1, 0)))
  1586. args = array([[0.0, 2.0, 1.0],
  1587. [2.0, 3.0, 4.0],
  1588. [1.0j, -1.0j, 2.0],
  1589. [0.0, 1.0j, -1.0j],
  1590. [0.0, -1.0+1.0j, 1.0j],
  1591. [-2.0-1.0j, -1.0j, -1.0+1.0j]])
  1592. expected_results = array([1.7972103521034,
  1593. 0.16510527294261,
  1594. 0.65933854154220,
  1595. 1.2708196271910+2.7811120159521j,
  1596. -1.8577235439239-0.96193450888839j,
  1597. 1.8249027393704-1.2218475784827j])
  1598. for i, arr in enumerate(args):
  1599. assert_allclose(elliprd(*arr), expected_results[i])
  1600. def test_elliprf(self):
  1601. assert_allclose(elliprf(1, 1, 1), 1)
  1602. assert_allclose(elliprf(0, 1, 2), 1.31102877714605990523)
  1603. assert elliprf(1, inf, 1) == 0.0
  1604. assert np.isinf(elliprf(0, 1, 0))
  1605. assert isnan(elliprf(1, 1, -1))
  1606. assert elliprf(complex(inf), 0, 1) == 0.0
  1607. assert isnan(elliprf(1, 1, complex(-inf, 1)))
  1608. args = array([[1.0, 2.0, 0.0],
  1609. [1.0j, -1.0j, 0.0],
  1610. [0.5, 1.0, 0.0],
  1611. [-1.0+1.0j, 1.0j, 0.0],
  1612. [2.0, 3.0, 4.0],
  1613. [1.0j, -1.0j, 2.0],
  1614. [-1.0+1.0j, 1.0j, 1.0-1.0j]])
  1615. expected_results = array([1.3110287771461,
  1616. 1.8540746773014,
  1617. 1.8540746773014,
  1618. 0.79612586584234-1.2138566698365j,
  1619. 0.58408284167715,
  1620. 1.0441445654064,
  1621. 0.93912050218619-0.53296252018635j])
  1622. for i, arr in enumerate(args):
  1623. assert_allclose(elliprf(*arr), expected_results[i])
  1624. def test_elliprg(self):
  1625. assert_allclose(elliprg(1, 1, 1), 1)
  1626. assert_allclose(elliprg(0, 0, 1), 0.5)
  1627. assert_allclose(elliprg(0, 0, 0), 0)
  1628. assert np.isinf(elliprg(1, inf, 1))
  1629. assert np.isinf(elliprg(complex(inf), 1, 1))
  1630. args = array([[0.0, 16.0, 16.0],
  1631. [2.0, 3.0, 4.0],
  1632. [0.0, 1.0j, -1.0j],
  1633. [-1.0+1.0j, 1.0j, 0.0],
  1634. [-1.0j, -1.0+1.0j, 1.0j],
  1635. [0.0, 0.0796, 4.0]])
  1636. expected_results = array([np.pi,
  1637. 1.7255030280692,
  1638. 0.42360654239699,
  1639. 0.44660591677018+0.70768352357515j,
  1640. 0.36023392184473+0.40348623401722j,
  1641. 1.0284758090288])
  1642. for i, arr in enumerate(args):
  1643. assert_allclose(elliprg(*arr), expected_results[i])
  1644. def test_elliprj(self):
  1645. assert_allclose(elliprj(1, 1, 1, 1), 1)
  1646. assert elliprj(1, 1, inf, 1) == 0.0
  1647. assert isnan(elliprj(1, 0, 0, 0))
  1648. assert isnan(elliprj(-1, 1, 1, 1))
  1649. assert elliprj(1, 1, 1, inf) == 0.0
  1650. args = array([[0.0, 1.0, 2.0, 3.0],
  1651. [2.0, 3.0, 4.0, 5.0],
  1652. [2.0, 3.0, 4.0, -1.0+1.0j],
  1653. [1.0j, -1.0j, 0.0, 2.0],
  1654. [-1.0+1.0j, -1.0-1.0j, 1.0, 2.0],
  1655. [1.0j, -1.0j, 0.0, 1.0-1.0j],
  1656. [-1.0+1.0j, -1.0-1.0j, 1.0, -3.0+1.0j],
  1657. [2.0, 3.0, 4.0, -0.5], # Cauchy principal value
  1658. [2.0, 3.0, 4.0, -5.0]]) # Cauchy principal value
  1659. expected_results = array([0.77688623778582,
  1660. 0.14297579667157,
  1661. 0.13613945827771-0.38207561624427j,
  1662. 1.6490011662711,
  1663. 0.94148358841220,
  1664. 1.8260115229009+1.2290661908643j,
  1665. -0.61127970812028-1.0684038390007j,
  1666. 0.24723819703052, # Cauchy principal value
  1667. -0.12711230042964]) # Caucny principal value
  1668. for i, arr in enumerate(args):
  1669. assert_allclose(elliprj(*arr), expected_results[i])
  1670. @pytest.mark.xfail(reason="Insufficient accuracy on 32-bit")
  1671. def test_elliprj_hard(self):
  1672. assert_allclose(elliprj(6.483625725195452e-08,
  1673. 1.1649136528196886e-27,
  1674. 3.6767340167168e+13,
  1675. 0.493704617023468),
  1676. 8.63426920644241857617477551054e-6,
  1677. rtol=5e-15, atol=1e-20)
  1678. assert_allclose(elliprj(14.375105857849121,
  1679. 9.993988969725365e-11,
  1680. 1.72844262269944e-26,
  1681. 5.898871222598245e-06),
  1682. 829774.1424801627252574054378691828,
  1683. rtol=5e-15, atol=1e-20)
  1684. class TestEllipLegendreCarlsonIdentities:
  1685. """Test identities expressing the Legendre elliptic integrals in terms
  1686. of Carlson's symmetric integrals. These identities can be found
  1687. in the DLMF https://dlmf.nist.gov/19.25#i .
  1688. """
  1689. def setup_class(self):
  1690. self.m_n1_1 = np.arange(-1., 1., 0.01)
  1691. # For double, this is -(2**1024)
  1692. self.max_neg = finfo(double).min
  1693. # Lots of very negative numbers
  1694. self.very_neg_m = -1. * 2.**arange(-1 +
  1695. np.log2(-self.max_neg), 0.,
  1696. -1.)
  1697. self.ms_up_to_1 = np.concatenate(([self.max_neg],
  1698. self.very_neg_m,
  1699. self.m_n1_1))
  1700. def test_k(self):
  1701. """Test identity:
  1702. K(m) = R_F(0, 1-m, 1)
  1703. """
  1704. m = self.ms_up_to_1
  1705. assert_allclose(ellipk(m), elliprf(0., 1.-m, 1.))
  1706. def test_km1(self):
  1707. """Test identity:
  1708. K(m) = R_F(0, 1-m, 1)
  1709. But with the ellipkm1 function
  1710. """
  1711. # For double, this is 2**-1022
  1712. tiny = finfo(double).tiny
  1713. # All these small powers of 2, up to 2**-1
  1714. m1 = tiny * 2.**arange(0., -np.log2(tiny))
  1715. assert_allclose(ellipkm1(m1), elliprf(0., m1, 1.))
  1716. def test_e(self):
  1717. """Test identity:
  1718. E(m) = 2*R_G(0, 1-k^2, 1)
  1719. """
  1720. m = self.ms_up_to_1
  1721. assert_allclose(ellipe(m), 2.*elliprg(0., 1.-m, 1.))
  1722. class TestErf:
  1723. def test_erf(self):
  1724. er = special.erf(.25)
  1725. assert_allclose(er, 0.2763263902, atol=1.5e-8, rtol=0)
  1726. def test_erf_zeros(self):
  1727. erz = special.erf_zeros(5)
  1728. erzr = array([1.45061616+1.88094300j,
  1729. 2.24465928+2.61657514j,
  1730. 2.83974105+3.17562810j,
  1731. 3.33546074+3.64617438j,
  1732. 3.76900557+4.06069723j])
  1733. assert_allclose(erz, erzr, atol=1.5e-4, rtol=0)
  1734. def _check_variant_func(self, func, other_func, rtol, atol=0):
  1735. rng = np.random.RandomState(1234)
  1736. n = 10000
  1737. x = rng.pareto(0.02, n) * (2*rng.randint(0, 2, n) - 1)
  1738. y = rng.pareto(0.02, n) * (2*rng.randint(0, 2, n) - 1)
  1739. z = x + 1j*y
  1740. with np.errstate(all='ignore'):
  1741. w = other_func(z)
  1742. w_real = other_func(x).real
  1743. mask = np.isfinite(w)
  1744. w = w[mask]
  1745. z = z[mask]
  1746. mask = np.isfinite(w_real)
  1747. w_real = w_real[mask]
  1748. x = x[mask]
  1749. # test both real and complex variants
  1750. assert_func_equal(func, w, z, rtol=rtol, atol=atol)
  1751. assert_func_equal(func, w_real, x, rtol=rtol, atol=atol)
  1752. def test_erfc_consistent(self):
  1753. self._check_variant_func(
  1754. cephes.erfc,
  1755. lambda z: 1 - cephes.erf(z),
  1756. rtol=1e-12,
  1757. atol=1e-14 # <- the test function loses precision
  1758. )
  1759. def test_erfcx_consistent(self):
  1760. self._check_variant_func(
  1761. cephes.erfcx,
  1762. lambda z: np.exp(z*z) * cephes.erfc(z),
  1763. rtol=1e-12
  1764. )
  1765. def test_erfi_consistent(self):
  1766. self._check_variant_func(
  1767. cephes.erfi,
  1768. lambda z: -1j * cephes.erf(1j*z),
  1769. rtol=1e-12
  1770. )
  1771. def test_dawsn_consistent(self):
  1772. self._check_variant_func(
  1773. cephes.dawsn,
  1774. lambda z: sqrt(pi)/2 * np.exp(-z*z) * cephes.erfi(z),
  1775. rtol=1e-12
  1776. )
  1777. def test_erf_nan_inf(self):
  1778. vals = [np.nan, -np.inf, np.inf]
  1779. expected = [np.nan, -1, 1]
  1780. assert_allclose(special.erf(vals), expected, rtol=1e-15)
  1781. def test_erfc_nan_inf(self):
  1782. vals = [np.nan, -np.inf, np.inf]
  1783. expected = [np.nan, 2, 0]
  1784. assert_allclose(special.erfc(vals), expected, rtol=1e-15)
  1785. def test_erfcx_nan_inf(self):
  1786. vals = [np.nan, -np.inf, np.inf]
  1787. expected = [np.nan, np.inf, 0]
  1788. assert_allclose(special.erfcx(vals), expected, rtol=1e-15)
  1789. def test_erfi_nan_inf(self):
  1790. vals = [np.nan, -np.inf, np.inf]
  1791. expected = [np.nan, -np.inf, np.inf]
  1792. assert_allclose(special.erfi(vals), expected, rtol=1e-15)
  1793. def test_dawsn_nan_inf(self):
  1794. vals = [np.nan, -np.inf, np.inf]
  1795. expected = [np.nan, -0.0, 0.0]
  1796. assert_allclose(special.dawsn(vals), expected, rtol=1e-15)
  1797. def test_wofz_nan_inf(self):
  1798. vals = [np.nan, -np.inf, np.inf]
  1799. expected = [np.nan + np.nan * 1.j, 0.-0.j, 0.+0.j]
  1800. assert_allclose(special.wofz(vals), expected, rtol=1e-15)
  1801. class TestEuler:
  1802. def test_euler(self):
  1803. eu0 = special.euler(0)
  1804. eu1 = special.euler(1)
  1805. eu2 = special.euler(2) # just checking segfaults
  1806. assert_allclose(eu0, [1], rtol=1e-15)
  1807. assert_allclose(eu1, [1, 0], rtol=1e-15)
  1808. assert_allclose(eu2, [1, 0, -1], rtol=1e-15)
  1809. eu24 = special.euler(24)
  1810. mathworld = [1,1,5,61,1385,50521,2702765,199360981,
  1811. 19391512145,2404879675441,
  1812. 370371188237525,69348874393137901,
  1813. 15514534163557086905]
  1814. correct = zeros((25,),'d')
  1815. for k in range(0,13):
  1816. if (k % 2):
  1817. correct[2*k] = -float(mathworld[k])
  1818. else:
  1819. correct[2*k] = float(mathworld[k])
  1820. with np.errstate(all='ignore'):
  1821. err = nan_to_num((eu24-correct)/correct)
  1822. errmax = max(err)
  1823. assert_allclose(errmax, 0.0, atol=1.5e-14, rtol=0)
  1824. class TestExp:
  1825. def test_exp2(self):
  1826. ex = special.exp2(2)
  1827. exrl = 2**2
  1828. assert_equal(ex,exrl)
  1829. def test_exp2more(self):
  1830. exm = special.exp2(2.5)
  1831. exmrl = 2**(2.5)
  1832. assert_allclose(exm, exmrl, atol=1.5e-8, rtol=0)
  1833. def test_exp10(self):
  1834. ex = special.exp10(2)
  1835. exrl = 10**2
  1836. assert_allclose(ex, exrl, atol=1e-6, rtol=0)
  1837. def test_exp10more(self):
  1838. exm = special.exp10(2.5)
  1839. exmrl = 10**(2.5)
  1840. assert_allclose(exm, exmrl, atol=1.5e-8, rtol=0)
  1841. def test_expm1(self):
  1842. ex = (special.expm1(2), special.expm1(3), special.expm1(4))
  1843. exrl = (exp(2) - 1, exp(3) - 1, exp(4) - 1)
  1844. assert_allclose(ex, exrl, atol=1.5e-8, rtol=0)
  1845. def test_expm1more(self):
  1846. ex1 = (special.expm1(2), special.expm1(2.1), special.expm1(2.2))
  1847. exrl1 = (exp(2) - 1, exp(2.1) - 1, exp(2.2) - 1)
  1848. assert_allclose(ex1, exrl1, atol=1.5e-8, rtol=0)
  1849. def assert_really_equal(x, y, rtol=None):
  1850. """
  1851. Sharper assertion function that is stricter about matching types, not just values
  1852. This is useful/necessary in some cases:
  1853. * dtypes for arrays that have the same _values_ (e.g. element 1.0 vs 1)
  1854. * distinguishing complex from real NaN
  1855. * result types for scalars
  1856. We still want to be able to allow a relative tolerance for the values though.
  1857. The main logic comparison logic is handled by the xp_assert_* functions.
  1858. """
  1859. def assert_func(x, y):
  1860. xp_assert_equal(x, y) if rtol is None else xp_assert_close(x, y, rtol=rtol)
  1861. def assert_complex_nan(x):
  1862. assert np.isnan(x.real) and np.isnan(x.imag)
  1863. assert type(x) is type(y), f"types not equal: {type(x)}, {type(y)}"
  1864. # ensure we also compare the values _within_ an array appropriately,
  1865. # e.g. assert_equal does not distinguish different complex nans in arrays
  1866. if isinstance(x, np.ndarray):
  1867. # assert_equal does not compare (all) types, only values
  1868. assert x.dtype == y.dtype
  1869. # for empty arrays resp. to ensure shapes match
  1870. assert_func(x, y)
  1871. for elem_x, elem_y in zip(x.ravel(), y.ravel()):
  1872. assert_really_equal(elem_x, elem_y, rtol=rtol)
  1873. elif np.isnan(x) and np.isnan(y) and _is_subdtype(type(x), "c"):
  1874. assert_complex_nan(x) and assert_complex_nan(y)
  1875. # no need to consider complex infinities due to numpy/numpy#25493
  1876. else:
  1877. assert_func(x, y)
  1878. class TestFactorialFunctions:
  1879. def factorialk_ref(self, n, k, exact, extend):
  1880. if exact:
  1881. return special.factorialk(n, k=k, exact=True)
  1882. # for details / explanation see factorialk-docstring
  1883. r = np.mod(n, k) if extend == "zero" else 1
  1884. vals = np.power(k, (n - r)/k) * special.gamma(n/k + 1) * special.rgamma(r/k + 1)
  1885. # np.maximum is element-wise, which is what we want
  1886. return vals * np.maximum(r, 1)
  1887. @pytest.mark.parametrize("exact,extend",
  1888. [(True, "zero"), (False, "zero"), (False, "complex")])
  1889. def test_factorialx_scalar_return_type(self, exact, extend):
  1890. kw = {"exact": exact, "extend": extend}
  1891. assert np.isscalar(special.factorial(1, **kw))
  1892. assert np.isscalar(special.factorial2(1, **kw))
  1893. assert np.isscalar(special.factorialk(1, k=3, **kw))
  1894. @pytest.mark.parametrize("n", [-1, -2, -3])
  1895. @pytest.mark.parametrize("exact", [True, False])
  1896. def test_factorialx_negative_extend_zero(self, exact, n):
  1897. kw = {"exact": exact}
  1898. assert_equal(special.factorial(n, **kw), 0)
  1899. assert_equal(special.factorial2(n, **kw), 0)
  1900. assert_equal(special.factorialk(n, k=3, **kw), 0)
  1901. @pytest.mark.parametrize("exact", [True, False])
  1902. def test_factorialx_negative_extend_zero_array(self, exact):
  1903. kw = {"exact": exact}
  1904. rtol = 1e-15
  1905. n = [-5, -4, 0, 1]
  1906. # Consistent output for n < 0
  1907. expected = np.array([0, 0, 1, 1], dtype=native_int if exact else np.float64)
  1908. assert_really_equal(special.factorial(n, **kw), expected, rtol=rtol)
  1909. assert_really_equal(special.factorial2(n, **kw), expected, rtol=rtol)
  1910. assert_really_equal(special.factorialk(n, k=3, **kw), expected, rtol=rtol)
  1911. @pytest.mark.parametrize("n", [-1.1, -2.2, -3.3])
  1912. def test_factorialx_negative_extend_complex(self, n):
  1913. kw = {"extend": "complex"}
  1914. exp_1 = {-1.1: -10.686287021193184771,
  1915. -2.2: 4.8509571405220931958,
  1916. -3.3: -1.4471073942559181166}
  1917. exp_2 = {-1.1: 1.0725776858167496309,
  1918. -2.2: -3.9777171783768419874,
  1919. -3.3: -0.99588841846200555977}
  1920. exp_k = {-1.1: 0.73565345382163025659,
  1921. -2.2: 1.1749163167190809498,
  1922. -3.3: -2.4780584257450583713}
  1923. rtol = 3e-15
  1924. assert_allclose(special.factorial(n, **kw), exp_1[n], rtol=rtol)
  1925. assert_allclose(special.factorial2(n, **kw), exp_2[n], rtol=rtol)
  1926. assert_allclose(special.factorialk(n, k=3, **kw), exp_k[n], rtol=rtol)
  1927. assert_allclose(special.factorial([n], **kw)[0], exp_1[n], rtol=rtol)
  1928. assert_allclose(special.factorial2([n], **kw)[0], exp_2[n], rtol=rtol)
  1929. assert_allclose(special.factorialk([n], k=3, **kw)[0], exp_k[n], rtol=rtol)
  1930. @pytest.mark.parametrize("imag", [0, 0j])
  1931. @pytest.mark.parametrize("n_outer", [-1, -2, -3])
  1932. def test_factorialx_negative_extend_complex_poles(self, n_outer, imag):
  1933. kw = {"extend": "complex"}
  1934. def _check(n):
  1935. complexify = _is_subdtype(type(n), "c")
  1936. # like for gamma, we expect complex nans for complex inputs
  1937. complex_nan = np.complex128("nan+nanj")
  1938. exp = np.complex128("nan+nanj") if complexify else np.float64("nan")
  1939. # poles are at negative integers that are multiples of k
  1940. assert_really_equal(special.factorial(n, **kw), exp)
  1941. assert_really_equal(special.factorial2(n * 2, **kw), exp)
  1942. assert_really_equal(special.factorialk(n * 3, k=3, **kw), exp)
  1943. # also test complex k for factorialk
  1944. c = 1.5 - 2j
  1945. assert_really_equal(special.factorialk(n * c, k=c, **kw), complex_nan)
  1946. # same for array case
  1947. assert_really_equal(special.factorial([n], **kw)[0], exp)
  1948. assert_really_equal(special.factorial2([n * 2], **kw)[0], exp)
  1949. assert_really_equal(special.factorialk([n * 3], k=3, **kw)[0], exp)
  1950. assert_really_equal(special.factorialk([n * c], k=c, **kw)[0], complex_nan)
  1951. # more specific tests in test_factorial{,2,k}_complex_reference
  1952. # imag ensures we test both real and complex representations of the poles
  1953. _check(n_outer + imag)
  1954. # check for large multiple of period
  1955. _check(100_000 * n_outer + imag)
  1956. @pytest.mark.parametrize("boxed", [True, False])
  1957. @pytest.mark.parametrize("extend", ["zero", "complex"])
  1958. @pytest.mark.parametrize(
  1959. "n",
  1960. [
  1961. np.nan, np.float64("nan"), np.nan + np.nan*1j, np.complex128("nan+nanj"),
  1962. np.inf, np.inf + 0j, -np.inf, -np.inf + 0j, None, np.datetime64("nat")
  1963. ],
  1964. ids=[
  1965. "NaN", "np.float64('nan')", "NaN+i*NaN", "np.complex128('nan+nanj')",
  1966. "inf", "inf+0i", "-inf", "-inf+0i", "None", "NaT"
  1967. ]
  1968. )
  1969. @pytest.mark.parametrize(
  1970. "factorialx",
  1971. [special.factorial, special.factorial2, special.factorialk]
  1972. )
  1973. def test_factorialx_inf_nan(self, factorialx, n, extend, boxed):
  1974. # NaNs not allowed (by dtype) for exact=True
  1975. kw = {"exact": False, "extend": extend}
  1976. if factorialx == special.factorialk:
  1977. kw["k"] = 3
  1978. # None is allowed for scalars, but would cause object type in array case
  1979. permissible_types = ["i", "f", "c"] if boxed else ["i", "f", "c", type(None)]
  1980. # factorial allows floats also for extend="zero"
  1981. types_need_complex_ext = "c" if factorialx == special.factorial else ["f", "c"]
  1982. if not _is_subdtype(type(n), permissible_types):
  1983. with pytest.raises(ValueError, match="Unsupported data type.*"):
  1984. factorialx([n] if boxed else n, **kw)
  1985. elif _is_subdtype(type(n), types_need_complex_ext) and extend != "complex":
  1986. with pytest.raises(ValueError, match="In order to use non-integer.*"):
  1987. factorialx([n] if boxed else n, **kw)
  1988. else:
  1989. # account for type and whether extend="complex"
  1990. complexify = (extend == "complex") and _is_subdtype(type(n), "c")
  1991. # note that the type of the naïve `np.nan + np.nan * 1j` is `complex`
  1992. # instead of `numpy.complex128`, which trips up assert_really_equal
  1993. expected = np.complex128("nan+nanj") if complexify else np.float64("nan")
  1994. # the only exception are real infinities
  1995. if _is_subdtype(type(n), "f") and np.isinf(n):
  1996. # unchanged for positive infinity; negative one depends on extension
  1997. neg_inf_result = np.float64(0 if (extend == "zero") else "nan")
  1998. expected = np.float64("inf") if (n > 0) else neg_inf_result
  1999. result = factorialx([n], **kw)[0] if boxed else factorialx(n, **kw)
  2000. assert_really_equal(result, expected)
  2001. # also tested in test_factorial{,2,k}_{array,scalar}_corner_cases
  2002. @pytest.mark.parametrize("extend", [0, 1.1, np.nan, "string"])
  2003. def test_factorialx_raises_extend(self, extend):
  2004. with pytest.raises(ValueError, match="argument `extend` must be.*"):
  2005. special.factorial(1, extend=extend)
  2006. with pytest.raises(ValueError, match="argument `extend` must be.*"):
  2007. special.factorial2(1, extend=extend)
  2008. with pytest.raises(ValueError, match="argument `extend` must be.*"):
  2009. special.factorialk(1, k=3, exact=True, extend=extend)
  2010. @pytest.mark.parametrize("levels", range(1, 5))
  2011. @pytest.mark.parametrize("exact", [True, False])
  2012. def test_factorialx_array_shape(self, levels, exact):
  2013. def _nest_me(x, k=1):
  2014. """
  2015. Double x and nest it k times
  2016. For example:
  2017. >>> _nest_me([3, 4], 2)
  2018. [[[3, 4], [3, 4]], [[3, 4], [3, 4]]]
  2019. """
  2020. if k == 0:
  2021. return x
  2022. else:
  2023. return _nest_me([x, x], k-1)
  2024. def _check(res, nucleus):
  2025. exp = np.array(_nest_me(nucleus, k=levels), dtype=object)
  2026. # test that ndarray shape is maintained
  2027. # need to cast to float due to numpy/numpy#21220
  2028. assert_allclose(res.astype(np.float64), exp.astype(np.float64))
  2029. n = np.array(_nest_me([5, 25], k=levels))
  2030. exp_nucleus = {1: [120, math.factorial(25)],
  2031. # correctness of factorial{2,k}() is tested elsewhere
  2032. 2: [15, special.factorial2(25, exact=True)],
  2033. 3: [10, special.factorialk(25, 3, exact=True)]}
  2034. _check(special.factorial(n, exact=exact), exp_nucleus[1])
  2035. _check(special.factorial2(n, exact=exact), exp_nucleus[2])
  2036. _check(special.factorialk(n, 3, exact=exact), exp_nucleus[3])
  2037. @pytest.mark.parametrize("exact", [True, False])
  2038. @pytest.mark.parametrize("dtype", [
  2039. None, int, np.int8, np.int16, np.int32, np.int64,
  2040. np.uint8, np.uint16, np.uint32, np.uint64
  2041. ])
  2042. @pytest.mark.parametrize("dim", range(0, 5))
  2043. def test_factorialx_array_dimension(self, dim, dtype, exact):
  2044. n = np.array(5, dtype=dtype, ndmin=dim)
  2045. exp = {1: 120, 2: 15, 3: 10}
  2046. assert_allclose(special.factorial(n, exact=exact),
  2047. np.array(exp[1], ndmin=dim))
  2048. assert_allclose(special.factorial2(n, exact=exact),
  2049. np.array(exp[2], ndmin=dim))
  2050. assert_allclose(special.factorialk(n, 3, exact=exact),
  2051. np.array(exp[3], ndmin=dim))
  2052. @pytest.mark.parametrize("exact", [True, False])
  2053. @pytest.mark.parametrize("level", range(1, 5))
  2054. def test_factorialx_array_like(self, level, exact):
  2055. def _nest_me(x, k=1):
  2056. if k == 0:
  2057. return x
  2058. else:
  2059. return _nest_me([x], k-1)
  2060. n = _nest_me([5], k=level-1) # nested list
  2061. exp_nucleus = {1: 120, 2: 15, 3: 10}
  2062. assert_func = assert_array_equal if exact else assert_allclose
  2063. assert_func(special.factorial(n, exact=exact),
  2064. np.array(exp_nucleus[1], ndmin=level))
  2065. assert_func(special.factorial2(n, exact=exact),
  2066. np.array(exp_nucleus[2], ndmin=level))
  2067. assert_func(special.factorialk(n, 3, exact=exact),
  2068. np.array(exp_nucleus[3], ndmin=level))
  2069. @pytest.mark.fail_slow(5)
  2070. @pytest.mark.parametrize("dtype", [np.uint8, np.uint16, np.uint32, np.uint64])
  2071. @pytest.mark.parametrize("exact,extend",
  2072. [(True, "zero"), (False, "zero"), (False, "complex")])
  2073. def test_factorialx_uint(self, exact, extend, dtype):
  2074. # ensure that uint types work correctly as inputs
  2075. kw = {"exact": exact, "extend": extend}
  2076. assert_func = assert_array_equal if exact else assert_allclose
  2077. def _check(n):
  2078. n_ref = n.astype(np.int64) if isinstance(n, np.ndarray) else np.int64(n)
  2079. assert_func(special.factorial(n, **kw), special.factorial(n_ref, **kw))
  2080. assert_func(special.factorial2(n, **kw), special.factorial2(n_ref, **kw))
  2081. assert_func(special.factorialk(n, k=3, **kw),
  2082. special.factorialk(n_ref, k=3, **kw))
  2083. def _check_inf(n):
  2084. # produce inf of same type/dimension
  2085. with warnings.catch_warnings():
  2086. warnings.simplefilter("ignore", RuntimeWarning)
  2087. shaped_inf = n / 0
  2088. assert_func(special.factorial(n, **kw), shaped_inf)
  2089. assert_func(special.factorial2(n, **kw), shaped_inf)
  2090. assert_func(special.factorialk(n, k=3, **kw), shaped_inf)
  2091. _check(dtype(0))
  2092. _check(dtype(1))
  2093. _check(np.array(0, dtype=dtype))
  2094. _check(np.array([0, 1], dtype=dtype))
  2095. # test that maximal uint values work as well
  2096. N = dtype(np.iinfo(dtype).max)
  2097. # TODO: cannot use N itself yet; factorial uses `gamma(N+1)` resp. `(hi+lo)//2`
  2098. if dtype == np.uint64:
  2099. if exact:
  2100. # avoid attempting huge calculation
  2101. pass
  2102. elif np.lib.NumpyVersion(np.__version__) >= "2.0.0":
  2103. # N does not fit into int64 --> cannot use _check
  2104. _check_inf(dtype(N-1))
  2105. _check_inf(np.array(N-1, dtype=dtype))
  2106. _check_inf(np.array([N-1], dtype=dtype))
  2107. elif dtype in [np.uint8, np.uint16] or not exact:
  2108. # factorial(65535, exact=True) has 287189 digits and is calculated almost
  2109. # instantaneously on modern hardware; however, dtypes bigger than uint16
  2110. # would blow up runtime and memory consumption for exact=True
  2111. _check(N-1)
  2112. _check(np.array(N-1, dtype=dtype))
  2113. _check(np.array([N-2, N-1], dtype=dtype))
  2114. # note that n=170 is the last integer such that factorial(n) fits float64
  2115. @pytest.mark.parametrize('n', range(30, 180, 10))
  2116. def test_factorial_accuracy(self, n):
  2117. # Compare exact=True vs False, i.e. that the accuracy of the
  2118. # approximation is better than the specified tolerance.
  2119. rtol = 6e-14 if sys.platform == 'win32' else 1e-15
  2120. # need to cast exact result to float due to numpy/numpy#21220
  2121. assert_allclose(float(special.factorial(n, exact=True)),
  2122. special.factorial(n, exact=False), rtol=rtol)
  2123. assert_allclose(special.factorial([n], exact=True).astype(float),
  2124. special.factorial([n], exact=False), rtol=rtol)
  2125. @pytest.mark.parametrize('n',
  2126. list(range(0, 22)) + list(range(30, 180, 10)))
  2127. def test_factorial_int_reference(self, n):
  2128. # Compare all with math.factorial
  2129. correct = math.factorial(n)
  2130. assert_array_equal(correct, special.factorial(n, exact=True))
  2131. assert_array_equal(correct, special.factorial([n], exact=True)[0])
  2132. rtol = 8e-14 if sys.platform == 'win32' else 1e-15
  2133. # need to cast exact result to float due to numpy/numpy#21220
  2134. correct = float(correct)
  2135. assert_allclose(correct, special.factorial(n, exact=False), rtol=rtol)
  2136. assert_allclose(correct, special.factorial([n], exact=False)[0], rtol=rtol)
  2137. # extend="complex" only works for exact=False
  2138. kw = {"exact": False, "extend": "complex"}
  2139. assert_allclose(correct, special.factorial(n, **kw), rtol=rtol)
  2140. assert_allclose(correct, special.factorial([n], **kw)[0], rtol=rtol)
  2141. def test_factorial_float_reference(self):
  2142. def _check(n, expected):
  2143. rtol = 8e-14 if sys.platform == 'win32' else 1e-15
  2144. assert_allclose(special.factorial(n), expected, rtol=rtol)
  2145. assert_allclose(special.factorial([n])[0], expected, rtol=rtol)
  2146. # using floats with `exact=True` raises an error for scalars and arrays
  2147. with pytest.raises(ValueError, match="`exact=True` only supports.*"):
  2148. special.factorial(n, exact=True)
  2149. with pytest.raises(ValueError, match="`exact=True` only supports.*"):
  2150. special.factorial([n], exact=True)
  2151. # Reference values from mpmath for gamma(n+1)
  2152. _check(0.01, 0.994325851191506032181932988)
  2153. _check(1.11, 1.051609009483625091514147465)
  2154. _check(5.55, 314.9503192327208241614959052)
  2155. _check(11.1, 50983227.84411615655137170553)
  2156. _check(33.3, 2.493363339642036352229215273e+37)
  2157. _check(55.5, 9.479934358436729043289162027e+73)
  2158. _check(77.7, 3.060540559059579022358692625e+114)
  2159. _check(99.9, 5.885840419492871504575693337e+157)
  2160. # close to maximum for float64
  2161. _check(170.6243, 1.79698185749571048960082e+308)
  2162. def test_factorial_complex_reference(self):
  2163. def _check(n, expected):
  2164. rtol = 3e-15 if sys.platform == 'win32' else 2e-15
  2165. kw = {"exact": False, "extend": "complex"}
  2166. assert_allclose(special.factorial(n, **kw), expected, rtol=rtol)
  2167. assert_allclose(special.factorial([n], **kw)[0], expected, rtol=rtol)
  2168. # Reference values from mpmath.gamma(n+1)
  2169. # negative & complex values
  2170. _check(-0.5, expected=1.7724538509055160276)
  2171. _check(-0.5 + 0j, expected=1.7724538509055160276 + 0j)
  2172. _check(2 + 2j, expected=-0.42263728631120216694 + 0.87181425569650686062j)
  2173. # close to poles
  2174. _check(-0.9999, expected=9999.422883232725532)
  2175. _check(-1 + 0.0001j, expected=-0.57721565582674219 - 9999.9999010944009697j)
  2176. @pytest.mark.parametrize("dtype", [np.int64, np.float64,
  2177. np.complex128, object])
  2178. @pytest.mark.parametrize("extend", ["zero", "complex"])
  2179. @pytest.mark.parametrize("exact", [True, False])
  2180. @pytest.mark.parametrize("dim", range(0, 5))
  2181. # test empty & non-empty arrays, with nans and mixed
  2182. @pytest.mark.parametrize(
  2183. "content",
  2184. [[], [1], [1.1], [np.nan], [np.nan + np.nan * 1j], [np.nan, 1]],
  2185. ids=["[]", "[1]", "[1.1]", "[NaN]", "[NaN+i*NaN]", "[NaN, 1]"],
  2186. )
  2187. def test_factorial_array_corner_cases(self, content, dim, exact, extend, dtype):
  2188. if dtype is object and SCIPY_ARRAY_API:
  2189. pytest.skip("object arrays unsupported in array API mode")
  2190. # get dtype without calling array constructor (that might fail or mutate)
  2191. if dtype is np.int64 and any(np.isnan(x) or (x != int(x)) for x in content):
  2192. pytest.skip("impossible combination")
  2193. if dtype == np.float64 and any(_is_subdtype(type(x), "c") for x in content):
  2194. pytest.skip("impossible combination")
  2195. kw = {"exact": exact, "extend": extend}
  2196. # np.array(x, ndim=0) will not be 0-dim. unless x is too
  2197. content = content if (dim > 0 or len(content) != 1) else content[0]
  2198. n = np.array(content, ndmin=dim, dtype=dtype)
  2199. result = None
  2200. if extend == "complex" and exact:
  2201. with pytest.raises(ValueError, match="Incompatible options:.*"):
  2202. special.factorial(n, **kw)
  2203. elif not _is_subdtype(n.dtype, ["i", "f", "c"]):
  2204. with pytest.raises(ValueError, match="Unsupported data type.*"):
  2205. special.factorial(n, **kw)
  2206. elif _is_subdtype(n.dtype, "c") and extend != "complex":
  2207. with pytest.raises(ValueError, match="In order to use non-integer.*"):
  2208. special.factorial(n, **kw)
  2209. elif exact and not _is_subdtype(n.dtype, "i"):
  2210. with pytest.raises(ValueError, match="`exact=True` only supports.*"):
  2211. special.factorial(n, **kw)
  2212. else:
  2213. result = special.factorial(n, **kw)
  2214. if result is not None:
  2215. # use scalar case as reference; tested separately in *_scalar_corner_cases
  2216. ref = [special.factorial(x, **kw) for x in n.ravel()]
  2217. # unpack length-1 lists so that np.array(x, ndim=0) works correctly
  2218. ref = ref[0] if len(ref) == 1 else ref
  2219. # result is empty if and only if n is empty, and has the same dimension
  2220. # as n; dtype stays the same, except when not empty and not exact:
  2221. if n.size:
  2222. cx = (extend == "complex") and _is_subdtype(n.dtype, "c")
  2223. dtype = np.complex128 if cx else (native_int if exact else np.float64)
  2224. expected = np.array(ref, ndmin=dim, dtype=dtype)
  2225. assert_really_equal(result, expected, rtol=1e-15)
  2226. @pytest.mark.parametrize("extend", ["zero", "complex"])
  2227. @pytest.mark.parametrize("exact", [True, False])
  2228. @pytest.mark.parametrize("n", [1, 1.1, 2 + 2j, np.nan, np.nan + np.nan*1j, None],
  2229. ids=["1", "1.1", "2+2j", "NaN", "NaN+i*NaN", "None"])
  2230. def test_factorial_scalar_corner_cases(self, n, exact, extend):
  2231. kw = {"exact": exact, "extend": extend}
  2232. if extend == "complex" and exact:
  2233. with pytest.raises(ValueError, match="Incompatible options:.*"):
  2234. special.factorial(n, **kw)
  2235. elif not _is_subdtype(type(n), ["i", "f", "c", type(None)]):
  2236. with pytest.raises(ValueError, match="Unsupported data type.*"):
  2237. special.factorial(n, **kw)
  2238. elif _is_subdtype(type(n), "c") and extend != "complex":
  2239. with pytest.raises(ValueError, match="In order to use non-integer.*"):
  2240. special.factorial(n, **kw)
  2241. elif n is None or np.isnan(n):
  2242. # account for dtype and whether extend="complex"
  2243. complexify = (extend == "complex") and _is_subdtype(type(n), "c")
  2244. expected = np.complex128("nan+nanj") if complexify else np.float64("nan")
  2245. assert_really_equal(special.factorial(n, **kw), expected)
  2246. elif exact and _is_subdtype(type(n), "f"):
  2247. with pytest.raises(ValueError, match="`exact=True` only supports.*"):
  2248. special.factorial(n, **kw)
  2249. else:
  2250. assert_equal(special.factorial(n, **kw), special.gamma(n + 1))
  2251. # use odd increment to make sure both odd & even numbers are tested!
  2252. @pytest.mark.parametrize('n', range(30, 180, 11))
  2253. def test_factorial2_accuracy(self, n):
  2254. # Compare exact=True vs False, i.e. that the accuracy of the
  2255. # approximation is better than the specified tolerance.
  2256. rtol = 2e-14 if sys.platform == 'win32' else 1e-15
  2257. # need to cast exact result to float due to numpy/numpy#21220
  2258. assert_allclose(float(special.factorial2(n, exact=True)),
  2259. special.factorial2(n, exact=False), rtol=rtol)
  2260. assert_allclose(special.factorial2([n], exact=True).astype(float),
  2261. special.factorial2([n], exact=False), rtol=rtol)
  2262. @pytest.mark.parametrize('n',
  2263. list(range(0, 22)) + list(range(30, 180, 11)))
  2264. def test_factorial2_int_reference(self, n):
  2265. # Compare all with correct value
  2266. # Cannot use np.product due to overflow
  2267. correct = functools.reduce(operator.mul, list(range(n, 0, -2)), 1)
  2268. assert_array_equal(correct, special.factorial2(n, exact=True))
  2269. assert_array_equal(correct, special.factorial2([n], exact=True)[0])
  2270. rtol = 2e-14 if sys.platform == 'win32' else 1e-15
  2271. # need to cast exact result to float due to numpy/numpy#21220
  2272. correct = float(correct)
  2273. assert_allclose(correct, special.factorial2(n, exact=False), rtol=rtol)
  2274. assert_allclose(correct, special.factorial2([n], exact=False)[0], rtol=rtol)
  2275. # extend="complex" only works for exact=False
  2276. kw = {"exact": False, "extend": "complex"}
  2277. # approximation only matches exactly for `n == 1 (mod k)`, see docstring
  2278. if n % 2 == 1:
  2279. assert_allclose(correct, special.factorial2(n, **kw), rtol=rtol)
  2280. assert_allclose(correct, special.factorial2([n], **kw)[0], rtol=rtol)
  2281. def test_factorial2_complex_reference(self):
  2282. # this tests for both floats and complex
  2283. def _check(n, expected):
  2284. rtol = 5e-15
  2285. kw = {"exact": False, "extend": "complex"}
  2286. assert_allclose(special.factorial2(n, **kw), expected, rtol=rtol)
  2287. assert_allclose(special.factorial2([n], **kw)[0], expected, rtol=rtol)
  2288. # Reference values from mpmath for:
  2289. # mpmath.power(2, n/2) * mpmath.gamma(n/2 + 1) * mpmath.sqrt(2 / mpmath.pi)
  2290. _check(3, expected=3)
  2291. _check(4, expected=special.factorial2(4) * math.sqrt(2 / math.pi))
  2292. _check(20, expected=special.factorial2(20) * math.sqrt(2 / math.pi))
  2293. # negative & complex values
  2294. _check(-0.5, expected=0.82217895866245855122)
  2295. _check(-0.5 + 0j, expected=0.82217895866245855122 + 0j)
  2296. _check(3 + 3j, expected=-1.0742236630142471526 + 1.4421398439387262897j)
  2297. # close to poles
  2298. _check(-1.9999, expected=7978.8918745523440682)
  2299. _check(-2 + 0.0001j, expected=0.0462499835314308444 - 7978.84559148876374493j)
  2300. @pytest.mark.parametrize("dtype", [np.int64, np.float64,
  2301. np.complex128, object])
  2302. @pytest.mark.parametrize("extend", ["zero", "complex"])
  2303. @pytest.mark.parametrize("exact", [True, False])
  2304. @pytest.mark.parametrize("dim", range(0, 5))
  2305. # test empty & non-empty arrays, with nans and mixed
  2306. @pytest.mark.parametrize(
  2307. "content",
  2308. [[], [1], [1.1], [np.nan], [np.nan + np.nan * 1j], [np.nan, 1]],
  2309. ids=["[]", "[1]", "[1.1]", "[NaN]", "[NaN+i*NaN]", "[NaN, 1]"],
  2310. )
  2311. def test_factorial2_array_corner_cases(self, content, dim, exact, extend, dtype):
  2312. # get dtype without calling array constructor (that might fail or mutate)
  2313. if dtype == np.int64 and any(np.isnan(x) or (x != int(x)) for x in content):
  2314. pytest.skip("impossible combination")
  2315. if dtype == np.float64 and any(_is_subdtype(type(x), "c") for x in content):
  2316. pytest.skip("impossible combination")
  2317. kw = {"exact": exact, "extend": extend}
  2318. # np.array(x, ndim=0) will not be 0-dim. unless x is too
  2319. content = content if (dim > 0 or len(content) != 1) else content[0]
  2320. n = np.array(content, ndmin=dim, dtype=dtype)
  2321. result = None
  2322. if extend == "complex" and exact:
  2323. with pytest.raises(ValueError, match="Incompatible options:.*"):
  2324. special.factorial2(n, **kw)
  2325. elif not _is_subdtype(n.dtype, ["i", "f", "c"]):
  2326. with pytest.raises(ValueError, match="Unsupported data type.*"):
  2327. special.factorial2(n, **kw)
  2328. elif _is_subdtype(n.dtype, ["f", "c"]) and extend != "complex":
  2329. with pytest.raises(ValueError, match="In order to use non-integer.*"):
  2330. special.factorial2(n, **kw)
  2331. else:
  2332. result = special.factorial2(n, **kw)
  2333. if result is not None:
  2334. # use scalar case as reference; tested separately in *_scalar_corner_cases
  2335. ref = [special.factorial2(x, **kw) for x in n.ravel()]
  2336. # unpack length-1 lists so that np.array(x, ndim=0) works correctly
  2337. ref = ref[0] if len(ref) == 1 else ref
  2338. # result is empty if and only if n is empty, and has the same dimension
  2339. # as n; dtype stays the same, except when not empty and not exact:
  2340. if n.size:
  2341. cx = (extend == "complex") and _is_subdtype(n.dtype, "c")
  2342. dtype = np.complex128 if cx else (native_int if exact else np.float64)
  2343. expected = np.array(ref, ndmin=dim, dtype=dtype)
  2344. assert_really_equal(result, expected, rtol=2e-15)
  2345. @pytest.mark.parametrize("extend", ["zero", "complex"])
  2346. @pytest.mark.parametrize("exact", [True, False])
  2347. @pytest.mark.parametrize("n", [1, 1.1, 2 + 2j, np.nan, np.nan + np.nan*1j, None],
  2348. ids=["1", "1.1", "2+2j", "NaN", "NaN+i*NaN", "None"])
  2349. def test_factorial2_scalar_corner_cases(self, n, exact, extend):
  2350. kw = {"exact": exact, "extend": extend}
  2351. if extend == "complex" and exact:
  2352. with pytest.raises(ValueError, match="Incompatible options:.*"):
  2353. special.factorial2(n, **kw)
  2354. elif not _is_subdtype(type(n), ["i", "f", "c", type(None)]):
  2355. with pytest.raises(ValueError, match="Unsupported data type.*"):
  2356. special.factorial2(n, **kw)
  2357. elif _is_subdtype(type(n), ["f", "c"]) and extend != "complex":
  2358. with pytest.raises(ValueError, match="In order to use non-integer.*"):
  2359. special.factorial2(n, **kw)
  2360. elif n is None or np.isnan(n):
  2361. # account for dtype and whether extend="complex"
  2362. complexify = (extend == "complex") and _is_subdtype(type(n), "c")
  2363. expected = np.complex128("nan+nanj") if complexify else np.float64("nan")
  2364. assert_really_equal(special.factorial2(n, **kw), expected)
  2365. else:
  2366. expected = self.factorialk_ref(n, k=2, **kw)
  2367. assert_really_equal(special.factorial2(n, **kw), expected, rtol=1e-15)
  2368. @pytest.mark.parametrize("k", range(1, 5))
  2369. # note that n=170 is the last integer such that factorial(n) fits float64;
  2370. # use odd increment to make sure both odd & even numbers are tested
  2371. @pytest.mark.parametrize('n', range(170, 20, -29))
  2372. def test_factorialk_accuracy(self, n, k):
  2373. # Compare exact=True vs False, i.e. that the accuracy of the
  2374. # approximation is better than the specified tolerance.
  2375. rtol = 6e-14 if sys.platform == 'win32' else 2e-14
  2376. # need to cast exact result to float due to numpy/numpy#21220
  2377. assert_allclose(float(special.factorialk(n, k=k, exact=True)),
  2378. special.factorialk(n, k=k, exact=False), rtol=rtol)
  2379. assert_allclose(special.factorialk([n], k=k, exact=True).astype(float),
  2380. special.factorialk([n], k=k, exact=False), rtol=rtol)
  2381. @pytest.mark.parametrize('k', list(range(1, 5)) + [10, 20])
  2382. @pytest.mark.parametrize('n',
  2383. list(range(0, 22)) + list(range(22, 100, 11)))
  2384. def test_factorialk_int_reference(self, n, k):
  2385. # Compare all with correct value
  2386. # Would be nice to use np.product here, but that's
  2387. # broken on windows, see numpy/numpy#21219
  2388. correct = functools.reduce(operator.mul, list(range(n, 0, -k)), 1)
  2389. assert_array_equal(correct, special.factorialk(n, k, exact=True))
  2390. assert_array_equal(correct, special.factorialk([n], k, exact=True)[0])
  2391. rtol = 3e-14 if sys.platform == 'win32' else 1e-14
  2392. # need to cast exact result to float due to numpy/numpy#21220
  2393. correct = float(correct)
  2394. assert_allclose(correct, special.factorialk(n, k, exact=False), rtol=rtol)
  2395. assert_allclose(correct, special.factorialk([n], k, exact=False)[0], rtol=rtol)
  2396. # extend="complex" only works for exact=False
  2397. kw = {"k": k, "exact": False, "extend": "complex"}
  2398. # approximation only matches exactly for `n == 1 (mod k)`, see docstring
  2399. if n % k == 1:
  2400. rtol = 2e-14
  2401. assert_allclose(correct, special.factorialk(n, **kw), rtol=rtol)
  2402. assert_allclose(correct, special.factorialk([n], **kw)[0], rtol=rtol)
  2403. def test_factorialk_complex_reference(self):
  2404. # this tests for both floats and complex
  2405. def _check(n, k, exp):
  2406. rtol = 1e-14
  2407. kw = {"k": k, "exact": False, "extend": "complex"}
  2408. assert_allclose(special.factorialk(n, **kw), exp, rtol=rtol)
  2409. assert_allclose(special.factorialk([n], **kw)[0], exp, rtol=rtol)
  2410. # Reference values from mpmath for:
  2411. # mpmath.power(k, (n-1)/k) * mpmath.gamma(n/k + 1) / mpmath.gamma(1/k + 1)
  2412. _check(n=4, k=3, exp=special.factorialk(4, k=3, exact=True))
  2413. _check(n=5, k=3, exp=7.29011132947227083)
  2414. _check(n=6.5, k=3, exp=19.6805080113566010)
  2415. # non-integer k
  2416. _check(n=3, k=2.5, exp=2.58465740293218541)
  2417. _check(n=11, k=2.5, exp=1963.5) # ==11*8.5*6*3.5; c.f. n == 1 (mod k)
  2418. _check(n=-3 + 3j + 1, k=-3 + 3j, exp=-2 + 3j)
  2419. # complex values
  2420. _check(n=4 + 4j, k=4, exp=-0.67855904082768043854 + 2.1993925819930311497j)
  2421. _check(n=4, k=4 - 4j, exp=1.9775338957222718742 + 0.92607172675423901371j)
  2422. _check(n=4 + 4j, k=4 - 4j, exp=0.1868492880824934475 + 0.87660580316894290247j)
  2423. # negative values
  2424. _check(n=-0.5, k=3, exp=0.72981013240713739354)
  2425. _check(n=-0.5 + 0j, k=3, exp=0.72981013240713739354 + 0j)
  2426. _check(n=2.9, k=-0.7, exp=0.45396591474966867296 + 0.56925525174685228866j)
  2427. _check(n=-0.6, k=-0.7, exp=-0.07190820089634757334 - 0.090170031876701730081j)
  2428. # close to poles
  2429. _check(n=-2.9999, k=3, exp=7764.7170695908828364)
  2430. _check(n=-3 + 0.0001j, k=3, exp=0.1349475632879599864 - 7764.5821055158365027j)
  2431. @pytest.mark.parametrize("dtype", [np.int64, np.float64,
  2432. np.complex128, object])
  2433. @pytest.mark.parametrize("extend", ["zero", "complex"])
  2434. @pytest.mark.parametrize("exact", [True, False])
  2435. @pytest.mark.parametrize("dim", range(0, 5))
  2436. # test empty & non-empty arrays, with nans and mixed
  2437. @pytest.mark.parametrize(
  2438. "content",
  2439. [[], [1], [1.1], [np.nan], [np.nan + np.nan * 1j], [np.nan, 1]],
  2440. ids=["[]", "[1]", "[1.1]", "[NaN]", "[NaN+i*NaN]", "[NaN, 1]"],
  2441. )
  2442. def test_factorialk_array_corner_cases(self, content, dim, exact, extend, dtype):
  2443. # get dtype without calling array constructor (that might fail or mutate)
  2444. if dtype == np.int64 and any(np.isnan(x) or (x != int(x)) for x in content):
  2445. pytest.skip("impossible combination")
  2446. if dtype == np.float64 and any(_is_subdtype(type(x), "c") for x in content):
  2447. pytest.skip("impossible combination")
  2448. kw = {"k": 3, "exact": exact, "extend": extend}
  2449. # np.array(x, ndim=0) will not be 0-dim. unless x is too
  2450. content = content if (dim > 0 or len(content) != 1) else content[0]
  2451. n = np.array(content, ndmin=dim, dtype=dtype)
  2452. result = None
  2453. if extend == "complex" and exact:
  2454. with pytest.raises(ValueError, match="Incompatible options:.*"):
  2455. special.factorialk(n, **kw)
  2456. elif not _is_subdtype(n.dtype, ["i", "f", "c"]):
  2457. with pytest.raises(ValueError, match="Unsupported data type.*"):
  2458. special.factorialk(n, **kw)
  2459. elif _is_subdtype(n.dtype, ["f", "c"]) and extend != "complex":
  2460. with pytest.raises(ValueError, match="In order to use non-integer.*"):
  2461. special.factorialk(n, **kw)
  2462. else:
  2463. result = special.factorialk(n, **kw)
  2464. if result is not None:
  2465. # use scalar case as reference; tested separately in *_scalar_corner_cases
  2466. ref = [special.factorialk(x, **kw) for x in n.ravel()]
  2467. # unpack length-1 lists so that np.array(x, ndim=0) works correctly
  2468. ref = ref[0] if len(ref) == 1 else ref
  2469. # result is empty if and only if n is empty, and has the same dimension
  2470. # as n; dtype stays the same, except when not empty and not exact:
  2471. if n.size:
  2472. cx = (extend == "complex") and _is_subdtype(n.dtype, "c")
  2473. dtype = np.complex128 if cx else (native_int if exact else np.float64)
  2474. expected = np.array(ref, ndmin=dim, dtype=dtype)
  2475. assert_really_equal(result, expected, rtol=2e-15)
  2476. @pytest.mark.parametrize("extend", ["zero", "complex"])
  2477. @pytest.mark.parametrize("exact", [True, False])
  2478. @pytest.mark.parametrize("k", range(1, 5))
  2479. @pytest.mark.parametrize("n", [1, 1.1, 2 + 2j, np.nan, np.nan + np.nan*1j, None],
  2480. ids=["1", "1.1", "2+2j", "NaN", "NaN+i*NaN", "None"])
  2481. def test_factorialk_scalar_corner_cases(self, n, k, exact, extend):
  2482. kw = {"k": k, "exact": exact, "extend": extend}
  2483. if extend == "complex" and exact:
  2484. with pytest.raises(ValueError, match="Incompatible options:.*"):
  2485. special.factorialk(n, **kw)
  2486. elif not _is_subdtype(type(n), ["i", "f", "c", type(None)]):
  2487. with pytest.raises(ValueError, match="Unsupported data type.*"):
  2488. special.factorialk(n, **kw)
  2489. elif _is_subdtype(type(n), ["f", "c"]) and extend != "complex":
  2490. with pytest.raises(ValueError, match="In order to use non-integer.*"):
  2491. special.factorialk(n, **kw)
  2492. elif n is None or np.isnan(n):
  2493. # account for dtype and whether extend="complex"
  2494. complexify = (extend == "complex") and _is_subdtype(type(n), "c")
  2495. expected = np.complex128("nan+nanj") if complexify else np.float64("nan")
  2496. assert_really_equal(special.factorialk(n, **kw), expected)
  2497. else:
  2498. expected = self.factorialk_ref(n, **kw)
  2499. assert_really_equal(special.factorialk(n, **kw), expected, rtol=1e-15)
  2500. @pytest.mark.parametrize("boxed", [True, False])
  2501. @pytest.mark.parametrize("exact,extend",
  2502. [(True, "zero"), (False, "zero"), (False, "complex")])
  2503. @pytest.mark.parametrize("k", [-1, -1.0, 0, 0.0, 0 + 1j, 1.1, np.nan])
  2504. def test_factorialk_raises_k_complex(self, k, exact, extend, boxed):
  2505. n = [1] if boxed else 1
  2506. kw = {"k": k, "exact": exact, "extend": extend}
  2507. if extend == "zero":
  2508. msg = "In order to use non-integer.*"
  2509. if _is_subdtype(type(k), "i") and (k < 1):
  2510. msg = "For `extend='zero'`.*"
  2511. with pytest.raises(ValueError, match=msg):
  2512. special.factorialk(n, **kw)
  2513. elif k == 0:
  2514. with pytest.raises(ValueError, match="Parameter k cannot be zero!"):
  2515. special.factorialk(n, **kw)
  2516. else:
  2517. # no error
  2518. special.factorialk(n, **kw)
  2519. @pytest.mark.parametrize("boxed", [True, False])
  2520. @pytest.mark.parametrize("exact,extend",
  2521. [(True, "zero"), (False, "zero"), (False, "complex")])
  2522. # neither integer, float nor complex
  2523. @pytest.mark.parametrize("k", ["string", np.datetime64("nat")],
  2524. ids=["string", "NaT"])
  2525. def test_factorialk_raises_k_other(self, k, exact, extend, boxed):
  2526. n = [1] if boxed else 1
  2527. kw = {"k": k, "exact": exact, "extend": extend}
  2528. with pytest.raises(ValueError, match="Unsupported data type.*"):
  2529. special.factorialk(n, **kw)
  2530. @pytest.mark.parametrize("exact,extend",
  2531. [(True, "zero"), (False, "zero"), (False, "complex")])
  2532. @pytest.mark.parametrize("k", range(1, 12))
  2533. def test_factorialk_dtype(self, k, exact, extend):
  2534. kw = {"k": k, "exact": exact, "extend": extend}
  2535. if exact and k in _FACTORIALK_LIMITS_64BITS.keys():
  2536. n = np.array([_FACTORIALK_LIMITS_32BITS[k]])
  2537. assert_equal(special.factorialk(n, **kw).dtype, np_long)
  2538. assert_equal(special.factorialk(n + 1, **kw).dtype, np.int64)
  2539. # assert maximality of limits for given dtype
  2540. assert special.factorialk(n + 1, **kw) > np.iinfo(np.int32).max
  2541. n = np.array([_FACTORIALK_LIMITS_64BITS[k]])
  2542. assert_equal(special.factorialk(n, **kw).dtype, np.int64)
  2543. assert_equal(special.factorialk(n + 1, **kw).dtype, object)
  2544. assert special.factorialk(n + 1, **kw) > np.iinfo(np.int64).max
  2545. else:
  2546. n = np.array([_FACTORIALK_LIMITS_64BITS.get(k, 1)])
  2547. # for exact=True and k >= 10, we always return object;
  2548. # for exact=False it's always float (unless input is complex)
  2549. dtype = object if exact else np.float64
  2550. assert_equal(special.factorialk(n, **kw).dtype, dtype)
  2551. def test_factorial_mixed_nan_inputs(self):
  2552. x = np.array([np.nan, 1, 2, 3, np.nan])
  2553. expected = np.array([np.nan, 1, 2, 6, np.nan])
  2554. assert_equal(special.factorial(x, exact=False), expected)
  2555. with pytest.raises(ValueError, match="`exact=True` only supports.*"):
  2556. special.factorial(x, exact=True)
  2557. class TestFresnel:
  2558. @pytest.mark.parametrize("z, s, c", [
  2559. # some positive value
  2560. (.5, 0.064732432859999287, 0.49234422587144644),
  2561. (.5 + .0j, 0.064732432859999287, 0.49234422587144644),
  2562. # negative half annulus
  2563. # https://github.com/scipy/scipy/issues/12309
  2564. # Reference values can be reproduced with
  2565. # https://www.wolframalpha.com/input/?i=FresnelS%5B-2.0+%2B+0.1i%5D
  2566. # https://www.wolframalpha.com/input/?i=FresnelC%5B-2.0+%2B+0.1i%5D
  2567. (
  2568. -2.0 + 0.1j,
  2569. -0.3109538687728942-0.0005870728836383176j,
  2570. -0.4879956866358554+0.10670801832903172j
  2571. ),
  2572. (
  2573. -0.1 - 1.5j,
  2574. -0.03918309471866977+0.7197508454568574j,
  2575. 0.09605692502968956-0.43625191013617465j
  2576. ),
  2577. # a different algorithm kicks in for "large" values, i.e., |z| >= 4.5,
  2578. # make sure to test both float and complex values; a different
  2579. # algorithm is used
  2580. (6.0, 0.44696076, 0.49953147),
  2581. (6.0 + 0.0j, 0.44696076, 0.49953147),
  2582. (6.0j, -0.44696076j, 0.49953147j),
  2583. (-6.0 + 0.0j, -0.44696076, -0.49953147),
  2584. (-6.0j, 0.44696076j, -0.49953147j),
  2585. # inf
  2586. (np.inf, 0.5, 0.5),
  2587. (-np.inf, -0.5, -0.5),
  2588. ])
  2589. def test_fresnel_values(self, z, s, c):
  2590. frs = array(special.fresnel(z))
  2591. assert_allclose(frs, array([s, c]), atol=1.5e-8, rtol=0)
  2592. # values from pg 329 Table 7.11 of A & S
  2593. # slightly corrected in 4th decimal place
  2594. def test_fresnel_zeros(self):
  2595. szo, czo = special.fresnel_zeros(5)
  2596. assert_allclose(szo, array([2.0093+0.2885j,
  2597. 2.8335+0.2443j,
  2598. 3.4675+0.2185j,
  2599. 4.0026+0.2009j,
  2600. 4.4742+0.1877j]),
  2601. atol=1.5e-3, rtol=0)
  2602. assert_allclose(czo, array([1.7437+0.3057j,
  2603. 2.6515+0.2529j,
  2604. 3.3204+0.2240j,
  2605. 3.8757+0.2047j,
  2606. 4.3611+0.1907j]),
  2607. atol=1.5e-3, rtol=0)
  2608. vals1 = special.fresnel(szo)[0]
  2609. vals2 = special.fresnel(czo)[1]
  2610. assert_allclose(vals1, 0, atol=1.5e-14, rtol=0)
  2611. assert_allclose(vals2, 0, atol=1.5e-14, rtol=0)
  2612. def test_fresnelc_zeros(self):
  2613. szo, czo = special.fresnel_zeros(6)
  2614. frc = special.fresnelc_zeros(6)
  2615. assert_allclose(frc, czo, atol=1.5e-12, rtol=0)
  2616. def test_fresnels_zeros(self):
  2617. szo, czo = special.fresnel_zeros(5)
  2618. frs = special.fresnels_zeros(5)
  2619. assert_allclose(frs, szo, atol=1.5e-12, rtol=0)
  2620. class TestGamma:
  2621. def test_gamma(self):
  2622. gam = special.gamma(5)
  2623. assert_equal(gam,24.0)
  2624. def test_gammaln(self):
  2625. gamln = special.gammaln(3)
  2626. lngam = log(special.gamma(3))
  2627. assert_allclose(gamln, lngam, atol=1.5e-8, rtol=0)
  2628. def test_gammainccinv(self):
  2629. gccinv = special.gammainccinv(.5,.5)
  2630. gcinv = special.gammaincinv(.5,.5)
  2631. assert_allclose(gccinv, gcinv, atol=1.5e-8, rtol=0)
  2632. @with_special_errors
  2633. def test_gammaincinv(self):
  2634. y = special.gammaincinv(.4,.4)
  2635. x = special.gammainc(.4,y)
  2636. assert_allclose(x, 0.4, atol=1.5e-10, rtol=0)
  2637. y = special.gammainc(10, 0.05)
  2638. x = special.gammaincinv(10, 2.5715803516000736e-20)
  2639. assert_allclose(0.05, x, atol=1.5e-10, rtol=0)
  2640. assert_allclose(y, 2.5715803516000736e-20, atol=1.5e-10, rtol=0)
  2641. x = special.gammaincinv(50, 8.20754777388471303050299243573393e-18)
  2642. assert_allclose(11.0, x, atol=1.5e-10, rtol=0)
  2643. @with_special_errors
  2644. def test_975(self):
  2645. # Regression test for ticket #975 -- switch point in algorithm
  2646. # check that things work OK at the point, immediately next floats
  2647. # around it, and a bit further away
  2648. pts = [0.25,
  2649. np.nextafter(0.25, 0), 0.25 - 1e-12,
  2650. np.nextafter(0.25, 1), 0.25 + 1e-12]
  2651. for pt in pts:
  2652. y = special.gammaincinv(.4, pt)
  2653. x = special.gammainc(0.4, y)
  2654. assert_allclose(x, pt, rtol=1e-12)
  2655. def test_rgamma(self):
  2656. rgam = special.rgamma(8)
  2657. rlgam = 1/special.gamma(8)
  2658. assert_allclose(rgam, rlgam, atol=1.5e-8, rtol=0)
  2659. def test_infinity(self):
  2660. assert_equal(special.rgamma(-1), 0)
  2661. @pytest.mark.parametrize(
  2662. "x,expected",
  2663. [
  2664. # infinities
  2665. ([-np.inf, np.inf], [np.nan, np.inf]),
  2666. # negative and positive zero
  2667. ([-0.0, 0.0], [-np.inf, np.inf]),
  2668. # small poles
  2669. (range(-32, 0), np.full(32, np.nan)),
  2670. # medium sized poles
  2671. (range(-1024, -32, 99), np.full(11, np.nan)),
  2672. # large pole
  2673. ([-4.141512231792294e+16], [np.nan]),
  2674. ]
  2675. )
  2676. def test_poles(self, x, expected):
  2677. assert_array_equal(special.gamma(x), expected)
  2678. class TestHankel:
  2679. def test_negv1(self):
  2680. assert_allclose(special.hankel1(-3, 2), -special.hankel1(3, 2),
  2681. atol=1.5e-14, rtol=0)
  2682. def test_hankel1(self):
  2683. hank1 = special.hankel1(1,.1)
  2684. hankrl = (special.jv(1,.1) + special.yv(1,.1)*1j)
  2685. assert_allclose(hank1, hankrl, atol=1.5e-8, rtol=0)
  2686. def test_negv1e(self):
  2687. assert_allclose(special.hankel1e(-3, 2), -special.hankel1e(3, 2),
  2688. atol=1.5e-14, rtol=0)
  2689. def test_hankel1e(self):
  2690. hank1e = special.hankel1e(1,.1)
  2691. hankrle = special.hankel1(1,.1)*exp(-.1j)
  2692. assert_allclose(hank1e, hankrle, atol=1.5e-8, rtol=0)
  2693. def test_negv2(self):
  2694. assert_allclose(special.hankel2(-3, 2), -special.hankel2(3, 2),
  2695. atol=1.5e-14, rtol=0)
  2696. def test_hankel2(self):
  2697. hank2 = special.hankel2(1,.1)
  2698. hankrl2 = (special.jv(1,.1) - special.yv(1,.1)*1j)
  2699. assert_allclose(hank2, hankrl2, atol=1.5e-8, rtol=0)
  2700. def test_neg2e(self):
  2701. assert_allclose(special.hankel2e(-3, 2), -special.hankel2e(3, 2),
  2702. atol=1.5e-14, rtol=0)
  2703. def test_hankl2e(self):
  2704. hank2e = special.hankel2e(1,.1)
  2705. hankrl2e = special.hankel2e(1,.1)
  2706. assert_allclose(hank2e, hankrl2e, atol=1.5e-8, rtol=0)
  2707. def test_hankel2_gh4517(self):
  2708. # Test edge case reported in https://github.com/scipy/scipy/issues/4517
  2709. res = special.hankel2(0, 0)
  2710. assert np.isnan(res.real)
  2711. assert np.isposinf(res.imag)
  2712. class TestHyper:
  2713. def test_h1vp(self):
  2714. h1 = special.h1vp(1,.1)
  2715. h1real = (special.jvp(1,.1) + special.yvp(1,.1)*1j)
  2716. assert_allclose(h1, h1real, atol=1.5e-8, rtol=0)
  2717. def test_h2vp(self):
  2718. h2 = special.h2vp(1,.1)
  2719. h2real = (special.jvp(1,.1) - special.yvp(1,.1)*1j)
  2720. assert_allclose(h2, h2real, atol=1.5e-8, rtol=0)
  2721. def test_hyp0f1(self):
  2722. # scalar input
  2723. assert_allclose(special.hyp0f1(2.5, 0.5), 1.21482702689997, rtol=1e-12)
  2724. assert_allclose(special.hyp0f1(2.5, 0), 1.0, rtol=1e-15)
  2725. # float input, expected values match mpmath
  2726. x = special.hyp0f1(3.0, [-1.5, -1, 0, 1, 1.5])
  2727. expected = np.array([0.58493659229143, 0.70566805723127, 1.0,
  2728. 1.37789689539747, 1.60373685288480])
  2729. assert_allclose(x, expected, rtol=1e-12)
  2730. # complex input
  2731. x = special.hyp0f1(3.0, np.array([-1.5, -1, 0, 1, 1.5]) + 0.j)
  2732. assert_allclose(x, expected.astype(complex), rtol=1e-12)
  2733. # test broadcasting
  2734. x1 = [0.5, 1.5, 2.5]
  2735. x2 = [0, 1, 0.5]
  2736. x = special.hyp0f1(x1, x2)
  2737. expected = [1.0, 1.8134302039235093, 1.21482702689997]
  2738. assert_allclose(x, expected, rtol=1e-12)
  2739. x = special.hyp0f1(np.vstack([x1] * 2), x2)
  2740. assert_allclose(x, np.vstack([expected] * 2), rtol=1e-12)
  2741. assert_raises(ValueError, special.hyp0f1,
  2742. np.vstack([x1] * 3), [0, 1])
  2743. def test_hyp0f1_gh5764(self):
  2744. # Just checks the point that failed; there's a more systematic
  2745. # test in test_mpmath
  2746. res = special.hyp0f1(0.8, 0.5 + 0.5*1J)
  2747. # The expected value was generated using mpmath
  2748. assert_allclose(res, 1.6139719776441115 + 1J*0.80893054061790665,
  2749. atol=1.5e-7, rtol=0)
  2750. def test_hyp1f1(self):
  2751. hyp1 = special.hyp1f1(.1,.1,.3)
  2752. assert_allclose(hyp1, 1.3498588075760032, atol=1.5e-7, rtol=0)
  2753. # test contributed by Moritz Deger (2008-05-29)
  2754. # https://github.com/scipy/scipy/issues/1186 (Trac #659)
  2755. # reference data obtained from mathematica [ a, b, x, m(a,b,x)]:
  2756. # produced with test_hyp1f1.nb
  2757. ref_data = array([
  2758. [-8.38132975e+00, -1.28436461e+01, -2.91081397e+01, 1.04178330e+04],
  2759. [2.91076882e+00, -6.35234333e+00, -1.27083993e+01, 6.68132725e+00],
  2760. [-1.42938258e+01, 1.80869131e-01, 1.90038728e+01, 1.01385897e+05],
  2761. [5.84069088e+00, 1.33187908e+01, 2.91290106e+01, 1.59469411e+08],
  2762. [-2.70433202e+01, -1.16274873e+01, -2.89582384e+01, 1.39900152e+24],
  2763. [4.26344966e+00, -2.32701773e+01, 1.91635759e+01, 6.13816915e+21],
  2764. [1.20514340e+01, -3.40260240e+00, 7.26832235e+00, 1.17696112e+13],
  2765. [2.77372955e+01, -1.99424687e+00, 3.61332246e+00, 3.07419615e+13],
  2766. [1.50310939e+01, -2.91198675e+01, -1.53581080e+01, -3.79166033e+02],
  2767. [1.43995827e+01, 9.84311196e+00, 1.93204553e+01, 2.55836264e+10],
  2768. [-4.08759686e+00, 1.34437025e+01, -1.42072843e+01, 1.70778449e+01],
  2769. [8.05595738e+00, -1.31019838e+01, 1.52180721e+01, 3.06233294e+21],
  2770. [1.81815804e+01, -1.42908793e+01, 9.57868793e+00, -2.84771348e+20],
  2771. [-2.49671396e+01, 1.25082843e+01, -1.71562286e+01, 2.36290426e+07],
  2772. [2.67277673e+01, 1.70315414e+01, 6.12701450e+00, 7.77917232e+03],
  2773. [2.49565476e+01, 2.91694684e+01, 6.29622660e+00, 2.35300027e+02],
  2774. [6.11924542e+00, -1.59943768e+00, 9.57009289e+00, 1.32906326e+11],
  2775. [-1.47863653e+01, 2.41691301e+01, -1.89981821e+01, 2.73064953e+03],
  2776. [2.24070483e+01, -2.93647433e+00, 8.19281432e+00, -6.42000372e+17],
  2777. [8.04042600e-01, 1.82710085e+01, -1.97814534e+01, 5.48372441e-01],
  2778. [1.39590390e+01, 1.97318686e+01, 2.37606635e+00, 5.51923681e+00],
  2779. [-4.66640483e+00, -2.00237930e+01, 7.40365095e+00, 4.50310752e+00],
  2780. [2.76821999e+01, -6.36563968e+00, 1.11533984e+01, -9.28725179e+23],
  2781. [-2.56764457e+01, 1.24544906e+00, 1.06407572e+01, 1.25922076e+01],
  2782. [3.20447808e+00, 1.30874383e+01, 2.26098014e+01, 2.03202059e+04],
  2783. [-1.24809647e+01, 4.15137113e+00, -2.92265700e+01, 2.39621411e+08],
  2784. [2.14778108e+01, -2.35162960e+00, -1.13758664e+01, 4.46882152e-01],
  2785. [-9.85469168e+00, -3.28157680e+00, 1.67447548e+01, -1.07342390e+07],
  2786. [1.08122310e+01, -2.47353236e+01, -1.15622349e+01, -2.91733796e+03],
  2787. [-2.67933347e+01, -3.39100709e+00, 2.56006986e+01, -5.29275382e+09],
  2788. [-8.60066776e+00, -8.02200924e+00, 1.07231926e+01, 1.33548320e+06],
  2789. [-1.01724238e-01, -1.18479709e+01, -2.55407104e+01, 1.55436570e+00],
  2790. [-3.93356771e+00, 2.11106818e+01, -2.57598485e+01, 2.13467840e+01],
  2791. [3.74750503e+00, 1.55687633e+01, -2.92841720e+01, 1.43873509e-02],
  2792. [6.99726781e+00, 2.69855571e+01, -1.63707771e+01, 3.08098673e-02],
  2793. [-2.31996011e+01, 3.47631054e+00, 9.75119815e-01, 1.79971073e-02],
  2794. [2.38951044e+01, -2.91460190e+01, -2.50774708e+00, 9.56934814e+00],
  2795. [1.52730825e+01, 5.77062507e+00, 1.21922003e+01, 1.32345307e+09],
  2796. [1.74673917e+01, 1.89723426e+01, 4.94903250e+00, 9.90859484e+01],
  2797. [1.88971241e+01, 2.86255413e+01, 5.52360109e-01, 1.44165360e+00],
  2798. [1.02002319e+01, -1.66855152e+01, -2.55426235e+01, 6.56481554e+02],
  2799. [-1.79474153e+01, 1.22210200e+01, -1.84058212e+01, 8.24041812e+05],
  2800. [-1.36147103e+01, 1.32365492e+00, -7.22375200e+00, 9.92446491e+05],
  2801. [7.57407832e+00, 2.59738234e+01, -1.34139168e+01, 3.64037761e-02],
  2802. [2.21110169e+00, 1.28012666e+01, 1.62529102e+01, 1.33433085e+02],
  2803. [-2.64297569e+01, -1.63176658e+01, -1.11642006e+01, -2.44797251e+13],
  2804. [-2.46622944e+01, -3.02147372e+00, 8.29159315e+00, -3.21799070e+05],
  2805. [-1.37215095e+01, -1.96680183e+01, 2.91940118e+01, 3.21457520e+12],
  2806. [-5.45566105e+00, 2.81292086e+01, 1.72548215e-01, 9.66973000e-01],
  2807. [-1.55751298e+00, -8.65703373e+00, 2.68622026e+01, -3.17190834e+16],
  2808. [2.45393609e+01, -2.70571903e+01, 1.96815505e+01, 1.80708004e+37],
  2809. [5.77482829e+00, 1.53203143e+01, 2.50534322e+01, 1.14304242e+06],
  2810. [-1.02626819e+01, 2.36887658e+01, -2.32152102e+01, 7.28965646e+02],
  2811. [-1.30833446e+00, -1.28310210e+01, 1.87275544e+01, -9.33487904e+12],
  2812. [5.83024676e+00, -1.49279672e+01, 2.44957538e+01, -7.61083070e+27],
  2813. [-2.03130747e+01, 2.59641715e+01, -2.06174328e+01, 4.54744859e+04],
  2814. [1.97684551e+01, -2.21410519e+01, -2.26728740e+01, 3.53113026e+06],
  2815. [2.73673444e+01, 2.64491725e+01, 1.57599882e+01, 1.07385118e+07],
  2816. [5.73287971e+00, 1.21111904e+01, 1.33080171e+01, 2.63220467e+03],
  2817. [-2.82751072e+01, 2.08605881e+01, 9.09838900e+00, -6.60957033e-07],
  2818. [1.87270691e+01, -1.74437016e+01, 1.52413599e+01, 6.59572851e+27],
  2819. [6.60681457e+00, -2.69449855e+00, 9.78972047e+00, -2.38587870e+12],
  2820. [1.20895561e+01, -2.51355765e+01, 2.30096101e+01, 7.58739886e+32],
  2821. [-2.44682278e+01, 2.10673441e+01, -1.36705538e+01, 4.54213550e+04],
  2822. [-4.50665152e+00, 3.72292059e+00, -4.83403707e+00, 2.68938214e+01],
  2823. [-7.46540049e+00, -1.08422222e+01, -1.72203805e+01, -2.09402162e+02],
  2824. [-2.00307551e+01, -7.50604431e+00, -2.78640020e+01, 4.15985444e+19],
  2825. [1.99890876e+01, 2.20677419e+01, -2.51301778e+01, 1.23840297e-09],
  2826. [2.03183823e+01, -7.66942559e+00, 2.10340070e+01, 1.46285095e+31],
  2827. [-2.90315825e+00, -2.55785967e+01, -9.58779316e+00, 2.65714264e-01],
  2828. [2.73960829e+01, -1.80097203e+01, -2.03070131e+00, 2.52908999e+02],
  2829. [-2.11708058e+01, -2.70304032e+01, 2.48257944e+01, 3.09027527e+08],
  2830. [2.21959758e+01, 4.00258675e+00, -1.62853977e+01, -9.16280090e-09],
  2831. [1.61661840e+01, -2.26845150e+01, 2.17226940e+01, -8.24774394e+33],
  2832. [-3.35030306e+00, 1.32670581e+00, 9.39711214e+00, -1.47303163e+01],
  2833. [7.23720726e+00, -2.29763909e+01, 2.34709682e+01, -9.20711735e+29],
  2834. [2.71013568e+01, 1.61951087e+01, -7.11388906e-01, 2.98750911e-01],
  2835. [8.40057933e+00, -7.49665220e+00, 2.95587388e+01, 6.59465635e+29],
  2836. [-1.51603423e+01, 1.94032322e+01, -7.60044357e+00, 1.05186941e+02],
  2837. [-8.83788031e+00, -2.72018313e+01, 1.88269907e+00, 1.81687019e+00],
  2838. [-1.87283712e+01, 5.87479570e+00, -1.91210203e+01, 2.52235612e+08],
  2839. [-5.61338513e-01, 2.69490237e+01, 1.16660111e-01, 9.97567783e-01],
  2840. [-5.44354025e+00, -1.26721408e+01, -4.66831036e+00, 1.06660735e-01],
  2841. [-2.18846497e+00, 2.33299566e+01, 9.62564397e+00, 3.03842061e-01],
  2842. [6.65661299e+00, -2.39048713e+01, 1.04191807e+01, 4.73700451e+13],
  2843. [-2.57298921e+01, -2.60811296e+01, 2.74398110e+01, -5.32566307e+11],
  2844. [-1.11431826e+01, -1.59420160e+01, -1.84880553e+01, -1.01514747e+02],
  2845. [6.50301931e+00, 2.59859051e+01, -2.33270137e+01, 1.22760500e-02],
  2846. [-1.94987891e+01, -2.62123262e+01, 3.90323225e+00, 1.71658894e+01],
  2847. [7.26164601e+00, -1.41469402e+01, 2.81499763e+01, -2.50068329e+31],
  2848. [-1.52424040e+01, 2.99719005e+01, -2.85753678e+01, 1.31906693e+04],
  2849. [5.24149291e+00, -1.72807223e+01, 2.22129493e+01, 2.50748475e+25],
  2850. [3.63207230e-01, -9.54120862e-02, -2.83874044e+01, 9.43854939e-01],
  2851. [-2.11326457e+00, -1.25707023e+01, 1.17172130e+00, 1.20812698e+00],
  2852. [2.48513582e+00, 1.03652647e+01, -1.84625148e+01, 6.47910997e-02],
  2853. [2.65395942e+01, 2.74794672e+01, 1.29413428e+01, 2.89306132e+05],
  2854. [-9.49445460e+00, 1.59930921e+01, -1.49596331e+01, 3.27574841e+02],
  2855. [-5.89173945e+00, 9.96742426e+00, 2.60318889e+01, -3.15842908e-01],
  2856. [-1.15387239e+01, -2.21433107e+01, -2.17686413e+01, 1.56724718e-01],
  2857. [-5.30592244e+00, -2.42752190e+01, 1.29734035e+00, 1.31985534e+00]
  2858. ])
  2859. for a,b,c,expected in ref_data:
  2860. result = special.hyp1f1(a,b,c)
  2861. assert_(abs(expected - result)/expected < 1e-4)
  2862. def test_hyp1f1_gh2957(self):
  2863. hyp1 = special.hyp1f1(0.5, 1.5, -709.7827128933)
  2864. hyp2 = special.hyp1f1(0.5, 1.5, -709.7827128934)
  2865. assert_allclose(hyp1, hyp2, atol=1.5e-12, rtol=0)
  2866. def test_hyp1f1_gh2282(self):
  2867. hyp = special.hyp1f1(0.5, 1.5, -1000)
  2868. assert_allclose(hyp, 0.028024956081989643, atol=1.5e-12, rtol=0)
  2869. def test_hyp2f1(self):
  2870. # a collection of special cases taken from AMS 55
  2871. values = [
  2872. [0.5, 1, 1.5, 0.2**2, 0.5/0.2*log((1+0.2)/(1-0.2))],
  2873. [0.5, 1, 1.5, -0.2**2, 1./0.2*arctan(0.2)],
  2874. [1, 1, 2, 0.2, -1/0.2*log(1-0.2)],
  2875. [3, 3.5, 1.5, 0.2**2, 0.5/0.2/(-5)*((1+0.2)**(-5)-(1-0.2)**(-5))],
  2876. [-3, 3, 0.5, sin(0.2)**2, cos(2*3*0.2)],
  2877. [3, 4, 8, 1,
  2878. special.gamma(8) * special.gamma(8-4-3)
  2879. / special.gamma(8-3) / special.gamma(8-4)],
  2880. [3, 2, 3-2+1, -1,
  2881. 1./2**3*sqrt(pi) * special.gamma(1+3-2)
  2882. / special.gamma(1+0.5*3-2) / special.gamma(0.5+0.5*3)],
  2883. [5, 2, 5-2+1, -1,
  2884. 1./2**5*sqrt(pi) * special.gamma(1+5-2)
  2885. / special.gamma(1+0.5*5-2) / special.gamma(0.5+0.5*5)],
  2886. [4, 0.5+4, 1.5-2*4, -1./3,
  2887. (8./9)**(-2*4)*special.gamma(4./3) * special.gamma(1.5-2*4)
  2888. / special.gamma(3./2) / special.gamma(4./3-2*4)],
  2889. # and some others
  2890. # ticket #424
  2891. [1.5, -0.5, 1.0, -10.0, 4.1300097765277476484],
  2892. # negative integer a or b, with c-a-b integer and x > 0.9
  2893. [-2,3,1,0.95,0.715],
  2894. [2,-3,1,0.95,-0.007],
  2895. [-6,3,1,0.95,0.0000810625],
  2896. [2,-5,1,0.95,-0.000029375],
  2897. # huge negative integers
  2898. (10, -900, 10.5, 0.99, 1.91853705796607664803709475658e-24),
  2899. (10, -900, -10.5, 0.99, 3.54279200040355710199058559155e-18),
  2900. ]
  2901. for i, (a, b, c, x, v) in enumerate(values):
  2902. cv = special.hyp2f1(a, b, c, x)
  2903. assert_allclose(cv, v, atol=1.5e-8, rtol=0, err_msg=f'test #{i}')
  2904. def test_hyperu(self):
  2905. val1 = special.hyperu(1,0.1,100)
  2906. assert_allclose(val1, 0.0098153, atol=1.5e-7, rtol=0)
  2907. a,b = [0.3,0.6,1.2,-2.7],[1.5,3.2,-0.4,-3.2]
  2908. a,b = asarray(a), asarray(b)
  2909. z = 0.5
  2910. hypu = special.hyperu(a,b,z)
  2911. hprl = (pi/sin(pi*b))*(special.hyp1f1(a,b,z) /
  2912. (special.gamma(1+a-b)*special.gamma(b)) -
  2913. z**(1-b)*special.hyp1f1(1+a-b,2-b,z)
  2914. / (special.gamma(a)*special.gamma(2-b)))
  2915. assert_allclose(hypu, hprl, atol=1.5e-12, rtol=0)
  2916. def test_hyperu_gh2287(self):
  2917. assert_allclose(special.hyperu(1, 1.5, 20.2), 0.048360918656699191,
  2918. atol=1.5e-12, rtol=0)
  2919. class TestBessel:
  2920. def test_itj0y0(self):
  2921. it0 = array(special.itj0y0(.2))
  2922. assert_allclose(it0, array([0.19933433254006822, -0.34570883800412566]),
  2923. atol=1.5e-8, rtol=0)
  2924. def test_it2j0y0(self):
  2925. it2 = array(special.it2j0y0(.2))
  2926. assert_allclose(it2, array([0.0049937546274601858, -0.43423067011231614]),
  2927. atol=1.5e-8, rtol=0)
  2928. def test_negv_iv(self):
  2929. assert_equal(special.iv(3,2), special.iv(-3,2))
  2930. def test_j0(self):
  2931. oz = special.j0(.1)
  2932. ozr = special.jn(0,.1)
  2933. assert_allclose(oz, ozr, atol=1.5e-8, rtol=0)
  2934. def test_j1(self):
  2935. o1 = special.j1(.1)
  2936. o1r = special.jn(1,.1)
  2937. assert_allclose(o1, o1r, atol=1.5e-8, rtol=0)
  2938. def test_jn(self):
  2939. jnnr = special.jn(1,.2)
  2940. assert_allclose(jnnr, 0.099500832639235995, atol=1.5e-8, rtol=0)
  2941. def test_negv_jv(self):
  2942. assert_allclose(special.jv(-3, 2), -special.jv(3, 2), atol=1.5e-14, rtol=0)
  2943. def test_jv(self):
  2944. values = [[0, 0.1, 0.99750156206604002],
  2945. [2./3, 1e-8, 0.3239028506761532e-5],
  2946. [2./3, 1e-10, 0.1503423854873779e-6],
  2947. [3.1, 1e-10, 0.1711956265409013e-32],
  2948. [2./3, 4.0, -0.2325440850267039],
  2949. ]
  2950. for i, (v, x, y) in enumerate(values):
  2951. yc = special.jv(v, x)
  2952. assert_allclose(yc, y, atol=1.5e-8, rtol=0, err_msg=f'test #{i}')
  2953. def test_negv_jve(self):
  2954. assert_allclose(special.jve(-3, 2), -special.jve(3, 2),
  2955. atol=1.5e-14, rtol=0)
  2956. def test_jve(self):
  2957. jvexp = special.jve(1,.2)
  2958. assert_allclose(jvexp, 0.099500832639235995, atol=1.5e-8, rtol=0)
  2959. jvexp1 = special.jve(1,.2+1j)
  2960. z = .2+1j
  2961. jvexpr = special.jv(1,z)*exp(-abs(z.imag))
  2962. assert_allclose(jvexp1, jvexpr, atol=1.5e-8, rtol=0)
  2963. def test_jn_zeros(self):
  2964. jn0 = special.jn_zeros(0,5)
  2965. jn1 = special.jn_zeros(1,5)
  2966. assert_allclose(jn0, array([2.4048255577,
  2967. 5.5200781103,
  2968. 8.6537279129,
  2969. 11.7915344391,
  2970. 14.9309177086]),
  2971. atol=1.5e-4, rtol=0)
  2972. assert_allclose(jn1, array([3.83171,
  2973. 7.01559,
  2974. 10.17347,
  2975. 13.32369,
  2976. 16.47063]),
  2977. atol=1.5e-4, rtol=0)
  2978. jn102 = special.jn_zeros(102,5)
  2979. assert_allclose(jn102, array([110.89174935992040343,
  2980. 117.83464175788308398,
  2981. 123.70194191713507279,
  2982. 129.02417238949092824,
  2983. 134.00114761868422559]), rtol=1e-13)
  2984. jn301 = special.jn_zeros(301,5)
  2985. assert_allclose(jn301, array([313.59097866698830153,
  2986. 323.21549776096288280,
  2987. 331.22338738656748796,
  2988. 338.39676338872084500,
  2989. 345.03284233056064157]), rtol=1e-13)
  2990. def test_jn_zeros_slow(self):
  2991. jn0 = special.jn_zeros(0, 300)
  2992. assert_allclose(jn0[260-1], 816.02884495068867280, rtol=1e-13)
  2993. assert_allclose(jn0[280-1], 878.86068707124422606, rtol=1e-13)
  2994. assert_allclose(jn0[300-1], 941.69253065317954064, rtol=1e-13)
  2995. jn10 = special.jn_zeros(10, 300)
  2996. assert_allclose(jn10[260-1], 831.67668514305631151, rtol=1e-13)
  2997. assert_allclose(jn10[280-1], 894.51275095371316931, rtol=1e-13)
  2998. assert_allclose(jn10[300-1], 957.34826370866539775, rtol=1e-13)
  2999. jn3010 = special.jn_zeros(3010,5)
  3000. assert_allclose(jn3010, array([3036.86590780927,
  3001. 3057.06598526482,
  3002. 3073.66360690272,
  3003. 3088.37736494778,
  3004. 3101.86438139042]), rtol=1e-8)
  3005. def test_jnjnp_zeros(self):
  3006. jn = special.jn
  3007. def jnp(n, x):
  3008. return (jn(n-1,x) - jn(n+1,x))/2
  3009. for nt in range(1, 30):
  3010. z, n, m, t = special.jnjnp_zeros(nt)
  3011. for zz, nn, tt in zip(z, n, t):
  3012. if tt == 0:
  3013. assert_allclose(jn(nn, zz), 0, atol=1e-6)
  3014. elif tt == 1:
  3015. assert_allclose(jnp(nn, zz), 0, atol=1e-6)
  3016. else:
  3017. raise AssertionError(f"Invalid t return for nt={nt}")
  3018. def test_jnp_zeros(self):
  3019. jnp = special.jnp_zeros(1,5)
  3020. assert_allclose(jnp, array([1.84118,
  3021. 5.33144,
  3022. 8.53632,
  3023. 11.70600,
  3024. 14.86359]),
  3025. atol=1.5e-4, rtol=0)
  3026. jnp = special.jnp_zeros(443,5)
  3027. assert_allclose(special.jvp(443, jnp), 0, atol=1e-15)
  3028. def test_jnyn_zeros(self):
  3029. jnz = special.jnyn_zeros(1, 5)
  3030. assert_allclose(jnz, (array([3.83171,
  3031. 7.01559,
  3032. 10.17347,
  3033. 13.32369,
  3034. 16.47063]),
  3035. array([1.84118,
  3036. 5.33144,
  3037. 8.53632,
  3038. 11.70600,
  3039. 14.86359]),
  3040. array([2.19714,
  3041. 5.42968,
  3042. 8.59601,
  3043. 11.74915,
  3044. 14.89744]),
  3045. array([3.68302,
  3046. 6.94150,
  3047. 10.12340,
  3048. 13.28576,
  3049. 16.44006])),
  3050. atol=1.5e-5, rtol=0)
  3051. def test_jvp(self):
  3052. jvprim = special.jvp(2,2)
  3053. jv0 = (special.jv(1,2)-special.jv(3,2))/2
  3054. assert_allclose(jvprim, jv0, atol=1.5e-10, rtol=0)
  3055. def test_k0(self):
  3056. ozk = special.k0(.1)
  3057. ozkr = special.kv(0,.1)
  3058. assert_allclose(ozk,ozkr, atol=1.5e-8, rtol=0)
  3059. def test_k0e(self):
  3060. ozke = special.k0e(.1)
  3061. ozker = special.kve(0,.1)
  3062. assert_allclose(ozke, ozker, atol=1.5e-8, rtol=0)
  3063. def test_k1(self):
  3064. o1k = special.k1(.1)
  3065. o1kr = special.kv(1,.1)
  3066. assert_allclose(o1k,o1kr, atol=1.5e-8, rtol=0)
  3067. def test_k1e(self):
  3068. o1ke = special.k1e(.1)
  3069. o1ker = special.kve(1,.1)
  3070. assert_allclose(o1ke, o1ker, atol=1.5e-8, rtol=0)
  3071. def test_jacobi(self):
  3072. a = 5*np.random.random() - 1
  3073. b = 5*np.random.random() - 1
  3074. P0 = special.jacobi(0,a,b)
  3075. P1 = special.jacobi(1,a,b)
  3076. P2 = special.jacobi(2,a,b)
  3077. P3 = special.jacobi(3,a,b)
  3078. assert_allclose(P0.c, [1], atol=1.5e-13, rtol=0)
  3079. assert_allclose(P1.c, array([a + b + 2, a - b]) / 2.0,
  3080. atol=1.5e-13, rtol=0)
  3081. cp = [(a+b+3)*(a+b+4), 4*(a+b+3)*(a+2), 4*(a+1)*(a+2)]
  3082. p2c = [cp[0],cp[1]-2*cp[0],cp[2]-cp[1]+cp[0]]
  3083. assert_allclose(P2.c, array(p2c) / 8.0, atol=1.5e-13, rtol=0)
  3084. cp = [(a+b+4)*(a+b+5)*(a+b+6),6*(a+b+4)*(a+b+5)*(a+3),
  3085. 12*(a+b+4)*(a+2)*(a+3),8*(a+1)*(a+2)*(a+3)]
  3086. p3c = [cp[0],cp[1]-3*cp[0],cp[2]-2*cp[1]+3*cp[0],cp[3]-cp[2]+cp[1]-cp[0]]
  3087. assert_allclose(P3.c, array(p3c) / 48.0, atol=1.5e-13, rtol=0)
  3088. def test_kn(self):
  3089. kn1 = special.kn(0,.2)
  3090. assert_allclose(kn1, 1.7527038555281462, atol=1.5e-8, rtol=0)
  3091. def test_negv_kv(self):
  3092. assert_equal(special.kv(3.0, 2.2), special.kv(-3.0, 2.2))
  3093. def test_kv0(self):
  3094. kv0 = special.kv(0,.2)
  3095. assert_allclose(kv0, 1.7527038555281462, atol=1.5e-10, rtol=0)
  3096. def test_kv1(self):
  3097. kv1 = special.kv(1,0.2)
  3098. assert_allclose(kv1, 4.775972543220472, atol=1.5e-10, rtol=0)
  3099. def test_kv2(self):
  3100. kv2 = special.kv(2,0.2)
  3101. assert_allclose(kv2, 49.51242928773287, atol=1.5e-10, rtol=0)
  3102. def test_kn_largeorder(self):
  3103. assert_allclose(special.kn(32, 1), 1.7516596664574289e+43)
  3104. def test_kv_largearg(self):
  3105. assert_equal(special.kv(0, 1e19), 0)
  3106. def test_negv_kve(self):
  3107. assert_equal(special.kve(3.0, 2.2), special.kve(-3.0, 2.2))
  3108. def test_kve(self):
  3109. kve1 = special.kve(0,.2)
  3110. kv1 = special.kv(0,.2)*exp(.2)
  3111. assert_allclose(kve1, kv1, atol=1.5e-8, rtol=0)
  3112. z = .2+1j
  3113. kve2 = special.kve(0,z)
  3114. kv2 = special.kv(0,z)*exp(z)
  3115. assert_allclose(kve2, kv2, atol=1.5e-8, rtol=0)
  3116. def test_kvp_v0n1(self):
  3117. z = 2.2
  3118. assert_allclose(-special.kv(1, z), special.kvp(0, z, n=1),
  3119. atol=1.5e-10, rtol=0)
  3120. def test_kvp_n1(self):
  3121. v = 3.
  3122. z = 2.2
  3123. xc = -special.kv(v+1,z) + v/z*special.kv(v,z)
  3124. x = special.kvp(v,z, n=1)
  3125. # this function (kvp) is broken
  3126. assert_allclose(xc, x, atol=1.5e-10, rtol=0)
  3127. def test_kvp_n2(self):
  3128. v = 3.
  3129. z = 2.2
  3130. xc = (z**2+v**2-v)/z**2 * special.kv(v,z) + special.kv(v+1,z)/z
  3131. x = special.kvp(v, z, n=2)
  3132. assert_allclose(xc, x, atol=1.5e-10, rtol=0)
  3133. def test_y0(self):
  3134. oz = special.y0(.1)
  3135. ozr = special.yn(0,.1)
  3136. assert_allclose(oz, ozr, atol=1.5e-8, rtol=0)
  3137. def test_y1(self):
  3138. o1 = special.y1(.1)
  3139. o1r = special.yn(1,.1)
  3140. assert_allclose(o1,o1r, atol=1.5e-8, rtol=0)
  3141. def test_y0_zeros(self):
  3142. yo,ypo = special.y0_zeros(2)
  3143. zo,zpo = special.y0_zeros(2,complex=1)
  3144. all = r_[yo,zo]
  3145. allval = r_[ypo,zpo]
  3146. assert_allclose(abs(special.yv(0.0, all)), 0.0, atol=1.5e-11, rtol=0)
  3147. assert_allclose(abs(special.yv(1, all) - allval), 0.0, atol=1.5e-11, rtol=0)
  3148. def test_y1_zeros(self):
  3149. y1 = special.y1_zeros(1)
  3150. assert_allclose(y1, (array([2.19714]), array([0.52079])),
  3151. atol=1.5e-5, rtol=0)
  3152. def test_y1p_zeros(self):
  3153. y1p = special.y1p_zeros(1,complex=1)
  3154. assert_allclose(y1p, (array([0.5768+0.904j]), array([-0.7635+0.5892j])),
  3155. atol=1.5e-3, rtol=0)
  3156. def test_yn_zeros(self):
  3157. an = special.yn_zeros(4,2)
  3158. assert_allclose(an, array([5.64515, 9.36162]), atol=1.5e-5, rtol=0)
  3159. an = special.yn_zeros(443,5)
  3160. assert_allclose(an, [450.13573091578090314,
  3161. 463.05692376675001542,
  3162. 472.80651546418663566,
  3163. 481.27353184725625838,
  3164. 488.98055964441374646],
  3165. rtol=1e-15,)
  3166. def test_ynp_zeros(self):
  3167. ao = special.ynp_zeros(0,2)
  3168. assert_allclose(ao, array([2.19714133, 5.42968104]), atol=1.5e-6, rtol=0)
  3169. ao = special.ynp_zeros(43,5)
  3170. assert_allclose(special.yvp(43, ao), 0, atol=1e-15)
  3171. ao = special.ynp_zeros(443,5)
  3172. assert_allclose(special.yvp(443, ao), 0, atol=1e-9)
  3173. def test_ynp_zeros_large_order(self):
  3174. ao = special.ynp_zeros(443,5)
  3175. assert_allclose(special.yvp(443, ao), 0, atol=1e-14)
  3176. def test_yn(self):
  3177. yn2n = special.yn(1,.2)
  3178. assert_allclose(yn2n, -3.3238249881118471, atol=1.5e-8, rtol=0)
  3179. def test_yn_gh_20405(self):
  3180. # Enforce correct asymptotic behavior for large n.
  3181. observed = cephes.yn(500, 1)
  3182. assert observed == -np.inf
  3183. def test_negv_yv(self):
  3184. assert_allclose(special.yv(-3, 2), -special.yv(3, 2),
  3185. atol=1.5e-14, rtol=0)
  3186. def test_yv(self):
  3187. yv2 = special.yv(1,.2)
  3188. assert_allclose(yv2, -3.3238249881118471, atol=1.5e-8, rtol=0)
  3189. def test_negv_yve(self):
  3190. assert_allclose(special.yve(-3, 2), -special.yve(3, 2),
  3191. atol=1.5e-14, rtol=0)
  3192. def test_yve(self):
  3193. yve2 = special.yve(1,.2)
  3194. assert_allclose(yve2, -3.3238249881118471, atol=1.5e-8, rtol=0)
  3195. yve2r = special.yv(1,.2+1j)*exp(-1)
  3196. yve22 = special.yve(1,.2+1j)
  3197. assert_allclose(yve22, yve2r, atol=1.5e-8, rtol=0)
  3198. def test_yvp(self):
  3199. yvpr = (special.yv(1,.2) - special.yv(3,.2))/2.0
  3200. yvp1 = special.yvp(2,.2)
  3201. assert_allclose(yvp1, yvpr, atol=1.5e-10, rtol=0)
  3202. def _cephes_vs_amos_points(self):
  3203. """Yield points at which to compare Cephes implementation to AMOS"""
  3204. # check several points, including large-amplitude ones
  3205. v = [-120, -100.3, -20., -10., -1., -.5, 0., 1., 12.49, 120., 301]
  3206. z = [-1300, -11, -10, -1, 1., 10., 200.5, 401., 600.5, 700.6, 1300,
  3207. 10003]
  3208. yield from itertools.product(v, z)
  3209. # check half-integers; these are problematic points at least
  3210. # for cephes/iv
  3211. yield from itertools.product(0.5 + arange(-60, 60), [3.5])
  3212. def check_cephes_vs_amos(self, f1, f2, rtol=1e-11, atol=0, skip=None):
  3213. for v, z in self._cephes_vs_amos_points():
  3214. if skip is not None and skip(v, z):
  3215. continue
  3216. c1, c2, c3 = f1(v, z), f1(v,z+0j), f2(int(v), z)
  3217. if np.isinf(c1):
  3218. assert_(np.abs(c2) >= 1e300, (v, z))
  3219. elif np.isnan(c1):
  3220. assert_(c2.imag != 0, (v, z))
  3221. else:
  3222. assert_allclose(c1, c2, err_msg=(v, z), rtol=rtol, atol=atol)
  3223. if v == int(v):
  3224. assert_allclose(c3, c2, err_msg=(v, z),
  3225. rtol=rtol, atol=atol)
  3226. @pytest.mark.xfail(platform.machine() == 'ppc64le',
  3227. reason="fails on ppc64le")
  3228. def test_jv_cephes_vs_amos(self):
  3229. self.check_cephes_vs_amos(special.jv, special.jn, rtol=1e-10, atol=1e-305)
  3230. @pytest.mark.xfail(platform.machine() == 'ppc64le',
  3231. reason="fails on ppc64le")
  3232. def test_yv_cephes_vs_amos(self):
  3233. self.check_cephes_vs_amos(special.yv, special.yn, rtol=1e-11, atol=1e-305)
  3234. def test_yv_cephes_vs_amos_only_small_orders(self):
  3235. def skipper(v, z):
  3236. return abs(v) > 50
  3237. self.check_cephes_vs_amos(special.yv, special.yn, rtol=1e-11, atol=1e-305,
  3238. skip=skipper)
  3239. def test_iv_cephes_vs_amos(self):
  3240. with np.errstate(all='ignore'):
  3241. self.check_cephes_vs_amos(special.iv, special.iv, rtol=5e-9, atol=1e-305)
  3242. @pytest.mark.slow
  3243. def test_iv_cephes_vs_amos_mass_test(self):
  3244. N = 1000000
  3245. np.random.seed(1)
  3246. v = np.random.pareto(0.5, N) * (-1)**np.random.randint(2, size=N)
  3247. x = np.random.pareto(0.2, N) * (-1)**np.random.randint(2, size=N)
  3248. imsk = (np.random.randint(8, size=N) == 0)
  3249. v[imsk] = v[imsk].astype(np.int64)
  3250. with np.errstate(all='ignore'):
  3251. c1 = special.iv(v, x)
  3252. c2 = special.iv(v, x+0j)
  3253. # deal with differences in the inf and zero cutoffs
  3254. c1[abs(c1) > 1e300] = np.inf
  3255. c2[abs(c2) > 1e300] = np.inf
  3256. c1[abs(c1) < 1e-300] = 0
  3257. c2[abs(c2) < 1e-300] = 0
  3258. dc = abs(c1/c2 - 1)
  3259. dc[np.isnan(dc)] = 0
  3260. k = np.argmax(dc)
  3261. # Most error apparently comes from AMOS and not our implementation;
  3262. # there are some problems near integer orders there
  3263. assert_(
  3264. dc[k] < 2e-7,
  3265. (v[k], x[k], special.iv(v[k], x[k]), special.iv(v[k], x[k]+0j))
  3266. )
  3267. def test_kv_cephes_vs_amos(self):
  3268. self.check_cephes_vs_amos(special.kv, special.kn, rtol=1e-9, atol=1e-305)
  3269. self.check_cephes_vs_amos(special.kv, special.kv, rtol=1e-9, atol=1e-305)
  3270. def test_ticket_623(self):
  3271. assert_allclose(special.jv(3, 4), 0.43017147387562193)
  3272. assert_allclose(special.jv(301, 1300), 0.0183487151115275)
  3273. assert_allclose(special.jv(301, 1296.0682), -0.0224174325312048)
  3274. def test_ticket_853(self):
  3275. """Negative-order Bessels"""
  3276. # cephes
  3277. assert_allclose(special.jv(-1, 1), -0.4400505857449335)
  3278. assert_allclose(special.jv(-2, 1), 0.1149034849319005)
  3279. assert_allclose(special.yv(-1, 1), 0.7812128213002887)
  3280. assert_allclose(special.yv(-2, 1), -1.650682606816255)
  3281. assert_allclose(special.iv(-1, 1), 0.5651591039924851)
  3282. assert_allclose(special.iv(-2, 1), 0.1357476697670383)
  3283. assert_allclose(special.kv(-1, 1), 0.6019072301972347)
  3284. assert_allclose(special.kv(-2, 1), 1.624838898635178)
  3285. assert_allclose(special.jv(-0.5, 1), 0.43109886801837607952)
  3286. assert_allclose(special.yv(-0.5, 1), 0.6713967071418031)
  3287. assert_allclose(special.iv(-0.5, 1), 1.231200214592967)
  3288. assert_allclose(special.kv(-0.5, 1), 0.4610685044478945)
  3289. # amos
  3290. assert_allclose(special.jv(-1, 1+0j), -0.4400505857449335)
  3291. assert_allclose(special.jv(-2, 1+0j), 0.1149034849319005)
  3292. assert_allclose(special.yv(-1, 1+0j), 0.7812128213002887)
  3293. assert_allclose(special.yv(-2, 1+0j), -1.650682606816255)
  3294. assert_allclose(special.iv(-1, 1+0j), 0.5651591039924851)
  3295. assert_allclose(special.iv(-2, 1+0j), 0.1357476697670383)
  3296. assert_allclose(special.kv(-1, 1+0j), 0.6019072301972347)
  3297. assert_allclose(special.kv(-2, 1+0j), 1.624838898635178)
  3298. assert_allclose(special.jv(-0.5, 1+0j), 0.43109886801837607952)
  3299. assert_allclose(special.jv(-0.5, 1+1j), 0.2628946385649065-0.827050182040562j)
  3300. assert_allclose(special.yv(-0.5, 1+0j), 0.6713967071418031)
  3301. assert_allclose(special.yv(-0.5, 1+1j), 0.967901282890131+0.0602046062142816j)
  3302. assert_allclose(special.iv(-0.5, 1+0j), 1.231200214592967)
  3303. assert_allclose(special.iv(-0.5, 1+1j), 0.77070737376928+0.39891821043561j)
  3304. assert_allclose(special.kv(-0.5, 1+0j), 0.4610685044478945)
  3305. assert_allclose(special.kv(-0.5, 1+1j), 0.06868578341999-0.38157825981268j)
  3306. assert_allclose(special.jve(-0.5,1+0.3j), special.jv(-0.5, 1+0.3j)*exp(-0.3))
  3307. assert_allclose(special.yve(-0.5,1+0.3j), special.yv(-0.5, 1+0.3j)*exp(-0.3))
  3308. assert_allclose(special.ive(-0.5,0.3+1j), special.iv(-0.5, 0.3+1j)*exp(-0.3))
  3309. assert_allclose(special.kve(-0.5,0.3+1j), special.kv(-0.5, 0.3+1j)*exp(0.3+1j))
  3310. assert_allclose(
  3311. special.hankel1(-0.5, 1+1j),
  3312. special.jv(-0.5, 1+1j) + 1j*special.yv(-0.5,1+1j)
  3313. )
  3314. assert_allclose(
  3315. special.hankel2(-0.5, 1+1j),
  3316. special.jv(-0.5, 1+1j) - 1j*special.yv(-0.5,1+1j)
  3317. )
  3318. def test_ticket_854(self):
  3319. """Real-valued Bessel domains"""
  3320. assert_(isnan(special.jv(0.5, -1)))
  3321. assert_(isnan(special.iv(0.5, -1)))
  3322. assert_(isnan(special.yv(0.5, -1)))
  3323. assert_(isnan(special.yv(1, -1)))
  3324. assert_(isnan(special.kv(0.5, -1)))
  3325. assert_(isnan(special.kv(1, -1)))
  3326. assert_(isnan(special.jve(0.5, -1)))
  3327. assert_(isnan(special.ive(0.5, -1)))
  3328. assert_(isnan(special.yve(0.5, -1)))
  3329. assert_(isnan(special.yve(1, -1)))
  3330. assert_(isnan(special.kve(0.5, -1)))
  3331. assert_(isnan(special.kve(1, -1)))
  3332. assert_(isnan(special.airye(-1)[0:2]).all(), special.airye(-1))
  3333. assert_(not isnan(special.airye(-1)[2:4]).any(), special.airye(-1))
  3334. def test_gh_7909(self):
  3335. assert_(special.kv(1.5, 0) == np.inf)
  3336. assert_(special.kve(1.5, 0) == np.inf)
  3337. def test_ticket_503(self):
  3338. """Real-valued Bessel I overflow"""
  3339. assert_allclose(special.iv(1, 700), 1.528500390233901e302)
  3340. assert_allclose(special.iv(1000, 1120), 1.301564549405821e301)
  3341. def test_iv_hyperg_poles(self):
  3342. assert_allclose(special.iv(-0.5, 1), 1.231200214592967)
  3343. def iv_series(self, v, z, n=200):
  3344. k = arange(0, n).astype(double)
  3345. r = (v+2*k)*log(.5*z) - special.gammaln(k+1) - special.gammaln(v+k+1)
  3346. r[isnan(r)] = inf
  3347. r = exp(r)
  3348. err = abs(r).max() * finfo(double).eps * n + abs(r[-1])*10
  3349. return r.sum(), err
  3350. def test_i0_series(self):
  3351. for z in [1., 10., 200.5]:
  3352. value, err = self.iv_series(0, z)
  3353. assert_allclose(special.i0(z), value, atol=err, err_msg=z)
  3354. def test_i1_series(self):
  3355. for z in [1., 10., 200.5]:
  3356. value, err = self.iv_series(1, z)
  3357. assert_allclose(special.i1(z), value, atol=err, err_msg=z)
  3358. def test_iv_series(self):
  3359. for v in [-20., -10., -1., 0., 1., 12.49, 120.]:
  3360. for z in [1., 10., 200.5, -1+2j]:
  3361. value, err = self.iv_series(v, z)
  3362. assert_allclose(special.iv(v, z), value, atol=err, err_msg=(v, z))
  3363. def test_i0(self):
  3364. values = [[0.0, 1.0],
  3365. [1e-10, 1.0],
  3366. [0.1, 0.9071009258],
  3367. [0.5, 0.6450352706],
  3368. [1.0, 0.4657596077],
  3369. [2.5, 0.2700464416],
  3370. [5.0, 0.1835408126],
  3371. [20.0, 0.0897803119],
  3372. ]
  3373. for i, (x, v) in enumerate(values):
  3374. cv = special.i0(x) * exp(-x)
  3375. assert_allclose(cv, v, atol=1.5e-8, rtol=0, err_msg=f'test #{i}')
  3376. def test_i0e(self):
  3377. oize = special.i0e(.1)
  3378. oizer = special.ive(0, .1)
  3379. assert_allclose(oize, oizer, atol=1.5e-8, rtol=0)
  3380. def test_i1(self):
  3381. values = [[0.0, 0.0],
  3382. [1e-10, 0.4999999999500000e-10],
  3383. [0.1, 0.0452984468],
  3384. [0.5, 0.1564208032],
  3385. [1.0, 0.2079104154],
  3386. [5.0, 0.1639722669],
  3387. [20.0, 0.0875062222],
  3388. ]
  3389. for i, (x, v) in enumerate(values):
  3390. cv = special.i1(x) * exp(-x)
  3391. assert_allclose(cv, v, atol=1.5e-8, rtol=0, err_msg=f'test #{i}')
  3392. def test_i1e(self):
  3393. oi1e = special.i1e(.1)
  3394. oi1er = special.ive(1, .1)
  3395. assert_allclose(oi1e, oi1er, atol=1.5e-8, rtol=0)
  3396. def test_iti0k0(self):
  3397. iti0 = array(special.iti0k0(5))
  3398. assert_allclose(iti0, array([31.848667776169801, 1.5673873907283657]),
  3399. atol=1.5e-5, rtol=0)
  3400. def test_it2i0k0(self):
  3401. it2k = special.it2i0k0(.1)
  3402. assert_allclose(it2k, array([0.0012503906973464409, 3.3309450354686687]),
  3403. atol=1.5e-6, rtol=0)
  3404. def test_iv(self):
  3405. iv1 = special.iv(0,.1)*exp(-.1)
  3406. assert_allclose(iv1, 0.90710092578230106, atol=1.5e-10, rtol=0)
  3407. def test_negv_ive(self):
  3408. assert_equal(special.ive(3,2), special.ive(-3,2))
  3409. def test_ive(self):
  3410. ive1 = special.ive(0,.1)
  3411. iv1 = special.iv(0,.1)*exp(-.1)
  3412. assert_allclose(ive1, iv1, atol=1.5e-10, rtol=0)
  3413. def test_ivp0(self):
  3414. assert_allclose(special.iv(1, 2), special.ivp(0, 2), atol=1.5e-10, rtol=0)
  3415. def test_ivp(self):
  3416. y = (special.iv(0,2) + special.iv(2,2))/2
  3417. x = special.ivp(1,2)
  3418. assert_allclose(x, y, atol=1.5e-10, rtol=0)
  3419. class TestLaguerre:
  3420. def test_laguerre(self):
  3421. lag0 = special.laguerre(0)
  3422. lag1 = special.laguerre(1)
  3423. lag2 = special.laguerre(2)
  3424. lag3 = special.laguerre(3)
  3425. lag4 = special.laguerre(4)
  3426. lag5 = special.laguerre(5)
  3427. assert_allclose(lag0.c, [1], atol=1.5e-13, rtol=0)
  3428. assert_allclose(lag1.c, [-1, 1], atol=1.5e-13, rtol=0)
  3429. assert_allclose(lag2.c, array([1, -4,2]) / 2.0, atol=1.5e-13, rtol=0)
  3430. assert_allclose(lag3.c, array([-1, 9,-18,6])/6.0, atol=1.5e-13, rtol=0)
  3431. assert_allclose(lag4.c, array([1, -16,72,-96,24])/24.0,
  3432. atol=1.5e-13, rtol=0)
  3433. assert_allclose(lag5.c, array([-1, 25, -200, 600, -600, 120]) / 120.0,
  3434. atol=1.5e-13, rtol=0)
  3435. def test_genlaguerre(self):
  3436. k = 5*np.random.random() - 0.9
  3437. lag0 = special.genlaguerre(0,k)
  3438. lag1 = special.genlaguerre(1,k)
  3439. lag2 = special.genlaguerre(2,k)
  3440. lag3 = special.genlaguerre(3,k)
  3441. assert_equal(lag0.c, [1])
  3442. assert_equal(lag1.c, [-1, k + 1])
  3443. assert_allclose(lag2.c, array([1, -2 * (k + 2), (k + 1.) * (k + 2.)]) / 2.0,
  3444. atol=1.5e-7, rtol=0)
  3445. expected = array([-1,
  3446. 3 * (k + 3),
  3447. -3 * (k + 2) * (k + 3),
  3448. (k + 1) * (k + 2) * (k + 3)]) / 6.0
  3449. assert_allclose(lag3.c, expected, atol=1.5e-7, rtol=0)
  3450. class TestLambda:
  3451. def test_lmbda(self):
  3452. lam = special.lmbda(1,.1)
  3453. lamr = (
  3454. array([special.jn(0,.1), 2*special.jn(1,.1)/.1]),
  3455. array([special.jvp(0,.1), -2*special.jv(1,.1)/.01 + 2*special.jvp(1,.1)/.1])
  3456. )
  3457. assert_allclose(lam, lamr, atol=1.5e-8, rtol=0)
  3458. class TestLog1p:
  3459. def test_log1p(self):
  3460. l1p = (special.log1p(10), special.log1p(11), special.log1p(12))
  3461. l1prl = (log(11), log(12), log(13))
  3462. assert_allclose(l1p, l1prl, atol=1.5e-8, rtol=0)
  3463. def test_log1pmore(self):
  3464. l1pm = (special.log1p(1), special.log1p(1.1), special.log1p(1.2))
  3465. l1pmrl = (log(2),log(2.1),log(2.2))
  3466. assert_allclose(l1pm, l1pmrl, atol=1.5e-8, rtol=0)
  3467. def ce_fourier_coefficient_using_integral(k, n, q):
  3468. """
  3469. Compute the Fourier coefficient of the even Mathieu function.
  3470. The integral definition of a Fourier coefficient is used.
  3471. This function is used as an alternative implementation of
  3472. mathieu_even_coef().
  3473. """
  3474. period = 180 if n % 2 == 0 else 360
  3475. # For k = 0, the factor outside the integral is (1/period).
  3476. # For k = 1, 2, 3, ..., the factor is (2/period).
  3477. c = (1/period)*quad(lambda t: special.mathieu_cem(n, q, t)[0],
  3478. -period/2, period/2,
  3479. weight='cos', wvar=2*np.pi*k/period, epsrel=1e-14)[0]
  3480. if k > 0:
  3481. c *= 2
  3482. return c
  3483. def se_fourier_coefficient_using_integral(k, n, q):
  3484. """
  3485. Compute the Fourier coefficient of the odd Mathieu function.
  3486. The integral definition of a Fourier coefficient is used.
  3487. This function is used as an alternative implementation of
  3488. mathieu_odd_coef().
  3489. """
  3490. # For k == 0, the result is 0. (The test code won't call this
  3491. # function with k == 0, but we'll check anyway.)
  3492. if k == 0:
  3493. return 0.0
  3494. period = 180 if n % 2 == 0 else 360
  3495. c = (2/period)*quad(lambda t: special.mathieu_sem(n, q, t)[0],
  3496. -period/2, period/2,
  3497. weight='sin', wvar=2*np.pi*k/period, epsrel=1e-14)[0]
  3498. return c
  3499. class TestMathieu:
  3500. @pytest.mark.parametrize('n, q', [(4, 3.5), (8, 4.25)])
  3501. def test_mathieu_even_coef_against_integral_n_even(self, n, q):
  3502. # Get the nonzero Fourier coefficients. For the even Mathieu functions
  3503. # with even n, these are the coefficients of the cosine series. None of
  3504. # the coefficients are 0 for k = 0, 1, 2, 3, ...
  3505. A = special.mathieu_even_coef(n, q)
  3506. # Compare the first four nonzero Fourier coefficients to the coefficients
  3507. # computed using the integral definition.
  3508. c = [ce_fourier_coefficient_using_integral(k, n, q) for k in range(4)]
  3509. assert_allclose(c, A[:len(c)], rtol=1e-10)
  3510. @pytest.mark.parametrize('n, q', [(3, 3.5), (7, 2)])
  3511. def test_mathieu_even_coef_against_integral_n_odd(self, n, q):
  3512. # Get the nonzero Fourier coefficients. For the even Mathieu functions
  3513. # with odd n, these are the coefficients of the cosine series. Only the
  3514. # coefficients c[k] for k = 1, 3, 5, 7, ... are nonzero. These are the
  3515. # values returned by mathieu_even_coef(n, q).
  3516. A = special.mathieu_even_coef(n, q)
  3517. # Compare the first 4 nonzero Fourier coefficients to the coefficients
  3518. # computed using the integral definition.
  3519. c = [ce_fourier_coefficient_using_integral(k, n, q) for k in range(1, 9, 2)]
  3520. assert_allclose(c, A[:len(c)], rtol=1e-10)
  3521. @pytest.mark.parametrize('n, q', [(2, 3.5), (10, 2)])
  3522. def test_mathieu_odd_coef_against_integral_n_even(self, n, q):
  3523. # Get the nonzero Fourier coefficients. For the odd Mathieu functions
  3524. # with even n, these are the coefficients of the sine series. Only the
  3525. # coefficients c[k] for k = 1, 2, 3, 4, ... are nonzero. These are the
  3526. # values returned by mathieu_odd_coef(n, q).
  3527. B = special.mathieu_odd_coef(n, q)
  3528. # Compare the first 4 nonzero Fourier coefficients to the coefficients
  3529. # computed using the integral definition.
  3530. c = [se_fourier_coefficient_using_integral(k, n, q) for k in range(1, 5)]
  3531. assert_allclose(c, B[:len(c)], rtol=1e-10)
  3532. @pytest.mark.parametrize('n, q', [(3, 3.5), (7, 2)])
  3533. def test_mathieu_odd_coef_against_integral_n_odd(self, n, q):
  3534. # Get the nonzero Fourier coefficients. For the odd Mathieu functions
  3535. # with odd n, these are the coefficients of the sine series. Only the
  3536. # coefficients c[k] for k = 1, 3, 5, 7, ... are nonzero. These are the
  3537. # values returned by mathieu_odd_coef(n, q).
  3538. B = special.mathieu_odd_coef(n, q)
  3539. # Compare the first 4 nonzero Fourier coefficients to the coefficients
  3540. # computed using the integral definition.
  3541. c = [se_fourier_coefficient_using_integral(k, n, q) for k in range(1, 9, 2)]
  3542. assert_allclose(c, B[:len(c)], rtol=1e-10)
  3543. class TestFresnelIntegral:
  3544. def test_modfresnelp(self):
  3545. pass
  3546. def test_modfresnelm(self):
  3547. pass
  3548. class TestOblCvSeq:
  3549. def test_obl_cv_seq(self):
  3550. obl = special.obl_cv_seq(0,3,1)
  3551. assert_allclose(obl, array([-0.348602,
  3552. 1.393206,
  3553. 5.486800,
  3554. 11.492120]),
  3555. atol=1.5e-5, rtol=0)
  3556. class TestParabolicCylinder:
  3557. def test_pbdn_seq(self):
  3558. pb = special.pbdn_seq(1, .1)
  3559. assert_allclose(pb, (array([0.9975,
  3560. 0.0998]),
  3561. array([-0.0499,
  3562. 0.9925])),
  3563. atol=1.5e-4, rtol=0)
  3564. def test_pbdv(self):
  3565. special.pbdv(1,.2)
  3566. 1/2*(.2)*special.pbdv(1,.2)[0] - special.pbdv(0,.2)[0]
  3567. def test_pbdv_seq(self):
  3568. pbn = special.pbdn_seq(1,.1)
  3569. pbv = special.pbdv_seq(1,.1)
  3570. assert_allclose(pbv, (real(pbn[0]), real(pbn[1])), atol=1.5e-4, rtol=0)
  3571. def test_pbdv_points(self):
  3572. # simple case
  3573. eta = np.linspace(-10, 10, 5)
  3574. z = 2**(eta/2)*np.sqrt(np.pi)*special.rgamma(.5-.5*eta)
  3575. assert_allclose(special.pbdv(eta, 0.)[0], z, rtol=1e-14, atol=1e-14)
  3576. # some points
  3577. assert_allclose(special.pbdv(10.34, 20.44)[0], 1.3731383034455e-32, rtol=1e-12)
  3578. assert_allclose(special.pbdv(-9.53, 3.44)[0], 3.166735001119246e-8, rtol=1e-12)
  3579. def test_pbdv_gradient(self):
  3580. x = np.linspace(-4, 4, 8)[:,None]
  3581. eta = np.linspace(-10, 10, 5)[None,:]
  3582. p = special.pbdv(eta, x)
  3583. eps = 1e-7 + 1e-7*abs(x)
  3584. dp = (special.pbdv(eta, x + eps)[0] - special.pbdv(eta, x - eps)[0]) / eps / 2.
  3585. assert_allclose(p[1], dp, rtol=1e-6, atol=1e-6)
  3586. def test_pbvv_gradient(self):
  3587. x = np.linspace(-4, 4, 8)[:,None]
  3588. eta = np.linspace(-10, 10, 5)[None,:]
  3589. p = special.pbvv(eta, x)
  3590. eps = 1e-7 + 1e-7*abs(x)
  3591. dp = (special.pbvv(eta, x + eps)[0] - special.pbvv(eta, x - eps)[0]) / eps / 2.
  3592. assert_allclose(p[1], dp, rtol=1e-6, atol=1e-6)
  3593. def test_pbvv_seq(self):
  3594. res1, res2 = special.pbvv_seq(2, 3)
  3595. assert_allclose(res1, np.array([2.976319645712036,
  3596. 1.358840996329579,
  3597. 0.5501016716383508]))
  3598. assert_allclose(res2, np.array([3.105638472238475,
  3599. 0.9380581512176672,
  3600. 0.533688488872053]))
  3601. class TestPolygamma:
  3602. # from Table 6.2 (pg. 271) of A&S
  3603. def test_polygamma(self):
  3604. poly2 = special.polygamma(2, 1)
  3605. poly3 = special.polygamma(3, 1)
  3606. assert_allclose(poly2, -2.4041138063, atol=1.5e-10, rtol=0)
  3607. assert_allclose(poly3, 6.4939394023, atol=1.5e-10, rtol=0)
  3608. # Test polygamma(0, x) == psi(x)
  3609. x = [2, 3, 1.1e14]
  3610. assert_allclose(special.polygamma(0, x), special.psi(x),
  3611. atol=1.5e-7, rtol=0)
  3612. # Test broadcasting
  3613. n = [0, 1, 2]
  3614. x = [0.5, 1.5, 2.5]
  3615. expected = [-1.9635100260214238, 0.93480220054467933,
  3616. -0.23620405164172739]
  3617. assert_allclose(special.polygamma(n, x), expected, atol=1.5e-7, rtol=0)
  3618. expected = np.vstack([expected]*2)
  3619. assert_allclose(special.polygamma(n, np.vstack([x]*2)), expected,
  3620. atol=1.5e-7, rtol=0)
  3621. assert_allclose(special.polygamma(np.vstack([n]*2), x), expected,
  3622. atol=1.5e-7, rtol=0)
  3623. class TestProCvSeq:
  3624. def test_pro_cv_seq(self):
  3625. prol = special.pro_cv_seq(0, 3, 1)
  3626. assert_allclose(prol, array([0.319000,
  3627. 2.593084,
  3628. 6.533471,
  3629. 12.514462]),
  3630. atol=1.5e-5, rtol=0)
  3631. class TestPsi:
  3632. def test_psi(self):
  3633. ps = special.psi(1)
  3634. assert_allclose(ps, -0.57721566490153287, atol=1.5e-8, rtol=0)
  3635. class TestRadian:
  3636. def test_radian(self):
  3637. rad = special.radian(90, 0, 0)
  3638. assert_allclose(rad, pi/2.0, atol=1.5e-5, rtol=0)
  3639. def test_radianmore(self):
  3640. rad1 = special.radian(90, 1, 60)
  3641. assert_allclose(rad1, pi/2 + 0.0005816135199345904, atol=1.5e-5, rtol=0)
  3642. class TestRiccati:
  3643. def test_riccati_jn(self):
  3644. N, x = 2, 0.2
  3645. S = np.empty((N, N))
  3646. for n in range(N):
  3647. j = special.spherical_jn(n, x)
  3648. jp = special.spherical_jn(n, x, derivative=True)
  3649. S[0,n] = x*j
  3650. S[1,n] = x*jp + j
  3651. assert_allclose(S, special.riccati_jn(n, x), atol=1.5e-8, rtol=0)
  3652. def test_riccati_yn(self):
  3653. N, x = 2, 0.2
  3654. C = np.empty((N, N))
  3655. for n in range(N):
  3656. y = special.spherical_yn(n, x)
  3657. yp = special.spherical_yn(n, x, derivative=True)
  3658. C[0,n] = x*y
  3659. C[1,n] = x*yp + y
  3660. assert_allclose(C, special.riccati_yn(n, x), atol=1.5e-8, rtol=0)
  3661. class TestSoftplus:
  3662. def test_softplus(self):
  3663. # Test cases for the softplus function. Selected based on Eq.(10) of:
  3664. # Mächler, M. (2012). log1mexp-note.pdf. Rmpfr: R MPFR - Multiple Precision
  3665. # Floating-Point Reliable. Retrieved from:
  3666. # https://cran.r-project.org/web/packages/Rmpfr/vignettes/log1mexp-note.pdf
  3667. # Reference values computed with `mpmath`
  3668. import numpy as np
  3669. rng = np.random.default_rng(3298432985245)
  3670. n = 3
  3671. a1 = rng.uniform(-100, -37, size=n)
  3672. a2 = rng.uniform(-37, 18, size=n)
  3673. a3 = rng.uniform(18, 33.3, size=n)
  3674. a4 = rng.uniform(33.33, 100, size=n)
  3675. a = np.stack([a1, a2, a3, a4])
  3676. # from mpmath import mp
  3677. # mp.dps = 100
  3678. # @np.vectorize
  3679. # def softplus(x):
  3680. # return float(mp.log(mp.one + mp.exp(x)))
  3681. # softplus(a).tolist()
  3682. ref = [[1.692721323272333e-42, 7.42673911145206e-41, 8.504608846033205e-35],
  3683. [1.8425343736349797, 9.488245799395577e-15, 7.225195764021444e-08],
  3684. [31.253760266045106, 27.758244090327832, 29.995959179643634],
  3685. [73.26040086468937, 76.24944728617226, 37.83955519155184]]
  3686. res = softplus(a)
  3687. assert_allclose(res, ref, rtol=2e-15)
  3688. def test_softplus_with_kwargs(self):
  3689. x = np.arange(5) - 2
  3690. out = np.ones(5)
  3691. ref = out.copy()
  3692. where = x > 0
  3693. softplus(x, out=out, where=where)
  3694. ref[where] = softplus(x[where])
  3695. assert_allclose(out, ref)
  3696. class TestRound:
  3697. def test_round(self):
  3698. rnd = list(map(int, (special.round(10.1),
  3699. special.round(10.4),
  3700. special.round(10.5),
  3701. special.round(10.6))))
  3702. # Note: According to the documentation, scipy.special.round is
  3703. # supposed to round to the nearest even number if the fractional
  3704. # part is exactly 0.5. On some platforms, this does not appear
  3705. # to work and thus this test may fail. However, this unit test is
  3706. # correctly written.
  3707. rndrl = (10,10,10,11)
  3708. assert_array_equal(rnd,rndrl)
  3709. class TestStruve:
  3710. def _series(self, v, z, n=100):
  3711. """Compute Struve function & error estimate from its power series."""
  3712. k = arange(0, n)
  3713. r = (-1)**k * (.5*z)**(2*k+v+1)/special.gamma(k+1.5)/special.gamma(k+v+1.5)
  3714. err = abs(r).max() * finfo(double).eps * n
  3715. return r.sum(), err
  3716. def test_vs_series(self):
  3717. """Check Struve function versus its power series"""
  3718. for v in [-20, -10, -7.99, -3.4, -1, 0, 1, 3.4, 12.49, 16]:
  3719. for z in [1, 10, 19, 21, 30]:
  3720. value, err = self._series(v, z)
  3721. assert_allclose(special.struve(v, z), value, rtol=0, atol=err), (v, z)
  3722. def test_some_values(self):
  3723. assert_allclose(special.struve(-7.99, 21), 0.0467547614113, rtol=1e-7)
  3724. assert_allclose(special.struve(-8.01, 21), 0.0398716951023, rtol=1e-8)
  3725. assert_allclose(special.struve(-3.0, 200), 0.0142134427432, rtol=1e-12)
  3726. assert_allclose(special.struve(-8.0, -41), 0.0192469727846, rtol=1e-11)
  3727. assert_equal(special.struve(-12, -41), -special.struve(-12, 41))
  3728. assert_equal(special.struve(+12, -41), -special.struve(+12, 41))
  3729. assert_equal(special.struve(-11, -41), +special.struve(-11, 41))
  3730. assert_equal(special.struve(+11, -41), +special.struve(+11, 41))
  3731. assert_(isnan(special.struve(-7.1, -1)))
  3732. assert_(isnan(special.struve(-10.1, -1)))
  3733. def test_regression_679(self):
  3734. """Regression test for #679"""
  3735. assert_allclose(special.struve(-1.0, 20 - 1e-8),
  3736. special.struve(-1.0, 20 + 1e-8))
  3737. assert_allclose(special.struve(-2.0, 20 - 1e-8),
  3738. special.struve(-2.0, 20 + 1e-8))
  3739. assert_allclose(special.struve(-4.3, 20 - 1e-8),
  3740. special.struve(-4.3, 20 + 1e-8))
  3741. def test_chi2_smalldf():
  3742. assert_allclose(special.chdtr(0.6, 3), 0.957890536704110, atol=1.5e-7, rtol=0)
  3743. def test_ch2_inf():
  3744. assert_equal(special.chdtr(0.7,np.inf), 1.0)
  3745. @pytest.mark.parametrize("x", [-np.inf, -1.0, -0.0, 0.0, np.inf, np.nan])
  3746. def test_chi2_v_nan(x):
  3747. assert np.isnan(special.chdtr(np.nan, x))
  3748. @pytest.mark.parametrize("v", [-np.inf, -1.0, -0.0, 0.0, np.inf, np.nan])
  3749. def test_chi2_x_nan(v):
  3750. assert np.isnan(special.chdtr(v, np.nan))
  3751. @pytest.mark.parametrize("x", [-np.inf, -1.0, -0.0, 0.0, np.inf, np.nan])
  3752. def test_chi2c_v_nan(x):
  3753. assert np.isnan(special.chdtrc(np.nan, x))
  3754. @pytest.mark.parametrize("v", [-np.inf, -1.0, -0.0, 0.0, np.inf, np.nan])
  3755. def test_chi2c_x_nan(v):
  3756. assert np.isnan(special.chdtrc(v, np.nan))
  3757. def test_chi2_edgecases_gh20972():
  3758. # Tests that a variety of edgecases for chi square distribution functions
  3759. # correctly return NaN when and only when they are supposed to, when
  3760. # computed through different related ufuncs. See gh-20972.
  3761. v = np.asarray([-0.01, 0, 0.01, 1, np.inf])[:, np.newaxis]
  3762. x = np.asarray([-np.inf, -0.01, 0, 0.01, np.inf])
  3763. # Check that `gammainc` is NaN when it should be and finite otherwise
  3764. ref = special.gammainc(v / 2, x / 2)
  3765. mask = (x < 0) | (v < 0) | (x == 0) & (v == 0) | np.isinf(v) & np.isinf(x)
  3766. assert np.all(np.isnan(ref[mask]))
  3767. assert np.all(np.isfinite(ref[~mask]))
  3768. # Use `gammainc` as a reference for the rest
  3769. assert_allclose(special.chdtr(v, x), ref)
  3770. assert_allclose(special.gdtr(1, v / 2, x / 2), ref)
  3771. assert_allclose(1 - special.gammaincc(v / 2, x / 2), ref)
  3772. assert_allclose(1 - special.chdtrc(v, x), ref)
  3773. assert_allclose(1 - special.gdtrc(1, v / 2, x / 2), ref)
  3774. def test_chi2c_smalldf():
  3775. assert_allclose(special.chdtrc(0.6, 3), 1 - 0.957890536704110,
  3776. atol=1.5e-7, rtol=0)
  3777. def test_chi2_inv_smalldf():
  3778. assert_allclose(special.chdtri(0.6, 1 - 0.957890536704110), 3,
  3779. atol=1.5e-7, rtol=0)
  3780. def test_agm_simple():
  3781. rtol = 1e-13
  3782. # Gauss's constant
  3783. assert_allclose(1/special.agm(1, np.sqrt(2)), 0.834626841674073186,
  3784. rtol=rtol)
  3785. # These values were computed using Wolfram Alpha, with the
  3786. # function ArithmeticGeometricMean[a, b].
  3787. agm13 = 1.863616783244897
  3788. agm15 = 2.604008190530940
  3789. agm35 = 3.936235503649555
  3790. assert_allclose(special.agm([[1], [3]], [1, 3, 5]),
  3791. [[1, agm13, agm15],
  3792. [agm13, 3, agm35]], rtol=rtol)
  3793. # Computed by the iteration formula using mpmath,
  3794. # with mpmath.mp.prec = 1000:
  3795. agm12 = 1.4567910310469068
  3796. assert_allclose(special.agm(1, 2), agm12, rtol=rtol)
  3797. assert_allclose(special.agm(2, 1), agm12, rtol=rtol)
  3798. assert_allclose(special.agm(-1, -2), -agm12, rtol=rtol)
  3799. assert_allclose(special.agm(24, 6), 13.458171481725614, rtol=rtol)
  3800. assert_allclose(special.agm(13, 123456789.5), 11111458.498599306,
  3801. rtol=rtol)
  3802. assert_allclose(special.agm(1e30, 1), 2.229223055945383e+28, rtol=rtol)
  3803. assert_allclose(special.agm(1e-22, 1), 0.030182566420169886, rtol=rtol)
  3804. assert_allclose(special.agm(1e150, 1e180), 2.229223055945383e+178,
  3805. rtol=rtol)
  3806. assert_allclose(special.agm(1e180, 1e-150), 2.0634722510162677e+177,
  3807. rtol=rtol)
  3808. assert_allclose(special.agm(1e-150, 1e-170), 3.3112619670463756e-152,
  3809. rtol=rtol)
  3810. fi = np.finfo(1.0)
  3811. assert_allclose(special.agm(fi.tiny, fi.max), 1.9892072050015473e+305,
  3812. rtol=rtol)
  3813. assert_allclose(special.agm(0.75*fi.max, fi.max), 1.564904312298045e+308,
  3814. rtol=rtol)
  3815. assert_allclose(special.agm(fi.tiny, 3*fi.tiny), 4.1466849866735005e-308,
  3816. rtol=rtol)
  3817. # zero, nan and inf cases.
  3818. assert_equal(special.agm(0, 0), 0)
  3819. assert_equal(special.agm(99, 0), 0)
  3820. assert_equal(special.agm(-1, 10), np.nan)
  3821. assert_equal(special.agm(0, np.inf), np.nan)
  3822. assert_equal(special.agm(np.inf, 0), np.nan)
  3823. assert_equal(special.agm(0, -np.inf), np.nan)
  3824. assert_equal(special.agm(-np.inf, 0), np.nan)
  3825. assert_equal(special.agm(np.inf, -np.inf), np.nan)
  3826. assert_equal(special.agm(-np.inf, np.inf), np.nan)
  3827. assert_equal(special.agm(1, np.nan), np.nan)
  3828. assert_equal(special.agm(np.nan, -1), np.nan)
  3829. assert_equal(special.agm(1, np.inf), np.inf)
  3830. assert_equal(special.agm(np.inf, 1), np.inf)
  3831. assert_equal(special.agm(-1, -np.inf), -np.inf)
  3832. assert_equal(special.agm(-np.inf, -1), -np.inf)
  3833. def test_legacy():
  3834. # Legacy behavior: truncating arguments to integers
  3835. with warnings.catch_warnings():
  3836. warnings.filterwarnings(
  3837. "ignore", "floating point number truncated to an integer", RuntimeWarning)
  3838. assert_equal(special.expn(1, 0.3), special.expn(1.8, 0.3))
  3839. assert_equal(special.nbdtrc(1, 2, 0.3), special.nbdtrc(1.8, 2.8, 0.3))
  3840. assert_equal(special.nbdtr(1, 2, 0.3), special.nbdtr(1.8, 2.8, 0.3))
  3841. assert_equal(special.nbdtri(1, 2, 0.3), special.nbdtri(1.8, 2.8, 0.3))
  3842. assert_equal(special.pdtri(1, 0.3), special.pdtri(1.8, 0.3))
  3843. assert_equal(special.kn(1, 0.3), special.kn(1.8, 0.3))
  3844. assert_equal(special.yn(1, 0.3), special.yn(1.8, 0.3))
  3845. assert_equal(special.smirnov(1, 0.3), special.smirnov(1.8, 0.3))
  3846. assert_equal(special.smirnovi(1, 0.3), special.smirnovi(1.8, 0.3))
  3847. # This lock can be removed once errstate is made thread-safe (see gh-21956)
  3848. @pytest.fixture
  3849. def errstate_lock():
  3850. import threading
  3851. return threading.Lock()
  3852. @with_special_errors
  3853. def test_error_raising(errstate_lock):
  3854. with errstate_lock:
  3855. with special.errstate(all='raise'):
  3856. assert_raises(special.SpecialFunctionError, special.iv, 1, 1e99j)
  3857. def test_xlogy():
  3858. def xfunc(x, y):
  3859. with np.errstate(invalid='ignore'):
  3860. if x == 0 and not np.isnan(y):
  3861. return x
  3862. else:
  3863. return x*np.log(y)
  3864. z1 = np.asarray([(0,0), (0, np.nan), (0, np.inf), (1.0, 2.0)], dtype=float)
  3865. z2 = np.r_[z1, [(0, 1j), (1, 1j)]]
  3866. w1 = np.vectorize(xfunc)(z1[:,0], z1[:,1])
  3867. assert_func_equal(special.xlogy, w1, z1, rtol=1e-13, atol=1e-13)
  3868. w2 = np.vectorize(xfunc)(z2[:,0], z2[:,1])
  3869. assert_func_equal(special.xlogy, w2, z2, rtol=1e-13, atol=1e-13)
  3870. def test_xlog1py():
  3871. def xfunc(x, y):
  3872. with np.errstate(invalid='ignore'):
  3873. if x == 0 and not np.isnan(y):
  3874. return x
  3875. else:
  3876. return x * np.log1p(y)
  3877. z1 = np.asarray([(0,0), (0, np.nan), (0, np.inf), (1.0, 2.0),
  3878. (1, 1e-30)], dtype=float)
  3879. w1 = np.vectorize(xfunc)(z1[:,0], z1[:,1])
  3880. assert_func_equal(special.xlog1py, w1, z1, rtol=1e-13, atol=1e-13)
  3881. def test_entr():
  3882. def xfunc(x):
  3883. if x < 0:
  3884. return -np.inf
  3885. else:
  3886. return -special.xlogy(x, x)
  3887. values = (0, 0.5, 1.0, np.inf)
  3888. signs = [-1, 1]
  3889. arr = []
  3890. for sgn, v in itertools.product(signs, values):
  3891. arr.append(sgn * v)
  3892. z = np.array(arr, dtype=float)
  3893. w = np.vectorize(xfunc, otypes=[np.float64])(z)
  3894. assert_func_equal(special.entr, w, z, rtol=1e-13, atol=1e-13)
  3895. def test_kl_div():
  3896. def xfunc(x, y):
  3897. if x < 0 or y < 0 or (y == 0 and x != 0):
  3898. # extension of natural domain to preserve convexity
  3899. return np.inf
  3900. elif np.isposinf(x) or np.isposinf(y):
  3901. # limits within the natural domain
  3902. return np.inf
  3903. elif x == 0:
  3904. return y
  3905. else:
  3906. return special.xlogy(x, x/y) - x + y
  3907. values = (0, 0.5, 1.0)
  3908. signs = [-1, 1]
  3909. arr = []
  3910. for sgna, va, sgnb, vb in itertools.product(signs, values, signs, values):
  3911. arr.append((sgna*va, sgnb*vb))
  3912. z = np.array(arr, dtype=float)
  3913. w = np.vectorize(xfunc, otypes=[np.float64])(z[:,0], z[:,1])
  3914. assert_func_equal(special.kl_div, w, z, rtol=1e-13, atol=1e-13)
  3915. def test_rel_entr():
  3916. def xfunc(x, y):
  3917. if x > 0 and y > 0:
  3918. return special.xlogy(x, x/y)
  3919. elif x == 0 and y >= 0:
  3920. return 0
  3921. else:
  3922. return np.inf
  3923. values = (0, 0.5, 1.0)
  3924. signs = [-1, 1]
  3925. arr = []
  3926. for sgna, va, sgnb, vb in itertools.product(signs, values, signs, values):
  3927. arr.append((sgna*va, sgnb*vb))
  3928. z = np.array(arr, dtype=float)
  3929. w = np.vectorize(xfunc, otypes=[np.float64])(z[:,0], z[:,1])
  3930. assert_func_equal(special.rel_entr, w, z, rtol=1e-13, atol=1e-13)
  3931. def test_rel_entr_gh_20710_near_zero():
  3932. # Check accuracy of inputs which are very close
  3933. inputs = np.array([
  3934. # x, y
  3935. (0.9456657713430001, 0.9456657713430094),
  3936. (0.48066098564791515, 0.48066098564794774),
  3937. (0.786048657854401, 0.7860486578542367),
  3938. ])
  3939. # Known values produced using `x * mpmath.log(x / y)` with dps=30
  3940. expected = [
  3941. -9.325873406851269e-15,
  3942. -3.258504577274724e-14,
  3943. 1.6431300764454033e-13,
  3944. ]
  3945. x = inputs[:, 0]
  3946. y = inputs[:, 1]
  3947. assert_allclose(special.rel_entr(x, y), expected, rtol=1e-13, atol=0)
  3948. def test_rel_entr_gh_20710_overflow():
  3949. special.seterr(all='ignore')
  3950. inputs = np.array([
  3951. # x, y
  3952. # Overflow
  3953. (4, 2.22e-308),
  3954. # Underflow
  3955. (1e-200, 1e+200),
  3956. # Subnormal
  3957. (2.22e-308, 1e15),
  3958. ])
  3959. # Known values produced using `x * mpmath.log(x / y)` with dps=30
  3960. expected = [
  3961. 2839.139983229607,
  3962. -9.210340371976183e-198,
  3963. -1.6493212008074475e-305,
  3964. ]
  3965. x = inputs[:, 0]
  3966. y = inputs[:, 1]
  3967. assert_allclose(special.rel_entr(x, y), expected, rtol=1e-13, atol=0)
  3968. def test_huber():
  3969. assert_equal(special.huber(-1, 1.5), np.inf)
  3970. assert_allclose(special.huber(2, 1.5), 0.5 * np.square(1.5))
  3971. assert_allclose(special.huber(2, 2.5), 2 * (2.5 - 0.5 * 2))
  3972. def xfunc(delta, r):
  3973. if delta < 0:
  3974. return np.inf
  3975. elif np.abs(r) < delta:
  3976. return 0.5 * np.square(r)
  3977. else:
  3978. return delta * (np.abs(r) - 0.5 * delta)
  3979. z = np.random.randn(10, 2)
  3980. w = np.vectorize(xfunc, otypes=[np.float64])(z[:,0], z[:,1])
  3981. assert_func_equal(special.huber, w, z, rtol=1e-13, atol=1e-13)
  3982. def test_pseudo_huber():
  3983. def xfunc(delta, r):
  3984. if delta < 0:
  3985. return np.inf
  3986. elif (not delta) or (not r):
  3987. return 0
  3988. else:
  3989. return delta**2 * (np.sqrt(1 + (r/delta)**2) - 1)
  3990. z = np.array(np.random.randn(10, 2).tolist() + [[0, 0.5], [0.5, 0]])
  3991. w = np.vectorize(xfunc, otypes=[np.float64])(z[:,0], z[:,1])
  3992. assert_func_equal(special.pseudo_huber, w, z, rtol=1e-13, atol=1e-13)
  3993. def test_pseudo_huber_small_r():
  3994. delta = 1.0
  3995. r = 1e-18
  3996. y = special.pseudo_huber(delta, r)
  3997. # expected computed with mpmath:
  3998. # import mpmath
  3999. # mpmath.mp.dps = 200
  4000. # r = mpmath.mpf(1e-18)
  4001. # expected = float(mpmath.sqrt(1 + r**2) - 1)
  4002. expected = 5.0000000000000005e-37
  4003. assert_allclose(y, expected, rtol=1e-13)
  4004. def test_runtime_warning():
  4005. with pytest.warns(RuntimeWarning,
  4006. match=r'Too many predicted coefficients'):
  4007. mathieu_odd_coef(1000, 1000)
  4008. with pytest.warns(RuntimeWarning,
  4009. match=r'Too many predicted coefficients'):
  4010. mathieu_even_coef(1000, 1000)
  4011. class TestStirling2:
  4012. table = [
  4013. [1],
  4014. [0, 1],
  4015. [0, 1, 1],
  4016. [0, 1, 3, 1],
  4017. [0, 1, 7, 6, 1],
  4018. [0, 1, 15, 25, 10, 1],
  4019. [0, 1, 31, 90, 65, 15, 1],
  4020. [0, 1, 63, 301, 350, 140, 21, 1],
  4021. [0, 1, 127, 966, 1701, 1050, 266, 28, 1],
  4022. [0, 1, 255, 3025, 7770, 6951, 2646, 462, 36, 1],
  4023. [0, 1, 511, 9330, 34105, 42525, 22827, 5880, 750, 45, 1],
  4024. ]
  4025. @pytest.mark.parametrize("is_exact, comp, kwargs", [
  4026. (True, assert_equal, {}),
  4027. (False, assert_allclose, {'rtol': 1e-12})
  4028. ])
  4029. def test_table_cases(self, is_exact, comp, kwargs):
  4030. for n in range(1, len(self.table)):
  4031. k_values = list(range(n+1))
  4032. row = self.table[n]
  4033. comp(row, stirling2([n], k_values, exact=is_exact), **kwargs)
  4034. @pytest.mark.parametrize("is_exact, comp, kwargs", [
  4035. (True, assert_equal, {}),
  4036. (False, assert_allclose, {'rtol': 1e-12})
  4037. ])
  4038. def test_valid_single_integer(self, is_exact, comp, kwargs):
  4039. comp(stirling2(0, 0, exact=is_exact), self.table[0][0], **kwargs)
  4040. comp(stirling2(4, 2, exact=is_exact), self.table[4][2], **kwargs)
  4041. # a single 2-tuple of integers as arguments must return an int and not
  4042. # an array whereas arrays of single values should return array
  4043. comp(stirling2(5, 3, exact=is_exact), 25, **kwargs)
  4044. comp(stirling2([5], [3], exact=is_exact), [25], **kwargs)
  4045. @pytest.mark.parametrize("is_exact, comp, kwargs", [
  4046. (True, assert_equal, {}),
  4047. (False, assert_allclose, {'rtol': 1e-12})
  4048. ])
  4049. def test_negative_integer(self, is_exact, comp, kwargs):
  4050. # negative integers for n or k arguments return 0
  4051. comp(stirling2(-1, -1, exact=is_exact), 0, **kwargs)
  4052. comp(stirling2(-1, 2, exact=is_exact), 0, **kwargs)
  4053. comp(stirling2(2, -1, exact=is_exact), 0, **kwargs)
  4054. @pytest.mark.parametrize("is_exact, comp, kwargs", [
  4055. (True, assert_equal, {}),
  4056. (False, assert_allclose, {'rtol': 1e-12})
  4057. ])
  4058. def test_array_inputs(self, is_exact, comp, kwargs):
  4059. ans = [self.table[10][3], self.table[10][4]]
  4060. comp(stirling2(asarray([10, 10]),
  4061. asarray([3, 4]),
  4062. exact=is_exact),
  4063. ans)
  4064. comp(stirling2([10, 10],
  4065. asarray([3, 4]),
  4066. exact=is_exact),
  4067. ans)
  4068. comp(stirling2(asarray([10, 10]),
  4069. [3, 4],
  4070. exact=is_exact),
  4071. ans)
  4072. @pytest.mark.parametrize("is_exact, comp, kwargs", [
  4073. (True, assert_equal, {}),
  4074. (False, assert_allclose, {'rtol': 1e-13})
  4075. ])
  4076. def test_mixed_values(self, is_exact, comp, kwargs):
  4077. # negative values-of either n or k-should return 0 for the entry
  4078. ans = [0, 1, 3, 25, 1050, 5880, 9330]
  4079. n = [-1, 0, 3, 5, 8, 10, 10]
  4080. k = [-2, 0, 2, 3, 5, 7, 3]
  4081. comp(stirling2(n, k, exact=is_exact), ans, **kwargs)
  4082. def test_correct_parity(self):
  4083. """Test parity follows well known identity.
  4084. en.wikipedia.org/wiki/Stirling_numbers_of_the_second_kind#Parity
  4085. """
  4086. n, K = 100, np.arange(101)
  4087. assert_equal(
  4088. stirling2(n, K, exact=True) % 2,
  4089. [math.comb(n - (k // 2) - 1, n - k) % 2 for k in K],
  4090. )
  4091. def test_big_numbers(self):
  4092. # via mpmath (bigger than 32bit)
  4093. ans = asarray([48063331393110, 48004081105038305])
  4094. n = [25, 30]
  4095. k = [17, 4]
  4096. assert array_equal(stirling2(n, k, exact=True), ans)
  4097. # bigger than 64 bit
  4098. ans = asarray([2801934359500572414253157841233849412,
  4099. 14245032222277144547280648984426251])
  4100. n = [42, 43]
  4101. k = [17, 23]
  4102. assert array_equal(stirling2(n, k, exact=True), ans)
  4103. @pytest.mark.parametrize("N", [4.5, 3., 4+1j, "12", np.nan])
  4104. @pytest.mark.parametrize("K", [3.5, 3, "2", None])
  4105. @pytest.mark.parametrize("is_exact", [True, False])
  4106. def test_unsupported_input_types(self, N, K, is_exact):
  4107. # object, float, string, complex are not supported and raise TypeError
  4108. with pytest.raises(TypeError):
  4109. stirling2(N, K, exact=is_exact)
  4110. @pytest.mark.parametrize("is_exact", [True, False])
  4111. def test_numpy_array_int_object_dtype(self, is_exact):
  4112. # python integers with arbitrary precision are *not* allowed as
  4113. # object type in numpy arrays are inconsistent from api perspective
  4114. ans = asarray(self.table[4][1:])
  4115. n = asarray([4, 4, 4, 4], dtype=object)
  4116. k = asarray([1, 2, 3, 4], dtype=object)
  4117. with pytest.raises(TypeError):
  4118. array_equal(stirling2(n, k, exact=is_exact), ans)
  4119. @pytest.mark.parametrize("is_exact, comp, kwargs", [
  4120. (True, assert_equal, {}),
  4121. (False, assert_allclose, {'rtol': 1e-13})
  4122. ])
  4123. def test_numpy_array_unsigned_int_dtype(self, is_exact, comp, kwargs):
  4124. # numpy unsigned integers are allowed as dtype in numpy arrays
  4125. ans = asarray(self.table[4][1:])
  4126. n = asarray([4, 4, 4, 4], dtype=np_ulong)
  4127. k = asarray([1, 2, 3, 4], dtype=np_ulong)
  4128. comp(stirling2(n, k, exact=False), ans, **kwargs)
  4129. @pytest.mark.parametrize("is_exact, comp, kwargs", [
  4130. (True, assert_equal, {}),
  4131. (False, assert_allclose, {'rtol': 1e-13})
  4132. ])
  4133. def test_broadcasting_arrays_correctly(self, is_exact, comp, kwargs):
  4134. # broadcasting is handled by stirling2
  4135. # test leading 1s are replicated
  4136. ans = asarray([[1, 15, 25, 10], [1, 7, 6, 1]]) # shape (2,4)
  4137. n = asarray([[5, 5, 5, 5], [4, 4, 4, 4]]) # shape (2,4)
  4138. k = asarray([1, 2, 3, 4]) # shape (4,)
  4139. comp(stirling2(n, k, exact=is_exact), ans, **kwargs)
  4140. # test that dims both mismatch broadcast correctly (5,1) & (6,)
  4141. n = asarray([[4], [4], [4], [4], [4]])
  4142. k = asarray([0, 1, 2, 3, 4, 5])
  4143. ans = asarray([[0, 1, 7, 6, 1, 0] for _ in range(5)])
  4144. comp(stirling2(n, k, exact=False), ans, **kwargs)
  4145. def test_temme_rel_max_error(self):
  4146. # python integers with arbitrary precision are *not* allowed as
  4147. # object type in numpy arrays are inconsistent from api perspective
  4148. x = list(range(51, 101, 5))
  4149. for n in x:
  4150. k_entries = list(range(1, n+1))
  4151. denom = stirling2([n], k_entries, exact=True)
  4152. num = denom - stirling2([n], k_entries, exact=False)
  4153. assert np.max(np.abs(num / denom)) < 2e-5