def pow_cf_c(gen,t,srcs): nonzero = gen.symbols.newLabel() done = gen.symbols.newLabel() dst_re = gen.newTemp(Float) dst_im = gen.newTemp(Float) # FIXME: this shortcut breaks 3damand01, not sure why #gen.emit_cjump(srcs[0].im,nonzero) # compute result if just real #tdest = pow_ff_f(gen,t,[srcs[0].re,srcs[1]]) #gen.emit_move(tdest,dst_re) #gen.emit_move(ConstFloatArg(0.0),dst_im) #gen.emit_jump(done) #gen.emit_label(nonzero)\ # result if real + imag # temp = log(a+ib) # polar(y * real(temp), y * imag(temp)) temp = log_c_c(gen,t,[srcs[0]]) t_re = gen.emit_binop('*',[temp.re, srcs[1]], Float) t_re = gen.emit_func('exp',[t_re], Float) t_im = gen.emit_binop('*',[temp.im, srcs[1]], Float) temp2 = polar_ff_c(gen,t,[t_re, t_im]) gen.emit_move(temp2.re,dst_re) gen.emit_move(temp2.im,dst_im) gen.emit_label(done) return ComplexArg(dst_re,dst_im)
def pow_cc_c(gen,t,srcs): nonzero = gen.symbols.newLabel() done = gen.symbols.newLabel() dst_re = gen.newTemp(Float) dst_im = gen.newTemp(Float) gen.emit_cjump(srcs[0].re,nonzero) gen.emit_cjump(srcs[0].im,nonzero) # 0^foo = 0 gen.emit_move(ConstFloatArg(0.0),dst_re) gen.emit_move(ConstFloatArg(0.0),dst_im) gen.emit_jump(done) gen.emit_label(nonzero) # exp(y*log(x)) logx = log_c_c(gen,t,[srcs[0]]) ylogx = mul_cc_c(gen,t,[srcs[1],logx]) xtoy = exp_c_c(gen,t,[ylogx]) gen.emit_move(xtoy.re,dst_re) gen.emit_move(xtoy.im,dst_im) gen.emit_label(done) return ComplexArg(dst_re,dst_im)
def genfunc(gen,t,srcs): src = srcs[0] ax = gen.emit_binop('-', [src.parts[0], src.parts[3]], Float) ay = gen.emit_binop('+', [src.parts[1], src.parts[2]], Float) bx = gen.emit_binop('+', [src.parts[0], src.parts[3]], Float) by = gen.emit_binop('-', [src.parts[1], src.parts[2]], Float) res_a = f(gen,t, [ComplexArg(ax,ay)]) res_b = f(gen,t, [ComplexArg(bx,by)]) outa = gen.emit_binop('+', [res_a.re, res_b.re], Float) outb = gen.emit_binop('+', [res_a.im, res_b.im], Float) outc = gen.emit_binop('-', [res_a.im, res_b.im], Float) outd = gen.emit_binop('-', [res_b.re, res_a.re], Float) # divide by 2 return mul_hf_h(gen,t,[HyperArg(outa, outb, outc, outd), ConstFloatArg(0.5)])
def _read_lookup_aci_c(gen,t,srcs): # lookup pair of floats i1 = gen.emit_binop('*', [ConstIntArg(2), srcs[1]], Int) i2 = gen.emit_binop('+', [ConstIntArg(1), i1], Int) d1 = gen.emit_func2("read_float_array_1D", [srcs[0], i1], Float) d2 = gen.emit_func2("read_float_array_1D", [srcs[0], i2], Float) return ComplexArg(d1,d2)
def cos_c_c(gen,t,srcs): # cos(a+ib) = (cos(a) * cosh(b), -(sin(a) * sinh(b))) a = srcs[0].re ; b = srcs[0].im re = gen.emit_binop('*', [ cos_f_f(gen,t,[a]), cosh_f_f(gen,t,[b])], Float) im = gen.emit_binop('*', [ sin_f_f(gen,t,[a]), sinh_f_f(gen,t,[b])], Float) nim = gen.emit_func('-',[im], Float) return ComplexArg(re,nim)
def sqr_c_c(gen,t,srcs): # sqr(a+ib) = a2 - b2 + i(2ab) src = srcs[0] a2 = gen.emit_binop('*', [src.re, src.re], Float) b2 = gen.emit_binop('*', [src.im, src.im], Float) ab = gen.emit_binop('*', [src.re, src.im], Float) dst = ComplexArg( gen.emit_binop('-', [a2, b2], Float), gen.emit_binop('*', [ ConstFloatArg(2.0), ab], Float)) return dst
def mul_cc_c(gen,t,srcs): # (a+ib) * (c+id) = ac - bd + i(bc + ad) ac = gen.emit_binop('*', [srcs[0].re, srcs[1].re], Float) bd = gen.emit_binop('*', [srcs[0].im, srcs[1].im], Float) bc = gen.emit_binop('*', [srcs[0].im, srcs[1].re], Float) ad = gen.emit_binop('*', [srcs[0].re, srcs[1].im], Float) dst = ComplexArg( gen.emit_binop('-', [ac, bd], Float), gen.emit_binop('+', [bc, ad], Float)) return dst
def div_cc_c(gen,t,srcs): # (a+ib)/(c+id) = (a+ib)*(c-id) / (c+id)*(c-id) # = (ac + bd + i(bc - ad))/mag(c+id) denom = cmag_c_f(gen,'mag', [srcs[1]]) ac = gen.emit_binop('*', [srcs[0].re, srcs[1].re], Float) bd = gen.emit_binop('*', [srcs[0].im, srcs[1].im], Float) bc = gen.emit_binop('*', [srcs[0].im, srcs[1].re], Float) ad = gen.emit_binop('*', [srcs[0].re, srcs[1].im], Float) dre = gen.emit_binop('+', [ac, bd], Float) dim = gen.emit_binop('-', [bc, ad], Float) return ComplexArg( gen.emit_binop('/', [dre, denom], Float), gen.emit_binop('/', [dim, denom], Float))
def trunc_c_c(gen,t,srcs): return ComplexArg(trunc_f_i(gen,t,[srcs[0].re]), trunc_f_i(gen,t,[srcs[0].im]))
def sinh_c_c(gen,t,srcs): # sinh(a+ib) = sinh(a)*cos(b) + i (cosh(a) * sin(b)) a = [srcs[0].re]; b = [srcs[0].im] re = gen.emit_binop('*', [ sinh_f_f(gen,t,a), cos_f_f(gen,t,b)], Float) im = gen.emit_binop('*', [ cosh_f_f(gen,t,a), sin_f_f(gen,t,b)], Float) return ComplexArg(re,im)
def acos_c_c(gen,t,srcs): # acos(z) = pi/2 - asin(z) pi_by_2 = ComplexArg(ConstFloatArg(math.pi/2.0),ConstFloatArg(0.0)) return sub_cc_c(gen,t,[pi_by_2, asin_c_c(gen,t,srcs)])
def sin_c_c(gen,t,srcs): # sin(a+ib) = (sin(a) * cosh(b), cos(a) * sinh(b)) a = srcs[0].re ; b = srcs[0].im re = gen.emit_binop('*', [ sin_f_f(gen,t,[a]), cosh_f_f(gen,t,[b])], Float) im = gen.emit_binop('*', [ cos_f_f(gen,t,[a]), sinh_f_f(gen,t,[b])], Float) return ComplexArg(re,im)
def log_c_c(gen,t,srcs): # log(a+ib) = (log(mag(a+ib)), atan2(a+ib)) re = gen.emit_func('log', [cabs_c_f(gen,t,srcs)], Float) im = atan2_c_f(gen,t,srcs) return ComplexArg(re,im)
def mul_cf_c(gen,t,srcs): # multiply a complex number by a real one return ComplexArg( gen.emit_binop('*',[srcs[0].re, srcs[1]], Float), gen.emit_binop('*',[srcs[0].im, srcs[1]], Float))
def __init__(self): self.i = ComplexArg(ConstFloatArg(0.0),ConstFloatArg(1.0)) self.iby2 = ComplexArg(ConstFloatArg(0.0),ConstFloatArg(0.5)) self.minus_i = ComplexArg(ConstFloatArg(0.0),ConstFloatArg(-1.0)) self.one = ComplexArg(ConstFloatArg(1.0),ConstFloatArg(0.0))
def ceil_c_c(gen,t,srcs): return ComplexArg(ceil_f_i(gen,t,[srcs[0].re]), ceil_f_i(gen,t,[srcs[0].im]))
def times_i(gen,t,srcs): # multiply by i = (-im,re) return ComplexArg(neg_f_f(gen,t,[srcs[0].im]),srcs[0].re)
def hyper_jk_h_c(gen,t,srcs): return ComplexArg(srcs[0].parts[2], srcs[0].parts[3])
def recip_c_c(gen,t,srcs): return div_cc_c(gen, None, [ComplexArg(ConstFloatArg(1.0), ConstFloatArg(0.0)), srcs[0]])
def hyper_ri_h_c(gen,t,srcs): return ComplexArg(srcs[0].parts[0], srcs[0].parts[1])
def flip_c_c(gen,t,srcs): # flip(a+ib) = b+ia return ComplexArg(srcs[0].im,srcs[0].re)
def conj_c_c(gen,t,srcs): # conj (a+ib) = a-ib b = gen.emit_binop('-', [ ConstFloatArg(0.0), srcs[0].im], Float) return ComplexArg(srcs[0].re,b)
def round_c_c(gen,t,srcs): return ComplexArg(round_f_i(gen,t,[srcs[0].re]), round_f_i(gen,t,[srcs[0].im]))
def pow_ff_c(gen,t,srcs): arg = ComplexArg(srcs[0], ConstFloatArg(0.0)) return pow_cf_c(gen,t,[arg,srcs[1]])
def floor_c_c(gen,t,srcs): return ComplexArg(floor_f_i(gen,t,[srcs[0].re]), floor_f_i(gen,t,[srcs[0].im]))
def neg_c_c(gen,t,srcs): return ComplexArg( gen.emit_func('-', [srcs[0].re], Float), gen.emit_func('-', [srcs[0].im], Float))
def zero_c_c(gen,t,srcs): return ComplexArg(ConstFloatArg(0.0),ConstFloatArg(0.0))
def sqrt_c_c(gen,t,srcs): xnonzero = gen.symbols.newLabel() done = gen.symbols.newLabel() dst_re = gen.newTemp(Float) dst_im = gen.newTemp(Float) gen.emit_cjump(srcs[0].re,xnonzero) # only an imaginary part : # temp = sqrt(abs(z.im) / 2); # return (temp, __y < 0 ? -__temp : __temp); temp = sqrt_f_f(gen, t, [ abs_f_f(gen,t, [ gen.emit_binop('/',[srcs[0].im, ConstFloatArg(2.0)],Float)])]) gen.emit_move(temp,dst_re) # y >= 0? ypos = gen.emit_binop('>=',[srcs[0].im,ConstFloatArg(0.0)], Float) ygtzero = gen.symbols.newLabel() gen.emit_cjump(ypos,ygtzero) nt = neg_f_f(gen,t, [temp]) gen.emit_move(nt,temp) gen.emit_label(ygtzero) gen.emit_move(temp,dst_im) gen.emit_jump(done) gen.emit_label(xnonzero) # both real and imaginary # temp = sqrt(2 * (cabs(z) + abs(z.re))); # u = temp/2 temp = sqrt_f_f( gen,t, [ gen.emit_binop( '*', [ConstFloatArg(2.0), gen.emit_binop( '+', [cabs_c_f(gen,t,[srcs[0]]), abs_f_f(gen,t,[srcs[0].re])], Float) ], Float) ]) u = gen.emit_binop('/',[temp,ConstFloatArg(2.0)], Float) #x > 0? xpos = gen.emit_binop('>',[srcs[0].re,ConstFloatArg(0.0)], Float) xgtzero = gen.symbols.newLabel() gen.emit_cjump(xpos,xgtzero) # x < 0: # x = abs(im)/temp gen.emit_move(gen.emit_binop( '/', [abs_f_f(gen,t,[srcs[0].im]), temp], Float) , dst_re) # y < 0 ? -u : u ypos2 = gen.emit_binop('>=',[srcs[0].im,ConstFloatArg(0.0)], Float) ygtzero2 = gen.symbols.newLabel() gen.emit_cjump(ypos2,ygtzero2) gen.emit_move(neg_f_f(gen,t,[u]), dst_im) gen.emit_jump(done) gen.emit_label(ygtzero2) gen.emit_move(u, dst_im) gen.emit_jump(done) # x > 0: gen.emit_label(xgtzero) # (u, im/temp) gen.emit_move(u,dst_re) gen.emit_move(gen.emit_binop('/',[srcs[0].im, temp], Float),dst_im) gen.emit_label(done) return ComplexArg(dst_re,dst_im)
def abs_c_c(gen,t,srcs): return ComplexArg(abs_f_f(gen,t,[srcs[0].re]), abs_f_f(gen,t,[srcs[0].im]))
def polar_ff_c(gen,t,srcs): # polar(r,theta) = (r * cos(theta), r * sin(theta)) re = gen.emit_binop('*',[srcs[0],cos_f_f(gen,t,[srcs[1]])], Float) im = gen.emit_binop('*',[srcs[0],sin_f_f(gen,t,[srcs[1]])], Float) return ComplexArg(re,im)