kernel/eka/euser/maths/um_tan.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32\euser\maths\um_tan.cpp
       
    15 // Tangent.
       
    16 // 
       
    17 //
       
    18 
       
    19 #include "um_std.h"
       
    20 
       
    21 #if defined(__USE_VFP_MATH) && !defined(__CPU_HAS_VFP)
       
    22 #error	__USE_VFP_MATH was defined but not __CPU_HAS_VFP - impossible combination, check variant.mmh 
       
    23 #endif
       
    24 
       
    25 
       
    26 #ifndef __USE_VFP_MATH
       
    27 
       
    28 LOCAL_D const TUint32 TanCoeffs[] =
       
    29 	{
       
    30 	0x2168C235,0xC90FDAA2,0x7FFF0000,	// polynomial approximation to tan((pi/2)*x)
       
    31 	0x2DF4707D,0xA55DE731,0x7FFF0000,	// for |x|<=0.25
       
    32 	0xA9A1A71A,0xA335E33B,0x7FFF0000,
       
    33 	0x0BB9E431,0xA2FFFCDD,0x7FFF0000,
       
    34 	0x3E523A39,0xA2FA3863,0x7FFF0000,
       
    35 	0x8A35C401,0xA2F9D38B,0x7FFF0000,
       
    36 	0x91269411,0xA2F16003,0x7FFF0000,
       
    37 	0xDA32CC78,0xA3A93B13,0x7FFF0000,
       
    38 	0x4FB88317,0x9A146197,0x7FFF0000,
       
    39 	0x0D787ECE,0xE131DEE5,0x7FFF0000
       
    40 	};
       
    41 
       
    42 LOCAL_D const TUint32 Onedata[] = {0x00000000,0x80000000,0x7FFF0000};		// 1.0
       
    43 LOCAL_D const TUint32 Halfdata[] = {0x00000000,0x80000000,0x7FFE0000};		// 0.5
       
    44 LOCAL_D const TUint32 PiBy2Invdata[] = {0x4E44152A,0xA2F9836E,0x7FFE0000};	// 2/pi
       
    45 
       
    46 
       
    47 
       
    48 
       
    49 EXPORT_C TInt Math::Tan(TReal& aTrg, const TReal& aSrc)
       
    50 /**
       
    51 Calculates the tangent of a number.
       
    52 
       
    53 @param aTrg A reference containing the result.
       
    54 @param aSrc The argument of the tan function in radians. 
       
    55 
       
    56 @return KErrNone if successful, otherwise another of
       
    57         the system-wide error codes. 
       
    58 */
       
    59 	{
       
    60 	// Calculate tan(aSrc) and write result to aTrg.
       
    61 	// Algorithm:
       
    62 	//		Let x=aSrc/(pi/2). Throw away integer part, but if integer part odd
       
    63 	//			then replace final result y with -1/y
       
    64 	//			( use identities tan(x+n*pi)=tan(x), tan(x+pi/2)=-1/tan(x) )
       
    65 	//		Replace x with fractional part after division.
       
    66 	//		If x>=0.5, replace x with 1-x and replace result y with 1/y
       
    67 	//			( use identity tan(pi/2-x)=1/tan(x) )
       
    68 	//		If x>=0.25, replace x with 0.5-x and replace result y with (1-y)/(1+y)
       
    69 	//			( use identity tan(pi/4-x)=(1-tan(x))/(1+tan(x)) )
       
    70 	//		Use polynomial approximation to calculate tan(pi*x/2) for |x|<=0.25
       
    71 
       
    72 	const TRealX& One = *(const TRealX*)Onedata;
       
    73 	const TRealX& Half = *(const TRealX*)Halfdata;
       
    74 	const TRealX& PiBy2Inv = *(const TRealX*)PiBy2Invdata;
       
    75 
       
    76 	TRealX x;
       
    77 	TInt r=x.Set(aSrc);
       
    78 	if (r==KErrNone)
       
    79 		{
       
    80 		TInt8 sign=x.iSign;
       
    81 		x.iSign=0;
       
    82 		x*=PiBy2Inv;
       
    83 		TInt n=(TInt)x;
       
    84 		if (n<KMaxTInt && n>KMinTInt)
       
    85 			{
       
    86 			TInt flags=(n&1)<<1;
       
    87 			x-=TRealX(n);
       
    88 			if (x.iExp>=0x7FFE)
       
    89 				{
       
    90 				x=One-x;
       
    91 				flags^=2;
       
    92 				}
       
    93 			if (x.iExp>=0x7FFD)
       
    94 				{
       
    95 				x=Half-x;
       
    96 				flags^=1;
       
    97 				}
       
    98 			TRealX y;
       
    99 			PolyX(y,x*x,9,(const TRealX*)TanCoeffs);
       
   100 			y*=x;
       
   101 			if (flags==3)
       
   102 				y=(One+y)/(One-y);
       
   103 			else if (flags==2)
       
   104 				y=One/y;
       
   105 			else if (flags==1)
       
   106 				y=(One-y)/(One+y);
       
   107 			y.iSign=TInt8(sign ^ (n&1));
       
   108 			return y.GetTReal(aTrg);
       
   109 			}
       
   110 		}
       
   111 	SetNaN(aTrg);
       
   112 	return KErrArgument;
       
   113 	}
       
   114 
       
   115 #else // __USE_VFP_MATH
       
   116 
       
   117 // definitions come from RVCT math library
       
   118 extern "C" TReal tan(TReal);
       
   119 
       
   120 EXPORT_C TInt Math::Tan(TReal& aTrg, const TReal& aSrc)
       
   121 	{
       
   122 	if (aSrc<KMaxTInt && aSrc>KMinTInt)
       
   123 		{
       
   124 		aTrg = tan(aSrc);
       
   125 		if (Math::IsFinite(aTrg))
       
   126 			return KErrNone;
       
   127 		}
       
   128 	SetNaN(aTrg);
       
   129 	return KErrArgument;
       
   130 	}
       
   131 
       
   132 #endif