Skip to content

Commit b4f4673

Browse files
committed
Implement functions in parser: sqrt exp ln log2 asin tan
1 parent 80c7f28 commit b4f4673

File tree

6 files changed

+976
-652
lines changed

6 files changed

+976
-652
lines changed

unit.c

Lines changed: 111 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -907,21 +907,16 @@ unit_pow(PG_FUNCTION_ARGS)
907907
PG_RETURN_POINTER(result);
908908
}
909909

910-
PG_FUNCTION_INFO_V1(unit_sqrt);
911-
912-
Datum
913-
unit_sqrt(PG_FUNCTION_ARGS)
910+
void
911+
unit_sqrt_internal(Unit *a, Unit *result)
914912
{
915-
Unit *a = (Unit *) PG_GETARG_POINTER(0);
916-
Unit *result;
917913
int i;
918914

919915
/* compute root of value */
920916
if (a->value < 0)
921917
ereport(ERROR,
922918
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
923919
errmsg("cannot take square root of a negative-valued unit")));
924-
result = (Unit *) palloc(sizeof(Unit));
925920
result->value = sqrt(a->value);
926921

927922
/* compute root of base units */
@@ -934,7 +929,17 @@ unit_sqrt(PG_FUNCTION_ARGS)
934929
base_units[i])));
935930
result->units[i] = a->units[i] >> 1;
936931
}
932+
}
933+
934+
PG_FUNCTION_INFO_V1(unit_sqrt);
935+
936+
Datum
937+
unit_sqrt(PG_FUNCTION_ARGS)
938+
{
939+
Unit *a = (Unit *) PG_GETARG_POINTER(0);
940+
Unit *result = (Unit *) palloc(sizeof(Unit));
937941

942+
unit_sqrt_internal(a, result);
938943
PG_RETURN_POINTER(result);
939944
}
940945

@@ -965,6 +970,105 @@ unit_cbrt(PG_FUNCTION_ARGS)
965970
PG_RETURN_POINTER(result);
966971
}
967972

973+
void
974+
unit_exp_internal(Unit *a, Unit *result)
975+
{
976+
int i;
977+
978+
/* compute exp of value */
979+
result->value = exp(a->value);
980+
981+
/* check dimension */
982+
for (i = 0; i < N_UNITS; i++)
983+
{
984+
if (a->units[i] != 0)
985+
ereport(ERROR,
986+
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
987+
errmsg("cannot take base-e exponent of value that is not dimension-less")));
988+
result->units[i] = 0;
989+
}
990+
}
991+
992+
void
993+
unit_ln_internal(Unit *a, Unit *result)
994+
{
995+
int i;
996+
997+
/* compute ln of value */
998+
result->value = log(a->value);
999+
1000+
/* check dimension */
1001+
for (i = 0; i < N_UNITS; i++)
1002+
{
1003+
if (a->units[i] != 0)
1004+
ereport(ERROR,
1005+
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1006+
errmsg("cannot take ln of value that is not dimension-less")));
1007+
result->units[i] = 0;
1008+
}
1009+
}
1010+
1011+
void
1012+
unit_log2_internal(Unit *a, Unit *result)
1013+
{
1014+
int i;
1015+
1016+
/* compute log2 of value */
1017+
result->value = log2(a->value);
1018+
1019+
/* check dimension */
1020+
for (i = 0; i < N_UNITS; i++)
1021+
{
1022+
if (a->units[i] != 0)
1023+
ereport(ERROR,
1024+
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1025+
errmsg("cannot take log2 of value that is not dimension-less")));
1026+
result->units[i] = 0;
1027+
}
1028+
}
1029+
1030+
void
1031+
unit_asin_internal(Unit *a, Unit *result)
1032+
{
1033+
int i;
1034+
1035+
/* compute asin of value */
1036+
if (a->value < -1 || a->value > 1)
1037+
ereport(ERROR,
1038+
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1039+
errmsg("cannot asin of values outside the range -1 to 1")));
1040+
result->value = asin(a->value);
1041+
1042+
/* check dimension */
1043+
for (i = 0; i < N_UNITS; i++)
1044+
{
1045+
if (a->units[i] != 0)
1046+
ereport(ERROR,
1047+
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1048+
errmsg("cannot take asin of value that is not dimension-less")));
1049+
result->units[i] = 0;
1050+
}
1051+
}
1052+
1053+
void
1054+
unit_tan_internal(Unit *a, Unit *result)
1055+
{
1056+
int i;
1057+
1058+
/* compute tan of value */
1059+
result->value = tan(a->value);
1060+
1061+
/* check dimension */
1062+
for (i = 0; i < N_UNITS; i++)
1063+
{
1064+
if (a->units[i] != 0)
1065+
ereport(ERROR,
1066+
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1067+
errmsg("cannot take tan of value that is not dimension-less")));
1068+
result->units[i] = 0;
1069+
}
1070+
}
1071+
9681072
/* obsolete version of unit_at_text used in v1..3 */
9691073
/* needs search_path = @extschema@ due to use of unit_parse() */
9701074
PG_FUNCTION_INFO_V1(unit_at);

unit.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@
1616

1717
#define N_UNITS 8
1818

19+
/* functions recognized in parser */
20+
enum parser_function {
21+
FUNCTION_SQRT,
22+
FUNCTION_EXP,
23+
FUNCTION_LN,
24+
FUNCTION_LOG2,
25+
FUNCTION_ASIN,
26+
FUNCTION_TAN,
27+
};
28+
1929
/* defined units */
2030

2131
#define UNIT_NAME_LENGTH 32
@@ -132,4 +142,22 @@ unit_div_internal (Unit *a, Unit *b, Unit *result)
132142
result->units[i] = a->units[i] - b->units[i];
133143
}
134144

145+
void
146+
unit_sqrt_internal(Unit *a, Unit *result);
147+
148+
void
149+
unit_exp_internal(Unit *a, Unit *result);
150+
151+
void
152+
unit_ln_internal(Unit *a, Unit *result);
153+
154+
void
155+
unit_log2_internal(Unit *a, Unit *result);
156+
157+
void
158+
unit_asin_internal(Unit *a, Unit *result);
159+
160+
void
161+
unit_tan_internal(Unit *a, Unit *result);
162+
135163
#endif /* _UNIT_H */

unitparse.l

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,36 @@ SUPER_9 \xe2\x81\xb9
8484
return DOUBLE;
8585
}
8686
87+
sqrt {
88+
yyunitlval.FUNCTION = FUNCTION_SQRT;
89+
return FUNCTION;
90+
}
91+
92+
exp {
93+
yyunitlval.FUNCTION = FUNCTION_EXP;
94+
return FUNCTION;
95+
}
96+
97+
ln {
98+
yyunitlval.FUNCTION = FUNCTION_LN;
99+
return FUNCTION;
100+
}
101+
102+
log2 {
103+
yyunitlval.FUNCTION = FUNCTION_LOG2;
104+
return FUNCTION;
105+
}
106+
107+
asin {
108+
yyunitlval.FUNCTION = FUNCTION_ASIN;
109+
return FUNCTION;
110+
}
111+
112+
tan {
113+
yyunitlval.FUNCTION = FUNCTION_TAN;
114+
return FUNCTION;
115+
}
116+
87117
{TIME_R} { /* hh:mm:ss[.sss] */
88118
char *colon;
89119
yyunitlval.DOUBLE = TIME_HOUR * atoi(yytext); /* hh */

0 commit comments

Comments
 (0)