The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
// Copyright (C) 2000 - 2002 Hewlett-Packard Company
//
// This program is free software; you can redistribute it and/or modify it
// under the term of the GNU Lesser General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your
// option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
// for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
// _________________

// @(#) $Revision: 4.25 $ $Source: /judy/src/JudyCommon/JudyDecascade.c $
//
// "Decascade" support functions for JudyDel.c:  These functions convert
// smaller-index-size leaves to larger-index-size leaves, and also, bitmap
// leaves (LeafB1s) to Leaf1s, and some types of branches to smaller branches
// at the same index size.  Some "decascading" occurs explicitly in JudyDel.c,
// but rare or large subroutines appear as functions here, and the overhead to
// call them is negligible.
//
// Compile with one of -DJUDY1 or -DJUDYL.  Note:  Function names are converted
// to Judy1 or JudyL specific values by external #defines.

#if (! (defined(JUDY1) || defined(JUDYL)))
#error:  One of -DJUDY1 or -DJUDYL must be specified.
#endif

#ifdef JUDY1
#include "Judy1.h"
#endif
#ifdef JUDYL
#include "JudyL.h"
#endif

#include "JudyPrivate1L.h"

DBGCODE(extern void JudyCheckSorted(Pjll_t Pjll, Word_t Pop1, long IndexSize);)


// ****************************************************************************
// __ J U D Y   C O P Y   2   T O   3
//
// Copy one or more 2-byte Indexes to a series of 3-byte Indexes.

FUNCTION static void j__udyCopy2to3(
	uint8_t *  PDest,	// to where to copy 3-byte Indexes.
	uint16_t * PSrc,	// from where to copy 2-byte indexes.
	Word_t     Pop1,	// number of Indexes to copy.
	Word_t     MSByte)	// most-significant byte, prefix to each Index.
{
	Word_t	   Temp;	// for building 3-byte Index.

	assert(Pop1);

        do {
	    Temp = MSByte | *PSrc++;
	    JU_COPY3_LONG_TO_PINDEX(PDest, Temp);
	    PDest += 3;
        } while (--Pop1);

} // j__udyCopy2to3()


#ifdef JU_64BIT

// ****************************************************************************
// __ J U D Y   C O P Y   3   T O   4
//
// Copy one or more 3-byte Indexes to a series of 4-byte Indexes.

FUNCTION static void j__udyCopy3to4(
	uint32_t * PDest,	// to where to copy 4-byte Indexes.
	uint8_t *  PSrc,	// from where to copy 3-byte indexes.
	Word_t     Pop1,	// number of Indexes to copy.
	Word_t     MSByte)	// most-significant byte, prefix to each Index.
{
	Word_t	   Temp;	// for building 4-byte Index.

	assert(Pop1);

        do {
	    JU_COPY3_PINDEX_TO_LONG(Temp, PSrc);
	    Temp |= MSByte;
	    PSrc += 3;
	    *PDest++ = Temp;		// truncates to uint32_t.
        } while (--Pop1);

} // j__udyCopy3to4()


// ****************************************************************************
// __ J U D Y   C O P Y   4   T O   5
//
// Copy one or more 4-byte Indexes to a series of 5-byte Indexes.

FUNCTION static void j__udyCopy4to5(
	uint8_t *  PDest,	// to where to copy 4-byte Indexes.
	uint32_t * PSrc,	// from where to copy 4-byte indexes.
	Word_t     Pop1,	// number of Indexes to copy.
	Word_t     MSByte)	// most-significant byte, prefix to each Index.
{
	Word_t	   Temp;	// for building 5-byte Index.

	assert(Pop1);

        do {
	    Temp = MSByte | *PSrc++;
	    JU_COPY5_LONG_TO_PINDEX(PDest, Temp);
	    PDest += 5;
        } while (--Pop1);

} // j__udyCopy4to5()


// ****************************************************************************
// __ J U D Y   C O P Y   5   T O   6
//
// Copy one or more 5-byte Indexes to a series of 6-byte Indexes.

FUNCTION static void j__udyCopy5to6(
	uint8_t * PDest,	// to where to copy 6-byte Indexes.
	uint8_t * PSrc,		// from where to copy 5-byte indexes.
	Word_t    Pop1,		// number of Indexes to copy.
	Word_t    MSByte)	// most-significant byte, prefix to each Index.
{
	Word_t	  Temp;		// for building 6-byte Index.

	assert(Pop1);

        do {
	    JU_COPY5_PINDEX_TO_LONG(Temp, PSrc);
	    Temp |= MSByte;
	    JU_COPY6_LONG_TO_PINDEX(PDest, Temp);
	    PSrc  += 5;
	    PDest += 6;
        } while (--Pop1);

} // j__udyCopy5to6()


// ****************************************************************************
// __ J U D Y   C O P Y   6   T O   7
//
// Copy one or more 6-byte Indexes to a series of 7-byte Indexes.

FUNCTION static void j__udyCopy6to7(
	uint8_t * PDest,	// to where to copy 6-byte Indexes.
	uint8_t * PSrc,		// from where to copy 5-byte indexes.
	Word_t    Pop1,		// number of Indexes to copy.
	Word_t    MSByte)	// most-significant byte, prefix to each Index.
{
	Word_t	  Temp;		// for building 6-byte Index.

	assert(Pop1);

        do {
	    JU_COPY6_PINDEX_TO_LONG(Temp, PSrc);
	    Temp |= MSByte;
	    JU_COPY7_LONG_TO_PINDEX(PDest, Temp);
	    PSrc  += 6;
	    PDest += 7;
        } while (--Pop1);

} // j__udyCopy6to7()

