@@ -3938,10 +3938,32 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense):
3938
3938
[ 6*x 6*x^2 ]
3939
3939
[ 1 0 ]
3940
3940
[ 0 1 ]
3941
+
3942
+ Some particular cases ( matrix is zero, dimension is zero, column is zero) ::
3943
+
3944
+ sage: Matrix( pR, 2, 1) . minimal_kernel_basis( )
3945
+ [1 0 ]
3946
+ [0 1 ]
3947
+
3948
+ sage: Matrix( pR, 2, 0) . minimal_kernel_basis( )
3949
+ [1 0 ]
3950
+ [0 1 ]
3951
+
3952
+ sage: Matrix( pR, 0, 2) . minimal_kernel_basis( )
3953
+ []
3954
+
3955
+ sage: Matrix( pR, 3, 2, [[1,0 ],[1,0 ],[1,0 ]]) . minimal_kernel_basis( )
3956
+ [6 1 0 ]
3957
+ [6 0 1 ]
3958
+
3959
+ sage: Matrix( pR, 3, 2, [[x,0 ],[1,0 ],[x+1,0 ]]) . minimal_kernel_basis( )
3960
+ [6 x 0 ]
3961
+ [6 6 1 ]
3941
3962
"""
3963
+ from sage.matrix.constructor import matrix
3964
+
3942
3965
m = self .nrows()
3943
3966
n = self .ncols()
3944
- d = self .degree()
3945
3967
3946
3968
# set default shifts / check shifts dimension
3947
3969
if shifts is None :
@@ -3953,15 +3975,17 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense):
3953
3975
3954
3976
# compute kernel basis
3955
3977
if row_wise:
3956
- if d is - 1 : # matrix is zero
3957
- from sage.matrix.constructor import matrix
3958
- return matrix.identity(self .base_ring(), m, m)
3959
-
3960
3978
if m <= n and self .constant_matrix().rank() == m:
3961
- # early exit: kernel is empty
3962
- from sage.matrix.constructor import matrix
3979
+ # early exit: kernel is empty; note: this covers the case m==0
3963
3980
return matrix(self .base_ring(), 0 , m)
3964
3981
3982
+ if n == 0 : # early exit: kernel is identity
3983
+ return matrix.identity(self .base_ring(), m, m)
3984
+
3985
+ d = self .degree() # well defined since m > 0 and n > 0
3986
+ if d == - 1 : # matrix is zero: kernel is identity
3987
+ return matrix.identity(self .base_ring(), m, m)
3988
+
3965
3989
# degree bounds on the kernel basis
3966
3990
degree_bound = min (m,n)* d+ max (shifts)
3967
3991
degree_bounds = [degree_bound - shifts[i] for i in range (m)]
@@ -3970,6 +3994,17 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense):
3970
3994
orders = self .column_degrees(degree_bounds)
3971
3995
for i in range (n): orders[i] = orders[i]+ 1
3972
3996
3997
+ # note: minimal_approximant_basis requires orders[i] > 0
3998
+ # -> if d>0, then degree_bounds > 0 entry-wise and this tuple
3999
+ # `orders` already has all entries strictly positive
4000
+ # -> if d==0, then `orders[i]` is zero exactly when the column i
4001
+ # of self is zero; we may as well take orders[i] == 1 for such
4002
+ # columns which do not influence the left kernel
4003
+ if d == 0 :
4004
+ for i in range (n):
4005
+ if orders[i] == 0 :
4006
+ orders[i] = 1
4007
+
3973
4008
# compute approximant basis and retrieve kernel rows
3974
4009
P = self .minimal_approximant_basis(orders,shifts,True ,normal_form)
3975
4010
row_indices = []
@@ -3979,15 +4014,17 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense):
3979
4014
return P[row_indices,:]
3980
4015
3981
4016
else :
3982
- if d is - 1 : # matrix is zero
3983
- from sage.matrix.constructor import matrix
3984
- return matrix.identity(self .base_ring(), n, n)
3985
-
3986
4017
if n <= m and self .constant_matrix().rank() == n:
3987
- # early exit: kernel is empty
3988
- from sage.matrix.constructor import matrix
4018
+ # early exit: kernel is empty; this covers the case n==0
3989
4019
return matrix(self .base_ring(), n, 0 )
3990
4020
4021
+ if m == 0 : # early exit: kernel is identity
4022
+ return matrix.identity(self .base_ring(), n, n)
4023
+
4024
+ d = self .degree() # well defined since m > 0 and n > 0
4025
+ if d == - 1 : # matrix is zero
4026
+ return matrix.identity(self .base_ring(), n, n)
4027
+
3991
4028
# degree bounds on the kernel basis
3992
4029
degree_bound = min (m,n)* d+ max (shifts)
3993
4030
degree_bounds = [degree_bound - shifts[i] for i in range (n)]
@@ -3996,6 +4033,17 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense):
3996
4033
orders = self .row_degrees(degree_bounds)
3997
4034
for i in range (m): orders[i] = orders[i]+ 1
3998
4035
4036
+ # note: minimal_approximant_basis requires orders[i] > 0
4037
+ # -> if d>0, then degree_bounds > 0 entry-wise and this tuple
4038
+ # `orders` already has all entries strictly positive
4039
+ # -> if d==0, then `orders[i]` is zero exactly when the row i
4040
+ # of self is zero; we may as well take orders[i] == 1 for such
4041
+ # rows which do not influence the right kernel
4042
+ if d == 0 :
4043
+ for i in range (m):
4044
+ if orders[i] == 0 :
4045
+ orders[i] = 1
4046
+
3999
4047
# compute approximant basis and retrieve kernel columns
4000
4048
P = self .minimal_approximant_basis(orders,shifts,False ,normal_form)
4001
4049
column_indices = []
0 commit comments