1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_svtools.hxx" 26 27 #include <mcvmath.hxx> 28 29 // --------------------------------------------------------------------- 30 // die folgenden Tabellen enthalten sin(phi) * 2**14 31 // fuer phi= 360Grad*2**-32 bis 360 Grad 32 // def. fuer x: phi=360Grad * 2**(x-16) 33 // d.h. x = 16 -> 360 Grad 34 // x = -16 -> (2**-16) * 360 Grad 35 // x: -16 ... 0 ... 15 36 //x= 0, 1, 2, 3, 4, 5, 6, 7, 37 // 8, 9, 10, 11, 12, 13, 14, 15 38 39 static const short CosTab[16] = 40 { 41 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16383, 42 16379, 16364, 16305, 16069, 15137, 11585, 0, -16383 43 }; 44 static const short SinTab[16]= 45 { 46 2, 3, 6, 13, 25, 50, 101, 201, 47 402, 804, 1606, 3196, 6270, 11585, 16384, 0 48 }; 49 50 /************************************************************************** 51 |* 52 |* ImpMultBig2() 53 |* 54 |* Beschreibung Multiplikation fuer FixPoint-Berechnungen 55 |* Ersterstellung SH 01.07.93 56 |* Letzte Aenderung SH 01.07.93 57 |* 58 **************************************************************************/ 59 60 // first parameter should be the bigger one 61 62 Fix ImpMultBig2( const Fix& a, const Fix& b ) 63 { 64 Fix f; 65 f.x = (((b.x+FIX_A2)>>FIX_P2)*a.x+FIX_A3)>>FIX_P3; 66 return f; 67 } 68 69 /************************************************************************** 70 |* 71 |* ImpMultBig2() 72 |* 73 |* Beschreibung Multiplikation fuer FixPoint-Berechnungen 74 |* Ersterstellung SH 01.07.93 75 |* Letzte Aenderung SH 01.07.93 76 |* 77 **************************************************************************/ 78 79 // first parameter should be the bigger one 80 81 FixCpx ImpMultBig2( const FixCpx& ra, const FixCpx& rb ) 82 { 83 Fix rr = ImpMultBig2(ra.r,rb.r)-ImpMultBig2(ra.i,rb.i); 84 Fix ii = ImpMultBig2(ra.r,rb.i)+ImpMultBig2(ra.i,rb.r); 85 return FixCpx( rr,ii ); 86 } 87 88 /************************************************************************** 89 |* 90 |* ImpSqrt() 91 |* 92 |* Beschreibung Wurzelfunktion fuer FixPoint-Berechnungen 93 |* Ersterstellung SH 01.07.93 94 |* Letzte Aenderung SH 01.07.93 95 |* 96 **************************************************************************/ 97 98 sal_uInt16 ImpSqrt( sal_uLong nRadi ) 99 { 100 register sal_uLong inf = 1; 101 register sal_uLong sup = nRadi; 102 register sal_uLong sqr; 103 104 if ( !nRadi ) 105 return 0; 106 107 while ( (inf<<1) <= sup ) 108 { 109 sup >>= 1; 110 inf <<= 1; 111 } 112 sqr = (sup+inf) >> 1; // Anfangswert der Iteration 113 114 sqr = (nRadi/sqr + sqr) >> 1; // 2 Newton-Iterationen reichen fuer 115 sqr = (nRadi/sqr + sqr) >> 1; // +- 1 Digit 116 117 return sal::static_int_cast< sal_uInt16 >(sqr); 118 } 119 120 /************************************************************************** 121 |* 122 |* ImpExPI() 123 |* 124 |* Beschreibung EXPI-Funktion fuer FixPoint-Berechnungen 125 |* Ersterstellung SH 01.07.93 126 |* Letzte Aenderung SH 01.07.93 127 |* 128 **************************************************************************/ 129 130 // e**(i*nPhi), Einheit nPhi: 2**16 == 360 Grad 131 132 FixCpx ImpExPI( sal_uInt16 nPhi ) 133 { 134 short i; 135 FixCpx aIter(1L); // e**(0*i) 136 FixCpx Mul; 137 const char Sft=14-FIX_POST; 138 139 for ( i = 15; i >= 0; i-- ) 140 { 141 if ( (1L<<i) & nPhi ) 142 { 143 Mul.r.x = CosTab[i]>>Sft; // e**(i(phi1+phi2)) = 144 Mul.i.x = SinTab[i]>>Sft; // e**(i*phi1)) * e**(i*phi2)) 145 aIter *= Mul; 146 } 147 } 148 149 return aIter; 150 } 151 152 /************************************************************************** 153 |* 154 |* ImpATanx2() 155 |* 156 |* Beschreibung ATANX2-Funktion fuer FixPoint-Berechnungen 157 |* Ersterstellung SH 01.07.93 158 |* Letzte Aenderung SH 01.07.93 159 |* 160 **************************************************************************/ 161 162 // use for x*x+y*y==1 only 163 164 static sal_uInt16 ImpATanx2( const Fix& rX, const Fix& rY ) 165 { 166 sal_uInt16 phi0 = 0; // result angel higher part 167 sal_uInt16 phi = 0; // dito lower part 168 long x = rX.x; 169 long y = rY.x; 170 long z; 171 const char Sft=14-FIX_POST; 172 short i; 173 FixCpx aTry; 174 FixCpx aInc; 175 FixCpx aIter(1L); 176 sal_Bool Small = sal_False; 177 178 if ( (x==0) && (y==0) ) 179 return 0; 180 181 if ( y < 0) 182 { 183 // reduce 3. to 1. quadrant (0..90 Degree) 184 phi0 += 180L * 65536L / 360L; 185 // turn 180 degree 186 y *= -1; 187 x *= -1; 188 } 189 190 if ( x < 0) 191 { 192 // 2. to 1. q. 193 phi0 += 90L * 65536L / 360L; 194 // turn 90 degree clockwise 195 z = y; 196 y = -x; 197 x = z; 198 } 199 200 for ( i = 13; i >= 0; i-- ) 201 { 202 aInc.r.x = CosTab[i]>>Sft; // e**(i(phi1+phi2)) = 203 aInc.i.x = SinTab[i]>>Sft; // e**(i*phi1)) * e**(i*phi2)) 204 aTry = aIter*aInc; 205 206 if ( Small ) 207 { 208 // is try ok 209 if ( aTry.r.x >= x ) 210 { 211 aIter = aTry; 212 phi += (1<<i); 213 } 214 } 215 else 216 { 217 // is try ok 218 if ( aTry.i.x <= y ) 219 { 220 aIter = aTry; 221 phi += (1<<i); 222 223 if ( i > 11 ) 224 Small=sal_True; 225 } 226 } 227 } 228 229 return phi0+phi; 230 } 231 232 /************************************************************************** 233 |* 234 |* ImpATan2() 235 |* 236 |* Beschreibung ATAN-Funktion fuer FixPoint-Berechnungen 237 |* Ersterstellung SH 01.07.93 238 |* Letzte Aenderung SH 01.07.93 239 |* 240 **************************************************************************/ 241 242 sal_uInt16 ImpATan2( const short x, const short y ) 243 { 244 Fix rRad = ImpSqrt(sal_uLong(long(x)*x+long(y)*y)); 245 246 if ( !rRad.x ) 247 return 0; 248 Fix fx = x; 249 fx.DivBig( rRad ); // Normiere auf Einheitskreis 250 Fix fy = y; 251 fy.DivBig( rRad ); 252 253 return ImpATanx2( fx, fy ); 254 } 255 256 /************************************************************************** 257 |* 258 |* ImpCartToPolar() 259 |* 260 |* Beschreibung Koordinaaten-Wandlung 261 |* Ersterstellung SH 01.07.93 262 |* Letzte Aenderung SH 01.07.93 263 |* 264 **************************************************************************/ 265 266 void ImpCartToPolar( const short x, const short y, Fix& rRad, sal_uInt16& rPhi ) 267 { 268 rRad = Fix( ImpSqrt( sal_uLong( long(x)*x+long(y)*y ) ) ); 269 270 if ( !rRad.x ) 271 rPhi=0; 272 else 273 { 274 // Normiere auf Einheitskreis 275 Fix fx = x; 276 fx.DivBig(rRad); 277 Fix fy = y; 278 fy.DivBig(rRad); 279 rPhi = ImpATanx2(fx, fy); 280 } 281 } 282 283 /************************************************************************** 284 |* 285 |* ImpPolarToCart() 286 |* 287 |* Beschreibung Koordinaaten-Wandlung 288 |* Ersterstellung SH 01.07.93 289 |* Letzte Aenderung SH 01.07.93 290 |* 291 **************************************************************************/ 292 293 void ImpPolarToCart( const Fix& rR, const sal_uInt16 Phi, short& rX, short& rY ) 294 { 295 FixCpx fc = ImpExPI( Phi ); // calculate sin() & cos() 296 fc.GetReal().MultBig( rR ); 297 rX = sal::static_int_cast< short >(long( fc.GetReal() )); 298 fc.GetImag().MultBig( rR ); 299 rY = sal::static_int_cast< short >(long( fc.GetImag() )); 300 } 301 302