summaryrefslogtreecommitdiff
path: root/src/classlibnative/float
diff options
context:
space:
mode:
authordotnet-bot <dotnet-bot@microsoft.com>2015-01-30 14:14:42 -0800
committerdotnet-bot <dotnet-bot@microsoft.com>2015-01-30 14:14:42 -0800
commitef1e2ab328087c61a6878c1e84f4fc5d710aebce (patch)
treedee1bbb89e9d722e16b0d1485e3cdd1b6c8e2cfa /src/classlibnative/float
downloadcoreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.gz
coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.bz2
coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.zip
Initial commit to populate CoreCLR repo
[tfs-changeset: 1407945]
Diffstat (limited to 'src/classlibnative/float')
-rw-r--r--src/classlibnative/float/.gitmirror1
-rw-r--r--src/classlibnative/float/CMakeLists.txt16
-rw-r--r--src/classlibnative/float/Float.nativeproj35
-rw-r--r--src/classlibnative/float/floatnative.cpp491
-rw-r--r--src/classlibnative/float/floatnative.h34
5 files changed, 577 insertions, 0 deletions
diff --git a/src/classlibnative/float/.gitmirror b/src/classlibnative/float/.gitmirror
new file mode 100644
index 0000000000..f507630f94
--- /dev/null
+++ b/src/classlibnative/float/.gitmirror
@@ -0,0 +1 @@
+Only contents of this folder, excluding subfolders, will be mirrored by the Git-TFS Mirror. \ No newline at end of file
diff --git a/src/classlibnative/float/CMakeLists.txt b/src/classlibnative/float/CMakeLists.txt
new file mode 100644
index 0000000000..72e846cd0a
--- /dev/null
+++ b/src/classlibnative/float/CMakeLists.txt
@@ -0,0 +1,16 @@
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+include_directories("../inc")
+
+set(FLOAT_SOURCES
+ floatnative.cpp
+)
+
+if(CLR_CMAKE_PLATFORM_UNIX)
+ add_compile_options(-fPIC)
+endif(CLR_CMAKE_PLATFORM_UNIX)
+
+add_library(comfloat_wks
+ STATIC
+ ${FLOAT_SOURCES}
+)
diff --git a/src/classlibnative/float/Float.nativeproj b/src/classlibnative/float/Float.nativeproj
new file mode 100644
index 0000000000..091b8a75b9
--- /dev/null
+++ b/src/classlibnative/float/Float.nativeproj
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="dogfood">
+ <!--*****************************************************-->
+ <!--This MSBuild project file was automatically generated-->
+ <!--from the original SOURCES/DIRS file by the KBC tool.-->
+ <!--*****************************************************-->
+ <!--Import the settings-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.props" />
+ <Import Project="$(ClrBase)\src\debug\SetDebugTargetLocal.props" />
+ <PropertyGroup Label="Globals">
+ <SccProjectName>SAK</SccProjectName>
+ <SccAuxPath>SAK</SccAuxPath>
+ <SccLocalPath>SAK</SccLocalPath>
+ <SccProvider>SAK</SccProvider>
+ </PropertyGroup>
+ <!--Leaf project Properties-->
+ <PropertyGroup>
+ <BuildCoreBinaries>true</BuildCoreBinaries>
+ <BuildSysBinaries>true</BuildSysBinaries>
+ <!--OK to delete NO_NTDLL for devdiv builds.-->
+ <ClOptimization Condition="'$(DebugBuild)' == 'false'">Full</ClOptimization>
+ <UserIncludes>..\inc;$(UserIncludes);$(Clrbase)\src\vm;$(Clrbase)\src\vm\$(TargetCpu);$(VCToolsIncPath);$(Clrbase)\src\strongname\inc</UserIncludes>
+ <OutputName>comfloat_wks</OutputName>
+ <OutputPath>$(ClrLibDest)</OutputPath>
+ <TargetType>LIBRARY</TargetType>
+ <CDefines>$(CDefines);UNICODE;_UNICODE</CDefines>
+ <ClWarningLevel>4</ClWarningLevel>
+ </PropertyGroup>
+ <!--Leaf Project Items-->
+ <ItemGroup>
+ <CppCompile Include="FloatNative.cpp" />
+ </ItemGroup>
+ <!--Import the targets-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.targets" />
+</Project>
diff --git a/src/classlibnative/float/floatnative.cpp b/src/classlibnative/float/floatnative.cpp
new file mode 100644
index 0000000000..db3df4422e
--- /dev/null
+++ b/src/classlibnative/float/floatnative.cpp
@@ -0,0 +1,491 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+//
+// File: FloatNative.cpp
+//
+
+#include <common.h>
+
+#include "floatnative.h"
+#include "floatclass.h"
+
+#define IS_DBL_INFINITY(x) ((*((UINT64 *)((void *)&x)) & UI64(0x7FFFFFFFFFFFFFFF)) == UI64(0x7FF0000000000000))
+#define IS_DBL_ONE(x) ((*((UINT64 *)((void *)&x))) == UI64(0x3FF0000000000000))
+#define IS_DBL_NEGATIVEONE(x) ((*((UINT64 *)((void *)&x))) == UI64(0xBFF0000000000000))
+
+
+// Default compilation mode is /fp:precise, which disables fp intrinsics. This has caused
+// regression in floating point code. I've grouped all the helpers that are really simple
+// (where /fp:fast semantics are really unlikely to cause any regression) and grouped them
+// here in order to get back to Everett performance numbers
+
+////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////
+///
+/// Beggining of /fp:fast scope
+///
+////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef _MSC_VER
+#pragma float_control(precise, off)
+#endif
+
+/*====================================Floor=====================================
+**
+==============================================================================*/
+FCIMPL1_V(double, COMDouble::Floor, double d)
+ FCALL_CONTRACT;
+
+ return (double) floor(d);
+FCIMPLEND
+
+
+/*====================================Ceil=====================================
+**
+==============================================================================*/
+FCIMPL1_V(double, COMDouble::Ceil, double d)
+ FCALL_CONTRACT;
+
+ return (double) ceil(d);
+FCIMPLEND
+
+/*=====================================Sqrt=====================================
+**
+==============================================================================*/
+FCIMPL1_V(double, COMDouble::Sqrt, double d)
+ FCALL_CONTRACT;
+
+ return (double) sqrt(d);
+FCIMPLEND
+
+/*=====================================Acos=====================================
+**
+==============================================================================*/
+FCIMPL1_V(double, COMDouble::Acos, double d)
+ FCALL_CONTRACT;
+
+ return (double) acos(d);
+FCIMPLEND
+
+
+/*=====================================Asin=====================================
+**
+==============================================================================*/
+FCIMPL1_V(double, COMDouble::Asin, double d)
+ FCALL_CONTRACT;
+
+ return (double) asin(d);
+FCIMPLEND
+
+
+/*=====================================AbsFlt=====================================
+**
+==============================================================================*/
+FCIMPL1_V(float, COMDouble::AbsFlt, float f)
+ FCALL_CONTRACT;
+
+ FCUnique(0x14);
+
+ return fabsf(f);
+FCIMPLEND
+
+/*=====================================AbsDbl=====================================
+**
+==============================================================================*/
+FCIMPL1_V(double, COMDouble::AbsDbl, double d)
+ FCALL_CONTRACT;
+
+ return fabs(d);
+FCIMPLEND
+
+/*=====================================Atan=====================================
+**
+==============================================================================*/
+FCIMPL1_V(double, COMDouble::Atan, double d)
+ FCALL_CONTRACT;
+
+ return (double) atan(d);
+FCIMPLEND
+
+/*=====================================Atan2=====================================
+**
+==============================================================================*/
+FCIMPL2_VV(double, COMDouble::Atan2, double x, double y)
+ FCALL_CONTRACT;
+
+ // the intrinsic for Atan2 does not produce Nan for Atan2(+-inf,+-inf)
+ if (IS_DBL_INFINITY(x) && IS_DBL_INFINITY(y)) {
+ return(x / y); // create a NaN
+ }
+ return (double) atan2(x, y);
+FCIMPLEND
+
+// COMDouble::Sin/Cos/Tan are all implemented in JitHelpers_Fast.asm as x87 floating
+// point for code AMD64 (on Windows) because the CRT helpers is too slow (apparently they don't
+// have a /fp:fast v ersion).
+#if !defined(_TARGET_AMD64_) || defined(FEATURE_PAL)
+
+/*=====================================Sin=====================================
+**
+==============================================================================*/
+FCIMPL1_V(double, COMDouble::Sin, double d)
+ FCALL_CONTRACT;
+
+ return (double) sin(d);
+FCIMPLEND
+
+/*=====================================Cos=====================================
+**
+==============================================================================*/
+FCIMPL1_V(double, COMDouble::Cos, double d)
+ FCALL_CONTRACT;
+
+ return (double) cos(d);
+FCIMPLEND
+
+/*=====================================Tan=====================================
+**
+==============================================================================*/
+FCIMPL1_V(double, COMDouble::Tan, double d)
+ FCALL_CONTRACT;
+
+ return (double) tan(d);
+FCIMPLEND
+
+#endif // !defined(_TARGET_AMD64_) || defined(FEATURE_PAL)
+
+/*=====================================Sinh====================================
+**
+==============================================================================*/
+FCIMPL1_V(double, COMDouble::Sinh, double d)
+ FCALL_CONTRACT;
+
+ return (double) sinh(d);
+FCIMPLEND
+
+/*=====================================Cosh====================================
+**
+==============================================================================*/
+FCIMPL1_V(double, COMDouble::Cosh, double d)
+ FCALL_CONTRACT;
+
+ return (double) cosh(d);
+FCIMPLEND
+
+/*=====================================Tanh====================================
+**
+==============================================================================*/
+FCIMPL1_V(double, COMDouble::Tanh, double d)
+ FCALL_CONTRACT;
+
+ return (double) tanh(d);
+FCIMPLEND
+
+FCIMPL1(double, COMDouble::ModFDouble, double* pdblValue)
+ FCALL_CONTRACT;
+
+ double dblFrac;
+ dblFrac = modf(*pdblValue, pdblValue);
+ return dblFrac;
+FCIMPLEND
+
+#ifdef _MSC_VER
+#pragma float_control(precise, on )
+#endif
+
+////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////
+///
+/// End of /fp:fast scope
+///
+////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////
+//
+// Log, Log10 and Exp are slower with /fp:fast on SSE2 enabled HW (see #500373)
+// So we'll leave them as fp precise for the moment
+
+/*=====================================Log======================================
+**This is the natural log
+==============================================================================*/
+FCIMPL1_V(double, COMDouble::Log, double d)
+ FCALL_CONTRACT;
+
+ return (double) log(d);
+FCIMPLEND
+
+
+/*====================================Log10=====================================
+**This is log-10
+==============================================================================*/
+FCIMPL1_V(double, COMDouble::Log10, double d)
+ FCALL_CONTRACT;
+
+ return (double) log10(d);
+FCIMPLEND
+
+
+/*=====================================Exp======================================
+**
+==============================================================================*/
+FCIMPL1_V(double, COMDouble::Exp, double x)
+ FCALL_CONTRACT;
+
+ // The C intrinsic below does not handle +- infinity properly
+ // so we handle these specially here
+ if (IS_DBL_INFINITY(x)) {
+ if (x < 0)
+ return(+0.0);
+ return(x); // Must be + infinity
+ }
+ return((double) exp(x));
+FCIMPLEND
+
+#if defined(_TARGET_X86_)
+/*=====================================Pow======================================
+**This is the power function. Simple powers are done inline, and special
+ cases are sent to the CRT via the helper.
+==============================================================================*/
+FCIMPL2_VV(double, COMDouble::PowHelperSimple, double x, double y)
+{
+ FCALL_CONTRACT;
+
+ return (double) pow(x,y);
+}
+FCIMPLEND
+
+FCIMPL2_VV(double, COMDouble::PowHelper, double x, double y)
+{
+ FCALL_CONTRACT;
+
+ double r1;
+
+ // TODO: we can get rid following code if VC fixes pow function someday.
+ if(_isnan(y)) {
+ return y; // IEEE 754-2008: NaN payload must be preserved
+ }
+ if(_isnan(x)) {
+ return x; // IEEE 754-2008: NaN payload must be preserved
+ }
+ if(IS_DBL_INFINITY(y)) {
+ if(IS_DBL_ONE(x)) {
+ return x;
+ }
+
+ if(IS_DBL_NEGATIVEONE(x)) {
+ *((INT64 *)(&r1)) = CLR_NAN_64;
+ return r1;
+ }
+ }
+
+ return (double) pow(x, y);
+}
+FCIMPLEND
+
+#if defined (_DEBUG)
+__declspec(naked) static double F_CALL_CONV PowRetail(double x, double y)
+#else
+__declspec(naked) double F_CALL_CONV COMDouble::Pow(double x, double y)
+#endif
+{
+ WRAPPER_NO_CONTRACT;
+ STATIC_CONTRACT_SO_TOLERANT;
+
+ // Arguments:
+ // exponent: esp+4
+ // base: esp+12
+
+ _asm
+ {
+ mov ecx, [esp+8] ; high dword of exponent
+ mov edx, [esp+16] ; high dword of base
+
+ and ecx, 7ff00000H ; check for special exponent
+ cmp ecx, 7ff00000H
+ je callHelper
+
+ and edx, 7ff00000H ; check for special base
+ cmp edx, 7ff00000H
+ je callHelper
+
+ test edx, 7ff00000H ; see if the base has a zero exponent
+ jz test_if_we_have_zero_base
+
+base_is_not_zero:
+
+ mov cl, [esp+19] ; Handle negative base in the helper
+ and cl, 80H
+ jnz callHelper
+
+ jmp COMDouble::PowHelperSimple ;
+
+test_if_we_have_zero_base:
+
+ mov eax, [esp+16]
+ and eax, 000fffffH
+ or eax, [esp+12]
+ jnz base_is_not_zero
+ ; fall through to the helper
+
+callHelper:
+
+ jmp COMDouble::PowHelper ; The helper will return control
+ ; directly to our caller.
+ }
+}
+
+#ifdef _DEBUG
+
+#define EPSILON 0.0000000001
+
+void assertDoublesWithinRange(double r1, double r2)
+{
+ WRAPPER_NO_CONTRACT;
+
+ if (_finite(r1) && _finite(r2))
+ {
+ // Both numbers are finite--we need to check that they are close to
+ // each other. If they are large (> 1), the error could also be large,
+ // which is acceptable, so we compare the error against EPSILON*norm.
+
+ double norm = max(fabs(r1), fabs(r2));
+ double error = fabs(r1-r2);
+
+ assert((error < (EPSILON * norm)) || (error < EPSILON));
+ }
+ else if (!_isnan(r1) && !_isnan(r2))
+ {
+ // At least one of r1 and r2 is infinite, so when multiplied by
+ // (1 + EPSILON) they should be the same infinity.
+
+ assert((r1 * (1 + EPSILON)) == (r2 * (1 + EPSILON)));
+ }
+ else
+ {
+ // Otherwise at least one of r1 or r2 is a Nan. Is that case, they better be in
+ // the same class.
+
+ assert(_fpclass(r1) == _fpclass(r2));
+ }
+}
+
+FCIMPL2_VV(double, COMDouble::Pow, double x, double y)
+{
+ FCALL_CONTRACT;
+
+ double r1, r2;
+
+ if(_isnan(y)) {
+ return y; // IEEE 754-2008: NaN payload must be preserved
+ }
+ if(_isnan(x)) {
+ return x; // IEEE 754-2008: NaN payload must be preserved
+ }
+
+ if(IS_DBL_INFINITY(y)) {
+ if(IS_DBL_ONE(x)) {
+ return x;
+ }
+
+ if(IS_DBL_NEGATIVEONE(x)) {
+ *((INT64 *)(&r1)) = CLR_NAN_64;
+ return r1;
+ }
+ }
+
+ // Note that PowRetail expects the argument order to be reversed
+
+ r1 = (double) PowRetail(y, x);
+
+ r2 = (double) pow(x, y);
+
+ // Can't do a floating point compare in case r1 and r2 aren't
+ // valid fp numbers.
+
+ assertDoublesWithinRange(r1, r2);
+
+ return (double) r1;
+}
+FCIMPLEND
+
+#endif // _DEBUG
+
+#else // !defined(_TARGET_X86_)
+FCIMPL2_VV(double, COMDouble::Pow, double x, double y)
+{
+ FCALL_CONTRACT;
+
+ double r1;
+
+ if(_isnan(y)) {
+ return y; // IEEE 754-2008: NaN payload must be preserved
+ }
+ if(_isnan(x)) {
+ return x; // IEEE 754-2008: NaN payload must be preserved
+ }
+
+ if(IS_DBL_INFINITY(y)) {
+ if(IS_DBL_ONE(x)) {
+ return x;
+ }
+
+ if(IS_DBL_NEGATIVEONE(x)) {
+ *((INT64 *)(&r1)) = CLR_NAN_64;
+ return r1;
+ }
+ }
+
+ return (double) pow(x, y);
+}
+FCIMPLEND
+
+#endif // defined(_TARGET_X86_)
+
+
+/*====================================Round=====================================
+**
+==============================================================================*/
+#if defined(_TARGET_X86_)
+__declspec(naked)
+double __fastcall COMDouble::Round(double d)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ __asm {
+ fld QWORD PTR [ESP+4]
+ frndint
+ ret 8
+ }
+}
+
+#else // !defined(_TARGET_X86_)
+FCIMPL1_V(double, COMDouble::Round, double d)
+ FCALL_CONTRACT;
+
+ double tempVal;
+ double flrTempVal;
+ // If the number has no fractional part do nothing
+ // This shortcut is necessary to workaround precision loss in borderline cases on some platforms
+ if ( d == (double)(__int64)d )
+ return d;
+ tempVal = (d+0.5);
+ //We had a number that was equally close to 2 integers.
+ //We need to return the even one.
+ flrTempVal = floor(tempVal);
+ if (flrTempVal==tempVal) {
+ if (0 != fmod(tempVal, 2.0)) {
+ flrTempVal -= 1.0;
+ }
+ }
+ flrTempVal = _copysign(flrTempVal, d);
+ return flrTempVal;
+FCIMPLEND
+#endif // defined(_TARGET_X86_)
+
+
diff --git a/src/classlibnative/float/floatnative.h b/src/classlibnative/float/floatnative.h
new file mode 100644
index 0000000000..afce01fc77
--- /dev/null
+++ b/src/classlibnative/float/floatnative.h
@@ -0,0 +1,34 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+//
+// File: FloatNative.h
+//
+
+#ifndef _FLOATNATIVE_H
+#define _FLOATNATIVE_H
+
+// Removed due to compiler bug
+//
+// _CRTIMP double __cdecl floor(double);
+// _CRTIMP double __cdecl ceil(double);
+
+double __cdecl sqrt(double);
+double __cdecl log(double);
+double __cdecl log10(double);
+double __cdecl exp(double);
+double __cdecl pow(double, double);
+double __cdecl acos(double);
+double __cdecl asin(double);
+double __cdecl atan(double);
+double __cdecl atan2(double,double);
+double __cdecl cos(double);
+double __cdecl sin(double);
+double __cdecl tan(double);
+double __cdecl cosh(double);
+double __cdecl sinh(double);
+double __cdecl tanh(double);
+double __cdecl fmod(double, double);
+
+#endif // _FLOATNATIVE_H