Mercurial > octave
changeset 30786:ba07f81c8480
maint: Merge stable to default.
author | Markus Mützel <markus.muetzel@gmx.de> |
---|---|
date | Sun, 27 Feb 2022 13:36:58 +0100 |
parents | d37b9645fae7 (current diff) 290e7e3f859f (diff) |
children | 76398dfe2d55 |
files | |
diffstat | 1 files changed, 78 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- a/scripts/general/idivide.m Sat Feb 26 13:03:02 2022 +0100 +++ b/scripts/general/idivide.m Sun Feb 27 13:36:58 2022 +0100 @@ -84,33 +84,76 @@ op = tolower (op); endif - if (isfloat (x)) - if (isinteger (y)) - typ = class (y); - else - error ("idivide: at least one input (X or Y) must be an integer type"); - endif - elseif (isfloat (y)) - if (isinteger (x)) - typ = class (x); - else - error ("idivide: at least one input (X or Y) must be an integer type"); - endif - else - typ = class (x); - if (! strcmp (typ, class (y))) - error ("idivide: integer type of X (%s) must match integer type of Y (%s)", typ, class (y)); - endif + if (! isinteger (x) && ! isinteger (y)) + error ("idivide: at least one input (X or Y) must be an integer type"); + elseif (isinteger (x) && isinteger (y) && ! strcmp (class (x), class (y))) + error ("idivide: integer type of X (%s) must match integer type of Y (%s)", + class (x), class (y)); endif + z = x ./ y; if (strcmp (op, "fix")) - z = cast (fix (double (x) ./ double (y)), typ); + ## The following is an optimized version of `z -= (z .* y > x) .* sign (y)`. + if (isscalar (y)) + if (y > 0) + z -= (z * y > x); + else + z += (z * y > x); + endif + else + y_sel = (y > 0); + if (isscalar (x)) + z(y_sel) -= (z(y_sel) .* y(y_sel) > x); + y_sel = ! y_sel; + z(y_sel) += (z(y_sel) .* y(y_sel) > x); + else + z(y_sel) -= (z(y_sel) .* y(y_sel) > x(y_sel)); + y_sel = ! y_sel; + z(y_sel) += (z(y_sel) .* y(y_sel) > x(y_sel)); + endif + endif elseif (strcmp (op, "round")) - z = x ./ y; + return; elseif (strcmp (op, "floor")) - z = cast (floor (double (x) ./ double (y)), typ); + ## The following is an optimized version of `z -= (z .* abs (y) > sign (y) .* x)`. + if (isscalar (y)) + if (y > 0) + z -= (z * y > x); + else + z -= (z * y < x); + endif + else + y_sel = (y > 0); + if (isscalar (x)) + z(y_sel) -= (z(y_sel) .* y(y_sel) > x); + y_sel = ! y_sel; + z(y_sel) -= (z(y_sel) .* y(y_sel) < x); + else + z(y_sel) -= (z(y_sel) .* y(y_sel) > x(y_sel)); + y_sel = ! y_sel; + z(y_sel) -= (z(y_sel) .* y(y_sel) < x(y_sel)); + endif + endif elseif (strcmp (op, "ceil")) - z = cast (ceil (double (x) ./ double (y)), typ); + ## The following is an optimized version of `z += (z .* abs (y) < sign (y) .* x)`. + if (isscalar (y)) + if (y > 0) + z += (z * y < x); + else + z += (z * y > x); + endif + else + y_sel = (y > 0); + if (isscalar (x)) + z(y_sel) += (z(y_sel) .* y(y_sel) < x); + y_sel = ! y_sel; + z(y_sel) += (z(y_sel) .* y(y_sel) > x); + else + z(y_sel) += (z(y_sel) .* y(y_sel) < x(y_sel)); + y_sel = ! y_sel; + z(y_sel) += (z(y_sel) .* y(y_sel) > x(y_sel)); + endif + endif else error ('idivide: unrecognized rounding type "%s"', op); endif @@ -139,6 +182,20 @@ %!assert (idivide (a, bf, "ceil"), int8 ([0, 1])) %!assert (idivide (a, bf, "round"), int8 ([-1, 1])) +%!shared c, d +%! c = int64 (4e16); +%! d = int64 ([-2e8, 2e8]); + +%!assert <*61319> (idivide (c, d + int64 (1)), d + int64 ([-1, -1])) +%!assert <*61319> (idivide (c, d + int64 (1), "floor"), d + int64 ([-2, -1])) +%!assert <*61319> (idivide (c, d + int64 (1), "ceil"), d + int64 ([-1, 0])) +%!assert <*61319> (idivide (c, d + int64 (1), "round"), d + int64 ([-1, -1])) + +%!assert <*61319> (idivide (c + int64 (1), d), d) +%!assert <*61319> (idivide (c + int64 (1), d, "floor"), d + int64 ([-1, 0])) +%!assert <*61319> (idivide (c + int64 (1), d, "ceil"), d + int64 ([0, 1])) +%!assert <*61319> (idivide (c + int64 (1), d, "round"), d) + ## Test input validation %!error idivide (uint8 (1)) %!error idivide (uint8 (1), 2, 3)