summaryrefslogtreecommitdiffstats
path: root/generic/tclCmdIL.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclCmdIL.c')
-rw-r--r--generic/tclCmdIL.c441
1 files changed, 263 insertions, 178 deletions
diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c
index 4f63892..00b1e55 100644
--- a/generic/tclCmdIL.c
+++ b/generic/tclCmdIL.c
@@ -16,7 +16,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCmdIL.c,v 1.115.2.12 2007/12/05 18:09:52 dgp Exp $
+ * RCS: @(#) $Id: tclCmdIL.c,v 1.115.2.13 2008/01/23 16:42:18 dgp Exp $
*/
#include "tclInt.h"
@@ -29,8 +29,13 @@
*/
typedef struct SortElement {
- Tcl_Obj *objPtr; /* Object being sorted. */
- int count; /* Number of same elements in list. */
+ union {
+ char *strValuePtr;
+ long intValue;
+ double doubleValue;
+ Tcl_Obj *objValuePtr;
+ } index;
+ Tcl_Obj *objPtr; /* Object being sorted, or its index. */
struct SortElement *nextPtr;/* Next element in the list, or NULL for end
* of list. */
} SortElement;
@@ -54,8 +59,6 @@ typedef struct SortInfo {
int isIncreasing; /* Nonzero means sort in increasing order. */
int sortMode; /* The sort mode. One of SORTMODE_* values
* defined below. */
- SortStrCmpFn_t strCmpFn; /* Basic string compare command (used with
- * ASCII mode). */
Tcl_Obj *compareCmdPtr; /* The Tcl comparison command when sortMode is
* SORTMODE_COMMAND. Pre-initialized to hold
* base of command. */
@@ -67,6 +70,8 @@ typedef struct SortInfo {
* supplied. */
int indexc; /* Number of indexes in indexv array. */
int singleIndex; /* Static space for common index case. */
+ int unique;
+ int numElements;
Tcl_Interp *interp; /* The interpreter in which the sort is being
* done. */
int resultCode; /* Completion code for the lsort command. If
@@ -84,6 +89,7 @@ typedef struct SortInfo {
#define SORTMODE_REAL 2
#define SORTMODE_COMMAND 3
#define SORTMODE_DICTIONARY 4
+#define SORTMODE_ASCII_NC 8
/*
* Magic values for the index field of the SortInfo structure. Note that the
@@ -136,10 +142,9 @@ static int InfoSharedlibCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[]);
static int InfoTclVersionCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[]);
-static SortElement * MergeSort(SortElement *headPt, SortInfo *infoPtr);
static SortElement * MergeLists(SortElement *leftPtr, SortElement *rightPtr,
SortInfo *infoPtr);
-static int SortCompare(Tcl_Obj *firstPtr, Tcl_Obj *second,
+static int SortCompare(SortElement *firstPtr, SortElement *second,
SortInfo *infoPtr);
static Tcl_Obj * SelectObjFromSublist(Tcl_Obj *firstPtr,
SortInfo *infoPtr);
@@ -2604,6 +2609,15 @@ Tcl_LreverseObjCmd(
return TCL_ERROR;
}
+ /*
+ * If the list is empty, just return it [Bug 1876793]
+ */
+
+ if (!elemc) {
+ Tcl_SetObjResult(interp, objv[1]);
+ return TCL_OK;
+ }
+
if (Tcl_IsShared(objv[1])) {
Tcl_Obj *resultObj, **dataArray;
List *listPtr;
@@ -2714,7 +2728,7 @@ Tcl_LsearchObjCmd(
offset = 0;
noCase = 0;
sortInfo.compareCmdPtr = NULL;
- sortInfo.isIncreasing = 0;
+ sortInfo.isIncreasing = 1;
sortInfo.sortMode = 0;
sortInfo.interp = interp;
sortInfo.resultCode = TCL_OK;
@@ -2746,6 +2760,7 @@ Tcl_LsearchObjCmd(
break;
case LSEARCH_DECREASING: /* -decreasing */
isIncreasing = 0;
+ sortInfo.isIncreasing = 0;
break;
case LSEARCH_DICTIONARY: /* -dictionary */
dataType = DICTIONARY;
@@ -2758,6 +2773,7 @@ Tcl_LsearchObjCmd(
break;
case LSEARCH_INCREASING: /* -increasing */
isIncreasing = 1;
+ sortInfo.isIncreasing = 1;
break;
case LSEARCH_INLINE: /* -inline */
inlineReturn = 1;
@@ -3042,12 +3058,16 @@ Tcl_LsearchObjCmd(
upper = listc;
while (lower + 1 != upper && sortInfo.resultCode == TCL_OK) {
i = (lower + upper)/2;
- itemPtr = SelectObjFromSublist(listv[i], &sortInfo);
- if (sortInfo.resultCode != TCL_OK) {
- if (sortInfo.indexc > 1) {
- ckfree((char *) sortInfo.indexv);
+ if (sortInfo.indexc != 0) {
+ itemPtr = SelectObjFromSublist(listv[i], &sortInfo);
+ if (sortInfo.resultCode != TCL_OK) {
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return sortInfo.resultCode;
}
- return sortInfo.resultCode;
+ } else {
+ itemPtr = listv[i];
}
switch ((enum datatypes) dataType) {
case ASCII:
@@ -3136,16 +3156,21 @@ Tcl_LsearchObjCmd(
}
for (i = offset; i < listc; i++) {
match = 0;
- itemPtr = SelectObjFromSublist(listv[i], &sortInfo);
- if (sortInfo.resultCode != TCL_OK) {
- if (listPtr != NULL) {
- Tcl_DecrRefCount(listPtr);
- }
- if (sortInfo.indexc > 1) {
- ckfree((char *) sortInfo.indexv);
+ if (sortInfo.indexc != 0) {
+ itemPtr = SelectObjFromSublist(listv[i], &sortInfo);
+ if (sortInfo.resultCode != TCL_OK) {
+ if (listPtr != NULL) {
+ Tcl_DecrRefCount(listPtr);
+ }
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return sortInfo.resultCode;
}
- return sortInfo.resultCode;
+ } else {
+ itemPtr = listv[i];
}
+
switch ((enum modes) mode) {
case SORTED:
case EXACT:
@@ -3240,7 +3265,7 @@ Tcl_LsearchObjCmd(
* Note that these appends are not expected to fail.
*/
- if (returnSubindices) {
+ if (returnSubindices && (sortInfo.indexc != 0)) {
itemPtr = SelectObjFromSublist(listv[i], &sortInfo);
} else {
itemPtr = listv[i];
@@ -3410,8 +3435,8 @@ Tcl_LsortObjCmd(
int objc, /* Number of arguments. */
Tcl_Obj *CONST objv[]) /* Argument values. */
{
- int i, index, unique, indices, length;
- Tcl_Obj *resultPtr, *cmdPtr, **listObjPtrs, *listObj;
+ int i, j, index, unique, indices, length, nocase = 0, sortMode, indexc;
+ Tcl_Obj *resultPtr, *cmdPtr, **listObjPtrs, *listObj, *indexPtr;
SortElement *elementArray, *elementPtr;
SortInfo sortInfo; /* Information about this sort that needs to
* be passed to the comparison function. */
@@ -3425,6 +3450,13 @@ Tcl_LsortObjCmd(
LSORT_NOCASE, LSORT_REAL, LSORT_UNIQUE
};
+ /*
+ * The subList array below holds pointers to temporary lists built during
+ * the merge sort. Element i of the array holds a list of length 2**i.
+ */
+# define NUM_LISTS 30
+ SortElement *subList[NUM_LISTS+1];
+
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "?options? list");
return TCL_ERROR;
@@ -3436,11 +3468,11 @@ Tcl_LsortObjCmd(
sortInfo.isIncreasing = 1;
sortInfo.sortMode = SORTMODE_ASCII;
- sortInfo.strCmpFn = strcmp;
sortInfo.indexv = NULL;
sortInfo.indexc = 0;
+ sortInfo.unique = 0;
sortInfo.interp = interp;
- sortInfo.resultCode = TCL_OK;
+ sortInfo.resultCode = TCL_OK;
cmdPtr = NULL;
unique = 0;
indices = 0;
@@ -3477,7 +3509,6 @@ Tcl_LsortObjCmd(
sortInfo.isIncreasing = 1;
break;
case LSORT_INDEX: {
- int j;
Tcl_Obj **indices;
if (sortInfo.indexc > 1) {
@@ -3533,19 +3564,24 @@ Tcl_LsortObjCmd(
sortInfo.sortMode = SORTMODE_INTEGER;
break;
case LSORT_NOCASE:
- sortInfo.strCmpFn = strcasecmp;
+ nocase = 1;
break;
case LSORT_REAL:
sortInfo.sortMode = SORTMODE_REAL;
break;
case LSORT_UNIQUE:
unique = 1;
+ sortInfo.unique = 1;
break;
case LSORT_INDICES:
indices = 1;
break;
}
}
+ if (nocase && (sortInfo.sortMode == SORTMODE_ASCII)) {
+ sortInfo.sortMode = SORTMODE_ASCII_NC;
+ }
+
listObj = objv[objc-1];
if (sortInfo.sortMode == SORTMODE_COMMAND) {
@@ -3594,46 +3630,138 @@ Tcl_LsortObjCmd(
if (sortInfo.resultCode != TCL_OK || length <= 0) {
goto done;
}
+ sortInfo.numElements = length;
+
+ indexc = sortInfo.indexc;
+ sortMode = sortInfo.sortMode;
+ if ((sortMode == SORTMODE_ASCII_NC)
+ || (sortMode == SORTMODE_DICTIONARY)) {
+ /*
+ * For this function's purpose all string-based modes are equivalent
+ */
+
+ sortMode = SORTMODE_ASCII;
+ }
+
+ /*
+ * Initialize the sublists. After the following loop, subList[i] will
+ * contain a sorted sublist of length 2**i. Use one extra subList at the
+ * end, always at NULL, to indicate the end of the lists.
+ */
+
+ for (j=0 ; j<=NUM_LISTS ; j++) {
+ subList[j] = NULL;
+ }
+
+ /*
+ * The following loop creates a SortElement for each list element and
+ * begins sorting it into the sublists as it appears.
+ */
elementArray = (SortElement *)
TclStackAlloc(interp, length * sizeof(SortElement));
+
for (i=0; i < length; i++){
- elementArray[i].objPtr = listObjPtrs[i];
- elementArray[i].count = 0;
- elementArray[i].nextPtr = &elementArray[i+1];
+ if (indexc) {
+ /*
+ * If this is an indexed sort, retrieve the corresponding element
+ */
+ indexPtr = SelectObjFromSublist(listObjPtrs[i], &sortInfo);
+ if (sortInfo.resultCode != TCL_OK) {
+ goto done1;
+ }
+ } else {
+ indexPtr = listObjPtrs[i];
+ }
+
+ /*
+ * Determine the "value" of this object for sorting purposes
+ */
+
+ if (sortMode == SORTMODE_ASCII) {
+ elementArray[i].index.strValuePtr = TclGetString(indexPtr);
+ } else if (sortMode == SORTMODE_INTEGER) {
+ long a;
+ if (TclGetLongFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) {
+ sortInfo.resultCode = TCL_ERROR;
+ goto done1;
+ }
+ elementArray[i].index.intValue = a;
+ } else if (sortInfo.sortMode == SORTMODE_REAL) {
+ double a;
+ if (Tcl_GetDoubleFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) {
+ sortInfo.resultCode = TCL_ERROR;
+ goto done1;
+ }
+ elementArray[i].index.doubleValue = a;
+ } else {
+ elementArray[i].index.objValuePtr = indexPtr;
+ }
+
+ /*
+ * Determine the representation of this element in the result: either
+ * the objPtr itself, or its index in the original list.
+ */
+
+ elementArray[i].objPtr = (indices ? INT2PTR(i) : listObjPtrs[i]);
+
+ /*
+ * Merge this element in the pre-existing sublists (and merge together
+ * sublists when we have two of the same size).
+ */
+
+ elementArray[i].nextPtr = NULL;
+ elementPtr = &elementArray[i];
+ for (j=0 ; subList[j] ; j++) {
+ elementPtr = MergeLists(subList[j], elementPtr, &sortInfo);
+ subList[j] = NULL;
+ }
+ if (j >= NUM_LISTS) {
+ j = NUM_LISTS-1;
+ }
+ subList[j] = elementPtr;
}
- elementArray[length-1].nextPtr = NULL;
- elementPtr = MergeSort(elementArray, &sortInfo);
+
+ /*
+ * Merge all sublists
+ */
+
+ elementPtr = subList[0];
+ for (j=1 ; j<NUM_LISTS ; j++) {
+ elementPtr = MergeLists(subList[j], elementPtr, &sortInfo);
+ }
+
+
+ /*
+ * Now store the sorted elements in the result list.
+ */
+
if (sortInfo.resultCode == TCL_OK) {
- resultPtr = Tcl_NewObj();
- if (unique) {
- if (indices) {
- for (; elementPtr != NULL ; elementPtr = elementPtr->nextPtr){
- if (elementPtr->count == 0) {
- Tcl_ListObjAppendElement(NULL, resultPtr,
- Tcl_NewIntObj(elementPtr - &elementArray[0]));
- }
- }
- } else {
- for (; elementPtr != NULL; elementPtr = elementPtr->nextPtr) {
- if (elementPtr->count == 0) {
- Tcl_ListObjAppendElement(NULL, resultPtr,
- elementPtr->objPtr);
- }
- }
- }
- } else if (indices) {
- for (; elementPtr != NULL ; elementPtr = elementPtr->nextPtr) {
- Tcl_ListObjAppendElement(NULL, resultPtr,
- Tcl_NewIntObj(elementPtr - &elementArray[0]));
+ List *listRepPtr;
+ Tcl_Obj **newArray, *objPtr;
+ int i;
+
+ resultPtr = Tcl_NewListObj(sortInfo.numElements, NULL);
+ listRepPtr = (List *) resultPtr->internalRep.twoPtrValue.ptr1;
+ newArray = &listRepPtr->elements;
+ if (indices) {
+ for (i = 0; elementPtr != NULL ; elementPtr = elementPtr->nextPtr){
+ objPtr = Tcl_NewIntObj(PTR2INT(elementPtr->objPtr));
+ newArray[i++] = objPtr;
+ Tcl_IncrRefCount(objPtr);
}
} else {
- for (; elementPtr != NULL; elementPtr = elementPtr->nextPtr) {
- Tcl_ListObjAppendElement(NULL, resultPtr, elementPtr->objPtr);
+ for (i = 0; elementPtr != NULL ; elementPtr = elementPtr->nextPtr){
+ objPtr = elementPtr->objPtr;
+ newArray[i++] = objPtr;
+ Tcl_IncrRefCount(objPtr);
}
}
+ listRepPtr->elemCount = i;
Tcl_SetObjResult(interp, resultPtr);
}
+
+ done1:
TclStackFree(interp, elementArray);
done:
@@ -3651,62 +3779,6 @@ Tcl_LsortObjCmd(
/*
*----------------------------------------------------------------------
*
- * MergeSort -
- *
- * This procedure sorts a linked list of SortElement structures use the
- * merge-sort algorithm.
- *
- * Results:
- * A pointer to the head of the list after sorting is returned.
- *
- * Side effects:
- * None, unless a user-defined comparison command does something weird.
- *
- *----------------------------------------------------------------------
- */
-
-static SortElement *
-MergeSort(
- SortElement *headPtr, /* First element on the list. */
- SortInfo *infoPtr) /* Information needed by the comparison
- * operator. */
-{
- /*
- * The subList array below holds pointers to temporary lists built during
- * the merge sort. Element i of the array holds a list of length 2**i.
- */
-
-# define NUM_LISTS 30
- SortElement *subList[NUM_LISTS];
- SortElement *elementPtr;
- int i;
-
- for (i=0 ; i<NUM_LISTS ; i++) {
- subList[i] = NULL;
- }
- while (headPtr != NULL) {
- elementPtr = headPtr;
- headPtr = headPtr->nextPtr;
- elementPtr->nextPtr = 0;
- for (i=0 ; i<NUM_LISTS && subList[i]!=NULL ; i++) {
- elementPtr = MergeLists(subList[i], elementPtr, infoPtr);
- subList[i] = NULL;
- }
- if (i >= NUM_LISTS) {
- i = NUM_LISTS-1;
- }
- subList[i] = elementPtr;
- }
- elementPtr = NULL;
- for (i=0 ; i<NUM_LISTS ; i++) {
- elementPtr = MergeLists(subList[i], elementPtr, infoPtr);
- }
- return elementPtr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
* MergeLists -
*
* This procedure combines two sorted lists of SortElement structures
@@ -3716,8 +3788,21 @@ MergeSort(
* The unified list of SortElement structures.
*
* Side effects:
- * None, unless a user-defined comparison command does something weird.
+ * If infoPtr->unique is set then infoPtr->numElements may be updated.
+ * Possibly others, if a user-defined comparison command does something
+ * weird.
*
+ * Note:
+ * If infoPtr->unique is set, the merge assumes that there are no
+ * "repeated" elements in each of the left and right lists. In that case,
+ * if any element of the left list is equivalent to one in the right list
+ * it is omitted from the merged list.
+ * This simplified mechanism works because of the special way
+ * our MergeSort creates the sublists to be merged and will fail to
+ * eliminate all repeats in the general case where they are already
+ * present in either the left or right list. A general code would need to
+ * skip adjacent initial repeats in the left and right lists before
+ * comparing their initial elements, at each step.
*----------------------------------------------------------------------
*/
@@ -3737,31 +3822,48 @@ MergeLists(
if (rightPtr == NULL) {
return leftPtr;
}
- cmp = SortCompare(leftPtr->objPtr, rightPtr->objPtr, infoPtr);
- if (cmp > 0) {
+ cmp = SortCompare(leftPtr, rightPtr, infoPtr);
+ if (cmp > 0 || (cmp == 0 && infoPtr->unique)) {
+ if (cmp == 0) {
+ infoPtr->numElements--;
+ leftPtr = leftPtr->nextPtr;
+ }
tailPtr = rightPtr;
rightPtr = rightPtr->nextPtr;
} else {
- if (cmp == 0) {
- leftPtr->count++;
- }
tailPtr = leftPtr;
leftPtr = leftPtr->nextPtr;
}
headPtr = tailPtr;
- while ((leftPtr != NULL) && (rightPtr != NULL)) {
- cmp = SortCompare(leftPtr->objPtr, rightPtr->objPtr, infoPtr);
- if (cmp > 0) {
- tailPtr->nextPtr = rightPtr;
- tailPtr = rightPtr;
- rightPtr = rightPtr->nextPtr;
- } else {
- if (cmp == 0) {
- leftPtr->count++;
+ if (!infoPtr->unique) {
+ while ((leftPtr != NULL) && (rightPtr != NULL)) {
+ cmp = SortCompare(leftPtr, rightPtr, infoPtr);
+ if (cmp > 0) {
+ tailPtr->nextPtr = rightPtr;
+ tailPtr = rightPtr;
+ rightPtr = rightPtr->nextPtr;
+ } else {
+ tailPtr->nextPtr = leftPtr;
+ tailPtr = leftPtr;
+ leftPtr = leftPtr->nextPtr;
+ }
+ }
+ } else {
+ while ((leftPtr != NULL) && (rightPtr != NULL)) {
+ cmp = SortCompare(leftPtr, rightPtr, infoPtr);
+ if (cmp >= 0) {
+ if (cmp == 0) {
+ infoPtr->numElements--;
+ leftPtr = leftPtr->nextPtr;
+ }
+ tailPtr->nextPtr = rightPtr;
+ tailPtr = rightPtr;
+ rightPtr = rightPtr->nextPtr;
+ } else {
+ tailPtr->nextPtr = leftPtr;
+ tailPtr = leftPtr;
+ leftPtr = leftPtr->nextPtr;
}
- tailPtr->nextPtr = leftPtr;
- tailPtr = leftPtr;
- leftPtr = leftPtr->nextPtr;
}
}
if (leftPtr != NULL) {
@@ -3794,69 +3896,52 @@ MergeLists(
static int
SortCompare(
- Tcl_Obj *objPtr1, Tcl_Obj *objPtr2,
+ SortElement *elemPtr1, SortElement *elemPtr2,
/* Values to be compared. */
SortInfo *infoPtr) /* Information passed from the top-level
* "lsort" command. */
{
- int order;
-
- order = 0;
- if (infoPtr->resultCode != TCL_OK) {
- /*
- * Once an error has occurred, skip any future comparisons so as to
- * preserve the error message in sortInterp->result.
- */
-
- return order;
- }
-
- objPtr1 = SelectObjFromSublist(objPtr1, infoPtr);
- if (infoPtr->resultCode != TCL_OK) {
- return order;
- }
- objPtr2 = SelectObjFromSublist(objPtr2, infoPtr);
- if (infoPtr->resultCode != TCL_OK) {
- return order;
- }
+ int order = 0;
if (infoPtr->sortMode == SORTMODE_ASCII) {
- order = infoPtr->strCmpFn(TclGetString(objPtr1),
- TclGetString(objPtr2));
+ order = strcmp(elemPtr1->index.strValuePtr,
+ elemPtr2->index.strValuePtr);
+ } else if (infoPtr->sortMode == SORTMODE_ASCII_NC) {
+ order = strcasecmp(elemPtr1->index.strValuePtr,
+ elemPtr2->index.strValuePtr);
} else if (infoPtr->sortMode == SORTMODE_DICTIONARY) {
- order = DictionaryCompare(
- TclGetString(objPtr1), TclGetString(objPtr2));
+ order = DictionaryCompare(elemPtr1->index.strValuePtr,
+ elemPtr2->index.strValuePtr);
} else if (infoPtr->sortMode == SORTMODE_INTEGER) {
long a, b;
- if ((TclGetLongFromObj(infoPtr->interp, objPtr1, &a) != TCL_OK)
- || (TclGetLongFromObj(infoPtr->interp, objPtr2, &b)
- != TCL_OK)) {
- infoPtr->resultCode = TCL_ERROR;
- return order;
- }
- if (a > b) {
- order = 1;
- } else if (b > a) {
- order = -1;
- }
+ a = elemPtr1->index.intValue;
+ b = elemPtr2->index.intValue;
+ order = ((a >= b) - (a <= b));
} else if (infoPtr->sortMode == SORTMODE_REAL) {
double a, b;
- if (Tcl_GetDoubleFromObj(infoPtr->interp, objPtr1, &a) != TCL_OK ||
- Tcl_GetDoubleFromObj(infoPtr->interp, objPtr2, &b) != TCL_OK){
- infoPtr->resultCode = TCL_ERROR;
- return order;
- }
- if (a > b) {
- order = 1;
- } else if (b > a) {
- order = -1;
- }
+ a = elemPtr1->index.doubleValue;
+ b = elemPtr2->index.doubleValue;
+ order = ((a >= b) - (a <= b));
} else {
Tcl_Obj **objv, *paramObjv[2];
int objc;
+ Tcl_Obj *objPtr1, *objPtr2;
+
+ if (infoPtr->resultCode != TCL_OK) {
+ /*
+ * Once an error has occurred, skip any future comparisons so as
+ * to preserve the error message in sortInterp->result.
+ */
+
+ return 0;
+ }
+
+ objPtr1 = elemPtr1->index.objValuePtr;
+ objPtr2 = elemPtr2->index.objValuePtr;
+
paramObjv[0] = objPtr1;
paramObjv[1] = objPtr2;
@@ -3876,7 +3961,7 @@ SortCompare(
if (infoPtr->resultCode != TCL_OK) {
Tcl_AddErrorInfo(infoPtr->interp,
"\n (-compare command)");
- return order;
+ return 0;
}
/*
@@ -3889,7 +3974,7 @@ SortCompare(
Tcl_AppendResult(infoPtr->interp,
"-compare command returned non-integer result", NULL);
infoPtr->resultCode = TCL_ERROR;
- return order;
+ return 0;
}
}
if (!infoPtr->isIncreasing) {