PRIVATE void dump_singletons
(
    Int head,		/* head of the queue */
    Int tail,		/* tail of the queue */
    Int Next [ ],	/* Next [i] is the next object after i */
    char *name,		/* "row" or "col" */
    Int Deg [ ],	/* Deg [i] is the degree of object i */
    Int n		/* objects are in the range 0 to n-1 */
)
{
    Int i, next, cnt ;
    DEBUG6 (("%s Singleton list: head "ID" tail "ID"\n", name, head, tail)) ;
    i = head ;
    ASSERT (head >= EMPTY && head < n) ;
    ASSERT (tail >= EMPTY && tail < n) ;
    cnt = 0 ;
    while (i != EMPTY)
    {
	DEBUG7 ((" "ID": "ID" deg: "ID"\n", cnt, i, Deg [i])) ;
	ASSERT (i >= 0 && i < n) ;
	next = Next [i] ;
	if (i == tail) ASSERT (next == EMPTY) ;
	i = next ;
	cnt++ ;
	ASSERT (cnt <= n) ;
    }
}
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
//
void core_scan_list_c::print_contents()
    {
    u32_t size( sizeof( *this ) );
    u64_t timestamp = core_am_tools_c::timestamp();

    for( core_scan_list_entry_s* iter = scan_list_m.first(); iter; iter = scan_list_m.next() )
        {
        const core_mac_address_s bssid(
            iter->ap_data->bssid() );
        core_ssid_s ssid(
            iter->ap_data->ssid() );    

        DEBUG6( "core_scan_list_c::print_contents() - BSSID %02X:%02X:%02X:%02X:%02X:%02X",
            bssid.addr[0], bssid.addr[1], bssid.addr[2],
            bssid.addr[3], bssid.addr[4], bssid.addr[5] );                
        DEBUG1S( "core_scan_list_c::print_contents() - SSID ",
            ssid.length, &ssid.ssid[0] );
        DEBUG1( "core_scan_list_c::print_contents() - age %u second(s)",
            static_cast<u32_t>( timestamp - iter->timestamp ) / SECONDS_FROM_MICROSECONDS );
        DEBUG1( "core_scan_list_c::print_contents() - tags 0x%02X",
            iter->tags );

        DEBUG( "core_scan_list_c::print_contents()" );
        
        size += sizeof( *iter ) + sizeof( *iter->ap_data ) +
                sizeof( *iter->ap_data->frame() ) + iter->ap_data->frame()->data_length();
        }

    DEBUG2( "core_scan_list_c::print_contents() - total size for scan list is %u bytes with %u AP(s)",
        size, count() );
    }
Example #3
0
// ---------------------------------------------------------------------------
// From class MWlanBgScanProvider.
// CWlanBgScan::NotifyChangedSettings
// ---------------------------------------------------------------------------
//
void CWlanBgScan::NotifyChangedSettings( MWlanBgScanProvider::TWlanBgScanSettings& aSettings )
    {
    DEBUG6( "CWlanBgScan::NotifyChangedSettings( interval: %u, psm srv mode: %u, peak start: %04u, peak end: %04u, peak: %u, off-peak: %u )",
            aSettings.backgroundScanInterval,
            aSettings.psmServerMode,
            aSettings.bgScanPeakStartTime,
            aSettings.bgScanPeakEndTime,
            aSettings.bgScanIntervalPeak,
            aSettings.bgScanIntervalOffPeak);
    
    // validate settings and use default values if needed
    MWlanBgScanProvider::TWlanBgScanSettings settingsToUse;
    CheckSettings( settingsToUse, aSettings ); // Note: Any PSM server mode value is allowed.
    
    // store settings for later use
    iBgScanSettings = settingsToUse;
    
    IntervalChanged();
    
    if( iCurrentPsmServerMode != iBgScanSettings.psmServerMode )
        {
        if( AwsPresence() == CWlanBgScan::EAwsPresent )
            {
            DEBUG( "CWlanBgScan::NotifyChangedSettings() - sending power mode command to AWS" );
            MWlanBgScanAwsComms::TAwsMessage msg = { MWlanBgScanAwsComms::ESetPowerSaveMode, iBgScanSettings.psmServerMode };
            iAwsComms->SendOrQueueAwsCommand( msg );
            }
        
        // remember current psm server mode
        iCurrentPsmServerMode = iBgScanSettings.psmServerMode;
        }
    
    }
PRIVATE void dump_mat
(
    char *xname,
    char *yname,
    Int nx,
    Int ny,
    const Int Xp [ ],
    const Int Xi [ ],
    Int Xdeg [ ],
    Int Ydeg [ ]
)
{
    Int x, y, p, p1, p2, xdeg, do_xdeg, ydeg ;
    DEBUG6 (("\n ==== Dump %s mat:\n", xname)) ;
    for (x = 0 ; x < nx ; x++)
    {
	p1 = Xp [x] ;
	p2 = Xp [x+1] ;
	xdeg = Xdeg [x] ;
	DEBUG6 (("Dump %s "ID" p1 "ID" p2 "ID" deg "ID"\n",
	    xname, x, p1, p2, xdeg)) ;
	do_xdeg = (xdeg >= 0) ;
	for (p = p1 ; p < p2 ; p++)
	{
	    y = Xi [p] ;
	    DEBUG7 (("    %s "ID" deg: ", yname, y)) ;
	    ASSERT (y >= 0 && y < ny) ;
	    ydeg = Ydeg [y] ;
	    DEBUG7 ((ID"\n", ydeg)) ;
	    if (do_xdeg && ydeg >= 0)
	    {
		xdeg-- ;
	    }
	}
	ASSERT (IMPLIES (do_xdeg, xdeg == 0)) ;
    }
}
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
//
void core_scan_list_c::remove_entries_by_bssid(
    const core_mac_address_s& bssid )
    {
    DEBUG6( "core_scan_list_c::remove_entries_by_bssid() - removing entries with BSSID %02X:%02X:%02X:%02X:%02X:%02X",
        bssid.addr[0], bssid.addr[1], bssid.addr[2],
        bssid.addr[3], bssid.addr[4], bssid.addr[5] );                

    core_type_list_iterator_c<core_scan_list_entry_s> iter( scan_list_m );
    for( core_scan_list_entry_s* current = iter.first(); current; current = iter.next() )
        {
        if ( current->ap_data->bssid() == bssid )
            {
            DEBUG( "core_scan_list_c::remove_entries_by_bssid() - matching entry found" );
            
            iter.remove();
            
            delete current->ap_data;
            delete current;
            current = NULL;
            }
        }
    }
// ---------------------------------------------------------
// CWlanMgmtCommandHandler::AddCipherKey
// ---------------------------------------------------------
//
void CWlanMgmtCommandHandler::AddCipherKey(
    TWlanCipherSuite aCipherSuite,
    TUint8 aKeyIndex,
    TUint32 aLength,
    const TUint8* aData,
    const TMacAddress& aMacAddr,
    TBool aUseAsDefault )
    {
    DEBUG( "CWlanMgmtCommandHandler::AddCipherKey()" );

    DEBUG1( "CWlanMgmtCommandHandler::AddCipherKey() - aCipherSuite = %u",
        aCipherSuite );       
    DEBUG1( "CWlanMgmtCommandHandler::AddCipherKey() - aKeyIndex = %u",
        aKeyIndex );
    DEBUG1( "CWlanMgmtCommandHandler::AddCipherKey() - aUseAsDefault = %u",
        aUseAsDefault );
    DEBUG6( "CWlanMgmtCommandHandler::AddCipherKey() - aMacAddr = %02X:%02X:%02X:%02X:%02X:%02X",
        aMacAddr.iMacAddress[0], aMacAddr.iMacAddress[1], aMacAddr.iMacAddress[2], 
        aMacAddr.iMacAddress[3], aMacAddr.iMacAddress[4], aMacAddr.iMacAddress[5] );        
    DEBUG1( "CWlanMgmtCommandHandler::AddCipherKey() - aLength = %u",
        aLength );
    DEBUG_BUFFER( aLength, aData );

    TAddCipherKeyMsg msg;
    msg.hdr.oid_id = E802_11_ADD_CIPHER_KEY;
    msg.cipherSuite = aCipherSuite;
    Mem::Copy( msg.data, aData, aLength );
    msg.length = aLength;
    msg.keyIndex = aKeyIndex;
    msg.macAddress = aMacAddr;
    msg.useAsDefaultKey = aUseAsDefault;    
    TPckg<TAddCipherKeyMsg> buf( msg );

    TInt err = iChannel.ManagementCommand( buf, NULL );
    if( err )
        {
        DEBUG1("ERROR calling RWlanLogicalChannel::ManagementCommand(): %d", err );
        }
    }
