## Copyright (C) 2026 Andreas Bertsatos <abertsatos@biol.uoa.gr>
##
## This file is part of the datatypes package for GNU Octave.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 3 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, see <http://www.gnu.org/licenses/>.

################################################################################
##                 ** Create and convert 'duration' type **                   ##
################################################################################
##                             Available Methods                              ##
##                                                                            ##
## 'duration'         'dispstrings'      'cellstr'          'char'            ##
## 'datevec'          'datenum'          'hms'              'years'           ##
## 'days'                                                                     ##
## 'hours'            'minutes'          'seconds'          'milliseconds'    ##
##                                                                            ##
################################################################################

%!assert_equal (isscalar (duration ()), true)
%!assert_equal (isempty (duration ()), false)
%!assert_equal (class (duration), 'duration')
%!assert_equal (dispstrings (duration ()), {'00:00:00'})
%!assert_equal (size (duration (zeros (4, 3))), [4, 1])
## size with no dimension named folds the trailing dimensions into the last
## output when fewer outputs are asked for than the array has dimensions, and
## pads with ones when more are asked for, as core Octave and MATLAB both do.
%!test
%! A = duration (ones (2, 2, 2), 0, 0);
%! [r, c] = size (A);
%! assert_equal ([r, c], [2, 4]);
%!test
%! A = duration (ones (2, 2), 0, 0);
%! [a, b, c, d] = size (A);
%! assert_equal ([a, b, c, d], [2, 2, 1, 1]);
%!assert_equal (isempty (duration (ones (0, 3))), true)
%!assert_equal (seconds (duration ([0, 0, 15])), 15)
%!assert_equal (minutes (duration ([0, 50, 30])), 50.5)
%!assert_equal (hours (duration ([1, 0, 3600; 5, 60, 0])), [2; 6])
%!assert_equal (seconds (duration ('30:15', 'InputFormat', 'mm:ss')), 1815)
%!assert_equal (hours (duration ({'01:00', '02:30'}, 'InputFormat', 'hh:mm')), [1, 2.5])
%!assert_equal (minutes (duration ({'01:00:30'}, 'InputFormat', 'hh:mm:ss')), 60.5)
%!assert_equal (minutes (duration ({'01:00:45'}, 'InputFormat', 'hh:mm:ss')), 60.75)
%!assert_equal (days (duration ({'24:00:00'}, 'InputFormat', 'hh:mm:ss')), 1)
%!assert_equal (days (duration ({'1:12:00:00'}, 'InputFormat', 'dd:hh:mm:ss')), 1.5)
%!assert_equal (seconds (duration (0, 0, 15)), 15)
%!assert_equal (seconds (duration (0, zeros (4), 15)), ones (4) * 15)
%!assert_equal (minutes (duration (0, 50, 30)), 50.5)
%!assert_equal (minutes (duration (0, 40:50, 30)), [40:50] + 0.5)
%!assert_equal (seconds (duration (0, 0, 0, 15)), 0.015)
%!assert_equal (size (duration (ones (2, 4, 3), 0, 0)), [2, 4, 3])
%!assert_equal (size (duration (0, ones (2, 3, 4), 0)), [2, 3, 4])
%!assert_equal (size (duration (zeros (4), zeros (4), 0, 0)), [4, 4])
%!assert_equal (size (duration (zeros (4), 0, 0, zeros (4))), [4, 4])
%!error<duration: 'Format' must be a character vector or a string scalar.> ...
%! duration (0, 0, 0, 'Format', 5)
%!error<duration: 'Format' must be a character vector or a string scalar.> ...
%! duration (0, 0, 0, 'Format', {'mm:ss'})
%!error<duration: 'Format' must be a character vector or a string scalar.> ...
%! duration (0, 0, 0, 'Format', string ({'mm:ss', 'hh:mm:ss'}))
%!error<duration: invalid display format.> duration (0, 0, 0, 'Format', 't')
%!error<duration: invalid display format.> duration (0, 0, 0, 'Format', 'd.h.S')
%!error<duration: invalid display format.> duration (0, 0, 0, 'Format', 's.SS')
%!error<duration: 'hh:mm' display format cannot indicate fractional second digits.> ...
%! duration (0, 0, 0, 'Format', 'hh:mm.SS')
%!error<duration: invalid display format for fractional second digits.> ...
%! duration (0, 0, 0, 'Format', 'hh:mm.SM')
%!error<duration: more than nine fractional second digits in display format.> ...
%! duration (0, 0, 0, 'Format', 'hh:mm:ss.SSSSSSSSSS')
%!error<duration: 'InputFormat' must be a character vector or a string scalar.> ...
%! duration (0, 0, 0, 'InputFormat', {'hh:mm'})
%!error<duration: 'InputFormat' must be a character vector or a string scalar.> ...
%! duration (0, 0, 0, 'InputFormat', string ({'hh:mm', 'hh:mm'}))
%!error<duration: invalid 'InputFormat'.> duration (0, 0, 0, 'InputFormat', 'hh:mmm')
%!error<duration: invalid 'InputFormat'.> duration (0, 0, 0, 'InputFormat', string ('hh:mmm'))
%!error<duration: 'hh:mm' input format cannot indicate fractional second digits.> ...
%! duration (0, 0, 0, 'InputFormat', 'hh:mm.SSS')
%!error<duration: invalid 'InputFormat' for fractional second digits.> ...
%! duration (0, 0, 0, 'InputFormat', string ('hh:mm:ss.SSM'))
%!error<duration: more than nine fractional second digits in 'InputFormat'.> ...
%! duration (0, 0, 0, 'InputFormat', string ('hh:mm:ss.SSSSSSSSSS'))
%!error<duration: more than nine fractional second digits in 'InputFormat'.> ...
%! duration (0, 0, 0, 'InputFormat', 'hh:mm:ss.SSSSSSSSSS')
%!error<duration: numeric X must be a matrix.> duration (ones (2, 2, 2))
%!error<duration: numeric X must be real.> duration (ones (2, 3) * i)
%!error<duration: X must have 3 columns.> duration (ones (2, 4))
%!error<duration: invalid type of single input data argument.> duration ({1})
%!error<duration: invalid type of single input data argument.> duration (struct ('a', 1))
%!error<duration: H, MI, and S must be numeric arrays.> duration ('a', 0, 0)
%!error<duration: H, MI, and S must be numeric arrays.> duration (0, 'a', 0)
%!error<duration: H, MI, and S must be numeric arrays.> duration (0, 0, 'a')
%!error<duration: H, MI, and S must be real.> duration (i, 0, 0)
%!error<duration: H, MI, and S must be real.> duration (0, i, 0)
%!error<duration: H, MI, and S must be real.> duration (0, 0, i)
%!error<duration: H, MI, and S must be of common size or scalars.> ...
%! duration (0, [0, 0], [0; 0])
%!error<duration: H, MI, S, and MS must be numeric arrays.> duration ('a', 0, 0, 0)
%!error<duration: H, MI, S, and MS must be numeric arrays.> duration (0, 'a', 0, 0)
%!error<duration: H, MI, S, and MS must be numeric arrays.> duration (0, 0, 'a', 0)
%!error<duration: H, MI, S, and MS must be numeric arrays.> duration (0, 0, 0, 'a')
%!error<duration: H, MI, S, and MS must be real.> duration (i, 0, 0, 0)
%!error<duration: H, MI, S, and MS must be real.> duration (0, i, 0, 0)
%!error<duration: H, MI, S, and MS must be real.> duration (0, 0, i, 0)
%!error<duration: H, MI, S, and MS must be real.> duration (0, 0, 0, i)
%!error<duration: H, MI, S, and MS must be of common size or scalars.> ...
%! duration (0, [0, 0], [0; 0], 0)
%!error<duration: invalid number of input arguments.> duration (1, 2, 3, 4, 5)
%!warning<duration: 'InputFormat' has no effect on numeric data.> ...
%! duration ([0, 0, 0], 'InputFormat', 'hh:mm');
%!warning<duration: 'InputFormat' has no effect on numeric data.> ...
%! duration (0, 0, 0, 'InputFormat', 'hh:mm');
%!warning<duration: 'InputFormat' has no effect on numeric data.> ...
%! duration (0, 0, 0, 0, 'InputFormat', 'hh:mm');

%!assert_equal (dispstrings (years (1)), {'1 yr'})
%!assert_equal (dispstrings (years (2)), {'2 yrs'})
%!assert_equal (dispstrings (years ([1, 2, 2.4])), {'1 yr', '2 yrs', '2.4 yrs'})
%!assert_equal (dispstrings (years ([1; 2; 2.4])), {'1 yr'; '2 yrs'; '2.4 yrs'})
%!assert_equal (dispstrings (days (1)), {'1 day'})
%!assert_equal (dispstrings (days (2)), {'2 days'})
%!assert_equal (dispstrings (days ([1, 2, 2.4])), {'1 day', '2 days', '2.4 days'})
%!assert_equal (dispstrings (days ([1; 2; 2.4])), {'1 day'; '2 days'; '2.4 days'})
%!assert_equal (dispstrings (duration (36, 0, 0)), {'36:00:00'})
%!assert_equal (dispstrings (duration (-36, 0, 0)), {'-36:00:00'})
%!assert_equal (dispstrings (duration (36, 0, 0, 'Format', 'y')), {'0.00410686 yrs'})
%!assert_equal (dispstrings (duration (36, 0, 0, 'Format', 'd')), {'1.5 days'})
%!assert_equal (dispstrings (duration (36, 0, 0, 'Format', 'h')), {'36 hr'})
%!assert_equal (dispstrings (duration (36, 0, 0, 'Format', 'm')), {'2160 min'})
%!assert_equal (dispstrings (duration (36, 0, 0, 'Format', 's')), {'129600 sec'})
%!assert_equal (dispstrings (duration (36, 0, 0, 'Format', 'dd:hh:mm:ss.SSSSS')), {'01:12:00:00.00000'})
%!assert_equal (dispstrings (duration (36, 0, 0, 'Format', 'hh:mm:ss.SSSSS')), {'36:00:00.00000'})
%!assert_equal (dispstrings (duration (36, 0, 0, 'Format', 'hh:mm:ss.SSSS')), {'36:00:00.0000'})
%!assert_equal (dispstrings (duration (36, 0, 0, 'Format', 'hh:mm:ss.SSS')), {'36:00:00.000'})
%!assert_equal (dispstrings (duration (36, 0, 0, 'Format', 'hh:mm:ss.SS')), {'36:00:00.00'})
%!assert_equal (dispstrings (duration (36, 0, 0, 'Format', 'hh:mm:ss.S')), {'36:00:00.0'})
%!assert_equal (dispstrings (duration (36, 0, 0, 'Format', 'hh:mm')), {'36:00'})
%!assert_equal (dispstrings (duration (36, 0, 0.025, 'Format', 'hh:mm')), {'36:00'})
%!assert_equal (dispstrings (duration (36, 0, 55.025, 'Format', 'hh:mm')), {'36:00'})
%!assert_equal (dispstrings (duration (36, 0, 0, 'Format', 'mm:ss.SSSSS')), {'2160:00.00000'})
%!assert_equal (dispstrings (duration (36, 0, 0, 'Format', 'mm:ss.SSSSSS')), {'2160:00.000000'})
%!assert_equal (dispstrings (duration (36, 0, 0, 'Format', 'mm:ss.SSSSSSS')), {'2160:00.0000000'})
%!assert_equal (dispstrings (duration (36, 0, 0, 'Format', 'mm:ss.SSSSSSSS')), {'2160:00.00000000'})
%!assert_equal (dispstrings (duration (36, 0, 0, 'Format', 'mm:ss.SSSSSSSSS')), {'2160:00.000000000'})
%!assert_equal (dispstrings (duration (0, 36, 0)), {'00:36:00'})
%!assert_equal (dispstrings (duration (0, 36, 0, 'Format', 'y')), {'6.84477e-05 yrs'})
%!assert_equal (dispstrings (duration (0, 36, 0, 'Format', 'd')), {'0.025 days'})
%!assert_equal (dispstrings (duration (0, 36, 0, 'Format', 'h')), {'0.6 hr'})
%!assert_equal (dispstrings (duration (0, 36, 0, 'Format', 'm')), {'36 min'})
%!assert_equal (dispstrings (duration (0, 36, 0, 'Format', 's')), {'2160 sec'})
%!assert_equal (dispstrings (duration (0, 36, 0.025, 'Format', 'dd:hh:mm:ss.SSSSS')), {'00:36:00.02500'})
%!assert_equal (dispstrings (duration (0, 36, 0.025, 'Format', 'hh:mm:ss.SSSSS')), {'00:36:00.02500'})
%!assert_equal (dispstrings (duration (0, 36, 0.025, 'Format', 'hh:mm:ss.SSSS')), {'00:36:00.0250'})
%!assert_equal (dispstrings (duration (0, 36, 0.025, 'Format', 'hh:mm:ss.SSS')), {'00:36:00.025'})
%!assert_equal (dispstrings (duration (0, 36, 0.025, 'Format', 'hh:mm:ss.SS')), {'00:36:00.02'})
%!assert_equal (dispstrings (duration (0, 36, 0.025, 'Format', 'hh:mm:ss.S')), {'00:36:00.0'})
%!assert_equal (dispstrings (duration (0, 36, 0.025, 'Format', 'hh:mm')), {'00:36'})
%!assert_equal (dispstrings (duration (0, 36, 5.025, 'Format', 'hh:mm')), {'00:36'})
%!assert_equal (dispstrings (duration (0, 36, 0.025, 'Format', 'mm:ss.SSSSS')), {'36:00.02500'})
%!assert_equal (dispstrings (duration (0, 36, 0.025, 'Format', 'mm:ss.SSSSSS')), {'36:00.025000'})
%!assert_equal (dispstrings (duration (0, 36, 0.025, 'Format', 'mm:ss.SSSSSSS')), {'36:00.0250000'})
%!assert_equal (dispstrings (duration (0, 36, 0.025, 'Format', 'mm:ss.SSSSSSSS')), {'36:00.02500000'})
%!assert_equal (dispstrings (duration (0, 36, 0.025, 'Format', 'mm:ss.SSSSSSSSS')), {'36:00.025000000'})
%!test
%! D = duration ([1, 2.3, NaN, Inf, -Inf], 0, 0, 'Format', 'y');
%! assert_equal (dispstrings (D), {'0.000114079 yrs', '0.000262383 yrs', 'NaN yrs', 'Inf yrs', '-Inf yrs'});
%!test
%! D = duration ([1, 2.3, NaN, Inf, -Inf], 0, 0, 'Format', 'd');
%! assert_equal (dispstrings (D), {'0.0416667 days', '0.0958333 days', 'NaN days', 'Inf days', '-Inf days'});
%!test
%! D = duration ([1, 2.3, NaN, Inf, -Inf], 0, 0, 'Format', 'h');
%! assert_equal (dispstrings (D), {'1 hr', '2.3 hr', 'NaN hr', 'Inf hr', '-Inf hr'});
%!test
%! D = duration ([1, 2.3, NaN, Inf, -Inf], 0, 0, 'Format', 'm');
%! assert_equal (dispstrings (D), {'60 min', '138 min', 'NaN min', 'Inf min', '-Inf min'});
%!test
%! D = duration ([1, 2.3, NaN, Inf, -Inf], 0, 0, 'Format', 's');
%! assert_equal (dispstrings (D), {'3600 sec', '8280 sec', 'NaN sec', 'Inf sec', '-Inf sec'});
%!test
%! D = duration ([1, 2.3, NaN, Inf, -Inf], 0, 0, 'Format', 'hh:mm');
%! assert_equal (dispstrings (D), {'01:00', '02:18', 'NaN', 'Inf', '-Inf'});
%!test
%! D = duration ([1, 2.3, NaN, Inf, -Inf], 0, 0, 'Format', 'mm:ss');
%! assert_equal (dispstrings (D), {'60:00', '138:00', 'NaN', 'Inf', '-Inf'});
%!test
%! D = duration ([1, 2.3, NaN, Inf, -Inf], 0, 0, 'Format', 'hh:mm:ss');
%! assert_equal (dispstrings (D), {'01:00:00', '02:18:00', 'NaN', 'Inf', '-Inf'});
%!test
%! D = duration ([1, 2.3, NaN, Inf, -Inf], 0, 0, 'Format', 'hh:mm:ss.SS');
%! assert_equal (dispstrings (D), {'01:00:00.00', '02:18:00.00', 'NaN', 'Inf', '-Inf'});
%!test
%! D = duration ([1, 2.3, NaN, Inf, -Inf], 0, 0, 'Format', 'dd:hh:mm:ss');
%! assert_equal (dispstrings (D), {'01:00:00', '02:18:00', 'NaN', 'Inf', '-Inf'});
%!test
%! D = duration ([1, 2.3, NaN, Inf, -Inf], 0, 0, 'Format', 'dd:hh:mm:ss.SS');
%! assert_equal (dispstrings (D), {'01:00:00.00', '02:18:00.00', 'NaN', 'Inf', '-Inf'});
%!test
%! D = duration ([24.001, 2.3001, NaN, Inf, -Inf], 0, 0, 'Format', 'dd:hh:mm:ss');
%! assert_equal (dispstrings (D), {'01:00:00:03', '02:18:00', 'NaN', 'Inf', '-Inf'});
%!test
%! D = duration ([24.001, 2.3001, NaN, Inf, -Inf], 0, 0, 'Format', 'dd:hh:mm:ss.SSS');
%! assert_equal (dispstrings (D), {'01:00:00:03.600', '02:18:00.360', 'NaN', 'Inf', '-Inf'});

%!assert_equal (cellstr (years (1)), {'1 yr'})
%!assert_equal (cellstr (years (1), 'd'), {'365.243 days'})
%!assert_equal (cellstr (years (2)), {'2 yrs'})
%!assert_equal (cellstr (years (2), 'd'), {'730.485 days'})
%!assert_equal (cellstr (days (1)), {'1 day'})
%!assert_equal (cellstr (days (1), 'y'), {'0.00273791 yrs'})
%!assert_equal (cellstr (days (2), 'm'), {'2880 min'})
%!assert_equal (cellstr (duration (36, 0, 0)), {'36:00:00'})
%!assert_equal (cellstr (duration (36, 0, 0), 'y'), {'0.00410686 yrs'})
%!assert_equal (cellstr (duration (36, 0, 0), 'd'), {'1.5 days'})
%!assert_equal (cellstr (duration (36, 0, 0), 'h'), {'36 hr'})
%!assert_equal (cellstr (duration (36, 0, 0), 'm'), {'2160 min'})
%!assert_equal (cellstr (duration (36, 0, 0), 's'), {'129600 sec'})
%!assert_equal (cellstr (duration (36, 0, 0), 'dd:hh:mm:ss.SSSSS'), {'01:12:00:00.00000'})
%!assert_equal (cellstr (duration (36, 0, 0), 'hh:mm:ss.SSSSS'), {'36:00:00.00000'})
%!assert_equal (cellstr (duration (36, 0, 0), 'hh:mm:ss.SSSS'), {'36:00:00.0000'})
%!assert_equal (cellstr (duration (36, 0, 0), 'hh:mm:ss.SSS'), {'36:00:00.000'})
%!assert_equal (cellstr (duration (36, 0, 0), 'hh:mm:ss.SS'), {'36:00:00.00'})
%!assert_equal (cellstr (duration (36, 0, 0), 'hh:mm:ss.S'), {'36:00:00.0'})
%!assert_equal (cellstr (duration (36, 0, 0), 'hh:mm'), {'36:00'})
%!assert_equal (cellstr (duration (36, 0, 0.025), 'hh:mm'), {'36:00'})
%!assert_equal (cellstr (duration (36, 0, 55.025), 'hh:mm'), {'36:00'})
%!assert_equal (cellstr (duration (36, 0, 0), 'mm:ss.SSSSS'), {'2160:00.00000'})
%!assert_equal (cellstr (duration (36, 0, 0), 'mm:ss.SSSSSS'), {'2160:00.000000'})
%!assert_equal (cellstr (duration (36, 0, 0), 'mm:ss.SSSSSSS'), {'2160:00.0000000'})
%!assert_equal (cellstr (duration (36, 0, 0), 'mm:ss.SSSSSSSS'), {'2160:00.00000000'})
%!assert_equal (cellstr (duration (36, 0, 0), 'mm:ss.SSSSSSSSS'), {'2160:00.000000000'})
%!assert_equal (cellstr (duration (0, 36, 0)), {'00:36:00'})
%!assert_equal (cellstr (duration (0, 36, 0), 'y'), {'6.84477e-05 yrs'})
%!assert_equal (cellstr (duration (0, 36, 0), 'd'), {'0.025 days'})
%!assert_equal (cellstr (duration (0, 36, 0), 'h'), {'0.6 hr'})
%!assert_equal (cellstr (duration (0, 36, 0), 'm'), {'36 min'})
%!assert_equal (cellstr (duration (0, 36, 0), 's'), {'2160 sec'})
%!assert_equal (cellstr (duration (0, 36, 0.025), 'dd:hh:mm:ss.SSSSS'), {'00:36:00.02500'})
%!assert_equal (cellstr (duration (0, 36, 0.025), 'hh:mm:ss.SSSSS'), {'00:36:00.02500'})
%!assert_equal (cellstr (duration (0, 36, 0.025), 'hh:mm:ss.SSSS'), {'00:36:00.0250'})
%!assert_equal (cellstr (duration (0, 36, 0.025), 'hh:mm:ss.SSS'), {'00:36:00.025'})
%!assert_equal (cellstr (duration (0, 36, 0.025), 'hh:mm:ss.SS'), {'00:36:00.02'})
%!assert_equal (cellstr (duration (0, 36, 0.025), 'hh:mm:ss.S'), {'00:36:00.0'})
%!assert_equal (cellstr (duration (0, 36, 0.025), 'hh:mm'), {'00:36'})
%!assert_equal (cellstr (duration (0, 36, 5.025), 'hh:mm'), {'00:36'})
%!assert_equal (cellstr (duration (0, 36, 0.025), 'mm:ss.SSSSS'), {'36:00.02500'})
%!assert_equal (cellstr (duration (0, 36, 0.025), 'mm:ss.SSSSSS'), {'36:00.025000'})
%!assert_equal (cellstr (duration (0, 36, 0.025), 'mm:ss.SSSSSSS'), {'36:00.0250000'})
%!assert_equal (cellstr (duration (0, 36, 0.025), 'mm:ss.SSSSSSSS'), {'36:00.02500000'})
%!assert_equal (cellstr (duration (0, 36, 0.025), 'mm:ss.SSSSSSSSS'), {'36:00.025000000'})
%!error<duration.cellstr: FORMAT must be a character vector or a string scalar.> ...
%! cellstr (days (2), string ({'m', 'y'}))
%!error<duration.cellstr: FORMAT must be a character vector or a string scalar.> ...
%! cellstr (days (2), ['m'; 'y'])
%!error<duration.cellstr: FORMAT must be a character vector or a string scalar.> ...
%! cellstr (days (2), {'m'})
%!error<duration.cellstr: FORMAT must be a character vector or a string scalar.> ...
%! cellstr (days (2), 2)
%!error<duration.cellstr: invalid display format.> cellstr (duration (0, 0, 0), 't')
%!error<duration.cellstr: invalid display format.> cellstr (duration (0, 0, 0), 'd.h.S')
%!error<duration.cellstr: invalid display format.> cellstr (duration (0, 0, 0), 's.SS')
%!error<duration.cellstr: 'hh:mm' display format cannot indicate fractional second digits.> ...
%! cellstr (duration (0, 0, 0), 'hh:mm.SS')
%!error<duration.cellstr: invalid display format for fractional second digits.> ...
%! cellstr (duration (0, 0, 0), 'hh:mm.SM')
%!error<duration.cellstr: more than nine fractional second digits in display format.> ...
%! cellstr (duration (0, 0, 0), 'hh:mm:ss.SSSSSSSSSS')

%!assert_equal (char (years (1)), '1 yr')
%!assert_equal (char (years ([1, 2])), [' 1 yr'; '2 yrs'])
%!assert_equal (char (days ([1, 20])), ['  1 day'; '20 days'])
%!assert_equal (char (years (1), 'd'), '365.243 days')
%!assert_equal (char (years (2)), '2 yrs')
%!assert_equal (char (years (2), 'd'), '730.485 days')
%!assert_equal (char (days (1)), '1 day')
%!assert_equal (char (days ([1; 2])), [' 1 day'; '2 days'])
%!assert_equal (char (days (1), 'y'), '0.00273791 yrs')
%!assert_equal (char (days (2), 'm'), '2880 min')
%!assert_equal (char (duration (36, 0, 0)), '36:00:00')
%!assert_equal (char (duration (36, 0, 0), 'y'), '0.00410686 yrs')
%!assert_equal (char (duration (36, 0, 0), 'd'), '1.5 days')
%!assert_equal (char (duration (36, 0, 0), 'h'), '36 hr')
%!assert_equal (char (duration (36, 0, 0), 'm'), '2160 min')
%!assert_equal (char (duration (36, 0, 0), 's'), '129600 sec')
%!assert_equal (char (duration (36, 0, 0), 'dd:hh:mm:ss.SSSSS'), '01:12:00:00.00000')
%!assert_equal (char (duration (36, 0, 0), 'hh:mm:ss.SSSSS'), '36:00:00.00000')
%!assert_equal (char (duration (36, 0, 0), 'hh:mm:ss.SSSS'), '36:00:00.0000')
%!assert_equal (char (duration (36, 0, 0), 'hh:mm:ss.SSS'), '36:00:00.000')
%!assert_equal (char (duration (36, 0, 0), 'hh:mm:ss.SS'), '36:00:00.00')
%!assert_equal (char (duration (36, 0, 0), 'hh:mm:ss.S'), '36:00:00.0')
%!assert_equal (char (duration (36, 0, 0), 'hh:mm'), '36:00')
%!assert_equal (char (duration (36, 0, 0.025), 'hh:mm'), '36:00')
%!assert_equal (char (duration (36, 0, 55.025), 'hh:mm'), '36:00')
%!assert_equal (char (duration (36, 0, 0), 'mm:ss.SSSSS'), '2160:00.00000')
%!assert_equal (char (duration (36, 0, 0), 'mm:ss.SSSSSS'), '2160:00.000000')
%!assert_equal (char (duration (36, 0, 0), 'mm:ss.SSSSSSS'), '2160:00.0000000')
%!assert_equal (char (duration (36, 0, 0), 'mm:ss.SSSSSSSS'), '2160:00.00000000')
%!assert_equal (char (duration (36, 0, 0), 'mm:ss.SSSSSSSSS'), '2160:00.000000000')
%!assert_equal (char (duration (0, 36, 0)), '00:36:00')
%!assert_equal (char (duration (0, 36, 0), 'y'), '6.84477e-05 yrs')
%!assert_equal (char (duration (0, 36, 0), 'd'), '0.025 days')
%!assert_equal (char (duration (0, 36, 0), 'h'), '0.6 hr')
%!assert_equal (char (duration (0, 36, 0), 'm'), '36 min')
%!assert_equal (char (duration (0, 36, 0), 's'), '2160 sec')
%!assert_equal (char (duration (0, 36, 0.025), 'dd:hh:mm:ss.SSSSS'), '00:36:00.02500')
%!assert_equal (char (duration (0, 36, 0.025), 'hh:mm:ss.SSSSS'), '00:36:00.02500')
%!assert_equal (char (duration (0, 36, 0.025), 'hh:mm:ss.SSSS'), '00:36:00.0250')
%!assert_equal (char (duration (0, 36, 0.025), 'hh:mm:ss.SSS'), '00:36:00.025')
%!assert_equal (char (duration (0, 36, 0.025), 'hh:mm:ss.SS'), '00:36:00.02')
%!assert_equal (char (duration (0, 36, 0.025), 'hh:mm:ss.S'), '00:36:00.0')
%!assert_equal (char (duration (0, 36, 0.025), 'hh:mm'), '00:36')
%!assert_equal (char (duration (0, 36, 5.025), 'hh:mm'), '00:36')
%!assert_equal (char (duration (0, 36, 0.025), 'mm:ss.SSSSS'), '36:00.02500')
%!assert_equal (char (duration (0, 36, 0.025), 'mm:ss.SSSSSS'), '36:00.025000')
%!assert_equal (char (duration (0, 36, 0.025), 'mm:ss.SSSSSSS'), '36:00.0250000')
%!assert_equal (char (duration (0, 36, 0.025), 'mm:ss.SSSSSSSS'), '36:00.02500000')
%!assert_equal (char (duration (0, 36, 0.025), 'mm:ss.SSSSSSSSS'), '36:00.025000000')
%!error<duration.char: FORMAT must be a character vector or a string scalar.> ...
%! char (days (2), string ({'m', 'y'}))
%!error<duration.char: FORMAT must be a character vector or a string scalar.> ...
%! char (days (2), ['m'; 'y'])
%!error<duration.char: FORMAT must be a character vector or a string scalar.> ...
%! char (days (2), {'m'})
%!error<duration.char: FORMAT must be a character vector or a string scalar.> ...
%! char (days (2), 2)
%!error<duration.char: invalid display format.> char (duration (0, 0, 0), 't')
%!error<duration.char: invalid display format.> char (duration (0, 0, 0), 'd.h.S')
%!error<duration.char: invalid display format.> char (duration (0, 0, 0), 's.SS')
%!error<duration.char: 'hh:mm' display format cannot indicate fractional second digits.> ...
%! char (duration (0, 0, 0), 'hh:mm.SS')
%!error<duration.char: invalid display format for fractional second digits.> ...
%! char (duration (0, 0, 0), 'hh:mm.SM')
%!error<duration.char: more than nine fractional second digits in display format.> ...
%! char (duration (0, 0, 0), 'hh:mm:ss.SSSSSSSSSS')
%!test
%! cmat = char (duration ([1; 100], 0, 0));
%! assert_equal (size (cmat), [2, 9]);
%! assert_equal (cmat(1,:), ' 01:00:00');
%! assert_equal (cmat(2,:), '100:00:00');
%!test
%! cmat = char (duration ([1; NaN], 0, 0));
%! assert_equal (size (cmat), [2, 8]);
%! assert_equal (cmat(1,:), '01:00:00');
%! assert_equal (cmat(2,:), '     NaN');
%!test
%! cmat = char (duration ([-1; 100], 0, 0));
%! assert_equal (cmat(1,:), '-01:00:00');
%! assert_equal (cmat(2,:), '100:00:00');
%!test
%! cmat = char (duration ([], [], []));
%! assert_equal (size (cmat), [0, 0]);

%!test
%! [y, mo, d, h, mi, s] = datevec (years (1));
%! assert_equal (y, 1);
%! assert_equal (mo, 0);
%! assert_equal (d, 0);
%! assert_equal (h, 0);
%! assert_equal (mi, 0);
%! assert_equal (s, 0);
%!test
%! [y, mo, d, h, mi, s] = datevec (years (1.0258123));
%! assert_equal (y, 1);
%! assert_equal (mo, 0);
%! assert_equal (d, 9);
%! assert_equal (h, 10);
%! assert_equal (mi, 15);
%! assert_equal (s, 57.5121, 1E-4);
%!test
%! [y, mo, d, h, mi, s] = datevec (years (1.5));
%! assert_equal (y, 1);
%! assert_equal (mo, 0);
%! assert_equal (d, 182);
%! assert_equal (h, 14);
%! assert_equal (mi, 54);
%! assert_equal (s, 36, 1e-8);
%!test
%! [y, mo, d, h, mi, s] = datevec (days (1));
%! assert_equal (y, 0);
%! assert_equal (mo, 0);
%! assert_equal (d, 1);
%! assert_equal (h, 0);
%! assert_equal (mi, 0);
%! assert_equal (s, 0);
%!test
%! [y, mo, d, h, mi, s] = datevec (days (1.0258123));
%! assert_equal (y, 0);
%! assert_equal (mo, 0);
%! assert_equal (d, 1);
%! assert_equal (h, 0);
%! assert_equal (mi, 37);
%! assert_equal (s, 10.1827, 1E-4);
%!test
%! [y, mo, d, h, mi, s] = datevec (days (1.5));
%! assert_equal (y, 0);
%! assert_equal (mo, 0);
%! assert_equal (d, 1);
%! assert_equal (h, 12);
%! assert_equal (mi, 0);
%! assert_equal (s, 0, 1e-8);
%!assert_equal (datevec (years (1)), [1, 0, 0, 0, 0, 0])
%!assert_equal (datevec (years (1.0258123)), [1, 0, 9, 10, 15, 57.5121], 1e-4)
%!assert_equal (datevec (years (1.5)), [1, 0, 182, 14, 54, 36], 1e-8)
%!assert_equal (datevec (days (1)), [0, 0, 1, 0, 0, 0])
%!assert_equal (datevec (days (1.0258123)), [0, 0, 1, 0, 37, 10.1827], 1e-4)
%!assert_equal (datevec (days (1.5)), [0, 0, 1, 12, 0, 0])
%!test
%! [y, mo, d, h, mi, s] = datevec (days (magic (3)));
%! assert_equal (y, zeros (3));
%! assert_equal (mo, zeros (3));
%! assert_equal (d, magic (3));
%! assert_equal (h, zeros (3));
%! assert_equal (mi, zeros (3));
%! assert_equal (s, zeros (3));
%!test
%! DV = datevec (days (magic (3)));
%! out = zeros (9, 6);
%! out(:,3) = magic (3)(:);
%! assert_equal (DV, out);
%!test
%! [y, mo, d, h, mi, s] = datevec (days (ones (2, 3, 4)));
%! assert_equal (y, zeros (2, 3, 4));
%! assert_equal (mo, zeros (2, 3, 4));
%! assert_equal (d, ones (2, 3, 4));
%! assert_equal (h, zeros (2, 3, 4));
%! assert_equal (mi, zeros (2, 3, 4));
%! assert_equal (s, zeros (2, 3, 4));
%!test
%! DV = datevec (days (ones (2, 3, 4)));
%! out = zeros (24, 6);
%! out(:,3) = ones (24, 1);
%! assert_equal (DV, out);
%!test
%! DV = datevec (years (reshape ([1:24], 2, 3, 4)));
%! out = zeros (24, 6);
%! out(:,1) = [1:24]';
%! assert_equal (DV, out);
%!test
%! DV = datevec (days (reshape ([1:24], 2, 3, 4)));
%! out = zeros (24, 6);
%! out(:,3) = [1:24]';
%! assert_equal (DV, out);
%!test
%! DV = datevec (hours (reshape ([1:24], 2, 3, 4)));
%! out = zeros (24, 6);
%! out(:,4) = [1:23,0]';
%! out(24,3) = 1;
%! assert_equal (DV, out);
%!test
%! DV = datevec (minutes (reshape ([1:24], 2, 3, 4)));
%! out = zeros (24, 6);
%! out(:,5) = [1:24]';
%! assert_equal (DV, out);
%!test
%! DV = datevec (seconds (reshape ([1:24], 2, 3, 4)));
%! out = zeros (24, 6);
%! out(:,6) = [1:24]';
%! assert_equal (DV, out, 2e-15);
%!test
%! DV = datevec (milliseconds (reshape ([1:24], 2, 3, 4)));
%! out = zeros (24, 6);
%! out(:,6) = 1e-3 * [1:24]';
%! assert_equal (DV, out, 2e-15);
%!test
%! X = reshape ([1:24], 2, 3, 4);
%! X([12,17]) = NaN;
%! DV = datevec (days (X));
%! out = zeros (24, 6);
%! out(:, 3) = [1:24]';
%! out([12,17],:) = NaN;
%! assert_equal (DV, out);
%!test
%! X = reshape ([1:24], 2, 3, 4);
%! X([12,17]) = NaN;
%! [y, mo, d, h, mi, s] = datevec (days (X));
%! y_out = mo_out = h_out = mi_out = s_out = zeros (2, 3, 4);
%! d_out = X;
%! y_out([12,17]) = mo_out([12,17]) = NaN;
%! h_out([12,17]) = mi_out([12,17]) = s_out([12,17]) = NaN;
%! assert_equal (y, y_out);
%! assert_equal (mo, mo_out);
%! assert_equal (d, d_out);
%! assert_equal (h, h_out);
%! assert_equal (mi, mi_out);
%! assert_equal (s, s_out);

