1 /*
2  $Id$
3  */
4 
5 #include <math.h>
6 #include <stdio.h>
7 #ifndef WIN32
8 #include <strings.h>
9 #endif
10 #include <stdlib.h>
11 #include "ga.h"
12 
13 extern int fortchar_to_string();
14 
15 /* Maximum number of open shells and corresponding maximum number
16    of spin functions for any possible multiplicity */
17 #define nsmax 14
18 #define nfmax 1001
19 
20 /* #define nsmax 15 */
21 /* #define nfmax 2002 */
22 
Error(char * string,int integer)23 static void Error(char *string, int integer)
24 {
25 /*
26   (void) fflush(stdout);
27   (void) fprintf(stderr,"\n\nError was called.\n");
28   (void) fprintf(stderr,string);
29   (void) fprintf(stderr," %d (%#x).\n",integer,integer);
30   exit(1); */
31   GA_Error(string, (long) integer);
32 }
33 
34 
Dscal(int n,double s,double * u,int iu)35 static void Dscal(int n, double s, double *u, int iu)
36 /*
37   Scale double precision vector u by s
38 */
39 {
40   while (n--) {
41     *u = *u * s;
42     u += iu;
43   }
44 }
45 
Dfill(int n,double s,double * u,int iu)46 static void Dfill(int n, double s, double *u, int iu)
47 /*
48   Fill double precision vector u with s
49 */
50 {
51   while (n--) {
52     *u = s;
53     u += iu;
54   }
55 }
56 
Screen(int n,double s,double * u,int iu)57 static void Screen(int n, double s, double *u, int iu)
58 /*
59   zero elements of double precision vector u if they are less
60   in absolute magnitude than the threshold s
61 */
62 {
63   s = fabs(s);
64   while (n--) {
65     if (fabs(*u) < s)
66       *u = 0.0;
67     u += iu;
68   }
69 }
70 
Sparsity(int n,double * u,int iu)71 static double Sparsity(int n, double *u, int iu)
72 /*
73   Return (no. zero elements)/(total no. elements)
74 */
75 {
76   int zero=0, nn;
77 
78   nn = n;
79   while (nn--) {
80     if (*u == 0.0)
81       ++zero;
82     u += iu;
83   }
84 
85   return (double) zero / (double) n;
86 }
87 
Identity(double * u,int n)88 static void Identity(double *u, int n)
89 /*
90   Form the n*n double precision identity matrix
91 */
92 {
93   Dfill(n*n, 0.0, u, 1);
94 
95   Dfill(n, 1.0, u, n+1);
96 }
97 
PrintMatrix(const double * u,int mcol,int mrow,int ncol,int nrow)98 static void PrintMatrix(const double *u, int mcol, int mrow,
99 			int ncol, int nrow)
100 /*
101   Print a double precision matrix.
102   mcol = skip between elements down a column
103   mrow = skip between elements across a column
104   ncol = no. of columns
105   nrow = no. of rows
106 */
107 {
108   double *uu, *uuu;
109   int todo, nnrow, nncol, ttodo, i;
110 
111   (void) printf("\n\n");
112   nncol = ncol;
113   while(nncol) {
114 
115     if (nncol < 6)
116       todo = nncol;
117     else
118       todo = 6;
119 
120     (void) printf("  ");
121     for (i=1; i<=todo; i++)
122       (void) printf("%12d",ncol-nncol+i);
123     (void) printf("\n\n");
124 
125 
126     uu = (double *)u;
127     nnrow = nrow;
128     while(nnrow--) {
129 
130       (void) printf("%3d  ",nrow-nnrow);
131       uuu = uu;
132       ttodo = todo;
133       while(ttodo--) {
134 	(void) printf("%12.6f",*uuu);
135 	uuu += mrow;
136       }
137       (void) printf("\n");
138       uu += mcol;
139     }
140 
141     (void) printf("\n\n");
142     u += todo*mrow;
143     nncol -= todo;
144   }
145 }
146 
MakeBranchingDiagram(int bd[nsmax+3][nsmax+3],int ns,int multi,int order,int info)147 static void MakeBranchingDiagram(int bd[nsmax+3][nsmax+3],
148 				 int ns, int multi, int order, int info)
149 /*
150   Form the branching diagram weights
151   bd[m][n] = weight of node with multiplicty m and n electrons
152   ns = maximum no. of open shells or unpaired electrons
153   multi = state multiplicity
154   order = 0 -> normal branching diagram
155           1 -> reversed diagram (for use with dictionary order functions)
156 */
157 {
158   int i, j, wrote;
159 
160   for (i=0; i<ns+3; i++)
161     for (j=0; j<ns+3; j++)
162       bd[i][j] = 0;
163 
164   if (order == 0) {
165     bd[1][0] = 1;
166 
167     for (i=1; i<=ns; i++) {
168       for (j=i%2+1; j<=ns+1; j+=2) {
169 	if (abs(multi-j) > (ns-i))
170 	  continue;
171 	bd[j][i] = bd[j-1][i-1] + bd[j+1][i-1];
172       }
173     }
174   }
175   else {
176     bd[multi][ns] = 1;
177 
178     for (i=ns-1; i>=0; i--) {
179       for (j=i%2+1; j<=ns+1; j+=2) {
180 	if (j > i+1)
181 	  continue;
182 	bd[j][i] = bd[j-1][i+1] + bd[j+1][i+1];
183       }
184     }
185   }
186 
187 #ifndef DEBUG
188   if (order == 1)
189     return;
190 #endif
191 
192   if (info) {
193       if (order == 0)
194 	  (void) printf("\nBranching diagram weights.\n\n");
195       else
196 	  (void) printf("\nReversed branching diagram weights.\n\n");
197 
198 
199       for (j=ns+1; j>=1; j--) {
200 	  wrote = 0;
201 	  for (i=0; i<=ns; i++)
202 	      if (bd[j][i])
203 		  wrote=1;
204 	  if (wrote) {
205 	      for (i=0; i<=ns; i++) {
206 		  if (bd[j][i])
207 		      (void) printf("%4d",bd[j][i]);
208 		  else
209 		      (void) printf("    ");
210 	      }
211 	      (void) printf("\n");
212 	  }
213       }
214       (void) printf("\n");
215   }
216 }
217 
MakeSpinFunctions(int bd[nsmax+3][nsmax+3],int ns,int multi,int f[nsmax+1][nfmax+1],int nf,int order,int info)218 static void MakeSpinFunctions(int bd[nsmax+3][nsmax+3],
219 			      int ns, int multi, int f[nsmax+1][nfmax+1],
220 			      int nf, int order, int info)
221 /*
222   Form the ordered spin functions as an array of 1s and 2s.
223   bd = branching diagram (reversed if want dictionary ordered functions)
224   ns = required no. of unpaired electrons
225   multi = state multiplicity
226   f[j][i] = occupation (1 or 2) of orbital j in function i
227   nf = no. of functions
228   order = 0 -> reversed dictionary, 1 -> dictionary
229 
230   if (reversed dictionary)
231     weight of arc (m,k)->(m+1,k+1) = weight of node (m+2,k)
232     and the graph has to be traversed right to left
233   else
234     weight of arc (m,k)->(m+1,k+1) = weight of node (m-1,k+1)
235     and the graph has to be traversed left to right
236 */
237 {
238   int i, test, j, m;
239 
240   if (order ==0) {
241     for (i=1; i<=nf; i++) {
242       test = i-1;
243       m = multi;
244       for (j=ns; j>0; j--){
245 
246 	if (bd[m-1][j-1] && (test-bd[m+1][j-1]) >= 0) {
247 	  test -= bd[m+1][j-1];
248 	  f[j][i] = 1;
249 	  m--;
250 	}
251 	else if (bd[m+1][j-1]){
252 	  f[j][i] = 2;
253 	  m++;
254 	}
255 	else
256 	  Error("mis-match walking spin-graph",j);
257       }
258       if (test != 0 || m != 1) {
259 	(void) printf("test=%d, m=%d\n",test,m);
260 	Error("invalid tail on spin graph",i);
261       }
262     }
263   }
264   else {
265     for (i=1; i<=nf; i++) {
266       test = i-1;
267       m = 1;
268       for (j=0; j<ns; j++){
269 
270 	if (bd[m+1][j+1] && (test-bd[m-1][j+1]) >= 0) {
271 	  test -= bd[m-1][j+1];
272 	  f[j+1][i] = 1;
273 	  m++;
274 	}
275 	else if (bd[m-1][j+1]){
276 	  f[j+1][i] = 2;
277 	  m--;
278 	}
279 	else
280 	  Error("mis-match walking reversed spin-graph",j);
281       }
282       if (test != 0 || m != multi) {
283 	(void) printf("test=%d, m=%d\n",test,m);
284 	Error("invalid tail on reversed spin graph",i);
285       }
286     }
287   }
288 
289   if (info) {
290       (void) printf("\nSpin functions\n\n");
291 
292       test = 0;
293       for (i=1; i<=nf; i++) {
294 	  test += printf("%4d [",i);
295 	  for (j=1; j<=ns; j++)
296 	      test += printf("%1d",f[j][i]);
297 	  if (test > (71-ns)) {
298 	      test = 0;
299 	      (void) printf("]\n");
300 	  }
301 	  else
302 	      test += printf("] ");
303       }
304       if (test)
305 	  (void) printf("\n");
306   }
307 }
308 
309 
MakeAxialDistances(int ns,int f[nsmax+1][nfmax+1],int nf,int d[nsmax][nfmax+1],double p[nsmax][nfmax+1],double g[nsmax][nfmax+1])310 static void MakeAxialDistances(int ns, int f[nsmax+1][nfmax+1],
311 			       int nf, int d[nsmax][nfmax+1],
312 			       double p[nsmax][nfmax+1], double g[nsmax][nfmax+1])
313 /*
314   Compute the axial distances for transpostions (j, j+1) for
315   the Standard Young Tableaux represented by the branching diagram
316   paths in f. (See Paunz, "Spin Eigenfunctions", p106.)
317   ns = no. of electrons
318   f[j][i] = 1 or 2, step j in the ith function
319   d[j][i] = axial distance for (j,j+1) in tableau i
320   p[j][i] = -1.0/d[j][i]
321   g[j][i] = sqrt(1-p[j][i]^2)
322 */
323 {
324   int i, j, k, jb;
325 
326 #ifdef DEBUG
327   int test;
328 #endif
329 
330   for (i=1; i<=nf; i++) {
331     for (j=1; j<ns; j++) {
332 
333       if (f[j][i] == f[j+1][i])
334 	d[j][i] = -1;
335       else {
336 	jb=0;
337 	for (k=1; k<j; k++) {
338 	  jb += (f[k][i] == f[j][i]);
339 	  jb -= (f[k][i] == f[j+1][i]);
340 	}
341 	if (f[j][i] == 1)
342 	  d[j][i] = jb + 1;
343 	else
344 	  d[j][i] = jb - 1;
345       }
346     }
347   }
348 
349   for (j=1; j<ns; j++) {
350     for (i=1; i<=nf; i++) {
351       p[j][i] = -1.0 / d[j][i];
352       g[j][i] = sqrt(1.0 - p[j][i]*p[j][i]);
353     }
354   }
355 
356 #ifdef DEBUG
357   (void) printf("\nAxial distances for (j,j+1)\n\n");
358 
359   test = 0;
360   for (i=1; i<=nf; i++) {
361     test += printf("%4d [",i);
362     for (j=1; j<ns; j++)
363       test += printf("%4d",d[j][i]);
364     if (test > (71-4*ns)) {
365       test = 0;
366       (void) printf("]\n");
367     }
368     else
369       test += printf("] ");
370   }
371   if (test)
372     (void) printf("\n");
373 #endif
374 }
375 
376 
MakePerm(int bd[nsmax+3][nsmax+3],int ns,int f[nsmax+1][nfmax+1],int nf,int perm[nsmax][nfmax+1],int order)377 static void MakePerm(int bd[nsmax+3][nsmax+3], int ns, int f[nsmax+1][nfmax+1],
378 		     int nf, int perm[nsmax][nfmax+1], int order)
379 /*
380   Compute the effect of the transpositions (j j+1) on the spin functions
381   bd = branching diagram (reversed if dictionary order)
382   ns = no. of electrons
383   f[j][i] = 1 or 2, step j in ith function
384   nf = no. of functions
385   perm[j][i] = result of permutation (j j+1) on the ith tableau.
386                is the no. of another standard tableau or zero
387   order = 0 -> reversed dictionary order, 1 -> dictionary order
388   See comments in MakeBranchingDiagram
389 */
390 {
391   int i, j, k, m, test, step;
392 
393   for (i=1; i<=nf; i++) {
394 
395     for (j=1; j<ns; j++) {
396 
397       test = 1;
398       m = 1;
399       for (k=1; k<=ns; k++) {
400 
401 	if ( k == j )
402 	  step = f[j+1][i];
403 	else if ( k == j+1 )
404 	  step = f[j][i];
405 	else
406 	  step = f[k][i];
407 
408 	if (step == 1) {
409 	  if (order == 0)
410 	    test = test + bd[m+2][k-1];
411 	  else
412 	    test = test + bd[m-1][k];
413 	  m++;
414 	}
415 	else
416 	  m--;
417 
418 	if ( m<=0 || bd[m][k] == 0) {
419 	    test = 0;
420 	    break;
421 	  }
422       }
423       perm[j][i] = test;
424     }
425   }
426 
427 #ifdef DEBUG
428   (void) printf("\nResults of permutations for (j,j+1)\n\n");
429 
430   test = 0;
431   for (i=1; i<=nf; i++) {
432     test += printf("%4d [",i);
433     for (j=1; j<ns; j++)
434       test += printf("%4d",perm[j][i]);
435     if (test > (71-4*ns)) {
436       test = 0;
437       (void) printf("]\n");
438     }
439     else
440       test += printf("] ");
441   }
442   if (test)
443     (void) printf("\n");
444 #endif
445 }
446 
447 
RightMultiply(int i,double * u,double * uu,int nf,double pp[nsmax][nfmax+1],double g[nsmax][nfmax+1],int perm[nsmax][nfmax+1])448 static void RightMultiply(int i, double *u, double *uu, int nf,
449 			  double pp[nsmax][nfmax+1], double g[nsmax][nfmax+1],
450 			  int perm[nsmax][nfmax+1])
451 /*
452   uu = (-1) * u * U(i i+1), where u and uu are pointers to
453   other represenation matrices.
454   i = index of required permutation (i i+1)
455   u = pointer to input matrix
456   uu = pointer to result matrix
457   nf = no. of functions = dimension of representation
458   pp[i][j] = negative reciprocal axial distance of (i i+1) in tableau j
459   gg[i][j] = sqrt(1-pp[i][j]^2)
460   perm[i][j] = action of (i i+1) on tableau j
461 */
462 {
463   int p, q, m;
464 
465   for (p=0; p<nf; p++) {
466     for (q=0; q<nf; q++) {
467 
468       *(uu+p+q*nf) = -(*(u+p+q*nf) * pp[i][q+1]);
469       m = perm[i][q+1];
470       if (m)
471 	*(uu+p+q*nf) -= *(u+p+(m-1)*nf)*g[i][q+1];
472     }
473   }
474 }
LeftMultiply(int i,double * u,double * uu,int nf,double pp[nsmax][nfmax+1],double g[nsmax][nfmax+1],int perm[nsmax][nfmax+1])475 static void LeftMultiply(int i, double *u, double *uu, int nf,
476 			 double pp[nsmax][nfmax+1], double g[nsmax][nfmax+1],
477 			 int perm[nsmax][nfmax+1])
478 /*
479   uu = (-1) * U(i i+1) * u, where u and uu are pointers to
480   other represenation matrices.
481   i = index of required permutation (i i+1)
482   u = pointer to input matrix
483   uu = pointer to result matrix
484   nf = no. of functions = dimension of representation
485   pp[i][j] = negative reciprocal axial distance of (i i+1) in tableau j
486   gg[i][j] = sqrt(1-pp[i][j]^2)
487   perm[i][j] = action of (i i+1) on tableau j
488 */
489 {
490   int p, q, m;
491 
492   for (p=0; p<nf; p++) {
493     for (q=0; q<nf; q++) {
494 
495       *(uu+p+q*nf) = -(*(u+p+q*nf) * pp[i][p+1]);
496       m = perm[i][p+1];
497       if (m)
498 	*(uu+p+q*nf) -= *(u+m-1+q*nf)*g[i][p+1];
499     }
500   }
501 }
502 
503 
504 #ifdef OLDCODE
ReadArguments(argc,argv,ns,multi,print)505 static void ReadArguments(argc, argv, ns, multi, print)
506      int argc, *ns, *multi, *print;
507      char **argv;
508 /*
509   The syntax is
510 
511   command [-p] multiplicity [ nsmax ]
512 
513   If no arguments are specified the command syntax is returned.
514   If only the multiplicity is specified then a sensible default
515   for nsmax is used (this may be too small for large calculations).
516   The -p option, which must precede the other arguments will cause
517   more printout to be generated.
518 */
519 {
520   *print = 0;
521 
522   if (argc==1 || (argc==2 && !strcmp(*(argv+1),"-p"))) {
523     (void) fprintf(stderr,"Usage: %s [-p] multiplicity [ nsmax ]\n",*argv);
524     exit(1);
525   }
526 
527   argv++;
528   argc--;
529 
530   if (!strcmp(*argv,"-p")) {
531     *print = 1;
532     argv++;
533     argc--;
534   }
535 
536   *multi = atoi(*(argv++));
537   if (argc == 1)
538     *ns = 8 + (*multi-1)%2;
539   else
540     *ns = atoi(*argv);
541 }
542 
543 /*int main(argc, argv)
544      int argc;
545      char **argv;
546      */
547 #endif
548 
549 #if (defined(CRAY) ||defined(WIN32))&& !defined(__crayx1) && !defined(__MINGW32__)
SELCI_COUPLE(Integer * pmulti,Integer * pns,Integer * pprint,char * pfilename,int flen)550 void FATR SELCI_COUPLE(Integer *pmulti, Integer *pns, Integer *pprint, char *pfilename, int flen)
551 #else
552 void FATR selci_couple_(Integer *pmulti, Integer *pns, Integer *pprint, char *pfilename, int flen)
553 #endif
554 /*
555   Generate the one particle coupling coefficients between two orbital
556   occupancies including all spin couplings. The spin functions are
557   the standard genealogical functions in the order specified by the
558   variable order. If dictionary order is used (order=1) then the matrices
559   for smaller no.s of open shells are just submatrices of the largest
560   dimension matrix. Thus order is hardwired to 1 just below, but
561   order = 0 (reverse dictionary) does work.
562 
563   n(i)=1
564         W1(u,v,i) = <Iu|Eia|Jv> = (-1)^p U(P)uv , P=(i...ns)
565 
566   n(i)=2
567         W2(u,v,i) = <Iu|Eia|Jv> = sqrt(2) (-1)^p U(P)uv , P=(1...ns)(1...i)
568 
569   i is the position of the orbital i in the open shell orbitals.
570   ns is the no. of open shells, p is the parity of P, and a is an
571   orbital higher in index (so coupled last) than any in |I>, which
572   represents an orbital occupation of the form
573 
574   |I> = d1(1)d1(2)d2(3)d2(4) ... dn(2n-1)dn(2n)dn+1(2n+1)...dn+ns(2n+ns)
575 
576   That is the ordered doubly occupied orbitals are put first and the
577   the singly occupied are ordered on the end.
578 
579   The matrices U(P) are the representation matrices for the permutation
580   P in the genealogical basis.
581 
582   The input is just the two command arguments multiplicity and ns.
583 
584   The output file 'wmatrix' is a binary stream containing the following
585 
586   multi
587   nsmax
588   (nf(i),i=multi-1,nsmax,2)
589   (((w1(u,v,i),u=1,nf(nsmax)),v=1,nf(nsmax)),i=nsmax,1)
590   (((w2(u,v,i),u=1,nf(nsmax-2)),v=1,nf(nsmax)),i=1,nsmax-1)
591 
592   multi  = multiplicity
593   nf(ns) = no. of spin functions for ns open shells
594   w1,w2 are the desired matrices. note the odd i order for w1.
595 
596   Note that in dictionary order w*(*,*,i) for ns=nsmax-m is just
597   w*(*,*,i+m).
598 
599 */
600 {
601   int order = 1;
602   static int bd[nsmax+3][nsmax+3], rbd[nsmax+3][nsmax+3];
603   static int d[nsmax][nfmax+1], f[nsmax+1][nfmax+1];
604   int ns, multi, nf, nf2, print, info;
605   static int perm[nsmax][nfmax+1], i, j, k, kk;
606   static double p[nsmax][nfmax+1], g[nsmax][nfmax+1], *u, *uu, *temp, *ttemp;
607   FILE *wmatrix;
608   char filename[255];
609 
610   /*ReadArguments(argc, argv, &ns, &multi, &print);*/
611 
612   ns = *pns;
613   multi = *pmulti;
614   if (!fortchar_to_string(pfilename, flen, filename, sizeof filename))
615       Error("couple: failed to convert fortran filename", 0);
616   info = *pprint;		/*  Information output */
617   print = 0;			/*  Debug output */
618 
619   if (info) {
620       (void) printf("\n");
621       (void) printf("      Symmetric Group Coupling Coefficient Generation Program (8/9/89)\n");
622       (void) printf("      ----------------------------------------------------------------\n\n");
623 
624       (void) printf("Maximum dimension of open shell  %2d\n",ns);
625   }
626 
627   if (ns < 0 || ns > nsmax)
628     Error("ns is invalid",ns);
629 
630   if (info) {
631       (void) printf("Multiplicity of electronic state %2d\n",multi);
632 
633       if (order == 0)
634 	  (void) printf("Spin functions will be in reverse dictionary order\n");
635       else
636 	  (void) printf("Spin functions will be in dictionary order\n");
637   }
638 
639   if (print)
640     (void) printf("High level print requested\n");
641 
642   if ( (multi<1) || (multi>ns+1) || (((multi+ns)%2) != 1) )
643     Error("multiplicity invalid or not consistent with ns",multi);
644 
645   MakeBranchingDiagram(bd, ns, multi, 0, info);
646 
647 
648   nf = bd[multi][ns];
649   if (nf > nfmax)
650     Error("number of spin functions exceeds maximum",nf);
651   nf = nf*nf*sizeof(double);
652   if ( (u = (double *) malloc((unsigned) nf)) == (double *) NULL )
653     Error("failed to allocate memory for u",nf);
654   if ( (uu = (double *) malloc((unsigned) nf)) == (double *) NULL )
655     Error("failed to allocate memory for uu",nf);
656 
657 /* open the file for coupling coefficients and write header info */
658 
659   if ( (wmatrix = fopen(filename, "w")) == (FILE *) NULL)
660     Error("failed to open file wmatrix for write",0);
661 
662   (void) fprintf(wmatrix,"%d\n%d\n",multi,ns);
663   for (i=ns%2; i<=ns; i+=2)
664     (void) fprintf(wmatrix,"%d ",bd[multi][i]);
665   (void) fprintf(wmatrix,"\n");
666 
667 /* with dictionary order can get matrices for smaller values of ns
668    from the largest value, so only make that. Using the
669    commented for loop computes the matrices for all values of ns.
670    for (i=ns%2; i<=ns; i+=2) {
671 */
672   for (i=ns; i<=ns; i+=2) {
673 
674     nf = bd[multi][i];
675     if (nf == 0)
676       continue;
677 
678     if (print) {
679       (void) printf("\n\n---------------------\n");
680       (void) printf("No. of open shells %d\n",i);
681       (void) printf("No. of functions   %d\n",nf);
682       (void) printf("---------------------\n\n");
683     }
684 
685     if (order == 0)
686       MakeSpinFunctions(bd, i, multi, f, nf, 0, info);
687     else {
688       MakeBranchingDiagram(rbd, i, multi, 1, info);
689       MakeSpinFunctions(rbd, i, multi, f, nf, 1, info);
690     }
691 
692     MakeAxialDistances(i, f, nf, d, p, g);
693 
694     if (order==0)
695       MakePerm(bd, i, f, nf, perm,0);
696     else
697       MakePerm(rbd, i, f, nf, perm,1);
698 
699 /* Make the matrices (-1)^p U(P), P=(j...m) */
700 
701     Identity(u, nf);
702     if (print) {
703       (void) printf("\n(-1)^p U(P), P=(%d...%d)\n",i,i);
704       PrintMatrix(u, 1, nf, nf, nf);
705     }
706 
707 /*  Write matrix out to disk  */
708     temp = u;
709     for (k=0; k<nf*nf; k++)
710       (void) fprintf(wmatrix,"%.14g\n",*temp++);
711 
712     for (j=i-1; j>=1; j--) {
713       LeftMultiply(j, u, uu, nf, p, g, perm);
714       temp = uu;
715       uu = u;
716       u = temp;
717 
718       Screen(nf*nf, 1.0e-8, u, 1);
719       if (print) {
720 	(void) printf("\n(-1)^p U(P), P=(%d...%d)\n",j,i);
721 	(void) printf("Sparsity of the matrix is %4.2f\n",Sparsity(nf*nf,u,1));
722 	PrintMatrix(u,1,nf,nf,nf);
723       }
724 
725 /*  Write matrix out to disk  */
726       temp = u;
727       for (k=0; k<nf*nf; k++)
728 	(void) fprintf(wmatrix,"%.14g\n",*temp++);
729 
730     }
731 
732     if (i >= 2 && (nf2 = bd[multi][i-2]) ) {
733 
734 /* Make the matrices (-1)^p sqrt(2) U(P), P=(1...m)(1...j)
735    Note that in u we already have (-1)^m U(1...m) */
736 
737       Dscal(nf*nf, sqrt(2.0), u, 1);
738 
739       if (print) {
740 	(void) printf("\n(-1)^p sqrt(2) U(P), P=(1...%d)(1...%d)\n",i,1);
741 	(void) printf("Sparsity of the matrix is %4.2f\n",Sparsity(nf*nf,u,1));
742 	PrintMatrix(u, 1, nf, nf, nf2);
743       }
744 
745 /*  Write matrix out to disk  */
746       temp = u;
747       for (k=0; k<nf; k++) {
748 	ttemp = temp;
749 	for (kk=0; kk<nf2; kk++)
750 	  (void) fprintf(wmatrix,"%.14g\n",*ttemp++);
751 	temp += nf;
752       }
753 
754       for (j=1; j<i-1; j++) {
755 	RightMultiply(j, u, uu, nf, p, g, perm);
756 	temp = uu;
757 	uu = u;
758 	u = temp;
759 
760 	Screen(nf*nf, 1.0e-8, u, 1);
761 	if (print) {
762 	  (void) printf("\n(-1)^p sqrt(2) U(P), P=(1...%d)(1...%d)\n",i,j+1);
763 	  (void) printf("Sparsity of the matrix is %4.2f\n",
764 			Sparsity(nf*nf,u,1));
765 	  PrintMatrix(u,1,nf,nf,nf2);
766 	}
767 /*  Write matrix out to disk  */
768 	temp = u;
769 	for (k=0; k<nf; k++) {
770 	  ttemp = temp;
771 	  for (kk=0; kk<nf2; kk++)
772 	    (void) fprintf(wmatrix,"%.14g\n",*ttemp++);
773 	  temp += nf;
774 	}
775 
776       }
777     }
778 
779   }
780 
781   (void) free((char *) u);
782   (void) free((char *) uu);
783   (void) fclose(wmatrix);
784 }
785 
786 
787 
788