Ejemplo n.º 1
0
        private void ParseDecimalNumber(ref TokenInfo info)
        {
            _builder.Clear();

            SkipDecimalDigits(_builder);
            if (_reader.IsNext('.'))
            {
                _builder.Append(_reader.Read() !.Value);
                SkipDecimalDigits(_builder);
            }

            if (CharUtils.AsciiLowerCase(_reader.Peek().GetValueOrDefault()) == 'e')
            {
                _builder.Append(_reader.Read() !.Value);
                if (_reader.IsNext('+') || _reader.IsNext('-'))
                {
                    _builder.Append(_reader.Read() !.Value);
                }
                SkipDecimalDigits(_builder);
            }

            info.Text = GetText(intern: true);
            if (!Options.SyntaxOptions.AcceptUnderscoreInNumberLiterals && info.Text.IndexOf('_') >= 0)
            {
                AddError(ErrorCode.ERR_UnderscoreInNumericLiteralNotSupportedInVersion);
            }
            if (!RealParser.TryParseDouble(Intern(_builder), out var result))
            {
                AddError(ErrorCode.ERR_DoubleOverflow);
            }
            info.DoubleValue = result;
        }
Ejemplo n.º 2
0
    public void TestRandomFloatStrings()
    {
        var start = DateTime.UtcNow;

        // compare our atof on random strings against C's strtof
        Parallel.For(
            0,
            150,
            part =>
        {
            Random r = new Random(start.GetHashCode() + part);
            var b    = new StringBuilder();
            for (int i = 0; i < 100000; i++)
            {
                b.Clear();
                int beforeCount = r.Next(3);
                int afterCount  = r.Next(1 + part % 50);
                int exp         = r.Next(-50, 40);
                if (beforeCount == 0)
                {
                    b.Append('0');
                }
                for (int j = 0; j < beforeCount; j++)
                {
                    b.Append((char)('0' + r.Next(10)));
                }
                b.Append('.');
                for (int j = 0; j < afterCount; j++)
                {
                    b.Append((char)('0' + r.Next(10)));
                }
                b.Append('e');
                if (exp >= 0 && r.Next(2) == 0)
                {
                    b.Append('+');
                }
                b.Append(exp);
                var s = b.ToString();
                float d1;
                d1 = CLibraryShim.RealConversions.atof(s);
                float d2;
                if (!RealParser.TryParseFloat(s, out d2))
                {
                    d2 = 1.0f / 0.0f;
                }
                Assert.AreEqual(
                    d1,
                    d2,
                    0.0,
                    $"{s} differ\n  RealParser=>{d2:G17}\n  atof=>{d1:G17}\n"
                    );
            }
        }
            );
    }
