os/kernelhwsrv/kernel/eka/euser/maths/um_sin.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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