1 2 // Copyright (C) 2001-2003 by Digital Mars 3 // All Rights Reserved 4 // www.digitalmars.com 5 6 // Runtime support for complex arithmetic code generation 7 // (for linux) 8 9 /* 10 * Modified by Sean Kelly <sean@f4.ca> for use with Tango. 11 */ 12 13 module rt.compiler.dmd.rt.cmath2; 14 15 //private import tango.stdc.math; 16 17 extern (C): 18 19 /**************************** 20 * Multiply two complex floating point numbers, x and y. 21 * Input: 22 * x.re ST3 23 * x.im ST2 24 * y.re ST1 25 * y.im ST0 26 * Output: 27 * ST1 real part 28 * ST0 imaginary part 29 */ 30 31 void _Cmul() 32 { 33 // p.re = x.re * y.re - x.im * y.im; 34 // p.im = x.im * y.re + x.re * y.im; 35 asm 36 { naked ; 37 fld ST(1) ; // x.re 38 fmul ST,ST(4) ; // ST0 = x.re * y.re 39 40 fld ST(1) ; // y.im 41 fmul ST,ST(4) ; // ST0 = x.im * y.im 42 43 fsubp ST(1),ST ; // ST0 = x.re * y.re - x.im * y.im 44 45 fld ST(3) ; // x.im 46 fmul ST,ST(3) ; // ST0 = x.im * y.re 47 48 fld ST(5) ; // x.re 49 fmul ST,ST(3) ; // ST0 = x.re * y.im 50 51 faddp ST(1),ST ; // ST0 = x.im * y.re + x.re * y.im 52 53 fxch ST(4),ST ; 54 fstp ST(0) ; 55 fxch ST(4),ST ; 56 fstp ST(0) ; 57 fstp ST(0) ; 58 fstp ST(0) ; 59 60 ret ; 61 } 62 /+ 63 if (isnan(x) && isnan(y)) 64 { 65 // Recover infinities that computed as NaN+ iNaN ... 66 int recalc = 0; 67 if ( isinf( a) || isinf( b) ) 68 { // z is infinite 69 // "Box" the infinity and change NaNs in the other factor to 0 70 a = copysignl( isinf( a) ? 1.0 : 0.0, a); 71 b = copysignl( isinf( b) ? 1.0 : 0.0, b); 72 if (isnan( c)) c = copysignl( 0.0, c); 73 if (isnan( d)) d = copysignl( 0.0, d); 74 recalc = 1; 75 } 76 if (isinf(c) || isinf(d)) 77 { // w is infinite 78 // "Box" the infinity and change NaNs in the other factor to 0 79 c = copysignl( isinf( c) ? 1.0 : 0.0, c); 80 d = copysignl( isinf( d) ? 1.0 : 0.0, d); 81 if (isnan( a)) a = copysignl( 0.0, a); 82 if (isnan( b)) b = copysignl( 0.0, b); 83 recalc = 1; 84 } 85 if (!recalc && (isinf(ac) || isinf(bd) || 86 isinf(ad) || isinf(bc))) 87 { 88 // Recover infinities from overflow by changing NaNs to 0 ... 89 if (isnan( a)) a = copysignl( 0.0, a); 90 if (isnan( b)) b = copysignl( 0.0, b); 91 if (isnan( c)) c = copysignl( 0.0, c); 92 if (isnan( d)) d = copysignl( 0.0, d); 93 recalc = 1; 94 } 95 if (recalc) 96 { 97 x = INFINITY * (a * c - b * d); 98 y = INFINITY * (a * d + b * c); 99 } 100 } 101 +/ 102 } 103 104 /**************************** 105 * Divide two complex floating point numbers, x / y. 106 * Input: 107 * x.re ST3 108 * x.im ST2 109 * y.re ST1 110 * y.im ST0 111 * Output: 112 * ST1 real part 113 * ST0 imaginary part 114 */ 115 116 void _Cdiv() 117 { 118 real x_re, x_im; 119 real y_re, y_im; 120 real q_re, q_im; 121 real r; 122 real den; 123 124 asm 125 { 126 fstp y_im ; 127 fstp y_re ; 128 fstp x_im ; 129 fstp x_re ; 130 } 131 132 if (((y_re<0)?-y_re:y_re) < ((y_im<0)?-y_im:y_im)) 133 { 134 r = y_re / y_im; 135 den = y_im + r * y_re; 136 q_re = (x_re * r + x_im) / den; 137 q_im = (x_im * r - x_re) / den; 138 } 139 else 140 { 141 r = y_im / y_re; 142 den = y_re + r * y_im; 143 q_re = (x_re + r * x_im) / den; 144 q_im = (x_im - r * x_re) / den; 145 } 146 //printf("q.re = %g, q.im = %g\n", (double)q_re, (double)q_im); 147 /+ 148 if (isnan(q_re) && isnan(q_im)) 149 { 150 real denom = y_re * y_re + y_im * y_im; 151 152 // non-zero / zero 153 if (denom == 0.0 && (!isnan(x_re) || !isnan(x_im))) 154 { 155 q_re = copysignl(INFINITY, y_re) * x_re; 156 q_im = copysignl(INFINITY, y_re) * x_im; 157 } 158 // infinite / finite 159 else if ((isinf(x_re) || isinf(x_im)) && isfinite(y_re) && isfinite(y_im)) 160 { 161 x_re = copysignl(isinf(x_re) ? 1.0 : 0.0, x_re); 162 x_im = copysignl(isinf(x_im) ? 1.0 : 0.0, x_im); 163 q_re = INFINITY * (x_re * y_re + x_im * y_im); 164 q_im = INFINITY * (x_im * y_re - x_re * y_im); 165 } 166 // finite / infinite 167 else if (isinf(logbw) && isfinite(x_re) && isfinite(x_im)) 168 { 169 y_re = copysignl(isinf(y_re) ? 1.0 : 0.0, y_re); 170 y_im = copysignl(isinf(y_im) ? 1.0 : 0.0, y_im); 171 q_re = 0.0 * (x_re * y_re + x_im * y_im); 172 q_im = 0.0 * (x_im * y_re - x_re * y_im); 173 } 174 } 175 return q_re + q_im * 1.0i; 176 +/ 177 asm 178 { 179 fld q_re; 180 fld q_im; 181 } 182 } 183 184 /**************************** 185 * Compare two complex floating point numbers, x and y. 186 * Input: 187 * x.re ST3 188 * x.im ST2 189 * y.re ST1 190 * y.im ST0 191 * Output: 192 * 8087 stack is cleared 193 * flags set 194 */ 195 196 void _Ccmp() 197 { 198 asm 199 { naked ; 200 fucomp ST(2) ; // compare x.im and y.im 201 fstsw AX ; 202 sahf ; 203 jne L1 ; 204 jp L1 ; // jmp if NAN 205 fucomp ST(2) ; // compare x.re and y.re 206 fstsw AX ; 207 sahf ; 208 fstp ST(0) ; // pop 209 fstp ST(0) ; // pop 210 ret ; 211 212 L1: 213 fstp ST(0) ; // pop 214 fstp ST(0) ; // pop 215 fstp ST(0) ; // pop 216 ret ; 217 } 218 }