summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaymaekers Luca <luca@spacehb.net>2025-11-14 15:17:18 +0100
committerRaymaekers Luca <luca@spacehb.net>2025-11-14 15:17:18 +0100
commitd8beb0293bde2b758897df2f70118115d6620539 (patch)
treee7cea252e63bce2ffc0e456909ec2692d7a0d094
parentf0208e736ee473e80c8bc0d282ff9d9947374f15 (diff)
checkpointmain
-rw-r--r--computerenhance.md35
-rwxr-xr-xmisc/tmux.sh5
-rw-r--r--src/haversine_generator/haversine_generator.cpp243
-rw-r--r--src/haversine_generator/haversine_random.h43
-rwxr-xr-xsrc/haversine_processor/build.sh2
-rw-r--r--src/haversine_processor/haversine_processor.cpp212
6 files changed, 300 insertions, 240 deletions
diff --git a/computerenhance.md b/computerenhance.md
index bb83851..153c511 100644
--- a/computerenhance.md
+++ b/computerenhance.md
@@ -777,8 +777,43 @@ f16 are used to save bandwidth everywhere but also because of a lot of other thi
No libraries json processor.
# 50. [Monday Q&A #14 (2023-06-05)](https://www.computerenhance.com/p/monday-q-and-a-14-2023-06-05)
+Reading a file completely into memory is not the most efficient.
+You don't need to be completely bit-accurate for the exercise.
+To use a text format for floating point you need very precise serialize-deserialize code (e.g., serialize-deserialize pairs).
+For precision you should not need precision.
+You can serialize into hex digits to have precise binary numbers.
+
# 51. [Initial Haversine Processor Code Review](https://www.computerenhance.com/p/initial-haversine-processor-code)
+Generator
+- JSF RNG
+x You know pair count beforehand so you can use a coefficient
+x Set uniform as default method
+x MaxPairCount to avoid generating infinite pairs
+x MaxAllowed(X/Y) values (random degree function)
+x Collapsed both uniform and cluster codepaths by creating one cluster when uniform is selected
+x No clusters array, just regenerate the 4 values for each cluster
+
+Processor
+- simple loop that mimics generator and returns the sum
+- haversine_pair type
+- minimum amount of json per pair -> you can get the max number of pairs from json file size
+
+Cleanup times can be adressed.
+Clearing data that holds pointers can catch use-after-free.
+
# 52. [Monday Q&A #15 (2023-06-12)](https://www.computerenhance.com/p/monday-q-and-a-15-2023-06-12)
+Missing fields becoming 0s.
+
+Aligment
+- Old processor would require memory alignment for some instructions
+- Nowadays unaligned loads have mostly no penalties
+- The unit of operation for CPUs is a cache line i.e., 64 aligned bytes.
+ - This means if your data is unaligned you might end up using more cache lines than needed
+ - In a multicore setup threads will communicate via cache lines and their might be contension and threads
+ might be writing to the same cache lines.
+
+cpuid will put information into registers so you can query the capabilities
+
# 53. [Introduction to RDTSC](https://www.computerenhance.com/p/introduction-to-rdtsc)
# 54. [Monday Q&A #16 (2023-06-19)](https://www.computerenhance.com/p/monday-q-and-a-16-2023-06-19)
# 55. [How does QueryPerformanceCounter measure time?](https://www.computerenhance.com/p/how-does-queryperformancecounter)
diff --git a/misc/tmux.sh b/misc/tmux.sh
new file mode 100755
index 0000000..d3c61fe
--- /dev/null
+++ b/misc/tmux.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+tmux new-window nnd --tty=$(tty) --session=compenhance $@
+clear
+sleep 1000000
diff --git a/src/haversine_generator/haversine_generator.cpp b/src/haversine_generator/haversine_generator.cpp
index e0bc37a..3ce2f11 100644
--- a/src/haversine_generator/haversine_generator.cpp
+++ b/src/haversine_generator/haversine_generator.cpp
@@ -21,23 +21,27 @@ POP_WARNINGS
//~ Macro's
#define MemoryCopy memcpy
-
-//~ Constants
-#define ClusterCount 64
-// NOTE(luca): A double's mantissa is 52 bits. 2^52 - 1 is 4503599627370495 which has
-// 16 digits.
-#define PointJsonFormat "{ \"x0\": %.15f, \"y0\": %.15f, \"x1\": %.15f, \"y1\": %.15f }\n"
-
//~ Types
#include "generated/types.h"
-struct cluster
+//~ Helpers
+
+void WriteMemoryTofile(umm Size, void *Memory, umm PairCount, char *Name, char *Extension)
{
- f64 X;
- f64 Y;
- f64 Width;
- f64 Height;
-};
+ char FileName[256] = {};
+ stbsp_sprintf(FileName, "data_%lu_%s.%s", PairCount, Name, Extension);
+
+ int File = open(FileName, O_RDWR|O_CREAT|O_TRUNC, 0600);
+ if(File != -1)
+ {
+ smm BytesWritten = write(File, Memory, Size);
+ Assert(BytesWritten == Size);
+ }
+ else
+ {
+
+ }
+}
//~ Main
int main(int ArgsCount, char *Args[], char *Env[])
@@ -49,52 +53,35 @@ int main(int ArgsCount, char *Args[], char *Env[])
u32 Method = 0;
u64 RandomSeed = 0;;
u64 PairCount = 0;
- b32 Error = false;
- char *MethodString = Args[1];
+ char *MethodName = Args[1];
char *SeedString = Args[2];
- char *PairCountString = Args[3];
- if(!strcmp(MethodString, "uniform"))
- {
- Method = Method_Uniform;
- }
- else if(!strcmp(MethodString, "cluster"))
- {
- Method = Method_Cluster;
- }
- else
- {
- Error = true;
- }
+ u64 ClusterCountLeft = U64Max;
- RandomSeed = atoll(SeedString);
+ f64 MaxAllowedX = 180.0;
+ f64 MaxAllowedY = 90.0;
+ f64 XCenter = 0.0;
+ f64 YCenter = 0.0;
+ f64 XRadius = MaxAllowedX;
+ f64 YRadius = MaxAllowedY;
- if(RandomSeed == 0)
+ if(!strcmp(MethodName, "cluster"))
{
- if(SeedString[0] == '0')
- {
- RandomSeed = 0;
- }
- else
- {
- Error = true;
- }
+ ClusterCountLeft = 0;
}
-
- PairCount = atoll(PairCountString);
- if(PairCount == 0)
+ else if(strcmp(MethodName, "uniform"))
{
- Error = true;
+ MethodName = "uniform";
+ printf("Warning: Unknown method '%s', uniform used.\n", MethodName);
}
- if(!Error)
+ RandomSeed = atoll(Args[2]);
+ PairCount = atoll(Args[3]);
+
+ u64 MaxPairCount = (1LL << 34);
+ if(PairCount < MaxPairCount)
{
- printf("Method: %s\n"
- "Random seed: %lu\n"
- "Pairs count: %lu\n"
- , MethodString, RandomSeed, PairCount);
-
umm JsonMemorySize = Gigabytes(4);
u8 *JsonMemory = (u8 *)mmap(0, JsonMemorySize, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED, -1, 0);
u8 *JsonOut = JsonMemory;
@@ -103,141 +90,69 @@ int main(int ArgsCount, char *Args[], char *Env[])
u8 *BinMemory = (u8 *)mmap(0, BinMemorySize, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED, -1, 0);
u8 *BinOut = BinMemory;
- // Generate pairs in the following format.
- //
- // {
- // "pairs":
- // [
- // { "x0": ..., "y0": ..., "x1": ..., "y1": ... },
- // { "x0": ..., "y0": ..., "x1": ..., "y1": ... }
- // ]
- // }
- //
+ JsonOut += stbsp_sprintf((char *)JsonOut,
+ "{\n"
+ " \"pairs\":\n"
+ " [\n");
- char *JsonHeader =
- "{\n"
- " \"pairs\":\n"
- " [\n";
- char *JsonFooter =
- " ]\n"
- "}\n";
+ pcg64_random_t Series = {};
+ pcg64_srandom_r(&Series, RandomSeed, RandomSeed);
- JsonOut += stbsp_sprintf((char *)JsonOut, "%s", JsonHeader);
+ u64 ClusterCountMax = 1 + (PairCount / 64);
- pcg64_random_t RNG = {};
- pcg64_srandom_r(&RNG, RandomSeed, RandomSeed);
+ f64 SumCoefficient = 1.0/(f64)PairCount;
+ f64 Sum = 0;
- if(0) {}
- else if(Method == Method_Uniform)
+ for(u32 PairIndex = 0;
+ PairIndex < PairCount;
+ PairIndex += 1)
{
- f64 AverageSum = 0;
- f64 TotalSum = 0;
- for(u64 PairsIndex = 0;
- PairsIndex < PairCount;
- PairsIndex += 1)
+ if(ClusterCountLeft-- == 0)
{
- f64 X0 = RandomBetween(&RNG, -180.0, 180.0);
- f64 Y0 = RandomBetween(&RNG, -90.0, 90.0);
- f64 X1 = RandomBetween(&RNG, -180.0, 180.0);
- f64 Y1 = RandomBetween(&RNG, -90.0, 360.0);
-
- f64 Sum = ReferenceHaversine(X0, Y0, X1, Y1, 6372.8);
- TotalSum += Sum;
-
- *(f64 *)BinOut = Sum;
- BinOut += sizeof(Sum);
+ ClusterCountLeft = ClusterCountMax;
- JsonOut += stbsp_sprintf((char *)JsonOut, " " PointJsonFormat, X0, Y0, X1, Y1);
+ XCenter = RandomBetween(&Series, -MaxAllowedX, MaxAllowedX);
+ YCenter = RandomBetween(&Series, -MaxAllowedY, MaxAllowedY);
+ XRadius = RandomBetween(&Series, 0, MaxAllowedX);
+ YRadius = RandomBetween(&Series, 0, MaxAllowedY);
}
- AverageSum = TotalSum / (f64)PairCount;
- *(f64 *)BinOut = AverageSum;
- BinOut += sizeof(AverageSum);
+ f64 X0 = RandomDegree(&Series, XCenter, XRadius, MaxAllowedX);
+ f64 Y0 = RandomDegree(&Series, YCenter, YRadius, MaxAllowedY);
+ f64 X1 = RandomDegree(&Series, XCenter, XRadius, MaxAllowedX);
+ f64 Y1 = RandomDegree(&Series, YCenter, YRadius, MaxAllowedY);
- printf("Average sum: %f\n", AverageSum);
- }
- else if(Method == Method_Cluster)
- {
- cluster Clusters[ClusterCount] = {};
- for(u32 ClusterIndex = 0;
- ClusterIndex < ClusterCount;
- ClusterIndex += 1)
- {
- cluster *ClusterAt = Clusters + ClusterIndex;
- ClusterAt->X = RandomBetween(&RNG, -180.0, 180.0);
- ClusterAt->Y = RandomBetween(&RNG, -90.0, 90.0);
- ClusterAt->Width = RandomBetween(&RNG, 0.0, 180.0);
- ClusterAt->Height = RandomBetween(&RNG, 0.0, 90.0);
- }
-
- f64 AverageSum = 0;
- f64 TotalSum = 0;
- u32 ClusterIndex = 0;
- for(u32 PairIndex = 0;
- PairIndex < PairCount;
- PairIndex += 1)
- {
- cluster *ClusterAt = Clusters + ClusterIndex;
-
- f64 X0 = RandomBetween(&RNG, ClusterAt->X - ClusterAt->Width, ClusterAt->X + ClusterAt->Width);
- f64 Y0 = RandomBetween(&RNG, ClusterAt->Y - ClusterAt->Height, ClusterAt->Y + ClusterAt->Height);
- f64 X1 = RandomBetween(&RNG, ClusterAt->X - ClusterAt->Width, ClusterAt->X + ClusterAt->Width);
- f64 Y1 = RandomBetween(&RNG, ClusterAt->Y - ClusterAt->Height, ClusterAt->Y + ClusterAt->Height);
-
- f64 Sum = ReferenceHaversine(X0, Y0, X1, Y1, 6372.8);
- TotalSum += Sum;
-
- *(f64 *)BinOut = Sum;
- BinOut += sizeof(Sum);
-
- JsonOut += stbsp_sprintf((char *)JsonOut, " " PointJsonFormat, X0, Y0, X1, Y1);
-
- ClusterIndex += 1;
- if(ClusterIndex == ClusterCount)
- {
- ClusterIndex -= ClusterCount;
- }
-
- }
- AverageSum = TotalSum / (f64)PairCount;
+ f64 EarthRadius = 6372.8;
+ f64 Distance = ReferenceHaversine(X0, Y0, X1, Y1, EarthRadius);
+ Sum += SumCoefficient*Distance;
- *(f64 *)BinOut = AverageSum;
- BinOut += sizeof(AverageSum);
+ *(f64 *)BinOut = Distance;
+ BinOut += sizeof(Distance);
- printf("Average sum: %f\n", AverageSum);
- }
- else
- {
- Assert(0);
+ const char *Separator = (PairIndex == PairCount - 1) ? "\n" : ",\n";
+ JsonOut += stbsp_sprintf((char *)JsonOut,
+ " { \"x0\": %.16f, \"y0\": %.16f, \"x1\": %.16f, \"y1\": %.16f }%s",
+ X0, Y0, X1, Y1, Separator);
}
- JsonOut += stbsp_sprintf((char *)JsonOut, "%s", JsonFooter);
+ *(f64 *)BinOut = Sum;
+ BinOut += sizeof(Sum);
- // Write memory to json file
- {
- char JsonFileName[256] = {};
- stbsp_sprintf(JsonFileName, "data_%lu.json", PairCount);
-
- int File = open(JsonFileName, O_RDWR|O_CREAT|O_TRUNC, 0600);
- Assert(File != -1);
- smm Result = write(File, JsonMemory, JsonOut - JsonMemory);
- Assert(Result == JsonOut - JsonMemory);
- }
+ printf("Method: %s\n"
+ "Random seed: %lu\n"
+ "Pairs count: %lu\n"
+ , MethodName, RandomSeed, PairCount);
+ printf("Average sum: %.16f\n", Sum);
- // Write memory to binary answer file
- char BinFileName[256] = {};
- {
- stbsp_sprintf(BinFileName, "data_%lu_haveranswer.f64", PairCount);
- int File = open(BinFileName, O_RDWR|O_CREAT|O_TRUNC, 0600);
- Assert(File != -1);
- smm Result = write(File, BinMemory, BinOut - BinMemory);
- Assert(Result == BinOut - BinMemory);
- }
+ JsonOut += stbsp_sprintf((char *)JsonOut,
+ " ]\n"
+ "}\n");
+ WriteMemoryTofile(JsonOut - JsonMemory, JsonMemory, PairCount, "flex", "json");
+ WriteMemoryTofile(BinOut - BinMemory, BinMemory, PairCount, "haveranswer", "f64");
}
else
{
- printf("Usage: %s [uniform/cluster] [random seed] [number of pairs to generate]\n",
- Args[0]);
+ printf("Massive files unsupported. Number of pairs must be less than %lu.\n", MaxPairCount);
}
}
else
diff --git a/src/haversine_generator/haversine_random.h b/src/haversine_generator/haversine_random.h
index e80df7d..76d766e 100644
--- a/src/haversine_generator/haversine_random.h
+++ b/src/haversine_generator/haversine_random.h
@@ -5,10 +5,12 @@ POP_WARNINGS
#define CountLeadingZeroes64(Value) __builtin_clzll(Value)
+typedef pcg64_random_t random_series;
+
u64
-RandomU64(pcg64_random_t *RNG)
+RandomU64(random_series *Series)
{
- u64 Result = pcg64_random_r(RNG);
+ u64 Result = pcg64_random_r(Series);
return Result;
}
@@ -30,7 +32,7 @@ RandomU64(pcg64_random_t *RNG)
* number in [0, 1], 0.00001010011111010100...; then round it.
*/
f64
-RandomF64(pcg64_random_t *RNG)
+RandomF64(random_series *Series)
{
s32 Exponent = -64;
u64 Significand;
@@ -40,7 +42,7 @@ RandomF64(pcg64_random_t *RNG)
* Read zeros into the exponent until we hit a one; the rest
* will go into the significand.
*/
- while((Significand = RandomU64(RNG)) == 0)
+ while((Significand = RandomU64(Series)) == 0)
{
Exponent -= 64;
/*
@@ -66,7 +68,7 @@ RandomF64(pcg64_random_t *RNG)
if (Shift != 0) {
Exponent -= Shift;
Significand <<= Shift;
- Significand |= (RandomU64(RNG) >> (64 - Shift));
+ Significand |= (RandomU64(Series) >> (64 - Shift));
}
/*
@@ -86,22 +88,41 @@ RandomF64(pcg64_random_t *RNG)
}
f64
-RandomUnilateral(pcg64_random_t *RNG)
+RandomUnilateral(random_series *Series)
{
- return RandomF64(RNG);
+ return RandomF64(Series);
}
f64
-RandomBilateral(pcg64_random_t *RNG)
+RandomBilateral(random_series *Series)
{
- f64 Result = 2.0*RandomUnilateral(RNG) - 1.0;
+ f64 Result = 2.0*RandomUnilateral(Series) - 1.0;
return Result;
}
f64
-RandomBetween(pcg64_random_t *RNG, f64 Min, f64 Max)
+RandomBetween(random_series *Series, f64 Min, f64 Max)
{
f64 Range = Max - Min;
- f64 Result = Min + RandomUnilateral(RNG)*Range;
+ f64 Result = Min + RandomUnilateral(Series)*Range;
+ return Result;
+}
+
+
+static f64 RandomDegree(random_series *Series, f64 Center, f64 Radius, f64 MaxAllowed)
+{
+ f64 MinVal = Center - Radius;
+ if(MinVal < -MaxAllowed)
+ {
+ MinVal = -MaxAllowed;
+ }
+
+ f64 MaxVal = Center + Radius;
+ if(MaxVal > MaxAllowed)
+ {
+ MaxVal = MaxAllowed;
+ }
+
+ f64 Result = RandomBetween(Series, MinVal, MaxVal);
return Result;
} \ No newline at end of file
diff --git a/src/haversine_processor/build.sh b/src/haversine_processor/build.sh
index 2cd5f25..73991e9 100755
--- a/src/haversine_processor/build.sh
+++ b/src/haversine_processor/build.sh
@@ -8,7 +8,7 @@ cd "$ScriptDirectory"
#- Globals
CommonCompilerFlags="-DOS_LINUX=1 -fsanitize-trap -nostdinc++"
CommonWarningFlags="-Wall -Wextra -Wconversion -Wdouble-promotion -Wno-sign-conversion -Wno-sign-compare -Wno-double-promotion -Wno-unused-but-set-variable -Wno-unused-variable -Wno-write-strings -Wno-pointer-arith -Wno-unused-parameter -Wno-unused-function"
-LinkerFlags=""
+LinkerFlags="-lm"
DebugFlags="-g -ggdb -g3"
ReleaseFlags="-O3"
diff --git a/src/haversine_processor/haversine_processor.cpp b/src/haversine_processor/haversine_processor.cpp
index 8571627..ffb3a28 100644
--- a/src/haversine_processor/haversine_processor.cpp
+++ b/src/haversine_processor/haversine_processor.cpp
@@ -2,6 +2,7 @@
#define STB_SPRINTF_IMPLEMENTATION
#include "libs/stb_sprintf.h"
+#include <math.h>
#include <errno.h>
#include <unistd.h>
@@ -21,6 +22,46 @@ struct str8
global_variable u8 LogBuffer[Kilobytes(64)];
//~ Functions
+
+//- Haversine
+static f64 Square(f64 A)
+{
+ f64 Result = (A*A);
+ return Result;
+}
+
+static f64 RadiansFromDegrees(f64 Degrees)
+{
+ f64 Result = 0.01745329251994329577 * Degrees;
+ return Result;
+}
+
+// NOTE(casey): EarthRadius is generally expected to be 6372.8
+static f64 ReferenceHaversine(f64 X0, f64 Y0, f64 X1, f64 Y1, f64 EarthRadius)
+{
+ /* NOTE(casey): This is not meant to be a "good" way to calculate the Haversine distance.
+ Instead, it attempts to follow, as closely as possible, the formula used in the real-world
+ question on which these homework exercises are loosely based.
+ */
+
+ f64 lat1 = Y0;
+ f64 lat2 = Y1;
+ f64 lon1 = X0;
+ f64 lon2 = X1;
+
+ f64 dLat = RadiansFromDegrees(lat2 - lat1);
+ f64 dLon = RadiansFromDegrees(lon2 - lon1);
+ lat1 = RadiansFromDegrees(lat1);
+ lat2 = RadiansFromDegrees(lat2);
+
+ f64 a = Square(sin(dLat/2.0)) + cos(lat1)*cos(lat2)*Square(sin(dLon/2));
+ f64 c = 2.0*asin(sqrt(a));
+
+ f64 Result = EarthRadius * c;
+
+ return Result;
+}
+
//- Debug utilities
void AssertErrnoNotEquals(smm Result, smm ErrorValue)
{
@@ -51,6 +92,24 @@ void LogFormat(char *Format, ...)
AssertErrnoEquals(BytesWritten, Length);
}
+
+str8 ReadEntireFileIntoMemory(char *FileName)
+{
+ str8 Result = {};
+
+ int File = open(FileName, O_RDONLY);
+
+ struct stat StatBuffer = {};
+ int Error = fstat(File, &StatBuffer);
+ AssertErrnoNotEquals(Error, -1);
+
+ Result.Size = StatBuffer.st_size;
+ Result.Data = (u8 *)mmap(0, Result.Size, PROT_READ, MAP_PRIVATE, File, 0);
+ AssertErrnoNotEquals((smm)Result.Data, (smm)MAP_FAILED);
+
+ return Result;
+}
+
//- Parsing utilities
b32 IsWhiteSpace(u8 Char)
@@ -169,18 +228,34 @@ void ParseFloatNumber(umm Size, u8 *In, umm *Start, f64 *Value)
*Start = At;
}
+void ConsumeHaversineJsonNumber(umm Size, u8 *In, umm *Start, str8 Name, f64 *Value, b32 NumberLeft)
+{
+ umm At = *Start;
+
+ ConsumePastJsonString(Size, In, &At, Name);
+ ConsumeWhiteSpacePastChar(Size, In, &At, ':');
+ while(At < Size && IsWhiteSpace(In[At])) At += 1;
+ ParseFloatNumber(Size, In, &At, Value);
+
+ if(NumberLeft)
+ {
+ ConsumeWhiteSpacePastChar(Size, In, &At, ',');
+ }
+
+ *Start = At;
+}
+
//-
int main(int ArgsCount, char *Args[])
{
-
- char *JsonFileName = 0;
- char *AnswersFileName = 0;
-
+ str8 Answers = {};
+ umm AnswerIndex = 0;
+ str8 Json = {};
if(ArgsCount >= 2)
{
- JsonFileName = Args[1];
+ Json = ReadEntireFileIntoMemory(Args[1]);
}
else
{
@@ -189,75 +264,84 @@ int main(int ArgsCount, char *Args[])
if(ArgsCount >= 3)
{
- AnswersFileName = Args[1];
+ Answers = ReadEntireFileIntoMemory(Args[2]);
}
- if(JsonFileName)
+ if(Json.Size)
{
- int JsonFile = open(JsonFileName, O_RDONLY);
- if(JsonFile != -1)
- {
- struct stat StatBuffer = {};
- int Result = fstat(JsonFile, &StatBuffer);
- AssertErrnoNotEquals(Result, -1);
+ f64 X0 = 0.0;
+ f64 X1 = 0.0;
+ f64 Y0 = 0.0;
+ f64 Y1 = 0.0;
+
+ // Json Parsing
+ u8 *In = Json.Data;
+
+ umm At = 0;
+ ConsumeWhiteSpacePastChar(Json.Size, In, &At, '{');
+ ConsumePastJsonString(Json.Size, In, &At, S8Lit("pairs"));
+ ConsumeWhiteSpacePastChar(Json.Size, In, &At, ':');
+ ConsumeWhiteSpacePastChar(Json.Size, In, &At, '[');
+
+ f64 TotalSum = 0;
+ umm PairCount = 0;
+ b32 PairsRemaining = true;
+
+ // One pair
+ while(PairsRemaining && (At < Json.Size))
+ {
+ ConsumeWhiteSpacePastChar(Json.Size, In, &At, '{');
- umm FileSize = StatBuffer.st_size;
- u8 *JsonMemory = (u8 *)mmap(0, FileSize, PROT_READ, MAP_PRIVATE, JsonFile, 0);
- AssertErrnoNotEquals((smm)JsonMemory, (smm)MAP_FAILED);
+ ConsumeHaversineJsonNumber(Json.Size, In, &At, S8Lit("x0"), &X0, true);
+ ConsumeHaversineJsonNumber(Json.Size, In, &At, S8Lit("y0"), &Y0, true);
+ ConsumeHaversineJsonNumber(Json.Size, In, &At, S8Lit("x1"), &X1, true);
+ ConsumeHaversineJsonNumber(Json.Size, In, &At, S8Lit("y1"), &Y1, false);
- f64 X0 = 0.0;
- f64 X1 = 0.0;
- f64 Y0 = 0.0;
- f64 Y1 = 0.0;
+ f64 Sum = ReferenceHaversine(X0, Y0, X1, Y1, 6372.8);
+ TotalSum += Sum;
- // Json Parsing
- u8 *In = JsonMemory;
+ if(Answers.Size)
+ {
+ // NOTE(luca): What to do here?
+ //f64 AnswerSum = ((f64 *)Answers.Data)[AnswerIndex];
+
+ AnswerIndex += 1;
+ }
- umm At = 0;
- ConsumeWhiteSpacePastChar(FileSize, In, &At, '{');
- ConsumePastJsonString(FileSize, In, &At, S8Lit("pairs"));
- ConsumeWhiteSpacePastChar(FileSize, In, &At, ':');
- ConsumeWhiteSpacePastChar(FileSize, In, &At, '[');
+ ConsumeWhiteSpacePastChar(Json.Size, In, &At, '}');
- b32 PairsRemaining = true;
- // One pair
- while(PairsRemaining && (At < FileSize))
- {
- ConsumeWhiteSpacePastChar(FileSize, In, &At, '{');
-
- ConsumePastJsonString(FileSize, In, &At, S8Lit("x0"));
- ConsumeWhiteSpacePastChar(FileSize, In, &At, ':');
- while(At < FileSize && IsWhiteSpace(In[At])) At += 1;
- ParseFloatNumber(FileSize, In, &At, &X0);
- ConsumeWhiteSpacePastChar(FileSize, In, &At, ',');
-
- ConsumePastJsonString(FileSize, In, &At, S8Lit("y0"));
- ConsumeWhiteSpacePastChar(FileSize, In, &At, ':');
- while(At < FileSize && IsWhiteSpace(In[At])) At += 1;
- ParseFloatNumber(FileSize, In, &At, &Y0);
- ConsumeWhiteSpacePastChar(FileSize, In, &At, ',');
-
- ConsumePastJsonString(FileSize, In, &At, S8Lit("x1"));
- ConsumeWhiteSpacePastChar(FileSize, In, &At, ':');
- while(At < FileSize && IsWhiteSpace(In[At])) At += 1;
- ParseFloatNumber(FileSize, In, &At, &X1);
- ConsumeWhiteSpacePastChar(FileSize, In, &At, ',');
-
- ConsumePastJsonString(FileSize, In, &At, S8Lit("y1"));
- ConsumeWhiteSpacePastChar(FileSize, In, &At, ':');
- while(At < FileSize && IsWhiteSpace(In[At])) At += 1;
- ParseFloatNumber(FileSize, In, &At, &Y1);
-
- LogFormat("X0: %.15f, Y0: %.15f, X1: %.15f, Y1: %.15f\n", X0, Y0, X1, Y1);
-
- ConsumeWhiteSpacePastChar(FileSize, In, &At, '}');
-
- while(At < FileSize && IsWhiteSpace(In[At])) At += 1;
- PairsRemaining = (In[At] == '{' || At >= FileSize);
+ if(At < Json.Size && In[At] == ',')
+ {
+ At += 1;
}
- ConsumeWhiteSpacePastChar(FileSize, In, &At, ']');
- ConsumeWhiteSpacePastChar(FileSize, In, &At, '}');
+ while(At < Json.Size && IsWhiteSpace(In[At])) At += 1;
+ PairsRemaining = (In[At] == '{' || At >= Json.Size);
+
+ PairCount += 1;
+ }
+
+ ConsumeWhiteSpacePastChar(Json.Size, In, &At, ']');
+ ConsumeWhiteSpacePastChar(Json.Size, In, &At, '}');
+
+ f64 AverageSum = TotalSum / (f64)PairCount;
+ LogFormat("Input size: %lu\n"
+ "Pair count: %lu\n"
+ "Haversine sum: %.16f\n"
+ , Json.Size, PairCount, AverageSum);
+
+ if(Answers.Size)
+ {
+ f64 AnswerAverageSum = ((f64 *)Answers.Data)[AnswerIndex];
+ AnswerIndex += 1;
+
+ Assert((AnswerIndex * sizeof(f64)) == Answers.Size);
+
+ LogFormat("\nValidation\n"
+ "Reference sum: %.16f\n"
+ "Difference: %.16f\n"
+ , AnswerAverageSum, AnswerAverageSum - AverageSum);
+
}