Merge pull request #445 from fanoI/master

Continuation of Float work
This commit is contained in:
fanoI 2016-08-24 15:13:50 +02:00 committed by GitHub
commit 552ded82b8
30 changed files with 547 additions and 565 deletions

View file

@ -17,11 +17,12 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DefineConstants>TRACE;DEBUG</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\Release\</OutputPath>
@ -85,6 +86,7 @@
<Compile Include="System\BooleanTest.cs" />
<Compile Include="System\ByteTest.cs" />
<Compile Include="System\CharTest.cs" />
<Compile Include="System\Collections\Generic\DictionaryTest.cs" />
<Compile Include="System\Collections\Generic\ListTest.cs" />
<Compile Include="System\Collections\Generic\QueueTest.cs" />
<Compile Include="System\DecimalTest.cs" />
@ -100,6 +102,7 @@
<Compile Include="System\UInt16Test.cs" />
<Compile Include="System\UInt32Test.cs" />
<Compile Include="System\UInt64Test.cs" />
<Compile Include="System\UnsafeCodeTest.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Cosmos.TestRunner.TestController\Cosmos.TestRunner.TestController.csproj">

View file

@ -37,12 +37,11 @@ namespace Cosmos.Compiler.Tests.Bcl
BooleanTest.Execute();
SingleTest.Execute();
DoubleTest.Execute();
#if false
BitConverterTest.Execute();
UnsafeCodeTest.Execute();
#if false
DecimalTest.Execute();
//BitConverterTest.Execute();
//DecimalTest.Execute();
System.Collections.Generic.ListTest.Execute();
System.Collections.Generic.QueueTest.Execute();
System.DelegatesTest.Execute();

View file

@ -21,7 +21,6 @@ namespace Cosmos.Compiler.Tests.Bcl.System
Assert.IsTrue((result == expectedResult), "BitConverter.ToString(intBytes) doesn't work: result " + result + " != " + expectedResult);
long aLong = 1;
byte[] longBytes = BitConverter.GetBytes(aLong);

View file

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Cosmos.TestRunner;
namespace Cosmos.Compiler.Tests.Bcl.System.Collections.Generic
{
public static class DictionaryTest
{
public static void Execute()
{
Dictionary<String, Object> commands = new Dictionary<String, Object>()
{
{"echo", "ECHO"},
{"reboot", "REBOOT" },
{"shutdown", "SHUTDOWN"}
};
Assert.IsTrue(commands.ContainsKey("echo"), "Dictionary ContainsKey does not work");
}
}
}

View file

@ -10,13 +10,14 @@ namespace Cosmos.Compiler.Tests.Bcl.System
// This does not compile:
public static void Execute()
{
#if false
Decimal value;
String result;
String expectedResult;
value = 42.42M; // It exists Single.MaxValue but it is a too big value an can be represented only on Scientific notation but then how to confront with a String?
#if false
// This does not compile: Error: Exception: System.Exception: Native code encountered, plug required. Please see https://github.com/CosmosOS/Cosmos/wiki/Plugs). System.String System.Number.FormatDecimal(System.Decimal, System.String, System.Globalization.NumberFormatInfo
result = value.ToString();
expectedResult = "42.42";

View file

@ -26,31 +26,63 @@ namespace Cosmos.Compiler.Tests.Bcl.System
String result;
String expectedResult;
value = 42.42; // It exists Single.MaxValue but it is a too big value an can be represented only on Scientific notation but then how to confront with a String?
// It seems to be a problem in BitConverter.GetBytes with a Double value that in turn broke toString() for now a solution to this is not found
#if false
value = 1;
// Let's try to see as a ByteArray
byte[] doubleBytes = BitConverter.GetBytes(value);
Console.WriteLine($"doubleByte is of {doubleBytes.Length} bytes");
foreach (byte aByte in doubleBytes)
Console.WriteLine(aByte);
//Console.WriteLine("Double (as long) " + DoubleToUlong(value));
/* First start with some weird value (not really numbers) that the IEEE standard has */
value = Double.PositiveInfinity;
result = value.ToString();
expectedResult = "1";
expectedResult = "∞";
// The test fails the conversion returns "Double Underrange"
Assert.IsTrue((result == expectedResult), "Double.ToString doesn't work");
Assert.IsTrue((result == expectedResult), "Double.ToString of INF doesn't work");
value = Double.NegativeInfinity;
result = value.ToString();
expectedResult = "-∞";
Assert.IsTrue((result == expectedResult), "Double.ToString of -INF doesn't work");
value = Double.NaN;
result = value.ToString();
expectedResult = "NaN";
Assert.IsTrue((result == expectedResult), "Double.ToString of -NaN doesn't work");
/* Another special value is '0' */
value = 0;
result = value.ToString();
expectedResult = "0";
Assert.IsTrue((result == expectedResult), "Double.ToString of 0 doesn't work");
/* A negative value */
value = -42.42;
result = value.ToString();
expectedResult = "-42.42";
Assert.IsTrue((result == expectedResult), "Double.ToString of negative number doesn't work");
/* A big value (to be correct toString should convert it in scientific notation) */
value = 9223372036854775808;
result = value.ToString();
expectedResult = "9223372036854775808";
Assert.IsTrue((result == expectedResult), "Double.ToString of big number doesn't work");
/* OK now a normal value */
value = 42.42; // It exists Double.MaxValue but it is a too big value an can be represented only on Scientific notation but then how to confront with a String?
result = value.ToString();
expectedResult = "42.42";
Assert.IsTrue((result == expectedResult), "Double.ToString of normal number doesn't work");
// Now let's try to concat to a String using '+' operator
result = "The value of the Double is " + value;
expectedResult = "The value of the Double is 1";
expectedResult = "The value of the Double is 42.42";
Assert.IsTrue((result == expectedResult), "String concat (Double) doesn't work");
@ -59,14 +91,14 @@ namespace Cosmos.Compiler.Tests.Bcl.System
// Actually 'expectedResult' should be the same so...
Assert.IsTrue((result == expectedResult), "String format (Double) doesn't work");
#if false
// Now let's Get the HashCode of a value
int resultAsInt = value.GetHashCode();
// actually the Hash Code of a Int32 is the same value
Assert.IsTrue((resultAsInt == value), "Double.GetHashCode() doesn't work");
#endif
#if false
// Now let's try ToString() again but printed in hex (this test fails for now!)
result = value.ToString("X2");
expectedResult = "0x7FFFFFFF";
@ -163,22 +195,9 @@ namespace Cosmos.Compiler.Tests.Bcl.System
Assert.IsTrue((DoublesAreEqual(valueNegated, 42d)), "(double) negation doesn't work");
// Let's try if it works in the other way too
//value = 42.0;
//valueNegated = -value;
//Assert.IsTrue((DoublesAreEqual(valueNegated, -42.0f)), "(double) negation of positive float doesn't work");
#if false
unchecked
{
ulong anULong = (ulong)-1;
byte[] anULongAsBytes = BitConverter.GetBytes(anULong);
value = (double)anULong;
byte[] valueAsBytes = BitConverter.GetBytes(value);
//Assert.IsTrue((DoublesAreEqual(value, 18446744073709551615d)), "(double) from ulong operator doesn't work");
Assert.IsTrue((DoublesAreEqual(value, 18446744073709551615d)), "(double) from ulong operator doesn't work long is " + BitConverter.ToString(anULongAsBytes) + " value (as bytes) is " + BitConverter.ToString(valueAsBytes));
}
#endif
value = 42.0;
valueNegated = -value;
Assert.IsTrue((DoublesAreEqual(valueNegated, -42.0f)), "(double) negation of positive double doesn't work");
}
}
}

