-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
283 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
EXEC_NAME := a.out | ||
|
||
CC := gcc | ||
CFLAGS += -I./../../lib | ||
CFLAGS += -Wall -Wextra -Wshadow -Wconversion -pedantic | ||
CFLAGS += -ggdb3 | ||
CFLAGS += -fsanitize=undefined | ||
CFLAGS += -fsanitize=address | ||
|
||
C_FILES := $(wildcard *.c) | ||
OBJ_FILES := $(C_FILES:.c=.o) | ||
|
||
LD_FLAGS += -fsanitize=undefined | ||
LD_FLAGS += -fsanitize=address | ||
|
||
.PHONY: all clean test | ||
|
||
all: $(EXEC_NAME) | ||
|
||
clean: | ||
rm -rf $(OBJ_FILES) | ||
rm -rf $(EXEC_NAME) | ||
|
||
test: $(EXEC_NAME) | ||
./a.out | ||
|
||
$(EXEC_NAME): $(OBJ_FILES) | ||
$(CC) $(LD_FLAGS) $^ -o $(EXEC_NAME) | ||
|
||
$(OBJ_FILES): $(SRC_FILES) | ||
|
||
$(SRC_FILES): | ||
$(CC) -c $(CFLAGS) $@ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
|
||
#include <float.h> | ||
#include <math.h> | ||
|
||
#define NAME flt_queue | ||
#define VALUE_TYPE float | ||
#include "fqueue.h" | ||
|
||
struct data_stream { | ||
float avg; | ||
struct flt_queue *queue; | ||
}; | ||
|
||
static inline void data_stream_init(struct data_stream *s, uint32_t max_elm) | ||
{ | ||
s->avg = FP_NAN; | ||
s->queue = flt_queue_create(max_elm); | ||
} | ||
|
||
static inline void data_stream_deinit(struct data_stream *s) | ||
{ | ||
flt_queue_destroy(s->queue); | ||
} | ||
|
||
static inline void data_stream_enqueue(struct data_stream *s, float val) | ||
{ | ||
if (flt_queue_is_full(s->queue)) { | ||
return; | ||
} | ||
if (s->queue->count == 0) { | ||
s->avg = val; | ||
} | ||
else { | ||
s->avg = (s->avg * (float)s->queue->count + val) / (float)(s->queue->count + 1); | ||
} | ||
flt_queue_enqueue(s->queue, val); | ||
} | ||
|
||
static inline float data_stream_dequeue(struct data_stream *s) | ||
{ | ||
if (flt_queue_is_empty(s->queue)) { | ||
return FP_NAN; | ||
} | ||
s->avg = (s->avg * (float)(s->queue->count) - flt_queue_peek(s->queue)) / (float)(s->queue->count - 1); | ||
return flt_queue_dequeue(s->queue); | ||
} | ||
|
||
static inline void data_stream_print(struct data_stream *s) | ||
{ | ||
printf("stream: ["); | ||
if (!flt_queue_is_empty(s->queue)) { | ||
printf(" %.2f", flt_queue_at(s->queue, 0)); | ||
} | ||
for (size_t i = 1; i < s->queue->count; i++) { | ||
printf(", %.2f", flt_queue_at(s->queue, (uint32_t)i)); | ||
} | ||
printf(" ]\n"); | ||
} | ||
|
||
static inline bool float_is_nearly_equal(const float a, const float b, const uint16_t n) | ||
{ | ||
return fabsf(a - b) <= FLT_EPSILON * (float)n; | ||
} | ||
|
||
#define print_line(expr) \ | ||
__extension__({ \ | ||
(expr); \ | ||
printf("%-34s", #expr); \ | ||
}) | ||
|
||
int main(void) | ||
{ | ||
struct data_stream s; | ||
data_stream_init(&s, 8); | ||
|
||
print_line(data_stream_enqueue(&s, 3.f)); | ||
printf("average: %-10.2f ", s.avg); | ||
data_stream_print(&s); | ||
assert(float_is_nearly_equal(s.avg, (3.f) / (float)(1), 128)); | ||
|
||
print_line(data_stream_enqueue(&s, 5.f)); | ||
printf("average: %-10.2f ", s.avg); | ||
data_stream_print(&s); | ||
assert(float_is_nearly_equal(s.avg, (3.f + 5.f) / (float)(2), 128)); | ||
|
||
print_line(data_stream_enqueue(&s, 15.f)); | ||
printf("average: %-10.2f ", s.avg); | ||
data_stream_print(&s); | ||
assert(float_is_nearly_equal(s.avg, (3.f + 5.f + 15.f) / (float)(3), 128)); | ||
|
||
print_line(data_stream_dequeue(&s)); | ||
printf("average: %-10.2f ", s.avg); | ||
data_stream_print(&s); | ||
assert(float_is_nearly_equal(s.avg, (5.f + 15.f) / (float)(2), 128)); | ||
|
||
print_line(data_stream_dequeue(&s)); | ||
printf("average: %-10.2f ", s.avg); | ||
data_stream_print(&s); | ||
assert(float_is_nearly_equal(s.avg, (15.f) / (float)(1), 128)); | ||
|
||
print_line(data_stream_enqueue(&s, 45.f)); | ||
printf("average: %-10.2f ", s.avg); | ||
data_stream_print(&s); | ||
assert(float_is_nearly_equal(s.avg, (15.f + 45.f) / (float)(2), 128)); | ||
|
||
print_line(data_stream_dequeue(&s)); | ||
printf("average: %-10.2f ", s.avg); | ||
data_stream_print(&s); | ||
assert(float_is_nearly_equal(s.avg, (45.f) / (float)(1), 128)); | ||
|
||
print_line(data_stream_dequeue(&s)); | ||
printf("average: %-10.2f ", s.avg); | ||
data_stream_print(&s); | ||
assert(isnanf(s.avg)); | ||
|
||
data_stream_deinit(&s); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
EXEC_NAME := a.out | ||
|
||
CC := gcc | ||
CFLAGS += -I./../../lib | ||
CFLAGS += -Wall -Wextra -Wshadow -Wconversion -pedantic | ||
CFLAGS += -ggdb3 | ||
CFLAGS += -fsanitize=undefined | ||
CFLAGS += -fsanitize=address | ||
|
||
C_FILES := $(wildcard *.c) | ||
OBJ_FILES := $(C_FILES:.c=.o) | ||
|
||
LD_FLAGS += -fsanitize=undefined | ||
LD_FLAGS += -fsanitize=address | ||
|
||
.PHONY: all clean test | ||
|
||
all: $(EXEC_NAME) | ||
|
||
clean: | ||
rm -rf $(OBJ_FILES) | ||
rm -rf $(EXEC_NAME) | ||
|
||
test: $(EXEC_NAME) | ||
./a.out | ||
|
||
$(EXEC_NAME): $(OBJ_FILES) | ||
$(CC) $(LD_FLAGS) $^ -o $(EXEC_NAME) | ||
|
||
$(OBJ_FILES): $(SRC_FILES) | ||
|
||
$(SRC_FILES): | ||
$(CC) -c $(CFLAGS) $@ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
#include <stdint.h> | ||
#include <stdio.h> | ||
#include <string.h> | ||
|
||
#define NAME paren_stk | ||
#define VALUE_TYPE char | ||
#include "fstack.h" | ||
|
||
void print_paren_stk(struct paren_stk *stk) | ||
{ | ||
if (stk->count > 0) { | ||
printf("%c", paren_stk_at(stk, 0)); | ||
} | ||
else { | ||
printf("(empty)"); | ||
} | ||
for (size_t i = 1; i < stk->count; i++) { | ||
printf(" <- %c", paren_stk_at(stk, (uint32_t)i)); | ||
} | ||
printf("\n"); | ||
} | ||
|
||
char matching_paren(char c) | ||
{ | ||
switch (c) { | ||
case '(': | ||
return ')'; | ||
case '{': | ||
return '}'; | ||
case '[': | ||
return ']'; | ||
case ')': | ||
return '('; | ||
case '}': | ||
return '{'; | ||
case ']': | ||
return '['; | ||
} | ||
return '\0'; | ||
} | ||
|
||
bool isValid(char *s) | ||
{ | ||
const size_t n = strlen(s); | ||
struct paren_stk *stk = paren_stk_create((uint32_t)n); | ||
|
||
bool retVal = true; | ||
|
||
for (size_t i = 0; i < n; i++) { | ||
switch (s[i]) { | ||
case '(': | ||
case '{': | ||
case '[': | ||
if (!paren_stk_is_full(stk)) { | ||
paren_stk_push(stk, matching_paren(s[i])); | ||
} | ||
else { | ||
assert(false); | ||
} | ||
break; | ||
case ')': | ||
case '}': | ||
case ']': | ||
retVal &= !paren_stk_is_empty(stk) && paren_stk_pop(stk) == s[i]; | ||
break; | ||
default: | ||
assert(false); | ||
break; | ||
} | ||
} | ||
retVal &= stk->count == 0; | ||
|
||
paren_stk_destroy(stk); | ||
|
||
return retVal; | ||
} | ||
|
||
#define print_and_assert(expr, expected) \ | ||
__extension__({ \ | ||
bool res = (expr); \ | ||
assert(res == (expected)); \ | ||
printf("%-17s = %s\n", #expr, res ? "true" : "false"); \ | ||
}) | ||
|
||
int main(void) | ||
{ | ||
(void)(print_paren_stk); | ||
|
||
print_and_assert(isValid("()"), true); | ||
print_and_assert(isValid("("), false); | ||
print_and_assert(isValid(")"), false); | ||
print_and_assert(isValid("(]"), false); | ||
print_and_assert(isValid("([]){}"), true); | ||
print_and_assert(isValid("([){}"), false); | ||
print_and_assert(isValid("{[][]}"), true); | ||
print_and_assert(isValid("{[[]}"), false); | ||
print_and_assert(isValid("{[(])}"), false); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters