mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-22 07:30:43 +00:00
nullable min/max
This commit is contained in:
parent
94697cdb31
commit
fbf92524bb
7 changed files with 138 additions and 6 deletions
|
|
@ -167,6 +167,38 @@ lrec_evaluator_t* lrec_evaluator_alloc_from_f_ff_func(mv_binary_func_t* pfunc,
|
|||
return pevaluator;
|
||||
}
|
||||
|
||||
mv_t lrec_evaluator_f_ff_nullable_func(lrec_t* prec, context_t* pctx, void* pvstate) {
|
||||
lrec_evaluator_f_ff_state_t* pstate = pvstate;
|
||||
mv_t val1 = pstate->parg1->pevaluator_func(prec, pctx, pstate->parg1->pvstate);
|
||||
ERROR_OUT(val1);
|
||||
mt_get_double_nullable(&val1);
|
||||
if (val1.type != MT_DOUBLE && val1.type != MT_NULL)
|
||||
return MV_ERROR;
|
||||
|
||||
mv_t val2 = pstate->parg2->pevaluator_func(prec, pctx, pstate->parg2->pvstate);
|
||||
ERROR_OUT(val2);
|
||||
mt_get_double_nullable(&val2);
|
||||
if (val2.type != MT_DOUBLE && val2.type != MT_NULL)
|
||||
return MV_ERROR;
|
||||
|
||||
return pstate->pfunc(&val1, &val2);
|
||||
}
|
||||
|
||||
lrec_evaluator_t* lrec_evaluator_alloc_from_f_ff_nullable_func(mv_binary_func_t* pfunc,
|
||||
lrec_evaluator_t* parg1, lrec_evaluator_t* parg2)
|
||||
{
|
||||
lrec_evaluator_f_ff_state_t* pstate = mlr_malloc_or_die(sizeof(lrec_evaluator_f_ff_state_t));
|
||||
pstate->pfunc = pfunc;
|
||||
pstate->parg1 = parg1;
|
||||
pstate->parg2 = parg2;
|
||||
|
||||
lrec_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(lrec_evaluator_t));
|
||||
pevaluator->pvstate = pstate;
|
||||
pevaluator->pevaluator_func = lrec_evaluator_f_ff_nullable_func;
|
||||
|
||||
return pevaluator;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef struct _lrec_evaluator_s_s_state_t {
|
||||
mv_unary_func_t* pfunc;
|
||||
|
|
@ -889,8 +921,8 @@ lrec_evaluator_t* lrec_evaluator_alloc_from_binary_func_name(char* fnnm,
|
|||
} else if (streq(fnnm, "<")) { return lrec_evaluator_alloc_from_b_xx_func(lt_op_func, parg1, parg2);
|
||||
} else if (streq(fnnm, "<=")) { return lrec_evaluator_alloc_from_b_xx_func(le_op_func, parg1, parg2);
|
||||
} else if (streq(fnnm, ".")) { return lrec_evaluator_alloc_from_s_ss_func(s_ss_dot_func, parg1, parg2);
|
||||
} else if (streq(fnnm, "max")) { return lrec_evaluator_alloc_from_f_ff_func(f_ff_max_func, parg1, parg2);
|
||||
} else if (streq(fnnm, "min")) { return lrec_evaluator_alloc_from_f_ff_func(f_ff_min_func, parg1, parg2);
|
||||
} else if (streq(fnnm, "max")) { return lrec_evaluator_alloc_from_f_ff_nullable_func(f_ff_max_func, parg1, parg2);
|
||||
} else if (streq(fnnm, "min")) { return lrec_evaluator_alloc_from_f_ff_nullable_func(f_ff_min_func, parg1, parg2);
|
||||
} else if (streq(fnnm, "pow")) { return lrec_evaluator_alloc_from_f_ff_func(f_ff_pow_func, parg1, parg2);
|
||||
} else if (streq(fnnm, "+")) { return lrec_evaluator_alloc_from_f_ff_func(f_ff_plus_func, parg1, parg2);
|
||||
} else if (streq(fnnm, "-")) { return lrec_evaluator_alloc_from_f_ff_func(f_ff_minus_func, parg1, parg2);
|
||||
|
|
|
|||
|
|
@ -115,6 +115,37 @@ void mt_get_double_strict(mv_t* pval) {
|
|||
// xxx else panic
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// xxx merge with mt_get_double_string w/ a nullable parameter
|
||||
void mt_get_double_nullable(mv_t* pval) {
|
||||
if (pval->type == MT_NULL)
|
||||
return;
|
||||
if (pval->type == MT_ERROR)
|
||||
return;
|
||||
if (pval->type == MT_DOUBLE)
|
||||
return;
|
||||
if (pval->type == MT_STRING) {
|
||||
double dblv;
|
||||
if (*pval->u.strv == '\0') {
|
||||
pval->type = MT_NULL;
|
||||
pval->u.intv = 0;
|
||||
} else if (!mlr_try_double_from_string(pval->u.strv, &dblv)) {
|
||||
pval->type = MT_ERROR;
|
||||
pval->u.intv = 0;
|
||||
} else {
|
||||
pval->type = MT_DOUBLE;
|
||||
pval->u.dblv = dblv;
|
||||
}
|
||||
} else if (pval->type == MT_INT) {
|
||||
pval ->type = MT_DOUBLE;
|
||||
pval->u.dblv = (double)pval->u.intv;
|
||||
} else if (pval->type == MT_BOOL) {
|
||||
pval->type = MT_ERROR;
|
||||
pval->u.intv = 0;
|
||||
}
|
||||
// xxx else panic
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
mv_t s_ss_dot_func(mv_t* pval1, mv_t* pval2) {
|
||||
int len1 = strlen(pval1->u.strv);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,11 @@ extern mv_t MV_ERROR;
|
|||
return MV_NULL; \
|
||||
}
|
||||
|
||||
#define ERROR_OUT(val) { \
|
||||
if ((val).type == MT_ERROR) \
|
||||
return MV_ERROR; \
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
char* mt_describe_type(int type);
|
||||
|
||||
|
|
@ -53,6 +58,7 @@ char* mt_describe_val(mv_t val);
|
|||
// xxx explain why one is void & the other isn't
|
||||
int mt_get_boolean_strict(mv_t* pval);
|
||||
void mt_get_double_strict(mv_t* pval);
|
||||
void mt_get_double_nullable(mv_t* pval);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
typedef mv_t mv_zary_func_t();
|
||||
|
|
@ -137,12 +143,24 @@ static inline mv_t f_ff_divide_func(mv_t* pval1, mv_t* pval2) {
|
|||
return rv;
|
||||
}
|
||||
static inline mv_t f_ff_max_func(mv_t* pval1, mv_t* pval2) {
|
||||
mv_t rv = {.type = MT_DOUBLE, .u.dblv = fmax(pval1->u.dblv, pval2->u.dblv)}; // xxx impl: null loses ...
|
||||
return rv;
|
||||
if (pval1->type == MT_NULL) {
|
||||
return *pval2;
|
||||
} else if (pval2->type == MT_NULL) {
|
||||
return *pval1;
|
||||
} else {
|
||||
mv_t rv = {.type = MT_DOUBLE, .u.dblv = fmax(pval1->u.dblv, pval2->u.dblv)};
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
static inline mv_t f_ff_min_func(mv_t* pval1, mv_t* pval2) {
|
||||
mv_t rv = {.type = MT_DOUBLE, .u.dblv = fmin(pval1->u.dblv, pval2->u.dblv)}; // xxx impl: null loses ...
|
||||
return rv;
|
||||
if (pval1->type == MT_NULL) {
|
||||
return *pval2;
|
||||
} else if (pval2->type == MT_NULL) {
|
||||
return *pval1;
|
||||
} else {
|
||||
mv_t rv = {.type = MT_DOUBLE, .u.dblv = fmin(pval1->u.dblv, pval2->u.dblv)};
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
static inline mv_t f_ff_pow_func(mv_t* pval1, mv_t* pval2) {
|
||||
mv_t rv = {.type = MT_DOUBLE, .u.dblv = pow(pval1->u.dblv, pval2->u.dblv)};
|
||||
|
|
|
|||
|
|
@ -1517,6 +1517,26 @@ gmt,sec
|
|||
2017-07-14T02:40:00Z,1500000000
|
||||
2033-05-18T03:33:20Z,2000000000
|
||||
|
||||
./test/../mlr put $z=min($x, $y) ./test/input/minmax.dkvp
|
||||
x=1,y=2,z=1.000000
|
||||
x=1,y=,z=1.000000
|
||||
x=,y=,z=
|
||||
x=,y=2,z=2.000000
|
||||
x=3,y=2,z=2.000000
|
||||
x=3,y=,z=3.000000
|
||||
x=,y=,z=
|
||||
x=,y=2,z=2.000000
|
||||
|
||||
./test/../mlr put $z=max($x, $y) ./test/input/minmax.dkvp
|
||||
x=1,y=2,z=2.000000
|
||||
x=1,y=,z=1.000000
|
||||
x=,y=,z=
|
||||
x=,y=2,z=2.000000
|
||||
x=3,y=2,z=3.000000
|
||||
x=3,y=,z=3.000000
|
||||
x=,y=,z=
|
||||
x=,y=2,z=2.000000
|
||||
|
||||
|
||||
================================================================
|
||||
CHAINING
|
||||
|
|
|
|||
8
c/test/input/minmax.dkvp
Normal file
8
c/test/input/minmax.dkvp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
x=1,y=2
|
||||
x=1,y=
|
||||
x=,y=
|
||||
x=,y=2
|
||||
x=3,y=2
|
||||
x=3,y=
|
||||
x=,y=
|
||||
x=,y=2
|
||||
|
|
@ -1517,6 +1517,26 @@ gmt,sec
|
|||
2017-07-14T02:40:00Z,1500000000
|
||||
2033-05-18T03:33:20Z,2000000000
|
||||
|
||||
./test/../mlr put $z=min($x, $y) ./test/input/minmax.dkvp
|
||||
x=1,y=2,z=1.000000
|
||||
x=1,y=,z=1.000000
|
||||
x=,y=,z=
|
||||
x=,y=2,z=2.000000
|
||||
x=3,y=2,z=2.000000
|
||||
x=3,y=,z=3.000000
|
||||
x=,y=,z=
|
||||
x=,y=2,z=2.000000
|
||||
|
||||
./test/../mlr put $z=max($x, $y) ./test/input/minmax.dkvp
|
||||
x=1,y=2,z=2.000000
|
||||
x=1,y=,z=1.000000
|
||||
x=,y=,z=
|
||||
x=,y=2,z=2.000000
|
||||
x=3,y=2,z=3.000000
|
||||
x=3,y=,z=3.000000
|
||||
x=,y=,z=
|
||||
x=,y=2,z=2.000000
|
||||
|
||||
|
||||
================================================================
|
||||
CHAINING
|
||||
|
|
|
|||
|
|
@ -269,6 +269,9 @@ run_command $mlr filter -v '$x<$a*$b+-$c' /dev/null
|
|||
run_command $mlr --csv put '$gmt=sec2gmt($sec)' $indir/sec2gmt
|
||||
run_command $mlr --csv put '$sec=gmt2sec($gmt)' $indir/gmt2sec
|
||||
|
||||
run_command $mlr put '$z=min($x, $y)' $indir/minmax.dkvp
|
||||
run_command $mlr put '$z=max($x, $y)' $indir/minmax.dkvp
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
announce CHAINING
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue