-
Notifications
You must be signed in to change notification settings - Fork 0
/
modemath.c
111 lines (104 loc) · 2.62 KB
/
modemath.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "modemath.h"
#include <string.h>
#include <math.h>
#include <bsd/stdlib.h>
#define MODE_INDEX_FOUND 4
#define MODE_INDEX_NOT_FOUND 5
int indexOf(ModeData data[static 1], double value, size_t idx[static 1])
{
for (size_t i = 0; i < data->size; i++)
{
if (fabs(data->values[i] - value) <= __DBL_EPSILON__)
{
*idx = i;
return MODE_INDEX_FOUND;
}
}
return MODE_INDEX_NOT_FOUND;
}
int computeMode(ModeData *data, double *result, int *hasResult)
{
ModeData summaryValues;
ModeData summaryOccurrences;
int status = MODE_OK;
if ((status = modeDataInit(&summaryValues)) != MODE_OK)
{
return status;
}
if ((status = modeDataInit(&summaryOccurrences)) != MODE_OK)
{
modeDataFinish(&summaryValues);
return status;
}
*hasResult = 0;
for (size_t i = 0, idx; i < data->size; i++)
{
// TODO: improve performance, see #1
if (indexOf(&summaryValues, data->values[i], &idx) == MODE_INDEX_FOUND)
{
summaryOccurrences.values[idx]++;
}
else
{
if ((status = modeAddValue(&summaryValues, data->values[i])) != MODE_OK)
{
goto stop;
}
if ((status = modeAddValue(&summaryOccurrences, 1)) != MODE_OK)
{
goto stop;
}
}
}
size_t mode_occurrences;
double mode_value;
for (size_t i = 0; i < summaryOccurrences.size; i++)
{
// XXX is this the right way?
if (!i || summaryOccurrences.values[i] > mode_occurrences)
{
mode_occurrences = summaryOccurrences.values[i];
mode_value = summaryValues.values[i];
}
}
*result = mode_value;
*hasResult = 1;
stop:
modeDataFinish(&summaryValues);
modeDataFinish(&summaryOccurrences);
return status;
}
int modeDataInit(ModeData *data)
{
memset(data, 0, sizeof(ModeData));
return MODE_OK;
}
void modeDataFinish(ModeData *data)
{
free(data->values);
memset(data, 0, sizeof(ModeData));
}
static int ensureCapacity(ModeData *data)
{
if (data->size > data->capacity)
{
data->capacity = data->size * 2;
data->values = (double *)reallocf(data->values, data->capacity * sizeof(double));
if (!data->values)
{
return MODE_ERR;
}
}
return MODE_OK;
}
int modeAddValue(ModeData *data, double value)
{
data->size++;
int result = ensureCapacity(data);
if (result != MODE_OK)
{
return result;
}
data->values[data->size - 1] = value;
return result;
}