Changeset 3111:b790f0e707f0


Ignore:
Timestamp:
02/21/07 02:04:30 (6 years ago)
Author:
William Stein <wstein@…>
Branch:
default
Message:

snapshot -- first version of sparse rational matrices.

Files:
1 added
6 edited
2 moved

Legend:

Unmodified
Added
Removed
  • sage/matrix/matrix_integer_dense.pyx

    r3110 r3111  
    6868cdef Linbox_integer_dense linbox 
    6969linbox = Linbox_integer_dense() 
    70  
    71 #import sage.misc.misc 
    72 #USE_LINBOX_POLY = not sage.misc.misc.is_64bit() 
    7370 
    7471USE_LINBOX_POLY = True 
     
    553550    cdef sage.structure.element.Matrix _matrix_times_matrix_c_impl(self, sage.structure.element.Matrix right): 
    554551         
    555         return self._multiply_classical(right) 
    556      
    557         # NOTE -- the multimodular matrix multiply implementation 
    558         # breaks on 64-bit machines; e..g, the following doctests 
    559         # *all* fail if multimodular matrix multiply is enabled 
    560         # on sage.math.washington.edu: 
    561          
    562         #sage -t  devel/sage-main/sage/modular/modsym/modsym.py 
    563         #sage -t  devel/sage-main/sage/modular/modsym/space.py 
    564         #sage -t  devel/sage-main/sage/modular/modsym/subspace.py 
    565         #sage -t  devel/sage-main/sage/modular/hecke/hecke_operator.py 
    566         #sage -t  devel/sage-main/sage/modular/hecke/module.py 
    567  
    568552        ############# 
    569553        # see the tune_multiplication function below. 
     
    571555        if n <= 20: 
    572556            return self._multiply_classical(right) 
    573         return self._multiply_multi_modular(right) 
    574 ##         a = self.height(); b = right.height() 
    575 ##         # waiting for multiply_multi_modular to get fixed, and not assume all matrix entries 
    576 ##         # are between 0 and prod - 1. 
    577 ##         if float(max(a,b)) / float(n) >= 0.70: 
    578 ##             return self._multiply_classical(right) 
    579 ##         else: 
    580 ##             return self._multiply_multi_modular(right) 
     557        a = self.height(); b = right.height() 
     558        if float(max(a,b)) / float(n) >= 0.70: 
     559            return self._multiply_classical(right) 
     560        else: 
     561            return self._multiply_multi_modular(right) 
    581562 
    582563    cdef ModuleElement _lmul_c_impl(self, RingElement right): 
  • sage/matrix/matrix_modn_sparse.pyx

    r3109 r3111  
    145145            coerce -- ignored 
    146146        """ 
    147         cdef int s, y, z, p 
     147        cdef int s, z, p 
    148148        cdef Py_ssize_t i, j, k 
    149149         
    150         cdef object seq 
    151150        cdef void** X 
    152151 
     
    160159            R = self._base_ring 
    161160            for ij, x in entries.iteritems(): 
    162                 y = x 
    163                 z = R(y) 
     161                z = R(x) 
    164162                if z != 0: 
    165163                    i, j = ij  # nothing better to do since this is user input, which may be bogus. 
     
    178176            for i from 0 <= i < self._nrows: 
    179177                for  j from 0 <= j < self._ncols: 
    180                     set_entry(&self.rows[i], j, R(<object>X[k])) 
     178                    z = R(<object>X[k]) 
     179                    if z != 0: 
     180                        set_entry(&self.rows[i], j, z) 
    181181                    k = k + 1 
    182182        else: 
  • sage/matrix/matrix_rational_sparse.pyx.orig

    r3092 r3111  
    7979 
    8080START_PRIME = 20011  # used for multi-modular algorithms 
    81  
    82 cdef class Vector_mpq 
    83  
    84 cdef void Vector_mpq_rescale(Vector_mpq w, mpq_t x): 
    85     scale_mpq_vector(&w.v, x) 
    86      
    87 cdef class Vector_mpq: 
    88     """ 
    89     Vector_mpq -- a sparse vector of GMP rationals.  This is a Python 
    90     extension type that wraps the C implementation of sparse vectors 
    91     modulo a small prime. 
    92     """ 
    93     cdef mpq_vector v 
    94      
    95     def __init__(self, int degree, int num_nonzero=0, entries=[], sort=True): 
    96         cdef int i 
    97         init_mpq_vector(&self.v, degree, num_nonzero) 
    98         if entries != []: 
    99             if len(entries) != num_nonzero: 
    100                 raise ValueError, "length of entries (=%s) must equal num_nonzero (=%s)"%(len(entries), num_nonzero) 
    101             if sort: 
    102                 entries = list(entries) # copy so as not to modify passed in list 
    103                 entries.sort() 
    104             for i from 0 <= i < num_nonzero: 
    105                 s = str(entries[i][1]) 
    106                 mpq_set_str(self.v.entries[i], s, 0) 
    107                 self.v.positions[i] = entries[i][0] 
    108  
    109     def __dealloc__(self): 
    110         clear_mpq_vector(&self.v) 
    111  
    112     def __getitem__(self, int n): 
    113         cdef mpq_t x 
    114         cdef sage.rings.rational.Rational a 
    115         mpq_init(x) 
    116         mpq_vector_get_entry(&x, &self.v, n) 
    117         a = sage.rings.rational.Rational() 
    118         a.set_from_mpq(x) 
    119         mpq_clear(x) 
    120         return a 
    121  
    122     def cmp(self, Vector_mpq other): 
    123         return mpq_vector_cmp(&self.v, &other.v) 
    124  
    125     def __richcmp__(Vector_mpq self, x, int op): 
    126         if not isinstance(x, Vector_mpq): 
    127             return -1 
    128         cdef int n 
    129         n = self.cmp(x) 
    130         if op == 0: 
    131             return bool(n < 0) 
    132         elif op == 1: 
    133             return bool(n <= 0) 
    134         elif op == 2: 
    135             return bool(n == 0) 
    136         elif op == 3: 
    137             return bool(n != 0) 
    138         elif op == 4: 
    139             return bool(n > 0) 
    140         elif op == 5: 
    141             return bool(n >= 0) 
    142  
    143     def __setitem__(self, int n, x): 
    144         cdef object s 
    145         s = str(x) 
    146         mpq_vector_set_entry_str(&self.v, n, s) 
    147  
    148     def __repr__(self): 
    149         return str(list(self)) 
    150  
    151     def degree(self): 
    152         return self.v.degree 
    153  
    154     def num_nonzero(self): 
    155         return self.v.num_nonzero 
    156  
    157     def list(self): 
    158         return mpq_vector_to_list(&self.v) 
    159  
    160     cdef void rescale(self, mpq_t x): 
    161         scale_mpq_vector(&self.v, x) 
    162  
    163     def __add__(Vector_mpq self, Vector_mpq other): 
    164         cdef mpq_vector z1, *z2 
    165         cdef Vector_mpq w 
    166         cdef mpq_t ONE 
    167         mpq_init(ONE) 
    168         mpq_set_si(ONE,1,1) 
    169  
    170         add_mpq_vector_init(&z1, &self.v, &other.v, ONE) 
    171         mpq_clear(ONE) 
    172         w = Vector_mpq(self.v.degree) 
    173         z2 = &(w.v) 
    174         clear_mpq_vector(z2)   # free memory wasted on allocated w 
    175         z2.entries = z1.entries       
    176         z2.positions = z1.positions 
    177         z2.num_nonzero = z1.num_nonzero 
    178         # at this point we do *not* free z1, since it is referenced by w. 
    179         return w 
    180  
    181     def __sub__(Vector_mpq self, Vector_mpq other): 
    182         return self + other*(-1) 
    183  
    184     def copy(self): 
    185         cdef int i 
    186         cdef Vector_mpq w 
    187         w = Vector_mpq(self.v.degree, self.v.num_nonzero) 
    188         for i from 0 <= i < self.v.num_nonzero: 
    189             mpq_set(w.v.entries[i], self.v.entries[i]) 
    190             w.v.positions[i] = self.v.positions[i] 
    191         return w 
    192  
    193     def __mul__(x, y): 
    194         if isinstance(x, Vector_mpq): 
    195             self = x 
    196             other = y 
    197         elif isinstance(y, Vector_mpq): 
    198             self = y 
    199             other = x 
    200         else: 
    201             raise TypeError, "Invalid types." 
    202         cdef object s, z 
    203         cdef mpq_t t 
    204         z = self.copy() 
    205         mpq_init(t) 
    206         s = str(other) 
    207         mpq_set_str(t, s, 0) 
    208         Vector_mpq_rescale(z, t) 
    209         mpq_clear(t) 
    210         return z 
    211  
    212     def randomize(self, int sparcity, bound=3): 
    213         """ 
    214         randomize(self, int sparcity, exact=False): 
    215          
    216         The sparcity is a bound on the number of nonzeros per row. 
    217         """ 
    218         cdef int i 
    219         for i from 0 <= i < sparcity: 
    220             self[random.randrange(self.v.degree)] = random.randrange(1,bound) 
    221  
    22281     
    22382############################################################# 
     
    23291        cdef int i 
    23392        self.rows = <mpq_vector*> sage_malloc(nrows*sizeof(mpq_vector)) 
     93        # TODO: check worked  -- bug  
    23494        self.is_init = init 
    23595        if self.is_init: 
  • sage/matrix/matrix_space.py

    r3109 r3111  
    4040 
    4141import matrix_rational_dense 
    42 ##import matrix_rational_sparse 
     42import matrix_rational_sparse 
    4343 
    4444## import matrix_cyclo_dense 
     
    428428                return matrix_modn_sparse.Matrix_modn_sparse 
    429429            # the default 
     430            elif sage.rings.rational_field.is_RationalField(R): 
     431                return matrix_rational_sparse.Matrix_rational_sparse 
    430432            return matrix_generic_sparse.Matrix_generic_sparse 
    431433             
  • sage/modules/vector_rational_sparse.pyx

    r3092 r3111  
    11include 'vector_rational_sparse_c.pxi' 
     2 
     3 
     4cdef class Vector_mpq 
     5 
     6cdef void Vector_mpq_rescale(Vector_mpq w, mpq_t x): 
     7    scale_mpq_vector(&w.v, x) 
     8     
     9cdef class Vector_mpq: 
     10    """ 
     11    Vector_mpq -- a sparse vector of GMP rationals.  This is a Python 
     12    extension type that wraps the C implementation of sparse vectors 
     13    modulo a small prime. 
     14    """ 
     15    cdef mpq_vector v 
     16     
     17    def __init__(self, int degree, int num_nonzero=0, entries=[], sort=True): 
     18        cdef int i 
     19        init_mpq_vector(&self.v, degree, num_nonzero) 
     20        if entries != []: 
     21            if len(entries) != num_nonzero: 
     22                raise ValueError, "length of entries (=%s) must equal num_nonzero (=%s)"%(len(entries), num_nonzero) 
     23            if sort: 
     24                entries = list(entries) # copy so as not to modify passed in list 
     25                entries.sort() 
     26            for i from 0 <= i < num_nonzero: 
     27                s = str(entries[i][1]) 
     28                mpq_set_str(self.v.entries[i], s, 0) 
     29                self.v.positions[i] = entries[i][0] 
     30 
     31    def __dealloc__(self): 
     32        clear_mpq_vector(&self.v) 
     33 
     34    def __getitem__(self, int n): 
     35        cdef mpq_t x 
     36        cdef sage.rings.rational.Rational a 
     37        mpq_init(x) 
     38        mpq_vector_get_entry(&x, &self.v, n) 
     39        a = sage.rings.rational.Rational() 
     40        a.set_from_mpq(x) 
     41        mpq_clear(x) 
     42        return a 
     43 
     44    def cmp(self, Vector_mpq other): 
     45        return mpq_vector_cmp(&self.v, &other.v) 
     46 
     47    def __richcmp__(Vector_mpq self, x, int op): 
     48        if not isinstance(x, Vector_mpq): 
     49            return -1 
     50        cdef int n 
     51        n = self.cmp(x) 
     52        if op == 0: 
     53            return bool(n < 0) 
     54        elif op == 1: 
     55            return bool(n <= 0) 
     56        elif op == 2: 
     57            return bool(n == 0) 
     58        elif op == 3: 
     59            return bool(n != 0) 
     60        elif op == 4: 
     61            return bool(n > 0) 
     62        elif op == 5: 
     63            return bool(n >= 0) 
     64 
     65    def __setitem__(self, int n, x): 
     66        cdef object s 
     67        s = str(x) 
     68        mpq_vector_set_entry_str(&self.v, n, s) 
     69 
     70    def __repr__(self): 
     71        return str(list(self)) 
     72 
     73    def degree(self): 
     74        return self.v.degree 
     75 
     76    def num_nonzero(self): 
     77        return self.v.num_nonzero 
     78 
     79    def list(self): 
     80        return mpq_vector_to_list(&self.v) 
     81 
     82    cdef void rescale(self, mpq_t x): 
     83        scale_mpq_vector(&self.v, x) 
     84 
     85    def __add__(Vector_mpq self, Vector_mpq other): 
     86        cdef mpq_vector z1, *z2 
     87        cdef Vector_mpq w 
     88        cdef mpq_t ONE 
     89        mpq_init(ONE) 
     90        mpq_set_si(ONE,1,1) 
     91 
     92        add_mpq_vector_init(&z1, &self.v, &other.v, ONE) 
     93        mpq_clear(ONE) 
     94        w = Vector_mpq(self.v.degree) 
     95        z2 = &(w.v) 
     96        clear_mpq_vector(z2)   # free memory wasted on allocated w 
     97        z2.entries = z1.entries       
     98        z2.positions = z1.positions 
     99        z2.num_nonzero = z1.num_nonzero 
     100        # at this point we do *not* free z1, since it is referenced by w. 
     101        return w 
     102 
     103    def __sub__(Vector_mpq self, Vector_mpq other): 
     104        return self + other*(-1) 
     105 
     106    def copy(self): 
     107        cdef int i 
     108        cdef Vector_mpq w 
     109        w = Vector_mpq(self.v.degree, self.v.num_nonzero) 
     110        for i from 0 <= i < self.v.num_nonzero: 
     111            mpq_set(w.v.entries[i], self.v.entries[i]) 
     112            w.v.positions[i] = self.v.positions[i] 
     113        return w 
     114 
     115    def __mul__(x, y): 
     116        if isinstance(x, Vector_mpq): 
     117            self = x 
     118            other = y 
     119        elif isinstance(y, Vector_mpq): 
     120            self = y 
     121            other = x 
     122        else: 
     123            raise TypeError, "Invalid types." 
     124        cdef object s, z 
     125        cdef mpq_t t 
     126        z = self.copy() 
     127        mpq_init(t) 
     128        s = str(other) 
     129        mpq_set_str(t, s, 0) 
     130        Vector_mpq_rescale(z, t) 
     131        mpq_clear(t) 
     132        return z 
     133 
     134    def randomize(self, int sparcity, bound=3): 
     135        """ 
     136        randomize(self, int sparcity, exact=False): 
     137         
     138        The sparcity is a bound on the number of nonzeros per row. 
     139        """ 
     140        cdef int i 
     141        for i from 0 <= i < sparcity: 
     142            self[random.randrange(self.v.degree)] = random.randrange(1,bound) 
     143 
  • sage/modules/vector_rational_sparse_c.pxi

    r3092 r3111  
    55############################################################# 
    66 
    7 include "../ext/cdefs.pxi" 
    8  
    9 cdef struct mpq_vector: 
    10     mpq_t *entries      # array of nonzero entries 
    11     int   *positions    # positions of those nonzero entries, starting at 0 
    12     int    degree       # the degree of this sparse vector 
    13     int    num_nonzero  # the number of nonzero entries of this vector. 
    14  
    15 cdef int allocate_mpq_vector(mpq_vector* v, int num_nonzero) except -1: 
     7include 'vector_rational_sparse_h.pxi' 
     8 
     9from sage.rings.rational cimport Rational 
     10 
     11cdef int allocate_mpq_vector(mpq_vector* v, Py_ssize_t num_nonzero) except -1: 
    1612    """ 
    1713    Allocate memory for a mpq_vector -- most user code won't call this. 
     
    2117    It does *not* clear the entries of v, if there are any. 
    2218    """ 
    23     cdef int i 
     19    cdef Py_ssize_t i 
    2420    v.entries = <mpq_t*>sage_malloc(num_nonzero*sizeof(mpq_t)) 
    25     if v.entries == <mpq_t*> 0: 
     21    if v.entries == NULL: 
    2622        raise MemoryError, "Error allocating memory" 
    2723    for i from 0 <= i < num_nonzero: 
    2824        mpq_init(v.entries[i]) 
    29     v.positions = <int*>sage_malloc(num_nonzero*sizeof(int)) 
    30     if v.positions == <int*> 0: 
     25    v.positions = <Py_ssize_t*>sage_malloc(num_nonzero*sizeof(Py_ssize_t)) 
     26    if v.positions == NULL: 
     27        for i from 0 <= i < num_nonzero: 
     28            mpq_clear(v.entries[i]) 
     29        sage_free(v.entries) 
     30        v.entries = NULL 
    3131        raise MemoryError, "Error allocating memory" 
    3232    return 0 
    3333 
    34 cdef int init_mpq_vector(mpq_vector* v, int degree, int num_nonzero) except -1: 
     34cdef int init_mpq_vector(mpq_vector* v, Py_ssize_t degree, Py_ssize_t num_nonzero) except -1: 
    3535    """ 
    3636    Initialize a mpq_vector -- most user code *will* call this. 
     
    4141 
    4242cdef void clear_mpq_vector(mpq_vector* v): 
    43     cdef int i 
     43    cdef Py_ssize_t i 
    4444    # Free all mpq objects allocated in creating v 
    4545    for i from 0 <= i < v.num_nonzero: 
     
    5252    sage_free(v.positions) 
    5353 
    54 cdef int mpq_binary_search0(mpq_t* v, int n, mpq_t x): 
     54cdef Py_ssize_t binary_search(Py_ssize_t* v, Py_ssize_t n, Py_ssize_t x, Py_ssize_t* ins): 
     55    """ 
     56    Find the position of the integer x in the array v, which has length n. 
     57    Returns -1 if x is not in the array v, and in this case ins is 
     58    set equal to the position where x should be inserted in order to 
     59    obtain an ordered array. 
     60    """ 
     61    if n == 0: 
     62        ins[0] = 0 
     63        return -1 
     64 
     65    cdef Py_ssize_t i, j, k 
     66    i = 0 
     67    j = n-1 
     68    while i<=j: 
     69        if i == j: 
     70            if v[i] == x: 
     71                ins[0] = i 
     72                return i 
     73            if v[i] < x: 
     74                ins[0] = i + 1 
     75            else: 
     76                ins[0] = i 
     77            return -1 
     78        k = (i+j)/2 
     79        if v[k] > x: 
     80            j = k-1 
     81        elif v[k] < x: 
     82            i = k+1 
     83        else:   # only possibility is that v[k] == x 
     84            ins[0] = k 
     85            return k 
     86    # end while 
     87    ins[0] = j+1 
     88    return -1 
     89 
     90cdef Py_ssize_t binary_search0(Py_ssize_t* v, Py_ssize_t n, Py_ssize_t x): 
     91    """ 
     92    Find the position of the int x in the array v, which has length n. 
     93    Returns -1 if x is not in the array v. 
     94    """ 
     95    if n == 0: 
     96        return -1 
     97 
     98    cdef Py_ssize_t i, j, k 
     99    i = 0 
     100    j = n-1 
     101    while i<=j: 
     102        if i == j: 
     103            if v[i] == x: 
     104                return i 
     105            return -1 
     106        k = (i+j)/2 
     107        if v[k] > x: 
     108            j = k-1 
     109        elif v[k] < x: 
     110            i = k+1 
     111        else:   # only possibility is that v[k] == x 
     112            return k 
     113    return -1 
     114 
     115cdef Py_ssize_t mpq_binary_search0(mpq_t* v, Py_ssize_t n, mpq_t x): 
    55116    """ 
    56117    Find the position of the rational x in the array v, which has length n. 
    57118    Returns -1 if x is not in the array v. 
    58119    """ 
    59     cdef int i, j, k, c 
     120    cdef Py_ssize_t i, j, k, c 
    60121    if n == 0: 
    61122        return -1 
     
    77138    return -1 
    78139 
    79 cdef int mpq_binary_search(mpq_t* v, int n, mpq_t x, int* ins): 
     140cdef Py_ssize_t mpq_binary_search(mpq_t* v, Py_ssize_t n, mpq_t x, Py_ssize_t* ins): 
    80141    """ 
    81142    Find the position of the integer x in the array v, which has length n. 
     
    89150       x -- mpq_t  (rational) 
    90151    OUTPUT: 
    91        position of x (as an int) 
     152       position of x (as an Py_ssize_t) 
    92153       ins -- (call be pointer), the insertion point if x is not found. 
    93154    """ 
    94     cdef int i, j, k, c 
     155    cdef Py_ssize_t i, j, k, c 
    95156    if n == 0: 
    96157        ins[0] = 0 
     
    122183    return -1 
    123184 
    124 cdef int mpq_vector_get_entry(mpq_t* ans, mpq_vector* v, int n) except -1: 
     185cdef int mpq_vector_get_entry(mpq_t* ans, mpq_vector* v, Py_ssize_t n) except -1: 
    125186    """ 
    126187    Returns the n-th entry of the sparse vector v.  This 
     
    132193    if n >= v.degree: 
    133194        raise IndexError, "Index must be between 0 and %s."%(v.degree - 1) 
    134     cdef int m 
     195    cdef Py_ssize_t m 
    135196    m = binary_search0(v.positions, v.num_nonzero, n) 
    136197    if m == -1: 
     
    145206    through the nonzero elements of x, in order. 
    146207    """ 
    147     cdef X 
    148     cdef sage.rings.rational.Rational a 
    149     cdef int i 
     208    cdef object X 
     209    cdef Rational a 
     210    cdef Py_ssize_t i 
    150211    X = [] 
    151212    for i from 0 <= i < v.num_nonzero: 
    152         a = sage.rings.rational.Rational() 
     213        a = Rational() 
    153214        a.set_from_mpq(v.entries[i]) 
    154215        X.append( (v.positions[i], a) ) 
     
    156217 
    157218 
    158 cdef int mpq_vector_set_entry(mpq_vector* v, int n, mpq_t x) except -1: 
     219cdef int mpq_vector_set_entry(mpq_vector* v, Py_ssize_t n, mpq_t x) except -1: 
    159220    """ 
    160221    Set the n-th component of the sparse vector v equal to x. 
     
    163224    if n >= v.degree or n < 0: 
    164225        raise IndexError, "Index must be between 0 and the degree minus 1." 
    165         return -1 
    166     cdef int i, m, ins 
    167     cdef int m2, ins2 
    168     cdef int *pos 
     226    cdef Py_ssize_t i, m, ins 
     227    cdef Py_ssize_t m2, ins2 
     228    cdef Py_ssize_t *pos 
    169229    cdef mpq_t *e 
    170230 
     
    232292cdef mpq_t mpq_set_tmp 
    233293mpq_init(mpq_set_tmp) 
    234 cdef int mpq_vector_set_entry_str(mpq_vector* v, int n, char *x_str) except -1: 
     294cdef int mpq_vector_set_entry_str(mpq_vector* v, Py_ssize_t n, char *x_str) except -1: 
    235295    """ 
    236296    Set the n-th component of the sparse vector v equal to x. 
     
    252312        raise ArithmeticError, "The vectors must have the same degree." 
    253313 
    254     cdef int nz, i, j, k, do_multiply 
     314    cdef Py_ssize_t nz, i, j, k, do_multiply 
    255315    cdef mpq_vector* z 
    256316    cdef mpq_t tmp 
     
    341401        init_mpq_vector(v, v.degree, 0) 
    342402        return 0 
    343     cdef int i 
     403    cdef Py_ssize_t i 
    344404    for i from 0 <= i < v.num_nonzero: 
    345405        # v.entries[i] = scalar * v.entries[i]  
     
    352412    elif v.degree > w.degree: 
    353413        return 1 
    354     cdef int i, c 
     414    cdef Py_ssize_t i 
     415    cdef int c 
    355416    for i from 0 <= i < v.num_nonzero: 
    356417        c = mpq_cmp(v.entries[i], w.entries[i]) 
  • setup.py

    r3104 r3111  
    195195                                 libraries = ['gmp']) 
    196196 
     197matrix_rational_sparse = Extension('sage.matrix.matrix_rational_sparse', 
     198                                  ['sage/matrix/matrix_rational_sparse.pyx'], 
     199                                 libraries = ['gmp']) 
     200 
    197201matrix_integer_dense = Extension('sage.matrix.matrix_integer_dense', 
    198202                                 ['sage/matrix/matrix_integer_dense.pyx'], 
     
    327331     matrix_integer_dense, 
    328332     matrix_rational_dense, 
     333     matrix_rational_sparse, 
    329334     matrix_integer_2x2, 
    330335##     matrix_integer_sparse,     
Note: See TracChangeset for help on using the changeset viewer.