Mercurial > projects > ldc
comparison gen/complex.cpp @ 438:3c133dd1eda3
Rework complex divison.
author | Christian Kamm <kamm incasoftware de> |
---|---|
date | Wed, 30 Jul 2008 16:48:35 +0200 |
parents | 798ee94a0be7 |
children | cc40db549aea |
comparison
equal
deleted
inserted
replaced
437:11a8a45759a8 | 438:3c133dd1eda3 |
---|---|
316 | 316 |
317 ////////////////////////////////////////////////////////////////////////////////////////// | 317 ////////////////////////////////////////////////////////////////////////////////////////// |
318 | 318 |
319 DValue* DtoComplexDiv(Loc& loc, Type* type, DValue* lhs, DValue* rhs) | 319 DValue* DtoComplexDiv(Loc& loc, Type* type, DValue* lhs, DValue* rhs) |
320 { | 320 { |
321 lhs = DtoComplex(loc, type, resolveLR(lhs, true)); | 321 DValue* clhs = DtoComplex(loc, type, resolveLR(lhs, true)); |
322 rhs = DtoComplex(loc, type, resolveLR(rhs, false)); | 322 DValue* crhs = DtoComplex(loc, type, resolveLR(rhs, false)); |
323 | 323 |
324 llvm::Value *a, *b, *c, *d; | 324 llvm::Value *lhs_re, *lhs_im, *rhs_re, *rhs_im, *res_re, *res_im; |
325 | 325 |
326 // lhs values | 326 // lhs values |
327 DtoGetComplexParts(lhs, a, b); | 327 DtoGetComplexParts(clhs, lhs_re, lhs_im); |
328 // rhs values | 328 // rhs values |
329 DtoGetComplexParts(rhs, c, d); | 329 DtoGetComplexParts(crhs, rhs_re, rhs_im); |
330 | 330 |
331 llvm::Value *tmp1, *tmp2, *denom, *re, *im; | 331 Type* lhstype = lhs->getType(); |
332 | 332 Type* rhstype = rhs->getType(); |
333 tmp1 = gIR->ir->CreateMul(c, c, "tmp"); | 333 |
334 tmp2 = gIR->ir->CreateMul(d, d, "tmp"); | 334 // if divisor is only real, division is simple |
335 denom = gIR->ir->CreateAdd(tmp1, tmp2, "tmp"); | 335 if(hasRe(rhstype) && !hasIm(rhstype)) { |
336 | 336 if(hasRe(lhstype)) |
337 tmp1 = gIR->ir->CreateMul(a, c, "tmp"); | 337 res_re = gIR->ir->CreateFDiv(lhs_re, rhs_re, "re_divby_re"); |
338 tmp2 = gIR->ir->CreateMul(b, d, "tmp"); | 338 else |
339 re = gIR->ir->CreateAdd(tmp1, tmp2, "tmp"); | 339 res_re = lhs_re; |
340 re = gIR->ir->CreateFDiv(re, denom, "tmp"); | 340 if(hasIm(lhstype)) |
341 | 341 res_im = gIR->ir->CreateFDiv(lhs_im, rhs_re, "im_divby_re"); |
342 tmp1 = gIR->ir->CreateMul(b, c, "tmp"); | 342 else |
343 tmp2 = gIR->ir->CreateMul(a, d, "tmp"); | 343 res_im = lhs_im; |
344 im = gIR->ir->CreateSub(tmp1, tmp2, "tmp"); | 344 } |
345 im = gIR->ir->CreateFDiv(im, denom, "tmp"); | 345 // if divisor is only imaginary, division is simple too |
346 | 346 else if(!hasRe(rhstype) && hasIm(rhstype)) { |
347 return new DComplexValue(type, re, im); | 347 if(hasRe(lhstype)) |
348 res_im = gIR->ir->CreateNeg(gIR->ir->CreateFDiv(lhs_re, rhs_im, "re_divby_im"), "neg"); | |
349 else | |
350 res_im = lhs_re; | |
351 if(hasIm(lhstype)) | |
352 res_re = gIR->ir->CreateFDiv(lhs_im, rhs_im, "im_divby_im"); | |
353 else | |
354 res_re = lhs_im; | |
355 } | |
356 // full division | |
357 else { | |
358 llvm::Value *tmp1, *tmp2, *denom; | |
359 | |
360 if(hasRe(lhstype) && hasIm(lhstype)) { | |
361 tmp1 = gIR->ir->CreateMul(lhs_re, rhs_re, "rere"); | |
362 tmp2 = gIR->ir->CreateMul(lhs_im, rhs_im, "imim"); | |
363 res_re = gIR->ir->CreateAdd(tmp1, tmp2, "rere_plus_imim"); | |
364 | |
365 tmp1 = gIR->ir->CreateMul(lhs_re, rhs_im, "reim"); | |
366 tmp2 = gIR->ir->CreateMul(lhs_im, rhs_re, "imre"); | |
367 res_im = gIR->ir->CreateSub(tmp2, tmp1, "imre_sub_reim"); | |
368 } | |
369 else if(hasRe(lhstype)) { | |
370 res_re = gIR->ir->CreateMul(lhs_re, rhs_re, "rere"); | |
371 | |
372 res_im = gIR->ir->CreateMul(lhs_re, rhs_im, "reim"); | |
373 res_im = gIR->ir->CreateNeg(res_im); | |
374 } | |
375 else if(hasIm(lhstype)) { | |
376 res_re = gIR->ir->CreateMul(lhs_im, rhs_im, "imim"); | |
377 res_im = gIR->ir->CreateMul(lhs_im, rhs_re, "imre"); | |
378 } | |
379 else | |
380 assert(0 && "lhs has neither real nor imaginary part"); | |
381 | |
382 tmp1 = gIR->ir->CreateMul(rhs_re, rhs_re, "rhs_resq"); | |
383 tmp2 = gIR->ir->CreateMul(rhs_im, rhs_im, "rhs_imsq"); | |
384 denom = gIR->ir->CreateAdd(tmp1, tmp2, "denom"); | |
385 | |
386 res_re = gIR->ir->CreateFDiv(res_re, denom, "res_re"); | |
387 res_im = gIR->ir->CreateFDiv(res_im, denom, "res_im"); | |
388 } | |
389 | |
390 return new DComplexValue(type, res_re, res_im); | |
348 } | 391 } |
349 | 392 |
350 ////////////////////////////////////////////////////////////////////////////////////////// | 393 ////////////////////////////////////////////////////////////////////////////////////////// |
351 | 394 |
352 DValue* DtoComplexNeg(Loc& loc, Type* type, DValue* val) | 395 DValue* DtoComplexNeg(Loc& loc, Type* type, DValue* val) |