View file

@ -18,24 +18,24 @@ namespace Cosmos.Compiler.Tests.Bcl.System
result = value.ToString();
expectedResult = "2147483647";
//Assert.IsTrue((result == expectedResult), "Int32.ToString doesn't work");
Assert.IsTrue((result == expectedResult), "Int32.ToString doesn't work");
// Now let's try to concat to a String using '+' operator
result = "The Maximum value of an Int32 is " + value;
expectedResult = "The Maximum value of an Int32 is 2147483647";
//Assert.IsTrue((result == expectedResult), "String concat (Int32) doesn't work");
Assert.IsTrue((result == expectedResult), "String concat (Int32) doesn't work");
// Now let's try to use '$ instead of '+'
result = $"The Maximum value of an Int32 is {value}";
// Actually 'expectedResult' should be the same so...
//Assert.IsTrue((result == expectedResult), "String format (Int32) doesn't work");
Assert.IsTrue((result == expectedResult), "String format (Int32) doesn't work");
// Now let's Get the HashCode of a value
int resultAsInt = value.GetHashCode();
// actually the Hash Code of an Int32 is the same value
//Assert.IsTrue((resultAsInt == value), "Int32.GetHashCode() doesn't work");
Assert.IsTrue((resultAsInt == value), "Int32.GetHashCode() doesn't work");
#if false
// Now let's try ToString() again but printed in hex (this test fails for now!)

View file

@ -48,6 +48,24 @@ namespace Cosmos.Compiler.Tests.Bcl.System
val2 = long.Parse("42");
Assert.IsTrue(val2 == 42, "Parsing Int64 doesn't work.");
/* Let's test right shift */
value = 4631166901565532406;
val2 = value >> 20;
Assert.IsTrue(val2 == 4416624929013, "long right shift does not work");
val2 = value >> 52;
Assert.IsTrue(val2 == 1028, "long right shift (count >=32) does not work");
/* ... and now left shift */
value = 4631166901565532406;
val2 = value << 20;
Assert.IsTrue(val2 == 6640827866535690240, "long left shift does not work got " + val2);
val2 = value << 52;
Assert.IsTrue(val2 == -8115486528521633792, "long left shift (count >=32) does not work got " + val2);
#if false
// Now let's try ToString() again but printed in hex (this test fails for now!)

View file

