1
// ---------------------------------------------------------------------------
3
// - afnix:mth module - real matrix interface implementation -
4
// ---------------------------------------------------------------------------
5
// - This program is free software; you can redistribute it and/or modify -
6
// - it provided that this copyright notice is kept intact. -
8
// - This program is distributed in the hope that it will be useful, but -
9
// - without any warranty; without even the implied warranty of -
10
// - merchantability or fitness for a particular purpose. In no event shall -
11
// - the copyright holder be liable for any direct, indirect, incidental or -
12
// - special damages arising in any way out of the use of this software. -
13
// ---------------------------------------------------------------------------
14
// - copyright (c) 1999-2011 amaury darsch -
15
// ---------------------------------------------------------------------------
21
#include "Algebra.hpp"
22
#include "Boolean.hpp"
23
#include "QuarkZone.hpp"
24
#include "Exception.hpp"
28
// -------------------------------------------------------------------------
30
// -------------------------------------------------------------------------
32
// create a default matrix
39
// create a square matrix by size
41
Rmi::Rmi (const t_long size) {
44
throw Exception ("size-error", "invalid real matrix size");
50
// create a matrix by size
52
Rmi::Rmi (const t_long rsiz, const t_long csiz) {
54
if ((rsiz < 0) || (csiz < 0)) {
55
throw Exception ("size-error", "invalid real matrix size");
63
void Rmi::clear (void) {
66
for (t_long i = 0; i < d_rsiz; i++) {
67
for (t_long j = 0; j < d_csiz; j++) {
78
// get the matrix row size
80
t_long Rmi::getrsiz (void) const {
83
t_long result = d_rsiz;
92
// get the matrix column size
94
t_long Rmi::getcsiz (void) const {
97
t_long result = d_csiz;
106
// return true if the matrix is square
108
bool Rmi::issquare (void) const {
111
bool result = (d_rsiz == d_csiz);
120
// compare two matrices by precision
122
bool Rmi::cmp (const Rmi& mx) const {
127
if ((d_rsiz != mx.d_rsiz) || (d_csiz != mx.d_csiz)) {
128
throw Exception ("matrix-error",
129
"incompatible matrix size with compare");
134
for (t_long i = 0; i < d_rsiz; i++) {
135
for (t_long j = 0; j < d_csiz; j++) {
136
t_real tij = get (i, j);
137
t_real mij = mx.get (i, j);
138
t_real dij = (mij < tij) ? mij - tij : tij - mij;
139
if (dij > Real::d_aeps) {
156
// compute the matrix norm
158
t_real Rmi::norm (void) const {
162
for (t_long i = 0; i < d_rsiz; i++) {
163
for (t_long j = 0; j < d_csiz; j++) {
164
t_real mij = get (i, j);
168
t_real result = Math::sqrt (sum);
177
// positive multiply a matrix with a vector
179
Rvi& Rmi::pmul (Rvi& r, const Rvi& x) const {
182
Algebra::mul (r, *this, x, 1.0);
191
// negative multiply a matrix with a vector
193
Rvi& Rmi::nmul (Rvi& r, const Rvi& x) const {
196
Algebra::mul (r, *this, x, -1.0);
205
// multiply a matrix with a vector and a scaling factor
207
Rvi& Rmi::smul (Rvi& r, const Rvi& x, const t_real s) const {
210
Algebra::mul (r, *this, x, s);
219
// -------------------------------------------------------------------------
220
// - object section -
221
// -------------------------------------------------------------------------
224
static const long QUARK_ZONE_LENGTH = 9;
225
static QuarkZone zone (QUARK_ZONE_LENGTH);
227
// the rmi supported quarks
228
static const long QUARK_QEQ = zone.intern ("?=");
229
static const long QUARK_SET = zone.intern ("set");
230
static const long QUARK_GET = zone.intern ("get");
231
static const long QUARK_NORM = zone.intern ("norm");
232
static const long QUARK_CLEAR = zone.intern ("clear");
233
static const long QUARK_TORSO = zone.intern ("to-row-sparse");
234
static const long QUARK_GETCFM = zone.intern ("get-cofactor");
235
static const long QUARK_GETRSIZ = zone.intern ("get-row-size");
236
static const long QUARK_GETCSIZ = zone.intern ("get-col-size");
238
// return true if the given quark is defined
240
bool Rmi::isquark (const long quark, const bool hflg) const {
242
if (zone.exists (quark) == true){
246
bool result = hflg ? Object::isquark (quark, hflg) : false;
251
// apply this object with a set of arguments and a quark
253
Object* Rmi::apply (Runnable* robj, Nameset* nset, const long quark,
255
// get the number of arguments
256
long argc = (argv == nilp) ? 0 : argv->length ();
258
// dispatch 0 argument
260
if (quark == QUARK_NORM) return new Real (norm ());
261
if (quark == QUARK_GETRSIZ) return new Integer (getrsiz ());
262
if (quark == QUARK_GETCSIZ) return new Integer (getcsiz ());
263
if (quark == QUARK_CLEAR) {
269
// dispatch 1 argument
271
if (quark == QUARK_QEQ) {
272
Object* obj = argv->get (0);
273
Rmi* rmo = dynamic_cast <Rmi*> (obj);
275
throw Exception ("type-error", "invalid object for compare",
278
return new Boolean (cmp (*rmo));
280
if (quark == QUARK_TORSO) {
281
t_long row = argv->getlong (0);
285
// dispatch 2 argument
287
if (quark == QUARK_GET) {
288
t_long lpos = argv->getlong (0);
289
t_long cpos = argv->getlong (1);
290
return new Real (get (lpos, cpos));
292
if (quark == QUARK_GETCFM) {
293
t_long row = argv->getlong (0);
294
t_long col = argv->getlong (1);
295
return getcfm (row, col);
298
// dispatch 3 arguments
300
if (quark == QUARK_SET) {
301
t_long lpos = argv->getlong (0);
302
t_long cpos = argv->getlong (1);
303
t_real val = argv->getreal (2);
304
set (lpos, cpos, val);
309
return Object::apply (robj, nset, quark, argv);