-
Notifications
You must be signed in to change notification settings - Fork 12
/
unit.h
163 lines (126 loc) · 3.36 KB
/
unit.h
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#ifndef _UNIT_H
#define _UNIT_H 1
#include <postgres.h>
#include <utils/hsearch.h>
/* indices */
#define UNIT_m 0 /* meter */
#define UNIT_kg 1 /* kilogram */
#define UNIT_s 2 /* second */
#define UNIT_A 3 /* ampere */
#define UNIT_K 4 /* kelvin */
#define UNIT_mol 5 /* mole */
#define UNIT_cd 6 /* candela */
#define UNIT_B 7 /* byte */
#define N_UNITS 8
/* functions recognized in parser */
enum parser_function {
FUNCTION_SQRT,
FUNCTION_EXP,
FUNCTION_LN,
FUNCTION_LOG2,
FUNCTION_ASIN,
FUNCTION_TAN,
};
/* defined units */
#define UNIT_NAME_LENGTH 32
/* longest unit names (without prefixes) observed in definitions.units:
* specificheat_glass_silica (25 chars)
* hardtranslucentarkansas (23 chars)
* venezuelanbolivarfuerte */
#define MIN_PLURAL_LENGTH 3
/* minimum length of input unit to consider stripping a trailing plural 's'
* lbs secs
*/
#define DBL_DIG 15
#define TIME_MINUTE 60
#define TIME_HOUR (60 * TIME_MINUTE)
#define TIME_DAY (24 * TIME_HOUR)
#define TIME_YEAR (365 * TIME_DAY)
#define TIME_YEAR_NAME "commonyear"
extern const char *base_units[N_UNITS]; /* names of base units */
struct derived_unit_t {
char *name;
signed char units[N_UNITS];
};
extern const struct derived_unit_t si_derived_units[];
/* type def */
typedef struct Unit {
double value;
signed char units[N_UNITS];
} Unit;
typedef struct UnitShift {
Unit unit;
double shift;
} UnitShift;
/* hash table and regex interface */
extern HTAB *unit_names;
typedef struct unit_names_t {
char name[UNIT_NAME_LENGTH];
UnitShift unit_shift;
} unit_names_t;
typedef struct unit_dimensions_t {
char units[N_UNITS];
char name[UNIT_NAME_LENGTH];
} unit_dimensions_t;
/* parser interface */
int unit_parse (char *s, UnitShift *unit); /* in unit.y */
char *unit_cstring (Unit *unit);
/* static functions */
/* test if two Units have the same dimension */
static inline void
test_same_dimension (char *op, Unit *a, Unit *b)
{
if (memcmp(a->units, b->units, N_UNITS))
ereport(ERROR,
(errcode(ERRCODE_DATA_EXCEPTION),
errmsg("dimension mismatch in \"%s\" operation: \"%s\", \"%s\"",
op, unit_cstring(a), unit_cstring(b))));
}
static inline void
unit_add_internal (Unit *a, Unit *b, Unit *result)
{
test_same_dimension("+", a, b);
result->value = a->value + b->value;
memcpy(result->units, a->units, N_UNITS);
}
static inline void
unit_sub_internal (Unit *a, Unit *b, Unit *result)
{
test_same_dimension("-", a, b);
result->value = a->value - b->value;
memcpy(result->units, a->units, N_UNITS);
}
static inline void
unit_mult_internal (Unit *a, Unit *b, Unit *result)
{
int i;
result->value = a->value * b->value;
for (i = 0; i < N_UNITS; i++)
result->units[i] = a->units[i] + b->units[i];
}
static inline void
unit_div_internal (Unit *a, Unit *b, Unit *result)
{
int i;
if (b->value == 0)
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero-valued unit: \"%s\"",
unit_cstring(b))));
result->value = a->value / b->value;
for (i = 0; i < N_UNITS; i++)
result->units[i] = a->units[i] - b->units[i];
}
void
unit_sqrt_internal(Unit *a, Unit *result);
void
unit_exp_internal(Unit *a, Unit *result);
void
unit_ln_internal(Unit *a, Unit *result);
void
unit_log2_internal(Unit *a, Unit *result);
void
unit_asin_internal(Unit *a, Unit *result);
void
unit_tan_internal(Unit *a, Unit *result);
#endif /* _UNIT_H */