@ -11,7 +11,7 @@ namespace Cosmos.Compiler.Tests.Bcl.System
private static bool SinglesAreEqual(Single left, Single right)
{
// Define the tolerance for variation in their values
Single difference = (Single)Math.Abs(left * .00001);
Single difference = (Single) Math.Abs(left * .00001);
if (Math.Abs(left - right) <= difference)
return true;
@ -19,38 +19,65 @@ namespace Cosmos.Compiler.Tests.Bcl.System
return false;
}
/* The double== equality operator is so imprecise to not be really ever useful we should be happy if the two values are "similar" */
private static bool DoublesAreEqual(double left, double right)
{
// Define the tolerance for variation in their values
double difference = Math.Abs(left * .00001);
if (Math.Abs(left - right) <= difference)
return true;
else
return false;
}
public static void negPositive()
{
// Let's try if it works in the other way too
//float value = 42.0f;
//float valueNegated = -value;
//Assert.IsTrue((SinglesAreEqual(valueNegated, -42.0f)), "(float) negation of positive float doesn't work got " + valueNegated);
}
public static void Execute()
{
Single value;
String result;
String expectedResult;
value = 42.42F; // It exists Single.MaxValue but it is a too big value an can be represented only on Scientific notation but then how to confront with a String?
/* First start with some weird value (not really numbers) that the IEEE standard has */
value = Single.PositiveInfinity;
result = value.ToString();
expectedResult = "∞";
Assert.IsTrue((result == expectedResult), "Single.ToString of INF doesn't work");
value = Single.NegativeInfinity;
result = value.ToString();
expectedResult = "-∞";
Assert.IsTrue((result == expectedResult), "Single.ToString of -INF doesn't work");
value = Single.NaN;
result = value.ToString();
expectedResult = "NaN";
Assert.IsTrue((result == expectedResult), "Single.ToString of -NaN doesn't work");
/* Another special value is '0' */
value = 0f;
result = value.ToString();
expectedResult = "0";
Assert.IsTrue((result == expectedResult), "Single.ToString of 0 doesn't work");
/* A negative value */
value = -42.42f;
result = value.ToString();
expectedResult = "-42.42";
Assert.IsTrue((result == expectedResult), "Single.ToString of negative number doesn't work");
/* A big value (to be correct toString should convert it in scientific notation) */
value = 9223372036854775808f;
result = value.ToString();
expectedResult = "9223372036854775808";
Assert.IsTrue((result == expectedResult), "Single.ToString of big number doesn't work");
/* OK now a normal value */
value = 42.42F; // It exists Single.MaxValue but it is a too big value an can be represented only on Scientific notation but then how to confront with a String?
result = value.ToString();
expectedResult = "42.42";
Assert.IsTrue((result == expectedResult), "Single.ToString doesn't work");
Assert.IsTrue((result == expectedResult), "Single.ToString of normal number doesn't work");
// Now let's try to concat to a String using '+' operator
result = "The value of the Single is " + value;
@ -101,42 +128,35 @@ namespace Cosmos.Compiler.Tests.Bcl.System
Single otherValue = 2.20f;
OperationResult = value + otherValue;
//expectedResult = "44.62";
Assert.IsTrue((SinglesAreEqual(OperationResult, 44.62f)), "float operator+ doesn't work");
//Assert.IsTrue((OperationResult.ToString() == expectedResult), "float operator+ doesn't work");
// Now test subtraction
OperationResult = value - otherValue;
//expectedResult = "40.22";
Assert.IsTrue((SinglesAreEqual(OperationResult, 40.22f)), "float operator- doesn't work");
//Assert.IsTrue((OperationResult.ToString() == expectedResult), "float operator- doesn't work");
// Now test multiplication
otherValue = 2.00f; // I'll change 'otherValue' to 2.00f because if not the result is too much wrong to make sense...
OperationResult = value * otherValue;
//expectedResult = "84.84";
Assert.IsTrue((SinglesAreEqual(OperationResult, 84.84f)), "float operator* doesn't work");
//Assert.IsTrue((OperationResult.ToString() == expectedResult), "float operator* doesn't work");
// Now test division
OperationResult = value / otherValue;
//expectedResult = "21.21";
Assert.IsTrue((SinglesAreEqual(OperationResult, 21.21f)), "float operator/ doesn't work");
//Assert.IsTrue((OperationResult.ToString() == expectedResult), "float operator/ doesn't work");
// Now test division again but with dividend 0 the expected result should be Double.PositiveInfinity
OperationResult = value / 0.00f;
Assert.IsTrue((OperationResult == Single.PositiveInfinity), "single operator/0 doesn't work");
Assert.IsTrue((OperationResult == Single.PositiveInfinity), "flot operator/0 doesn't work");
// Now test division again but with all values as 0 the expected result should be Double.NaN
OperationResult = 0.00f / 0.00f;
Assert.IsTrue((Single.IsNaN(OperationResult)), "single operator/(0/0) doesn't work");
Assert.IsTrue((Single.IsNaN(OperationResult)), "float operator/(0/0) doesn't work");
// Now test some castings operations
byte valueAsByte = (byte)value;
@ -178,31 +198,14 @@ namespace Cosmos.Compiler.Tests.Bcl.System
value = (float)anULong;
Assert.IsTrue((SinglesAreEqual(value, 9223372036854775849f)), "(float) from ulong operator doesn't work");
//value = -42.0f;
//float valueNegated = -value;
//Assert.IsTrue((SinglesAreEqual(valueNegated, 42.0f)), "(float) negation doesn't work");
value = -42.0f;
float valueNegated = -value;
Assert.IsTrue((SinglesAreEqual(valueNegated, 42.0f)), "(float) negation doesn't work");
//negPositive();
#if false
// Let's try if it works in the other way too
value = 42.0f;
valueNegated = -value;
Assert.IsTrue((SinglesAreEqual(valueNegated, -42.0f)), "(float) negation of positive float doesn't work");
#endif
#if false
//ulong anULong = 9223372036854775849;
ulong anULong = 9423372036854775870;
value = (float)anULong;
#if true
byte[] valueAsBytes = BitConverter.GetBytes(value);
Assert.IsTrue((SinglesAreEqual(value, 9223372036854775849f)), "(float) from ulong operator doesn't work returns " + value + " as bytes " + BitConverter.ToString(valueAsBytes));
#else
Assert.IsTrue((SinglesAreEqual(value, 9423372036854775870f)), "(float) from ulong operator doesn't work: ");
#endif
#endif
}
}
}

View file

@ -11,6 +11,11 @@ namespace Cosmos.Compiler.Tests.Bcl.System
Assert.IsTrue(("a" + "b") == "ab", "concatting 2 string using + doesn't work");
Assert.IsTrue(("a" + 'b') == "ab", "concatting 1 string and 1 character doesn't work");
string a = "a";
string b = "b";
string result = a + b;
Assert.IsTrue(result == "ab", "concatting 2 string (not optimizable) using + doesn't work"); // Fails
char x = 'a';
string y = "a";
Assert.IsTrue(x.ToString() == y, "String == operator ");

View file

@ -73,6 +73,22 @@ namespace Cosmos.Compiler.Tests.Bcl.System
Assert.IsTrue((value == 18446744073709551615), "Negative Double to UInt64 conversion doesn't work");
value = 4631166901565532406u;
val2 = value >> 20;
Assert.IsTrue(val2 == 4416624929013, "ulong right shift does not work");
val2 = value >> 52;
Assert.IsTrue(val2 == 1028, "ulong right shift (count >=32) does not work");
/* ... and now left shift */
value = 4631166901565532406;
val2 = value << 20;
Assert.IsTrue(val2 == 6640827866535690240, "ulong left shift does not work");
val2 = value << 52;
Assert.IsTrue(val2 == 10331257545187917824, "ulong left shift (count >=32) does not work");
#if false
// Now let's try ToString() again but printed in hex (this test fails for now!)