Example #7
0
GLOBAL void UMF_assemble
#else
GLOBAL void UMF_assemble_fixq
#endif
(
    NumericType *Numeric,
    WorkType *Work
)
{
    /* ---------------------------------------------------------------------- */
    /* local variables */
    /* ---------------------------------------------------------------------- */

    Int e, i, row, col, i2, nrows, ncols, f, tpi, extcdeg, extrdeg, rdeg0,
	cdeg0, son_list, next, nrows_to_assemble,
	ncols_to_assemble, ngetrows, j, j2,
	nrowsleft,	/* number of rows remaining in S */
	ncolsleft,	/* number of columns remaining in S */
	prior_Lson, prior_Uson, *E, *Cols, *Rows, *Wm, *Woo,
	*Row_tuples, *Row_degree, *Row_tlen,
	*Col_tuples, *Col_tlen ;
    Unit *Memory, *p ;
    Element *ep ;
    Tuple *tp, *tp1, *tp2, *tpend ;
    Entry
	*S,		/* a pointer into the contribution block of a son */
	*Fcblock,	/* current contribution block */
	*Fcol ;		/* a column of FC */
    Int *Frpos,
	*Fcpos,
	fnrows,		/* number of rows in contribution block in F */
	fncols ;	/* number of columns in contribution block in F */

#if !defined (FIXQ) || !defined (NDEBUG)
    Int *Col_degree ;
#endif

#ifndef NDEBUG
    Int n_row, n_col ;
    n_row = Work->n_row ;
    n_col = Work->n_col ;
    DEBUG3 (("::Assemble SCANS 1-4\n")) ;
    UMF_dump_current_front (Numeric, Work, TRUE) ;
#endif

#if !defined (FIXQ) || !defined (NDEBUG)
    Col_degree = Numeric->Cperm ;   /* not updated if FIXQ is true */
#endif

    /* ---------------------------------------------------------------------- */
    /* get parameters */
    /* ---------------------------------------------------------------------- */

    fncols = Work->fncols ;
    fnrows = Work->fnrows ;
    Fcpos = Work->Fcpos ;
    Frpos = Work->Frpos ;
    Row_degree = Numeric->Rperm ;
    Row_tuples = Numeric->Uip ;
    Row_tlen   = Numeric->Uilen ;
    Col_tuples = Numeric->Lip ;
    Col_tlen   = Numeric->Lilen ;
    E = Work->E ;
    Memory = Numeric->Memory ;
    Wm = Work->Wm ;
    Woo = Work->Woo ;
    rdeg0 = Work->rdeg0 ;
    cdeg0 = Work->cdeg0 ;

#ifndef NDEBUG
    DEBUG6 (("============================================\n")) ;
    DEBUG6 (("Degree update, assembly.\n")) ;
    DEBUG6 (("pivot row pattern:  fncols="ID"\n", fncols)) ;
    for (j = 0 ; j < fncols ; j++)
    {
	col = Work->Fcols [j] ;
	DEBUG6 ((ID" ", col)) ;
	ASSERT (Fcpos [col] == j * Work->fnr_curr) ;
	ASSERT (NON_PIVOTAL_COL (col)) ;
    }
    ASSERT (Fcpos [Work->pivcol] >= 0) ;
    DEBUG6 (("pivcol: "ID" pos "ID" fnr_curr "ID" fncols "ID"\n",
	Work->pivcol, Fcpos [Work->pivcol], Work->fnr_curr, fncols)) ;
    ASSERT (Fcpos [Work->pivcol] <  fncols * Work->fnr_curr) ;
    DEBUG6 (("\npivot col pattern:  fnrows="ID"\n", fnrows)) ;
    for (i = 0 ; i < fnrows ; i++)
    {
	row = Work->Frows [i] ;
	DEBUG6 ((ID" ", row)) ;
	ASSERT (Frpos [row] == i) ;
	ASSERT (NON_PIVOTAL_ROW (row)) ;
    }
    DEBUG6 (("\n")) ;
    ASSERT (Frpos [Work->pivrow] >= 0) ;
    ASSERT (Frpos [Work->pivrow] < fnrows) ;
    ASSERT (Work->Flublock == (Entry *) (Numeric->Memory + E [0])) ;
    ASSERT (Work->Fcblock == Work->Flublock + Work->nb *
	(Work->nb + Work->fnr_curr + Work->fnc_curr)) ;
#endif

    Fcblock = Work->Fcblock ;

    /* ---------------------------------------------------------------------- */
    /* determine the largest actual frontal matrix size (for Info only) */
    /* ---------------------------------------------------------------------- */

    ASSERT (fnrows == Work->fnrows_new + 1) ;
    ASSERT (fncols == Work->fncols_new + 1) ;

    Numeric->maxnrows = MAX (Numeric->maxnrows, fnrows) ;
    Numeric->maxncols = MAX (Numeric->maxncols, fncols) ;

    /* this is safe from integer overflow, since the current frontal matrix
     * is already allocated. */
    Numeric->maxfrsize = MAX (Numeric->maxfrsize, fnrows * fncols) ;

    /* ---------------------------------------------------------------------- */
    /* assemble from prior elements into the current frontal matrix */
    /* ---------------------------------------------------------------------- */

    DEBUG2 (("New assemble start [prior_element:"ID"\n", Work->prior_element)) ;

    /* Currently no rows or columns are marked.  No elements are scanned, */
    /* that is, (ep->next == EMPTY) is true for all elements */

    son_list = 0 ;	/* start creating son_list [ */

    /* ---------------------------------------------------------------------- */
    /* determine if most recent element is Lson or Uson of current front */
    /* ---------------------------------------------------------------------- */

    if (!Work->do_extend)
    {
	prior_Uson = ( Work->pivcol_in_front && !Work->pivrow_in_front) ;
	prior_Lson = (!Work->pivcol_in_front &&  Work->pivrow_in_front) ;
	if (prior_Uson || prior_Lson)
	{
	    e = Work->prior_element ;
	    if (e != EMPTY)
	    {
		ASSERT (E [e]) ;
		p = Memory + E [e] ;
		ep = (Element *) p ;
		ep->next = son_list ;
		son_list = e ;
#ifndef NDEBUG
		DEBUG2 (("e "ID" is Prior son "ID" "ID"\n",
		    e, prior_Uson, prior_Lson)) ;
		UMF_dump_element (Numeric, Work, e, FALSE) ;
#endif
		ASSERT (E [e]) ;
	    }
	}
    }
    Work->prior_element = EMPTY ;

    /* ---------------------------------------------------------------------- */
    /* SCAN1-row:  scan the element lists of each new row in the pivot col */
    /* and compute the external column degree for each frontal */
    /* ---------------------------------------------------------------------- */

    for (i2 = Work->fscan_row ; i2 < fnrows ; i2++)
    {
	/* Get a row */
	row = Work->NewRows [i2] ;
	if (row < 0) row = FLIP (row) ;
	ASSERT (row >= 0 && row < n_row) ;

	DEBUG6 (("SCAN1-row: "ID"\n", row)) ;
#ifndef NDEBUG
	UMF_dump_rowcol (0, Numeric, Work, row, FALSE) ;
#endif

	ASSERT (NON_PIVOTAL_ROW (row)) ;
	tpi = Row_tuples [row] ;
	if (!tpi) continue ;
	tp = (Tuple *) (Memory + tpi) ;
	tp1 = tp ;
	tp2 = tp ;
	tpend = tp + Row_tlen [row] ;
	for ( ; tp < tpend ; tp++)
	{
	    e = tp->e ;
	    ASSERT (e > 0 && e <= Work->nel) ;
	    if (!E [e]) continue ;	/* element already deallocated */
	    f = tp->f ;
	    p = Memory + E [e] ;
	    ep = (Element *) p ;
	    p += UNITS (Element, 1) ;
	    Rows = ((Int *) p) + ep->ncols ;
	    if (Rows [f] == EMPTY) continue ;	/* row already assembled */
	    ASSERT (row == Rows [f]) ;

	    if (ep->cdeg < cdeg0)
	    {
		/* first time seen in scan1-row */
		ep->cdeg = ep->nrowsleft + cdeg0 ;
		DEBUG6 (("e "ID" First seen: cdeg: "ID" ", e, ep->cdeg-cdeg0)) ;
		ASSERT (ep->ncolsleft > 0 && ep->nrowsleft > 0) ;
	    }

	    ep->cdeg-- ;	/* decrement external column degree */
	    DEBUG6 (("e "ID" New ext col deg: "ID"\n", e, ep->cdeg - cdeg0)) ;

	    /* this element is not yet in the new son list */
	    if (ep->cdeg == cdeg0 && ep->next == EMPTY)
	    {
		/* A new LUson or Uson has been found */
		ep->next = son_list ;
		son_list = e ;
	    }

	    ASSERT (ep->cdeg >= cdeg0) ;
	    *tp2++ = *tp ;	/* leave the tuple in the list */
	}
	Row_tlen [row] = tp2 - tp1 ;
    }

    /* ---------------------------------------------------------------------- */
    /* SCAN1-col:  scan the element lists of each new col in the pivot row */
    /*	 and compute the external row degree for each frontal */
    /* ---------------------------------------------------------------------- */

    for (j2 = Work->fscan_col ; j2 < fncols ; j2++)
    {
	/* Get a column */
	col = Work->NewCols [j2] ;
	if (col < 0) col = FLIP (col) ;
	ASSERT (col >= 0 && col < n_col) ;

	DEBUG6 (("SCAN 1-col: "ID"\n", col)) ;
#ifndef NDEBUG
	UMF_dump_rowcol (1, Numeric, Work, col, FALSE) ;
#endif

	ASSERT (NON_PIVOTAL_COL (col)) ;
	tpi = Col_tuples [col] ;
	if (!tpi) continue ;
	tp = (Tuple *) (Memory + tpi) ;
	tp1 = tp ;
	tp2 = tp ;
	tpend = tp + Col_tlen [col] ;
	for ( ; tp < tpend ; tp++)
	{
	    e = tp->e ;
	    ASSERT (e > 0 && e <= Work->nel) ;
	    if (!E [e]) continue ;	/* element already deallocated */
	    f = tp->f ;
	    p = Memory + E [e] ;
	    ep = (Element *) p ;
	    p += UNITS (Element, 1) ;
	    Cols = (Int *) p ;
	    if (Cols [f] == EMPTY) continue ;	/* column already assembled */
	    ASSERT (col == Cols [f]) ;

	    if (ep->rdeg < rdeg0)
	    {
		/* first time seen in scan1-col */
		ep->rdeg = ep->ncolsleft + rdeg0 ;
		DEBUG6 (("e "ID" First seen: rdeg: "ID" ", e, ep->rdeg-rdeg0)) ;
		ASSERT (ep->ncolsleft > 0 && ep->nrowsleft > 0) ;
	    }

	    ep->rdeg-- ;	/* decrement external row degree */
	    DEBUG6 (("e "ID" New ext row degree: "ID"\n", e, ep->rdeg-rdeg0)) ;

	    if (ep->rdeg == rdeg0 && ep->next == EMPTY)
	    {
		/* A new LUson or Lson has been found */
		ep->next = son_list ;
		son_list = e ;
	    }

	    ASSERT (ep->rdeg >= rdeg0) ;
	    *tp2++ = *tp ;	/* leave the tuple in the list */
	}
	Col_tlen [col] = tp2 - tp1 ;
    }

    /* ---------------------------------------------------------------------- */
    /* assemble new sons via full scans */
    /* ---------------------------------------------------------------------- */

    next = EMPTY ;

    for (e = son_list ; e > 0 ; e = next)
    {
	ASSERT (e > 0 && e <= Work->nel && E [e]) ;
	p = Memory + E [e] ;
	DEBUG2 (("New son: "ID"\n", e)) ;
#ifndef NDEBUG
	UMF_dump_element (Numeric, Work, e, FALSE) ;
#endif
	GET_ELEMENT (ep, p, Cols, Rows, ncols, nrows, S) ;
	nrowsleft = ep->nrowsleft ;
	ncolsleft = ep->ncolsleft ;
	next = ep->next ;
	ep->next = EMPTY ;

	extrdeg = (ep->rdeg < rdeg0) ? ncolsleft : (ep->rdeg - rdeg0) ;
	extcdeg = (ep->cdeg < cdeg0) ? nrowsleft : (ep->cdeg - cdeg0) ;
	ncols_to_assemble = ncolsleft - extrdeg ;
	nrows_to_assemble = nrowsleft - extcdeg ;
	DEBUG2 (("extrdeg "ID" extcdeg "ID"\n", extrdeg, extcdeg)) ;

	if (extrdeg == 0 && extcdeg == 0)
	{

	    /* -------------------------------------------------------------- */
	    /* this is an LUson - assemble an entire contribution block */
	    /* -------------------------------------------------------------- */

	    DEBUG6 (("LUson found: "ID"\n", e)) ;

	    if (nrows == nrowsleft)
	    {
		/* ---------------------------------------------------------- */
		/* no rows assembled out of this LUson yet */
		/* ---------------------------------------------------------- */

		/* compute the compressed column offset vector*/
		/* [ use Wm [0..nrows-1] for offsets */
#pragma ivdep
		for (i = 0 ; i < nrows ; i++)
		{
		    row = Rows [i] ;
		    Row_degree [row] -= ncolsleft ;
		    Wm [i] = Frpos [row] ;
		}

		if (ncols == ncolsleft)
		{
		    /* ------------------------------------------------------ */
		    /* no rows or cols assembled out of LUson yet */
		    /* ------------------------------------------------------ */

		    for (j = 0 ; j < ncols ; j++)
		    {
			col = Cols [j] ;
#ifndef FIXQ
			Col_degree [col] -= nrowsleft ;
#endif
			Fcol = Fcblock + Fcpos [col] ;
#pragma ivdep
			for (i = 0 ; i < nrows ; i++)
			{
			    /* Fcol [Wm [i]] += S [i] ; */
			    ASSEMBLE (Fcol [Wm [i]], S [i]) ;
			}
			S += nrows ;
		    }


		}
		else
		{
		    /* ------------------------------------------------------ */
		    /* only cols have been assembled out of LUson */
		    /* ------------------------------------------------------ */

		    for (j = 0 ; j < ncols ; j++)
		    {
			col = Cols [j] ;
			if (col >= 0)
			{
#ifndef FIXQ
			    Col_degree [col] -= nrowsleft ;
#endif
			    Fcol = Fcblock + Fcpos [col] ;
#pragma ivdep
			    for (i = 0 ; i < nrows ; i++)
			    {
				/* Fcol [Wm [i]] += S [i] ; */
				ASSEMBLE (Fcol [Wm [i]], S [i]) ;
			    }
			}
			S += nrows ;
		    }

		}
		/* ] done using Wm [0..nrows-1] for offsets */
	    }
	    else
	    {
		/* ---------------------------------------------------------- */
		/* some rows have been assembled out of this LUson */
		/* ---------------------------------------------------------- */

		/* compute the compressed column offset vector*/
		/* [ use Woo,Wm [0..nrowsleft-1] for offsets */
		ngetrows = 0 ;
		for (i = 0 ; i < nrows ; i++)
		{
		    row = Rows [i] ;
		    if (row >= 0)
		    {
			Row_degree [row] -= ncolsleft ;
			Woo [ngetrows] = i ;
			Wm [ngetrows++] = Frpos [row] ;
		    }
		}
		ASSERT (ngetrows == nrowsleft) ;

		if (ncols == ncolsleft)
		{
		    /* ------------------------------------------------------ */
		    /* only rows have been assembled out of this LUson */
		    /* ------------------------------------------------------ */

		    for (j = 0 ; j < ncols ; j++)
		    {
			col = Cols [j] ;
#ifndef FIXQ
			Col_degree [col] -= nrowsleft ;
#endif
			Fcol = Fcblock + Fcpos [col] ;
#pragma ivdep
			for (i = 0 ; i < nrowsleft ; i++)
			{
			    /* Fcol [Wm [i]] += S [Woo [i]] ; */
			    ASSEMBLE (Fcol [Wm [i]], S [Woo [i]]) ;
			}
			S += nrows ;
		    }

		}
		else
		{
		    /* ------------------------------------------------------ */
		    /* both rows and columns have been assembled out of LUson */
		    /* ------------------------------------------------------ */

		    for (j = 0 ; j < ncols ; j++)
		    {
			col = Cols [j] ;
			if (col >= 0)
			{
#ifndef FIXQ
			    Col_degree [col] -= nrowsleft ;
#endif
			    Fcol = Fcblock + Fcpos [col] ;
#pragma ivdep
			    for (i = 0 ; i < nrowsleft ; i++)
			    {
				/* Fcol [Wm [i]] += S [Woo [i]] ; */
				ASSEMBLE (Fcol [Wm [i]], S [Woo [i]]) ;
			    }
			}
			S += nrows ;
		    }

		}
		/* ] done using Woo,Wm [0..nrowsleft-1] */
	    }

	    /* deallocate the element: remove from ordered list */
	    UMF_mem_free_tail_block (Numeric, E [e]) ;
	    E [e] = 0 ;

	}
	else if (extcdeg == 0)
	{

	    /* -------------------------------------------------------------- */
	    /* this is a Uson - assemble all possible columns */
	    /* -------------------------------------------------------------- */

	    DEBUG6 (("New USON: "ID"\n", e)) ;
	    ASSERT (extrdeg > 0) ;

	    DEBUG6 (("New uson "ID" cols to do "ID"\n", e, ncols_to_assemble)) ;

	    if (ncols_to_assemble > 0)
	    {

		Int skip = FALSE ;
		if (ncols_to_assemble * 16 < ncols && nrows == 1)
		{
		    /* this is a tall and thin frontal matrix consisting of
		     * only one column (most likely an original column). Do
		     * not assemble it.   It cannot be the pivot column, since
		     * the pivot column element would be an LU son, not an Lson,
		     * of the current frontal matrix. */
		    ASSERT (nrowsleft == 1) ;
		    ASSERT (Rows [0] >= 0 && Rows [0] < Work->n_row) ;
		    skip = TRUE ;
		    Work->any_skip = TRUE ;
		}

		if (!skip)
		{

		    if (nrows == nrowsleft)
		    {
			/* -------------------------------------------------- */
			/* no rows have been assembled out of this Uson yet */
			/* -------------------------------------------------- */

			/* compute the compressed column offset vector */
			/* [ use Wm [0..nrows-1] for offsets */
#pragma ivdep
			for (i = 0 ; i < nrows ; i++)
			{
			    row = Rows [i] ;
			    ASSERT (row >= 0 && row < n_row) ;
			    Row_degree [row] -= ncols_to_assemble ;
			    Wm [i] = Frpos [row] ;
			}

			for (j = 0 ; j < ncols ; j++)
			{
			    col = Cols [j] ;
			    if ((col >= 0) && (Fcpos [col] >= 0))
			    {
#ifndef FIXQ
				Col_degree [col] -= nrowsleft ;
#endif
				Fcol = Fcblock + Fcpos [col] ;
#pragma ivdep
				for (i = 0 ; i < nrows ; i++)
				{
				    /* Fcol [Wm [i]] += S [i] ; */
				    ASSEMBLE (Fcol [Wm [i]], S [i]) ;
				}
				/* flag the column as assembled from Uson */
				Cols [j] = EMPTY ;
			    }
			    S += nrows ;
			}


			/* ] done using Wm [0..nrows-1] for offsets */
		    }
		    else
		    {
			/* -------------------------------------------------- */
			/* some rows have been assembled out of this Uson */
			/* -------------------------------------------------- */

			/* compute the compressed column offset vector*/
			/* [ use Woo,Wm [0..nrows-1] for offsets */
			ngetrows = 0 ;
			for (i = 0 ; i < nrows ; i++)
			{
			    row = Rows [i] ;
			    if (row >= 0)
			    {
				Row_degree [row] -= ncols_to_assemble ;
				ASSERT (row < n_row && Frpos [row] >= 0) ;
				Woo [ngetrows] = i ;
				Wm [ngetrows++] = Frpos [row] ;
			    }
			}
			ASSERT (ngetrows == nrowsleft) ;

			for (j = 0 ; j < ncols ; j++)
			{
			    col = Cols [j] ;
			    if ((col >= 0) && (Fcpos [col] >= 0))
			    {
#ifndef FIXQ
				Col_degree [col] -= nrowsleft ;
#endif
				Fcol = Fcblock + Fcpos [col] ;
#pragma ivdep
				for (i = 0 ; i < nrowsleft ; i++)
				{
				    /* Fcol [Wm [i]] += S [Woo [i]] ; */
				    ASSEMBLE (Fcol [Wm [i]], S [Woo [i]]) ;
				}
				/* flag the column as assembled from Uson */
				Cols [j] = EMPTY ;
			    }
			    S += nrows ;
			}

			/* ] done using Woo,Wm */
		    }
		    ep->ncolsleft = extrdeg ;
		}
	    }

	}
	else
	{

	    /* -------------------------------------------------------------- */
	    /* this is an Lson - assemble all possible rows */
	    /* -------------------------------------------------------------- */

	    DEBUG6 (("New LSON: "ID"\n", e)) ;
	    ASSERT (extrdeg == 0 && extcdeg > 0) ;

	    DEBUG6 (("New lson "ID" rows to do "ID"\n", e, nrows_to_assemble)) ;

	    if (nrows_to_assemble > 0)
	    {

		Int skip = FALSE ;
		if (nrows_to_assemble * 16 < nrows && ncols == 1)
		{
		    /* this is a tall and thin frontal matrix consisting of
		     * only one column (most likely an original column). Do
		     * not assemble it.   It cannot be the pivot column, since
		     * the pivot column element would be an LU son, not an Lson,
		     * of the current frontal matrix. */
		    ASSERT (ncolsleft == 1) ;
		    ASSERT (Cols [0] >= 0 && Cols [0] < Work->n_col) ;
		    Work->any_skip = TRUE ;
		    skip = TRUE ;
		}

		if (!skip)
		{

		    /* compute the compressed column offset vector */
		    /* [ use Woo,Wm [0..nrows-1] for offsets */
		    ngetrows = 0 ;
		    for (i = 0 ; i < nrows ; i++)
		    {
			row = Rows [i] ;
			if ((row >= 0) && (Frpos [row] >= 0))
			{
			    ASSERT (row < n_row) ;
			    Row_degree [row] -= ncolsleft ;
			    Woo [ngetrows] = i ;
			    Wm [ngetrows++] = Frpos [row] ;
			    /* flag the row as assembled from the Lson */
			    Rows [i] = EMPTY ;
			}
		    }
		    ASSERT (nrowsleft - ngetrows == extcdeg) ;
		    ASSERT (ngetrows == nrows_to_assemble) ;

		    if (ncols == ncolsleft)
		    {
			/* -------------------------------------------------- */
			/* no columns assembled out this Lson yet */
			/* -------------------------------------------------- */

			for (j = 0 ; j < ncols ; j++)
			{
			    col = Cols [j] ;
			    ASSERT (col >= 0 && col < n_col) ;
#ifndef FIXQ
			    Col_degree [col] -= nrows_to_assemble ;
#endif
			    Fcol = Fcblock + Fcpos [col] ;
#pragma ivdep
			    for (i = 0 ; i < nrows_to_assemble ; i++)
			    {
				/* Fcol [Wm [i]] += S [Woo [i]] ; */
				ASSEMBLE (Fcol [Wm [i]], S [Woo [i]]) ;
			    }
			    S += nrows ;
			}


		    }
		    else
		    {
			/* -------------------------------------------------- */
			/* some columns have been assembled out of this Lson */
			/* -------------------------------------------------- */

			for (j = 0 ; j < ncols ; j++)
			{
			    col = Cols [j] ;
			    ASSERT (col < n_col) ;
			    if (col >= 0)
			    {
#ifndef FIXQ
				Col_degree [col] -= nrows_to_assemble ;
#endif
				Fcol = Fcblock + Fcpos [col] ;
#pragma ivdep
				for (i = 0 ; i < nrows_to_assemble ; i++)
				{
				    /* Fcol [Wm [i]] += S [Woo [i]] ; */
				    ASSEMBLE (Fcol [Wm [i]], S [Woo [i]]) ;
				}
			    }
			    S += nrows ;
			}

		    }

		    /* ] done using Woo,Wm */

		    ep->nrowsleft = extcdeg ;
		}
	    }
	}
    }

    /* Note that garbage collection, and build tuples */
    /* both destroy the son list. */

    /* ] son_list now empty */

    /* ---------------------------------------------------------------------- */
    /* If frontal matrix extended, assemble old L/Usons from new rows/cols */
    /* ---------------------------------------------------------------------- */

    /* ---------------------------------------------------------------------- */
    /* SCAN2-row:  assemble rows of old Lsons from the new rows */
    /* ---------------------------------------------------------------------- */

#ifndef NDEBUG
    DEBUG7 (("Current frontal matrix: (prior to scan2-row)\n")) ;
    UMF_dump_current_front (Numeric, Work, TRUE) ;
#endif

    /* rescan the pivot row */
    if (Work->any_skip)
    {
	row_assemble (Work->pivrow, Numeric, Work) ;
    }

    if (Work->do_scan2row)
    {
	for (i2 = Work->fscan_row ; i2 < fnrows ; i2++)
	{
	    /* Get a row */
	    row = Work->NewRows [i2] ;
	    if (row < 0) row = FLIP (row) ;
	    ASSERT (row >= 0 && row < n_row) ;
	    if (!(row == Work->pivrow && Work->any_skip))
	    {
		/* assemble it */
		row_assemble (row, Numeric, Work) ;
	    }
	}
    }

    /* ---------------------------------------------------------------------- */
    /* SCAN2-col:  assemble columns of old Usons from the new columns */
    /* ---------------------------------------------------------------------- */

#ifndef NDEBUG
    DEBUG7 (("Current frontal matrix: (prior to scan2-col)\n")) ;
    UMF_dump_current_front (Numeric, Work, TRUE) ;
#endif

    /* rescan the pivot col */
    if (Work->any_skip)
    {
	col_assemble (Work->pivcol, Numeric, Work) ;
    }

    if (Work->do_scan2col)
    {

	for (j2 = Work->fscan_col ; j2 < fncols ; j2++)
	{
	    /* Get a column */
	    col = Work->NewCols [j2] ;
	    if (col < 0) col = FLIP (col) ;
	    ASSERT (col >= 0 && col < n_col) ;
	    if (!(col == Work->pivcol && Work->any_skip))
	    {
		/* assemble it */
		col_assemble (col, Numeric, Work) ;
	    }
	}
    }

    /* ---------------------------------------------------------------------- */
    /* done.  the remainder of this routine is used only when in debug mode */
    /* ---------------------------------------------------------------------- */

#ifndef NDEBUG

    /* ---------------------------------------------------------------------- */
    /* when debugging: make sure the assembly did everything that it could */
    /* ---------------------------------------------------------------------- */

    DEBUG3 (("::Assemble done\n")) ;

    for (i2 = 0 ; i2 < fnrows ; i2++)
    {
	/* Get a row */
	row = Work->Frows [i2] ;
	ASSERT (row >= 0 && row < n_row) ;

	DEBUG6 (("DEBUG SCAN 1: "ID"\n", row)) ;
	UMF_dump_rowcol (0, Numeric, Work, row, TRUE) ;

	ASSERT (NON_PIVOTAL_ROW (row)) ;
	tpi = Row_tuples [row] ;
	if (!tpi) continue ;
	tp = (Tuple *) (Memory + tpi) ;
	tpend = tp + Row_tlen [row] ;
	for ( ; tp < tpend ; tp++)
	{
	    e = tp->e ;
	    ASSERT (e > 0 && e <= Work->nel) ;
	    if (!E [e]) continue ;	/* element already deallocated */
	    f = tp->f ;
	    p = Memory + E [e] ;
	    ep = (Element *) p ;
	    p += UNITS (Element, 1) ;
	    Cols = (Int *) p ;
	    Rows = ((Int *) p) + ep->ncols ;
	    if (Rows [f] == EMPTY) continue ;	/* row already assembled */
	    ASSERT (row == Rows [f]) ;
	    extrdeg = (ep->rdeg < rdeg0) ? ep->ncolsleft : (ep->rdeg - rdeg0) ;
	    extcdeg = (ep->cdeg < cdeg0) ? ep->nrowsleft : (ep->cdeg - cdeg0) ;
	    DEBUG6 ((
		"e "ID" After assembly ext row deg: "ID" ext col degree "ID"\n",
		e, extrdeg, extcdeg)) ;

	    if (Work->any_skip)
	    {
		/* no Lsons in any row, except for very tall and thin ones */
		ASSERT (extrdeg >= 0) ;
		if (extrdeg == 0)
		{
		    /* this is an unassemble Lson */
		    ASSERT (ep->ncols == 1) ;
		    ASSERT (ep->ncolsleft == 1) ;
		    col = Cols [0] ;
		    ASSERT (col != Work->pivcol) ;
		}
	    }
	    else
	    {
		/* no Lsons in any row */
		ASSERT (extrdeg > 0) ;
		/* Uson external row degree is = number of cols left */
		ASSERT (IMPLIES (extcdeg == 0, extrdeg == ep->ncolsleft)) ;
	    }
	}
    }

    /* ---------------------------------------------------------------------- */

    for (j2 = 0 ; j2 < fncols ; j2++)
    {
	/* Get a column */
	col = Work->Fcols [j2] ;
	ASSERT (col >= 0 && col < n_col) ;

	DEBUG6 (("DEBUG SCAN 2: "ID"\n", col)) ;
#ifndef FIXQ
	UMF_dump_rowcol (1, Numeric, Work, col, TRUE) ;
#else
	UMF_dump_rowcol (1, Numeric, Work, col, FALSE) ;
#endif

	ASSERT (NON_PIVOTAL_COL (col)) ;
	tpi = Col_tuples [col] ;
	if (!tpi) continue ;
	tp = (Tuple *) (Memory + tpi) ;
	tpend = tp + Col_tlen [col] ;
	for ( ; tp < tpend ; tp++)
	{
	    e = tp->e ;
	    ASSERT (e > 0 && e <= Work->nel) ;
	    if (!E [e]) continue ;	/* element already deallocated */
	    f = tp->f ;
	    p = Memory + E [e] ;
	    ep = (Element *) p ;
	    p += UNITS (Element, 1) ;
	    Cols = (Int *) p ;
	    Rows = ((Int *) p) + ep->ncols ;
	    if (Cols [f] == EMPTY) continue ;	/* column already assembled */
	    ASSERT (col == Cols [f]) ;
	    extrdeg = (ep->rdeg < rdeg0) ? ep->ncolsleft : (ep->rdeg - rdeg0) ;
	    extcdeg = (ep->cdeg < cdeg0) ? ep->nrowsleft : (ep->cdeg - cdeg0) ;
	    DEBUG6 (("e "ID" After assembly ext col deg: "ID"\n", e, extcdeg)) ;

	    if (Work->any_skip)
	    {
		/* no Usons in any column, except for very tall and thin ones */
		ASSERT (extcdeg >= 0) ;
		if (extcdeg == 0)
		{
		    /* this is an unassemble Uson */
		    ASSERT (ep->nrows == 1) ;
		    ASSERT (ep->nrowsleft == 1) ;
		    row = Rows [0] ;
		    ASSERT (row != Work->pivrow) ;
		}
	    }
	    else
	    {
		/* no Usons in any column */
		ASSERT (extcdeg > 0) ;
		/* Lson external column degree is = number of rows left */
		ASSERT (IMPLIES (extrdeg == 0, extcdeg == ep->nrowsleft)) ;
	    }
	}
    }
#endif /* NDEBUG */
}
Example #8
0
PRIVATE void row_assemble
(
    Int row,
    NumericType *Numeric,
    WorkType *Work
)
{

    Entry *S, *Fcblock, *Frow ;
    Int tpi, e, *E, *Fcpos, *Frpos, *Row_degree, *Row_tuples, *Row_tlen, rdeg0,
	f, nrows, ncols, *Rows, *Cols, col, ncolsleft, j ;
    Tuple *tp, *tp1, *tp2, *tpend ;
    Unit *Memory, *p ;
    Element *ep ;

#ifndef FIXQ
    Int *Col_degree ;
    Col_degree = Numeric->Cperm ;
#endif

    Row_tuples = Numeric->Uip ;
    tpi = Row_tuples [row] ;
    if (!tpi) return ;

    Memory = Numeric->Memory ;
    E = Work->E ;
    Fcpos = Work->Fcpos ;
    Frpos = Work->Frpos ;
    Row_degree = Numeric->Rperm ;
    Row_tlen   = Numeric->Uilen ;
    E = Work->E ;
    Memory = Numeric->Memory ;
    rdeg0 = Work->rdeg0 ;
    Fcblock = Work->Fcblock ;

#ifndef NDEBUG
    DEBUG6 (("SCAN2-row: "ID"\n", row)) ;
    UMF_dump_rowcol (0, Numeric, Work, row, FALSE) ;
#endif

    ASSERT (NON_PIVOTAL_ROW (row)) ;

    tp = (Tuple *) (Memory + tpi) ;
    tp1 = tp ;
    tp2 = tp ;
    tpend = tp + Row_tlen [row] ;
    for ( ; tp < tpend ; tp++)
    {
	e = tp->e ;
	ASSERT (e > 0 && e <= Work->nel) ;
	if (!E [e]) continue ;	/* element already deallocated */
	f = tp->f ;
	p = Memory + E [e] ;
	ep = (Element *) p ;
	p += UNITS (Element, 1) ;
	Cols = (Int *) p ;
	Rows = Cols + ep->ncols ;
	if (Rows [f] == EMPTY) continue ;   /* row already assembled */
	ASSERT (row == Rows [f] && row >= 0 && row < Work->n_row) ;

	if (ep->rdeg == rdeg0)
	{
	    /* ------------------------------------------------------ */
	    /* this is an old Lson - assemble just one row */
	    /* ------------------------------------------------------ */

	    /* flag the row as assembled from the Lson */
	    Rows [f] = EMPTY ;

	    nrows = ep->nrows ;
	    ncols = ep->ncols ;

	    p += UNITS (Int, ncols + nrows) ;
	    S = ((Entry *) p) + f ;

	    DEBUG6 (("Old LSON: "ID"\n", e)) ;
#ifndef NDEBUG
	    UMF_dump_element (Numeric, Work, e, FALSE) ;
#endif

	    ncolsleft = ep->ncolsleft ;

	    Frow = Fcblock + Frpos [row] ;
	    DEBUG6 (("LSON found (in scan2-row): "ID"\n", e)) ;

	    Row_degree [row] -= ncolsleft ;

	    if (ncols == ncolsleft)
	    {
		/* -------------------------------------------------- */
		/* no columns assembled out this Lson yet */
		/* -------------------------------------------------- */

#pragma ivdep
		for (j = 0 ; j < ncols ; j++)
		{
		    col = Cols [j] ;
		    ASSERT (col >= 0 && col < Work->n_col) ;
#ifndef FIXQ
		    Col_degree [col] -- ;
#endif
		    /* Frow [Fcpos [col]] += *S ; */
		    ASSEMBLE (Frow [Fcpos [col]], *S) ;
		    S += nrows ;
		}

	    }
	    else
	    {
		/* -------------------------------------------------- */
		/* some columns have been assembled out of this Lson */
		/* -------------------------------------------------- */

#pragma ivdep
		for (j = 0 ; j < ncols ; j++)
		{
		    col = Cols [j] ;
		    if (col >= 0)
		    {
			ASSERT (col < Work->n_col) ;
#ifndef FIXQ
			Col_degree [col] -- ;
#endif
			/* Frow [Fcpos [col]] += *S ; */
			ASSEMBLE (Frow [Fcpos [col]], *S) ;
		    }
		    S += nrows ;
		}

	    }
	    ep->nrowsleft-- ;
	    ASSERT (ep->nrowsleft > 0) ;
	}
	else
	{
	    *tp2++ = *tp ;	/* leave the tuple in the list */
	}
    }
    Row_tlen [row] = tp2 - tp1 ;

#ifndef NDEBUG
    DEBUG7 (("row assembled in scan2-row: "ID"\n", row)) ;
    UMF_dump_rowcol (0, Numeric, Work, row, FALSE) ;
    DEBUG7 (("Current frontal matrix: (scan 1b)\n")) ;
    UMF_dump_current_front (Numeric, Work, TRUE) ;
#endif
}
Example #9
0
PRIVATE void col_assemble
(
    Int col,
    NumericType *Numeric,
    WorkType *Work
)
{

    Entry *S, *Fcblock, *Fcol ;
    Int tpi, e, *E, *Fcpos, *Frpos, *Row_degree, *Col_tuples, *Col_tlen, cdeg0,
	f, nrows, ncols, *Rows, *Cols, row, nrowsleft, i ;
    Tuple *tp, *tp1, *tp2, *tpend ;
    Unit *Memory, *p ;
    Element *ep ;

#if !defined (FIXQ) || !defined (NDEBUG)
    Int *Col_degree ;
    Col_degree = Numeric->Cperm ;
#endif

    Col_tuples = Numeric->Lip ;
    tpi = Col_tuples [col] ;
    if (!tpi) return ;

    Memory = Numeric->Memory ;
    E = Work->E ;
    Fcpos = Work->Fcpos ;
    Frpos = Work->Frpos ;
    Row_degree = Numeric->Rperm ;
    Col_tlen   = Numeric->Lilen ;
    E = Work->E ;
    Memory = Numeric->Memory ;
    cdeg0 = Work->cdeg0 ;
    Fcblock = Work->Fcblock ;

    DEBUG6 (("SCAN2-col: "ID"\n", col)) ;
#ifndef NDEBUG
    UMF_dump_rowcol (1, Numeric, Work, col, FALSE) ;
#endif

    ASSERT (NON_PIVOTAL_COL (col)) ;
    tp = (Tuple *) (Memory + tpi) ;
    tp1 = tp ;
    tp2 = tp ;
    tpend = tp + Col_tlen [col] ;
    for ( ; tp < tpend ; tp++)
    {
	e = tp->e ;
	ASSERT (e > 0 && e <= Work->nel) ;
	if (!E [e]) continue ;	/* element already deallocated */
	f = tp->f ;
	p = Memory + E [e] ;
	ep = (Element *) p ;
	p += UNITS (Element, 1) ;
	Cols = (Int *) p ;

	if (Cols [f] == EMPTY) continue ;   /* col already assembled */
	ASSERT (col == Cols [f] && col >= 0 && col < Work->n_col) ;

	if (ep->cdeg == cdeg0)
	{
	    /* ------------------------------------------------------ */
	    /* this is an old Uson - assemble just one col */
	    /* ------------------------------------------------------ */

	    /* flag the col as assembled from the Uson */
	    Cols [f] = EMPTY ;

	    nrows = ep->nrows ;
	    ncols = ep->ncols ;
	    Rows = Cols + ncols ;
	    p += UNITS (Int, ncols + nrows) ;
	    S = ((Entry *) p) + f * nrows ;

	    DEBUG6 (("Old USON: "ID"\n", e)) ;
#ifndef NDEBUG
	    UMF_dump_element (Numeric, Work, e, FALSE) ;
#endif

	    nrowsleft = ep->nrowsleft ;

	    Fcol = Fcblock + Fcpos [col] ;
	    DEBUG6 (("USON found (in scan2-col): "ID"\n", e)) ;
#ifndef FIXQ
	    Col_degree [col] -= nrowsleft ;
#endif
	    if (nrows == nrowsleft)
	    {
		/* -------------------------------------------------- */
		/* no rows assembled out of this Uson yet */
		/* -------------------------------------------------- */

#pragma ivdep
		for (i = 0 ; i < nrows ; i++)
		{
		    row = Rows [i] ;
		    ASSERT (row >= 0 && row < Work->n_row) ;
		    Row_degree [row]-- ;
		    /* Fcol [Frpos [row]] += S [i] ; */
		    ASSEMBLE (Fcol [Frpos [row]], S [i]) ;
		}
	    }
	    else
	    {
		/* -------------------------------------------------- */
		/* some rows have been assembled out of this Uson */
		/* -------------------------------------------------- */

#pragma ivdep
		for (i = 0 ; i < nrows ; i++)
		{
		    row = Rows [i] ;
		    if (row >= 0)
		    {
			ASSERT (row < Work->n_row) ;
			Row_degree [row]-- ;
			/* Fcol [Frpos [row]] += S [i] ; */
			ASSEMBLE (Fcol [Frpos [row]], S [i]) ;
		    }
		}
	    }
	    ep->ncolsleft-- ;
	    ASSERT (ep->ncolsleft > 0) ;
	}
	else
	{
	    *tp2++ = *tp ;	/* leave the tuple in the list */
	}
    }
    Col_tlen [col] = tp2 - tp1 ;

#ifndef NDEBUG
    DEBUG7 (("Column assembled in scan2-col: "ID"\n", col)) ;
    UMF_dump_rowcol (1, Numeric, Work, col, FALSE) ;
    DEBUG7 (("Current frontal matrix: after scan2-col\n")) ;
    UMF_dump_current_front (Numeric, Work, TRUE) ;
#endif

}
Example #10
0
GLOBAL Int UMF_extend_front
(
    NumericType *Numeric,
    WorkType *Work
)
{
    /* ---------------------------------------------------------------------- */
    /* local variables */
    /* ---------------------------------------------------------------------- */

    Int j, i, *Frows, row, col, *Wrow, fnr2, fnc2, *Frpos, *Fcpos, *Fcols,
	fnrows_extended, rrdeg, ccdeg, fncols_extended, fnr_curr, fnc_curr,
	fnrows, fncols, pos, fnpiv, *Wm ;
    Entry *Wx, *Wy, *Fu, *Fl ;

    /* ---------------------------------------------------------------------- */
    /* get current frontal matrix and check for frontal growth */
    /* ---------------------------------------------------------------------- */

    fnpiv = Work->fnpiv ;

#ifndef NDEBUG
    DEBUG2 (("EXTEND FRONT\n")) ;
    DEBUG2 (("Work->fnpiv "ID"\n", fnpiv)) ;
    ASSERT (Work->Flblock  == Work->Flublock + Work->nb*Work->nb) ;
    ASSERT (Work->Fublock  == Work->Flblock  + Work->fnr_curr*Work->nb) ;
    ASSERT (Work->Fcblock  == Work->Fublock  + Work->nb*Work->fnc_curr) ;
    DEBUG7 (("C  block: ")) ;
    UMF_dump_dense (Work->Fcblock,  Work->fnr_curr, Work->fnrows, Work->fncols) ;
    DEBUG7 (("L  block: ")) ;
    UMF_dump_dense (Work->Flblock,  Work->fnr_curr, Work->fnrows, fnpiv);
    DEBUG7 (("U' block: ")) ;
    UMF_dump_dense (Work->Fublock,  Work->fnc_curr, Work->fncols, fnpiv) ;
    DEBUG7 (("LU block: ")) ;
    UMF_dump_dense (Work->Flublock, Work->nb, fnpiv, fnpiv) ;
#endif

    if (Work->do_grow)
    {
	fnr2 = UMF_FRONTAL_GROWTH * Work->fnrows_new + 2 ;
	fnc2 = UMF_FRONTAL_GROWTH * Work->fncols_new + 2 ;
	if (!UMF_grow_front (Numeric, fnr2, fnc2, Work, 1))
	{
	    DEBUGm4 (("out of memory: extend front\n")) ;
	    return (FALSE) ;
	}
    }

    fnr_curr = Work->fnr_curr ;
    fnc_curr = Work->fnc_curr ;
    ASSERT (Work->fnrows_new + 1 <= fnr_curr) ;
    ASSERT (Work->fncols_new + 1 <= fnc_curr) ;
    ASSERT (fnr_curr >= 0 && fnr_curr % 2 == 1) ;

    /* ---------------------------------------------------------------------- */
    /* get parameters */
    /* ---------------------------------------------------------------------- */

    Frows = Work->Frows ;
    Frpos = Work->Frpos ;
    Fcols = Work->Fcols ;
    Fcpos = Work->Fcpos ;
    fnrows = Work->fnrows ;
    fncols = Work->fncols ;
    rrdeg = Work->rrdeg ;
    ccdeg = Work->ccdeg ;

    /* scan starts at the first new column in Fcols */
    /* also scan the pivot column if it was not in the front */
    Work->fscan_col = fncols ;
    Work->NewCols = Fcols ;

    /* scan1 starts at the first new row in Frows */
    /* also scan the pivot row if it was not in the front */
    Work->fscan_row = fnrows ;
    Work->NewRows = Frows ;

    /* ---------------------------------------------------------------------- */
    /* extend row pattern of the front with the new pivot column */
    /* ---------------------------------------------------------------------- */

    fnrows_extended = fnrows ;
    fncols_extended = fncols ;

#ifndef NDEBUG
    DEBUG2 (("Pivot col, before extension: "ID"\n", fnrows)) ;
    for (i = 0 ; i < fnrows ; i++)
    {
	DEBUG2 ((" "ID": row "ID"\n", i, Frows [i])) ;
	ASSERT (Frpos [Frows [i]] == i) ;
    }
    DEBUG2 (("Extending pivot column: pivcol_in_front: "ID"\n",
	Work->pivcol_in_front)) ;
#endif

    Fl = Work->Flblock + fnpiv * fnr_curr ;

    if (Work->pivcol_in_front)
    {
	/* extended pattern and position already in Frows, Frpos.  Values above
	 * the diagonal are already in LU block.  Values on and below the
	 * diagonal are in Wy [0 .. fnrows_extended-1].  Copy into the L
	 * block. */
	fnrows_extended += ccdeg ;
	Wy = Work->Wy ;

	for (i = 0 ; i < fnrows_extended ; i++)
	{
	    Fl [i] = Wy [i] ;
#ifndef NDEBUG
	    row = Frows [i] ;
	    DEBUG2 ((" "ID": row "ID" ", i, row)) ;
	    EDEBUG2 (Fl [i]) ;
	    if (row == Work->pivrow) DEBUG2 ((" <- pivrow")) ;
	    DEBUG2 (("\n")) ;
	    if (i == fnrows - 1) DEBUG2 ((" :::::::\n")) ;
	    ASSERT (row >= 0 && row < Work->n_row) ;
	    ASSERT (Frpos [row] == i) ;
#endif
	}

    }
    else
    {
	/* extended pattern,values is in (Wm,Wx), not yet in the front */
	Entry *F ;
	Fu = Work->Flublock + fnpiv * Work->nb ;
	Wm = Work->Wm ;
	Wx = Work->Wx ;
	F = Fu ;
	for (i = 0 ; i < fnpiv ; i++)
	{
	    CLEAR_AND_INCREMENT (F) ;
	}
	F = Fl ;
	for (i = 0 ; i < fnrows ; i++)
	{
	    CLEAR_AND_INCREMENT (F) ;
	}
	for (i = 0 ; i < ccdeg ; i++)
	{
	    row = Wm [i] ;
#ifndef NDEBUG
	    DEBUG2 ((" "ID": row "ID" (ext) ", fnrows_extended, row)) ;
	    EDEBUG2 (Wx [i]) ;
	    if (row == Work->pivrow) DEBUG2 ((" <- pivrow")) ;
	    DEBUG2 (("\n")) ;
	    ASSERT (row >= 0 && row < Work->n_row) ;
#endif
	    pos = Frpos [row] ;
	    if (pos < 0)
	    {
		pos = fnrows_extended++ ;
		Frows [pos] = row ;
		Frpos [row] = pos ;
	    }
	    Fl [pos] = Wx [i] ;
	}
    }

    ASSERT (fnrows_extended <= fnr_curr) ;

    /* ---------------------------------------------------------------------- */
    /* extend the column pattern of the front with the new pivot row */
    /* ---------------------------------------------------------------------- */

#ifndef NDEBUG
    DEBUG6 (("Pivot row, before extension: "ID"\n", fncols)) ;
    for (j = 0 ; j < fncols ; j++)
    {
	DEBUG7 ((" "ID": col "ID"\n", j, Fcols [j])) ;
	ASSERT (Fcpos [Fcols [j]] == j * fnr_curr) ;
    }
    DEBUG6 (("Extending pivot row:\n")) ;
#endif

    if (Work->pivrow_in_front)
    {
	if (Work->pivcol_in_front)
	{
	    ASSERT (Fcols == Work->Wrow) ;
	    for (j = fncols ; j < rrdeg ; j++)
	    {
#ifndef NDEBUG
		col = Fcols [j] ;
		DEBUG2 ((" "ID": col "ID" (ext)\n", j, col)) ;
		ASSERT (col != Work->pivcol) ;
		ASSERT (col >= 0 && col < Work->n_col) ;
		ASSERT (Fcpos [col] < 0) ;
#endif
		Fcpos [Fcols [j]] = j * fnr_curr ;
	    }
	}
	else
	{
	    /* OUT-IN option: pivcol not in front, but pivrow is in front */
	    Wrow = Work->Wrow ;
	    ASSERT (IMPLIES (Work->pivcol_in_front, Wrow == Fcols)) ;
	    if (Wrow == Fcols)
	    {
		/* Wrow and Fcols are equivalenced */
		for (j = fncols ; j < rrdeg ; j++)
		{
		    col = Wrow [j] ;
		    DEBUG2 ((" "ID": col "ID" (ext)\n", j, col)) ;
		    ASSERT (Fcpos [col] < 0) ;
		    /* Fcols [j] = col ;  not needed */
		    Fcpos [col] = j * fnr_curr ;
		}
	    }
	    else
	    {
		for (j = fncols ; j < rrdeg ; j++)
		{
		    col = Wrow [j] ;
		    DEBUG2 ((" "ID": col "ID" (ext)\n", j, col)) ;
		    ASSERT (Fcpos [col] < 0) ;
		    Fcols [j] = col ;
		    Fcpos [col] = j * fnr_curr ;
		}
	    }
	}
	fncols_extended = rrdeg ;
    }
    else
    {
	ASSERT (Fcols != Work->Wrow) ;
	Wrow = Work->Wrow ;
	for (j = 0 ; j < rrdeg ; j++)
	{
	    col = Wrow [j] ;
	    ASSERT (col >= 0 && col < Work->n_col) ;
	    if (Fcpos [col] < 0)
	    {
		DEBUG2 ((" col:: "ID" (ext)\n", col)) ;
		Fcols [fncols_extended] = col ;
		Fcpos [col] = fncols_extended * fnr_curr ;
		fncols_extended++ ;
	    }
	}
    }

    /* ---------------------------------------------------------------------- */
    /* pivot row and column have been extended */
    /* ---------------------------------------------------------------------- */

#ifndef NDEBUG
    ASSERT (fncols_extended <= fnc_curr) ;
    ASSERT (fnrows_extended <= fnr_curr) ;

    DEBUG6 (("Pivot col, after ext: "ID" "ID"\n", fnrows,fnrows_extended)) ;
    for (i = 0 ; i < fnrows_extended ; i++)
    {
	row = Frows [i] ;
	DEBUG7 ((" "ID": row "ID" pos "ID" old: %d", i, row, Frpos [row],
	    i < fnrows)) ;
	if (row == Work->pivrow ) DEBUG7 (("  <-- pivrow")) ;
	DEBUG7 (("\n")) ;
	ASSERT (Frpos [Frows [i]] == i) ;
    }

    DEBUG6 (("Pivot row position: "ID"\n", Frpos [Work->pivrow])) ;
    ASSERT (Frpos [Work->pivrow] >= 0) ;
    ASSERT (Frpos [Work->pivrow] < fnrows_extended) ;

    DEBUG6 (("Pivot row, after ext: "ID" "ID"\n", fncols,fncols_extended)) ;
    for (j = 0 ; j < fncols_extended ; j++)
    {
	col = Fcols [j] ;
	DEBUG7 ((" "ID": col "ID" pos "ID" old: %d", j, col, Fcpos [col],
	    j < fncols)) ;
	if (col == Work->pivcol ) DEBUG7 (("  <-- pivcol")) ;
	DEBUG7 (("\n")) ;
	ASSERT (Fcpos [Fcols [j]] == j * fnr_curr) ;
    }

    DEBUG6 (("Pivot col position: "ID"\n", Fcpos [Work->pivcol])) ;
    ASSERT (Fcpos [Work->pivcol] >= 0) ;
    ASSERT (Fcpos [Work->pivcol] < fncols_extended * fnr_curr) ;

#endif

    /* ---------------------------------------------------------------------- */
    /* Zero the newly extended frontal matrix */
    /* ---------------------------------------------------------------------- */

    zero_front (Work->Flblock, Work->Fublock, Work->Fcblock,
	fnrows, fncols, fnr_curr, fnc_curr,
	fnpiv, fnrows_extended, fncols_extended) ;

    /* ---------------------------------------------------------------------- */
    /* finalize extended row and column pattern of the frontal matrix */
    /* ---------------------------------------------------------------------- */

    Work->fnrows = fnrows_extended ;
    Work->fncols = fncols_extended ;

    ASSERT (fnrows_extended == Work->fnrows_new + 1) ;
    ASSERT (fncols_extended == Work->fncols_new + 1) ;

    return (TRUE) ;

}
Example #11
0
PRIVATE void get_U
(
    Int Up [ ],		/* of size n_col+1 */
    Int Ui [ ],		/* of size unz, where unz = Up [n_col] */
    double Ux [ ],	/* of size unz */
#ifdef COMPLEX
    double Uz [ ],	/* of size unz */
#endif
    NumericType *Numeric,
    Int Pattern [ ],	/* workspace of size n_col */
    Int Wi [ ]		/* workspace of size n_col */
)
{
    /* ---------------------------------------------------------------------- */
    /* local variables */
    /* ---------------------------------------------------------------------- */

    Entry value ;
    Entry *xp, *D, *Uval ;
    Int deg, j, *ip, col, *Upos, *Uilen, *Uip, n_col, ulen, *Usi,
        unz2, p, k, up, newUchain, pos, npiv, n1 ;
#ifdef COMPLEX
    Int split = SPLIT (Uz) ;
#endif
#ifndef NDEBUG
    Int nnzpiv = 0 ;
#endif

    /* ---------------------------------------------------------------------- */
    /* get parameters */
    /* ---------------------------------------------------------------------- */

    DEBUG4 (("get_U start:\n")) ;
    n_col = Numeric->n_col ;
    n1 = Numeric->n1 ;
    npiv = Numeric->npiv ;
    Upos = Numeric->Upos ;
    Uilen = Numeric->Uilen ;
    Uip = Numeric->Uip ;
    D = Numeric->D ;

    /* ---------------------------------------------------------------------- */
    /* count the nonzeros in each column of U */
    /* ---------------------------------------------------------------------- */

    for (col = 0 ; col < npiv ; col++)
    {
	/* include the diagonal entry in the column counts */
	DEBUG4 (("D ["ID"] = ", col)) ;
	EDEBUG4 (D [col]) ;
	Wi [col] = IS_NONZERO (D [col]) ;
	DEBUG4 ((" is nonzero: "ID"\n", Wi [col])) ;
#ifndef NDEBUG
	nnzpiv += IS_NONZERO (D [col]) ;
#endif
    }
    DEBUG4 (("nnzpiv "ID" "ID"\n", nnzpiv, Numeric->nnzpiv)) ;
    ASSERT (nnzpiv == Numeric->nnzpiv) ;
    for (col = npiv ; col < n_col ; col++)
    {
	/* diagonal entries are zero for structurally singular part */
	Wi [col] = 0 ;
    }

    deg = Numeric->ulen ;
    if (deg > 0)
    {
	/* make last pivot row of U (singular matrices only) */
	DEBUG0 (("Last pivot row of U: ulen "ID"\n", deg)) ;
	for (j = 0 ; j < deg ; j++)
	{
	    Pattern [j] = Numeric->Upattern [j] ;
	    DEBUG0 (("    column "ID"\n", Pattern [j])) ;
	}
    }

    /* non-singletons */
    for (k = npiv-1 ; k >= n1 ; k--)
    {

	/* ------------------------------------------------------------------ */
	/* use row k of U */
	/* ------------------------------------------------------------------ */

	up = Uip [k] ;
	ulen = Uilen [k] ;
	newUchain = (up < 0) ;
	if (newUchain)
	{
	    up = -up ;
	    xp = (Entry *) (Numeric->Memory + up + UNITS (Int, ulen)) ;
	}
	else
	{
	    xp = (Entry *) (Numeric->Memory + up) ;
	}

	for (j = 0 ; j < deg ; j++)
	{
	    DEBUG4 (("  k "ID" col "ID" value\n", k, Pattern [j])) ;
	    col = Pattern [j] ;
	    ASSERT (col >= 0 && col < n_col) ;
	    value = *xp++ ;
	    EDEBUG4 (value) ;
	    DEBUG4 (("\n")) ;
	    if (IS_NONZERO (value))
	    {
		Wi [col]++ ;
	    }
	}

	/* ------------------------------------------------------------------ */
	/* make row k-1 of U in Pattern [0..deg-1] */
	/* ------------------------------------------------------------------ */

	if (k == n1) break ;

	if (newUchain)
	{
	    /* next row is a new Uchain */
	    deg = ulen ;
	    DEBUG4 (("end of chain for row of U "ID" deg "ID"\n", k-1, deg)) ;
	    ip = (Int *) (Numeric->Memory + up) ;
	    for (j = 0 ; j < deg ; j++)
	    {
		col = *ip++ ;
		DEBUG4 (("  k "ID" col "ID"\n", k-1, col)) ;
		ASSERT (k <= col) ;
		Pattern [j] = col ;
	    }
	}
	else
	{
	    deg -= ulen ;
	    DEBUG4 (("middle of chain for row of U "ID" deg "ID"\n", k-1, deg));
	    ASSERT (deg >= 0) ;
	    pos = Upos [k] ;
	    if (pos != EMPTY)
	    {
		/* add the pivot column */
		DEBUG4 (("k "ID" add pivot entry at position "ID"\n", k, pos)) ;
		ASSERT (pos >= 0 && pos <= deg) ;
		Pattern [deg++] = Pattern [pos] ;
		Pattern [pos] = k ;
	    }
	}
    }

    /* singletons */
    for (k = n1 - 1 ; k >= 0 ; k--)
    {
	deg = Uilen [k] ;
	DEBUG4 (("Singleton k "ID"\n", k)) ;
	if (deg > 0)
	{
	    up = Uip [k] ;
	    Usi = (Int *) (Numeric->Memory + up) ;
	    up += UNITS (Int, deg) ;
	    Uval = (Entry *) (Numeric->Memory + up) ;
	    for (j = 0 ; j < deg ; j++)
	    {
		col = Usi [j] ;
		value = Uval [j] ;
		DEBUG4 (("  k "ID" col "ID" value", k, col)) ;
		EDEBUG4 (value) ;
		DEBUG4 (("\n")) ;
		if (IS_NONZERO (value))
		{
		    Wi [col]++ ;
		}
	    }
	}
    }

    /* ---------------------------------------------------------------------- */
    /* construct the final column form of U */
    /* ---------------------------------------------------------------------- */

    /* create the column pointers */
    unz2 = 0 ;
    for (col = 0 ; col < n_col ; col++)
    {
	Up [col] = unz2 ;
	unz2 += Wi [col] ;
    }
    Up [n_col] = unz2 ;
    DEBUG1 (("Numeric->unz "ID"  npiv "ID" nnzpiv "ID" unz2 "ID"\n",
	Numeric->unz, npiv, Numeric->nnzpiv, unz2)) ;
    ASSERT (Numeric->unz + Numeric->nnzpiv == unz2) ;

    for (col = 0 ; col < n_col ; col++)
    {
	Wi [col] = Up [col+1] ;
    }

    /* add all of the diagonal entries */
    for (col = 0 ; col < npiv ; col++)
    {
	if (IS_NONZERO (D [col]))
	{
	    p = --(Wi [col]) ;
	    Ui [p] = col ;
#ifdef COMPLEX
	    if (split)
	    {

	        Ux [p] = REAL_COMPONENT (D [col]) ;
		Uz [p] = IMAG_COMPONENT (D [col]) ;
	    }
	    else
	    {
		Ux [2*p  ] = REAL_COMPONENT (D [col]) ;
		Ux [2*p+1] = IMAG_COMPONENT (D [col]) ;
	    }
#else
	    Ux [p] = D [col] ;
#endif
	}
    }

    /* add all the entries from the rows of U */

    deg = Numeric->ulen ;
    if (deg > 0)
    {
	/* make last pivot row of U (singular matrices only) */
	for (j = 0 ; j < deg ; j++)
	{
	    Pattern [j] = Numeric->Upattern [j] ;
	}
    }

    /* non-singletons */
    for (k = npiv-1 ; k >= n1 ; k--)
    {

	/* ------------------------------------------------------------------ */
	/* use row k of U */
	/* ------------------------------------------------------------------ */

	up = Uip [k] ;
	ulen = Uilen [k] ;
	newUchain = (up < 0) ;
	if (newUchain)
	{
	    up = -up ;
	    xp = (Entry *) (Numeric->Memory + up + UNITS (Int, ulen)) ;
	}
	else
	{
	    xp = (Entry *) (Numeric->Memory + up) ;
	}

	xp += deg ;
	for (j = deg-1 ; j >= 0 ; j--)
	{
	    DEBUG4 (("  k "ID" col "ID" value", k, Pattern [j])) ;
	    col = Pattern [j] ;
	    ASSERT (col >= 0 && col < n_col) ;
	    value = *(--xp) ;
	    EDEBUG4 (value) ;
	    DEBUG4 (("\n")) ;
	    if (IS_NONZERO (value))
	    {
		p = --(Wi [col]) ;
		Ui [p] = k ;
#ifdef COMPLEX
		if (split)
		{
		    Ux [p] = REAL_COMPONENT (value) ;
		    Uz [p] = IMAG_COMPONENT (value) ;
		}
		else
		{
		    Ux [2*p  ] = REAL_COMPONENT (value) ;
		    Ux [2*p+1] = IMAG_COMPONENT (value) ;
		}
#else
		Ux [p] = value ;
#endif

	    }
	}

	/* ------------------------------------------------------------------ */
	/* make row k-1 of U in Pattern [0..deg-1] */
	/* ------------------------------------------------------------------ */

	if (newUchain)
	{
	    /* next row is a new Uchain */
	    deg = ulen ;
	    DEBUG4 (("end of chain for row of U "ID" deg "ID"\n", k-1, deg)) ;
	    ip = (Int *) (Numeric->Memory + up) ;
	    for (j = 0 ; j < deg ; j++)
	    {
		col = *ip++ ;
		DEBUG4 (("  k "ID" col "ID"\n", k-1, col)) ;
		ASSERT (k <= col) ;
		Pattern [j] = col ;
	    }
	}
	else
	{
	    deg -= ulen ;
	    DEBUG4 (("middle of chain for row of U "ID" deg "ID"\n", k-1, deg));
	    ASSERT (deg >= 0) ;
	    pos = Upos [k] ;
	    if (pos != EMPTY)
	    {
		/* add the pivot column */
		DEBUG4 (("k "ID" add pivot entry at position "ID"\n", k, pos)) ;
		ASSERT (pos >= 0 && pos <= deg) ;
		Pattern [deg++] = Pattern [pos] ;
		Pattern [pos] = k ;
	    }
	}
    }

    /* singletons */
    for (k = n1 - 1 ; k >= 0 ; k--)
    {
	deg = Uilen [k] ;
	DEBUG4 (("Singleton k "ID"\n", k)) ;
	if (deg > 0)
	{
	    up = Uip [k] ;
	    Usi = (Int *) (Numeric->Memory + up) ;
	    up += UNITS (Int, deg) ;
	    Uval = (Entry *) (Numeric->Memory + up) ;
	    for (j = 0 ; j < deg ; j++)
	    {
		col = Usi [j] ;
		value = Uval [j] ;
		DEBUG4 (("  k "ID" col "ID" value", k, col)) ;
		EDEBUG4 (value) ;
		DEBUG4 (("\n")) ;
		if (IS_NONZERO (value))
		{
		    p = --(Wi [col]) ;
		    Ui [p] = k ;
#ifdef COMPLEX
		    if (split)
		    {
			Ux [p] = REAL_COMPONENT (value) ;
			Uz [p] = IMAG_COMPONENT (value) ;
		    }
		    else
		    {
			Ux [2*p  ] = REAL_COMPONENT (value) ;
			Ux [2*p+1] = IMAG_COMPONENT (value) ;
		    }
#else
		    Ux [p] = value ;
#endif
		}
	    }
	}
    }

#ifndef NDEBUG
    DEBUG6 (("U matrix:")) ;
    UMF_dump_col_matrix (Ux,
#ifdef COMPLEX
	Uz,
#endif
	Ui, Up, Numeric->n_row, n_col, Numeric->unz + Numeric->nnzpiv) ;
#endif

}
Example #12
0
GLOBAL void UMF_scale_column
(
    NumericType *Numeric,
    WorkType *Work
)
{
    /* ---------------------------------------------------------------------- */
    /* local variables */
    /* ---------------------------------------------------------------------- */

    Entry pivot_value ;
    Entry *Fcol, *Flublock, *Flblock, *Fublock, *Fcblock ;
    Int k, k1, fnr_curr, fnrows, fncols, *Frpos, *Fcpos, pivrow, pivcol,
	*Frows, *Fcols, fnc_curr, fnpiv, *Row_tuples, nb,
	*Col_tuples, *Rperm, *Cperm, fspos, col2, row2 ;
#ifndef NDEBUG
    Int *Col_degree, *Row_degree ;
#endif

    /* ---------------------------------------------------------------------- */
    /* get parameters */
    /* ---------------------------------------------------------------------- */

    fnrows = Work->fnrows ;
    fncols = Work->fncols ;
    fnpiv = Work->fnpiv ;

    /* ---------------------------------------------------------------------- */

    Rperm = Numeric->Rperm ;
    Cperm = Numeric->Cperm ;

    /* ---------------------------------------------------------------------- */

    Flublock = Work->Flublock ;
    Flblock  = Work->Flblock ;
    Fublock  = Work->Fublock ;
    Fcblock  = Work->Fcblock ;

    fnr_curr = Work->fnr_curr ;
    fnc_curr = Work->fnc_curr ;
    Frpos = Work->Frpos ;
    Fcpos = Work->Fcpos ;
    Frows = Work->Frows ;
    Fcols = Work->Fcols ;
    pivrow = Work->pivrow ;
    pivcol = Work->pivcol ;

    ASSERT (pivrow >= 0 && pivrow < Work->n_row) ;
    ASSERT (pivcol >= 0 && pivcol < Work->n_col) ;

#ifndef NDEBUG
    Col_degree = Numeric->Cperm ;	/* for NON_PIVOTAL_COL macro */
    Row_degree = Numeric->Rperm ;	/* for NON_PIVOTAL_ROW macro */
#endif

    Row_tuples = Numeric->Uip ;
    Col_tuples = Numeric->Lip ;
    nb = Work->nb ;

#ifndef NDEBUG
    ASSERT (fnrows == Work->fnrows_new + 1) ;
    ASSERT (fncols == Work->fncols_new + 1) ;
    DEBUG1 (("SCALE COL: fnrows "ID" fncols "ID"\n", fnrows, fncols)) ;
    DEBUG2 (("\nFrontal matrix, including all space:\n"
		"fnr_curr "ID" fnc_curr "ID" nb    "ID"\n"
		"fnrows   "ID" fncols   "ID" fnpiv "ID"\n",
		fnr_curr, fnc_curr, nb, fnrows, fncols, fnpiv)) ;
    DEBUG2 (("\nJust the active part:\n")) ;
    DEBUG7 (("C  block: ")) ;
    UMF_dump_dense (Fcblock,  fnr_curr, fnrows, fncols) ;
    DEBUG7 (("L  block: ")) ;
    UMF_dump_dense (Flblock,  fnr_curr, fnrows, fnpiv);
    DEBUG7 (("U' block: ")) ;
    UMF_dump_dense (Fublock,  fnc_curr, fncols, fnpiv) ;
    DEBUG7 (("LU block: ")) ;
    UMF_dump_dense (Flublock, nb, fnpiv, fnpiv) ;
#endif

    /* ====================================================================== */
    /* === Shift pivot row and column ======================================= */
    /* ====================================================================== */

    /* ---------------------------------------------------------------------- */
    /* move pivot column into place */
    /* ---------------------------------------------------------------------- */

    /* Note that the pivot column is already in place.  Just shift the last
     * column into the position vacated by the pivot column. */

    fspos = Fcpos [pivcol] ;

    /* one less column in the contribution block */
    fncols = --(Work->fncols) ;

    if (fspos != fncols * fnr_curr)
    {

	Int fs = fspos / fnr_curr ;

	DEBUG6 (("Shift pivot column in front\n")) ;
	DEBUG6 (("fspos: "ID" flpos: "ID"\n", fspos, fncols * fnr_curr)) ;

	/* ------------------------------------------------------------------ */
	/* move Fe => Fs */
	/* ------------------------------------------------------------------ */

	/* column of the contribution block: */
	{
	    /* Fs: current position of pivot column in contribution block */
	    /* Fe: position of last column in contribution block */
	    Int i ;
	    Entry *Fs, *Fe ;
	    Fs = Fcblock + fspos ;
	    Fe = Fcblock + fncols * fnr_curr ;
#pragma ivdep
	    for (i = 0 ; i < fnrows ; i++)
	    {
		Fs [i] = Fe [i] ;
	    }
	}

	/* column of the U2 block */
	{
	    /* Fs: current position of pivot column in U block */
	    /* Fe: last column in U block */
	    Int i ;
	    Entry *Fs, *Fe ;
	    Fs = Fublock + fs ;
	    Fe = Fublock + fncols ;
#pragma ivdep
	    for (i = 0 ; i < fnpiv ; i++)
	    {
		Fs [i * fnc_curr] = Fe [i * fnc_curr] ;
	    }
	}

	/* move column Fe to Fs in the Fcols pattern */
	col2 = Fcols [fncols] ;
	Fcols [fs] = col2 ;
	Fcpos [col2] = fspos ;
    }

    /* pivot column is no longer in the frontal matrix */
    Fcpos [pivcol] = EMPTY ;

#ifndef NDEBUG
    DEBUG2 (("\nFrontal matrix after col swap, including all space:\n"
		"fnr_curr "ID" fnc_curr "ID" nb    "ID"\n"
		"fnrows   "ID" fncols   "ID" fnpiv "ID"\n",
		fnr_curr, fnc_curr, nb,
		fnrows, fncols, fnpiv)) ;
    DEBUG2 (("\nJust the active part:\n")) ;
    DEBUG7 (("C  block: ")) ;
    UMF_dump_dense (Fcblock,  fnr_curr, fnrows, fncols) ;
    DEBUG7 (("L  block: ")) ;
    UMF_dump_dense (Flblock,  fnr_curr, fnrows, fnpiv+1);
    DEBUG7 (("U' block: ")) ;
    UMF_dump_dense (Fublock,  fnc_curr, fncols, fnpiv) ;
    DEBUG7 (("LU block: ")) ;
    UMF_dump_dense (Flublock, nb, fnpiv, fnpiv+1) ;
#endif

    /* ---------------------------------------------------------------------- */
    /* move pivot row into place */
    /* ---------------------------------------------------------------------- */

    fspos = Frpos [pivrow] ;

    /* one less row in the contribution block */
    fnrows = --(Work->fnrows) ;

    DEBUG6 (("Swap/shift pivot row in front:\n")) ;
    DEBUG6 (("fspos: "ID" flpos: "ID"\n", fspos, fnrows)) ;

    if (fspos == fnrows)
    {

	/* ------------------------------------------------------------------ */
	/* move Fs => Fd */
	/* ------------------------------------------------------------------ */

	DEBUG6 (("row case 1\n")) ;

	/* row of the contribution block: */
	{
	    Int j ;
	    Entry *Fd, *Fs ;
	    Fd = Fublock + fnpiv * fnc_curr ;
	    Fs = Fcblock + fspos ;
#pragma ivdep
	    for (j = 0 ; j < fncols ; j++)
	    {
		Fd [j] = Fs [j * fnr_curr] ;
	    }
	}

	/* row of the L2 block: */
	if (Work->pivrow_in_front)
	{
	    Int j ;
	    Entry *Fd, *Fs ;
	    Fd = Flublock + fnpiv ;
	    Fs = Flblock  + fspos ;
#pragma ivdep
	    for (j = 0 ; j <= fnpiv ; j++)
	    {
		Fd [j * nb] = Fs [j * fnr_curr] ;
	    }
	}
	else
	{
	    Int j ;
	    Entry *Fd, *Fs ;
	    Fd = Flublock + fnpiv ;
	    Fs = Flblock  + fspos ;
#pragma ivdep
	    for (j = 0 ; j < fnpiv ; j++)
	    {
		ASSERT (IS_ZERO (Fs [j * fnr_curr])) ;
		CLEAR (Fd [j * nb]) ;
	    }
	    Fd [fnpiv * nb] = Fs [fnpiv * fnr_curr] ;
	}
    }
    else
    {

	/* ------------------------------------------------------------------ */
	/* move Fs => Fd */
	/* move Fe => Fs */
	/* ------------------------------------------------------------------ */

	DEBUG6 (("row case 2\n")) ;
	/* this is the most common case, by far */

	/* row of the contribution block: */
	{
	    /* Fd: destination of pivot row on U block */
	    /* Fs: current position of pivot row in contribution block */
	    /* Fe: position of last row in contribution block */
	    Entry *Fd, *Fs, *Fe ;
	    Fd = Fublock + fnpiv * fnc_curr ;
	    Fs = Fcblock + fspos ;
	    Fe = Fcblock + fnrows ;
	    shift_pivot_row (Fd, Fs, Fe, fncols, fnr_curr) ;
	}

	/* row of the L2 block: */
	if (Work->pivrow_in_front)
	{
	    /* Fd: destination of pivot row in LU block */
	    /* Fs: current position of pivot row in L block */
	    /* Fe: last row in L block */
	    Int j ;
	    Entry *Fd, *Fs, *Fe ;
	    Fd = Flublock + fnpiv ;
	    Fs = Flblock  + fspos ;
	    Fe = Flblock  + fnrows ;
#pragma ivdep
	    for (j = 0 ; j <= fnpiv ; j++)
	    {
		Fd [j * nb]       = Fs [j * fnr_curr] ;
		Fs [j * fnr_curr] = Fe [j * fnr_curr] ;
	    }
	}
	else
	{
	    Int j ;
	    Entry *Fd, *Fs, *Fe ;
	    Fd = Flublock + fnpiv ;
	    Fs = Flblock  + fspos ;
	    Fe = Flblock  + fnrows ;
#pragma ivdep
	    for (j = 0 ; j < fnpiv ; j++)
	    {
		ASSERT (IS_ZERO (Fs [j * fnr_curr])) ;
		CLEAR (Fd [j * nb]) ;
		Fs [j * fnr_curr] = Fe [j * fnr_curr] ;
	    }
	    Fd [fnpiv * nb]       = Fs [fnpiv * fnr_curr] ;
	    Fs [fnpiv * fnr_curr] = Fe [fnpiv * fnr_curr] ;
	}

	/* move row Fe to Fs in the Frows pattern */
	row2 = Frows [fnrows] ;
	Frows [fspos] = row2 ;
	Frpos [row2] = fspos ;

    }
    /* pivot row is no longer in the frontal matrix */
    Frpos [pivrow] = EMPTY ;

#ifndef NDEBUG
    DEBUG2 (("\nFrontal matrix after row swap, including all space:\n"
		"fnr_curr "ID" fnc_curr "ID" nb    "ID"\n"
		"fnrows   "ID" fncols   "ID" fnpiv "ID"\n",
		Work->fnr_curr, Work->fnc_curr, Work->nb,
		Work->fnrows, Work->fncols, Work->fnpiv)) ;
    DEBUG2 (("\nJust the active part:\n")) ;
    DEBUG7 (("C  block: ")) ;
    UMF_dump_dense (Fcblock,  fnr_curr, fnrows, fncols) ;
    DEBUG7 (("L  block: ")) ;
    UMF_dump_dense (Flblock,  fnr_curr, fnrows, fnpiv+1);
    DEBUG7 (("U' block: ")) ;
    UMF_dump_dense (Fublock,  fnc_curr, fncols, fnpiv+1) ;
    DEBUG7 (("LU block: ")) ;
    UMF_dump_dense (Flublock, nb, fnpiv+1, fnpiv+1) ;
#endif

    /* ---------------------------------------------------------------------- */
    /* Frpos [row] >= 0 for each row in pivot column pattern.   */
    /* offset into pattern is given by:				*/
    /* Frpos [row] == offset - 1				*/
    /* Frpos [pivrow] is EMPTY */

    /* Fcpos [col] >= 0 for each col in pivot row pattern.	*/
    /* Fcpos [col] == (offset - 1) * fnr_curr			*/
    /* Fcpos [pivcol] is EMPTY */

    /* Fcols [0..fncols-1] is the pivot row pattern (excl pivot cols) */
    /* Frows [0..fnrows-1] is the pivot col pattern (excl pivot rows) */

    /* ====================================================================== */
    /* === scale pivot column =============================================== */
    /* ====================================================================== */

    /* pivot column (except for pivot entry itself) */
    Fcol = Flblock + fnpiv * fnr_curr ;
    /* fnpiv-th pivot in frontal matrix located in Flublock (fnpiv, fnpiv) */
    pivot_value = Flublock [fnpiv + fnpiv * nb] ;

    /* this is the kth global pivot */
    k = Work->npiv + fnpiv ;

    DEBUG4 (("Pivot value: ")) ;
    EDEBUG4 (pivot_value) ;
    DEBUG4 (("\n")) ;

    UMF_scale (fnrows, pivot_value, Fcol) ;

    /* ---------------------------------------------------------------------- */
    /* deallocate the pivot row and pivot column tuples */
    /* ---------------------------------------------------------------------- */

    UMF_mem_free_tail_block (Numeric, Row_tuples [pivrow]) ;
    UMF_mem_free_tail_block (Numeric, Col_tuples [pivcol]) ;

    Row_tuples [pivrow] = 0 ;
    Col_tuples [pivcol] = 0 ;

    DEBUG5 (("number of pivots prior to this one: "ID"\n", k)) ;
    ASSERT (NON_PIVOTAL_ROW (pivrow)) ;
    ASSERT (NON_PIVOTAL_COL (pivcol)) ;

    /* save row and column inverse permutation */
    k1 = ONES_COMPLEMENT (k) ;
    Rperm [pivrow] = k1 ;			/* aliased with Row_degree */
    Cperm [pivcol] = k1 ;			/* aliased with Col_degree */

    ASSERT (!NON_PIVOTAL_ROW (pivrow)) ;
    ASSERT (!NON_PIVOTAL_COL (pivcol)) ;

    /* ---------------------------------------------------------------------- */
    /* Keep track of the pivot order.  This is the kth pivot row and column. */
    /* ---------------------------------------------------------------------- */

    /* keep track of pivot rows and columns in the LU, L, and U blocks */
    ASSERT (fnpiv < MAXNB) ;
    Work->Pivrow [fnpiv] = pivrow ;
    Work->Pivcol [fnpiv] = pivcol ;

    /* ====================================================================== */
    /* === one step in the factorization is done ============================ */
    /* ====================================================================== */

    /* One more step is done, except for pending updates to the U and C blocks
     * of this frontal matrix.  Those are saved up, and applied by
     * UMF_blas3_update when enough pivots have accumulated.   Also, the
     * LU factors for these pending pivots have not yet been stored. */

    Work->fnpiv++ ;

#ifndef NDEBUG
    DEBUG7 (("Current frontal matrix: (after pivcol scale)\n")) ;
    UMF_dump_current_front (Numeric, Work, TRUE) ;
#endif

}
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
//
core_error_e core_scan_list_c::update_entry(
    core_ap_data_c& ap_data )
    {
    bool_t is_match_found( false_t );
    const core_mac_address_s bssid(
        ap_data.bssid() );
    core_ssid_s ssid(
        ap_data.ssid() );    
    u64_t timestamp(
        core_am_tools_c::timestamp() );

    DEBUG6( "core_scan_list_c::update_entry() - searching for entries with BSSID %02X:%02X:%02X:%02X:%02X:%02X",
        bssid.addr[0], bssid.addr[1], bssid.addr[2],
        bssid.addr[3], bssid.addr[4], bssid.addr[5] );                
    DEBUG1S( "core_scan_list_c::update_entry() - and with SSID ",
        ssid.length, &ssid.ssid[0] );

    core_scan_list_entry_s* iter = scan_list_m.first();
    while( iter )
        {
        bool_t is_goto_next_entry( true_t );

        if ( iter->ap_data->bssid() == bssid )
            {
            if ( iter->ap_data->ssid() == ssid )
                {
                if ( !is_match_found )
                    {
                    if ( !iter->tags && iter->ap_data->rcpi() >= ap_data.rcpi() )
                        {                      
                        if ( ap_data.frame()->type() == core_frame_dot11_c::core_dot11_type_beacon )
                            {
                            DEBUG2( "core_scan_list_c::update_entry() - an entry with matching BSSID and SSID (age %u, RCPI %u) already received, ignoring beacon entry",
                                static_cast<u32_t>( timestamp - iter->timestamp ) / SECONDS_FROM_MICROSECONDS, iter->ap_data->rcpi() );
                            }
                        else
                            {
                            DEBUG2( "core_scan_list_c::update_entry() - an entry with matching BSSID and SSID (age %u, RCPI %u) already received, ignoring probe entry",
                                static_cast<u32_t>( timestamp - iter->timestamp ) / SECONDS_FROM_MICROSECONDS, iter->ap_data->rcpi() );
                            }

                        is_match_found = true_t;
                        }
                    else
                        {
                        if ( ap_data.frame()->type() == core_frame_dot11_c::core_dot11_type_beacon )
                            {
                            DEBUG2( "core_scan_list_c::update_entry() - an entry with matching BSSID and SSID (age %u, RCPI %u) found, replacing entry with a beacon entry",
                                static_cast<u32_t>( timestamp - iter->timestamp ) / SECONDS_FROM_MICROSECONDS, iter->ap_data->rcpi() );
                            }
                        else
                            {
                            DEBUG2( "core_scan_list_c::update_entry() - an entry with matching BSSID and SSID (age %u, RCPI %u) found, replacing entry with a probe entry",
                                static_cast<u32_t>( timestamp - iter->timestamp ) / SECONDS_FROM_MICROSECONDS, iter->ap_data->rcpi() );
                            }

                        is_match_found = true_t;

                        *(iter->ap_data) = ap_data;
                        iter->timestamp = timestamp;
                        iter->tags = 0;
                        }
                    }
                else
                    {
                    DEBUG( "core_scan_list_c::update_entry() - an entry with matching BSSID and SSID found (duplicate), removing entry" );

                    core_scan_list_entry_s* temp = iter;
                    iter = scan_list_m.next();
                    scan_list_m.remove( temp );

                    is_goto_next_entry = false_t;
                    }
                }
            else if ( iter->ap_data->frame()->type() == core_frame_dot11_c::core_dot11_type_beacon &&
                      ap_data.frame()->type() == core_frame_dot11_c::core_dot11_type_beacon )
                {
                /**
                 * If both the new entry and the old entry are beacons with different SSIDs,
                 * it means the SSID has changed and the old entry needs to be replaced or
                 * removed.
                 */
                if ( !is_match_found )
                    {
                    DEBUG( "core_scan_list_c::update_entry() - two beacons with the same BSSID but different SSID found, replacing entry" );
                    is_match_found = true_t;

                    *(iter->ap_data) = ap_data;
                    iter->timestamp = timestamp;
                    iter->tags = 0;
                    }
                else
                    {
                    DEBUG( "core_scan_list_c::update_entry() - two beacons with the same BSSID but different SSID found (duplicate), removing entry" );

                    core_scan_list_entry_s* temp = iter;
                    iter = scan_list_m.next();
                    scan_list_m.remove( temp );

                    is_goto_next_entry = false_t;
                    }
                }
#if 0                
            else
                {            
                DEBUG( "core_scan_list_c::update_entry() - an entry with matching BSSID found but SSID doesn't match, refreshing entry timestamp" );
                iter->timestamp = timestamp;
                }
#endif // 0                
            }

        if ( is_goto_next_entry )
            {
            iter = scan_list_m.next();
            }
        }

    if ( !is_match_found )
        {
        if ( ap_data.frame()->type() == core_frame_dot11_c::core_dot11_type_beacon )
            {
            DEBUG( "core_scan_list_c::update_entry() - no entry matching BSSID and SSID found, adding a new beacon entry" );
            }
        else
            {
            DEBUG( "core_scan_list_c::update_entry() - no entry matching BSSID and SSID found, adding a new probe entry" );
            }

        core_scan_list_entry_s* entry = new core_scan_list_entry_s;
        if ( entry )
            {
            entry->ap_data = core_ap_data_c::instance( ap_data );
            entry->timestamp = timestamp;
            entry->tags = 0;

            scan_list_m.append( entry );
            }
        }

    return core_error_ok;         
    }
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
//
core_error_e core_operation_release_c::next_state()
    {
    DEBUG( "core_operation_release_c::next_state()" );
    switch( operation_state_m )
        {
        case core_state_init:
            {                        
            DEBUG( "core_operation_release_c::next_state() - core_state_init" );
            // ensure state is correct
            if( server_m->get_core_settings().connection_state() 
                == core_connection_state_notconnected )
                {
                return core_error_not_supported;
                }

            DEBUG( "core_operation_release_c::next_state() - marking is_disconnecting as true" );
            server_m->get_connection_data()->set_disconnecting(
                true_t );

            server_m->cancel_roam_timer();
            server_m->cancel_dhcp_timer();
            server_m->get_wpx_adaptation_instance().handle_wpx_connection_stop();

#ifdef _DEBUG
            switch ( reason_m )
                {
                case core_release_reason_external_request:
                    DEBUG( "core_operation_release_c::next_state() - release due to core_release_reason_external_request" );
                    break;
                case core_release_reason_max_roam_attempts_exceeded:
                    DEBUG( "core_operation_release_c::next_state() - release due to core_release_reason_max_roam_attempts_exceeded" );

                    switch ( server_m->get_connection_data()->last_roam_reason() )
                        {
                        case core_roam_reason_initial_connect:
                            DEBUG( "core_operation_release_c::next_state() - roam was initiated due to core_roam_reason_initial_connect" );
                            break;
                        case core_roam_reason_bss_lost:
                            DEBUG( "core_operation_release_c::next_state() - roam was initiated due to core_roam_reason_bss_lost" );
                            break;
                        case core_roam_reason_media_disconnect:
                            DEBUG( "core_operation_release_c::next_state() - roam was initiated due to core_roam_reason_media_disconnect" );
                            break;
                        case core_roam_reason_signal_strength:
                            DEBUG( "core_operation_release_c::next_state() - roam was initiated due to core_roam_reason_signal_strength" );
                            break;
                        case core_roam_reason_signal_loss_prediction:
                            DEBUG( "core_operation_release_c::next_state() - roam was initiated due to core_roam_reason_signal_loss_prediction" );
                            break;
                        case core_roam_reason_failed_reauthentication:
                            DEBUG( "core_operation_release_c::next_state() - roam was initiated due to core_roam_reason_failed_reauthentication" );
                            break;
                        default:
                            DEBUG( "core_operation_release_c::next_state() - roam was initiated due to an undefined reason" );
                            ASSERT( false_t );
                        }
                    
                    switch ( server_m->get_connection_data()->last_roam_failed_reason() )
                        {
                        case core_roam_failed_reason_timeout:
                            DEBUG( "core_operation_release_c::next_state() - roam failed due to core_roam_failed_reason_timeout" );
                            break;
                        case core_roam_failed_reason_no_suitable_ap:
                            DEBUG( "core_operation_release_c::next_state() - roam failed due to core_roam_failed_reason_no_suitable_ap" );
                            break;
                        case core_roam_failed_reason_ap_status_code:
                            DEBUG( "core_operation_release_c::next_state() - roam failed due to core_roam_failed_reason_ap_status_code" );
                            break;
                        case core_roam_failed_reason_eapol_failure:
                            DEBUG( "core_operation_release_c::next_state() - roam failed due to core_roam_failed_reason_eapol_failure" );
                            break;
                        case core_roam_failed_reason_other_failure:
                            DEBUG( "core_operation_release_c::next_state() - roam failed due to core_roam_failed_reason_other_failure" );
                            break;
                        default:
                            DEBUG( "core_operation_release_c::next_state() - roam failed due to an undefined reason" );
                            ASSERT( false_t );
                        }
                    break;
                case core_release_reason_hw_failure:
                    DEBUG( "core_operation_release_c::next_state() - release due to core_release_reason_hw_failure" );
                    break;
                case core_release_reason_tkip_mic_failure:
                    DEBUG( "core_operation_release_c::next_state() - release due to core_release_reason_tkip_mic_failure" );
                    break;
                case core_release_reason_other:
                    DEBUG( "core_operation_release_c::next_state() - release due to core_release_reason_other" );
                    break;
                default:
                    DEBUG( "core_operation_release_c::next_state() - release due to an undefined reason" );
                    ASSERT( false_t );
                }

            server_m->get_core_settings().roam_metrics().trace_current_roam_metrics();
#endif // _DEBUG

            /**
             * EAPOL must notified about the disassociation.
             */
            if ( ( server_m->get_connection_data()->iap_data().is_eap_used() ||
                   server_m->get_connection_data()->iap_data().is_wapi_used() ) &&
                 server_m->get_connection_data()->current_ap_data() )
                {
                /*const*/ core_mac_address_s bssid =
                    server_m->get_connection_data()->current_ap_data()->bssid();
                
                network_id_c network(
                    &bssid.addr[0],
                    MAC_ADDR_LEN,
                    &server_m->own_mac_addr().addr[0],
                    MAC_ADDR_LEN,
                    server_m->get_eapol_instance().ethernet_type() );

                DEBUG6( "core_operation_release_c::next_state() - EAPOL disassociation from BSSID %02X:%02X:%02X:%02X:%02X:%02X",
                    bssid.addr[0], bssid.addr[1], bssid.addr[2],
                    bssid.addr[3], bssid.addr[4], bssid.addr[5] );
                DEBUG( "core_operation_release_c::next_state() - marking is_eapol_disconnecting as true" );
                server_m->get_connection_data()->set_eapol_disconnecting(
                    true );

                server_m->get_eapol_instance().disassociation( &network );
                operation_state_m = core_state_eapol_disassociated;

                return core_error_request_pending;
                }

            return goto_state( core_state_eapol_disassociated );
            }
        case core_state_eapol_disassociated:
            {
            DEBUG( "core_operation_release_c::next_state() - core_state_eapol_disassociated" );
            // disable user data
            drivers_m->disable_user_data( request_id_m );
            operation_state_m = core_state_disable_user_data;
            break;
            }
        case core_state_disable_user_data:
            {
            DEBUG( "core_operation_release_c::next_state() - core_state_disable_user_data" );
            drivers_m->set_tx_power_level(
                request_id_m,
                server_m->get_device_settings().tx_power_level );
            operation_state_m = core_state_tx_power_level;            
            break;
            }
        case core_state_tx_power_level:
            {
            DEBUG( "core_operation_release_c::next_state() - core_state_tx_power_level" );

            u32_t tx_level = server_m->get_device_settings().tx_power_level;

            if ( server_m->get_connection_data()->last_tx_level() != tx_level )
                {
                DEBUG( "core_operation_release_c::next_state() - TX level has changed, notifying change" );

                adaptation_m->notify(
                    core_notification_tx_power_level_changed,
                    sizeof( tx_level ),
                    reinterpret_cast<u8_t*>( &tx_level ) );

                server_m->get_connection_data()->set_last_tx_level( tx_level );                    
                }

            drivers_m->disconnect( request_id_m );
            operation_state_m = core_state_disconnect;
            break;
            }
        case core_state_disconnect:
            {
            DEBUG( "core_operation_release_c::next_state() - core_state_disconnect" );

            // notify adaptation
            core_connection_state_e state = core_connection_state_notconnected;
            server_m->get_core_settings().set_connection_state( state );

            if ( server_m->get_connection_data()->last_connection_state() != state )
                {
                u8_t buf[5];
                buf[0] = static_cast<u8_t>( state );
                buf[1] = static_cast<u8_t>( reason_m );
                buf[2] = 0;
                buf[3] = 0;
                if ( reason_m == core_release_reason_max_roam_attempts_exceeded )
                    {
                    buf[2] = static_cast<u8_t>( 
                        server_m->get_connection_data()->last_roam_reason() );
                    buf[3] = static_cast<u8_t>(
                        server_m->get_connection_data()->last_roam_failed_reason() );
                    }

                adaptation_m->notify(
                    core_notification_connection_state_changed,
                    sizeof( buf ),
                    buf );
                    
                server_m->get_connection_data()->set_last_connection_state(
                    state );
                }            

            // destroy connection data
            server_m->clear_connection_data();              

            // Cancel any operations that depend on an active connection.
            server_m->cancel_operations_with_flags(
                core_operation_base_c::core_base_flag_connection_needed );

            return core_error_ok;
            }
        default:
            {
            ASSERT( false_t );
            }
        }
    return core_error_request_pending;
    }
