added some existing source code for various smaller tasks

This commit is contained in:
Steffen Vogel 2015-07-19 16:17:50 +02:00
parent 37578fab9d
commit ecd056a3a0
6 changed files with 512 additions and 0 deletions

174
project/hist.c Normal file
View file

@ -0,0 +1,174 @@
/** Histogram functions.
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014-2015, Institute for Automation of Complex Power Systems, EONERC
* This file is part of S2SS. All Rights Reserved. Proprietary and confidential.
* Unauthorized copying of this file, via any medium is strictly prohibited.
*********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <float.h>
#include <math.h>
#include <time.h>
#include "hist.h"
#include "utils.h"
#define VAL(h, i) ((h)->low + (i) * (h)->resolution)
#define INDEX(h, v) round((v - (h)->low) / (h)->resolution)
void hist_create(struct hist *h, double low, double high, double resolution)
{
h->low = low;
h->high = high;
h->resolution = resolution;
h->length = (high - low) / resolution;
h->data = alloc(h->length * sizeof(unsigned));
hist_reset(h);
}
void hist_destroy(struct hist *h)
{
free(h->data);
}
void hist_put(struct hist *h, double value)
{
int idx = INDEX(h, value);
/* Update min/max */
if (value > h->highest)
h->highest = value;
if (value < h->lowest)
h->lowest = value;
/* Check bounds and increment */
if (idx >= h->length)
h->higher++;
else if (idx < 0)
h->lower++;
else
h->data[idx]++;
h->total++;
/* Online / running calculation of variance and mean
* by Donald Knuths Art of Computer Programming, Vol 2, page 232, 3rd edition */
if (h->total == 1) {
h->_m[1] = h->_m[0] = value;
h->_s[1] = 0.0;
}
else {
h->_m[0] = h->_m[1] + (value - h->_m[1]) / h->total;
h->_s[0] = h->_s[1] + (value - h->_m[1]) * (value - h->_m[0]);
// set up for next iteration
h->_m[1] = h->_m[0];
h->_s[1] = h->_s[0];
}
}
void hist_reset(struct hist *h)
{
h->total = 0;
h->higher = 0;
h->lower = 0;
h->highest = DBL_MIN;
h->lowest = DBL_MAX;
memset(h->data, 0, h->length * sizeof(unsigned));
}
double hist_mean(struct hist *h)
{
return (h->total > 0) ? h->_m[0] : 0.0;
}
double hist_var(struct hist *h)
{
return (h->total > 1) ? h->_s[0] / (h->total - 1) : 0.0;
}
double hist_stddev(struct hist *h)
{
return sqrt(hist_var(h));
}
void hist_print(struct hist *h)
{
printf("Total: %u values\n", h->total);
printf("Highest value: %f\n", h->highest);
printf("Lowest value: %f\n", h->lowest);
printf("Mean: %f\n", hist_mean(h));
printf("Variance: %f\n", hist_var(h));
printf("Standard derivation: %f\n", hist_stddev(h));
if (h->higher > 0)
printf("Missed: %u values above %f\n", h->higher, h->high);
if (h->lower > 0)
printf("Missed: %u values below %f\n", h->lower, h->low);
if (h->total - h->higher - h->lower > 0) {
hist_plot(h);
char buf[(h->length + 1) * 8];
hist_dump(h, buf, sizeof(buf));
printf(buf);
}
}
void hist_plot(struct hist *h)
{
char buf[HIST_HEIGHT];
memset(buf, '#', sizeof(buf));
hist_cnt_t max = 1;
/* Get highest bar */
for (int i = 0; i < h->length; i++) {
if (h->data[i] > max)
max = h->data[i];
}
/* Print plot */
printf("%3s | %9s | %5s | %s\n", "#", "Value", "Occur", "Plot");
printf("--------------------------------------------------------------------------------\n");
for (int i = 0; i < h->length; i++) {
int bar = HIST_HEIGHT * ((double) h->data[i] / max);
printf("%3u | %+5.2e | " "%5u" " | %.*s\n", i, VAL(h, i), h->data[i], bar, buf);
}
}
void hist_dump(struct hist *h, char *buf, int len)
{
*buf = 0;
strap(buf, len, "[ ");
for (int i = 0; i < h->length; i++)
strap(buf, len, "%u ", h->data[i]);
strap(buf, len, "]");
}
void hist_matlab(struct hist *h, FILE *f)
{
char buf[h->length * 8];
hist_dump(h, buf, sizeof(buf));
fprintf(f, "%lu = struct( ", time(NULL));
fprintf(f, "'min', %f, 'max', %f, ", h->low, h->high);
fprintf(f, "'ok', %u, too_high', %u, 'too_low', %u, ", h->total, h->higher, h->lower);
fprintf(f, "'highest', %f, 'lowest', %f, ", h->highest, h->lowest);
fprintf(f, "'mean', %f, ", hist_mean(h));
fprintf(f, "'var', %f, ", hist_var(h));
fprintf(f, "'stddev', %f, ", hist_stddev(h));
fprintf(f, "'hist', %s ", buf);
fprintf(f, "),\n");
}

