123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596 |
- from __future__ import annotations
- import numbers
- import decimal
- import fractions
- import math
- import re as regex
- import sys
- from functools import lru_cache
- from .containers import Tuple
- from .sympify import (SympifyError, _sympy_converter, sympify, _convert_numpy_types,
- _sympify, _is_numpy_instance)
- from .singleton import S, Singleton
- from .basic import Basic
- from .expr import Expr, AtomicExpr
- from .evalf import pure_complex
- from .cache import cacheit, clear_cache
- from .decorators import _sympifyit
- from .logic import fuzzy_not
- from .kind import NumberKind
- from sympy.external.gmpy import SYMPY_INTS, HAS_GMPY, gmpy
- from sympy.multipledispatch import dispatch
- import mpmath
- import mpmath.libmp as mlib
- from mpmath.libmp import bitcount, round_nearest as rnd
- from mpmath.libmp.backend import MPZ
- from mpmath.libmp import mpf_pow, mpf_pi, mpf_e, phi_fixed
- from mpmath.ctx_mp import mpnumeric
- from mpmath.libmp.libmpf import (
- finf as _mpf_inf, fninf as _mpf_ninf,
- fnan as _mpf_nan, fzero, _normalize as mpf_normalize,
- prec_to_dps, dps_to_prec)
- from sympy.utilities.misc import as_int, debug, filldedent
- from .parameters import global_parameters
- _LOG2 = math.log(2)
- def comp(z1, z2, tol=None):
- r"""Return a bool indicating whether the error between z1 and z2
- is $\le$ ``tol``.
- Examples
- ========
- If ``tol`` is ``None`` then ``True`` will be returned if
- :math:`|z1 - z2|\times 10^p \le 5` where $p$ is minimum value of the
- decimal precision of each value.
- >>> from sympy import comp, pi
- >>> pi4 = pi.n(4); pi4
- 3.142
- >>> comp(_, 3.142)
- True
- >>> comp(pi4, 3.141)
- False
- >>> comp(pi4, 3.143)
- False
- A comparison of strings will be made
- if ``z1`` is a Number and ``z2`` is a string or ``tol`` is ''.
- >>> comp(pi4, 3.1415)
- True
- >>> comp(pi4, 3.1415, '')
- False
- When ``tol`` is provided and $z2$ is non-zero and
- :math:`|z1| > 1` the error is normalized by :math:`|z1|`:
- >>> abs(pi4 - 3.14)/pi4
- 0.000509791731426756
- >>> comp(pi4, 3.14, .001) # difference less than 0.1%
- True
- >>> comp(pi4, 3.14, .0005) # difference less than 0.1%
- False
- When :math:`|z1| \le 1` the absolute error is used:
- >>> 1/pi4
- 0.3183
- >>> abs(1/pi4 - 0.3183)/(1/pi4)
- 3.07371499106316e-5
- >>> abs(1/pi4 - 0.3183)
- 9.78393554684764e-6
- >>> comp(1/pi4, 0.3183, 1e-5)
- True
- To see if the absolute error between ``z1`` and ``z2`` is less
- than or equal to ``tol``, call this as ``comp(z1 - z2, 0, tol)``
- or ``comp(z1 - z2, tol=tol)``:
- >>> abs(pi4 - 3.14)
- 0.00160156249999988
- >>> comp(pi4 - 3.14, 0, .002)
- True
- >>> comp(pi4 - 3.14, 0, .001)
- False
- """
- if isinstance(z2, str):
- if not pure_complex(z1, or_real=True):
- raise ValueError('when z2 is a str z1 must be a Number')
- return str(z1) == z2
- if not z1:
- z1, z2 = z2, z1
- if not z1:
- return True
- if not tol:
- a, b = z1, z2
- if tol == '':
- return str(a) == str(b)
- if tol is None:
- a, b = sympify(a), sympify(b)
- if not all(i.is_number for i in (a, b)):
- raise ValueError('expecting 2 numbers')
- fa = a.atoms(Float)
- fb = b.atoms(Float)
- if not fa and not fb:
- # no floats -- compare exactly
- return a == b
- # get a to be pure_complex
- for _ in range(2):
- ca = pure_complex(a, or_real=True)
- if not ca:
- if fa:
- a = a.n(prec_to_dps(min([i._prec for i in fa])))
- ca = pure_complex(a, or_real=True)
- break
- else:
- fa, fb = fb, fa
- a, b = b, a
- cb = pure_complex(b)
- if not cb and fb:
- b = b.n(prec_to_dps(min([i._prec for i in fb])))
- cb = pure_complex(b, or_real=True)
- if ca and cb and (ca[1] or cb[1]):
- return all(comp(i, j) for i, j in zip(ca, cb))
- tol = 10**prec_to_dps(min(a._prec, getattr(b, '_prec', a._prec)))
- return int(abs(a - b)*tol) <= 5
- diff = abs(z1 - z2)
- az1 = abs(z1)
- if z2 and az1 > 1:
- return diff/az1 <= tol
- else:
- return diff <= tol
- def mpf_norm(mpf, prec):
- """Return the mpf tuple normalized appropriately for the indicated
- precision after doing a check to see if zero should be returned or
- not when the mantissa is 0. ``mpf_normlize`` always assumes that this
- is zero, but it may not be since the mantissa for mpf's values "+inf",
- "-inf" and "nan" have a mantissa of zero, too.
- Note: this is not intended to validate a given mpf tuple, so sending
- mpf tuples that were not created by mpmath may produce bad results. This
- is only a wrapper to ``mpf_normalize`` which provides the check for non-
- zero mpfs that have a 0 for the mantissa.
- """
- sign, man, expt, bc = mpf
- if not man:
- # hack for mpf_normalize which does not do this;
- # it assumes that if man is zero the result is 0
- # (see issue 6639)
- if not bc:
- return fzero
- else:
- # don't change anything; this should already
- # be a well formed mpf tuple
- return mpf
- # Necessary if mpmath is using the gmpy backend
- from mpmath.libmp.backend import MPZ
- rv = mpf_normalize(sign, MPZ(man), expt, bc, prec, rnd)
- return rv
- # TODO: we should use the warnings module
- _errdict = {"divide": False}
- def seterr(divide=False):
- """
- Should SymPy raise an exception on 0/0 or return a nan?
- divide == True .... raise an exception
- divide == False ... return nan
- """
- if _errdict["divide"] != divide:
- clear_cache()
- _errdict["divide"] = divide
- def _as_integer_ratio(p):
- neg_pow, man, expt, _ = getattr(p, '_mpf_', mpmath.mpf(p)._mpf_)
- p = [1, -1][neg_pow % 2]*man
- if expt < 0:
- q = 2**-expt
- else:
- q = 1
- p *= 2**expt
- return int(p), int(q)
- def _decimal_to_Rational_prec(dec):
- """Convert an ordinary decimal instance to a Rational."""
- if not dec.is_finite():
- raise TypeError("dec must be finite, got %s." % dec)
- s, d, e = dec.as_tuple()
- prec = len(d)
- if e >= 0: # it's an integer
- rv = Integer(int(dec))
- else:
- s = (-1)**s
- d = sum([di*10**i for i, di in enumerate(reversed(d))])
- rv = Rational(s*d, 10**-e)
- return rv, prec
- _floatpat = regex.compile(r"[-+]?((\d*\.\d+)|(\d+\.?))")
- def _literal_float(f):
- """Return True if n starts like a floating point number."""
- return bool(_floatpat.match(f))
- # (a,b) -> gcd(a,b)
- # TODO caching with decorator, but not to degrade performance
- @lru_cache(1024)
- def igcd(*args):
- """Computes nonnegative integer greatest common divisor.
- Explanation
- ===========
- The algorithm is based on the well known Euclid's algorithm [1]_. To
- improve speed, ``igcd()`` has its own caching mechanism.
- Examples
- ========
- >>> from sympy import igcd
- >>> igcd(2, 4)
- 2
- >>> igcd(5, 10, 15)
- 5
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/Euclidean_algorithm
- """
- if len(args) < 2:
- raise TypeError(
- 'igcd() takes at least 2 arguments (%s given)' % len(args))
- args_temp = [abs(as_int(i)) for i in args]
- if 1 in args_temp:
- return 1
- a = args_temp.pop()
- if HAS_GMPY: # Using gmpy if present to speed up.
- for b in args_temp:
- a = gmpy.gcd(a, b) if b else a
- return as_int(a)
- for b in args_temp:
- a = math.gcd(a, b)
- return a
- igcd2 = math.gcd
- def igcd_lehmer(a, b):
- r"""Computes greatest common divisor of two integers.
- Explanation
- ===========
- Euclid's algorithm for the computation of the greatest
- common divisor ``gcd(a, b)`` of two (positive) integers
- $a$ and $b$ is based on the division identity
- $$ a = q \times b + r$$,
- where the quotient $q$ and the remainder $r$ are integers
- and $0 \le r < b$. Then each common divisor of $a$ and $b$
- divides $r$, and it follows that ``gcd(a, b) == gcd(b, r)``.
- The algorithm works by constructing the sequence
- r0, r1, r2, ..., where r0 = a, r1 = b, and each rn
- is the remainder from the division of the two preceding
- elements.
- In Python, ``q = a // b`` and ``r = a % b`` are obtained by the
- floor division and the remainder operations, respectively.
- These are the most expensive arithmetic operations, especially
- for large a and b.
- Lehmer's algorithm [1]_ is based on the observation that the quotients
- ``qn = r(n-1) // rn`` are in general small integers even
- when a and b are very large. Hence the quotients can be
- usually determined from a relatively small number of most
- significant bits.
- The efficiency of the algorithm is further enhanced by not
- computing each long remainder in Euclid's sequence. The remainders
- are linear combinations of a and b with integer coefficients
- derived from the quotients. The coefficients can be computed
- as far as the quotients can be determined from the chosen
- most significant parts of a and b. Only then a new pair of
- consecutive remainders is computed and the algorithm starts
- anew with this pair.
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/Lehmer%27s_GCD_algorithm
- """
- a, b = abs(as_int(a)), abs(as_int(b))
- if a < b:
- a, b = b, a
- # The algorithm works by using one or two digit division
- # whenever possible. The outer loop will replace the
- # pair (a, b) with a pair of shorter consecutive elements
- # of the Euclidean gcd sequence until a and b
- # fit into two Python (long) int digits.
- nbits = 2*sys.int_info.bits_per_digit
- while a.bit_length() > nbits and b != 0:
- # Quotients are mostly small integers that can
- # be determined from most significant bits.
- n = a.bit_length() - nbits
- x, y = int(a >> n), int(b >> n) # most significant bits
- # Elements of the Euclidean gcd sequence are linear
- # combinations of a and b with integer coefficients.
- # Compute the coefficients of consecutive pairs
- # a' = A*a + B*b, b' = C*a + D*b
- # using small integer arithmetic as far as possible.
- A, B, C, D = 1, 0, 0, 1 # initial values
- while True:
- # The coefficients alternate in sign while looping.
- # The inner loop combines two steps to keep track
- # of the signs.
- # At this point we have
- # A > 0, B <= 0, C <= 0, D > 0,
- # x' = x + B <= x < x" = x + A,
- # y' = y + C <= y < y" = y + D,
- # and
- # x'*N <= a' < x"*N, y'*N <= b' < y"*N,
- # where N = 2**n.
- # Now, if y' > 0, and x"//y' and x'//y" agree,
- # then their common value is equal to q = a'//b'.
- # In addition,
- # x'%y" = x' - q*y" < x" - q*y' = x"%y',
- # and
- # (x'%y")*N < a'%b' < (x"%y')*N.
- # On the other hand, we also have x//y == q,
- # and therefore
- # x'%y" = x + B - q*(y + D) = x%y + B',
- # x"%y' = x + A - q*(y + C) = x%y + A',
- # where
- # B' = B - q*D < 0, A' = A - q*C > 0.
- if y + C <= 0:
- break
- q = (x + A) // (y + C)
- # Now x'//y" <= q, and equality holds if
- # x' - q*y" = (x - q*y) + (B - q*D) >= 0.
- # This is a minor optimization to avoid division.
- x_qy, B_qD = x - q*y, B - q*D
- if x_qy + B_qD < 0:
- break
- # Next step in the Euclidean sequence.
- x, y = y, x_qy
- A, B, C, D = C, D, A - q*C, B_qD
- # At this point the signs of the coefficients
- # change and their roles are interchanged.
- # A <= 0, B > 0, C > 0, D < 0,
- # x' = x + A <= x < x" = x + B,
- # y' = y + D < y < y" = y + C.
- if y + D <= 0:
- break
- q = (x + B) // (y + D)
- x_qy, A_qC = x - q*y, A - q*C
- if x_qy + A_qC < 0:
- break
- x, y = y, x_qy
- A, B, C, D = C, D, A_qC, B - q*D
- # Now the conditions on top of the loop
- # are again satisfied.
- # A > 0, B < 0, C < 0, D > 0.
- if B == 0:
- # This can only happen when y == 0 in the beginning
- # and the inner loop does nothing.
- # Long division is forced.
- a, b = b, a % b
- continue
- # Compute new long arguments using the coefficients.
- a, b = A*a + B*b, C*a + D*b
- # Small divisors. Finish with the standard algorithm.
- while b:
- a, b = b, a % b
- return a
- def ilcm(*args):
- """Computes integer least common multiple.
- Examples
- ========
- >>> from sympy import ilcm
- >>> ilcm(5, 10)
- 10
- >>> ilcm(7, 3)
- 21
- >>> ilcm(5, 10, 15)
- 30
- """
- if len(args) < 2:
- raise TypeError(
- 'ilcm() takes at least 2 arguments (%s given)' % len(args))
- if 0 in args:
- return 0
- a = args[0]
- for b in args[1:]:
- a = a // igcd(a, b) * b # since gcd(a,b) | a
- return a
- def igcdex(a, b):
- """Returns x, y, g such that g = x*a + y*b = gcd(a, b).
- Examples
- ========
- >>> from sympy.core.numbers import igcdex
- >>> igcdex(2, 3)
- (-1, 1, 1)
- >>> igcdex(10, 12)
- (-1, 1, 2)
- >>> x, y, g = igcdex(100, 2004)
- >>> x, y, g
- (-20, 1, 4)
- >>> x*100 + y*2004
- 4
- """
- if (not a) and (not b):
- return (0, 1, 0)
- if not a:
- return (0, b//abs(b), abs(b))
- if not b:
- return (a//abs(a), 0, abs(a))
- if a < 0:
- a, x_sign = -a, -1
- else:
- x_sign = 1
- if b < 0:
- b, y_sign = -b, -1
- else:
- y_sign = 1
- x, y, r, s = 1, 0, 0, 1
- while b:
- (c, q) = (a % b, a // b)
- (a, b, r, s, x, y) = (b, c, x - q*r, y - q*s, r, s)
- return (x*x_sign, y*y_sign, a)
- def mod_inverse(a, m):
- r"""
- Return the number $c$ such that, $a \times c = 1 \pmod{m}$
- where $c$ has the same sign as $m$. If no such value exists,
- a ValueError is raised.
- Examples
- ========
- >>> from sympy import mod_inverse, S
- Suppose we wish to find multiplicative inverse $x$ of
- 3 modulo 11. This is the same as finding $x$ such
- that $3x = 1 \pmod{11}$. One value of x that satisfies
- this congruence is 4. Because $3 \times 4 = 12$ and $12 = 1 \pmod{11}$.
- This is the value returned by ``mod_inverse``:
- >>> mod_inverse(3, 11)
- 4
- >>> mod_inverse(-3, 11)
- 7
- When there is a common factor between the numerators of
- `a` and `m` the inverse does not exist:
- >>> mod_inverse(2, 4)
- Traceback (most recent call last):
- ...
- ValueError: inverse of 2 mod 4 does not exist
- >>> mod_inverse(S(2)/7, S(5)/2)
- 7/2
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/Modular_multiplicative_inverse
- .. [2] https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
- """
- c = None
- try:
- a, m = as_int(a), as_int(m)
- if m != 1 and m != -1:
- x, _, g = igcdex(a, m)
- if g == 1:
- c = x % m
- except ValueError:
- a, m = sympify(a), sympify(m)
- if not (a.is_number and m.is_number):
- raise TypeError(filldedent('''
- Expected numbers for arguments; symbolic `mod_inverse`
- is not implemented
- but symbolic expressions can be handled with the
- similar function,
- sympy.polys.polytools.invert'''))
- big = (m > 1)
- if big not in (S.true, S.false):
- raise ValueError('m > 1 did not evaluate; try to simplify %s' % m)
- elif big:
- c = 1/a
- if c is None:
- raise ValueError('inverse of %s (mod %s) does not exist' % (a, m))
- return c
- class Number(AtomicExpr):
- """Represents atomic numbers in SymPy.
- Explanation
- ===========
- Floating point numbers are represented by the Float class.
- Rational numbers (of any size) are represented by the Rational class.
- Integer numbers (of any size) are represented by the Integer class.
- Float and Rational are subclasses of Number; Integer is a subclass
- of Rational.
- For example, ``2/3`` is represented as ``Rational(2, 3)`` which is
- a different object from the floating point number obtained with
- Python division ``2/3``. Even for numbers that are exactly
- represented in binary, there is a difference between how two forms,
- such as ``Rational(1, 2)`` and ``Float(0.5)``, are used in SymPy.
- The rational form is to be preferred in symbolic computations.
- Other kinds of numbers, such as algebraic numbers ``sqrt(2)`` or
- complex numbers ``3 + 4*I``, are not instances of Number class as
- they are not atomic.
- See Also
- ========
- Float, Integer, Rational
- """
- is_commutative = True
- is_number = True
- is_Number = True
- __slots__ = ()
- # Used to make max(x._prec, y._prec) return x._prec when only x is a float
- _prec = -1
- kind = NumberKind
- def __new__(cls, *obj):
- if len(obj) == 1:
- obj = obj[0]
- if isinstance(obj, Number):
- return obj
- if isinstance(obj, SYMPY_INTS):
- return Integer(obj)
- if isinstance(obj, tuple) and len(obj) == 2:
- return Rational(*obj)
- if isinstance(obj, (float, mpmath.mpf, decimal.Decimal)):
- return Float(obj)
- if isinstance(obj, str):
- _obj = obj.lower() # float('INF') == float('inf')
- if _obj == 'nan':
- return S.NaN
- elif _obj == 'inf':
- return S.Infinity
- elif _obj == '+inf':
- return S.Infinity
- elif _obj == '-inf':
- return S.NegativeInfinity
- val = sympify(obj)
- if isinstance(val, Number):
- return val
- else:
- raise ValueError('String "%s" does not denote a Number' % obj)
- msg = "expected str|int|long|float|Decimal|Number object but got %r"
- raise TypeError(msg % type(obj).__name__)
- def could_extract_minus_sign(self):
- return bool(self.is_extended_negative)
- def invert(self, other, *gens, **args):
- from sympy.polys.polytools import invert
- if getattr(other, 'is_number', True):
- return mod_inverse(self, other)
- return invert(self, other, *gens, **args)
- def __divmod__(self, other):
- from sympy.functions.elementary.complexes import sign
- try:
- other = Number(other)
- if self.is_infinite or S.NaN in (self, other):
- return (S.NaN, S.NaN)
- except TypeError:
- return NotImplemented
- if not other:
- raise ZeroDivisionError('modulo by zero')
- if self.is_Integer and other.is_Integer:
- return Tuple(*divmod(self.p, other.p))
- elif isinstance(other, Float):
- rat = self/Rational(other)
- else:
- rat = self/other
- if other.is_finite:
- w = int(rat) if rat >= 0 else int(rat) - 1
- r = self - other*w
- else:
- w = 0 if not self or (sign(self) == sign(other)) else -1
- r = other if w else self
- return Tuple(w, r)
- def __rdivmod__(self, other):
- try:
- other = Number(other)
- except TypeError:
- return NotImplemented
- return divmod(other, self)
- def _as_mpf_val(self, prec):
- """Evaluation of mpf tuple accurate to at least prec bits."""
- raise NotImplementedError('%s needs ._as_mpf_val() method' %
- (self.__class__.__name__))
- def _eval_evalf(self, prec):
- return Float._new(self._as_mpf_val(prec), prec)
- def _as_mpf_op(self, prec):
- prec = max(prec, self._prec)
- return self._as_mpf_val(prec), prec
- def __float__(self):
- return mlib.to_float(self._as_mpf_val(53))
- def floor(self):
- raise NotImplementedError('%s needs .floor() method' %
- (self.__class__.__name__))
- def ceiling(self):
- raise NotImplementedError('%s needs .ceiling() method' %
- (self.__class__.__name__))
- def __floor__(self):
- return self.floor()
- def __ceil__(self):
- return self.ceiling()
- def _eval_conjugate(self):
- return self
- def _eval_order(self, *symbols):
- from sympy.series.order import Order
- # Order(5, x, y) -> Order(1,x,y)
- return Order(S.One, *symbols)
- def _eval_subs(self, old, new):
- if old == -self:
- return -new
- return self # there is no other possibility
- @classmethod
- def class_key(cls):
- return 1, 0, 'Number'
- @cacheit
- def sort_key(self, order=None):
- return self.class_key(), (0, ()), (), self
- @_sympifyit('other', NotImplemented)
- def __add__(self, other):
- if isinstance(other, Number) and global_parameters.evaluate:
- if other is S.NaN:
- return S.NaN
- elif other is S.Infinity:
- return S.Infinity
- elif other is S.NegativeInfinity:
- return S.NegativeInfinity
- return AtomicExpr.__add__(self, other)
- @_sympifyit('other', NotImplemented)
- def __sub__(self, other):
- if isinstance(other, Number) and global_parameters.evaluate:
- if other is S.NaN:
- return S.NaN
- elif other is S.Infinity:
- return S.NegativeInfinity
- elif other is S.NegativeInfinity:
- return S.Infinity
- return AtomicExpr.__sub__(self, other)
- @_sympifyit('other', NotImplemented)
- def __mul__(self, other):
- if isinstance(other, Number) and global_parameters.evaluate:
- if other is S.NaN:
- return S.NaN
- elif other is S.Infinity:
- if self.is_zero:
- return S.NaN
- elif self.is_positive:
- return S.Infinity
- else:
- return S.NegativeInfinity
- elif other is S.NegativeInfinity:
- if self.is_zero:
- return S.NaN
- elif self.is_positive:
- return S.NegativeInfinity
- else:
- return S.Infinity
- elif isinstance(other, Tuple):
- return NotImplemented
- return AtomicExpr.__mul__(self, other)
- @_sympifyit('other', NotImplemented)
- def __truediv__(self, other):
- if isinstance(other, Number) and global_parameters.evaluate:
- if other is S.NaN:
- return S.NaN
- elif other in (S.Infinity, S.NegativeInfinity):
- return S.Zero
- return AtomicExpr.__truediv__(self, other)
- def __eq__(self, other):
- raise NotImplementedError('%s needs .__eq__() method' %
- (self.__class__.__name__))
- def __ne__(self, other):
- raise NotImplementedError('%s needs .__ne__() method' %
- (self.__class__.__name__))
- def __lt__(self, other):
- try:
- other = _sympify(other)
- except SympifyError:
- raise TypeError("Invalid comparison %s < %s" % (self, other))
- raise NotImplementedError('%s needs .__lt__() method' %
- (self.__class__.__name__))
- def __le__(self, other):
- try:
- other = _sympify(other)
- except SympifyError:
- raise TypeError("Invalid comparison %s <= %s" % (self, other))
- raise NotImplementedError('%s needs .__le__() method' %
- (self.__class__.__name__))
- def __gt__(self, other):
- try:
- other = _sympify(other)
- except SympifyError:
- raise TypeError("Invalid comparison %s > %s" % (self, other))
- return _sympify(other).__lt__(self)
- def __ge__(self, other):
- try:
- other = _sympify(other)
- except SympifyError:
- raise TypeError("Invalid comparison %s >= %s" % (self, other))
- return _sympify(other).__le__(self)
- def __hash__(self):
- return super().__hash__()
- def is_constant(self, *wrt, **flags):
- return True
- def as_coeff_mul(self, *deps, rational=True, **kwargs):
- # a -> c*t
- if self.is_Rational or not rational:
- return self, ()
- elif self.is_negative:
- return S.NegativeOne, (-self,)
- return S.One, (self,)
- def as_coeff_add(self, *deps):
- # a -> c + t
- if self.is_Rational:
- return self, ()
- return S.Zero, (self,)
- def as_coeff_Mul(self, rational=False):
- """Efficiently extract the coefficient of a product."""
- if rational and not self.is_Rational:
- return S.One, self
- return (self, S.One) if self else (S.One, self)
- def as_coeff_Add(self, rational=False):
- """Efficiently extract the coefficient of a summation."""
- if not rational:
- return self, S.Zero
- return S.Zero, self
- def gcd(self, other):
- """Compute GCD of `self` and `other`. """
- from sympy.polys.polytools import gcd
- return gcd(self, other)
- def lcm(self, other):
- """Compute LCM of `self` and `other`. """
- from sympy.polys.polytools import lcm
- return lcm(self, other)
- def cofactors(self, other):
- """Compute GCD and cofactors of `self` and `other`. """
- from sympy.polys.polytools import cofactors
- return cofactors(self, other)
- class Float(Number):
- """Represent a floating-point number of arbitrary precision.
- Examples
- ========
- >>> from sympy import Float
- >>> Float(3.5)
- 3.50000000000000
- >>> Float(3)
- 3.00000000000000
- Creating Floats from strings (and Python ``int`` and ``long``
- types) will give a minimum precision of 15 digits, but the
- precision will automatically increase to capture all digits
- entered.
- >>> Float(1)
- 1.00000000000000
- >>> Float(10**20)
- 100000000000000000000.
- >>> Float('1e20')
- 100000000000000000000.
- However, *floating-point* numbers (Python ``float`` types) retain
- only 15 digits of precision:
- >>> Float(1e20)
- 1.00000000000000e+20
- >>> Float(1.23456789123456789)
- 1.23456789123457
- It may be preferable to enter high-precision decimal numbers
- as strings:
- >>> Float('1.23456789123456789')
- 1.23456789123456789
- The desired number of digits can also be specified:
- >>> Float('1e-3', 3)
- 0.00100
- >>> Float(100, 4)
- 100.0
- Float can automatically count significant figures if a null string
- is sent for the precision; spaces or underscores are also allowed. (Auto-
- counting is only allowed for strings, ints and longs).
- >>> Float('123 456 789.123_456', '')
- 123456789.123456
- >>> Float('12e-3', '')
- 0.012
- >>> Float(3, '')
- 3.
- If a number is written in scientific notation, only the digits before the
- exponent are considered significant if a decimal appears, otherwise the
- "e" signifies only how to move the decimal:
- >>> Float('60.e2', '') # 2 digits significant
- 6.0e+3
- >>> Float('60e2', '') # 4 digits significant
- 6000.
- >>> Float('600e-2', '') # 3 digits significant
- 6.00
- Notes
- =====
- Floats are inexact by their nature unless their value is a binary-exact
- value.
- >>> approx, exact = Float(.1, 1), Float(.125, 1)
- For calculation purposes, evalf needs to be able to change the precision
- but this will not increase the accuracy of the inexact value. The
- following is the most accurate 5-digit approximation of a value of 0.1
- that had only 1 digit of precision:
- >>> approx.evalf(5)
- 0.099609
- By contrast, 0.125 is exact in binary (as it is in base 10) and so it
- can be passed to Float or evalf to obtain an arbitrary precision with
- matching accuracy:
- >>> Float(exact, 5)
- 0.12500
- >>> exact.evalf(20)
- 0.12500000000000000000
- Trying to make a high-precision Float from a float is not disallowed,
- but one must keep in mind that the *underlying float* (not the apparent
- decimal value) is being obtained with high precision. For example, 0.3
- does not have a finite binary representation. The closest rational is
- the fraction 5404319552844595/2**54. So if you try to obtain a Float of
- 0.3 to 20 digits of precision you will not see the same thing as 0.3
- followed by 19 zeros:
- >>> Float(0.3, 20)
- 0.29999999999999998890
- If you want a 20-digit value of the decimal 0.3 (not the floating point
- approximation of 0.3) you should send the 0.3 as a string. The underlying
- representation is still binary but a higher precision than Python's float
- is used:
- >>> Float('0.3', 20)
- 0.30000000000000000000
- Although you can increase the precision of an existing Float using Float
- it will not increase the accuracy -- the underlying value is not changed:
- >>> def show(f): # binary rep of Float
- ... from sympy import Mul, Pow
- ... s, m, e, b = f._mpf_
- ... v = Mul(int(m), Pow(2, int(e), evaluate=False), evaluate=False)
- ... print('%s at prec=%s' % (v, f._prec))
- ...
- >>> t = Float('0.3', 3)
- >>> show(t)
- 4915/2**14 at prec=13
- >>> show(Float(t, 20)) # higher prec, not higher accuracy
- 4915/2**14 at prec=70
- >>> show(Float(t, 2)) # lower prec
- 307/2**10 at prec=10
- The same thing happens when evalf is used on a Float:
- >>> show(t.evalf(20))
- 4915/2**14 at prec=70
- >>> show(t.evalf(2))
- 307/2**10 at prec=10
- Finally, Floats can be instantiated with an mpf tuple (n, c, p) to
- produce the number (-1)**n*c*2**p:
- >>> n, c, p = 1, 5, 0
- >>> (-1)**n*c*2**p
- -5
- >>> Float((1, 5, 0))
- -5.00000000000000
- An actual mpf tuple also contains the number of bits in c as the last
- element of the tuple:
- >>> _._mpf_
- (1, 5, 0, 3)
- This is not needed for instantiation and is not the same thing as the
- precision. The mpf tuple and the precision are two separate quantities
- that Float tracks.
- In SymPy, a Float is a number that can be computed with arbitrary
- precision. Although floating point 'inf' and 'nan' are not such
- numbers, Float can create these numbers:
- >>> Float('-inf')
- -oo
- >>> _.is_Float
- False
- Zero in Float only has a single value. Values are not separate for
- positive and negative zeroes.
- """
- __slots__ = ('_mpf_', '_prec')
- _mpf_: tuple[int, int, int, int]
- # A Float represents many real numbers,
- # both rational and irrational.
- is_rational = None
- is_irrational = None
- is_number = True
- is_real = True
- is_extended_real = True
- is_Float = True
- def __new__(cls, num, dps=None, precision=None):
- if dps is not None and precision is not None:
- raise ValueError('Both decimal and binary precision supplied. '
- 'Supply only one. ')
- if isinstance(num, str):
- # Float accepts spaces as digit separators
- num = num.replace(' ', '').lower()
- if num.startswith('.') and len(num) > 1:
- num = '0' + num
- elif num.startswith('-.') and len(num) > 2:
- num = '-0.' + num[2:]
- elif num in ('inf', '+inf'):
- return S.Infinity
- elif num == '-inf':
- return S.NegativeInfinity
- elif isinstance(num, float) and num == 0:
- num = '0'
- elif isinstance(num, float) and num == float('inf'):
- return S.Infinity
- elif isinstance(num, float) and num == float('-inf'):
- return S.NegativeInfinity
- elif isinstance(num, float) and math.isnan(num):
- return S.NaN
- elif isinstance(num, (SYMPY_INTS, Integer)):
- num = str(num)
- elif num is S.Infinity:
- return num
- elif num is S.NegativeInfinity:
- return num
- elif num is S.NaN:
- return num
- elif _is_numpy_instance(num): # support for numpy datatypes
- num = _convert_numpy_types(num)
- elif isinstance(num, mpmath.mpf):
- if precision is None:
- if dps is None:
- precision = num.context.prec
- num = num._mpf_
- if dps is None and precision is None:
- dps = 15
- if isinstance(num, Float):
- return num
- if isinstance(num, str) and _literal_float(num):
- try:
- Num = decimal.Decimal(num)
- except decimal.InvalidOperation:
- pass
- else:
- isint = '.' not in num
- num, dps = _decimal_to_Rational_prec(Num)
- if num.is_Integer and isint:
- dps = max(dps, len(str(num).lstrip('-')))
- dps = max(15, dps)
- precision = dps_to_prec(dps)
- elif precision == '' and dps is None or precision is None and dps == '':
- if not isinstance(num, str):
- raise ValueError('The null string can only be used when '
- 'the number to Float is passed as a string or an integer.')
- ok = None
- if _literal_float(num):
- try:
- Num = decimal.Decimal(num)
- except decimal.InvalidOperation:
- pass
- else:
- isint = '.' not in num
- num, dps = _decimal_to_Rational_prec(Num)
- if num.is_Integer and isint:
- dps = max(dps, len(str(num).lstrip('-')))
- precision = dps_to_prec(dps)
- ok = True
- if ok is None:
- raise ValueError('string-float not recognized: %s' % num)
- # decimal precision(dps) is set and maybe binary precision(precision)
- # as well.From here on binary precision is used to compute the Float.
- # Hence, if supplied use binary precision else translate from decimal
- # precision.
- if precision is None or precision == '':
- precision = dps_to_prec(dps)
- precision = int(precision)
- if isinstance(num, float):
- _mpf_ = mlib.from_float(num, precision, rnd)
- elif isinstance(num, str):
- _mpf_ = mlib.from_str(num, precision, rnd)
- elif isinstance(num, decimal.Decimal):
- if num.is_finite():
- _mpf_ = mlib.from_str(str(num), precision, rnd)
- elif num.is_nan():
- return S.NaN
- elif num.is_infinite():
- if num > 0:
- return S.Infinity
- return S.NegativeInfinity
- else:
- raise ValueError("unexpected decimal value %s" % str(num))
- elif isinstance(num, tuple) and len(num) in (3, 4):
- if isinstance(num[1], str):
- # it's a hexadecimal (coming from a pickled object)
- num = list(num)
- # If we're loading an object pickled in Python 2 into
- # Python 3, we may need to strip a tailing 'L' because
- # of a shim for int on Python 3, see issue #13470.
- if num[1].endswith('L'):
- num[1] = num[1][:-1]
- # Strip leading '0x' - gmpy2 only documents such inputs
- # with base prefix as valid when the 2nd argument (base) is 0.
- # When mpmath uses Sage as the backend, however, it
- # ends up including '0x' when preparing the picklable tuple.
- # See issue #19690.
- if num[1].startswith('0x'):
- num[1] = num[1][2:]
- # Now we can assume that it is in standard form
- num[1] = MPZ(num[1], 16)
- _mpf_ = tuple(num)
- else:
- if len(num) == 4:
- # handle normalization hack
- return Float._new(num, precision)
- else:
- if not all((
- num[0] in (0, 1),
- num[1] >= 0,
- all(type(i) in (int, int) for i in num)
- )):
- raise ValueError('malformed mpf: %s' % (num,))
- # don't compute number or else it may
- # over/underflow
- return Float._new(
- (num[0], num[1], num[2], bitcount(num[1])),
- precision)
- else:
- try:
- _mpf_ = num._as_mpf_val(precision)
- except (NotImplementedError, AttributeError):
- _mpf_ = mpmath.mpf(num, prec=precision)._mpf_
- return cls._new(_mpf_, precision, zero=False)
- @classmethod
- def _new(cls, _mpf_, _prec, zero=True):
- # special cases
- if zero and _mpf_ == fzero:
- return S.Zero # Float(0) -> 0.0; Float._new((0,0,0,0)) -> 0
- elif _mpf_ == _mpf_nan:
- return S.NaN
- elif _mpf_ == _mpf_inf:
- return S.Infinity
- elif _mpf_ == _mpf_ninf:
- return S.NegativeInfinity
- obj = Expr.__new__(cls)
- obj._mpf_ = mpf_norm(_mpf_, _prec)
- obj._prec = _prec
- return obj
- # mpz can't be pickled
- def __getnewargs_ex__(self):
- return ((mlib.to_pickable(self._mpf_),), {'precision': self._prec})
- def _hashable_content(self):
- return (self._mpf_, self._prec)
- def floor(self):
- return Integer(int(mlib.to_int(
- mlib.mpf_floor(self._mpf_, self._prec))))
- def ceiling(self):
- return Integer(int(mlib.to_int(
- mlib.mpf_ceil(self._mpf_, self._prec))))
- def __floor__(self):
- return self.floor()
- def __ceil__(self):
- return self.ceiling()
- @property
- def num(self):
- return mpmath.mpf(self._mpf_)
- def _as_mpf_val(self, prec):
- rv = mpf_norm(self._mpf_, prec)
- if rv != self._mpf_ and self._prec == prec:
- debug(self._mpf_, rv)
- return rv
- def _as_mpf_op(self, prec):
- return self._mpf_, max(prec, self._prec)
- def _eval_is_finite(self):
- if self._mpf_ in (_mpf_inf, _mpf_ninf):
- return False
- return True
- def _eval_is_infinite(self):
- if self._mpf_ in (_mpf_inf, _mpf_ninf):
- return True
- return False
- def _eval_is_integer(self):
- return self._mpf_ == fzero
- def _eval_is_negative(self):
- if self._mpf_ in (_mpf_ninf, _mpf_inf):
- return False
- return self.num < 0
- def _eval_is_positive(self):
- if self._mpf_ in (_mpf_ninf, _mpf_inf):
- return False
- return self.num > 0
- def _eval_is_extended_negative(self):
- if self._mpf_ == _mpf_ninf:
- return True
- if self._mpf_ == _mpf_inf:
- return False
- return self.num < 0
- def _eval_is_extended_positive(self):
- if self._mpf_ == _mpf_inf:
- return True
- if self._mpf_ == _mpf_ninf:
- return False
- return self.num > 0
- def _eval_is_zero(self):
- return self._mpf_ == fzero
- def __bool__(self):
- return self._mpf_ != fzero
- def __neg__(self):
- if not self:
- return self
- return Float._new(mlib.mpf_neg(self._mpf_), self._prec)
- @_sympifyit('other', NotImplemented)
- def __add__(self, other):
- if isinstance(other, Number) and global_parameters.evaluate:
- rhs, prec = other._as_mpf_op(self._prec)
- return Float._new(mlib.mpf_add(self._mpf_, rhs, prec, rnd), prec)
- return Number.__add__(self, other)
- @_sympifyit('other', NotImplemented)
- def __sub__(self, other):
- if isinstance(other, Number) and global_parameters.evaluate:
- rhs, prec = other._as_mpf_op(self._prec)
- return Float._new(mlib.mpf_sub(self._mpf_, rhs, prec, rnd), prec)
- return Number.__sub__(self, other)
- @_sympifyit('other', NotImplemented)
- def __mul__(self, other):
- if isinstance(other, Number) and global_parameters.evaluate:
- rhs, prec = other._as_mpf_op(self._prec)
- return Float._new(mlib.mpf_mul(self._mpf_, rhs, prec, rnd), prec)
- return Number.__mul__(self, other)
- @_sympifyit('other', NotImplemented)
- def __truediv__(self, other):
- if isinstance(other, Number) and other != 0 and global_parameters.evaluate:
- rhs, prec = other._as_mpf_op(self._prec)
- return Float._new(mlib.mpf_div(self._mpf_, rhs, prec, rnd), prec)
- return Number.__truediv__(self, other)
- @_sympifyit('other', NotImplemented)
- def __mod__(self, other):
- if isinstance(other, Rational) and other.q != 1 and global_parameters.evaluate:
- # calculate mod with Rationals, *then* round the result
- return Float(Rational.__mod__(Rational(self), other),
- precision=self._prec)
- if isinstance(other, Float) and global_parameters.evaluate:
- r = self/other
- if r == int(r):
- return Float(0, precision=max(self._prec, other._prec))
- if isinstance(other, Number) and global_parameters.evaluate:
- rhs, prec = other._as_mpf_op(self._prec)
- return Float._new(mlib.mpf_mod(self._mpf_, rhs, prec, rnd), prec)
- return Number.__mod__(self, other)
- @_sympifyit('other', NotImplemented)
- def __rmod__(self, other):
- if isinstance(other, Float) and global_parameters.evaluate:
- return other.__mod__(self)
- if isinstance(other, Number) and global_parameters.evaluate:
- rhs, prec = other._as_mpf_op(self._prec)
- return Float._new(mlib.mpf_mod(rhs, self._mpf_, prec, rnd), prec)
- return Number.__rmod__(self, other)
- def _eval_power(self, expt):
- """
- expt is symbolic object but not equal to 0, 1
- (-p)**r -> exp(r*log(-p)) -> exp(r*(log(p) + I*Pi)) ->
- -> p**r*(sin(Pi*r) + cos(Pi*r)*I)
- """
- if equal_valued(self, 0):
- if expt.is_extended_positive:
- return self
- if expt.is_extended_negative:
- return S.ComplexInfinity
- if isinstance(expt, Number):
- if isinstance(expt, Integer):
- prec = self._prec
- return Float._new(
- mlib.mpf_pow_int(self._mpf_, expt.p, prec, rnd), prec)
- elif isinstance(expt, Rational) and \
- expt.p == 1 and expt.q % 2 and self.is_negative:
- return Pow(S.NegativeOne, expt, evaluate=False)*(
- -self)._eval_power(expt)
- expt, prec = expt._as_mpf_op(self._prec)
- mpfself = self._mpf_
- try:
- y = mpf_pow(mpfself, expt, prec, rnd)
- return Float._new(y, prec)
- except mlib.ComplexResult:
- re, im = mlib.mpc_pow(
- (mpfself, fzero), (expt, fzero), prec, rnd)
- return Float._new(re, prec) + \
- Float._new(im, prec)*S.ImaginaryUnit
- def __abs__(self):
- return Float._new(mlib.mpf_abs(self._mpf_), self._prec)
- def __int__(self):
- if self._mpf_ == fzero:
- return 0
- return int(mlib.to_int(self._mpf_)) # uses round_fast = round_down
- def __eq__(self, other):
- from sympy.logic.boolalg import Boolean
- try:
- other = _sympify(other)
- except SympifyError:
- return NotImplemented
- if isinstance(other, Boolean):
- return False
- if other.is_NumberSymbol:
- if other.is_irrational:
- return False
- return other.__eq__(self)
- if other.is_Float:
- # comparison is exact
- # so Float(.1, 3) != Float(.1, 33)
- return self._mpf_ == other._mpf_
- if other.is_Rational:
- return other.__eq__(self)
- if other.is_Number:
- # numbers should compare at the same precision;
- # all _as_mpf_val routines should be sure to abide
- # by the request to change the prec if necessary; if
- # they don't, the equality test will fail since it compares
- # the mpf tuples
- ompf = other._as_mpf_val(self._prec)
- return bool(mlib.mpf_eq(self._mpf_, ompf))
- if not self:
- return not other
- return False # Float != non-Number
- def __ne__(self, other):
- return not self == other
- def _Frel(self, other, op):
- try:
- other = _sympify(other)
- except SympifyError:
- return NotImplemented
- if other.is_Rational:
- # test self*other.q <?> other.p without losing precision
- '''
- >>> f = Float(.1,2)
- >>> i = 1234567890
- >>> (f*i)._mpf_
- (0, 471, 18, 9)
- >>> mlib.mpf_mul(f._mpf_, mlib.from_int(i))
- (0, 505555550955, -12, 39)
- '''
- smpf = mlib.mpf_mul(self._mpf_, mlib.from_int(other.q))
- ompf = mlib.from_int(other.p)
- return _sympify(bool(op(smpf, ompf)))
- elif other.is_Float:
- return _sympify(bool(
- op(self._mpf_, other._mpf_)))
- elif other.is_comparable and other not in (
- S.Infinity, S.NegativeInfinity):
- other = other.evalf(prec_to_dps(self._prec))
- if other._prec > 1:
- if other.is_Number:
- return _sympify(bool(
- op(self._mpf_, other._as_mpf_val(self._prec))))
- def __gt__(self, other):
- if isinstance(other, NumberSymbol):
- return other.__lt__(self)
- rv = self._Frel(other, mlib.mpf_gt)
- if rv is None:
- return Expr.__gt__(self, other)
- return rv
- def __ge__(self, other):
- if isinstance(other, NumberSymbol):
- return other.__le__(self)
- rv = self._Frel(other, mlib.mpf_ge)
- if rv is None:
- return Expr.__ge__(self, other)
- return rv
- def __lt__(self, other):
- if isinstance(other, NumberSymbol):
- return other.__gt__(self)
- rv = self._Frel(other, mlib.mpf_lt)
- if rv is None:
- return Expr.__lt__(self, other)
- return rv
- def __le__(self, other):
- if isinstance(other, NumberSymbol):
- return other.__ge__(self)
- rv = self._Frel(other, mlib.mpf_le)
- if rv is None:
- return Expr.__le__(self, other)
- return rv
- def __hash__(self):
- return super().__hash__()
- def epsilon_eq(self, other, epsilon="1e-15"):
- return abs(self - other) < Float(epsilon)
- def __format__(self, format_spec):
- return format(decimal.Decimal(str(self)), format_spec)
- # Add sympify converters
- _sympy_converter[float] = _sympy_converter[decimal.Decimal] = Float
- # this is here to work nicely in Sage
- RealNumber = Float
- class Rational(Number):
- """Represents rational numbers (p/q) of any size.
- Examples
- ========
- >>> from sympy import Rational, nsimplify, S, pi
- >>> Rational(1, 2)
- 1/2
- Rational is unprejudiced in accepting input. If a float is passed, the
- underlying value of the binary representation will be returned:
- >>> Rational(.5)
- 1/2
- >>> Rational(.2)
- 3602879701896397/18014398509481984
- If the simpler representation of the float is desired then consider
- limiting the denominator to the desired value or convert the float to
- a string (which is roughly equivalent to limiting the denominator to
- 10**12):
- >>> Rational(str(.2))
- 1/5
- >>> Rational(.2).limit_denominator(10**12)
- 1/5
- An arbitrarily precise Rational is obtained when a string literal is
- passed:
- >>> Rational("1.23")
- 123/100
- >>> Rational('1e-2')
- 1/100
- >>> Rational(".1")
- 1/10
- >>> Rational('1e-2/3.2')
- 1/320
- The conversion of other types of strings can be handled by
- the sympify() function, and conversion of floats to expressions
- or simple fractions can be handled with nsimplify:
- >>> S('.[3]') # repeating digits in brackets
- 1/3
- >>> S('3**2/10') # general expressions
- 9/10
- >>> nsimplify(.3) # numbers that have a simple form
- 3/10
- But if the input does not reduce to a literal Rational, an error will
- be raised:
- >>> Rational(pi)
- Traceback (most recent call last):
- ...
- TypeError: invalid input: pi
- Low-level
- ---------
- Access numerator and denominator as .p and .q:
- >>> r = Rational(3, 4)
- >>> r
- 3/4
- >>> r.p
- 3
- >>> r.q
- 4
- Note that p and q return integers (not SymPy Integers) so some care
- is needed when using them in expressions:
- >>> r.p/r.q
- 0.75
- If an unevaluated Rational is desired, ``gcd=1`` can be passed and
- this will keep common divisors of the numerator and denominator
- from being eliminated. It is not possible, however, to leave a
- negative value in the denominator.
- >>> Rational(2, 4, gcd=1)
- 2/4
- >>> Rational(2, -4, gcd=1).q
- 4
- See Also
- ========
- sympy.core.sympify.sympify, sympy.simplify.simplify.nsimplify
- """
- is_real = True
- is_integer = False
- is_rational = True
- is_number = True
- __slots__ = ('p', 'q')
- p: int
- q: int
- is_Rational = True
- @cacheit
- def __new__(cls, p, q=None, gcd=None):
- if q is None:
- if isinstance(p, Rational):
- return p
- if isinstance(p, SYMPY_INTS):
- pass
- else:
- if isinstance(p, (float, Float)):
- return Rational(*_as_integer_ratio(p))
- if not isinstance(p, str):
- try:
- p = sympify(p)
- except (SympifyError, SyntaxError):
- pass # error will raise below
- else:
- if p.count('/') > 1:
- raise TypeError('invalid input: %s' % p)
- p = p.replace(' ', '')
- pq = p.rsplit('/', 1)
- if len(pq) == 2:
- p, q = pq
- fp = fractions.Fraction(p)
- fq = fractions.Fraction(q)
- p = fp/fq
- try:
- p = fractions.Fraction(p)
- except ValueError:
- pass # error will raise below
- else:
- return Rational(p.numerator, p.denominator, 1)
- if not isinstance(p, Rational):
- raise TypeError('invalid input: %s' % p)
- q = 1
- gcd = 1
- Q = 1
- if not isinstance(p, SYMPY_INTS):
- p = Rational(p)
- Q *= p.q
- p = p.p
- else:
- p = int(p)
- if not isinstance(q, SYMPY_INTS):
- q = Rational(q)
- p *= q.q
- Q *= q.p
- else:
- Q *= int(q)
- q = Q
- # p and q are now ints
- if q == 0:
- if p == 0:
- if _errdict["divide"]:
- raise ValueError("Indeterminate 0/0")
- else:
- return S.NaN
- return S.ComplexInfinity
- if q < 0:
- q = -q
- p = -p
- if not gcd:
- gcd = igcd(abs(p), q)
- if gcd > 1:
- p //= gcd
- q //= gcd
- if q == 1:
- return Integer(p)
- if p == 1 and q == 2:
- return S.Half
- obj = Expr.__new__(cls)
- obj.p = p
- obj.q = q
- return obj
- def limit_denominator(self, max_denominator=1000000):
- """Closest Rational to self with denominator at most max_denominator.
- Examples
- ========
- >>> from sympy import Rational
- >>> Rational('3.141592653589793').limit_denominator(10)
- 22/7
- >>> Rational('3.141592653589793').limit_denominator(100)
- 311/99
- """
- f = fractions.Fraction(self.p, self.q)
- return Rational(f.limit_denominator(fractions.Fraction(int(max_denominator))))
- def __getnewargs__(self):
- return (self.p, self.q)
- def _hashable_content(self):
- return (self.p, self.q)
- def _eval_is_positive(self):
- return self.p > 0
- def _eval_is_zero(self):
- return self.p == 0
- def __neg__(self):
- return Rational(-self.p, self.q)
- @_sympifyit('other', NotImplemented)
- def __add__(self, other):
- if global_parameters.evaluate:
- if isinstance(other, Integer):
- return Rational(self.p + self.q*other.p, self.q, 1)
- elif isinstance(other, Rational):
- #TODO: this can probably be optimized more
- return Rational(self.p*other.q + self.q*other.p, self.q*other.q)
- elif isinstance(other, Float):
- return other + self
- else:
- return Number.__add__(self, other)
- return Number.__add__(self, other)
- __radd__ = __add__
- @_sympifyit('other', NotImplemented)
- def __sub__(self, other):
- if global_parameters.evaluate:
- if isinstance(other, Integer):
- return Rational(self.p - self.q*other.p, self.q, 1)
- elif isinstance(other, Rational):
- return Rational(self.p*other.q - self.q*other.p, self.q*other.q)
- elif isinstance(other, Float):
- return -other + self
- else:
- return Number.__sub__(self, other)
- return Number.__sub__(self, other)
- @_sympifyit('other', NotImplemented)
- def __rsub__(self, other):
- if global_parameters.evaluate:
- if isinstance(other, Integer):
- return Rational(self.q*other.p - self.p, self.q, 1)
- elif isinstance(other, Rational):
- return Rational(self.q*other.p - self.p*other.q, self.q*other.q)
- elif isinstance(other, Float):
- return -self + other
- else:
- return Number.__rsub__(self, other)
- return Number.__rsub__(self, other)
- @_sympifyit('other', NotImplemented)
- def __mul__(self, other):
- if global_parameters.evaluate:
- if isinstance(other, Integer):
- return Rational(self.p*other.p, self.q, igcd(other.p, self.q))
- elif isinstance(other, Rational):
- return Rational(self.p*other.p, self.q*other.q, igcd(self.p, other.q)*igcd(self.q, other.p))
- elif isinstance(other, Float):
- return other*self
- else:
- return Number.__mul__(self, other)
- return Number.__mul__(self, other)
- __rmul__ = __mul__
- @_sympifyit('other', NotImplemented)
- def __truediv__(self, other):
- if global_parameters.evaluate:
- if isinstance(other, Integer):
- if self.p and other.p == S.Zero:
- return S.ComplexInfinity
- else:
- return Rational(self.p, self.q*other.p, igcd(self.p, other.p))
- elif isinstance(other, Rational):
- return Rational(self.p*other.q, self.q*other.p, igcd(self.p, other.p)*igcd(self.q, other.q))
- elif isinstance(other, Float):
- return self*(1/other)
- else:
- return Number.__truediv__(self, other)
- return Number.__truediv__(self, other)
- @_sympifyit('other', NotImplemented)
- def __rtruediv__(self, other):
- if global_parameters.evaluate:
- if isinstance(other, Integer):
- return Rational(other.p*self.q, self.p, igcd(self.p, other.p))
- elif isinstance(other, Rational):
- return Rational(other.p*self.q, other.q*self.p, igcd(self.p, other.p)*igcd(self.q, other.q))
- elif isinstance(other, Float):
- return other*(1/self)
- else:
- return Number.__rtruediv__(self, other)
- return Number.__rtruediv__(self, other)
- @_sympifyit('other', NotImplemented)
- def __mod__(self, other):
- if global_parameters.evaluate:
- if isinstance(other, Rational):
- n = (self.p*other.q) // (other.p*self.q)
- return Rational(self.p*other.q - n*other.p*self.q, self.q*other.q)
- if isinstance(other, Float):
- # calculate mod with Rationals, *then* round the answer
- return Float(self.__mod__(Rational(other)),
- precision=other._prec)
- return Number.__mod__(self, other)
- return Number.__mod__(self, other)
- @_sympifyit('other', NotImplemented)
- def __rmod__(self, other):
- if isinstance(other, Rational):
- return Rational.__mod__(other, self)
- return Number.__rmod__(self, other)
- def _eval_power(self, expt):
- if isinstance(expt, Number):
- if isinstance(expt, Float):
- return self._eval_evalf(expt._prec)**expt
- if expt.is_extended_negative:
- # (3/4)**-2 -> (4/3)**2
- ne = -expt
- if (ne is S.One):
- return Rational(self.q, self.p)
- if self.is_negative:
- return S.NegativeOne**expt*Rational(self.q, -self.p)**ne
- else:
- return Rational(self.q, self.p)**ne
- if expt is S.Infinity: # -oo already caught by test for negative
- if self.p > self.q:
- # (3/2)**oo -> oo
- return S.Infinity
- if self.p < -self.q:
- # (-3/2)**oo -> oo + I*oo
- return S.Infinity + S.Infinity*S.ImaginaryUnit
- return S.Zero
- if isinstance(expt, Integer):
- # (4/3)**2 -> 4**2 / 3**2
- return Rational(self.p**expt.p, self.q**expt.p, 1)
- if isinstance(expt, Rational):
- intpart = expt.p // expt.q
- if intpart:
- intpart += 1
- remfracpart = intpart*expt.q - expt.p
- ratfracpart = Rational(remfracpart, expt.q)
- if self.p != 1:
- return Integer(self.p)**expt*Integer(self.q)**ratfracpart*Rational(1, self.q**intpart, 1)
- return Integer(self.q)**ratfracpart*Rational(1, self.q**intpart, 1)
- else:
- remfracpart = expt.q - expt.p
- ratfracpart = Rational(remfracpart, expt.q)
- if self.p != 1:
- return Integer(self.p)**expt*Integer(self.q)**ratfracpart*Rational(1, self.q, 1)
- return Integer(self.q)**ratfracpart*Rational(1, self.q, 1)
- if self.is_extended_negative and expt.is_even:
- return (-self)**expt
- return
- def _as_mpf_val(self, prec):
- return mlib.from_rational(self.p, self.q, prec, rnd)
- def _mpmath_(self, prec, rnd):
- return mpmath.make_mpf(mlib.from_rational(self.p, self.q, prec, rnd))
- def __abs__(self):
- return Rational(abs(self.p), self.q)
- def __int__(self):
- p, q = self.p, self.q
- if p < 0:
- return -int(-p//q)
- return int(p//q)
- def floor(self):
- return Integer(self.p // self.q)
- def ceiling(self):
- return -Integer(-self.p // self.q)
- def __floor__(self):
- return self.floor()
- def __ceil__(self):
- return self.ceiling()
- def __eq__(self, other):
- try:
- other = _sympify(other)
- except SympifyError:
- return NotImplemented
- if not isinstance(other, Number):
- # S(0) == S.false is False
- # S(0) == False is True
- return False
- if not self:
- return not other
- if other.is_NumberSymbol:
- if other.is_irrational:
- return False
- return other.__eq__(self)
- if other.is_Rational:
- # a Rational is always in reduced form so will never be 2/4
- # so we can just check equivalence of args
- return self.p == other.p and self.q == other.q
- if other.is_Float:
- # all Floats have a denominator that is a power of 2
- # so if self doesn't, it can't be equal to other
- if self.q & (self.q - 1):
- return False
- s, m, t = other._mpf_[:3]
- if s:
- m = -m
- if not t:
- # other is an odd integer
- if not self.is_Integer or self.is_even:
- return False
- return m == self.p
- from .power import integer_log
- if t > 0:
- # other is an even integer
- if not self.is_Integer:
- return False
- # does m*2**t == self.p
- return self.p and not self.p % m and \
- integer_log(self.p//m, 2) == (t, True)
- # does non-integer s*m/2**-t = p/q?
- if self.is_Integer:
- return False
- return m == self.p and integer_log(self.q, 2) == (-t, True)
- return False
- def __ne__(self, other):
- return not self == other
- def _Rrel(self, other, attr):
- # if you want self < other, pass self, other, __gt__
- try:
- other = _sympify(other)
- except SympifyError:
- return NotImplemented
- if other.is_Number:
- op = None
- s, o = self, other
- if other.is_NumberSymbol:
- op = getattr(o, attr)
- elif other.is_Float:
- op = getattr(o, attr)
- elif other.is_Rational:
- s, o = Integer(s.p*o.q), Integer(s.q*o.p)
- op = getattr(o, attr)
- if op:
- return op(s)
- if o.is_number and o.is_extended_real:
- return Integer(s.p), s.q*o
- def __gt__(self, other):
- rv = self._Rrel(other, '__lt__')
- if rv is None:
- rv = self, other
- elif not isinstance(rv, tuple):
- return rv
- return Expr.__gt__(*rv)
- def __ge__(self, other):
- rv = self._Rrel(other, '__le__')
- if rv is None:
- rv = self, other
- elif not isinstance(rv, tuple):
- return rv
- return Expr.__ge__(*rv)
- def __lt__(self, other):
- rv = self._Rrel(other, '__gt__')
- if rv is None:
- rv = self, other
- elif not isinstance(rv, tuple):
- return rv
- return Expr.__lt__(*rv)
- def __le__(self, other):
- rv = self._Rrel(other, '__ge__')
- if rv is None:
- rv = self, other
- elif not isinstance(rv, tuple):
- return rv
- return Expr.__le__(*rv)
- def __hash__(self):
- return super().__hash__()
- def factors(self, limit=None, use_trial=True, use_rho=False,
- use_pm1=False, verbose=False, visual=False):
- """A wrapper to factorint which return factors of self that are
- smaller than limit (or cheap to compute). Special methods of
- factoring are disabled by default so that only trial division is used.
- """
- from sympy.ntheory.factor_ import factorrat
- return factorrat(self, limit=limit, use_trial=use_trial,
- use_rho=use_rho, use_pm1=use_pm1,
- verbose=verbose).copy()
- @property
- def numerator(self):
- return self.p
- @property
- def denominator(self):
- return self.q
- @_sympifyit('other', NotImplemented)
- def gcd(self, other):
- if isinstance(other, Rational):
- if other == S.Zero:
- return other
- return Rational(
- igcd(self.p, other.p),
- ilcm(self.q, other.q))
- return Number.gcd(self, other)
- @_sympifyit('other', NotImplemented)
- def lcm(self, other):
- if isinstance(other, Rational):
- return Rational(
- self.p // igcd(self.p, other.p) * other.p,
- igcd(self.q, other.q))
- return Number.lcm(self, other)
- def as_numer_denom(self):
- return Integer(self.p), Integer(self.q)
- def as_content_primitive(self, radical=False, clear=True):
- """Return the tuple (R, self/R) where R is the positive Rational
- extracted from self.
- Examples
- ========
- >>> from sympy import S
- >>> (S(-3)/2).as_content_primitive()
- (3/2, -1)
- See docstring of Expr.as_content_primitive for more examples.
- """
- if self:
- if self.is_positive:
- return self, S.One
- return -self, S.NegativeOne
- return S.One, self
- def as_coeff_Mul(self, rational=False):
- """Efficiently extract the coefficient of a product."""
- return self, S.One
- def as_coeff_Add(self, rational=False):
- """Efficiently extract the coefficient of a summation."""
- return self, S.Zero
- class Integer(Rational):
- """Represents integer numbers of any size.
- Examples
- ========
- >>> from sympy import Integer
- >>> Integer(3)
- 3
- If a float or a rational is passed to Integer, the fractional part
- will be discarded; the effect is of rounding toward zero.
- >>> Integer(3.8)
- 3
- >>> Integer(-3.8)
- -3
- A string is acceptable input if it can be parsed as an integer:
- >>> Integer("9" * 20)
- 99999999999999999999
- It is rarely needed to explicitly instantiate an Integer, because
- Python integers are automatically converted to Integer when they
- are used in SymPy expressions.
- """
- q = 1
- is_integer = True
- is_number = True
- is_Integer = True
- __slots__ = ()
- def _as_mpf_val(self, prec):
- return mlib.from_int(self.p, prec, rnd)
- def _mpmath_(self, prec, rnd):
- return mpmath.make_mpf(self._as_mpf_val(prec))
- @cacheit
- def __new__(cls, i):
- if isinstance(i, str):
- i = i.replace(' ', '')
- # whereas we cannot, in general, make a Rational from an
- # arbitrary expression, we can make an Integer unambiguously
- # (except when a non-integer expression happens to round to
- # an integer). So we proceed by taking int() of the input and
- # let the int routines determine whether the expression can
- # be made into an int or whether an error should be raised.
- try:
- ival = int(i)
- except TypeError:
- raise TypeError(
- "Argument of Integer should be of numeric type, got %s." % i)
- # We only work with well-behaved integer types. This converts, for
- # example, numpy.int32 instances.
- if ival == 1:
- return S.One
- if ival == -1:
- return S.NegativeOne
- if ival == 0:
- return S.Zero
- obj = Expr.__new__(cls)
- obj.p = ival
- return obj
- def __getnewargs__(self):
- return (self.p,)
- # Arithmetic operations are here for efficiency
- def __int__(self):
- return self.p
- def floor(self):
- return Integer(self.p)
- def ceiling(self):
- return Integer(self.p)
- def __floor__(self):
- return self.floor()
- def __ceil__(self):
- return self.ceiling()
- def __neg__(self):
- return Integer(-self.p)
- def __abs__(self):
- if self.p >= 0:
- return self
- else:
- return Integer(-self.p)
- def __divmod__(self, other):
- if isinstance(other, Integer) and global_parameters.evaluate:
- return Tuple(*(divmod(self.p, other.p)))
- else:
- return Number.__divmod__(self, other)
- def __rdivmod__(self, other):
- if isinstance(other, int) and global_parameters.evaluate:
- return Tuple(*(divmod(other, self.p)))
- else:
- try:
- other = Number(other)
- except TypeError:
- msg = "unsupported operand type(s) for divmod(): '%s' and '%s'"
- oname = type(other).__name__
- sname = type(self).__name__
- raise TypeError(msg % (oname, sname))
- return Number.__divmod__(other, self)
- # TODO make it decorator + bytecodehacks?
- def __add__(self, other):
- if global_parameters.evaluate:
- if isinstance(other, int):
- return Integer(self.p + other)
- elif isinstance(other, Integer):
- return Integer(self.p + other.p)
- elif isinstance(other, Rational):
- return Rational(self.p*other.q + other.p, other.q, 1)
- return Rational.__add__(self, other)
- else:
- return Add(self, other)
- def __radd__(self, other):
- if global_parameters.evaluate:
- if isinstance(other, int):
- return Integer(other + self.p)
- elif isinstance(other, Rational):
- return Rational(other.p + self.p*other.q, other.q, 1)
- return Rational.__radd__(self, other)
- return Rational.__radd__(self, other)
- def __sub__(self, other):
- if global_parameters.evaluate:
- if isinstance(other, int):
- return Integer(self.p - other)
- elif isinstance(other, Integer):
- return Integer(self.p - other.p)
- elif isinstance(other, Rational):
- return Rational(self.p*other.q - other.p, other.q, 1)
- return Rational.__sub__(self, other)
- return Rational.__sub__(self, other)
- def __rsub__(self, other):
- if global_parameters.evaluate:
- if isinstance(other, int):
- return Integer(other - self.p)
- elif isinstance(other, Rational):
- return Rational(other.p - self.p*other.q, other.q, 1)
- return Rational.__rsub__(self, other)
- return Rational.__rsub__(self, other)
- def __mul__(self, other):
- if global_parameters.evaluate:
- if isinstance(other, int):
- return Integer(self.p*other)
- elif isinstance(other, Integer):
- return Integer(self.p*other.p)
- elif isinstance(other, Rational):
- return Rational(self.p*other.p, other.q, igcd(self.p, other.q))
- return Rational.__mul__(self, other)
- return Rational.__mul__(self, other)
- def __rmul__(self, other):
- if global_parameters.evaluate:
- if isinstance(other, int):
- return Integer(other*self.p)
- elif isinstance(other, Rational):
- return Rational(other.p*self.p, other.q, igcd(self.p, other.q))
- return Rational.__rmul__(self, other)
- return Rational.__rmul__(self, other)
- def __mod__(self, other):
- if global_parameters.evaluate:
- if isinstance(other, int):
- return Integer(self.p % other)
- elif isinstance(other, Integer):
- return Integer(self.p % other.p)
- return Rational.__mod__(self, other)
- return Rational.__mod__(self, other)
- def __rmod__(self, other):
- if global_parameters.evaluate:
- if isinstance(other, int):
- return Integer(other % self.p)
- elif isinstance(other, Integer):
- return Integer(other.p % self.p)
- return Rational.__rmod__(self, other)
- return Rational.__rmod__(self, other)
- def __eq__(self, other):
- if isinstance(other, int):
- return (self.p == other)
- elif isinstance(other, Integer):
- return (self.p == other.p)
- return Rational.__eq__(self, other)
- def __ne__(self, other):
- return not self == other
- def __gt__(self, other):
- try:
- other = _sympify(other)
- except SympifyError:
- return NotImplemented
- if other.is_Integer:
- return _sympify(self.p > other.p)
- return Rational.__gt__(self, other)
- def __lt__(self, other):
- try:
- other = _sympify(other)
- except SympifyError:
- return NotImplemented
- if other.is_Integer:
- return _sympify(self.p < other.p)
- return Rational.__lt__(self, other)
- def __ge__(self, other):
- try:
- other = _sympify(other)
- except SympifyError:
- return NotImplemented
- if other.is_Integer:
- return _sympify(self.p >= other.p)
- return Rational.__ge__(self, other)
- def __le__(self, other):
- try:
- other = _sympify(other)
- except SympifyError:
- return NotImplemented
- if other.is_Integer:
- return _sympify(self.p <= other.p)
- return Rational.__le__(self, other)
- def __hash__(self):
- return hash(self.p)
- def __index__(self):
- return self.p
- ########################################
- def _eval_is_odd(self):
- return bool(self.p % 2)
- def _eval_power(self, expt):
- """
- Tries to do some simplifications on self**expt
- Returns None if no further simplifications can be done.
- Explanation
- ===========
- When exponent is a fraction (so we have for example a square root),
- we try to find a simpler representation by factoring the argument
- up to factors of 2**15, e.g.
- - sqrt(4) becomes 2
- - sqrt(-4) becomes 2*I
- - (2**(3+7)*3**(6+7))**Rational(1,7) becomes 6*18**(3/7)
- Further simplification would require a special call to factorint on
- the argument which is not done here for sake of speed.
- """
- from sympy.ntheory.factor_ import perfect_power
- if expt is S.Infinity:
- if self.p > S.One:
- return S.Infinity
- # cases -1, 0, 1 are done in their respective classes
- return S.Infinity + S.ImaginaryUnit*S.Infinity
- if expt is S.NegativeInfinity:
- return Rational(1, self, 1)**S.Infinity
- if not isinstance(expt, Number):
- # simplify when expt is even
- # (-2)**k --> 2**k
- if self.is_negative and expt.is_even:
- return (-self)**expt
- if isinstance(expt, Float):
- # Rational knows how to exponentiate by a Float
- return super()._eval_power(expt)
- if not isinstance(expt, Rational):
- return
- if expt is S.Half and self.is_negative:
- # we extract I for this special case since everyone is doing so
- return S.ImaginaryUnit*Pow(-self, expt)
- if expt.is_negative:
- # invert base and change sign on exponent
- ne = -expt
- if self.is_negative:
- return S.NegativeOne**expt*Rational(1, -self, 1)**ne
- else:
- return Rational(1, self.p, 1)**ne
- # see if base is a perfect root, sqrt(4) --> 2
- x, xexact = integer_nthroot(abs(self.p), expt.q)
- if xexact:
- # if it's a perfect root we've finished
- result = Integer(x**abs(expt.p))
- if self.is_negative:
- result *= S.NegativeOne**expt
- return result
- # The following is an algorithm where we collect perfect roots
- # from the factors of base.
- # if it's not an nth root, it still might be a perfect power
- b_pos = int(abs(self.p))
- p = perfect_power(b_pos)
- if p is not False:
- dict = {p[0]: p[1]}
- else:
- dict = Integer(b_pos).factors(limit=2**15)
- # now process the dict of factors
- out_int = 1 # integer part
- out_rad = 1 # extracted radicals
- sqr_int = 1
- sqr_gcd = 0
- sqr_dict = {}
- for prime, exponent in dict.items():
- exponent *= expt.p
- # remove multiples of expt.q: (2**12)**(1/10) -> 2*(2**2)**(1/10)
- div_e, div_m = divmod(exponent, expt.q)
- if div_e > 0:
- out_int *= prime**div_e
- if div_m > 0:
- # see if the reduced exponent shares a gcd with e.q
- # (2**2)**(1/10) -> 2**(1/5)
- g = igcd(div_m, expt.q)
- if g != 1:
- out_rad *= Pow(prime, Rational(div_m//g, expt.q//g, 1))
- else:
- sqr_dict[prime] = div_m
- # identify gcd of remaining powers
- for p, ex in sqr_dict.items():
- if sqr_gcd == 0:
- sqr_gcd = ex
- else:
- sqr_gcd = igcd(sqr_gcd, ex)
- if sqr_gcd == 1:
- break
- for k, v in sqr_dict.items():
- sqr_int *= k**(v//sqr_gcd)
- if sqr_int == b_pos and out_int == 1 and out_rad == 1:
- result = None
- else:
- result = out_int*out_rad*Pow(sqr_int, Rational(sqr_gcd, expt.q))
- if self.is_negative:
- result *= Pow(S.NegativeOne, expt)
- return result
- def _eval_is_prime(self):
- from sympy.ntheory.primetest import isprime
- return isprime(self)
- def _eval_is_composite(self):
- if self > 1:
- return fuzzy_not(self.is_prime)
- else:
- return False
- def as_numer_denom(self):
- return self, S.One
- @_sympifyit('other', NotImplemented)
- def __floordiv__(self, other):
- if not isinstance(other, Expr):
- return NotImplemented
- if isinstance(other, Integer):
- return Integer(self.p // other)
- return divmod(self, other)[0]
- def __rfloordiv__(self, other):
- return Integer(Integer(other).p // self.p)
- # These bitwise operations (__lshift__, __rlshift__, ..., __invert__) are defined
- # for Integer only and not for general SymPy expressions. This is to achieve
- # compatibility with the numbers.Integral ABC which only defines these operations
- # among instances of numbers.Integral. Therefore, these methods check explicitly for
- # integer types rather than using sympify because they should not accept arbitrary
- # symbolic expressions and there is no symbolic analogue of numbers.Integral's
- # bitwise operations.
- def __lshift__(self, other):
- if isinstance(other, (int, Integer, numbers.Integral)):
- return Integer(self.p << int(other))
- else:
- return NotImplemented
- def __rlshift__(self, other):
- if isinstance(other, (int, numbers.Integral)):
- return Integer(int(other) << self.p)
- else:
- return NotImplemented
- def __rshift__(self, other):
- if isinstance(other, (int, Integer, numbers.Integral)):
- return Integer(self.p >> int(other))
- else:
- return NotImplemented
- def __rrshift__(self, other):
- if isinstance(other, (int, numbers.Integral)):
- return Integer(int(other) >> self.p)
- else:
- return NotImplemented
- def __and__(self, other):
- if isinstance(other, (int, Integer, numbers.Integral)):
- return Integer(self.p & int(other))
- else:
- return NotImplemented
- def __rand__(self, other):
- if isinstance(other, (int, numbers.Integral)):
- return Integer(int(other) & self.p)
- else:
- return NotImplemented
- def __xor__(self, other):
- if isinstance(other, (int, Integer, numbers.Integral)):
- return Integer(self.p ^ int(other))
- else:
- return NotImplemented
- def __rxor__(self, other):
- if isinstance(other, (int, numbers.Integral)):
- return Integer(int(other) ^ self.p)
- else:
- return NotImplemented
- def __or__(self, other):
- if isinstance(other, (int, Integer, numbers.Integral)):
- return Integer(self.p | int(other))
- else:
- return NotImplemented
- def __ror__(self, other):
- if isinstance(other, (int, numbers.Integral)):
- return Integer(int(other) | self.p)
- else:
- return NotImplemented
- def __invert__(self):
- return Integer(~self.p)
- # Add sympify converters
- _sympy_converter[int] = Integer
- class AlgebraicNumber(Expr):
- r"""
- Class for representing algebraic numbers in SymPy.
- Symbolically, an instance of this class represents an element
- $\alpha \in \mathbb{Q}(\theta) \hookrightarrow \mathbb{C}$. That is, the
- algebraic number $\alpha$ is represented as an element of a particular
- number field $\mathbb{Q}(\theta)$, with a particular embedding of this
- field into the complex numbers.
- Formally, the primitive element $\theta$ is given by two data points: (1)
- its minimal polynomial (which defines $\mathbb{Q}(\theta)$), and (2) a
- particular complex number that is a root of this polynomial (which defines
- the embedding $\mathbb{Q}(\theta) \hookrightarrow \mathbb{C}$). Finally,
- the algebraic number $\alpha$ which we represent is then given by the
- coefficients of a polynomial in $\theta$.
- """
- __slots__ = ('rep', 'root', 'alias', 'minpoly', '_own_minpoly')
- is_AlgebraicNumber = True
- is_algebraic = True
- is_number = True
- kind = NumberKind
- # Optional alias symbol is not free.
- # Actually, alias should be a Str, but some methods
- # expect that it be an instance of Expr.
- free_symbols: set[Basic] = set()
- def __new__(cls, expr, coeffs=None, alias=None, **args):
- r"""
- Construct a new algebraic number $\alpha$ belonging to a number field
- $k = \mathbb{Q}(\theta)$.
- There are four instance attributes to be determined:
- =========== ============================================================================
- Attribute Type/Meaning
- =========== ============================================================================
- ``root`` :py:class:`~.Expr` for $\theta$ as a complex number
- ``minpoly`` :py:class:`~.Poly`, the minimal polynomial of $\theta$
- ``rep`` :py:class:`~sympy.polys.polyclasses.DMP` giving $\alpha$ as poly in $\theta$
- ``alias`` :py:class:`~.Symbol` for $\theta$, or ``None``
- =========== ============================================================================
- See Parameters section for how they are determined.
- Parameters
- ==========
- expr : :py:class:`~.Expr`, or pair $(m, r)$
- There are three distinct modes of construction, depending on what
- is passed as *expr*.
- **(1)** *expr* is an :py:class:`~.AlgebraicNumber`:
- In this case we begin by copying all four instance attributes from
- *expr*. If *coeffs* were also given, we compose the two coeff
- polynomials (see below). If an *alias* was given, it overrides.
- **(2)** *expr* is any other type of :py:class:`~.Expr`:
- Then ``root`` will equal *expr*. Therefore it
- must express an algebraic quantity, and we will compute its
- ``minpoly``.
- **(3)** *expr* is an ordered pair $(m, r)$ giving the
- ``minpoly`` $m$, and a ``root`` $r$ thereof, which together
- define $\theta$. In this case $m$ may be either a univariate
- :py:class:`~.Poly` or any :py:class:`~.Expr` which represents the
- same, while $r$ must be some :py:class:`~.Expr` representing a
- complex number that is a root of $m$, including both explicit
- expressions in radicals, and instances of
- :py:class:`~.ComplexRootOf` or :py:class:`~.AlgebraicNumber`.
- coeffs : list, :py:class:`~.ANP`, None, optional (default=None)
- This defines ``rep``, giving the algebraic number $\alpha$ as a
- polynomial in $\theta$.
- If a list, the elements should be integers or rational numbers.
- If an :py:class:`~.ANP`, we take its coefficients (using its
- :py:meth:`~.ANP.to_list()` method). If ``None``, then the list of
- coefficients defaults to ``[1, 0]``, meaning that $\alpha = \theta$
- is the primitive element of the field.
- If *expr* was an :py:class:`~.AlgebraicNumber`, let $g(x)$ be its
- ``rep`` polynomial, and let $f(x)$ be the polynomial defined by
- *coeffs*. Then ``self.rep`` will represent the composition
- $(f \circ g)(x)$.
- alias : str, :py:class:`~.Symbol`, None, optional (default=None)
- This is a way to provide a name for the primitive element. We
- described several ways in which the *expr* argument can define the
- value of the primitive element, but none of these methods gave it
- a name. Here, for example, *alias* could be set as
- ``Symbol('theta')``, in order to make this symbol appear when
- $\alpha$ is printed, or rendered as a polynomial, using the
- :py:meth:`~.as_poly()` method.
- Examples
- ========
- Recall that we are constructing an algebraic number as a field element
- $\alpha \in \mathbb{Q}(\theta)$.
- >>> from sympy import AlgebraicNumber, sqrt, CRootOf, S
- >>> from sympy.abc import x
- Example (1): $\alpha = \theta = \sqrt{2}$
- >>> a1 = AlgebraicNumber(sqrt(2))
- >>> a1.minpoly_of_element().as_expr(x)
- x**2 - 2
- >>> a1.evalf(10)
- 1.414213562
- Example (2): $\alpha = 3 \sqrt{2} - 5$, $\theta = \sqrt{2}$. We can
- either build on the last example:
- >>> a2 = AlgebraicNumber(a1, [3, -5])
- >>> a2.as_expr()
- -5 + 3*sqrt(2)
- or start from scratch:
- >>> a2 = AlgebraicNumber(sqrt(2), [3, -5])
- >>> a2.as_expr()
- -5 + 3*sqrt(2)
- Example (3): $\alpha = 6 \sqrt{2} - 11$, $\theta = \sqrt{2}$. Again we
- can build on the previous example, and we see that the coeff polys are
- composed:
- >>> a3 = AlgebraicNumber(a2, [2, -1])
- >>> a3.as_expr()
- -11 + 6*sqrt(2)
- reflecting the fact that $(2x - 1) \circ (3x - 5) = 6x - 11$.
- Example (4): $\alpha = \sqrt{2}$, $\theta = \sqrt{2} + \sqrt{3}$. The
- easiest way is to use the :py:func:`~.to_number_field()` function:
- >>> from sympy import to_number_field
- >>> a4 = to_number_field(sqrt(2), sqrt(2) + sqrt(3))
- >>> a4.minpoly_of_element().as_expr(x)
- x**2 - 2
- >>> a4.to_root()
- sqrt(2)
- >>> a4.primitive_element()
- sqrt(2) + sqrt(3)
- >>> a4.coeffs()
- [1/2, 0, -9/2, 0]
- but if you already knew the right coefficients, you could construct it
- directly:
- >>> a4 = AlgebraicNumber(sqrt(2) + sqrt(3), [S(1)/2, 0, S(-9)/2, 0])
- >>> a4.to_root()
- sqrt(2)
- >>> a4.primitive_element()
- sqrt(2) + sqrt(3)
- Example (5): Construct the Golden Ratio as an element of the 5th
- cyclotomic field, supposing we already know its coefficients. This time
- we introduce the alias $\zeta$ for the primitive element of the field:
- >>> from sympy import cyclotomic_poly
- >>> from sympy.abc import zeta
- >>> a5 = AlgebraicNumber(CRootOf(cyclotomic_poly(5), -1),
- ... [-1, -1, 0, 0], alias=zeta)
- >>> a5.as_poly().as_expr()
- -zeta**3 - zeta**2
- >>> a5.evalf()
- 1.61803398874989
- (The index ``-1`` to ``CRootOf`` selects the complex root with the
- largest real and imaginary parts, which in this case is
- $\mathrm{e}^{2i\pi/5}$. See :py:class:`~.ComplexRootOf`.)
- Example (6): Building on the last example, construct the number
- $2 \phi \in \mathbb{Q}(\phi)$, where $\phi$ is the Golden Ratio:
- >>> from sympy.abc import phi
- >>> a6 = AlgebraicNumber(a5.to_root(), coeffs=[2, 0], alias=phi)
- >>> a6.as_poly().as_expr()
- 2*phi
- >>> a6.primitive_element().evalf()
- 1.61803398874989
- Note that we needed to use ``a5.to_root()``, since passing ``a5`` as
- the first argument would have constructed the number $2 \phi$ as an
- element of the field $\mathbb{Q}(\zeta)$:
- >>> a6_wrong = AlgebraicNumber(a5, coeffs=[2, 0])
- >>> a6_wrong.as_poly().as_expr()
- -2*zeta**3 - 2*zeta**2
- >>> a6_wrong.primitive_element().evalf()
- 0.309016994374947 + 0.951056516295154*I
- """
- from sympy.polys.polyclasses import ANP, DMP
- from sympy.polys.numberfields import minimal_polynomial
- expr = sympify(expr)
- rep0 = None
- alias0 = None
- if isinstance(expr, (tuple, Tuple)):
- minpoly, root = expr
- if not minpoly.is_Poly:
- from sympy.polys.polytools import Poly
- minpoly = Poly(minpoly)
- elif expr.is_AlgebraicNumber:
- minpoly, root, rep0, alias0 = (expr.minpoly, expr.root,
- expr.rep, expr.alias)
- else:
- minpoly, root = minimal_polynomial(
- expr, args.get('gen'), polys=True), expr
- dom = minpoly.get_domain()
- if coeffs is not None:
- if not isinstance(coeffs, ANP):
- rep = DMP.from_sympy_list(sympify(coeffs), 0, dom)
- scoeffs = Tuple(*coeffs)
- else:
- rep = DMP.from_list(coeffs.to_list(), 0, dom)
- scoeffs = Tuple(*coeffs.to_list())
- else:
- rep = DMP.from_list([1, 0], 0, dom)
- scoeffs = Tuple(1, 0)
- if rep0 is not None:
- from sympy.polys.densetools import dup_compose
- c = dup_compose(rep.rep, rep0.rep, dom)
- rep = DMP.from_list(c, 0, dom)
- scoeffs = Tuple(*c)
- if rep.degree() >= minpoly.degree():
- rep = rep.rem(minpoly.rep)
- sargs = (root, scoeffs)
- alias = alias or alias0
- if alias is not None:
- from .symbol import Symbol
- if not isinstance(alias, Symbol):
- alias = Symbol(alias)
- sargs = sargs + (alias,)
- obj = Expr.__new__(cls, *sargs)
- obj.rep = rep
- obj.root = root
- obj.alias = alias
- obj.minpoly = minpoly
- obj._own_minpoly = None
- return obj
- def __hash__(self):
- return super().__hash__()
- def _eval_evalf(self, prec):
- return self.as_expr()._evalf(prec)
- @property
- def is_aliased(self):
- """Returns ``True`` if ``alias`` was set. """
- return self.alias is not None
- def as_poly(self, x=None):
- """Create a Poly instance from ``self``. """
- from sympy.polys.polytools import Poly, PurePoly
- if x is not None:
- return Poly.new(self.rep, x)
- else:
- if self.alias is not None:
- return Poly.new(self.rep, self.alias)
- else:
- from .symbol import Dummy
- return PurePoly.new(self.rep, Dummy('x'))
- def as_expr(self, x=None):
- """Create a Basic expression from ``self``. """
- return self.as_poly(x or self.root).as_expr().expand()
- def coeffs(self):
- """Returns all SymPy coefficients of an algebraic number. """
- return [ self.rep.dom.to_sympy(c) for c in self.rep.all_coeffs() ]
- def native_coeffs(self):
- """Returns all native coefficients of an algebraic number. """
- return self.rep.all_coeffs()
- def to_algebraic_integer(self):
- """Convert ``self`` to an algebraic integer. """
- from sympy.polys.polytools import Poly
- f = self.minpoly
- if f.LC() == 1:
- return self
- coeff = f.LC()**(f.degree() - 1)
- poly = f.compose(Poly(f.gen/f.LC()))
- minpoly = poly*coeff
- root = f.LC()*self.root
- return AlgebraicNumber((minpoly, root), self.coeffs())
- def _eval_simplify(self, **kwargs):
- from sympy.polys.rootoftools import CRootOf
- from sympy.polys import minpoly
- measure, ratio = kwargs['measure'], kwargs['ratio']
- for r in [r for r in self.minpoly.all_roots() if r.func != CRootOf]:
- if minpoly(self.root - r).is_Symbol:
- # use the matching root if it's simpler
- if measure(r) < ratio*measure(self.root):
- return AlgebraicNumber(r)
- return self
- def field_element(self, coeffs):
- r"""
- Form another element of the same number field.
- Explanation
- ===========
- If we represent $\alpha \in \mathbb{Q}(\theta)$, form another element
- $\beta \in \mathbb{Q}(\theta)$ of the same number field.
- Parameters
- ==========
- coeffs : list, :py:class:`~.ANP`
- Like the *coeffs* arg to the class
- :py:meth:`constructor<.AlgebraicNumber.__new__>`, defines the
- new element as a polynomial in the primitive element.
- If a list, the elements should be integers or rational numbers.
- If an :py:class:`~.ANP`, we take its coefficients (using its
- :py:meth:`~.ANP.to_list()` method).
- Examples
- ========
- >>> from sympy import AlgebraicNumber, sqrt
- >>> a = AlgebraicNumber(sqrt(5), [-1, 1])
- >>> b = a.field_element([3, 2])
- >>> print(a)
- 1 - sqrt(5)
- >>> print(b)
- 2 + 3*sqrt(5)
- >>> print(b.primitive_element() == a.primitive_element())
- True
- See Also
- ========
- AlgebraicNumber
- """
- return AlgebraicNumber(
- (self.minpoly, self.root), coeffs=coeffs, alias=self.alias)
- @property
- def is_primitive_element(self):
- r"""
- Say whether this algebraic number $\alpha \in \mathbb{Q}(\theta)$ is
- equal to the primitive element $\theta$ for its field.
- """
- c = self.coeffs()
- # Second case occurs if self.minpoly is linear:
- return c == [1, 0] or c == [self.root]
- def primitive_element(self):
- r"""
- Get the primitive element $\theta$ for the number field
- $\mathbb{Q}(\theta)$ to which this algebraic number $\alpha$ belongs.
- Returns
- =======
- AlgebraicNumber
- """
- if self.is_primitive_element:
- return self
- return self.field_element([1, 0])
- def to_primitive_element(self, radicals=True):
- r"""
- Convert ``self`` to an :py:class:`~.AlgebraicNumber` instance that is
- equal to its own primitive element.
- Explanation
- ===========
- If we represent $\alpha \in \mathbb{Q}(\theta)$, $\alpha \neq \theta$,
- construct a new :py:class:`~.AlgebraicNumber` that represents
- $\alpha \in \mathbb{Q}(\alpha)$.
- Examples
- ========
- >>> from sympy import sqrt, to_number_field
- >>> from sympy.abc import x
- >>> a = to_number_field(sqrt(2), sqrt(2) + sqrt(3))
- The :py:class:`~.AlgebraicNumber` ``a`` represents the number
- $\sqrt{2}$ in the field $\mathbb{Q}(\sqrt{2} + \sqrt{3})$. Rendering
- ``a`` as a polynomial,
- >>> a.as_poly().as_expr(x)
- x**3/2 - 9*x/2
- reflects the fact that $\sqrt{2} = \theta^3/2 - 9 \theta/2$, where
- $\theta = \sqrt{2} + \sqrt{3}$.
- ``a`` is not equal to its own primitive element. Its minpoly
- >>> a.minpoly.as_poly().as_expr(x)
- x**4 - 10*x**2 + 1
- is that of $\theta$.
- Converting to a primitive element,
- >>> a_prim = a.to_primitive_element()
- >>> a_prim.minpoly.as_poly().as_expr(x)
- x**2 - 2
- we obtain an :py:class:`~.AlgebraicNumber` whose ``minpoly`` is that of
- the number itself.
- Parameters
- ==========
- radicals : boolean, optional (default=True)
- If ``True``, then we will try to return an
- :py:class:`~.AlgebraicNumber` whose ``root`` is an expression
- in radicals. If that is not possible (or if *radicals* is
- ``False``), ``root`` will be a :py:class:`~.ComplexRootOf`.
- Returns
- =======
- AlgebraicNumber
- See Also
- ========
- is_primitive_element
- """
- if self.is_primitive_element:
- return self
- m = self.minpoly_of_element()
- r = self.to_root(radicals=radicals)
- return AlgebraicNumber((m, r))
- def minpoly_of_element(self):
- r"""
- Compute the minimal polynomial for this algebraic number.
- Explanation
- ===========
- Recall that we represent an element $\alpha \in \mathbb{Q}(\theta)$.
- Our instance attribute ``self.minpoly`` is the minimal polynomial for
- our primitive element $\theta$. This method computes the minimal
- polynomial for $\alpha$.
- """
- if self._own_minpoly is None:
- if self.is_primitive_element:
- self._own_minpoly = self.minpoly
- else:
- from sympy.polys.numberfields.minpoly import minpoly
- theta = self.primitive_element()
- self._own_minpoly = minpoly(self.as_expr(theta), polys=True)
- return self._own_minpoly
- def to_root(self, radicals=True, minpoly=None):
- """
- Convert to an :py:class:`~.Expr` that is not an
- :py:class:`~.AlgebraicNumber`, specifically, either a
- :py:class:`~.ComplexRootOf`, or, optionally and where possible, an
- expression in radicals.
- Parameters
- ==========
- radicals : boolean, optional (default=True)
- If ``True``, then we will try to return the root as an expression
- in radicals. If that is not possible, we will return a
- :py:class:`~.ComplexRootOf`.
- minpoly : :py:class:`~.Poly`
- If the minimal polynomial for `self` has been pre-computed, it can
- be passed in order to save time.
- """
- if self.is_primitive_element and not isinstance(self.root, AlgebraicNumber):
- return self.root
- m = minpoly or self.minpoly_of_element()
- roots = m.all_roots(radicals=radicals)
- if len(roots) == 1:
- return roots[0]
- ex = self.as_expr()
- for b in roots:
- if m.same_root(b, ex):
- return b
- class RationalConstant(Rational):
- """
- Abstract base class for rationals with specific behaviors
- Derived classes must define class attributes p and q and should probably all
- be singletons.
- """
- __slots__ = ()
- def __new__(cls):
- return AtomicExpr.__new__(cls)
- class IntegerConstant(Integer):
- __slots__ = ()
- def __new__(cls):
- return AtomicExpr.__new__(cls)
- class Zero(IntegerConstant, metaclass=Singleton):
- """The number zero.
- Zero is a singleton, and can be accessed by ``S.Zero``
- Examples
- ========
- >>> from sympy import S, Integer
- >>> Integer(0) is S.Zero
- True
- >>> 1/S.Zero
- zoo
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/Zero
- """
- p = 0
- q = 1
- is_positive = False
- is_negative = False
- is_zero = True
- is_number = True
- is_comparable = True
- __slots__ = ()
- def __getnewargs__(self):
- return ()
- @staticmethod
- def __abs__():
- return S.Zero
- @staticmethod
- def __neg__():
- return S.Zero
- def _eval_power(self, expt):
- if expt.is_extended_positive:
- return self
- if expt.is_extended_negative:
- return S.ComplexInfinity
- if expt.is_extended_real is False:
- return S.NaN
- if expt.is_zero:
- return S.One
- # infinities are already handled with pos and neg
- # tests above; now throw away leading numbers on Mul
- # exponent since 0**-x = zoo**x even when x == 0
- coeff, terms = expt.as_coeff_Mul()
- if coeff.is_negative:
- return S.ComplexInfinity**terms
- if coeff is not S.One: # there is a Number to discard
- return self**terms
- def _eval_order(self, *symbols):
- # Order(0,x) -> 0
- return self
- def __bool__(self):
- return False
- class One(IntegerConstant, metaclass=Singleton):
- """The number one.
- One is a singleton, and can be accessed by ``S.One``.
- Examples
- ========
- >>> from sympy import S, Integer
- >>> Integer(1) is S.One
- True
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/1_%28number%29
- """
- is_number = True
- is_positive = True
- p = 1
- q = 1
- __slots__ = ()
- def __getnewargs__(self):
- return ()
- @staticmethod
- def __abs__():
- return S.One
- @staticmethod
- def __neg__():
- return S.NegativeOne
- def _eval_power(self, expt):
- return self
- def _eval_order(self, *symbols):
- return
- @staticmethod
- def factors(limit=None, use_trial=True, use_rho=False, use_pm1=False,
- verbose=False, visual=False):
- if visual:
- return S.One
- else:
- return {}
- class NegativeOne(IntegerConstant, metaclass=Singleton):
- """The number negative one.
- NegativeOne is a singleton, and can be accessed by ``S.NegativeOne``.
- Examples
- ========
- >>> from sympy import S, Integer
- >>> Integer(-1) is S.NegativeOne
- True
- See Also
- ========
- One
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/%E2%88%921_%28number%29
- """
- is_number = True
- p = -1
- q = 1
- __slots__ = ()
- def __getnewargs__(self):
- return ()
- @staticmethod
- def __abs__():
- return S.One
- @staticmethod
- def __neg__():
- return S.One
- def _eval_power(self, expt):
- if expt.is_odd:
- return S.NegativeOne
- if expt.is_even:
- return S.One
- if isinstance(expt, Number):
- if isinstance(expt, Float):
- return Float(-1.0)**expt
- if expt is S.NaN:
- return S.NaN
- if expt in (S.Infinity, S.NegativeInfinity):
- return S.NaN
- if expt is S.Half:
- return S.ImaginaryUnit
- if isinstance(expt, Rational):
- if expt.q == 2:
- return S.ImaginaryUnit**Integer(expt.p)
- i, r = divmod(expt.p, expt.q)
- if i:
- return self**i*self**Rational(r, expt.q)
- return
- class Half(RationalConstant, metaclass=Singleton):
- """The rational number 1/2.
- Half is a singleton, and can be accessed by ``S.Half``.
- Examples
- ========
- >>> from sympy import S, Rational
- >>> Rational(1, 2) is S.Half
- True
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/One_half
- """
- is_number = True
- p = 1
- q = 2
- __slots__ = ()
- def __getnewargs__(self):
- return ()
- @staticmethod
- def __abs__():
- return S.Half
- class Infinity(Number, metaclass=Singleton):
- r"""Positive infinite quantity.
- Explanation
- ===========
- In real analysis the symbol `\infty` denotes an unbounded
- limit: `x\to\infty` means that `x` grows without bound.
- Infinity is often used not only to define a limit but as a value
- in the affinely extended real number system. Points labeled `+\infty`
- and `-\infty` can be added to the topological space of the real numbers,
- producing the two-point compactification of the real numbers. Adding
- algebraic properties to this gives us the extended real numbers.
- Infinity is a singleton, and can be accessed by ``S.Infinity``,
- or can be imported as ``oo``.
- Examples
- ========
- >>> from sympy import oo, exp, limit, Symbol
- >>> 1 + oo
- oo
- >>> 42/oo
- 0
- >>> x = Symbol('x')
- >>> limit(exp(x), x, oo)
- oo
- See Also
- ========
- NegativeInfinity, NaN
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/Infinity
- """
- is_commutative = True
- is_number = True
- is_complex = False
- is_extended_real = True
- is_infinite = True
- is_comparable = True
- is_extended_positive = True
- is_prime = False
- __slots__ = ()
- def __new__(cls):
- return AtomicExpr.__new__(cls)
- def _latex(self, printer):
- return r"\infty"
- def _eval_subs(self, old, new):
- if self == old:
- return new
- def _eval_evalf(self, prec=None):
- return Float('inf')
- def evalf(self, prec=None, **options):
- return self._eval_evalf(prec)
- @_sympifyit('other', NotImplemented)
- def __add__(self, other):
- if isinstance(other, Number) and global_parameters.evaluate:
- if other in (S.NegativeInfinity, S.NaN):
- return S.NaN
- return self
- return Number.__add__(self, other)
- __radd__ = __add__
- @_sympifyit('other', NotImplemented)
- def __sub__(self, other):
- if isinstance(other, Number) and global_parameters.evaluate:
- if other in (S.Infinity, S.NaN):
- return S.NaN
- return self
- return Number.__sub__(self, other)
- @_sympifyit('other', NotImplemented)
- def __rsub__(self, other):
- return (-self).__add__(other)
- @_sympifyit('other', NotImplemented)
- def __mul__(self, other):
- if isinstance(other, Number) and global_parameters.evaluate:
- if other.is_zero or other is S.NaN:
- return S.NaN
- if other.is_extended_positive:
- return self
- return S.NegativeInfinity
- return Number.__mul__(self, other)
- __rmul__ = __mul__
- @_sympifyit('other', NotImplemented)
- def __truediv__(self, other):
- if isinstance(other, Number) and global_parameters.evaluate:
- if other is S.Infinity or \
- other is S.NegativeInfinity or \
- other is S.NaN:
- return S.NaN
- if other.is_extended_nonnegative:
- return self
- return S.NegativeInfinity
- return Number.__truediv__(self, other)
- def __abs__(self):
- return S.Infinity
- def __neg__(self):
- return S.NegativeInfinity
- def _eval_power(self, expt):
- """
- ``expt`` is symbolic object but not equal to 0 or 1.
- ================ ======= ==============================
- Expression Result Notes
- ================ ======= ==============================
- ``oo ** nan`` ``nan``
- ``oo ** -p`` ``0`` ``p`` is number, ``oo``
- ================ ======= ==============================
- See Also
- ========
- Pow
- NaN
- NegativeInfinity
- """
- if expt.is_extended_positive:
- return S.Infinity
- if expt.is_extended_negative:
- return S.Zero
- if expt is S.NaN:
- return S.NaN
- if expt is S.ComplexInfinity:
- return S.NaN
- if expt.is_extended_real is False and expt.is_number:
- from sympy.functions.elementary.complexes import re
- expt_real = re(expt)
- if expt_real.is_positive:
- return S.ComplexInfinity
- if expt_real.is_negative:
- return S.Zero
- if expt_real.is_zero:
- return S.NaN
- return self**expt.evalf()
- def _as_mpf_val(self, prec):
- return mlib.finf
- def __hash__(self):
- return super().__hash__()
- def __eq__(self, other):
- return other is S.Infinity or other == float('inf')
- def __ne__(self, other):
- return other is not S.Infinity and other != float('inf')
- __gt__ = Expr.__gt__
- __ge__ = Expr.__ge__
- __lt__ = Expr.__lt__
- __le__ = Expr.__le__
- @_sympifyit('other', NotImplemented)
- def __mod__(self, other):
- if not isinstance(other, Expr):
- return NotImplemented
- return S.NaN
- __rmod__ = __mod__
- def floor(self):
- return self
- def ceiling(self):
- return self
- oo = S.Infinity
- class NegativeInfinity(Number, metaclass=Singleton):
- """Negative infinite quantity.
- NegativeInfinity is a singleton, and can be accessed
- by ``S.NegativeInfinity``.
- See Also
- ========
- Infinity
- """
- is_extended_real = True
- is_complex = False
- is_commutative = True
- is_infinite = True
- is_comparable = True
- is_extended_negative = True
- is_number = True
- is_prime = False
- __slots__ = ()
- def __new__(cls):
- return AtomicExpr.__new__(cls)
- def _latex(self, printer):
- return r"-\infty"
- def _eval_subs(self, old, new):
- if self == old:
- return new
- def _eval_evalf(self, prec=None):
- return Float('-inf')
- def evalf(self, prec=None, **options):
- return self._eval_evalf(prec)
- @_sympifyit('other', NotImplemented)
- def __add__(self, other):
- if isinstance(other, Number) and global_parameters.evaluate:
- if other in (S.Infinity, S.NaN):
- return S.NaN
- return self
- return Number.__add__(self, other)
- __radd__ = __add__
- @_sympifyit('other', NotImplemented)
- def __sub__(self, other):
- if isinstance(other, Number) and global_parameters.evaluate:
- if other in (S.NegativeInfinity, S.NaN):
- return S.NaN
- return self
- return Number.__sub__(self, other)
- @_sympifyit('other', NotImplemented)
- def __rsub__(self, other):
- return (-self).__add__(other)
- @_sympifyit('other', NotImplemented)
- def __mul__(self, other):
- if isinstance(other, Number) and global_parameters.evaluate:
- if other.is_zero or other is S.NaN:
- return S.NaN
- if other.is_extended_positive:
- return self
- return S.Infinity
- return Number.__mul__(self, other)
- __rmul__ = __mul__
- @_sympifyit('other', NotImplemented)
- def __truediv__(self, other):
- if isinstance(other, Number) and global_parameters.evaluate:
- if other is S.Infinity or \
- other is S.NegativeInfinity or \
- other is S.NaN:
- return S.NaN
- if other.is_extended_nonnegative:
- return self
- return S.Infinity
- return Number.__truediv__(self, other)
- def __abs__(self):
- return S.Infinity
- def __neg__(self):
- return S.Infinity
- def _eval_power(self, expt):
- """
- ``expt`` is symbolic object but not equal to 0 or 1.
- ================ ======= ==============================
- Expression Result Notes
- ================ ======= ==============================
- ``(-oo) ** nan`` ``nan``
- ``(-oo) ** oo`` ``nan``
- ``(-oo) ** -oo`` ``nan``
- ``(-oo) ** e`` ``oo`` ``e`` is positive even integer
- ``(-oo) ** o`` ``-oo`` ``o`` is positive odd integer
- ================ ======= ==============================
- See Also
- ========
- Infinity
- Pow
- NaN
- """
- if expt.is_number:
- if expt is S.NaN or \
- expt is S.Infinity or \
- expt is S.NegativeInfinity:
- return S.NaN
- if isinstance(expt, Integer) and expt.is_extended_positive:
- if expt.is_odd:
- return S.NegativeInfinity
- else:
- return S.Infinity
- inf_part = S.Infinity**expt
- s_part = S.NegativeOne**expt
- if inf_part == 0 and s_part.is_finite:
- return inf_part
- if (inf_part is S.ComplexInfinity and
- s_part.is_finite and not s_part.is_zero):
- return S.ComplexInfinity
- return s_part*inf_part
- def _as_mpf_val(self, prec):
- return mlib.fninf
- def __hash__(self):
- return super().__hash__()
- def __eq__(self, other):
- return other is S.NegativeInfinity or other == float('-inf')
- def __ne__(self, other):
- return other is not S.NegativeInfinity and other != float('-inf')
- __gt__ = Expr.__gt__
- __ge__ = Expr.__ge__
- __lt__ = Expr.__lt__
- __le__ = Expr.__le__
- @_sympifyit('other', NotImplemented)
- def __mod__(self, other):
- if not isinstance(other, Expr):
- return NotImplemented
- return S.NaN
- __rmod__ = __mod__
- def floor(self):
- return self
- def ceiling(self):
- return self
- def as_powers_dict(self):
- return {S.NegativeOne: 1, S.Infinity: 1}
- class NaN(Number, metaclass=Singleton):
- """
- Not a Number.
- Explanation
- ===========
- This serves as a place holder for numeric values that are indeterminate.
- Most operations on NaN, produce another NaN. Most indeterminate forms,
- such as ``0/0`` or ``oo - oo` produce NaN. Two exceptions are ``0**0``
- and ``oo**0``, which all produce ``1`` (this is consistent with Python's
- float).
- NaN is loosely related to floating point nan, which is defined in the
- IEEE 754 floating point standard, and corresponds to the Python
- ``float('nan')``. Differences are noted below.
- NaN is mathematically not equal to anything else, even NaN itself. This
- explains the initially counter-intuitive results with ``Eq`` and ``==`` in
- the examples below.
- NaN is not comparable so inequalities raise a TypeError. This is in
- contrast with floating point nan where all inequalities are false.
- NaN is a singleton, and can be accessed by ``S.NaN``, or can be imported
- as ``nan``.
- Examples
- ========
- >>> from sympy import nan, S, oo, Eq
- >>> nan is S.NaN
- True
- >>> oo - oo
- nan
- >>> nan + 1
- nan
- >>> Eq(nan, nan) # mathematical equality
- False
- >>> nan == nan # structural equality
- True
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/NaN
- """
- is_commutative = True
- is_extended_real = None
- is_real = None
- is_rational = None
- is_algebraic = None
- is_transcendental = None
- is_integer = None
- is_comparable = False
- is_finite = None
- is_zero = None
- is_prime = None
- is_positive = None
- is_negative = None
- is_number = True
- __slots__ = ()
- def __new__(cls):
- return AtomicExpr.__new__(cls)
- def _latex(self, printer):
- return r"\text{NaN}"
- def __neg__(self):
- return self
- @_sympifyit('other', NotImplemented)
- def __add__(self, other):
- return self
- @_sympifyit('other', NotImplemented)
- def __sub__(self, other):
- return self
- @_sympifyit('other', NotImplemented)
- def __mul__(self, other):
- return self
- @_sympifyit('other', NotImplemented)
- def __truediv__(self, other):
- return self
- def floor(self):
- return self
- def ceiling(self):
- return self
- def _as_mpf_val(self, prec):
- return _mpf_nan
- def __hash__(self):
- return super().__hash__()
- def __eq__(self, other):
- # NaN is structurally equal to another NaN
- return other is S.NaN
- def __ne__(self, other):
- return other is not S.NaN
- # Expr will _sympify and raise TypeError
- __gt__ = Expr.__gt__
- __ge__ = Expr.__ge__
- __lt__ = Expr.__lt__
- __le__ = Expr.__le__
- nan = S.NaN
- @dispatch(NaN, Expr) # type:ignore
- def _eval_is_eq(a, b): # noqa:F811
- return False
- class ComplexInfinity(AtomicExpr, metaclass=Singleton):
- r"""Complex infinity.
- Explanation
- ===========
- In complex analysis the symbol `\tilde\infty`, called "complex
- infinity", represents a quantity with infinite magnitude, but
- undetermined complex phase.
- ComplexInfinity is a singleton, and can be accessed by
- ``S.ComplexInfinity``, or can be imported as ``zoo``.
- Examples
- ========
- >>> from sympy import zoo
- >>> zoo + 42
- zoo
- >>> 42/zoo
- 0
- >>> zoo + zoo
- nan
- >>> zoo*zoo
- zoo
- See Also
- ========
- Infinity
- """
- is_commutative = True
- is_infinite = True
- is_number = True
- is_prime = False
- is_complex = False
- is_extended_real = False
- kind = NumberKind
- __slots__ = ()
- def __new__(cls):
- return AtomicExpr.__new__(cls)
- def _latex(self, printer):
- return r"\tilde{\infty}"
- @staticmethod
- def __abs__():
- return S.Infinity
- def floor(self):
- return self
- def ceiling(self):
- return self
- @staticmethod
- def __neg__():
- return S.ComplexInfinity
- def _eval_power(self, expt):
- if expt is S.ComplexInfinity:
- return S.NaN
- if isinstance(expt, Number):
- if expt.is_zero:
- return S.NaN
- else:
- if expt.is_positive:
- return S.ComplexInfinity
- else:
- return S.Zero
- zoo = S.ComplexInfinity
- class NumberSymbol(AtomicExpr):
- is_commutative = True
- is_finite = True
- is_number = True
- __slots__ = ()
- is_NumberSymbol = True
- kind = NumberKind
- def __new__(cls):
- return AtomicExpr.__new__(cls)
- def approximation(self, number_cls):
- """ Return an interval with number_cls endpoints
- that contains the value of NumberSymbol.
- If not implemented, then return None.
- """
- def _eval_evalf(self, prec):
- return Float._new(self._as_mpf_val(prec), prec)
- def __eq__(self, other):
- try:
- other = _sympify(other)
- except SympifyError:
- return NotImplemented
- if self is other:
- return True
- if other.is_Number and self.is_irrational:
- return False
- return False # NumberSymbol != non-(Number|self)
- def __ne__(self, other):
- return not self == other
- def __le__(self, other):
- if self is other:
- return S.true
- return Expr.__le__(self, other)
- def __ge__(self, other):
- if self is other:
- return S.true
- return Expr.__ge__(self, other)
- def __int__(self):
- # subclass with appropriate return value
- raise NotImplementedError
- def __hash__(self):
- return super().__hash__()
- class Exp1(NumberSymbol, metaclass=Singleton):
- r"""The `e` constant.
- Explanation
- ===========
- The transcendental number `e = 2.718281828\ldots` is the base of the
- natural logarithm and of the exponential function, `e = \exp(1)`.
- Sometimes called Euler's number or Napier's constant.
- Exp1 is a singleton, and can be accessed by ``S.Exp1``,
- or can be imported as ``E``.
- Examples
- ========
- >>> from sympy import exp, log, E
- >>> E is exp(1)
- True
- >>> log(E)
- 1
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/E_%28mathematical_constant%29
- """
- is_real = True
- is_positive = True
- is_negative = False # XXX Forces is_negative/is_nonnegative
- is_irrational = True
- is_number = True
- is_algebraic = False
- is_transcendental = True
- __slots__ = ()
- def _latex(self, printer):
- return r"e"
- @staticmethod
- def __abs__():
- return S.Exp1
- def __int__(self):
- return 2
- def _as_mpf_val(self, prec):
- return mpf_e(prec)
- def approximation_interval(self, number_cls):
- if issubclass(number_cls, Integer):
- return (Integer(2), Integer(3))
- elif issubclass(number_cls, Rational):
- pass
- def _eval_power(self, expt):
- if global_parameters.exp_is_pow:
- return self._eval_power_exp_is_pow(expt)
- else:
- from sympy.functions.elementary.exponential import exp
- return exp(expt)
- def _eval_power_exp_is_pow(self, arg):
- if arg.is_Number:
- if arg is oo:
- return oo
- elif arg == -oo:
- return S.Zero
- from sympy.functions.elementary.exponential import log
- if isinstance(arg, log):
- return arg.args[0]
- # don't autoexpand Pow or Mul (see the issue 3351):
- elif not arg.is_Add:
- Ioo = I*oo
- if arg in [Ioo, -Ioo]:
- return nan
- coeff = arg.coeff(pi*I)
- if coeff:
- if (2*coeff).is_integer:
- if coeff.is_even:
- return S.One
- elif coeff.is_odd:
- return S.NegativeOne
- elif (coeff + S.Half).is_even:
- return -I
- elif (coeff + S.Half).is_odd:
- return I
- elif coeff.is_Rational:
- ncoeff = coeff % 2 # restrict to [0, 2pi)
- if ncoeff > 1: # restrict to (-pi, pi]
- ncoeff -= 2
- if ncoeff != coeff:
- return S.Exp1**(ncoeff*S.Pi*S.ImaginaryUnit)
- # Warning: code in risch.py will be very sensitive to changes
- # in this (see DifferentialExtension).
- # look for a single log factor
- coeff, terms = arg.as_coeff_Mul()
- # but it can't be multiplied by oo
- if coeff in (oo, -oo):
- return
- coeffs, log_term = [coeff], None
- for term in Mul.make_args(terms):
- if isinstance(term, log):
- if log_term is None:
- log_term = term.args[0]
- else:
- return
- elif term.is_comparable:
- coeffs.append(term)
- else:
- return
- return log_term**Mul(*coeffs) if log_term else None
- elif arg.is_Add:
- out = []
- add = []
- argchanged = False
- for a in arg.args:
- if a is S.One:
- add.append(a)
- continue
- newa = self**a
- if isinstance(newa, Pow) and newa.base is self:
- if newa.exp != a:
- add.append(newa.exp)
- argchanged = True
- else:
- add.append(a)
- else:
- out.append(newa)
- if out or argchanged:
- return Mul(*out)*Pow(self, Add(*add), evaluate=False)
- elif arg.is_Matrix:
- return arg.exp()
- def _eval_rewrite_as_sin(self, **kwargs):
- from sympy.functions.elementary.trigonometric import sin
- return sin(I + S.Pi/2) - I*sin(I)
- def _eval_rewrite_as_cos(self, **kwargs):
- from sympy.functions.elementary.trigonometric import cos
- return cos(I) + I*cos(I + S.Pi/2)
- E = S.Exp1
- class Pi(NumberSymbol, metaclass=Singleton):
- r"""The `\pi` constant.
- Explanation
- ===========
- The transcendental number `\pi = 3.141592654\ldots` represents the ratio
- of a circle's circumference to its diameter, the area of the unit circle,
- the half-period of trigonometric functions, and many other things
- in mathematics.
- Pi is a singleton, and can be accessed by ``S.Pi``, or can
- be imported as ``pi``.
- Examples
- ========
- >>> from sympy import S, pi, oo, sin, exp, integrate, Symbol
- >>> S.Pi
- pi
- >>> pi > 3
- True
- >>> pi.is_irrational
- True
- >>> x = Symbol('x')
- >>> sin(x + 2*pi)
- sin(x)
- >>> integrate(exp(-x**2), (x, -oo, oo))
- sqrt(pi)
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/Pi
- """
- is_real = True
- is_positive = True
- is_negative = False
- is_irrational = True
- is_number = True
- is_algebraic = False
- is_transcendental = True
- __slots__ = ()
- def _latex(self, printer):
- return r"\pi"
- @staticmethod
- def __abs__():
- return S.Pi
- def __int__(self):
- return 3
- def _as_mpf_val(self, prec):
- return mpf_pi(prec)
- def approximation_interval(self, number_cls):
- if issubclass(number_cls, Integer):
- return (Integer(3), Integer(4))
- elif issubclass(number_cls, Rational):
- return (Rational(223, 71, 1), Rational(22, 7, 1))
- pi = S.Pi
- class GoldenRatio(NumberSymbol, metaclass=Singleton):
- r"""The golden ratio, `\phi`.
- Explanation
- ===========
- `\phi = \frac{1 + \sqrt{5}}{2}` is an algebraic number. Two quantities
- are in the golden ratio if their ratio is the same as the ratio of
- their sum to the larger of the two quantities, i.e. their maximum.
- GoldenRatio is a singleton, and can be accessed by ``S.GoldenRatio``.
- Examples
- ========
- >>> from sympy import S
- >>> S.GoldenRatio > 1
- True
- >>> S.GoldenRatio.expand(func=True)
- 1/2 + sqrt(5)/2
- >>> S.GoldenRatio.is_irrational
- True
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/Golden_ratio
- """
- is_real = True
- is_positive = True
- is_negative = False
- is_irrational = True
- is_number = True
- is_algebraic = True
- is_transcendental = False
- __slots__ = ()
- def _latex(self, printer):
- return r"\phi"
- def __int__(self):
- return 1
- def _as_mpf_val(self, prec):
- # XXX track down why this has to be increased
- rv = mlib.from_man_exp(phi_fixed(prec + 10), -prec - 10)
- return mpf_norm(rv, prec)
- def _eval_expand_func(self, **hints):
- from sympy.functions.elementary.miscellaneous import sqrt
- return S.Half + S.Half*sqrt(5)
- def approximation_interval(self, number_cls):
- if issubclass(number_cls, Integer):
- return (S.One, Rational(2))
- elif issubclass(number_cls, Rational):
- pass
- _eval_rewrite_as_sqrt = _eval_expand_func
- class TribonacciConstant(NumberSymbol, metaclass=Singleton):
- r"""The tribonacci constant.
- Explanation
- ===========
- The tribonacci numbers are like the Fibonacci numbers, but instead
- of starting with two predetermined terms, the sequence starts with
- three predetermined terms and each term afterwards is the sum of the
- preceding three terms.
- The tribonacci constant is the ratio toward which adjacent tribonacci
- numbers tend. It is a root of the polynomial `x^3 - x^2 - x - 1 = 0`,
- and also satisfies the equation `x + x^{-3} = 2`.
- TribonacciConstant is a singleton, and can be accessed
- by ``S.TribonacciConstant``.
- Examples
- ========
- >>> from sympy import S
- >>> S.TribonacciConstant > 1
- True
- >>> S.TribonacciConstant.expand(func=True)
- 1/3 + (19 - 3*sqrt(33))**(1/3)/3 + (3*sqrt(33) + 19)**(1/3)/3
- >>> S.TribonacciConstant.is_irrational
- True
- >>> S.TribonacciConstant.n(20)
- 1.8392867552141611326
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/Generalizations_of_Fibonacci_numbers#Tribonacci_numbers
- """
- is_real = True
- is_positive = True
- is_negative = False
- is_irrational = True
- is_number = True
- is_algebraic = True
- is_transcendental = False
- __slots__ = ()
- def _latex(self, printer):
- return r"\text{TribonacciConstant}"
- def __int__(self):
- return 1
- def _eval_evalf(self, prec):
- rv = self._eval_expand_func(function=True)._eval_evalf(prec + 4)
- return Float(rv, precision=prec)
- def _eval_expand_func(self, **hints):
- from sympy.functions.elementary.miscellaneous import cbrt, sqrt
- return (1 + cbrt(19 - 3*sqrt(33)) + cbrt(19 + 3*sqrt(33))) / 3
- def approximation_interval(self, number_cls):
- if issubclass(number_cls, Integer):
- return (S.One, Rational(2))
- elif issubclass(number_cls, Rational):
- pass
- _eval_rewrite_as_sqrt = _eval_expand_func
- class EulerGamma(NumberSymbol, metaclass=Singleton):
- r"""The Euler-Mascheroni constant.
- Explanation
- ===========
- `\gamma = 0.5772157\ldots` (also called Euler's constant) is a mathematical
- constant recurring in analysis and number theory. It is defined as the
- limiting difference between the harmonic series and the
- natural logarithm:
- .. math:: \gamma = \lim\limits_{n\to\infty}
- \left(\sum\limits_{k=1}^n\frac{1}{k} - \ln n\right)
- EulerGamma is a singleton, and can be accessed by ``S.EulerGamma``.
- Examples
- ========
- >>> from sympy import S
- >>> S.EulerGamma.is_irrational
- >>> S.EulerGamma > 0
- True
- >>> S.EulerGamma > 1
- False
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/Euler%E2%80%93Mascheroni_constant
- """
- is_real = True
- is_positive = True
- is_negative = False
- is_irrational = None
- is_number = True
- __slots__ = ()
- def _latex(self, printer):
- return r"\gamma"
- def __int__(self):
- return 0
- def _as_mpf_val(self, prec):
- # XXX track down why this has to be increased
- v = mlib.libhyper.euler_fixed(prec + 10)
- rv = mlib.from_man_exp(v, -prec - 10)
- return mpf_norm(rv, prec)
- def approximation_interval(self, number_cls):
- if issubclass(number_cls, Integer):
- return (S.Zero, S.One)
- elif issubclass(number_cls, Rational):
- return (S.Half, Rational(3, 5, 1))
- class Catalan(NumberSymbol, metaclass=Singleton):
- r"""Catalan's constant.
- Explanation
- ===========
- $G = 0.91596559\ldots$ is given by the infinite series
- .. math:: G = \sum_{k=0}^{\infty} \frac{(-1)^k}{(2k+1)^2}
- Catalan is a singleton, and can be accessed by ``S.Catalan``.
- Examples
- ========
- >>> from sympy import S
- >>> S.Catalan.is_irrational
- >>> S.Catalan > 0
- True
- >>> S.Catalan > 1
- False
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/Catalan%27s_constant
- """
- is_real = True
- is_positive = True
- is_negative = False
- is_irrational = None
- is_number = True
- __slots__ = ()
- def __int__(self):
- return 0
- def _as_mpf_val(self, prec):
- # XXX track down why this has to be increased
- v = mlib.catalan_fixed(prec + 10)
- rv = mlib.from_man_exp(v, -prec - 10)
- return mpf_norm(rv, prec)
- def approximation_interval(self, number_cls):
- if issubclass(number_cls, Integer):
- return (S.Zero, S.One)
- elif issubclass(number_cls, Rational):
- return (Rational(9, 10, 1), S.One)
- def _eval_rewrite_as_Sum(self, k_sym=None, symbols=None):
- if (k_sym is not None) or (symbols is not None):
- return self
- from .symbol import Dummy
- from sympy.concrete.summations import Sum
- k = Dummy('k', integer=True, nonnegative=True)
- return Sum(S.NegativeOne**k / (2*k+1)**2, (k, 0, S.Infinity))
- def _latex(self, printer):
- return "G"
- class ImaginaryUnit(AtomicExpr, metaclass=Singleton):
- r"""The imaginary unit, `i = \sqrt{-1}`.
- I is a singleton, and can be accessed by ``S.I``, or can be
- imported as ``I``.
- Examples
- ========
- >>> from sympy import I, sqrt
- >>> sqrt(-1)
- I
- >>> I*I
- -1
- >>> 1/I
- -I
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/Imaginary_unit
- """
- is_commutative = True
- is_imaginary = True
- is_finite = True
- is_number = True
- is_algebraic = True
- is_transcendental = False
- kind = NumberKind
- __slots__ = ()
- def _latex(self, printer):
- return printer._settings['imaginary_unit_latex']
- @staticmethod
- def __abs__():
- return S.One
- def _eval_evalf(self, prec):
- return self
- def _eval_conjugate(self):
- return -S.ImaginaryUnit
- def _eval_power(self, expt):
- """
- b is I = sqrt(-1)
- e is symbolic object but not equal to 0, 1
- I**r -> (-1)**(r/2) -> exp(r/2*Pi*I) -> sin(Pi*r/2) + cos(Pi*r/2)*I, r is decimal
- I**0 mod 4 -> 1
- I**1 mod 4 -> I
- I**2 mod 4 -> -1
- I**3 mod 4 -> -I
- """
- if isinstance(expt, Integer):
- expt = expt % 4
- if expt == 0:
- return S.One
- elif expt == 1:
- return S.ImaginaryUnit
- elif expt == 2:
- return S.NegativeOne
- elif expt == 3:
- return -S.ImaginaryUnit
- if isinstance(expt, Rational):
- i, r = divmod(expt, 2)
- rv = Pow(S.ImaginaryUnit, r, evaluate=False)
- if i % 2:
- return Mul(S.NegativeOne, rv, evaluate=False)
- return rv
- def as_base_exp(self):
- return S.NegativeOne, S.Half
- @property
- def _mpc_(self):
- return (Float(0)._mpf_, Float(1)._mpf_)
- I = S.ImaginaryUnit
- def equal_valued(x, y):
- """Compare expressions treating plain floats as rationals.
- Examples
- ========
- >>> from sympy import S, symbols, Rational, Float
- >>> from sympy.core.numbers import equal_valued
- >>> equal_valued(1, 2)
- False
- >>> equal_valued(1, 1)
- True
- In SymPy expressions with Floats compare unequal to corresponding
- expressions with rationals:
- >>> x = symbols('x')
- >>> x**2 == x**2.0
- False
- However an individual Float compares equal to a Rational:
- >>> Rational(1, 2) == Float(0.5)
- True
- In a future version of SymPy this might change so that Rational and Float
- compare unequal. This function provides the behavior currently expected of
- ``==`` so that it could still be used if the behavior of ``==`` were to
- change in future.
- >>> equal_valued(1, 1.0) # Float vs Rational
- True
- >>> equal_valued(S(1).n(3), S(1).n(5)) # Floats of different precision
- True
- Explanation
- ===========
- In future SymPy verions Float and Rational might compare unequal and floats
- with different precisions might compare unequal. In that context a function
- is needed that can check if a number is equal to 1 or 0 etc. The idea is
- that instead of testing ``if x == 1:`` if we want to accept floats like
- ``1.0`` as well then the test can be written as ``if equal_valued(x, 1):``
- or ``if equal_valued(x, 2):``. Since this function is intended to be used
- in situations where one or both operands are expected to be concrete
- numbers like 1 or 0 the function does not recurse through the args of any
- compound expression to compare any nested floats.
- References
- ==========
- .. [1] https://github.com/sympy/sympy/pull/20033
- """
- x = _sympify(x)
- y = _sympify(y)
- # Handle everything except Float/Rational first
- if not x.is_Float and not y.is_Float:
- return x == y
- elif x.is_Float and y.is_Float:
- # Compare values without regard for precision
- return x._mpf_ == y._mpf_
- elif x.is_Float:
- x, y = y, x
- if not x.is_Rational:
- return False
- # Now y is Float and x is Rational. A simple approach at this point would
- # just be x == Rational(y) but if y has a large exponent creating a
- # Rational could be prohibitively expensive.
- sign, man, exp, _ = y._mpf_
- p, q = x.p, x.q
- if sign:
- man = -man
- if exp == 0:
- # y odd integer
- return q == 1 and man == p
- elif exp > 0:
- # y even integer
- if q != 1:
- return False
- if p.bit_length() != man.bit_length() + exp:
- return False
- return man << exp == p
- else:
- # y non-integer. Need p == man and q == 2**-exp
- if p != man:
- return False
- neg_exp = -exp
- if q.bit_length() - 1 != neg_exp:
- return False
- return (1 << neg_exp) == q
- @dispatch(Tuple, Number) # type:ignore
- def _eval_is_eq(self, other): # noqa: F811
- return False
- def sympify_fractions(f):
- return Rational(f.numerator, f.denominator, 1)
- _sympy_converter[fractions.Fraction] = sympify_fractions
- if HAS_GMPY:
- def sympify_mpz(x):
- return Integer(int(x))
- # XXX: The sympify_mpq function here was never used because it is
- # overridden by the other sympify_mpq function below. Maybe it should just
- # be removed or maybe it should be used for something...
- def sympify_mpq(x):
- return Rational(int(x.numerator), int(x.denominator))
- _sympy_converter[type(gmpy.mpz(1))] = sympify_mpz
- _sympy_converter[type(gmpy.mpq(1, 2))] = sympify_mpq
- def sympify_mpmath_mpq(x):
- p, q = x._mpq_
- return Rational(p, q, 1)
- _sympy_converter[type(mpmath.rational.mpq(1, 2))] = sympify_mpmath_mpq
- def sympify_mpmath(x):
- return Expr._from_mpmath(x, x.context.prec)
- _sympy_converter[mpnumeric] = sympify_mpmath
- def sympify_complex(a):
- real, imag = list(map(sympify, (a.real, a.imag)))
- return real + S.ImaginaryUnit*imag
- _sympy_converter[complex] = sympify_complex
- from .power import Pow, integer_nthroot
- from .mul import Mul
- Mul.identity = One()
- from .add import Add
- Add.identity = Zero()
- def _register_classes():
- numbers.Number.register(Number)
- numbers.Real.register(Float)
- numbers.Rational.register(Rational)
- numbers.Integral.register(Integer)
- _register_classes()
- _illegal = (S.NaN, S.Infinity, S.NegativeInfinity, S.ComplexInfinity)
|