View file

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Cosmos.Compiler.Tests.Bcl.System
{
using Cosmos.TestRunner;
unsafe class UnsafeCodeTest
{
static long DoubleToInt64Bits(double value)
{
return *(long*)(&value);
}
static ulong Test(ref ulong a)
{
a = 12345678;
return a;
}
public static void Execute()
{
long val = Int64.MaxValue;
long* p = &val;
long newVal = *p;
Assert.IsTrue(val == newVal, $"Pointer deferencing failed expected {val} got {newVal}");
/* This the same thing BitConverter does to convert a Double to a Long it should fail in this case too */
double d = 1.0;
long asLong = *(long*)(&d);
byte[] hexDump;
hexDump = BitConverter.GetBytes(asLong);
Assert.IsTrue(asLong == 0x3FF0000000000000, "double asLong is wrong!");
ulong aLong = 0;
ulong retVal;
retVal = Test(ref aLong);
Assert.IsTrue(retVal == 12345678, "Ulong ref passing not works");
asLong = DoubleToInt64Bits(d);
hexDump = BitConverter.GetBytes(asLong);
Console.WriteLine("asLong is : " + BitConverter.ToString(hexDump, 0));
Assert.IsTrue(asLong == 0x3FF0000000000000, "DoubleToInt64Bits is wrong!");
}
}
}

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Cosmos.Common
{
@ -131,6 +127,254 @@ namespace Cosmos.Common
return xResult;
}
/*
* This implementation could only print values which integer part is < ULONG_MAX, the only solution would have been to use BigInteger but then
* I'd have an analogous problem: to plug BigInteger.ToString() and I don't know how many other things.
* We will retain this code for now it is OK for debug purposes and big value should be printed in scientific notation to be readable anyway...
*/
public static string GetNumberString(float aValue)
{
var singleBytes = BitConverter.GetBytes(aValue);
int hexVal = BitConverter.ToInt32(singleBytes, 0);
/* Let's extract the parts that compose our single: sign, exponent and mantissa */
bool isNeg = (hexVal >> 31) != 0;
int exp = ((hexVal >> 23) & 0xFF);
ulong mantissa = (ulong)(hexVal & 0x7FFFFF);
ulong intPart = 0, fracPart = 0;
/* First we handle the special cases INF, NaN, 0 and denormalized float */
switch (exp)
{
/*
* INF or NaN?
*/
case 0xFF:
if (mantissa == 0)
{
if (isNeg)
return "-∞";
else
return "∞";
}
else
/* It could exist -NaN but this is always printed as NaN */
return "NaN";
/* 0 or denormalized float? */
case 0x00:
if (mantissa == 0)
return "0";
/* Denormalized float have always exp -126 */
else
exp = -126;
break;
/* Normalized float the exponent is unbiased and the implicit leading one is placed in the mantissa */
default:
exp -= 127;
mantissa |= 0x800000;
break;
}
if (exp >= 23)
{
intPart = mantissa << (exp - 23);
}
else if (exp >= 0)
{
intPart = mantissa >> (23 - exp);
fracPart = (mantissa << (exp + 1)) & 0xFFFFFF;
}
else
{
fracPart = (mantissa & 0xFFFFFF) >> (-(exp + 1));
}
string result = "";
if (isNeg)
{
result += "-";
}
result += intPart.ToString();
int usedDigits = intPart.ToString().Length;
if (fracPart == 0)
{
return result;
}
result += ".";
if (usedDigits >= 7)
{
usedDigits = 6;
}
for (int m = usedDigits; m < 7; m++)
{
fracPart = (fracPart << 3) + (fracPart << 1);
char p = (char)((fracPart >> 24) + '0');
result += p;
fracPart &= 0xFFFFFF;
}
fracPart = (fracPart << 3) + (fracPart << 1);
char remain = (char)((fracPart >> 24) + '0');
if ((remain > '5') && (result[result.Length - 1] > '0'))
{
char[] answer = result.ToCharArray();
int digitPos = answer.Length - 1;
char digit = result[digitPos];
answer[digitPos] = (char)(digit + 1);
while (answer[digitPos] > '9')
{
answer[digitPos] = '0';
digitPos--;
digit = result[digitPos];
if (digit == '.')
{
digitPos--;
digit = result[digitPos];
}
answer[digitPos] = (char)(digit + 1);
}
result = new string(answer);
}
while (result[result.Length - 1] == '0')
{
result = result.Substring(0, result.Length - 1);
}
return result;
}
/*
* This implementation could only print values which integer part is < ULONG_MAX, the only solution would have been to use BigInteger but then
* I'd have an analogous problem: to plug BigInteger.ToString() and I don't know how many other things.
* We will retain this code for now it is OK for debug purposes and big value should be printed in scientific notation to be readable anyway...
*/
public static string GetNumberString(double aValue)
{
long hexVal = BitConverter.DoubleToInt64Bits(aValue);
/* Let's extract the parts that compose our double: sign, exponent and mantissa */
bool isNeg = (hexVal >> 63) != 0;
int exp = (int)((hexVal >> 52) & 0x07FF);
ulong mantissa = (ulong)(hexVal & 0x0FFFFFFFFFFFFF);
ulong intPart = 0, fracPart = 0;
/* First we handle the special cases INF, NaN, 0 and denormalized float */
switch (exp)
{
/*
* INF or NaN?
*/
case 0x07ff:
if (mantissa == 0)
{
if (isNeg)
return "-∞";
else
return "∞";
}
else
/* It could exist -NaN but this is always printed as NaN */
return "NaN";
/* 0 or denormalized double? */
case 0x0000:
if (mantissa == 0)
return "0";
/* Denormalized float have always exp -1022 */
else
exp = -1022;
break;
/* Normalized double the exponent is unbiased and the implicit leading one is placed in the mantissa */
default:
exp -= 1023;
mantissa |= 0x10000000000000;
break;
}
if (exp >= 52)
{
intPart = mantissa << (exp - 52);
}
else if (exp >= 0)
{
intPart = mantissa >> (52 - exp);
fracPart = (mantissa << (exp + 1)) & 0x1FFFFFFFFFFFFF;
}
else
{
fracPart = (mantissa & 0x1FFFFFFFFFFFFF) >> (-(exp + 1));
}
string result = "";
if (isNeg)
{
result += "-";
}
result += intPart.ToString();
int usedDigits = result.Length;
if (fracPart == 0)
{
return result;
}
result += ".";
if (usedDigits >= 15)
{
usedDigits = 14;
}
for (int m = usedDigits; m < 15; m++)
{
fracPart = (fracPart << 3) + (fracPart << 1);
char p = (char)(((fracPart >> 53) & 0xFF) + '0');
result += p;
fracPart &= 0x1FFFFFFFFFFFFF;
}
fracPart = (fracPart << 3) + (fracPart << 1);
char remain = (char)((fracPart >> 53) + '0');
if ((remain > '5') && (result[result.Length - 1] > '0'))
{
char[] answer = result.ToCharArray();
int digitPos = answer.Length - 1;
char digit = result[digitPos];
answer[digitPos] = (char)(digit + 1);
while (answer[digitPos] > '9')
{
answer[digitPos] = '0';
digitPos--;
digit = result[digitPos];
if (digit == '.')
{
digitPos--;
digit = result[digitPos];
}
answer[digitPos] = (char)(digit + 1);
}
result = new string(answer);
}
while (result[result.Length - 1] == '0')
{
result = result.Substring(0, result.Length - 1);
}
return result;
}
public static int GetStringToNumber(string aString)
{
bool xIsNegative = false;

View file

@ -242,7 +242,7 @@ namespace Cosmos.IL2CPU
DataMembers.Add(new DataMember(@"__uint2double_const", new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x41 }));
DataMembers.Add(new DataMember(@"__ulong2double_const", 0x5F800000));
DataMembers.Add(new DataMember(@"__doublesignbit", 0x8000000000000000));
//DataMembers.Add(new DataMember(@"__floatsignbit", 0x80000000));
DataMembers.Add(new DataMember(@"__floatsignbit", 0x80000000));
if (mComPort > 0)
{

View file

@ -44,13 +44,6 @@ namespace Cosmos.IL2CPU.X86.IL
XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
XS.SSE2.AddSD(XMM1, XMM0);
XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true);
#if false
XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
XS.Add(ESP, 8);
new CPUx86.x87.FloatAdd { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, Size = 64 };
XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Long64);
#endif
}
else // long
{

View file

@ -75,26 +75,6 @@ namespace Cosmos.IL2CPU.X86.IL {
// We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack!
XS.Add(ESP, 4);
XS.Set(ESP, EBX, destinationIsIndirect: true);
// This is the x87 version I left it here commented if in future will be needed...
#if false
XS.Set(XSRegisters.ESI, 1);
// esi = 1
XS.Xor(XSRegisters.EDI, XSRegisters.EDI);
// edi = 0
// value 1
new FloatLoad { DestinationReg = RegistersEnum.ESP, Size = 64, DestinationDisplacement = 8, DestinationIsIndirect = true };
// value 2
XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
XS.FPU.FloatCompareAndSet(ST1);
// if zero is set, ST(0) == ST(i)
new ConditionalMove { Condition = ConditionalTestEnum.Equal, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI };
// pops fpu stack
XS.FPU.FloatStoreAndPop(ST0);
XS.FPU.FloatStoreAndPop(ST0);
XS.Add(XSRegisters.ESP, 16);
XS.Push(XSRegisters.EDI);
#endif
}
else
{

View file

@ -56,20 +56,6 @@ namespace Cosmos.IL2CPU.X86.IL
// We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack!
XS.Add(ESP, 4);
XS.Set(ESP, EBX, destinationIsIndirect: true);
// This is the x87 version I left it here commented if in future will be needed...
#if false
// value 1
new FloatLoad { DestinationReg = RegistersEnum.ESP, Size = 64, DestinationDisplacement = 8, DestinationIsIndirect = true };
// value 2
XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
XS.FPU.FloatCompareAndSet(ST1);
// if carry is set, ST(0) < ST(i)
new ConditionalMove { Condition = ConditionalTestEnum.Below, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI };
// pops fpu stack
XS.FPU.FloatStoreAndPop(ST0);
XS.FPU.FloatStoreAndPop(ST0);
XS.Add(XSRegisters.ESP, 16);
#endif
}
else
{

View file

@ -54,20 +54,6 @@ namespace Cosmos.IL2CPU.X86.IL
// We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack!
XS.Add(ESP, 4);
XS.Set(ESP, EBX, destinationIsIndirect: true);
// This is the x87 version I left it here commented if in future will be needed...
#if false
// value 1
new FloatLoad { DestinationReg = RegistersEnum.ESP, Size = 64, DestinationDisplacement = 8, DestinationIsIndirect = true };
// value 2
XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
XS.FPU.FloatCompareAndSet(ST1);
// if carry is set, ST(0) < ST(i)
new ConditionalMove { Condition = ConditionalTestEnum.Below, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI };
// pops fpu stack
XS.FPU.FloatStoreAndPop(ST0);
XS.FPU.FloatStoreAndPop(ST0);
XS.Add(XSRegisters.ESP, 16);
#endif
}
else
{

View file

@ -60,20 +60,6 @@ namespace Cosmos.IL2CPU.X86.IL
// We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack!
XS.Add(ESP, 4);
XS.Set(ESP, EBX, destinationIsIndirect: true);
// This is the x87 version I left it here commented if in future will be needed...
#if false
// value 2
XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
// value 1
new FloatLoad { DestinationReg = RegistersEnum.ESP, Size = 64, DestinationDisplacement = 8, DestinationIsIndirect = true };
XS.FPU.FloatCompareAndSet(ST1);
// if carry is set, ST(0) < ST(i)
new ConditionalMove { Condition = ConditionalTestEnum.Below, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI };
// pops fpu stack
XS.FPU.FloatStoreAndPop(ST0);
XS.FPU.FloatStoreAndPop(ST0);
XS.Add(XSRegisters.ESP, 16);
#endif
}
else
{

View file

@ -53,20 +53,6 @@ namespace Cosmos.IL2CPU.X86.IL
// We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack!
XS.Add(ESP, 4);
XS.Set(ESP, EBX, destinationIsIndirect: true);
// This is the x87 version I left it here commented if in future will be needed...
#if false
// value 2
XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
// value 1
new FloatLoad { DestinationReg = RegistersEnum.ESP, Size = 64, DestinationDisplacement = 8, DestinationIsIndirect = true };
XS.FPU.FloatCompareAndSet(ST1);
// if carry is set, ST(0) < ST(i)
new ConditionalMove { Condition = ConditionalTestEnum.Below, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI };
// pops fpu stack
XS.FPU.FloatStoreAndPop(ST0);
XS.FPU.FloatStoreAndPop(ST0);
XS.Add(XSRegisters.ESP, 16);
#endif
}
else
{

View file

@ -35,18 +35,6 @@ namespace Cosmos.IL2CPU.X86.IL
XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
XS.SSE2.DivSD(XMM1, XMM0);
XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true);
// x87 version left here for future use
#if false
// TODO add 0/0 infinity/infinity X/infinity
// value 1
new CPUx86.x87.FloatLoad { DestinationReg = CPUx86.RegistersEnum.ESP, Size = 64, DestinationIsIndirect = true, DestinationDisplacement = 8 };
// value 2
new CPUx86.x87.FloatDivide { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, Size = 64 };
// override value 1
new CPUx86.x87.FloatStoreAndPop { DestinationReg = CPUx86.RegistersEnum.ESP, Size = 64, DestinationIsIndirect = true, DestinationDisplacement = 8 };
// pop value 2
XS.Add(XSRegisters.ESP, 8);
#endif
}
else
{

View file

@ -17,131 +17,49 @@ namespace Cosmos.IL2CPU.X86.IL
{
}
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode )
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
{
var xOpVar = (OpVar)aOpCode;
var xDisplacement = Ldarg.GetArgumentDisplacement(aMethod, xOpVar.Value);
/*
* The function GetArgumentDisplacement() does not give the correct displacement for the Ldarga opcode
* we need to "fix" it subtracting the argSize and 4
*/
Type xArgType;
if (aMethod.MethodBase.IsStatic)
{
xArgType = aMethod.MethodBase.GetParameters()[xOpVar.Value].ParameterType;
}
else
{
if (xOpVar.Value == 0u)
{
xArgType = aMethod.MethodBase.DeclaringType;
if (xArgType.IsValueType)
{
xArgType = xArgType.MakeByRefType();
}
}
else
{
xArgType = aMethod.MethodBase.GetParameters()[xOpVar.Value - 1].ParameterType;
}
}
uint xArgRealSize = SizeOfType(xArgType);
uint xArgSize = Align(xArgRealSize, 4);
XS.Comment("Arg type = " + xArgType.ToString());
XS.Comment("Arg real size = " + xArgRealSize + " aligned size = " + xArgSize);
xDisplacement -= (int)(xArgSize - 4);
XS.Comment("Real displacement " + xDisplacement);
XS.Set(XSRegisters.EBX, (uint)(xDisplacement));
XS.Set(XSRegisters.EAX, XSRegisters.EBP);
XS.Add(XSRegisters.EAX, XSRegisters.EBX);
XS.Push(XSRegisters.EAX);
// if (aMethod.MethodBase.DeclaringType.FullName == "Cosmos.Kernel.Plugs.Console"
// && aMethod.MethodBase.Name == "Write"
// && aMethod.MethodBase.GetParameters()[0].ParameterType == typeof(int))
// {
// Console.Write("");
// }
// Cosmos.IL2CPU.ILOpCodes.OpVar xOpVar = ( Cosmos.IL2CPU.ILOpCodes.OpVar )aOpCode;
// var xMethodInfo = aMethod.MethodBase as System.Reflection.MethodInfo;
// uint xReturnSize = 0;
// if( xMethodInfo != null )
// {
// xReturnSize = Align( SizeOfType( xMethodInfo.ReturnType ), 4 );
// }
// uint xOffset = 8;
// var xCorrectedOpValValue = xOpVar.Value;
// if( !aMethod.MethodBase.IsStatic && xOpVar.Value > 0 )
// {
// // if the method has a $this, the OpCode value includes the this at index 0, but GetParameters() doesnt include the this
// xCorrectedOpValValue -= 1;
// }
// var xParams = aMethod.MethodBase.GetParameters();
// for( int i = xParams.Length - 1; i > xCorrectedOpValValue; i-- )
// {
// var xSize = Align( SizeOfType( xParams[ i ].ParameterType ), 4 );
// xOffset += xSize;
// }
// var xCurArgSize = Align( SizeOfType( xParams[ xCorrectedOpValValue ].ParameterType ), 4 );
// uint xArgSize = 0;
// foreach( var xParam in xParams )
// {
// xArgSize += Align( SizeOfType( xParam.ParameterType ), 4 );
// }
// xReturnSize = 0;
// uint xExtraSize = 0;
// if( xReturnSize > xArgSize )
// {
// xExtraSize = xArgSize - xReturnSize;
// }
// xOffset += xExtraSize;
//#warning TODO: check this
// XS.Push(XSRegisters.EBP);
// for( int i = 0; i < ( xCurArgSize / 4 ); i++ )
// {
// XS.Push(( uint )( xCurArgSize - ( ( i + 1 ) * 4 ) ));
// }
// Assembler.Stack.Push( ( int )xCurArgSize, xParams[ xCorrectedOpValValue ].ParameterType );
// //for( int i = 0; i < ( mSize / 4 ); i++ )
// //{
// // mVirtualAddresses[ i ] = ( mOffset + ( ( i + 1 ) * 4 ) + 4 );
// //}
// //mAddress = aMethodInfo.Arguments[ aIndex ].VirtualAddresses.First();
// Assembler.Stack.Push( new StackContents.Item( 4, typeof( uint ) ) );
// //XS.Push(( uint )mAddress);
// //
// Assembler.Stack.Push( new StackContents.Item( 4, typeof( uint ) ) );
// new Add( Assembler ).Execute( aMethod, aOpCode );
}
// using System;
// using System.Linq;
//
//
// using CPU = Cosmos.Assembler.x86;
// using Cosmos.IL2CPU.X86;
//
// namespace Cosmos.IL2CPU.IL.X86 {
// [Cosmos.Assembler.OpCode(OpCodeEnum.Ldarga)]
// public class Ldarga: Op {
// private int mAddress;
// private string mNextLabel;
// private string mCurLabel;
// private uint mCurOffset;
// private MethodInformation mMethodInformation;
// protected void SetArgIndex(int aIndex, MethodInformation aMethodInfo) {
// mAddress = aMethodInfo.Arguments[aIndex].VirtualAddresses.First();
// }
// public Ldarga(MethodInformation aMethodInfo, int aIndex, string aCurrentLabel, uint aCurrentOffset, string aNextLabel)
// : base(null, aMethodInfo) {
// SetArgIndex(aIndex, aMethodInfo);
//
// mMethodInformation = aMethodInfo;
// mCurOffset = aCurrentOffset;
// mCurLabel = aCurrentLabel;
// mNextLabel = aNextLabel;
// }
//
// public Ldarga(ILReader aReader, MethodInformation aMethodInfo)
// : base(aReader, aMethodInfo) {
// if (aReader != null) {
// SetArgIndex(aReader.OperandValueInt32, aMethodInfo);
// //ParameterDefinition xParam = aReader.Operand as ParameterDefinition;
// //if (xParam != null) {
// // SetArgIndex(xParam.Sequence - 1, aMethodInfo);
// //}
// }
// mMethodInformation = aMethodInfo;
// mCurOffset = aReader.Position;
// mCurLabel = IL.Op.GetInstructionLabel(aReader);
// mNextLabel = IL.Op.GetInstructionLabel(aReader.NextPosition);
// }
// public override void DoAssemble() {
// XS.Push(XSRegisters.EBP);
// Assembler.Stack.Push(new StackContent(4, typeof(uint)));
// XS.Push((uint)mAddress);
// Assembler.Stack.Push(new StackContent(4, typeof(uint)));
// Add(Assembler, GetServiceProvider(), mCurLabel, mMethodInformation, mCurOffset, mNextLabel);
// }
// }
// }
}
}

