NEURON
pxop.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 /* pxop.c 1.5 12/03/87 */
29 
30 
31 #include <stdio.h>
32 #include "matrix.h"
33 
34 static char rcsid[] = "pxop.c,v 1.1 1997/12/04 17:55:44 hines Exp";
35 
36 /**********************************************************************
37 Note: A permutation is often interpreted as a matrix
38  (i.e. a permutation matrix).
39  A permutation px represents a permutation matrix P where
40  P[i][j] == 1 if and only if px->pe[i] == j
41 **********************************************************************/
42 
43 
44 /* px_inv -- invert permutation -- in situ
45  -- taken from ACM Collected Algorithms #250 */
46 PERM *px_inv(px,out)
47 PERM *px, *out;
48 {
49  int i, j, k, n, *p;
50 
51  out = px_copy(px, out);
52  n = out->size;
53  p = (int *)(out->pe);
54  for ( n--; n>=0; n-- )
55  {
56  i = p[n];
57  if ( i < 0 ) p[n] = -1 - i;
58  else if ( i != n )
59  {
60  k = n;
61  while (TRUE)
62  {
63  if ( i < 0 || i >= out->size )
64  error(E_BOUNDS,"px_inv");
65  j = p[i]; p[i] = -1 - k;
66  if ( j == n )
67  { p[n] = i; break; }
68  k = i; i = j;
69  }
70  }
71  }
72  return out;
73 }
74 
75 /* px_mlt -- permutation multiplication (composition) */
76 PERM *px_mlt(px1,px2,out)
77 PERM *px1,*px2,*out;
78 {
79  u_int i,size;
80 
81  if ( px1==(PERM *)NULL || px2==(PERM *)NULL )
82  error(E_NULL,"px_mlt");
83  if ( px1->size != px2->size )
84  error(E_SIZES,"px_mlt");
85  if ( px1 == out || px2 == out )
86  error(E_INSITU,"px_mlt");
87  if ( out==(PERM *)NULL || out->size < px1->size )
88  out = px_resize(out,px1->size);
89 
90  size = px1->size;
91  for ( i=0; i<size; i++ )
92  if ( px2->pe[i] >= size )
93  error(E_BOUNDS,"px_mlt");
94  else
95  out->pe[i] = px1->pe[px2->pe[i]];
96 
97  return out;
98 }
99 
100 /* px_vec -- permute vector */
101 VEC *px_vec(px,vector,out)
102 PERM *px;
103 VEC *vector,*out;
104 {
105  u_int old_i, i, size, start;
106  Real tmp;
107 
108  if ( px==(PERM *)NULL || vector==(VEC *)NULL )
109  error(E_NULL,"px_vec");
110  if ( px->size > vector->dim )
111  error(E_SIZES,"px_vec");
112  if ( out==(VEC *)NULL || out->dim < vector->dim )
113  out = v_resize(out,vector->dim);
114 
115  size = px->size;
116  if ( size == 0 )
117  return v_copy(vector,out);
118  if ( out != vector )
119  {
120  for ( i=0; i<size; i++ )
121  if ( px->pe[i] >= size )
122  error(E_BOUNDS,"px_vec");
123  else
124  out->ve[i] = vector->ve[px->pe[i]];
125  }
126  else
127  { /* in situ algorithm */
128  start = 0;
129  while ( start < size )
130  {
131  old_i = start;
132  i = px->pe[old_i];
133  if ( i >= size )
134  {
135  start++;
136  continue;
137  }
138  tmp = vector->ve[start];
139  while ( TRUE )
140  {
141  vector->ve[old_i] = vector->ve[i];
142  px->pe[old_i] = i+size;
143  old_i = i;
144  i = px->pe[old_i];
145  if ( i >= size )
146  break;
147  if ( i == start )
148  {
149  vector->ve[old_i] = tmp;
150  px->pe[old_i] = i+size;
151  break;
152  }
153  }
154  start++;
155  }
156 
157  for ( i = 0; i < size; i++ )
158  if ( px->pe[i] < size )
159  error(E_BOUNDS,"px_vec");
160  else
161  px->pe[i] = px->pe[i]-size;
162  }
163 
164  return out;
165 }
166 
167 /* pxinv_vec -- apply the inverse of px to x, returning the result in out */
168 VEC *pxinv_vec(px,x,out)
169 PERM *px;
170 VEC *x, *out;
171 {
172  u_int i, size;
173 
174  if ( ! px || ! x )
175  error(E_NULL,"pxinv_vec");
176  if ( px->size > x->dim )
177  error(E_SIZES,"pxinv_vec");
178  /* if ( x == out )
179  error(E_INSITU,"pxinv_vec"); */
180  if ( ! out || out->dim < x->dim )
181  out = v_resize(out,x->dim);
182 
183  size = px->size;
184  if ( size == 0 )
185  return v_copy(x,out);
186  if ( out != x )
187  {
188  for ( i=0; i<size; i++ )
189  if ( px->pe[i] >= size )
190  error(E_BOUNDS,"pxinv_vec");
191  else
192  out->ve[px->pe[i]] = x->ve[i];
193  }
194  else
195  { /* in situ algorithm --- cheat's way out */
196  px_inv(px,px);
197  px_vec(px,x,out);
198  px_inv(px,px);
199  }
200 
201  return out;
202 }
203 
204 
205 
206 /* px_transp -- transpose elements of permutation
207  -- Really multiplying a permutation by a transposition */
208 PERM *px_transp(px,i1,i2)
209 PERM *px; /* permutation to transpose */
210 u_int i1,i2; /* elements to transpose */
211 {
212  u_int temp;
213 
214  if ( px==(PERM *)NULL )
215  error(E_NULL,"px_transp");
216 
217  if ( i1 < px->size && i2 < px->size )
218  {
219  temp = px->pe[i1];
220  px->pe[i1] = px->pe[i2];
221  px->pe[i2] = temp;
222  }
223 
224  return px;
225 }
226 
227 /* myqsort -- a cheap implementation of Quicksort on integers
228  -- returns number of swaps */
229 static int myqsort(a,num)
230 int *a, num;
231 {
232  int i, j, tmp, v;
233  int numswaps;
234 
235  numswaps = 0;
236  if ( num <= 1 )
237  return 0;
238 
239  i = 0; j = num; v = a[0];
240  for ( ; ; )
241  {
242  while ( a[++i] < v )
243  ;
244  while ( a[--j] > v )
245  ;
246  if ( i >= j ) break;
247 
248  tmp = a[i];
249  a[i] = a[j];
250  a[j] = tmp;
251  numswaps++;
252  }
253 
254  tmp = a[0];
255  a[0] = a[j];
256  a[j] = tmp;
257  if ( j != 0 )
258  numswaps++;
259 
260  numswaps += myqsort(&a[0],j);
261  numswaps += myqsort(&a[j+1],num-(j+1));
262 
263  return numswaps;
264 }
265 
266 
267 /* px_sign -- compute the ``sign'' of a permutation = +/-1 where
268  px is the product of an even/odd # transpositions */
269 int px_sign(px)
270 PERM *px;
271 {
272  int numtransp;
273  PERM *px2;
274 
275  if ( px==(PERM *)NULL )
276  error(E_NULL,"px_sign");
277  px2 = px_copy(px,PNULL);
278  numtransp = myqsort((int*)px2->pe,px2->size);
279  px_free(px2);
280 
281  return ( numtransp % 2 ) ? -1 : 1;
282 }
283 
284 
285 /* px_cols -- permute columns of matrix A; out = A.px'
286  -- May NOT be in situ */
287 MAT *px_cols(px,A,out)
288 PERM *px;
289 MAT *A, *out;
290 {
291  int i, j, m, n, px_j;
292  Real **A_me, **out_me;
293 #ifdef ANSI_C
294  MAT *m_get(int, int);
295 #else
296  extern MAT *m_get();
297 #endif
298 
299  if ( ! A || ! px )
300  error(E_NULL,"px_cols");
301  if ( px->size != A->n )
302  error(E_SIZES,"px_cols");
303  if ( A == out )
304  error(E_INSITU,"px_cols");
305  m = A->m; n = A->n;
306  if ( ! out || out->m != m || out->n != n )
307  out = m_get(m,n);
308  A_me = A->me; out_me = out->me;
309 
310  for ( j = 0; j < n; j++ )
311  {
312  px_j = px->pe[j];
313  if ( px_j >= n )
314  error(E_BOUNDS,"px_cols");
315  for ( i = 0; i < m; i++ )
316  out_me[i][px_j] = A_me[i][j];
317  }
318 
319  return out;
320 }
321 
322 /* px_rows -- permute columns of matrix A; out = px.A
323  -- May NOT be in situ */
324 MAT *px_rows(px,A,out)
325 PERM *px;
326 MAT *A, *out;
327 {
328  int i, j, m, n, px_i;
329  Real **A_me, **out_me;
330 #ifdef ANSI_C
331  MAT *m_get(int, int);
332 #else
333  extern MAT *m_get();
334 #endif
335 
336  if ( ! A || ! px )
337  error(E_NULL,"px_rows");
338  if ( px->size != A->m )
339  error(E_SIZES,"px_rows");
340  if ( A == out )
341  error(E_INSITU,"px_rows");
342  m = A->m; n = A->n;
343  if ( ! out || out->m != m || out->n != n )
344  out = m_get(m,n);
345  A_me = A->me; out_me = out->me;
346 
347  for ( i = 0; i < m; i++ )
348  {
349  px_i = px->pe[i];
350  if ( px_i >= m )
351  error(E_BOUNDS,"px_rows");
352  for ( j = 0; j < n; j++ )
353  out_me[i][j] = A_me[px_i][j];
354  }
355 
356  return out;
357 }
358 
MAT * m_get(int, int)
Definition: memory.c:36
#define PNULL
Definition: matrix.h:633
int px_free(PERM *)
Definition: memory.c:201
#define Real
Definition: machine.h:189
static Object ** v_resize(void *v)
Definition: ivocvect.cpp:1297
size_t p
#define TRUE
Definition: err.c:57
PERM * px_copy(PERM *in, PERM *out)
Definition: copy.c:79
PERM * px_mlt(PERM *px1, PERM *px2, PERM *out)
Definition: pxop.c:76
#define v
Definition: md1redef.h:4
MAT * px_cols(PERM *px, MAT *A, MAT *out)
Definition: pxop.c:287
static philox4x32_key_t k
Definition: nrnran123.cpp:11
u_int n
Definition: matrix.h:74
void start()
Definition: hel2mos.cpp:205
Real * ve
Definition: matrix.h:69
Definition: matrix.h:67
VEC * pxinv_vec(PERM *px, VEC *x, VEC *out)
Definition: pxop.c:168
#define v_copy(in, out)
Definition: matrix.h:404
u_int size
Definition: matrix.h:88
#define E_SIZES
Definition: err.h:95
PERM * px_inv(PERM *px, PERM *out)
Definition: pxop.c:46
uint32_t u_int
Definition: machine.h:38
int const size_t const size_t n
Definition: nrngsl.h:12
int px_sign(PERM *px)
Definition: pxop.c:269
PERM * px_resize(PERM *, int)
Definition: memory.c:399
u_int dim
Definition: matrix.h:68
#define E_BOUNDS
Definition: err.h:96
#define E_NULL
Definition: err.h:102
size_t j
MAT * px_rows(PERM *px, MAT *A, MAT *out)
Definition: pxop.c:324
static int myqsort(int *a, int num)
Definition: pxop.c:229
#define i
Definition: md1redef.h:12
#define A(i)
Definition: multisplit.cpp:61
PERM * px_transp(PERM *px, u_int i1, u_int i2)
Definition: pxop.c:208
#define error(err_num, fn_name)
Definition: err.h:73
u_int m
Definition: matrix.h:74
VEC * px_vec(PERM *px, VEC *vector, VEC *out)
Definition: pxop.c:101
Definition: matrix.h:87
static char rcsid[]
Definition: pxop.c:34
return NULL
Definition: cabcode.cpp:461
Real ** me
Definition: matrix.h:76
Definition: matrix.h:73
u_int * pe
Definition: matrix.h:88
#define E_INSITU
Definition: err.h:106