Question: I'm unable to understand how NumPy calculates the inner product of two 2D matrices.

For example, this program:

```
mat = [[1, 2, 3, 4],
       [5, 6, 7, 8]]

result = np.inner(mat, mat)

print('\n' + 'result: ')
print(result)
print('')

```

produces this output:

```
result: 
[[ 30  70]
 [ 70 174]]

```

How are these numbers calculated ??

Before somebody says "read the documentation" I did, <https://numpy.org/doc/stable/reference/generated/numpy.inner.html>, it's not clear to me from this how this result is calculated.

Before somebody says "check the Wikipedia article" I did, <https://en.wikipedia.org/wiki/Frobenius_inner_product> shows various math symbols I'm not familiar with and does not explain how a calculation such as the one above is performed.

Before somebody says "Google it", I did, most examples are for 1-d arrays (which is an easy calculation), and others like this video <https://www.youtube.com/watch?v=_YtHyjcQ1gw> produce a different result than NumPy does.

Any clarification would be greatly appreciated.

Answer: 
```
In [55]: mat = [[1, 2, 3, 4],
    ...:        [5, 6, 7, 8]]
    ...: 
In [56]: arr = np.array(mat)

In [58]: arr.dot(arr.T)
Out[58]: 
array([[ 30,  70],
       [ 70, 174]])

```

That's a matrix product of a (2,4) with a (4,2), resulting in a (2,2). This is the usual 'scan across the columns, down the rows' method.

A couple of other expressions that do this:

I like the expressiveness of `einsum`, where the sum-of-products is on the `j` dimension:

```
In [60]: np.einsum('ij,kj->ik',arr,arr)
Out[60]: 
array([[ 30,  70],
       [ 70, 174]])

```

With broadcasted elementwise multiplication and summation:

```
In [61]: (arr[:,None,:]*arr[None,:,:]).sum(axis=-1)
Out[61]: 
array([[ 30,  70],
       [ 70, 174]])

```

Without the `sum`, the products are:

```
In [62]: (arr[:,None,:]*arr[None,:,:])
Out[62]: 
array([[[ 1,  4,  9, 16],
        [ 5, 12, 21, 32]],

       [[ 5, 12, 21, 32],
        [25, 36, 49, 64]]])

```

Which are the values you discovered.
I finally found this site <https://www.tutorialspoint.com/numpy/numpy_inner.htm> which explains things a little better. The above is computed as follows:

```
(1*1)+(2*2)+(3*3)+(4*4)     (1*5)+(2*6)+(3*7)+(4*8)
  1  +  4  +  9  + 16         5  + 12  + 21  + 32
         = 30                        = 70

(5*1)+(6*2)+(7*3)+(8*4)     (5*5)+(6*6)+(7*7)+(8*8)
  5  + 12  + 21  + 32        25  + 36  + 49  + 64
         = 70                        = 174

```