84
project/hist.h Normal file
View file

@ -0,0 +1,84 @@
/** Histogram functions.
*
* @file
* @author Steffen Vogel <post@steffenvogel.de>
* @copyright 2014-2015, Steffen Vogel
* @license GPLv3
*********************************************************************************/
#ifndef _HIST_H_
#define _HIST_H_
#include <stdio.h>
#define HIST_HEIGHT 75
#define HIST_SEQ 17
typedef unsigned hist_cnt_t;
/** Histogram structure used to collect statistics. */
struct hist {
/** The distance between two adjacent buckets. */
double resolution;
/** The value of the highest bucket. */
double high;
/** The value of the lowest bucket. */
double low;
/** The highest value observed (may be higher than #high). */
double highest;
/** The lowest value observed (may be lower than #low). */
double lowest;
/** The number of buckets in #data. */
int length;
/** Total number of counted values between #low and #high. */
hist_cnt_t total;
/** The number of values which are higher than #high. */
hist_cnt_t higher;
/** The number of values which are lower than #low. */
hist_cnt_t lower;
/** Pointer to dynamically allocated array of size length. */
hist_cnt_t *data;
/** Private variables for online variance calculation */
double _m[2], _s[2];
};
/** Initialize struct hist with supplied values and allocate memory for buckets. */
void hist_create(struct hist *h, double start, double end, double resolution);
/** Free the dynamically allocated memory. */
void hist_destroy(struct hist *h);
/** Reset all counters and values back to zero. */
void hist_reset(struct hist *h);
/** Count a value within its corresponding bucket. */
void hist_put(struct hist *h, double value);
/** Calcluate the variance of all counted values. */
double hist_var(struct hist *h);
/** Calculate the mean average of all counted values. */
double hist_mean(struct hist *h);
/** Calculate the standard derivation of all counted values. */
double hist_stddev(struct hist *h);
/** Print all statistical properties of distribution including a graphilcal plot of the histogram. */
void hist_print(struct hist *h);
/** Print ASCII style plot of histogram */
void hist_plot(struct hist *h);
/** Dump histogram data in Matlab format to buf */
void hist_dump(struct hist *h, char *buf, int len);
/** Prints Matlab struct containing all infos to file. */
void hist_matlab(struct hist *h, FILE *f);
#endif /* _HIST_H_ */

89
project/timing.c Normal file
View file

@ -0,0 +1,89 @@
/** Time related functions.
*
* @author Steffen Vogel <post@steffenvogel.de>
* @copyright 2014-2015, Steffen Vogel
* @license GPLv3
*********************************************************************************/
#include "timing.h"
uint64_t timerfd_wait(int fd)
{
uint64_t runs;
return read(fd, &runs, sizeof(runs)) < 0 ? 0 : runs;
}
uint64_t timerfd_wait_until(int fd, struct timespec *until)
{
struct itimerspec its = {
.it_value = *until
};
if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &its, NULL))
return 0;
else
return timerfd_wait(fd);
}
struct timespec time_add(struct timespec *start, struct timespec *end)
{
struct timespec sum = {
.tv_sec = end->tv_sec + start->tv_sec,
.tv_nsec = end->tv_nsec + start->tv_nsec
};
if (sum.tv_nsec > 1000000000) {
sum.tv_sec += 1;
sum.tv_nsec -= 1000000000;
}
return sum;
}
struct timespec time_diff(struct timespec *start, struct timespec *end)
{
struct timespec diff = {
.tv_sec = end->tv_sec - start->tv_sec,
.tv_nsec = end->tv_nsec - start->tv_nsec
};
if (diff.tv_nsec < 0) {
diff.tv_sec -= 1;
diff.tv_nsec += 1000000000;
}
return diff;
}
struct timespec time_from_double(double secs)
{
struct timespec ts;
ts.tv_sec = secs;
ts.tv_nsec = 1.0e9 * (secs - ts.tv_sec);
return ts;
}
double time_to_double(struct timespec *ts)
{
return ts->tv_sec + ts->tv_nsec * 1e-9;
}
double time_delta(struct timespec *start, struct timespec *end)
{
struct timespec diff = time_diff(start, end);
return time_to_double(&diff);
}
int time_fscan(FILE *f, struct timespec *ts)
{
return fscanf(f, "%lu.%lu", &ts->tv_sec, &ts->tv_nsec);
}
int time_fprint(FILE *f, struct timespec *ts)
{
return fprintf(f, "%lu.%09lu\t", ts->tv_sec, ts->tv_nsec);
}

