1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
#![doc="Traits for matrices
"]





// Standard library imports
use std::cmp;
use num::{Float};

// external imports
use num::traits::{Signed};

// local imports
use algebra::structure::{MagmaBase, CommutativeMonoidAddPartial,
        CommutativeMonoidMulPartial,
        FieldPartial};
use matrix::matrix::Matrix;
use error::SRError;


// Reexports
pub use matrix::eo::eo_traits::{ERO, ECO};
pub use matrix::update::traits::{
    InPlaceUpdates, CopyUpdates};
pub use matrix::transpose::traits::{Transpose, Frame};
pub use matrix::extract::traits::{Extraction};


#[doc="Defines the features which all matrix types must implement.
This API focuses only on the shape of the matrix.
"] 
pub trait Shape<T:MagmaBase> {
    
    /// Returns the number of rows
    fn num_rows(&self) -> usize;

    /// Returns the number of columns
    fn num_cols(&self) -> usize;


    /// Returns the size in an (r, c) tuple
    fn size (&self)-> (usize, usize);
 
 
     /// Returns the number of cells in matrix
    fn num_cells(&self)->usize;

    /// Indicates if the matrix is a row vector
    fn is_row(&self) -> bool {
        self.num_rows() == 1
    }

    /// Indicates if the matrix is a column vector
    fn is_col(&self) -> bool {
        self.num_cols() == 1
    }

    /// Indicates if the matrix is a scalar actually
    fn is_scalar(&self) -> bool {
        self.num_cells() == 1
    }

    /// Indicates if the matrix is a vector
    fn is_vector(&self) -> bool {
        (self.num_rows() == 1) ^ (self.num_cols() == 1)
    } 

    /// Indicates if the matrix is empty
    fn is_empty(&self) -> bool {
        self.num_rows() * self.num_cols() == 0
    }

    /// Indicates if the matrix is square
    fn is_square(&self) -> bool {
        self.num_rows() == self.num_cols()
    }


    /// Gets an element by its row and column number
    /// Assumes that the caller knows that (r, c) indices are proper
    unsafe fn get_unchecked(&self, r : usize, c : usize) -> T;

    /// Gets an element by its row and column number
    /// Returns data if array bounds are followed.
    fn get(&self, r : usize, c : usize) -> Option<T>{
        if (r >= self.num_rows()) || (c >= self.num_cols()) {
            return None;
        }
        Some(unsafe { self.get_unchecked(r, c) } )
    }


    /// Sets an element in the view
    fn set(&mut self, r : usize, c : usize, value : T);


    /// Converts an index to cell address (row, column)
    #[inline]
    fn index_to_cell(&self, index : usize) -> (usize, usize){
        debug_assert!(index < self.num_cells());
        let rows = self.num_rows();
        let c = index / rows;
        let r = index - c*rows;
        (r, c)
    }

    /// Converts a cell address to an index (r, c) to index
    #[inline]
    fn cell_to_index(&self, r : usize,  c: usize) -> usize{
        let rows = self.num_rows();
        debug_assert!(r < rows);
        debug_assert!(c < self.num_cols());
        c * rows + r
    }

    /// Returns the minimum of rows and columns
    fn smaller_dim(&self) -> usize {
        cmp::min(self.num_rows(), self.num_cols())
    }

    /// Returns the larger of rows and columns
    fn larger_dim(&self)-> usize {
        cmp::max(self.num_rows(), self.num_cols())
    }

}


#[doc=" Defines the low level interface to the internal
memory buffer of a matrix implementation.  Use it with
caution. 
"]
pub trait MatrixBuffer<T:MagmaBase> {

    /// Returns a constant pointer to matrix's buffer
    fn as_ptr(&self)-> *const T;

    /// Returns a mutable pointer to matrix's buffer
    fn as_mut_ptr(&mut self) -> *mut T;


    /// Maps a cell index to actual offset in buffer
    fn cell_to_offset(&self, r : usize,  c: usize)-> isize;

    /// Returns the offset of the first cell in the buffer
    #[inline]
    fn start_offset(&self) -> isize {
        0
    }
}

#[doc="A matrix structure whose storage is in terms
of columns with a fixed number of storage elements
per column given by its stride. 
"]
pub trait Strided {

    /// Returns the number of actual memory elements 
    /// per column
    fn stride (&self)->usize;


}


/// Defines a set of basic methods implemented by matrices of numbers
pub trait NumberMatrix<T:CommutativeMonoidAddPartial+CommutativeMonoidMulPartial> : Shape<T> + MatrixBuffer<T>{
    
    /// Returns if the matrix is an identity matrix
    fn is_identity(&self) -> bool;

    /// Returns if the matrix is a diagonal matrix
    fn is_diagonal(&self) -> bool;

