File: pdtrmr2.c

package info (click to toggle)
scalapack 1.7.4-2
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 34,004 kB
  • ctags: 30,444
  • sloc: fortran: 310,201; ansic: 64,027; makefile: 1,838; sh: 4
file content (357 lines) | stat: -rw-r--r-- 11,426 bytes parent folder | download | duplicates (10)
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
357
#include "redist.h"
/* $Id: pdtrmr2.c,v 1.1.1.1 2000/02/15 18:04:09 susan Exp $
 * 
 * some functions used by the pdtrmr2d routine see file pdtrmr.c for more
 * documentation.
 * 
 * Created March 1993 by B. Tourancheau (See sccs for modifications). */
#define static2 static
#if defined(Add_) || defined(f77IsF2C)
#define fortran_mr2d pdtrmr2do_
#define fortran_mr2dnew pdtrmr2d_
#elif defined(UpCase)
#define fortran_mr2dnew PDTRMR2D
#define fortran_mr2d PDTRMR2DO
#define dcopy_ DCOPY
#define dlacpy_ DLACPY
#else
#define fortran_mr2d pdtrmr2do
#define fortran_mr2dnew pdtrmr2d
#define dcopy_ dcopy
#define dlacpy_ dlacpy
#endif
#define Clacpy Cdtrlacpy
void  Clacpy();
typedef struct {
  int   desctype;
  int   ctxt;
  int   m;
  int   n;
  int   nbrow;
  int   nbcol;
  int   sprow;
  int   spcol;
  int   lda;
}     MDESC;
#define BLOCK_CYCLIC_2D 1
typedef struct {
  int   gstart;
  int   len;
}     IDESC;
#define SHIFT(row,sprow,nbrow) ((row)-(sprow)+ ((row) >= (sprow) ? 0 : (nbrow)))
#define max(A,B) ((A)>(B)?(A):(B))
#define min(A,B) ((A)>(B)?(B):(A))
#define DIVUP(a,b) ( ((a)-1) /(b)+1)
#define ROUNDUP(a,b) (DIVUP(a,b)*(b))
#ifdef MALLOCDEBUG
#define malloc mymalloc
#define free myfree
#define realloc myrealloc
#endif
/* Cblacs */
extern void Cblacs_pcoord();
extern int Cblacs_pnum();
extern void Csetpvmtids();
extern void Cblacs_get();
extern void Cblacs_pinfo();
extern void Cblacs_gridinfo();
extern void Cblacs_gridinit();
extern void Cblacs_exit();
extern void Cblacs_gridexit();
extern void Cblacs_setup();
extern void Cigebs2d();
extern void Cigebr2d();
extern void Cigesd2d();
extern void Cigerv2d();
extern void Cigsum2d();
extern void Cigamn2d();
extern void Cigamx2d();
extern void Cdgesd2d();
extern void Cdgerv2d();
/* lapack */
void  dlacpy_();
/* aux fonctions */
extern int localindice();
extern void *mr2d_malloc();
extern int ppcm();
extern int localsize();
extern int memoryblocksize();
extern int changeorigin();
extern void paramcheck();
/* tools and others function */
#define scanD0 dtrscanD0
#define dispmat dtrdispmat
#define setmemory dtrsetmemory
#define freememory dtrfreememory
#define scan_intervals dtrscan_intervals
extern void scanD0();
extern void dispmat();
extern void setmemory();
extern void freememory();
extern int scan_intervals();
extern void Cpdtrmr2do();
extern void Cpdtrmr2d();
/* some defines for Cpdtrmr2do */
#define SENDBUFF 0
#define RECVBUFF 1
#define SIZEBUFF 2
#if 0
#define DEBUG
#endif
#ifndef DEBUG
#define NDEBUG
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
/* Created March 1993 by B. Tourancheau (See sccs for modifications). */
/************************************************************************/
/* Set the memory space with the malloc function */
void
setmemory(adpointer, blocksize)
  double **adpointer;
  int   blocksize;
{
  assert(blocksize >= 0);
  if (blocksize == 0) {
    *adpointer = NULL;
    return;
  }
  *adpointer = (double *) mr2d_malloc(
				      blocksize * sizeof(double));
}
/******************************************************************/
/* Free the memory space after the malloc */
void
freememory(ptrtobefreed)
  double *ptrtobefreed;
{
  if (ptrtobefreed == NULL)
    return;
  free((char *) ptrtobefreed);
}
/* extern functions for intersect() extern dcopy_(); */
/**************************************************************/
/* return the number of elements int the column after i and the distance of
 * the first one from i, i,j can be negative out of borns, the number of
 * elements returned can be negative (means 0) */
