Skip to content

Commit 706c912

Browse files
committed
Optimized FastParse and ReadOnlySpanSplitter
1 parent 4ea5121 commit 706c912

File tree

5 files changed

+87
-133
lines changed

5 files changed

+87
-133
lines changed

.editorconfig

+2-1
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,10 @@ csharp_style_expression_bodied_indexers = true:silent
5353
csharp_style_expression_bodied_accessors = true:silent
5454
csharp_style_expression_bodied_lambdas = true:silent
5555
csharp_style_expression_bodied_local_functions = false:silent
56-
csharp_indent_labels = one_less_than_current
56+
csharp_indent_labels = no_change
5757
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
5858
csharp_space_after_cast = false
59+
csharp_indent_switch_labels = true
5960

6061
[*.{cs,vb}]
6162
#### Naming styles ####

modules/veldrid-spirv

src/Veldrid.Utilities/FastParse.cs

+45-70
Original file line numberDiff line numberDiff line change
@@ -5,105 +5,76 @@ namespace Veldrid.Utilities
55
{
66
internal static class FastParse
77
{
8-
private static readonly long[] _powLookup = new[]
9-
{
10-
1, // 10^0
11-
10, // 10^1
12-
100, // 10^2
13-
1000, // 10^3
14-
10000, // 10^4
15-
100000, // 10^5
16-
1000000, // 10^6
17-
10000000, // 10^7
18-
100000000, // 10^8
19-
1000000000, // 10^9,
20-
10000000000, // 10^10,
21-
100000000000, // 10^11,
22-
1000000000000, // 10^12,
23-
10000000000000, // 10^13,
24-
100000000000000, // 10^14,
25-
1000000000000000, // 10^15,
26-
10000000000000000, // 10^16,
27-
100000000000000000, // 10^17,
28-
};
29-
308
private static readonly double[] _doubleExpLookup = GetDoubleExponents();
319

32-
public static bool TryParseDouble(ReadOnlySpan<char> s, out double result, char decimalSeparator = '.')
33-
{
34-
return TryParseDouble(s, out result, out _, decimalSeparator);
35-
}
36-
3710
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
3811
public static bool TryParseInt(ReadOnlySpan<char> s, out int result)
3912
{
4013
int r = 0;
4114
int sign;
42-
int start;
15+
int i = 0;
4316

44-
char c = s[0];
17+
char c = s[i];
4518
if (c == '-')
4619
{
4720
sign = -1;
48-
start = 1;
21+
i = 1;
4922
}
5023
else if (c > '9' || c < '0')
5124
{
52-
result = 0;
53-
return false;
25+
goto Fail;
5426
}
5527
else
5628
{
57-
start = 1;
29+
i = 1;
5830
r = 10 * r + (c - '0');
5931
sign = 1;
6032
}
6133

62-
int i = start;
6334
for (; i < s.Length; i++)
6435
{
6536
c = s[i];
6637
if (c > '9' || c < '0')
6738
{
68-
result = 0;
69-
return false;
39+
goto Fail;
7040
}
7141

7242
r = 10 * r + (c - '0');
7343
}
7444

7545
result = r * sign;
7646
return true;
47+
48+
Fail:
49+
result = i;
50+
return false;
7751
}
7852

79-
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
8053
public static bool TryParseDouble(ReadOnlySpan<char> s, out double result, out bool hasFraction, char decimalSeparator = '.')
8154
{
8255
hasFraction = false;
8356

8457
double r = 0;
8558
int sign;
86-
int start;
59+
int i = 0;
8760

88-
char c = s[0];
61+
char c = s[i];
8962
if (c == '-')
9063
{
9164
sign = -1;
92-
start = 1;
65+
i = 1;
9366
}
9467
else if (c > '9' || c < '0')
9568
{
96-
result = 0;
97-
return false;
69+
goto Fail;
9870
}
9971
else
10072
{
101-
start = 1;
73+
i = 1;
10274
r = 10 * r + (c - '0');
10375
sign = 1;
10476
}
10577

106-
int i = start;
10778
for (; i < s.Length; i++)
10879
{
10980
c = s[i];
@@ -120,8 +91,7 @@ public static bool TryParseDouble(ReadOnlySpan<char> s, out double result, out b
12091
}
12192
else
12293
{
123-
result = 0;
124-
return false;
94+
goto Fail;
12595
}
12696
}
12797

@@ -132,7 +102,7 @@ public static bool TryParseDouble(ReadOnlySpan<char> s, out double result, out b
132102
goto Finish;
133103

134104
DecimalPoint:
135-
long tmp = 0;
105+
double tmp = 0;
136106
int length = i;
137107
double exponent = 0;
138108
hasFraction = true;
@@ -144,42 +114,42 @@ public static bool TryParseDouble(ReadOnlySpan<char> s, out double result, out b
144114
{
145115
if (c == 'e' || c == 'E')
146116
{
147-
length = i - length;
148-
goto ProcessExponent;
117+
exponent = ProcessExponent(s, i);
118+
break;
149119
}
150120

151-
result = 0;
152-
return false;
121+
goto Fail;
153122
}
154123
tmp = 10 * tmp + (c - '0');
155124
}
156125
length = i - length;
157126

158-
ProcessFraction:
159-
double fraction = tmp;
160-
161-
if (length < _powLookup.Length)
162-
fraction /= _powLookup[length];
163-
else
164-
fraction /= _powLookup[^1];
165-
127+
double fraction = tmp * GetInversedBaseTen(length);
166128
r += fraction;
167129
r *= sign;
168130

169131
if (exponent > 0)
170-
r *= exponent;
132+
r /= exponent;
171133
else if (exponent < 0)
172-
r /= -exponent;
134+
r *= -exponent;
173135

174-
goto Finish;
136+
Finish:
137+
result = r;
138+
return true;
139+
140+
Fail:
141+
result = i;
142+
return false;
143+
}
175144

176-
ProcessExponent:
145+
private static double ProcessExponent(ReadOnlySpan<char> s, int i)
146+
{
177147
int expSign = 1;
178148
int exp = 0;
179149

180150
for (i++; i < s.Length; i++)
181151
{
182-
c = s[i];
152+
char c = s[i];
183153
if (c > '9' || c < '0')
184154
{
185155
if (c == '-')
@@ -192,12 +162,17 @@ public static bool TryParseDouble(ReadOnlySpan<char> s, out double result, out b
192162
exp = 10 * exp + (c - '0');
193163
}
194164

195-
exponent = _doubleExpLookup[exp] * expSign;
196-
goto ProcessFraction;
165+
double exponent = GetInversedBaseTen(exp) * expSign;
166+
return exponent;
167+
}
197168

198-
Finish:
199-
result = r;
200-
return true;
169+
private static double GetInversedBaseTen(int index)
170+
{
171+
double[] array = _doubleExpLookup;
172+
if ((uint)index < (uint)array.Length)
173+
return array[index];
174+
else
175+
return Math.Pow(10, -index);
201176
}
202177

203178
private static double[] GetDoubleExponents()
@@ -206,7 +181,7 @@ private static double[] GetDoubleExponents()
206181

207182
for (int i = 0; i < exps.Length; i++)
208183
{
209-
exps[i] = Math.Pow(10, i);
184+
exps[i] = Math.Pow(10, -i);
210185
}
211186

212187
return exps;

src/Veldrid.Utilities/ObjParser.cs

+12-8
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,16 @@ public void Process(ReadOnlySpan<char> line)
152152

153153
if (piece0.SequenceEqual("v"))
154154
{
155-
ExpectPieces(ref splitter, "v", true, out ReadOnlySpan<char> piece1, out ReadOnlySpan<char> piece2, out ReadOnlySpan<char> piece3);
155+
ExpectPieces(
156+
ref splitter, "v", true,
157+
out ReadOnlySpan<char> piece1, out ReadOnlySpan<char> piece2, out ReadOnlySpan<char> piece3);
156158
DiscoverPosition(ParseVector3(piece1, piece2, piece3, "position data"));
157159
}
158160
else if (piece0.SequenceEqual("vn"))
159161
{
160-
ExpectPieces(ref splitter, "vn", true, out ReadOnlySpan<char> piece1, out ReadOnlySpan<char> piece2, out ReadOnlySpan<char> piece3);
162+
ExpectPieces(
163+
ref splitter, "vn", true,
164+
out ReadOnlySpan<char> piece1, out ReadOnlySpan<char> piece2, out ReadOnlySpan<char> piece3);
161165
DiscoverNormal(ParseVector3(piece1, piece2, piece3, "normal data"));
162166
}
163167
else if (piece0.SequenceEqual("vt"))
@@ -255,7 +259,7 @@ private ObjFile.FaceVertex ParseFaceVertex(ReadOnlySpan<char> faceComponents)
255259
{
256260
if (faceComponents.IsEmpty)
257261
ThrowExceptionForWrongFaceCount("There must be at least one face component");
258-
262+
259263
int firstSlash = faceComponents.IndexOf(_slashChar);
260264
ReadOnlySpan<char> firstSlice = firstSlash == -1
261265
? faceComponents
@@ -360,9 +364,9 @@ public ObjFile FinalizeFile()
360364

361365
private Vector3 ParseVector3(ReadOnlySpan<char> xStr, ReadOnlySpan<char> yStr, ReadOnlySpan<char> zStr, string location)
362366
{
363-
if (FastParse.TryParseDouble(xStr, out double x) &&
364-
FastParse.TryParseDouble(yStr, out double y) &&
365-
FastParse.TryParseDouble(zStr, out double z))
367+
if (FastParse.TryParseDouble(xStr, out double x, out _) &&
368+
FastParse.TryParseDouble(yStr, out double y, out _) &&
369+
FastParse.TryParseDouble(zStr, out double z, out _))
366370
{
367371
return new Vector3((float)x, (float)y, (float)z);
368372
}
@@ -372,8 +376,8 @@ private Vector3 ParseVector3(ReadOnlySpan<char> xStr, ReadOnlySpan<char> yStr, R
372376

373377
private Vector2 ParseVector2(ReadOnlySpan<char> xStr, ReadOnlySpan<char> yStr, string location)
374378
{
375-
if (FastParse.TryParseDouble(xStr, out double x) &&
376-
FastParse.TryParseDouble(yStr, out double y))
379+
if (FastParse.TryParseDouble(xStr, out double x, out _) &&
380+
FastParse.TryParseDouble(yStr, out double y, out _))
377381
{
378382
return new Vector2((float)x, (float)y);
379383
}

0 commit comments

Comments
 (0)