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