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