function dmsvec = mat2dms(d,m,s,n)
% MAT2DMS Converts a [deg min sec] matrix to vector format
%
%  dms = MAT2DMS(d,m,s) converts a deg:min:sec matrix into a vector
%  format.  The vector format is dms = 100*deg + min + sec/100.
%  This allows d,m,s triple to be compressed into a single value,
%  which can then be employed similar to a degree or radian vector.
%  The inputs d, m and s must be of equal size.  Minutes and
%  second must be between 0 and 60.
%
%  dms = MAT2DMS(mat) assumes and input matrix of [d m s].  This is
%  useful only for single column vectors for d, m and s.
%
%  dms = MAT2DMS(d,m) and dms = MAT2DMS([d m]) assume that seconds
%  are zero, s = 0.
%
%  dms = MAT2DMS(d,m,s,n) uses n as the accuracy of the seconds
%  calculation.  n = -2 uses accuracy in the hundredths position,
%  n = 0 uses accuracy in the units position.  Default is n = -5.
%  For further discussion of the input n, see ROUNDN.
%
%  See also DMS2MAT

% Written by:  E. Byrns, E. Brown
% Revision: 1.10    Date: 2002/03/20 21:25:51
%
% GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
% This file is part of GNSS-SDR.
%
% SPDX-FileCopyrightText: 1996-2002 Systems Planning and Analysis, Inc. and The MathWorks, Inc.
% SPDX-License-Identifier: GPL-3.0-or-later


if nargin == 0
    error('Incorrect number of arguments')

elseif nargin==1
    if size(d,2)== 3
        s = d(:,3);   m = d(:,2);   d = d(:,1);
    elseif size(d,2)== 2
        m = d(:,2);   d = d(:,1);   s = zeros(size(d));
    elseif size(d,2) == 0
        d = [];   m = [];   s = [];
    else
        error('Single input matrices must be n-by-2 or n-by-3.');
    end
    n = -5;

elseif nargin == 2
    s = zeros(size(d));
    n = -5;

elseif nargin == 3
    n = -5;
end

%  Test for empty arguments

if isempty(d) & isempty(m) & isempty(s);  dmsvec = [];  return;  end

%  Don't let seconds be rounded beyond the tens place.
%  If you did, then 55 seconds rounds to 100, which is not good.

if n == 2;  n = 1;   end

%  Complex argument tests

if any([~isreal(d) ~isreal(m) ~isreal(s)])
    warning('Imaginary parts of complex ANGLE argument ignored')
    d = real(d);   m = real(m);   s = real(s);
end

%  Dimension and value tests

if ~isequal(size(d),size(m),size(s))
    error('Inconsistent dimensions for input arguments')
elseif any(rem(d(~isnan(d)),1) ~= 0 | rem(m(~isnan(m)),1) ~= 0)
    error('Degrees and minutes must be integers')
end

if any(abs(m) > 60) | any (abs(m) < 0)       %  Actually algorithm allows for
    error('Minutes must be >= 0 and < 60')   %  up to exactly 60 seconds or
    %  60 minutes, but the error message
elseif any(abs(s) > 60) | any(abs(s) < 0)    %  doesn't reflect this so that angst
    error('Seconds must be >= 0 and < 60')   %  is minimized in the user docs
end

%  Ensure that only one negative sign is present and at the correct location

if any((s<0 & m<0) | (s<0 & d<0) | (m<0 & d<0) )
    error('Multiple negative entries in a DMS specification')
elseif any((s<0 & (m~=0 | d~= 0)) | (m<0 & d~=0))
    error('Incorrect negative DMS specification')
end

%  Construct a sign vector which has +1 when
%  angle >= 0 and -1 when angle < 0.  Note that the sign of the
%  angle is associated with the largest nonzero component of d:m:s

negvec = (d<0) | (m<0) | (s<0);
signvec = ~negvec - negvec;

%  Convert to all positive numbers.  Allows for easier
%  adjusting at 60 seconds and 60 minutes

d = abs(d);     m = abs(m);    s = abs(s);

%  Truncate seconds to a specified accuracy to eliminate round-off errors

[s,msg] = roundn(s,n);
if ~isempty(msg);   error(msg);   end

%  Adjust for 60 seconds or 60 minutes. If s > 60, this can only be
%  from round-off during roundn since s > 60 is already tested above.
%  This round-off effect has happened though.

indx = find(s >= 60);
if ~isempty(indx);   m(indx) = m(indx) + 1;   s(indx) = 0;   end

%  The user can not put minutes > 60 as input.  However, the line
%  above may create minutes > 60 (since the user can put in m == 60),
%  thus, the test below includes the greater than condition.

indx = find(m >= 60);
if ~isempty(indx);   d(indx) = d(indx) + 1;   m(indx) = m(indx)-60;   end

%  Construct the dms vector format

dmsvec = signvec .* (100*d + m + s/100);