Ejemplo n.º 3
0
        private static void CheckOneFloat(string s, float expected)
        {
            float actual;

            if (!RealParser.TryParseFloat(s, out actual))
            {
                actual = 1.0f / 0.0f;
            }
            if (!actual.Equals(expected))
            {
                throw new Exception($@"Error for float input ""{s}""
   expected {InvariantToString(expected)}
   actual {InvariantToString(actual)}");
            }
        }
Ejemplo n.º 4
0
        private static void CheckOneDouble(string s, double expected)
        {
            double actual;

            if (!RealParser.TryParseDouble(s, out actual))
            {
                actual = 1.0 / 0.0;
            }
            if (!actual.Equals(expected))
            {
                throw new Exception($@"
Error for double input ""{s}""
   expected {InvariantToString(expected)}
   actual {InvariantToString(actual)}");
            }
        }
Ejemplo n.º 5
0
    private void Awake()
    {
        if (_rp != null && _rp != this)
        {
            Destroy(this.gameObject);
        }
        else
        {
            _rp = this;
        }

        //blank key to give access to any dialoge that has no key
        inv.Add(000, "");

        pickUp = GetComponent <AudioSource>();
    }
Ejemplo n.º 6
0
        static void CheckOneFloat(string s, float expected)
        {
            float actual;

            if (!RealParser.TryParseFloat(s, out actual))
            {
                actual = 1.0f / 0.0f;
            }
            if (!actual.Equals(expected))
            {
#if DEBUG
                throw new AssertFailureException($@"Error for float input ""{s}""
   expected {expected:G17}
   actual {actual:G17}");
#else
                throw new Exception($@"Error for float input ""{s}""
   expected {expected:G17}
   actual {actual:G17}");
#endif
            }
        }
Ejemplo n.º 7
0
        static void CheckOneDouble(string s, double expected)
        {
            double actual;

            if (!RealParser.TryParseDouble(s, out actual))
            {
                actual = 1.0 / 0.0;
            }
            if (!actual.Equals(expected))
            {
#if DEBUG
                throw new AssertFailureException($@"
Error for double input ""{s}""
   expected {expected:G17}
   actual {actual:G17}");
#else
                throw new Exception($@"
Error for double input ""{s}""
   expected {expected:G17}
   actual {actual:G17}");
#endif
            }
        }
Ejemplo n.º 8
0
        public static void TestSpecificDoubles()
        {
            CheckOneDouble("0.0", 0x0000000000000000ul);

            // Verify the smallest denormals:
            for (ulong i = 0x0000000000000001ul; i != 0x0000000000000100ul; ++i)
            {
                TestRoundTripDouble(i);
            }

            // Verify the largest denormals and the smallest normals:
            for (ulong i = 0x000fffffffffff00ul; i != 0x0010000000000100ul; ++i)
            {
                TestRoundTripDouble(i);
            }

            // Verify the largest normals:
            for (ulong i = 0x7fefffffffffff00ul; i != 0x7ff0000000000000ul; ++i)
            {
                TestRoundTripDouble(i);
            }

            // Verify all representable powers of two and nearby values:
            for (int pow = -1022; pow <= 1023; pow++)
            {
                ulong twoToThePow = ((ulong)(pow + 1023)) << 52;
                TestRoundTripDouble(twoToThePow);
                TestRoundTripDouble(twoToThePow + 1);
                TestRoundTripDouble(twoToThePow - 1);
            }

            // Verify all representable powers of ten and nearby values:
            for (int pow = -323; pow <= 308; pow++)
            {
                var    s = $"1.0e{pow}";
                double value;
                RealParser.TryParseDouble(s, out value);
                var tenToThePow = (ulong)BitConverter.DoubleToInt64Bits(value);
                CheckOneDouble(s, value);
                TestRoundTripDouble(tenToThePow + 1);
                TestRoundTripDouble(tenToThePow - 1);
            }

            // Verify a few large integer values:
            TestRoundTripDouble((double)long.MaxValue);
            TestRoundTripDouble((double)ulong.MaxValue);

            // Verify small and large exactly representable integers:
            CheckOneDouble("1", 0x3ff0000000000000);
            CheckOneDouble("2", 0x4000000000000000);
            CheckOneDouble("3", 0x4008000000000000);
            CheckOneDouble("4", 0x4010000000000000);
            CheckOneDouble("5", 0x4014000000000000);
            CheckOneDouble("6", 0x4018000000000000);
            CheckOneDouble("7", 0x401C000000000000);
            CheckOneDouble("8", 0x4020000000000000);

            CheckOneDouble("9007199254740984", 0x433ffffffffffff8);
            CheckOneDouble("9007199254740985", 0x433ffffffffffff9);
            CheckOneDouble("9007199254740986", 0x433ffffffffffffa);
            CheckOneDouble("9007199254740987", 0x433ffffffffffffb);
            CheckOneDouble("9007199254740988", 0x433ffffffffffffc);
            CheckOneDouble("9007199254740989", 0x433ffffffffffffd);
            CheckOneDouble("9007199254740990", 0x433ffffffffffffe);
            CheckOneDouble("9007199254740991", 0x433fffffffffffff); // 2^53 - 1

            // Verify the smallest and largest denormal values:
            CheckOneDouble("5.0e-324", 0x0000000000000001);
            CheckOneDouble("1.0e-323", 0x0000000000000002);
            CheckOneDouble("1.5e-323", 0x0000000000000003);
            CheckOneDouble("2.0e-323", 0x0000000000000004);
            CheckOneDouble("2.5e-323", 0x0000000000000005);
            CheckOneDouble("3.0e-323", 0x0000000000000006);
            CheckOneDouble("3.5e-323", 0x0000000000000007);
            CheckOneDouble("4.0e-323", 0x0000000000000008);
            CheckOneDouble("4.5e-323", 0x0000000000000009);
            CheckOneDouble("5.0e-323", 0x000000000000000a);
            CheckOneDouble("5.5e-323", 0x000000000000000b);
            CheckOneDouble("6.0e-323", 0x000000000000000c);
            CheckOneDouble("6.5e-323", 0x000000000000000d);
            CheckOneDouble("7.0e-323", 0x000000000000000e);
            CheckOneDouble("7.5e-323", 0x000000000000000f);

            CheckOneDouble("2.2250738585071935e-308", 0x000ffffffffffff0);
            CheckOneDouble("2.2250738585071940e-308", 0x000ffffffffffff1);
            CheckOneDouble("2.2250738585071945e-308", 0x000ffffffffffff2);
            CheckOneDouble("2.2250738585071950e-308", 0x000ffffffffffff3);
            CheckOneDouble("2.2250738585071955e-308", 0x000ffffffffffff4);
            CheckOneDouble("2.2250738585071960e-308", 0x000ffffffffffff5);
            CheckOneDouble("2.2250738585071964e-308", 0x000ffffffffffff6);
            CheckOneDouble("2.2250738585071970e-308", 0x000ffffffffffff7);
            CheckOneDouble("2.2250738585071974e-308", 0x000ffffffffffff8);
            CheckOneDouble("2.2250738585071980e-308", 0x000ffffffffffff9);
            CheckOneDouble("2.2250738585071984e-308", 0x000ffffffffffffa);
            CheckOneDouble("2.2250738585071990e-308", 0x000ffffffffffffb);
            CheckOneDouble("2.2250738585071994e-308", 0x000ffffffffffffc);
            CheckOneDouble("2.2250738585072000e-308", 0x000ffffffffffffd);
            CheckOneDouble("2.2250738585072004e-308", 0x000ffffffffffffe);
            CheckOneDouble("2.2250738585072010e-308", 0x000fffffffffffff);

            // Test cases from Rick Regan's article, "Incorrectly Rounded Conversions in Visual C++":
            //
            //     http://www.exploringbinary.com/incorrectly-rounded-conversions-in-visual-c-plus-plus/
            //
            // Example 1:
            CheckOneDouble(
                "9214843084008499",
                0x43405e6cec57761a);

            // Example 2:
            CheckOneDouble(
                "0.500000000000000166533453693773481063544750213623046875",
                0x3fe0000000000002);

            // Example 3 (2^-1 + 2^-53 + 2^-54):
            CheckOneDouble(
                "30078505129381147446200",
                0x44997a3c7271b021);

            // Example 4:
            CheckOneDouble(
                "1777820000000000000001",
                0x4458180d5bad2e3e);

            // Example 5 (2^-1 + 2^-53 + 2^-54 + 2^-66):
            CheckOneDouble(
                "0.500000000000000166547006220929549868969843373633921146392822265625",
                0x3fe0000000000002);

            // Example 6 (2^-1 + 2^-53 + 2^-54 + 2^-65):
            CheckOneDouble(
                "0.50000000000000016656055874808561867439493653364479541778564453125",
                0x3fe0000000000002);

            // Example 7:
            CheckOneDouble(
                "0.3932922657273",
                0x3fd92bb352c4623a
                );

            // The following test cases are taken from other articles on Rick Regan's
            // Exploring Binary blog.  These are conversions that other implementations
            // were found to perform incorrectly.

            // http://www.exploringbinary.com/nondeterministic-floating-point-conversions-in-java/
            // http://www.exploringbinary.com/incorrectly-rounded-subnormal-conversions-in-java/
            // Example 1 (2^-1047 + 2^-1075, half-ulp above a power of two):
            CheckOneDouble(
                "6.6312368714697582767853966302759672433990999473553031442499717587" +
                "362866301392654396180682007880487441059604205526018528897150063763" +
                "256665955396033303618005191075917832333584923372080578494993608994" +
                "251286407188566165030934449228547591599881603044399098682919739314" +
                "266256986631577498362522745234853124423586512070512924530832781161" +
                "439325697279187097860044978723221938561502254152119972830784963194" +
                "121246401117772161481107528151017752957198119743384519360959074196" +
                "224175384736794951486324803914359317679811223967034438033355297560" +
                "033532098300718322306892013830155987921841729099279241763393155074" +
                "022348361207309147831684007154624400538175927027662135590421159867" +
                "638194826541287705957668068727833491469671712939495988506756821156" +
                "96218943412532098591327667236328125E-316",
                0x0000000008000000);

            // Example 2 (2^-1058 - 2^-1075, half-ulp below a power of two):
            CheckOneDouble(
                "3.2378839133029012895883524125015321748630376694231080599012970495" +
                "523019706706765657868357425877995578606157765598382834355143910841" +
                "531692526891905643964595773946180389283653051434639551003566966656" +
                "292020173313440317300443693602052583458034314716600326995807313009" +
                "548483639755486900107515300188817581841745696521731104736960227499" +
                "346384253806233697747365600089974040609674980283891918789639685754" +
                "392222064169814626901133425240027243859416510512935526014211553334" +
                "302252372915238433223313261384314778235911424088000307751706259156" +
                "707286570031519536642607698224949379518458015308952384398197084033" +
                "899378732414634842056080000272705311068273879077914449185347715987" +
                "501628125488627684932015189916680282517302999531439241685457086639" +
                "13273994694463908672332763671875E-319",
                0x0000000000010000);

            // Example 3 (2^-1027 + 2^-1066 + 2^-1075, half-ulp above a non-power of two):
            CheckOneDouble(
                "6.9533558078476771059728052155218916902221198171459507544162056079" +
                "800301315496366888061157263994418800653863998640286912755395394146" +
                "528315847956685600829998895513577849614468960421131982842131079351" +
                "102171626549398024160346762138294097205837595404767869364138165416" +
                "212878432484332023692099166122496760055730227032447997146221165421" +
                "888377703760223711720795591258533828013962195524188394697705149041" +
                "926576270603193728475623010741404426602378441141744972109554498963" +
                "891803958271916028866544881824524095839813894427833770015054620157" +
                "450178487545746683421617594966617660200287528887833870748507731929" +
                "971029979366198762266880963149896457660004790090837317365857503352" +
                "620998601508967187744019647968271662832256419920407478943826987518" +
                "09812609536720628966577351093292236328125E-310",
                0x0000800000000100
                );

            // Example 4 (2^-1058 + 2^-1063 + 2^-1075, half-ulp below a non-power of two):
            CheckOneDouble(
                "3.3390685575711885818357137012809439119234019169985217716556569973" +
                "284403145596153181688491490746626090999981130094655664268081703784" +
                "340657229916596426194677060348844249897410807907667784563321682004" +
                "646515939958173717821250106683466529959122339932545844611258684816" +
                "333436749050742710644097630907080178565840197768788124253120088123" +
                "262603630354748115322368533599053346255754042160606228586332807443" +
                "018924703005556787346899784768703698535494132771566221702458461669" +
                "916553215355296238706468887866375289955928004361779017462862722733" +
                "744717014529914330472578638646014242520247915673681950560773208853" +
                "293843223323915646452641434007986196650406080775491621739636492640" +
                "497383622906068758834568265867109610417379088720358034812416003767" +
                "05491726170293986797332763671875E-319",
                0x0000000000010800
                );

            // http://www.exploringbinary.com/gays-strtod-returns-zero-for-inputs-just-above-2-1075/
            // A number between 2^-2074 and 2^-1075, just slightly larger than 2^-1075.
            // It has bit 1075 set (the denormal rounding bit), followed by 2506 zeroes,
            // followed by one bits.  It should round up to 2^-1074.
            CheckOneDouble(
                "2.470328229206232720882843964341106861825299013071623822127928412503" +
                "37753635104375932649918180817996189898282347722858865463328355177969" +
                "89819938739800539093906315035659515570226392290858392449105184435931" +
                "80284993653615250031937045767824921936562366986365848075700158576926" +
                "99037063119282795585513329278343384093519780155312465972635795746227" +
                "66465272827220056374006485499977096599470454020828166226237857393450" +
                "73633900796776193057750674017632467360096895134053553745851666113422" +
                "37666786041621596804619144672918403005300575308490487653917113865916" +
                "46239524912623653881879636239373280423891018672348497668235089863388" +
                "58792562830275599565752445550725518931369083625477918694866799496832" +
                "40497058210285131854513962138377228261454376934125320985913276672363" +
                "28125001e-324",
                0x0000000000000001);
        }
Ejemplo n.º 9
0
#pragma warning restore IDE0079 // Remove unnecessary suppression
        private void ParseDecimalNumber(ref TokenInfo info)
        {
            _builder.Clear();

            var isFloat = false;

            ConsumeDecimalDigits(_builder);
            if (TextWindow.PeekChar() == '.')
            {
                TextWindow.AdvanceChar();
                isFloat = true;
                _builder.Append('.');
                ConsumeDecimalDigits(_builder);
            }

            if (CharUtils.AsciiLowerCase(TextWindow.PeekChar()) == 'e')
            {
                TextWindow.AdvanceChar();
                isFloat = true;
                _builder.Append('e');
                if (TextWindow.PeekChar() is '+' or '-')
                {
                    _builder.Append(TextWindow.NextChar());
                }
                ConsumeDecimalDigits(_builder);
            }

            var(isUnsignedLong, isSignedLong, isComplex) = (false, false, false);

            if (TextWindow.AdvanceIfMatches("ull", true))
            {
                if (isFloat)
                {
                    AddError(ErrorCode.ERR_LuajitSuffixInFloat);
                }
                else
                {
                    isUnsignedLong = true;
                }
            }
            else if (TextWindow.AdvanceIfMatches("ll", true))
            {
                if (isFloat)
                {
                    AddError(ErrorCode.ERR_LuajitSuffixInFloat);
                }
                else
                {
                    isSignedLong = true;
                }
            }
            else if (TextWindow.AdvanceIfMatches("i", true))
            {
                isComplex = true;
            }

            info.Text = TextWindow.GetText(intern: true);
            if (!_options.SyntaxOptions.AcceptUnderscoreInNumberLiterals && info.Text.IndexOf('_') >= 0)
            {
                AddError(ErrorCode.ERR_UnderscoreInNumericLiteralNotSupportedInVersion);
            }
            if (!Options.SyntaxOptions.AcceptLuaJITNumberSuffixes && (isUnsignedLong || isSignedLong || isComplex))
            {
                AddError(ErrorCode.ERR_NumberSuffixNotSupportedInVersion);
            }

            if (isUnsignedLong)
            {
                if (!ulong.TryParse(TextWindow.Intern(_builder), NumberStyles.None, CultureInfo.InvariantCulture, out var result))
                {
                    AddError(ErrorCode.ERR_NumericLiteralTooLarge);
                }

                info.ValueKind  = ValueKind.ULong;
                info.ULongValue = result;
            }
            else if (isSignedLong)
            {
                if (!long.TryParse(TextWindow.Intern(_builder), NumberStyles.None, CultureInfo.InvariantCulture, out var result))
                {
                    AddError(ErrorCode.ERR_NumericLiteralTooLarge);
                }

                info.ValueKind = ValueKind.Long;
                info.LongValue = result;
            }
            else if (isComplex)
            {
                if (!RealParser.TryParseDouble(TextWindow.Intern(_builder), out var result))
                {
                    AddError(ErrorCode.ERR_DoubleOverflow);
                }

                info.ValueKind    = ValueKind.Complex;
                info.ComplexValue = new Complex(0, result);
            }
            else if (isFloat || _options.SyntaxOptions.DecimalIntegerFormat == IntegerFormats.NotSupported)
            {
                if (!RealParser.TryParseDouble(TextWindow.Intern(_builder), out var result))
                {
                    AddError(ErrorCode.ERR_DoubleOverflow);
                }

                info.ValueKind   = ValueKind.Double;
                info.DoubleValue = result;
            }
            else
            {
                if (!long.TryParse(TextWindow.Intern(_builder), NumberStyles.None, CultureInfo.InvariantCulture, out var result))
                {
                    AddError(ErrorCode.ERR_NumericLiteralTooLarge);
                }

                switch (_options.SyntaxOptions.DecimalIntegerFormat)
                {
                case IntegerFormats.Double:
                    info.ValueKind   = ValueKind.Double;
                    info.DoubleValue = result;
                    break;

                case IntegerFormats.Int64:
                    info.ValueKind = ValueKind.Long;
                    info.LongValue = result;
                    break;

                default:
                    throw ExceptionUtilities.UnexpectedValue(_options.SyntaxOptions.DecimalIntegerFormat);
                }
            }
        }