#endif // JU_64BIT


#ifndef JU_64BIT // 32-bit

// ****************************************************************************
// __ J U D Y   C O P Y   3   T O   W
//
// Copy one or more 3-byte Indexes to a series of longs (words, always 4-byte).

FUNCTION static void j__udyCopy3toW(
	PWord_t   PDest,	// to where to copy full-word Indexes.
	uint8_t * PSrc,		// from where to copy 3-byte indexes.
	Word_t    Pop1,		// number of Indexes to copy.
	Word_t    MSByte)	// most-significant byte, prefix to each Index.
{
	assert(Pop1);

        do {
	    JU_COPY3_PINDEX_TO_LONG(*PDest, PSrc);
	    *PDest++ |= MSByte;
	    PSrc     += 3;
        } while (--Pop1);

} // j__udyCopy3toW()


#else // JU_64BIT

// ****************************************************************************
// __ J U D Y   C O P Y   7   T O   W
//
// Copy one or more 7-byte Indexes to a series of longs (words, always 8-byte).

FUNCTION static void j__udyCopy7toW(
	PWord_t   PDest,	// to where to copy full-word Indexes.
	uint8_t * PSrc,		// from where to copy 7-byte indexes.
	Word_t    Pop1,		// number of Indexes to copy.
	Word_t    MSByte)	// most-significant byte, prefix to each Index.
{
	assert(Pop1);

        do {
	    JU_COPY7_PINDEX_TO_LONG(*PDest, PSrc);
	    *PDest++ |= MSByte;
	    PSrc     += 7;
        } while (--Pop1);

} // j__udyCopy7toW()

#endif // JU_64BIT


// ****************************************************************************
// __ J U D Y   B R A N C H   B   T O   B R A N C H   L
//
// When a BranchB shrinks to have few enough JPs, call this function to convert
// it to a BranchL.  Return 1 for success, or -1 for failure (with details in
// Pjpm).

FUNCTION int j__udyBranchBToBranchL(
	Pjp_t	Pjp,		// points to BranchB to shrink.
	Pvoid_t	Pjpm)		// for global accounting.
{
	Pjbb_t	PjbbRaw;	// old BranchB to shrink.
	Pjbb_t	Pjbb;
	Pjbl_t	PjblRaw;	// new BranchL to create.
	Pjbl_t	Pjbl;
	Word_t	Digit;		// in BranchB.
	Word_t  NumJPs;		// non-null JPs in BranchB.
	uint8_t Expanse[cJU_BRANCHLMAXJPS];	// for building jbl_Expanse[].
	Pjp_t	Pjpjbl;		// current JP in BranchL.
	Word_t  SubExp;		// in BranchB.

	assert(JU_JPTYPE(Pjp) >= cJU_JPBRANCH_B2);
	assert(JU_JPTYPE(Pjp) <= cJU_JPBRANCH_B);

	PjbbRaw	= (Pjbb_t) (Pjp->jp_Addr);
	Pjbb	= P_JBB(PjbbRaw);

// Copy 1-byte subexpanse digits from BranchB to temporary buffer for BranchL,
// for each bit set in the BranchB:
//
// TBD:  The following supports variable-sized linear branches, but they are no
// longer variable; this could be simplified to save the copying.
//
// TBD:  Since cJU_BRANCHLMAXJP == 7 now, and cJU_BRANCHUNUMJPS == 256, the
// following might be inefficient; is there a faster way to do it?  At least
// skip wholly empty subexpanses?

	for (NumJPs = Digit = 0; Digit < cJU_BRANCHUNUMJPS; ++Digit)
	{
	    if (JU_BITMAPTESTB(Pjbb, Digit))
	    {
		Expanse[NumJPs++] = Digit;
		assert(NumJPs <= cJU_BRANCHLMAXJPS);	// required of caller.
	    }
	}

// Allocate and populate the BranchL:

	if ((PjblRaw = j__udyAllocJBL(Pjpm)) == (Pjbl_t) NULL) return(-1);
	Pjbl = P_JBL(PjblRaw);

	JU_COPYMEM(Pjbl->jbl_Expanse, Expanse, NumJPs);

	Pjbl->jbl_NumJPs = NumJPs;
	DBGCODE(JudyCheckSorted((Pjll_t) (Pjbl->jbl_Expanse), NumJPs, 1);)

// Copy JPs from each BranchB subexpanse subarray:

	Pjpjbl = P_JP(Pjbl->jbl_jp);	// start at first JP in array.

	for (SubExp = 0; SubExp < cJU_NUMSUBEXPB; ++SubExp)
	{
	    Pjp_t PjpRaw = JU_JBB_PJP(Pjbb, SubExp);	// current Pjp.
	    Pjp_t Pjp;

	    if (PjpRaw == (Pjp_t) NULL) continue;  // skip empty subexpanse.
	    Pjp = P_JP(PjpRaw);

	    NumJPs = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, SubExp));
	    assert(NumJPs);
	    JU_COPYMEM(Pjpjbl, Pjp, NumJPs);	 // one subarray at a time.

	    Pjpjbl += NumJPs;
	    j__udyFreeJBBJP(PjpRaw, NumJPs, Pjpm);	// subarray.
	}
	j__udyFreeJBB(PjbbRaw, Pjpm);		// BranchB itself.

// Finish up:  Calculate new JP type (same index size = level in new class),
// and tie new BranchB into parent JP:

	Pjp->jp_Type += cJU_JPBRANCH_L - cJU_JPBRANCH_B;
	Pjp->jp_Addr  = (Word_t) PjblRaw;

	return(1);

} // j__udyBranchBToBranchL()


