@@ -12,6 +12,7 @@ from cpython.sequence cimport *
12
12
13
13
from cysignals.signals cimport sig_str, sig_off
14
14
15
+ from sage.arith.power cimport generic_power
15
16
from sage.structure.sage_object cimport SageObject
16
17
from sage.structure.element cimport Element, Matrix
17
18
from sage.libs.flint.nmod_mat cimport *
@@ -147,11 +148,14 @@ cdef class Matrix_nmod_dense(Matrix_dense):
147
148
cdef int k
148
149
149
150
from sage.structure.richcmp cimport Py_EQ, PY_NE
151
+ raise NotImplementedError (" I'm here" )
150
152
if op == PY_EQ:
151
153
# FIXME
154
+ return rich_to_bool(op, 0 )
152
155
153
156
elif op == PY_NE:
154
157
# FIXME
158
+ return rich_to_bool(op, 0 )
155
159
156
160
else :
157
161
sig_on()
@@ -194,22 +198,186 @@ cdef class Matrix_nmod_dense(Matrix_dense):
194
198
195
199
# Extra
196
200
197
- # add inplace and not inplace versions
201
+ def tranpose (self ):
202
+ cdef Matrix_nmod_dense M = self ._new(self ._nrows, self ._ncols)
203
+ sig_on()
204
+ nmod_mat_transpose(M._matrix, self ._matrix)
205
+ sig_off()
206
+ return M
207
+
208
+
209
+ def echelonize (self ):
210
+ """
211
+ Echelon form in place
212
+ """
213
+ if not self ._parent._base.is_field():
214
+ raise NotImplementedError (" Only implemented over fields" )
215
+ self .check_mutability()
216
+ self .clear_cache()
217
+ rank = nmod_mat_rref(self ._matrix)
218
+ self .cache(' rank' , rank)
219
+
220
+ def echelon_form (self ):
221
+ key= ' echelon_form'
222
+ ans = self .fetch(key)
223
+ if ans is not None :
224
+ return ans
225
+ ans = self .__copy__()
226
+ self .cache(key, ans)
227
+ ans.echelonize()
228
+ return ans
229
+
230
+
231
+
232
+ def rank (self ):
233
+ key = ' rank'
234
+ ans = self .fetch(key)
235
+ if ans is not None :
236
+ return ans
237
+ sig_on()
238
+ ans = nmod_mat_rank(self ._matrix)
239
+ sig_off()
240
+ self .cache(key, ans)
241
+ return ans
242
+
243
+ def det (self ):
244
+ if self ._nrows != self ._ncols:
245
+ raise ValueError (" self must be a square matrix" )
246
+ key = ' det'
247
+ ans = self .fetch(key)
248
+ if ans is not None :
249
+ return ans
250
+ sig_on()
251
+ ans = nmod_mat_det(self ._matrix)
252
+ sig_off()
253
+ self .cache(key, ans)
254
+ return ans
255
+
256
+ def trace (self ):
257
+ if self ._nrows != self ._ncols:
258
+ raise ValueError (" self must be a square matrix" )
259
+ key = ' trace'
260
+ ans = self .fetch(key)
261
+ if ans is not None :
262
+ return ans
263
+ sig_on()
264
+ ans = nmod_mat_trace(self ._matrix)
265
+ sig_off()
266
+ self .cache(key, ans)
267
+ return ans
268
+
269
+ def _strong_echelon_form (self ):
270
+ """
271
+ In place strong echelon form of self
272
+ """
273
+ if self ._nrows >= self ._ncols:
274
+ raise ValueError (" self must must have at least as many rows as columns." )
275
+ self .check_mutability()
276
+ self .clear_cache()
277
+ sig_on()
278
+ nmod_mat_strong_echelon_form(self ._matrix)
279
+ sig_off()
198
280
199
281
def strong_echelon_form (self ):
200
- # Edgar: fix so not in place
282
+ """
283
+ Strong echelon form of self
284
+ """
285
+ key= ' strong_echelon_form'
286
+ ans = self .fetch(key)
287
+ if ans is not None :
288
+ return ans
289
+ ans = self .__copy__()
290
+ ans._strong_echelon_form()
291
+ self .cache(key, ans)
292
+ return ans
293
+
294
+ def _howell_form (self ):
295
+ """
296
+ In place Howell form of self
297
+ """
201
298
if self ._nrows >= self ._ncols:
202
- nmod_mat_strong_echelon_form(self ._matrix)
299
+ raise ValueError (" self must must have at least as many rows as columns." )
300
+ self .check_mutability()
301
+ self .clear_cache()
302
+ nmod_mat_howell_form(self ._matrix)
303
+
304
+ def howell_form (self ):
305
+ """
306
+ Howell form of self
307
+ """
308
+ key= ' howell_form'
309
+ ans = self .fetch(key)
310
+ if ans is not None :
311
+ return ans
312
+ ans = self .__copy__()
313
+ ans._howell_form()
314
+ self .cache(key, ans)
315
+ return ans
316
+
317
+ def __pow__ (sself , n , dummy ):
318
+ cdef Matrix_nmod_dense self = < Matrix_nmod_dense?> sself
319
+
320
+ if dummy is not None :
321
+ raise ValueError
322
+ if self ._nrows != self ._ncols:
323
+ raise ArithmeticError (" self must be a square matrix" )
324
+
325
+ cdef unsigned long e
326
+ cdef long e_sgn
327
+ cdef int err
328
+
329
+ if integer_check_long_py(n, & e_sgn, & err) and not err:
330
+ if e_sgn < 0 :
331
+ return (~ self ) ** (- n)
332
+ e = < unsigned long > e_sgn
203
333
else :
204
- raise ValueError (" Matrix must have at least as many rows as columns." )
334
+ if not isinstance (n, Integer):
335
+ try :
336
+ n = Integer(n)
337
+ except TypeError :
338
+ from sage.symbolic.expression import Expression
339
+ if isinstance (n, Expression):
340
+ from sage.matrix.matrix2 import _matrix_power_symbolic
341
+ return _matrix_power_symbolic(self , n)
342
+ else :
343
+ raise NotImplementedError (" the given exponent is not supported" )
344
+ if mpz_sgn((< Integer> n).value) < 0 :
345
+ return (~ self ) ** (- n)
346
+
347
+ if mpz_fits_ulong_p((< Integer> n).value):
348
+ e = mpz_get_ui((< Integer> n).value)
349
+ else :
350
+ # it is very likely that the following will never finish except
351
+ # if self has only eigenvalues 0, 1 or -1.
352
+ return generic_power(self , n)
353
+
354
+ if e == 0 :
355
+ return self ._parent.identity_matrix()
356
+ if e == 1 :
357
+ return self
205
358
359
+ cdef Matrix_nmod_dense M = self ._new(self ._nrows, self ._ncols)
360
+ sig_on()
361
+ nmod_mat_pow(M._matrix, self ._matrix, e)
362
+ sig_off()
363
+ return M
206
364
207
- def howell_form (self ):
208
- # Edgar: fix so not in place
209
- if self ._nrows >= self ._ncols:
210
- nmod_mat_howell_form(self ._matrix)
365
+ def _right_kernel_matrix (self ):
366
+ if self ._parent._base.is_field():
367
+ # nmod_mut_nullspace will do this regardless
368
+ # so we are better off to start in echelon form to have the rank
369
+ echelon_form = self .echelon_form()
370
+ cdef Matrix_nmod_dense X = self ._new(self .ncols, self ._nrows - self .rank(), self ._ncols)
371
+ cdef Matrix_nmod_dense ans = self ._new(self ._nrows - self .rank(), self ._ncols)
372
+ sig_on()
373
+ nmod_mat_nullspace(X._matrix, echelon_form._matrix) # columns of X form a basis
374
+ nmod_mat_tranpose(ans._natrix, X._matrix)
375
+ sig_off()
376
+ return ans
211
377
else :
212
- raise ValueError (" Matrix must have at least as many rows as columns." )
378
+ raise NotImplementedError (" I'm here" )
379
+ strong_echelon_form = self .strong_echelon_form()
380
+
213
381
214
382
# random matrix generation (David)
215
383
# swap rows, columns (David)
@@ -218,9 +386,10 @@ cdef class Matrix_nmod_dense(Matrix_dense):
218
386
219
387
220
388
221
- # transpose (Edgar)
222
- # nmod_mat_pow (Edgar)
223
- # nmod_mat_trace (Edgar)
224
- # rank and det (only primes) (Egar)
225
- # right_kernel_matrix (nmod_mat_nullspace) (Edgar)
226
- # row reduction (nmod_mat_rref) (Edgar)
389
+ # transpose (Edgar) x
390
+ # nmod_mat_pow (Edgar) x
391
+ # nmod_mat_trace (Edgar) X
392
+ # rank and det (only primes) (Edgar) X
393
+ # right_kernel_matrix (nmod_mat_nullspace) (Edgar) x
394
+ # row reduction (nmod_mat_rref) (Edgar) ~
395
+ # richcmp ~
0 commit comments