Dividing by complex zero

I am trying to fix a bug in bode.m and at least part of the problem is the following:

> 1/complex(0)
ans =  Inf - NaNi

> 1./(0*i)
ans = Inf

> 1./(0+0*j)
ans = Inf

The NaN is stopping bode from doing what it should do.
I think that if it was Inf only and not Inf-Nani then I can get past this part of the problem.

Is the Nani the expected answer?

Doug

For compatibility with Matlab, the result of 0*i is automatically converted to a real value but complex (0) is not. Octave doesn’t have a special case for 1 / (0, 0) so you get the Inf - NaNi result from the C++ library division operator for std::complex<T> objects.

Thanks John. I can adjust the answer to Inf for my needs.
The code is doing a difference operation when it hits a NaN then it goes bad but Inf is ok.
I will add a line of code to fix this.

Fwiw, in Matlab R2022a:

>> complex(0,0)/complex(0,0)
ans =
   NaN
>> complex(1,0)/complex(0,0)
ans =
   Inf
>> complex(-1,0)/complex(0,0)
ans =
  -Inf
>> complex(-1,1)/complex(0,0)
ans =
     -Inf +    Infi
>> complex(-1,-1)/complex(0,0)
ans =
     -Inf -    Infi
>> complex(1,-1)/complex(0,0)
ans =
      Inf -    Infi
>> complex(0,-1)/complex(0,0)
ans =
   0.0000 -    Infi
>> complex(0,1)/complex(0,0)
ans =
   0.0000 +    Infi

Thanks mmuetzel:

I now have this question

a=1:10
a(5)=1./complex(0);

for k=1:10
  if (a(k)==(1./complex(0)))
    a(k)=Inf
  endif

endfor

a

I am trying to replace the NaNi part but it does not do it!!!
Any help would be accepted :slight_smile:

isn’t the 1/complex(0) case where matlab gives Inf but Octave gives Inf - NaNi related to a long standing bug on complex case handling? maybe

You can’t use == to detect NaN so you’ll need to check with isnan.

1 Like

Yes, that bug report and probably others.

We could have a special case in the interpreter for the scalar case.

We could define and use our own complex<T> class to provide the special case so that we get more consistent behavior. But that still won’t fix the same problem that could occur in Fortran, C, or other C++ code.

But, I don’t know, maybe we should just do what is compatible so that things appear to be “correct”.

@mmuetzel

Thanks John.

I also noticed this

>> b=1./complex(0);

>> b==b
ans = 0

What does Matlab do with these two lines of code?

matlab 2022a:

>> b = 1./complex(0)
b =
   Inf

>> b==b
ans =
  logical
   1

Inf’s equate but NaN’s don’t, so matlab has no issues with your loop above.

it’ll be expensive but
if (isinf(a(k)) && isnan(a(k))

or a(isinf(a)&isnan(a)) = Inf

correctly flags a(5) without catching just NaN or Inf values. I can’t think of any other cases that would produce Inf+/- NaNi.

i guess you could pile on the explicit checks with

a(isinf(real(a)) & isnan(imag(a))) = Inf

To keep the sign of the Inf value, you could use:

b(isinf (real (b))) = real (b);
1 Like

Like @jwe already wrote, NaN values never compare equal. So, this is the expected result given what Octave returns for 1./complex(0).

Edit: If you prefer that NaN values compare equal, you could use isequaln.

I used

b(isnan(b))=inf

and it works ok.

Should we make an incompatible bug report, or has this been flagged already?

Be aware that this expression replaces all NaN values with Inf. That includes values that might have resulted from, e.g., 0/0 (which in general isn’t expected to result in Inf).

1 Like

similar to why I also added on the isnan part. not knowing what matters where you’re trying to fix this, Inf+3i is a valid number that would be lost if just checking for isinf(real(b))

Yeah. Depends on where you use it if Inf or Inf+3i actually mean something different for you. If they do, you could probably use b(isinf (real (b)) & isnan (imag (b))) = real (b); and maybe also b(isnan (real (b)) & isinf (imag (b))) = complex(0, imag (b));.

Edit: Or if b isn’t a scalar:

b(isinf (real (b)) & isnan (imag (b))) = real (b(isinf (real (b)) & isnan (imag (b))));
b(isnan (real (b)) & isinf (imag (b))) = complex (0, imag (b(isnan (real (b)) & isinf (imag (b)))));
1 Like