static2 int
insidemat(uplo, diag, i, j, m, n, offset)
  int   m, n, i, j;	/* coordonnees de depart, taille de la sous-matrice */
  char *uplo, *diag;
  int  *offset;
{
  /* tests outside mxn */
  assert(j >= 0 && j < n);
  assert(i >= 0);
  if (toupper(*uplo) == 'U') {
    int   nbline;	/* number of lines in the j_th column */
    int   virtualnbline;	/* number of line if we were not limited by m */
    *offset = 0;
    virtualnbline = max(m - n, 0) + j + (toupper(*diag) == 'N');
    nbline = min(virtualnbline, m);
    return nbline - i;
  } else {
    int   firstline;	/* first line in the j_th column */
    int   diagcol;	/* column where the diag begin */
    int   virtualline;	/* virtual first line if the matrix was extended with
			 * negative indices */
    int   off;
    diagcol = max(n - m, 0);;
    virtualline = j - diagcol + (toupper(*diag) == 'U');
    firstline = max(0, virtualline);
    off = max(firstline - i, 0);
    *offset = off;
    i += off;
    return m - i;
  }
}/* insidemat() */
/********************************************************************/
/* Execute an action on the local memories when an intersection occurs (the
 * action can be the filling of the memory buffer, the count of the memory
 * buffer size or the setting of the memory with the element received) */
static2 void
intersect(uplo, diag,
	  j, start, end,
	  action,
	  ptrsizebuff, pptrbuff, ptrblock,
	  m, n,
	  ma, ia, ja, templateheight0, templatewidth0,
	  mb, ib, jb, templateheight1, templatewidth1)
  int   action, *ptrsizebuff;
  int   j, start, end;
  double **pptrbuff, *ptrblock;
  int   templateheight0, templatewidth0;
  int   templateheight1, templatewidth1;
  MDESC *ma, *mb;
  int   ia, ja, ib, jb, m, n;
  char *uplo, *diag;
/* Execute the action on the local memory for the current interval and
 * increment pptrbuff and ptrsizebuff of the intervalsize */
/* Notice that if the interval is contigous in the virtual matrice, it is
 * also contigous in the real one ! */
{
  /* int       un = 1; only when we use dcopy instead of memcpy */
  double *ptrstart;
  int   offset, nbline;
  int   intervalsize;
  assert(start < end);
  assert(j >= 0 && j < n);
  nbline =
	insidemat(uplo, diag, start, j, m, n, &offset);
  if (nbline <= 0)
    return;
  start += offset;
  if (start >= end)
    return;
  intervalsize = min(end - start, nbline);
  (*ptrsizebuff) += intervalsize;
  switch (action) {
  case SENDBUFF:	/* fill buff with local elements to be sent */
    ptrstart = ptrblock + localindice(start + ia, j + ja,
				      templateheight0, templatewidth0, ma);
    memcpy((char *) (*pptrbuff), (char *) ptrstart,
	   intervalsize * sizeof(double));
    /* dcopy_(&intervalsize, (char *) (ptrstart), &un, (char *) (*pptrbuff),
     * &un); */
    (*pptrbuff) += intervalsize;
    break;
  case RECVBUFF:	/* fill local memory with the values received */
    ptrstart = ptrblock + localindice(start + ib, j + jb,
				      templateheight1, templatewidth1, mb);
    memcpy((char *) ptrstart, (char *) (*pptrbuff),
	   intervalsize * sizeof(double));
    /* dcopy_(&intervalsize, (char *) (*pptrbuff), &un, (char *) (ptrstart),
     * &un); */
    (*pptrbuff) += intervalsize;
    break;
  case SIZEBUFF:	/* computation of sizebuff */
    break;
  default:
    printf("action is  %d outside the scope of the case [0..2] !! \n ", action);
    exit(0);
    break;
  };	/* switch (action) */
}/* intersect() */
/* scan_intervals: scans two distributions in one dimension, and compute the
 * intersections on the local processor. result must be long enough to
 * contains the result that are stocked in IDESC structure, the function
 * returns the number of intersections found */
