From 2a3bc0982b4069e3a768070f55b8cf46de970bb8 Mon Sep 17 00:00:00 2001 From: John Kerl Date: Wed, 11 Nov 2015 23:04:45 -0500 Subject: [PATCH] urandint --- c/mapping/lrec_evaluators.c | 43 +++++++++++++++++++++++++++++++++++++ c/mapping/mlr_val.h | 11 ++++++++++ c/todo.txt | 4 ++-- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/c/mapping/lrec_evaluators.c b/c/mapping/lrec_evaluators.c index ed1c804c9..c3e53b6e9 100644 --- a/c/mapping/lrec_evaluators.c +++ b/c/mapping/lrec_evaluators.c @@ -277,6 +277,47 @@ lrec_evaluator_t* lrec_evaluator_alloc_from_f_fff_func(mv_ternary_func_t* pfunc, return pevaluator; } +// ---------------------------------------------------------------- +typedef struct _lrec_evaluator_i_ii_state_t { + mv_binary_func_t* pfunc; + lrec_evaluator_t* parg1; + lrec_evaluator_t* parg2; +} lrec_evaluator_i_ii_state_t; + +mv_t lrec_evaluator_i_ii_func(lrec_t* prec, context_t* pctx, void* pvstate) { + lrec_evaluator_i_ii_state_t* pstate = pvstate; + mv_t val1 = pstate->parg1->pevaluator_func(prec, pctx, pstate->parg1->pvstate); + NULL_OR_ERROR_OUT(val1); + mt_get_int_nullable(&val1); + NULL_OUT(val1); + if (val1.type != MT_INT) + return MV_ERROR; + + mv_t val2 = pstate->parg2->pevaluator_func(prec, pctx, pstate->parg2->pvstate); + NULL_OR_ERROR_OUT(val2); + mt_get_int_nullable(&val2); + NULL_OUT(val2); + if (val2.type != MT_INT) + return MV_ERROR; + + return pstate->pfunc(&val1, &val2); +} + +lrec_evaluator_t* lrec_evaluator_alloc_from_i_ii_func(mv_binary_func_t* pfunc, + lrec_evaluator_t* parg1, lrec_evaluator_t* parg2) +{ + lrec_evaluator_i_ii_state_t* pstate = mlr_malloc_or_die(sizeof(lrec_evaluator_i_ii_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_i_ii_func; + + return pevaluator; +} + // ---------------------------------------------------------------- typedef struct _lrec_evaluator_i_iii_state_t { mv_ternary_func_t* pfunc; @@ -981,6 +1022,7 @@ static function_lookup_t FUNCTION_LOOKUP_TABLE[] = { { FUNC_CLASS_MATH, "tan", 1 , "Trigonometric tangent."}, { FUNC_CLASS_MATH, "tanh", 1 , "Hyperbolic tangent."}, { FUNC_CLASS_MATH, "urand", 0 , "Floating-point numbers on the unit interval. Int-valued example: '$n=floor(20+urand()*11)'." }, + { FUNC_CLASS_MATH, "urandint", 2 , "Integer uniformly distributed between inclusive integer endpoints." }, { FUNC_CLASS_MATH, "+", 2 , "Addition."}, { FUNC_CLASS_MATH, "-", 1 , "Unary minus."}, @@ -1233,6 +1275,7 @@ lrec_evaluator_t* lrec_evaluator_alloc_from_binary_func_name(char* fnnm, } else if (streq(fnnm, "min")) { return lrec_evaluator_alloc_from_f_ff_nullable_func(f_ff_min_func, parg1, parg2); } else if (streq(fnnm, "roundm")) { return lrec_evaluator_alloc_from_f_ff_nullable_func(f_ff_roundm_func, parg1, parg2); } else if (streq(fnnm, "fmtnum")) { return lrec_evaluator_alloc_from_s_xs_func(s_xs_fmtnum_func, parg1, parg2); + } else if (streq(fnnm, "urandint")) { return lrec_evaluator_alloc_from_i_ii_func(i_ii_urandint_func, parg1, parg2); } else { return NULL; } } diff --git a/c/mapping/mlr_val.h b/c/mapping/mlr_val.h index ef8ba5aae..31fc2d990 100644 --- a/c/mapping/mlr_val.h +++ b/c/mapping/mlr_val.h @@ -214,6 +214,17 @@ static inline mv_t f_fff_logifit_func(mv_t* pval1, mv_t* pval2, mv_t* pval3) { return rv; } +static inline mv_t i_ii_urandint_func(mv_t* pval1, mv_t* pval2) { + long long lo = pval1->u.intv; + long long hi = pval2->u.intv + 1; + if (hi <= lo) { + return (mv_t) {.type = MT_ERROR, .u.intv = 0LL}; + } else { + long long u = lo + (hi - lo) * get_mtrand_double(); + return (mv_t) {.type = MT_INT, .u.intv = u}; + } +} + mv_t i_iii_modadd_func(mv_t* pval1, mv_t* pval2, mv_t* pval3); mv_t i_iii_modsub_func(mv_t* pval1, mv_t* pval2, mv_t* pval3); mv_t i_iii_modmul_func(mv_t* pval1, mv_t* pval2, mv_t* pval3); diff --git a/c/todo.txt b/c/todo.txt index 2d325509c..6acd22966 100644 --- a/c/todo.txt +++ b/c/todo.txt @@ -25,14 +25,14 @@ TOP OF LIST * full-int64 I/O & math: o now is a good time to look at bitops. first get the precedence right. o int-int math -> int result: disposition matrices & fi_fifi infra. - o make int-to-int-enabled: abs ceil floor round roundm max min + o make int-to-int-enabled: abs ceil floor round roundm max min sgn ! make int-to-int enabled ... but beware, we are introducing overflow for bignums where it wasn't before: doc needs to be clear re '$z=float($x)+float($y)' :^/ + - u- * % // note that // should be floor division for floats, too. http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html. o int-range urand - o sgn function + o sgn function needs UT cases * verb bar: - out-of-place bar -- preserving count as separate column?