#ifdef notdef

// ****************************************************************************
// __ J U D Y   B R A N C H   U   T O   B R A N C H   B
//
// When a BranchU shrinks to need little enough memory, call this function to
// convert it to a BranchB to save memory (at the cost of some speed).  Return
// 1 for success, or -1 for failure (with details in Pjpm).
//
// TBD:  Fill out if/when needed.  Not currently used in JudyDel.c for reasons
// explained there.

FUNCTION int j__udyBranchUToBranchB(
	Pjp_t	Pjp,		// points to BranchU to shrink.
	Pvoid_t	Pjpm)		// for global accounting.
{
	assert(FALSE);
	return(1);
}
#endif // notdef


#if (defined(JUDYL) || (! defined(JU_64BIT)))

// ****************************************************************************
// __ J U D Y   L E A F   B 1   T O   L E A F   1
//
// Shrink a bitmap leaf (cJU_LEAFB1) to linear leaf (cJU_JPLEAF1).
// Return 1 for success, or -1 for failure (with details in Pjpm).
//
// Note:  This function is different than the other JudyLeaf*ToLeaf*()
// functions because it receives a Pjp, not just a leaf, and handles its own
// allocation and free, in order to allow the caller to continue with a LeafB1
// if allocation fails.

FUNCTION int j__udyLeafB1ToLeaf1(
	Pjp_t	  Pjp,		// points to LeafB1 to shrink.
	Pvoid_t	  Pjpm)		// for global accounting.
{
	Pjlb_t    PjlbRaw;	// bitmap in old leaf.
	Pjlb_t    Pjlb;
	Pjll_t	  PjllRaw;	// new Leaf1.
	uint8_t	* Pleaf1;	// Leaf1 pointer type.
	Word_t    Digit;	// in LeafB1 bitmap.
#ifdef JUDYL
	Pjv_t	  PjvNew;	// value area in new Leaf1.
	Word_t    Pop1;
	Word_t    SubExp;
#endif

	assert(JU_JPTYPE(Pjp) == cJU_JPLEAF_B1);
	assert(((JU_JPDCDPOP0(Pjp) & 0xFF) + 1) == cJU_LEAF1_MAXPOP1);

// Allocate JPLEAF1 and prepare pointers:

	if ((PjllRaw = j__udyAllocJLL1(cJU_LEAF1_MAXPOP1, Pjpm)) == 0)
	    return(-1);

	Pleaf1	= (uint8_t *) P_JLL(PjllRaw);
	PjlbRaw	= (Pjlb_t) (Pjp->jp_Addr);
	Pjlb	= P_JLB(PjlbRaw);
	JUDYLCODE(PjvNew = JL_LEAF1VALUEAREA(Pleaf1, cJL_LEAF1_MAXPOP1);)

// Copy 1-byte indexes from old LeafB1 to new Leaf1:

	for (Digit = 0; Digit < cJU_BRANCHUNUMJPS; ++Digit)
	    if (JU_BITMAPTESTL(Pjlb, Digit))
		*Pleaf1++ = Digit;

#ifdef JUDYL

// Copy all old-LeafB1 value areas from value subarrays to new Leaf1:

	for (SubExp = 0; SubExp < cJU_NUMSUBEXPL; ++SubExp)
	{
	    Pjv_t PjvRaw = JL_JLB_PVALUE(Pjlb, SubExp);
	    Pjv_t Pjv    = P_JV(PjvRaw);

	    if (Pjv == (Pjv_t) NULL) continue;	// skip empty subarray.

	    Pop1 = j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, SubExp));  // subarray.
	    assert(Pop1);

	    JU_COPYMEM(PjvNew, Pjv, Pop1);		// copy value areas.
	    j__udyLFreeJV(PjvRaw, Pop1, Pjpm);
	    PjvNew += Pop1;				// advance through new.
	}

	assert((((Word_t) Pleaf1) - (Word_t) P_JLL(PjllRaw))
	    == (PjvNew - JL_LEAF1VALUEAREA(P_JLL(PjllRaw), cJL_LEAF1_MAXPOP1)));
#endif // JUDYL

	DBGCODE(JudyCheckSorted((Pjll_t) P_JLL(PjllRaw),
			    (((Word_t) Pleaf1) - (Word_t) P_JLL(PjllRaw)), 1);)

// Finish up:  Free the old LeafB1 and plug the new Leaf1 into the JP:
//
// Note:  jp_DcdPopO does not change here.

	j__udyFreeJLB1(PjlbRaw, Pjpm);

	Pjp->jp_Addr = (Word_t) PjllRaw;
	Pjp->jp_Type = cJU_JPLEAF1;

	return(1);

} // j__udyLeafB1ToLeaf1()

#endif // (JUDYL || (! JU_64BIT))


// ****************************************************************************
// __ J U D Y   L E A F   1   T O   L E A F   2
//
// Copy 1-byte Indexes from a LeafB1 or Leaf1 to 2-byte Indexes in a Leaf2.
// Pjp MUST be one of:  cJU_JPLEAF_B1, cJU_JPLEAF1, or cJU_JPIMMED_1_*.
// Return number of Indexes copied.
//
// TBD:  In this and all following functions, the caller should already be able
// to compute the Pop1 return value, so why return it?