View file

@ -35,18 +35,6 @@ namespace Cosmos.IL2CPU.X86.IL
XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
XS.SSE2.MulSD(XMM1, XMM0);
XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true);
// x87 code left for future use
#if false
XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
XS.Add(ESP, 8);
new CPUx86.x87.FloatMul
{
DestinationReg = CPUx86.RegistersEnum.ESP,
DestinationIsIndirect = true,
Size = 64
};
XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Long64);
#endif
}
else
{

View file

@ -9,8 +9,6 @@ namespace Cosmos.IL2CPU.X86.IL
[Cosmos.IL2CPU.OpCode( ILOpCode.Code.Neg )]
public class Neg : ILOp
{
static bool varDone = false;
public Neg( Cosmos.Assembler.Assembler aAsmblr )
: base( aAsmblr )
{
@ -29,12 +27,6 @@ namespace Cosmos.IL2CPU.X86.IL
XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true);
XS.SSE2.XorPD(XMM0, "__doublesignbit", sourceIsIndirect: true);
XS.SSE2.MoveSD(ESP, XMM0, destinationIsIndirect: true);
#if false
XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
XS.FPU.FloatNegate();
XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Long64);
#endif
}
else
{
@ -51,24 +43,11 @@ namespace Cosmos.IL2CPU.X86.IL
{
if (xStackContentIsFloat)
{
#if true
if (varDone == false)
{
XS.DataMember("__floatsignbit", 0x80000000);
varDone = true;
}
#endif
// There is no direct float negate instruction in SSE simply we do a XOR with 0x80000000 to flip the sign bit
XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
XS.SSE.MoveSS(XMM1, "__floatsignbit", sourceIsIndirect: true);
XS.SSE.XorPS(XMM0, XMM1);
XS.SSE.MoveSS(ESP, XMM0, destinationIsIndirect: true);
#if false
XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Int32);
XS.FPU.FloatNegate();
XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Int32);
#endif
}
else
{

View file

@ -48,17 +48,18 @@ namespace Cosmos.IL2CPU.X86.IL
XS.Jump(CPUx86.ConditionalTestEnum.AboveOrEqual, LowPartIsZero);
// shift higher part
XS.ShiftLeftDouble(ESP, EAX, CL, destinationDisplacement: 4);
// shift lower part
XS.ShiftLeft(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32);
// shift lower part
// To retain the sign bit we must use ShiftLeftArithmetic and not ShiftLeft!
XS.ShiftLeftArithmetic(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32);
XS.Jump(End_Shl);
XS.Label(LowPartIsZero);
// remove bits >= 32, so that CL max value could be only 31
XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8);
// shift low part in EAX and move it in high part
XS.ShiftLeft(EAX, CL);
// shift low part in EAX and move it in high part
// To retain the sign bit we must use ShiftLeftArithmetic and not ShiftLeft!
XS.ShiftLeftArithmetic(EAX, CL);
XS.Set(ESP, EAX, destinationDisplacement: 4);
// replace unknown low part with a zero, if <= 32
XS.Set(XSRegisters.ESP, 0, destinationIsIndirect: true);

