Reorganise and start working on the json parser
This commit is contained in:
65
haversine_02/src/argparser.cpp
Normal file
65
haversine_02/src/argparser.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "argparser.h"
|
||||
#include <argp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
static error_t argp_parser(i32 key, char *arg, argp_state *state);
|
||||
|
||||
static argp parser = {};
|
||||
|
||||
static argp_option options[] = {
|
||||
{.name = "seed", .key = 's', .arg = "SEED"},
|
||||
{.name = "cluster", .key = 'c'},
|
||||
{0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
GeneratorArgs parse_args(i32 argc, char *argv[]) {
|
||||
GeneratorArgs args = {};
|
||||
|
||||
parser.options = options;
|
||||
parser.parser = argp_parser;
|
||||
parser.args_doc = "COUNT";
|
||||
|
||||
argp_parse(&parser, argc, argv, 0, 0, &args);
|
||||
|
||||
if (args.seed == 0) {
|
||||
args.seed = time(NULL);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
error_t argp_parser(i32 key, char *arg, argp_state *state) {
|
||||
GeneratorArgs *args = (GeneratorArgs *)state->input;
|
||||
|
||||
switch (key) {
|
||||
case 's':
|
||||
args->seed = strtoul(arg, NULL, 10);
|
||||
|
||||
break;
|
||||
case 'c':
|
||||
args->clustered = true;
|
||||
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
if (state->arg_num >= 1) {
|
||||
argp_usage(state);
|
||||
}
|
||||
|
||||
args->count = strtoull(arg, NULL, 10);
|
||||
|
||||
break;
|
||||
case ARGP_KEY_END:
|
||||
if (state->arg_num < 1) {
|
||||
argp_usage(state);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
115
haversine_02/src/generator.cpp
Normal file
115
haversine_02/src/generator.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
#include "generator.h"
|
||||
#include "aliases.h"
|
||||
#include "point_types.h"
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define X_MIN -180.0
|
||||
#define X_MAX 180.0
|
||||
#define Y_MIN -90.0
|
||||
#define Y_MAX 90.0
|
||||
|
||||
f64 generate_random_double(f64 min, f64 max);
|
||||
Point generate_random_point(f64 x_min, f64 x_max, f64 y_min, f64 y_max);
|
||||
PointPair generate_random_pair(f64 x_min, f64 x_max, f64 y_min, f64 y_max);
|
||||
|
||||
void fill_pairs_array(PairArray *pairs, bool clustered) {
|
||||
if (clustered) {
|
||||
u64 digit_count = (u64)log10(pairs->count) + 1;
|
||||
|
||||
u64 cluster_count = 0;
|
||||
|
||||
if (digit_count > 2) {
|
||||
cluster_count = digit_count * 8;
|
||||
} else {
|
||||
cluster_count = digit_count;
|
||||
}
|
||||
|
||||
Point clusters[cluster_count];
|
||||
f64 radii[cluster_count];
|
||||
|
||||
u64 pairs_per_cluster = pairs->count / cluster_count;
|
||||
u64 generated_pairs = 0;
|
||||
u64 pairs_to_generate = 0;
|
||||
|
||||
for (u64 i = 0; i < cluster_count; ++i) {
|
||||
clusters[i] = {
|
||||
generate_random_double(X_MIN, X_MAX),
|
||||
generate_random_double(Y_MIN, Y_MAX),
|
||||
};
|
||||
|
||||
radii[i] = generate_random_double(0.0, (digit_count - 1) * 40.0);
|
||||
|
||||
f64 cluster_x_min = clusters[i].x - radii[i];
|
||||
if (cluster_x_min < X_MIN) {
|
||||
cluster_x_min = X_MIN;
|
||||
}
|
||||
|
||||
f64 cluster_x_max = clusters[i].x + radii[i];
|
||||
if (cluster_x_max > X_MAX) {
|
||||
cluster_x_max = X_MAX;
|
||||
}
|
||||
|
||||
f64 cluster_y_min = clusters[i].y - radii[i];
|
||||
if (cluster_y_min < Y_MIN) {
|
||||
cluster_y_min = Y_MIN;
|
||||
}
|
||||
|
||||
f64 cluster_y_max = clusters[i].y + radii[i];
|
||||
if (cluster_y_max > Y_MAX) {
|
||||
cluster_y_max = Y_MAX;
|
||||
}
|
||||
|
||||
pairs_to_generate = 0;
|
||||
|
||||
if (generated_pairs + pairs_per_cluster < pairs->count) {
|
||||
pairs_to_generate = pairs_per_cluster;
|
||||
} else {
|
||||
pairs_to_generate = pairs->count - generated_pairs;
|
||||
}
|
||||
|
||||
for (u64 i = 0; i < pairs_to_generate; ++i) {
|
||||
// clang-format off
|
||||
pairs->pairs[generated_pairs + i] = generate_random_pair(
|
||||
cluster_x_min,
|
||||
cluster_x_max,
|
||||
cluster_y_min,
|
||||
cluster_y_max
|
||||
);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
generated_pairs += pairs_to_generate;
|
||||
}
|
||||
} else {
|
||||
for (u64 i = 0; i < pairs->count; ++i) {
|
||||
pairs->pairs[i] = generate_random_pair(X_MIN, X_MAX, Y_MIN, Y_MAX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
f64 generate_random_double(f64 min, f64 max) {
|
||||
u32 num = rand();
|
||||
|
||||
f64 result = min + (((f64)num / (f64)RAND_MAX) * (max - min));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Point generate_random_point(f64 x_min, f64 x_max, f64 y_min, f64 y_max) {
|
||||
Point p = {
|
||||
generate_random_double(x_min, x_max),
|
||||
generate_random_double(y_min, y_max),
|
||||
};
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
PointPair generate_random_pair(f64 x_min, f64 x_max, f64 y_min, f64 y_max) {
|
||||
PointPair pair = {
|
||||
generate_random_point(x_min, x_max, y_min, y_max),
|
||||
generate_random_point(x_min, x_max, y_min, y_max),
|
||||
};
|
||||
|
||||
return pair;
|
||||
}
|
||||
45
haversine_02/src/genmain.cpp
Normal file
45
haversine_02/src/genmain.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "aliases.h"
|
||||
#include "argparser.h"
|
||||
#include "generator.h"
|
||||
#include "haversine.h"
|
||||
#include "point_types.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#define EARTH_RADIUS_KM 6371.0
|
||||
|
||||
i32 main(i32 argc, char *argv[]) {
|
||||
GeneratorArgs args = parse_args(argc, argv);
|
||||
|
||||
srand(args.seed);
|
||||
|
||||
PairArray arr = {args.count, NULL};
|
||||
arr.pairs = (PointPair *)malloc(arr.count * sizeof(PointPair));
|
||||
|
||||
fill_pairs_array(&arr, args.clustered);
|
||||
|
||||
write_pairs_to_json(arr, "pairs.json");
|
||||
|
||||
FILE *fp = fopen("count_and_distances", "w");
|
||||
|
||||
if (fp) {
|
||||
fwrite(&(arr.count), sizeof(arr.count), 1, fp);
|
||||
|
||||
i64 sum = 0;
|
||||
for (u64 i = 0; i < arr.count; ++i) {
|
||||
f64 distance = haversine_of_degrees(arr.pairs[i], EARTH_RADIUS_KM);
|
||||
|
||||
fwrite(&distance, sizeof(f64), 1, fp);
|
||||
|
||||
sum += distance;
|
||||
}
|
||||
printf("%ld\n", sum / arr.count);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
free(arr.pairs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
30
haversine_02/src/haversine.cpp
Normal file
30
haversine_02/src/haversine.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "haversine.h"
|
||||
#include "aliases.h"
|
||||
#include "point_types.h"
|
||||
#include <math.h>
|
||||
|
||||
#define PI 3.14159265358979323845
|
||||
#define SQUARE(X) ((X) * (X))
|
||||
|
||||
f64 radians(f64 degrees);
|
||||
|
||||
f64 haversine_of_degrees(const PointPair &pair, f64 radius) {
|
||||
f64 x0 = pair.p1.x;
|
||||
f64 y0 = pair.p1.y;
|
||||
f64 x1 = pair.p2.x;
|
||||
f64 y1 = pair.p2.y;
|
||||
|
||||
f64 dy = radians(y1 - y0);
|
||||
f64 dx = radians(x1 - x0);
|
||||
y0 = radians(y0);
|
||||
y1 = radians(y1);
|
||||
|
||||
f64 root_term =
|
||||
SQUARE(sin(dy / 2.0)) + cos(y0) * cos(y1) * SQUARE(sin(dx / 2.0));
|
||||
|
||||
f64 result = 2.0 * radius * asin(sqrt(root_term));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
f64 radians(f64 degrees) { return (degrees * PI) / 180.0; }
|
||||
47
haversine_02/src/jsonparse.cpp
Normal file
47
haversine_02/src/jsonparse.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "aliases.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
i32 main(i32 argc, char *argv[]) {
|
||||
if (argc < 2) {
|
||||
printf("Missing filename\n");
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const char *filename = argv[1];
|
||||
|
||||
FILE *fp = fopen(filename, "r");
|
||||
if (!fp) {
|
||||
printf("Failed to open file: %s\n", filename);
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
|
||||
u64 length = ftell(fp);
|
||||
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
char text[length + 1];
|
||||
|
||||
memset(text, 0, length);
|
||||
|
||||
fread(text, sizeof(char), length, fp);
|
||||
text[length] = '\0';
|
||||
|
||||
const char *delim = ", \t\n";
|
||||
|
||||
char *token = strtok(text, delim);
|
||||
while (token) {
|
||||
printf("TOKEN: %s\n", token);
|
||||
|
||||
token = strtok(NULL, delim);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
75
haversine_02/src/point_types.cpp
Normal file
75
haversine_02/src/point_types.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
#include "point_types.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
bool compare_point(const Point &p1, const Point &p2);
|
||||
bool compare_pair(const PointPair &pair1, const PointPair &pair2);
|
||||
|
||||
void write_pairs_to_binary(const PairArray &arr, const char *filename) {
|
||||
FILE *fp = fopen(filename, "w");
|
||||
|
||||
if (fp) {
|
||||
fwrite(&arr, sizeof(arr.count), 1, fp);
|
||||
|
||||
u64 total_size = sizeof(*(arr.pairs)) * arr.count;
|
||||
|
||||
fwrite(arr.pairs, total_size, 1, fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
void read_pairs_from_binary(PairArray &arr, const char *filename) {
|
||||
FILE *fp = fopen(filename, "r");
|
||||
|
||||
if (fp) {
|
||||
fread(&(arr.count), sizeof(arr.count), 1, fp);
|
||||
|
||||
arr.pairs = (PointPair *)malloc(arr.count * sizeof(PointPair));
|
||||
|
||||
fread(arr.pairs, sizeof(PointPair), arr.count, fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
void write_pairs_to_json(const PairArray &arr, const char *filename) {
|
||||
FILE *fp = fopen(filename, "w");
|
||||
|
||||
if (fp) {
|
||||
fprintf(fp, "{\n\t\"pairs\": [\n");
|
||||
|
||||
for (u64 i = 0; i < arr.count; ++i) {
|
||||
PointPair pair = arr.pairs[i];
|
||||
fprintf(fp, "\t\t{\"x0\": %f, \"y0\": %f, \"x1\": %f, \"y1\": %f}%s\n",
|
||||
pair.p1.x, pair.p1.y, pair.p2.x, pair.p2.y,
|
||||
i + 1 < arr.count ? "," : "");
|
||||
}
|
||||
|
||||
fprintf(fp, "\t]\n}\n");
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
bool compare_pair_array(const PairArray &arr1, const PairArray &arr2) {
|
||||
if (arr1.count != arr2.count) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (u64 i = 0; i < arr1.count; ++i) {
|
||||
if (!compare_pair(arr1.pairs[i], arr2.pairs[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool compare_point(const Point &p1, const Point &p2) {
|
||||
return p1.x == p2.x && p1.y == p2.y;
|
||||
}
|
||||
|
||||
bool compare_pair(const PointPair &pair1, const PointPair &pair2) {
|
||||
return compare_point(pair1.p1, pair2.p1) && compare_point(pair1.p2, pair2.p2);
|
||||
}
|
||||
Reference in New Issue
Block a user