Click here to Skip to main content
15,878,953 members
Articles / Desktop Programming / Win32

Windows Development in C++, Working with Menus

Rate me:
Please Sign up or sign in to vote.
4.96/5 (60 votes)
3 Jan 2015CPOL19 min read 171.4K   4.1K   163  
Windows API, menus, C++ lambda expressions, std::enable_shared_from_this
#include "stdafx.h"
#include <stdlib.h>
#include "hnum_slucmn.h"

#define EMPTY    (-1)
#define ROOT     (neqns)   /* dummy root of the e-tree */

namespace harlinn
{
    namespace numerics
    {
        namespace SuperLU
        {


                int
                qrnzcnt(int neqns, int adjlen, int *xadj, int *adjncy, int *zfdperm,
	                int *perm, int *invp, int *etpar, int *colcnt_h,
	                int *nlnz, int *part_super_ata, int *part_super_h)
                {
                /*
                     o 5/20/95 Xiaoye S. Li:
                         Translated from fcnthn.f using f2c;
                         Modified to use 0-based indexing in C;
                         Initialize xsup = 0 as suggested by B. Peyton to handle singletons.

                     o 5/24/95 Xiaoye S. Li:
                         Modified to compute row/column counts of R in QR factorization
                           1. Compute row counts of A, and f(i) in a separate pass
	                                        def
	                   2. Re-define hadj[k] ===   U    { j | j in Struct(A_i*), j>k}
	                                          i:f(i)==k
	                 Record supernode partition in part_super_ata[*] of size neqns:
	                   part_super_ata[k] = size of the supernode beginning at column k;
 	                                     = 0, elsewhere.

                     o 1/16/96 Xiaoye S. Li:
                         Modified to incorporate row/column counts of the Householder
	                 Matrix H in the QR factorization A --> H , R.
	 
	                 Record supernode partition in part_super_h[*] of size neqns:
	                   part_super_h[k] = size of the supernode beginning at column k;
 	                                   = 0, elsewhere.
	 
                   ***********************************************************************   
                     Version:        0.3   
                     Last modified:  January 12, 1995   
                     Authors:        Esmond G. Ng and Barry W. Peyton   

                     Mathematical Sciences Section, Oak Ridge National Laboratoy   

                   ***********************************************************************   
                   **************     FCNTHN  ..... FIND NONZERO COUNTS    ***************   
                   ***********************************************************************   

                     PURPOSE:   
                         THIS SUBROUTINE DETERMINES THE ROW COUNTS AND COLUMN COUNTS IN   
                         THE CHOLESKY FACTOR.  IT USES A DISJOINT SET UNION ALGORITHM.   

                         TECHNIQUES:   
                         1) SUPERNODE DETECTION.   
                         2) PATH HALVING.   
                         3) NO UNION BY RANK.   

                     NOTES:   
                         1) ASSUMES A POSTORDERING OF THE ELIMINATION TREE.   

                     INPUT PARAMETERS:   
                         (I) NEQNS       -   NUMBER OF EQUATIONS.   
                         (I) ADJLEN      -   LENGTH OF ADJACENCY STRUCTURE.   
                         (I) XADJ(*)     -   ARRAY OF LENGTH NEQNS+1, CONTAINING POINTERS   
                                             TO THE ADJACENCY STRUCTURE.
                         (I) ADJNCY(*)   -   ARRAY OF LENGTH ADJLEN, CONTAINING   
                                             THE ADJACENCY STRUCTURE.
                         (I) ZFDPERM(*)  -   THE ROW PERMUTATION VECTOR THAT PERMUTES THE
	                                     MATRIX TO HAVE ZERO-FREE DIAGONAL.
			                     ZFDPERM(I) = J MEANS ROW I OF THE ORIGINAL
			                     MATRIX IS IN ROW J OF THE PERMUTED MATRIX.
                         (I) PERM(*)     -   ARRAY OF LENGTH NEQNS, CONTAINING THE   
                                             POSTORDERING.   
                         (I) INVP(*)     -   ARRAY OF LENGTH NEQNS, CONTAINING THE   
                                             INVERSE OF THE POSTORDERING.   
                         (I) ETPAR(*)    -   ARRAY OF LENGTH NEQNS, CONTAINING THE   
                                             ELIMINATION TREE OF THE POSTORDERED MATRIX.   

                     OUTPUT PARAMETERS:   
                         (I) ROWCNT(*)   -   ARRAY OF LENGTH NEQNS, CONTAINING THE NUMBER   
                                             OF NONZEROS IN EACH ROW OF THE FACTOR,   
                                             INCLUDING THE DIAGONAL ENTRY.   
                         (I) COLCNT(*)   -   ARRAY OF LENGTH NEQNS, CONTAINING THE NUMBER   
                                             OF NONZEROS IN EACH COLUMN OF THE FACTOR,   
                                             INCLUDING THE DIAGONAL ENTRY.   
                         (I) NLNZ        -   NUMBER OF NONZEROS IN THE FACTOR, INCLUDING   
                                             THE DIAGONAL ENTRIES.
                         (I) PART_SUPER_ATA  SUPERNODE PARTITION IN THE CHOLESKY FACTOR
	                                     OF A'A.
	                 (I) PART_SUPER_H    SUPERNODE PARTITION IN THE HOUSEHOLDER
	                                     MATRIX H.

                     WORK PARAMETERS:   
                         (I) SET(*)      -   ARRAY OF LENGTH NEQNS USED TO MAINTAIN THE   
                                             DISJOINT SETS (I.E., SUBTREES).   
                         (I) PRVLF(*)    -   ARRAY OF LENGTH NEQNS USED TO RECORD THE   
                                             PREVIOUS LEAF OF EACH ROW SUBTREE.   
                         (I) LEVEL(*)    -   ARRAY OF LENGTH NEQNS+1 CONTAINING THE LEVEL   
                                             (DISTANCE FROM THE ROOT).   
                         (I) WEIGHT(*)   -   ARRAY OF LENGTH NEQNS+1 CONTAINING WEIGHTS   
                                             USED TO COMPUTE COLUMN COUNTS.   
                         (I) FDESC(*)    -   ARRAY OF LENGTH NEQNS+1 CONTAINING THE   
                                             FIRST (I.E., LOWEST-NUMBERED) DESCENDANT.   
                         (I) NCHILD(*)   -   ARRAY OF LENGTH NEQNS+1 CONTAINING THE   
                                             NUMBER OF CHILDREN.   
                         (I) PRVNBR(*)   -   ARRAY OF LENGTH NEQNS USED TO RECORD THE   
                                             PREVIOUS ``LOWER NEIGHBOR'' OF EACH NODE.   

                     FIRST CREATED ON    APRIL 12, 1990.   
                     LAST UPDATED ON     JANUARY 12, 1995.   

                   ***********************************************************************   
                */

                    /* Local variables */
                    int  temp, last1, last2, i, j, k, lflag, pleaf, hinbr, jstop,
	                 jstrt, ifdesc, oldnbr, parent, lownbr, lca;
                    int  xsup;        /* the ongoing supernode */
                    int  *set, *prvlf, *level, *weight, *fdesc, *nchild, *prvnbr;
                    int  *fnz;        /* first nonzero column subscript in each row */
                    int  *marker;     /* used to remove duplicate indices */
                    int  *fnz_hadj;   /* higher-numbered neighbors of the first nonzero
			                 (higher adjacency set of A'A) */
                    int  *hadj_begin; /* pointers to the fnz_hadj[] structure */
                    int  *hadj_end;   /* pointers to the fnz_hadj[] structure */

                    /* Locally malloc'd room for QR purpose */

                    /* ----------------------------------------------------------
                       FIRST set is defined as first[j] := { i : f[i] = j } ,
                       which is a collection of disjoint sets of integers between
                       0 and n-1.
                       ---------------------------------------------------------- */    
                    int  *first;    /* header pointing to FIRST set */
                    int  *firstset; /* linked list to describe FIRST set */
                    int  *weight_h; /* weights for H */
                    int  *rowcnt;   /* row colunts for Lc */ 
                    int  *colcnt;   /* column colunts for Lc */ 
                    int  *rowcnt_h; /* row colunts for H */ 
                    int  nsuper;    /* total number of fundamental supernodes in Lc */
                    int  nhnz;
    
                    set    = intMalloc(neqns);
                    prvlf  = intMalloc(neqns);
                    level  = intMalloc(neqns + 1);    /* length n+1 */
                    weight = intMalloc(neqns + 1);    /* length n+1 */
                    fdesc  = intMalloc(neqns + 1);    /* length n+1 */
                    nchild = intMalloc(neqns + 1);    /* length n+1 */
                    prvnbr = intMalloc(neqns);
                    fnz_hadj   = intMalloc(adjlen + 2*neqns + 1);
                    hadj_begin = fnz_hadj + adjlen;        /* neqns+1 */
                    hadj_end   = hadj_begin + neqns + 1;   /* neqns */
                    fnz        = set;    /* aliasing for the time being */
                    marker     = prvlf;  /*     "    "    "             */
    
                    first    = intMalloc(neqns);
                    firstset = intMalloc(neqns);
                    weight_h = intCalloc(neqns + 1);  /* length n+1 */
                    rowcnt_h = intMalloc(neqns);
                    rowcnt   = intMalloc(neqns);
                    colcnt   = intMalloc(neqns);
    
                    /* -------------------------------------------------------
                     * Compute fnz[*], first[*], nchild[*] and row counts of A.
                     * Also find supernodes in H.
                     *
                     * Note that the structure of each row of H forms a simple path in
                     * the etree between fnz[i] and i (George, Liu & Ng (1988)).
                     * The "first vertices" of the supernodes in H are characterized
                     * by the following conditions:
                     *     1) first nonzero in each row of A, i.e., fnz(i);
                     *  or 2) nchild >= 2;
                     * ------------------------------------------------------- */
                    for (k = 0; k < neqns; ++k) {
	                fnz[k] = first[k] = marker[k] = EMPTY;
	                rowcnt[k] = part_super_ata[k] = 0;
	                part_super_h[k] = 0;
	                nchild[k] = 0;
                    }
                    nchild[ROOT] = 0;
                    xsup = 0;
                    for (k = 0; k < neqns; ++k) {
	                parent = etpar[k];
	                ++nchild[parent];
	                if ( k != 0 && nchild[k] >= 2 ) {
	                    part_super_h[xsup] = k - xsup;
	                    xsup = k;
	                }
	                oldnbr = perm[k];
	                for (j = xadj[oldnbr]; j < xadj[oldnbr+1]; ++j) {
	                    /*
	                     * Renumber vertices of G(A) by postorder
	                     */
                /*	    i = invp[zfdperm[adjncy[j]]];*/
	                    i = zfdperm[adjncy[j]];
	                    ++rowcnt[i];
	                    if (fnz[i] == EMPTY) {
		                /*
		                 * Build linked list to describe FIRST sets
		                 */
		                fnz[i] = k;
		                firstset[i] = first[k];
		                first[k] = i;
		                if ( k != 0 && xsup != k ) {
		                    part_super_h[xsup] = k - xsup;
		                    xsup = k;
		                }
	                    }
	                }
                    }
                    part_super_h[xsup] = neqns - xsup;

                #ifdef CHK_NZCNT
                    printf("%8s%8s%8s\n", "k", "fnz", "first");
                    for (k = 0; k < neqns; ++k)
	                printf("%8d%8d%8d\n", k, fnz[k], first[k]);
                #endif
    
                    /* Set up fnz_hadj[*] structure. */
                    hadj_begin[0] = 0;
                    for (k = 0; k < neqns; ++k) {
	                temp = 0;
	                oldnbr = perm[k];
	                hadj_end[k] = hadj_begin[k];
	                for (j = xadj[oldnbr]; j < xadj[oldnbr+1]; ++j) {
                /*	    hinbr = invp[zfdperm[adjncy[j]]];*/
	                    hinbr = zfdperm[adjncy[j]];
	                    jstrt = fnz[hinbr];    /* first nonzero must be <= k */
	                    if ( jstrt != k && marker[jstrt] < k ) {
		                /* ----------------------------------
		                   filtering k itself and duplicates
		                   ---------------------------------- */
		                fnz_hadj[hadj_end[jstrt]] = k;
		                ++hadj_end[jstrt];
		                marker[jstrt] = k;
	                    }
	                    if ( jstrt == k ) temp += rowcnt[hinbr];
	                }
	                hadj_begin[k+1] = hadj_begin[k] + temp;
                    }

                #ifdef CHK_NZCNT
                    printf("%8s%8s\n", "k", "hadj");
                    for (k = 0; k < neqns; ++k) {
	                printf("%8d", k);
	                for (j = hadj_begin[k]; j < hadj_end[k]; ++j)
	                    printf("%8d", fnz_hadj[j]);
	                printf("\n");
                    }
                #endif
	
                    /*   --------------------------------------------------   
                         COMPUTE LEVEL(*), FDESC(*), NCHILD(*).   
                         INITIALIZE ROWCNT(*), COLCNT(*),   
                                    SET(*), PRVLF(*), WEIGHT(*), PRVNBR(*).   
                         --------------------------------------------------   */
                    level[ROOT] = 0;
                    for (k = neqns-1; k >= 0; --k) {
	                rowcnt[k] = 1;
	                colcnt[k] = 0;
	                set[k] = k;
	                prvlf[k] = EMPTY;
	                level[k] = level[etpar[k]] + 1;
	                weight[k] = 1;
	                fdesc[k] = k;
	                prvnbr[k] = EMPTY;
                    }
                    fdesc[ROOT] = EMPTY;
                    for (k = 0; k < neqns; ++k) {
	                parent = etpar[k];
	                weight[parent] = 0;
	                colcnt_h[k] = 0;
	                ifdesc = fdesc[k];
	                if (ifdesc < fdesc[parent]) {
	                    fdesc[parent] = ifdesc;
	                }
                    }

                    xsup    = 0;      /* BUG FIX */
                    nsuper = 0;
    
                    /*   ------------------------------------   
                         FOR EACH ``LOW NEIGHBOR'' LOWNBR ...   
                         ------------------------------------ */
                    for (lownbr = 0; lownbr < neqns; ++lownbr) {
	                for (i = first[lownbr]; i != EMPTY; i = firstset[i]) {
	                    rowcnt_h[i] = 1 + ( level[lownbr] - level[i] );
	                    ++weight_h[lownbr];
	                    parent = etpar[i];
	                    --weight_h[parent];
	                }
	
	                lflag  = 0;
	                ifdesc = fdesc[lownbr];
	                jstrt  = hadj_begin[lownbr];
	                jstop  = hadj_end[lownbr];
	                /*   -----------------------------------------------   
                             FOR EACH ``HIGH NEIGHBOR'', HINBR OF LOWNBR ...   
                             ----------------------------------------------- */
	                for (j = jstrt; j < jstop; ++j) {	    
	                    hinbr = fnz_hadj[j];
	                    if (hinbr > lownbr) {
                                if (ifdesc > prvnbr[hinbr]) {
		                    /*  -------------------------   
			                INCREMENT WEIGHT(LOWNBR).   
			                ------------------------- */
		                    ++weight[lownbr];
		                    pleaf = prvlf[hinbr];
		                    /*  -----------------------------------------   
			                IF HINBR HAS NO PREVIOUS ``LOW NEIGHBOR'' THEN ...   
			                ----------------------------------------- */
		                    if (pleaf == EMPTY) {
			                /* -----------------------------------------   
			                   ... ACCUMULATE LOWNBR-->HINBR PATH LENGTH   
			                       IN ROWCNT(HINBR).   
			                   ----------------------------------------- */
			                rowcnt[hinbr] = rowcnt[hinbr] +
			                                level[lownbr] - level[hinbr];
		                    } else {
			                /* -----------------------------------------   
			                   ... OTHERWISE, LCA <-- FIND(PLEAF), WHICH   
                                               IS THE LEAST COMMON ANCESTOR OF PLEAF   
                                               AND LOWNBR. (PATH HALVING.)   
			                   ----------------------------------------- */
			                last1 = pleaf;
			                last2 = set[last1];
			                lca = set[last2];
			                while ( lca != last2 ) {
			                    set[last1] = lca;
			                    last1 = lca;
			                    last2 = set[last1];
			                    lca = set[last2];
			                }
			                /* -------------------------------------   
			                   ACCUMULATE PLEAF-->LCA PATH LENGTH IN   
			                   ROWCNT(HINBR). DECREMENT WEIGHT(LCA).   
			                   ------------------------------------- */
			                rowcnt[hinbr] = rowcnt[hinbr] + 
					                level[lownbr] - level[lca];
			                --weight[lca];
		                    }
		                    /* ----------------------------------------------   
		                       LOWNBR NOW BECOMES ``PREVIOUS LEAF'' OF HINBR.   
		                       ---------------------------------------------- */
		                    prvlf[hinbr] = lownbr;
		                    lflag = 1;
        	                }
		                /* --------------------------------------------------   
		                   LOWNBR NOW BECOMES ``PREVIOUS NEIGHBOR'' OF HINBR.   
		                   -------------------------------------------------- */
		                prvnbr[hinbr] = lownbr;
	                    }
	                } /* for j ... */
	
	                /* ----------------------------------------------------   
	                   DECREMENT WEIGHT ( PARENT(LOWNBR) ).   
	                   SET ( P(LOWNBR) ) <-- SET ( P(LOWNBR) ) + SET(XSUP).   
	                   ---------------------------------------------------- */
	                parent = etpar[lownbr];
	                --weight[parent];
	                if (lflag == 1 || nchild[lownbr] >= 2) {
	                    /* lownbr is detected as the beginning of the new supernode */
	                    if ( lownbr != 0 ) part_super_ata[xsup] = lownbr - xsup;
	                    ++nsuper;
	                    xsup = lownbr;
	                } else {
	                    if ( parent == ROOT && ifdesc == lownbr ) {
		                /* lownbr is a singleton, and begins a new supernode
		                   but is not detected as doing so -- BUG FIX */
		                part_super_ata[lownbr] = 1;
		                ++nsuper;
		                xsup = lownbr;
	                    }
	                }
	                set[xsup] = parent;
                    } /* for lownbr ... */
    
                    /* ---------------------------------------------------------   
                       USE WEIGHTS TO COMPUTE COLUMN (AND TOTAL) NONZERO COUNTS.   
                       --------------------------------------------------------- */
                    *nlnz = nhnz = 0;
                    for (k = 0; k < neqns; ++k) {
	                /* for R */
	                temp = colcnt[k] + weight[k];
	                colcnt[k] = temp;
	                *nlnz += temp;
	                parent = etpar[k];
	                if (parent != ROOT) {
	                    colcnt[parent] += temp;
	                }

	                /* for H */
	                temp = colcnt_h[k] + weight_h[k];
	                colcnt_h[k] = temp;
	                nhnz += temp;
	                if (parent != ROOT) {
	                    colcnt_h[parent] += temp;	    
	                }
                    }
                    part_super_ata[xsup] = neqns - xsup;

                    /* Fix the supernode partition in H. */
    
                    free (set);
                    free (prvlf);
                    free (level);
                    free (weight);
                    free (fdesc);
                    free (nchild);
                    free (prvnbr);
                    free (fnz_hadj);

                    free (first);
                    free (firstset);
                    free (weight_h);
                    free (rowcnt_h);
                    free (rowcnt);
                    free (colcnt);
    
                #if ( PRNTlevel==1 )
                    printf(".. qrnzcnt() nlnz %d, nhnz %d, nlnz/nhnz %.2f\n", 
		                *nlnz, nhnz, (float) *nlnz/nhnz);
                #endif

                #if ( DEBUGlevel>=2 )
                    print_int_vec("part_super_h", neqns, part_super_h);
                #endif    

                    return 0;
    
                } /* qrnzcnt_ */

        };
    };
};

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Sea Surveillance AS
Norway Norway
Chief Architect - Sea Surveillance AS.

Specializing in integrated operations and high performance computing solutions.

I’ve been fooling around with computers since the early eighties, I’ve even done work on CP/M and MP/M.

Wrote my first “real” program on a BBC micro model B based on a series in a magazine at that time. It was fun and I got hooked on this thing called programming ...

A few Highlights:

  • High performance application server development
  • Model Driven Architecture and Code generators
  • Real-Time Distributed Solutions
  • C, C++, C#, Java, TSQL, PL/SQL, Delphi, ActionScript, Perl, Rexx
  • Microsoft SQL Server, Oracle RDBMS, IBM DB2, PostGreSQL
  • AMQP, Apache qpid, RabbitMQ, Microsoft Message Queuing, IBM WebSphereMQ, Oracle TuxidoMQ
  • Oracle WebLogic, IBM WebSphere
  • Corba, COM, DCE, WCF
  • AspenTech InfoPlus.21(IP21), OsiSoft PI


More information about what I do for a living can be found at: harlinn.com or LinkedIn

You can contact me at espen@harlinn.no

Comments and Discussions