##  Copyright (C) 2014  Daniel Kraft <d@domob.eu>
##  GNU Octave level-set package.
##
##  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/>.

## -*- texinfo -*-
## @deftypefn  {Function File} {@var{d} =} ls_copy_sign (@var{d}, @var{phi})
## 
## Internal routine for taking over the sign of @var{phi} onto @var{d}.  This
## routine assumes that @var{d} is positive initially.  It copies over the
## sign of @var{phi} to @var{d}, taking signed zeros into account.
##
## @seealso{ls_signed_distance, ls_init_narrowband, ls_nb_from_geom, sign}
## @end deftypefn

function d = ls_copy_sign (d, phi)
  if (nargin () != 2)
    print_usage ();
  endif

  sz = size (phi);
  if (!all (size (d) == sz))
    error ("size mismatch in the arguments");
  endif

  if (!all (d(:) >= 0 | isna (d(:))))
    error ("D should initially be positive");
  endif

  if (exist ("signbit") == 5)
    where = signbit (phi);
  else
    where = (phi < 0);
  endif
  d(where & !isna (d)) *= -1;
endfunction

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Tests.

% Test for errors.
%!error <Invalid call to>
%!  ls_copy_sign (1);
%!error <Invalid call to>
%!  ls_copy_sign (1, 2, 3);
%!error <size mismatch in the arguments>
%!  ls_copy_sign (1, [2, 3]);
%!error <D should initially be positive>
%!  ls_copy_sign (-1, 5);

% Test basic functionality.
%!test
%!  d = [0, 1, 2, eps, Inf];
%!  zeros = (d == 0);
%!  phi = [-1, 1, 1, -1, -1];
%!  dp = ls_copy_sign (d, phi);
%!  assert (abs (dp), d);
%!  assert (sign (dp(!zeros)), sign (phi(!zeros)));

% Test signed zeros.
%!test
%!  if (exist ("signbit") == 5)
%!    d = [0, 0, 1, 1];
%!    phi = [-0, 0, -0, 0];
%!    dp = ls_copy_sign (d, phi);
%!    assert (signbit (dp), signbit (phi));
%!    assert (dp, [-0, 0, -1, 1]);
%!  else
%!    warning ("'signbit' function not available, skipping test.");
%!  endif