%!assert_equal (hms (hours ([1:5])), [1:5])
%!assert_equal (hms (days ([1:5])), 24 * [1:5])
%!assert_equal (hms (hours (reshape ([1:24], 2, 3, 4))), reshape ([1:24], 2, 3, 4))
%!test
%! [h, m, s] = hms (days (0.25 * reshape ([1:24], 2, 3, 4)));
%! assert_equal (h, 6 * reshape ([1:24], 2, 3, 4));
%! assert_equal (m, zeros (2, 3, 4));
%! assert_equal (s, zeros (2, 3, 4));
%!test
%! [h, m, s] = hms (years (0.25 * reshape ([1:24], 2, 3, 4)));
%! h_out = fix (hours (years (0.25 * reshape ([1:24], 2, 3, 4))));
%! assert_equal (h, h_out);
%! m_out = fix (minutes (years (0.25 * reshape ([1:24], 2, 3, 4)))) - h_out * 60;
%! assert_equal (m, m_out);
%! s_out = round (seconds (years (0.25 * reshape ([1:24], 2, 3, 4))));
%! assert_equal (s, s_out - (h_out * 3600 + m_out * 60), 5e-8);
%!test
%! [h, m, s] = hms (hours ([1:5]));
%! assert_equal (m, zeros (1, 5));
%! assert_equal (s, zeros (1, 5));
%!test
%! [h, m, s] = hms (minutes ([1:5]));
%! assert_equal (h, zeros (1, 5));
%! assert_equal (m, [1:5]);
%! assert_equal (s, zeros (1, 5));
%!test
%! [h, m, s] = hms (seconds ([1:5]));
%! assert_equal (h, zeros (1, 5));
%! assert_equal (m, zeros (1, 5));
%! assert_equal (s, [1:5]);
%!error<duration.hms: too many output arguments.> [h, m, s, ms] = hms (days (1))
%!test
%! [h, m, s] = hms (duration (-4, -5, -6.5));
%! assert_equal ([h, m, s], [-4, -5, -6.5]);
%!test
%! [h, m, s] = hms (duration (0, 0, -0.5));
%! assert_equal ([h, m, s], [0, 0, -0.5]);
%!test
%! [h, m, s] = hms (duration ([Inf, -Inf, NaN], 0, 0));
%! assert_equal (h, [Inf, -Inf, NaN]);
%! assert_equal (m, [Inf, -Inf, NaN]);
%! assert_equal (s, [Inf, -Inf, NaN]);
%!test
%! [h, m, s] = hms (duration (0, 0, -3599.9999999999995));
%! assert_equal ([h, m], [0, -59]);
%! assert_equal (s, -59.999999999999545, 1e-12);
%!test
%! [h, m, s] = hms (duration (0, 0, 3599.9999999999995));
%! assert_equal ([h, m], [0, 59]);
%! assert_equal (s, 59.999999999999545, 1e-12);
%!test
%! [h, m, s] = hms (duration (0, 0, -1e-13));
%! assert_equal ([h, m], [0, 0]);
%! assert_equal (s, -1e-13);
%!test
%! [h, m, s] = hms (duration ([1, -1], 0, [0.5, -0.5]));
%! assert_equal (h, [1, -1]);
%! assert_equal (m, [0, 0]);
%! assert_equal (s, [0.5, -0.5]);

################################################################################
##                         ** Summary Information **                          ##
################################################################################
##                             Available Methods                              ##
##                                                                            ##
## 'size'             'ndims'            'numel'            'nnz'             ##
## 'length'           'keyHash'                                               ##
##                                                                            ##
################################################################################

%!assert_equal (size (duration), [1, 1])
%!assert_equal (size (days ([])), [0, 0])
%!assert_equal (size (days (ones (2, 0, 3, 4))), [2, 0, 3, 4])
%!assert_equal (size (duration (ones (2, 4), 0, 0)), [2, 4])
%!assert_equal (size (duration (ones (2, 4, 1, 1), 0, 0)), [2, 4])
%!assert_equal (size (duration (ones (2, 4, 1, 0), 0, 0)), [2, 4, 1, 0])
%!assert_equal (size (duration (zeros (6, 3))), [6, 1])

%!assert_equal (ndims (duration), 2)
%!assert_equal (ndims (days ([])), 2)
%!assert_equal (ndims (days (ones (2, 0, 3, 4))), 4)
%!assert_equal (ndims (duration (ones (2, 4), 0, 0)), 2)
%!assert_equal (ndims (duration (zeros (6, 3))), 2)

%!assert_equal (numel (duration), 1)
%!assert_equal (numel (days ([])), 0)
%!assert_equal (numel (days (ones (2, 0, 3, 4))), 0)
%!assert_equal (numel (duration (ones (2, 4), 0, 0)), 8)
%!assert_equal (numel (duration (zeros (6, 3))), 6)

%!assert_equal (nnz (days ([])), 0)
%!assert_equal (nnz (duration), 0)
%!assert_equal (nnz (days (ones (2, 0, 3, 4))), 0)
%!assert_equal (nnz (days (zeros (2, 0, 3, 4))), 0)
%!assert_equal (nnz (days (zeros (2, 1, 3, 4))), 0)
%!assert_equal (nnz (days (ones (2, 1, 3, 4))), 24)
%!assert_equal (nnz (days ([1, 4, 0, 9, 0, 8])), 4)
%!assert_equal (nnz (days ([1, 4, 0; 9, 0, 8])), 4)

%!assert_equal (length (duration (1, 1, 1)), 1)
%!assert_equal (length (duration (0, 0, 0)), 1)
%!assert_equal (length (duration (0:5, 0, 0)), 6)
%!assert_equal (length (duration ([0, 0, 0, 1, 1], 0, 0)), 5)
%!assert_equal (length (duration (ones (2, 3, 4), 0, 0)), 4)
%!assert_equal (length (duration (ones (2, 10, 4), 0, 0)), 10)

%!assert_equal (keyHash (duration), uint64 (8095976253982599603))
%!assert_equal (keyHash (duration (0, 0, 0)), uint64 (8095976253982599603))
%!assert_equal (keyHash (duration ([], [], [])), uint64 (14859204025010592219))
%!assert_equal (keyHash (duration (1, 1, 1)), uint64 (9684925284775797661))
%!test
%! key = keyHash (duration ([1, 2; 3, 4], 1, 1));
%! assert_equal (key, uint64 (6302809889869477948));
%!test
%! key = keyHash (duration (0, 0, 0, [1, 2, 3]));
%! assert_equal (key, uint64 (11458397730511227888));
%!test
%! base_key = uint64 (2342124352342344234);
%! key = keyHash (duration (0, 0, 0, [1, 2, 3]), base_key);
%! assert_equal (key, uint64 (14450751741045872781));
%!error<duration.keyHash: BASE must be a UINT64 scalar.> ...
%! keyHash (duration (0, 0, 0), uint64 ([1, 2]))
%!error<duration.keyHash: BASE must be a UINT64 scalar.> ...
%! keyHash (duration (0, 0, 0), 2231107818551636405)

################################################################################
##                          ** Query Operations **                            ##
################################################################################
##                             Available Methods                              ##
##                                                                            ##
## 'isbetween'        'iscolumn'         'isempty'          'isequal'         ##
## 'isequaln'         'isfinite'         'isinf'            'ismatrix'        ##
## 'ismember'         'ismissing'        'isnan'            'isregular'       ##
## 'isrow'            'isscalar'         'issorted'         'issortedrows'    ##
## 'isvector'                                                                 ##
##                                                                            ##
################################################################################

%!test
%! TF = isbetween (days ([0:5]), days (2), days (3));
%! assert_equal (TF, logical ([0, 0, 1, 1, 0, 0,]));
%!test
%! TF = isbetween (days ([0:5]), duration ('02:00:00:00'), days (3));
%! assert_equal (TF, logical ([0, 0, 1, 1, 0, 0,]));
%!test
%! TF = isbetween (days ([0:5]), duration ("1:00:00:00"), days (3));
%! assert_equal (TF, logical ([0, 1, 1, 1, 0, 0,]));
%!test
%! TF = isbetween (days ([0:5]), duration ("1:00:00:00"), days (4));
%! assert_equal (TF, logical ([0, 1, 1, 1, 1, 0,]));
%!test
%! TF =  isbetween (days ([0:5]), days (2), days (3), 'open');
%! assert_equal (TF, false (1, 6));
%!test
%! TF = isbetween (days ([0:5]), duration ('02:00:00:00'), days (3), 'open');
%! assert_equal (TF, false (1, 6));
%!test
%! TF = isbetween (days ([0:5]), duration ('01:00:00:00'), days (3), 'open');
%! assert_equal (TF, logical ([0, 0, 1, 0, 0, 0,]));
%!test
%! TF = isbetween (days ([0:5]), duration ('01:00:00:00'), days (4), 'open');
%! assert_equal (TF, logical ([0, 0, 1, 1, 0, 0,]));
%!test
%! TF = isbetween (days ([0:5]), days (2), hours (72), 'open');
%! assert_equal (TF, false (1, 6));
%!test
%! TF =  isbetween (days ([0:5]), days (2), days (3), 'openleft');
%! assert_equal (TF, logical ([0, 0, 0, 1, 0, 0,]));
%!test
%! TF = isbetween (days ([0:5]), duration ('02:00:00:00'), days (3), 'openleft');
%! assert_equal (TF, logical ([0, 0, 0, 1, 0, 0,]));
%!test
%! TF = isbetween (days ([0:5]), duration ('01:00:00:00'), days (3), 'openleft');
%! assert_equal (TF, logical ([0, 0, 1, 1, 0, 0,]));
%!test
%! TF = isbetween (days ([0:5]), duration ('01:00:00:00'), days (4), 'openleft');
%! assert_equal (TF, logical ([0, 0, 1, 1, 1, 0,]));
%!test
%! TF = isbetween (days ([0:5]), days (2), hours (72), 'openleft');
%! assert_equal (TF, logical ([0, 0, 0, 1, 0, 0,]));
%!test
%! TF =  isbetween (days ([0:5]), days (2), days (3), 'closedleft');
%! assert_equal (TF, logical ([0, 0, 1, 0, 0, 0,]));
%!test
%! TF = isbetween (days ([0:5]), duration ('02:00:00:00'), days (3), 'closedleft');
%! assert_equal (TF, logical ([0, 0, 1, 0, 0, 0,]));
%!test
%! TF = isbetween (days ([0:5]), duration ('01:00:00:00'), days (3), 'closedleft');
%! assert_equal (TF, logical ([0, 1, 1, 0, 0, 0,]));
%!test
%! TF = isbetween (days ([0:5]), duration ('01:00:00:00'), days (4), 'closedleft');
%! assert_equal (TF, logical ([0, 1, 1, 1, 0, 0,]));
%!test
%! TF = isbetween (days ([0:5]), days (2), hours (72), 'closedleft');
%! assert_equal (TF, logical ([0, 0, 1, 0, 0, 0,]));
%!test
%! TF = isbetween (days ([0:5]),'1:23:00:00', hours (72));
%! assert_equal (TF, logical ([0, 0, 1, 1, 0, 0,]));
%!assert_equal (isbetween (years (1), years (1), years (1)), true)
%!error<duration.isbetween: too few input arguments.> ...
%! isbetween (days (1), days (1))
%!error<duration.isbetween: optional paired arguments are not supported for duration arrays.> ...
%! isbetween (days (1), days (1), days (1), 'open', 'OutputFormat', 'logical')
%!error<duration.isbetween: LOWER and UPPER cannot be numeric.> ...
%! isbetween (days (1), 1, 2)
%!error<duration.isbetween: invalid INTERVALTYPE option.> ...
%! isbetween (days (1), days (1), days (1), 'asd')

%!assert_equal (iscolumn (days ([1, 2, 3, 4])), false)
%!assert_equal (iscolumn (days ([1; 2; 3; 4])), true)
%!assert_equal (iscolumn (days ([1, 2; 3, 4])), false)
%!assert_equal (iscolumn (days ([])), false)
%!assert_equal (iscolumn (days (ones (1, 0))), false)
%!assert_equal (iscolumn (days (ones (0, 1))), true)
%!assert_equal (iscolumn (days (1)), true)
%!assert_equal (iscolumn (days (ones (2, 3, 4))), false)

%!assert_equal (isempty (days ([])), true)
%!assert_equal (isempty (days (ones (2, 0, 3))), true)
%!assert_equal (isempty (days (ones (2, 1, 3))), false)
%!assert_equal (isempty (days (1)), false)
%!assert_equal (isempty (duration), false)

%!assert_equal (isequal (duration (24, 0, 0), days (1)), true)
%!assert_equal (isequal (duration (24, 0, 0), '24:00:00'), true)
%!assert_equal (isequal (duration (24, 0, 0), '24:00:01'), false)
%!assert_equal (isequal (duration (24, 0, 1), {'24:00:01'}), true)
%!assert_equal (isequal (duration (24, 0, 1), {'24:00:00'}), false)
%!assert_equal (isequal (days ([1, 2]), string ({'24:00:00', '48:00:00'})), true)
%!assert_equal (isequal (days ([1, 2]), string ({'24:00:00'; '48:00:00'})), false)
%!assert_equal (isequal (days ([1; 2]), string ({'24:00:00'; '48:00:00'})), true)
%!assert_equal (isequal (days ([1; 2]), string ({'24:00:00', '48:00:00'})), false)
%!assert_equal (isequal (days (ones (2, 3, 4)), days (ones (2, 3, 4))), true)
%!assert_equal (isequal (duration (ones (2, 3, 4) * 24, 0, 0), days (ones (2, 3, 4))), true)
%!assert_equal (isequal (repmat ({'24:00:00'}, 2, 3, 4), days (ones (2, 3, 4))), true)
%!assert_equal (isequal (repmat ({'24:00:05'}, 2, 3, 4), duration (24 * ones (2, 3, 4), 0, 5)), true)
%!assert_equal (isequal (days (1), duration (24, 0, 0), '24:00:00'), true)
%!assert_equal (isequal (days ([1, NaN]), duration ([24, NaN], 0, 0)), false)

%!assert_equal (isequaln (duration (24, 0, 0), days (1)), true)
%!assert_equal (isequaln (duration (24, 0, 0), '24:00:00'), true)
%!assert_equal (isequaln (duration (24, 0, 0), '24:00:01'), false)
%!assert_equal (isequaln (duration (24, 0, 1), {'24:00:01'}), true)
%!assert_equal (isequaln (duration (24, 0, 1), {'24:00:00'}), false)
%!assert_equal (isequaln (days ([1, 2]), string ({'24:00:00', '48:00:00'})), true)
%!assert_equal (isequaln (days ([1, 2]), string ({'24:00:00'; '48:00:00'})), false)
%!assert_equal (isequaln (days ([1; 2]), string ({'24:00:00'; '48:00:00'})), true)
%!assert_equal (isequaln (days ([1; 2]), string ({'24:00:00', '48:00:00'})), false)
%!assert_equal (isequaln (days (ones (2, 3, 4)), days (ones (2, 3, 4))), true)
%!assert_equal (isequaln (duration (ones (2, 3, 4) * 24, 0, 0), days (ones (2, 3, 4))), true)
%!assert_equal (isequaln (repmat ({'24:00:00'}, 2, 3, 4), days (ones (2, 3, 4))), true)
%!assert_equal (isequaln (repmat ({'24:00:05'}, 2, 3, 4), duration (24 * ones (2, 3, 4), 0, 5)), true)
%!assert_equal (isequaln (days (1), duration (24, 0, 0), '24:00:00'), true)
%!assert_equal (isequaln (days ([1, NaN]), duration ([24, NaN], 0, 0)), true)

%!assert_equal (isfinite (days ([1, -Inf, NaN, Inf])), [true, false, false, false])
%!assert_equal (isfinite (days ([1, -Inf; NaN, Inf])), [true, false; false, false])
%!assert_equal (isfinite (days (ones (0, 1))), true (0, 1))
%!assert_equal (isfinite (days (ones (1, 0))), true (1, 0))
%!assert_equal (isfinite (days ([])), true ([]))
%!assert_equal (isfinite (duration (ones (2, 3, 4), 0, 0)), true (2, 3, 4))
%!assert_equal (isfinite (duration (Inf (2, 3, 4), 0, 0)), false (2, 3, 4))
%!assert_equal (isfinite (duration (-Inf (2, 3, 4), 0, 0)), false (2, 3, 4))
%!assert_equal (isfinite (duration (NaN (2, 3, 4), 0, 0)), false (2, 3, 4))

%!assert_equal (isinf (days ([1, -Inf, NaN, Inf])), [false, true, false, true])
%!assert_equal (isinf (days ([1, -Inf; NaN, Inf])), [false, true; false, true])
%!assert_equal (isinf (days (ones (0, 1))), true (0, 1))
%!assert_equal (isinf (days (ones (1, 0))), true (1, 0))
%!assert_equal (isinf (days ([])), true ([]))
%!assert_equal (isinf (duration (ones (2, 3, 4), 0, 0)), false (2, 3, 4))
%!assert_equal (isinf (duration (Inf (2, 3, 4), 0, 0)), true (2, 3, 4))
%!assert_equal (isinf (duration (-Inf (2, 3, 4), 0, 0)), true (2, 3, 4))
%!assert_equal (isinf (duration (NaN (2, 3, 4), 0, 0)), false (2, 3, 4))

%!assert_equal (ismatrix (duration), true)
%!assert_equal (ismatrix (duration ([], [], [])), true)
%!assert_equal (ismatrix (duration (ones (2, 4), 0, 0)), true)
%!assert_equal (ismatrix (duration (ones (2, 4, 1), 0, 0)), true)
%!assert_equal (ismatrix (duration (ones (2, 1, 4), 0, 0)), false)
%!assert_equal (ismatrix (duration (ones (2, 3, 4), 0, 0)), false)
%!assert_equal (ismatrix (days (ones (0, 1))), true)
%!assert_equal (ismatrix (days (ones (1, 0))), true)

%!assert_equal (ismember (days (1), days ([1, 2])), true)
%!assert_equal (ismember (days ([1, 2]), days (1)), [true, false])
%!assert_equal (ismember (days ([1; 2]), days (1)), [true; false])
%!assert_equal (ismember (days (1), days ([1; 2])), true)
%!test
%! [TF, index] = ismember (days (1), days (ones (2, 3, 4)));
%! assert_equal (TF, true);
%! assert_equal (index, 1);
%!test
%! [TF, index] = ismember (days (1), days (ones (2, 3, 4)), 'legacy');
%! assert_equal (TF, true);
%! assert_equal (index, 24);
%!test
%! x = ones (2, 3, 4);
%! x(1) = 2;
%! [TF, index] = ismember (days (1), days (x));
%! assert_equal (TF, true);
%! assert_equal (index, 2); # This is MATLAB incompatible
%!test
%! x = ones (2, 3, 4);
%! x(1) = 2;
%! [TF, index] = ismember (days (1), days (x), 'legacy');
%! assert_equal (TF, true);
%! assert_equal (index, 24);
%!test
%! [TF, index] = ismember (days ([0:4]), days ([1, 2]));
%! assert_equal (TF, [false, true, true, false, false]);
%! assert_equal (index, [0, 1, 2, 0, 0]);
%!test
%! [TF, index] = ismember (days ([0:4]), days ([-1, 2]));
%! assert_equal (TF, [false, false, true, false, false]);
%! assert_equal (index, [0, 0, 2, 0, 0]);
%!test
%! [TF, index] = ismember (days ([0:4]), [-1, 2]);
%! assert_equal (TF, [false, false, true, false, false]);
%! assert_equal (index, [0, 0, 2, 0, 0]);
%!test
%! [TF, index] = ismember (days ([0:4]), {'24:00:00', '18:00:00'});
%! assert_equal (TF, [false, true, false, false, false]);
%! assert_equal (index, [0, 1, 0, 0, 0]);
%!test
%! [TF, index] = ismember (days ([2,3;1,2;-1,2;4,5]), days ([-1, 2]), 'rows');
%! assert_equal (TF, [false; false; true; false]);
%! assert_equal (index, [0; 0; 1; 0]);
%!error<duration.ismember: 'rows' applies only to 2-D matrices.> ...
%! ismember (days (1), days (ones (2, 3, 4)), 'rows')
%!error<duration.ismember: 'rows' requires same number of columns.> ...
%! ismember (days (1), days (ones (2, 3)), 'rows')
%!error<duration.ismember: all options must be character vectors.> ...
%! ismember (days (1), days (1), 3)
%!error<duration.ismember: only 'rows' and 'legacy' are valid options.> ...
%! ismember (days (1), days (1), 'row')

%!assert_equal (ismissing (days ([1, 2, 3, NaN, 5])), logical ([0, 0, 0, 1, 0]))
%!assert_equal (ismissing (days ([1, 2, 3, NaN, 5]), days (1)), logical ([1, 0, 0, 0, 0]))
%!assert_equal (ismissing (days ([1, 2, 3, NaN, 5]), duration (24, 0, 0)), logical ([1, 0, 0, 0, 0]))
%!assert_equal (ismissing (days ([1, 2, 3, NaN, 5]), duration ('48:00:00')), logical ([0, 1, 0, 0, 0]))
%!assert_equal (ismissing (seconds ([1:5]), duration (0, 0, [1:3])), logical ([1, 1, 1, 0, 0]))
%!assert_equal (ismissing (days ([1, 2, 3, NaN, 5]), days ([1, 3])), logical ([1, 0, 1, 0, 0]))
%!assert_equal (ismissing (days ([1, 2, 3, NaN, 5]), days ([1, 6])), logical ([1, 0, 0, 0, 0]))
%!assert_equal (ismissing (days ([1, 2, 3, NaN, 5]), days ([1, 5, 6])), logical ([1, 0, 0, 0, 1]))
%!error<duration.ismissing: too many input arguments.> ...
%! ismissing (days (1), days (1), days (1))
%!error<duration.ismissing: INDICATOR must be a 'duration' array.> ...
%! ismissing (days ([1, 2, 3, NaN, 5]), 5)
%!error<duration.ismissing: INDICATOR must be a 'duration' array.> ...
%! ismissing (days ([1, 2, 3, NaN, 5]), '24:00:00')
%!error<duration.ismissing: INDICATOR must be a 'duration' array.> ...
%! ismissing (days ([1, 2, 3, NaN, 5]), string ('24:00:00'))

%!assert_equal (isnan (minutes ([1:10])), false (1, 10))
%!assert_equal (isnan (days ([1, 2, NaN, 4, NaN])), logical ([0, 0, 1, 0, 1]))
%!assert_equal (isnan (duration (NaN (3, 4, 5), 0, 0)), true (3, 4, 5))
%!assert_equal (isnan (duration (zeros (3, 4, 5), 0, 0)), false (3, 4, 5))

%!assert_equal (isrow (days ([1, 2, 3, 4])), true)
%!assert_equal (isrow (days ([1; 2; 3; 4])), false)
%!assert_equal (isrow (days ([1, 2; 3, 4])), false)
%!assert_equal (isrow (days ([])), false)
%!assert_equal (isrow (days (ones (1, 0))), true)
%!assert_equal (isrow (days (ones (0, 1))), false)
%!assert_equal (isrow (days (1)), true)
%!assert_equal (isrow (days (ones (2, 3, 4))), false)

%!assert_equal (isscalar (days ([])), false)
%!assert_equal (isscalar (days (ones (1, 0))), false)
%!assert_equal (isscalar (days (ones (0, 1))), false)
%!assert_equal (isscalar (days (1)), true)
%!assert_equal (isscalar (days (NaN)), true)
%!assert_equal (isscalar (days ([1, 2])), false)

%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! assert_equal (issorted (sort (D)), true);
%! assert_equal (issorted (sort (D), 'ascend'), true);
%! assert_equal (issorted (sort (D), 'descend'), false);
%! assert_equal (issorted (sort (D), 'monotonic'), true);
%! assert_equal (issorted (sort (D), 'strictascend'), false);
%! assert_equal (issorted (sort (D), 'strictdescend'), false);
%! assert_equal (issorted (sort (D), 'strictmonotonic'), false);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! assert_equal (issorted (sort (D, 2), 2), true);
%! assert_equal (issorted (sort (D, 2), 2, 'ascend'), true);
%! assert_equal (issorted (sort (D, 2), 2, 'descend'), false);
%! assert_equal (issorted (sort (D, 2), 2, 'monotonic'), true);
%! assert_equal (issorted (sort (D, 2), 2, 'strictascend'), true);
%! assert_equal (issorted (sort (D, 2), 2, 'strictdescend'), false);
%! assert_equal (issorted (sort (D, 2), 2, 'strictmonotonic'), true);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! assert_equal (issorted (sort (D, 2), 'ascend'), false);
%! assert_equal (issorted (sort (D, 2), 'descend'), false);
%! assert_equal (issorted (sort (D, 2), 'monotonic'), false);
%! assert_equal (issorted (sort (D, 2), 'strictascend'), false);
%! assert_equal (issorted (sort (D, 2), 'strictdescend'), false);
%! assert_equal (issorted (sort (D, 2), 'strictmonotonic'), false);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! assert_equal (issorted (sort (D, 'descend'), 'ascend'), false);
%! assert_equal (issorted (sort (D, 'descend'), 'descend'), true);
%! assert_equal (issorted (sort (D, 'descend'), 'monotonic'), true);
%! assert_equal (issorted (sort (D, 'descend'), 'strictascend'), false);
%! assert_equal (issorted (sort (D, 'descend'), 'strictdescend'), false);
%! assert_equal (issorted (sort (D, 'descend'), 'strictmonotonic'), false);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! assert_equal (issorted (sort (D, 2, 'descend'), 2, 'ascend'), false);
%! assert_equal (issorted (sort (D, 2, 'descend'), 2, 'descend'), true);
%! assert_equal (issorted (sort (D, 2, 'descend'), 2, 'monotonic'), true);
%! assert_equal (issorted (sort (D, 2, 'descend'), 2, 'strictascend'), false);
%! assert_equal (issorted (sort (D, 2, 'descend'), 2, 'strictdescend'), true);
%! assert_equal (issorted (sort (D, 2, 'descend'), 2, 'strictmonotonic'), true);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! assert_equal (issorted (sort (D, 2, 'descend'), 'ascend'), false);
%! assert_equal (issorted (sort (D, 2, 'descend'), 'descend'), false);
%! assert_equal (issorted (sort (D, 2, 'descend'), 'monotonic'), false);
%! assert_equal (issorted (sort (D, 2, 'descend'), 'strictascend'), false);
%! assert_equal (issorted (sort (D, 2, 'descend'), 'strictdescend'), false);
%! assert_equal (issorted (sort (D, 2, 'descend'), 'strictmonotonic'), false);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! assert_equal (issorted (sort (D, 'ComparisonMethod', 'real')), true);
%! assert_equal (issorted (sort (D, 'ComparisonMethod', 'abs')), false);
%! assert_equal (issorted (sort (D, 'ComparisonMethod', 'abs'), ...
%!                   'ComparisonMethod', 'abs'), true);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! assert_equal (issorted (sort (D, 2, 'ComparisonMethod', 'real'), 2), true);
%! assert_equal (issorted (sort (D, 2, 'ComparisonMethod', 'abs'), 2), false);
%! assert_equal (issorted (sort (D, 2, 'ComparisonMethod', 'abs'), 2, ...
%!                   'ComparisonMethod', 'abs'), true);
%!test
%! D = days ([1, 2; 2, 3; 3, 4; 4, 5]);
%! assert_equal (issorted (sort (D), 'ascend'), true);
%! assert_equal (issorted (sort (D), 'descend'), false);
%! assert_equal (issorted (sort (D), 'monotonic'), true);
%! assert_equal (issorted (sort (D), 'strictascend'), true);
%! assert_equal (issorted (sort (D), 'strictdescend'), false);
%! assert_equal (issorted (sort (D), 'strictmonotonic'), true);
%!test
%! D = days ([1, 2; 2, 3; 3, 4; 4, 5]);
%! assert_equal (issorted (sort (D, 'descend'), 'ascend'), false);
%! assert_equal (issorted (sort (D, 'descend'), 'descend'), true);
%! assert_equal (issorted (sort (D, 'descend'), 'monotonic'), true);
%! assert_equal (issorted (sort (D, 'descend'), 'strictascend'), false);
%! assert_equal (issorted (sort (D, 'descend'), 'strictdescend'), true);
%! assert_equal (issorted (sort (D, 'descend'), 'strictmonotonic'), true);
%!test
%! D = days ([1, 2; 2, 3; 3, 4; 4, NaN]);
%! assert_equal (issorted (sort (D)), true);
%! assert_equal (issorted (sort (D), 'ascend'), true);
%! assert_equal (issorted (sort (D), 'descend'), false);
%! assert_equal (issorted (sort (D), 'monotonic'), true);
%! assert_equal (issorted (sort (D), 'strictascend'), false);
%! assert_equal (issorted (sort (D), 'strictdescend'), false);
%! assert_equal (issorted (sort (D), 'strictmonotonic'), false);
%!test
%! D = days ([1, 2; 2, 3; 3, 4; 4, NaN]);
%! assert_equal (issorted (sort (D, 'descend'), 'ascend'), false);
%! assert_equal (issorted (sort (D, 'descend'), 'descend'), true);
%! assert_equal (issorted (sort (D, 'descend'), 'monotonic'), true);
%! assert_equal (issorted (sort (D, 'descend'), 'strictascend'), false);
%! assert_equal (issorted (sort (D, 'descend'), 'strictdescend'), false);
%! assert_equal (issorted (sort (D, 'descend'), 'strictmonotonic'), false);
%!test
%! D = days ([1, 2; 2, 3; 3, 4; 4, NaN]);
%! assert_equal (issorted (sort (D, 'MissingPlacement', 'auto')), true);
%! assert_equal (issorted (sort (D, 'MissingPlacement', 'first')), false);
%! assert_equal (issorted (sort (D, 'MissingPlacement', 'first'), ...
%!                   'MissingPlacement', 'first'), true);
%!test
%! D = days ([1, 2; 2, 3; 3, 4; 4, NaN]);
%! assert_equal (issorted (sort (D, 'descend', 'MissingPlacement', 'auto'), 'descend'), true);
%! assert_equal (issorted (sort (D, 'descend', 'MissingPlacement', 'last'), 'descend'), false);
%! assert_equal (issorted (sort (D, 'descend', 'MissingPlacement', 'first'), ...
%!                   'descend', 'MissingPlacement', 'first'), true);
%!test
%! D = days ([1, 2; 2, 3; 3, 4; 4, NaN]);
%! assert_equal (issorted (sort (D, 2, 'MissingPlacement', 'auto'), 2), true);
%! assert_equal (issorted (sort (D, 2, 'MissingPlacement', 'first'), 2), false);
%! assert_equal (issorted (sort (D, 2, 'MissingPlacement', 'first'), 2, ...
%!                   'MissingPlacement', 'first'), true);
%!test
%! D = days ([1, 2; 2, 3; 3, 4; 4, NaN]);
%! assert_equal (issorted (sort (D, 2, 'descend', 'MissingPlacement', 'auto'), 2, 'descend'), true);
%! assert_equal (issorted (sort (D, 2, 'descend', 'MissingPlacement', 'last'), 2, 'descend'), false);
%! assert_equal (issorted (sort (D, 2, 'descend', 'MissingPlacement', 'first'), 2, ...
%!                   'descend', 'MissingPlacement', 'first'), true);
%!test
%! D = days ([1, 2; 2, 3; 3, 4; 4, NaN]);
%! assert_equal (issorted (sort (D, 2, string ('ascend'), 'MissingPlacement', 'auto'), 2), true);
%! assert_equal (issorted (sort (D, 2, string ('ascend'), 'MissingPlacement', 'first'), 2), false);
%! assert_equal (issorted (sort (D, 2, string ('ascend'), 'MissingPlacement', 'first'), 2, ...
%!                   'MissingPlacement', 'first'), true);
%!test
%! D = days ([1, 2; 2, 3; 3, 4; 4, NaN]);
%! assert_equal (issorted (sort (D, 2, string ('descend'), 'MissingPlacement', 'auto'), 2, 'descend'), true);
%! assert_equal (issorted (sort (D, 2, string ('descend'), 'MissingPlacement', 'last'), 2, 'descend'), false);
%! assert_equal (issorted (sort (D, 2, string ('descend'), 'MissingPlacement', 'first'), 2, ...
%!                   'descend', 'MissingPlacement', 'first'), true);
%!test
%! D = days ([1, 2; 2, -3; 3, 4; 4, NaN]);
%! assert_equal (issorted (sort (D, 'MissingPlacement', 'auto', ...
%!                         'ComparisonMethod', 'real')), true);
%! assert_equal (issorted (sort (D, 'MissingPlacement', 'auto', ...
%!                         'ComparisonMethod', 'abs')), false);
%! assert_equal (issorted (sort (D, 'MissingPlacement', 'auto', ...
%!                         'ComparisonMethod', 'abs'), 'ComparisonMethod', 'abs'), true);
%! assert_equal (issorted (sort (D, 'MissingPlacement', 'last', ...
%!                         'ComparisonMethod', 'abs')), false);
%! assert_equal (issorted (sort (D, 'MissingPlacement', 'last', ...
%!                         'ComparisonMethod', 'abs'), 'ComparisonMethod', 'abs'), true);
%! assert_equal (issorted (sort (D, 'MissingPlacement', 'first', ...
%!                         'ComparisonMethod', 'abs'), ...
%!                   'MissingPlacement', 'first', 'ComparisonMethod', 'abs'), true);
%!test
%! D = days ([1, 2; 2, -3; 3, 4; 4, NaN]);
%! assert_equal (issorted (sort (D, 'descend', 'MissingPlacement', 'auto', ...
%!                         'ComparisonMethod', 'real'), 'descend'), true);
%! assert_equal (issorted (sort (D, 'descend', 'MissingPlacement', 'auto', ...
%!                         'ComparisonMethod', 'abs'), 'descend'), false);
%! assert_equal (issorted (sort (D, 'descend', 'MissingPlacement', 'auto', ...
%!                         'ComparisonMethod', 'abs'), ...
%!                   'descend', 'ComparisonMethod', 'abs'), true);
%! assert_equal (issorted (sort (D, 'descend', 'MissingPlacement', 'last', ...
%!                         'ComparisonMethod', 'abs'), 'descend'), false);
%! assert_equal (issorted (sort (D, 'descend', 'MissingPlacement', 'last', ...
%!                         'ComparisonMethod', 'abs'), ...
%!                   'descend', 'ComparisonMethod', 'abs'), false);
%! assert_equal (issorted (sort (D, 'descend', 'MissingPlacement', 'first', ...
%!                         'ComparisonMethod', 'abs'), 'descend'), false);
%! assert_equal (issorted (sort (D, 'descend', 'MissingPlacement', 'first', ...
%!                         'ComparisonMethod', 'abs'), ...
%!                   'descend', 'ComparisonMethod', 'abs'), true);
%! assert_equal (issorted (sort (D, 'descend', 'MissingPlacement', 'first', ...
%!                         'ComparisonMethod', 'abs'), 'descend', ...
%!                   'MissingPlacement', 'first', 'ComparisonMethod', 'abs'), true);