FUNCTION Word_t  j__udyLeaf1ToLeaf2(
	uint16_t * PLeaf2,	// destination uint16_t * Index portion of leaf.
#ifdef JUDYL
	Pjv_t	   Pjv2,	// destination value part of leaf.
#endif
	Pjp_t	   Pjp,		// 1-byte-index object from which to copy.
	Word_t     MSByte,	// most-significant byte, prefix to each Index.
	Pvoid_t	   Pjpm)	// for global accounting.
{
	Word_t	   Pop1;	// Indexes in leaf.
	Word_t	   Offset;	// in linear leaf list.
JUDYLCODE(Pjv_t	   Pjv1Raw;)	// source object value area.
JUDYLCODE(Pjv_t	   Pjv1;)

	switch (JU_JPTYPE(Pjp))
	{


// JPLEAF_B1:

	case cJU_JPLEAF_B1:
	{
	    Pjlb_t Pjlb = P_JLB(Pjp->jp_Addr);
	    Word_t Digit;	// in LeafB1 bitmap.
  JUDYLCODE(Word_t SubExp;)	// in LeafB1.

	    Pop1 = JU_JPBRANCH_POP0(Pjp, 1) + 1; assert(Pop1);

// Copy 1-byte indexes from old LeafB1 to new Leaf2, including splicing in
// the missing MSByte needed in the Leaf2:

	    for (Digit = 0; Digit < cJU_BRANCHUNUMJPS; ++Digit)
		if (JU_BITMAPTESTL(Pjlb, Digit))
		    *PLeaf2++ = MSByte | Digit;

#ifdef JUDYL

// Copy all old-LeafB1 value areas from value subarrays to new Leaf2:

	    for (SubExp = 0; SubExp < cJU_NUMSUBEXPL; ++SubExp)
	    {
		Word_t SubExpPop1;

		Pjv1Raw = JL_JLB_PVALUE(Pjlb, SubExp);
		if (Pjv1Raw == (Pjv_t) NULL) continue;	// skip empty.
		Pjv1 = P_JV(Pjv1Raw);

		SubExpPop1 = j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, SubExp));
		assert(SubExpPop1);

		JU_COPYMEM(Pjv2, Pjv1, SubExpPop1);	// copy value areas.
		j__udyLFreeJV(Pjv1Raw, SubExpPop1, Pjpm);
		Pjv2 += SubExpPop1;			// advance through new.
	    }
#endif // JUDYL

	    j__udyFreeJLB1((Pjlb_t) (Pjp->jp_Addr), Pjpm);  // LeafB1 itself.
	    return(Pop1);

	} // case cJU_JPLEAF_B1


#if (defined(JUDYL) || (! defined(JU_64BIT)))

// JPLEAF1:

	case cJU_JPLEAF1:
	{
	    uint8_t * PLeaf1 = (uint8_t *) P_JLL(Pjp->jp_Addr);

	    Pop1 = JU_JPBRANCH_POP0(Pjp, 1) + 1; assert(Pop1);
	    JUDYLCODE(Pjv1 = JL_LEAF1VALUEAREA(PLeaf1, Pop1);)

// Copy all Index bytes including splicing in missing MSByte needed in Leaf2
// (plus, for JudyL, value areas):

	    for (Offset = 0; Offset < Pop1; ++Offset)
	    {
		PLeaf2[Offset] = MSByte | PLeaf1[Offset];
		JUDYLCODE(Pjv2[Offset] = Pjv1[Offset];)
	    }
	    j__udyFreeJLL1((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
	    return(Pop1);
	}
#endif // (JUDYL || (! JU_64BIT))


// JPIMMED_1_01:
//
// Note:  jp_DcdPopO has 3 [7] bytes of Index (all but most significant byte),
// so the assignment to PLeaf2[] truncates and MSByte is not needed.

	case cJU_JPIMMED_1_01:
	{
	    PLeaf2[0] = JU_JPDCDPOP0(Pjp);	// see above.
	    JUDYLCODE(Pjv2[0] = Pjp->jp_Addr;)
	    return(1);
	}


// JPIMMED_1_0[2+]:

	case cJU_JPIMMED_1_02:
	case cJU_JPIMMED_1_03:
#if (defined(JUDY1) || defined(JU_64BIT))
	case cJU_JPIMMED_1_04:
	case cJU_JPIMMED_1_05:
	case cJU_JPIMMED_1_06:
	case cJU_JPIMMED_1_07:
#endif
#if (defined(JUDY1) && defined(JU_64BIT))
	case cJ1_JPIMMED_1_08:
	case cJ1_JPIMMED_1_09:
	case cJ1_JPIMMED_1_10:
	case cJ1_JPIMMED_1_11:
	case cJ1_JPIMMED_1_12:
	case cJ1_JPIMMED_1_13:
	case cJ1_JPIMMED_1_14:
	case cJ1_JPIMMED_1_15:
#endif
	{
	    Pop1 = JU_JPTYPE(Pjp) - cJU_JPIMMED_1_02 + 2; assert(Pop1);
	    JUDYLCODE(Pjv1Raw = (Pjv_t) (Pjp->jp_Addr);)
	    JUDYLCODE(Pjv1    = P_JV(Pjv1Raw);)

	    for (Offset = 0; Offset < Pop1; ++Offset)
	    {
#ifdef JUDY1
		PLeaf2[Offset] = MSByte | Pjp->jp_1Index[Offset];
#else
		PLeaf2[Offset] = MSByte | Pjp->jp_LIndex[Offset];
		Pjv2  [Offset] = Pjv1[Offset];
#endif
	    }
	    JUDYLCODE(j__udyLFreeJV(Pjv1Raw, Pop1, Pjpm);)
	    return(Pop1);
	}


// UNEXPECTED CASES, including JPNULL1, should be handled by caller:

	default: assert(FALSE); break;

	} // switch

	return(0);

} // j__udyLeaf1ToLeaf2()


