zerodiv.m 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. function f = zerodiv(x,y,val,wantcaution)
  2. % function f = zerodiv(x,y,val,wantcaution)
  3. %
  4. % <x>,<y> are matrices of the same size or either or both can be scalars.
  5. % <val> (optional) is the value to use when <y> is 0. default: 0.
  6. % <wantcaution> (optional) is whether to perform special handling of weird
  7. % cases (see below). default: 1.
  8. %
  9. % calculate x./y but use <val> when y is 0.
  10. % if <wantcaution>, then if the absolute value of one or more elements of y is
  11. % less than 1e-5 (but not exactly 0), we issue a warning and then treat these
  12. % elements as if they are exactly 0.
  13. % if not <wantcaution>, then we do nothing special.
  14. %
  15. % note some weird cases:
  16. % if either x or y is [], we return [].
  17. % NaNs in x and y are handled in the usual way.
  18. %
  19. % history:
  20. % 2011/02/02 - in the case that y is not a scalar and wantcaution is set to 0,
  21. % we were allowing division by 0 to result in Inf and *not* replaced
  22. % with val as desired. big mistake. we have now fixed this.
  23. %
  24. % example:
  25. % isequalwithequalnans(zerodiv([1 2 3],[1 0 NaN]),[1 0 NaN])
  26. % input
  27. if nargin < 4 % need optimal speed so try to bypass in the fully specified case if we can
  28. if ~exist('val','var') || isempty(val)
  29. val = 0;
  30. end
  31. if ~exist('wantcaution','var') || isempty(wantcaution)
  32. wantcaution = 1;
  33. end
  34. else
  35. if isempty(val)
  36. val = 0;
  37. end
  38. if isempty(wantcaution)
  39. wantcaution = 1;
  40. end
  41. end
  42. % handle special case of y being scalar
  43. if isscalar(y)
  44. if y==0
  45. f = repmat(val,size(x));
  46. else
  47. if wantcaution && abs(y) < 1e-5 % see allzero.m
  48. warning('abs value of divisor is less than 1e-5. we are treating the divisor as 0.');
  49. f = repmat(val,size(x));
  50. else
  51. %REMOVED:
  52. % if abs(y) < 1e-5 && ~wantcaution
  53. % warning('abs value of divisor is less than 1e-5. we are treating the divisor as-is.');
  54. % end
  55. f = x./y;
  56. end
  57. end
  58. else
  59. % do it
  60. bad = y==0;
  61. bad2 = abs(y) < 1e-5; % see allzero.m
  62. if wantcaution && any(bad2(:) & ~bad(:))
  63. warning('abs value of one or more divisors is less than 1e-5. we are treating these divisors as 0.');
  64. end
  65. %REMOVED:
  66. % if any(bad2 & ~bad) && ~wantcaution
  67. % warning('abs value of one or more divisors is less than 1e-5. we are treating the divisors as-is.');
  68. % end
  69. if wantcaution
  70. y(bad2) = 1;
  71. f = x./y;
  72. f(bad2) = val;
  73. else
  74. y(bad) = 1;
  75. f = x./y;
  76. f(bad) = val;
  77. end
  78. end