int 
scan_intervals(type, ja, jb, n, ma, mb, q0, q1, col0, col1,
	       result)
  char  type;
  int   ja, jb, n, q0, q1, col0, col1;
  MDESC *ma, *mb;
  IDESC *result;
{
  int   offset, j0, j1, templatewidth0, templatewidth1, nbcol0, nbcol1;
  int   l;	/* local indice on the beginning of the interval */
  assert(type == 'c' || type == 'r');
  nbcol0 = (type == 'c' ? ma->nbcol : ma->nbrow);
  nbcol1 = (type == 'c' ? mb->nbcol : mb->nbrow);
  templatewidth0 = q0 * nbcol0;
  templatewidth1 = q1 * nbcol1;
  {
    int   sp0 = (type == 'c' ? ma->spcol : ma->sprow);
    int   sp1 = (type == 'c' ? mb->spcol : mb->sprow);
    j0 = SHIFT(col0, sp0, q0) * nbcol0 - ja;
    j1 = SHIFT(col1, sp1, q1) * nbcol1 - jb;
  }
  offset = 0;
  l = 0;
  /* a small check to verify that the submatrix begin inside the first block
   * of the original matrix, this done by a sort of coordinate change at the
   * beginning of the Cpdtrmr2d */
  assert(j0 + nbcol0 > 0);
  assert(j1 + nbcol1 > 0);
  while ((j0 < n) && (j1 < n)) {
    int   end0, end1;
    int   start, end;
    end0 = j0 + nbcol0;
    end1 = j1 + nbcol1;
    if (end0 <= j1) {
      j0 += templatewidth0;
      l += nbcol0;
      continue;
    }
    if (end1 <= j0) {
      j1 += templatewidth1;
      continue;
    }
    /* compute the raw intersection */
    start = max(j0, j1);
    start = max(start, 0);
    /* the start is correct now, update the corresponding fields */
    result[offset].gstart = start;
    end = min(end0, end1);
    if (end0 == end) {
      j0 += templatewidth0;
      l += nbcol0;
    }
    if (end1 == end)
      j1 += templatewidth1;
    /* throw the limit if they go out of the matrix */
    end = min(end, n);
    assert(end > start);
    /* it is a bit tricky to see why the length is always positive after all
     * this min and max, first we have the property that every interval
     * considered is at least partly into the submatrix, second we arrive
     * here only if the raw intersection is non-void, if we remove a limit
     * that means the corresponding frontier is in both intervals which
     * proove the final interval is non-void, clear ?? */
    result[offset].len = end - start;
    offset += 1;
  }	/* while */
  return offset;
}
/*********************************************************************/
/* Do the scanning of intervals and the requested action */
void
scanD0(uplo, diag, action, ptrbuff, ptrsizebuff,
       m, n,
       ma, ia, ja, p0, q0,
       mb, ib, jb, p1, q1,
       v_inter, vinter_nb,
       h_inter, hinter_nb,
       ptrblock)
  int   action,	/* # of the action done on the intersected intervals  */
       *ptrsizebuff;	/* size of the communication ptrbuffer (chosen to be
			 * an output parameter in every cases) */
  double *ptrbuff	/* address of the communication ptrbuffer (a
			 * suffisant memory space is supposed to be allocated
      before the call) */ , *ptrblock;
  int   p0, q0, p1, q1;
  IDESC *v_inter, *h_inter;
  int   vinter_nb, hinter_nb;
  int   m, n;
  int   ia, ja, ib, jb;
  MDESC *ma, *mb;
  char *uplo, *diag;
{/* Rmk: the a+au type addresses are strict bounds as a+au does not belong to
  * the [a..a+au-1] interval of length au */
  int   templateheight1, templatewidth1;
  int   templateheight0, templatewidth0;
  int   h, v;	/* for scanning the intervals */
  /* initializations */
  templateheight1 = p1 * mb->nbrow;
  templateheight0 = p0 * ma->nbrow;
  templatewidth1 = q1 * mb->nbcol;
  templatewidth0 = q0 * ma->nbcol;
  /* we now will deal will logical grids, that's to say we change our
   * numbering of processors so that (0,0) begin on logical processor (0,0) */
  /* in case we will not enter the while loop */
  (*ptrsizebuff) = 0;
  for (h = 0; h < hinter_nb; h++)
    for (v = 0; v < vinter_nb; v++) {
      int   j;
      for (j = 0; j < h_inter[h].len; j++)
	intersect(uplo, diag, j + h_inter[h].gstart,
		  v_inter[v].gstart, v_inter[v].gstart + v_inter[v].len,
		  action, ptrsizebuff, &ptrbuff, ptrblock, m, n,
		  ma, ia, ja, templateheight0, templatewidth0,
		  mb, ib, jb, templateheight1, templatewidth1);
    }
}/* scanD0() */