NEURON
matop.c
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 
3 /**************************************************************************
4 **
5 ** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved.
6 **
7 ** Meschach Library
8 **
9 ** This Meschach Library is provided "as is" without any express
10 ** or implied warranty of any kind with respect to this software.
11 ** In particular the authors shall not be liable for any direct,
12 ** indirect, special, incidental or consequential damages arising
13 ** in any way from use of the software.
14 **
15 ** Everyone is granted permission to copy, modify and redistribute this
16 ** Meschach Library, provided:
17 ** 1. All copies contain this copyright notice.
18 ** 2. All modified copies shall carry a notice stating who
19 ** made the last modification and the date of such modification.
20 ** 3. No charge is made for this software or works derived from it.
21 ** This clause shall not be construed as constraining other software
22 ** distributed on the same medium as this software, nor is a
23 ** distribution fee considered a charge.
24 **
25 ***************************************************************************/
26 
27 
28 /* matop.c 1.3 11/25/87 */
29 
30 
31 #include <stdio.h>
32 #include "matrix.h"
33 
34 static char rcsid[] = "matop.c,v 1.1 1997/12/04 17:55:35 hines Exp";
35 
36 
37 /* m_add -- matrix addition -- may be in-situ */
38 MAT *m_add(mat1,mat2,out)
39 MAT *mat1,*mat2,*out;
40 {
41  u_int m,n,i;
42 
43  if ( mat1==(MAT *)NULL || mat2==(MAT *)NULL )
44  error(E_NULL,"m_add");
45  if ( mat1->m != mat2->m || mat1->n != mat2->n )
46  error(E_SIZES,"m_add");
47  if ( out==(MAT *)NULL || out->m != mat1->m || out->n != mat1->n )
48  out = m_resize(out,mat1->m,mat1->n);
49  m = mat1->m; n = mat1->n;
50  for ( i=0; i<m; i++ )
51  {
52  __add__(mat1->me[i],mat2->me[i],out->me[i],(int)n);
53  /**************************************************
54  for ( j=0; j<n; j++ )
55  out->me[i][j] = mat1->me[i][j]+mat2->me[i][j];
56  **************************************************/
57  }
58 
59  return (out);
60 }
61 
62 /* m_sub -- matrix subtraction -- may be in-situ */
63 MAT *m_sub(mat1,mat2,out)
64 MAT *mat1,*mat2,*out;
65 {
66  u_int m,n,i;
67 
68  if ( mat1==(MAT *)NULL || mat2==(MAT *)NULL )
69  error(E_NULL,"m_sub");
70  if ( mat1->m != mat2->m || mat1->n != mat2->n )
71  error(E_SIZES,"m_sub");
72  if ( out==(MAT *)NULL || out->m != mat1->m || out->n != mat1->n )
73  out = m_resize(out,mat1->m,mat1->n);
74  m = mat1->m; n = mat1->n;
75  for ( i=0; i<m; i++ )
76  {
77  __sub__(mat1->me[i],mat2->me[i],out->me[i],(int)n);
78  /**************************************************
79  for ( j=0; j<n; j++ )
80  out->me[i][j] = mat1->me[i][j]-mat2->me[i][j];
81  **************************************************/
82  }
83 
84  return (out);
85 }
86 
87 /* m_mlt -- matrix-matrix multiplication */
89 MAT *A,*B,*OUT;
90 {
91  u_int i, /* j, */ k, m, n, p;
92  Real **A_v, **B_v /*, *B_row, *OUT_row, sum, tmp */;
93 
94  if ( A==(MAT *)NULL || B==(MAT *)NULL )
95  error(E_NULL,"m_mlt");
96  if ( A->n != B->m )
97  error(E_SIZES,"m_mlt");
98  if ( A == OUT || B == OUT )
99  error(E_INSITU,"m_mlt");
100  m = A->m; n = A->n; p = B->n;
101  A_v = A->me; B_v = B->me;
102 
103  if ( OUT==(MAT *)NULL || OUT->m != A->m || OUT->n != B->n )
104  OUT = m_resize(OUT,A->m,B->n);
105 
106 /****************************************************************
107  for ( i=0; i<m; i++ )
108  for ( j=0; j<p; j++ )
109  {
110  sum = 0.0;
111  for ( k=0; k<n; k++ )
112  sum += A_v[i][k]*B_v[k][j];
113  OUT->me[i][j] = sum;
114  }
115 ****************************************************************/
116  m_zero(OUT);
117  for ( i=0; i<m; i++ )
118  for ( k=0; k<n; k++ )
119  {
120  if ( A_v[i][k] != 0.0 )
121  __mltadd__(OUT->me[i],B_v[k],A_v[i][k],(int)p);
122  /**************************************************
123  B_row = B_v[k]; OUT_row = OUT->me[i];
124  for ( j=0; j<p; j++ )
125  (*OUT_row++) += tmp*(*B_row++);
126  **************************************************/
127  }
128 
129  return OUT;
130 }
131 
132 /* mmtr_mlt -- matrix-matrix transposed multiplication
133  -- A.B^T is returned, and stored in OUT */
135 MAT *A, *B, *OUT;
136 {
137  int i, j, limit;
138  /* Real *A_row, *B_row, sum; */
139 
140  if ( ! A || ! B )
141  error(E_NULL,"mmtr_mlt");
142  if ( A == OUT || B == OUT )
143  error(E_INSITU,"mmtr_mlt");
144  if ( A->n != B->n )
145  error(E_SIZES,"mmtr_mlt");
146  if ( ! OUT || OUT->m != A->m || OUT->n != B->m )
147  OUT = m_resize(OUT,A->m,B->m);
148 
149  limit = A->n;
150  for ( i = 0; i < A->m; i++ )
151  for ( j = 0; j < B->m; j++ )
152  {
153  OUT->me[i][j] = __ip__(A->me[i],B->me[j],(int)limit);
154  /**************************************************
155  sum = 0.0;
156  A_row = A->me[i];
157  B_row = B->me[j];
158  for ( k = 0; k < limit; k++ )
159  sum += (*A_row++)*(*B_row++);
160  OUT->me[i][j] = sum;
161  **************************************************/
162  }
163 
164  return OUT;
165 }
166 
167 /* mtrm_mlt -- matrix transposed-matrix multiplication
168  -- A^T.B is returned, result stored in OUT */
170 MAT *A, *B, *OUT;
171 {
172  int i, k, limit;
173  /* Real *B_row, *OUT_row, multiplier; */
174 
175  if ( ! A || ! B )
176  error(E_NULL,"mmtr_mlt");
177  if ( A == OUT || B == OUT )
178  error(E_INSITU,"mtrm_mlt");
179  if ( A->m != B->m )
180  error(E_SIZES,"mmtr_mlt");
181  if ( ! OUT || OUT->m != A->n || OUT->n != B->n )
182  OUT = m_resize(OUT,A->n,B->n);
183 
184  limit = B->n;
185  m_zero(OUT);
186  for ( k = 0; k < A->m; k++ )
187  for ( i = 0; i < A->n; i++ )
188  {
189  if ( A->me[k][i] != 0.0 )
190  __mltadd__(OUT->me[i],B->me[k],A->me[k][i],(int)limit);
191  /**************************************************
192  multiplier = A->me[k][i];
193  OUT_row = OUT->me[i];
194  B_row = B->me[k];
195  for ( j = 0; j < limit; j++ )
196  *(OUT_row++) += multiplier*(*B_row++);
197  **************************************************/
198  }
199 
200  return OUT;
201 }
202 
203 /* mv_mlt -- matrix-vector multiplication
204  -- Note: b is treated as a column vector */
205 VEC *mv_mlt(A,b,out)
206 MAT *A;
207 VEC *b,*out;
208 {
209  u_int i, m, n;
210  Real **A_v, *b_v /*, *A_row */;
211  /* register Real sum; */
212 
213  if ( A==(MAT *)NULL || b==(VEC *)NULL )
214  error(E_NULL,"mv_mlt");
215  if ( A->n != b->dim )
216  error(E_SIZES,"mv_mlt");
217  if ( b == out )
218  error(E_INSITU,"mv_mlt");
219  if ( out == (VEC *)NULL || out->dim != A->m )
220  out = v_resize(out,A->m);
221 
222  m = A->m; n = A->n;
223  A_v = A->me; b_v = b->ve;
224  for ( i=0; i<m; i++ )
225  {
226  /* for ( j=0; j<n; j++ )
227  sum += A_v[i][j]*b_v[j]; */
228  out->ve[i] = __ip__(A_v[i],b_v,(int)n);
229  /**************************************************
230  A_row = A_v[i]; b_v = b->ve;
231  for ( j=0; j<n; j++ )
232  sum += (*A_row++)*(*b_v++);
233  out->ve[i] = sum;
234  **************************************************/
235  }
236 
237  return out;
238 }
239 
240 /* sm_mlt -- scalar-matrix multiply -- may be in-situ */
241 MAT *sm_mlt(scalar,matrix,out)
242 double scalar;
243 MAT *matrix,*out;
244 {
245  u_int m,n,i;
246 
247  if ( matrix==(MAT *)NULL )
248  error(E_NULL,"sm_mlt");
249  if ( out==(MAT *)NULL || out->m != matrix->m || out->n != matrix->n )
250  out = m_resize(out,matrix->m,matrix->n);
251  m = matrix->m; n = matrix->n;
252  for ( i=0; i<m; i++ )
253  __smlt__(matrix->me[i],(double)scalar,out->me[i],(int)n);
254  /**************************************************
255  for ( j=0; j<n; j++ )
256  out->me[i][j] = scalar*matrix->me[i][j];
257  **************************************************/
258  return (out);
259 }
260 
261 /* vm_mlt -- vector-matrix multiplication
262  -- Note: b is treated as a row vector */
263 VEC *vm_mlt(A,b,out)
264 MAT *A;
265 VEC *b,*out;
266 {
267  u_int j,m,n;
268  /* Real sum,**A_v,*b_v; */
269 
270  if ( A==(MAT *)NULL || b==(VEC *)NULL )
271  error(E_NULL,"vm_mlt");
272  if ( A->m != b->dim )
273  error(E_SIZES,"vm_mlt");
274  if ( b == out )
275  error(E_INSITU,"vm_mlt");
276  if ( out == (VEC *)NULL || out->dim != A->n )
277  out = v_resize(out,A->n);
278 
279  m = A->m; n = A->n;
280 
281  v_zero(out);
282  for ( j = 0; j < m; j++ )
283  if ( b->ve[j] != 0.0 )
284  __mltadd__(out->ve,A->me[j],b->ve[j],(int)n);
285  /**************************************************
286  A_v = A->me; b_v = b->ve;
287  for ( j=0; j<n; j++ )
288  {
289  sum = 0.0;
290  for ( i=0; i<m; i++ )
291  sum += b_v[i]*A_v[i][j];
292  out->ve[j] = sum;
293  }
294  **************************************************/
295 
296  return out;
297 }
298 
299 /* m_transp -- transpose matrix */
300 MAT *m_transp(in,out)
301 MAT *in, *out;
302 {
303  int i, j;
304  int in_situ;
305  Real tmp;
306 
307  if ( in == (MAT *)NULL )
308  error(E_NULL,"m_transp");
309  if ( in == out && in->n != in->m )
310  error(E_INSITU2,"m_transp");
311  in_situ = ( in == out );
312  if ( out == (MAT *)NULL || out->m != in->n || out->n != in->m )
313  out = m_resize(out,in->n,in->m);
314 
315  if ( ! in_situ )
316  for ( i = 0; i < in->m; i++ )
317  for ( j = 0; j < in->n; j++ )
318  out->me[j][i] = in->me[i][j];
319  else
320  for ( i = 1; i < in->m; i++ )
321  for ( j = 0; j < i; j++ )
322  { tmp = in->me[i][j];
323  in->me[i][j] = in->me[j][i];
324  in->me[j][i] = tmp;
325  }
326 
327  return out;
328 }
329 
330 /* swap_rows -- swaps rows i and j of matrix A upto column lim */
331 MAT *swap_rows(A,i,j,lo,hi)
332 MAT *A;
333 int i, j, lo, hi;
334 {
335  int k;
336  Real **A_me, tmp;
337 
338  if ( ! A )
339  error(E_NULL,"swap_rows");
340  if ( i < 0 || j < 0 || i >= A->m || j >= A->m )
341  error(E_SIZES,"swap_rows");
342  lo = max(0,lo);
343  hi = min(hi,A->n-1);
344  A_me = A->me;
345 
346  for ( k = lo; k <= hi; k++ )
347  {
348  tmp = A_me[k][i];
349  A_me[k][i] = A_me[k][j];
350  A_me[k][j] = tmp;
351  }
352  return A;
353 }
354 
355 /* swap_cols -- swap columns i and j of matrix A upto row lim */
356 MAT *swap_cols(A,i,j,lo,hi)
357 MAT *A;
358 int i, j, lo, hi;
359 {
360  int k;
361  Real **A_me, tmp;
362 
363  if ( ! A )
364  error(E_NULL,"swap_cols");
365  if ( i < 0 || j < 0 || i >= A->n || j >= A->n )
366  error(E_SIZES,"swap_cols");
367  lo = max(0,lo);
368  hi = min(hi,A->m-1);
369  A_me = A->me;
370 
371  for ( k = lo; k <= hi; k++ )
372  {
373  tmp = A_me[i][k];
374  A_me[i][k] = A_me[j][k];
375  A_me[j][k] = tmp;
376  }
377  return A;
378 }
379 
380 /* ms_mltadd -- matrix-scalar multiply and add
381  -- may be in situ
382  -- returns out == A1 + s*A2 */
383 MAT *ms_mltadd(A1,A2,s,out)
384 MAT *A1, *A2, *out;
385 double s;
386 {
387  /* register Real *A1_e, *A2_e, *out_e; */
388  /* register int j; */
389  int i, m, n;
390 
391  if ( ! A1 || ! A2 )
392  error(E_NULL,"ms_mltadd");
393  if ( A1->m != A2->m || A1->n != A2->n )
394  error(E_SIZES,"ms_mltadd");
395 
396  if ( out != A1 && out != A2 )
397  out = m_resize(out,A1->m,A1->n);
398 
399  if ( s == 0.0 )
400  return m_copy(A1,out);
401  if ( s == 1.0 )
402  return m_add(A1,A2,out);
403 
404  tracecatch(out = m_copy(A1,out),"ms_mltadd");
405 
406  m = A1->m; n = A1->n;
407  for ( i = 0; i < m; i++ )
408  {
409  __mltadd__(out->me[i],A2->me[i],s,(int)n);
410  /**************************************************
411  A1_e = A1->me[i];
412  A2_e = A2->me[i];
413  out_e = out->me[i];
414  for ( j = 0; j < n; j++ )
415  out_e[j] = A1_e[j] + s*A2_e[j];
416  **************************************************/
417  }
418 
419  return out;
420 }
421 
422 /* mv_mltadd -- matrix-vector multiply and add
423  -- may not be in situ
424  -- returns out == v1 + alpha*A*v2 */
425 VEC *mv_mltadd(v1,v2,A,alpha,out)
426 VEC *v1, *v2, *out;
427 MAT *A;
428 double alpha;
429 {
430  /* register int j; */
431  int i, m, n;
432  Real *v2_ve, *out_ve;
433 
434  if ( ! v1 || ! v2 || ! A )
435  error(E_NULL,"mv_mltadd");
436  if ( out == v2 )
437  error(E_INSITU,"mv_mltadd");
438  if ( v1->dim != A->m || v2->dim != A->n )
439  error(E_SIZES,"mv_mltadd");
440 
441  tracecatch(out = v_copy(v1,out),"mv_mltadd");
442 
443  v2_ve = v2->ve; out_ve = out->ve;
444  m = A->m; n = A->n;
445 
446  if ( alpha == 0.0 )
447  return out;
448 
449  for ( i = 0; i < m; i++ )
450  {
451  out_ve[i] += alpha*__ip__(A->me[i],v2_ve,(int)n);
452  /**************************************************
453  A_e = A->me[i];
454  sum = 0.0;
455  for ( j = 0; j < n; j++ )
456  sum += A_e[j]*v2_ve[j];
457  out_ve[i] = v1->ve[i] + alpha*sum;
458  **************************************************/
459  }
460 
461  return out;
462 }
463 
464 /* vm_mltadd -- vector-matrix multiply and add
465  -- may not be in situ
466  -- returns out' == v1' + v2'*A */
467 VEC *vm_mltadd(v1,v2,A,alpha,out)
468 VEC *v1, *v2, *out;
469 MAT *A;
470 double alpha;
471 {
472  int /* i, */ j, m, n;
473  Real tmp, /* *A_e, */ *out_ve;
474 
475  if ( ! v1 || ! v2 || ! A )
476  error(E_NULL,"vm_mltadd");
477  if ( v2 == out )
478  error(E_INSITU,"vm_mltadd");
479  if ( v1->dim != A->n || A->m != v2->dim )
480  error(E_SIZES,"vm_mltadd");
481 
482  tracecatch(out = v_copy(v1,out),"vm_mltadd");
483 
484  out_ve = out->ve; m = A->m; n = A->n;
485  for ( j = 0; j < m; j++ )
486  {
487  tmp = v2->ve[j]*alpha;
488  if ( tmp != 0.0 )
489  __mltadd__(out_ve,A->me[j],tmp,(int)n);
490  /**************************************************
491  A_e = A->me[j];
492  for ( i = 0; i < n; i++ )
493  out_ve[i] += A_e[i]*tmp;
494  **************************************************/
495  }
496 
497  return out;
498 }
499 
MAT * mmtr_mlt(MAT *A, MAT *B, MAT *OUT)
Definition: matop.c:134
MAT * swap_rows(MAT *A, int i, int j, int lo, int hi)
Definition: matop.c:331
double max(double a, double b)
Definition: geometry3d.cpp:22
#define B(i)
Definition: multisplit.cpp:62
#define min(a, b)
Definition: matrix.h:157
#define Real
Definition: machine.h:189
static Object ** v_resize(void *v)
Definition: ivocvect.cpp:1297
size_t p
VEC * vm_mltadd(VEC *v1, VEC *v2, MAT *A, double alpha, VEC *out)
Definition: matop.c:467
MAT * sm_mlt(double scalar, MAT *matrix, MAT *out)
Definition: matop.c:241
static philox4x32_key_t k
Definition: nrnran123.cpp:11
#define m_copy(in, out)
Definition: matrix.h:403
u_int n
Definition: matrix.h:74
Real * ve
Definition: matrix.h:69
MAT * ms_mltadd(MAT *A1, MAT *A2, double s, MAT *out)
Definition: matop.c:383
Definition: matrix.h:67
#define v_copy(in, out)
Definition: matrix.h:404
#define E_SIZES
Definition: err.h:95
uint32_t u_int
Definition: machine.h:38
int const size_t const size_t n
Definition: nrngsl.h:12
_CONST char * s
Definition: system.cpp:74
static char rcsid[]
Definition: matop.c:34
void __mltadd__(Real *dp1, Real *dp2, double s, int len)
Definition: machine.c:76
u_int dim
Definition: matrix.h:68
MAT * m_add(MAT *mat1, MAT *mat2, MAT *out)
Definition: matop.c:38
#define tracecatch(ok_part, function)
Definition: err.h:166
#define E_NULL
Definition: err.h:102
size_t j
void __add__(Real *dp1, Real *dp2, Real *out, int len)
Definition: machine.c:113
#define alpha
Definition: bkpfacto.c:43
double __ip__(Real *dp1, Real *dp2, int len)
Definition: machine.c:40
MAT * mtrm_mlt(MAT *A, MAT *B, MAT *OUT)
Definition: matop.c:169
#define E_INSITU2
Definition: err.h:105
VEC * v_zero(VEC *x)
Definition: init.c:40
MAT * swap_cols(MAT *A, int i, int j, int lo, int hi)
Definition: matop.c:356
static Object ** m_resize(void *v)
Definition: matrix.cpp:190
VEC * mv_mlt(MAT *A, VEC *b, VEC *out)
Definition: matop.c:205
#define i
Definition: md1redef.h:12
#define A(i)
Definition: multisplit.cpp:61
static Object ** m_zero(void *v)
Definition: matrix.cpp:511
#define OUT
Definition: matrix.h:51
MAT * m_mlt(MAT *A, MAT *B, MAT *OUT)
Definition: matop.c:88
#define error(err_num, fn_name)
Definition: err.h:73
void __sub__(Real *dp1, Real *dp2, Real *out, int len)
Definition: machine.c:123
u_int m
Definition: matrix.h:74
for(i=0;i< n;i++)
void __smlt__(Real *dp, double s, Real *out, int len)
Definition: machine.c:102
return NULL
Definition: cabcode.cpp:461
VEC * vm_mlt(MAT *A, VEC *b, VEC *out)
Definition: matop.c:263
Real ** me
Definition: matrix.h:76
Definition: matrix.h:73
MAT * m_sub(MAT *mat1, MAT *mat2, MAT *out)
Definition: matop.c:63
MAT * m_transp(MAT *in, MAT *out)
Definition: matop.c:300
#define E_INSITU
Definition: err.h:106
VEC * mv_mltadd(VEC *v1, VEC *v2, MAT *A, double alpha, VEC *out)
Definition: matop.c:425