Click here to Skip to main content
15,895,011 members
Articles / Programming Languages / C#

Windows Development in C++, COM API Clients

Rate me:
Please Sign up or sign in to vote.
4.98/5 (31 votes)
3 Jan 2015CPOL7 min read 63.1K   1.6K   106  
Using the Facade Pattern to simplify development with COM based APIs
#include "stdafx.h"
#include "hnum_pdsp_defs.h"

namespace harlinn
{
    namespace numerics
    {
        namespace SuperLU
        {
            void
            sp_colorder(SuperMatrix *A, int *perm_c, superlumt_options_t *options,
	                SuperMatrix *AC)
            {
            /*
                * -- SuperLU MT routine (version 2.0) --
                * Lawrence Berkeley National Lab, Univ. of California Berkeley,
                * and Xerox Palo Alto Research Center.
                * September 10, 2007
                *
                *
                * Purpose
                * =======
                *
                * sp_colorder() permutes the columns of the original matrix A into AC. 
                * It performs the following steps:
                *
                *    1. Apply column permutation perm_c[] to A's column pointers to form AC;
                *
                *    2. If options->refact = NO, then
                *       (1) Allocate etree[], and compute column etree etree[] of AC'AC;
                *       (2) Post order etree[] to get a postordered elimination tree etree[],
                *           and a postorder permutation post[];
                *       (3) Apply post[] permutation to columns of AC;
                *       (4) Overwrite perm_c[] with the product perm_c * post.
                *       (5) Allocate storage, and compute the column count (colcnt_h) and the
                *           supernode partition (part_super_h) for the Householder matrix H.
                *
                * Arguments
                * =========
                *
                * A      (input) SuperMatrix*
                *        Matrix A in A*X=B, of dimension (A->nrow, A->ncol). The number
                *        of the linear equations is A->nrow. Currently, the type of A can be:
                *        Stype = NC or NCP; Dtype = _D; Mtype = GE.
                *
                * perm_c (input/output) int*
                *	  Column permutation vector of size A->ncol, which defines the 
                *        permutation matrix Pc; perm_c[i] = j means column i of A is 
                *        in position j in A*Pc.
                *
                * options (input/output) superlumt_options_t*
                *        If options->refact = YES, then options is an
                *        input argument. The arrays etree[], colcnt_h[] and part_super_h[]
                *        are available from a previous factor and will be re-used.
                *        If options->refact = NO, then options is an output argument. 
                *
                * AC     (output) SuperMatrix*
                *        The resulting matrix after applied the column permutation
                *        perm_c[] to matrix A. The type of AC can be:
                *        Stype = NCP; Dtype = _D; Mtype = GE.
                *
                */

                NCformat  *Astore;
                NCPformat *ACstore;
                int i, n, nnz, nlnz;
                yes_no_t  refact = options->refact;
                int *etree;
                int *colcnt_h;
                int *part_super_h;
                int *iwork, *post, *iperm;
                int *invp;
                int *part_super_ata;

                n     = A->ncol;
                iwork = intMalloc(n+1);
                part_super_ata = intMalloc(n);
    
                /* Apply column permutation perm_c to A's column pointers so to
                    obtain NCP format in AC = A*Pc.  */
                AC->Stype       = SLU_NCP;
                AC->Dtype       = A->Dtype;
                AC->Mtype       = A->Mtype;
                AC->nrow        = A->nrow;
                AC->ncol        = A->ncol;
                Astore          = (NCformat*)A->Store;
                ACstore = (NCPformat*)(void *) malloc( sizeof(NCPformat) );
                AC->Store = ACstore;
                ACstore->nnz    = Astore->nnz;
                ACstore->nzval  = Astore->nzval;
                ACstore->rowind = Astore->rowind;
                ACstore->colbeg = intMalloc(n);
                ACstore->colend = intMalloc(n);
                nnz             = Astore->nnz;

            #ifdef CHK_COLORDER
                print_int_vec("pre_order:", n, perm_c);
                dcheck_perm("Initial perm_c", n, perm_c);
            #endif      

                for (i = 0; i < n; i++) {
	            ACstore->colbeg[perm_c[i]] = Astore->colptr[i]; 
	            ACstore->colend[perm_c[i]] = Astore->colptr[i+1];
                }
	
                if ( refact == NO ) {
	
	            options->etree = etree = intMalloc(n);
	            options->colcnt_h = colcnt_h = intMalloc(n);
	            options->part_super_h = part_super_h = intMalloc(n);
	
	            /* Compute the column elimination tree. */
	            sp_coletree(ACstore->colbeg, ACstore->colend, ACstore->rowind,
		                A->nrow, A->ncol, etree);
            #ifdef CHK_COLORDER	
	            print_int_vec("etree:", n, etree);
            #endif	

	            /* In symmetric mode, do not do postorder here. */
	            if ( options->SymmetricMode == NO ) {

	                /* Post order etree. */
	                post = (int *) TreePostorder(n, etree);
	                invp  = intMalloc(n);
	                for (i = 0; i < n; ++i) invp[post[i]] = i;

            #ifdef CHK_COLORDER
	                print_int_vec("post:", n+1, post);
	                dcheck_perm("post", n, post);	
            #endif	

	                /* Renumber etree in postorder. */
	                for (i = 0; i < n; ++i) iwork[post[i]] = post[etree[i]];
	                for (i = 0; i < n; ++i) etree[i] = iwork[i];

            #ifdef CHK_COLORDER	
	                print_int_vec("postorder etree:", n, etree);
            #endif

	                /* Postmultiply A*Pc by post[]. */
	                for (i = 0; i < n; ++i) iwork[post[i]] = ACstore->colbeg[i];
	                for (i = 0; i < n; ++i) ACstore->colbeg[i] = iwork[i];
	                for (i = 0; i < n; ++i) iwork[post[i]] = ACstore->colend[i];
	                for (i = 0; i < n; ++i) ACstore->colend[i] = iwork[i];

	                for (i = 0; i < n; ++i)
		            iwork[i] = post[perm_c[i]];  /* product of perm_c and post */
	                for (i = 0; i < n; ++i) perm_c[i] = iwork[i];
	                for (i = 0; i < n; ++i) invp[perm_c[i]] = i; /* inverse of perm_c*/

	                iperm = post;

            #ifdef ZFD_PERM
	                /* Permute the rows of AC to have zero-free diagonal. */
	                printf("** Permute the rows to have zero-free diagonal....\n");
	                for (i = 0; i < n; ++i)
		            iwork[i] = ACstore->colend[i] - ACstore->colbeg[i];
	                zfdperm(n, nnz, ACstore->rowind, ACstore->colbeg, iwork, iperm);
            #else
	                for (i = 0; i < n; ++i) iperm[i] = i;
            #endif	

	                /* NOTE: iperm is returned as column permutation so that
	                    * the diagonal is nonzero. Since a symmetric permutation
	                    * preserves the diagonal, we can do the following:
	                    *     P'(AP')P = P'A
	                    * That is, we apply the inverse of iperm to rows of A
	                    * to get zero-free diagonal. But since iperm is defined
	                    * in MC21A inversely as our definition of permutation,
	                    * so it is indeed an inverse for our purpose. We can
	                    * apply it directly.
	                    */
	
	                /* Determine the row and column counts in the QR factor. */
	                qrnzcnt(n, nnz, Astore->colptr, Astore->rowind, iperm,
		                invp, perm_c, etree, colcnt_h, &nlnz,
		                part_super_ata, part_super_h);

            #if 0	
	                dCheckZeroDiagonal(n, ACstore->rowind, ACstore->colbeg,
			                    ACstore->colend, iperm);
	                dPrintSuperPart("Hpart", n, part_super_h);
	                exit(0);
	                print_int_vec("iperm", n, iperm);
            #endif	
	
            #ifdef CHK_COLORDER
	                print_int_vec("Pc*post:", n, perm_c);
	                dcheck_perm("final perm_c", n, perm_c);	
            #endif

	                SUPERLU_FREE (post);
	                SUPERLU_FREE (invp);
	            }

                } /* if refact == NO */

                SUPERLU_FREE (iwork);
                SUPERLU_FREE (part_super_ata);
            }