View file

@ -60,16 +60,17 @@ namespace Cosmos.IL2CPU.X86.IL
XS.Jump(End_Shr);
XS.Label(HighPartIsZero);
// remove bits >= 32, so that CL max value could be only 31
XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8);
// shift high part and move it in low part
// To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight!
//XS.ShiftRight(XSRegisters.EAX, XSRegisters.CL);
XS.ShiftRightArithmetic(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32);
XS.ShiftRightArithmetic(XSRegisters.EAX, XSRegisters.CL);
XS.Set(ESP, EAX, destinationIsIndirect: true);
// replace unknown high part with a zero, if <= 32
new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0};
// replace unknown high part with a zero
XS.Set(ESP, 0, destinationIsIndirect: true, destinationDisplacement: 4);
//new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0};
XS.Label(End_Shr);
}
@ -94,6 +95,6 @@ namespace Cosmos.IL2CPU.X86.IL
// shift high part
XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32);
}*/
}
}
}
}

View file

@ -62,7 +62,7 @@ namespace Cosmos.IL2CPU.X86.IL
// shift high part and move it in low part
XS.ShiftRight(XSRegisters.EAX, XSRegisters.CL);
XS.Set(ESP, EAX, destinationIsIndirect: true);
// replace unknown high part with a zero, if <= 32
// replace unknown high part with a zero
new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0};
XS.Label(End_Shr);

