Andrey Zhezherun : msvcp: Fixed complex division.

Alexandre Julliard julliard at winehq.org
Tue Nov 5 15:02:33 CST 2013


Module: wine
Branch: master
Commit: 44bf8dc4295c12b954a166aa72811fee022e0135
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=44bf8dc4295c12b954a166aa72811fee022e0135

Author: Andrey Zhezherun <zhezherun at yandex.ru>
Date:   Mon Nov  4 09:41:25 2013 +0000

msvcp: Fixed complex division.

---

 dlls/msvcp71/math.c |   40 ++++++++++++++++++++++------------------
 dlls/msvcp80/math.c |   40 ++++++++++++++++++++++------------------
 dlls/msvcp90/math.c |   40 ++++++++++++++++++++++------------------
 3 files changed, 66 insertions(+), 54 deletions(-)

diff --git a/dlls/msvcp71/math.c b/dlls/msvcp71/math.c
index 69e4509..7d56c70 100644
--- a/dlls/msvcp71/math.c
+++ b/dlls/msvcp71/math.c
@@ -1087,6 +1087,7 @@ complex_float* __cdecl complex_float_add_cf(complex_float *ret, const complex_fl
 /* ??$?KM at std@@YA?AV?$complex at M@0 at AEBV10@0 at Z */
 complex_float* __cdecl complex_float_div(complex_float *ret, const complex_float *l, const complex_float *r)
 {
+    float tmp, den;
     if((!r->real && !r->imag) || _isnan(l->real) || _isnan(l->imag)
             || _isnan(r->real) || _isnan(r->imag)) {
         ret->real = std_numeric_limits_float_quiet_NaN();
@@ -1094,15 +1095,16 @@ complex_float* __cdecl complex_float_div(complex_float *ret, const complex_float
         return ret;
     }
 
-    ret->real = 0;
-    ret->imag = 0;
-    if(r->real) {
-        ret->real = l->real / r->real;
-        ret->imag = l->imag / r->real;
-    }
-    if(r->imag) {
-        ret->real += l->imag / r->imag;
-        ret->imag -= l->real / r->imag;
+    if (fabsf(r->real) >= fabsf(r->imag)) {
+        tmp = r->imag / r->real;
+        den = r->real + r->imag*tmp;
+        ret->real = (l->real + l->imag*tmp) / den;
+        ret->imag = (l->imag - l->real*tmp) / den;
+    } else {
+        tmp = r->real / r->imag;
+        den = r->real*tmp + r->imag;
+        ret->real = (l->real*tmp + l->imag) / den;
+        ret->imag = (l->imag*tmp - l->real) / den;
     }
     return ret;
 }
@@ -1705,6 +1707,7 @@ complex_double* __cdecl complex_double_add_cd(complex_double *ret, const complex
 /* ??$?KO at std@@YA?AV?$complex at O@0 at AEBV10@0 at Z */
 complex_double* __cdecl complex_double_div(complex_double *ret, const complex_double *l, const complex_double *r)
 {
+    double tmp, den;
     if((!r->real && !r->imag) || _isnan(l->real) || _isnan(l->imag)
             || _isnan(r->real) || _isnan(r->imag)) {
         ret->real = std_numeric_limits_double_quiet_NaN();
@@ -1712,15 +1715,16 @@ complex_double* __cdecl complex_double_div(complex_double *ret, const complex_do
         return ret;
     }
 
-    ret->real = 0;
-    ret->imag = 0;
-    if(r->real) {
-        ret->real = l->real / r->real;
-        ret->imag = l->imag / r->real;
-    }
-    if(r->imag) {
-        ret->real += l->imag / r->imag;
-        ret->imag -= l->real / r->imag;
+    if (fabs(r->real) >= fabs(r->imag)) {
+        tmp = r->imag / r->real;
+        den = r->real + r->imag*tmp;
+        ret->real = (l->real + l->imag*tmp) / den;
+        ret->imag = (l->imag - l->real*tmp) / den;
+    } else {
+        tmp = r->real / r->imag;
+        den = r->real*tmp + r->imag;
+        ret->real = (l->real*tmp + l->imag) / den;
+        ret->imag = (l->imag*tmp - l->real) / den;
     }
     return ret;
 }
diff --git a/dlls/msvcp80/math.c b/dlls/msvcp80/math.c
index 69e4509..7d56c70 100644
--- a/dlls/msvcp80/math.c
+++ b/dlls/msvcp80/math.c
@@ -1087,6 +1087,7 @@ complex_float* __cdecl complex_float_add_cf(complex_float *ret, const complex_fl
 /* ??$?KM at std@@YA?AV?$complex at M@0 at AEBV10@0 at Z */
 complex_float* __cdecl complex_float_div(complex_float *ret, const complex_float *l, const complex_float *r)
 {
+    float tmp, den;
     if((!r->real && !r->imag) || _isnan(l->real) || _isnan(l->imag)
             || _isnan(r->real) || _isnan(r->imag)) {
         ret->real = std_numeric_limits_float_quiet_NaN();
@@ -1094,15 +1095,16 @@ complex_float* __cdecl complex_float_div(complex_float *ret, const complex_float
         return ret;
     }
 
-    ret->real = 0;
-    ret->imag = 0;
-    if(r->real) {
-        ret->real = l->real / r->real;
-        ret->imag = l->imag / r->real;
-    }
-    if(r->imag) {
-        ret->real += l->imag / r->imag;
-        ret->imag -= l->real / r->imag;
+    if (fabsf(r->real) >= fabsf(r->imag)) {
+        tmp = r->imag / r->real;
+        den = r->real + r->imag*tmp;
+        ret->real = (l->real + l->imag*tmp) / den;
+        ret->imag = (l->imag - l->real*tmp) / den;
+    } else {
+        tmp = r->real / r->imag;
+        den = r->real*tmp + r->imag;
+        ret->real = (l->real*tmp + l->imag) / den;
+        ret->imag = (l->imag*tmp - l->real) / den;
     }
     return ret;
 }
@@ -1705,6 +1707,7 @@ complex_double* __cdecl complex_double_add_cd(complex_double *ret, const complex
 /* ??$?KO at std@@YA?AV?$complex at O@0 at AEBV10@0 at Z */
 complex_double* __cdecl complex_double_div(complex_double *ret, const complex_double *l, const complex_double *r)
 {
+    double tmp, den;
     if((!r->real && !r->imag) || _isnan(l->real) || _isnan(l->imag)
             || _isnan(r->real) || _isnan(r->imag)) {
         ret->real = std_numeric_limits_double_quiet_NaN();
@@ -1712,15 +1715,16 @@ complex_double* __cdecl complex_double_div(complex_double *ret, const complex_do
         return ret;
     }
 
-    ret->real = 0;
-    ret->imag = 0;
-    if(r->real) {
-        ret->real = l->real / r->real;
-        ret->imag = l->imag / r->real;
-    }
-    if(r->imag) {
-        ret->real += l->imag / r->imag;
-        ret->imag -= l->real / r->imag;
+    if (fabs(r->real) >= fabs(r->imag)) {
+        tmp = r->imag / r->real;
+        den = r->real + r->imag*tmp;
+        ret->real = (l->real + l->imag*tmp) / den;
+        ret->imag = (l->imag - l->real*tmp) / den;
+    } else {
+        tmp = r->real / r->imag;
+        den = r->real*tmp + r->imag;
+        ret->real = (l->real*tmp + l->imag) / den;
+        ret->imag = (l->imag*tmp - l->real) / den;
     }
     return ret;
 }
diff --git a/dlls/msvcp90/math.c b/dlls/msvcp90/math.c
index e049d69..f804ac9 100644
--- a/dlls/msvcp90/math.c
+++ b/dlls/msvcp90/math.c
@@ -1087,6 +1087,7 @@ complex_float* __cdecl complex_float_add_cf(complex_float *ret, const complex_fl
 /* ??$?KM at std@@YA?AV?$complex at M@0 at AEBV10@0 at Z */
 complex_float* __cdecl complex_float_div(complex_float *ret, const complex_float *l, const complex_float *r)
 {
+    float tmp, den;
     if((!r->real && !r->imag) || _isnan(l->real) || _isnan(l->imag)
             || _isnan(r->real) || _isnan(r->imag)) {
         ret->real = std_numeric_limits_float_quiet_NaN();
@@ -1094,15 +1095,16 @@ complex_float* __cdecl complex_float_div(complex_float *ret, const complex_float
         return ret;
     }
 
-    ret->real = 0;
-    ret->imag = 0;
-    if(r->real) {
-        ret->real = l->real / r->real;
-        ret->imag = l->imag / r->real;
-    }
-    if(r->imag) {
-        ret->real += l->imag / r->imag;
-        ret->imag -= l->real / r->imag;
+    if (fabsf(r->real) >= fabsf(r->imag)) {
+        tmp = r->imag / r->real;
+        den = r->real + r->imag*tmp;
+        ret->real = (l->real + l->imag*tmp) / den;
+        ret->imag = (l->imag - l->real*tmp) / den;
+    } else {
+        tmp = r->real / r->imag;
+        den = r->real*tmp + r->imag;
+        ret->real = (l->real*tmp + l->imag) / den;
+        ret->imag = (l->imag*tmp - l->real) / den;
     }
     return ret;
 }
@@ -1705,6 +1707,7 @@ complex_double* __cdecl complex_double_add_cd(complex_double *ret, const complex
 /* ??$?KO at std@@YA?AV?$complex at O@0 at AEBV10@0 at Z */
 complex_double* __cdecl complex_double_div(complex_double *ret, const complex_double *l, const complex_double *r)
 {
+    double tmp, den;
     if((!r->real && !r->imag) || _isnan(l->real) || _isnan(l->imag)
             || _isnan(r->real) || _isnan(r->imag)) {
         ret->real = std_numeric_limits_double_quiet_NaN();
@@ -1712,15 +1715,16 @@ complex_double* __cdecl complex_double_div(complex_double *ret, const complex_do
         return ret;
     }
 
-    ret->real = 0;
-    ret->imag = 0;
-    if(r->real) {
-        ret->real = l->real / r->real;
-        ret->imag = l->imag / r->real;
-    }
-    if(r->imag) {
-        ret->real += l->imag / r->imag;
-        ret->imag -= l->real / r->imag;
+    if (fabs(r->real) >= fabs(r->imag)) {
+        tmp = r->imag / r->real;
+        den = r->real + r->imag*tmp;
+        ret->real = (l->real + l->imag*tmp) / den;
+        ret->imag = (l->imag - l->real*tmp) / den;
+    } else {
+        tmp = r->real / r->imag;
+        den = r->real*tmp + r->imag;
+        ret->real = (l->real*tmp + l->imag) / den;
+        ret->imag = (l->imag*tmp - l->real) / den;
     }
     return ret;
 }




More information about the wine-cvs mailing list