It looks like this has been resolved, but nevertheless I'd like to chime in.
In reference to comment 4:
"I would still open a discussion on Octave Maintainers list just to see if there is a good mathematical reason for returning either 0 or Inf. "
There is a good mathematical reason for returning pinv(0) = 0. Although there are different mathematical notions of generalized inverse, the most widely used is the MoorePenrose inverse (https://en.wikipedia.org/wiki/Moore%E2%80%93Penrose_inverse). For any matrix A, there exists a unique matrix B with the following four properties:
 A*B*A = A
 B*A*B = B
 A*B is Hermitian
 B*A is Hermitian
B is the MoorePenrose inverse of A. It is easy to verify that the MoorePenrose inverse of a zero matrix is a zero matrix.
If you look at the documentation of pinv in Matlab, this is precisely what is returned there. This is what Octave should return as well.

I checked in a change along with BIST tests here (http://hg.savannah.gnu.org/hgweb/octave/rev/d3dc76efb38b).
I also found that we were not calculating the tolerance correctly for single matrices. Apparently there was a copy and paste error from the code for double matrices and we were using
in calculations instead of the "float" version of epsilon.

>> pinv ([0 1e15; 0 0], 1e14)
ans =
0 0
0 0
>> pinv (zeros (2,2))
ans =
0 0
0 0
>> version
ans =
'9.3.0.713579 (R2017b)'
>>
Looks OK.

Hmm, okay. What about the following:
I think numbers below the tolerance should be rounded to zero and this will be equivalent to
which should be a 2x2 zero matrix according to the results so far.

Last pinv (D) needs fixing:
D = diag ([0 0 0])
D =
0 0 0
0 0 0
0 0 0
pinv (D)
ans =
0 0 0
0 0 0
0 0 0
>> version
ans =
'9.3.0.713579 (R2017b)'
>>
>> D = full (diag ([0 0 0]))
D =
0 0 0
0 0 0
0 0 0
>> pinv (D)
ans =
0 0 0
0 0 0
0 0 0
>>

@Michael: Thanks. I've got a cset that addresses this issue. I know it is a corner case, but I'm actually not pleased that Octave has been returning the wrong answer for zero vectors and scalars for many years.
A final test to run through Matlab for diagonal matrices
In Octave, this creates a special Diagonal matrix and the result is
But if I use full matrices, I get NaN
So what does Matlab do?

>> pinv (complex (0,0))
pinv ([complex(0,0), complex(0,0), complex(0,0)])
ans =
0
ans =
0
0
0
>> version
ans =
'9.3.0.713579 (R2017b)'
>>

I've been looking at resolving the issues with inv(0) and am now revisiting this bug. What does Matlab return for

So Matlab and Octave agree on the 2x2 matrices. Is the patch of comment #9 ready to be pushed or are there other issues to take care of?


Attached is a quick hack (inverse.diff) which applies only to double matrices. It explicitly checks for the case of a scalar which is either 0 or Inf and returns the correct output value.
What does Matlab return for these two cases

Any fix also needs to respect bug #49690 where the inverse of Inf should be 0 for Matlab compatibility. My guess is that is where the problem in inverse for the input 0 has crept in. See cset 22154.

The code for the pseudo_inverse of a double matrix is in liboctave/array/dMatrix.cc. It looks like it calculates the svd, and then also calculates an inverse. My guess is the inverse code is where the problem creeps in.

The pseudoinverse of 0 is 0 (wikipedia, for instance). And the pseudoinverse of a null vector is the transposed null vector (this answers comment #5).
inv(0) was Inf on 4.2.0 and this is correct.

pinv is a weird function.
What does Matlab do for this test case?

I would still open a discussion on Octave Maintainers list just to see if there is a good mathematical reason for returning either 0 or Inf.
And from the results of your test it looks like there are two Matlab incompatibilities.

In Matlab:
I agree this is a design choice but I would say that 100% compatible with Matlab is required for functions as fundamental as inv & pinv.

Leaving aside what Matlab does for the moment, what would you like to see for the inverse of a scalar?
In general, the inverse would just be 1/x for a scalar. So,
If I follow this analogy, pinv(0) should return 1/0
which is what the function seems to be doing.
Of course, maybe it is better to be Matlab compatible for this case. Or maybe pinv should follow inv.
There is definitely room for interpretation here, rather than being absolutely the wrong answer. Maybe you should post on the Octave Maintainer's list to gather some other opinions.

I confirm and changed to regression, since it was 0 on 4.0.2. Moreover
is correct on dev.

pinv(0) returns Inf in Octave and 0 in Matlab.
