os/kernelhwsrv/kernel/eka/euser/maths/um_asin.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.
sl@0
     1
// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32\euser\maths\um_asin.cpp
sl@0
    15
// Arc sin.
sl@0
    16
// 
sl@0
    17
//
sl@0
    18
sl@0
    19
#include "um_std.h"
sl@0
    20
sl@0
    21
#if defined(__USE_VFP_MATH) && !defined(__CPU_HAS_VFP)
sl@0
    22
#error	__USE_VFP_MATH was defined but not __CPU_HAS_VFP - impossible combination, check variant.mmh 
sl@0
    23
#endif
sl@0
    24
sl@0
    25
#ifndef __USE_VFP_MATH
sl@0
    26
sl@0
    27
LOCAL_D const TUint32 ArcsinCoeffs[] =
sl@0
    28
	{
sl@0
    29
	0x00000000,0x80000000,0x7FFF0000,	// polynomial approximation to arcsin(x)
sl@0
    30
	0xAA893CD8,0xAAAAAAAA,0x7FFC0000,	// for -0.5<=x<=0.5
sl@0
    31
	0xD07ED410,0x99999999,0x7FFB0000,
sl@0
    32
	0xB6C64A72,0xB6DB6D94,0x7FFA0000,
sl@0
    33
	0xF5527DD4,0xF8E3995C,0x7FF90000,
sl@0
    34
	0xA87499FB,0xB744B969,0x7FF90000,
sl@0
    35
	0x2E8953AD,0x8E392B24,0x7FF90000,
sl@0
    36
	0xFEDBB4E4,0xE3481C4A,0x7FF80000,
sl@0
    37
	0x4A32ED70,0xC89998E1,0x7FF80000,
sl@0
    38
	0x848A2B53,0xCCAE4AE5,0x7FF70000,
sl@0
    39
	0x09C1F387,0xA587A043,0x7FF90000,
sl@0
    40
	0x722B9041,0x8C9BD20B,0x7FF90001,
sl@0
    41
	0xC88B75CC,0x850CE779,0x7FFA0000
sl@0
    42
	};
sl@0
    43
sl@0
    44
LOCAL_D const TUint32 Onedata[] = {0x00000000,0x80000000,0x7FFF0000};		// 1.0
sl@0
    45
LOCAL_D const TUint32 Halfdata[] = {0x00000000,0x80000000,0x7FFE0000};		// 0.5
sl@0
    46
LOCAL_D const TUint32 Pidata[] = {0x2168C235,0xC90FDAA2,0x80000000};		// pi
sl@0
    47
LOCAL_D const TUint32 PiBy2data[] = {0x2168C235,0xC90FDAA2,0x7FFF0000};		// pi/2
sl@0
    48
sl@0
    49
LOCAL_C TInt CalcArcsinArccos(TReal& aTrg, TRealX& x, TBool aCos)
sl@0
    50
	{
sl@0
    51
	//	Calculate arcsin (if aCos false) or arccos (if aCos true) of x
sl@0
    52
	//	and write result to aTrg.
sl@0
    53
	//	Algorithm (arcsin):
sl@0
    54
	//		If x>0.5, replace x with Sqrt((1-x)/2)
sl@0
    55
	//			( use identity cos(x)=2(cos(x/2))^2-1 )
sl@0
    56
	//		Use polynomial approximation for arcsin(x), 0<=x<=0.5
sl@0
    57
	//		If original x>0.5, replace result y with pi/2-2y
sl@0
    58
sl@0
    59
	const TRealX One = *(const TRealX*)Onedata;
sl@0
    60
	const TRealX Half = *(const TRealX*)Halfdata;
sl@0
    61
	const TRealX Pi = *(const TRealX*)Pidata;
sl@0
    62
	const TRealX PiBy2 = *(const TRealX*)PiBy2data;
sl@0
    63
sl@0
    64
	TInt sign=x.iSign&1;
sl@0
    65
	x.iSign=0;
sl@0
    66
	if (x<=One)
sl@0
    67
		{
sl@0
    68
		TBool big=(x>Half);
sl@0
    69
		if (big)
sl@0
    70
			{
sl@0
    71
			x=One-x;
sl@0
    72
			if (x.iExp>1)
sl@0
    73
				x.iExp--;
sl@0
    74
			TReal temp;
sl@0
    75
			Math::Sqrt(temp, (TReal)x);
sl@0
    76
			x=temp;
sl@0
    77
			}
sl@0
    78
		TRealX y;
sl@0
    79
		Math::PolyX(y,x*x,12,(const TRealX*)ArcsinCoeffs);
sl@0
    80
		y*=x;
sl@0
    81
		if (big)
sl@0
    82
			{
sl@0
    83
			if (y.iExp)
sl@0
    84
				y.iExp++;
sl@0
    85
			if (aCos)
sl@0
    86
				{
sl@0
    87
				if (sign)
sl@0
    88
					y=Pi-y;
sl@0
    89
				}
sl@0
    90
			else
sl@0
    91
				{
sl@0
    92
				y=PiBy2-y;
sl@0
    93
				y.iSign=TInt8(sign);
sl@0
    94
				}
sl@0
    95
			}
sl@0
    96
		else
sl@0
    97
			{
sl@0
    98
			y.iSign=TInt8(sign);
sl@0
    99
			if (aCos)
sl@0
   100
				y=PiBy2-y;
sl@0
   101
			}
sl@0
   102
		return y.GetTReal(aTrg);
sl@0
   103
		}
sl@0
   104
	return KErrArgument;
sl@0
   105
	}