Example #15
0
void MisCheck(char plr, char mpad)
{
    int tomflag = 0; // toms checking flag
    int val, safety, save, PROBLEM, i, lc, durxx;
    struct XFails Now;
    unsigned char gork = 0;

    lc = 0; /* XXX check uninitialized */

    STEPnum = STEP;
    FINAL = STEP = MFlag = 0; // Clear Everything
    Unm = MANNED[0] + MANNED[1];
    Dock_Skip = 0; // used for mission branching
    MPad = mpad;
    SCRUBS = noDock = InSpace = 0;



    if (!AI[plr] && !fullscreenMissionPlayback) {
        //FadeOut(1,pal,100,128,1);
        if (plr == 1) {
            fill_rectangle(189, 173, 249, 196, 55);

            for (i = 190; i < 250; i += 2) {
                display::graphics.legacyScreen()->setPixel(i, 178, 61);
                display::graphics.legacyScreen()->setPixel(i, 184, 61);
                display::graphics.legacyScreen()->setPixel(i, 190, 61);
            }

            lc = 191;
        } else if (plr == 0) {
            fill_rectangle(73, 173, 133, 196, 55);

            for (i = 73; i < 133; i += 2) {
                display::graphics.legacyScreen()->setPixel(i, 178, 61);
                display::graphics.legacyScreen()->setPixel(i, 184, 61);
                display::graphics.legacyScreen()->setPixel(i, 190, 61);
            }

            lc = 76;
        }
    } // END if (!AI[plr])

    if (!AI[plr] && !fullscreenMissionPlayback) {
        Tick(2);
    }

    Mev[0].trace = 0;
    death = 0;

    durxx = durx = -1;

    if (Data->P[plr].Mission[mpad].Duration > 0) {
        durxx = Data->P[plr].Mission[mpad].Duration - 1;
        Data->P[plr].Mission[mpad].Duration = 0;
    }

    if (JOINT == 1) {
        durxx = MAX(durxx, Data->P[plr].Mission[mpad + 1].Duration - 1);
        Data->P[plr].Mission[mpad + 1].Duration = 0;
    }

    do {
        if (STEP > 30 || STEP < 0) {
            delay(20);
        }

        if (Dock_Skip == 1) {
            if (Mev[Mev[STEP].trace].loc == 8) {
                Mev[STEP].trace++;    // skip over docking.
            }
        }

        if (Mev[STEP].loc == 16 && Mis.PCat[4] == 22) {
            FirstManOnMoon(plr, 0, Mis.Index);
        }

        // Duration Hack Part 1 of 3   (during the Duration stuff)
        if ((Mev[STEP].loc == 27 || Mev[STEP].loc == 28) && durx > 0) {

            if (Mev[STEP].StepInfo != 1) {
                Data->P[plr].Mission[MPad + Mev[STEP].pad].Duration = 1; //Original code would also return 1
                durx = -1; // end durations
            } else {
                Data->P[plr].Mission[MPad + Mev[STEP].pad].Duration++;
                durx--;

                if ((Data->Def.Lev1 == 0 && plr == 0) || (Data->Def.Lev2 == 0 && plr == 1)) {
                    Mev[STEP].dice = MisRandom();
                } else {
                    Mev[STEP].dice = brandom(100) + 1;
                }

                Mev[STEP].rnum = brandom(10000); // reroll failure type
                Mev[STEP].trace = STEP;
            }
        }

        if (Mev[STEP].Name[0] == 'A' || Mev[STEP].StepInfo == 9 || Mev[STEP].StepInfo == 19) {
            STEP = Mev[STEP].trace;
        } else {
            if (Mev[STEP].trace != 0) {
                STEP = Mev[STEP].trace;
            } else {
                Mev[STEP].trace = STEP + 1;
                STEP++;
            }
        }

        // Duration Hack Part 2 of 3    (set up durx for duration use)
        if ((Mev[STEP].loc == 27 || Mev[STEP].loc == 28) && durx == -1) {
            durx = durxx - 1;
            Data->P[plr].Mission[MPad + Mev[STEP].pad].Duration = 2;
        }

        if (Mev[STEP].Name[0] == 'A') {
            display::graphics.setForegroundColor(11);

            if (!AI[plr] && !fullscreenMissionPlayback) {
                if (plr == 0) {
                    x = 5;
                    y = 112;
                    fill_rectangle(2, 107, 140, 115, 3);
                } else {
                    x = 82, y = 8;
                    fill_rectangle(78, 2, 241, 10, 3);
                }

                draw_string(x, y, "COUNTDOWN");

                if (plr == 0) {
                    fill_rectangle(188, 107, 294, 113, 3);
                    display::graphics.setForegroundColor(1);
                    draw_string(190, 112, (Mev[STEP].pad == 0) ? "PRIMARY LAUNCH" : "SECOND LAUNCH");
                } else {
                    fill_rectangle(244, 56, 314, 62, 3);
                    display::graphics.setForegroundColor(1);
                    draw_string(246, 61, (Mev[STEP].pad == 0) ? "PRIMARY PAD" : "SECOND PAD");
                }

            }

            memset(Name, 0x00, sizeof Name);
            strcpy(Name, Mev[STEP].Name);
            Name[0] = '#'; // Launch Code
            PlaySequence(plr, STEP, Name, 0); // Special Case #47236
        };

        // Necessary to keep code from crashing on bogus mission step
        while (Mev[STEP].E == NULL) {
            STEP++;
        }

        // Draw Mission Step Name
        if (!AI[plr] && !fullscreenMissionPlayback) {
            if (!(fEarly && STEP != 0)) {
                if (plr == 0) {
                    x = 5;
                    y = 112;
                    fill_rectangle(2, 107, 140, 115, 3);
                } else {
                    x = 82, y = 8;
                    fill_rectangle(78, 2, 241, 10, 3);
                }

                display::graphics.setForegroundColor(11);
                MisStep(x, y, Mev[STEP].loc);

                if (plr == 0) {
                    fill_rectangle(188, 107, 294, 113, 3);
                    display::graphics.setForegroundColor(1);
                    draw_string(190, 112, (Mev[STEP].pad == 0) ? "PRIMARY LAUNCH" : "SECOND LAUNCH");
                } else {
                    fill_rectangle(244, 56, 314, 62, 3);
                    display::graphics.setForegroundColor(1);
                    draw_string(246, 61, (Mev[STEP].pad == 0) ? "PRIMARY PAD" : "SECOND PAD");
                }
            }
        }


        // SAFETY FACTOR STUFF

        safety = Mev[STEP].E->MisSaf;

        if ((Mev[STEP].Name[0] == 'A') && MH[Mev[STEP].pad][7] != NULL) {
            // boosters involved
            safety = RocketBoosterSafety(safety, MH[Mev[STEP].pad][7]->Safety);
        }

        // Duration Hack Part 3 of 3
        if (Mev[STEP].loc == 28 || Mev[STEP].loc == 27) {
            safety = Mev[STEP].E->MisSaf; // needs to be for both

            if (InSpace == 2) {
                safety = (MH[0][0]->MisSaf + MH[1][0]->MisSaf) / 2;    //joints
            }
        }

        if (strncmp(Mev[STEP].E->Name, "DO", 2) == 0) {
            if (Mev[STEP].loc == 1 || Mev[STEP].loc == 2) {
                safety = Mev[STEP].E->MSF;
            }
        }

        val = Mev[STEP].dice;
        safety += Mev[STEP].asf;

        if (safety >= 100) {
            safety = 99;
        }

        save = (Mev[STEP].E->SaveCard == 1) ? 1 : 0;

        PROBLEM = val > safety;

        if (!AI[plr] && options.want_cheats) {
            PROBLEM = 0;
        }

        DEBUG6("step %c:%s safety %d rolled %d%s", Mev[STEP].Name[0], S_Name[Mev[STEP].loc],
               safety, val,
               PROBLEM ? " problem" : (options.want_cheats ? " cheating" : ""));

        if (!AI[plr] && !fullscreenMissionPlayback)
            if (!(fEarly && STEP != 0)) {
                lc = MCGraph(plr, lc, MAX(0, safety), MAX(0, val), PROBLEM);    // Graph Chart
            }

        if (PROBLEM && save == 1) {  // Failure Saved
            Mev[STEP].E->SaveCard--;    // Deduct SCard
            PROBLEM = 0; // Fix problem
        }


        // Fix wrong anim thing for the Jt Durations
        if (Mev[STEP].loc == 28 || Mev[STEP].loc == 27) {
            strcpy(Mev[STEP].Name, (plr == 0) ? "_BUSC0\0" : "_BSVC0");
            Mev[STEP].Name[5] = Mev[STEP].E->ID[1];
        }

        if (PROBLEM == 1) {  //Step Problem
            // for the unmanned mission
            if (MANNED[Mev[STEP].pad] == 0 && MANNED[other(Mev[STEP].pad)] == 0) {
                Mev[STEP].rnum = (-1) * (brandom(5) + 1);
            }

            // Unmanned also
            if (MANNED[Mev[STEP].pad] == 0 && noDock == 0) {
                Mev[STEP].rnum = (-1) * (brandom(5) + 1);
            }

            memset(&Now, 0x00, sizeof Now);


            //***************TC Special little HMOON EVA FAILURE FIX

            tomflag = 0;

            if (Mev[STEP].Name[0] == 'H' && Mev[STEP].Name[1] == 'M') {

                gork = Data->P[plr].Mission[mpad].Prog;

                if (gork == 2) {
                    strcpy(Mev[STEP].Name, (plr == 0) ? "HUM3C1" : "HSM3C1");
                } else if (gork == 3) {
                    strcpy(Mev[STEP].Name, (plr == 0) ? "HUM3C2" : "HSM3C2");
                } else {
                    strcpy(Mev[STEP].Name, (plr == 0) ? "HUM3C3" : "HSM3C3");
                }

                tomflag = 1;
            };



            //:::::: Failure docking klugge

            if (Mev[STEP].Name[0] == 'I') {
                gork = Data->P[plr].Mission[mpad].Prog;

                if (gork == 2) {
                    strcpy(Mev[STEP].Name, (plr == 0) ? "IUM4C1" : "ISM4C1");
                } else if (gork == 3) {
                    strcpy(Mev[STEP].Name, (plr == 0) ? "IUM4C2" : "ISM4C2");
                } else {
                    strcpy(Mev[STEP].Name, (plr == 0) ? "IUM4C3" : "ISM4C3");
                }
            };

// *********** TOM's FAIL HMOON KLUDGE

            // if HMOON FAILURE
            if (tomflag) {
                GetFailStat(&Now, Mev[STEP].FName, 7595);
            } else {
                DEBUG3("Failing !tomflag - calling GetFailStat(&Now, Mev[STEP].FName %s, MEV[STEP].rnum %d))", Mev[STEP].FName, Mev[STEP].rnum);
                GetFailStat(&Now, Mev[STEP].FName, Mev[STEP].rnum);     // all others
            }


            memset(Name, 0x00, sizeof Name);
            memcpy(Name, Mev[STEP].Name, strlen(Mev[STEP].Name)); // copy orig failure
            Name[strlen(Name)] = 0x30 + (Now.fail / 10);
            Name[strlen(Name)] = 0x30 + Now.fail % 10;
            Name[strlen(Name)] = 0x00;




            //:::::: STEP FAILURE :::::::::
            //:::::::::::::::::::::::::::::

            PlaySequence(plr, STEP, Name, 1);

            if (!AI[plr]) {
                Tick(2);    //reset dials
            }

            FailEval(plr, Now.code, Now.text, Now.val, Now.xtra);
        } else {   // Step Success

            if (Mev[STEP].loc == 28 || Mev[STEP].loc == 27) {
                strcpy(Mev[STEP].Name, (plr == 0) ? "bUC0" : "bSC0");
                Mev[STEP].Name[5] = Mev[STEP].E->ID[1];
            }

            if (strncmp(Mev[STEP].E->Name, "DO", 2) == 0) {
                if (Mev[STEP].loc == 2) {
                    Data->P[plr].DockingModuleInOrbit = 2;
                }
            }

            //::::::::::::::::::::::::::::::::::
            //::: SUCCESS: Docking klugge ::::::
            //::::::::::::::::::::::::::::::::::
            if (Mev[STEP].Name[0] == 'I') {
                gork = Data->P[plr].Mission[mpad].Prog;

                if (gork == 2) {
                    strcpy(Mev[STEP].Name, (plr == 0) ? "IUM4C1" : "ISM4C1");
                } else if (gork == 3) {
                    strcpy(Mev[STEP].Name, (plr == 0) ? "IUM4C2" : "ISM4C2");
                } else {
                    strcpy(Mev[STEP].Name, (plr == 0) ? "IUM4C3" : "ISM4C3");
                }
            };

            if (Mev[STEP].Name[0] == 'e' && Data->P[plr].Mission[mpad].MissionCode == Mission_LunarFlyby) {
                strcpy(Mev[STEP].Name, (plr == 0) ? "VUP1" : "VSP1");
            }

            //:::::: STEP SUCCESS :::::::::
            //:::::::::::::::::::::::::::::
            // FemaleAstronautsAllowed step klugge
            // third parameter (0 -> MALE) (2 -> FEMALE)
            //:::::::::::::::::::::::::::::

            gork = ((MA[0][0].A != NULL && MA[0][0].A->Sex && EVA[0] == 0)
                    || (MA[0][1].A != NULL && MA[0][1].A->Sex && EVA[0] == 1)
                    || (MA[0][2].A != NULL && MA[0][2].A->Sex && EVA[0] == 2)
                    || (MA[0][3].A != NULL && MA[0][3].A->Sex && EVA[0] == 3)
                    || (MA[1][0].A != NULL && MA[1][0].A->Sex && EVA[1] == 0)
                    || (MA[1][1].A != NULL && MA[1][1].A->Sex && EVA[1] == 1)
                    || (MA[1][2].A != NULL && MA[1][2].A->Sex && EVA[1] == 2)
                    || (MA[1][3].A != NULL && MA[1][3].A->Sex && EVA[1] == 3));

            //if (!((mcc==9 || mcc==11) && (Mev[STEP].Name[0]=='W')))
            PlaySequence(plr, STEP, Mev[STEP].Name, (gork == 1) ? 2 : 0); // Play Animations

            if (Mev[STEP].sgoto == 100) {
                Mev[STEP].trace = 0x7F;
            } else if (Mev[STEP].sgoto != 0) {
                Mev[STEP].trace = Mev[STEP].sgoto;
            } else {
                Mev[STEP].trace = STEP + 1;
            }

            if (!(strncmp(Mev[STEP].E->Name, "DO", 2) == 0 && Mev[STEP].loc == 0x02)) {
                Mev[STEP].E->MisSucc++; // set for all but docking power on
            }

            Mev[STEP].StepInfo = 1;

            // Bottom of success statement
        }

        if (Mev[STEP].loc == 0x7f || Mev[STEP].sgoto == 100) { // force mission end
            Mev[STEP].trace = 0x7f;
        }

        if ((mcc == 10 || mcc == 12 || mcc == 13) && STEP == 2) {
            Mev[STEP].trace = 0x7f;
        }

        if (STEP > 30 || STEP < 0) {
            delay(20);
        }

        if (Mev[STEP].Prest != 0) {
            pAry[pCnt++] = STEP;
        }

        if (Mev[STEP].sgoto == Mev[STEP].fgoto && Mev[STEP].trace != 0x7f) {
            Mev[STEP].trace = Mev[STEP].sgoto;
        }

        if (Mev[STEP].loc == 8 && Mev[STEP].StepInfo == 1) {
            noDock = 1;
        }

        if (Mev[STEP].loc == 0 && MANNED[Mev[STEP].pad] > 0) {
            InSpace++;
        }

        if (Mev[STEP].loc == 4 && MANNED[Mev[STEP].pad] > 0) {
            InSpace--;
        }

        // these two lines fix a problem with Lab Missions failing on launch and
        // ending the mission.
        // Yet another in the ongoing series of special cases.
        //

        if (Mev[STEP].trace == 0x7f && STEP == 3) {
            switch (Mis.Index) {
            case 19:
            case 22:
            case 23:
            case 30:
            case 32:
            case 35:
            case 36:
            case 37:
                InSpace = 1;
                Mev[STEP].trace = Mev[STEP].dgoto;

            default:
                break;
            }
        }

//  if (Mev[STEP].trace==0x7f && InSpace>0) Mev[STEP].trace=STEP+1;

    } while (Mev[STEP].trace != 0x7f);         // End mission

    //end do
    if (!AI[plr] && death == 0) {
        delay(1000);
    }

    if ((MA[0][0].A != NULL && MA[0][0].A->Status == AST_ST_DEAD)
        || (MA[0][1].A != NULL && MA[0][1].A->Status == AST_ST_DEAD)
        || (MA[0][2].A != NULL && MA[0][2].A->Status == AST_ST_DEAD)
        || (MA[0][3].A != NULL && MA[0][3].A->Status == AST_ST_DEAD)
        || (MA[1][0].A != NULL && MA[1][0].A->Status == AST_ST_DEAD)
        || (MA[1][1].A != NULL && MA[1][1].A->Status == AST_ST_DEAD)
        || (MA[1][2].A != NULL && MA[1][2].A->Status == AST_ST_DEAD)
        || (MA[1][3].A != NULL && MA[1][3].A->Status == AST_ST_DEAD)) {
        // Mission Death
        if (!AI[plr]) {
            if (!fullscreenMissionPlayback) {
                display::AutoPal p(display::graphics.legacyScreen());
                memset(&p.pal[64 * 3], 0x00, 64 * 3); //Specs: 0x08

                if (plr == 0) {
                    fill_rectangle(2, 107, 140, 115, 3);
                } else {
                    fill_rectangle(78, 2, 241, 10, 3);
                }

                if (plr == 0) {
                    fill_rectangle(188, 107, 294, 113, 3);
                } else {
                    fill_rectangle(244, 56, 314, 62, 3);
                }
            }

            PlaySequence(plr, STEP, (plr == 0) ? "UFUN" : "SFUN", 0);
        }

        if (!AI[plr]) {
            delay(1000);
        }

        death = 1;
    } else {
        death = 0;
    };

    return;
}
Example #16
0
GLOBAL Int UMF_row_search
(
    NumericType *Numeric,
    WorkType *Work,
    SymbolicType *Symbolic,
    Int cdeg0,			/* length of column in Front */
    Int cdeg1,			/* length of column outside Front */
    const Int Pattern [ ],	/* pattern of column, Pattern [0..cdeg1 -1] */
    const Int Pos [ ],		/* Pos [Pattern [0..cdeg1 -1]] = 0..cdeg1 -1 */
    Int pivrow [2],		/* pivrow [IN] and pivrow [OUT] */
    Int rdeg [2],		/* rdeg [IN] and rdeg [OUT] */
    Int W_i [ ],		/* pattern of pivrow [IN], */
				/* either Fcols or Woi */
    Int W_o [ ],		/* pattern of pivrow [OUT], */
				/* either Wio or Woo */
    Int prior_pivrow [2],	/* the two other rows just scanned, if any */
    const Entry Wxy [ ],	/* numerical values Wxy [0..cdeg1-1],
				   either Wx or Wy */

    Int pivcol,			/* the candidate column being searched */
    Int freebie [ ]
)
{

    /* ---------------------------------------------------------------------- */
    /* local variables */
    /* ---------------------------------------------------------------------- */

    double maxval, toler, toler2, value, pivot [2] ;
    Int i, row, deg, col, *Frpos, fnrows, *E, j, ncols, *Cols, *Rows,
	e, f, Wrpflag, *Fcpos, fncols, tpi, max_rdeg, nans_in_col, was_offdiag,
	diag_row, prefer_diagonal, *Wrp, found, *Diagonal_map ;
    Tuple *tp, *tpend, *tp1, *tp2 ;
    Unit *Memory, *p ;
    Element *ep ;
    Int *Row_tuples, *Row_degree, *Row_tlen ;

#ifndef NDEBUG
    Int *Col_degree ;
    DEBUG2 (("Row_search:\n")) ;
    for (i = 0 ; i < cdeg1 ; i++)
    {
	row = Pattern [i] ;
	DEBUG4 (("   row: "ID"\n", row)) ;
	ASSERT (row >= 0 && row < Numeric->n_row) ;
	ASSERT (i == Pos [row]) ;
    }
    /* If row is not in Pattern [0..cdeg1-1], then Pos [row] == EMPTY */
    if (UMF_debug > 0 || Numeric->n_row < 1000)
    {
	Int cnt = cdeg1 ;
	DEBUG4 (("Scan all rows:\n")) ;
	for (row = 0 ; row < Numeric->n_row ; row++)
	{
	    if (Pos [row] < 0)
	    {
		cnt++ ;
	    }
	    else
	    {
		DEBUG4 (("   row: "ID" pos "ID"\n", row, Pos [row])) ;
	    }
	}
	ASSERT (cnt == Numeric->n_row) ;
    }
    Col_degree = Numeric->Cperm ;   /* for NON_PIVOTAL_COL macro only */
    ASSERT (pivcol >= 0 && pivcol < Work->n_col) ;
    ASSERT (NON_PIVOTAL_COL (pivcol)) ;
#endif

    pivot [IN] = 0. ;
    pivot [OUT] = 0. ;

    /* ---------------------------------------------------------------------- */
    /* get parameters */
    /* ---------------------------------------------------------------------- */

    Row_degree = Numeric->Rperm ;
    Row_tuples = Numeric->Uip ;
    Row_tlen   = Numeric->Uilen ;
    Wrp = Work->Wrp ;
    Frpos = Work->Frpos ;
    E = Work->E ;
    Memory = Numeric->Memory ;
    fnrows = Work->fnrows ;

    prefer_diagonal = Symbolic->prefer_diagonal ;
    Diagonal_map = Work->Diagonal_map ;

    if (Diagonal_map)
    {
	diag_row = Diagonal_map [pivcol] ;
	was_offdiag = diag_row < 0 ;
	if (was_offdiag)
	{
	    /* the "diagonal" entry in this column was permuted here by an
	     * earlier pivot choice.  The tighter off-diagonal tolerance will
	     * be used instead of the symmetric tolerance. */
	    diag_row = FLIP (diag_row) ;
	}
	ASSERT (diag_row >= 0 && diag_row < Numeric->n_row) ;
    }
    else
    {
	diag_row = EMPTY ;	/* unused */
	was_offdiag = EMPTY ;	/* unused */
    }

    /* pivot row degree cannot exceed max_rdeg */
    max_rdeg = Work->fncols_max ;

    /* ---------------------------------------------------------------------- */
    /* scan pivot column for candidate rows */
    /* ---------------------------------------------------------------------- */

    maxval = 0.0 ;
    nans_in_col = FALSE ;

    for (i = 0 ; i < cdeg1 ; i++)
    {
	APPROX_ABS (value, Wxy [i]) ;
	if (SCALAR_IS_NAN (value))
	{
	    nans_in_col = TRUE ;
	    maxval = value ;
	    break ;
	}
	/* This test can now ignore the NaN case: */
	maxval = MAX (maxval, value) ;
    }

    /* if maxval is zero, the matrix is numerically singular */

    toler = Numeric->relpt * maxval ;
    toler2 = Numeric->relpt2 * maxval ;
    toler2 = was_offdiag ? toler : toler2 ;

    DEBUG5 (("Row_search begins [ maxval %g toler %g %g\n",
	maxval, toler, toler2)) ;
    if (SCALAR_IS_NAN (toler) || SCALAR_IS_NAN (toler2))
    {
	nans_in_col = TRUE ;
    }

    if (!nans_in_col)
    {

	/* look for the diagonal entry, if it exists */
	found = FALSE ;
	ASSERT (!SCALAR_IS_NAN (toler)) ;

	if (prefer_diagonal)
	{
	    ASSERT (diag_row != EMPTY) ;
	    i = Pos [diag_row] ;
	    if (i >= 0)
	    {
		double a ;
		ASSERT (i < cdeg1) ;
		ASSERT (diag_row == Pattern [i]) ;

		APPROX_ABS (a, Wxy [i]) ;

		ASSERT (!SCALAR_IS_NAN (a)) ;
		ASSERT (!SCALAR_IS_NAN (toler2)) ;

		if (SCALAR_IS_NONZERO (a) && a >= toler2)
		{
		    /* found it! */
		    DEBUG3 (("Symmetric pivot: "ID" "ID"\n", pivcol, diag_row));
		    found = TRUE ;
		    if (Frpos [diag_row] >= 0 && Frpos [diag_row] < fnrows)
		    {
			pivrow [IN] = diag_row ;
			pivrow [OUT] = EMPTY ;
		    }
		    else
		    {
			pivrow [IN] = EMPTY ;
			pivrow [OUT] = diag_row ;
		    }
		}
	    }
	}

	/* either no diagonal found, or we didn't look for it */
	if (!found)
	{
	    if (cdeg0 > 0)
	    {

		/* this is a column in the front */
		for (i = 0 ; i < cdeg0 ; i++)
		{
		    double a ;
		    APPROX_ABS (a, Wxy [i]) ;
		    ASSERT (!SCALAR_IS_NAN (a)) ;
		    ASSERT (!SCALAR_IS_NAN (toler)) ;
		    if (SCALAR_IS_NONZERO (a) && a >= toler)
		    {
			row = Pattern [i] ;
			deg = Row_degree [row] ;
#ifndef NDEBUG
			DEBUG6 ((ID" candidate row "ID" deg "ID" absval %g\n",
			    i, row, deg, a)) ;
			UMF_dump_rowcol (0, Numeric, Work, row, TRUE) ;
#endif
			ASSERT (Frpos [row] >= 0 && Frpos [row] < fnrows) ;
			ASSERT (Frpos [row] == i) ;
			/* row is in the current front */
			DEBUG4 ((" in front\n")) ;
			if (deg < rdeg [IN]
			    /* break ties by picking the largest entry: */
			       || (deg == rdeg [IN] && a > pivot [IN])
			    /* break ties by picking the diagonal entry: */
			    /* || (deg == rdeg [IN] && row == diag_row) */
			   )
			{
			    /* best row in front, so far */
			    pivrow [IN] = row ;
			    rdeg [IN] = deg ;
			    pivot [IN] = a ;
			}
		    }
		}
		for ( ; i < cdeg1 ; i++)
		{
		    double a ;
		    APPROX_ABS (a, Wxy [i]) ;
		    ASSERT (!SCALAR_IS_NAN (a)) ;
		    ASSERT (!SCALAR_IS_NAN (toler)) ;
		    if (SCALAR_IS_NONZERO (a) && a >= toler)
		    {
			row = Pattern [i] ;
			deg = Row_degree [row] ;
#ifndef NDEBUG
			DEBUG6 ((ID" candidate row "ID" deg "ID" absval %g\n",
			    i, row, deg, a)) ;
			UMF_dump_rowcol (0, Numeric, Work, row, TRUE) ;
#endif
			ASSERT (Frpos [row] == i) ;
			/* row is not in the current front */
			DEBUG4 ((" NOT in front\n")) ;
			if (deg < rdeg [OUT]
			    /* break ties by picking the largest entry: */
			       || (deg == rdeg [OUT] && a > pivot [OUT])
			    /* break ties by picking the diagonal entry: */
			    /* || (deg == rdeg [OUT] && row == diag_row) */
			   )
			{
			    /* best row not in front, so far */
			    pivrow [OUT] = row ;
			    rdeg [OUT] = deg ;
			    pivot [OUT] = a ;
			}
		    }
		}

	    }
	    else
	    {

		/* this column is not in the front */
		for (i = 0 ; i < cdeg1 ; i++)
		{
		    double a ;
		    APPROX_ABS (a, Wxy [i]) ;
		    ASSERT (!SCALAR_IS_NAN (a)) ;
		    ASSERT (!SCALAR_IS_NAN (toler)) ;
		    if (SCALAR_IS_NONZERO (a) && a >= toler)
		    {
			row = Pattern [i] ;
			deg = Row_degree [row] ;
#ifndef NDEBUG
			DEBUG6 ((ID" candidate row "ID" deg "ID" absval %g\n",
			    i, row, deg, a)) ;
			UMF_dump_rowcol (0, Numeric, Work, row, TRUE) ;
#endif
			if (Frpos [row] >= 0 && Frpos [row] < fnrows)
			{
			    /* row is in the current front */
			    DEBUG4 ((" in front\n")) ;
			    if (deg < rdeg [IN]
			    /* break ties by picking the largest entry: */
			       || (deg == rdeg [IN] && a > pivot [IN])
			    /* break ties by picking the diagonal entry: */
			    /* || (deg == rdeg [IN] && row == diag_row) */
			       )
			    {
				/* best row in front, so far */
				pivrow [IN] = row ;
				rdeg [IN] = deg ;
				pivot [IN] = a ;
			    }
			}
			else
			{
			    /* row is not in the current front */
			    DEBUG4 ((" NOT in front\n")) ;
			    if (deg < rdeg [OUT]
			    /* break ties by picking the largest entry: */
			       || (deg == rdeg[OUT] && a > pivot [OUT])
			    /* break ties by picking the diagonal entry: */
			    /* || (deg == rdeg[OUT] && row == diag_row) */
			       )
			    {
				/* best row not in front, so far */
				pivrow [OUT] = row ;
				rdeg [OUT] = deg ;
				pivot [OUT] = a ;
			    }
			}
		    }
		}
	    }
	}
    }

    /* ---------------------------------------------------------------------- */
    /* NaN handling */
    /* ---------------------------------------------------------------------- */

    /* if cdeg1 > 0 then we must have found a pivot row ... unless NaN's */
    /* exist.  Try with no numerical tests if no pivot found. */

    if (cdeg1 > 0 && pivrow [IN] == EMPTY && pivrow [OUT] == EMPTY)
    {
	/* cleanup for the NaN case */
	DEBUG0 (("Found a NaN in pivot column!\n")) ;

	/* grab the first entry in the pivot column, ignoring degree, */
	/* numerical stability, and symmetric preference */
	row = Pattern [0] ;
	deg = Row_degree [row] ;
	if (Frpos [row] >= 0 && Frpos [row] < fnrows)
	{
	    /* row is in the current front */
	    DEBUG4 ((" in front\n")) ;
	    pivrow [IN] = row ;
	    rdeg [IN] = deg ;
	}
	else
	{
	    /* row is not in the current front */
	    DEBUG4 ((" NOT in front\n")) ;
	    pivrow [OUT] = row ;
	    rdeg [OUT] = deg ;
	}

	/* We are now guaranteed to have a pivot, no matter how broken */
	/* (non-IEEE compliant) the underlying numerical operators are. */
	/* This is particularly a problem for Microsoft compilers (they do */
	/* not handle NaN's properly). Now try to find a sparser pivot, if */
	/* possible. */

	for (i = 1 ; i < cdeg1 ; i++)
	{
	    row = Pattern [i] ;
	    deg = Row_degree [row] ;

	    if (Frpos [row] >= 0 && Frpos [row] < fnrows)
	    {
		/* row is in the current front */
		DEBUG4 ((" in front\n")) ;
		if (deg < rdeg [IN] || (deg == rdeg [IN] && row == diag_row))
		{
		    /* best row in front, so far */
		    pivrow [IN] = row ;
		    rdeg [IN] = deg ;
		}
	    }
	    else
	    {
		/* row is not in the current front */
		DEBUG4 ((" NOT in front\n")) ;
		if (deg < rdeg [OUT] || (deg == rdeg [OUT] && row == diag_row))
		{
		    /* best row not in front, so far */
		    pivrow [OUT] = row ;
		    rdeg [OUT] = deg ;
		}
	    }
	}
    }

    /* We found a pivot if there are entries (even zero ones) in pivot col */
    ASSERT (IMPLIES (cdeg1 > 0, pivrow[IN] != EMPTY || pivrow[OUT] != EMPTY)) ;

    /* If there are no entries in the pivot column, then no pivot is found */
    ASSERT (IMPLIES (cdeg1 == 0, pivrow[IN] == EMPTY && pivrow[OUT] == EMPTY)) ;

    /* ---------------------------------------------------------------------- */
    /* check for singular matrix */
    /* ---------------------------------------------------------------------- */

    if (cdeg1  == 0)
    {
	if (fnrows > 0)
	{
	    /*
		Get the pivrow [OUT][IN] from the current front.
		The frontal matrix looks like this:

			pivcol[OUT]
			|
			v
		x x x x 0   <- so grab this row as the pivrow [OUT][IN].
		x x x x 0
		x x x x 0
		0 0 0 0 0

		The current frontal matrix has some rows in it.  The degree
		of the pivcol[OUT] is zero.  The column is empty, and the
		current front does not contribute to it.

	    */
	    pivrow [IN] = Work->Frows [0] ;
	    DEBUGm4 (("Got zero pivrow[OUT][IN] "ID" from current front\n",
		pivrow [IN])) ;
	}
	else
	{

	    /*
		Get a pivot row from the row-merge tree, use as
		pivrow [OUT][OUT].   pivrow [IN] remains EMPTY.
		This can only happen if the current front is 0-by-0.
	    */

	    Int *Front_leftmostdesc, *Front_1strow, *Front_new1strow, row1,
		row2, fleftmost, nfr, n_row, frontid ;

	    ASSERT (Work->fncols == 0) ;

	    Front_leftmostdesc = Symbolic->Front_leftmostdesc ;
	    Front_1strow = Symbolic->Front_1strow ;
	    Front_new1strow = Work->Front_new1strow ;
	    nfr = Symbolic->nfr ;
	    n_row = Numeric->n_row ;
	    frontid = Work->frontid ;

	    DEBUGm4 (("Note: pivcol: "ID" is empty front "ID"\n",
		pivcol, frontid)) ;
#ifndef NDEBUG
	    DEBUG1 (("Calling dump rowmerge\n")) ;
	    UMF_dump_rowmerge (Numeric, Symbolic, Work) ;
#endif

	    /* Row-merge set is the non-pivotal rows in the range */
	    /* Front_new1strow [Front_leftmostdesc [frontid]] to */
	    /* Front_1strow [frontid+1] - 1. */
	    /* If this is empty, then use the empty rows, in the range */
	    /* Front_new1strow [nfr] to n_row-1. */
	    /* If this too is empty, then pivrow [OUT] will be empty. */
	    /* In both cases, update Front_new1strow [...]. */

	    fleftmost = Front_leftmostdesc [frontid] ;
	    row1 = Front_new1strow [fleftmost] ;
	    row2 = Front_1strow [frontid+1] - 1 ;
	    DEBUG1 (("Leftmost: "ID" Rows ["ID" to "ID"] srch ["ID" to "ID"]\n",
		fleftmost, Front_1strow [frontid], row2, row1, row2)) ;

	    /* look in the range row1 ... row2 */
	    for (row = row1 ; row <= row2 ; row++)
	    {
		DEBUG3 (("   Row: "ID"\n", row)) ;
		if (NON_PIVOTAL_ROW (row))
		{
		    /* found it */
		    DEBUG3 (("   Row: "ID" found\n", row)) ;
		    ASSERT (Frpos [row] == EMPTY) ;
		    pivrow [OUT] = row ;
		    DEBUGm4 (("got row merge pivrow %d\n", pivrow [OUT])) ;
		    break ;
		}
	    }
	    Front_new1strow [fleftmost] = row ;

	    if (pivrow [OUT] == EMPTY)
	    {
		/* not found, look in empty row set in "dummy" front */
		row1 = Front_new1strow [nfr] ;
		row2 = n_row-1 ;
		DEBUG3 (("Empty: "ID" Rows ["ID" to "ID"] srch["ID" to "ID"]\n",
		    nfr, Front_1strow [nfr], row2, row1, row2)) ;

		/* look in the range row1 ... row2 */
		for (row = row1 ; row <= row2 ; row++)
		{
		    DEBUG3 (("   Empty Row: "ID"\n", row)) ;
		    if (NON_PIVOTAL_ROW (row))
		    {
			/* found it */
			DEBUG3 (("   Empty Row: "ID" found\n", row)) ;
			ASSERT (Frpos [row] == EMPTY) ;
			pivrow [OUT] = row ;
			DEBUGm4 (("got dummy row pivrow %d\n", pivrow [OUT])) ;
			break ;
		    }
		}
		Front_new1strow [nfr] = row ;
	    }

	    if (pivrow [OUT] == EMPTY)
	    {
		/* Row-merge set is empty.  We can just discard */
		/* the candidate pivot column. */
		DEBUG0 (("Note: row-merge set empty\n")) ;
		DEBUGm4 (("got no pivrow \n")) ;
		return (UMFPACK_WARNING_singular_matrix) ;
	    }
	}
    }

    /* ---------------------------------------------------------------------- */
    /* construct the candidate row in the front, if any */
    /* ---------------------------------------------------------------------- */

#ifndef NDEBUG
    /* check Wrp */
    ASSERT (Work->Wrpflag > 0) ;
    if (UMF_debug > 0 || Work->n_col < 1000)
    {
	for (i = 0 ; i < Work->n_col ; i++)
	{
	    ASSERT (Wrp [i] < Work->Wrpflag) ;
	}
    }
#endif

#ifndef NDEBUG
    DEBUG4 (("pivrow [IN]: "ID"\n", pivrow [IN])) ;
    UMF_dump_rowcol (0, Numeric, Work, pivrow [IN], TRUE) ;
#endif

    if (pivrow [IN] != EMPTY)
    {

	/* the row merge candidate row is not pivrow [IN] */
	freebie [IN] = (pivrow [IN] == prior_pivrow [IN]) && (cdeg1  > 0) ;
	ASSERT (cdeg1  >= 0) ;

	if (!freebie [IN])
	{
	    /* include current front in the degree of this row */

	    Fcpos = Work->Fcpos ;
	    fncols = Work->fncols ;

	    Wrpflag = Work->Wrpflag ;

	    /* -------------------------------------------------------------- */
	    /* construct the pattern of the IN row */
	    /* -------------------------------------------------------------- */

#ifndef NDEBUG
	    /* check Fcols */
	    DEBUG5 (("ROW ASSEMBLE: rdeg "ID"\nREDUCE ROW "ID"\n",
		fncols, pivrow [IN])) ;
	    for (j = 0 ; j < fncols ; j++)
	    {
		col = Work->Fcols [j] ;
		ASSERT (col >= 0 && col < Work->n_col) ;
		ASSERT (Fcpos [col] >= 0) ;
	    }
	    if (UMF_debug > 0 || Work->n_col < 1000)
	    {
		Int cnt = fncols ;
		for (col = 0 ; col < Work->n_col ; col++)
		{
		    if (Fcpos [col] < 0) cnt++ ;
		}
		ASSERT (cnt == Work->n_col) ;
	    }
#endif

	    rdeg [IN] = fncols ;

	    ASSERT (pivrow [IN] >= 0 && pivrow [IN] < Work->n_row) ;
	    ASSERT (NON_PIVOTAL_ROW (pivrow [IN])) ;

	    /* add the pivot column itself */
	    ASSERT (Wrp [pivcol] != Wrpflag) ;
	    if (Fcpos [pivcol] < 0)
	    {
		DEBUG3 (("Adding pivot col to pivrow [IN] pattern\n")) ;
		if (rdeg [IN] >= max_rdeg)
		{
		    /* :: pattern change (in) :: */
		    return (UMFPACK_ERROR_different_pattern) ;
		}
		Wrp [pivcol] = Wrpflag ;
		W_i [rdeg [IN]++] = pivcol ;
	    }

	    tpi = Row_tuples [pivrow [IN]] ;
	    if (tpi)
	    {
		tp = (Tuple *) (Memory + tpi) ;
		tp1 = tp ;
		tp2 = tp ;
		tpend = tp + Row_tlen [pivrow [IN]] ;
		for ( ; tp < tpend ; tp++)
		{
		    e = tp->e ;
		    ASSERT (e > 0 && e <= Work->nel) ;
		    if (!E [e])
		    {
			continue ;	/* element already deallocated */
		    }
		    f = tp->f ;
		    p = Memory + E [e] ;
		    ep = (Element *) p ;
		    p += UNITS (Element, 1) ;
		    Cols = (Int *) p ;
		    ncols = ep->ncols ;
		    Rows = Cols + ncols ;
		    if (Rows [f] == EMPTY)
		    {
			continue ;	/* row already assembled */
		    }
		    ASSERT (pivrow [IN] == Rows [f]) ;

		    for (j = 0 ; j < ncols ; j++)
		    {
			col = Cols [j] ;
			ASSERT (col >= EMPTY && col < Work->n_col) ;
			if ((col >= 0) && (Wrp [col] != Wrpflag)
			    && Fcpos [col] <0)
			{
			    ASSERT (NON_PIVOTAL_COL (col)) ;
			    if (rdeg [IN] >= max_rdeg)
			    {
				/* :: pattern change (rdeg in failure) :: */
				DEBUGm4 (("rdeg [IN] >= max_rdeg failure\n")) ;
				return (UMFPACK_ERROR_different_pattern) ;
			    }
			    Wrp [col] = Wrpflag ;
			    W_i [rdeg [IN]++] = col ;
			}
		    }

		    *tp2++ = *tp ;	/* leave the tuple in the list */
		}
		Row_tlen [pivrow [IN]] = tp2 - tp1 ;
	    }

#ifndef NDEBUG
	    DEBUG4 (("Reduced IN row:\n")) ;
	    for (j = 0 ; j < fncols ; j++)
	    {
		DEBUG6 ((" "ID" "ID" "ID"\n",
		    j, Work->Fcols [j], Fcpos [Work->Fcols [j]])) ;
		ASSERT (Fcpos [Work->Fcols [j]] >= 0) ;
	    }
	    for (j = fncols ; j < rdeg [IN] ; j++)
	    {
		DEBUG6 ((" "ID" "ID" "ID"\n", j, W_i [j], Wrp [W_i [j]]));
		ASSERT (W_i [j] >= 0 && W_i [j] < Work->n_col) ;
		ASSERT (Wrp [W_i [j]] == Wrpflag) ;
	    }
	    /* mark the end of the pattern in case we scan it by mistake */
	    /* Note that this means W_i must be of size >= fncols_max + 1 */
	    W_i [rdeg [IN]] = EMPTY ;
#endif

	    /* rdeg [IN] is now the exact degree of the IN row */

	    /* clear Work->Wrp. */
	    Work->Wrpflag++ ;
	    /* All Wrp [0..n_col] is now < Wrpflag */
	}
    }

#ifndef NDEBUG
    /* check Wrp */
    if (UMF_debug > 0 || Work->n_col < 1000)
    {
	for (i = 0 ; i < Work->n_col ; i++)
	{
	    ASSERT (Wrp [i] < Work->Wrpflag) ;
	}
    }
#endif

    /* ---------------------------------------------------------------------- */
    /* construct the candidate row not in the front, if any */
    /* ---------------------------------------------------------------------- */

#ifndef NDEBUG
    DEBUG4 (("pivrow [OUT]: "ID"\n", pivrow [OUT])) ;
    UMF_dump_rowcol (0, Numeric, Work, pivrow [OUT], TRUE) ;
#endif

    /* If this is a candidate row from the row merge set, force it to be */
    /* scanned (ignore prior_pivrow [OUT]). */

    if (pivrow [OUT] != EMPTY)
    {
	freebie [OUT] = (pivrow [OUT] == prior_pivrow [OUT]) && cdeg1  > 0 ;
	ASSERT (cdeg1  >= 0) ;

	if (!freebie [OUT])
	{

	    Wrpflag = Work->Wrpflag ;

	    /* -------------------------------------------------------------- */
	    /* construct the pattern of the row */
	    /* -------------------------------------------------------------- */

	    rdeg [OUT] = 0 ;

	    ASSERT (pivrow [OUT] >= 0 && pivrow [OUT] < Work->n_row) ;
	    ASSERT (NON_PIVOTAL_ROW (pivrow [OUT])) ;

	    /* add the pivot column itself */
	    ASSERT (Wrp [pivcol] != Wrpflag) ;
	    DEBUG3 (("Adding pivot col to pivrow [OUT] pattern\n")) ;
	    if (rdeg [OUT] >= max_rdeg)
	    {
		/* :: pattern change (out) :: */
		return (UMFPACK_ERROR_different_pattern) ;
	    }
	    Wrp [pivcol] = Wrpflag ;
	    W_o [rdeg [OUT]++] = pivcol ;

	    tpi = Row_tuples [pivrow [OUT]] ;
	    if (tpi)
	    {
		tp = (Tuple *) (Memory + tpi) ;
		tp1 = tp ;
		tp2 = tp ;
		tpend = tp + Row_tlen [pivrow [OUT]] ;
		for ( ; tp < tpend ; tp++)
		{
		    e = tp->e ;
		    ASSERT (e > 0 && e <= Work->nel) ;
		    if (!E [e])
		    {
			continue ;	/* element already deallocated */
		    }
		    f = tp->f ;
		    p = Memory + E [e] ;
		    ep = (Element *) p ;
		    p += UNITS (Element, 1) ;
		    Cols = (Int *) p ;
		    ncols = ep->ncols ;
		    Rows = Cols + ncols ;
		    if (Rows [f] == EMPTY)
		    {
			continue ;	/* row already assembled */
		    }
		    ASSERT (pivrow [OUT] == Rows [f]) ;

		    for (j = 0 ; j < ncols ; j++)
		    {
			col = Cols [j] ;
			ASSERT (col >= EMPTY && col < Work->n_col) ;
			if ((col >= 0) && (Wrp [col] != Wrpflag))
			{
			    ASSERT (NON_PIVOTAL_COL (col)) ;
			    if (rdeg [OUT] >= max_rdeg)
			    {
				/* :: pattern change (rdeg out failure) :: */
				DEBUGm4 (("rdeg [OUT] failure\n")) ;
				return (UMFPACK_ERROR_different_pattern) ;
			    }
			    Wrp [col] = Wrpflag ;
			    W_o [rdeg [OUT]++] = col ;
			}
		    }
		    *tp2++ = *tp ;	/* leave the tuple in the list */
		}
		Row_tlen [pivrow [OUT]] = tp2 - tp1 ;
	    }

#ifndef NDEBUG
	    DEBUG4 (("Reduced row OUT:\n")) ;
	    for (j = 0 ; j < rdeg [OUT] ; j++)
	    {
		DEBUG6 ((" "ID" "ID" "ID"\n", j, W_o [j], Wrp [W_o [j]])) ;
		ASSERT (W_o [j] >= 0 && W_o [j] < Work->n_col) ;
		ASSERT (Wrp [W_o [j]] == Wrpflag) ;
	    }
	    /* mark the end of the pattern in case we scan it by mistake */
	    /* Note that this means W_o must be of size >= fncols_max + 1 */
	    W_o [rdeg [OUT]] = EMPTY ;
#endif

	    /* rdeg [OUT] is now the exact degree of the row */

	    /* clear Work->Wrp. */
	    Work->Wrpflag++ ;
	    /* All Wrp [0..n] is now < Wrpflag */

	}

    }
    DEBUG5 (("Row_search end ] \n")) ;

#ifndef NDEBUG
    /* check Wrp */
    if (UMF_debug > 0 || Work->n_col < 1000)
    {
	for (i = 0 ; i < Work->n_col ; i++)
	{
	    ASSERT (Wrp [i] < Work->Wrpflag) ;
	}
    }
#endif

    return (UMFPACK_OK) ;
}
Example #17
0
PRIVATE void get_L
(
    Int Lp [ ],		/* of size n_row+1 */
    Int Lj [ ],		/* of size lnz, where lnz = Lp [n_row] */
    double Lx [ ],	/* of size lnz */
#ifdef COMPLEX
    double Lz [ ],	/* of size lnz */
#endif
    NumericType *Numeric,
    Int Pattern [ ],	/* workspace of size n_row */
    Int Wi [ ]		/* workspace of size n_row */
)
{
    /* ---------------------------------------------------------------------- */
    /* local variables */
    /* ---------------------------------------------------------------------- */

    Entry value ;
    Entry *xp, *Lval ;
    Int deg, *ip, j, row, n_row, n_col, n_inner, *Lpos, *Lilen, *Lip, p, llen,
        lnz2, lp, newLchain, k, pos, npiv, *Li, n1 ;
#ifdef COMPLEX
    Int split = SPLIT (Lz) ;
#endif

    /* ---------------------------------------------------------------------- */
    /* get parameters */
    /* ---------------------------------------------------------------------- */

    DEBUG4 (("get_L start:\n")) ;
    n_row = Numeric->n_row ;
    n_col = Numeric->n_col ;
    n_inner = MIN (n_row, n_col) ;
    npiv = Numeric->npiv ;
    n1 = Numeric->n1 ;
    Lpos = Numeric->Lpos ;
    Lilen = Numeric->Lilen ;
    Lip = Numeric->Lip ;
    deg = 0 ;

    /* ---------------------------------------------------------------------- */
    /* count the nonzeros in each row of L */
    /* ---------------------------------------------------------------------- */

#pragma ivdep
    for (row = 0 ; row < n_inner ; row++)
    {
	/* include the diagonal entry in the row counts */
	Wi [row] = 1 ;
    }
#pragma ivdep
    for (row = n_inner ; row < n_row ; row++)
    {
	Wi [row] = 0 ;
    }

    /* singletons */
    for (k = 0 ; k < n1 ; k++)
    {
	DEBUG4 (("Singleton k "ID"\n", k)) ;
	deg = Lilen [k] ;
	if (deg > 0)
	{
	    lp = Lip [k] ;
	    Li = (Int *) (Numeric->Memory + lp) ;
	    lp += UNITS (Int, deg) ;
	    Lval = (Entry *) (Numeric->Memory + lp) ;
	    for (j = 0 ; j < deg ; j++)
	    {
		row = Li [j] ;
		value = Lval [j] ;
		DEBUG4 (("  row "ID"  k "ID" value", row, k)) ;
		EDEBUG4 (value) ;
		DEBUG4 (("\n")) ;
		if (IS_NONZERO (value))
		{
		    Wi [row]++ ;
		}
	    }
	}
    }

    /* non-singletons */
    for (k = n1 ; k < npiv ; k++)
    {

	/* ------------------------------------------------------------------ */
	/* make column of L in Pattern [0..deg-1] */
	/* ------------------------------------------------------------------ */

	lp = Lip [k] ;
	newLchain = (lp < 0) ;
	if (newLchain)
	{
	    lp = -lp ;
	    deg = 0 ;
	    DEBUG4 (("start of chain for column of L\n")) ;
	}

	/* remove pivot row */
	pos = Lpos [k] ;
	if (pos != EMPTY)
	{
	    DEBUG4 (("  k "ID" removing row "ID" at position "ID"\n",
	    k, Pattern [pos], pos)) ;
	    ASSERT (!newLchain) ;
	    ASSERT (deg > 0) ;
	    ASSERT (pos >= 0 && pos < deg) ;
	    ASSERT (Pattern [pos] == k) ;
	    Pattern [pos] = Pattern [--deg] ;
	}

	/* concatenate the pattern */
	ip = (Int *) (Numeric->Memory + lp) ;
	llen = Lilen [k] ;
	for (j = 0 ; j < llen ; j++)
	{
	    row = *ip++ ;
	    DEBUG4 (("  row "ID"  k "ID"\n", row, k)) ;
	    ASSERT (row > k && row < n_row) ;
	    Pattern [deg++] = row ;
	}

	xp = (Entry *) (Numeric->Memory + lp + UNITS (Int, llen)) ;

	for (j = 0 ; j < deg ; j++)
	{
	    DEBUG4 (("  row "ID"  k "ID" value", Pattern [j], k)) ;
	    row = Pattern [j] ;
	    value = *xp++ ;
	    EDEBUG4 (value) ;
	    DEBUG4 (("\n")) ;
	    if (IS_NONZERO (value))
	    {
		Wi [row]++ ;
	    }
	}
    }

    /* ---------------------------------------------------------------------- */
    /* construct the final row form of L */
    /* ---------------------------------------------------------------------- */

    /* create the row pointers */
    lnz2 = 0 ;
    for (row = 0 ; row < n_row ; row++)
    {
	Lp [row] = lnz2 ;
	lnz2 += Wi [row] ;
	Wi [row] = Lp [row] ;
    }
    Lp [n_row] = lnz2 ;
    ASSERT (Numeric->lnz + n_inner == lnz2) ;

    /* add entries from the rows of L (singletons) */
    for (k = 0 ; k < n1 ; k++)
    {
	DEBUG4 (("Singleton k "ID"\n", k)) ;
	deg = Lilen [k] ;
	if (deg > 0)
	{
	    lp = Lip [k] ;
	    Li = (Int *) (Numeric->Memory + lp) ;
	    lp += UNITS (Int, deg) ;
	    Lval = (Entry *) (Numeric->Memory + lp) ;
	    for (j = 0 ; j < deg ; j++)
	    {
		row = Li [j] ;
		value = Lval [j] ;
		DEBUG4 (("  row "ID"  k "ID" value", row, k)) ;
		EDEBUG4 (value) ;
		DEBUG4 (("\n")) ;
		if (IS_NONZERO (value))
		{
		    p = Wi [row]++ ;
		    Lj [p] = k ;
#ifdef COMPLEX
		    if (split)
		    {

		        Lx [p] = REAL_COMPONENT (value) ;
			Lz [p] = IMAG_COMPONENT (value) ;
		    }
		    else
		    {
			Lx [2*p  ] = REAL_COMPONENT (value) ;
			Lx [2*p+1] = IMAG_COMPONENT (value) ;
		    }
#else
		    Lx [p] = value ;
#endif
		}
	    }
	}
    }

    /* add entries from the rows of L (non-singletons) */
    for (k = n1 ; k < npiv ; k++)
    {

	/* ------------------------------------------------------------------ */
	/* make column of L in Pattern [0..deg-1] */
	/* ------------------------------------------------------------------ */

	lp = Lip [k] ;
	newLchain = (lp < 0) ;
	if (newLchain)
	{
	    lp = -lp ;
	    deg = 0 ;
	    DEBUG4 (("start of chain for column of L\n")) ;
	}

	/* remove pivot row */
	pos = Lpos [k] ;
	if (pos != EMPTY)
	{
	    DEBUG4 (("  k "ID" removing row "ID" at position "ID"\n",
	    k, Pattern [pos], pos)) ;
	    ASSERT (!newLchain) ;
	    ASSERT (deg > 0) ;
	    ASSERT (pos >= 0 && pos < deg) ;
	    ASSERT (Pattern [pos] == k) ;
	    Pattern [pos] = Pattern [--deg] ;
	}

	/* concatenate the pattern */
	ip = (Int *) (Numeric->Memory + lp) ;
	llen = Lilen [k] ;
	for (j = 0 ; j < llen ; j++)
	{
	    row = *ip++ ;
	    DEBUG4 (("  row "ID"  k "ID"\n", row, k)) ;
	    ASSERT (row > k) ;
	    Pattern [deg++] = row ;
	}

	xp = (Entry *) (Numeric->Memory + lp + UNITS (Int, llen)) ;

	for (j = 0 ; j < deg ; j++)
	{
	    DEBUG4 (("  row "ID"  k "ID" value", Pattern [j], k)) ;
	    row = Pattern [j] ;
	    value = *xp++ ;
	    EDEBUG4 (value) ;
	    DEBUG4 (("\n")) ;
	    if (IS_NONZERO (value))
	    {
		p = Wi [row]++ ;
		Lj [p] = k ;
#ifdef COMPLEX
		if (split)
		{
		    Lx [p] = REAL_COMPONENT (value) ;
		    Lz [p] = IMAG_COMPONENT (value) ;
		}
		else
		{
		    Lx [2*p  ] = REAL_COMPONENT (value) ;
		    Lx [2*p+1] = IMAG_COMPONENT (value) ;
		}
#else
		Lx [p] = value ;
#endif
	    }
	}
    }

    /* add all of the diagonal entries (L is unit diagonal) */
    for (row = 0 ; row < n_inner ; row++)
    {
	p = Wi [row]++ ;
	Lj [p] = row ;

#ifdef COMPLEX
	if (split)
	{
	    Lx [p] = 1. ;
	    Lz [p] = 0. ;
	}
	else
	{
	    Lx [2*p  ] = 1. ;
	    Lx [2*p+1] = 0. ;
	}
#else
	Lx [p] = 1. ;
#endif

	ASSERT (Wi [row] == Lp [row+1]) ;
    }

#ifndef NDEBUG
    DEBUG6 (("L matrix (stored by rows):")) ;
    UMF_dump_col_matrix (Lx,
#ifdef COMPLEX
	Lz,
#endif
	Lj, Lp, n_inner, n_row, Numeric->lnz+n_inner) ;
#endif

    DEBUG4 (("get_L done:\n")) ;
}