View file

@ -58,23 +58,6 @@ namespace Cosmos.IL2CPU.X86.IL
XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
XS.SSE2.SubSD(XMM1, XMM0);
XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true);
#if false
new FloatLoad
{
DestinationReg = RegistersEnum.ESP,
Size = 64,
DestinationIsIndirect = true,
DestinationDisplacement = 8
};
new FloatSub
{
DestinationReg = RegistersEnum.ESP,
DestinationIsIndirect = true,
Size = 64
};
XS.Add(ESP, 8);
XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Long64);
#endif
}
else
{

View file

@ -1,5 +1,6 @@
using System;
using Cosmos.Common;
using Cosmos.IL2CPU.Plugs;
namespace Cosmos.System.Plugs.System
@ -9,97 +10,7 @@ namespace Cosmos.System.Plugs.System
{
public static string ToString(ref double aThis)
{
if (aThis == 0.0)
{
return "0";
}
double val = aThis;
long hexVal = BitConverter.DoubleToInt64Bits(val);
long mantissa = (hexVal & 0x1FFFFFFFFFFFFF) | 0x10000000000000;
int exp2 = (int) (((hexVal >> 52) & 0x07FF) - 1023);
long intPart = 0, fracPart = 0;
if (exp2 >= 63)
{
return "Double Overrange";
}
if (exp2 < -52)
{
return "Double Underrange";
}
if (exp2 >= 52)
{
intPart = mantissa << (exp2 - 52);
}
else if (exp2 >= 0)
{
intPart = mantissa >> (52 - exp2);
fracPart = (mantissa << (exp2 + 1)) & 0x1FFFFFFFFFFFFF;
}
else
{
fracPart = (mantissa & 0x1FFFFFFFFFFFFF) >> (-(exp2 + 1));
}
string result = "";
if (hexVal < 0)
{
result += "-";
}
result += intPart.ToString();
int usedDigits = result.Length;
if (fracPart == 0)
{
return result;
}
result += ".";
if (usedDigits >= 15)
{
usedDigits = 14;
}
for (int m = usedDigits; m < 15; m++)
{
fracPart = (fracPart << 3) + (fracPart << 1);
char p = (char) (((fracPart >> 53) & 0xFF) + '0');
result += p;
fracPart &= 0x1FFFFFFFFFFFFF;
}
fracPart = (fracPart << 3) + (fracPart << 1);
char remain = (char) ((fracPart >> 53) + '0');
if ((remain > '5') && (result[result.Length - 1] > '0'))
{
char[] answer = result.ToCharArray();
int digitPos = answer.Length - 1;
char digit = result[digitPos];
answer[digitPos] = (char) (digit + 1);
while (answer[digitPos] > '9')
{
answer[digitPos] = '0';
digitPos--;
digit = result[digitPos];
if (digit == '.')
{
digitPos--;
digit = result[digitPos];
}
answer[digitPos] = (char) (digit + 1);
}
result = new string(answer);
}
while (result[result.Length - 1] == '0')
{
result = result.Substring(0, result.Length - 1);
}
return result;
return StringHelper.GetNumberString(aThis);
}
}
}

