symport/e32/euser/maths/um_ln.cpp
changeset 1 0a7b44b10206
child 2 806186ab5e14
equal deleted inserted replaced
0:c55016431358 1:0a7b44b10206
       
     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 "Symbian Foundation License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32\euser\maths\um_ln.cpp
       
    15 // Natural log.
       
    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 ArtanhCoeffs[] =
       
    29 	{
       
    30 	0x5C17F0BC,0xB8AA3B29,0x80010000,	// polynomial approximation to (4/ln2)artanh(x)
       
    31 	0xD02489EE,0xF6384EE1,0x7FFF0000,	// for |x| <= (sqr2-1)/(sqr2+1)
       
    32 	0x7008CA5F,0x93BB6287,0x7FFF0000,
       
    33 	0xE32D1D6B,0xD30BB16D,0x7FFE0000,
       
    34 	0x461D071E,0xA4257CE2,0x7FFE0000,
       
    35 	0xC3B0EC87,0x8650D459,0x7FFE0000,
       
    36 	0x53BEC0CD,0xE23137E3,0x7FFD0000,
       
    37 	0xC523F21B,0xDAF79221,0x7FFD0000
       
    38 	};
       
    39 
       
    40 LOCAL_D const TUint32 Ln2By2data[] = {0xD1CF79AC,0xB17217F7,0x7FFD0000};	// (ln2)/2
       
    41 LOCAL_D const TUint32 Sqr2data[] = {0xF9DE6484,0xB504F333,0x7FFF0000};		// sqr2
       
    42 LOCAL_D const TUint32 Sqr2Invdata[] = {0xF9DE6484,0xB504F333,0x7FFE0000};	// 1/sqr2
       
    43 LOCAL_D const TUint32 Onedata[] = {0x00000000,0x80000000,0x7FFF0000};		// 1.0
       
    44 
       
    45 
       
    46 
       
    47 
       
    48 EXPORT_C TInt Math::Ln(TReal& aTrg, const TReal& aSrc)
       
    49 /**
       
    50 Calculates the natural logarithm of a number.
       
    51 
       
    52 @param aTrg A reference containing the result. 
       
    53 @param aSrc The number whose natural logarithm is required.
       
    54 
       
    55 @return KErrNone if successful, otherwise another of
       
    56         the system-wide error codes. 
       
    57 */
       
    58 	{
       
    59 	// Calculate ln(aSrc) and write to aTrg
       
    60 	// Algorithm:
       
    61 	//		Calculate log2(aSrc) and multiply by ln2
       
    62 	//		log2(aSrc)=log2(2^e.m) e=exponent of aSrc, m=mantissa 1<=m<2
       
    63 	//		log2(aSrc)=e+log2(m)
       
    64 	//		If e=-1 (0.5<=aSrc<1), let x=aSrc else let x=mantissa(aSrc)
       
    65 	//		If x>Sqr2, replace x with x/Sqr2
       
    66 	//		If x<Sqr2/2, replace x with x*Sqr2
       
    67 	//		Replace x with (x-1)/(x+1)
       
    68 	//		Use polynomial to calculate artanh(x) for |x| <= (sqr2-1)/(sqr2+1)
       
    69 	//			( use identity ln(x) = 2artanh((x-1)/(x+1)) )
       
    70 
       
    71 	TRealX x;
       
    72 	const TRealX& Ln2By2=*(const TRealX*)Ln2By2data;
       
    73 	const TRealX& Sqr2=*(const TRealX*)Sqr2data;
       
    74 	const TRealX& Sqr2Inv=*(const TRealX*)Sqr2Invdata;
       
    75 	const TRealX& One=*(const TRealX*)Onedata;
       
    76 
       
    77 	TInt r=x.Set(aSrc);
       
    78 	if (r==KErrNone)
       
    79 		{
       
    80 		if (x.iExp==0)
       
    81 			{
       
    82 			SetInfinite(aTrg,1);
       
    83 			return KErrOverflow;
       
    84 			}
       
    85 		if (x.iSign&1)
       
    86 			{
       
    87 			SetNaN(aTrg);
       
    88 			return KErrArgument;
       
    89 			}
       
    90 		TInt n=(x.iExp-0x7FFF)<<1;
       
    91 		x.iExp=0x7FFF;
       
    92 		if (n!=-2)
       
    93 			{
       
    94 			if (x>Sqr2)
       
    95 				{
       
    96 				x*=Sqr2Inv;
       
    97 				n++;
       
    98 				}
       
    99 			}
       
   100 		else 
       
   101 			{
       
   102 			n=0;
       
   103 			x.iExp=0x7FFE;
       
   104 			if (x<Sqr2Inv)
       
   105 				{
       
   106 				x*=Sqr2;
       
   107 				n--;
       
   108 				}
       
   109 			}
       
   110 		x=(x-One)/(x+One);	// ln(x)=2artanh((x-1)/(x+1))
       
   111 		TRealX y;
       
   112 		PolyX(y,x*x,7,(const TRealX*)ArtanhCoeffs);
       
   113 		y*=x;
       
   114 		y+=TRealX(n);
       
   115 		y*=Ln2By2;
       
   116 		return y.GetTReal(aTrg);
       
   117 		}
       
   118 	if (r==KErrArgument || (r==KErrOverflow && (x.iSign&1)))
       
   119 		{
       
   120 		SetNaN(aTrg);
       
   121 		return KErrArgument;
       
   122 		}
       
   123 	SetInfinite(aTrg,0);
       
   124 	return KErrOverflow;
       
   125 	}
       
   126 
       
   127 #else // __USE_VFP_MATH
       
   128 
       
   129 // definitions come from RVCT math library
       
   130 extern "C" TReal log(TReal);
       
   131 
       
   132 EXPORT_C TInt Math::Ln(TReal& aTrg, const TReal& aSrc)
       
   133 	{
       
   134 	aTrg = log(aSrc);
       
   135 	if (Math::IsFinite(aTrg))
       
   136 		return KErrNone;
       
   137 	if (Math::IsInfinite(aTrg))
       
   138 		return KErrOverflow;
       
   139 	SetNaN(aTrg);
       
   140 	return KErrArgument;
       
   141 	}
       
   142 
       
   143 #endif