%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! assert_equal (issortedrows (sortrows (D)), true);
%! assert_equal (issortedrows (sortrows (D, 1)), true);
%! assert_equal (issortedrows (sortrows (D, 1), -1), false);
%! assert_equal (issortedrows (sortrows (D, 1), 1), true);
%! assert_equal (issortedrows (sortrows (D, 2)), false);
%! assert_equal (issortedrows (sortrows (D, 2), 2), true);
%! assert_equal (issortedrows (sortrows (D, 2), -2), false);
%! assert_equal (issortedrows (sortrows (D, -2), 2), false);
%! assert_equal (issortedrows (sortrows (D, -2), -2), true);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! assert_equal (issortedrows (sortrows (D, 'ComparisonMethod', 'abs')), false);
%! assert_equal (issortedrows (sortrows (D, 'ComparisonMethod', 'real')), true);
%! assert_equal (issortedrows (sortrows (D, 'ComparisonMethod', 'abs'), ...
%!                       'ComparisonMethod', 'abs'), true);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! assert_equal (issortedrows (sortrows (D, 2, 'ComparisonMethod', 'abs'), 2), false);
%! assert_equal (issortedrows (sortrows (D, 2, 'ComparisonMethod', 'real'), 2), true);
%! assert_equal (issortedrows (sortrows (D, 2, 'ComparisonMethod', 'abs'), 2, ...
%!                       'ComparisonMethod', 'abs'), true);
%! assert_equal (issortedrows (sortrows (D, [1, 2], 'ComparisonMethod', 'abs'), ...
%!                       {'ascend', 'ascend'}), false);
%! assert_equal (issortedrows (sortrows (D, [1, 2], 'ComparisonMethod', 'abs'), ...
%!                       {'ascend', 'ascend'}, 'ComparisonMethod', 'abs'), true);
%! assert_equal (issortedrows (sortrows (D, 2, 'ComparisonMethod', 'real'), 2), true);
%! assert_equal (issortedrows (sortrows (D, [1, 2], 'ComparisonMethod', 'real'), ...
%!                       {'ascend', 'ascend'}, 'ComparisonMethod', 'auto'), true);
%! assert_equal (issortedrows (sortrows (D, [-1, 2], 'ComparisonMethod', 'abs'), ...
%!                       {'ascend', 'ascend'}, 'ComparisonMethod', 'abs'), false);
%! assert_equal (issortedrows (sortrows (D, 2, 'ComparisonMethod', 'real'), -2), false);
%! assert_equal (issortedrows (sortrows (D, [1, 2], 'ComparisonMethod', 'real'), ...
%!                       {'ascend', 'descend'}, 'ComparisonMethod', 'auto'), false);
%! assert_equal (issortedrows (sortrows (D, [1, -2], 'ComparisonMethod', 'real'), ...
%!                       {'ascend', 'descend'}, 'ComparisonMethod', 'auto'), true);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! assert_equal (issortedrows (sortrows (D, [1, 2], 'ComparisonMethod', 'abs'), ...
%!                       [1, 2], string ({'ascend', 'ascend'})), false);
%! assert_equal (issortedrows (sortrows (D, [1, 2], 'ComparisonMethod', 'abs'), ...
%!                       [1, 2], string ({'ascend', 'ascend'}), ...
%!                       'ComparisonMethod', 'abs'), true);
%! assert_equal (issortedrows (sortrows (D, [1, 2], 'ComparisonMethod', 'abs'), ...
%!                       [1, -2], string ({'ascend', 'ascend'}), ...
%!                       'ComparisonMethod', 'abs'), true);
%! assert_equal (issortedrows (sortrows (D, [1, 2], 'ComparisonMethod', 'real'), ...
%!                       [1, 2], string ({'ascend', 'ascend'}), ...
%!                       'ComparisonMethod', 'auto'), true);
%! assert_equal (issortedrows (sortrows (D, [1, -2], string ({'ascend', 'ascend'}), ...
%!                                 'ComparisonMethod', 'real'), ...
%!                       [1, 2], string ({'ascend', 'ascend'}), ...
%!                       'ComparisonMethod', 'auto'), true);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! assert_equal (issortedrows (sortrows (D)), true);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! assert_equal (issortedrows (sortrows (D, -2, 'MissingPlacement', 'first')), false);
%! assert_equal (issortedrows (sortrows (D, -2, 'MissingPlacement', 'first'), -2), true);
%! assert_equal (issortedrows (sortrows (D, -2, 'MissingPlacement', 'last'), -2), false);
%! assert_equal (issortedrows (sortrows (D, -2, 'MissingPlacement', 'last'), -2, ...
%!                       'MissingPlacement', 'last'), true);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! assert_equal (issortedrows (sortrows (D, 2, 'MissingPlacement', 'last')), false);
%! assert_equal (issortedrows (sortrows (D, 2, 'MissingPlacement', 'last'), 2), true);
%! assert_equal (issortedrows (sortrows (D, 2, 'MissingPlacement', 'first'), 2), false);
%! assert_equal (issortedrows (sortrows (D, 2, 'MissingPlacement', 'first'), 2, ...
%!                       'MissingPlacement', 'first'), true);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! assert_equal (issortedrows (sortrows (D, 'ComparisonMethod', 'abs', ...
%!                                 'MissingPlacement', 'first'), ...
%!                       'ComparisonMethod', 'abs', ...
%!                       'MissingPlacement', 'first'), true);
%! assert_equal (issortedrows (sortrows (D, 'ComparisonMethod', 'abs', ...
%!                                 'MissingPlacement', 'last'), ...
%!                       'ComparisonMethod', 'abs', ...
%!                       'MissingPlacement', 'first'), false);
%! assert_equal (issortedrows (sortrows (D, 'ComparisonMethod', 'abs', ...
%!                                 'MissingPlacement', 'last'), ...
%!                       'ComparisonMethod', 'abs', ...
%!                       'MissingPlacement', 'auto'), true);
%! assert_equal (issortedrows (sortrows (D, 'ComparisonMethod', 'abs', ...
%!                                 'MissingPlacement', 'last'), ...
%!                       'ComparisonMethod', 'abs'), true);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! assert_equal (issortedrows (sortrows (D, [1, -2, 3]), [1, -2, 3]), true);
%! assert_equal (issortedrows (sortrows (D, [1, 2, -3]), [1, -2, 3]), false);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! assert_equal (issortedrows (sortrows (D, string ({'ascend', 'descend', 'ascend'})), ...
%!                       string ({'ascend', 'descend', 'ascend'})), true);
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! assert_equal (issortedrows (sortrows (D, string ({'ascend', 'descend', 'ascend'})), ...
%!                       string ({'descend', 'ascend', 'ascend'})), false);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! assert_equal (issortedrows (sortrows (D, [2, 3], string ({'descend', 'ascend'})), ...
%!                       [2, 3], string ({'descend', 'ascend'})), true);
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! assert_equal (issortedrows (sortrows (D, [2, 3], string ({'ascend', 'descend'})), ...
%!                       [2, -3]), true);
%! assert_equal (issortedrows (sortrows (D, [2, 3], string ({'descend', 'descend'})), ...
%!                       [2, -3], string ({'descend', 'ascend'})), false);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! assert_equal (issortedrows (sortrows (D, [1, -2, 3], 'MissingPlacement', 'first'), ...
%!         [1, -2, 3], 'MissingPlacement', 'first'), true);
%! assert_equal (issortedrows (sortrows (D, [-1, -2, -3], 'MissingPlacement', 'first'), ...
%!         [-1, -2, -3]), true);
%! assert_equal (issortedrows (sortrows (D, [-1, -2, -3], 'MissingPlacement', 'first'), ...
%!         [1, -2,-3], string ({'descend', 'descend', 'descend'})), true);
%!test  ## strict issortedrows semantics, verified against MATLAB R2026a
%! assert_equal (issortedrows (days ([1, 3; 1, 4]), 'strictascend'), false);
%! assert_equal (issortedrows (days ([1, 3; 1, 3]), 'strictascend'), false);
%! assert_equal (issortedrows (days ([1, 3; 1, 4]), {'strictascend', 'ascend'}), false);
%! assert_equal (issortedrows (days ([1, 3; 2, 3]), {'ascend', 'strictascend'}), true);
%! assert_equal (issortedrows (days ([2, 4; 1, 3]), 'monotonic'), true);
%! assert_equal (issortedrows (days ([2, 4; 1, 3]), 'descend'), true);
%! assert_equal (issortedrows (days ([1, 4; 2, 3]), 2, 'strictascend'), false);
%! assert_equal (issortedrows (days ([2, 3; 1, 4]), 2, 'strictascend'), true);
%!test  ## strict issortedrows with missing values (vs MATLAB R2026a)
%! assert_equal (issortedrows (days ([1, 3; NaN, 4]), {'strictascend', 'ascend'}), false);
%! assert_equal (issortedrows (days ([1, 3; NaN, 4]), {'ascend', 'strictascend'}), true);
%! assert_equal (issortedrows (days ([NaN, 3; 2, 4]), 2, 'strictascend'), true);
%! assert_equal (issortedrows (days ([1, NaN; 2, 4]), 'strictascend'), true);

%!assert_equal (isvector (days ([1, 2, 3, 4])), true)
%!assert_equal (isvector (days ([1; 2; 3; 4])), true)
%!assert_equal (isvector (days ([1, 2; 3, 4])), false)
%!assert_equal (isvector (days ([])), false)
%!assert_equal (isvector (days (ones (1, 0))), true)
%!assert_equal (isvector (days (ones (0, 1))), true)
%!assert_equal (isvector (days (1)), true)
%!assert_equal (isvector (days (ones (2, 3, 4))), false)

################################################################################
##                        ** Relational Operations **                         ##
################################################################################
##                             Available Methods                              ##
##                                                                            ##
## 'eq'               'ge'               'gt'               'le'              ##
## 'lt'               'ne'                                                    ##
##                                                                            ##
################################################################################

%!assert_equal (duration (1, 0, 0) == '01:00:00', true)
%!assert_equal (duration (1, 0, 0) == '01:00:01', false)
%!assert_equal (duration (1, 0, 0) == {'01:00:00'}, true)
%!assert_equal (duration (1, 0, 1) == {'01:00:00'}, false)
%!assert_equal (duration (1, 0, 0) == string ('01:00:00'), true)
%!assert_equal (duration (NaN, 0, 0) == string ('01:00:00'), false)
%!assert_equal (duration (24, 0, 0) == 1, true)
%!assert_equal (duration (NaN, 0, 0) == NaN, false)
%!assert_equal (duration (24, 0, 0) == days (1), true)
%!assert_equal ('01:00:00' == duration (1, 0, 0), true)
%!assert_equal ({'01:00:00'} == duration (1, 0, 0), true)
%!assert_equal (string ('01:00:00') == duration (1, 0, 0), true)
%!assert_equal (1 == duration (24, 0, 0), true)
%!assert_equal (days (1) == duration (24, 0, 0), true)
%!assert_equal (days (NaN) == duration (NaN, 0, 0), false)
%!assert_equal (duration (1, 0, 0) == hours (1), true)
%!assert_equal (duration (0, 1, 0) == minutes (1), true)
%!assert_equal (duration (0, 0, 1) == seconds (1), true)
%!assert_equal (days ([1, 2]) == 1, [true, false])
%!assert_equal (days ([1; 2]) == 1, [true; false])
%!assert_equal (days ([1, 2]) == [1, 2], [true, true])
%!assert_equal (days ([1, 2]) == [1; 2], logical (eye (2)))

%!assert_equal (duration (1, 0, 0) >= '01:00:00', true)
%!assert_equal (duration (1, 0, 0) >= '01:00:01', false)
%!assert_equal (duration (1, 0, 0) >= {'01:00:00'}, true)
%!assert_equal (duration (1, 0, 1) >= {'01:00:00'}, true)
%!assert_equal (duration (1, 0, 0) >= string ('01:00:00'), true)
%!assert_equal (duration (NaN, 0, 0) >= string ('01:00:00'), false)
%!assert_equal (duration (24, 0, 0) >= 1, true)
%!assert_equal (duration (NaN, 0, 0) >= NaN, false)
%!assert_equal (duration (24, 0, 0) >= days (1), true)
%!assert_equal ('01:00:00' >= duration (1, 0, 0), true)
%!assert_equal ('01:00:00' >= duration (1, 0, 1), false)
%!assert_equal ({'01:00:00'} >= duration (1, 0, 0), true)
%!assert_equal (string ('01:00:00') >= duration (1, 0, 0), true)
%!assert_equal (string ('01:00:01') >= duration (1, 0, 0), true)
%!assert_equal (string ('01:00:00') >= duration (1, 1, 0), false)
%!assert_equal (1 >= duration (24, 0, 0), true)
%!assert_equal (days (1) >= duration (24, 0, 0), true)
%!assert_equal (days (NaN) >= duration (NaN, 0, 0), false)
%!assert_equal (duration (1, 0, 0) >= hours (1), true)
%!assert_equal (duration (0, 1, 0) >= minutes (1), true)
%!assert_equal (duration (0, 0, 1) >= seconds (1), true)
%!assert_equal (days ([1, 2]) >= 1, [true, true])
%!assert_equal (days ([1; 2]) >= 1, [true; true])
%!assert_equal (days ([1, 2]) >= [1, 2], [true, true])
%!assert_equal (days ([1, 2]) >= [1; 2], [true, true; false, true])

%!assert_equal (duration (1, 0, 0) > '01:00:00', false)
%!assert_equal (duration (1, 0, 0) > '01:00:01', false)
%!assert_equal (duration (1, 0, 0) > {'01:00:00'}, false)
%!assert_equal (duration (1, 0, 1) > {'01:00:00'}, true)
%!assert_equal (duration (1, 0, 0) > string ('01:00:00'), false)
%!assert_equal (duration (NaN, 0, 0) > string ('01:00:00'), false)
%!assert_equal (duration (24, 0, 0) > 1, false)
%!assert_equal (duration (NaN, 0, 0) > NaN, false)
%!assert_equal (duration (24, 0, 0) > days (1), false)
%!assert_equal (duration (24, 0, 1) > days (1), true)
%!assert_equal ('01:00:00' > duration (1, 0, 0), false)
%!assert_equal ('01:00:01' > duration (1, 0, 0), true)
%!assert_equal ('01:00:00' > duration (1, 0, 1), false)
%!assert_equal ({'01:00:00'} > duration (1, 0, 0), false)
%!assert_equal (string ('01:00:00') > duration (1, 0, 0), false)
%!assert_equal (string ('01:00:01') > duration (1, 0, 0), true)
%!assert_equal (string ('01:00:00') > duration (1, 1, 0), false)
%!assert_equal (1 > duration (24, 0, 0), false)
%!assert_equal (days (1) > duration (24, 0, 0), false)
%!assert_equal (days (1.05) > duration (24, 0, 0), true)
%!assert_equal (days (NaN) > duration (NaN, 0, 0), false)
%!assert_equal (duration (1, 0, 0) > hours (1), false)
%!assert_equal (duration (0, 1, 0) > minutes (1), false)
%!assert_equal (duration (0, 0, 1) > seconds (1), false)
%!assert_equal (days ([1, 2]) > 1, [false, true])
%!assert_equal (days ([1; 2]) > 1, [false; true])
%!assert_equal (days ([1, 2]) > [1, 2], [false, false])
%!assert_equal (days ([1, 2]) > [1; 2], [false, true; false, false])

%!assert_equal (duration (1, 0, 0) <= '01:00:00', true)
%!assert_equal (duration (1, 0, 0) <= '01:00:01', true)
%!assert_equal (duration (1, 0, 0) <= {'01:00:00'}, true)
%!assert_equal (duration (1, 0, 1) <= {'01:00:00'}, false)
%!assert_equal (duration (1, 0, 0) <= string ('01:00:00'), true)
%!assert_equal (duration (NaN, 0, 0) <= string ('01:00:00'), false)
%!assert_equal (duration (24, 0, 0) <= 1, true)
%!assert_equal (duration (NaN, 0, 0) <= NaN, false)
%!assert_equal (duration (24, 0, 0) <= days (1), true)
%!assert_equal ('01:00:00' <= duration (1, 0, 0), true)
%!assert_equal ('01:00:00' <= duration (1, 0, 1), true)
%!assert_equal ({'01:00:00'} <= duration (1, 0, 0), true)
%!assert_equal (string ('01:00:00') <= duration (1, 0, 0), true)
%!assert_equal (string ('01:00:01') <= duration (1, 0, 0), false)
%!assert_equal (string ('01:00:00') <= duration (1, 1, 0), true)
%!assert_equal (1 <= duration (24, 0, 0), true)
%!assert_equal (days (1) <= duration (24, 0, 0), true)
%!assert_equal (days (NaN) <= duration (NaN, 0, 0), false)
%!assert_equal (duration (1, 0, 0) <= hours (1), true)
%!assert_equal (duration (0, 1, 0) <= minutes (1), true)
%!assert_equal (duration (0, 0, 1) <= seconds (1), true)
%!assert_equal (days ([1, 2]) <= 1, [true, false])
%!assert_equal (days ([1; 2]) <= 1, [true; false])
%!assert_equal (days ([1, 2]) <= [1, 2], [true, true])
%!assert_equal (days ([1, 2]) <= [1; 2], [true, false; true, true])

%!assert_equal (duration (1, 0, 0) < '01:00:00', false)
%!assert_equal (duration (1, 0, 0) < '01:00:01', true)
%!assert_equal (duration (1, 0, 0) < {'01:00:00'}, false)
%!assert_equal (duration (1, 0, 1) < {'01:00:00'}, false)
%!assert_equal (duration (1, 0, 0) < string ('01:00:00'), false)
%!assert_equal (duration (NaN, 0, 0) < string ('01:00:00'), false)
%!assert_equal (duration (24, 0, 0) < 1, false)
%!assert_equal (duration (NaN, 0, 0) < NaN, false)
%!assert_equal (duration (24, 0, 0) < days (1), false)
%!assert_equal (duration (24, 0, 1) < days (1), false)
%!assert_equal ('01:00:00' < duration (1, 0, 0), false)
%!assert_equal ('01:00:01' < duration (1, 0, 0), false)
%!assert_equal ('01:00:00' < duration (1, 0, 1), true)
%!assert_equal ({'01:00:00'} < duration (1, 0, 0), false)
%!assert_equal (string ('01:00:00') < duration (1, 0, 0), false)
%!assert_equal (string ('01:00:01') < duration (1, 0, 0), false)
%!assert_equal (string ('01:00:00') < duration (1, 1, 0), true)
%!assert_equal (1 < duration (24, 0, 0), false)
%!assert_equal (days (1) < duration (24, 0, 0), false)
%!assert_equal (days (1.05) < duration (24, 0, 0), false)
%!assert_equal (days (NaN) < duration (NaN, 0, 0), false)
%!assert_equal (duration (1, 0, 0) < hours (1), false)
%!assert_equal (duration (0, 1, 0) < minutes (1), false)
%!assert_equal (duration (0, 0, 1) < seconds (1), false)
%!assert_equal (days ([1, 2]) < 1, [false, false])
%!assert_equal (days ([1; 2]) < 1, [false; false])
%!assert_equal (days ([1, 2]) < [1, 2], [false, false])
%!assert_equal (days ([1, 2]) < [1; 2], [false, false; true, false])

%!assert_equal (duration (1, 0, 0) != '01:00:00', false)
%!assert_equal (duration (1, 0, 0) != '01:00:01', true)
%!assert_equal (duration (1, 0, 0) != {'01:00:00'}, false)
%!assert_equal (duration (1, 0, 1) != {'01:00:00'}, true)
%!assert_equal (duration (1, 0, 0) != string ('01:00:00'), false)
%!assert_equal (duration (NaN, 0, 0) != string ('01:00:00'), true)
%!assert_equal (duration (24, 0, 0) != 1, false)
%!assert_equal (duration (NaN, 0, 0) != NaN, true)
%!assert_equal (duration (24, 0, 0) != days (1), false)
%!assert_equal ('01:00:00' != duration (1, 0, 0), false)
%!assert_equal ({'01:00:00'} != duration (1, 0, 0), false)
%!assert_equal (string ('01:00:00') != duration (1, 0, 0), false)
%!assert_equal (1 != duration (24, 0, 0), false)
%!assert_equal (days (1) != duration (24, 0, 0), false)
%!assert_equal (days (NaN) != duration (NaN, 0, 0), true)
%!assert_equal (duration (1, 0, 0) != hours (1), false)
%!assert_equal (duration (0, 1, 0) != minutes (1), false)
%!assert_equal (duration (0, 0, 1) != seconds (1), false)
%!assert_equal (days ([1, 2]) != 1, [false, true])
%!assert_equal (days ([1; 2]) != 1, [false; true])
%!assert_equal (days ([1, 2]) != [1, 2], [false, false])
%!assert_equal (days ([1, 2]) != [1; 2], [false, true; true, false])

################################################################################
##                       ** Mathematical Operations **                        ##
################################################################################
##                             Available Methods                              ##
##                                                                            ##
## 'abs'              'plus'             'uplus'            'minus'           ##
## 'uminus'           'times'            'mtimes'           'ldivide'         ##
## 'rdivide'          'mldivide'         'mrdivide'         'mod'             ##
## 'rem'              'eps'              'colon'            'linspace'        ##
## 'sign'                                                                     ##
## 'sum'              'cumsum'           'diff'             'min'             ##
## 'max'              'cummin'           'cummax'           'floor'           ##
## 'ceil'             'round'                                                 ##
##                                                                            ##
################################################################################

%!assert_equal (days (abs (days ([1, -1, NaN, -Inf, Inf]))), [1, 1, NaN, Inf, Inf])
%!assert_equal (days (abs (days (- ones (2, 3, 4)))), ones (2, 3, 4))

%!assert_equal (days (days ([1, 2; NaN, Inf]) + [2, 3]), [3, 5; NaN, Inf])
%!assert_equal (days (days ([1, 2; NaN, Inf]) + days ([2, 3])), [3, 5; NaN, Inf])
%!assert_equal (days ([2, 3] + days ([1, 2; NaN, Inf])), [3, 5; NaN, Inf])
%!assert_equal (days (days ([2, 3]) + days ([1, 2; NaN, Inf])), [3, 5; NaN, Inf])
%!assert_equal (caldays (days (1) + calendarDuration), 0)
%!assert_equal (caldays (days (1) + calendarDuration (0, 0, 1)), 1)
%!assert_equal (hours (time (days (1) + calendarDuration)), 24)
%!assert_equal (hours (time (days (1) + calendarDuration (0, 0, 1))), 24)
%!assert_equal (class (days (1) + calendarDuration), 'calendarDuration')
%!error<duration: addition is not defined between 'duration' and 'char' arrays.> ...
%! days (1) + '24:00:00'
%!error<duration: addition is not defined between 'duration' and 'cell' arrays.> ...
%! days (1) + {'24:00:00'}
%!error<duration: addition is not defined between 'duration' and 'string' arrays.> ...
%! days (1) + string('24:00:00')

## mod: remainder takes the sign of the divisor.  Asserted in days, the unit a
## duration stores, so the arithmetic is exact; the same in hours carries the
## rounding of 7/24 and needs a tolerance.
%!assert_equal (days (mod (days ([7, -7, 7, -7]), days ([2, 2, -2, -2]))), ...
%!              [1, 1, -1, -1])
%!assert_equal (days (mod (days ([1, 2, 3]), days (2))), [1, 0, 1])
%!assert_equal (hours (mod (hours ([7, -7, 7, -7]), hours ([2, 2, -2, -2]))), ...
%!              [1, 1, -1, -1], 1e-9)
## mod: a numeric operand counts days, on either side
%!assert_equal (hours (mod (hours (7), 2)), 7, 1e-9)
%!assert_equal (hours (mod (7, hours (2))), 0, 1e-9)
%!assert_equal (hours (mod (hours (7), days (1))), 7, 1e-9)
## mod: a zero divisor leaves the dividend, and NaN carries through either side
%!assert_equal (days (mod (days (7), days (0))), 7)
%!assert_equal (days (mod (days (NaN), days (2))), NaN)
%!assert_equal (days (mod (days (7), days (NaN))), NaN)
## mod: the display format comes from the duration operand
%!assert_equal (mod (hours (7), hours (2)).Format, 'h')
%!assert_equal (mod (7, hours (2)).Format, 'h')
%!test
%! x = days (3);
%! x.Format = 'h';
%! assert_equal (mod (x, days (2)).Format, 'h');
## mod: shape is kept for an array of any number of dimensions
%!assert_equal (size (mod (hours (reshape (1:8, 2, 2, 2)), hours (3))), [2, 2, 2])
%!assert_equal (days (mod (days (reshape (1:8, 2, 2, 2)), days (3))), ...
%!              mod (reshape (1:8, 2, 2, 2), 3))
## mod: anything that is not a duration or numeric is refused
%!error<duration: 'mod' is not defined between 'duration' and 'calendarDuration' arrays.> ...
%! mod (hours (7), calmonths (1))
%!error<duration: 'mod' is not defined between 'duration' and 'char' arrays.> ...
%! mod (hours (7), '2')
%!error<duration: 'mod' is not defined between 'cell' and 'duration' arrays.> ...
%! mod ({2}, hours (7))

## rem: remainder takes the sign of the dividend, where mod takes the divisor's
%!assert_equal (days (rem (days ([7, -7, 7, -7]), days ([2, 2, -2, -2]))), ...
%!              [1, -1, 1, -1])
%!assert_equal (days (rem (days ([1, 2, 3]), days (2))), [1, 0, 1])
%!assert_equal (hours (rem (hours ([7, -7, 7, -7]), hours ([2, 2, -2, -2]))), ...
%!              [1, -1, 1, -1], 1e-9)
## rem: the two agree only where the operands share a sign, and part ways on a
## zero divisor, where rem is NaN and mod is the dividend
%!test
%! a = days ([7, -7, 7, -7]);
%! b = days ([2, 2, -2, -2]);
%! assert_equal (days (mod (a, b)) == days (rem (a, b)), logical ([1, 0, 0, 1]));
%!assert_equal (days (rem (days (7), days (0))), NaN)
%!assert_equal (days (mod (days (7), days (0))), 7)
## rem: a numeric operand counts days, on either side
%!assert_equal (hours (rem (hours (7), 2)), 7, 1e-9)
%!assert_equal (hours (rem (7, hours (2))), 0, 1e-9)
%!assert_equal (hours (rem (hours (7), days (1))), 7, 1e-9)
## rem: NaN carries through from either side
%!assert_equal (days (rem (days (NaN), days (2))), NaN)
%!assert_equal (days (rem (days (7), days (NaN))), NaN)
## rem: the display format comes from the duration operand
%!assert_equal (rem (hours (7), hours (2)).Format, 'h')
%!assert_equal (rem (7, hours (2)).Format, 'h')
%!test
%! x = days (3);
%! x.Format = 'h';
%! assert_equal (rem (x, days (2)).Format, 'h');
## rem: shape is kept for an array of any number of dimensions
%!assert_equal (days (rem (days (reshape (1:8, 2, 2, 2)), days (3))), ...
%!              rem (reshape (1:8, 2, 2, 2), 3))
## rem: anything that is not a duration or numeric is refused
%!error<duration: 'rem' is not defined between 'duration' and 'calendarDuration' arrays.> ...
%! rem (hours (7), calmonths (1))
%!error<duration: 'rem' is not defined between 'duration' and 'char' arrays.> ...
%! rem (hours (7), '2')
%!error<duration: 'rem' is not defined between 'cell' and 'duration' arrays.> ...
%! rem ({2}, hours (7))

## mldivide: the denominator decides the result.  A number scales the duration;
## a duration gives how many times one goes into the other, without a unit.
%!assert_equal (days (mldivide (2, days (6))), 3)
%!assert_equal (class (mldivide (2, days (6))), 'duration')
%!assert_equal (mldivide (days (2), days (6)), 3)
%!assert_equal (class (mldivide (days (2), days (6))), 'double')
%!assert_equal (mldivide (days (2), days ([6, 8])), [3, 4])
%!assert_equal (days (2 \ days (6)), 3)
## mldivide: a zero denominator gives Inf, and NaN carries through
%!assert_equal (mldivide (days (0), days (6)), Inf)
%!assert_equal (days (mldivide (0, days (6))), Inf)
%!assert_equal (days (mldivide (2, days (NaN))), NaN)
## mldivide: the format of a duration result is the numerator's
%!assert_equal (mldivide (2, hours (6)).Format, 'h')
## mldivide: a logical or integer denominator is converted, an Octave extension
%!assert_equal (days (mldivide (true, days (6))), 6)
%!assert_equal (days (mldivide (int32 (2), days (6))), 3)
## mldivide: the denominator must be scalar and real, and dividing a number by
## a duration has no meaning
%!error<duration: left division of a 'double' array by a duration is not defined.> ...
%! mldivide (days (2), 6)
%!error<duration: the denominator in left division must be a scalar.> ...
%! mldivide ([1, 2], days ([6, 8]))
%!error<duration: the denominator in left division must be a scalar.> ...
%! mldivide (days ([1, 2]), days ([6, 8]))
%!error<duration: the denominator in left division must be real.> ...
%! mldivide (2 + 1i, days (6))
%!error<duration: left division of a 'calendarDuration' array by a duration is not defined.> ...
%! mldivide (days (6), calmonths (1))
%!error<duration: left division is not defined between 'cell' and 'duration' arrays.> ...
%! mldivide ({2}, days (6))

## mrdivide: the mirror of mldivide, the denominator deciding the result
%!assert_equal (days (mrdivide (days (6), 2)), 3)
%!assert_equal (class (mrdivide (days (6), 2)), 'duration')
%!assert_equal (mrdivide (days (6), days (2)), 3)
%!assert_equal (class (mrdivide (days (6), days (2))), 'double')
%!assert_equal (mrdivide (days ([6, 8]), days (2)), [3, 4])
%!assert_equal (days (days (6) / 2), 3)
## mrdivide: A / B is B \ A, which is what makes it the mirror
%!test
%! a = days ([6, -8, 0, NaN]);
%! assert_equal (mrdivide (a, days (2)), mldivide (days (2), a));
%! assert_equal (days (mrdivide (a, 4)), days (mldivide (4, a)));
## mrdivide: a zero denominator gives Inf, and NaN carries through
%!assert_equal (days (mrdivide (days (6), 0)), Inf)
%!assert_equal (days (mrdivide (days (NaN), 2)), NaN)
%!assert_equal (mrdivide (days (6), days (0)), Inf)
## mrdivide: format kept, and a logical or integer denominator is converted
%!assert_equal (mrdivide (hours (6), 2).Format, 'h')
%!assert_equal (days (mrdivide (days (6), true)), 6)
%!assert_equal (days (mrdivide (days (6), int32 (2))), 3)
## mrdivide: the denominator must be scalar and real; use rdivide to divide by
## an array of divisors
%!error<duration: right division of a 'double' array by a duration is not defined.> ...
%! mrdivide (6, days (2))
%!error<duration: the denominator in right division must be a scalar.> ...
%! mrdivide (days ([6, 8]), [1, 2])
%!error<duration: the denominator in right division must be a scalar.> ...
%! mrdivide (days (6), days ([1, 2]))
%!error<duration: the denominator in right division must be real.> ...
%! mrdivide (days (6), 2 + 1i)
%!error<duration: right division is not defined between 'duration' and 'cell' arrays.> ...
%! mrdivide (days (6), {2})

## eps: the spacing of the milliseconds a duration is stored in, which is what
## MATLAB stores too.  Every figure below is bit-exact against R2024a.
%!assert_equal (class (eps (hours (1))), 'duration')
%!assert_equal (milliseconds (eps (days (1))), eps (86400000))
%!assert_equal (milliseconds (eps (hours (1))), eps (3600000))
%!assert_equal (milliseconds (eps (days ([1, 2, 4]))), ...
%!               eps ([1, 2, 4] * 86400000))
%!assert_equal (seconds (eps (seconds (1))), 1.1368683772161603e-16)
%!assert_equal (seconds (eps (seconds (3600))), 4.6566128730773927e-13)
%!assert_equal (seconds (eps (seconds (1e9))), 1.220703125e-07)
## eps: a negative duration has the spacing of its magnitude, and NaN gives NaN
%!assert_equal (milliseconds (eps (days (-5))), eps (5 * 86400000))
%!assert_equal (days (eps (days (NaN))), NaN)
## eps: format and shape are kept
%!assert_equal (eps (hours (1)).Format, 'h')
%!assert_equal (size (eps (days (reshape (1:8, 2, 2, 2)))), [2, 2, 2])
%!assert_equal (milliseconds (eps (days (reshape (1:8, 2, 2, 2)))), ...
%!              eps (reshape (1:8, 2, 2, 2) * 86400000))

## datenum: the length in days, the same value days() gives under the name the
## older date functions use
%!assert_equal (datenum (hours (24)), 1)
%!assert_equal (class (datenum (hours (24))), 'double')
%!assert_equal (datenum (days ([1, 2.5])), [1, 2.5])
%!assert_equal (datenum (days (NaN)), NaN)
%!assert_equal (datenum (hours ([1, 2, 3])), days (hours ([1, 2, 3])))
%!assert_equal (size (datenum (days (reshape (1:8, 2, 2, 2)))), [2, 2, 2])
## datenum: it counts elapsed days, so adding it to a serial date shifts that
## date by the duration
%!assert_equal (datenum (2024, 1, 1) + datenum (hours (36)), ...
%!              datenum (2024, 1, 2) + 0.5)

## isregular: evenly spaced, in either direction, with the step as second output
%!test
%! [tf, dt] = isregular (hours ([1, 2, 3]));
%! assert_equal (tf, true);
%! assert_equal (char (dt), '1 hr');
%!test
%! [tf, dt] = isregular (hours ([3, 2, 1]));
%! assert_equal (tf, true);
%! assert_equal (char (dt), '-1 hr');
%!assert_equal (isregular (hours ([1, 2])), true)
%!assert_equal (isregular (hours ([1; 2; 3])), true)
%!assert_equal (isregular (hours ([-3, -2, -1])), true)
%!assert_equal (isregular (hours ([1, 2, 4])), false)
## isregular: a vector that does not move has no spacing, so it is not regular
%!test
%! [tf, dt] = isregular (hours ([2, 2, 2]));
%! assert_equal (tf, false);
%! assert_equal (isnan (dt), true);
%!assert_equal (isregular (hours ([5, 5])), false)
## isregular: a NaN or an infinite element makes it irregular, as does having
## fewer than two elements
%!assert_equal (isregular (hours ([1, NaN, 3])), false)
%!assert_equal (isregular (hours ([1, 2, NaN])), false)
%!assert_equal (isregular (hours ([1, Inf, 3])), false)
%!assert_equal (isregular (hours ([Inf, Inf])), false)
%!assert_equal (isregular (hours (5)), false)
%!assert_equal (isregular (hours ([])), false)
%!assert_equal (isregular (hours (zeros (1, 0))), false)
## isregular: steps are compared within a few eps, since subtracting durations
## rounds; one, two and three hours differ in the last bit and are still regular
%!assert_equal (isregular (hours ([1, 2, 3 + 1e-15])), true)
%!assert_equal (isregular (hours ([1, 2, 3 + 1e-14])), false)
%!assert_equal (isregular (hours ([1, 2, 3 + 1e-9])), false)
%!assert_equal (isregular (hours ([0, 1/3, 2/3])), true)
## isregular: the step keeps the vector's own format, in either direction
%!test
%! [~, dt] = isregular (days ([1, 2, 3]));
%! assert_equal (dt.Format, 'd');
%! assert_equal (char (dt), '1 day');
%!test
%! [~, dt] = isregular (seconds ([3, 2, 1]));
%! assert_equal (dt.Format, 's');
%! assert_equal (char (dt), '-1 sec');
## isregular: only elapsed time can be regular, a duration having no calendar,
## so every calendar component is false however the vector is spaced
%!assert_equal (isregular (hours ([1, 2, 3]), 'time'), true)
%!assert_equal (isregular (hours ([1, 2, 3]), 'days'), false)
%!assert_equal (isregular (days ([1, 2, 3]), 'days'), false)
%!assert_equal (isregular (days ([1, 2, 3]), 'Time'), true)
%!assert_equal (isregular (hours ([1, 2, 3]), 'months'), false)
## isregular: input must be a vector, and the component must be one MATLAB names
%!error<duration.isregular: input must be a duration vector.> ...
%! isregular (hours ([1, 2; 3, 4]))
%!error<duration.isregular: COMPONENT must be 'Years', 'Quarters', 'Months', 'Weeks', 'Days', or 'Time'.> ...
%! isregular (hours ([1, 2, 3]), 'bogus')

%!assert_equal (days (+ days (-3)), -3)
%!assert_equal (days (+ days (magic (3))), magic (3))

%!assert_equal (days (days ([3, 5; NaN, Inf]) - [2, 3]), [1, 2; NaN, Inf])
%!assert_equal (days (days ([3, 5; NaN, Inf]) - days ([2, 3])), [1, 2; NaN, Inf])
%!assert_equal (days ([3, 5] - days ([2, 3; NaN, Inf])), [1, 2; NaN, -Inf])
%!assert_equal (days (days ([3, 5]) - days ([2, 3; NaN, Inf])), [1, 2; NaN, -Inf])
%!assert_equal (caldays (days (1) - calendarDuration), 0)
%!assert_equal (caldays (days (1) - calendarDuration (0, 0, 1)), -1)
%!assert_equal (hours (time (days (1) - calendarDuration)), 24)
%!assert_equal (hours (time (days (1) - calendarDuration (0, 0, 1))), 24)
%!assert_equal (class (days (1) - calendarDuration), 'calendarDuration')
%!error<duration: subtraction is not defined between 'duration' and 'char' arrays.> ...
%! days (1) - '24:00:00'
%!error<duration: subtraction is not defined between 'duration' and 'cell' arrays.> ...
%! days (1) - {'24:00:00'}
%!error<duration: subtraction is not defined between 'duration' and 'string' arrays.> ...
%! days (1) - string('24:00:00')

%!assert_equal (days (- days (-3)), 3)
%!assert_equal (days (- days (3)), -3)
%!assert_equal (days (- days (magic (3))), - magic (3))

%!assert_equal (days (days ([1:3]) .* [1:3]), [1, 4, 9])
%!assert_equal (days ([1:3] .* days ([1:3])), [1, 4, 9])
%!assert_equal (days (days ([1:3]) .* [1; 2]), [1, 2, 3; 2, 4, 6])
%!assert_equal (days ([1; 2] .* days ([1:3])), [1, 2, 3; 2, 4, 6])
%!assert_equal (class (1 .* duration), 'duration')
%!assert_equal (class (duration .* magic (3)), 'duration')
%!assert_equal (hours (duration .* magic (3)), zeros (3))
%!error<duration: multiplication is not defined between 'duration' and 'duration' arrays.> ...
%! days (1) .* days (1)
%!error<duration: multiplication is not defined between 'duration' and 'char' arrays.> ...
%! days (1) .* 'asd'
%!error<duration: multiplication is not defined between 'duration' and 'string' arrays.> ...
%! days (1) .* string ({'asd'})
%!error<duration: multiplication is not defined between 'cell' and 'duration' arrays.> ...
%! {'asd'} .*  days (1)

