12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049 |
- from .functions import defun, defun_wrapped
- @defun
- def _jacobi_theta2(ctx, z, q):
- extra1 = 10
- extra2 = 20
- # the loops below break when the fixed precision quantities
- # a and b go to zero;
- # right shifting small negative numbers by wp one obtains -1, not zero,
- # so the condition a**2 + b**2 > MIN is used to break the loops.
- MIN = 2
- if z == ctx.zero:
- if (not ctx._im(q)):
- wp = ctx.prec + extra1
- x = ctx.to_fixed(ctx._re(q), wp)
- x2 = (x*x) >> wp
- a = b = x2
- s = x2
- while abs(a) > MIN:
- b = (b*x2) >> wp
- a = (a*b) >> wp
- s += a
- s = (1 << (wp+1)) + (s << 1)
- s = ctx.ldexp(s, -wp)
- else:
- wp = ctx.prec + extra1
- xre = ctx.to_fixed(ctx._re(q), wp)
- xim = ctx.to_fixed(ctx._im(q), wp)
- x2re = (xre*xre - xim*xim) >> wp
- x2im = (xre*xim) >> (wp-1)
- are = bre = x2re
- aim = bim = x2im
- sre = (1<<wp) + are
- sim = aim
- while are**2 + aim**2 > MIN:
- bre, bim = (bre * x2re - bim * x2im) >> wp, \
- (bre * x2im + bim * x2re) >> wp
- are, aim = (are * bre - aim * bim) >> wp, \
- (are * bim + aim * bre) >> wp
- sre += are
- sim += aim
- sre = (sre << 1)
- sim = (sim << 1)
- sre = ctx.ldexp(sre, -wp)
- sim = ctx.ldexp(sim, -wp)
- s = ctx.mpc(sre, sim)
- else:
- if (not ctx._im(q)) and (not ctx._im(z)):
- wp = ctx.prec + extra1
- x = ctx.to_fixed(ctx._re(q), wp)
- x2 = (x*x) >> wp
- a = b = x2
- c1, s1 = ctx.cos_sin(ctx._re(z), prec=wp)
- cn = c1 = ctx.to_fixed(c1, wp)
- sn = s1 = ctx.to_fixed(s1, wp)
- c2 = (c1*c1 - s1*s1) >> wp
- s2 = (c1 * s1) >> (wp - 1)
- cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
- s = c1 + ((a * cn) >> wp)
- while abs(a) > MIN:
- b = (b*x2) >> wp
- a = (a*b) >> wp
- cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
- s += (a * cn) >> wp
- s = (s << 1)
- s = ctx.ldexp(s, -wp)
- s *= ctx.nthroot(q, 4)
- return s
- # case z real, q complex
- elif not ctx._im(z):
- wp = ctx.prec + extra2
- xre = ctx.to_fixed(ctx._re(q), wp)
- xim = ctx.to_fixed(ctx._im(q), wp)
- x2re = (xre*xre - xim*xim) >> wp
- x2im = (xre*xim) >> (wp - 1)
- are = bre = x2re
- aim = bim = x2im
- c1, s1 = ctx.cos_sin(ctx._re(z), prec=wp)
- cn = c1 = ctx.to_fixed(c1, wp)
- sn = s1 = ctx.to_fixed(s1, wp)
- c2 = (c1*c1 - s1*s1) >> wp
- s2 = (c1 * s1) >> (wp - 1)
- cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
- sre = c1 + ((are * cn) >> wp)
- sim = ((aim * cn) >> wp)
- while are**2 + aim**2 > MIN:
- bre, bim = (bre * x2re - bim * x2im) >> wp, \
- (bre * x2im + bim * x2re) >> wp
- are, aim = (are * bre - aim * bim) >> wp, \
- (are * bim + aim * bre) >> wp
- cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
- sre += ((are * cn) >> wp)
- sim += ((aim * cn) >> wp)
- sre = (sre << 1)
- sim = (sim << 1)
- sre = ctx.ldexp(sre, -wp)
- sim = ctx.ldexp(sim, -wp)
- s = ctx.mpc(sre, sim)
- #case z complex, q real
- elif not ctx._im(q):
- wp = ctx.prec + extra2
- x = ctx.to_fixed(ctx._re(q), wp)
- x2 = (x*x) >> wp
- a = b = x2
- prec0 = ctx.prec
- ctx.prec = wp
- c1, s1 = ctx.cos_sin(z)
- ctx.prec = prec0
- cnre = c1re = ctx.to_fixed(ctx._re(c1), wp)
- cnim = c1im = ctx.to_fixed(ctx._im(c1), wp)
- snre = s1re = ctx.to_fixed(ctx._re(s1), wp)
- snim = s1im = ctx.to_fixed(ctx._im(s1), wp)
- #c2 = (c1*c1 - s1*s1) >> wp
- c2re = (c1re*c1re - c1im*c1im - s1re*s1re + s1im*s1im) >> wp
- c2im = (c1re*c1im - s1re*s1im) >> (wp - 1)
- #s2 = (c1 * s1) >> (wp - 1)
- s2re = (c1re*s1re - c1im*s1im) >> (wp - 1)
- s2im = (c1re*s1im + c1im*s1re) >> (wp - 1)
- #cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
- t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp
- t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp
- t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp
- t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp
- cnre = t1
- cnim = t2
- snre = t3
- snim = t4
- sre = c1re + ((a * cnre) >> wp)
- sim = c1im + ((a * cnim) >> wp)
- while abs(a) > MIN:
- b = (b*x2) >> wp
- a = (a*b) >> wp
- t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp
- t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp
- t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp
- t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp
- cnre = t1
- cnim = t2
- snre = t3
- snim = t4
- sre += ((a * cnre) >> wp)
- sim += ((a * cnim) >> wp)
- sre = (sre << 1)
- sim = (sim << 1)
- sre = ctx.ldexp(sre, -wp)
- sim = ctx.ldexp(sim, -wp)
- s = ctx.mpc(sre, sim)
- # case z and q complex
- else:
- wp = ctx.prec + extra2
- xre = ctx.to_fixed(ctx._re(q), wp)
- xim = ctx.to_fixed(ctx._im(q), wp)
- x2re = (xre*xre - xim*xim) >> wp
- x2im = (xre*xim) >> (wp - 1)
- are = bre = x2re
- aim = bim = x2im
- prec0 = ctx.prec
- ctx.prec = wp
- # cos(z), sin(z) with z complex
- c1, s1 = ctx.cos_sin(z)
- ctx.prec = prec0
- cnre = c1re = ctx.to_fixed(ctx._re(c1), wp)
- cnim = c1im = ctx.to_fixed(ctx._im(c1), wp)
- snre = s1re = ctx.to_fixed(ctx._re(s1), wp)
- snim = s1im = ctx.to_fixed(ctx._im(s1), wp)
- c2re = (c1re*c1re - c1im*c1im - s1re*s1re + s1im*s1im) >> wp
- c2im = (c1re*c1im - s1re*s1im) >> (wp - 1)
- s2re = (c1re*s1re - c1im*s1im) >> (wp - 1)
- s2im = (c1re*s1im + c1im*s1re) >> (wp - 1)
- t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp
- t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp
- t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp
- t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp
- cnre = t1
- cnim = t2
- snre = t3
- snim = t4
- n = 1
- termre = c1re
- termim = c1im
- sre = c1re + ((are * cnre - aim * cnim) >> wp)
- sim = c1im + ((are * cnim + aim * cnre) >> wp)
- n = 3
- termre = ((are * cnre - aim * cnim) >> wp)
- termim = ((are * cnim + aim * cnre) >> wp)
- sre = c1re + ((are * cnre - aim * cnim) >> wp)
- sim = c1im + ((are * cnim + aim * cnre) >> wp)
- n = 5
- while are**2 + aim**2 > MIN:
- bre, bim = (bre * x2re - bim * x2im) >> wp, \
- (bre * x2im + bim * x2re) >> wp
- are, aim = (are * bre - aim * bim) >> wp, \
- (are * bim + aim * bre) >> wp
- #cn, sn = (cn*c1 - sn*s1) >> wp, (sn*c1 + cn*s1) >> wp
- t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp
- t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp
- t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp
- t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp
- cnre = t1
- cnim = t2
- snre = t3
- snim = t4
- termre = ((are * cnre - aim * cnim) >> wp)
- termim = ((aim * cnre + are * cnim) >> wp)
- sre += ((are * cnre - aim * cnim) >> wp)
- sim += ((aim * cnre + are * cnim) >> wp)
- n += 2
- sre = (sre << 1)
- sim = (sim << 1)
- sre = ctx.ldexp(sre, -wp)
- sim = ctx.ldexp(sim, -wp)
- s = ctx.mpc(sre, sim)
- s *= ctx.nthroot(q, 4)
- return s
- @defun
- def _djacobi_theta2(ctx, z, q, nd):
- MIN = 2
- extra1 = 10
- extra2 = 20
- if (not ctx._im(q)) and (not ctx._im(z)):
- wp = ctx.prec + extra1
- x = ctx.to_fixed(ctx._re(q), wp)
- x2 = (x*x) >> wp
- a = b = x2
- c1, s1 = ctx.cos_sin(ctx._re(z), prec=wp)
- cn = c1 = ctx.to_fixed(c1, wp)
- sn = s1 = ctx.to_fixed(s1, wp)
- c2 = (c1*c1 - s1*s1) >> wp
- s2 = (c1 * s1) >> (wp - 1)
- cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
- if (nd&1):
- s = s1 + ((a * sn * 3**nd) >> wp)
- else:
- s = c1 + ((a * cn * 3**nd) >> wp)
- n = 2
- while abs(a) > MIN:
- b = (b*x2) >> wp
- a = (a*b) >> wp
- cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
- if nd&1:
- s += (a * sn * (2*n+1)**nd) >> wp
- else:
- s += (a * cn * (2*n+1)**nd) >> wp
- n += 1
- s = -(s << 1)
- s = ctx.ldexp(s, -wp)
- # case z real, q complex
- elif not ctx._im(z):
- wp = ctx.prec + extra2
- xre = ctx.to_fixed(ctx._re(q), wp)
- xim = ctx.to_fixed(ctx._im(q), wp)
- x2re = (xre*xre - xim*xim) >> wp
- x2im = (xre*xim) >> (wp - 1)
- are = bre = x2re
- aim = bim = x2im
- c1, s1 = ctx.cos_sin(ctx._re(z), prec=wp)
- cn = c1 = ctx.to_fixed(c1, wp)
- sn = s1 = ctx.to_fixed(s1, wp)
- c2 = (c1*c1 - s1*s1) >> wp
- s2 = (c1 * s1) >> (wp - 1)
- cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
- if (nd&1):
- sre = s1 + ((are * sn * 3**nd) >> wp)
- sim = ((aim * sn * 3**nd) >> wp)
- else:
- sre = c1 + ((are * cn * 3**nd) >> wp)
- sim = ((aim * cn * 3**nd) >> wp)
- n = 5
- while are**2 + aim**2 > MIN:
- bre, bim = (bre * x2re - bim * x2im) >> wp, \
- (bre * x2im + bim * x2re) >> wp
- are, aim = (are * bre - aim * bim) >> wp, \
- (are * bim + aim * bre) >> wp
- cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
- if (nd&1):
- sre += ((are * sn * n**nd) >> wp)
- sim += ((aim * sn * n**nd) >> wp)
- else:
- sre += ((are * cn * n**nd) >> wp)
- sim += ((aim * cn * n**nd) >> wp)
- n += 2
- sre = -(sre << 1)
- sim = -(sim << 1)
- sre = ctx.ldexp(sre, -wp)
- sim = ctx.ldexp(sim, -wp)
- s = ctx.mpc(sre, sim)
- #case z complex, q real
- elif not ctx._im(q):
- wp = ctx.prec + extra2
- x = ctx.to_fixed(ctx._re(q), wp)
- x2 = (x*x) >> wp
- a = b = x2
- prec0 = ctx.prec
- ctx.prec = wp
- c1, s1 = ctx.cos_sin(z)
- ctx.prec = prec0
- cnre = c1re = ctx.to_fixed(ctx._re(c1), wp)
- cnim = c1im = ctx.to_fixed(ctx._im(c1), wp)
- snre = s1re = ctx.to_fixed(ctx._re(s1), wp)
- snim = s1im = ctx.to_fixed(ctx._im(s1), wp)
- #c2 = (c1*c1 - s1*s1) >> wp
- c2re = (c1re*c1re - c1im*c1im - s1re*s1re + s1im*s1im) >> wp
- c2im = (c1re*c1im - s1re*s1im) >> (wp - 1)
- #s2 = (c1 * s1) >> (wp - 1)
- s2re = (c1re*s1re - c1im*s1im) >> (wp - 1)
- s2im = (c1re*s1im + c1im*s1re) >> (wp - 1)
- #cn, sn = (cn*c2 - sn*s2) >> wp, (sn*c2 + cn*s2) >> wp
- t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp
- t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp
- t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp
- t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp
- cnre = t1
- cnim = t2
- snre = t3
- snim = t4
- if (nd&1):
- sre = s1re + ((a * snre * 3**nd) >> wp)
- sim = s1im + ((a * snim * 3**nd) >> wp)
- else:
- sre = c1re + ((a * cnre * 3**nd) >> wp)
- sim = c1im + ((a * cnim * 3**nd) >> wp)
- n = 5
- while abs(a) > MIN:
- b = (b*x2) >> wp
- a = (a*b) >> wp
- t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp
- t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp
- t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp
- t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp
- cnre = t1
- cnim = t2
- snre = t3
- snim = t4
- if (nd&1):
- sre += ((a * snre * n**nd) >> wp)
- sim += ((a * snim * n**nd) >> wp)
- else:
- sre += ((a * cnre * n**nd) >> wp)
- sim += ((a * cnim * n**nd) >> wp)
- n += 2
- sre = -(sre << 1)
- sim = -(sim << 1)
- sre = ctx.ldexp(sre, -wp)
- sim = ctx.ldexp(sim, -wp)
- s = ctx.mpc(sre, sim)
- # case z and q complex
- else:
- wp = ctx.prec + extra2
- xre = ctx.to_fixed(ctx._re(q), wp)
- xim = ctx.to_fixed(ctx._im(q), wp)
- x2re = (xre*xre - xim*xim) >> wp
- x2im = (xre*xim) >> (wp - 1)
- are = bre = x2re
- aim = bim = x2im
- prec0 = ctx.prec
- ctx.prec = wp
- # cos(2*z), sin(2*z) with z complex
- c1, s1 = ctx.cos_sin(z)
- ctx.prec = prec0
- cnre = c1re = ctx.to_fixed(ctx._re(c1), wp)
- cnim = c1im = ctx.to_fixed(ctx._im(c1), wp)
- snre = s1re = ctx.to_fixed(ctx._re(s1), wp)
- snim = s1im = ctx.to_fixed(ctx._im(s1), wp)
- c2re = (c1re*c1re - c1im*c1im - s1re*s1re + s1im*s1im) >> wp
- c2im = (c1re*c1im - s1re*s1im) >> (wp - 1)
- s2re = (c1re*s1re - c1im*s1im) >> (wp - 1)
- s2im = (c1re*s1im + c1im*s1re) >> (wp - 1)
- t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp
- t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp
- t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp
- t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp
- cnre = t1
- cnim = t2
- snre = t3
- snim = t4
- if (nd&1):
- sre = s1re + (((are * snre - aim * snim) * 3**nd) >> wp)
- sim = s1im + (((are * snim + aim * snre)* 3**nd) >> wp)
- else:
- sre = c1re + (((are * cnre - aim * cnim) * 3**nd) >> wp)
- sim = c1im + (((are * cnim + aim * cnre)* 3**nd) >> wp)
- n = 5
- while are**2 + aim**2 > MIN:
- bre, bim = (bre * x2re - bim * x2im) >> wp, \
- (bre * x2im + bim * x2re) >> wp
- are, aim = (are * bre - aim * bim) >> wp, \
- (are * bim + aim * bre) >> wp
- #cn, sn = (cn*c1 - sn*s1) >> wp, (sn*c1 + cn*s1) >> wp
- t1 = (cnre*c2re - cnim*c2im - snre*s2re + snim*s2im) >> wp
- t2 = (cnre*c2im + cnim*c2re - snre*s2im - snim*s2re) >> wp
- t3 = (snre*c2re - snim*c2im + cnre*s2re - cnim*s2im) >> wp
- t4 = (snre*c2im + snim*c2re + cnre*s2im + cnim*s2re) >> wp
- cnre = t1
- cnim = t2
- snre = t3
- snim = t4
- if (nd&1):
- sre += (((are * snre - aim * snim) * n**nd) >> wp)
- sim += (((aim * snre + are * snim) * n**nd) >> wp)
- else:
- sre += (((are * cnre - aim * cnim) * n**nd) >> wp)
- sim += (((aim * cnre + are * cnim) * n**nd) >> wp)
- n += 2
- sre = -(sre << 1)
- sim = -(sim << 1)
- sre = ctx.ldexp(sre, -wp)
- sim = ctx.ldexp(sim, -wp)
- s = ctx.mpc(sre, sim)
- s *= ctx.nthroot(q, 4)
- if (nd&1):
- return (-1)**(nd//2) * s
- else:
- return (-1)**(1 + nd//2) * s
- @defun
- def _jacobi_theta3(ctx, z, q):
- extra1 = 10
- extra2 = 20
- MIN = 2
- if z == ctx.zero:
- if not ctx._im(q):
- wp = ctx.prec + extra1
- x = ctx.to_fixed(ctx._re(q), wp)
- s = x
- a = b = x
- x2 = (x*x) >> wp
- while abs(a) > MIN:
- b = (b*x2) >> wp
- a = (a*b) >> wp
- s += a
- s = (1 << wp) + (s << 1)
- s = ctx.ldexp(s, -wp)
- return s
- else:
- wp = ctx.prec + extra1
- xre = ctx.to_fixed(ctx._re(q), wp)
- xim = ctx.to_fixed(ctx._im(q), wp)
- x2re = (xre*xre - xim*xim) >> wp
- x2im = (xre*xim) >> (wp - 1)
- sre = are = bre = xre
- sim = aim = bim = xim
- while are**2 + aim**2 > MIN:
- bre, bim = (bre * x2re - bim * x2im) >> wp, \
- (bre * x2im + bim * x2re) >> wp
- are, aim = (are * bre - aim * bim) >> wp, \
- (are * bim + aim * bre) >> wp
- sre += are
- sim += aim
- sre = (1 << wp) + (sre << 1)
- sim = (sim << 1)
- sre = ctx.ldexp(sre, -wp)
- sim = ctx.ldexp(sim, -wp)
- s = ctx.mpc(sre, sim)
- return s
- else:
- if (not ctx._im(q)) and (not ctx._im(z)):
- s = 0
- wp = ctx.prec + extra1
- x = ctx.to_fixed(ctx._re(q), wp)
- a = b = x
- x2 = (x*x) >> wp
- c1, s1 = ctx.cos_sin(ctx._re(z)*2, prec=wp)
- c1 = ctx.to_fixed(c1, wp)
- s1 = ctx.to_fixed(s1, wp)
- cn = c1
- sn = s1
- s += (a * cn) >> wp
- while abs(a) > MIN:
- b = (b*x2) >> wp
- a = (a*b) >> wp
- cn, sn = (cn*c1 - sn*s1) >> wp, (sn*c1 + cn*s1) >> wp
- s += (a * cn) >> wp
- s = (1 << wp) + (s << 1)
- s = ctx.ldexp(s, -wp)
- return s
- # case z real, q complex
- elif not ctx._im(z):
- wp = ctx.prec + extra2
- xre = ctx.to_fixed(ctx._re(q), wp)
- xim = ctx.to_fixed(ctx._im(q), wp)
- x2re = (xre*xre - xim*xim) >> wp
- x2im = (xre*xim) >> (wp - 1)
- are = bre = xre
- aim = bim = xim
- c1, s1 = ctx.cos_sin(ctx._re(z)*2, prec=wp)
- c1 = ctx.to_fixed(c1, wp)
- s1 = ctx.to_fixed(s1, wp)
- cn = c1
- sn = s1
- sre = (are * cn) >> wp
- sim = (aim * cn) >> wp
- while are**2 + aim**2 > MIN:
- bre, bim = (bre * x2re - bim * x2im) >> wp, \
- (bre * x2im + bim * x2re) >> wp
- are, aim = (are * bre - aim * bim) >> wp, \
- (are * bim + aim * bre) >> wp
- cn, sn = (cn*c1 - sn*s1) >> wp, (sn*c1 + cn*s1) >> wp
- sre += (are * cn) >> wp
- sim += (aim * cn) >> wp
- sre = (1 << wp) + (sre << 1)
- sim = (sim << 1)
- sre = ctx.ldexp(sre, -wp)
- sim = ctx.ldexp(sim, -wp)
- s = ctx.mpc(sre, sim)
- return s
- #case z complex, q real
- elif not ctx._im(q):
- wp = ctx.prec + extra2
- x = ctx.to_fixed(ctx._re(q), wp)
- a = b = x
- x2 = (x*x) >> wp
- prec0 = ctx.prec
- ctx.prec = wp
- c1, s1 = ctx.cos_sin(2*z)
- ctx.prec = prec0
- cnre = c1re = ctx.to_fixed(ctx._re(c1), wp)
- cnim = c1im = ctx.to_fixed(ctx._im(c1), wp)
- snre = s1re = ctx.to_fixed(ctx._re(s1), wp)
- snim = s1im = ctx.to_fixed(ctx._im(s1), wp)
- sre = (a * cnre) >> wp
- sim = (a * cnim) >> wp
- while abs(a) > MIN:
- b = (b*x2) >> wp
- a = (a*b) >> wp
- t1 = (cnre*c1re - cnim*c1im - snre*s1re + snim*s1im) >> wp
- t2 = (cnre*c1im + cnim*c1re - snre*s1im - snim*s1re) >> wp
- t3 = (snre*c1re - snim*c1im + cnre*s1re - cnim*s1im) >> wp
- t4 = (snre*c1im + snim*c1re + cnre*s1im + cnim*s1re) >> wp
- cnre = t1
- cnim = t2
- snre = t3
- snim = t4
- sre += (a * cnre) >> wp
- sim += (a * cnim) >> wp
- sre = (1 << wp) + (sre << 1)
- sim = (sim << 1)
- sre = ctx.ldexp(sre, -wp)
- sim = ctx.ldexp(sim, -wp)
- s = ctx.mpc(sre, sim)
- return s
- # case z and q complex
- else:
- wp = ctx.prec + extra2
- xre = ctx.to_fixed(ctx._re(q), wp)
- xim = ctx.to_fixed(ctx._im(q), wp)
- x2re = (xre*xre - xim*xim) >> wp
- x2im = (xre*xim) >> (wp - 1)
- are = bre = xre
- aim = bim = xim
- prec0 = ctx.prec
- ctx.prec = wp
- # cos(2*z), sin(2*z) with z complex
- c1, s1 = ctx.cos_sin(2*z)
- ctx.prec = prec0
- cnre = c1re = ctx.to_fixed(ctx._re(c1), wp)
- cnim = c1im = ctx.to_fixed(ctx._im(c1), wp)
- snre = s1re = ctx.to_fixed(ctx._re(s1), wp)
- snim = s1im = ctx.to_fixed(ctx._im(s1), wp)
- sre = (are * cnre - aim * cnim) >> wp
- sim = (aim * cnre + are * cnim) >> wp
- while are**2 + aim**2 > MIN:
- bre, bim = (bre * x2re - bim * x2im) >> wp, \
- (bre * x2im + bim * x2re) >> wp
- are, aim = (are * bre - aim * bim) >> wp, \
- (are * bim + aim * bre) >> wp
- t1 = (cnre*c1re - cnim*c1im - snre*s1re + snim*s1im) >> wp
- t2 = (cnre*c1im + cnim*c1re - snre*s1im - snim*s1re) >> wp
- t3 = (snre*c1re - snim*c1im + cnre*s1re - cnim*s1im) >> wp
- t4 = (snre*c1im + snim*c1re + cnre*s1im + cnim*s1re) >> wp
- cnre = t1
- cnim = t2
- snre = t3
- snim = t4
- sre += (are * cnre - aim * cnim) >> wp
- sim += (aim * cnre + are * cnim) >> wp
- sre = (1 << wp) + (sre << 1)
- sim = (sim << 1)
- sre = ctx.ldexp(sre, -wp)
- sim = ctx.ldexp(sim, -wp)
- s = ctx.mpc(sre, sim)
- return s
- @defun
- def _djacobi_theta3(ctx, z, q, nd):
- """nd=1,2,3 order of the derivative with respect to z"""
- MIN = 2
- extra1 = 10
- extra2 = 20
- if (not ctx._im(q)) and (not ctx._im(z)):
- s = 0
- wp = ctx.prec + extra1
- x = ctx.to_fixed(ctx._re(q), wp)
- a = b = x
- x2 = (x*x) >> wp
- c1, s1 = ctx.cos_sin(ctx._re(z)*2, prec=wp)
- c1 = ctx.to_fixed(c1, wp)
- s1 = ctx.to_fixed(s1, wp)
- cn = c1
- sn = s1
- if (nd&1):
- s += (a * sn) >> wp
- else:
- s += (a * cn) >> wp
- n = 2
- while abs(a) > MIN:
- b = (b*x2) >> wp
- a = (a*b) >> wp
- cn, sn = (cn*c1 - sn*s1) >> wp, (sn*c1 + cn*s1) >> wp
- if nd&1:
- s += (a * sn * n**nd) >> wp
- else:
- s += (a * cn * n**nd) >> wp
- n += 1
- s = -(s << (nd+1))
- s = ctx.ldexp(s, -wp)
- # case z real, q complex
- elif not ctx._im(z):
- wp = ctx.prec + extra2
- xre = ctx.to_fixed(ctx._re(q), wp)
- xim = ctx.to_fixed(ctx._im(q), wp)
- x2re = (xre*xre - xim*xim) >> wp
- x2im = (xre*xim) >> (wp - 1)
- are = bre = xre
- aim = bim = xim
- c1, s1 = ctx.cos_sin(ctx._re(z)*2, prec=wp)
- c1 = ctx.to_fixed(c1, wp)
- s1 = ctx.to_fixed(s1, wp)
- cn = c1
- sn = s1
- if (nd&1):
- sre = (are * sn) >> wp
- sim = (aim * sn) >> wp
- else:
- sre = (are * cn) >> wp
- sim = (aim * cn) >> wp
- n = 2
- while are**2 + aim**2 > MIN:
- bre, bim = (bre * x2re - bim * x2im) >> wp, \
- (bre * x2im + bim * x2re) >> wp
- are, aim = (are * bre - aim * bim) >> wp, \
- (are * bim + aim * bre) >> wp
- cn, sn = (cn*c1 - sn*s1) >> wp, (sn*c1 + cn*s1) >> wp
- if nd&1:
- sre += (are * sn * n**nd) >> wp
- sim += (aim * sn * n**nd) >> wp
- else:
- sre += (are * cn * n**nd) >> wp
- sim += (aim * cn * n**nd) >> wp
- n += 1
- sre = -(sre << (nd+1))
- sim = -(sim << (nd+1))
- sre = ctx.ldexp(sre, -wp)
- sim = ctx.ldexp(sim, -wp)
- s = ctx.mpc(sre, sim)
- #case z complex, q real
- elif not ctx._im(q):
- wp = ctx.prec + extra2
- x = ctx.to_fixed(ctx._re(q), wp)
- a = b = x
- x2 = (x*x) >> wp
- prec0 = ctx.prec
- ctx.prec = wp
- c1, s1 = ctx.cos_sin(2*z)
- ctx.prec = prec0
- cnre = c1re = ctx.to_fixed(ctx._re(c1), wp)
- cnim = c1im = ctx.to_fixed(ctx._im(c1), wp)
- snre = s1re = ctx.to_fixed(ctx._re(s1), wp)
- snim = s1im = ctx.to_fixed(ctx._im(s1), wp)
- if (nd&1):
- sre = (a * snre) >> wp
- sim = (a * snim) >> wp
- else:
- sre = (a * cnre) >> wp
- sim = (a * cnim) >> wp
- n = 2
- while abs(a) > MIN:
- b = (b*x2) >> wp
- a = (a*b) >> wp
- t1 = (cnre*c1re - cnim*c1im - snre*s1re + snim*s1im) >> wp
- t2 = (cnre*c1im + cnim*c1re - snre*s1im - snim*s1re) >> wp
- t3 = (snre*c1re - snim*c1im + cnre*s1re - cnim*s1im) >> wp
- t4 = (snre*c1im + snim*c1re + cnre*s1im + cnim*s1re) >> wp
- cnre = t1
- cnim = t2
- snre = t3
- snim = t4
- if (nd&1):
- sre += (a * snre * n**nd) >> wp
- sim += (a * snim * n**nd) >> wp
- else:
- sre += (a * cnre * n**nd) >> wp
- sim += (a * cnim * n**nd) >> wp
- n += 1
- sre = -(sre << (nd+1))
- sim = -(sim << (nd+1))
- sre = ctx.ldexp(sre, -wp)
- sim = ctx.ldexp(sim, -wp)
- s = ctx.mpc(sre, sim)
- # case z and q complex
- else:
- wp = ctx.prec + extra2
- xre = ctx.to_fixed(ctx._re(q), wp)
- xim = ctx.to_fixed(ctx._im(q), wp)
- x2re = (xre*xre - xim*xim) >> wp
- x2im = (xre*xim) >> (wp - 1)
- are = bre = xre
- aim = bim = xim
- prec0 = ctx.prec
- ctx.prec = wp
- # cos(2*z), sin(2*z) with z complex
- c1, s1 = ctx.cos_sin(2*z)
- ctx.prec = prec0
- cnre = c1re = ctx.to_fixed(ctx._re(c1), wp)
- cnim = c1im = ctx.to_fixed(ctx._im(c1), wp)
- snre = s1re = ctx.to_fixed(ctx._re(s1), wp)
- snim = s1im = ctx.to_fixed(ctx._im(s1), wp)
- if (nd&1):
- sre = (are * snre - aim * snim) >> wp
- sim = (aim * snre + are * snim) >> wp
- else:
- sre = (are * cnre - aim * cnim) >> wp
- sim = (aim * cnre + are * cnim) >> wp
- n = 2
- while are**2 + aim**2 > MIN:
- bre, bim = (bre * x2re - bim * x2im) >> wp, \
- (bre * x2im + bim * x2re) >> wp
- are, aim = (are * bre - aim * bim) >> wp, \
- (are * bim + aim * bre) >> wp
- t1 = (cnre*c1re - cnim*c1im - snre*s1re + snim*s1im) >> wp
- t2 = (cnre*c1im + cnim*c1re - snre*s1im - snim*s1re) >> wp
- t3 = (snre*c1re - snim*c1im + cnre*s1re - cnim*s1im) >> wp
- t4 = (snre*c1im + snim*c1re + cnre*s1im + cnim*s1re) >> wp
- cnre = t1
- cnim = t2
- snre = t3
- snim = t4
- if(nd&1):
- sre += ((are * snre - aim * snim) * n**nd) >> wp
- sim += ((aim * snre + are * snim) * n**nd) >> wp
- else:
- sre += ((are * cnre - aim * cnim) * n**nd) >> wp
- sim += ((aim * cnre + are * cnim) * n**nd) >> wp
- n += 1
- sre = -(sre << (nd+1))
- sim = -(sim << (nd+1))
- sre = ctx.ldexp(sre, -wp)
- sim = ctx.ldexp(sim, -wp)
- s = ctx.mpc(sre, sim)
- if (nd&1):
- return (-1)**(nd//2) * s
- else:
- return (-1)**(1 + nd//2) * s
- @defun
- def _jacobi_theta2a(ctx, z, q):
- """
- case ctx._im(z) != 0
- theta(2, z, q) =
- q**1/4 * Sum(q**(n*n + n) * exp(j*(2*n + 1)*z), n=-inf, inf)
- max term for minimum (2*n+1)*log(q).real - 2* ctx._im(z)
- n0 = int(ctx._im(z)/log(q).real - 1/2)
- theta(2, z, q) =
- q**1/4 * Sum(q**(n*n + n) * exp(j*(2*n + 1)*z), n=n0, inf) +
- q**1/4 * Sum(q**(n*n + n) * exp(j*(2*n + 1)*z), n, n0-1, -inf)
- """
- n = n0 = int(ctx._im(z)/ctx._re(ctx.log(q)) - 1/2)
- e2 = ctx.expj(2*z)
- e = e0 = ctx.expj((2*n+1)*z)
- a = q**(n*n + n)
- # leading term
- term = a * e
- s = term
- eps1 = ctx.eps*abs(term)
- while 1:
- n += 1
- e = e * e2
- term = q**(n*n + n) * e
- if abs(term) < eps1:
- break
- s += term
- e = e0
- e2 = ctx.expj(-2*z)
- n = n0
- while 1:
- n -= 1
- e = e * e2
- term = q**(n*n + n) * e
- if abs(term) < eps1:
- break
- s += term
- s = s * ctx.nthroot(q, 4)
- return s
- @defun
- def _jacobi_theta3a(ctx, z, q):
- """
- case ctx._im(z) != 0
- theta3(z, q) = Sum(q**(n*n) * exp(j*2*n*z), n, -inf, inf)
- max term for n*abs(log(q).real) + ctx._im(z) ~= 0
- n0 = int(- ctx._im(z)/abs(log(q).real))
- """
- n = n0 = int(-ctx._im(z)/abs(ctx._re(ctx.log(q))))
- e2 = ctx.expj(2*z)
- e = e0 = ctx.expj(2*n*z)
- s = term = q**(n*n) * e
- eps1 = ctx.eps*abs(term)
- while 1:
- n += 1
- e = e * e2
- term = q**(n*n) * e
- if abs(term) < eps1:
- break
- s += term
- e = e0
- e2 = ctx.expj(-2*z)
- n = n0
- while 1:
- n -= 1
- e = e * e2
- term = q**(n*n) * e
- if abs(term) < eps1:
- break
- s += term
- return s
- @defun
- def _djacobi_theta2a(ctx, z, q, nd):
- """
- case ctx._im(z) != 0
- dtheta(2, z, q, nd) =
- j* q**1/4 * Sum(q**(n*n + n) * (2*n+1)*exp(j*(2*n + 1)*z), n=-inf, inf)
- max term for (2*n0+1)*log(q).real - 2* ctx._im(z) ~= 0
- n0 = int(ctx._im(z)/log(q).real - 1/2)
- """
- n = n0 = int(ctx._im(z)/ctx._re(ctx.log(q)) - 1/2)
- e2 = ctx.expj(2*z)
- e = e0 = ctx.expj((2*n + 1)*z)
- a = q**(n*n + n)
- # leading term
- term = (2*n+1)**nd * a * e
- s = term
- eps1 = ctx.eps*abs(term)
- while 1:
- n += 1
- e = e * e2
- term = (2*n+1)**nd * q**(n*n + n) * e
- if abs(term) < eps1:
- break
- s += term
- e = e0
- e2 = ctx.expj(-2*z)
- n = n0
- while 1:
- n -= 1
- e = e * e2
- term = (2*n+1)**nd * q**(n*n + n) * e
- if abs(term) < eps1:
- break
- s += term
- return ctx.j**nd * s * ctx.nthroot(q, 4)
- @defun
- def _djacobi_theta3a(ctx, z, q, nd):
- """
- case ctx._im(z) != 0
- djtheta3(z, q, nd) = (2*j)**nd *
- Sum(q**(n*n) * n**nd * exp(j*2*n*z), n, -inf, inf)
- max term for minimum n*abs(log(q).real) + ctx._im(z)
- """
- n = n0 = int(-ctx._im(z)/abs(ctx._re(ctx.log(q))))
- e2 = ctx.expj(2*z)
- e = e0 = ctx.expj(2*n*z)
- a = q**(n*n) * e
- s = term = n**nd * a
- if n != 0:
- eps1 = ctx.eps*abs(term)
- else:
- eps1 = ctx.eps*abs(a)
- while 1:
- n += 1
- e = e * e2
- a = q**(n*n) * e
- term = n**nd * a
- if n != 0:
- aterm = abs(term)
- else:
- aterm = abs(a)
- if aterm < eps1:
- break
- s += term
- e = e0
- e2 = ctx.expj(-2*z)
- n = n0
- while 1:
- n -= 1
- e = e * e2
- a = q**(n*n) * e
- term = n**nd * a
- if n != 0:
- aterm = abs(term)
- else:
- aterm = abs(a)
- if aterm < eps1:
- break
- s += term
- return (2*ctx.j)**nd * s
- @defun
- def jtheta(ctx, n, z, q, derivative=0):
- if derivative:
- return ctx._djtheta(n, z, q, derivative)
- z = ctx.convert(z)
- q = ctx.convert(q)
- # Implementation note
- # If ctx._im(z) is close to zero, _jacobi_theta2 and _jacobi_theta3
- # are used,
- # which compute the series starting from n=0 using fixed precision
- # numbers;
- # otherwise _jacobi_theta2a and _jacobi_theta3a are used, which compute
- # the series starting from n=n0, which is the largest term.
- # TODO: write _jacobi_theta2a and _jacobi_theta3a using fixed-point
- if abs(q) > ctx.THETA_Q_LIM:
- raise ValueError('abs(q) > THETA_Q_LIM = %f' % ctx.THETA_Q_LIM)
- extra = 10
- if z:
- M = ctx.mag(z)
- if M > 5 or (n == 1 and M < -5):
- extra += 2*abs(M)
- cz = 0.5
- extra2 = 50
- prec0 = ctx.prec
- try:
- ctx.prec += extra
- if n == 1:
- if ctx._im(z):
- if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))):
- ctx.dps += extra2
- res = ctx._jacobi_theta2(z - ctx.pi/2, q)
- else:
- ctx.dps += 10
- res = ctx._jacobi_theta2a(z - ctx.pi/2, q)
- else:
- res = ctx._jacobi_theta2(z - ctx.pi/2, q)
- elif n == 2:
- if ctx._im(z):
- if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))):
- ctx.dps += extra2
- res = ctx._jacobi_theta2(z, q)
- else:
- ctx.dps += 10
- res = ctx._jacobi_theta2a(z, q)
- else:
- res = ctx._jacobi_theta2(z, q)
- elif n == 3:
- if ctx._im(z):
- if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))):
- ctx.dps += extra2
- res = ctx._jacobi_theta3(z, q)
- else:
- ctx.dps += 10
- res = ctx._jacobi_theta3a(z, q)
- else:
- res = ctx._jacobi_theta3(z, q)
- elif n == 4:
- if ctx._im(z):
- if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))):
- ctx.dps += extra2
- res = ctx._jacobi_theta3(z, -q)
- else:
- ctx.dps += 10
- res = ctx._jacobi_theta3a(z, -q)
- else:
- res = ctx._jacobi_theta3(z, -q)
- else:
- raise ValueError
- finally:
- ctx.prec = prec0
- return res
- @defun
- def _djtheta(ctx, n, z, q, derivative=1):
- z = ctx.convert(z)
- q = ctx.convert(q)
- nd = int(derivative)
- if abs(q) > ctx.THETA_Q_LIM:
- raise ValueError('abs(q) > THETA_Q_LIM = %f' % ctx.THETA_Q_LIM)
- extra = 10 + ctx.prec * nd // 10
- if z:
- M = ctx.mag(z)
- if M > 5 or (n != 1 and M < -5):
- extra += 2*abs(M)
- cz = 0.5
- extra2 = 50
- prec0 = ctx.prec
- try:
- ctx.prec += extra
- if n == 1:
- if ctx._im(z):
- if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))):
- ctx.dps += extra2
- res = ctx._djacobi_theta2(z - ctx.pi/2, q, nd)
- else:
- ctx.dps += 10
- res = ctx._djacobi_theta2a(z - ctx.pi/2, q, nd)
- else:
- res = ctx._djacobi_theta2(z - ctx.pi/2, q, nd)
- elif n == 2:
- if ctx._im(z):
- if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))):
- ctx.dps += extra2
- res = ctx._djacobi_theta2(z, q, nd)
- else:
- ctx.dps += 10
- res = ctx._djacobi_theta2a(z, q, nd)
- else:
- res = ctx._djacobi_theta2(z, q, nd)
- elif n == 3:
- if ctx._im(z):
- if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))):
- ctx.dps += extra2
- res = ctx._djacobi_theta3(z, q, nd)
- else:
- ctx.dps += 10
- res = ctx._djacobi_theta3a(z, q, nd)
- else:
- res = ctx._djacobi_theta3(z, q, nd)
- elif n == 4:
- if ctx._im(z):
- if abs(ctx._im(z)) < cz * abs(ctx._re(ctx.log(q))):
- ctx.dps += extra2
- res = ctx._djacobi_theta3(z, -q, nd)
- else:
- ctx.dps += 10
- res = ctx._djacobi_theta3a(z, -q, nd)
- else:
- res = ctx._djacobi_theta3(z, -q, nd)
- else:
- raise ValueError
- finally:
- ctx.prec = prec0
- return +res
|