sl@0
   106
sl@0
   107
sl@0
   108
sl@0
   109
sl@0
   110
EXPORT_C TInt Math::ASin(TReal& aTrg, const TReal& aSrc)
sl@0
   111
/**
sl@0
   112
Calculates the principal value of the inverse sine of a number.
sl@0
   113
sl@0
   114
@param aTrg A reference containing the result in radians,
sl@0
   115
            a value between -pi/2 and +pi/2. 
sl@0
   116
@param aSrc The argument of the arcsin function, a value
sl@0
   117
            between -1 and +1 inclusive.
sl@0
   118
sl@0
   119
@return KErrNone if successful, otherwise another of the system-wide
sl@0
   120
        error codes.
sl@0
   121
*/
sl@0
   122
	{
sl@0
   123
	TRealX x;
sl@0
   124
	TInt r=x.Set(aSrc);
sl@0
   125
	if (r==KErrNone)
sl@0
   126
		r=CalcArcsinArccos(aTrg,x,EFalse);
sl@0
   127
	if (r==KErrNone)
sl@0
   128
		return r;
sl@0
   129
	SetNaN(aTrg);
sl@0
   130
	return KErrArgument;
sl@0
   131
	}
sl@0
   132
sl@0
   133
sl@0
   134
sl@0
   135
sl@0
   136
EXPORT_C TInt Math::ACos(TReal& aTrg, const TReal& aSrc)
sl@0
   137
/**
sl@0
   138
Calculates the principal value of the inverse cosine of a number.
sl@0
   139
sl@0
   140
@param aTrg A reference containing the result in radians,
sl@0
   141
            a value between 0 and pi. 
sl@0
   142
@param aSrc The argument of the arccos function, a value
sl@0
   143
            between -1 and +1 inclusive. 
sl@0
   144
sl@0
   145
@return KErrNone if successful, otherwise another of the system-wide
sl@0
   146
        error codes.
sl@0
   147
*/
sl@0
   148
	{
sl@0
   149
	TRealX x;
sl@0
   150
	TInt r=x.Set(aSrc);
sl@0
   151
	if (r==KErrNone)
sl@0
   152
		r=CalcArcsinArccos(aTrg,x,ETrue);
sl@0
   153
	if (r==KErrNone)
sl@0
   154
		return r;
sl@0
   155
	SetNaN(aTrg);
sl@0
   156
	return KErrArgument;
sl@0
   157
	}
sl@0
   158
sl@0
   159
#else // __USE_VFP_MATH
sl@0
   160
sl@0
   161
// definitions come from RVCT math library
sl@0
   162
extern "C" TReal asin(TReal);
sl@0
   163
extern "C" TReal acos(TReal);
sl@0
   164
sl@0
   165
EXPORT_C TInt Math::ASin(TReal& aTrg, const TReal& aSrc)
sl@0
   166
	{
sl@0
   167
	aTrg = asin(aSrc);
sl@0
   168
	if (Math::IsFinite(aTrg))
sl@0
   169
		return KErrNone;
sl@0
   170
	SetNaN(aTrg);
sl@0
   171
	return KErrArgument;
sl@0
   172
	}
sl@0
   173
sl@0
   174
EXPORT_C TInt Math::ACos(TReal& aTrg, const TReal& aSrc)
sl@0
   175
	{
sl@0
   176
	aTrg = acos(aSrc);
sl@0
   177
	if (Math::IsFinite(aTrg))
sl@0
   178
		return KErrNone;
sl@0
   179
	SetNaN(aTrg);
sl@0
   180
	return KErrArgument;
sl@0
   181
	}
sl@0
   182
sl@0
   183
#endif