// *****************************************************************************
// __ J U D Y   L E A F   2   T O   L E A F   3
//
// Copy 2-byte Indexes from a Leaf2 to 3-byte Indexes in a Leaf3.
// Pjp MUST be one of:  cJU_JPLEAF2 or cJU_JPIMMED_2_*.
// Return number of Indexes copied.
//
// Note:  By the time this function is called to compress a level-3 branch to a
// Leaf3, the branch has no narrow pointers under it, meaning only level-2
// objects are below it and must be handled here.

FUNCTION Word_t  j__udyLeaf2ToLeaf3(
	uint8_t * PLeaf3,	// destination "uint24_t *" Index part of leaf.
#ifdef JUDYL
	Pjv_t	  Pjv3,		// destination value part of leaf.
#endif
	Pjp_t	  Pjp,		// 2-byte-index object from which to copy.
	Word_t    MSByte,	// most-significant byte, prefix to each Index.
	Pvoid_t	  Pjpm)		// for global accounting.
{
	Word_t	  Pop1;		// Indexes in leaf.
#if (defined(JUDYL) && defined(JU_64BIT))
	Pjv_t	  Pjv2Raw;	// source object value area.
#endif
JUDYLCODE(Pjv_t	  Pjv2;)

	switch (JU_JPTYPE(Pjp))
	{


// JPLEAF2:

	case cJU_JPLEAF2:
	{
	    uint16_t * PLeaf2 = (uint16_t *) P_JLL(Pjp->jp_Addr);

	    Pop1 = JU_JPLEAF_POP0(Pjp) + 1; assert(Pop1);
	    j__udyCopy2to3(PLeaf3, PLeaf2, Pop1, MSByte);
#ifdef JUDYL
	    Pjv2 = JL_LEAF2VALUEAREA(PLeaf2, Pop1);
	    JU_COPYMEM(Pjv3, Pjv2, Pop1);
#endif
	    j__udyFreeJLL2((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
	    return(Pop1);
	}


// JPIMMED_2_01:
//
// Note:  jp_DcdPopO has 3 [7] bytes of Index (all but most significant byte),
// so the "assignment" to PLeaf3[] is exact [truncates] and MSByte is not
// needed.

	case cJU_JPIMMED_2_01:
	{
	    JU_COPY3_LONG_TO_PINDEX(PLeaf3, JU_JPDCDPOP0(Pjp));	// see above.
	    JUDYLCODE(Pjv3[0] = Pjp->jp_Addr;)
	    return(1);
	}


// JPIMMED_2_0[2+]:

#if (defined(JUDY1) || defined(JU_64BIT))
	case cJU_JPIMMED_2_02:
	case cJU_JPIMMED_2_03:
#endif
#if (defined(JUDY1) && defined(JU_64BIT))
	case cJ1_JPIMMED_2_04:
	case cJ1_JPIMMED_2_05:
	case cJ1_JPIMMED_2_06:
	case cJ1_JPIMMED_2_07:
#endif
#if (defined(JUDY1) || defined(JU_64BIT))
	{
	    JUDY1CODE(uint16_t * PLeaf2 = (uint16_t *) (Pjp->jp_1Index);)
	    JUDYLCODE(uint16_t * PLeaf2 = (uint16_t *) (Pjp->jp_LIndex);)

	    Pop1 = JU_JPTYPE(Pjp) - cJU_JPIMMED_2_02 + 2; assert(Pop1);
	    j__udyCopy2to3(PLeaf3, PLeaf2, Pop1, MSByte);
#ifdef JUDYL
	    Pjv2Raw = (Pjv_t) (Pjp->jp_Addr);
	    Pjv2    = P_JV(Pjv2Raw);
	    JU_COPYMEM(Pjv3, Pjv2, Pop1);
	    j__udyLFreeJV(Pjv2Raw, Pop1, Pjpm);
#endif
	    return(Pop1);
	}
#endif // (JUDY1 || JU_64BIT)


// UNEXPECTED CASES, including JPNULL2, should be handled by caller:

	default: assert(FALSE); break;

	} // switch

	return(0);

} // j__udyLeaf2ToLeaf3()


#ifdef JU_64BIT

// ****************************************************************************
// __ J U D Y   L E A F   3   T O   L E A F   4
//
// Copy 3-byte Indexes from a Leaf3 to 4-byte Indexes in a Leaf4.
// Pjp MUST be one of:  cJU_JPLEAF3 or cJU_JPIMMED_3_*.
// Return number of Indexes copied.
//
// Note:  By the time this function is called to compress a level-4 branch to a
// Leaf4, the branch has no narrow pointers under it, meaning only level-3
// objects are below it and must be handled here.

FUNCTION Word_t  j__udyLeaf3ToLeaf4(
	uint32_t * PLeaf4,	// destination uint32_t * Index part of leaf.
#ifdef JUDYL
	Pjv_t	   Pjv4,	// destination value part of leaf.
#endif
	Pjp_t	   Pjp,		// 3-byte-index object from which to copy.
	Word_t     MSByte,	// most-significant byte, prefix to each Index.
	Pvoid_t	   Pjpm)	// for global accounting.
{
	Word_t	   Pop1;	// Indexes in leaf.
JUDYLCODE(Pjv_t	   Pjv3Raw;)	// source object value area.
JUDYLCODE(Pjv_t	   Pjv3;)

	switch (JU_JPTYPE(Pjp))
	{


// JPLEAF3:

	case cJU_JPLEAF3:
	{
	    uint8_t * PLeaf3 = (uint8_t *) P_JLL(Pjp->jp_Addr);

	    Pop1 = JU_JPLEAF_POP0(Pjp) + 1; assert(Pop1);
	    j__udyCopy3to4(PLeaf4, (uint8_t *) PLeaf3, Pop1, MSByte);
#ifdef JUDYL
	    Pjv3 = JL_LEAF3VALUEAREA(PLeaf3, Pop1);
	    JU_COPYMEM(Pjv4, Pjv3, Pop1);
#endif
	    j__udyFreeJLL3((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
	    return(Pop1);
	}


// JPIMMED_3_01:
//
// Note:  jp_DcdPopO has 7 bytes of Index (all but most significant byte), so
// the assignment to PLeaf4[] truncates and MSByte is not needed.

	case cJU_JPIMMED_3_01:
	{
	    PLeaf4[0] = JU_JPDCDPOP0(Pjp);	// see above.
	    JUDYLCODE(Pjv4[0] = Pjp->jp_Addr;)
	    return(1);
	}


// JPIMMED_3_0[2+]:

	case cJU_JPIMMED_3_02:
#ifdef JUDY1
	case cJ1_JPIMMED_3_03:
	case cJ1_JPIMMED_3_04:
	case cJ1_JPIMMED_3_05:
#endif
	{
	    JUDY1CODE(uint8_t * PLeaf3 = (uint8_t *) (Pjp->jp_1Index);)
	    JUDYLCODE(uint8_t * PLeaf3 = (uint8_t *) (Pjp->jp_LIndex);)

	    JUDY1CODE(Pop1 = JU_JPTYPE(Pjp) - cJU_JPIMMED_3_02 + 2;)
	    JUDYLCODE(Pop1 = 2;)

	    j__udyCopy3to4(PLeaf4, PLeaf3, Pop1, MSByte);
#ifdef JUDYL
	    Pjv3Raw = (Pjv_t) (Pjp->jp_Addr);
	    Pjv3    = P_JV(Pjv3Raw);
	    JU_COPYMEM(Pjv4, Pjv3, Pop1);
	    j__udyLFreeJV(Pjv3Raw, Pop1, Pjpm);
#endif
	    return(Pop1);
	}


// UNEXPECTED CASES, including JPNULL3, should be handled by caller:

	default: assert(FALSE); break;

	} // switch

	return(0);

} // j__udyLeaf3ToLeaf4()


// Note:  In all following j__udyLeaf*ToLeaf*() functions, JPIMMED_*_0[2+]
// cases exist for Judy1 (&& 64-bit) only.  JudyL has no equivalent Immeds.


// *****************************************************************************
// __ J U D Y   L E A F   4   T O   L E A F   5
//
// Copy 4-byte Indexes from a Leaf4 to 5-byte Indexes in a Leaf5.
// Pjp MUST be one of:  cJU_JPLEAF4 or cJU_JPIMMED_4_*.
// Return number of Indexes copied.
//
// Note:  By the time this function is called to compress a level-5 branch to a
// Leaf5, the branch has no narrow pointers under it, meaning only level-4
// objects are below it and must be handled here.

FUNCTION Word_t  j__udyLeaf4ToLeaf5(
	uint8_t * PLeaf5,	// destination "uint40_t *" Index part of leaf.
#ifdef JUDYL
	Pjv_t	  Pjv5,		// destination value part of leaf.
#endif
	Pjp_t	  Pjp,		// 4-byte-index object from which to copy.
	Word_t    MSByte,	// most-significant byte, prefix to each Index.
	Pvoid_t	  Pjpm)		// for global accounting.
{
	Word_t	  Pop1;		// Indexes in leaf.
JUDYLCODE(Pjv_t	  Pjv4;)	// source object value area.

	switch (JU_JPTYPE(Pjp))
	{


// JPLEAF4:

	case cJU_JPLEAF4:
	{
	    uint32_t * PLeaf4 = (uint32_t *) P_JLL(Pjp->jp_Addr);

	    Pop1 = JU_JPLEAF_POP0(Pjp) + 1; assert(Pop1);
	    j__udyCopy4to5(PLeaf5, PLeaf4, Pop1, MSByte);
#ifdef JUDYL
	    Pjv4 = JL_LEAF4VALUEAREA(PLeaf4, Pop1);
	    JU_COPYMEM(Pjv5, Pjv4, Pop1);
#endif
	    j__udyFreeJLL4((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
	    return(Pop1);
	}


// JPIMMED_4_01:
//
// Note:  jp_DcdPopO has 7 bytes of Index (all but most significant byte), so
// the assignment to PLeaf5[] truncates and MSByte is not needed.

	case cJU_JPIMMED_4_01:
	{
	    JU_COPY5_LONG_TO_PINDEX(PLeaf5, JU_JPDCDPOP0(Pjp));	// see above.
	    JUDYLCODE(Pjv5[0] = Pjp->jp_Addr;)
	    return(1);
	}


#ifdef JUDY1

// JPIMMED_4_0[4+]:

	case cJ1_JPIMMED_4_02:
	case cJ1_JPIMMED_4_03:
	{
	    uint32_t * PLeaf4 = (uint32_t *) (Pjp->jp_1Index);

	    Pop1 = JU_JPTYPE(Pjp) - cJ1_JPIMMED_4_02 + 2;
	    j__udyCopy4to5(PLeaf5, PLeaf4, Pop1, MSByte);
	    return(Pop1);
	}
#endif // JUDY1


// UNEXPECTED CASES, including JPNULL4, should be handled by caller:

	default: assert(FALSE); break;

	} // switch

	return(0);

} // j__udyLeaf4ToLeaf5()


// ****************************************************************************
// __ J U D Y   L E A F   5   T O   L E A F   6
//
// Copy 5-byte Indexes from a Leaf5 to 6-byte Indexes in a Leaf6.
// Pjp MUST be one of:  cJU_JPLEAF5 or cJU_JPIMMED_5_*.
// Return number of Indexes copied.
//
// Note:  By the time this function is called to compress a level-6 branch to a
// Leaf6, the branch has no narrow pointers under it, meaning only level-5
// objects are below it and must be handled here.

FUNCTION Word_t  j__udyLeaf5ToLeaf6(
	uint8_t * PLeaf6,	// destination uint8_t * Index part of leaf.
#ifdef JUDYL
	Pjv_t	  Pjv6,		// destination value part of leaf.
#endif
	Pjp_t	  Pjp,		// 5-byte-index object from which to copy.
	Word_t    MSByte,	// most-significant byte, prefix to each Index.
	Pvoid_t	  Pjpm)		// for global accounting.
{
	Word_t	  Pop1;		// Indexes in leaf.
JUDYLCODE(Pjv_t	  Pjv5;)	// source object value area.

	switch (JU_JPTYPE(Pjp))
	{


// JPLEAF5:

	case cJU_JPLEAF5:
	{
	    uint8_t * PLeaf5 = (uint8_t *) P_JLL(Pjp->jp_Addr);

	    Pop1 = JU_JPLEAF_POP0(Pjp) + 1; assert(Pop1);
	    j__udyCopy5to6(PLeaf6, PLeaf5, Pop1, MSByte);
#ifdef JUDYL
	    Pjv5 = JL_LEAF5VALUEAREA(PLeaf5, Pop1);
	    JU_COPYMEM(Pjv6, Pjv5, Pop1);
#endif
	    j__udyFreeJLL5((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
	    return(Pop1);
	}


// JPIMMED_5_01:
//
// Note:  jp_DcdPopO has 7 bytes of Index (all but most significant byte), so
// the assignment to PLeaf6[] truncates and MSByte is not needed.

	case cJU_JPIMMED_5_01:
	{
	    JU_COPY6_LONG_TO_PINDEX(PLeaf6, JU_JPDCDPOP0(Pjp));	// see above.
	    JUDYLCODE(Pjv6[0] = Pjp->jp_Addr;)
	    return(1);
	}


#ifdef JUDY1

// JPIMMED_5_0[2+]:

	case cJ1_JPIMMED_5_02:
	case cJ1_JPIMMED_5_03:
	{
	    uint8_t * PLeaf5 = (uint8_t *) (Pjp->jp_1Index);

	    Pop1 = JU_JPTYPE(Pjp) - cJ1_JPIMMED_5_02 + 2;
	    j__udyCopy5to6(PLeaf6, PLeaf5, Pop1, MSByte);
	    return(Pop1);
	}
#endif // JUDY1


// UNEXPECTED CASES, including JPNULL5, should be handled by caller:

	default: assert(FALSE); break;

	} // switch

	return(0);

} // j__udyLeaf5ToLeaf6()


// *****************************************************************************
// __ J U D Y   L E A F   6   T O   L E A F   7
//
// Copy 6-byte Indexes from a Leaf2 to 7-byte Indexes in a Leaf7.
// Pjp MUST be one of:  cJU_JPLEAF6 or cJU_JPIMMED_6_*.
// Return number of Indexes copied.
//
// Note:  By the time this function is called to compress a level-7 branch to a
// Leaf7, the branch has no narrow pointers under it, meaning only level-6
// objects are below it and must be handled here.

FUNCTION Word_t  j__udyLeaf6ToLeaf7(
	uint8_t * PLeaf7,	// destination "uint24_t *" Index part of leaf.
#ifdef JUDYL
	Pjv_t	  Pjv7,		// destination value part of leaf.
#endif
	Pjp_t	  Pjp,		// 6-byte-index object from which to copy.
	Word_t    MSByte,	// most-significant byte, prefix to each Index.
	Pvoid_t	  Pjpm)		// for global accounting.
{
	Word_t	  Pop1;		// Indexes in leaf.
JUDYLCODE(Pjv_t	  Pjv6;)	// source object value area.

	switch (JU_JPTYPE(Pjp))
	{


// JPLEAF6:

	case cJU_JPLEAF6:
	{
	    uint8_t * PLeaf6 = (uint8_t *) P_JLL(Pjp->jp_Addr);

	    Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
	    j__udyCopy6to7(PLeaf7, PLeaf6, Pop1, MSByte);
#ifdef JUDYL
	    Pjv6 = JL_LEAF6VALUEAREA(PLeaf6, Pop1);
	    JU_COPYMEM(Pjv7, Pjv6, Pop1);
#endif
	    j__udyFreeJLL6((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
	    return(Pop1);
	}


// JPIMMED_6_01:
//
// Note:  jp_DcdPopO has 7 bytes of Index (all but most significant byte), so
// the "assignment" to PLeaf7[] is exact and MSByte is not needed.

	case cJU_JPIMMED_6_01:
	{
	    JU_COPY7_LONG_TO_PINDEX(PLeaf7, JU_JPDCDPOP0(Pjp));	// see above.
	    JUDYLCODE(Pjv7[0] = Pjp->jp_Addr;)
	    return(1);
	}


#ifdef JUDY1

// JPIMMED_6_02:

	case cJ1_JPIMMED_6_02:
	{
	    uint8_t * PLeaf6 = (uint8_t *) (Pjp->jp_1Index);

	    j__udyCopy6to7(PLeaf7, PLeaf6, /* Pop1 = */ 2, MSByte);
	    return(2);
	}
#endif // JUDY1


// UNEXPECTED CASES, including JPNULL6, should be handled by caller:

	default: assert(FALSE); break;

	} // switch

	return(0);

} // j__udyLeaf6ToLeaf7()

#endif // JU_64BIT


#ifndef JU_64BIT // 32-bit version first

// ****************************************************************************
// __ J U D Y   L E A F   3   T O   L E A F   W
//
// Copy 3-byte Indexes from a Leaf3 to 4-byte Indexes in a LeafW.  Pjp MUST be
// one of:  cJU_JPLEAF3 or cJU_JPIMMED_3_*.  Return number of Indexes copied.
//
// Note:  By the time this function is called to compress a level-L branch to a
// LeafW, the branch has no narrow pointers under it, meaning only level-3
// objects are below it and must be handled here.

FUNCTION Word_t  j__udyLeaf3ToLeafW(
	Pjlw_t	Pjlw,		// destination Index part of leaf.
#ifdef JUDYL
	Pjv_t	PjvW,		// destination value part of leaf.
#endif
	Pjp_t	Pjp,		// 3-byte-index object from which to copy.
	Word_t	MSByte,		// most-significant byte, prefix to each Index.
	Pvoid_t	Pjpm)		// for global accounting.
{
	Word_t	Pop1;		// Indexes in leaf.
JUDYLCODE(Pjv_t Pjv3;)		// source object value area.

	switch (JU_JPTYPE(Pjp))
	{


// JPLEAF3:

	case cJU_JPLEAF3:
	{
	    uint8_t * PLeaf3 = (uint8_t *) P_JLL(Pjp->jp_Addr);

	    Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
	    j__udyCopy3toW((PWord_t) Pjlw, PLeaf3, Pop1, MSByte);
#ifdef JUDYL
	    Pjv3 = JL_LEAF3VALUEAREA(PLeaf3, Pop1);
	    JU_COPYMEM(PjvW, Pjv3, Pop1);
#endif
	    j__udyFreeJLL3((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
	    return(Pop1);
	}


// JPIMMED_3_01:
//
// Note:  jp_DcdPopO has 3 bytes of Index (all but most significant byte), and
// MSByte must be ord in.

	case cJU_JPIMMED_3_01:
	{
	    Pjlw[0] = MSByte | JU_JPDCDPOP0(Pjp);		// see above.
	    JUDYLCODE(PjvW[0] = Pjp->jp_Addr;)
	    return(1);
	}


#ifdef JUDY1

// JPIMMED_3_02:

	case cJU_JPIMMED_3_02:
	{
	    uint8_t * PLeaf3 = (uint8_t *) (Pjp->jp_1Index);

	    j__udyCopy3toW((PWord_t) Pjlw, PLeaf3, /* Pop1 = */ 2, MSByte);
	    return(2);
	}
#endif // JUDY1


// UNEXPECTED CASES, including JPNULL3, should be handled by caller:

	default: assert(FALSE); break;

	} // switch

	return(0);

} // j__udyLeaf3ToLeafW()


#else // JU_64BIT


// ****************************************************************************
// __ J U D Y   L E A F   7   T O   L E A F   W
//
// Copy 7-byte Indexes from a Leaf7 to 8-byte Indexes in a LeafW.
// Pjp MUST be one of:  cJU_JPLEAF7 or cJU_JPIMMED_7_*.
// Return number of Indexes copied.
//
// Note:  By the time this function is called to compress a level-L branch to a
// LeafW, the branch has no narrow pointers under it, meaning only level-7
// objects are below it and must be handled here.

FUNCTION Word_t  j__udyLeaf7ToLeafW(
	Pjlw_t	Pjlw,		// destination Index part of leaf.
#ifdef JUDYL
	Pjv_t	PjvW,		// destination value part of leaf.
#endif
	Pjp_t	Pjp,		// 7-byte-index object from which to copy.
	Word_t	MSByte,		// most-significant byte, prefix to each Index.
	Pvoid_t	Pjpm)		// for global accounting.
{
	Word_t	Pop1;		// Indexes in leaf.
JUDYLCODE(Pjv_t	Pjv7;)		// source object value area.

	switch (JU_JPTYPE(Pjp))
	{


// JPLEAF7:

	case cJU_JPLEAF7:
	{
	    uint8_t * PLeaf7 = (uint8_t *) P_JLL(Pjp->jp_Addr);

	    Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
	    j__udyCopy7toW((PWord_t) Pjlw, PLeaf7, Pop1, MSByte);
#ifdef JUDYL
	    Pjv7 = JL_LEAF7VALUEAREA(PLeaf7, Pop1);
	    JU_COPYMEM(PjvW, Pjv7, Pop1);
#endif
	    j__udyFreeJLL7((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
	    return(Pop1);
	}


// JPIMMED_7_01:
//
// Note:  jp_DcdPopO has 7 bytes of Index (all but most significant byte), and
// MSByte must be ord in.

	case cJU_JPIMMED_7_01:
	{
	    Pjlw[0] = MSByte | JU_JPDCDPOP0(Pjp);		// see above.
	    JUDYLCODE(PjvW[0] = Pjp->jp_Addr;)
	    return(1);
	}


#ifdef JUDY1

// JPIMMED_7_02:

	case cJ1_JPIMMED_7_02:
	{
	    uint8_t * PLeaf7 = (uint8_t *) (Pjp->jp_1Index);

	    j__udyCopy7toW((PWord_t) Pjlw, PLeaf7, /* Pop1 = */ 2, MSByte);
	    return(2);
	}
#endif


// UNEXPECTED CASES, including JPNULL7, should be handled by caller:

	default: assert(FALSE); break;

	} // switch

	return(0);

} // j__udyLeaf7ToLeafW()

#endif // JU_64BIT