%!assert_equal (days (days ([1:3]) * [1:3]'), 14)
%!assert_equal (days (days ([1:3]') * [1:3]), [1, 2, 3; 2, 4, 6; 3, 6, 9])
%!assert_equal (days ([1:3] * days ([1:3]')), 14)
%!assert_equal (days ([1:3]' * days ([1:3])), [1, 2, 3; 2, 4, 6; 3, 6, 9])
%!assert_equal (class (1 * duration), 'duration')
%!assert_equal (class (days (magic (3)) * magic (3)), 'duration')
%!assert_equal (days (days (magic (3)) * magic (3)), magic (3) * magic (3))
%!assert_equal (days (magic (3) * days (magic (3))), magic (3) * magic (3))
%!error<duration: matrix multiplication is not defined between 'duration' and 'duration' arrays.> ...
%! days (1) * days (1)
%!error<duration: matrix multiplication is not defined between 'duration' and 'char' arrays.> ...
%! days (1) * 'asd'
%!error<duration: matrix multiplication is not defined between 'duration' and 'string' arrays.> ...
%! days (1) * string ({'asd'})
%!error<duration: matrix multiplication is not defined between 'cell' and 'duration' arrays.> ...
%! {'asd'} *  days (1)

%!assert_equal (days ([1:3]) .\ days ([1:3]), [1, 1, 1])
%!assert_equal (days ([1:3] .\ days ([1:3])), [1, 1, 1])
%!assert_equal (days ([1; 2] .\ days ([1:3])), [1, 2, 3; 0.5, 1, 1.5])
%!assert_equal (class (1 .\ duration), 'duration')
%!assert_equal (class (duration .\ duration), 'double')
%!error<duration: right-hand side must be a duration array for left division: got 'double'> ...
%! days (1) .\ 1
%!error<duration: left division is not defined between 'char' and 'duration' arrays.> ...
%! 'asd' .\ days (1)

%!assert_equal (days ([1:3]) ./ days ([1:3]), [1, 1, 1])
%!assert_equal (days (days ([1:3]) ./ [1:3]), [1, 1, 1])
%!assert_equal (days (days ([1; 2]) ./ [1:3]), [1, 0.5, 1/3; 2, 1, 2/3])
%!assert_equal (class (duration ./ 1), 'duration')
%!assert_equal (class (duration ./ duration), 'double')
%!error<duration: left-hand side must be a duration array for right division: got 'double'> ...
%! 1 ./ days (1)
%!error<duration: right division is not defined between 'duration' and 'char' arrays.> ...
%! days (1) ./ 'asd'

%!assert_equal (days(1):days(10), days ([1:10]))
%!assert_equal (days(1):2:days(10), days ([1:2:10]))
%!assert_equal (days(1):days(2):days(10), days ([1:2:10]))
%!test
%! R = days(1):'72:00:00';
%! assert_equal (R, days ([1:3]))
%! assert_equal (R.Format, 'd')
%!test
%! R = '00:00:00':days(1):'72:00:00';
%! assert_equal (R, days ([0:3]))
%! assert_equal (R.Format, 'd')
%!test
%! R = days(1):'06:00:00':days(10);
%! assert_equal (R, days ([1:0.25:10]))
%! assert_equal (R.Format, 'd')
%!assert_equal (days(1):{'72:00:00'}, days ([1:3]))
%!assert_equal (days(1):string('72:00:00'), days ([1:3]))
%!assert_equal (string('00:00:00'):days(1):string('72:00:00'), days ([0:3]))
%!assert_equal (days(1):string({'06:00:00'}):days(10), days ([1:0.25:10]))
%!assert_equal (days(1):{'06:00:00'}:days(10), days ([1:0.25:10]))
%!error<duration.colon: invalid number of input arguments.> colon (days (1))
%!error<duration.colon: invalid number of input arguments.> colon (days (1), 2, 3, 4)
%!error<duration.colon: input arguments must be scalars.> days([1, 2]):days(2)
%!error<duration.colon: input arguments must be scalars.> days(1):days([1, 2])
%!error<duration.colon: input arguments must be scalars.> days(1):days(2):days([1, 2])

%!assert_equal (milliseconds (linspace (days (1), days (2))), ...
%!               linspace (86400000, 172800000))
%!assert_equal (milliseconds (linspace (days (1), days (2), 15)), ...
%!               linspace (86400000, 172800000, 15))
%!assert_equal (milliseconds (linspace (days (1), 2)), ...
%!               linspace (86400000, 172800000))
%!assert_equal (milliseconds (linspace (1, days (2))), ...
%!               linspace (86400000, 172800000))
%!assert_equal (milliseconds (linspace (1, days (2), 15)), ...
%!               linspace (86400000, 172800000, 15))
%!assert_equal (milliseconds (linspace (days (1), '48:00:00')), ...
%!               linspace (86400000, 172800000))
%!assert_equal (milliseconds (linspace (days (1), {'48:00:00'})), ...
%!               linspace (86400000, 172800000))
%!assert_equal (milliseconds (linspace (days (1), string ({'48:00:00'}))), ...
%!               linspace (86400000, 172800000))
%!assert_equal (milliseconds (linspace (days (1), '48:00:00', 15)), ...
%!               linspace (86400000, 172800000, 15))
%!assert_equal (milliseconds (linspace (days (1), {'48:00:00'}, 15)), ...
%!               linspace (86400000, 172800000, 15))
%!assert_equal (milliseconds ( ...
%!               linspace (days (1), string ({'48:00:00'}), 15)), ...
%!               
%!               linspace (86400000, 172800000, 15))
%!assert_equal (milliseconds (linspace ('48:00:00', days (1))), ...
%!               linspace (172800000, 86400000))
%!assert_equal (milliseconds (linspace ({'48:00:00'}, days (1))), ...
%!               linspace (172800000, 86400000))
%!assert_equal (milliseconds (linspace (string ({'48:00:00'}), days (1))), ...
%!               linspace (172800000, 86400000))
%!assert_equal (milliseconds (linspace ('48:00:00', days (1), 15)), ...
%!               linspace (172800000, 86400000, 15))
%!assert_equal (milliseconds (linspace ({'48:00:00'}, days (1), 15)), ...
%!               linspace (172800000, 86400000, 15))
%!assert_equal (milliseconds ( ...
%!               linspace (string ({'48:00:00'}), days (1), 15)), ...
%!               
%!               linspace (172800000, 86400000, 15))
%!error<duration.linspace: too few input arguments.> ...
%! linspace (days (1))

%!assert_equal (days (diff (days (magic (3)))), diff (magic (3)))
%!assert_equal (days (diff (days (magic (3)), 2)), diff (magic (3), 2))
%!assert_equal (days (diff (days (magic (3)), 1, 1)), diff (magic (3), 1, 1))
%!assert_equal (days (diff (days (magic (3)), 1, 2)), diff (magic (3), 1, 2))

%!assert_equal (sum (days ([1, 2, 3])), days (6))
%!assert_equal (sum (days ([-1; -2; -3])), days (-6))
%!assert_equal (sum (days ([1, 2; 3, 4]), 1), days ([4, 6]))
%!assert_equal (sum (days ([1, 2; 3, 4]), 2), days ([3; 7]))
%!assert_equal (sum (days ([])), days(0))
%!assert_equal (size (sum (days ([]), 1)), [1, 0])
%!assert_equal (size (sum (days ([]), 2)), [0, 1])
%!assert_equal (size (sum (days ([]), 3)), [0, 0])
%!assert_equal (sum (days (zeros (1, 0))), days (0))
%!assert_equal (sum (days (zeros (1, 0)), 1), days (zeros (1, 0)))
%!assert_equal (sum (days (zeros (1, 0)), 2), days (0))
%!assert_equal (sum (days (zeros (0, 1))), days (0))
%!assert_equal (sum (days (zeros (0, 1)), 1), days (0))
%!assert_equal (sum (days (zeros (0, 1)), 2), days (zeros (0, 1)))
%!test
%! x = repmat (days ([1:20;6:25]), [5, 2, 6, 3]);
%! assert_equal (size (sum (x, [3, 2])), [10, 1, 1, 3]);
%! assert_equal (size (sum (x, [1, 2])), [1, 1, 6, 3]);
%! assert_equal (size (sum (x, [1, 2, 4])), [1, 1, 6]);
%! assert_equal (size (sum (x, [1, 4, 3])), [1, 40]);
%! assert_equal (size (sum (x, [1, 2, 3, 4])), [1, 1]);
%!assert_equal (sum (days (ones (2,2)), 3), days (ones (2,2)))
%!assert_equal (sum (days (ones (2,2,2)), 99), days (ones (2,2,2)))
%!assert_equal (sum (days (magic (3)), 3), days (magic (3)))
%!test
%! x = days (ones (3, 4, 5));
%! x(1) = NaN;
%! assert_equal (isequaln (sum (x)(:,:,1), days ([NaN, 3, 3, 3])), true);
%! assert_equal (isequaln (sum (x, "includenan")(:,:,1), days ([NaN, 3, 3, 3])), true);
%! assert_equal (sum (x, "omitnan")(:,:,1), days ([2, 3, 3, 3]));
%! assert_equal (sum (x, "omitmissing")(:,:,1), days ([2, 3, 3, 3]));
%! assert_equal (isequaln (sum (x, [2 3]), days ([NaN; 20; 20])), true);
%! assert_equal (sum (x, [2 3], "omitnan"), days ([19; 20; 20]));

%!assert_equal (cumsum (days ([1, 2, 3])), days ([1, 3, 6]))
%!assert_equal (cumsum (days ([-1; -2; -3])), days ([-1; -3; -6]))
%!assert_equal (cumsum (days ([1, 2; 3, 4]), 1), days ([1, 2; 4, 6]))
%!assert_equal (cumsum (days ([1, 2; 3, 4]), 2), days ([1, 3; 3, 7]))
%!test
%! x = reshape (days ([1:8]), 2, 2, 2);
%! y = cumsum (x);
%! assert_equal (y(:,:,1), days ([1, 3; 3, 7]));
%! assert_equal (y(:,:,2), days ([5, 7; 11, 15]));
%! assert_equal (flip (cumsum (flip (x))), cumsum (x, "reverse"));
%! y = cumsum (x, 2);
%! assert_equal (y(:,:,1), days ([1, 4; 2, 6]));
%! assert_equal (y(:,:,2), days ([5, 12; 6, 14]));
%! y = cumsum (x, 2, "reverse");
%! assert_equal (y(:,:,1), days ([4, 3; 6, 4]));
%! assert_equal (y(:,:,2), days ([12, 7; 14, 8]));
%! assert_equal (flip (cumsum (flip (x, 2), 2), 2), cumsum (x, 2, "reverse"));
%! y = cumsum (x, [1, 2]);
%! assert_equal (y(:,:,1), days ([1; 3; 6; 10]));
%! assert_equal (y(:,:,2), days ([5; 11; 18; 26]));
%! y = cumsum (x, [1, 3]);
%! assert_equal (y(:,1), days ([1; 3; 8; 14]));
%! assert_equal (y(:,2), days ([3; 7; 14; 22]));
%! y = cumsum (x, [2, 3]);
%! assert_equal (y(1,:), days ([1, 4, 9, 16]));
%! assert_equal (y(2,:), days ([2, 6, 12, 20]));
%! assert_equal (cumsum (x, [1, 2, 3]), cumsum (x, "all"));
%!test
%! x = reshape (days ([1:8]), 2, 2, 2);
%! assert_equal (cumsum (x, 4), x);
%! assert_equal (cumsum (x, 2), cumsum (x, [2, 4]));
%! assert_equal (cumsum (x, 2, "reverse"), cumsum (x, [2, 4], "reverse"));
%! x(3) = NaN;
%! assert_equal (isequaln (cumsum (x, 4), x), true);
%! y = x;
%! y(3) = 0;
%! assert_equal (cumsum (x, 4, "omitnan"), y);
%! assert_equal (cumsum (x, 2, "omitnan"), cumsum (x, [2, 4], "omitnan"));
%! assert_equal (cumsum (x, 2, "reverse", "omitnan"),
%!               cumsum (x, [2, 4], "reverse", "omitnan"));
%!assert_equal (cumsum (days ([NaN, NaN]), "omitnan"), days ([0, 0]))

%!assert_equal (min (days ([1, 4, 2, 3])), days (1))
%!assert_equal (min (days ([1; -10; 5; -2])), days (-10))
%!test
%! x = reshape (days ([1:8]), [2,2,2]);
%! assert_equal (min (x, [], 1), reshape (days ([1, 3, 5, 7]), [1, 2, 2]));
%! assert_equal (min (x, [], 2), reshape (days ([1, 2, 5, 6]), [2, 1, 2]));
%! [y, i] = min (x, [], 3);
%! assert_equal (ndims (y), 2);
%! assert_equal (y, days ([1, 3; 2, 4]));
%! assert_equal (ndims (i), 2);
%! assert_equal (i, [1, 1; 1, 1]);
%!test
%! x = reshape (days ([1:8]), [2, 2, 2]);
%! assert_equal (min (x, [], [1, 3]), days ([1, 3]));
%! assert_equal (min (x, [], [2, 3]), days ([1; 2]));
%! assert_equal (min (x, [], [1, 2]), reshape (days ([1, 5]), [1, 1, 2]));
%! assert_equal (min (x, [], [1, 2, 3]), min (x, [], "all"));
%!test
%! x = days ([1, 2, 3, 4]);
%! y = flip (x);
%! assert_equal (min (x, y), days ([1, 2, 2, 1]));
%! assert_equal (min (x, 3), days ([1, 2, 3, 3]));
%! assert_equal (min (2, x), days ([1, 2, 2, 2]));
%!test
%! [m, i] = min (days ([1, 2, 3; 4, 3, NaN; 4, 5, 6]), [], 2, "includenan");
%! assert_equal (isequaln (m, days ([1; NaN; 4])), true);
%! assert_equal (i, [1; 3; 1]);
%! [m,i] = min (days ([1, 2, 3; 4, NaN, NaN; 4, 5, 6]), [], 2, "includenan");
%! assert_equal (isequaln (m, [1; NaN; 4]), true);
%! assert_equal (i, [1; 2; 1]);
%!test
%! x = days (magic (3));
%! x(2, 3) = NaN;
%! assert_equal (isequaln (min (x, [], 2, "includenan"), days ([1; NaN; 2])), true);
%!assert_equal (size (min (days (0), days (zeros (0, 1)))), [0, 1])
%!assert_equal (size (min (days ([]), days (zeros (0, 1)))), [0, 0])
%!assert_equal (size (min (days (zeros (0, 1)), days ([]))), [0, 0])
%!assert_equal (size (min (days ([]), days (zeros (1, 0)))), [0, 0])
%!assert_equal (size (min (days (zeros (1, 0)), days ([]))), [0, 0])
%!test
%! x = repmat (days ([4, 3, 2, 4, 1, 5, 3, 2]), 3, 2, 5, 2);
%! [m, i] = min (x, [], [2, 3], 'linear');
%! assert_equal (m, days (ones (3, 1, 1, 2)));
%! assert_equal (i(:,:,1,1), [13; 14; 15]);
%! assert_equal (i(:,:,1,2), [253; 254; 255]);
%!test
%! x = repmat (days ([4, 3, 2, 4, 1, 5, 3, 2]), 3, 2, 5, 2);
%! [m, i] = min (x, [], [1, 3], 'linear');
%! assert_equal (m, x(1,:,1,:));
%! assert_equal (i(:,:,1,1), [1:3:46]);
%! assert_equal (i(:,:,1,2), [241:3:286]);

%!assert_equal (cummin (days ([1, 4, 2, 3])), days ([1, 1, 1, 1]))
%!assert_equal (cummin (days ([1; -10; 5; -2])), days ([1; -10; -10; -10]))
%!test
%! x = reshape (days ([1:8]), [2, 2, 2]);
%! assert_equal (cummin (x, 1), reshape (days ([1, 1, 3, 3, 5, 5, 7, 7]), [2, 2, 2]));
%! assert_equal (cummin (x, 2), reshape (days ([1, 2, 1, 2, 5, 6, 5, 6]), [2, 2, 2]));
%! [w, iw] = cummin (x, 3);
%! assert_equal (ndims (w), 3);
%! assert_equal (w, repmat (days ([1, 3; 2, 4]), [1, 1, 2]));
%! assert_equal (ndims (iw), 3);
%! assert_equal (iw, ones (2, 2, 2));
%!assert_equal (isequaln (cummin (days ([1; -10; NaN; -2]), 'includenan'), days ([1; -10; NaN; NaN])), true)
%!assert_equal (isequaln (cummin (days ([1; -10; NaN; -2]), 'reverse', 'includenan'), days ([NaN(3,1); -2])), true)
%!assert_equal (isequaln (cummin (days ([1, -10, NaN, -2]), 'includenan'), days ([1, -10, NaN, NaN])), true)
%!assert_equal (isequaln (cummin (days ([1, -10, NaN, -2]), 'reverse', 'includenan'), days ([NaN(1,3), -2])), true)
%!shared A
%! A = days ([3, 5, NaN, 4, 2; 2, 6, 2, 9, 4; 1, 3, 0, NaN, 1; 5, 3, 4, 2, 0]);
%!test
%! [m, i] = cummin (A, 'includenan');
%! m_exp = days ([3, 5, NaN, 4, 2; 2, 5, NaN, 4, 2; ...
%!                1, 3, NaN, NaN, 1; 1, 3, NaN, NaN, 0]);
%! i_exp = [1, 1, 1, 1, 1; 2, 1, 1, 1, 1; 3, 3, 1, 3, 3; 3, 3, 1, 3, 4];
%! assert_equal (isequaln (m, m_exp), true);
%! assert_equal (i, i_exp);
%!test
%! [m, i] = cummin (A, 'includenan', 'reverse');
%! m_exp = days ([1, 3, NaN, NaN, 0; 1, 3, 0, NaN, 0; ...
%!                1, 3, 0, NaN, 0; 5, 3, 4, 2, 0]);
%! i_exp = [3, 4, 1, 3, 4; 3, 4, 3, 3, 4; 3, 4, 3, 3, 4; 4, 4, 4, 4, 4];
%! assert_equal (isequaln (m, m_exp), true);
%! assert_equal (i, i_exp);
%!test
%! [m, i] = cummin (A, 'reverse');
%! m_exp = days ([1, 3, 0, 2, 0; 1, 3, 0, 2, 0; 1, 3, 0, 2, 0; 5, 3, 4, 2, 0]);
%! i_exp = [3, 4, 3, 4, 4; 3, 4, 3, 4, 4; 3, 4, 3, 4, 4; 4, 4, 4, 4, 4];
%! assert_equal (m, m_exp);
%! assert_equal (i, i_exp);
%!test
%! [m, i] = cummin (A);
%! m_exp = days ([3, 5, NaN, 4, 2; 2, 5, 2, 4, 2; 1, 3, 0, 4, 1; 1, 3, 0, 2, 0]);
%! i_exp = [1, 1, 1, 1, 1; 2, 1, 2, 1, 1; 3, 3, 3, 1, 3; 3, 3, 3, 4, 4];
%! assert_equal (isequaln (m, m_exp), true);
%! assert_equal (i, i_exp);
%!test
%! [m, i] = cummin (A, 2, 'includenan');
%! m_exp = days ([3, 3, NaN, NaN, NaN; 2, 2, 2, 2, 2; 1, 1, 0, NaN, NaN; 5, 3, 3, 2, 0]);
%! i_exp = [1, 1, 3, 3, 3; 1, 1, 1, 1, 1; 1, 1, 3, 4, 4; 1, 2, 2, 4, 5];
%! assert_equal (isequaln (m, m_exp), true);
%! assert_equal (i, i_exp);
%!test
%! [m, i] = cummin (A, 2, 'includenan', 'reverse');
%! m_exp = days ([NaN, NaN, NaN, 2, 2; 2, 2, 2, 4, 4; ...
%!                NaN, NaN, NaN, NaN, 1; 0, 0, 0, 0, 0]);
%! i_exp = [3, 3, 3, 5, 5; 3, 3, 3, 5, 5; 4, 4, 4, 4, 5; 5, 5, 5, 5, 5];
%! assert_equal (isequaln (m, m_exp), true);
%! assert_equal (i, i_exp);
%!test
%! [m, i] = cummin (A, 2, 'reverse');
%! m_exp = days ([2, 2, 2, 2, 2; 2, 2, 2, 4, 4; 0, 0, 0, 1, 1; 0, 0, 0, 0, 0]);
%! i_exp = [5, 5, 5, 5, 5; 3, 3, 3, 5, 5; 3, 3, 3, 5, 5; 5, 5, 5, 5, 5];
%! assert_equal (m, m_exp);
%! assert_equal (i, i_exp);
%!test
%! [m, i] = cummin (A, 2);
%! m_exp = days ([3, 3, 3, 3, 2; 2, 2, 2, 2, 2; 1, 1, 0, 0, 0; 5, 3, 3, 2, 0]);
%! i_exp = [1, 1, 1, 1, 5; 1, 1, 1, 1, 1; 1, 1, 3, 3, 3; 1, 2, 2, 4, 5];
%! assert_equal (m, m_exp);
%! assert_equal (i, i_exp);
%!test
%! [~, i_lin] = cummin (A, 'includenan', 'linear');
%! assert_equal (isequaln (cummin (A, 'includenan'), A(i_lin)), true);
%!test
%! [~, i_lin] = cummin (A, 'includenan', 'reverse', 'linear');
%! assert_equal (isequaln (cummin (A, 'includenan', 'reverse'), A(i_lin)), true);
%!test
%! [~, i_lin] = cummin (A, 'reverse', 'linear');
%! assert_equal (isequaln (cummin (A, 'reverse'), A(i_lin)), true);
%!test
%! [~, i_lin] = cummin (A, 'linear');
%! assert_equal (isequaln (cummin (A), A(i_lin)), true);
%!test
%! [~, i_lin] = cummin (A, 2, 'includenan', 'linear');
%! assert_equal (isequaln (cummin (A, 2, 'includenan'), A(i_lin)), true);
%!test
%! [~, i_lin] = cummin (A, 2, 'includenan', 'reverse', 'linear');
%! assert_equal (isequaln (cummin (A, 2, 'includenan', 'reverse'), A(i_lin)), true);
%!test
%! [~, i_lin] = cummin (A, 2, 'reverse', 'linear');
%! assert_equal (isequaln (cummin (A, 2, 'reverse'), A(i_lin)), true);
%!test
%! [~, i_lin] = cummin (A, 2, 'linear');
%! assert_equal (isequaln (cummin (A, 2), A(i_lin)), true);
%!shared x
%! x = days (randi ([-10, 10], 3, 4, 5, 2));
%!test
%! [m, i] = cummin (x, [2, 3], 'linear');
%! assert_equal (m, x(i));
%!test
%! [m, i] = cummin (x, [1, 3], 'linear');
%! assert_equal (m, x(i));
%!test
%! [m, i] = cummin (x, [2, 4], 'linear');
%! assert_equal (m, x(i));
%!test
%! [m, i] = cummin (x, [1, 4], 'linear');
%! assert_equal (m, x(i));
%!test
%! [m, i] = cummin (x, [1, 2, 3], 'linear');
%! assert_equal (m, x(i));
%!test
%! [m, i] = cummin (x, [2, 3, 4], 'linear');
%! assert_equal (m, x(i));

%!assert_equal (max (days ([1, 4, 2, 3])), days (4))
%!assert_equal (max (days ([1; -10; 5; -2])), days (5))
%!test
%! x = reshape (days ([1:8]), [2,2,2]);
%! assert_equal (max (x, [], 1), reshape (days ([2, 4, 6, 8]), [1, 2, 2]));
%! assert_equal (max (x, [], 2), reshape (days ([3, 4, 7, 8]), [2, 1, 2]));
%! [y, i] = max (x, [], 3);
%! assert_equal (ndims (y), 2);
%! assert_equal (y, days ([5, 7; 6, 8]));
%! assert_equal (ndims (i), 2);
%! assert_equal (i, [2, 2; 2, 2]);
%!test
%! x = reshape (days ([1:8]), [2, 2, 2]);
%! assert_equal (max (x, [], [1, 3]), days ([6, 8]));
%! assert_equal (max (x, [], [2, 3]), days ([7; 8]));
%! assert_equal (max (x, [], [1, 2]), reshape (days ([4, 8]), [1, 1, 2]));
%! assert_equal (max (x, [], [1, 2, 3]), max (x, [], "all"));
%!test
%! x = days ([1, 2, 3, 4]);
%! y = flip (x);
%! assert_equal (max (x, y), days ([4, 3, 3, 4]));
%! assert_equal (max (x, 3), days ([3, 3, 3, 4]));
%! assert_equal (max (2, x), days ([2, 2, 3, 4]));
%!test
%! [m, i] = max (days ([1, 2, 3; 4, 3, NaN; 4, 5, 6]), [], 2, "includenan");
%! assert_equal (isequaln (m, days ([3; NaN; 6])), true);
%! assert_equal (i, [3; 3; 3]);
%! [m,i] = max (days ([1, 2, 3; 4, NaN, NaN; 4, 5, 6]), [], 2, "includenan");
%! assert_equal (isequaln (m, [3; NaN; 6]), true);
%! assert_equal (i, [3; 2; 3]);
%!test
%! x = days (magic (3));
%! x(2, 3) = NaN;
%! assert_equal (isequaln (max (x, [], 2, "includenan"), days ([8; NaN; 9])), true);
%!assert_equal (size (max (days (0), days (zeros (0, 1)))), [0, 1])
%!assert_equal (size (max (days ([]), days (zeros (0, 1)))), [0, 0])
%!assert_equal (size (max (days (zeros (0, 1)), days ([]))), [0, 0])
%!assert_equal (size (max (days ([]), days (zeros (1, 0)))), [0, 0])
%!assert_equal (size (max (days (zeros (1, 0)), days ([]))), [0, 0])
%!test
%! x = repmat (days ([4, 3, 2, 4, 1, 5, 3, 2]), 3, 2, 5, 2);
%! [m, i] = max (x, [], [2, 3], 'linear');
%! assert_equal (m, days (5 * ones (3, 1, 1, 2)));
%! assert_equal (i(:,:,1,1), [16; 17; 18]);
%! assert_equal (i(:,:,1,2), [256; 257; 258]);
%!test
%! x = repmat (days ([4, 3, 2, 4, 1, 5, 3, 2]), 3, 2, 5, 2);
%! [m, i] = max (x, [], [1, 3], 'linear');
%! assert_equal (m, x(1,:,1,:));
%! assert_equal (i(:,:,1,1), [1:3:46]);
%! assert_equal (i(:,:,1,2), [241:3:286]);

%!assert_equal (cummax (days ([1, 4, 2, 3])), days ([1, 4, 4, 4]))
%!assert_equal (cummax (days ([1; -10; 5; -2])), days ([1; 1; 5; 5]))
%!test
%! x = reshape (days ([8:-1:1]), [2, 2, 2]);
%! assert_equal (cummax (x, 1), reshape (days ([8, 8, 6, 6, 4, 4, 2, 2]), [2, 2, 2]));
%! assert_equal (cummax (x, 2), reshape (days ([8, 7, 8, 7, 4, 3, 4, 3]), [2, 2, 2]));
%! [w, iw] = cummax (x, 3);
%! assert_equal (ndims (w), 3);
%! assert_equal (w, repmat (days ([8, 6; 7, 5]), [1, 1, 2]));
%! assert_equal (ndims (iw), 3);
%! assert_equal (iw, ones (2, 2, 2));
%!assert_equal (isequaln (cummax (days ([1; -10; NaN; -2]), 'includenan'), days ([1; 1; NaN; NaN])), true)
%!assert_equal (isequaln (cummax (days ([1; -10; NaN; -2]), 'reverse', 'includenan'), days ([NaN(3,1); -2])), true)
%!assert_equal (isequaln (cummax (days ([1, -10, NaN, -2]), 'includenan'), days ([1, 1, NaN, NaN])), true)
%!assert_equal (isequaln (cummax (days ([1, -10, NaN, -2]), 'reverse', 'includenan'), days ([NaN(1,3), -2])), true)
%!shared A
%! A = days ([3, 5, NaN, 4, 2; 2, 6, 2, 9, 4; 1, 3, 0, NaN, 1; 5, 3, 4, 2, 0]);
%!test
%! [m, i] = cummax (A, 'includenan');
%! m_exp = days ([3, 5, NaN, 4, 2; 3, 6, NaN, 9, 4; ...
%!                3, 6, NaN, NaN, 4; 5, 6, NaN, NaN, 4]);
%! i_exp = [1, 1, 1, 1, 1; 1, 2, 1, 2, 2; 1, 2, 1, 3, 2; 4, 2, 1, 3, 2];
%! assert_equal (isequaln (m, m_exp), true);
%! assert_equal (i, i_exp);
%!test
%! [m, i] = cummax (A, 'includenan', 'reverse');
%! m_exp = days ([5, 6, NaN, NaN, 4; 5, 6, 4, NaN, 4; ...
%!                5, 3, 4, NaN, 1; 5, 3, 4, 2, 0]);
%! i_exp = [4, 2, 1, 3, 2; 4, 2, 4, 3, 2; 4, 4, 4, 3, 3; 4, 4, 4, 4, 4];
%! assert_equal (isequaln (m, m_exp), true);
%! assert_equal (i, i_exp);
%!test
%! [m, i] = cummax (A, 'reverse');
%! m_exp = days ([5, 6, 4, 9, 4; 5, 6, 4, 9, 4; 5, 3, 4, 2, 1; 5, 3, 4, 2, 0]);
%! i_exp = [4, 2, 4, 2, 2; 4, 2, 4, 2, 2; 4, 4, 4, 4, 3; 4, 4, 4, 4, 4];
%! assert_equal (m, m_exp);
%! assert_equal (i, i_exp);
%!test
%! [m, i] = cummax (A);
%! m_exp = days ([3, 5, NaN, 4, 2; 3, 6, 2, 9, 4; 3, 6, 2, 9, 4; 5, 6, 4, 9, 4]);
%! i_exp = [1, 1, 1, 1, 1; 1, 2, 2, 2, 2; 1, 2, 2, 2, 2; 4, 2, 4, 2, 2];
%! assert_equal (isequaln (m, m_exp), true);
%! assert_equal (i, i_exp);
%!test
%! [m, i] = cummax (A, 2, 'includenan');
%! m_exp = days ([3, 5, NaN, NaN, NaN; 2, 6, 6, 9, 9; 1, 3, 3, NaN, NaN; 5, 5, 5, 5, 5]);
%! i_exp = [1, 2, 3, 3, 3; 1, 2, 2, 4, 4; 1, 2, 2, 4, 4; 1, 1, 1, 1, 1];
%! assert_equal (isequaln (m, m_exp), true);
%! assert_equal (i, i_exp);
%!test
%! [m, i] = cummax (A, 2, 'includenan', 'reverse');
%! m_exp = days ([NaN, NaN, NaN, 4, 2; 9, 9, 9, 9, 4; ...
%!                NaN, NaN, NaN, NaN, 1; 5, 4, 4, 2, 0]);
%! i_exp = [3, 3, 3, 4, 5; 4, 4, 4, 4, 5; 4, 4, 4, 4, 5; 1, 3, 3, 4, 5];
%! assert_equal (isequaln (m, m_exp), true);
%! assert_equal (i, i_exp);
%!test
%! [m, i] = cummax (A, 2, 'reverse');
%! m_exp = days ([5, 5, 4, 4, 2; 9, 9, 9, 9, 4; 3, 3, 1, 1, 1; 5, 4, 4, 2, 0]);
%! i_exp = [2, 2, 4, 4, 5; 4, 4, 4, 4, 5; 2, 2, 5, 5, 5; 1, 3, 3, 4, 5];
%! assert_equal (m, m_exp);
%! assert_equal (i, i_exp);
%!test
%! [m, i] = cummax (A, 2);
%! m_exp = days ([3, 5, 5, 5, 5; 2, 6, 6, 9, 9; 1, 3, 3, 3, 3; 5, 5, 5, 5, 5]);
%! i_exp = [1, 2, 2, 2, 2; 1, 2, 2, 4, 4; 1, 2, 2, 2, 2; 1, 1, 1, 1, 1];
%! assert_equal (m, m_exp);
%! assert_equal (i, i_exp);
%!test
%! [~, i_lin] = cummax (A, 'includenan', 'linear');
%! assert_equal (isequaln (cummax (A, 'includenan'), A(i_lin)), true);
%!test
%! [~, i_lin] = cummax (A, 'includenan', 'reverse', 'linear');
%! assert_equal (isequaln (cummax (A, 'includenan', 'reverse'), A(i_lin)), true);
%!test
%! [~, i_lin] = cummax (A, 'reverse', 'linear');
%! assert_equal (isequaln (cummax (A, 'reverse'), A(i_lin)), true);
%!test
%! [~, i_lin] = cummax (A, 'linear');
%! assert_equal (isequaln (cummax (A), A(i_lin)), true);
%!test
%! [~, i_lin] = cummax (A, 2, 'includenan', 'linear');
%! assert_equal (isequaln (cummax (A, 2, 'includenan'), A(i_lin)), true);
%!test
%! [~, i_lin] = cummax (A, 2, 'includenan', 'reverse', 'linear');
%! assert_equal (isequaln (cummax (A, 2, 'includenan', 'reverse'), A(i_lin)), true);
%!test
%! [~, i_lin] = cummax (A, 2, 'reverse', 'linear');
%! assert_equal (isequaln (cummax (A, 2, 'reverse'), A(i_lin)), true);
%!test
%! [~, i_lin] = cummax (A, 2, 'linear');
%! assert_equal (isequaln (cummax (A, 2), A(i_lin)), true);
%!shared x
%! x = days (randi ([-10, 10], 3, 4, 5, 2));
%!test
%! [m, i] = cummax (x, [2, 3], 'linear');
%! assert_equal (m, x(i));
%!test
%! [m, i] = cummax (x, [1, 3], 'linear');
%! assert_equal (m, x(i));
%!test
%! [m, i] = cummax (x, [2, 4], 'linear');
%! assert_equal (m, x(i));
%!test
%! [m, i] = cummax (x, [1, 4], 'linear');
%! assert_equal (m, x(i));
%!test
%! [m, i] = cummax (x, [1, 2, 3], 'linear');
%! assert_equal (m, x(i));
%!test
%! [m, i] = cummax (x, [2, 3, 4], 'linear');
%! assert_equal (m, x(i));

%!test
%! D = hours(8) + minutes(29:31) + seconds(1.23);
%! D.Format = 'hh:mm:ss.SS';
%! assert_equal (dispstrings (D), {'08:29:01.23', '08:30:01.23', '08:31:01.23'});
%! Y = dispstrings (floor (D));
%! assert_equal (Y, {'08:29:01.00', '08:30:01.00', '08:31:01.00'});
%! Y = dispstrings (floor (D, 'seconds'));
%! assert_equal (Y, {'08:29:01.00', '08:30:01.00', '08:31:01.00'});
%! Y = dispstrings (floor (D, 'minutes'));
%! assert_equal (Y, {'08:29:00.00', '08:30:00.00', '08:31:00.00'});
%! Y = dispstrings (floor (D, 'hours'));
%! assert_equal (Y, {'08:00:00.00', '08:00:00.00', '08:00:00.00'});
%!test
%! D = days (3) + hours (6.5);
%! assert_equal (floor (D, 'days'), days (3));

%!test
%! D = hours(8) + minutes(29:31) + seconds(1.23);
%! D.Format = 'hh:mm:ss.SS';
%! assert_equal (dispstrings (D), {'08:29:01.23', '08:30:01.23', '08:31:01.23'});
%! Y = dispstrings (ceil (D));
%! assert_equal (Y, {'08:29:02.00', '08:30:02.00', '08:31:02.00'});
%! Y = dispstrings (ceil (D, 'seconds'));
%! assert_equal (Y, {'08:29:02.00', '08:30:02.00', '08:31:02.00'});
%! Y = dispstrings (ceil (D, 'minutes'));
%! assert_equal (Y, {'08:30:00.00', '08:31:00.00', '08:32:00.00'});
%! Y = dispstrings (ceil (D, 'hours'));
%! assert_equal (Y, {'09:00:00.00', '09:00:00.00', '09:00:00.00'});
%!test
%! D = days (3) + hours (6.5);
%! assert_equal (ceil (D, 'days'), days (4));

%!test
%! D = hours(8) + minutes(29:31) + seconds(1.23);
%! D.Format = 'hh:mm:ss.SS';
%! assert_equal (dispstrings (D), {'08:29:01.23', '08:30:01.23', '08:31:01.23'});
%! Y = dispstrings (round (D));
%! assert_equal (Y, {'08:29:01.00', '08:30:01.00', '08:31:01.00'});
%! Y = dispstrings (round (D, 'seconds'));
%! assert_equal (Y, {'08:29:01.00', '08:30:01.00', '08:31:01.00'});
%! Y = dispstrings (round (D, 'minutes'));
%! assert_equal (Y, {'08:29:00.00', '08:30:00.00', '08:31:00.00'});
%! Y = dispstrings (round (D, 'hours'));
%! assert_equal (Y, {'08:00:00.00', '09:00:00.00', '09:00:00.00'});
%!test
%! D = days (3) + hours (6.5);
%! assert_equal (round (D, 'days'), days (3));

%!assert_equal (sign (days ([-1, 0, 1, NaN])), [-1, 0, 1, NaN])
%!assert_equal (sign (seconds ([-2:2] .* ones (5))), repmat ([-1, -1, 0, 1, 1], 5, 1))

################################################################################
##                        ** Statistical Operations **                        ##
################################################################################
##                             Available Methods                              ##
##                                                                            ##
## 'bounds'           'center'           'histc'            'iqr'             ##
## 'kendal'           'kurtosis'         'mad'              'mape'            ##
## 'mean'             'median'           'mode'             'prctile'         ##
## 'quantile'         'range'            'rmse'             'skewness'        ##
## 'spearman'         'statistics'       'std'              'var'             ##
##                                                                            ##
################################################################################

%!test
%! [s, l] = bounds (days (1:10));
%! assert_equal ([s, l], days ([1, 10]));
%!test
%! [s, l] = bounds (days ([10:-1:1]'));
%! assert_equal ([s, l], days ([1, 10]));
%!assert_equal (bounds (days (magic (3))), days ([3, 1, 2]))
%!assert_equal (bounds (days (magic (3)), 2), days ([1; 3; 2]))
%!test
%! x = days (magic (3));
%! x(2,3) = NaN;
%! assert_equal (bounds (x), days ([3, 1, 2]));
%! assert_equal (bounds (x, "omitnan"), days ([3, 1, 2]));
%! assert_equal (isequaln (bounds (x, "includenan"), days ([3, 1, NaN])), true);
%! assert_equal (bounds (x, 2), days ([1; 3; 2]));
%! assert_equal (bounds (x, 2, "omitnan"), days ([1; 3; 2]));
%! assert_equal (isequaln (bounds (x, 2, "includenan"), days ([1; NaN; 2])), true);
%!test
%! x = reshape (days (1:27), [3, 3, 3]);
%! [s, l] = bounds (x, 3);
%! assert_equal (s, x(:,:,1));
%! assert_equal (l, x(:,:,3));
%!test
%! [s, l] = bounds (x, [2, 3]);
%! assert_equal (s, x(:,1,1));
%! assert_equal (l, x(:,3,3));
%!test
%! [s, l] = bounds (x, [1, 3]);
%! assert_equal (s, x(1,:,1));
%! assert_equal (l, x(3,:,3));
%!test
%! [s, l] = bounds (x, [1, 2, 3]);
%! assert_equal (s, days (1));
%! assert_equal (l, days (27));
%!test
%! [s, l] = bounds (x, "all");
%! assert_equal (s, days (1));
%! assert_equal (l, days (27));
%!test
%! x(3) = NaN;
%! [s, l] = bounds (x, "all");
%! assert_equal (s, days (1));
%! assert_equal (l, days (27));
%!test
%! [s,l] = bounds (x, "all", "omitnan");
%! assert_equal (s, days (1));
%! assert_equal (l, days (27));
%!test
%! [s,l] = bounds (x, "all", "includenan");
%! assert_equal (isnan (s), true);
%! assert_equal (isnan (l), true);
%!test
%! [s,l] = bounds (x, "includenan");
%! assert_equal (isequaln (s, min (x, [], "includenan")), true);
%! assert_equal (isequaln (l, max (x, [], "includenan")), true);

%!assert_equal (center (days ([1, 2, 3])), days ([-1,0,1]))
%!assert_equal (center (days (ones (3, 2, 0, 2))), days (zeros (3, 2, 0,2 )))
%!assert_equal (center (days (magic (3))), days ([3, -4, 1; -2, 0, 2; -1, 4, -3]))
%!assert_equal (center (days ([1, 2, 3; 6, 5, 4]), 2), days ([-1, 0, 1; 1, 0, -1]))
%!assert_equal (center (days (1), 3), days (0))
%!assert_equal (center (repmat (days ([1, 2, 3]), 5, 1)), days (zeros (5, 3)))
%!assert_equal (center (repmat (days ([1, 2, 3]), 5, 1), 2), repmat (days ([-1, 0, 1]), 5, 1))
%!test
%! out = center (days ([1, 3, 2; 2, NaN, 1]));
%! assert_equal (isequaln (out, days ([-0.5, NaN, 0.5; 0.5, NaN, -0.5])), true);
%!test
%! out = center (days ([1, 3, 2; 2, NaN, 1]), 'omitnan');
%! assert_equal (isequaln (out, days ([-0.5, 0, 0.5; 0.5, NaN, -0.5])), true);
%!test
%! out = center (days ([1, 3, 2; 2, NaN, 1]), 2, 'omitnan');
%! assert_equal (isequaln (out, days ([-1, 1, 0; 0.5, NaN, -0.5])), true);

%!test
%! x = linspace (days (0), days (10), 1001);
%! n = histc (x, 0:10);
%! assert_equal (n, [repmat(100, 1, 10), 1]);
%!test
%! x = repmat (linspace (days (0), days (10), 1001), [2, 1, 3]);
%! n = histc (x, 0:10, 2);
%! assert_equal (n, repmat ([repmat(100, 1, 10), 1], [2, 1, 3]));

%!assert_equal (iqr (days (17)), duration)
%!assert_equal (iqr (days (17), 1), duration)
%!assert_equal (iqr (days (17), 4), duration)
%!assert_equal (iqr (days ([1:3])), days (1.5))
%!assert_equal (iqr (days ([1:4])), days (2))
%!assert_equal (iqr (days ([1:5])), days (2.5))
%!assert_equal (iqr (days ([1:10])), days (5))
%!assert_equal (iqr (days ([1:10]')), days (5))
%!assert_equal (iqr (days ([1:10]), 2), days (5))
%!assert_equal (iqr (days ([1:10]), 1), days (zeros (1, 10)))
%!assert_equal (iqr (days ([1:10]), 3), days (zeros (1, 10)))
%!assert_equal (iqr (days ([1:5; 2:6]), [1, 2]), days (3))
%!assert_equal (iqr (days ([1:5; 2:6]), 'all'), days (3))
%!test
%! x = reshape (days (1:6), [1, 2, 3]);
%! assert_equal (iqr (x), days (ones (1, 1, 3)));
%! assert_equal (iqr (x, 1), days (zeros (1, 2, 3)));
%! assert_equal (iqr (x, 2), days (ones (1, 1, 3)));
%! assert_equal (iqr (x, 3), days ([3, 3]));
%!test
%! x = magic (4); x = cat (3,x, 2*x, 3*x); x = cat (4, x, 2*x);
%! y = cat (3, 8*[1, 1, 1, 1], 16*[1, 1, 1, 1], 24*[1, 1, 1, 1]);
%! x = days (x); y = days (y);
%! assert_equal (iqr (x), cat (4, y, 2*y));
%! assert_equal (iqr (x, 1), cat (4, y, 2*y));
%! y = cat (3, 4*[3, 1, 1, 3].', 8*[3, 1, 1, 3].', 12*[3, 1, 1, 3].');
%! y = days (y);
%! assert_equal (iqr (x, 2), cat (4, y, 2*y));
%! y = [24, 3, 4.5, 19.5; 7.5, 16.5, 15, 12; 13.5, 10.5, 9, 18; 6, 21, 22.5, 1.5];
%! y = days (y);
%! assert_equal (iqr (x, 3), cat (4, y, 2*y));
%! y = [16, 2, 3, 13; 5, 11, 10, 8; 9, 7, 6, 12; 4, 14, 15, 1];
%! y = days (y);
%! assert_equal (iqr (x, 4), cat (3, y, 2*y, 3*y));
%! assert_equal (iqr (x, 5), days (zeros (size (x))));
%!assert_equal (iqr (days (17), [1, 8]), duration)
%!assert_equal (iqr (days ([1, 2, 5; 2, 5, 6]), [1, 2]), days (3))
%!test
%! x = days (cat (3, [1, 2, 5; 2, 5, 6], [1, 2, 5; 2, 5, 6]));
%! assert_equal (iqr (x, [1, 2]), days (cat (3, 3, 3)));
%! assert_equal (iqr (x, [1, 2]'), days (cat (3, 3, 3)));

%!test
%! x = [-1; 0; 0; 0; 1];
%! y = days ([x, 2*x]);
%! assert_equal (kurtosis (y), [2.5, 2.5], sqrt (eps));
%!assert_equal (kurtosis (days ([-3, 0, 1])), kurtosis (days ([-1, 0, 3])))
%!assert_equal (kurtosis (days (ones (3, 5))), NaN (1, 5))
%!assert_equal (kurtosis (days (1), [], 3), NaN)
%!test
%! clear x;
%! x(:,:,1) = [0.5377, 0.3188, 3.5784; 1.8339, -1.3077, 2.7694; ...
%!             -2.2588, -0.4336, -1.3499; 0.8622, 0.3426, 3.0349];
%! x(:,:,2) = [0.7254, -0.1241, 0.6715; -0.0631, 1.4897, -1.2075; ...
%!             0.7147 1.4090 0.7172; -0.2050, 1.4172, 1.6302];
%! y = kurtosis (days (x));
%! assert_equal (class (y), 'double');
%! assert_equal (y(:,:,1), [2.1350, 1.7060, 2.2789], 1e-4);
%! assert_equal (y(:,:,2), [1.0542, 2.3278, 2.0996], 1e-4);
%! y = kurtosis (days (x), 1, 2);
%! assert_equal (y(:,:,1), [1.5; 1.5; 1.5; 1.5], 8 * eps);
%! assert_equal (y(:,:,2), [1.5; 1.5; 1.5; 1.5], 8 * eps);
%! y = kurtosis (days (x), 1, 3);
%! assert_equal (y, ones (4, 3), 8 * eps);
%!test
%! x(:,:,1) = [0.5377, 0.3188, 3.5784; 1.8339, -1.3077, 2.7694; ...
%!             -2.2588, -0.4336, -1.3499; 0.8622, 0.3426, 3.0349];
%! x(:,:,2) = [0.7254, -0.1241, 0.6715; -0.0631, 1.4897, -1.2075; ...
%!             0.7147 1.4090 0.7172; -0.2050, 1.4172, 1.6302];
%! y = kurtosis (days (x), 1, "all");
%! assert_equal (y, 2.8029, 1e-4);
%! y = kurtosis (days (x), 1, [1, 2]);
%! assert_equal (y(:,:,1), 1.9345, 1e-4);
%! assert_equal (y(:,:,2), 2.5877, 1e-4);
%! y = kurtosis (days (x), 1, [2, 3]);
%! assert_equal (y, [3.8457; 1.4306; 1.7094; 2.3378], 1e-4);

%!assert_equal (mad (days (123)), duration)
%!assert_equal (isnan (mad (days (Inf))), true)
%!assert_equal (mad (days ([3, Inf])), days (Inf))
%!assert_equal (mad (days ([0, 0, 1, 2, 100])), days (31.76))
%!assert_equal (mad (days ([0, 0, 1, 2, 100]')), days (31.76))
%!assert_equal (mad (days ([0, 0, 1, 2, 100]), 1), days (1))
%!assert_equal (mad (days ([0, 0, 1, 2, 100]'), 1), days (1))
%!assert_equal (mad (days (magic (4))), days ([4, 4, 4, 4]))
%!assert_equal (mad (days (magic (4)), [], 2), days ([6; 2; 2; 6]))
%!assert_equal (mad (days (magic (4)), 1), days ([2.5, 3.5, 3.5, 2.5]))
%!assert_equal (mad (days (magic (4)), 1, 2), days ([5.5; 1.5; 1.5; 5.5]))
%!assert_equal (mad (days (magic (4)), 0, 3), days (zeros (4)))
%!assert_equal (mad (days (magic (4)), 1, 3), days (zeros (4)))
%!assert_equal (mad (days (cat (3, magic (4), magic (4)))), days (4 * ones (1, 4, 2)))
%!assert_equal (mad (days (magic (4)), 0, "all"), days (4))
%!assert_equal (mad (days (magic (4)), 1, "all"), days (4))
%!assert_equal (mad (days (magic (4)), 0, [1 2]), days (4))
%!assert_equal (mad (days (magic (4)), 0, [1 3]), mad (days (magic (4)), 0, 1))
%!assert_equal (mad (days (magic (4)), 0, [1 2 3]), days (4))
%!assert_equal (mad (days (magic (4)), 1, [1 2]), days (4))
%!assert_equal (mad (days (magic (4)), 1, [1 3]), mad (days (magic (4)), 1, 1))
%!assert_equal (mad (days (magic (4)), 1, [1 2 3]), days (4))
%!assert_equal (mad (days (magic (4)), 0, [3 4 99]), days (zeros (4)))
%!assert_equal (mad (days (magic (4)), 1, [3 4 99]), days (zeros (4)))
%!assert_equal (isequaln (mad (days (NaN)), days (NaN)), true)
%!assert_equal (isequaln (mad (days (NaN (2))), days (NaN (1, 2))), true)
%!assert_equal (mad (days ([1, 2; 3, NaN])), days ([1, 0]))
%!assert_equal (isequaln (mad (days ([1, 2; 3, NaN]), [], 1), days ([1, 0])), true)
%!assert_equal (isequaln (mad (days ([1, NaN; 3, NaN]), [], 1), days ([1, NaN])), true)
%!assert_equal (mad (days ([1, NaN; 3, NaN]), [], 2), days ([0; 0]))

%!test
%! F = days ([2, 11, 6]);
%! A = days ([3, 10, 8]);
%! assert_equal (mape (F, A), 22.7778, 1e-4);
%! assert_equal (mape (F, A, 1), [33.3333, 10.0000, 25.0000], 1e-4);
%! assert_equal (mape (F, A, 2), 22.7778, 1e-4);
%! assert_equal (mape (F, A, 3), [33.3333, 10.0000, 25.0000], 1e-4);
%! assert_equal (mape (F, A, 'all'), 22.7778, 1e-4);
%!test
%! F = days ([3; 7; 4; NaN]);
%! A = days ([4; 0; 6; 4]);
%! assert_equal (mape (F, A), NaN);
%! assert_equal (mape (F, A, 'omitnan'), Inf);
%! assert_equal (mape (F, A, 'omitzero'), NaN);
%! assert_equal (mape (F, A, 'omitnan', 'omitzero'), 29.1667, 1e-4);
%! assert_equal (mape (F, A, 1, 'omitnan', 'omitzero'), 29.1667, 1e-4);
%! E = mape (F, A, 2, 'omitnan', 'omitzero');
%! assert_equal (E, [25; NaN; 33.3333; NaN], 1e-4);
%!test
%! F = days ([17, 21; 1, 5; 13, 17]);
%! A = days ([18, 19; 5, 4; 15, 13]);
%! assert_equal (mape (F, A), [32.9630, 22.0985], 1e-4);
%! assert_equal (mape (F, A, 1), [32.9630, 22.0985], 1e-4);
%! assert_equal (mape (F, A, 2), [8.0409; 52.5000; 22.0513], 1e-4);
%! assert_equal (mape (F, A, 'all'), 27.5307, 1e-4);
%! assert_equal (mape (F, A, [1, 2]), 27.5307, 1e-4);
%!test
%! F = days ([3, 5; -1, 2]);
%! F(:,:,2) = days ([4, 2; 7, -4]);
%! A = days ([6, 5; 0, 3]);
%! E = mape (F, A, [1, 2]);
%! assert_equal (E(:,:,1), Inf);
%! assert_equal (E(:,:,2), Inf);
%! E = mape (F, A, [1, 2], 'omitzero');
%! assert_equal (E(:,:,1), 27.7778, 1e-4);
%! assert_equal (E(:,:,2), 108.8889, 1e-4);
%! assert_equal (mape (F, A, [1, 3]), [Inf, 81.6667], 1e-4);
%! assert_equal (mape (F, A, [1, 3], 'omitzero'), [41.6667, 81.6667], 1e-4);
%! assert_equal (mape (F, A, [2, 3]), [35.8333; Inf], 1e-4);
%! assert_equal (mape (F, A, [2, 3], 'omitzero'), [35.8333; 133.3333], 1e-4);
%!assert_equal (mape ([1:4], zeros (1, 4)), Inf)
%!assert_equal (mape ([1:4], zeros (1, 4), "omitzero"), NaN)
%!test
%! F = days ([2, 11, 6]);
%! A = days ([3, 10, 8]);
%! W = [1, 2, 1];
%! assert_equal (mape (F, A, 'Weights', W), 19.5833, 1e-4);
%! assert_equal (mape (F, A, 1, 'Weights', W), [33.3333, 10, 25], 1e-4);
%! assert_equal (mape (F, A, 2, 'Weights', W), 19.5833, 1e-4);
%! assert_equal (mape (F, A, 3, 'Weights', W), [33.3333, 10, 25], 1e-4);
%!test
%! F = days ([3; 7; 4; NaN]);
%! A = days ([4; 0; 6; 4]);
%! W = [1, 2, 1, 2];
%! assert_equal (mape (F, A, 'Weights', W), NaN);
%! assert_equal (mape (F, A, 'omitnan', 'Weights', W), Inf);
%! assert_equal (mape (F, A, 'omitzero', 'Weights', W), NaN);
%! assert_equal (mape (F, A, 'omitnan', 'omitzero', 'Weights', W), 29.1667, 1e-4);
%! assert_equal (mape (F, A, 1, 'omitnan', 'omitzero', 'Weights', W), 29.1667, 1e-4);
%!test
%! F = days ([3; 7; 4; NaN]);
%! A = days ([4; 0; 6; 4]);
%! W = [1; 2; 1; 2];
%! E = mape (F, A, 2, 'omitnan', 'omitzero', 'Weights', W);
%! assert_equal (E, [25; NaN; 33.3333; NaN], 1e-4);
%! E = mape (F, A, 3, 'omitnan', 'omitzero', 'Weights', W);
%! assert_equal (E, [25; NaN; 33.3333; NaN], 1e-4);
%!test
%! F = days ([3, 5; -1, 2]);
%! F(:,:,2) = days ([4, 2; 7, -4]);
%! A = days ([6, 5; 0, 3]);
%! W = [1, 1; 1, 1];
%! Ew = mape (F, A, [1, 2], 'omitzero', 'Weights', W);
%! E = mape (F, A, [1, 2], 'omitzero');
%! assert_equal (Ew, E);
%! Ew = mape (F, A, [1, 3], 'omitzero', 'Weights', W);
%! E = mape (F, A, [1, 3], 'omitzero');
%! assert_equal (Ew, E);
%! Ew = mape (F, A, [2, 3], 'omitzero', 'Weights', W);
%! E = mape (F, A, [2, 3], 'omitzero');
%! assert_equal (Ew, E);
%!test
%! F = days ([3, 5; -1, 2]);
%! F(:,:,2) = days ([4, NaN; 7, -4]);
%! A = days ([6, 5; 2, 3]);
%! W = [1, 1; 1, 1];
%! Ew = mape (F, A, [1, 2], 'omitnan', 'Weights', W);
%! E = mape (F, A, [1, 2], 'omitnan');
%! assert_equal (Ew, E);
%! Ew = mape (F, A, [1, 3], 'omitnan','Weights', W);
%! E = mape (F, A, [1, 3], 'omitnan');
%! assert_equal (Ew, E);
%! Ew = mape (F, A, [2, 3], 'omitnan','Weights', W);
%! E = mape (F, A, [2, 3], 'omitnan');
%! assert_equal (Ew, E);
%!error<duration.mape: both F and A must be duration arrays.> ...
%! mape (days ([1, 2, 3]), 1:3)
%!error<duration.mape: both F and A must be duration arrays.> ...
%! mape (1:3, days ([1, 2, 3]))

%!assert_equal (mean (days (magic (3)), 1), days ([5, 5, 5]))
%!assert_equal (mean (days (magic (3)), 2), days ([5; 5; 5]))
%!test
%! x = days ([-10:10]);
%! y = [x;x+5;x-5];
%! assert_equal (mean (x), days (0));
%! assert_equal (mean (y, 2), days ([0, 5, -5]'));
%! assert_equal (mean (y, 'all'), days (0));
%! y(2,4) = NaN;
%! assert_equal (all (mean (y', 'omitnan') - days ([0, 5.35, -5]) < 1e-14), true);
%! z = y + 20;
%! assert_equal (isequaln (mean (z, "all"), days (NaN)), true);
%! assert_equal (isequaln (mean (z, "all", "includenan"), days (NaN)), true);
%! assert_equal (days (mean (z, "all", "omitnan")), 20.03225806451613, 4e-14);
%!test
%! x = repmat ([1:20;6:25], [5 2 6 3]);
%! assert_equal (size (mean (x, [3 2])), [10 1 1 3]);
%! assert_equal (size (mean (x, [1 2])), [1 1 6 3]);
%! assert_equal (size (mean (x, [1 2 4])), [1 1 6]);
%! assert_equal (size (mean (x, [1 4 3])), [1 40]);
%! assert_equal (size (mean (x, [1 2 3 4])), [1 1]);

## Test exceeding dimensions
%!assert_equal (mean (days (ones (2, 2)), 3), days (ones (2, 2)))
%!assert_equal (mean (days (ones (2, 2, 2)), 99), days (ones (2, 2, 2)))
%!assert_equal (mean (days (magic (3)), 3), days (magic (3)))
%!assert_equal (mean (days (magic (3)), [1, 3]), days ([5, 5, 5]))
%!assert_equal (mean (days (magic (3)), [1, 99]), days ([5, 5, 5]))
%!test
%! x = days ([1, 1; 7, 9; 1, 9; 1, 9; 6, 2]);
%! w = [1; 2; 1; 2; 3];
%! assert_equal (days (mean (x, 'Weights', w)), [4, 5.7778], 1e-4);
%! assert_equal (days (mean (x, 'Weights', w')), [4, 5.7778], 1e-4);
%! assert_equal (days (mean (x, 1, 'Weights', w)), [4, 5.7778], 1e-4);
%! assert_equal (days (mean (x, 1, 'Weights', w')), [4, 5.7778], 1e-4);
%! assert_equal (days (mean (x', 2, 'Weights', w)), [4; 5.7778], 1e-4);
%! assert_equal (days (mean (x', 2, 'Weights', w')), [4; 5.7778], 1e-4);
%!test
%! x = days ([1, 1; 7, 9; 1, 9; 1, 9; 6, 2]);
%! x = reshape (x', [1, 2, 5]);
%! w = [1, 2, 1, 2, 3];
%! assert_equal (size (x)([1, 3]), size (w));
%! assert_equal (days (mean (x, [1, 3], 'Weights', w)), [4, 5.7778], 1e-4);
%!test
%! x = days ([1, 1; 7, 9; 1, 9; 1, 9; 6, 2]);
%! x = reshape (x', [1, 2, 5]);
%! w = ones (1, 2, 5);
%! assert_equal (size (x), size (w));
%! assert_equal (days (mean (x, 'all', 'Weights', w)), days (mean (x, 'all')), 1e-4);
%! assert_equal (days (mean (x, [1, 2, 3], 'Weights', w)), days (mean (x, [1, 2, 3])), 1e-4);

%!assert_equal (median (days (1)), days (1))
%!assert_equal (median (days ([1, 2, 3])), days (2))
%!assert_equal (median (days ([1, 2, 3]')), days (2))
%!assert_equal (median (days (cat (3, 3, 1, 2))), days (2))
%!assert_equal (median (days ([3, 1, 2])), days (2))
%!assert_equal (median (days ([2, 4, 6, 8])), days (5))
%!assert_equal (median (days ([8, 2, 6, 4])), days (5))
%!assert_equal (median (days ([1, 2]), 3), days ([1, 2]))
%!test
%! x = days ([1, 2, 3, 4, 5, 6]);
%! x2 = x';
%! y = days ([1, 2, 3, 4, 5, 6, 7]);
%! y2 = y';
%!
%! assert_equal (median (x) == median (x2) && median (x) == days (3.5), true);
%! assert_equal (median (y) == median (y2) && median (y) == days (4), true);
%! assert_equal (median ([x2, 2 * x2]), days ([3.5, 7]));
%! assert_equal (median ([y2, 3 * y2]), days ([4, 12]));
%!test
%! x = repmat (days ([2 2.1 2.2 2 NaN; 3 1 2 NaN 5; 1 1.1 1.4 5 3]), [1, 1, 4]);
%! y = repmat (days ([2 1.1 2 NaN NaN]), [1, 1, 4]);
%! assert_equal (isequaln (median (x), y), true);
%! assert_equal (isequaln (median (x, 1), y), true);
%! y = repmat (days ([2, 1.1, 2, 3.5, 4]), [1, 1, 4]);
%! assert_equal (median (x, "omitnan"), y);
%! assert_equal (median (x, 1, "omitnan"), y);
%! y = repmat (days ([2.05; 2.5; 1.4]), [1, 1, 4]);
%! ## Averaging two stored values and building one from a day figure differ in
%! ## the last bit, as they do in MATLAB, which stores milliseconds too.
%! assert_equal (milliseconds (median (x, 2, "omitnan")), ...
%!               milliseconds (y), 1e-6);
%! y = repmat (days ([NaN; NaN; 1.4]), [1, 1, 4]);
%! assert_equal (isequaln (median (x, 2), y), true);
%! assert_equal (isequaln (median (x, "all"), NaN), true);
%! assert_equal (isequaln (median (x, "all", "omitnan"), 2), true);
%!assert_equal (median (cat (3, 3, 1, NaN, 2), "omitnan"), 2)
%!assert_equal (median (cat (3, 3, 1, NaN, 2), 3, "omitnan"), 2)

%!test
%! [m, f, c] = mode (days (toeplitz (1:5)));
%! assert_equal (m, days ([1, 2, 2, 2, 1]));
%! assert_equal (f, [1, 2, 2, 2, 1]);
%! assert_equal (c, {days([1;2;3;4;5]), days(2), days([2;3]), days(2), days([1;2;3;4;5])});
%!test
%! [m, f, c] = mode (days (toeplitz (1:5)), 2);
%! assert_equal (m, days ([1; 2; 2; 2;1 ]));
%! assert_equal (f, [1; 2; 2; 2; 1]);
%! assert_equal (c, {days([1;2;3;4;5]); days(2); days([2;3]); days(2); days([1;2;3;4;5])});
%!assert_equal (mode (days ([2,3,1,2,3,4]), 1), days ([2,3,1,2,3,4]))
%!assert_equal (mode (days ([2,3,1,2,3,4]), 2), days (2))
%!assert_equal (mode (days ([2,3,1,2,3,4])), days (2))
%!assert_equal (mode (days ([2;3;1;2;3;4]), 1), days (2))
%!assert_equal (mode (days ([2;3;1;2;3;4]), 2), days ([2;3;1;2;3;4]))
%!assert_equal (mode (days ([2;3;1;2;3;4])), days (2))
%!shared
%!shared x
%! x(:,:,1) = toeplitz (1:3);
%! x(:,:,2) = circshift (toeplitz (1:3), 1);
%! x(:,:,3) = circshift (toeplitz (1:3), 2);
%! x = days (x);
%!test
%! [m, f, c] = mode (x, 1);
%! assert_equal (reshape (m, [3, 3]), days ([1, 1, 1; 2, 2, 2; 1, 1, 1]));
%! assert_equal (reshape (f, [3, 3]), [1, 1, 1; 2, 2, 2; 1, 1, 1]);
%! c = reshape (c, [3, 3]);
%! assert_equal (c{1}, days ([1; 2; 3]));
%! assert_equal (c{2}, days (2));
%! assert_equal (c{3}, days ([1; 2; 3]));
%!test
%! [m, f, c] = mode (x, 2);
%! assert_equal (reshape (m, [3, 3]), days ([1, 1, 2; 2, 1, 1; 1, 2, 1]));
%! assert_equal (reshape (f, [3, 3]), [1, 1, 2; 2, 1, 1; 1, 2, 1]);
%! c = reshape (c, [3, 3]);
%! assert_equal (c{1}, days ([1; 2; 3]));
%! assert_equal (c{2}, days (2));
%! assert_equal (c{3}, days ([1; 2; 3]));
%!test
%! [m, f, c] = mode (x, 3);
%! assert_equal (reshape (m, [3, 3]), days ([1, 2, 1; 1, 2, 1; 1, 2, 1]));
%! assert_equal (reshape (f, [3, 3]), [1, 2, 1; 1, 2, 1; 1, 2, 1]);
%! c = reshape (c, [3, 3]);
%! assert_equal (c{1}, days ([1; 2; 3]));
%! assert_equal (c{2}, days ([1; 2; 3]));
%! assert_equal (c{3}, days ([1; 2; 3]));
%!shared

%!test
%! pct = 50;
%! q = prctile (days (1:4), pct);
%! qa = days (2.5);
%! assert_equal (q, qa);
%! q = prctile (days (1:4), pct, 1);
%! qa = days ([1, 2, 3, 4]);
%! assert_equal (q, qa);
%! q = prctile (days (1:4), pct, 2);
%! qa = days (2.5);
%! assert_equal (q, qa);
%!test
%! pct = [50 75];
%! q = prctile (days (1:4), pct);
%! qa = days ([2.5, 3.5]);
%! assert_equal (q, qa);
%! q = prctile (days (1:4), pct, 1);
%! qa = days ([1, 2, 3, 4; 1, 2, 3, 4]);
%! assert_equal (q, qa);
%! q = prctile (days (1:4), pct, 2);
%! qa = days ([2.5, 3.5]);
%! assert_equal (q, qa);
%!test
%! pct = 50;
%! x = [0.1126, 0.1148, 0.0521, 0.2364, 0.1393
%!      0.1718, 0.7273, 0.2041, 0.4531, 0.1585
%!      0.2795, 0.7978, 0.3296, 0.5567, 0.7307
%!      0.4288, 0.8753, 0.6477, 0.6287, 0.8165
%!      0.9331, 0.9312, 0.9635, 0.7796, 0.8461];
%! tol = 0.0001;
%! q = days (prctile (days (x), pct, 1));
%! qa = [0.2795, 0.7978, 0.3296, 0.5567, 0.7307];
%! assert_equal (q, qa, tol);
%! q = days (prctile (days (x), pct, 2));
%! qa = [0.1148; 0.2041; 0.5567; 0.6477; 0.9312];
%! assert_equal (q, qa, tol);
%!test
%! pct = 50;
%! tol = 0.0001;
%! x = [0.1126, 0.1148, 0.0521, 0.2364, 0.1393
%!      0.1718, 0.7273, 0.2041, 0.4531, 0.1585
%!      0.2795, 0.7978, 0.3296, 0.5567, 0.7307
%!      0.4288, 0.8753, 0.6477, 0.6287, 0.8165
%!      0.9331, 0.9312, 0.9635, 0.7796, 0.8461];
%! x(5,5) = Inf;
%! q = days (prctile (days (x), pct, 1));
%! qa = [0.2795, 0.7978, 0.3296, 0.5567, 0.7307];
%! assert_equal (q, qa, tol);
%! x(5,5) = -Inf;
%! q = days (prctile (days (x), pct, 1));
%! qa = [0.2795, 0.7978, 0.3296, 0.5567, 0.1585];
%! assert_equal (q, qa, tol);
%! x(1,1) = Inf;
%! q = days (prctile (days (x), pct, 1));
%! qa = [0.4288, 0.7978, 0.3296, 0.5567, 0.1585];
%! assert_equal (q, qa, tol);
%!test
%! pct = 50;
%! tol = 0.0001;
%! x = [0.1126, 0.1148, 0.0521, 0.2364, 0.1393
%!      0.1718, 0.7273, 0.2041, 0.4531, 0.1585
%!      0.2795, 0.7978, 0.3296, 0.5567, 0.7307
%!      0.4288, 0.8753, 0.6477, 0.6287, 0.8165
%!      0.9331, 0.9312, 0.9635, 0.7796, 0.8461];
%! x(3,3) = Inf;
%! q = days (prctile (days (x), pct, 1));
%! qa = [0.2795, 0.7978, 0.6477, 0.5567, 0.7307];
%! assert_equal (q, qa, tol);
%! q = days (prctile (days (x), pct, 2));
%! qa = [0.1148; 0.2041; 0.7307; 0.6477; 0.9312];
%! assert_equal (q, qa, tol);
%!test
%! pct = 50;
%! tol = 0.0001;
%! x = [0.1126, 0.1148, 0.0521, 0.2364, 0.1393
%!      0.1718, 0.7273, 0.2041, 0.4531, 0.1585
%!      0.2795, 0.7978, 0.3296, 0.5567, 0.7307
%!      0.4288, 0.8753, 0.6477, 0.6287, 0.8165
%!      0.9331, 0.9312, 0.9635, 0.7796, 0.8461];
%! x(5,5) = NaN;
%! q = days (prctile (days (x), pct, 2));
%! qa = [0.1148; 0.2041; 0.5567; 0.6477; 0.9322];
%! assert_equal (q, qa, tol);
%! x(1,1) = NaN;
%! q = days (prctile (days (x), pct, 2));
%! qa = [0.1270; 0.2041; 0.5567; 0.6477; 0.9322];
%! assert_equal (q, qa, tol);
%! x(3,3) = NaN;
%! q = days (prctile (days (x), pct, 2));
%! qa = [0.1270; 0.2041; 0.6437; 0.6477; 0.9322];
%! assert_equal (q, qa, tol);
%!assert_equal (prctile (days ([1:10]), 1, 3), days ([1:10]))

%!test
%! p = 0.50;
%! q = quantile (days (1:4), p);
%! qa = days (2.5);
%! assert_equal (q, qa);
%! q = quantile (days (1:4), p, 1);
%! qa = days ([1, 2, 3, 4]);
%! assert_equal (q, qa);
%! q = quantile (days (1:4), p, 2);
%! qa = days (2.5);
%! assert_equal (q, qa);
%!test
%! p = [0.50 0.75];
%! q = quantile (days (1:4), p);
%! qa = days ([2.5 3.5]);
%! assert_equal (q, qa);
%! q = quantile (days (1:4), p, 1);
%! qa = days ([1, 2, 3, 4; 1, 2, 3, 4]);
%! assert_equal (q, qa);
%! q = quantile (days (1:4), p, 2);
%! qa = days ([2.5 3.5]);
%! assert_equal (q, qa);
%!test
%! p = 0.5;
%! x = days (sort (rand (11)));
%! q = quantile (x, p);
%! assert_equal (q, x(6,:));
%! x = x.';
%! q = quantile (x, p, 2);
%! assert_equal (q, x(:,6));
%!test
%! sx = [2, 3, 4];
%! x = days (rand (sx));
%! dim = 2;
%! p = 0.5;
%! yobs = quantile (x, p, dim);
%! yexp = median (x, dim);
%! assert_equal (yobs, yexp);

%!assert_equal (range (days (1:10)), days (9))
%!assert_equal (range (days (magic (3))), days ([5, 8, 5]))
%!assert_equal (range (days (magic (3)), 2), days ([7; 4; 7]))
%!assert_equal (range (days (2)), duration)
%!test
%! x = days (magic (3));
%! x(2,3) = NaN;
%! assert_equal (range (x), days ([5, 8, 4]));
%! assert_equal (range (x, "omitnan"), days ([5, 8, 4]));
%! assert_equal (isequaln (range (x, "includenan"), days ([5, 8, NaN])), true);
%! assert_equal (range (x, 2), days ([7; 2; 7]));
%! assert_equal (range (x, 2, "omitnan"), days ([7; 2; 7]));
%! assert_equal (isequaln (range (x, 2, "includenan"), days ([7; NaN; 7])), true);
%!test
%! x = reshape (days (1:27), [3, 3, 3]);
%! assert_equal (range (x, 3), x(:,:,3) - x(:,:,1));
%!test
%! x = reshape (days (1:27), [3, 3, 3]);
%! assert_equal (range (x, [2, 3]), x(:,3,3) - x(:,1,1));
%!test
%! x = reshape (days (1:27), [3, 3, 3]);
%! assert_equal (range (x, [1, 3]), x(3,:,3) - x(1,:,1));
%!test
%! x = reshape (days (1:27), [3, 3, 3]);
%! assert_equal (range (x, [1, 2, 3]), days (26));
%!test
%! x = reshape (days (1:27), [3, 3, 3]);
%! assert_equal (range (x, "all"), days (26));
%!test
%! x = reshape (days (1:27), [3, 3, 3]);
%! x(3) = NaN;
%! assert_equal (range (x, "all"), days (26));
%!test
%! x = reshape (days (1:27), [3, 3, 3]);
%! x(3) = NaN;
%! assert_equal (range (x, "all", "omitnan"), days (26));
%!test
%! x = reshape (days (1:27), [3, 3, 3]);
%! x(3) = NaN;
%! assert_equal (isequaln (range (x, "all", "includenan"), days (NaN)), true);
%!test
%! x = reshape (days (1:27), [3, 3, 3]);
%! x(3) = NaN;
%! s = min (x, [], "includenan");
%! l = max (x, [], "includenan");
%! assert_equal (isequaln (range (x, "includenan"), l - s), true);
%!test
%! x = reshape (days (1:27), [3, 3, 3]);
%! x(3) = NaN;
%! y = range (x, 3, "includenan");
%! assert_equal (isequaln (y(3), days (NaN)), true);

%!test
%! F = days ([2, 11, 6]);
%! A = days ([3, 10, 8]);
%! assert_equal (days (rmse (F, A)), sqrt (2), eps);
%! assert_equal (days (rmse (F, A, 1)), [1, 1, 2], eps);
%! assert_equal (days (rmse (F, A, 2)), sqrt (2), eps);
%! assert_equal (days (rmse (F, A, 3)), [1, 1, 2], eps);
%! assert_equal (days (rmse (F, A, 'all')), sqrt (2), eps);
%!test
%! F = days ([3; 7; 4; NaN]);
%! A = days ([4; 0; 6; 4]);
%! assert_equal (days (rmse (F, A)), NaN);
%! assert_equal (days (rmse (F, A, 'omitnan')), 4.2426, 1e-4);
%! assert_equal (days (rmse (F, A, 1, 'omitnan')), 4.2426, 1e-4);
%! assert_equal (days (rmse (F, A, 2, 'omitnan')), [1; 7; 2; NaN]);
%!test
%! F = days ([17, 21; 1, 5; 13, 17]);
%! A = days ([18, 19; 5, 4; 15, 13]);
%! assert_equal (days (rmse (F, A)), [2.6458, 2.6458], 1e-4);
%! assert_equal (days (rmse (F, A, 1)), [2.6458, 2.6458], 1e-4);
%! assert_equal (days (rmse (F, A, 2)), [1.5811; 2.9155; 3.1623], 1e-4);
%! assert_equal (days (rmse (F, A, 'all')), 2.6458, 1e-4);
%! assert_equal (days (rmse (F, A, [1, 2])), 2.6458, 1e-4);
%!test
%! F = days ([3, 5; -1, 2]);
%! F(:,:,2) = days ([4, 2; 7, -4]);
%! A = days ([6, 5; NaN, 3]);
%! E = days (rmse (F, A, [1, 2]));
%! assert_equal (E(:,:,1), NaN);
%! assert_equal (E(:,:,2), NaN);
%! E = days (rmse (F, A, [1, 2], 'omitnan'));
%! assert_equal (E(:,:,1), 1.8257, 1e-4);
%! assert_equal (E(:,:,2), 4.5461, 1e-4);
%! assert_equal (days (rmse (F, A, [1, 3])), [NaN, 3.8406], 1e-4);
%! assert_equal (days (rmse (F, A, [1, 3], 'omitnan')), [2.5495, 3.8406], 1e-4);
%! assert_equal (days (rmse (F, A, [2, 3])), [2.3452; NaN], 1e-4);
%! assert_equal (days (rmse (F, A, [2, 3], 'omitnan')), [2.3452; 5], 1e-4);
%!test
%! F = days ([2, 11, 6]);
%! A = days ([3, 10, 8]);
%! W = [1, 2, 1];
%! assert_equal (days (rmse (F, A, 'Weights', W)), 1.3229, 1e-4);
%! assert_equal (days (rmse (F, A, 1, 'Weights', W)), [1, 1, 2]);
%! assert_equal (days (rmse (F, A, 2, 'Weights', W)), 1.3229, 1e-4);
%! assert_equal (days (rmse (F, A, 3, 'Weights', W)), [1, 1, 2]);
%!test
%! F = days ([3; 7; 4; NaN]);
%! A = days ([4; 0; 6; 4]);
%! W = [1, 2, 1, 2];
%! assert_equal (days (rmse (F, A, 'Weights', W)), NaN);
%! assert_equal (days (rmse (F, A, 'omitnan', 'Weights', W)), 5.0744, 1e-4);
%! assert_equal (days (rmse (F, A, 1, 'omitnan', 'Weights', W)), 5.0744, 1e-4);
%!test
%! F = days ([3; 7; 4; NaN]);
%! A = days ([4; 0; 6; 4]);
%! W = [1; 2; 1; 2];
%! assert_equal (days (rmse (F, A, 2, 'Weights', W)), [1; 7; 2; NaN], 1e-4);
%! assert_equal (days (rmse (F, A, 2, 'omitnan', 'Weights', W)), [1; 7; 2; NaN], 1e-4);
%! assert_equal (days (rmse (F, A, 3, 'Weights', W)), [1; 7; 2; NaN], 1e-4);
%! assert_equal (days (rmse (F, A, 3, 'omitnan', 'Weights', W)), [1; 7; 2; NaN], 1e-4);
%!test
%! F = days ([3, 4; 7, 5; 4, 3; NaN, 8]);
%! A = days ([4; 0; 6; 4]);
%! W = [3; 1; 2; 2];
%! E = days (rmse (F, A, 1, 'omitnan', 'Weights', W));
%! assert_equal (E, [3.1623, 3.0619], 1e-4);
%!test
%! F = days ([3, 4; 7, 5; 4, 3; NaN, 8]);
%! A = days ([4; 0; 6; 4]);
%! W = [3, 0.4; 1, 0.2; 2, 0.2; 2, 0.2];
%! assert_equal (days (rmse (F, A, 1, 'Weights', W)), [NaN, 3.1623], 1e-4);
%! assert_equal (days (rmse (F, A, 1, 'omitnan', 'Weights', W)), [3.1623, 3.1623], 1e-4);
%! assert_equal (days (rmse (F, A, 2, 'Weights', W)), [0.9393; 6.7082; 2.1106; NaN], 1e-4);
%! E = rmse (F, A, 2, 'omitnan', 'Weights', W);
%! assert_equal (days (E), [0.9393; 6.7082; 2.1106; 4], 1e-4);
%!test
%! F = days ([3, 5; -1, 2]);
%! F(:,:,2) = days ([4, NaN; 7, -4]);
%! A = days ([6, 5; 2, 3]);
%! W = [1, 1; 1, 1];
%! Ew = rmse (F, A, [1, 2], 'omitnan', 'Weights', W);
%! E = rmse (F, A, [1, 2], 'omitnan');
%! assert_equal (Ew, E);
%! Ew = rmse (F, A, [1, 3], 'omitnan','Weights', W);
%! E = rmse (F, A, [1, 3], 'omitnan');
%! assert_equal (Ew, E);
%! Ew = rmse (F, A, [2, 3], 'omitnan','Weights', W);
%! E = rmse (F, A, [2, 3], 'omitnan');
%! assert_equal (Ew, E);
%!test
%! F = days ([3, 5; -1, 2]);
%! F(:,:,2) = days ([4, 2; 7, -4]);
%! A = days ([6, 5; 0, 3]);
%! W = [1, 2; 1, 1];
%! F1 = reshape (F, 1, 4, 2);
%! A1 = reshape (A, 1, 4);
%! W1 = reshape (W, 1, 4);
%! E1w = days (rmse (F1, A1, 2, 'Weights', W1));
%! assert_equal (E1w(:,:,1), 1.4832, 1e-4);
%! assert_equal (E1w(:,:,2), 4.8990, 1e-4);
%! E1 = days (rmse (F1, A1, 2));
%! assert_equal (E1(:,:,1), 1.6583, 1e-4);
%! assert_equal (E1(:,:,2), 5.2678, 1e-4);
%! assert_equal (days (rmse (F, A, [1, 2], 'Weights', W)), E1w, 1e-12);
%! assert_equal (days (rmse (F, A, [1, 2])), E1, 1e-12);
%!test
%! F = days ([3, 5; -1, 2]);
%! F(:,:,2) = days ([4, 2; 7, -4]);
%! A = days ([6, 5; 0, 3]);
%! W = [0.5, 2; 1, 3];
%! F1 = reshape (F, 2, 4, 1);
%! A1 = reshape (repmat (A, 1, 1, 2), 2, 4, 1);
%! W1 = [0.5, 1, 2, 3; 0.5, 1, 2, 3];
%! E1w = rmse (F1, A1, 2, 'Weights', W1);
%! assert_equal (days (E1w), [2.4651; 6.1582], 1e-4);
%! E1 = rmse (F1, A1, 2);
%! assert_equal (days (E1), [2.3452; 5], 1e-4);
%! assert_equal (rmse (F, A, [2, 3], 'Weights', W), E1w);
%! assert_equal (rmse (F, A, [2, 3]), E1);
%!error<duration.rmse: both F and A must be duration arrays.> ...
%! rmse (days ([1, 2, 3]), 1:3)
%!error<duration.rmse: both F and A must be duration arrays.> ...
%! rmse (1:3, days ([1, 2, 3]))

%!assert_equal (skewness (days ([-1, 0, 1])), 0)
%!assert_equal (skewness (days ([-2, 0, 1])) < 0, true)
%!assert_equal (skewness (days ([-1, 0, 2])) > 0, true)
## Skewness is scale free, so the sign flips with the data; the two are
## equal to within a rounding of the stored milliseconds.
%!assert_equal (skewness (days ([-3, 0, 1])), -1 * skewness ([-1, 0, 3]), 1e-12)
%!assert_equal (skewness (days (ones (3, 5))), NaN (1, 5))
%!assert_equal (skewness (days (1), [], 3), NaN)
%!test
%! x = [0; 0; 0; 1];
%! y = days ([x, 2*x]);
%! assert_equal (skewness (y), 1.154700538379251 * [1 1], 5*eps);
%!assert_equal (skewness (days ([1:5, 10; 1:5, 10]),  0, 2), 1.439590274527954 * [1; 1], eps)
%!assert_equal (skewness (days ([1:5, 10; 1:5, 10]),  1, 2), 1.051328089232020 * [1; 1], 2*eps)
%!assert_equal (skewness (days ([1:5, 10; 1:5, 10]), [], 2), 1.051328089232020 * [1; 1], 2*eps)
%!test
%! x(:,:,1) = [0.5377, 0.3188, 3.5784; 1.8339, -1.3077, 2.7694; ...
%!             -2.2588, -0.4336, -1.3499; 0.8622, 0.3426, 3.0349];
%! x(:,:,2) = [0.7254, -0.1241, 0.6715; -0.0631, 1.4897, -1.2075; ...
%!             0.7147 1.4090 0.7172; -0.2050, 1.4172, 1.6302];
%! y = skewness (days (x));
%! assert_equal (y(:,:,1), [-0.8084, -0.5578, -1.0772], 1e-4);
%! assert_equal (y(:,:,2), [-0.0403, -1.1472, -0.6632], 1e-4);
%! y = skewness (days (x), 1, 2);
%! assert_equal (y(:,:,1), [0.6956; -0.5575; 0.0049; 0.6033], 1e-4);
%! assert_equal (y(:,:,2), [-0.6969; 0.1828; 0.7071; -0.6714], 1e-4);
%! y = skewness (days (x), 1, 3);
%! assert_equal (y, zeros (4, 3), 8 * eps);
%!test
%! x(:,:,1) = [0.5377, 0.3188, 3.5784; 1.8339, -1.3077, 2.7694; ...
%!             -2.2588, -0.4336, -1.3499; 0.8622, 0.3426, 3.0349];
%! x(:,:,2) = [0.7254, -0.1241, 0.6715; -0.0631, 1.4897, -1.2075; ...
%!             0.7147 1.4090 0.7172; -0.2050, 1.4172, 1.6302];
%! y = skewness (days (x), 1, "all");
%! assert_equal (y, 0.0916, 1e-4);
%! y = skewness (days (x), 1, [1, 2]);
%! assert_equal (y(:,:,1), 0.1070, 1e-4);
%! assert_equal (y(:,:,2), -0.6263, 1e-4);
%! y = skewness (days (x), 1, [1, 3]);
%! assert_equal (y, [-1.0755, -0.3108, -0.2209], 1e-4);

%!test
%! x = days (ones (10, 2));
%! y = days ([1, 3]);
%! assert_equal (std (x), days ([0, 0]));
%! assert_equal (days (std (y)), sqrt (2), sqrt (eps));
%! assert_equal (std (x, 0, 2), days (zeros (10, 1)));
%!assert_equal (std (days (ones (3, 1, 2)), 0, 2), days (zeros (3, 1, 2)))
%!assert_equal (days (std (days ([1, 2]), 0)), sqrt (2)/2, 5*eps)
%!assert_equal (days (std (days ([1, 2]), 1)), 0.5, 5*eps)
%!assert_equal (std (days (1)), duration)
%!assert_equal (std (days ([1, 2, 3]), [], 3), days ([0, 0, 0]))
%!test
%! x = days ([-10:10]);
%! y = [x;x+5;x-5];
%! assert_equal (std (x), days (sqrt (38.5)));
%! assert_equal (std (y, [], 2), days (sqrt ([38.5; 38.5; 38.5])));
%! assert_equal (std (y, 0, 2), days (sqrt ([38.5; 38.5; 38.5])));
%! assert_equal (days (std (y, 1, 2)), sqrt (ones (3,1) * 36.66666666666666), 1e-14);
%! assert_equal (days (std (y, "all")), sqrt (54.19354838709678), 1e-14);
%! y(2,4) = NaN;
%! assert_equal (isequaln (std (y, "all"), days (NaN)), true);
%! assert_equal (isequaln (std (y, "all", "includenan"), days (NaN)), true);
%! assert_equal (days (std (y, "all", "omitnan")), sqrt (55.01533580116342), 1e-14);
%! assert_equal (isequaln (std (y, 0, 2, "includenan"), days (sqrt ([38.5; NaN; 38.5]))), true);
%! assert_equal (isequaln (std (y, [], 2), days (sqrt ([38.5; NaN; 38.5]))), true);
%! assert_equal (days (std (y, [], 2, "omitnan")), sqrt ([38.5; 37.81842105263158; 38.5]), 1e-14);
%!assert_equal (days (std (days ([1, NaN, 3]), [1 2 3], "omitnan")), sqrt (0.75), eps)
%!assert_equal (days (std (days ([1, 2, 3]), [1 NaN 3], "omitnan")), sqrt (0.75), eps)
%!assert_equal (days (std (days (magic (3)), [1 NaN 3], "omitnan")), sqrt ([3, 12, 3]), eps)
%!assert_equal (days (std (days ([1, NaN, 3]), [1 2 3], "omitnan", "all")), sqrt (0.75), eps)
%!assert_equal (days (std (days ([1, NaN, 3]), [1 2 3], "all", "omitnan")), sqrt (0.75), eps)
%!assert_equal (days (std (days ([1, 2, 3]), [1 NaN 3], "omitnan", "all")), sqrt (0.75), eps)
%!assert_equal (days (std (days ([1, NaN, 3]), [1 2 3], 2, "omitnan")), sqrt (0.75), eps)
%!assert_equal (days (std (days ([1, 2, 3]), [1 NaN 3], 2, "omitnan")), sqrt (0.75), eps)
%!assert_equal (days (std (days (magic (3)), [1 NaN 3], 1, "omitnan")), sqrt ([3, 12, 3]), eps)
%!assert_equal (days (std (days (magic (3)), [1 NaN 3], 2, "omitnan")), sqrt ([0.75;3;0.75]), eps)
%!assert_equal (days (std (days ([4, 4; 4, 6; 6, 6]), [1 3], 2, 'omitnan')), sqrt ([0;0.75;0]), eps)
%!assert_equal (days (std (days ([4, NaN; 4, 6; 6, 6]), [1, 2, 3], 1, 'omitnan')), sqrt ([1 0]))
%!assert_equal (days (std (days ([4, NaN; 4, 6; 6, 6]), [1, 3], 2, 'omitnan')), sqrt ([0;0.75;0]), eps)
%!assert_equal (days (std (days (3*reshape(1:18, [3, 3, 2])), [1, 2, 3], 1, 'omitnan')), ...
%!        sqrt (ones (1, 3, 2) * 5))
%!assert_equal (days (std (reshape (days (1:18), [3, 3, 2]), [1, 2, 3], 2, 'omitnan')), ...
%!        sqrt (5 * ones(3, 1, 2)))
%!assert_equal (days (std (3 * reshape (days (1:18), [3, 3, 2]), ones (3,3,2), [1 2], 'omitnan')), ...
%!        sqrt (60 * ones (1, 1, 2)))
%!assert_equal (days (std (3*reshape(days (1:18), [3, 3, 2]), ones (3,3,2), [1 4], 'omitnan')), ...
%!        sqrt (6 * ones (1, 3, 2)))
%!assert_equal (days (std (6 * reshape (days (1:18), [3, 3, 2]), ones (3,3,2), [1:3], 'omitnan')), sqrt (969))
%!test
%! x = reshape (days (1:18), [3, 3, 2]);
%! x([2, 14]) = NaN;
%! w = ones (3,3,2);
%! assert_equal (std (16 * x, w, [1:3], 'omitnan'), days (sqrt (6519)));

################################################################################
##                   ** Sort, Filter, and Set Operations **                   ##
################################################################################
##                             Available Methods                              ##
##                                                                            ##
## 'maxk'             'mink'             'sort'             'sortrows'        ##
## 'topkrows'         'unique'           'interp1'          'intersect'       ##
## 'setdiff'          'setxor'           'union'                              ##
##                                                                            ##
################################################################################

%!test
%! D = days ([3, 1, NaN, 2, 1, NaN]);
%! [B, I] = maxk (D, 3);
%! assert_equal (days (B), [3, 2, 1]);
%! assert_equal (I, [1, 4, 2]);
%!test
%! D = days ([3, 1, NaN, 2, 1, NaN]);
%! [B, I] = maxk (D, 10);
%! assert_equal (days (B), [3, 2, 1, 1, NaN, NaN]);
%! assert_equal (I, [1, 4, 2, 5, 3, 6]);
%!test
%! D = days ([3; 1; NaN; 2]);
%! [B, I] = maxk (D, 2);
%! assert_equal (days (B), [3; 2]);
%! assert_equal (I, [1; 4]);
%!test
%! D = days ([2, 1, 2, 1, 2]);
%! [B, I] = maxk (D, 3);
%! assert_equal (days (B), [2, 2, 2]);
%! assert_equal (I, [1, 3, 5]);
%!test
%! D = days ([1, 5; 4, 2; 3, 6]);
%! [B, I] = maxk (D, 2);
%! assert_equal (days (B), [4, 6; 3, 5]);
%! assert_equal (I, [2, 3; 3, 1]);
%!test
%! D = days ([1, 5; 4, 2; 3, 6]);
%! [B, I] = maxk (D, 2, 2);
%! assert_equal (days (B), [5, 1; 4, 2; 6, 3]);
%! assert_equal (I, [2, 1; 1, 2; 2, 1]);
%!test
%! D = days ([1, 5; 4, 2; 3, 6]);
%! [B, I] = maxk (D, 2, 3);
%! assert_equal (days (B), [1, 5; 4, 2; 3, 6]);
%! assert_equal (I, ones (3, 2));
%!test
%! D = days ([3, 1, NaN, 2, 1, NaN]);
%! [B, I] = maxk (D, 3, 1);
%! assert_equal (days (B), [3, 1, NaN, 2, 1, NaN]);
%! assert_equal (I, ones (1, 6));
%!test
%! D = days ([1, NaN; NaN, 2; 3, 4]);
%! [B, I] = maxk (D, 3);
%! assert_equal (days (B), [3, 4; 1, 2; NaN, NaN]);
%! assert_equal (I, [3, 3; 1, 2; 2, 1]);
%!test
%! D = days ([Inf, -Inf, 1, NaN]);
%! [B, I] = maxk (D, 4);
%! assert_equal (days (B), [Inf, 1, -Inf, NaN]);
%! assert_equal (I, [1, 3, 2, 4]);
%!test
%! D = days (reshape (1:24, 2, 3, 4));
%! [B, I] = maxk (D, 2, 3);
%! assert_equal (size (B), [2, 3, 2]);
%! assert_equal (days (B), days (D(:,:,[4, 3])));
%! assert_equal (I, cat (3, 4 * ones (2, 3), 3 * ones (2, 3)));
%!test
%! D = days ([NaN, NaN, NaN]);
%! [B, I] = maxk (D, 2);
%! assert_equal (days (B), [NaN, NaN]);
%! assert_equal (I, [1, 2]);
%!test
%! D = days ([3, 1, 2]);
%! D.Format = 'hh:mm';
%! B = maxk (D, 2);
%! assert_equal (B.Format, 'hh:mm');
%!assert_equal (class (maxk (days ([3, 1, 2]), 2)), 'duration')
%!assert_equal (size (maxk (days ([3, 1, 2]), 0)), [1, 0])
%!assert_equal (size (maxk (days ([1, 5; 4, 2; 3, 6]), 0)), [0, 2])
%!assert_equal (size (maxk (days ([]), 2)), [0, 0])
%!error<duration.maxk: too few input arguments.> maxk (days (1))
%!error<duration.maxk: K must be a nonnegative integer scalar.> ...
%! maxk (days ([1, 2, 3]), 2.5)
%!error<duration.maxk: K must be a nonnegative integer scalar.> ...
%! maxk (days ([1, 2, 3]), -1)
%!error<duration.maxk: K must be a nonnegative integer scalar.> ...
%! maxk (days ([1, 2, 3]), [2, 3])
%!error<duration.maxk: K must be a nonnegative integer scalar.> ...
%! maxk (days ([1, 2, 3]), Inf)
%!error<duration.maxk: DIM must be a positive integer scalar.> ...
%! maxk (days ([1, 2, 3]), 2, 0)
%!error<duration.maxk: DIM must be a positive integer scalar.> ...
%! maxk (days ([1, 2, 3]), 2, 1.5)
%!error<duration.maxk: 'ComparisonMethod' is not a supported option.> ...
%! maxk (days ([1, 2, 3]), 2, 'ComparisonMethod', 'abs')
%!error<duration.maxk: 'MissingPlacement' is not a supported option.> ...
%! maxk (days ([1, 2, 3]), 2, 'MissingPlacement', 'first')
%!error<duration.maxk: too many input arguments.> ...
%! maxk (days ([1, 2, 3]), 2, 1, 2)

%!test
%! D = days ([3, 1, NaN, 2, 1, NaN]);
%! [B, I] = mink (D, 3);
%! assert_equal (days (B), [1, 1, 2]);
%! assert_equal (I, [2, 5, 4]);
%!test
%! D = days ([3, 1, NaN, 2, 1, NaN]);
%! [B, I] = mink (D, 10);
%! assert_equal (days (B), [1, 1, 2, 3, NaN, NaN]);
%! assert_equal (I, [2, 5, 4, 1, 3, 6]);
%!test
%! D = days ([3, NaN, 1]);
%! [B, I] = mink (D, 3);
%! assert_equal (days (B), [1, 3, NaN]);
%! assert_equal (I, [3, 1, 2]);
%!test
%! D = days ([2, 1, 2, 1, 2]);
%! [B, I] = mink (D, 3);
%! assert_equal (days (B), [1, 1, 2]);
%! assert_equal (I, [2, 4, 1]);
%!test
%! D = days ([1, 5; 4, 2; 3, 6]);
%! [B, I] = mink (D, 2);
%! assert_equal (days (B), [1, 2; 3, 5]);
%! assert_equal (I, [1, 2; 3, 1]);
%!test
%! D = days ([1, 5; 4, 2; 3, 6]);
%! [B, I] = mink (D, 2, 2);
%! assert_equal (days (B), [1, 5; 2, 4; 3, 6]);
%! assert_equal (I, [1, 2; 2, 1; 1, 2]);
%!test
%! D = days ([1, NaN; NaN, 2; 3, 4]);
%! [B, I] = mink (D, 3);
%! assert_equal (days (B), [1, 2; 3, 4; NaN, NaN]);
%! assert_equal (I, [1, 2; 3, 3; 2, 1]);
%!test
%! D = days ([Inf, -Inf, 1, NaN]);
%! [B, I] = mink (D, 4);
%! assert_equal (days (B), [-Inf, 1, Inf, NaN]);
%! assert_equal (I, [2, 3, 1, 4]);
%!test
%! D = days ([3, 1, NaN, 2, 1, NaN]);
%! [B, I] = mink (D, 3, 1);
%! assert_equal (days (B), [3, 1, NaN, 2, 1, NaN]);
%! assert_equal (I, ones (1, 6));
%!test
%! D = days ([NaN, NaN, NaN]);
%! [B, I] = mink (D, 2);
%! assert_equal (days (B), [NaN, NaN]);
%! assert_equal (I, [1, 2]);
%!test
%! D = days ([3, 1, 2]);
%! D.Format = 'hh:mm';
%! B = mink (D, 2);
%! assert_equal (B.Format, 'hh:mm');
%!assert_equal (class (mink (days ([3, 1, 2]), 2)), 'duration')
%!assert_equal (size (mink (days ([3, 1, 2]), 0)), [1, 0])
%!assert_equal (size (mink (days ([1, 5; 4, 2; 3, 6]), 0)), [0, 2])
%!assert_equal (size (mink (days ([]), 2)), [0, 0])
%!error<duration.mink: too few input arguments.> mink (days (1))
%!error<duration.mink: K must be a nonnegative integer scalar.> ...
%! mink (days ([1, 2, 3]), 2.5)
%!error<duration.mink: K must be a nonnegative integer scalar.> ...
%! mink (days ([1, 2, 3]), -1)
%!error<duration.mink: K must be a nonnegative integer scalar.> ...
%! mink (days ([1, 2, 3]), [2, 3])
%!error<duration.mink: K must be a nonnegative integer scalar.> ...
%! mink (days ([1, 2, 3]), Inf)
%!error<duration.mink: DIM must be a positive integer scalar.> ...
%! mink (days ([1, 2, 3]), 2, 0)
%!error<duration.mink: DIM must be a positive integer scalar.> ...
%! mink (days ([1, 2, 3]), 2, 1.5)
%!error<duration.mink: 'ComparisonMethod' is not a supported option.> ...
%! mink (days ([1, 2, 3]), 2, 'ComparisonMethod', 'abs')
%!error<duration.mink: 'MissingPlacement' is not a supported option.> ...
%! mink (days ([1, 2, 3]), 2, 'MissingPlacement', 'first')
%!error<duration.mink: too many input arguments.> ...
%! mink (days ([1, 2, 3]), 2, 1, 2)

%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! [B, I] = sort (D);
%! assert_equal (days (B), [1, -4; 1, 1; 2, 2; 2, 3]);
%! assert_equal (I, [1, 3; 2, 4; 3, 1; 4, 2]);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! [B, I] = sort (D, 1);
%! assert_equal (days (B), [1, -4; 1, 1; 2, 2; 2, 3]);
%! assert_equal (I, [1, 3; 2, 4; 3, 1; 4, 2]);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! [B, I] = sort (D, 2);
%! assert_equal (days (B), [1, 2; 1, 3; -4, 2; 1, 2]);
%! assert_equal (I, [1, 2; 1, 2; 2, 1; 2, 1]);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! [B, I] = sort (D, 1, 'ComparisonMethod', 'abs');
%! assert_equal (days (B), [1, 1; 1, 2; 2, 3; 2, -4]);
%! assert_equal (I, [1, 4; 2, 1; 3, 2; 4, 3]);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! [B, I] = sort (D, 2, 'ComparisonMethod', 'abs');
%! assert_equal (days (B), [1, 2; 1, 3; 2, -4; 1, 2]);
%! assert_equal (I, [1, 2; 1, 2; 1, 2; 2, 1]);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! [B, I] = sort (D, 'descend');
%! assert_equal (days (B), [2, 3; 2, 2; 1, 1; 1, -4]);
%! assert_equal (I, [3, 2; 4, 1; 1, 4; 2, 3]);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! [B, I] = sort (D, 1, 'descend');
%! assert_equal (days (B), [2, 3; 2, 2; 1, 1; 1, -4]);
%! assert_equal (I, [3, 2; 4, 1; 1, 4; 2, 3]);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! [B, I] = sort (D, 2, 'descend');
%! assert_equal (days (B), [2, 1; 3, 1; 2, -4; 2, 1]);
%! assert_equal (I, [2, 1; 2, 1; 1, 2; 1, 2]);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! [B, I] = sort (D, 1, 'descend', 'ComparisonMethod', 'abs');
%! assert_equal (days (B), [2, -4; 2, 3; 1, 2; 1, 1]);
%! assert_equal (I, [3, 3; 4, 2; 1, 1; 2, 4]);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! [B, I] = sort (D, 2, 'descend', 'ComparisonMethod', 'abs');
%! assert_equal (days (B), [2, 1; 3, 1; -4, 2; 2, 1]);
%! assert_equal (I, [2, 1; 2, 1; 2, 1; 1, 2]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D);
%! X = [-2, -4, 1; 1, 1, 2; 1, 2, 2; 1, 3, 2; 2, 3, 3; 2, NaN, NaN];
%! assert_equal (days (B), X);
%! assert_equal (I, [5, 3, 2; 1, 4, 1; 2, 1, 3; 6, 2, 6; 3, 6, 5; 4, 5, 4]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 1);
%! X = [-2, -4, 1; 1, 1, 2; 1, 2, 2; 1, 3, 2; 2, 3, 3; 2, NaN, NaN];
%! assert_equal (days (B), X);
%! assert_equal (I, [5, 3, 2; 1, 4, 1; 2, 1, 3; 6, 2, 6; 3, 6, 5; 4, 5, 4]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 2);
%! X = [1, 2, 2; 1, 1, 3; -4, 2, 2; 1, 2, NaN; -2, 3, NaN; 1, 2, 3];
%! assert_equal (days (B), X);
%! assert_equal (I, [1, 2, 3; 1, 3, 2; 2, 1, 3; 2, 1, 3; 1, 3, 2; 1, 3, 2]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 1, 'ComparisonMethod', 'abs');
%! X = [1, 1, 1; 1, 2, 2; 1, 3, 2; 2, 3, 2; 2, -4, 3; -2, NaN, NaN];
%! assert_equal (days (B), X);
%! assert_equal (I, [1, 4, 2; 2, 1, 1; 6, 2, 3; 3, 6, 6; 4, 3, 5; 5, 5, 4]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 2, 'ComparisonMethod', 'abs');
%! X = [1, 2, 2; 1, 1, 3; 2, 2, -4; 1, 2, NaN; -2, 3, NaN; 1, 2, 3];
%! assert_equal (days (B), X);
%! assert_equal (I, [1, 2, 3; 1, 3, 2; 1, 3, 2; 2, 1, 3; 1, 3, 2; 1, 3, 2]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 1, 'MissingPlacement', 'first');
%! X = [-2, NaN, NaN; 1, -4, 1; 1, 1, 2; 1, 2, 2; 2, 3, 2; 2, 3, 3];
%! assert_equal (days (B), X);
%! assert_equal (I, [5, 5, 4; 1, 3, 2; 2, 4, 1; 6, 1, 3; 3, 2, 6; 4, 6, 5]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 2, 'MissingPlacement', 'first');
%! X = [1, 2, 2; 1, 1, 3; -4, 2, 2; NaN, 1, 2; NaN, -2, 3; 1, 2, 3];
%! assert_equal (days (B), X);
%! assert_equal (I, [1, 2, 3; 1, 3, 2; 2, 1, 3; 3, 2, 1; 2, 1, 3; 1, 3, 2]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 1, 'MissingPlacement', 'last');
%! X = [-2, -4, 1; 1, 1, 2; 1, 2, 2; 1, 3, 2; 2, 3, 3; 2, NaN, NaN];
%! assert_equal (days (B), X);
%! assert_equal (I, [5, 3, 2; 1, 4, 1; 2, 1, 3; 6, 2, 6; 3, 6, 5; 4, 5, 4]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 2, 'MissingPlacement', 'last');
%! X = [1, 2, 2; 1, 1, 3; -4, 2, 2; 1, 2, NaN; -2, 3, NaN; 1, 2, 3];
%! assert_equal (days (B), X);
%! assert_equal (I, [1, 2, 3; 1, 3, 2; 2, 1, 3; 2, 1, 3; 1, 3, 2; 1, 3, 2]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 'descend');
%! X = [2, NaN, NaN; 2, 3, 3; 1, 3, 2; 1, 2, 2; 1, 1, 2; -2, -4, 1];
%! assert_equal (days (B), X);
%! assert_equal (I, [3, 5, 4; 4, 2, 5; 1, 6, 1; 2, 1, 3; 6, 4, 6; 5, 3, 2]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 1, 'descend');
%! X = [2, NaN, NaN; 2, 3, 3; 1, 3, 2; 1, 2, 2; 1, 1, 2; -2, -4, 1];
%! assert_equal (days (B), X);
%! assert_equal (I, [3, 5, 4; 4, 2, 5; 1, 6, 1; 2, 1, 3; 6, 4, 6; 5, 3, 2]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 2, 'descend');
%! X = [2, 2, 1; 3, 1, 1; 2, 2, -4; NaN, 2, 1; NaN, 3, -2; 3, 2, 1];
%! assert_equal (days (B), X);
%! assert_equal (I, [2, 3, 1; 2, 1, 3; 1, 3, 2; 3, 1, 2; 2, 3, 1; 2, 3, 1]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 1, 'descend', 'ComparisonMethod', 'abs');
%! X = [2, NaN, NaN; 2, -4, 3; -2, 3, 2; 1, 3, 2; 1, 2, 2; 1, 1, 1];
%! assert_equal (days (B), X);
%! assert_equal (I, [3, 5, 4; 4, 3, 5; 5, 2, 1; 1, 6, 3; 2, 1, 6; 6, 4, 2]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 2, 'descend', 'ComparisonMethod', 'abs');
%! X = [2, 2, 1; 3, 1, 1; -4, 2, 2; NaN, 2, 1; NaN, 3, -2; 3, 2, 1];
%! assert_equal (days (B), X);
%! assert_equal (I, [2, 3, 1; 2, 1, 3; 2, 1, 3; 3, 1, 2; 2, 3, 1; 2, 3, 1]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 1, 'descend', 'MissingPlacement', 'first');
%! X = [2, NaN, NaN; 2, 3, 3; 1, 3, 2; 1, 2, 2; 1, 1, 2; -2, -4, 1];
%! assert_equal (days (B), X);
%! assert_equal (I, [3, 5, 4; 4, 2, 5; 1, 6, 1; 2, 1, 3; 6, 4, 6; 5, 3, 2]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 2, 'descend', 'MissingPlacement', 'first');
%! X = [2, 2, 1; 3, 1, 1; 2, 2, -4; NaN, 2, 1; NaN, 3, -2; 3, 2, 1];
%! assert_equal (days (B), X);
%! assert_equal (I, [2, 3, 1; 2, 1, 3; 1, 3, 2; 3, 1, 2; 2, 3, 1; 2, 3, 1]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 1, 'descend', 'MissingPlacement', 'last');
%! X = [2, 3, 3; 2, 3, 2; 1, 2, 2; 1, 1, 2; 1, -4, 1; -2, NaN, NaN];
%! assert_equal (days (B), X);
%! assert_equal (I, [3, 2, 5; 4, 6, 1; 1, 1, 3; 2, 4, 6; 6, 3, 2; 5, 5, 4]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 2, 'descend', 'MissingPlacement', 'last');
%! X = [2, 2, 1; 3, 1, 1; 2, 2, -4; 2, 1, NaN; 3, -2, NaN; 3, 2, 1];
%! assert_equal (days (B), X);
%! assert_equal (I, [2, 3, 1; 2, 1, 3; 1, 3, 2; 1, 2, 3; 3, 1, 2; 2, 3, 1]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 1, 'MissingPlacement', 'first', 'ComparisonMethod', 'abs');
%! X = [1, NaN, NaN; 1, 1, 1; 1, 2, 2; 2, 3, 2; 2, 3, 2; -2, -4, 3];
%! assert_equal (days (B), X);
%! assert_equal (I, [1, 5, 4; 2, 4, 2; 6, 1, 1; 3, 2, 3; 4, 6, 6; 5, 3, 5]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 2, 'MissingPlacement', 'first', 'ComparisonMethod', 'abs');
%! X = [1, 2, 2; 1, 1, 3; 2, 2, -4; NaN, 1, 2; NaN, -2, 3; 1, 2, 3];
%! assert_equal (days (B), X);
%! assert_equal (I, [1, 2, 3; 1, 3, 2; 1, 3, 2; 3, 2, 1; 2, 1, 3; 1, 3, 2]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 1, 'MissingPlacement', 'last', 'ComparisonMethod', 'abs');
%! X = [1, 1, 1; 1, 2, 2; 1, 3, 2; 2, 3, 2; 2, -4, 3; -2, NaN, NaN];
%! assert_equal (days (B), X);
%! assert_equal (I, [1, 4, 2; 2, 1, 1; 6, 2, 3; 3, 6, 6; 4, 3, 5; 5, 5, 4]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 2, 'MissingPlacement', 'last', 'ComparisonMethod', 'abs');
%! X = [1, 2, 2; 1, 1, 3; 2, 2, -4; 1, 2, NaN; -2, 3, NaN; 1, 2, 3];
%! assert_equal (days (B), X);
%! assert_equal (I, [1, 2, 3; 1, 3, 2; 1, 3, 2; 2, 1, 3; 1, 3, 2; 1, 3, 2]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 1, 'descend', 'MissingPlacement', 'first', 'ComparisonMethod', 'abs');
%! X = [2, NaN, NaN; 2, -4, 3; -2, 3, 2; 1, 3, 2; 1, 2, 2; 1, 1, 1];
%! assert_equal (days (B), X);
%! assert_equal (I, [3, 5, 4; 4, 3, 5; 5, 2, 1; 1, 6, 3; 2, 1, 6; 6, 4, 2]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 2, 'descend', 'MissingPlacement', 'first', 'ComparisonMethod', 'abs');
%! X = [2, 2, 1; 3, 1, 1; -4, 2, 2; NaN, 2, 1; NaN, 3, -2; 3, 2, 1];
%! assert_equal (days (B), X);
%! assert_equal (I, [2, 3, 1; 2, 1, 3; 2, 1, 3; 3, 1, 2; 2, 3, 1; 2, 3, 1]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 1, 'descend', 'MissingPlacement', 'last', 'ComparisonMethod', 'abs');
%! X = [2, -4, 3; 2, 3, 2; -2, 3, 2; 1, 2, 2; 1, 1, 1; 1, NaN, NaN];
%! assert_equal (days (B), X);
%! assert_equal (I, [3, 3, 5; 4, 2, 1; 5, 6, 3; 1, 1, 6; 2, 4, 2; 6, 5, 4]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! [B, I] = sort (D, 2, 'descend', 'MissingPlacement', 'last', 'ComparisonMethod', 'abs');
%! X = [2, 2, 1; 3, 1, 1; -4, 2, 2; 2, 1, NaN; 3, -2, NaN; 3, 2, 1];
%! assert_equal (days (B), X);
%! assert_equal (I, [2, 3, 1; 2, 1, 3; 2, 1, 3; 1, 2, 3; 3, 1, 2; 2, 3, 1]);

%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! D = sortrows (D);
%! assert_equal (days (D), [1, 2; 1, 3; 2, -4; 2, 1]);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! D = sortrows (D, 'ComparisonMethod', 'abs');
%! assert_equal (days (D), [1, 2; 1, 3; 2, 1; 2, -4]);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! D = sortrows (D, 1, 'ComparisonMethod', 'abs');
%! assert_equal (days (D), [1, 2; 1, 3; 2, -4; 2, 1]);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! D = sortrows (D, 2, 'ComparisonMethod', 'abs');
%! assert_equal (days (D), [2, 1; 1, 2; 1, 3; 2, -4]);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! D = sortrows (D, -1, 'ComparisonMethod', 'abs');
%! assert_equal (days (D), [2, -4; 2, 1; 1, 2; 1, 3]);
%!test
%! D = days ([1, 2; 1, 3; 2, -4; 2, 1]);
%! D = sortrows (D, -2, 'ComparisonMethod', 'abs');
%! assert_equal (days (D), [2, -4; 1, 3; 1, 2; 2, 1]);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D);
%! X = [-2, NaN, 3; 1, 2, 2; 1, 3, 1; 1, 3, 2; 2, -4, 2; 2, 1, NaN];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, -2, 'MissingPlacement', 'first');
%! X = [-2, NaN, 3; 1, 3, 1; 1, 3, 2; 1, 2, 2; 2, 1, NaN; 2, -4, 2];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, -2, 'MissingPlacement', 'last');
%! X = [1, 3, 1; 1, 3, 2; 1, 2, 2; 2, 1, NaN; 2, -4, 2; -2, NaN, 3];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, 2, 'MissingPlacement', 'first');
%! X = [-2, NaN, 3; 2, -4, 2; 2, 1, NaN; 1, 2, 2; 1, 3, 1; 1, 3, 2];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, 2, 'MissingPlacement', 'last');
%! X = [2, -4, 2; 2, 1, NaN; 1, 2, 2; 1, 3, 1; 1, 3, 2; -2, NaN, 3];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, 'ComparisonMethod', 'abs', 'MissingPlacement', 'first');
%! X = [1, 2, 2; 1, 3, 1; 1, 3, 2; -2, NaN, 3; 2, 1, NaN; 2, -4, 2];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, 'ComparisonMethod', 'abs', 'MissingPlacement', 'last');
%! X = [1, 2, 2; 1, 3, 1; 1, 3, 2; 2, 1, NaN; 2, -4, 2; -2, NaN, 3];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, -2, 3]);
%! X = [-2, NaN, 3; 1, 3, 1; 1, 3, 2; 1, 2, 2; 2, 1, NaN; 2, -4, 2];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [-1, -2, 3]);
%! X = [2, 1, NaN; 2, -4, 2; 1, 3, 1; 1, 3, 2; 1, 2, 2; -2, NaN, 3];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, -2, -3]);
%! X = [-2, NaN, 3; 1, 3, 2; 1, 3, 1; 1, 2, 2; 2, 1, NaN; 2, -4, 2];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, -2], {'ascend', 'descend'});
%! X = [-2, NaN, 3; 1, 3, 1; 1, 3, 2; 1, 2, 2; 2, 1, NaN; 2, -4, 2];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, -2], {'descend', 'ascend'});
%! X = [2, -4, 2; 2, 1, NaN; 1, 2, 2; 1, 3, 1; 1, 3, 2; -2, NaN, 3];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [-1, -2, 3], {'ascend', 'ascend', 'descend'});
%! X = [-2, NaN, 3; 1, 2, 2; 1, 3, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, -2, -3], string ({'ascend', 'ascend', 'descend'}));
%! X = [-2, NaN, 3; 1, 2, 2; 1, 3, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, string ({'ascend', 'ascend', 'descend'}));
%! X = [-2, NaN, 3; 1, 2, 2; 1, 3, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, string ({'ascend', 'ascend', 'descend'}));
%! X = [-2, NaN, 3; 1, 2, 2; 1, 3, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, 2, -3]);
%! X = [-2, NaN, 3; 1, 2, 2; 1, 3, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, -2, 3], 'MissingPlacement', 'first');
%! X = [-2, NaN, 3; 1, 3, 1; 1, 3, 2; 1, 2, 2; 2, 1, NaN; 2, -4, 2];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [-1, -2, 3], 'MissingPlacement', 'first');
%! X = [2, 1, NaN; 2, -4, 2; 1, 3, 1; 1, 3, 2; 1, 2, 2; -2, NaN, 3];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, -2, -3], 'MissingPlacement', 'first');
%! X = [-2, NaN, 3; 1, 3, 2; 1, 3, 1; 1, 2, 2; 2, 1, NaN; 2, -4, 2];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, -2, 3], 'MissingPlacement', 'last');
%! X = [-2, NaN, 3; 1, 3, 1; 1, 3, 2; 1, 2, 2; 2, 1, NaN; 2, -4, 2];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [-1, -2, 3], 'MissingPlacement', 'last');
%! X = [2, 1, NaN; 2, -4, 2; 1, 3, 1; 1, 3, 2; 1, 2, 2; -2, NaN, 3];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, -2, -3], 'MissingPlacement', 'last');
%! X = [-2, NaN, 3; 1, 3, 2; 1, 3, 1; 1, 2, 2; 2, 1, NaN; 2, -4, 2];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, -2, 3], 'MissingPlacement', 'first', 'ComparisonMethod', 'abs');
%! X = [1, 3, 1; 1, 3, 2; 1, 2, 2; -2, NaN, 3; 2, -4, 2; 2, 1, NaN];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [-1, -2, 3], 'MissingPlacement', 'first', 'ComparisonMethod', 'abs');
%! X = [-2, NaN, 3; 2, -4, 2; 2, 1, NaN; 1, 3, 1; 1, 3, 2; 1, 2, 2];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, -2, -3], 'MissingPlacement', 'first', 'ComparisonMethod', 'abs');
%! X = [1, 3, 2; 1, 3, 1; 1, 2, 2; -2, NaN, 3; 2, -4, 2; 2, 1, NaN];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, -2, 3], 'MissingPlacement', 'last', 'ComparisonMethod', 'abs');
%! X = [1, 3, 1; 1, 3, 2; 1, 2, 2; 2, -4, 2; 2, 1, NaN; -2, NaN, 3];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [-1, -2, 3], 'MissingPlacement', 'last', 'ComparisonMethod', 'abs');
%! X = [2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 1; 1, 3, 2; 1, 2, 2];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, -2, -3], 'MissingPlacement', 'last', 'ComparisonMethod', 'abs');
%! X = [1, 3, 2; 1, 3, 1; 1, 2, 2; 2, -4, 2; 2, 1, NaN; -2, NaN, 3];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, -2], {'ascend', 'descend'}, 'MissingPlacement', 'first');
%! X = [-2, NaN, 3; 1, 3, 1; 1, 3, 2; 1, 2, 2; 2, 1, NaN; 2, -4, 2];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, -2], {'descend', 'ascend'}, 'MissingPlacement', 'last');
%! X = [2, -4, 2; 2, 1, NaN; 1, 2, 2; 1, 3, 1; 1, 3, 2; -2, NaN, 3];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [-1, -2, 3], {'ascend', 'ascend', 'descend'}, ...
%!               'ComparisonMethod', 'abs', 'MissingPlacement', 'first');
%! X = [1, 2, 2; 1, 3, 2; 1, 3, 1; -2, NaN, 3; 2, 1, NaN; 2, -4, 2];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, -2, -3], {'ascend', 'ascend', 'descend'}, ...
%!               'ComparisonMethod', 'abs', 'MissingPlacement', 'first');
%! X = [1, 2, 2; 1, 3, 2; 1, 3, 1; -2, NaN, 3; 2, 1, NaN; 2, -4, 2];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [-1, -2, 3], {'ascend', 'ascend', 'descend'}, ...
%!               'ComparisonMethod', 'abs', 'MissingPlacement', 'last');
%! X = [1, 2, 2; 1, 3, 2; 1, 3, 1; 2, 1, NaN; 2, -4, 2; -2, NaN, 3];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, -2, -3], {'ascend', 'ascend', 'descend'}, ...
%!               'ComparisonMethod', 'abs', 'MissingPlacement', 'last');
%! X = [1, 2, 2; 1, 3, 2; 1, 3, 1; 2, 1, NaN; 2, -4, 2; -2, NaN, 3];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, {'ascend', 'ascend', 'descend'}, 'ComparisonMethod', 'abs');
%! X = [1, 2, 2; 1, 3, 2; 1, 3, 1; 2, 1, NaN; 2, -4, 2; -2, NaN, 3];
%! assert_equal (days (D), X);
%!test
%! D = days ([1, 2, 2; 1, 3, 1; 2, -4, 2; 2, 1, NaN; -2, NaN, 3; 1, 3, 2]);
%! D = sortrows (D, [1, 2, -3], 'ComparisonMethod', 'abs');
%! X = [1, 2, 2; 1, 3, 2; 1, 3, 1; 2, 1, NaN; 2, -4, 2; -2, NaN, 3];
%! assert_equal (days (D), X);
%!error<duration.sortrows: A must be a 2-D matrix.> ...
%! sortrows (days (ones (2, 3, 4)))
%!error<duration.sortrows: invalid value for 'MissingPlacement'.> ...
%! sortrows (days (2), 'MissingPlacement', 2)
%!error<duration.sortrows: invalid value for 'ComparisonMethod'.> ...
%! sortrows (days (2), 'ComparisonMethod', 2)
%!error<duration.sortrows: too many input arguments.> ...
%! sortrows (days (1), 1, 'ascend', 2)
%!error<duration.sortrows: COL must be a vector of nonzero integers indexing columns in A.> ...
%! sortrows (days (1), 1.5)
%!error<duration.sortrows: COL must be a vector of nonzero integers indexing columns in A.> ...
%! sortrows (days (1), ones (2))
%!error<duration.sortrows: COL indexes non-existing column.> ...
%! sortrows (days (1), 2)
%!error<duration.sortrows: DIRECTION input must contain either 'ascend' or 'descend' values.> ...
%! sortrows (days (1), {'a'})
%!error<duration.sortrows: DIRECTION does not match the elements in COL.> ...
%! sortrows (days (1), 1, {'ascend', 'descend'})
%!error<duration.sortrows: invalid type for COL argument.> ...
%! sortrows (days (1), {1})
%!error<duration.sortrows: invalid third input argument.> ...
%! sortrows (days (1), {'ascend'}, 'ascend')
%!error<duration.sortrows: invalid third input argument.> ...
%! sortrows (days (1), {'ascend'}, 1)
%!error<duration.sortrows: invalid type for DIRECTION argument.> ...
%! sortrows (days (1), 1, 1)
%!error<duration.sortrows: DIRECTION input must contain either 'ascend' or 'descend' values.> ...
%! sortrows (days (1), 1, {'a'})
%!error<duration.sortrows: DIRECTION does not match the elements in COL.> ...
%! sortrows (days (1), 1, {'ascend', 'descend'})

