| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382 |
- #
- # Author: Travis Oliphant, 2002
- #
- import numpy as np
- import math
- import warnings
- from collections import defaultdict
- from heapq import heapify, heappop
- from numpy import (pi, asarray, floor, isscalar, sqrt, where,
- sin, place, issubdtype, extract, inexact, nan, zeros, sinc)
- from . import _ufuncs
- from ._ufuncs import (mathieu_a, mathieu_b, iv, jv, gamma, rgamma,
- psi, hankel1, hankel2, yv, kv, poch, binom,
- _stirling2_inexact)
- from ._gufuncs import _lqn, _lqmn, _rctj, _rcty
- from ._input_validation import _nonneg_int_or_fail
- from . import _specfun
- from ._comb import _comb_int
- __all__ = [
- 'ai_zeros',
- 'assoc_laguerre',
- 'bei_zeros',
- 'beip_zeros',
- 'ber_zeros',
- 'bernoulli',
- 'berp_zeros',
- 'bi_zeros',
- 'comb',
- 'digamma',
- 'diric',
- 'erf_zeros',
- 'euler',
- 'factorial',
- 'factorial2',
- 'factorialk',
- 'fresnel_zeros',
- 'fresnelc_zeros',
- 'fresnels_zeros',
- 'h1vp',
- 'h2vp',
- 'ivp',
- 'jn_zeros',
- 'jnjnp_zeros',
- 'jnp_zeros',
- 'jnyn_zeros',
- 'jvp',
- 'kei_zeros',
- 'keip_zeros',
- 'kelvin_zeros',
- 'ker_zeros',
- 'kerp_zeros',
- 'kvp',
- 'lmbda',
- 'lqmn',
- 'lqn',
- 'mathieu_even_coef',
- 'mathieu_odd_coef',
- 'obl_cv_seq',
- 'pbdn_seq',
- 'pbdv_seq',
- 'pbvv_seq',
- 'perm',
- 'polygamma',
- 'pro_cv_seq',
- 'riccati_jn',
- 'riccati_yn',
- 'sinc',
- 'softplus',
- 'stirling2',
- 'y0_zeros',
- 'y1_zeros',
- 'y1p_zeros',
- 'yn_zeros',
- 'ynp_zeros',
- 'yvp',
- 'zeta'
- ]
- # mapping k to last n such that factorialk(n, k) < np.iinfo(np.int64).max
- _FACTORIALK_LIMITS_64BITS = {1: 20, 2: 33, 3: 44, 4: 54, 5: 65,
- 6: 74, 7: 84, 8: 93, 9: 101}
- # mapping k to last n such that factorialk(n, k) < np.iinfo(np.int32).max
- _FACTORIALK_LIMITS_32BITS = {1: 12, 2: 19, 3: 25, 4: 31, 5: 37,
- 6: 43, 7: 47, 8: 51, 9: 56}
- def diric(x, n):
- """Periodic sinc function, also called the Dirichlet kernel.
- The Dirichlet kernel is defined as::
- diric(x, n) = sin(x * n/2) / (n * sin(x / 2)),
- where `n` is a positive integer.
- Parameters
- ----------
- x : array_like
- Input data
- n : int
- Integer defining the periodicity.
- Returns
- -------
- diric : ndarray
- Examples
- --------
- >>> import numpy as np
- >>> from scipy import special
- >>> import matplotlib.pyplot as plt
- >>> x = np.linspace(-8*np.pi, 8*np.pi, num=201)
- >>> plt.figure(figsize=(8, 8));
- >>> for idx, n in enumerate([2, 3, 4, 9]):
- ... plt.subplot(2, 2, idx+1)
- ... plt.plot(x, special.diric(x, n))
- ... plt.title('diric, n={}'.format(n))
- >>> plt.show()
- The following example demonstrates that `diric` gives the magnitudes
- (modulo the sign and scaling) of the Fourier coefficients of a
- rectangular pulse.
- Suppress output of values that are effectively 0:
- >>> np.set_printoptions(suppress=True)
- Create a signal `x` of length `m` with `k` ones:
- >>> m = 8
- >>> k = 3
- >>> x = np.zeros(m)
- >>> x[:k] = 1
- Use the FFT to compute the Fourier transform of `x`, and
- inspect the magnitudes of the coefficients:
- >>> np.abs(np.fft.fft(x))
- array([ 3. , 2.41421356, 1. , 0.41421356, 1. ,
- 0.41421356, 1. , 2.41421356])
- Now find the same values (up to sign) using `diric`. We multiply
- by `k` to account for the different scaling conventions of
- `numpy.fft.fft` and `diric`:
- >>> theta = np.linspace(0, 2*np.pi, m, endpoint=False)
- >>> k * special.diric(theta, k)
- array([ 3. , 2.41421356, 1. , -0.41421356, -1. ,
- -0.41421356, 1. , 2.41421356])
- """
- x, n = asarray(x), asarray(n)
- n = asarray(n + (x-x))
- x = asarray(x + (n-n))
- if issubdtype(x.dtype, inexact):
- ytype = x.dtype
- else:
- ytype = float
- y = zeros(x.shape, ytype)
- # empirical minval for 32, 64 or 128 bit float computations
- # where sin(x/2) < minval, result is fixed at +1 or -1
- if np.finfo(ytype).eps < 1e-18:
- minval = 1e-11
- elif np.finfo(ytype).eps < 1e-15:
- minval = 1e-7
- else:
- minval = 1e-3
- mask1 = (n <= 0) | (n != floor(n))
- place(y, mask1, nan)
- x = x / 2
- denom = sin(x)
- mask2 = (1-mask1) & (abs(denom) < minval)
- xsub = extract(mask2, x)
- nsub = extract(mask2, n)
- zsub = xsub / pi
- place(y, mask2, pow(-1, np.round(zsub)*(nsub-1)))
- mask = (1-mask1) & (1-mask2)
- xsub = extract(mask, x)
- nsub = extract(mask, n)
- dsub = extract(mask, denom)
- place(y, mask, sin(nsub*xsub)/(nsub*dsub))
- return y
- def jnjnp_zeros(nt):
- """Compute zeros of integer-order Bessel functions Jn and Jn'.
- Results are arranged in order of the magnitudes of the zeros.
- Parameters
- ----------
- nt : int
- Number (<=1200) of zeros to compute
- Returns
- -------
- zo[l-1] : ndarray
- Value of the lth zero of Jn(x) and Jn'(x). Of length `nt`.
- n[l-1] : ndarray
- Order of the Jn(x) or Jn'(x) associated with lth zero. Of length `nt`.
- m[l-1] : ndarray
- Serial number of the zeros of Jn(x) or Jn'(x) associated
- with lth zero. Of length `nt`.
- t[l-1] : ndarray
- 0 if lth zero in zo is zero of Jn(x), 1 if it is a zero of Jn'(x). Of
- length `nt`.
- See Also
- --------
- jn_zeros, jnp_zeros : to get separated arrays of zeros.
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996, chapter 5.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if not isscalar(nt) or (floor(nt) != nt) or (nt > 1200):
- raise ValueError("Number must be integer <= 1200.")
- nt = int(nt)
- n, m, t, zo = _specfun.jdzo(nt)
- return zo[1:nt+1], n[:nt], m[:nt], t[:nt]
- def jnyn_zeros(n, nt):
- """Compute nt zeros of Bessel functions Jn(x), Jn'(x), Yn(x), and Yn'(x).
- Returns 4 arrays of length `nt`, corresponding to the first `nt`
- zeros of Jn(x), Jn'(x), Yn(x), and Yn'(x), respectively. The zeros
- are returned in ascending order.
- Parameters
- ----------
- n : int
- Order of the Bessel functions
- nt : int
- Number (<=1200) of zeros to compute
- Returns
- -------
- Jn : ndarray
- First `nt` zeros of Jn
- Jnp : ndarray
- First `nt` zeros of Jn'
- Yn : ndarray
- First `nt` zeros of Yn
- Ynp : ndarray
- First `nt` zeros of Yn'
- See Also
- --------
- jn_zeros, jnp_zeros, yn_zeros, ynp_zeros
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996, chapter 5.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- Examples
- --------
- Compute the first three roots of :math:`J_1`, :math:`J_1'`,
- :math:`Y_1` and :math:`Y_1'`.
- >>> from scipy.special import jnyn_zeros
- >>> jn_roots, jnp_roots, yn_roots, ynp_roots = jnyn_zeros(1, 3)
- >>> jn_roots, yn_roots
- (array([ 3.83170597, 7.01558667, 10.17346814]),
- array([2.19714133, 5.42968104, 8.59600587]))
- Plot :math:`J_1`, :math:`J_1'`, :math:`Y_1`, :math:`Y_1'` and their roots.
- >>> import numpy as np
- >>> import matplotlib.pyplot as plt
- >>> from scipy.special import jnyn_zeros, jvp, jn, yvp, yn
- >>> jn_roots, jnp_roots, yn_roots, ynp_roots = jnyn_zeros(1, 3)
- >>> fig, ax = plt.subplots()
- >>> xmax= 11
- >>> x = np.linspace(0, xmax)
- >>> x[0] += 1e-15
- >>> ax.plot(x, jn(1, x), label=r"$J_1$", c='r')
- >>> ax.plot(x, jvp(1, x, 1), label=r"$J_1'$", c='b')
- >>> ax.plot(x, yn(1, x), label=r"$Y_1$", c='y')
- >>> ax.plot(x, yvp(1, x, 1), label=r"$Y_1'$", c='c')
- >>> zeros = np.zeros((3, ))
- >>> ax.scatter(jn_roots, zeros, s=30, c='r', zorder=5,
- ... label=r"$J_1$ roots")
- >>> ax.scatter(jnp_roots, zeros, s=30, c='b', zorder=5,
- ... label=r"$J_1'$ roots")
- >>> ax.scatter(yn_roots, zeros, s=30, c='y', zorder=5,
- ... label=r"$Y_1$ roots")
- >>> ax.scatter(ynp_roots, zeros, s=30, c='c', zorder=5,
- ... label=r"$Y_1'$ roots")
- >>> ax.hlines(0, 0, xmax, color='k')
- >>> ax.set_ylim(-0.6, 0.6)
- >>> ax.set_xlim(0, xmax)
- >>> ax.legend(ncol=2, bbox_to_anchor=(1., 0.75))
- >>> plt.tight_layout()
- >>> plt.show()
- """
- if not (isscalar(nt) and isscalar(n)):
- raise ValueError("Arguments must be scalars.")
- if (floor(n) != n) or (floor(nt) != nt):
- raise ValueError("Arguments must be integers.")
- if (nt <= 0):
- raise ValueError("nt > 0")
- return _specfun.jyzo(abs(n), nt)
- def jn_zeros(n, nt):
- r"""Compute zeros of integer-order Bessel functions Jn.
- Compute `nt` zeros of the Bessel functions :math:`J_n(x)` on the
- interval :math:`(0, \infty)`. The zeros are returned in ascending
- order. Note that this interval excludes the zero at :math:`x = 0`
- that exists for :math:`n > 0`.
- Parameters
- ----------
- n : int
- Order of Bessel function
- nt : int
- Number of zeros to return
- Returns
- -------
- ndarray
- First `nt` zeros of the Bessel function.
- See Also
- --------
- jv: Real-order Bessel functions of the first kind
- jnp_zeros: Zeros of :math:`Jn'`
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996, chapter 5.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- Examples
- --------
- Compute the first four positive roots of :math:`J_3`.
- >>> from scipy.special import jn_zeros
- >>> jn_zeros(3, 4)
- array([ 6.3801619 , 9.76102313, 13.01520072, 16.22346616])
- Plot :math:`J_3` and its first four positive roots. Note
- that the root located at 0 is not returned by `jn_zeros`.
- >>> import numpy as np
- >>> import matplotlib.pyplot as plt
- >>> from scipy.special import jn, jn_zeros
- >>> j3_roots = jn_zeros(3, 4)
- >>> xmax = 18
- >>> xmin = -1
- >>> x = np.linspace(xmin, xmax, 500)
- >>> fig, ax = plt.subplots()
- >>> ax.plot(x, jn(3, x), label=r'$J_3$')
- >>> ax.scatter(j3_roots, np.zeros((4, )), s=30, c='r',
- ... label=r"$J_3$_Zeros", zorder=5)
- >>> ax.scatter(0, 0, s=30, c='k',
- ... label=r"Root at 0", zorder=5)
- >>> ax.hlines(0, 0, xmax, color='k')
- >>> ax.set_xlim(xmin, xmax)
- >>> plt.legend()
- >>> plt.show()
- """
- return jnyn_zeros(n, nt)[0]
- def jnp_zeros(n, nt):
- r"""Compute zeros of integer-order Bessel function derivatives Jn'.
- Compute `nt` zeros of the functions :math:`J_n'(x)` on the
- interval :math:`(0, \infty)`. The zeros are returned in ascending
- order. Note that this interval excludes the zero at :math:`x = 0`
- that exists for :math:`n > 1`.
- Parameters
- ----------
- n : int
- Order of Bessel function
- nt : int
- Number of zeros to return
- Returns
- -------
- ndarray
- First `nt` zeros of the Bessel function.
- See Also
- --------
- jvp: Derivatives of integer-order Bessel functions of the first kind
- jv: Float-order Bessel functions of the first kind
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996, chapter 5.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- Examples
- --------
- Compute the first four roots of :math:`J_2'`.
- >>> from scipy.special import jnp_zeros
- >>> jnp_zeros(2, 4)
- array([ 3.05423693, 6.70613319, 9.96946782, 13.17037086])
- As `jnp_zeros` yields the roots of :math:`J_n'`, it can be used to
- compute the locations of the peaks of :math:`J_n`. Plot
- :math:`J_2`, :math:`J_2'` and the locations of the roots of :math:`J_2'`.
- >>> import numpy as np
- >>> import matplotlib.pyplot as plt
- >>> from scipy.special import jn, jnp_zeros, jvp
- >>> j2_roots = jnp_zeros(2, 4)
- >>> xmax = 15
- >>> x = np.linspace(0, xmax, 500)
- >>> fig, ax = plt.subplots()
- >>> ax.plot(x, jn(2, x), label=r'$J_2$')
- >>> ax.plot(x, jvp(2, x, 1), label=r"$J_2'$")
- >>> ax.hlines(0, 0, xmax, color='k')
- >>> ax.scatter(j2_roots, np.zeros((4, )), s=30, c='r',
- ... label=r"Roots of $J_2'$", zorder=5)
- >>> ax.set_ylim(-0.4, 0.8)
- >>> ax.set_xlim(0, xmax)
- >>> plt.legend()
- >>> plt.show()
- """
- return jnyn_zeros(n, nt)[1]
- def yn_zeros(n, nt):
- r"""Compute zeros of integer-order Bessel function Yn(x).
- Compute `nt` zeros of the functions :math:`Y_n(x)` on the interval
- :math:`(0, \infty)`. The zeros are returned in ascending order.
- Parameters
- ----------
- n : int
- Order of Bessel function
- nt : int
- Number of zeros to return
- Returns
- -------
- ndarray
- First `nt` zeros of the Bessel function.
- See Also
- --------
- yn: Bessel function of the second kind for integer order
- yv: Bessel function of the second kind for real order
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996, chapter 5.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- Examples
- --------
- Compute the first four roots of :math:`Y_2`.
- >>> from scipy.special import yn_zeros
- >>> yn_zeros(2, 4)
- array([ 3.38424177, 6.79380751, 10.02347798, 13.20998671])
- Plot :math:`Y_2` and its first four roots.
- >>> import numpy as np
- >>> import matplotlib.pyplot as plt
- >>> from scipy.special import yn, yn_zeros
- >>> xmin = 2
- >>> xmax = 15
- >>> x = np.linspace(xmin, xmax, 500)
- >>> fig, ax = plt.subplots()
- >>> ax.hlines(0, xmin, xmax, color='k')
- >>> ax.plot(x, yn(2, x), label=r'$Y_2$')
- >>> ax.scatter(yn_zeros(2, 4), np.zeros((4, )), s=30, c='r',
- ... label='Roots', zorder=5)
- >>> ax.set_ylim(-0.4, 0.4)
- >>> ax.set_xlim(xmin, xmax)
- >>> plt.legend()
- >>> plt.show()
- """
- return jnyn_zeros(n, nt)[2]
- def ynp_zeros(n, nt):
- r"""Compute zeros of integer-order Bessel function derivatives Yn'(x).
- Compute `nt` zeros of the functions :math:`Y_n'(x)` on the
- interval :math:`(0, \infty)`. The zeros are returned in ascending
- order.
- Parameters
- ----------
- n : int
- Order of Bessel function
- nt : int
- Number of zeros to return
- Returns
- -------
- ndarray
- First `nt` zeros of the Bessel derivative function.
- See Also
- --------
- yvp
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996, chapter 5.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- Examples
- --------
- Compute the first four roots of the first derivative of the
- Bessel function of second kind for order 0 :math:`Y_0'`.
- >>> from scipy.special import ynp_zeros
- >>> ynp_zeros(0, 4)
- array([ 2.19714133, 5.42968104, 8.59600587, 11.74915483])
- Plot :math:`Y_0`, :math:`Y_0'` and confirm visually that the roots of
- :math:`Y_0'` are located at local extrema of :math:`Y_0`.
- >>> import numpy as np
- >>> import matplotlib.pyplot as plt
- >>> from scipy.special import yn, ynp_zeros, yvp
- >>> zeros = ynp_zeros(0, 4)
- >>> xmax = 13
- >>> x = np.linspace(0, xmax, 500)
- >>> fig, ax = plt.subplots()
- >>> ax.plot(x, yn(0, x), label=r'$Y_0$')
- >>> ax.plot(x, yvp(0, x, 1), label=r"$Y_0'$")
- >>> ax.scatter(zeros, np.zeros((4, )), s=30, c='r',
- ... label=r"Roots of $Y_0'$", zorder=5)
- >>> for root in zeros:
- ... y0_extremum = yn(0, root)
- ... lower = min(0, y0_extremum)
- ... upper = max(0, y0_extremum)
- ... ax.vlines(root, lower, upper, color='r')
- >>> ax.hlines(0, 0, xmax, color='k')
- >>> ax.set_ylim(-0.6, 0.6)
- >>> ax.set_xlim(0, xmax)
- >>> plt.legend()
- >>> plt.show()
- """
- return jnyn_zeros(n, nt)[3]
- def y0_zeros(nt, complex=False):
- """Compute nt zeros of Bessel function Y0(z), and derivative at each zero.
- The derivatives are given by Y0'(z0) = -Y1(z0) at each zero z0.
- Parameters
- ----------
- nt : int
- Number of zeros to return
- complex : bool, default False
- Set to False to return only the real zeros; set to True to return only
- the complex zeros with negative real part and positive imaginary part.
- Note that the complex conjugates of the latter are also zeros of the
- function, but are not returned by this routine.
- Returns
- -------
- z0n : ndarray
- Location of nth zero of Y0(z)
- y0pz0n : ndarray
- Value of derivative Y0'(z0) for nth zero
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996, chapter 5.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- Examples
- --------
- Compute the first 4 real roots and the derivatives at the roots of
- :math:`Y_0`:
- >>> import numpy as np
- >>> from scipy.special import y0_zeros
- >>> zeros, grads = y0_zeros(4)
- >>> with np.printoptions(precision=5):
- ... print(f"Roots: {zeros}")
- ... print(f"Gradients: {grads}")
- Roots: [ 0.89358+0.j 3.95768+0.j 7.08605+0.j 10.22235+0.j]
- Gradients: [-0.87942+0.j 0.40254+0.j -0.3001 +0.j 0.2497 +0.j]
- Plot the real part of :math:`Y_0` and the first four computed roots.
- >>> import matplotlib.pyplot as plt
- >>> from scipy.special import y0
- >>> xmin = 0
- >>> xmax = 11
- >>> x = np.linspace(xmin, xmax, 500)
- >>> fig, ax = plt.subplots()
- >>> ax.hlines(0, xmin, xmax, color='k')
- >>> ax.plot(x, y0(x), label=r'$Y_0$')
- >>> zeros, grads = y0_zeros(4)
- >>> ax.scatter(zeros.real, np.zeros((4, )), s=30, c='r',
- ... label=r'$Y_0$_zeros', zorder=5)
- >>> ax.set_ylim(-0.5, 0.6)
- >>> ax.set_xlim(xmin, xmax)
- >>> plt.legend(ncol=2)
- >>> plt.show()
- Compute the first 4 complex roots and the derivatives at the roots of
- :math:`Y_0` by setting ``complex=True``:
- >>> y0_zeros(4, True)
- (array([ -2.40301663+0.53988231j, -5.5198767 +0.54718001j,
- -8.6536724 +0.54841207j, -11.79151203+0.54881912j]),
- array([ 0.10074769-0.88196771j, -0.02924642+0.5871695j ,
- 0.01490806-0.46945875j, -0.00937368+0.40230454j]))
- """
- if not isscalar(nt) or (floor(nt) != nt) or (nt <= 0):
- raise ValueError("Arguments must be scalar positive integer.")
- kf = 0
- kc = not complex
- return _specfun.cyzo(nt, kf, kc)
- def y1_zeros(nt, complex=False):
- """Compute nt zeros of Bessel function Y1(z), and derivative at each zero.
- The derivatives are given by Y1'(z1) = Y0(z1) at each zero z1.
- Parameters
- ----------
- nt : int
- Number of zeros to return
- complex : bool, default False
- Set to False to return only the real zeros; set to True to return only
- the complex zeros with negative real part and positive imaginary part.
- Note that the complex conjugates of the latter are also zeros of the
- function, but are not returned by this routine.
- Returns
- -------
- z1n : ndarray
- Location of nth zero of Y1(z)
- y1pz1n : ndarray
- Value of derivative Y1'(z1) for nth zero
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996, chapter 5.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- Examples
- --------
- Compute the first 4 real roots and the derivatives at the roots of
- :math:`Y_1`:
- >>> import numpy as np
- >>> from scipy.special import y1_zeros
- >>> zeros, grads = y1_zeros(4)
- >>> with np.printoptions(precision=5):
- ... print(f"Roots: {zeros}")
- ... print(f"Gradients: {grads}")
- Roots: [ 2.19714+0.j 5.42968+0.j 8.59601+0.j 11.74915+0.j]
- Gradients: [ 0.52079+0.j -0.34032+0.j 0.27146+0.j -0.23246+0.j]
- Extract the real parts:
- >>> realzeros = zeros.real
- >>> realzeros
- array([ 2.19714133, 5.42968104, 8.59600587, 11.74915483])
- Plot :math:`Y_1` and the first four computed roots.
- >>> import matplotlib.pyplot as plt
- >>> from scipy.special import y1
- >>> xmin = 0
- >>> xmax = 13
- >>> x = np.linspace(xmin, xmax, 500)
- >>> zeros, grads = y1_zeros(4)
- >>> fig, ax = plt.subplots()
- >>> ax.hlines(0, xmin, xmax, color='k')
- >>> ax.plot(x, y1(x), label=r'$Y_1$')
- >>> ax.scatter(zeros.real, np.zeros((4, )), s=30, c='r',
- ... label=r'$Y_1$_zeros', zorder=5)
- >>> ax.set_ylim(-0.5, 0.5)
- >>> ax.set_xlim(xmin, xmax)
- >>> plt.legend()
- >>> plt.show()
- Compute the first 4 complex roots and the derivatives at the roots of
- :math:`Y_1` by setting ``complex=True``:
- >>> y1_zeros(4, True)
- (array([ -0.50274327+0.78624371j, -3.83353519+0.56235654j,
- -7.01590368+0.55339305j, -10.17357383+0.55127339j]),
- array([-0.45952768+1.31710194j, 0.04830191-0.69251288j,
- -0.02012695+0.51864253j, 0.011614 -0.43203296j]))
- """
- if not isscalar(nt) or (floor(nt) != nt) or (nt <= 0):
- raise ValueError("Arguments must be scalar positive integer.")
- kf = 1
- kc = not complex
- return _specfun.cyzo(nt, kf, kc)
- def y1p_zeros(nt, complex=False):
- """Compute nt zeros of Bessel derivative Y1'(z), and value at each zero.
- The values are given by Y1(z1) at each z1 where Y1'(z1)=0.
- Parameters
- ----------
- nt : int
- Number of zeros to return
- complex : bool, default False
- Set to False to return only the real zeros; set to True to return only
- the complex zeros with negative real part and positive imaginary part.
- Note that the complex conjugates of the latter are also zeros of the
- function, but are not returned by this routine.
- Returns
- -------
- z1pn : ndarray
- Location of nth zero of Y1'(z)
- y1z1pn : ndarray
- Value of derivative Y1(z1) for nth zero
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996, chapter 5.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- Examples
- --------
- Compute the first four roots of :math:`Y_1'` and the values of
- :math:`Y_1` at these roots.
- >>> import numpy as np
- >>> from scipy.special import y1p_zeros
- >>> y1grad_roots, y1_values = y1p_zeros(4)
- >>> with np.printoptions(precision=5):
- ... print(f"Y1' Roots: {y1grad_roots.real}")
- ... print(f"Y1 values: {y1_values.real}")
- Y1' Roots: [ 3.68302 6.9415 10.1234 13.28576]
- Y1 values: [ 0.41673 -0.30317 0.25091 -0.21897]
- `y1p_zeros` can be used to calculate the extremal points of :math:`Y_1`
- directly. Here we plot :math:`Y_1` and the first four extrema.
- >>> import matplotlib.pyplot as plt
- >>> from scipy.special import y1, yvp
- >>> y1_roots, y1_values_at_roots = y1p_zeros(4)
- >>> real_roots = y1_roots.real
- >>> xmax = 15
- >>> x = np.linspace(0, xmax, 500)
- >>> x[0] += 1e-15
- >>> fig, ax = plt.subplots()
- >>> ax.plot(x, y1(x), label=r'$Y_1$')
- >>> ax.plot(x, yvp(1, x, 1), label=r"$Y_1'$")
- >>> ax.scatter(real_roots, np.zeros((4, )), s=30, c='r',
- ... label=r"Roots of $Y_1'$", zorder=5)
- >>> ax.scatter(real_roots, y1_values_at_roots.real, s=30, c='k',
- ... label=r"Extrema of $Y_1$", zorder=5)
- >>> ax.hlines(0, 0, xmax, color='k')
- >>> ax.set_ylim(-0.5, 0.5)
- >>> ax.set_xlim(0, xmax)
- >>> ax.legend(ncol=2, bbox_to_anchor=(1., 0.75))
- >>> plt.tight_layout()
- >>> plt.show()
- """
- if not isscalar(nt) or (floor(nt) != nt) or (nt <= 0):
- raise ValueError("Arguments must be scalar positive integer.")
- kf = 2
- kc = not complex
- return _specfun.cyzo(nt, kf, kc)
- def _bessel_diff_formula(v, z, n, L, phase):
- # from AMS55.
- # L(v, z) = J(v, z), Y(v, z), H1(v, z), H2(v, z), phase = -1
- # L(v, z) = I(v, z) or exp(v*pi*i)K(v, z), phase = 1
- # For K, you can pull out the exp((v-k)*pi*i) into the caller
- v = asarray(v)
- p = 1.0
- s = L(v-n, z)
- for i in range(1, n+1):
- p = phase * (p * (n-i+1)) / i # = choose(k, i)
- s += p*L(v-n + i*2, z)
- return s / (2.**n)
- def jvp(v, z, n=1):
- """Compute derivatives of Bessel functions of the first kind.
- Compute the nth derivative of the Bessel function `Jv` with
- respect to `z`.
- Parameters
- ----------
- v : array_like or float
- Order of Bessel function
- z : complex
- Argument at which to evaluate the derivative; can be real or
- complex.
- n : int, default 1
- Order of derivative. For 0 returns the Bessel function `jv` itself.
- Returns
- -------
- scalar or ndarray
- Values of the derivative of the Bessel function.
- Notes
- -----
- The derivative is computed using the relation DLFM 10.6.7 [2]_.
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996, chapter 5.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- .. [2] NIST Digital Library of Mathematical Functions.
- https://dlmf.nist.gov/10.6.E7
- Examples
- --------
- Compute the Bessel function of the first kind of order 0 and
- its first two derivatives at 1.
- >>> from scipy.special import jvp
- >>> jvp(0, 1, 0), jvp(0, 1, 1), jvp(0, 1, 2)
- (0.7651976865579666, -0.44005058574493355, -0.3251471008130331)
- Compute the first derivative of the Bessel function of the first
- kind for several orders at 1 by providing an array for `v`.
- >>> jvp([0, 1, 2], 1, 1)
- array([-0.44005059, 0.3251471 , 0.21024362])
- Compute the first derivative of the Bessel function of the first
- kind of order 0 at several points by providing an array for `z`.
- >>> import numpy as np
- >>> points = np.array([0., 1.5, 3.])
- >>> jvp(0, points, 1)
- array([-0. , -0.55793651, -0.33905896])
- Plot the Bessel function of the first kind of order 1 and its
- first three derivatives.
- >>> import matplotlib.pyplot as plt
- >>> x = np.linspace(-10, 10, 1000)
- >>> fig, ax = plt.subplots()
- >>> ax.plot(x, jvp(1, x, 0), label=r"$J_1$")
- >>> ax.plot(x, jvp(1, x, 1), label=r"$J_1'$")
- >>> ax.plot(x, jvp(1, x, 2), label=r"$J_1''$")
- >>> ax.plot(x, jvp(1, x, 3), label=r"$J_1'''$")
- >>> plt.legend()
- >>> plt.show()
- """
- n = _nonneg_int_or_fail(n, 'n')
- if n == 0:
- return jv(v, z)
- else:
- return _bessel_diff_formula(v, z, n, jv, -1)
- def yvp(v, z, n=1):
- """Compute derivatives of Bessel functions of the second kind.
- Compute the nth derivative of the Bessel function `Yv` with
- respect to `z`.
- Parameters
- ----------
- v : array_like of float
- Order of Bessel function
- z : complex
- Argument at which to evaluate the derivative
- n : int, default 1
- Order of derivative. For 0 returns the BEssel function `yv`
- Returns
- -------
- scalar or ndarray
- nth derivative of the Bessel function.
- See Also
- --------
- yv : Bessel functions of the second kind
- Notes
- -----
- The derivative is computed using the relation DLFM 10.6.7 [2]_.
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996, chapter 5.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- .. [2] NIST Digital Library of Mathematical Functions.
- https://dlmf.nist.gov/10.6.E7
- Examples
- --------
- Compute the Bessel function of the second kind of order 0 and
- its first two derivatives at 1.
- >>> from scipy.special import yvp
- >>> yvp(0, 1, 0), yvp(0, 1, 1), yvp(0, 1, 2)
- (0.088256964215677, 0.7812128213002889, -0.8694697855159659)
- Compute the first derivative of the Bessel function of the second
- kind for several orders at 1 by providing an array for `v`.
- >>> yvp([0, 1, 2], 1, 1)
- array([0.78121282, 0.86946979, 2.52015239])
- Compute the first derivative of the Bessel function of the
- second kind of order 0 at several points by providing an array for `z`.
- >>> import numpy as np
- >>> points = np.array([0.5, 1.5, 3.])
- >>> yvp(0, points, 1)
- array([ 1.47147239, 0.41230863, -0.32467442])
- Plot the Bessel function of the second kind of order 1 and its
- first three derivatives.
- >>> import matplotlib.pyplot as plt
- >>> x = np.linspace(0, 5, 1000)
- >>> x[0] += 1e-15
- >>> fig, ax = plt.subplots()
- >>> ax.plot(x, yvp(1, x, 0), label=r"$Y_1$")
- >>> ax.plot(x, yvp(1, x, 1), label=r"$Y_1'$")
- >>> ax.plot(x, yvp(1, x, 2), label=r"$Y_1''$")
- >>> ax.plot(x, yvp(1, x, 3), label=r"$Y_1'''$")
- >>> ax.set_ylim(-10, 10)
- >>> plt.legend()
- >>> plt.show()
- """
- n = _nonneg_int_or_fail(n, 'n')
- if n == 0:
- return yv(v, z)
- else:
- return _bessel_diff_formula(v, z, n, yv, -1)
- def kvp(v, z, n=1):
- """Compute derivatives of real-order modified Bessel function Kv(z)
- Kv(z) is the modified Bessel function of the second kind.
- Derivative is calculated with respect to `z`.
- Parameters
- ----------
- v : array_like of float
- Order of Bessel function
- z : array_like of complex
- Argument at which to evaluate the derivative
- n : int, default 1
- Order of derivative. For 0 returns the Bessel function `kv` itself.
- Returns
- -------
- out : ndarray
- The results
- See Also
- --------
- kv
- Notes
- -----
- The derivative is computed using the relation DLFM 10.29.5 [2]_.
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996, chapter 6.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- .. [2] NIST Digital Library of Mathematical Functions.
- https://dlmf.nist.gov/10.29.E5
- Examples
- --------
- Compute the modified bessel function of the second kind of order 0 and
- its first two derivatives at 1.
- >>> from scipy.special import kvp
- >>> kvp(0, 1, 0), kvp(0, 1, 1), kvp(0, 1, 2)
- (0.42102443824070834, -0.6019072301972346, 1.0229316684379428)
- Compute the first derivative of the modified Bessel function of the second
- kind for several orders at 1 by providing an array for `v`.
- >>> kvp([0, 1, 2], 1, 1)
- array([-0.60190723, -1.02293167, -3.85158503])
- Compute the first derivative of the modified Bessel function of the
- second kind of order 0 at several points by providing an array for `z`.
- >>> import numpy as np
- >>> points = np.array([0.5, 1.5, 3.])
- >>> kvp(0, points, 1)
- array([-1.65644112, -0.2773878 , -0.04015643])
- Plot the modified bessel function of the second kind and its
- first three derivatives.
- >>> import matplotlib.pyplot as plt
- >>> x = np.linspace(0, 5, 1000)
- >>> fig, ax = plt.subplots()
- >>> ax.plot(x, kvp(1, x, 0), label=r"$K_1$")
- >>> ax.plot(x, kvp(1, x, 1), label=r"$K_1'$")
- >>> ax.plot(x, kvp(1, x, 2), label=r"$K_1''$")
- >>> ax.plot(x, kvp(1, x, 3), label=r"$K_1'''$")
- >>> ax.set_ylim(-2.5, 2.5)
- >>> plt.legend()
- >>> plt.show()
- """
- n = _nonneg_int_or_fail(n, 'n')
- if n == 0:
- return kv(v, z)
- else:
- return (-1)**n * _bessel_diff_formula(v, z, n, kv, 1)
- def ivp(v, z, n=1):
- """Compute derivatives of modified Bessel functions of the first kind.
- Compute the nth derivative of the modified Bessel function `Iv`
- with respect to `z`.
- Parameters
- ----------
- v : array_like or float
- Order of Bessel function
- z : array_like
- Argument at which to evaluate the derivative; can be real or
- complex.
- n : int, default 1
- Order of derivative. For 0, returns the Bessel function `iv` itself.
- Returns
- -------
- scalar or ndarray
- nth derivative of the modified Bessel function.
- See Also
- --------
- iv
- Notes
- -----
- The derivative is computed using the relation DLFM 10.29.5 [2]_.
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996, chapter 6.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- .. [2] NIST Digital Library of Mathematical Functions.
- https://dlmf.nist.gov/10.29.E5
- Examples
- --------
- Compute the modified Bessel function of the first kind of order 0 and
- its first two derivatives at 1.
- >>> from scipy.special import ivp
- >>> ivp(0, 1, 0), ivp(0, 1, 1), ivp(0, 1, 2)
- (1.2660658777520084, 0.565159103992485, 0.7009067737595233)
- Compute the first derivative of the modified Bessel function of the first
- kind for several orders at 1 by providing an array for `v`.
- >>> ivp([0, 1, 2], 1, 1)
- array([0.5651591 , 0.70090677, 0.29366376])
- Compute the first derivative of the modified Bessel function of the
- first kind of order 0 at several points by providing an array for `z`.
- >>> import numpy as np
- >>> points = np.array([0., 1.5, 3.])
- >>> ivp(0, points, 1)
- array([0. , 0.98166643, 3.95337022])
- Plot the modified Bessel function of the first kind of order 1 and its
- first three derivatives.
- >>> import matplotlib.pyplot as plt
- >>> x = np.linspace(-5, 5, 1000)
- >>> fig, ax = plt.subplots()
- >>> ax.plot(x, ivp(1, x, 0), label=r"$I_1$")
- >>> ax.plot(x, ivp(1, x, 1), label=r"$I_1'$")
- >>> ax.plot(x, ivp(1, x, 2), label=r"$I_1''$")
- >>> ax.plot(x, ivp(1, x, 3), label=r"$I_1'''$")
- >>> plt.legend()
- >>> plt.show()
- """
- n = _nonneg_int_or_fail(n, 'n')
- if n == 0:
- return iv(v, z)
- else:
- return _bessel_diff_formula(v, z, n, iv, 1)
- def h1vp(v, z, n=1):
- """Compute derivatives of Hankel function H1v(z) with respect to `z`.
- Parameters
- ----------
- v : array_like
- Order of Hankel function
- z : array_like
- Argument at which to evaluate the derivative. Can be real or
- complex.
- n : int, default 1
- Order of derivative. For 0 returns the Hankel function `hankel1` itself.
- Returns
- -------
- scalar or ndarray
- Values of the derivative of the Hankel function.
- See Also
- --------
- hankel1
- Notes
- -----
- The derivative is computed using the relation DLFM 10.6.7 [2]_.
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996, chapter 5.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- .. [2] NIST Digital Library of Mathematical Functions.
- https://dlmf.nist.gov/10.6.E7
- Examples
- --------
- Compute the Hankel function of the first kind of order 0 and
- its first two derivatives at 1.
- >>> from scipy.special import h1vp
- >>> h1vp(0, 1, 0), h1vp(0, 1, 1), h1vp(0, 1, 2)
- ((0.7651976865579664+0.088256964215677j),
- (-0.44005058574493355+0.7812128213002889j),
- (-0.3251471008130329-0.8694697855159659j))
- Compute the first derivative of the Hankel function of the first kind
- for several orders at 1 by providing an array for `v`.
- >>> h1vp([0, 1, 2], 1, 1)
- array([-0.44005059+0.78121282j, 0.3251471 +0.86946979j,
- 0.21024362+2.52015239j])
- Compute the first derivative of the Hankel function of the first kind
- of order 0 at several points by providing an array for `z`.
- >>> import numpy as np
- >>> points = np.array([0.5, 1.5, 3.])
- >>> h1vp(0, points, 1)
- array([-0.24226846+1.47147239j, -0.55793651+0.41230863j,
- -0.33905896-0.32467442j])
- """
- n = _nonneg_int_or_fail(n, 'n')
- if n == 0:
- return hankel1(v, z)
- else:
- return _bessel_diff_formula(v, z, n, hankel1, -1)
- def h2vp(v, z, n=1):
- """Compute derivatives of Hankel function H2v(z) with respect to `z`.
- Parameters
- ----------
- v : array_like
- Order of Hankel function
- z : array_like
- Argument at which to evaluate the derivative. Can be real or
- complex.
- n : int, default 1
- Order of derivative. For 0 returns the Hankel function `hankel2` itself.
- Returns
- -------
- scalar or ndarray
- Values of the derivative of the Hankel function.
- See Also
- --------
- hankel2
- Notes
- -----
- The derivative is computed using the relation DLFM 10.6.7 [2]_.
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996, chapter 5.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- .. [2] NIST Digital Library of Mathematical Functions.
- https://dlmf.nist.gov/10.6.E7
- Examples
- --------
- Compute the Hankel function of the second kind of order 0 and
- its first two derivatives at 1.
- >>> from scipy.special import h2vp
- >>> h2vp(0, 1, 0), h2vp(0, 1, 1), h2vp(0, 1, 2)
- ((0.7651976865579664-0.088256964215677j),
- (-0.44005058574493355-0.7812128213002889j),
- (-0.3251471008130329+0.8694697855159659j))
- Compute the first derivative of the Hankel function of the second kind
- for several orders at 1 by providing an array for `v`.
- >>> h2vp([0, 1, 2], 1, 1)
- array([-0.44005059-0.78121282j, 0.3251471 -0.86946979j,
- 0.21024362-2.52015239j])
- Compute the first derivative of the Hankel function of the second kind
- of order 0 at several points by providing an array for `z`.
- >>> import numpy as np
- >>> points = np.array([0.5, 1.5, 3.])
- >>> h2vp(0, points, 1)
- array([-0.24226846-1.47147239j, -0.55793651-0.41230863j,
- -0.33905896+0.32467442j])
- """
- n = _nonneg_int_or_fail(n, 'n')
- if n == 0:
- return hankel2(v, z)
- else:
- return _bessel_diff_formula(v, z, n, hankel2, -1)
- def riccati_jn(n, x):
- r"""Compute Riccati-Bessel function of the first kind and its derivative.
- The Riccati-Bessel function of the first kind is defined as :math:`x
- j_n(x)`, where :math:`j_n` is the spherical Bessel function of the first
- kind of order :math:`n`.
- This function computes the value and first derivative of the
- Riccati-Bessel function for all orders up to and including `n`.
- Parameters
- ----------
- n : int
- Maximum order of function to compute
- x : float
- Argument at which to evaluate
- Returns
- -------
- jn : ndarray
- Value of j0(x), ..., jn(x)
- jnp : ndarray
- First derivative j0'(x), ..., jn'(x)
- Notes
- -----
- The computation is carried out via backward recurrence, using the
- relation DLMF 10.51.1 [2]_.
- Wrapper for a Fortran routine created by Shanjie Zhang and Jianming
- Jin [1]_.
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- .. [2] NIST Digital Library of Mathematical Functions.
- https://dlmf.nist.gov/10.51.E1
- """
- if not (isscalar(n) and isscalar(x)):
- raise ValueError("arguments must be scalars.")
- n = _nonneg_int_or_fail(n, 'n', strict=False)
- if (n == 0):
- n1 = 1
- else:
- n1 = n
- jn = np.empty((n1 + 1,), dtype=np.float64)
- jnp = np.empty_like(jn)
- _rctj(x, out=(jn, jnp))
- return jn[:(n+1)], jnp[:(n+1)]
- def riccati_yn(n, x):
- """Compute Riccati-Bessel function of the second kind and its derivative.
- The Riccati-Bessel function of the second kind is defined here as :math:`+x
- y_n(x)`, where :math:`y_n` is the spherical Bessel function of the second
- kind of order :math:`n`. *Note that this is in contrast to a common convention
- that includes a minus sign in the definition.*
- This function computes the value and first derivative of the function for
- all orders up to and including `n`.
- Parameters
- ----------
- n : int
- Maximum order of function to compute
- x : float
- Argument at which to evaluate
- Returns
- -------
- yn : ndarray
- Value of y0(x), ..., yn(x)
- ynp : ndarray
- First derivative y0'(x), ..., yn'(x)
- Notes
- -----
- The computation is carried out via ascending recurrence, using the
- relation DLMF 10.51.1 [2]_.
- Wrapper for a Fortran routine created by Shanjie Zhang and Jianming
- Jin [1]_.
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- .. [2] NIST Digital Library of Mathematical Functions.
- https://dlmf.nist.gov/10.51.E1
- """
- if not (isscalar(n) and isscalar(x)):
- raise ValueError("arguments must be scalars.")
- n = _nonneg_int_or_fail(n, 'n', strict=False)
- if (n == 0):
- n1 = 1
- else:
- n1 = n
- yn = np.empty((n1 + 1,), dtype=np.float64)
- ynp = np.empty_like(yn)
- _rcty(x, out=(yn, ynp))
- return yn[:(n+1)], ynp[:(n+1)]
- def erf_zeros(nt):
- """Compute the first nt zero in the first quadrant, ordered by absolute value.
- Zeros in the other quadrants can be obtained by using the symmetries
- erf(-z) = erf(z) and erf(conj(z)) = conj(erf(z)).
- Parameters
- ----------
- nt : int
- The number of zeros to compute
- Returns
- -------
- The locations of the zeros of erf : ndarray (complex)
- Complex values at which zeros of erf(z)
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- Examples
- --------
- >>> from scipy import special
- >>> special.erf_zeros(1)
- array([1.45061616+1.880943j])
- Check that erf is (close to) zero for the value returned by erf_zeros
- >>> special.erf(special.erf_zeros(1))
- array([4.95159469e-14-1.16407394e-16j])
- """
- if (floor(nt) != nt) or (nt <= 0) or not isscalar(nt):
- raise ValueError("Argument must be positive scalar integer.")
- return _specfun.cerzo(nt)
- def fresnelc_zeros(nt):
- """Compute nt complex zeros of cosine Fresnel integral C(z).
- Parameters
- ----------
- nt : int
- Number of zeros to compute
- Returns
- -------
- fresnelc_zeros: ndarray
- Zeros of the cosine Fresnel integral
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if (floor(nt) != nt) or (nt <= 0) or not isscalar(nt):
- raise ValueError("Argument must be positive scalar integer.")
- return _specfun.fcszo(1, nt)
- def fresnels_zeros(nt):
- """Compute nt complex zeros of sine Fresnel integral S(z).
- Parameters
- ----------
- nt : int
- Number of zeros to compute
- Returns
- -------
- fresnels_zeros: ndarray
- Zeros of the sine Fresnel integral
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if (floor(nt) != nt) or (nt <= 0) or not isscalar(nt):
- raise ValueError("Argument must be positive scalar integer.")
- return _specfun.fcszo(2, nt)
- def fresnel_zeros(nt):
- """Compute nt complex zeros of sine and cosine Fresnel integrals S(z) and C(z).
- Parameters
- ----------
- nt : int
- Number of zeros to compute
- Returns
- -------
- zeros_sine: ndarray
- Zeros of the sine Fresnel integral
- zeros_cosine : ndarray
- Zeros of the cosine Fresnel integral
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if (floor(nt) != nt) or (nt <= 0) or not isscalar(nt):
- raise ValueError("Argument must be positive scalar integer.")
- return _specfun.fcszo(2, nt), _specfun.fcszo(1, nt)
- def assoc_laguerre(x, n, k=0.0):
- """Compute the generalized (associated) Laguerre polynomial of degree n and order k.
- The polynomial :math:`L^{(k)}_n(x)` is orthogonal over ``[0, inf)``,
- with weighting function ``exp(-x) * x**k`` with ``k > -1``.
- Parameters
- ----------
- x : float or ndarray
- Points where to evaluate the Laguerre polynomial
- n : int
- Degree of the Laguerre polynomial
- k : int
- Order of the Laguerre polynomial
- Returns
- -------
- assoc_laguerre: float or ndarray
- Associated laguerre polynomial values
- Notes
- -----
- `assoc_laguerre` is a simple wrapper around `eval_genlaguerre`, with
- reversed argument order ``(x, n, k=0.0) --> (n, k, x)``.
- """
- return _ufuncs.eval_genlaguerre(n, k, x)
- digamma = psi
- def polygamma(n, x):
- r"""Polygamma functions.
- Defined as :math:`\psi^{(n)}(x)` where :math:`\psi` is the
- `digamma` function. See [dlmf]_ for details.
- Parameters
- ----------
- n : array_like
- The order of the derivative of the digamma function; must be
- integral
- x : array_like
- Real valued input
- Returns
- -------
- ndarray
- Function results
- See Also
- --------
- digamma
- References
- ----------
- .. [dlmf] NIST, Digital Library of Mathematical Functions,
- https://dlmf.nist.gov/5.15
- Examples
- --------
- >>> from scipy import special
- >>> x = [2, 3, 25.5]
- >>> special.polygamma(1, x)
- array([ 0.64493407, 0.39493407, 0.03999467])
- >>> special.polygamma(0, x) == special.psi(x)
- array([ True, True, True], dtype=bool)
- """
- n, x = asarray(n), asarray(x)
- fac2 = (-1.0)**(n+1) * gamma(n+1.0) * zeta(n+1, x)
- return where(n == 0, psi(x), fac2)
- def mathieu_even_coef(m, q):
- r"""Fourier coefficients for even Mathieu and modified Mathieu functions.
- The Fourier series of the even solutions of the Mathieu differential
- equation are of the form
- .. math:: \mathrm{ce}_{2n}(z, q) = \sum_{k=0}^{\infty} A_{(2n)}^{(2k)} \cos 2kz
- .. math:: \mathrm{ce}_{2n+1}(z, q) =
- \sum_{k=0}^{\infty} A_{(2n+1)}^{(2k+1)} \cos (2k+1)z
- This function returns the coefficients :math:`A_{(2n)}^{(2k)}` for even
- input m=2n, and the coefficients :math:`A_{(2n+1)}^{(2k+1)}` for odd input
- m=2n+1.
- Parameters
- ----------
- m : int
- Order of Mathieu functions. Must be non-negative.
- q : float (>=0)
- Parameter of Mathieu functions. Must be non-negative.
- Returns
- -------
- Ak : ndarray
- Even or odd Fourier coefficients, corresponding to even or odd m.
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- .. [2] NIST Digital Library of Mathematical Functions
- https://dlmf.nist.gov/28.4#i
- """
- if not (isscalar(m) and isscalar(q)):
- raise ValueError("m and q must be scalars.")
- if (q < 0):
- raise ValueError("q >=0")
- if (m != floor(m)) or (m < 0):
- raise ValueError("m must be an integer >=0.")
- if (q <= 1):
- qm = 7.5 + 56.1*sqrt(q) - 134.7*q + 90.7*sqrt(q)*q
- else:
- qm = 17.0 + 3.1*sqrt(q) - .126*q + .0037*sqrt(q)*q
- km = int(qm + 0.5*m)
- if km > 251:
- warnings.warn("Too many predicted coefficients.", RuntimeWarning, stacklevel=2)
- kd = 1
- m = int(floor(m))
- if m % 2:
- kd = 2
- a = mathieu_a(m, q)
- fc = _specfun.fcoef(kd, m, q, a)
- return fc[:km]
- def mathieu_odd_coef(m, q):
- r"""Fourier coefficients for odd Mathieu and modified Mathieu functions.
- The Fourier series of the odd solutions of the Mathieu differential
- equation are of the form
- .. math:: \mathrm{se}_{2n+1}(z, q) =
- \sum_{k=0}^{\infty} B_{(2n+1)}^{(2k+1)} \sin (2k+1)z
- .. math:: \mathrm{se}_{2n+2}(z, q) =
- \sum_{k=0}^{\infty} B_{(2n+2)}^{(2k+2)} \sin (2k+2)z
- This function returns the coefficients :math:`B_{(2n+2)}^{(2k+2)}` for even
- input m=2n+2, and the coefficients :math:`B_{(2n+1)}^{(2k+1)}` for odd
- input m=2n+1.
- Parameters
- ----------
- m : int
- Order of Mathieu functions. Must be non-negative.
- q : float (>=0)
- Parameter of Mathieu functions. Must be non-negative.
- Returns
- -------
- Bk : ndarray
- Even or odd Fourier coefficients, corresponding to even or odd m.
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if not (isscalar(m) and isscalar(q)):
- raise ValueError("m and q must be scalars.")
- if (q < 0):
- raise ValueError("q >=0")
- if (m != floor(m)) or (m <= 0):
- raise ValueError("m must be an integer > 0")
- if (q <= 1):
- qm = 7.5 + 56.1*sqrt(q) - 134.7*q + 90.7*sqrt(q)*q
- else:
- qm = 17.0 + 3.1*sqrt(q) - .126*q + .0037*sqrt(q)*q
- km = int(qm + 0.5*m)
- if km > 251:
- warnings.warn("Too many predicted coefficients.", RuntimeWarning, stacklevel=2)
- kd = 4
- m = int(floor(m))
- if m % 2:
- kd = 3
- b = mathieu_b(m, q)
- fc = _specfun.fcoef(kd, m, q, b)
- return fc[:km]
- def lqmn(m, n, z):
- """Sequence of associated Legendre functions of the second kind.
- Computes the associated Legendre function of the second kind of order m and
- degree n, ``Qmn(z)`` = :math:`Q_n^m(z)`, and its derivative, ``Qmn'(z)``.
- Returns two arrays of size ``(m+1, n+1)`` containing ``Qmn(z)`` and
- ``Qmn'(z)`` for all orders from ``0..m`` and degrees from ``0..n``.
- Parameters
- ----------
- m : int
- ``|m| <= n``; the order of the Legendre function.
- n : int
- where ``n >= 0``; the degree of the Legendre function. Often
- called ``l`` (lower case L) in descriptions of the associated
- Legendre function
- z : array_like, complex
- Input value.
- Returns
- -------
- Qmn_z : (m+1, n+1) array
- Values for all orders 0..m and degrees 0..n
- Qmn_d_z : (m+1, n+1) array
- Derivatives for all orders 0..m and degrees 0..n
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if not isscalar(m) or (m < 0):
- raise ValueError("m must be a non-negative integer.")
- if not isscalar(n) or (n < 0):
- raise ValueError("n must be a non-negative integer.")
- m, n = int(m), int(n) # Convert to int to maintain backwards compatibility.
- # Ensure neither m nor n == 0
- mm = max(1, m)
- nn = max(1, n)
- z = np.asarray(z)
- if (not np.issubdtype(z.dtype, np.inexact)):
- z = z.astype(np.float64)
- if np.iscomplexobj(z):
- q = np.empty((mm + 1, nn + 1) + z.shape, dtype=np.complex128)
- else:
- q = np.empty((mm + 1, nn + 1) + z.shape, dtype=np.float64)
- qd = np.empty_like(q)
- if (z.ndim == 0):
- _lqmn(z, out=(q, qd))
- else:
- # new axes must be last for the ufunc
- _lqmn(z,
- out=(np.moveaxis(q, (0, 1), (-2, -1)),
- np.moveaxis(qd, (0, 1), (-2, -1))))
- return q[:(m+1), :(n+1)], qd[:(m+1), :(n+1)]
- def bernoulli(n):
- """Bernoulli numbers B0..Bn (inclusive).
- Parameters
- ----------
- n : int
- Indicated the number of terms in the Bernoulli series to generate.
- Returns
- -------
- ndarray
- The Bernoulli numbers ``[B(0), B(1), ..., B(n)]``.
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- .. [2] "Bernoulli number", Wikipedia, https://en.wikipedia.org/wiki/Bernoulli_number
- Examples
- --------
- >>> import numpy as np
- >>> from scipy.special import bernoulli, zeta
- >>> bernoulli(4)
- array([ 1. , -0.5 , 0.16666667, 0. , -0.03333333])
- The Wikipedia article ([2]_) points out the relationship between the
- Bernoulli numbers and the zeta function, ``B_n^+ = -n * zeta(1 - n)``
- for ``n > 0``:
- >>> n = np.arange(1, 5)
- >>> -n * zeta(1 - n)
- array([ 0.5 , 0.16666667, -0. , -0.03333333])
- Note that, in the notation used in the wikipedia article,
- `bernoulli` computes ``B_n^-`` (i.e. it used the convention that
- ``B_1`` is -1/2). The relation given above is for ``B_n^+``, so the
- sign of 0.5 does not match the output of ``bernoulli(4)``.
- """
- if not isscalar(n) or (n < 0):
- raise ValueError("n must be a non-negative integer.")
- n = int(n)
- if (n < 2):
- n1 = 2
- else:
- n1 = n
- return _specfun.bernob(int(n1))[:(n+1)]
- def euler(n):
- """Euler numbers E(0), E(1), ..., E(n).
- The Euler numbers [1]_ are also known as the secant numbers.
- Because ``euler(n)`` returns floating point values, it does not give
- exact values for large `n`. The first inexact value is E(22).
- Parameters
- ----------
- n : int
- The highest index of the Euler number to be returned.
- Returns
- -------
- ndarray
- The Euler numbers [E(0), E(1), ..., E(n)].
- The odd Euler numbers, which are all zero, are included.
- References
- ----------
- .. [1] Sequence A122045, The On-Line Encyclopedia of Integer Sequences,
- https://oeis.org/A122045
- .. [2] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- Examples
- --------
- >>> import numpy as np
- >>> from scipy.special import euler
- >>> euler(6)
- array([ 1., 0., -1., 0., 5., 0., -61.])
- >>> euler(13).astype(np.int64)
- array([ 1, 0, -1, 0, 5, 0, -61,
- 0, 1385, 0, -50521, 0, 2702765, 0])
- >>> euler(22)[-1] # Exact value of E(22) is -69348874393137901.
- -69348874393137976.0
- """
- if not isscalar(n) or (n < 0):
- raise ValueError("n must be a non-negative integer.")
- n = int(n)
- if (n < 2):
- n1 = 2
- else:
- n1 = n
- return _specfun.eulerb(n1)[:(n+1)]
- def lqn(n, z):
- """Legendre function of the second kind.
- Compute sequence of Legendre functions of the second kind, Qn(z) and
- derivatives for all degrees from 0 to n (inclusive).
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- n = _nonneg_int_or_fail(n, 'n', strict=False)
- if (n < 1):
- n1 = 1
- else:
- n1 = n
- z = np.asarray(z)
- if (not np.issubdtype(z.dtype, np.inexact)):
- z = z.astype(float)
- if np.iscomplexobj(z):
- qn = np.empty((n1 + 1,) + z.shape, dtype=np.complex128)
- else:
- qn = np.empty((n1 + 1,) + z.shape, dtype=np.float64)
- qd = np.empty_like(qn)
- if (z.ndim == 0):
- _lqn(z, out=(qn, qd))
- else:
- # new axes must be last for the ufunc
- _lqn(z,
- out=(np.moveaxis(qn, 0, -1),
- np.moveaxis(qd, 0, -1)))
- return qn[:(n+1)], qd[:(n+1)]
- def ai_zeros(nt):
- """
- Compute `nt` zeros and values of the Airy function Ai and its derivative.
- Computes the first `nt` zeros, `a`, of the Airy function Ai(x);
- first `nt` zeros, `ap`, of the derivative of the Airy function Ai'(x);
- the corresponding values Ai(a');
- and the corresponding values Ai'(a).
- Parameters
- ----------
- nt : int
- Number of zeros to compute
- Returns
- -------
- a : ndarray
- First `nt` zeros of Ai(x)
- ap : ndarray
- First `nt` zeros of Ai'(x)
- ai : ndarray
- Values of Ai(x) evaluated at first `nt` zeros of Ai'(x)
- aip : ndarray
- Values of Ai'(x) evaluated at first `nt` zeros of Ai(x)
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- Examples
- --------
- >>> from scipy import special
- >>> a, ap, ai, aip = special.ai_zeros(3)
- >>> a
- array([-2.33810741, -4.08794944, -5.52055983])
- >>> ap
- array([-1.01879297, -3.24819758, -4.82009921])
- >>> ai
- array([ 0.53565666, -0.41901548, 0.38040647])
- >>> aip
- array([ 0.70121082, -0.80311137, 0.86520403])
- """
- kf = 1
- if not isscalar(nt) or (floor(nt) != nt) or (nt <= 0):
- raise ValueError("nt must be a positive integer scalar.")
- return _specfun.airyzo(nt, kf)
- def bi_zeros(nt):
- """
- Compute `nt` zeros and values of the Airy function Bi and its derivative.
- Computes the first `nt` zeros, b, of the Airy function Bi(x);
- first `nt` zeros, b', of the derivative of the Airy function Bi'(x);
- the corresponding values Bi(b');
- and the corresponding values Bi'(b).
- Parameters
- ----------
- nt : int
- Number of zeros to compute
- Returns
- -------
- b : ndarray
- First `nt` zeros of Bi(x)
- bp : ndarray
- First `nt` zeros of Bi'(x)
- bi : ndarray
- Values of Bi(x) evaluated at first `nt` zeros of Bi'(x)
- bip : ndarray
- Values of Bi'(x) evaluated at first `nt` zeros of Bi(x)
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- Examples
- --------
- >>> from scipy import special
- >>> b, bp, bi, bip = special.bi_zeros(3)
- >>> b
- array([-1.17371322, -3.2710933 , -4.83073784])
- >>> bp
- array([-2.29443968, -4.07315509, -5.51239573])
- >>> bi
- array([-0.45494438, 0.39652284, -0.36796916])
- >>> bip
- array([ 0.60195789, -0.76031014, 0.83699101])
- """
- kf = 2
- if not isscalar(nt) or (floor(nt) != nt) or (nt <= 0):
- raise ValueError("nt must be a positive integer scalar.")
- return _specfun.airyzo(nt, kf)
- def lmbda(v, x):
- r"""Jahnke-Emden Lambda function, Lambdav(x).
- This function is defined as [2]_,
- .. math:: \Lambda_v(x) = \Gamma(v+1) \frac{J_v(x)}{(x/2)^v},
- where :math:`\Gamma` is the gamma function and :math:`J_v` is the
- Bessel function of the first kind.
- Parameters
- ----------
- v : float
- Order of the Lambda function
- x : float
- Value at which to evaluate the function and derivatives
- Returns
- -------
- vl : ndarray
- Values of Lambda_vi(x), for vi=v-int(v), vi=1+v-int(v), ..., vi=v.
- dl : ndarray
- Derivatives Lambda_vi'(x), for vi=v-int(v), vi=1+v-int(v), ..., vi=v.
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- .. [2] Jahnke, E. and Emde, F. "Tables of Functions with Formulae and
- Curves" (4th ed.), Dover, 1945
- """
- if not (isscalar(v) and isscalar(x)):
- raise ValueError("arguments must be scalars.")
- if (v < 0):
- raise ValueError("argument must be > 0.")
- n = int(v)
- v0 = v - n
- if (n < 1):
- n1 = 1
- else:
- n1 = n
- v1 = n1 + v0
- if (v != floor(v)):
- vm, vl, dl = _specfun.lamv(v1, x)
- else:
- vm, vl, dl = _specfun.lamn(v1, x)
- return vl[:(n+1)], dl[:(n+1)]
- def pbdv_seq(v, x):
- """Parabolic cylinder functions Dv(x) and derivatives.
- Parameters
- ----------
- v : float
- Order of the parabolic cylinder function
- x : float
- Value at which to evaluate the function and derivatives
- Returns
- -------
- dv : ndarray
- Values of D_vi(x), for vi=v-int(v), vi=1+v-int(v), ..., vi=v.
- dp : ndarray
- Derivatives D_vi'(x), for vi=v-int(v), vi=1+v-int(v), ..., vi=v.
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996, chapter 13.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if not (isscalar(v) and isscalar(x)):
- raise ValueError("arguments must be scalars.")
- n = int(v)
- v0 = v-n
- if (n < 1):
- n1 = 1
- else:
- n1 = n
- v1 = n1 + v0
- dv, dp, pdf, pdd = _specfun.pbdv(v1, x)
- return dv[:n1+1], dp[:n1+1]
- def pbvv_seq(v, x):
- """Parabolic cylinder functions Vv(x) and derivatives.
- Parameters
- ----------
- v : float
- Order of the parabolic cylinder function
- x : float
- Value at which to evaluate the function and derivatives
- Returns
- -------
- dv : ndarray
- Values of V_vi(x), for vi=v-int(v), vi=1+v-int(v), ..., vi=v.
- dp : ndarray
- Derivatives V_vi'(x), for vi=v-int(v), vi=1+v-int(v), ..., vi=v.
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996, chapter 13.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if not (isscalar(v) and isscalar(x)):
- raise ValueError("arguments must be scalars.")
- n = int(v)
- v0 = v-n
- if (n <= 1):
- n1 = 1
- else:
- n1 = n
- v1 = n1 + v0
- dv, dp, pdf, pdd = _specfun.pbvv(v1, x)
- return dv[:n1+1], dp[:n1+1]
- def pbdn_seq(n, z):
- """Parabolic cylinder functions Dn(z) and derivatives.
- Parameters
- ----------
- n : int
- Order of the parabolic cylinder function
- z : complex
- Value at which to evaluate the function and derivatives
- Returns
- -------
- dv : ndarray
- Values of D_i(z), for i=0, ..., i=n.
- dp : ndarray
- Derivatives D_i'(z), for i=0, ..., i=n.
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996, chapter 13.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if not (isscalar(n) and isscalar(z)):
- raise ValueError("arguments must be scalars.")
- if (floor(n) != n):
- raise ValueError("n must be an integer.")
- if (abs(n) <= 1):
- n1 = 1
- else:
- n1 = n
- cpb, cpd = _specfun.cpbdn(n1, z)
- return cpb[:n1+1], cpd[:n1+1]
- def ber_zeros(nt):
- """Compute nt zeros of the Kelvin function ber.
- Parameters
- ----------
- nt : int
- Number of zeros to compute. Must be positive.
- Returns
- -------
- ndarray
- First `nt` zeros of the Kelvin function.
- See Also
- --------
- ber
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if not isscalar(nt) or (floor(nt) != nt) or (nt <= 0):
- raise ValueError("nt must be positive integer scalar.")
- return _specfun.klvnzo(nt, 1)
- def bei_zeros(nt):
- """Compute nt zeros of the Kelvin function bei.
- Parameters
- ----------
- nt : int
- Number of zeros to compute. Must be positive.
- Returns
- -------
- ndarray
- First `nt` zeros of the Kelvin function.
- See Also
- --------
- bei
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if not isscalar(nt) or (floor(nt) != nt) or (nt <= 0):
- raise ValueError("nt must be positive integer scalar.")
- return _specfun.klvnzo(nt, 2)
- def ker_zeros(nt):
- """Compute nt zeros of the Kelvin function ker.
- Parameters
- ----------
- nt : int
- Number of zeros to compute. Must be positive.
- Returns
- -------
- ndarray
- First `nt` zeros of the Kelvin function.
- See Also
- --------
- ker
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if not isscalar(nt) or (floor(nt) != nt) or (nt <= 0):
- raise ValueError("nt must be positive integer scalar.")
- return _specfun.klvnzo(nt, 3)
- def kei_zeros(nt):
- """Compute nt zeros of the Kelvin function kei.
- Parameters
- ----------
- nt : int
- Number of zeros to compute. Must be positive.
- Returns
- -------
- ndarray
- First `nt` zeros of the Kelvin function.
- See Also
- --------
- kei
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if not isscalar(nt) or (floor(nt) != nt) or (nt <= 0):
- raise ValueError("nt must be positive integer scalar.")
- return _specfun.klvnzo(nt, 4)
- def berp_zeros(nt):
- """Compute nt zeros of the derivative of the Kelvin function ber.
- Parameters
- ----------
- nt : int
- Number of zeros to compute. Must be positive.
- Returns
- -------
- ndarray
- First `nt` zeros of the derivative of the Kelvin function.
- See Also
- --------
- ber, berp
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- Examples
- --------
- Compute the first 5 zeros of the derivative of the Kelvin function.
- >>> from scipy.special import berp_zeros
- >>> berp_zeros(5)
- array([ 6.03871081, 10.51364251, 14.96844542, 19.41757493, 23.86430432])
- """
- if not isscalar(nt) or (floor(nt) != nt) or (nt <= 0):
- raise ValueError("nt must be positive integer scalar.")
- return _specfun.klvnzo(nt, 5)
- def beip_zeros(nt):
- """Compute nt zeros of the derivative of the Kelvin function bei.
- Parameters
- ----------
- nt : int
- Number of zeros to compute. Must be positive.
- Returns
- -------
- ndarray
- First `nt` zeros of the derivative of the Kelvin function.
- See Also
- --------
- bei, beip
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if not isscalar(nt) or (floor(nt) != nt) or (nt <= 0):
- raise ValueError("nt must be positive integer scalar.")
- return _specfun.klvnzo(nt, 6)
- def kerp_zeros(nt):
- """Compute nt zeros of the derivative of the Kelvin function ker.
- Parameters
- ----------
- nt : int
- Number of zeros to compute. Must be positive.
- Returns
- -------
- ndarray
- First `nt` zeros of the derivative of the Kelvin function.
- See Also
- --------
- ker, kerp
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if not isscalar(nt) or (floor(nt) != nt) or (nt <= 0):
- raise ValueError("nt must be positive integer scalar.")
- return _specfun.klvnzo(nt, 7)
- def keip_zeros(nt):
- """Compute nt zeros of the derivative of the Kelvin function kei.
- Parameters
- ----------
- nt : int
- Number of zeros to compute. Must be positive.
- Returns
- -------
- ndarray
- First `nt` zeros of the derivative of the Kelvin function.
- See Also
- --------
- kei, keip
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if not isscalar(nt) or (floor(nt) != nt) or (nt <= 0):
- raise ValueError("nt must be positive integer scalar.")
- return _specfun.klvnzo(nt, 8)
- def kelvin_zeros(nt):
- """Compute nt zeros of all Kelvin functions.
- Returned in a length-8 tuple of arrays of length nt. The tuple contains
- the arrays of zeros of (ber, bei, ker, kei, ber', bei', ker', kei').
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if not isscalar(nt) or (floor(nt) != nt) or (nt <= 0):
- raise ValueError("nt must be positive integer scalar.")
- return (_specfun.klvnzo(nt, 1),
- _specfun.klvnzo(nt, 2),
- _specfun.klvnzo(nt, 3),
- _specfun.klvnzo(nt, 4),
- _specfun.klvnzo(nt, 5),
- _specfun.klvnzo(nt, 6),
- _specfun.klvnzo(nt, 7),
- _specfun.klvnzo(nt, 8))
- def pro_cv_seq(m, n, c):
- """Characteristic values for prolate spheroidal wave functions.
- Compute a sequence of characteristic values for the prolate
- spheroidal wave functions for mode m and n'=m..n and spheroidal
- parameter c.
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if not (isscalar(m) and isscalar(n) and isscalar(c)):
- raise ValueError("Arguments must be scalars.")
- if (n != floor(n)) or (m != floor(m)):
- raise ValueError("Modes must be integers.")
- if (n-m > 199):
- raise ValueError("Difference between n and m is too large.")
- maxL = n-m+1
- return _specfun.segv(m, n, c, 1)[1][:maxL]
- def obl_cv_seq(m, n, c):
- """Characteristic values for oblate spheroidal wave functions.
- Compute a sequence of characteristic values for the oblate
- spheroidal wave functions for mode m and n'=m..n and spheroidal
- parameter c.
- References
- ----------
- .. [1] Zhang, Shanjie and Jin, Jianming. "Computation of Special
- Functions", John Wiley and Sons, 1996.
- https://people.sc.fsu.edu/~jburkardt/f77_src/special_functions/special_functions.html
- """
- if not (isscalar(m) and isscalar(n) and isscalar(c)):
- raise ValueError("Arguments must be scalars.")
- if (n != floor(n)) or (m != floor(m)):
- raise ValueError("Modes must be integers.")
- if (n-m > 199):
- raise ValueError("Difference between n and m is too large.")
- maxL = n-m+1
- return _specfun.segv(m, n, c, -1)[1][:maxL]
- def comb(N, k, *, exact=False, repetition=False):
- """The number of combinations of N things taken k at a time.
- This is often expressed as "N choose k".
- Parameters
- ----------
- N : int, ndarray
- Number of things.
- k : int, ndarray
- Number of elements taken.
- exact : bool, optional
- For integers, if `exact` is False, then floating point precision is
- used, otherwise the result is computed exactly.
- repetition : bool, optional
- If `repetition` is True, then the number of combinations with
- repetition is computed.
- Returns
- -------
- val : int, float, ndarray
- The total number of combinations.
- See Also
- --------
- binom : Binomial coefficient considered as a function of two real
- variables.
- Notes
- -----
- - Array arguments accepted only for exact=False case.
- - If N < 0, or k < 0, then 0 is returned.
- - If k > N and repetition=False, then 0 is returned.
- Examples
- --------
- >>> import numpy as np
- >>> from scipy.special import comb
- >>> k = np.array([3, 4])
- >>> n = np.array([10, 10])
- >>> comb(n, k, exact=False)
- array([ 120., 210.])
- >>> comb(10, 3, exact=True)
- 120
- >>> comb(10, 3, exact=True, repetition=True)
- 220
- """
- if repetition:
- # Special case: C(n, 0) with repetition = 1 for n >= 0
- # Without this check, comb(0, 0, repetition=True) would compute
- # comb(-1, 0) which incorrectly returns 0
- if exact:
- if k == 0 and int(N) == N and N >= 0:
- return 1
- else:
- k, N = asarray(k), asarray(N)
- cond = (k == 0) & (N >= 0)
- vals = binom(N + k - 1, k)
- if isinstance(vals, np.ndarray):
- vals[cond] = 1.0
- elif cond:
- vals = np.float64(1.0)
- return vals
- return comb(N + k - 1, k, exact=exact)
- if exact:
- if int(N) == N and int(k) == k:
- # _comb_int casts inputs to integers, which is safe & intended here
- return _comb_int(N, k)
- else:
- raise ValueError("Non-integer `N` and `k` with `exact=True` is not "
- "supported.")
- else:
- k, N = asarray(k), asarray(N)
- cond = (k <= N) & (N >= 0) & (k >= 0)
- vals = binom(N, k)
- if isinstance(vals, np.ndarray):
- vals[~cond] = 0
- elif not cond:
- vals = np.float64(0)
- return vals
- def perm(N, k, exact=False):
- """Permutations of N things taken k at a time, i.e., k-permutations of N.
- It's also known as "partial permutations".
- Parameters
- ----------
- N : int, ndarray
- Number of things.
- k : int, ndarray
- Number of elements taken.
- exact : bool, optional
- If ``True``, calculate the answer exactly using long integer arithmetic (`N`
- and `k` must be scalar integers). If ``False``, a floating point approximation
- is calculated (more rapidly) using `poch`. Default is ``False``.
- Returns
- -------
- val : int, ndarray
- The number of k-permutations of N.
- Notes
- -----
- - Array arguments accepted only for exact=False case.
- - If k > N, N < 0, or k < 0, then a 0 is returned.
- Examples
- --------
- >>> import numpy as np
- >>> from scipy.special import perm
- >>> k = np.array([3, 4])
- >>> n = np.array([10, 10])
- >>> perm(n, k)
- array([ 720., 5040.])
- >>> perm(10, 3, exact=True)
- 720
- """
- if exact:
- N = np.squeeze(N)[()] # for backward compatibility (accepted size 1 arrays)
- k = np.squeeze(k)[()]
- if not (isscalar(N) and isscalar(k)):
- raise ValueError("`N` and `k` must be scalar integers with `exact=True`.")
- floor_N, floor_k = int(N), int(k)
- non_integral = not (floor_N == N and floor_k == k)
- if non_integral:
- raise ValueError("Non-integer `N` and `k` with `exact=True` is not "
- "supported.")
- if (k > N) or (N < 0) or (k < 0):
- return 0
- val = 1
- for i in range(floor_N - floor_k + 1, floor_N + 1):
- val *= i
- return val
- else:
- k, N = asarray(k), asarray(N)
- cond = (k <= N) & (N >= 0) & (k >= 0)
- vals = poch(N - k + 1, k)
- if isinstance(vals, np.ndarray):
- vals[~cond] = 0
- elif not cond:
- vals = np.float64(0)
- return vals
- # https://stackoverflow.com/a/16327037
- def _range_prod(lo, hi, k=1):
- """
- Product of a range of numbers spaced k apart (from hi).
- For k=1, this returns the product of
- lo * (lo+1) * (lo+2) * ... * (hi-2) * (hi-1) * hi
- = hi! / (lo-1)!
- For k>1, it correspond to taking only every k'th number when
- counting down from hi - e.g. 18!!!! = _range_prod(1, 18, 4).
- Breaks into smaller products first for speed:
- _range_prod(2, 9) = ((2*3)*(4*5))*((6*7)*(8*9))
- """
- if lo == 1 and k == 1:
- return math.factorial(hi)
- if lo + k < hi:
- mid = (hi + lo) // 2
- if k > 1:
- # make sure mid is a multiple of k away from hi
- mid = mid - ((mid - hi) % k)
- return _range_prod(lo, mid, k) * _range_prod(mid + k, hi, k)
- elif lo + k == hi:
- return lo * hi
- else:
- return hi
- def _factorialx_array_exact(n, k=1):
- """
- Exact computation of factorial for an array.
- The factorials are computed in incremental fashion, by taking
- the sorted unique values of n and multiplying the intervening
- numbers between the different unique values.
- In other words, the factorial for the largest input is only
- computed once, with each other result computed in the process.
- k > 1 corresponds to the multifactorial.
- """
- un = np.unique(n)
- # Convert to object array if np.int64 can't handle size
- if k in _FACTORIALK_LIMITS_64BITS.keys():
- if un[-1] > _FACTORIALK_LIMITS_64BITS[k]:
- # e.g. k=1: 21! > np.iinfo(np.int64).max
- dt = object
- elif un[-1] > _FACTORIALK_LIMITS_32BITS[k]:
- # e.g. k=3: 26!!! > np.iinfo(np.int32).max
- dt = np.int64
- else:
- dt = np.dtype("long")
- else:
- # for k >= 10, we always use object
- dt = object
- out = np.empty_like(n, dtype=dt)
- # Handle invalid/trivial values
- un = un[un > 1]
- out[n < 2] = 1
- out[n < 0] = 0
- # Calculate products of each range of numbers
- # we can only multiply incrementally if the values are k apart;
- # therefore we partition `un` into "lanes", i.e. its residues modulo k
- for lane in range(0, k):
- ul = un[(un % k) == lane] if k > 1 else un
- if ul.size:
- # after np.unique, un resp. ul are sorted, ul[0] is the smallest;
- # cast to python ints to avoid overflow with np.int-types
- val = _range_prod(1, int(ul[0]), k=k)
- out[n == ul[0]] = val
- for i in range(len(ul) - 1):
- # by the filtering above, we have ensured that prev & current
- # are a multiple of k apart
- prev = ul[i]
- current = ul[i + 1]
- # we already multiplied all factors until prev; continue
- # building the full factorial from the following (`prev + 1`);
- # use int() for the same reason as above
- val *= _range_prod(int(prev + 1), int(current), k=k)
- out[n == current] = val
- return out
- def _factorialx_array_approx(n, k, extend):
- """
- Calculate approximation to multifactorial for array n and integer k.
- Ensure that values aren't calculated unnecessarily.
- """
- if extend == "complex":
- return _factorialx_approx_core(n, k=k, extend=extend)
- # at this point we are guaranteed that extend='zero' and that k>0 is an integer
- result = zeros(n.shape)
- # keep nans as nans
- place(result, np.isnan(n), np.nan)
- # only compute where n >= 0 (excludes nans), everything else is 0
- cond = (n >= 0)
- n_to_compute = extract(cond, n)
- place(result, cond, _factorialx_approx_core(n_to_compute, k=k, extend=extend))
- return result
- def _gamma1p(vals):
- """
- returns gamma(n+1), though with NaN at -1 instead of inf, c.f. #21827
- """
- res = gamma(vals + 1)
- # replace infinities at -1 (from gamma function at 0) with nan
- # gamma only returns inf for real inputs; can ignore complex case
- if isinstance(res, np.ndarray):
- if not _is_subdtype(vals.dtype, "c"):
- res[vals == -1] = np.nan
- elif np.isinf(res) and vals == -1:
- res = np.float64("nan")
- return res
- def _factorialx_approx_core(n, k, extend):
- """
- Core approximation to multifactorial for array n and integer k.
- """
- if k == 1:
- # shortcut for k=1; same for both extensions, because we assume the
- # handling of extend == 'zero' happens in _factorialx_array_approx
- result = _gamma1p(n)
- if isinstance(n, np.ndarray):
- # gamma does not maintain 0-dim arrays; fix it
- result = np.array(result)
- return result
- if extend == "complex":
- # see https://numpy.org/doc/stable/reference/generated/numpy.power.html
- p_dtype = complex if (_is_subdtype(type(k), "c") or k < 0) else None
- with warnings.catch_warnings():
- # do not warn about 0 * inf, nan / nan etc.; the results are correct
- warnings.simplefilter("ignore", RuntimeWarning)
- # don't use `(n-1)/k` in np.power; underflows if 0 is of a uintX type
- result = np.power(k, n / k, dtype=p_dtype) * _gamma1p(n / k)
- result *= rgamma(1 / k + 1) / np.power(k, 1 / k, dtype=p_dtype)
- if isinstance(n, np.ndarray):
- # ensure we keep array-ness for 0-dim inputs; already n/k above loses it
- result = np.array(result)
- return result
- # at this point we are guaranteed that extend='zero' and that k>0 is an integer
- n_mod_k = n % k
- # scalar case separately, unified handling would be inefficient for arrays;
- # don't use isscalar due to numpy/numpy#23574; 0-dim arrays treated below
- if not isinstance(n, np.ndarray):
- with warnings.catch_warnings():
- # large n cause overflow warnings, but infinity is fine
- warnings.simplefilter("ignore", RuntimeWarning)
- return (
- np.power(k, (n - n_mod_k) / k)
- * gamma(n / k + 1) / gamma(n_mod_k / k + 1)
- * max(n_mod_k, 1)
- )
- # factor that's independent of the residue class (see factorialk docstring)
- with warnings.catch_warnings():
- # large n cause overflow warnings, but infinity is fine
- warnings.simplefilter("ignore", RuntimeWarning)
- result = np.power(k, n / k) * gamma(n / k + 1)
- # factor dependent on residue r (for `r=0` it's 1, so we skip `r=0`
- # below and thus also avoid evaluating `max(r, 1)`)
- def corr(k, r): return np.power(k, -r / k) / gamma(r / k + 1) * r
- for r in np.unique(n_mod_k):
- if r == 0:
- continue
- # cast to int because uint types break on `-r`
- result[n_mod_k == r] *= corr(k, int(r))
- return result
- def _is_subdtype(dtype, dtypes):
- """
- Shorthand for calculating whether dtype is subtype of some dtypes.
- Also allows specifying a list instead of just a single dtype.
- Additionaly, the most important supertypes from
- https://numpy.org/doc/stable/reference/arrays.scalars.html
- can optionally be specified using abbreviations as follows:
- "i": np.integer
- "f": np.floating
- "c": np.complexfloating
- "n": np.number (contains the other three)
- """
- dtypes = dtypes if isinstance(dtypes, list) else [dtypes]
- # map single character abbreviations, if they are in dtypes
- mapping = {
- "i": np.integer,
- "f": np.floating,
- "c": np.complexfloating,
- "n": np.number
- }
- dtypes = [mapping.get(x, x) for x in dtypes]
- return any(np.issubdtype(dtype, dt) for dt in dtypes)
- def _factorialx_wrapper(fname, n, k, exact, extend):
- """
- Shared implementation for factorial, factorial2 & factorialk.
- """
- if extend not in ("zero", "complex"):
- raise ValueError(
- f"argument `extend` must be either 'zero' or 'complex', received: {extend}"
- )
- if exact and extend == "complex":
- raise ValueError("Incompatible options: `exact=True` and `extend='complex'`")
- msg_unsup = (
- "Unsupported data type for {vname} in {fname}: {dtype}\n"
- )
- if fname == "factorial":
- msg_unsup += (
- "Permitted data types are integers and floating point numbers, "
- "as well as complex numbers if `extend='complex' is passed."
- )
- else:
- msg_unsup += (
- "Permitted data types are integers, as well as floating point "
- "numbers and complex numbers if `extend='complex' is passed."
- )
- msg_exact_not_possible = (
- "`exact=True` only supports integers, cannot use data type {dtype}"
- )
- msg_needs_complex = (
- "In order to use non-integer arguments, you must opt into this by passing "
- "`extend='complex'`. Note that this changes the result for all negative "
- "arguments (which by default return 0)."
- )
- if fname == "factorial2":
- msg_needs_complex += (" Additionally, it will rescale the values of the double"
- " factorial at even integers by a factor of sqrt(2/pi).")
- elif fname == "factorialk":
- msg_needs_complex += (" Additionally, it will perturb the values of the"
- " multifactorial at most positive integers `n`.")
- # check type of k
- if not _is_subdtype(type(k), ["i", "f", "c"]):
- raise ValueError(msg_unsup.format(vname="`k`", fname=fname, dtype=type(k)))
- elif _is_subdtype(type(k), ["f", "c"]) and extend != "complex":
- raise ValueError(msg_needs_complex)
- # check value of k
- if extend == "zero" and k < 1:
- msg = f"For `extend='zero'`, k must be a positive integer, received: {k}"
- raise ValueError(msg)
- elif k == 0:
- raise ValueError("Parameter k cannot be zero!")
- # factorial allows floats also for extend="zero"
- types_requiring_complex = "c" if fname == "factorial" else ["f", "c"]
- # don't use isscalar due to numpy/numpy#23574; 0-dim arrays treated below
- if np.ndim(n) == 0 and not isinstance(n, np.ndarray):
- # scalar cases
- if not _is_subdtype(type(n), ["i", "f", "c", type(None)]):
- raise ValueError(msg_unsup.format(vname="`n`", fname=fname, dtype=type(n)))
- elif _is_subdtype(type(n), types_requiring_complex) and extend != "complex":
- raise ValueError(msg_needs_complex)
- elif n is None or np.isnan(n):
- complexify = (extend == "complex") and _is_subdtype(type(n), "c")
- return np.complex128("nan+nanj") if complexify else np.float64("nan")
- elif extend == "zero" and n < 0:
- return 0 if exact else np.float64(0)
- elif n in {0, 1}:
- return 1 if exact else np.float64(1)
- elif exact and _is_subdtype(type(n), "i"):
- # calculate with integers; cast away other int types (like unsigned)
- return _range_prod(1, int(n), k=k)
- elif exact:
- # only relevant for factorial
- raise ValueError(msg_exact_not_possible.format(dtype=type(n)))
- # approximation
- return _factorialx_approx_core(n, k=k, extend=extend)
- # arrays & array-likes
- n = asarray(n)
- if not _is_subdtype(n.dtype, ["i", "f", "c"]):
- raise ValueError(msg_unsup.format(vname="`n`", fname=fname, dtype=n.dtype))
- elif _is_subdtype(n.dtype, types_requiring_complex) and extend != "complex":
- raise ValueError(msg_needs_complex)
- elif exact and _is_subdtype(n.dtype, ["f"]):
- # only relevant for factorial
- raise ValueError(msg_exact_not_possible.format(dtype=n.dtype))
- if n.size == 0:
- # return empty arrays unchanged
- return n
- elif exact:
- # calculate with integers
- return _factorialx_array_exact(n, k=k)
- # approximation
- return _factorialx_array_approx(n, k=k, extend=extend)
- def factorial(n, exact=False, extend="zero"):
- """
- The factorial of a number or array of numbers.
- The factorial of non-negative integer `n` is the product of all
- positive integers less than or equal to `n`::
- n! = n * (n - 1) * (n - 2) * ... * 1
- Parameters
- ----------
- n : int or float or complex (or array_like thereof)
- Input values for ``n!``. Complex values require ``extend='complex'``.
- By default, the return value for ``n < 0`` is 0.
- exact : bool, optional
- If ``exact`` is set to True, calculate the answer exactly using
- integer arithmetic, otherwise approximate using the gamma function
- (faster, but yields floats instead of integers).
- Default is False.
- extend : string, optional
- One of ``'zero'`` or ``'complex'``; this determines how values ``n<0``
- are handled - by default they are 0, but it is possible to opt into the
- complex extension of the factorial (see below).
- Returns
- -------
- nf : int or float or complex or ndarray
- Factorial of ``n``, as integer, float or complex (depending on ``exact``
- and ``extend``). Array inputs are returned as arrays.
- Notes
- -----
- For arrays with ``exact=True``, the factorial is computed only once, for
- the largest input, with each other result computed in the process.
- The output dtype is increased to ``int64`` or ``object`` if necessary.
- With ``exact=False`` the factorial is approximated using the gamma
- function (which is also the definition of the complex extension):
- .. math:: n! = \\Gamma(n+1)
- Examples
- --------
- >>> import numpy as np
- >>> from scipy.special import factorial
- >>> arr = np.array([3, 4, 5])
- >>> factorial(arr, exact=False)
- array([ 6., 24., 120.])
- >>> factorial(arr, exact=True)
- array([ 6, 24, 120])
- >>> factorial(5, exact=True)
- 120
- """
- return _factorialx_wrapper("factorial", n, k=1, exact=exact, extend=extend)
- def factorial2(n, exact=False, extend="zero"):
- """Double factorial.
- This is the factorial with every second value skipped. E.g., ``7!! = 7 * 5
- * 3 * 1``. It can be approximated numerically as::
- n!! = 2 ** (n / 2) * gamma(n / 2 + 1) * sqrt(2 / pi) n odd
- = 2 ** (n / 2) * gamma(n / 2 + 1) n even
- = 2 ** (n / 2) * (n / 2)! n even
- The formula for odd ``n`` is the basis for the complex extension.
- Parameters
- ----------
- n : int or float or complex (or array_like thereof)
- Input values for ``n!!``. Non-integer values require ``extend='complex'``.
- By default, the return value for ``n < 0`` is 0.
- exact : bool, optional
- If ``exact`` is set to True, calculate the answer exactly using
- integer arithmetic, otherwise use above approximation (faster,
- but yields floats instead of integers).
- Default is False.
- extend : string, optional
- One of ``'zero'`` or ``'complex'``; this determines how values ``n<0``
- are handled - by default they are 0, but it is possible to opt into the
- complex extension of the double factorial. This also enables passing
- complex values to ``n``.
- .. warning::
- Using the ``'complex'`` extension also changes the values of the
- double factorial for even integers, reducing them by a factor of
- ``sqrt(2/pi) ~= 0.79``, see [1].
- Returns
- -------
- nf : int or float or complex or ndarray
- Double factorial of ``n``, as integer, float or complex (depending on
- ``exact`` and ``extend``). Array inputs are returned as arrays.
- Examples
- --------
- >>> from scipy.special import factorial2
- >>> factorial2(7, exact=False)
- np.float64(105.00000000000001)
- >>> factorial2(7, exact=True)
- 105
- References
- ----------
- .. [1] Complex extension to double factorial
- https://en.wikipedia.org/wiki/Double_factorial#Complex_arguments
- """
- return _factorialx_wrapper("factorial2", n, k=2, exact=exact, extend=extend)
- def factorialk(n, k, exact=False, extend="zero"):
- """Multifactorial of n of order k, n(!!...!).
- This is the multifactorial of n skipping k values. For example,
- factorialk(17, 4) = 17!!!! = 17 * 13 * 9 * 5 * 1
- In particular, for any integer ``n``, we have
- factorialk(n, 1) = factorial(n)
- factorialk(n, 2) = factorial2(n)
- Parameters
- ----------
- n : int or float or complex (or array_like thereof)
- Input values for multifactorial. Non-integer values require
- ``extend='complex'``. By default, the return value for ``n < 0`` is 0.
- k : int or float or complex (or array_like thereof)
- Order of multifactorial. Non-integer values require ``extend='complex'``.
- exact : bool, optional
- If ``exact`` is set to True, calculate the answer exactly using
- integer arithmetic, otherwise use an approximation (faster,
- but yields floats instead of integers)
- Default is False.
- extend : string, optional
- One of ``'zero'`` or ``'complex'``; this determines how values ``n<0`` are
- handled - by default they are 0, but it is possible to opt into the complex
- extension of the multifactorial. This enables passing complex values,
- not only to ``n`` but also to ``k``.
- .. warning::
- Using the ``'complex'`` extension also changes the values of the
- multifactorial at integers ``n != 1 (mod k)`` by a factor depending
- on both ``k`` and ``n % k``, see below or [1].
- Returns
- -------
- nf : int or float or complex or ndarray
- Multifactorial (order ``k``) of ``n``, as integer, float or complex (depending
- on ``exact`` and ``extend``). Array inputs are returned as arrays.
- Examples
- --------
- >>> from scipy.special import factorialk
- >>> factorialk(5, k=1, exact=True)
- 120
- >>> factorialk(5, k=3, exact=True)
- 10
- >>> factorialk([5, 7, 9], k=3, exact=True)
- array([ 10, 28, 162])
- >>> factorialk([5, 7, 9], k=3, exact=False)
- array([ 10., 28., 162.])
- Notes
- -----
- While less straight-forward than for the double-factorial, it's possible to
- calculate a general approximation formula of n!(k) by studying ``n`` for a given
- remainder ``r < k`` (thus ``n = m * k + r``, resp. ``r = n % k``), which can be
- put together into something valid for all integer values ``n >= 0`` & ``k > 0``::
- n!(k) = k ** ((n - r)/k) * gamma(n/k + 1) / gamma(r/k + 1) * max(r, 1)
- This is the basis of the approximation when ``exact=False``.
- In principle, any fixed choice of ``r`` (ignoring its relation ``r = n%k``
- to ``n``) would provide a suitable analytic continuation from integer ``n``
- to complex ``z`` (not only satisfying the functional equation but also
- being logarithmically convex, c.f. Bohr-Mollerup theorem) -- in fact, the
- choice of ``r`` above only changes the function by a constant factor. The
- final constraint that determines the canonical continuation is ``f(1) = 1``,
- which forces ``r = 1`` (see also [1]).::
- z!(k) = k ** ((z - 1)/k) * gamma(z/k + 1) / gamma(1/k + 1)
- References
- ----------
- .. [1] Complex extension to multifactorial
- https://en.wikipedia.org/wiki/Double_factorial#Alternative_extension_of_the_multifactorial
- """
- return _factorialx_wrapper("factorialk", n, k=k, exact=exact, extend=extend)
- def stirling2(N, K, *, exact=False):
- r"""Generate Stirling number(s) of the second kind.
- Stirling numbers of the second kind count the number of ways to
- partition a set with N elements into K non-empty subsets.
- The values this function returns are calculated using a dynamic
- program which avoids redundant computation across the subproblems
- in the solution. For array-like input, this implementation also
- avoids redundant computation across the different Stirling number
- calculations.
- The numbers are sometimes denoted
- .. math::
- {N \brace{K}}
- see [1]_ for details. This is often expressed-verbally-as
- "N subset K".
- Parameters
- ----------
- N : int, ndarray
- Number of things.
- K : int, ndarray
- Number of non-empty subsets taken.
- exact : bool, optional
- Uses dynamic programming (DP) with floating point
- numbers for smaller arrays and uses a second order approximation due to
- Temme for larger entries of `N` and `K` that allows trading speed for
- accuracy. See [2]_ for a description. Temme approximation is used for
- values ``n>50``. The max error from the DP has max relative error
- ``4.5*10^-16`` for ``n<=50`` and the max error from the Temme approximation
- has max relative error ``5*10^-5`` for ``51 <= n < 70`` and
- ``9*10^-6`` for ``70 <= n < 101``. Note that these max relative errors will
- decrease further as `n` increases.
- Returns
- -------
- val : int, float, ndarray
- The number of partitions.
- See Also
- --------
- comb : The number of combinations of N things taken k at a time.
- Notes
- -----
- - If N < 0, or K < 0, then 0 is returned.
- - If K > N, then 0 is returned.
- The output type will always be `int` or ndarray of `object`.
- The input must contain either numpy or python integers otherwise a
- TypeError is raised.
- References
- ----------
- .. [1] R. L. Graham, D. E. Knuth and O. Patashnik, "Concrete
- Mathematics: A Foundation for Computer Science," Addison-Wesley
- Publishing Company, Boston, 1989. Chapter 6, page 258.
- .. [2] Temme, Nico M. "Asymptotic estimates of Stirling numbers."
- Studies in Applied Mathematics 89.3 (1993): 233-243.
- Examples
- --------
- >>> import numpy as np
- >>> from scipy.special import stirling2
- >>> k = np.array([3, -1, 3])
- >>> n = np.array([10, 10, 9])
- >>> stirling2(n, k)
- array([9330.0, 0.0, 3025.0])
- """
- output_is_scalar = np.isscalar(N) and np.isscalar(K)
- # make a min-heap of unique (n,k) pairs
- N, K = asarray(N), asarray(K)
- if not np.issubdtype(N.dtype, np.integer):
- raise TypeError("Argument `N` must contain only integers")
- if not np.issubdtype(K.dtype, np.integer):
- raise TypeError("Argument `K` must contain only integers")
- if not exact:
- # NOTE: here we allow np.uint via casting to double types prior to
- # passing to private ufunc dispatcher. All dispatched functions
- # take double type for (n,k) arguments and return double.
- return _stirling2_inexact(N.astype(float), K.astype(float))
- nk_pairs = list(
- set([(n.take(0), k.take(0))
- for n, k in np.nditer([N, K], ['refs_ok'])])
- )
- heapify(nk_pairs)
- # base mapping for small values
- snsk_vals = defaultdict(int)
- for pair in [(0, 0), (1, 1), (2, 1), (2, 2)]:
- snsk_vals[pair] = 1
- # for each pair in the min-heap, calculate the value, store for later
- n_old, n_row = 2, [0, 1, 1]
- while nk_pairs:
- n, k = heappop(nk_pairs)
- if n < 2 or k > n or k <= 0:
- continue
- elif k == n or k == 1:
- snsk_vals[(n, k)] = 1
- continue
- elif n != n_old:
- num_iters = n - n_old
- while num_iters > 0:
- n_row.append(1)
- # traverse from back to remove second row
- for j in range(len(n_row)-2, 1, -1):
- n_row[j] = n_row[j]*j + n_row[j-1]
- num_iters -= 1
- snsk_vals[(n, k)] = n_row[k]
- else:
- snsk_vals[(n, k)] = n_row[k]
- n_old, n_row = n, n_row
- out_types = [object, object, object] if exact else [float, float, float]
- # for each pair in the map, fetch the value, and populate the array
- it = np.nditer(
- [N, K, None],
- ['buffered', 'refs_ok'],
- [['readonly'], ['readonly'], ['writeonly', 'allocate']],
- op_dtypes=out_types,
- )
- with it:
- while not it.finished:
- it[2] = snsk_vals[(int(it[0]), int(it[1]))]
- it.iternext()
- output = it.operands[2]
- # If N and K were both scalars, convert output to scalar.
- if output_is_scalar:
- output = output.take(0)
- return output
- def zeta(x, q=None, out=None):
- r"""
- Riemann or Hurwitz zeta function.
- Parameters
- ----------
- x : array_like of float or complex.
- Input data
- q : array_like of float, optional
- Input data, must be real. Defaults to Riemann zeta. When `q` is
- ``None``, complex inputs `x` are supported. If `q` is not ``None``,
- then currently only real inputs `x` with ``x >= 1`` are supported,
- even when ``q = 1.0`` (corresponding to the Riemann zeta function).
- out : ndarray, optional
- Output array for the computed values.
- Returns
- -------
- out : array_like
- Values of zeta(x).
- See Also
- --------
- zetac
- Notes
- -----
- The two-argument version is the Hurwitz zeta function
- .. math::
- \zeta(x, q) = \sum_{k=0}^{\infty} \frac{1}{(k + q)^x};
- see [dlmf]_ for details. The Riemann zeta function corresponds to
- the case when ``q = 1``.
- For complex inputs with ``q = None``, points with
- ``abs(z.imag) > 1e9`` and ``0 <= abs(z.real) < 2.5`` are currently not
- supported due to slow convergence causing excessive runtime.
- References
- ----------
- .. [dlmf] NIST, Digital Library of Mathematical Functions,
- https://dlmf.nist.gov/25.11#i
- Examples
- --------
- >>> import numpy as np
- >>> from scipy.special import zeta, polygamma, factorial
- Some specific values:
- >>> zeta(2), np.pi**2/6
- (1.6449340668482266, 1.6449340668482264)
- >>> zeta(4), np.pi**4/90
- (1.0823232337111381, 1.082323233711138)
- First nontrivial zero:
- >>> zeta(0.5 + 14.134725141734695j)
- 0 + 0j
- Relation to the `polygamma` function:
- >>> m = 3
- >>> x = 1.25
- >>> polygamma(m, x)
- array(2.782144009188397)
- >>> (-1)**(m+1) * factorial(m) * zeta(m+1, x)
- 2.7821440091883969
- """
- if q is None:
- return _ufuncs._riemann_zeta(x, out)
- else:
- return _ufuncs._zeta(x, q, out)
- def softplus(x, **kwargs):
- r"""
- Compute the softplus function element-wise.
- The softplus function is defined as: ``softplus(x) = log(1 + exp(x))``.
- It is a smooth approximation of the rectifier function (ReLU).
- Parameters
- ----------
- x : array_like
- Input value.
- **kwargs
- For other keyword-only arguments, see the
- `ufunc docs <https://numpy.org/doc/stable/reference/ufuncs.html>`_.
- Returns
- -------
- softplus : ndarray
- Logarithm of ``exp(0) + exp(x)``.
- Examples
- --------
- >>> from scipy import special
- >>> special.softplus(0)
- 0.6931471805599453
- >>> special.softplus([-1, 0, 1])
- array([0.31326169, 0.69314718, 1.31326169])
- """
- return np.logaddexp(0, x, **kwargs)
|