            int
            dCheckZeroDiagonal(int n, int *rowind, int *colbeg,
		                int *colend, int *iperm)
            {
                register int i, j, nzd;

                for (j = 0; j < n; ++j) {
	            nzd = 0;
	            for (i = colbeg[j]; i < colend[j]; ++i) {
	                if ( iperm[rowind[i]] == j ) nzd = 1;
	            }
	            if ( nzd == 0 ) printf("Diagonal of column %d is zero.\n", j);
                }

                return 0;
            }

            int
            dPrintSuperPart(char *pname, int n, int *part_super)
            {
                register int i;
                FILE *fp;
                char fname[20];
                strcpy(fname, pname);
                strcat(fname, ".dat");
                fp = fopen(fname, "w");
                for (i = 0; i < n; ++i)
	            if ( part_super[i] )
	                fprintf(fp, "%8d", i);
                fprintf(fp, "%8d", n);
                fclose(fp);
                return 0;
            }

            int dcheck_perm(char *what, int n, int *perm)
            {
                register int i;
                int          *marker;
                marker = (int *) intCalloc(n);

                for (i = 0; i < n; ++i) {
	            if ( marker[perm[i]] == 1 || perm[i] >= n ) {
	                printf("%s: Not a valid PERM[%d] = %d\n", what, i, perm[i]);
	                SUPERLU_ABORT("Invalid perm.");
	            } else {
	                marker[perm[i]] = 1;
	            }
                }

                return 0;
            }

        };
    };
};

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