From 177bea75a11bc62915095213c351c8385ea12226 Mon Sep 17 00:00:00 2001 From: "Douglas B. Rumbaugh" Date: Mon, 6 Jan 2025 12:23:42 -0500 Subject: Initial commit of cdf program and basic build system --- .gitignore | 5 ++ Makefile | 4 + include/cdf.h | 40 ++++++++++ src/cdf.c | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 293 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 include/cdf.h create mode 100644 src/cdf.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d5d3e26 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.cache +compile_commands.json +bin/* +build/* +*.bak diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0374e62 --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +all: bin/cdf + +bin/cdf: src/cdf.c include/cdf.h + gcc -std=c23 -Iinclude src/cdf.c -o bin/cdf diff --git a/include/cdf.h b/include/cdf.h new file mode 100644 index 0000000..418ffeb --- /dev/null +++ b/include/cdf.h @@ -0,0 +1,40 @@ +/* + */ + +#ifndef H_CDF +#define H_CDF + +#include +#include +#include +#include +#include +#include +#include +#include + +typedef union { + int64_t i; + uint64_t u; + double d; +} Number; + +typedef struct { + Number data; + uint64_t count; +} DistRecord; + +static int parse_options(int argc, char*const* argv); +static void help(); +static int process_data(FILE *file); +static DistRecord *expand_array(DistRecord *records, size_t *capacity); +static int read_data_int(DistRecord **records, size_t capacity, FILE *file); +static int read_data_uint(DistRecord **records, size_t capacity, FILE *file); +static int read_data_fp(DistRecord **records, size_t capacity, FILE *file); +static int print_data_fp(DistRecord *records, long double *freqs, size_t cnt); +static int print_data_int(DistRecord *records, long double *freqs, size_t cnt); +static int print_data_uint(DistRecord *records, long double *freqs, size_t cnt); + +#endif + + diff --git a/src/cdf.c b/src/cdf.c new file mode 100644 index 0000000..7d0bd87 --- /dev/null +++ b/src/cdf.c @@ -0,0 +1,244 @@ +/* + * + */ + + +#include "cdf.h" + +/* + * Global configuration variables. These are set based on command-line + * arguments, and read-only beyond that point. + */ +static bool ARG_REVERSE_CDF = false; +static bool ARG_FP_INPUT = false; +static bool ARG_UINT_INPUT = false; +static bool ARG_HELP = false; + +static int parse_options(int argc, char*const* argv) { + int arg_index = 0; + int arg; + bool error = false; + + while ((arg = getopt(argc, argv, "frhu")) != -1) { + switch (arg) { + case 'f': + ARG_FP_INPUT = true; + break; + case 'r': + ARG_REVERSE_CDF = true; + break; + case 'u': + ARG_UINT_INPUT = true; + case 'h': + ARG_HELP = true; + break; + case '?': + if (isprint(optopt)) { + fprintf(stderr, "Unknown option `-%c`.\n", optopt); + } else { + fprintf(stderr, "Unknown option character `\\x%x`.\n", optopt); + } + error = true; + break; + default: + error = true; + break; + } + } + + if (ARG_UINT_INPUT && ARG_FP_INPUT) { + fprintf(stderr, "Error: the -u and -f flags are mutually exclusive.\n"); + error = true; + } + + if (!error) { + arg_index = optind; + } + + return arg_index; +} + +static void help() { + fprintf(stderr, "Usage:\ncdf [-f] [-r] [filename]\n"); +} + +static DistRecord *expand_array(DistRecord *records, size_t *capacity) { + (*capacity) *= 2; + DistRecord *new = realloc(records, *capacity); + if (!new) { + fprintf(stderr, "ERROR: Memory allocation failed\n"); + return nullptr; + } + + return new; +} + +static int read_data_int(DistRecord **records, size_t capacity, FILE *file) { + size_t reccnt = 0; + while (fscanf(file, "%ld %ld\n", &(*records + reccnt)->count, + &(*records + reccnt)->data.i) != EOF) { + + reccnt++; + if (reccnt == capacity) { + if (!(*records = expand_array(*records, &capacity))) { + return -1; + } + } + } + + return reccnt; +} + +static int read_data_fp(DistRecord **records, size_t capacity, FILE *file) { + size_t reccnt = 0; + while (fscanf(file, "%ld %lf\n", &(*records + reccnt)->count, + &(*records + reccnt)->data.d) != EOF) { + + reccnt++; + if (reccnt == capacity) { + if (!(*records = expand_array(*records, &capacity))) { + return -1; + } + } + } + + return reccnt; +} + +static int read_data_uint(DistRecord **records, size_t capacity, FILE *file) { + size_t reccnt = 0; + while (fscanf(file, "%ld %ld\n", &(*records + reccnt)->count, + &(*records + reccnt)->data.u) != EOF) { + + reccnt++; + if (reccnt == capacity) { + if (!(*records = expand_array(*records, &capacity))) { + return -1; + } + } + } + + return reccnt; +} + +static int print_data_fp(DistRecord *records, long double *freqs, size_t cnt) { + for (size_t i=0; i