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