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)