58
project/timing.h Normal file
View file

@ -0,0 +1,58 @@
/** Time related functions.
*
* @author Steffen Vogel <post@steffenvogel.de>
* @copyright 2014-2015, Steffen Vogel
* @license GPLv3
*********************************************************************************/
#ifndef _TIME_H_
#define _TIME_H_
#define _POSIX_C_SOURCE 199309L
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <sys/timerfd.h>
/** Wait until timer elapsed
*
* @param fd A file descriptor which was created by timerfd_create(3).
* @retval 0 An error occured. Maybe the timer was stopped.
* @retval >0 The nummer of runs this timer already fired.
*/
uint64_t timerfd_wait(int fd);
/** Wait until a fixed time in the future is reached
*
* @param fd A file descriptor which was created by timerfd_create(3).
* @param until A pointer to a time in the future.
* @retval 0 An error occured. Maybe the timer was stopped.
* @retval >0 The nummer of runs this timer already fired.
*/
uint64_t timerfd_wait_until(int fd, struct timespec *until);
/** Get delta between two timespec structs */
struct timespec time_diff(struct timespec *start, struct timespec *end);
/** Get sum of two timespec structs */
struct timespec time_add(struct timespec *start, struct timespec *end);
/** Return the diffrence off two timestamps as double value in seconds. */
double time_delta(struct timespec *start, struct timespec *end);
/** Convert timespec to double value representing seconds */
double time_to_double(struct timespec *ts);
/** Convert double containing seconds after 1970 to timespec. */
struct timespec time_from_double(double secs);
/** Read a timestamp from a file with the format: "secs.nanosecs\t" */
int time_fscan(FILE *f, struct timespec *ts);
/** Write a timestamp to a file with the format: "secs.nanosecs\t" */
int time_fprint(FILE *f, struct timespec *ts);
#endif

77
project/utils.c Normal file
View file

@ -0,0 +1,77 @@
/** Utilities.
*
* @author Steffen Vogel <post@steffenvogel.de>
* @copyright 2014-2015, Steffen Vogel
* @license GPLv3
*********************************************************************************/
#ifndef HEXDUMP_COLS
#define HEXDUMP_COLS 8
#endif
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <error.h>
#include <string.h>
#include "utils.h"
void hexdump(void *mem, unsigned int len)
{
unsigned int i, j;
for (i = 0; i < len + ((len % HEXDUMP_COLS) ? (HEXDUMP_COLS - len % HEXDUMP_COLS) : 0); i++) {
if (i % HEXDUMP_COLS == 0)
printf("0x%06x: ", i); /* print offset */
if (i < len)
printf("%02x ", 0xFF & ((char*)mem)[i]); /* print hex data */
else
printf(" "); /* end of block, just aligning for ASCII dump */
/* print ASCII dump */
if (i % HEXDUMP_COLS == (HEXDUMP_COLS - 1)) {
for (j = i - (HEXDUMP_COLS - 1); j <= i; j++) {
if (j >= len) /* end of block, not really printing */
putchar(' ');
else if (isprint(((char*)mem)[j])) /* printable char */
putchar(0xFF & ((char*)mem)[j]);
else /* other char */
putchar('.');
}
putchar('\n');
}
}
}
void * alloc(size_t bytes)
{
void *p = malloc(bytes);
if (!p)
error(-1, 0, "Failed to allocate memory");
memset(p, 0, bytes);
return p;
}
int strap(char *dest, size_t size, const char *fmt, ...)
{
int ret;
va_list ap;
va_start(ap, fmt);
ret = vstrap(dest, size, fmt, ap);
va_end(ap);
return ret;
}
int vstrap(char *dest, size_t size, const char *fmt, va_list ap)
{
int len = strlen(dest);
return vsnprintf(dest + len, size - len, fmt, ap);
}

30
project/utils.h Normal file
View file

@ -0,0 +1,30 @@
/** Utilities.
*
* @author Steffen Vogel <post@steffenvogel.de>
* @copyright 2014-2015, Steffen Vogel
* @license GPLv3
* @file
*********************************************************************************/
#ifndef _UTILS_H_
#define _UTILS_H_
#include <stdarg.h>
#define MIN(x, y) ((x < y) ? x : y)
#define MAX(x, y) ((x > y) ? x : y)
void hexdump(void *mem, unsigned int len);
void * alloc(size_t bytes);
/** Safely append a format string to an existing string.
*
* This function is similar to strlcat() from BSD.
*/
int strap(char *dest, size_t size, const char *fmt, ...);
/** Variadic version of strap() */
int vstrap(char *dest, size_t size, const char *fmt, va_list va);
#endif