diff options
author | Arnold D. Robbins <arnold@skeeve.com> | 2014-07-10 16:32:44 -0700 |
---|---|---|
committer | Arnold D. Robbins <arnold@skeeve.com> | 2014-07-10 16:32:44 -0700 |
commit | df2eaea6a92c7d89d604d0a4e885d064678ce3ed (patch) | |
tree | 127610b11382d876d1be2ebce2f770d60147788b /builtin.c | |
parent | 21606db0d06b91332b1514f6662f7bc6d414e54e (diff) | |
download | egawk-df2eaea6a92c7d89d604d0a4e885d064678ce3ed.tar.gz egawk-df2eaea6a92c7d89d604d0a4e885d064678ce3ed.tar.bz2 egawk-df2eaea6a92c7d89d604d0a4e885d064678ce3ed.zip |
Add div() function for integer division & remainder.
Diffstat (limited to 'builtin.c')
-rw-r--r-- | builtin.c | 66 |
1 files changed, 66 insertions, 0 deletions
@@ -3612,6 +3612,72 @@ do_bindtextdomain(int nargs) return make_string(the_result, strlen(the_result)); } +/* do_div --- do integer division, return quotient and remainder in dest array */ + +/* + * We define the semantics as: + * numerator = int(numerator) + * denominator = int(denonmator) + * quotient = int(numerator / denomator) + * remainder = int(numerator % denomator) + */ + +NODE * +do_div(int nargs) +{ + NODE *numerator, *denominator, *result; + double num, denom, quotient, remainder; + NODE *sub, **lhs; + + result = POP_PARAM(); + if (result->type != Node_var_array) + fatal(_("div: third argument is not an array")); + assoc_clear(result); + + denominator = POP_SCALAR(); + numerator = POP_SCALAR(); + + if (do_lint) { + if ((numerator->flags & (NUMCUR|NUMBER)) == 0) + lintwarn(_("div: received non-numeric first argument")); + if ((denominator->flags & (NUMCUR|NUMBER)) == 0) + lintwarn(_("div: received non-numeric second argument")); + } + + (void) force_number(numerator); + (void) force_number(denominator); + num = double_to_int(get_number_d(numerator)); + denom = double_to_int(get_number_d(denominator)); + + if (denom == 0.0) + fatal(_("div: division by zero attempted")); + + quotient = double_to_int(num / denom); + /* + * FIXME: This code is duplicated, factor it out to a + * separate function. + */ +#ifdef HAVE_FMOD + remainder = fmod(num, denom); +#else /* ! HAVE_FMOD */ + (void) modf(num / denom, & remainder); + remainder = num - remainder * denom; +#endif /* ! HAVE_FMOD */ + remainder = double_to_int(remainder); + + sub = make_string("quotient", 8); + lhs = assoc_lookup(result, sub); + unref(*lhs); + *lhs = make_number((AWKNUM) quotient); + + sub = make_string("remainder", 9); + lhs = assoc_lookup(result, sub); + unref(*lhs); + *lhs = make_number((AWKNUM) remainder); + + return make_number((AWKNUM) 0.0); +} + /* mbc_byte_count --- return number of bytes for corresponding numchars multibyte characters */ |