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_asin.cpp sl@0: // Arc sin. 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: #ifndef __USE_VFP_MATH sl@0: sl@0: LOCAL_D const TUint32 ArcsinCoeffs[] = sl@0: { sl@0: 0x00000000,0x80000000,0x7FFF0000, // polynomial approximation to arcsin(x) sl@0: 0xAA893CD8,0xAAAAAAAA,0x7FFC0000, // for -0.5<=x<=0.5 sl@0: 0xD07ED410,0x99999999,0x7FFB0000, sl@0: 0xB6C64A72,0xB6DB6D94,0x7FFA0000, sl@0: 0xF5527DD4,0xF8E3995C,0x7FF90000, sl@0: 0xA87499FB,0xB744B969,0x7FF90000, sl@0: 0x2E8953AD,0x8E392B24,0x7FF90000, sl@0: 0xFEDBB4E4,0xE3481C4A,0x7FF80000, sl@0: 0x4A32ED70,0xC89998E1,0x7FF80000, sl@0: 0x848A2B53,0xCCAE4AE5,0x7FF70000, sl@0: 0x09C1F387,0xA587A043,0x7FF90000, sl@0: 0x722B9041,0x8C9BD20B,0x7FF90001, sl@0: 0xC88B75CC,0x850CE779,0x7FFA0000 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 Pidata[] = {0x2168C235,0xC90FDAA2,0x80000000}; // pi sl@0: LOCAL_D const TUint32 PiBy2data[] = {0x2168C235,0xC90FDAA2,0x7FFF0000}; // pi/2 sl@0: sl@0: LOCAL_C TInt CalcArcsinArccos(TReal& aTrg, TRealX& x, TBool aCos) sl@0: { sl@0: // Calculate arcsin (if aCos false) or arccos (if aCos true) of x sl@0: // and write result to aTrg. sl@0: // Algorithm (arcsin): sl@0: // If x>0.5, replace x with Sqrt((1-x)/2) sl@0: // ( use identity cos(x)=2(cos(x/2))^2-1 ) sl@0: // Use polynomial approximation for arcsin(x), 0<=x<=0.5 sl@0: // If original x>0.5, replace result y with pi/2-2y sl@0: sl@0: const TRealX One = *(const TRealX*)Onedata; sl@0: const TRealX Half = *(const TRealX*)Halfdata; sl@0: const TRealX Pi = *(const TRealX*)Pidata; sl@0: const TRealX PiBy2 = *(const TRealX*)PiBy2data; sl@0: sl@0: TInt sign=x.iSign&1; sl@0: x.iSign=0; sl@0: if (x<=One) sl@0: { sl@0: TBool big=(x>Half); sl@0: if (big) sl@0: { sl@0: x=One-x; sl@0: if (x.iExp>1) sl@0: x.iExp--; sl@0: TReal temp; sl@0: Math::Sqrt(temp, (TReal)x); sl@0: x=temp; sl@0: } sl@0: TRealX y; sl@0: Math::PolyX(y,x*x,12,(const TRealX*)ArcsinCoeffs); sl@0: y*=x; sl@0: if (big) sl@0: { sl@0: if (y.iExp) sl@0: y.iExp++; sl@0: if (aCos) sl@0: { sl@0: if (sign) sl@0: y=Pi-y; sl@0: } sl@0: else sl@0: { sl@0: y=PiBy2-y; sl@0: y.iSign=TInt8(sign); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: y.iSign=TInt8(sign); sl@0: if (aCos) sl@0: y=PiBy2-y; sl@0: } sl@0: return y.GetTReal(aTrg); sl@0: } sl@0: return KErrArgument; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C TInt Math::ASin(TReal& aTrg, const TReal& aSrc) sl@0: /** sl@0: Calculates the principal value of the inverse sine of a number. sl@0: sl@0: @param aTrg A reference containing the result in radians, sl@0: a value between -pi/2 and +pi/2. sl@0: @param aSrc The argument of the arcsin function, a value sl@0: between -1 and +1 inclusive. sl@0: sl@0: @return KErrNone if successful, otherwise another of the system-wide sl@0: error codes. sl@0: */ sl@0: { sl@0: TRealX x; sl@0: TInt r=x.Set(aSrc); sl@0: if (r==KErrNone) sl@0: r=CalcArcsinArccos(aTrg,x,EFalse); sl@0: if (r==KErrNone) sl@0: return r; sl@0: SetNaN(aTrg); sl@0: return KErrArgument; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C TInt Math::ACos(TReal& aTrg, const TReal& aSrc) sl@0: /** sl@0: Calculates the principal value of the inverse cosine of a number. sl@0: sl@0: @param aTrg A reference containing the result in radians, sl@0: a value between 0 and pi. sl@0: @param aSrc The argument of the arccos function, a value sl@0: between -1 and +1 inclusive. sl@0: sl@0: @return KErrNone if successful, otherwise another of the system-wide sl@0: error codes. sl@0: */ sl@0: { sl@0: TRealX x; sl@0: TInt r=x.Set(aSrc); sl@0: if (r==KErrNone) sl@0: r=CalcArcsinArccos(aTrg,x,ETrue); sl@0: if (r==KErrNone) sl@0: return r; 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 asin(TReal); sl@0: extern "C" TReal acos(TReal); sl@0: sl@0: EXPORT_C TInt Math::ASin(TReal& aTrg, const TReal& aSrc) sl@0: { sl@0: aTrg = asin(aSrc); sl@0: if (Math::IsFinite(aTrg)) sl@0: return KErrNone; sl@0: SetNaN(aTrg); sl@0: return KErrArgument; sl@0: } sl@0: sl@0: EXPORT_C TInt Math::ACos(TReal& aTrg, const TReal& aSrc) sl@0: { sl@0: aTrg = acos(aSrc); sl@0: if (Math::IsFinite(aTrg)) sl@0: return KErrNone; sl@0: SetNaN(aTrg); sl@0: return KErrArgument; sl@0: } sl@0: sl@0: #endif