kernel/eka/euser/maths/um_sin.cpp
changeset 43 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 43:96e5fb8b040d
       
     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_sin.cpp
       
    15 // Floating point sine and cosine functions
       
    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 SinCoeffs[] =
       
    29 	{
       
    30 	0x2168C235,0xC90FDAA2,0x80000000,	// polynomial approximation to sin(pi*x)
       
    31 	0x2DF200BF,0xA55DE731,0x80010001,	// for |x| <= 0.25
       
    32 	0xAC273AA1,0xA335E33B,0x80000000,
       
    33 	0x5AB23F44,0x99696671,0x7FFE0001,
       
    34 	0xD585EAFE,0xA83C17D9,0x7FFB0000,
       
    35 	0xA30DE7AD,0xF1802BAC,0x7FF70001,
       
    36 	0xF57FD821,0xF1F6A1C9,0x7FF30000
       
    37 	};
       
    38 
       
    39 LOCAL_D const TUint32 CosCoeffs[] =
       
    40 	{
       
    41 	0x00000000,0x80000000,0x7FFF0000,	// polynomial approximation to cos(pi*x)
       
    42 	0xF22EF286,0x9DE9E64D,0x80010001,	// for |x| <= 0.25
       
    43 	0xDAD59F90,0x81E0F840,0x80010000,
       
    44 	0xE4E45144,0xAAE9E3F1,0x7FFF0001,
       
    45 	0x3232D733,0xF0FA8342,0x7FFC0000,
       
    46 	0x03E16BB8,0xD368F6A3,0x7FF90001,
       
    47 	0x712FD084,0xFCE66DE2,0x7FF50000,
       
    48 	0x9E5353EE,0xD94951B0,0x7FF10001
       
    49 	};
       
    50 
       
    51 LOCAL_D const TUint32 PiInvdata[] = {0x4E44152A,0xA2F9836E,0x7FFD0000};			// 1/pi
       
    52 LOCAL_D const TUint32 Halfdata[] = {0x00000000,0x80000000,0x7FFE0000};			// 0.5
       
    53 LOCAL_D const TUint32 Onedata[] = {0x00000000,0x80000000,0x7FFF0000};			// 1.0
       
    54 
       
    55 LOCAL_C TInt CalcSinCos(TReal& aTrg, TRealX& aSrc, TBool aCos)
       
    56 	{
       
    57 	// Calculate sin(aSrc) if aCos=false or cos(aSrc) if aCos=true
       
    58 	// and write result to aTrg.
       
    59 	// Algorithm:
       
    60 	//		Divide aSrc by pi and throw away integer part, but change sign
       
    61 	//			of result if integer part odd. Replace aSrc with remainder.
       
    62 	//			( use identities	sin(x+n*pi)=(-1)^n*sin(x)
       
    63 	//								cos(x+n*pi)=(-1)^n*cos(x) )
       
    64 	//		If aSrc>=0.5 replace aSrc with 1-aSrc, and change sign of result
       
    65 	//			if cos required.
       
    66 	//			( use identities sin(pi-x)=sin(x), cos(pi-x)=-cos(x) )
       
    67 	//		If aSrc>=0.25 replace aSrc with 0.5-aSrc and swap sin and cos
       
    68 	//			( use identities sin(pi/2-x)=cos(x), cos(pi/2-x)=sin(x) )
       
    69 	//		Use polynomial approximation to evaluate sin(pi*x) or cos(pi*x)
       
    70 	//		for |x|<=0.25
       
    71 
       
    72 	const TRealX& One = *(const TRealX*)Onedata;
       
    73 	const TRealX& Half = *(const TRealX*)Halfdata;
       
    74 	const TRealX& PiInv = *(const TRealX*)PiInvdata;
       
    75 
       
    76 	TRealX y;
       
    77 	aSrc*=PiInv;
       
    78 	TInt n=(TInt)aSrc;
       
    79 	if (n<KMaxTInt && n>KMinTInt)
       
    80 		{
       
    81 		aSrc-=TRealX(n);
       
    82 		TInt sign=0;
       
    83 		if (!aCos)
       
    84 			sign=aSrc.iSign & 1;
       
    85 		sign^=n;
       
    86 		aSrc.iSign=0;
       
    87 		if (aSrc.iExp>=0x7FFE)			// if remainder>=pi/2
       
    88 			{
       
    89 			aSrc=One-aSrc;
       
    90 			if (aCos)
       
    91 				sign^=1;
       
    92 			}
       
    93 		if (aSrc.iExp>=0x7FFD)			// if remainder>=pi/4
       
    94 			{
       
    95 			aSrc=Half-aSrc;				// take complementary angle
       
    96 			aCos=!aCos;					// and swap sin and cos
       
    97 			}
       
    98 		if (aCos)
       
    99 			Math::PolyX(y,aSrc*aSrc,7,(const TRealX*)CosCoeffs);
       
   100 		else
       
   101 			{
       
   102 			Math::PolyX(y,aSrc*aSrc,6,(const TRealX*)SinCoeffs);
       
   103 			y*=aSrc;
       
   104 			}
       
   105 		if (sign & 1)
       
   106 			y=-y;
       
   107 		return y.GetTReal(aTrg);
       
   108 		}
       
   109 	return KErrArgument;
       
   110 	}
       
   111 
       
   112 
       
   113 
       
   114 
       
   115 EXPORT_C TInt Math::Sin(TReal& aTrg, const TReal& aSrc)
       
   116 /**
       
   117 Calculates the sine of a number.
       
   118 
       
   119 @param aTrg A reference containing the result. 
       
   120 @param aSrc The argument of the sin function in radians.
       
   121 
       
   122 @return KErrNone if successful, otherwise another of
       
   123         the system-wide error codes.
       
   124 */
       
   125 	{
       
   126 	TRealX x;
       
   127 	TInt r=x.Set(aSrc);
       
   128 	if (r==KErrNone)
       
   129 		r=CalcSinCos(aTrg,x,EFalse);
       
   130 	if (r==KErrNone)
       
   131 		return r;
       
   132 	SetNaN(aTrg);
       
   133 	return KErrArgument;
       
   134 	}
       
   135 
       
   136 
       
   137 
       
   138 
       
   139 EXPORT_C TInt Math::Cos(TReal& aTrg, const TReal& aSrc)
       
   140 /**
       
   141 Calculates the cosine of a number.
       
   142 
       
   143 @param aTrg A reference containing the result. 
       
   144 @param aSrc The argument of the cos function in radians
       
   145 
       
   146 @return KErrNone if successful, otherwise another of
       
   147         the system-wide error codes.
       
   148 */
       
   149 	{
       
   150 	TRealX x;
       
   151 	TInt r=x.Set(aSrc);
       
   152 	if (r==KErrNone)
       
   153 		r=CalcSinCos(aTrg,x,ETrue);
       
   154 	if (r==KErrNone)
       
   155 		return r;
       
   156 	SetNaN(aTrg);
       
   157 	return KErrArgument;
       
   158 	}
       
   159 
       
   160 #else // __USE_VFP_MATH
       
   161 
       
   162 // definitions come from RVCT math library
       
   163 extern "C" TReal sin(TReal);
       
   164 extern "C" TReal cos(TReal);
       
   165 
       
   166 EXPORT_C TInt Math::Sin(TReal& aTrg, const TReal& aSrc)
       
   167 	{
       
   168 	if (aSrc<KMaxTInt && aSrc>KMinTInt)
       
   169 		{
       
   170 		aTrg = sin(aSrc);
       
   171 		if (Math::IsFinite(aTrg))
       
   172 			return KErrNone;
       
   173 		}
       
   174 	SetNaN(aTrg);
       
   175 	return KErrArgument;
       
   176 	}
       
   177 
       
   178 EXPORT_C TInt Math::Cos(TReal& aTrg, const TReal& aSrc)
       
   179 	{
       
   180 	if (aSrc<KMaxTInt && aSrc>KMinTInt)
       
   181 		{
       
   182 		aTrg = cos(aSrc);
       
   183 		if (Math::IsFinite(aTrg))
       
   184 			return KErrNone;
       
   185 		}
       
   186 	SetNaN(aTrg);
       
   187 	return KErrArgument;
       
   188 	}
       
   189 
       
   190 #endif