```Issue #8223 has been updated by boris_stitnicky (Boris Stitnicky).

For starters, I propose changing the existing Matrix#* method to the following:

class Matrix
# Matrix multiplication.
#
def * arg # arg is matrix or vector or number
case arg
when Numeric
rows = @rows.map { |row| row.map { |e| e * arg } }
return new_matrix rows, column_size
when Vector
arg = Matrix.column_vector arg
result = self * arg
return result.column 0
when Matrix
Matrix.Raise ErrDimensionMismatch if column_size != arg.row_size
rows = Array.new row_size do |i|
Array.new arg.column_size do |j|
( 0...column_size ).map { |c| arg[c, j] * self[i, c] }.reduce :+
end
end
return new_matrix( rows, arg.column_size )
else
compat_1, compat_2 = arg.coerce self
return compat_1 * compat_2
end
end
end

Provided that I didn't make a mistake, this version of matrix multiplication does not perform
addition of 0 to the sum. I know that there is actually a reason why we should always write
#reduce with starting value, but I now cannot remember what the reason was. And patching with
this method makes the matrix multiplication of metres work...
----------------------------------------
Feature #8223: Make Matrix more omnivorous.
https://bugs.ruby-lang.org/issues/8223#change-38314

Author: boris_stitnicky (Boris Stitnicky)
Status: Open
Priority: Normal
Assignee:
Category:
Target version:

Let's imagine a class Metre, whose instances represent physical magnitudes in metres.

class Metre
def initialize magnitude; @magnitude = magnitude end
def to_s; magnitude.to_s + ".m" end
end

Let's say that metres can be multiplied by a number:

class Metre
def * multiplicand
case multiplicand
when Numeric then Metre.new( magnitude * multiplicand )
else
raise "Metres can only be multiplied by numbers, multiplication by #{multiplicand.class} attempted!"
end
end
end

And that they can be summed up with other magnitudes in metres, but, as a feature,
not with numbers (apples, pears, seconds, kelvins...).

class Metre
def + summand
case summand
when Metre then Metre.new( magnitude + summand.magnitude )
else
raise "Metres can only be summed with metres, summation with #{summand.class} attempted!"
end
end
end

Now with one more convenience constructor Numeric#m:

class Numeric
def m; Metre.new self end
end

We can write expressions such as

3.m + 5.m
#=> 8.m
3.m * 2
#=> 6.m

And with defined #coerce:

class Metre
def coerce other; [ self, other ] end
end

Also this expression is valid:

2 * 3.m
#=> 6.m

Before long, the user will want to make a matrix of magnitudes:

require 'matrix'
mx = Matrix.build 2, 2 do 1.m end
#=> Matrix[[1.m, 1.m], [1.m, 1.m]]

It works, but the joy does not last long. The user will fail miserably if ze wants to perform matrix multiplication:

cv = Matrix.column_vector [1, 1]
mx * cv
#=> RuntimeError: Metres can only be summed with metres, summation with Fixnum attempted!
# where 2.m would be expected

In theory, everything should be O.K., since Metre class has both metre summation and multiplication by a number defined. The failure happens due to the internal workings of the Matrix class, which assumes that the elements can be summed together with numeric 0. But it is a feature of metres, that they are picky and allow themselves to be summed only with other Metre instances.

In my real physical units library that I have written, I have solved this problem by
defining an über zero object that produces the expected result, when summed with objects, that would otherwise not lend themselves to summation with ordinary numeric 0,
and patching the Matrix class so that it uses this über zero instead of the ordinary one.

But this is not a very systematic solution. Actually, I think that the Matrix class would be more flexible, if, instead of simply using 0, it asked the elements of the matrix what their zero is, as in:

class << Metre
def zero; new 0 end
end

But of course, that would also require that ordinary numeric classes can tell what their zero is, as in:

def Integer.zero; 0 end
def Float.zero; 0.0 end
def Complex.zero; Complex 0.0, 0.0 end
# etc.

I think that this way of doing things (that is, having #zero methods in numeric classes and making Matrix actually require the class of the objects in it to have public class method #zero defined) would make everything more consistent and more algebra-like. I am having this problem for already almost half a year, but I only gathered courage today to encumber you guys with this proposal. Please don't judge me harshly for it. I have actually already seen something like this, in particular with bigdecimal's Jacobian (http://ruby-doc.org/stdlib-2.0/libdoc/bigdecimal/rdoc/Jacobian.html), which requires that the object from which the Jacobian is computed implements methods #zero, #one, #two etc. Sorry again.

--
http://bugs.ruby-lang.org/

```