K i $ddlmZddlmZddlmZmZmZmZm Z m Z m Z m Z ddl mZddlmZmZmZmZmZmZmZddlmZmZddlmZddlmZdd lmZm Z m!Z!dd l"m#Z#dd l$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-dd l$m.Z.dd l/m0Z0ddl1m2Z2ddl3m4Z4m5Z5m6Z6m7Z7ddl8m9Z9ddl:m;Z;ddlm?Z?ddl@mAZAddlBmCZCddlDmEZEddlFmGZGgdddfdZHe2e0fZIdZJd0dZKdZLddd ZMd!ZNd"aOd#ZPd$ZQd%ZRd&ZSd'ZTd(ZUd0d)ZVed0d*ZWdd+d,ZXd-ZYd.ZZd1d/Z[y")2) defaultdict)reduce)sympifyBasicSExpr factor_termsMulAdd bottom_up)cacheit) count_ops_mexpand FunctionClassexpand expand_mul _coeff_isneg Derivative)IInteger)igcd)_nodes)DummysymbolsWild) SYMPY_INTS) sincosexpcoshtanhsinhtancotcoth)atan2)HyperbolicFunction)TrigonometricFunction)Polyfactorcancelparallel_poly_from_expr)ZZ)PolificationFailed)groebner)cse)identity)greedy)iterable)debugFgrlexc ddfd}td|jtj}tjfg}t |j \}} t ||g\\} } } td| j|| j|\} } }td| td|dt|td | dt||s|St| ||t }td t|dt|d d lm}| r| j t#|j%| jrt'||| zj(|}g}|j+D]}\}}t#t ||gdj}d}|rd}| D]}t'|}|j-|jr*|j t#|jj/|r\d}|j1|j3j|r|Dcgc] }||vs| }}|j4Dcgc]:}|j |j%|jr|j7<}}|j9t;t=| |Dcgc] \}}||z c}}|||z ||||t|j|zt?|S||t||| |z|t|j|S#t$r|cYSwxYwcc}wcc}wcc}}w)a Simplify trigonometric expressions using a groebner basis algorithm. Explanation =========== This routine takes a fraction involving trigonometric or hyperbolic expressions, and tries to simplify it. The primary metric is the total degree. Some attempts are made to choose the simplest possible expression of the minimal degree, but this is non-rigorous, and also very slow (see the ``quick=True`` option). If ``polynomial`` is set to True, instead of simplifying numerator and denominator together, this function just brings numerator and denominator into a canonical form. This is much faster, but has potentially worse results. However, if the input is a polynomial, then the result is guaranteed to be an equivalent polynomial of minimal degree. The most important option is hints. Its entries can be any of the following: - a natural number - a function - an iterable of the form (func, var1, var2, ...) - anything else, interpreted as a generator A number is used to indicate that the search space should be increased. A function is used to indicate that said function is likely to occur in a simplified expression. An iterable is used indicate that func(var1 + var2 + ...) is likely to occur in a simplified . An additional generator also indicates that it is likely to occur. (See examples below). This routine carries out various computationally intensive algorithms. The option ``quick=True`` can be used to suppress one particularly slow step (at the expense of potentially more complicated results, but never at the expense of increased total degree). Examples ======== >>> from sympy.abc import x, y >>> from sympy import sin, tan, cos, sinh, cosh, tanh >>> from sympy.simplify.trigsimp import trigsimp_groebner Suppose you want to simplify ``sin(x)*cos(x)``. Naively, nothing happens: >>> ex = sin(x)*cos(x) >>> trigsimp_groebner(ex) sin(x)*cos(x) This is because ``trigsimp_groebner`` only looks for a simplification involving just ``sin(x)`` and ``cos(x)``. You can tell it to also try ``2*x`` by passing ``hints=[2]``: >>> trigsimp_groebner(ex, hints=[2]) sin(2*x)/2 >>> trigsimp_groebner(sin(x)**2 - cos(x)**2, hints=[2]) -cos(2*x) Increasing the search space this way can quickly become expensive. A much faster way is to give a specific expression that is likely to occur: >>> trigsimp_groebner(ex, hints=[sin(2*x)]) sin(2*x)/2 Hyperbolic expressions are similarly supported: >>> trigsimp_groebner(sinh(2*x)/sinh(x)) 2*cosh(x) Note how no hints had to be passed, since the expression already involved ``2*x``. The tangent function is also supported. You can either pass ``tan`` in the hints, to indicate that tan should be tried whenever cosine or sine are, or you can pass a specific generator: >>> trigsimp_groebner(sin(x)/cos(x), hints=[tan]) tan(x) >>> trigsimp_groebner(sinh(x)/cosh(x), hints=[tanh(x)]) tanh(x) Finally, you can use the iterable form to suggest that angle sum formulae should be tried: >>> ex = (tan(x) + tan(y))/(1 - tan(x)*tan(y)) >>> trigsimp_groebner(ex, hints=[(tan, x, y)]) tan(x + y) c d}ggg}}}|D]}t|ttfr|}t|tr|j |>t |rq|j |d|ddf|j t|ddDcgc] }|d|c}|dt|ddgzdj|j |||||fScc}w)z-Split hints into (n, funcs, iterables, gens).rN) isinstancerrrappendr3extendr,r gens)hintsnfuncs iterablesr<exs ]/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/simplify/trigsimp.py parse_hintsz&trigsimp_groebner..parse_hintss !#R$y A!j'23A}- Q!  !A$!"/ 3&'e,TQqT!W,!S!AB%[0A/BBDDEGGKtM A %D((-sCc ~g}td}|D]\}}tttt|dzt|dzzdz gtt t t |dzt |dzz dz gfD]\}}}} |dk(r|||fvr|j| &||k(r4|j|||z|||zz|||zz _|||fvsf|||zjdj||} |j|||z| z tt|S)av Build generators for our ideal. ``Terms`` is an iterable with elements of the form (fn, coeff), indicating that we have a generator fn(coeff*x). If any of the terms is trigonometric, sin(x) and cos(x) are guaranteed to appear in terms. Similarly for hyperbolic functions. For tan(n*x), sin(n*x) and cos(n*x) are guaranteed. yr8Ttrig) rrrr#r r"r!r:rsubslistset) rBtermsrrFfncoeffcstrelcns rC build_idealz&trigsimp_groebner..build_ideals@  #J /IB#sCFAIA $9A$=>4tAwzDGQJ'>'BC!E / 1aA:"A,AHHSM1WAHHQuQwZ%' 2QuQwZ?@Aq6\E!G+++6;;AqABAHHRa[2-. / /CF|c l "|\}}}}td|||ft|}|j|tt|}tt|}tt|}tt t ttth}|Dcgc]9}|j|vr)|jdj|jf;}}|Dcgc]}|j|vs|} }g} i} |D]+\\} } | j| gj| f-g}| jD]7\}}|Dcgc]}|d }}|Dcgc]}|d }}t!t"|}t%||Dcgc] \}}|||z f}}}t||zt tt gtttgfD]@\}}}t'fd|||fDsj)|j)|BD])|jfdt+d|dzD+g}|D]\}t k(r.|jt|f|jt |ftt fvrt vr|jt |ftk(r.|jt|f|jt|fttfvstvs|jt|f|j||t-|z} ||}|j|| j|Dchc]\}}|||zc}}:|D]\}t k(r |jt|ft |fg/tk(r |jt|ft|fgXt/dt1|zt2}t5|j7d j9tt%||}|jt5||z !|vr9|j!d zdz| j;!| j!|| | fScc}wcc}wcc}wcc}wcc}}wcc}}w) z Analyse the generators ``gens``, using the hints ``hints``. The meaning of ``hints`` is described in the main docstring. Return a new list of generators, and also the ideal we should work with. z1n=%s funcs: %s iterables: %s extragens: %srr8c3&K|]}|v ywN).0rBfss rC z:trigsimp_groebner..analyse_gens..6s21qBw2c3&K|]}|f ywrYrZ)r[krNs rCr]z:trigsimp_groebner..analyse_gens..:s>b!W>r^zd:%iclsTrHrG)r4rKr;rLrrr#r"r r!funcargs as_coeff_mul setdefaultr:itemsrrzipanyaddranger rlenrr rrJremove)#r<r=r>r?r@ extragensallfuncsg trigtermsfreegensnewgenstrigdictrOvarreskeyvalrBfnsgcdrNvrMrPrQrRextrarrddummysexprr\rUmyIrDs# ` @rC analyse_gensz'trigsimp_groebner..analyse_genssK*5U);&5)Y Ai+ -Dz ISZ Y( CIc4t4AE,A(*ffQi,,.7, , $>!qvvX'=A>> ) = LUC"   R ( / / < = (, 9HC""%%A1Q4%C%!$%A1Q4%C%s#C03C >Wb!b!C%[>E>US[!B #sOdD$-?@ 1a2Aq 22FF1IFF1I  ? >eAq1uo>> ?E ,A9LL#q*LL#q*#s#r LL#q*:LL$+LL$+$%$"*LL$+ , LL CI AAu%A JJqM NN7ABqsG7 8Y, 9^" 2HBSy  3+T{!;<t  4,t !=> #d)!3?3<(//T/:??SQUEV@WX 2c4j>D01 2 $; JJsAvz " OOC NN3 Hg%%W,?0&%>08s*>R R4R R  R% R*R0 rz initial gens:zideal:z new gens:z -- lenz free gens:)orderr<domainzgroebner basis:r)ratsimpmodprime)r<r8TF)rr<quickr polynomial) rrJr ImaginaryUnitr+as_numer_denomr,r.r4r<rlr/r-rKsympy.simplify.ratsimpr has_only_gensrL intersectionr)ejectrM issuperset differenceupdateexcludepolysas_exprr:r rhr ) rr=rrrrrJnumdenompnumpdenomoptidealrrr<GrrvmonomrOourgenschangedprBrealgensrpourGabrUrrDs @@@rCtrigsimp_groebnerrsf)(0d&L *C 99Q__c *D !// " #D,,.JC5sElCv /388$(59E8T (E +tYD 2 ,)SY7  e$r:A T!WiQ8 7(F((#d)*@*@*MN1d3T(]+1148IIK JLE515%.A!DIIJGG9AQA"--aff5*1??CK,B,B7,KL"&qyy{'7'78 9$(8a1<8H8*+DA#AOOW%9%9!&&%ABIIKDDD JJsc(E.BCdaQTCD&uU{D,4E"2<>>Bd4jI J5 J<Cy $q'Xd]z;;?4: F{  H9DCs*,L> MM'?MM> M  M c0dfdt|S)Nc` |jd|jdk(S#t$rYywxYw)NrF)rd IndexError)rBrFs rC check_argsz%_trigsimp_inverse..check_argss4 66!9q ) )  s ! --ct|dd}|Ut|jd|r7t|dtr|jdjdSt|tr|j\}}t |rt | | St |r$t jt || z S||rrt|trt|tr|jdSt|tr3t|tr#t jdz |jdz S|S)Ninverserr8rG) getattrr9rdr(r&rrPirr)rvrprFrBrfs rCrz_trigsimp_inverse..fs B 4 ( MjQS9313q6#89771:??1% % b% 77DAqA%A,''attaa! o--!Qa%*Q*<66!9$a%*Q*<44!8affQi// rV)r )rrrs @@rC_trigsimp_inversers . R rVc Z ddlmt|}t|dd}||diSj dd}|s7j ddj ddj d d }nd}d fd d fd fdfdd|}||}|r t |}|S)a6Returns a reduced expression by using known trig identities. Parameters ========== inverse : bool, optional If ``inverse=True``, it will be assumed that a composition of inverse functions, such as sin and asin, can be cancelled in any order. For example, ``asin(sin(x))`` will yield ``x`` without checking whether x belongs to the set where this relation is true. The default is False. Default : True method : string, optional Specifies the method to use. Valid choices are: - ``'matching'``, default - ``'groebner'`` - ``'combined'`` - ``'fu'`` - ``'old'`` If ``'matching'``, simplify the expression recursively by targeting common patterns. If ``'groebner'``, apply an experimental groebner basis algorithm. In this case further options are forwarded to ``trigsimp_groebner``, please refer to its docstring. If ``'combined'``, it first runs the groebner basis algorithm with small default parameters, then runs the ``'matching'`` algorithm. If ``'fu'``, run the collection of trigonometric transformations described by Fu, et al. (see the :py:func:`~sympy.simplify.fu.fu` docstring). If ``'old'``, the original SymPy trig simplification function is run. opts : Optional keyword arguments passed to the method. See each method's function docstring for details. Examples ======== >>> from sympy import trigsimp, sin, cos, log >>> from sympy.abc import x >>> e = 2*sin(x)**2 + 2*cos(x)**2 >>> trigsimp(e) 2 Simplification occurs wherever trigonometric functions are located. >>> trigsimp(log(e)) log(2) Using ``method='groebner'`` (or ``method='combined'``) might lead to greater simplification. The old trigsimp routine can be accessed as with method ``method='old'``. >>> from sympy import coth, tanh >>> t = 3*tanh(x)**7 - 2/coth(x)**7 >>> trigsimp(t, method='old') == t True >>> trigsimp(t) tanh(x)**7 r)fu_eval_trigsimpNoldFdeep recursivemethodmatchingc^fd|}t|ts|St|fiS)Nc|jr|S|jDcgc] }| }}|js |jr|Dcgc]}t |fi}}|j |Scc}wcc}wrYis_Atomrd is_Functionis_PowrrcrArBrdoptstraverses rCrz0trigsimp..groebnersimp..traversemyy)*0AHQK0D0}}>BC)!4t4CC1664= 1C A/ A4)r9rr)exrnewrs ` @rC groebnersimpztrigsimp..groebnersimps2 !rl#t$J ---rVc|fiSrYrZ)rBrrs rCztrigsimp..,sArVct|SrY)futrigrBs rCrztrigsimp..-s vayrVc|fiSrYrZ)rBrrs rCrztrigsimp...s|A66rVc8t|ddtgSNTrG)rr=)rr#)rBrs rCrztrigsimp../s vl1*.q#h'@ ArVct|fiSrY) trigsimp_old)rBrs rCrztrigsimp..1sa040rV)rrr/combinedrrZ)sympy.simplify.furrrpopr) rrrrrr trigsimpfuncexpr_simplifiedrrs ` @@rCtrigsimprs~% 4=DT#3T:N!%%% ((5% C   d#(J/ .'(6A0 L#4(O+O< rVcFddlm}m}d}t||}fdt|}|j t r||\}||}|j t r||}|j tr|j tr|}|S)a# Simplifies exponential / trigonometric / hyperbolic functions. Examples ======== >>> from sympy import exptrigsimp, exp, cosh, sinh >>> from sympy.abc import z >>> exptrigsimp(exp(z) + exp(-z)) 2*cosh(z) >>> exptrigsimp(cosh(z) - sinh(z)) exp(-z) r) hyper_as_trigTR2ic|g}|jtr$|j|jt|j|jt t |dtiS)Nrw)has_trigsr:rewriterrminr)rAchoicess rCexp_trigzexptrigsimp..exp_trigLsP# 155&> NN199S> *qyy~&G+++rVcx |js|S|j\}}t|dkDr t|t|zS|j }|j }t jf fd |t j}|D]}|jst|jdk(s*|jd} |jd|z \}} | sW||} ||xx| zcc<|| | zdz k(rb|t jxx|zcc<d}|dk(r |d|zt| dz zxx| z cc<|d|zt| dz zxx| z cc<|d|t j| zzz | k(r]|d|t j| zzz =|dk(r|| t| dz z xx| z cc<5|| t| dz zxx| z cc<T|d|t j| zzzxx| z cc<||xx| z cc<t|Dcgc] }|||z c}Scc}w)Nr8c4|tjur|tjfSt|ts)|j r+|j tjk(r||jfS|tjur| tj Sy)N)sign)NN)rExp1Oner9rrbase)rrsignlogs rCrz'exptrigsimp..f..signlogbslqvv~QUU{"D#&4;;499;NTXX~%uAEE622!rVrGr)is_Mulargs_cncrlr as_powers_dictcopyrrris_Addrdr r"r!) rcommutative_partnoncommutative_partrvdnewdeer`rPrrBmrrs @rCrzexptrigsimp..fVs%yyI02 -- # $q (S*+,S2E-FF F!xxz uu "[ !AxxCK1,FF1I!!&&)A+.aFQ1 !Aa<LB&LBqyQqSac]+q0+RT$qs)^,1,!d16619n,-!3Qaffai/0qyaRQqS \*a/*aRQqS \*a/*T!&&!)^+,1,GqLG5 !8.AQQZ.//.s$H7)rrrr rr'r(r)rrrrnewexprrArs @rC exptrigsimpr;s6,h'G30h#G{{%&W%1DG*{{()w- KKN488A; KrVT)firstc |}|r-|jts|Stj|jtDcgc]}|j c}}t |dkDrddlm}||}|jr||dxs|}t|trDd}|jD],}|} t|}dd<t|fi} | |k(r| } || z}.|}nN|jrB|D];} |j!| \} } | sdd<| t| fiz}|jr;n|}j#dd}j#d d}j#d d }d d fdfdd|}|rNt%|\}}||d|}t'|D]#}|j)|d|d}|||}%|}n |||}j+ddrt-|}||k7r t/d||Scc}w)aC Reduces expression by using known trig identities. Notes ===== deep: - Apply trigsimp inside all objects with arguments recursive: - Use common subexpression elimination (cse()) and apply trigsimp recursively (this is quite expensive if the expression is large) method: - Determine the method to use. Valid choices are 'matching' (default), 'groebner', 'combined', 'fu' and 'futrig'. If 'matching', simplify the expression recursively by pattern matching. If 'groebner', apply an experimental groebner basis algorithm. In this case further options are forwarded to ``trigsimp_groebner``, please refer to its docstring. If 'combined', first run the groebner basis algorithm with small default parameters, then run the 'matching' algorithm. 'fu' runs the collection of trigonometric transformations described by Fu, et al. (see the `fu` docstring) while `futrig` runs a subset of Fu-transforms that mimic the behavior of `trigsimp`. compare: - show input and output from `trigsimp` and `futrig` when different, but returns the `trigsimp` value. Examples ======== >>> from sympy import trigsimp, sin, cos, log, cot >>> from sympy.abc import x >>> e = 2*sin(x)**2 + 2*cos(x)**2 >>> trigsimp(e, old=True) 2 >>> trigsimp(log(e), old=True) log(2*sin(x)**2 + 2*cos(x)**2) >>> trigsimp(log(e), deep=True, old=True) log(2) Using `method="groebner"` (or `"combined"`) can sometimes lead to a lot more simplification: >>> e = (-sin(x) + 1)/cos(x) + cos(x)/(-sin(x) + 1) >>> trigsimp(e, old=True) (1 - sin(x))/cos(x) + cos(x)/(1 - sin(x)) >>> trigsimp(e, method="groebner", old=True) 2/cos(x) >>> trigsimp(1/cot(x)**2, compare=True, old=True) futrig: tan(x)**2 cot(x)**(-2) r8r) separatevarsT)dictFrrrrrc>fd|r|}t|fiS)Nc|jr|S|jDcgc] }| }}|js |jr|Dcgc]}t |fi}}|j |Scc}wcc}wrYrrs rCrz4trigsimp_old..groebnersimp..traverserr)r)rrrrs `@rCrz"trigsimp_old..groebnersimps& ! "B ,t,,rVct||SrY) _trigsimp)rBds rCrztrigsimp_old..s )Aq/rVc||fiSrYrZ)rBrrrs rCrztrigsimp_old.. s,q!". s$)L'(T!S-K#$#&rV)rr/rcomparez futrig:)rrrLunionatoms free_symbolsrlsympy.simplify.simplifyrrr9rvaluesrrras_independentrr0reversedrJgetrprint)rrrrrRtrigsymsrrr{wasvnewrQr}rArrrrwrpsubresultrrs ` @rCrrs2t C txx K35;;V9L MA MN x=1  <T"Axx .3!!T"!AC"1 A$)DM#A..Dqy"DLD!88%&#22151,1DM#$x':T':#:D#';; % &Ce,I 88FE "D XXh +F -2<&  L4y1 1t $A; &Cs1vs1v&AQ%A &dD) xx 5! 3K ; +q ! MM!NsHc|j|jk(xrZ|jtxr|jtxs,|jtxr|jtS)zHelper to tell whether ``a`` and ``b`` have the same sorts of symbols in them -- no need to test hyperbolic patterns against expressions that have no hyperbolics in them.)rcrr(r')rrs rC_dotrigr"s^ 66QVV  A #$E/D)E @  !?aee,>&?ArVNctdt\}}}tdd}|t||zzt||zz |t ||zzt|t|f|t ||zzt||zz|t||zzt|t|f|t ||zzt||zz|t||zzt|t|f|t ||zzt||zz |t||zz t|t|f|t ||zzt||zz |t||zz t|t|f|t ||zzt ||zz|t|t|f|t|dz|zzt|dz |zz|t|dz |zzt|dzt|dz f|t|dz|zzt|dz |zz|t|dz |zzt|dzt|dz f|t ||zzt||zz |t||zztjtjf|t||zzt||zz|t ||zztjtjf|t||zzt ||zz|t||zztjtjf|t||zzt ||zz |t||zz tjtjf|t||zzt||zz |t ||zz tjtjf|t||zzt||zz|tjtjf|t|t|zzdt|t|zzz t||z|ztjtjff}|t|zt|z|t|zt|zz|zt||z|z|zf|t|zt|z|t|zt|zz |zt||z|z|zf|t|zt|z|t|zt|zz |zt||z |z|zf|t|zt|z|t|zt|zz|zt||z |z|zf|t |zt|z|t |zt|zz|zt ||z|z|zf|t|zt|z|t |zt |zz|zt||z|z|zff}|t|dzz||t|dzzz f|t |dzz|dt|z dzz|z f|t |dzz|dt|z dzz|z f|t||zz|t|t|zt|t|zzzf|t||zz|t|t|zt|t|zz zf|t ||zz|t |t |zdt |t |zz z zf|t |dzz|t|dzz|z f|t|dzz||dt|z dzzz f|t|dzz||dt |z dzzzf|t ||zz|t |t|zt |t|zzzf|t||zz|t|t|zt |t |zzzf|t||zz|t|t|zdt|t|zzz zff }||t|dzzz |z|t|dzz|ztf||dt|z dzzz |z| t |dzz|ztf||dt|z dzzz |z| t |dzz|ztf||t|dzzz |z| t |dzz|ztf||dt|z dzzz |z|t|dzz|ztf||dt |z dzzz|z|t|dzz|zt f||z||zt|dzzz |z||zt|dzz|ztf||z||zdt|z dzzz |z| |zt |dzz|ztf||z||zdt|z dzzz |z| |zt |dzz|ztf||z||zt|dzzz |z| |zt |dzz|ztf||z||zdt|z dzzz |z||zt|dzz|ztf||z||zdt |z dzzz|z||zt|dzz|zt ff }||||||||fa tS)Nza b crarF) commutativer8rG) rrrrr#r$r"r r!rrr%_trigpat)rrrPrmatchers_division matchers_addmatchers_identity artifactss rC _trigpatsr,s g4(GAq! Se$A 3q619SVQY #a&!) SVSV< 3q619SVQY #a&!) SVSV< 3q619SVQY #a&!) SVSV< 3q619SVQY #a&!) SVSV< 3q619SVQY #a&!) SVSV< 3q619SVQY 3q63q62 CFQJ? CFQJ? * A zAo s1vz3q6A: 7 CFQJ? CFQJ? * A zAo s1vz3q6A: 7 47A:d1gqj !DGQJ,quu= 47A:d1gqj !DGQJ,quu= 47A:d1gqj !DGQJ,quu= 47A:d1gqj !DGQJ,quu= 47A:d1gqj !DGQJ,quu= 47A:d1gqj !QUUAEE2 DGd1g  DGDGO 3 4 QKM155!%% )'0 3q6#a&1SV8CF? *Q .AE 1 q0@A 3q6#a&1SV8CF? *Q .AE 1 q0@A 3q6#a&1SV8CF? *Q .AE 1 q0@A 3q6#a&1SV8CF? *Q .AE 1 q0@A 4747 QtAwYtAw. . 2DQKMA4EF 4747 QtAwYtAw. . 2DQKMA4EF L 3q619a!CFAI+o& 3q619a3q6A o)* 3q619a3q6A o)* 3q1u:q#a&Q-#a&Q-789 3q1u:q#a&Q-#a&Q-789 3q1u:q3q6CF?QQA->?@A 47A:qa!|a'( 47A:q1aQi!^++, 47A:q1aQi!^++, 4A;4747?T!WT!W_<=> 4A;4747?T!WT!W_<=> 4A;DGd1g-DGDGO0CDEF( Qs1vqy[1 aA kAos3 Q#a&1}_ q 1"SVQY,"2C8 Q#a&1}_ q 1"SVQY,"2C8 QtAwz\ A r$q'1*}q0$7 Q$q' A~   !1T!WaZ 1qsAc!fHq= 1 $qbd3q619nq&8#> 1qs47A:~  !A2a4Q ?Q#6= 1qsAd1gI>! !A %qs47A:~'94@ 1qsAd1gI>! !A %qs47A:~'94@!I&1a-|9&H OrVctt}tt}g}|jD]} | js| j||fvr| j \} } | j s | jrT| j|k(r|| jdxx| z cc<t| j|k(r|| jdxx| z cc<|j| t|t|z} d} | rm| j}|j|}|j|}|||k(r#|j||||zd} n |||<|||<| rm| s|S|r0|j\}} |j||| z|r0|r0|j\}} |j||| z|r0t|S)zHelper for _match_div_rewrite. Replace f(b_)**c_*g(b_)**(rexp(c_)) with h(b)**rexph(c) if f(b_) and g(b_) are both positive or if c_ is an integer. rFT) rintrdrrc as_base_exp is_positive is_integerr:rLrpopitemr )rrrprexphrexphfargsgargsrdrBrrAcommonhitrwfeges rC_replace_mul_fpowxgpowr's  E  E D YY  88qvv!Q'==?DAq}} 66Q;!&&)$)$VVq[!&&)$)$ A Z#e* $F C jjl YYs^ YYs^ b> KK#b ) *CE#JE#J   Q AcFAI  Q AcFAI  :rVc|SrYrZrs rCrrsrVc| SrYrZrs rCrrs1"rVc"tjSrY)rrrs rCrrs rVc |dk(r&t|ttttt }|S|dk(r&t|ttt tt }|S|dk(r&t|t tt tt }|S|dk(r&t|ttttt}|S|dk(r&t|t tttt}|S|dk(r&t|t tt tt }|S|dk(r&t|ttttt }|S|dk(r&t|ttt tt }|S|d k(r&t|ttt tt }|S|d k(r&t|ttttt}|S|d k(r&t|ttttt}|S|d k(r&t|ttt tt }|Sy )zhelper for __trigsimprr8rG N) r'rr_midnr#_idnr$_oner"r r!r%)ris rC_match_div_rewriter9sAv%dC 3L KI a%dC #tF KC a%dC #t@ K= a%dC 3: K7 a%dC 34 K1 a%dC $. K) a%dD$ 4& K# a%dD$ $ K b%dD$ $ K b%dD$ 4  K b%dD$ 4  K b%dD$ $ KrVcD|jtr t||S|SrY)rr __trigsimp)rrs rCrrs$txx$%% KrVc . ddlm}t tt\}}}}}}|jrG|j sI|j \} } ttj| |tj| z}nt|D]\} \} } }}t|| st|| }| ||k7r|}n0|j| sDj|dsW|js<|j!}|j"s|j!}|j"st%fdj't(t*Dr| j!}n|j,rg}|j.D]}|j s>|j \} } tj| } tj| }nt0j2} t||}|D]+\} }|j| |j!}n|j5|| z||j.k7r#t7|}t9|t;|t<}|j,r|D]\} }t|| s||}|j?t*s1|j| 9vr5vr1t%fd|j't(t*Dr~|j!}n|D]\} }}t|| stAd|g}| j!|} |j!|}|j| }d}|s\||k7sb|}||dk(s#|| ||j.vs||||zdk(r||vr||||z||zdk(r|j!|}|j| }|jC|t0jD|s||k7rnW|js|jFs|r=|j.r1|jH|j.Dcgc]}t||c}} |j>tJstL|j'tN}|jQtN| }||k(rtLtS|}||k7rt9|tS|gt<}|j'tN|z s|}|Scc}w#tL$rY|SwxYw) zrecursive helper for trigsimpr)TR10iNc3HK|]}|jdk(ywrNrd)r[r rrvs rCr]z__trigsimp.. s(H1166!9A.Hs")rwc3PK|]}|jdfvywr?r@)r[r rrrvs rCr]z__trigsimp..0s4IH:;q c!fc!f%55IHs#&r)r)r)*rr=rrris_commutativerrr _from_args enumeraterr9matchrrrJrrirr(r'rrdrrr:r rrrrrrfZerorrcr TypeErrorrrr*)rrr=rPrrrrrcomncr8patternsimpok1ok2rokrdtermr ra_trr rrArfnewrrvs ` @@rCr;r;s( #+!Aq!Q!<y {{""mmoGCS^^C0$7r8JJD09:K0L ,,GT3tW-,T15&$& jj)3771a=q6,, XXc]!~~$ XXc]!~~$HA 13E9GHH 99S>D; > {{II !D&&--/R^^B'~~c*UUT4(D#4 jj)?!;;s+D   KKR  ! 499 :DtVD\y9D ;;#/ tW-T{88./**W-C{18SSIH?B1v||13E@GIHFH!!;;s+D $$- ( GVR4)sRD)Cll1c*G[[C(F 7#ACt S6Q;31Q499,#1 0B6afQqTkAaD0A5{{1~JJw' Q't  (.  t tyytyyA!9Q-AB txx O JJsOll3Tl* !8Oc{ 3;sF3K(i8C #"D K%B   K sT*BT TT)hyperc |ddlm}t|}t|ts|S|j s|S|}t |t}|r6|jtr!||\}}|t |t}||k7r;|jr/|j djrt|j}|S)aReturn simplified ``e`` using Fu-like transformations. This is not the "Fu" algorithm. This is called by default from ``trigsimp``. By default, hyperbolics subexpressions will be simplified, but this can be disabled by setting ``hyper=False``. Examples ======== >>> from sympy import trigsimp, tan, sinh, tanh >>> from sympy.simplify.trigsimp import futrig >>> from sympy.abc import x >>> trigsimp(1/tan(x)**2) tan(x)**(-2) >>> futrig(sinh(x)/tanh(x)) cosh(x) r)r)rrrr9rrdr _futrigrr'r is_Rationalr as_coeff_Mul)rArRkwargsrrrs rCrrgs(0 A a  66 C!WA )*Q1 i7# $CxAHH!6!6 ! " HrVc!,ddlm}mm}mm}mm}m}m m m m }m m}m}m} m} mm|j)t*s|S|j,r|j/t*\} }nd} fd} dt0||fdt0fdgfd| ||| fd | t0fd g||t0|gt0fd gfd fd gfdfdg|t0gt0fdg|t0fdgfg} t3| | |}| | |z}|S)zHelper for futrig.r)TR1TR2TR3rTR10Lr=TR8TR6TR15TR16TR111TR5TRmorrieTR11_TR11TR14TR22TR12Nc||jt|t|j|jfSrY)rrrlrdr)rBr]s rCrz_futrig..s,adAKKM6!9c!&&k188LrVc,|jtSrY)rr(rs rCrz_futrig..saee12rVc&tt|SrY_eapplyr*rBtrigss rCrz_futrig..'&!U+rVc&tt|SrYrnrros rCrz_futrig..WXq%8rVc td|S)Nc4t|jSrY)r*normal)r8s rCrz+_futrig....sF188:$6rV)rnros rCrz_futrig..s'65ArVc&tt|SrYrmros rCrz_futrig..rqrVc&tt|SrYrsros rCrz_futrig..rtrVc |SrYrZ)rBrZrs rCrz_futrig..sT#a&\rVc2tt|SrYrnr)rBrcrps rCrz_futrig..sgj#a&%8rVc2tt|SrYr|)rBr`rps rCrz_futrig..sgDGU,rVc2tt|SrYr|)rBr_rps rCrz_futrig..swz3q659rVc2tt|SrYr|)rBrarps rCrz_futrig..swDGU,rVc2tt|SrYr|)rBrhrps rCrz_futrig..sW Q(rVc2tt|SrY)rnr )rBrirps rCrz_futrig..sW $q'5*rV) objective)rrYrZr[rr\r]r=r^r_r`rarbrcrdrerfrgrhrirr(rrr1r2)rArYr[r\r=r^rbrdrerfrgrOLopstreer]rir`rarZrhrrcr_rps @@@@@@@@@@rCrTrTs8 55& 'xx##$9:q LD 2E    + 89 A    eS+ 89  3 )* 8 , - : , -  4 ( ) S$ * +C# $ DJ %tt$Q'A  AI HrVct|trt|jSt|tsyt d|j DS)zD_eapply helper to tell whether ``e`` and all its args are Exprs.Fc32K|]}t|ywrY)_is_Expr)r[r8s rCr]z_is_Expr..s+qx{+s)r9rrrrallrd)rAs rCrrs?!Z  a  +AFF+ ++rVc t|ts|St|s |js||S|j|jDcgc]}|||r t ||n|c}Scc}w)zdApply ``func`` to ``e`` if all args are Exprs else only apply it to those args that *are* Exprs.)r9rrrdrcrn)rcrAcondeis rCrnrnsq a {!&&Aw 166&& #ld2hbR? s A/)FrY)\ collectionsr functoolsr sympy.corerrrrr r r r sympy.core.cacher sympy.core.functionrrrrrrrsympy.core.numbersrrsympy.core.intfuncrsympy.core.sortingrsympy.core.symbolrrrsympy.external.gmpyrsympy.functionsrrrr r!r"r#r$r%r&%sympy.functions.elementary.hyperbolicr'(sympy.functions.elementary.trigonometricr( sympy.polysr)r*r+r,sympy.polys.domainsr-sympy.polys.polyerrorsr.sympy.polys.polytoolsr/sympy.simplify.cse_mainr0sympy.strategies.corer1sympy.strategies.treer2sympy.utilities.iterablesr3sympy.utilities.miscr4rrrrrrrrrr'r6r5r7r9rr;rrTrrnrZrVrCrs#---$GGG)#%22*KKK!DJEE"5*'*(.&"$E!&KF\ !3 4DiX[~!%EPA Qh)X)X ~ ~D( V< ~, rV