Problem with `cat`

I have a problem with cat. I am using polynomials (my own package but this is not the problem)

julia> q=Pol(:q)
Pol{Int64}: q

julia> (q+1)^3
Pol{Int64}: q³+3q²+3q+1

and I am all the time using cat to construct block-diagonal matrices:

julia> m=[q 0; 1 q+1]
2×2 Array{Pol{Int64},2}:
 q  0  
 1  q+1

julia> cat(m,m;dims=(1,2))
4×4 Array{Pol{Int64},2}:
    q       0    #undef  #undef
    1       q+1  #undef  #undef
 #undef  #undef     q       0  
 #undef  #undef     1       q+1

here is the problem: why is cat putting #undef in my matrix instead of polynomial 0?

julia> zero(q)
Pol{Int64}: 0

I tracked down the problem to lines 1443–1445 of abstractarray.jl:

  if T <: Number && count(!iszero, catdims) > 1
        fill!(A, zero(T))
    end

Is not the test T<:Number wrong? Should not the right test be that T has the method zero?

Thank you for help on what to do…

Can’t you simply declare your polynomial type to be <: Number, or is that abstraction wrong?

Why not simply roll your own function to construct a diagonal matrix?

function diagm(m, n)
     l = size(m)[1]
     nd = l * n
     d = fill(0, nd, nd);
     for j = 1 : n
           idx1 = 1 + (j-1) * l
           idx2 = idx1 + (l-1)
           d[idx1:idx2, idx1:idx2] = m
      end
      return d 
end

where the 0 in the fill would have to be replaced with the zero for your polynomial.

I would say it is wrong. I distinguish polynomials from their coefficients by saying that the coefficients are <:Number

That reads like an implementation detail, not like a hard requirement of Poly{T} where T.

In any case, you can also of course overload cat for your type.

EDIT:

I agree with you in that this probably should not just check for <: Number, but making your type <: Number is a valid fix until this can be fixed in Base. Moreover, polynomials do very much feel like numbers to me, so not having that parent type and all the associated methods available seems weird to me.

The question is not whether I can write myself functions from julia Base (I can) but whether cat is properly designed. By the way your code is wrong

  • It assumes m is square
  • You cannot initialize d to 0. One should rather use zero(promote_type(eltype(m),eltype(n)))

Well, if the cat code uses the zero function, then it makes sense to check for Number subtypes, because that’s how zero is defined (in addition to some other types).

I tried to make a system where I do not distinguish polynomials from their coefficients, to get free
multi-variate polynomials (polynomials with coefficients another polynomial) but this did not work (too long to explain here why). In my system I have many numbers: integers, rationals, BigInts, Cyclotomics, field extensions; I think my type system is ok.

I don’t know how your package is structured, but are you sure things break as soon as you add <: Number to the type definition? Because other than that, I don’t see how this could be resolved, if the <: Number check for zero is intended.

In my mind Number means “some subfield of the complex numbers” or perhaps also “element of a finite field”. If you think it should mean “any element of a ring” then that’s a completely different viewpoint.
Anyway, thinking in terms of “duck typing”, I think the logical test should be the existence or not of a zero method. I would like some authoritative answer (like a sound argument why it should not be so).