%!test
%! D = hours ([3, 1; 1, 2; 3, 0; NaN, 5; 1, 1]);
%! [B, I] = topkrows (D, 3);
%! assert_equal (hours (B), [3, 1; 3, 0; 1, 2]);
%! assert_equal (I, [1; 3; 2]);
%!test
%! D = hours ([3, 1; 1, 2; 3, 0; NaN, 5; 1, 1]);
%! [B, I] = topkrows (D, 5);
%! assert_equal (hours (B), [3, 1; 3, 0; 1, 2; 1, 1; NaN, 5]);
%! assert_equal (I, [1; 3; 2; 5; 4]);
%!test
%! D = hours ([3, 1; 1, 2; 3, 0; NaN, 5; 1, 1]);
%! [B, I] = topkrows (D, 5, 'ascend');
%! assert_equal (hours (B), [1, 1; 1, 2; 3, 0; 3, 1; NaN, 5]);
%! assert_equal (hours (topkrows (D, 5, 'descend')), hours (topkrows (D, 5)));
%!test
%! D = hours ([3, 1; 1, 2; 3, 0; NaN, 5; 1, 1]);
%! [B, I] = topkrows (D, 5, 1, 'ascend');
%! assert_equal (I, [2; 5; 1; 3; 4]);
%!test
%! D = hours ([3, 1; 1, 2; 3, 0; NaN, 5; 1, 1]);
%! [B, I] = topkrows (D, 3, [2, 1]);
%! assert_equal (hours (B), [NaN, 5; 1, 2; 3, 1]);
%!test
%! D = hours ([3, 1; 1, 2; 3, 0; NaN, 5; 1, 1]);
%! assert_equal (hours (topkrows (D, 3, [1, 2], {'ascend', 'descend'})), ...
%!               [1, 2; 1, 1; 3, 1]);
%! assert_equal (hours (topkrows (D, 3, [1, 2], {'descend', 'ascend'})), ...
%!               [3, 0; 3, 1; 1, 1]);
%!test  # a missing element demotes a row only in the column that decides it
%! E = hours ([3, 1; 1, NaN; 3, 0; 2, 5; 1, 1]);
%! [B, I] = topkrows (E, 5, 2);
%! assert_equal (I, [4; 1; 5; 3; 2]);
%! assert_equal (hours (topkrows (E, 5, 2, 'ascend')), ...
%!               [3, 0; 3, 1; 1, 1; 2, 5; 1, NaN]);
%! [B, I] = topkrows (E, 5, [1, 2]);
%! assert_equal (I, [1; 3; 4; 5; 2]);
%!test  # 'MissingPlacement' is an Octave extension; the default is 'last'
%! D = hours ([3, 1; 1, 2; 3, 0; NaN, 5; 1, 1]);
%! [~, I] = topkrows (D, 5, 'MissingPlacement', 'last');
%! assert_equal (I, [1; 3; 2; 5; 4]);
%! [~, I] = topkrows (D, 5, 'MissingPlacement', 'first');
%! assert_equal (I, [4; 1; 3; 2; 5]);
%!test
%! D = hours ([3, 1; 1, 2; 3, 0; NaN, 5; 1, 1]);
%! assert_equal (hours (topkrows (D, 10)), hours (topkrows (D, 5)));
%! assert_equal (size (topkrows (D, 0)), [0, 2]);
%! assert_equal (size (topkrows (hours ([]), 2)), [0, 0]);
%! assert_equal (size (topkrows (hours ([3, 1, 2]), 1)), [1, 3]);
%!test
%! [B, I] = topkrows (hours ([3; 1; NaN; 2]), 2);
%! assert_equal (hours (B), [3; 2]);
%! assert_equal (I, [1; 4]);
%!error<duration.topkrows: too few input arguments.> topkrows (days (1))
%!error<duration.topkrows: A must be a 2-D array.> ...
%! topkrows (days (reshape (1:8, 2, 2, 2)), 1)
%!error<duration.topkrows: K must be a nonnegative integer scalar.> ...
%! topkrows (days ([1, 2; 3, 4]), 2.5)
%!error<duration.topkrows: K must be a nonnegative integer scalar.> ...
%! topkrows (days ([1, 2; 3, 4]), -1)
%!error<duration.topkrows: COL must contain positive integers indexing existing columns in A.> ...
%! topkrows (days ([1, 2; 3, 4]), 1, -1)
%!error<duration.topkrows: COL must contain positive integers indexing existing columns in A.> ...
%! topkrows (days ([1, 2; 3, 4]), 1, 5)
%!error<duration.topkrows: DIRECTION must be 'ascend' or 'descend'.> ...
%! topkrows (days ([1, 2; 3, 4]), 1, 1, 'bogus')
%!error<duration.topkrows: invalid value for 'MissingPlacement'.> ...
%! topkrows (days ([1, 2; 3, 4]), 1, 'MissingPlacement', 'bogus')
%!error<duration.topkrows: 'MissingPlacement' requires a value.> ...
%! topkrows (days ([1, 2; 3, 4]), 1, 'MissingPlacement')