View file

@ -1,108 +1,16 @@
using System;
using Cosmos.Common;
using Cosmos.IL2CPU.Plugs;
namespace Cosmos.System.Plugs.System
{
[Plug(Target = typeof(float))]
public static class SingleImpl
{
{
public static string ToString(ref float aThis)
{
if (aThis == 0.0f)
{
return "0";
}
float xValue = aThis;
var singleBytes = BitConverter.GetBytes(xValue);
int hexVal = BitConverter.ToInt32(singleBytes, 0);
int intPart = 0, fracPart = 0;
int exp2 = ((hexVal >> 23) & 0xFF) - 127;
int mantissa = (hexVal & 0xFFFFFF) | 0x800000;
if (exp2 >= 31)
{
return "Single Overrange";
}
if (exp2 < -23)
{
return "Single Underrange";
}
if (exp2 >= 23)
{
intPart = mantissa << (exp2 - 23);
}
else if (exp2 >= 0)
{
intPart = mantissa >> (23 - exp2);
fracPart = (mantissa << (exp2 + 1)) & 0xFFFFFF;
}
else
{
fracPart = (mantissa & 0xFFFFFF) >> (-(exp2 + 1));
}
string result = "";
if (hexVal < 0)
{
result += "-";
}
result += ((uint)intPart).ToString();
int usedDigits = ((uint)intPart).ToString().Length;
if (fracPart == 0)
{
return result;
}
result += ".";
if (usedDigits >= 7)
{
usedDigits = 6;
}
for (int m = usedDigits; m < 7; m++)
{
fracPart = (fracPart << 3) + (fracPart << 1);
char p = (char)((fracPart >> 24) + '0');
result += p;
fracPart &= 0xFFFFFF;
}
fracPart = (fracPart << 3) + (fracPart << 1);
char remain = (char)((fracPart >> 24) + '0');
if ((remain > '5') && (result[result.Length - 1] > '0'))
{
char[] answer = result.ToCharArray();
int digitPos = answer.Length - 1;
char digit = result[digitPos];
answer[digitPos] = (char)(digit + 1);
while (answer[digitPos] > '9')
{
answer[digitPos] = '0';
digitPos--;
digit = result[digitPos];
if (digit == '.')
{
digitPos--;
digit = result[digitPos];
}
answer[digitPos] = (char)(digit + 1);
}
result = new string(answer);
}
while (result[result.Length - 1] == '0')
{
result = result.Substring(0, result.Length - 1);
}
return result;
return StringHelper.GetNumberString(aThis);
}
}
}