    /// Returns if the matrix is lower triangular 
    fn is_lt(&self) -> bool;

    /// Returns if the matrix is upper triangular 
    fn is_ut(&self) -> bool;


    /// Returns if the matrix is triangular
    fn is_triangular(&self) -> bool{
        self.is_lt() || self.is_ut()
    }

    /// Returns if the matrix is symmetric
    fn is_symmetric(&self) -> bool;

    /// Returns the trace of the matrix
    fn trace(&self) -> T ;
}

/// A matrix which is both a number matrix and is strided.
pub trait StridedNumberMatrix<T:FieldPartial> : 
NumberMatrix<T>+Strided{

}

#[doc=" These methods help in run time to query
about the properties of the type which is implementing
the trait. 

As an example, this API helps us decide if an object
of type Shape is a real matrix or a view 
extracted from a matrix. 

An implementing type needs to implement
only few of the methods below. For rest, it can
simply use the default implementation.

"]
pub trait Introspection {

    /// Indicates if the matrix is a view
    fn is_matrix_view_type(&self) -> bool {
        false
    }

    /// Indicates if the matrix is a standard matrix
    fn is_standard_matrix_type(&self) -> bool {
        false
    }

    /// Indicates if the matrix is a triangular matrix
    fn is_triangular_matrix_type(&self) -> bool {
        false
    }
}


/// Matrix conversion API
pub trait Conversion<T:MagmaBase> : Shape<T> {
    /// Converts the matrix to vector from standard library
    fn to_std_vec(&self) -> Vec<T>;

    /// Converts the matrix to a scalar 
    fn to_scalar(&self) -> T {
        if !self.is_scalar() {
            panic! (SRError::DimensionsMismatch.to_string());
        }
        unsafe { self.get_unchecked(0, 0)}
    }
}



/// Matrix min-max API
pub trait MinMax<T:CommutativeMonoidAddPartial+PartialOrd> : Shape<T> {

    /// Returns a column vector consisting of maximum over each row
    fn max_row_wise(&self) -> Matrix<T>;

    /// Returns a column vector consisting of minimum over each row
    fn min_row_wise(&self) -> Matrix<T>;

    /// Returns a row vector consisting of maximum over each column
    fn max_col_wise(&self) -> Matrix<T>;

    /// Returns a row vector consisting of minimum over each column
    fn min_col_wise(&self) -> Matrix<T>;
}


/// Matrix min-max with absolute values API
pub trait MinMaxAbs<T:Signed> : Shape<T> {

    // Returns the absolute minimum scalar value
    fn min_abs_scalar(&self) -> (T, usize, usize);

    // Returns the maximum scalar value
    fn max_abs_scalar(&self) -> (T, usize, usize);


}

#[doc="Features for searching within the matrix
"]
pub trait Search<T:MagmaBase+Signed+PartialOrd> : Shape<T>+MatrixBuffer<T> + Strided{

    /// Returns the largest entry (by magnitude) in the row between
    /// [start, end) columns
    fn max_abs_scalar_in_row(&self, 
        row : usize, 
        start_col: usize, 
        end_col : usize)-> (T, usize){
        debug_assert!(row < self.num_rows());
        debug_assert!(end_col <= self.num_cols());
        let p = self.as_ptr();
        let stride = self.stride();
        let mut offset = start_col * stride + row;
        let mut result = unsafe{*p.offset(offset as isize)}.abs();
        let mut index  = 0;
        for i in 1..(end_col - start_col){
            offset += stride;
            let s = unsafe{*p.offset(offset as isize)}.abs();
            if s > result {
                index = i;
                result = s;
            }
        }
        (result, index + start_col)
    }


    /// Returns the largest entry (by magnitude) in the column between
    /// [start, end) rows
    fn max_abs_scalar_in_col(&self, 
        col : usize, 
        start_row: usize, 
        end_row : usize)-> (T, usize){
        debug_assert!(end_row <= self.num_rows());
        debug_assert!(col < self.num_cols());
        let p = self.as_ptr();
        let stride = self.stride();
        let mut offset = col * stride + start_row;
        let mut result = unsafe{*p.offset(offset as isize)}.abs();
        let mut index  = 0;
        for i in 1..(end_row - start_row){
            offset += 1;
            let s = unsafe{*p.offset(offset as isize)}.abs();
            if s > result {
                index = i;
                result = s;
            }
        }
        (result, index + start_row)
    }
}


/// A matrix of integers <T:Number+Int>
pub trait IntMatrix {

}


/// A matrix of floats T:Number+Float
pub trait FloatMatrix {

}


/// A matrix of signed integers T:Number+SignedInt
pub trait SignedMatrix {

}


/// A strided buffer matrix of floats
pub trait StridedFloatMatrix <T:FieldPartial+Float> 
    : StridedNumberMatrix<T> {

}