sl@0: // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32\euser\maths\um_tan.cpp sl@0: // Tangent. sl@0: // sl@0: // sl@0: sl@0: #include "um_std.h" sl@0: sl@0: #if defined(__USE_VFP_MATH) && !defined(__CPU_HAS_VFP) sl@0: #error __USE_VFP_MATH was defined but not __CPU_HAS_VFP - impossible combination, check variant.mmh sl@0: #endif sl@0: sl@0: sl@0: #ifndef __USE_VFP_MATH sl@0: sl@0: LOCAL_D const TUint32 TanCoeffs[] = sl@0: { sl@0: 0x2168C235,0xC90FDAA2,0x7FFF0000, // polynomial approximation to tan((pi/2)*x) sl@0: 0x2DF4707D,0xA55DE731,0x7FFF0000, // for |x|<=0.25 sl@0: 0xA9A1A71A,0xA335E33B,0x7FFF0000, sl@0: 0x0BB9E431,0xA2FFFCDD,0x7FFF0000, sl@0: 0x3E523A39,0xA2FA3863,0x7FFF0000, sl@0: 0x8A35C401,0xA2F9D38B,0x7FFF0000, sl@0: 0x91269411,0xA2F16003,0x7FFF0000, sl@0: 0xDA32CC78,0xA3A93B13,0x7FFF0000, sl@0: 0x4FB88317,0x9A146197,0x7FFF0000, sl@0: 0x0D787ECE,0xE131DEE5,0x7FFF0000 sl@0: }; sl@0: sl@0: LOCAL_D const TUint32 Onedata[] = {0x00000000,0x80000000,0x7FFF0000}; // 1.0 sl@0: LOCAL_D const TUint32 Halfdata[] = {0x00000000,0x80000000,0x7FFE0000}; // 0.5 sl@0: LOCAL_D const TUint32 PiBy2Invdata[] = {0x4E44152A,0xA2F9836E,0x7FFE0000}; // 2/pi sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C TInt Math::Tan(TReal& aTrg, const TReal& aSrc) sl@0: /** sl@0: Calculates the tangent of a number. sl@0: sl@0: @param aTrg A reference containing the result. sl@0: @param aSrc The argument of the tan function in radians. sl@0: sl@0: @return KErrNone if successful, otherwise another of sl@0: the system-wide error codes. sl@0: */ sl@0: { sl@0: // Calculate tan(aSrc) and write result to aTrg. sl@0: // Algorithm: sl@0: // Let x=aSrc/(pi/2). Throw away integer part, but if integer part odd sl@0: // then replace final result y with -1/y sl@0: // ( use identities tan(x+n*pi)=tan(x), tan(x+pi/2)=-1/tan(x) ) sl@0: // Replace x with fractional part after division. sl@0: // If x>=0.5, replace x with 1-x and replace result y with 1/y sl@0: // ( use identity tan(pi/2-x)=1/tan(x) ) sl@0: // If x>=0.25, replace x with 0.5-x and replace result y with (1-y)/(1+y) sl@0: // ( use identity tan(pi/4-x)=(1-tan(x))/(1+tan(x)) ) sl@0: // Use polynomial approximation to calculate tan(pi*x/2) for |x|<=0.25 sl@0: sl@0: const TRealX& One = *(const TRealX*)Onedata; sl@0: const TRealX& Half = *(const TRealX*)Halfdata; sl@0: const TRealX& PiBy2Inv = *(const TRealX*)PiBy2Invdata; sl@0: sl@0: TRealX x; sl@0: TInt r=x.Set(aSrc); sl@0: if (r==KErrNone) sl@0: { sl@0: TInt8 sign=x.iSign; sl@0: x.iSign=0; sl@0: x*=PiBy2Inv; sl@0: TInt n=(TInt)x; sl@0: if (nKMinTInt) sl@0: { sl@0: TInt flags=(n&1)<<1; sl@0: x-=TRealX(n); sl@0: if (x.iExp>=0x7FFE) sl@0: { sl@0: x=One-x; sl@0: flags^=2; sl@0: } sl@0: if (x.iExp>=0x7FFD) sl@0: { sl@0: x=Half-x; sl@0: flags^=1; sl@0: } sl@0: TRealX y; sl@0: PolyX(y,x*x,9,(const TRealX*)TanCoeffs); sl@0: y*=x; sl@0: if (flags==3) sl@0: y=(One+y)/(One-y); sl@0: else if (flags==2) sl@0: y=One/y; sl@0: else if (flags==1) sl@0: y=(One-y)/(One+y); sl@0: y.iSign=TInt8(sign ^ (n&1)); sl@0: return y.GetTReal(aTrg); sl@0: } sl@0: } sl@0: SetNaN(aTrg); sl@0: return KErrArgument; sl@0: } sl@0: sl@0: #else // __USE_VFP_MATH sl@0: sl@0: // definitions come from RVCT math library sl@0: extern "C" TReal tan(TReal); sl@0: sl@0: EXPORT_C TInt Math::Tan(TReal& aTrg, const TReal& aSrc) sl@0: { sl@0: if (aSrcKMinTInt) sl@0: { sl@0: aTrg = tan(aSrc); sl@0: if (Math::IsFinite(aTrg)) sl@0: return KErrNone; sl@0: } sl@0: SetNaN(aTrg); sl@0: return KErrArgument; sl@0: } sl@0: sl@0: #endif