%!assert_equal (unique (days ([1, 2, 2, 3, 4, 4])), days ([1:4]))
%!assert_equal (unique (days ([1, 2, 2, 3, 4, 4]')), days ([1:4]'))
%!test
%! D = days ([1, 2, 2, 3, 4, 4]);
%! [c, i, j] = unique (D);
%! assert_equal (c, D(i));
%! assert_equal (c(j), D);
%!assert_equal (unique (days ([1, 4, 2, 2, 3]), 'sorted'), days (1:4))
%!test
%! D = days ([1, 4, 2, 2, 3]);
%! [c, i, j] = unique (D, 'sorted');
%! assert_equal (c, days (1:4));
%! assert_equal (c, D(i));
%! assert_equal (c(j), D);
%!test
%! D = days ([1, 4, 2, 2, 3]);
%! [c, i, j] = unique (D, 'stable');
%! assert_equal (c, days ([1, 4, 2, 3]));
%! assert_equal (c, D(i));
%! assert_equal (c(j), D);
%!test
%! D = days ([1, 4, 2, 2, 3]);
%! [c, i, j] = unique (D, 'sorted', 'last');
%! assert_equal (i, [1; 4; 5; 2]);
%! assert_equal (c, D(i));
%! assert_equal (c(j), D);
%!test
%! D = days ([1, 4, 2, 2, 3]);
%! [c, i, j] = unique (D, 'stable', 'last');
%! assert_equal (i, [1; 2; 4; 5]);
%! assert_equal (c, D(i));
%! assert_equal (c(j), D);
%!test
%! D = days ([3, 1, 3; 3, 3, 1; 1, 3, 3; 3, 2, 3; 2, 3, 3; ...
%!            1, 1, 3; 1, 2, 3; 2, 3, 2; 3, 3, 2; 3, 3, 1]);
%! [c, i, j] = unique (D(:,[1:2]), 'rows');
%! assert_equal (c, days ([1, 1; 1, 2; 1, 3; 2, 3; 3, 1; 3, 2; 3, 3]));
%! assert_equal (i, [6; 7; 3; 5; 1; 4; 2]);
%! assert_equal (j, [5; 7; 3; 6; 4; 1; 2; 4; 7; 7]);
%! assert_equal (D(i,[1:2]), days ([1, 1; 1, 2; 1, 3; 2, 3; 3, 1; 3, 2; 3, 3]));
%!test
%! [B, ia, ib] = unique (days ([1, 2; 2, 3; 1, 2]), 'rows', 'sorted', 'first');
%! assert_equal (B, days ([1, 2; 2, 3]));
%! assert_equal (ia, [1; 2]);
%! assert_equal (ib, [1; 2; 1]);
%!test
%! [B, ia, ib] = unique (days ([1, 2; 2, 3; 1, 2]), 'rows', 'sorted', 'last');
%! assert_equal (B, days ([1, 2; 2, 3]));
%! assert_equal (ia, [3; 2]);
%! assert_equal (ib, [1; 2; 1]);
%!test
%! [B, ia, ib] = unique (days ([1, 2; 2, 3; 1, 2]), 'rows', 'stable', 'first');
%! assert_equal (B, days ([1, 2; 2, 3]));
%! assert_equal (ia, [1; 2]);
%! assert_equal (ib, [1; 2; 1]);
%!test
%! [B, ia, ib] = unique (days ([1, 2; 2, 3; 1, 2]), 'rows', 'stable', 'last');
%! assert_equal (B, days ([2, 3; 1, 2]));
%! assert_equal (ia, [2; 3]);
%! assert_equal (ib, [2; 1; 2]);
%!error<duration.unique: 'legacy' option is not supported.> ...
%! unique (days ([1:3]), 'legacy')

%!assert_equal (interp1 (days ([1:5]), 1:5), days (1:5))
%!assert_equal (interp1 (days ([1:5]), 1:6, 'linear', days(1)), days ([1:5,1]))
%!assert_equal (interp1 (1:5, days ([1:5])), [1:5])
%!assert_equal (interp1 (1:5, days ([1:6]), 'linear', 1), [1:5,1])
%!assert_equal (interp1 (days ([1:5]), 1:5, days ([1.5, 2.5, 3.5, 4.5])), ...
%!              [1.5, 2.5, 3.5, 4.5])
%!assert_equal (interp1 (1:5, days ([1:5]), [1.5, 2.5, 3.5, 4.5]), ...
%!              days ([1.5, 2.5, 3.5, 4.5]))
%!assert_equal (interp1 (days ([1:5]), days ([1:5]), days ([1.5, 2.5, 3.5, 4.5])), ...
%!              days ([1.5, 2.5, 3.5, 4.5]))
%!assert_equal (isequaln (interp1 (1:5, days ([1:5]), [-1.5, 2.5, 3.5, 6.5]), ...
%!        days ([NaN, 2.5, 3.5, NaN])), true)
%!assert_equal (class (interp1 (1:5, days ([1:5]), 'pp')), 'struct')
%!assert_equal (isequaln (interp1 (1:5, days ([1:5]), [-1.5, 2.5, 3.5, 6.5], 'linear'), ...
%!                  days ([NaN, 2.5, 3.5, NaN])), true)
%!assert_equal (interp1 (1:5, days ([1:5]), [-1.5, 2.5, 3.5, 6.5], 'linear', days (2)), ...
%!              days ([2, 2.5, 3.5, 2]))
%!assert_equal (interp1 (1:5, days ([1:5]), [-1.5, 2.5, 3.5, 6.5], 'linear', 'extrap'), ...
%!              days ([-1.5, 2.5, 3.5, 6.5]))
%!test
%! YI = interp1 ([1:5], hours (1:5), [1.5, 2.5, 3.5, 4.5]);
%! assert_equal (round (YI), round (hours ([1.5, 2.5, 3.5, 4.5])));
%! assert_equal (YI.Format, 'h');
%!test
%! YI = interp1 (days ([1:5]), hours (1:5), days ([1.5, 2.5, 3.5, 4.5]));
%! assert_equal (round (YI), round (hours ([1.5, 2.5, 3.5, 4.5])));
%! assert_equal (YI.Format, 'h');
%!test
%! YI = interp1 (hours ([1:5]), days (1:5), hours ([1.5, 2.5, 3.5, 4.5]));
%! assert_equal (round (YI), round (days ([1.5, 2.5, 3.5, 4.5])));
%! assert_equal (YI.Format, 'd');
%!error<duration.interp1: EXTRAPOLATION scalar value must match Y.> ...
%! interp1 (1:5, days ([1:5]), 'linear', days (2))
%!error<duration.interp1: EXTRAPOLATION scalar value must match Y.> ...
%! interp1 (days ([1:5]), 1:5, 'linear', 2)
%!error<duration.interp1: if X is a duration array, XI must be also.> ...
%! interp1 (days ([1:5]), 1:5, [-1.5, 2.5, 3.5, 6.5])
%!error<duration.interp1: if X is a duration array, XI must be also.> ...
%! interp1 (1:5, days ([1:5]), days ([-1.5, 2.5, 3.5, 6.5]))
%!error<duration.interp1: EXTRAPOLATION scalar value must match Y.> ...
%! interp1 (1:5, days ([1:5]), [-1.5, 2.5, 3.5, 6.5], 'linear', 2)
%!error<duration.interp1: EXTRAPOLATION scalar value must match Y.> ...
%! interp1 (days ([1:5]), 1:5, days ([-1.5, 2.5, 3.5, 6.5]), 'linear', days (2))
%!error<duration.interp1: Y must be a duration or numeric array.> ...
%! interp1 (days ([1:5]), "asd", days ([1.5, 2.5, 3.5, 4.5]))
%!error<duration.interp1: Y must be a duration or numeric array.> ...
%! interp1 (days ([1:5]), {1:5}, days ([1.5, 2.5, 3.5, 4.5]))

%!test
%! A = days ([7 1 7 7 4]);
%! B = days ([7 0 4 4 0]);
%! [C, ixA, ixB] = intersect (A, B);
%! assert_equal (C, days ([4, 7]));
%! assert_equal (ixA, [5; 1]);
%! assert_equal (ixB, [3; 1]);
%!test
%! A = days ([7 1 7 7 4]);
%! B = days ([7 0 4 4 0]);
%! [C, ixA, ixB] = intersect (A, B, 'sorted');
%! assert_equal (C, days ([4, 7]));
%! assert_equal (ixA, [5; 1]);
%! assert_equal (ixB, [3; 1]);
%!test
%! A = days ([7 1 7 7 4]);
%! B = days ([7 0 4 4 0]);
%! [C, ixA, ixB] = intersect (A, B, 'stable');
%! assert_equal (C, days ([7, 4]));
%! assert_equal (ixA, [1; 5]);
%! assert_equal (ixB, [1; 3]);
%!test
%! A = days ([2, 2, 2; 0, 0, 1; 1, 2, 3; 1, 1, 1]);
%! B = days ([1, 2, 3; 2, 2, 2; 2, 2, 0]);
%! [C, ixA, ixB] = intersect (A, B, 'rows');
%! assert_equal (C, days ([1, 2, 3; 2, 2, 2]));
%! assert_equal (ixA, [3; 1]);
%! assert_equal (ixB, [1; 2]);
%!test
%! A = days ([2, 2, 2; 0, 0, 1; 1, 2, 3; 1, 1, 1]);
%! B = days ([1, 2, 3; 2, 2, 2; 2, 2, 0]);
%! [C, ixA, ixB] = intersect (A, B, 'sorted', 'rows');
%! assert_equal (C, days ([1, 2, 3; 2, 2, 2]));
%! assert_equal (ixA, [3; 1]);
%! assert_equal (ixB, [1; 2]);
%!test
%! A = days ([2, 2, 2; 0, 0, 1; 1, 2, 3; 1, 1, 1]);
%! B = days ([1, 2, 3; 2, 2, 2; 2, 2, 0]);
%! [C, ixA, ixB] = intersect (A, B, 'stable', 'rows');
%! assert_equal (C, days ([2, 2, 2; 1, 2, 3]));
%! assert_equal (ixA, [1; 3]);
%! assert_equal (ixB, [2; 1]);
%!assert_equal (intersect (days ([5, NaN, NaN]), days ([5, NaN, NaN])), days (5))
%!assert_equal (intersect (days ([1, 2]), '48:00:00'), days (2))
%!assert_equal (intersect (days ([1, 2]), {'48:00:00'}), days (2))
%!assert_equal (intersect (days ([1, 2]), string ({'48:00:00'})), days (2))
%!assert_equal (intersect (days ([1, 2]), 2), days (2))
%!assert_equal (intersect ('48:00:00', days ([1, 2])), days (2))
%!assert_equal (intersect ({'48:00:00'}, days ([1, 2])), days (2))
%!assert_equal (intersect (string ({'48:00:00'}), days ([1, 2])), days (2))
%!assert_equal (intersect (2, days ([1, 2])), days (2))
%!assert_equal (intersect (days ([2, 3]), 1:3), days ([2, 3]))
%!error<duration.intersect: 'legacy' option is not supported.> ...
%! intersect (days ([1, 2]), days (2), 'legacy')
%!error<duration.intersect: set operation not defined between 'cell' and 'duration' arrays.> ...
%! intersect ({1}, days ([1, 2]))
%!error<duration.intersect: set operation not defined between 'duration' and 'calendarDuration' arrays.> ...
%! intersect (days ([1, 2]), caldays)
%!error<duration.intersect: set operation not defined between 'duration' and 'datetime' arrays.> ...
%! intersect (days ([1, 2]), datetime)

%!test
%! A = days ([3, 6, 2, 1, 5, 1, 1]);
%! B = days ([2, 4, 6]);
%! [C, index] = setdiff (A, B);
%! assert_equal (C, days ([1, 3, 5]));
%! assert_equal (index, [4; 1; 5]);
%!test
%! A = days ([3, 6, 2, 1, 5, 1, 1]);
%! B = days ([2, 4, 6]);
%! [C, index] = setdiff (A, B, 'sorted');
%! assert_equal (C, days ([1, 3, 5]));
%! assert_equal (index, [4; 1; 5]);
%!test
%! A = days ([3, 6, 2, 1, 5, 1, 1]);
%! B = days ([2, 4, 6]);
%! [C, index] = setdiff (A, B, 'stable');
%! assert_equal (C, days ([3, 1, 5]));
%! assert_equal (index, [1; 4; 5]);
%!test
%! A = days ([7, 9, 7; 0, 0, 0; 7, 9, 7; 5, 5, 5; 1, 4, 5]);
%! B = days ([0, 0, 0; 5, 5, 5]);
%! [C, index] = setdiff (A, B, 'rows');
%! assert_equal (C, days ([1, 4, 5; 7, 9, 7]));
%! assert_equal (index, [5; 1]);
%!test
%! A = days ([7, 9, 7; 0, 0, 0; 7, 9, 7; 5, 5, 5; 1, 4, 5]);
%! B = days ([0, 0, 0; 5, 5, 5]);
%! [C, index] = setdiff (A, B, 'sorted', 'rows');
%! assert_equal (C, days ([1, 4, 5; 7, 9, 7]));
%! assert_equal (index, [5; 1]);
%!test
%! A = days ([7, 9, 7; 0, 0, 0; 7, 9, 7; 5, 5, 5; 1, 4, 5]);
%! B = days ([0, 0, 0; 5, 5, 5]);
%! [C, index] = setdiff (A, B, 'stable', 'rows');
%! assert_equal (C, days ([7, 9, 7; 1, 4, 5]));
%! assert_equal (index, [1; 5]);
%!test
%! C = setdiff (days ([5, NaN, NaN]), days ([5, NaN, NaN]));
%! assert_equal (isequaln (C, days ([NaN, NaN])), true);
%!assert_equal (setdiff (days ([1, 2]), days (2)), days (1))
%!assert_equal (setdiff (days ([1, 2]), '48:00:00'), days (1))
%!assert_equal (setdiff (days ([1, 2]), string ({'48:00:00'})), days (1))
%!assert_equal (size (setdiff (days ([1, 2]), string ({'48:00:00', '24:00:00'}))), [1, 0])
%!assert_equal (class (setdiff (days ([1, 2]), string ({'48:00:00', '24:00:00'}))), 'duration')
%!assert_equal (setdiff (days ([1, 2, 3]), string ({'48:00:00', '24:00:00'})), days (3))
%!assert_equal (setdiff (string ({'24:00:00', '48:00:00'}), days (2)), days (1))
%!assert_equal (size (setdiff (string ({'24:00:00'}), days ([1, 2]))), [1, 0])
%!assert_equal (class (setdiff (string ({'24:00:00'}), days ([1, 2]))), 'duration')
%!assert_equal (size (setdiff ('24:00:00', days ([1, 2]))), [1, 0])
%!assert_equal (class (setdiff ('24:00:00', days ([1, 2]))), 'duration')
%!assert_equal (setdiff ([1, 2, 3], days (2)), days ([1, 3]))
%!assert_equal (size (setdiff (days ([2, 3]), 1:3)), [1, 0])
%!error<duration.setdiff: 'legacy' option is not supported.> ...
%! setdiff (days ([1, 2]), days (2), 'legacy')
%!error<duration.setdiff: set operation not defined between 'cell' and 'duration' arrays.> ...
%! setdiff ({1}, days ([1, 2]))
%!error<duration.setdiff: set operation not defined between 'duration' and 'calendarDuration' arrays.> ...
%! setdiff (days ([1, 2]), caldays)
%!error<duration.setdiff: set operation not defined between 'duration' and 'datetime' arrays.> ...
%! setdiff (days ([1, 2]), datetime)

%!test
%! A = days ([5, 1, 3, 3, 3]);
%! B = days ([4, 1, 2]);
%! [C, ixA, ixB] = setxor (A, B);
%! assert_equal (C, days ([2, 3, 4, 5]));
%! assert_equal (ixA, [3; 1]);
%! assert_equal (ixB, [3; 1]);
%!test
%! A = days ([5, 1, 3, 3, 3]);
%! B = days ([4, 1, 2]);
%! [C, ixA, ixB] = setxor (A, B, 'sorted');
%! assert_equal (C, days ([2, 3, 4, 5]));
%! assert_equal (ixA, [3; 1]);
%! assert_equal (ixB, [3; 1]);
%!test
%! A = days ([5, 1, 3, 3, 3]);
%! B = days ([4, 1, 2]);
%! [C, ixA, ixB] = setxor (A, B, 'stable');
%! assert_equal (C, days ([5, 3, 4, 2]));
%! assert_equal (ixA, [1; 3]);
%! assert_equal (ixB, [1; 3]);
%!test
%! A = days ([7, 8, 9; 7, 7, 1; 7, 7, 1; 1, 2, 3; 4, 5, 6]);
%! B = days ([1, 2, 3; 4, 5, 6; 7, 7, 2]);
%! [C, ixA, ixB] = setxor (A, B, 'rows');
%! assert_equal (C, days ([7, 7, 1; 7, 7, 2; 7, 8, 9]));
%! assert_equal (ixA, [2; 1]);
%! assert_equal (ixB, [3]);
%!test
%! A = days ([7, 8, 9; 7, 7, 1; 7, 7, 1; 1, 2, 3; 4, 5, 6]);
%! B = days ([1, 2, 3; 4, 5, 6; 7, 7, 2]);
%! [C, ixA, ixB] = setxor (A, B, 'sorted', 'rows');
%! assert_equal (C, days ([7, 7, 1; 7, 7, 2; 7, 8, 9]));
%! assert_equal (ixA, [2; 1]);
%! assert_equal (ixB, [3]);
%!test
%! A = days ([7, 8, 9; 7, 7, 1; 7, 7, 1; 1, 2, 3; 4, 5, 6]);
%! B = days ([1, 2, 3; 4, 5, 6; 7, 7, 2]);
%! [C, ixA, ixB] = setxor (A, B, 'stable', 'rows');
%! assert_equal (C, days ([7, 8 ,9; 7, 7, 1; 7, 7, 2]));
%! assert_equal (ixA, [1; 2]);
%! assert_equal (ixB, [3]);
%!test
%! C = setxor (days ([5, NaN, NaN]), days ([5, NaN, NaN]));
%! assert_equal (isequaln (C, days ([NaN, NaN, NaN, NaN])), true);
%!assert_equal (setxor (days ([1, 2]), days (2)), days (1))
%!assert_equal (setxor (days ([1, 2]), '48:00:00'), days (1))
%!assert_equal (setxor (days ([1, 2]), string ('48:00:00')), days (1))
%!assert_equal (setxor (days ([1, 2]), string ('24:00:00')), days (2))
%!assert_equal (size (setxor (days ([1, 2]), string ({'48:00:00', '24:00:00'}))), [1, 0])
%!assert_equal (class (setxor (days ([1, 2]), string ({'48:00:00', '24:00:00'}))), 'duration')
%!assert_equal (setxor (days ([1, 2, 3]), string ({'48:00:00', '24:00:00'})), days (3))
%!assert_equal (setxor (days ([1, 2, 3]), {'48:00:00', '24:00:00'}), days (3))
%!assert_equal (setxor ({'24:00:00', '48:00:00'}, days (2)), days (1))
%!assert_equal (setxor (string ({'24:00:00', '48:00:00'}), days (2)), days (1))
%!assert_equal (setxor (string ('24:00:00'), days ([1, 2])), days (2))
%!assert_equal (setxor ('24:00:00', days ([1, 2])), days (2))
%!assert_equal (setxor ([1, 2, 3], days (2)), days ([1, 3]))
%!assert_equal (setxor (days ([2, 3]), 1:3), days (1))
%!error<duration.setxor: 'legacy' option is not supported.> ...
%! setxor (days ([1, 2]), days (2), 'legacy')
%!error<duration.setxor: set operation not defined between 'cell' and 'duration' arrays.> ...
%! setxor ({1}, days ([1, 2]))
%!error<duration.setxor: set operation not defined between 'duration' and 'calendarDuration' arrays.> ...
%! setxor (days ([1, 2]), caldays)
%!error<duration.setxor: set operation not defined between 'duration' and 'datetime' arrays.> ...
%! setxor (days ([1, 2]), datetime)

%!test
%! A = days ([5, 7, 1]);
%! B = days ([3, 1, 1]);
%! [C, ixA, ixB] = union (A, B);
%! assert_equal (C, days ([1, 3, 5, 7]));
%! assert_equal (ixA, [3; 1; 2]);
%! assert_equal (ixB, 1);
%!test
%! A = days ([5, 7, 1]);
%! B = days ([3, 1, 1]);
%! [C, ixA, ixB] = union (A, B, 'sorted');
%! assert_equal (C, days ([1, 3, 5, 7]));
%! assert_equal (ixA, [3; 1; 2]);
%! assert_equal (ixB, 1);
%!test
%! A = days ([5, 7, 1]);
%! B = days ([3, 1, 1]);
%! [C, ixA, ixB] = union (A, B, 'stable');
%! assert_equal (C, days ([5, 7, 1, 3]));
%! assert_equal (ixA, [1; 2; 3]);
%! assert_equal (ixB, 1);
%!test
%! A = days ([2, 2, 2; 0, 0, 1]);
%! B = days ([1, 2, 3; 2, 2, 2; 2, 2, 2]);
%! [C, ixA, ixB] = union (A, B, 'rows');
%! assert_equal (C, days ([0, 0, 1; 1, 2, 3; 2, 2, 2]));
%! assert_equal (ixA, [2; 1]);
%! assert_equal (ixB, 1);
%!test
%! A = days ([2, 2, 2; 0, 0, 1]);
%! B = days ([1, 2, 3; 2, 2, 2; 2, 2, 2]);
%! [C, ixA, ixB] = union (A, B, 'sorted', 'rows');
%! assert_equal (C, days ([0, 0, 1; 1, 2, 3; 2, 2, 2]));
%! assert_equal (ixA, [2; 1]);
%! assert_equal (ixB, 1);
%!test
%! A = days ([2, 2, 2; 0, 0, 1]);
%! B = days ([1, 2, 3; 2, 2, 2; 2, 2, 2]);
%! [C, ixA, ixB] = union (A, B, 'stable', 'rows');
%! assert_equal (C, days ([2, 2, 2; 0, 0, 1; 1, 2, 3]));
%! assert_equal (ixA, [1; 2]);
%! assert_equal (ixB, 1);
%!test
%! C = union (days ([5, NaN, 1]), days ([4, NaN, NaN]));
%! assert_equal (isequaln (C, days ([1, 4, 5, NaN, NaN, NaN])), true);
%!assert_equal (union (days ([1, 3]), days (2)), days ([1, 2, 3]))
%!assert_equal (union (days ([1, 3]), '48:00:00'), days ([1, 2, 3]))
%!assert_equal (union (days ([1, 4]), string ('48:00:00')), days ([1, 2, 4]))
%!assert_equal (union (days ([1, 4]), {'48:00:00'}), days ([1, 2, 4]))
%!assert_equal (union (days ([1, 1]), string ({'48:00:00', '24:00:00'})), days ([1, 2]))
%!assert_equal (union (days ([1, 1]), {'48:00:00', '24:00:00'}), days ([1, 2]))
%!assert_equal (union (days ([1, 3]), string ({'48:00:00', '24:00:00'})), days ([1, 2, 3]))
%!assert_equal (union (string ({'24:00:00', '48:00:00'}), days (2)), days ([1, 2]))
%!assert_equal (union (string ({'24:00:00'}), days ([1, 4])), days ([1, 4]))
%!assert_equal (union ('24:00:00', days ([0, 2])), days ([0, 1, 2]))
%!assert_equal (union ([1, 2, 3], days (2)), days ([1, 2, 3]))
%!assert_equal (union (days ([2, 3]), 1:3), days ([1, 2, 3]))
%!error<duration.union: 'legacy' option is not supported.> ...
%! union (days ([1, 2]), days (2), 'legacy')
%!error<duration.union: set operation not defined between 'cell' and 'duration' arrays.> ...
%! union ({1}, days ([1, 2]))
%!error<duration.union: set operation not defined between 'duration' and 'calendarDuration' arrays.> ...
%! union (days ([1, 2]), caldays)
%!error<duration.union: set operation not defined between 'duration' and 'datetime' arrays.> ...
%! union (days ([1, 2]), datetime)

################################################################################
##                           ** Array Operations **                           ##
################################################################################
##                             Available Methods                              ##
##                                                                            ##
## 'cat'              'horzcat'          'vertcat'          'repmat'          ##
## 'repelem'          'repelems'         'reshape'          'circshift'       ##
## 'permute'          'ipermute'         'transpose'        'ctranspose'      ##
##                                                                            ##
################################################################################

%!test
%! D = cat (2, days (2), hours (3));
%! assert_equal (D, days ([2, 0.125]));
%! assert_equal (D.Format, 'd');
%!test
%! D = cat (2, hours (3), days (3));
%! assert_equal (D, hours ([3, 72]));
%! assert_equal (D.Format, 'h');
%!test
%! D = cat (2, '24:00:00', hours (3), days (3));
%! assert_equal (D, hours ([24, 3, 72]));
%! assert_equal (D.Format, 'h');
%!test
%! D = cat (2, string ('24:00:00'), hours (3), days (3));
%! assert_equal (D, hours ([24, 3, 72]));
%! assert_equal (D.Format, 'h');
%!test
%! D = cat (2, string ('24:00:00:00'), hours (3), days (3));
%! assert_equal (D, hours ([576, 3, 72]));
%! assert_equal (D.Format, 'h');
%!test
%! D = cat (2, seconds (3), string ('24:00:00:00'), hours (3), days (3));
%! assert_equal (D, seconds ([3, 2.0736e+06, 10800, 2.592e+05]));
%! assert_equal (D.Format, 's');
%!test
%! D = cat (2, string ('24:00:00'), duration (3, 0, 0), days (3));
%! assert_equal (D, hours ([24, 3, 72]));
%! assert_equal (D.Format, 'hh:mm:ss');
%!test
%! D = cat (1, days (2), hours (3));
%! assert_equal (D, days ([2; 0.125]));
%! assert_equal (D.Format, 'd');
%!test
%! D = cat (1, hours (3), days (3));
%! assert_equal (D, hours ([3; 72]));
%! assert_equal (D.Format, 'h');
%!test
%! D = cat (1, '24:00:00', hours (3), days (3));
%! assert_equal (D, hours ([24; 3; 72]));
%! assert_equal (D.Format, 'h');
%!test
%! D = cat (1, string ('24:00:00'), hours (3), days (3));
%! assert_equal (D, hours ([24; 3; 72]));
%! assert_equal (D.Format, 'h');
%!test
%! D = cat (1, string ('24:00:00:00'), hours (3), days (3));
%! assert_equal (D, hours ([576; 3; 72]));
%! assert_equal (D.Format, 'h');
%!test
%! D = cat (1, seconds (3), string ('24:00:00:00'), hours (3), days (3));
%! assert_equal (D, seconds ([3; 2.0736e+06; 10800; 2.592e+05]));
%! assert_equal (D.Format, 's');
%!test
%! D = cat (1, string ('24:00:00'), duration (3, 0, 0), days (3));
%! assert_equal (D, hours ([24; 3; 72]));
%! assert_equal (D.Format, 'hh:mm:ss');

%!test
%! D = [days(2), hours(3)];
%! assert_equal (D, days ([2, 0.125]));
%! assert_equal (D.Format, 'd');
%!test
%! D = [hours(3), days(3)];
%! assert_equal (D, hours ([3, 72]));
%! assert_equal (D.Format, 'h');
%!test
%! D = ['24:00:00', hours(3), days(3)];
%! assert_equal (D, hours ([24, 3, 72]));
%! assert_equal (D.Format, 'h');
%!test
%! D = [string('24:00:00'), hours(3), days(3)];
%! assert_equal (D, hours ([24, 3, 72]));
%! assert_equal (D.Format, 'h');
%!test
%! D = [string('24:00:00:00'), hours(3), days(3)];
%! assert_equal (D, hours ([576, 3, 72]));
%! assert_equal (D.Format, 'h');
%!test
%! D = [seconds(3), string('24:00:00:00'), hours(3), days(3)];
%! assert_equal (D, seconds ([3, 2.0736e+06, 10800, 2.592e+05]));
%! assert_equal (D.Format, 's');
%!test
%! D = [string('24:00:00'), duration(3, 0, 0), days(3)];
%! assert_equal (D, hours ([24, 3, 72]));
%! assert_equal (D.Format, 'hh:mm:ss');

%!test
%! D = [days(2); hours(3)];
%! assert_equal (D, days ([2; 0.125]));
%! assert_equal (D.Format, 'd');
%!test
%! D = [hours(3); days(3)];
%! assert_equal (D, hours ([3; 72]));
%! assert_equal (D.Format, 'h');
%!test
%! D = ['24:00:00'; hours(3); days(3)];
%! assert_equal (D, hours ([24; 3; 72]));
%! assert_equal (D.Format, 'h');
%!test
%! D = [string('24:00:00'); hours(3); days(3)];
%! assert_equal (D, hours ([24; 3; 72]));
%! assert_equal (D.Format, 'h');
%!test
%! D = [string('24:00:00:00'); hours(3); days(3)];
%! assert_equal (D, hours ([576; 3; 72]));
%! assert_equal (D.Format, 'h');
%!test
%! D = [seconds(3); string('24:00:00:00'); hours(3); days(3)];
%! assert_equal (D, seconds ([3; 2.0736e+06; 10800; 2.592e+05]));
%! assert_equal (D.Format, 's');
%!test
%! D = [string('24:00:00'); duration(3, 0, 0); days(3)];
%! assert_equal (D, hours ([24; 3; 72]));
%! assert_equal (D.Format, 'hh:mm:ss');

%!assert_equal (repmat (days ([1, 2]), 4), days (repmat ([1, 2], 4)))
%!assert_equal (repmat (days ([1, 2]), 2, 3, 4), days (repmat ([1, 2], 2, 3, 4)))
%!assert_equal (repmat (days ([1, 2]), [2, 3]), days (repmat ([1, 2], [2, 3])))

%!assert_equal (repelem (days ([1:3]), 4), days (repelem ([1:3], 4)))
%!assert_equal (repelem (days ([1:3]), 2, 3, 4), days (repelem ([1:3], 2, 3, 4)))
%!assert_equal (repelem (days ([1:3]), [2, 3, 3]), days (repelem ([1:3], [2, 3, 3])))

%!assert_equal (repelems (days ([1:5]), [1, 3, 5; 2, 1, 2]), days ([1, 1, 3, 5, 5]))

%!assert_equal (reshape (days (magic (4)), 2, 2, 4), days (reshape (magic (4), 2, 2, 4)))
%!assert_equal (reshape (days (magic (4)), [2, 2, 4]), days (reshape (magic (4), [2, 2, 4])))
%!assert_equal (reshape (days (magic (4)), [], 2, 2), days (reshape (magic (4), [], 2, 2)))

%!assert_equal (circshift (days (magic (4)), 2), days (circshift (magic (4), 2)))
%!assert_equal (circshift (days (magic (4)), 1, 2), days (circshift (magic (4), 1, 2)))
%!assert_equal (circshift (days (magic (4)), 1, 1), days (circshift (magic (4), 1, 1)))
%!assert_equal (circshift (days (magic (4)), 1, 1), days (circshift (magic (4), 1)))

%!test
%! X = randi (10, 2, 3, 4);
%! D = days (X);
%! assert_equal (size (permute (D, [3, 1, 2])), [4, 2, 3]);
%! assert_equal (permute (D, [3, 1, 2]), days (permute (X, [3, 1, 2])));
%! assert_equal (D, ipermute (permute (D, [3, 1, 2]), [3, 1, 2]));

%!assert_equal (transpose (days ([1, 2; 3, 4])), days ([1, 3; 2, 4]))
%!assert_equal (transpose (days ([1, 2; 3, 4])), ctranspose (days ([1, 2; 3, 4])))

%!assert_equal (ctranspose (days ([1, 2; 3, 4])), days ([1, 3; 2, 4]))
%!assert_equal (ctranspose (days ([1, 2; 3, 4])), transpose (days ([1, 2; 3, 4])))

################################################################################
##                  ** Reference and Assignment Operations **                 ##
################################################################################
##                             Available Methods                              ##
##                                                                            ##
## 'end'              'subsref'          'subsasgn'                           ##
##                                                                            ##
################################################################################

%!test
%! X = magic (3);
%! D = days (X);
%! assert_equal (days (D(:, end)), X(:,end));
%!test
%! X = magic (3);
%! D = days (X);
%! assert_equal (days (D([1:end-1], end)), [6; 7]);

%!test
%! D = duration ([1:5], 0, 0);
%! out = D([2,3]);
%! assert_equal (size (out), [1, 2]);
%! assert_equal (hours (out), [2, 3]);
%!test
%! D = duration ([1:5], 0, 0);
%! assert_equal (D.Format, 'hh:mm:ss');
%!test
%! D = duration ([1:5], 0, 0, 'Format', 'hh:mm');
%! assert_equal (D.Format, 'hh:mm');
%!test
%! D = duration ([1:5], 0, 0, 'Format', 'y');
%! assert_equal (D.Format, 'y');
%!error<duration.subsref: '{}' invalid indexing for referencing values. Use '\(\)' instead.> ...
%! D = duration ([1:5], 0, 0); D{1}
%!error<duration.subsref: unrecognized property: 'form'> ...
%! D = duration ([1:5], 0, 0); D.form

%!test
%! D = duration ([1:5], 0, 0);
%! D([2,3]) = [4, 5];
%! assert_equal (hours (D), [1, 96, 120, 4, 5]);
%!test
%! D = duration ([1:5], 0, 0);
%! D([2,3]) = hours ([4, 5]);
%! assert_equal (hours (D), [1, 4, 5, 4, 5]);
%!test
%! D = days ([1:5]);
%! D([2,3]) = {'12:23:42', '00:12:23'};
%! assert_equal (days (D), [1, 0.51646, 0.0085995, 4, 5], 1e-5);
%!test
%! D = days ([1:5]);
%! D([2,3]) = string ({'12:23:42', '00:12:23'});
%! assert_equal (days (D), [1, 0.51646, 0.0085995, 4, 5], 1e-5);
%!test
%! D = days ([1:5]);
%! D([2,3]) = ['12:23:42'; '00:12:23'];
%! assert_equal (days (D), [1, 0.51646, 0.0085995, 4, 5], 1e-5);
%!test
%! D = days ([1:5]);
%! D([2,3]) = {'05:12:00:00', '01:00:00:00'};
%! assert_equal (days (D), [1, 5.5, 1, 4, 5]);
%!test
%! D = days ([1:5]);
%! D([2,3]) = string ({'05:12:00:00', '01:00:00:00'});
%! assert_equal (days (D), [1, 5.5, 1, 4, 5]);
%!test
%! D = days ([1:5]);
%! D([2,3]) = ['05:12:00:00'; '01:00:00:00'];
%! assert_equal (days (D), [1, 5.5, 1, 4, 5]);
%!test
%! D = days ([1:5]);
%! D([2,3]) = NaN;
%! assert_equal (days (D), [1, NaN, NaN, 4, 5]);
%! assert_equal (dispstrings (D), {'1 day', 'NaN days', 'NaN days', '4 days', '5 days'});
%!test
%! D = days ([1:5]);
%! D([1:3]) = missing;
%! assert_equal (days (D), [NaN, NaN, NaN, 4, 5]);
%! assert_equal (dispstrings (D), {'NaN days', 'NaN days', 'NaN days', '4 days', '5 days'});
%!test
%! D = days ([1:5]);
%! D([2,3]) = [Inf, -Inf];
%! assert_equal (days (D), [1, Inf, -Inf, 4, 5]);
%! assert_equal (dispstrings (D), {'1 day', 'Inf days', '-Inf days', '4 days', '5 days'});
%!test
%! D = days ([1:5]);
%! D([1:3]) = 2;
%! assert_equal (days (D), [2, 2, 2, 4, 5]);
%!test
%! D = days ([1:5]);
%! D([1:3]) = [NaN, 2, 3];
%! assert_equal (days (D), [NaN, 2, 3, 4, 5]);
%!test
%! D = duration (0, [1:5], 0);
%! D([1:3]) = [NaN, 2, 3];
%! assert_equal (minutes (D), [NaN, 48 * 60, 72 * 60, 4, 5]);
%! assert_equal (dispstrings (D), {'NaN', '48:00:00', '72:00:00', '00:04:00', '00:05:00'});
%!error<duration.subsasgn: chained subscripts not allowed.> ...
%! D = duration (); D(1)(1) = 1
%!error<duration.subsasgn: assignment value must be a duration array, a numeric array of days, or a text represention of durations.> ...
%! D = duration (); D(1) = {1}
%!error<duration.subsasgn: '{}' invalid indexing for assigning values. Use '\(\)' instead.> ...
%! D = duration ([1:5], 0, 0); D{1} = 1
%!error<duration.subsasgn: unrecognized property: 'form'> ...
%! D = duration ([1:5], 0, 0); D.form = 'f'
%!error<duration.subsasgn: 'Format' must be a character vector or a string scalar.> ...
%! D = duration ([1:5], 0, 0); D.Format = 3
%!error<duration.subsasgn: 'Format' must be a character vector or a string scalar.> ...
%! D = duration ([1:5], 0, 0); D.Format = ['y';'d']
%!error<duration.subsasgn: 'Format' must be a character vector or a string scalar.> ...
%! D = duration ([1:5], 0, 0); D.Format = string ({'mm:ss', 'hh:mm'})
%!error<duration.subsasgn: invalid display format.> ...
%! D = duration ([1:5], 0, 0); D.Format = 't'
%!error<duration.subsasgn: invalid display format.> ...
%! D = duration ([1:5], 0, 0); D.Format = 'd.h.S'
%!error<duration.subsasgn: invalid display format.> ...
%! D = duration ([1:5], 0, 0); D.Format = 's.SS'
%!error<duration.subsasgn: 'hh:mm' display format cannot indicate fractional second digits.> ...
%! D = duration ([1:5], 0, 0); D.Format = 'hh:mm.SS'
%!error<duration.subsasgn: invalid display format for fractional second digits.> ...
%! D = duration ([1:5], 0, 0); D.Format = 'hh:mm.SM'
%!error<duration.subsasgn: more than nine fractional second digits in display format.> ...
%! D = duration ([1:5], 0, 0); D.Format = 'hh:mm:ss.SSSSSSSSSS'

%!test
%! D = hours (0:9);
%! [b, e] = discretize (D, 3);
%! assert_equal (b, [1, 1, 1, 2, 2, 2, 3, 3, 3, 3]);
%! assert_equal (hours (e), [0, 3, 6, 9], 1e-12);
%! [~, e] = discretize (seconds (0:5), 3);
%! assert_equal (seconds (e), [-1, 1, 3, 5], 1e-12);
%! [~, e] = discretize (seconds (0:600), 3);
%! assert_equal (seconds (e), [-60, 180, 420, 660], 1e-9);
%! [~, e] = discretize (hours (0:100), 3);
%! assert_equal (seconds (e) / 86400, [-1, 1, 3, 5], 1e-12);
%! [~, e] = discretize (days (0:40), 3);
%! assert_equal (seconds (e) / 86400, [-1, 13, 27, 41], 1e-12);

%!test
%! D = hours (0:9);
%! [~, e] = discretize (D, hours (2));
%! assert_equal (hours (e), [0, 2, 4, 6, 8, 10], 1e-12);
%! [~, e] = discretize (D, 'hour');
%! assert_equal (hours (e), 0:9, 1e-12);
%! b = discretize (D, hours ([0, 4, 9]));
%! assert_equal (b, [1, 1, 1, 1, 2, 2, 2, 2, 2, 2]);
%! b = discretize (D, hours ([0, 4, 9]), 'IncludedEdge', 'right');
%! assert_equal (b, [1, 1, 1, 1, 1, 2, 2, 2, 2, 2]);
%! b = discretize (D, hours ([0, 4, 9]), [10, 20]);
%! assert_equal (b, [10, 10, 10, 10, 20, 20, 20, 20, 20, 20]);

%!test
%! D = hours (0:9);
%! [N, e] = histcounts (D, 3);
%! assert_equal (N, [3, 3, 4]);
%! assert_equal (hours (e), [0, 3, 6, 9], 1e-12);
%! [N, e] = histcounts (D, 'NumBins', 3);
%! assert_equal (N, [3, 3, 4]);
%! [N, e] = histcounts (D, hours ([0, 4, 9]));
%! assert_equal (N, [4, 6]);
%! [~, e] = histcounts (D, 'BinWidth', hours (3));
%! assert_equal (hours (e), [0, 3, 6, 9], 1e-12);
%! [~, e] = histcounts (D, 'BinMethod', 'hour');
%! assert_equal (hours (e), 0:9, 1e-12);

%!test
%! [~, e] = histcounts (seconds (0:90));
%! assert_equal (seconds (e), [0, 18, 36, 54, 72, 90], 1e-12);
%! [~, e] = histcounts (seconds (0:600));
%! assert_equal (seconds (e), [-2, 65, 132, 199, 266, 333, 400, 467, 534, 601], 1e-9);
%! [~, e] = histcounts (hours (0:9));
%! assert_equal (seconds (e), [-3600, 14400, 32400], 1e-9);
%! [~, e] = histcounts (seconds (0:90), 'BinMethod', 'sturges');
%! assert_equal (seconds (e), [-3, 9, 21, 33, 45, 57, 69, 81, 93], 1e-12);
%! [~, e] = histcounts (seconds (0:90), 'BinMethod', 'sqrt');
%! assert_equal (seconds (e), 0:9:90, 1e-12);
%! [~, e] = histcounts (seconds (0:90), 'BinMethod', 'fd');
%! assert_equal (seconds (e), [0, 18, 36, 54, 72, 90], 1e-12);

%!test
%! D = hours (0:9);
%! assert_equal (histcounts (D, 3, 'Normalization', 'cumcount'), [3, 6, 10]);
%! assert_equal (histcounts (D, 3, 'Normalization', 'probability'), ...
%!               [0.3, 0.3, 0.4], 1e-12);
%! assert_equal (histcounts (D, 3, 'Normalization', 'percentage'), ...
%!               [30, 30, 40], 1e-12);
%! assert_equal (histcounts (D, 3, 'Normalization', 'cdf'), ...
%!               [0.3, 0.6, 1], 1e-12);
%! [~, ~, b] = histcounts (D, 3);
%! assert_equal (b, [1, 1, 1, 2, 2, 2, 3, 3, 3, 3]);

%!error<duration.discretize: not enough input arguments.> discretize (hours (1));
%!error<duration.discretize: N must be a real positive integer.> ...
%! discretize (hours (0:9), 0);
%!error<duration.discretize: UNIT must be one of 'second', 'minute', 'hour', 'day', 'week', 'month', 'quarter', 'year', 'decade', or 'century'.> ...
%! discretize (hours (0:9), 'fortnight');
%!error<duration.discretize: numeric bin edges are not accepted for a duration; give a duration vector.> ...
%! discretize (hours (0:9), [1, 2, 3]);
%!error<duration.histcounts: 'integers' is not a valid 'BinMethod' for a duration.> ...
%! histcounts (hours (0:9), 'BinMethod', 'integers');
%!error<duration.histcounts: 'countdensity' is not a valid 'Normalization' for a duration; a density per unit time has no meaning.> ...
%! histcounts (hours (0:9), 'Normalization', 'countdensity');
%!error<duration.histcounts: 'pdf' is not a valid 'Normalization' for a duration; a density per unit time has no meaning.> ...
%! histcounts (hours (0:9), 'Normalization', 'pdf');
%!error<duration.histcounts: 'BinWidth' must be a duration.> ...
%! histcounts (hours (0:9), 'BinWidth', 3);

## Test 'histcounts' -- a single bin takes the width of the data, not of some
## far coarser unit.  A unit is kept only when it both needs every bin and is
## no more than 3/4 of the raw width; keeping the first test alone returned a
## bin one YEAR wide for an hour of data.
%!test
%! [~, e] = histcounts (hours (0:1));
%! assert_equal (seconds (e), [0 3600]);
%!test
%! [~, e] = histcounts (hours (0:2));
%! assert_equal (seconds (e), [0 7200]);
%!test
%! [~, e] = histcounts (seconds (0:1));
%! assert_equal (seconds (e), [0 1]);
%!test
%! [~, e] = histcounts (seconds (0:2));
%! assert_equal (seconds (e), [0 2]);
%!test
%! [~, e] = histcounts (hours (0:100));
%! assert_equal (seconds (e), [0 72000 144000 216000 288000 360000]);
## This was once documented as a deliberate deviation, on the reading that
## R2024a left one of the seven bins unused.  It does not: with the left edge
## placed correctly all seven are occupied, and we now agree with it exactly.
%!test
%! [~, e] = discretize (hours (0:24), 7);
%! assert_equal (seconds (e), ...
%!               [-7200 7200 21600 36000 50400 64800 79200 93600]);
%! assert_equal (unique (discretize (hours (0:24), 7)), 1:7);
%!test
%! [~, e] = discretize (hours (0:5), 3);
%! assert_equal (seconds (e), [-3600 3600 10800 18000]);
%!test
%! [~, e] = discretize (days (0:40), 3);
%! assert_equal (seconds (e) / 86400, [-1 13 27 41]);

## Test 'duration.empty' -- empty duration arrays
%!assert_equal (size (duration.empty), [0, 0])
%!assert_equal (class (duration.empty), 'duration')
%!assert_equal (isempty (duration.empty), true)
%!assert_equal (duration.empty.Format, 'hh:mm:ss')
%!assert_equal (size (duration.empty (2, 0)), [2, 0])
%!assert_equal (size (duration.empty (0, 3)), [0, 3])
%!error <duration.empty: at least one dimension must be zero for an empty array.> ...
%! duration.empty (3)

## Test 'duration.empty' -- size arguments follow 'zeros' rules: a
## negative dimension counts as zero, a size vector holding none names no size
%!assert_equal (size (duration.empty (0)), [0, 0])
%!assert_equal (size (duration.empty (-1)), [0, 0])
%!assert_equal (size (duration.empty (-2, -3)), [0, 0])
%!assert_equal (size (duration.empty ([])), [0, 0])
%!assert_equal (size (duration.empty (2, 0, 3)), [2, 0, 3])
%!assert_equal (size (duration.empty ([0 2 3])), [0, 2, 3])
%!error <duration.empty: dimensions must be integer values.> ...
%! duration.empty (1.5)

## Test 'histcounts' and 'discretize' -- with no finite value to bin, the bins
## go where they would for a single zero, as MATLAB places them.  The edges
## used to run 0, 1, ... N instead, which ignored the tick entirely.
%!test
%! [n, e] = histcounts (duration.empty);
%! assert_equal (n, 0);
%! assert_equal (seconds (e), [-0.0005 0.0005]);
%!test
%! [n, e] = histcounts (duration.empty, 3);
%! assert_equal (n, [0 0 0]);
%! assert_equal (max (abs (seconds (e) - (-0.0005 + (0:3) * 0.001 / 3))) ...
%!               < 1e-12, true);
%!test
%! [n, e] = histcounts (seconds ([NaN NaN]));
%! assert_equal (n, 0);
%! assert_equal (seconds (e), [-0.0005 0.0005]);
%!test
%! [b, e] = discretize (duration.empty, 3);
%! assert_equal (isempty (b), true);
%! assert_equal (max (abs (seconds (e) - (-0.0005 + (0:3) * 0.001 / 3))) ...
%!               < 1e-12, true);
%!test
%! [b, e] = discretize (seconds ([NaN NaN]), 3);
%! assert_equal (isnan (b), [true true]);
%!test
%! [~, e] = histcounts (duration.empty, 'BinMethod', 'scott');
%! assert_equal (seconds (e), [-0.0005 0.0005]);

## Test 'histcounts' -- a named unit or an explicit width still tiles from zero
## when there is no data, rather than collapsing to the numeric [0 1]
%!test
%! [~, e] = histcounts (duration.empty, 'BinWidth', hours (1));
%! assert_equal (seconds (e), [0 3600]);
%!test
%! [~, e] = histcounts (duration.empty, 'BinMethod', 'hour');
%! assert_equal (seconds (e), [0 3600]);
%!test
%! [~, e] = histcounts (seconds ([NaN NaN]), 'BinMethod', 'hour');
%! assert_equal (seconds (e), [0 3600]);
%!test
%! [~, e] = discretize (duration.empty, hours (1));
%! assert_equal (seconds (e), [0 3600]);
%!test
%! [~, e] = histcounts (duration.empty, 'BinLimits', hours ([1 3]));
%! assert_equal (seconds (e), [3600 10800]);

## Test the stored unit -- a duration counts milliseconds, as MATLAB's does, so
## a conversion out and back is exact rather than rounded to a picosecond grid.
## Every figure below is bit-exact against R2024a.
%!assert_equal (seconds (seconds (4.9998333333333331)), 4.9998333333333331)
%!assert_equal (seconds (seconds (1 / 3)), 1 / 3)
%!assert_equal (seconds (seconds (1e5 / 3)), 1e5 / 3)
%!assert_equal (seconds (seconds (1814.9999999999998)), 1814.9999999999998)
%!assert_equal (milliseconds (milliseconds (1234.5678)), 1234.5678)
%!assert_equal (minutes (minutes (1 / 7)), 1 / 7)
%!assert_equal (hours (hours (1 / 7)), 1 / 7)
%!assert_equal (days (days (1 / 7)), 1 / 7)

## Test the stored unit -- whole values stay whole through the conversions that
## used to need the picosecond snap to come out right
%!assert_equal (seconds (duration ('30:15', 'InputFormat', 'mm:ss')), 1815)
%!assert_equal (seconds (duration (0, 30, 15)), 1815)
%!assert_equal (minutes (duration (0, 30, 15)), 30.25)
%!assert_equal (seconds (minutes (1)), 60)
%!assert_equal (seconds (hours (1)), 3600)
%!assert_equal (seconds (days (1)), 86400)
%!assert_equal (milliseconds (seconds (1)), 1000)
%!assert_equal (seconds (milliseconds (1)), 0.001)
%!assert_equal (days (seconds (1)), 1.1574074074074073e-05)

## Test 'discretize' -- bin edges are computed in the stored milliseconds, not
## in seconds.  A width that is not a whole number of seconds cannot be held
## exactly in seconds but is a round integer in milliseconds, so binning in
## seconds left a last-bit error in every such edge.  Values captured from
## R2024a; these are bit-exact and must stay so.
%!test
%! [~, e] = discretize (seconds ([0 3.6]), 3);
%! assert_equal (seconds (e), [0 1.2 2.3999999999999999 3.6000000000000001]);
%!test
%! [~, e] = discretize (seconds ([0 3.72]), 3);
%! assert_equal (seconds (e), [0 1.3 2.6000000000000001 3.8999999999999999]);
%!test
%! [~, e] = discretize (seconds ([0 1e-4]), 3);
%! assert_equal (seconds (e), [0 4.0000000000000003e-05 ...
%!                             8.0000000000000007e-05 0.00011999999999999999]);
%!test
%! [~, e] = discretize (seconds ([0 10^-2.5]), 3);
%! assert_equal (seconds (e), [0 0.0011000000000000001 ...
%!                             0.0022000000000000001 0.0033000000000000004]);

## Test 'discretize' -- the left edge is the unit holding the smallest value
## moved down a whole number of units, so it is constant across a unit and
## steps once.  Sliding the start by an eighth of a second changes the width,
## because the span is counted with a ceiling at the top against a floor at the
## bottom.  Values captured from R2024a.
%!test
%! [~, e] = discretize (seconds ([0 6]), 3);
%! assert_equal (seconds (e), [0 2 4 6]);
%!test
%! [~, e] = discretize (seconds ([0.125 6.125]), 3);
%! assert_equal (seconds (e), [-1 2 5 8]);
%!test
%! [~, e] = discretize (seconds ([0.5 10.5]), 3);
%! assert_equal (seconds (e), [-1 3 7 11]);
%!test
%! [~, e] = discretize (seconds ([0.75 10.75]), 3);
%! assert_equal (seconds (e), [-1 3 7 11]);

## Test 'discretize' -- a whole unit is taken when the excess is under one
## width, and also when it is exactly one width provided the bins are at least
## three units across; below that the finer decimal grid wins.  R=12 at N=5 and
## N=7 are the pair that pins it: same excess-to-width ratio, different answer.
%!test
%! [~, e] = discretize (seconds ([0 12]), 5);
%! assert_equal (seconds (e), [-2 1 4 7 10 13]);
%!test
%! [~, e] = discretize (seconds ([0 12]), 7);
%! assert_equal (seconds (e), [0 1.8 3.6000000000000001 5.4000000000000004 ...
%!                             7.2000000000000002 9 10.800000000000001 12.6]);
%!test
%! [~, e] = discretize (seconds ([0 16]), 5);
%! assert_equal (seconds (e), [-2 2 6 10 14 18]);
%!test
%! [~, e] = discretize (seconds ([0 8]), 5);
%! assert_equal (seconds (e), [0 1.6000000000000001 3.2000000000000002 ...
%!                             4.7999999999999998 6.4000000000000004 8]);

## Test 'discretize' -- a whole unit is kept while the bins overshoot the data
## by less than twice one width less a unit, so the tolerance rises with the
## width: a 3-unit width takes an excess of 3 and a 5-unit width takes 7.  The
## rows below are the accept side, all of which the earlier, tighter rule sent
## to the decimal grid.  Values captured from R2024a.
%!test
%! [~, e] = discretize (seconds ([0 48]), 11);
%! assert_equal (seconds (e), [-4 1 6 11 16 21 26 31 36 41 46 51]);
%!test
%! [~, e] = discretize (seconds ([0.125 28.125]), 7);
%! assert_equal (seconds (e), [-3 2 7 12 17 22 27 32]);
%!test
%! [~, e] = discretize (seconds ([0.125 32.125]), 8);
%! assert_equal (seconds (e), [-4 1 6 11 16 21 26 31 36]);
%!test
%! [~, e] = discretize (seconds ([0.125 40.125]), 8);
%! assert_equal (seconds (e), [-4 2 8 14 20 26 32 38 44]);

## Test 'discretize' -- the reject side of the same bound, which must keep
## using the decimal rule.  A 2-unit width refuses an excess of 2 and a 3-unit
## width refuses 4, one step past what each tolerates above.
%!test
%! [~, e] = discretize (seconds ([0 8]), 5);
%! assert_equal (seconds (e), [0 1.6000000000000001 3.2000000000000002 ...
%!                             4.7999999999999998 6.4000000000000004 8]);
%!test
%! [~, e] = discretize (seconds ([0 14]), 6);
%! assert_equal (seconds (e), [0 2.3999999999999999 4.7999999999999998 ...
%!                             7.2000000000000002 9.5999999999999996 12 14.4]);
%!test
%! [~, e] = discretize (seconds ([0 12]), 3);
%! assert_equal (seconds (e), [0 4 8 12]);

## Test 'sort' -- option VALUES are matched without regard to case, as MATLAB
## matches them; the option names already were.
%!assert_equal (hours (sort (hours ([3 1 NaN 2]), 'Ascend')), [1 2 3 NaN])
%!assert_equal (hours (sort (hours ([3 1 NaN 2]), 'DESCEND')), [NaN 3 2 1])
%!assert_equal (hours (sort (hours ([3 1 NaN 2]), ...
%!                           'MissingPlacement', 'First')), [NaN 1 2 3])
%!assert_equal (hours (sort (hours ([3 1 NaN 2]), ...
%!                           'missingplacement', 'last')), [1 2 3 NaN])

## Adding or subtracting a zero duration is an identity, at any magnitude.
## A precision guard tuned for the old day-based storage used to snap results
## below 1e-15 ms to zero, destroying legitimately tiny durations.
%!assert_equal (milliseconds (milliseconds (5e-16) + milliseconds (0)), 5e-16)
%!assert_equal (seconds (seconds (1e-19) - seconds (0)), 1e-19)
%!assert_equal (milliseconds (milliseconds (5e-16) * 1), 5e-16)
%!assert_equal (seconds (abs (seconds (-1e-19))), 1e-19)
