summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgriffin <briang42@easystreet.net>2023-04-26 16:18:04 (GMT)
committergriffin <briang42@easystreet.net>2023-04-26 16:18:04 (GMT)
commitf9f1724b36d193a9e751235552723593c3e09e0a (patch)
treedfe11bfe51755f4f4ec2f80c282de1a6d4f8b3d7
parentf227a5d1ff1c36d3bc5eca3f7378d5064d59d4eb (diff)
parent3aaf8c054455ae5ad096a31922d26477397c8ed7 (diff)
downloadtcl-f9f1724b36d193a9e751235552723593c3e09e0a.zip
tcl-f9f1724b36d193a9e751235552723593c3e09e0a.tar.gz
tcl-f9f1724b36d193a9e751235552723593c3e09e0a.tar.bz2
Fix index descrepencies (bug-fa00fbbbabe).
Fix inconsistent rounding (bug-e5f06285de).
-rwxr-xr-xgeneric/tclArithSeries.c242
-rw-r--r--generic/tclArithSeries.h1
-rw-r--r--tests/lseq.test51
3 files changed, 224 insertions, 70 deletions
diff --git a/generic/tclArithSeries.c b/generic/tclArithSeries.c
index 9d87f1a..fd048a1 100755
--- a/generic/tclArithSeries.c
+++ b/generic/tclArithSeries.c
@@ -13,36 +13,95 @@
#include "tclInt.h"
#include "tclArithSeries.h"
#include <assert.h>
+#include <math.h>
/* -------------------------- ArithSeries object ---------------------------- */
+/*
+ * Helper functions
+ *
+ * - ArithRound -- Round doubles to the number of significant fractional
+ * digits
+ * - ArithSeriesIndexDbl -- base list indexing operation for doubles
+ * - ArithSeriesIndexInt -- " " " " " integers
+ * - ArithSeriesGetInternalRep -- Return the internal rep from a Tcl_Obj
+ * - Precision -- determine the number of factional digits for the given
+ * double value
+ * - maxPrecision -- Using the values provide, determine the longest percision
+ * in the arithSeries
+ */
+static inline double
+ArithRound(double d, unsigned int n) {
+ double scalefactor = pow(10, n);
+ return round(d*scalefactor)/scalefactor;
+}
-#define ArithSeriesRepPtr(arithSeriesObjPtr) \
- (ArithSeries *) ((arithSeriesObjPtr)->internalRep.twoPtrValue.ptr1)
+static inline double
+ArithSeriesIndexDbl(
+ ArithSeries *arithSeriesRepPtr,
+ Tcl_WideInt index)
+{
+ ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr;
+ if (arithSeriesRepPtr->isDouble) {
+ double d = dblRepPtr->start + (index * dblRepPtr->step);
+ unsigned n = (dblRepPtr->precision > 0 ? dblRepPtr->precision : 0);
+ return ArithRound(d, n);
+ } else {
+ return (double)(arithSeriesRepPtr->start + (index * arithSeriesRepPtr->step));
+ }
+}
-#define ArithSeriesIndexM(arithSeriesRepPtr, index) \
- ((arithSeriesRepPtr)->isDouble ? \
- (((ArithSeriesDbl*)(arithSeriesRepPtr))->start+((index) * ((ArithSeriesDbl*)(arithSeriesRepPtr))->step)) \
- : \
- ((arithSeriesRepPtr)->start+((index) * arithSeriesRepPtr->step)))
+static inline Tcl_WideInt
+ArithSeriesIndexInt(
+ ArithSeries *arithSeriesRepPtr,
+ Tcl_WideInt index)
+{
+ ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr;
+ if (arithSeriesRepPtr->isDouble) {
+ return (Tcl_WideInt)(dblRepPtr->start + ((index) * dblRepPtr->step));
+ } else {
+ return (arithSeriesRepPtr->start + (index * arithSeriesRepPtr->step));
+ }
+}
-#define ArithSeriesGetInternalRep(objPtr, arithRepPtr) \
- do { \
- const Tcl_ObjInternalRep *irPtr; \
- irPtr = TclFetchInternalRep((objPtr), &tclArithSeriesType.objType); \
- (arithRepPtr) = irPtr ? (ArithSeries *)irPtr->twoPtrValue.ptr1 : NULL; \
- } while (0)
+static inline ArithSeries*
+ArithSeriesGetInternalRep(Tcl_Obj *objPtr)
+{
+ const Tcl_ObjInternalRep *irPtr;
+ irPtr = TclFetchInternalRep((objPtr), &tclArithSeriesType.objType);
+ return irPtr ? (ArithSeries *)irPtr->twoPtrValue.ptr1 : NULL;
+}
+static inline int
+Precision(double d)
+{
+ char tmp[TCL_DOUBLE_SPACE+2], *off;
+ tmp[0] = 0;
+ Tcl_PrintDouble(NULL,d,tmp);
+ off = strchr(tmp, '.');
+ return (off ? strlen(off+1) : 0);
+}
+static inline int
+maxPrecision(double start, double end, double step)
+{
+ // Find longest number of digits after the decimal point.
+ int dp = Precision(step);
+ int i = Precision(start);
+ dp = i>dp ? i : dp;
+ i = Precision(end);
+ dp = i>dp ? i : dp;
+ return dp;
+}
/*
* Prototypes for procedures defined later in this file:
*/
-static void DupArithSeriesInternalRep (Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
-static void FreeArithSeriesInternalRep (Tcl_Obj *listPtr);
-static int SetArithSeriesFromAny (Tcl_Interp *interp, Tcl_Obj *objPtr);
-static void UpdateStringOfArithSeries (Tcl_Obj *arithSeriesObj);
-static Tcl_Obj *ArithSeriesObjStep(Tcl_Obj *arithSeriesPtr);
+static void DupArithSeriesInternalRep (Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
+static void FreeArithSeriesInternalRep (Tcl_Obj *listPtr);
+static int SetArithSeriesFromAny (Tcl_Interp *interp, Tcl_Obj *objPtr);
+static void UpdateStringOfArithSeries (Tcl_Obj *arithSeriesObj);
+static Tcl_Obj* ArithSeriesObjStep(Tcl_Obj *arithSeriesPtr);
static Tcl_Size ArithSeriesObjLength(Tcl_Obj *arithSeriesPtr);
/*
@@ -107,7 +166,7 @@ const TclObjTypeWithAbstractList tclArithSeriesType = {
*----------------------------------------------------------------------
*/
static Tcl_WideInt
-ArithSeriesLen(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step)
+ArithSeriesLenInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step)
{
Tcl_WideInt len;
@@ -118,6 +177,18 @@ ArithSeriesLen(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step)
return (len < 0) ? -1 : len;
}
+static Tcl_WideInt
+ArithSeriesLenDbl(double start, double end, double step)
+{
+ Tcl_WideInt len;
+
+ if (step == 0) {
+ return 0;
+ }
+ len = ((end-start+step)/step);
+ return (len < 0) ? -1 : len;
+}
+
/*
*----------------------------------------------------------------------
*
@@ -140,10 +211,13 @@ static
Tcl_Obj *
NewArithSeriesInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step, Tcl_WideInt len)
{
- Tcl_WideInt length = (len>=0 ? len : ArithSeriesLen(start, end, step));
+ Tcl_WideInt length;
Tcl_Obj *arithSeriesObj;
ArithSeries *arithSeriesRepPtr;
+ length = len>=0 ? len : -1;
+ if (length < 0) length = -1;
+
TclNewObj(arithSeriesObj);
if (length <= 0) {
@@ -184,14 +258,20 @@ NewArithSeriesInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step, Tcl_Wide
* None.
*----------------------------------------------------------------------
*/
+
static
Tcl_Obj *
NewArithSeriesDbl(double start, double end, double step, Tcl_WideInt len)
{
- Tcl_WideInt length = (len>=0 ? len : ArithSeriesLen(start, end, step));
+ Tcl_WideInt length;
Tcl_Obj *arithSeriesObj;
ArithSeriesDbl *arithSeriesRepPtr;
+ length = len>=0 ? len : -1;
+ if (length < 0) {
+ length = -1;
+ }
+
TclNewObj(arithSeriesObj);
if (length <= 0) {
@@ -205,11 +285,14 @@ NewArithSeriesDbl(double start, double end, double step, Tcl_WideInt len)
arithSeriesRepPtr->step = step;
arithSeriesRepPtr->len = length;
arithSeriesRepPtr->elements = NULL;
+ arithSeriesRepPtr->precision = maxPrecision(start,end,step);
arithSeriesObj->internalRep.twoPtrValue.ptr1 = arithSeriesRepPtr;
arithSeriesObj->internalRep.twoPtrValue.ptr2 = NULL;
arithSeriesObj->typePtr = &tclArithSeriesType.objType;
- if (length > 0)
+
+ if (length > 0) {
Tcl_InvalidateStringRep(arithSeriesObj);
+ }
return arithSeriesObj;
}
@@ -295,7 +378,7 @@ TclNewArithSeriesObj(
{
double dstart, dend, dstep;
Tcl_WideInt start, end, step;
- Tcl_WideInt len;
+ Tcl_WideInt len = -1;
if (startObj) {
assignNumber(useDoubles, &start, &dstart, startObj);
@@ -337,9 +420,9 @@ TclNewArithSeriesObj(
assert(dstep!=0);
if (!lenObj) {
if (useDoubles) {
- len = (dend - dstart + dstep)/dstep;
+ len = ArithSeriesLenDbl(dstart, dend, dstep);
} else {
- len = (end - start + step)/step;
+ len = ArithSeriesLenInt(start, end, step);
}
}
}
@@ -354,7 +437,8 @@ TclNewArithSeriesObj(
}
}
- if (TCL_MAJOR_VERSION < 9 && len > ListSizeT_MAX) {
+ if ((TCL_MAJOR_VERSION < 9 && ((len > ListSizeT_MAX))) ||
+ (len > TCL_SIZE_MAX)) {
Tcl_SetObjResult(
interp,
Tcl_NewStringObj("max length of a Tcl list exceeded", -1));
@@ -398,7 +482,7 @@ ArithSeriesObjStep(
if (arithSeriesObj->typePtr != &tclArithSeriesType.objType) {
Tcl_Panic("ArithSeriesObjStep called with a not ArithSeries Obj.");
}
- arithSeriesRepPtr = ArithSeriesRepPtr(arithSeriesObj);
+ arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);
if (arithSeriesRepPtr->isDouble) {
TclNewDoubleObj(stepObj, ((ArithSeriesDbl*)(arithSeriesRepPtr))->step);
} else {
@@ -430,7 +514,7 @@ ArithSeriesObjStep(
Tcl_Obj *
TclArithSeriesObjIndex(
- Tcl_Interp *interp,
+ TCL_UNUSED(Tcl_Interp *),
Tcl_Obj *arithSeriesObj,
Tcl_WideInt index)
{
@@ -439,21 +523,15 @@ TclArithSeriesObjIndex(
if (arithSeriesObj->typePtr != &tclArithSeriesType.objType) {
Tcl_Panic("TclArithSeriesObjIndex called with a not ArithSeries Obj.");
}
- arithSeriesRepPtr = ArithSeriesRepPtr(arithSeriesObj);
+ arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);
if (index < 0 || (Tcl_Size)index >= arithSeriesRepPtr->len) {
- if (interp) {
- Tcl_SetObjResult(interp,
- Tcl_ObjPrintf("index %" TCL_LL_MODIFIER "d is out of bounds 0 to %"
- TCL_LL_MODIFIER "d", index, (arithSeriesRepPtr->len-1)));
- Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
- }
- return NULL;
+ return Tcl_NewObj();
}
/* List[i] = Start + (Step * index) */
if (arithSeriesRepPtr->isDouble) {
- return Tcl_NewDoubleObj(ArithSeriesIndexM(arithSeriesRepPtr, index));
+ return Tcl_NewDoubleObj(ArithSeriesIndexDbl(arithSeriesRepPtr, index));
} else {
- return Tcl_NewWideIntObj(ArithSeriesIndexM(arithSeriesRepPtr, index));
+ return Tcl_NewWideIntObj(ArithSeriesIndexInt(arithSeriesRepPtr, index));
}
}
@@ -541,16 +619,25 @@ DupArithSeriesInternalRep(
Tcl_Obj *copyPtr) /* Object with internal rep to set. */
{
ArithSeries *srcArithSeriesRepPtr =
- (ArithSeries *) srcPtr->internalRep.twoPtrValue.ptr1;
- ArithSeries *copyArithSeriesRepPtr;
-
+ (ArithSeries *) srcPtr->internalRep.twoPtrValue.ptr1;
/*
* Allocate a new ArithSeries structure. */
- copyArithSeriesRepPtr = (ArithSeries*) Tcl_Alloc(sizeof(ArithSeries));
- *copyArithSeriesRepPtr = *srcArithSeriesRepPtr;
- copyArithSeriesRepPtr->elements = NULL;
- copyPtr->internalRep.twoPtrValue.ptr1 = copyArithSeriesRepPtr;
+ if (srcArithSeriesRepPtr->isDouble) {
+ ArithSeriesDbl *srcArithSeriesDblRepPtr =
+ (ArithSeriesDbl *)srcArithSeriesRepPtr;
+ ArithSeriesDbl *copyArithSeriesDblRepPtr =
+ (ArithSeriesDbl *) Tcl_Alloc(sizeof(ArithSeriesDbl));
+ *copyArithSeriesDblRepPtr = *srcArithSeriesDblRepPtr;
+ copyArithSeriesDblRepPtr->elements = NULL;
+ copyPtr->internalRep.twoPtrValue.ptr1 = copyArithSeriesDblRepPtr;
+ } else {
+ ArithSeries *copyArithSeriesRepPtr =
+ (ArithSeries *) Tcl_Alloc(sizeof(ArithSeries));
+ *copyArithSeriesRepPtr = *srcArithSeriesRepPtr;
+ copyArithSeriesRepPtr->elements = NULL;
+ copyPtr->internalRep.twoPtrValue.ptr1 = copyArithSeriesRepPtr;
+ }
copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
copyPtr->typePtr = &tclArithSeriesType.objType;
}
@@ -591,29 +678,47 @@ UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObj)
char *elem, *p;
Tcl_Obj *elemObj;
Tcl_Size i;
- Tcl_WideInt length = 0;
+ Tcl_Size length = 0;
Tcl_Size slen;
/*
* Pass 1: estimate space.
*/
- for (i = 0; i < arithSeriesRepPtr->len; i++) {
- elemObj = TclArithSeriesObjIndex(NULL, arithSeriesObj, i);
- elem = Tcl_GetStringFromObj(elemObj, &slen);
- Tcl_DecrRefCount(elemObj);
- slen += 1; /* + 1 is for the space or the nul-term */
- length += slen;
+ if (!arithSeriesRepPtr->isDouble) {
+ for (i = 0; i < arithSeriesRepPtr->len; i++) {
+ double d = ArithSeriesIndexDbl(arithSeriesRepPtr, i);
+ slen = d>0 ? log10(d)+1 : d<0 ? log10((0-d))+2 : 1;
+ length += slen;
+ }
+ } else {
+ for (i = 0; i < arithSeriesRepPtr->len; i++) {
+ double d = ArithSeriesIndexDbl(arithSeriesRepPtr, i);
+ char tmp[TCL_DOUBLE_SPACE+2];
+ tmp[0] = 0;
+ Tcl_PrintDouble(NULL,d,tmp);
+ if ((length + strlen(tmp)) > TCL_SIZE_MAX) {
+ break; // overflow
+ }
+ length += strlen(tmp);
+ }
}
+ length += arithSeriesRepPtr->len; // Space for each separator
/*
* Pass 2: generate the string repr.
*/
p = Tcl_InitStringRep(arithSeriesObj, NULL, length);
+ if (p == NULL) {
+ Tcl_Panic("Unable to allocate string size %" TCL_Z_MODIFIER "u", length);
+ }
for (i = 0; i < arithSeriesRepPtr->len; i++) {
elemObj = TclArithSeriesObjIndex(NULL, arithSeriesObj, i);
elem = Tcl_GetStringFromObj(elemObj, &slen);
- strcpy(p, elem);
+ if (((p - arithSeriesObj->bytes)+slen) > length) {
+ break;
+ }
+ strncpy(p, elem, slen);
p[slen] = ' ';
p += slen+1;
Tcl_DecrRefCount(elemObj);
@@ -685,7 +790,7 @@ TclArithSeriesObjCopy(
Tcl_Obj *copyPtr;
ArithSeries *arithSeriesRepPtr;
- ArithSeriesGetInternalRep(arithSeriesObj, arithSeriesRepPtr);
+ arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);
if (NULL == arithSeriesRepPtr) {
if (SetArithSeriesFromAny(interp, arithSeriesObj) != TCL_OK) {
/* We know this is going to panic, but it's the message we want */
@@ -728,17 +833,30 @@ TclArithSeriesObjRange(
ArithSeries *arithSeriesRepPtr;
Tcl_Obj *startObj, *endObj, *stepObj;
- ArithSeriesGetInternalRep(arithSeriesObj, arithSeriesRepPtr);
+ arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);
if (fromIdx == TCL_INDEX_NONE) {
fromIdx = 0;
}
- if (fromIdx > toIdx) {
+
+ if (fromIdx > toIdx ||
+ (toIdx > arithSeriesRepPtr->len-1 &&
+ fromIdx > arithSeriesRepPtr->len-1)) {
Tcl_Obj *obj;
TclNewObj(obj);
return obj;
}
+ if (fromIdx < 0) {
+ fromIdx = 0;
+ }
+ if (toIdx < 0) {
+ toIdx = 0;
+ }
+ if (toIdx > arithSeriesRepPtr->len-1) {
+ toIdx = arithSeriesRepPtr->len-1;
+ }
+
startObj = TclArithSeriesObjIndex(interp, arithSeriesObj, fromIdx);
if (startObj == NULL) {
return NULL;
@@ -778,15 +896,17 @@ TclArithSeriesObjRange(
TclInvalidateStringRep(arithSeriesObj);
if (arithSeriesRepPtr->isDouble) {
- ArithSeriesDbl *arithSeriesDblRepPtr = (ArithSeriesDbl*)arithSeriesObj;
+ ArithSeriesDbl *arithSeriesDblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr;
double start, end, step;
+
Tcl_GetDoubleFromObj(NULL, startObj, &start);
Tcl_GetDoubleFromObj(NULL, endObj, &end);
Tcl_GetDoubleFromObj(NULL, stepObj, &step);
arithSeriesDblRepPtr->start = start;
arithSeriesDblRepPtr->end = end;
arithSeriesDblRepPtr->step = step;
- arithSeriesDblRepPtr->len = (end-start+step)/step;
+ arithSeriesDblRepPtr->precision = maxPrecision(start, end, step);
+ arithSeriesDblRepPtr->len = ArithSeriesLenDbl(start, end, step);
arithSeriesDblRepPtr->elements = NULL;
} else {
@@ -797,7 +917,7 @@ TclArithSeriesObjRange(
arithSeriesRepPtr->start = start;
arithSeriesRepPtr->end = end;
arithSeriesRepPtr->step = step;
- arithSeriesRepPtr->len = (end-start+step)/step;
+ arithSeriesRepPtr->len = ArithSeriesLenInt(start, end, step);
arithSeriesRepPtr->elements = NULL;
}
@@ -852,7 +972,7 @@ TclArithSeriesGetElements(
Tcl_Obj **objv;
int i, objc;
- ArithSeriesGetInternalRep(objPtr, arithSeriesRepPtr);
+ arithSeriesRepPtr = ArithSeriesGetInternalRep(objPtr);
objc = arithSeriesRepPtr->len;
if (objc > 0) {
if (arithSeriesRepPtr->elements) {
@@ -927,7 +1047,7 @@ TclArithSeriesObjReverse(
double dstart, dend, dstep;
int isDouble;
- ArithSeriesGetInternalRep(arithSeriesObj, arithSeriesRepPtr);
+ arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);
isDouble = arithSeriesRepPtr->isDouble;
len = arithSeriesRepPtr->len;
diff --git a/generic/tclArithSeries.h b/generic/tclArithSeries.h
index bb8dfa8..61538c4 100644
--- a/generic/tclArithSeries.h
+++ b/generic/tclArithSeries.h
@@ -30,6 +30,7 @@ typedef struct {
double start;
double end;
double step;
+ int precision;
} ArithSeriesDbl;
diff --git a/tests/lseq.test b/tests/lseq.test
index 1dff72d..6bf89eb 100644
--- a/tests/lseq.test
+++ b/tests/lseq.test
@@ -19,7 +19,7 @@ testConstraint arithSeriesShimmer 1
testConstraint arithSeriesShimmerOk 1
testConstraint has64BitLengths [expr {$tcl_platform(pointerSize) == 8}]
-## Arg errors
+# Arg errors
test lseq-1.1 {error cases} -body {
lseq
} \
@@ -416,9 +416,9 @@ test lseq-3.30 {lreverse with double values} arithSeriesDouble {
arithseries
18.5 17.0 15.5 14.0 12.5 11.0 9.5 8.0 6.5 5.0 3.5}
-test lseq-3.31 {lreverse inplace with doubles} arithSeriesDouble {
+test lseq-3.31 {lreverse inplace with doubles} {arithSeriesDouble has64BitLengths} {
lreverse [lseq 1.1 29.9 0.3]
-} {29.9 29.599999999999998 29.299999999999997 29.0 28.7 28.4 28.099999999999998 27.799999999999997 27.5 27.2 26.9 26.599999999999998 26.299999999999997 26.0 25.7 25.4 25.099999999999998 24.799999999999997 24.5 24.2 23.9 23.599999999999998 23.299999999999997 23.0 22.7 22.4 22.099999999999998 21.799999999999997 21.5 21.2 20.9 20.6 20.299999999999997 20.0 19.7 19.4 19.1 18.799999999999997 18.5 18.2 17.9 17.6 17.299999999999997 17.0 16.7 16.4 16.1 15.799999999999999 15.5 15.2 14.899999999999999 14.6 14.299999999999999 14.0 13.7 13.399999999999999 13.099999999999998 12.8 12.5 12.2 11.899999999999999 11.599999999999998 11.3 11.0 10.7 10.399999999999999 10.099999999999998 9.8 9.5 9.2 8.899999999999999 8.599999999999998 8.3 8.0 7.699999999999999 7.399999999999999 7.099999999999998 6.800000000000001 6.5 6.199999999999999 5.899999999999999 5.599999999999998 5.300000000000001 5.0 4.699999999999999 4.399999999999999 4.099999999999998 3.8000000000000007 3.5 3.1999999999999993 2.8999999999999986 2.599999999999998 2.3000000000000007 2.0 1.6999999999999993 1.3999999999999986 1.1000000000000014}
+} {29.9 29.6 29.3 29.0 28.7 28.4 28.1 27.8 27.5 27.2 26.9 26.6 26.3 26.0 25.7 25.4 25.1 24.8 24.5 24.2 23.9 23.6 23.3 23.0 22.7 22.4 22.1 21.8 21.5 21.2 20.9 20.6 20.3 20.0 19.7 19.4 19.1 18.8 18.5 18.2 17.9 17.6 17.3 17.0 16.7 16.4 16.1 15.8 15.5 15.2 14.9 14.6 14.3 14.0 13.7 13.4 13.1 12.8 12.5 12.2 11.9 11.6 11.3 11.0 10.7 10.4 10.1 9.8 9.5 9.2 8.9 8.6 8.3 8.0 7.7 7.4 7.1 6.8 6.5 6.2 5.9 5.6 5.3 5.0 4.7 4.4 4.1 3.8 3.5 3.2 2.9 2.6 2.3 2.0 1.7 1.4 1.1}
test lseq-4.1 {end expressions} {
set start 7
@@ -538,12 +538,12 @@ test lseq-4.8 {error case lrange} -body {
} -returnCodes 1 \
-result {bad index "fred": must be integer?[+-]integer? or end?[+-]integer?}
-test lseq-4.9 {error case lrange} -body {
- set fred 7
- set ginger 8
- lrange [lseq 1 5] $fred $ginger
-} -returnCodes 1 \
- -result {index 7 is out of bounds 0 to 4}
+test lseq-4.9 {lrange empty/partial sets} -body {
+ foreach {fred ginger} {7 8 4 9 0 15 9 9 4 2} {
+ lappend res [lrange [lseq 1 5] $fred $ginger]
+ }
+ set res
+} -result {{} 5 {1 2 3 4 5} {} {}}
# Panic when using variable value?
test lseq-4.10 {panic using variable index} {
@@ -551,6 +551,39 @@ test lseq-4.10 {panic using variable index} {
lindex [lseq 10] $i
} {0}
+test lseq-4.11 {bug lseq / lindex discrepancies} -constraints has64BitLengths -body {
+ lindex [lseq 0x7fffffff] 0x80000000
+} -result {}
+
+test lseq-4.12 {bug lseq} -constraints has64BitLengths -body {
+ llength [lseq 0x100000000]
+} -result {4294967296}
+
+test lseq-4.13 {bug lseq} -constraints has64BitLengths -body {
+ set l [lseq 0x7fffffffffffffff]
+ list \
+ [llength $l] \
+ [lindex $l end] \
+ [lindex $l 9223372036854775800]
+} -result {9223372036854775807 9223372036854775806 9223372036854775800}
+
+
+test lseq-4.14 {bug lseq - inconsistent rounding} has64BitLengths {
+ # using a non-integer increment, [lseq] rounding seems to be not consistent:
+ lseq 4 40 0.1
+} {4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.0 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 8.0 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 9.0 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 10.0 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 11.0 11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 12.0 12.1 12.2 12.3 12.4 12.5 12.6 12.7 12.8 12.9 13.0 13.1 13.2 13.3 13.4 13.5 13.6 13.7 13.8 13.9 14.0 14.1 14.2 14.3 14.4 14.5 14.6 14.7 14.8 14.9 15.0 15.1 15.2 15.3 15.4 15.5 15.6 15.7 15.8 15.9 16.0 16.1 16.2 16.3 16.4 16.5 16.6 16.7 16.8 16.9 17.0 17.1 17.2 17.3 17.4 17.5 17.6 17.7 17.8 17.9 18.0 18.1 18.2 18.3 18.4 18.5 18.6 18.7 18.8 18.9 19.0 19.1 19.2 19.3 19.4 19.5 19.6 19.7 19.8 19.9 20.0 20.1 20.2 20.3 20.4 20.5 20.6 20.7 20.8 20.9 21.0 21.1 21.2 21.3 21.4 21.5 21.6 21.7 21.8 21.9 22.0 22.1 22.2 22.3 22.4 22.5 22.6 22.7 22.8 22.9 23.0 23.1 23.2 23.3 23.4 23.5 23.6 23.7 23.8 23.9 24.0 24.1 24.2 24.3 24.4 24.5 24.6 24.7 24.8 24.9 25.0 25.1 25.2 25.3 25.4 25.5 25.6 25.7 25.8 25.9 26.0 26.1 26.2 26.3 26.4 26.5 26.6 26.7 26.8 26.9 27.0 27.1 27.2 27.3 27.4 27.5 27.6 27.7 27.8 27.9 28.0 28.1 28.2 28.3 28.4 28.5 28.6 28.7 28.8 28.9 29.0 29.1 29.2 29.3 29.4 29.5 29.6 29.7 29.8 29.9 30.0 30.1 30.2 30.3 30.4 30.5 30.6 30.7 30.8 30.9 31.0 31.1 31.2 31.3 31.4 31.5 31.6 31.7 31.8 31.9 32.0 32.1 32.2 32.3 32.4 32.5 32.6 32.7 32.8 32.9 33.0 33.1 33.2 33.3 33.4 33.5 33.6 33.7 33.8 33.9 34.0 34.1 34.2 34.3 34.4 34.5 34.6 34.7 34.8 34.9 35.0 35.1 35.2 35.3 35.4 35.5 35.6 35.7 35.8 35.9 36.0 36.1 36.2 36.3 36.4 36.5 36.6 36.7 36.8 36.9 37.0 37.1 37.2 37.3 37.4 37.5 37.6 37.7 37.8 37.9 38.0 38.1 38.2 38.3 38.4 38.5 38.6 38.7 38.8 38.9 39.0 39.1 39.2 39.3 39.4 39.5 39.6 39.7 39.8 39.9 40.0}
+
+test lseq-4.15 {bug lseq - inconsistent rounding} has64BitLengths {
+ # using a non-integer increment, [lseq] rounding seems to be not consistent:
+ lseq 6 40 0.1
+} {6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.0 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 8.0 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 9.0 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 10.0 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 11.0 11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 12.0 12.1 12.2 12.3 12.4 12.5 12.6 12.7 12.8 12.9 13.0 13.1 13.2 13.3 13.4 13.5 13.6 13.7 13.8 13.9 14.0 14.1 14.2 14.3 14.4 14.5 14.6 14.7 14.8 14.9 15.0 15.1 15.2 15.3 15.4 15.5 15.6 15.7 15.8 15.9 16.0 16.1 16.2 16.3 16.4 16.5 16.6 16.7 16.8 16.9 17.0 17.1 17.2 17.3 17.4 17.5 17.6 17.7 17.8 17.9 18.0 18.1 18.2 18.3 18.4 18.5 18.6 18.7 18.8 18.9 19.0 19.1 19.2 19.3 19.4 19.5 19.6 19.7 19.8 19.9 20.0 20.1 20.2 20.3 20.4 20.5 20.6 20.7 20.8 20.9 21.0 21.1 21.2 21.3 21.4 21.5 21.6 21.7 21.8 21.9 22.0 22.1 22.2 22.3 22.4 22.5 22.6 22.7 22.8 22.9 23.0 23.1 23.2 23.3 23.4 23.5 23.6 23.7 23.8 23.9 24.0 24.1 24.2 24.3 24.4 24.5 24.6 24.7 24.8 24.9 25.0 25.1 25.2 25.3 25.4 25.5 25.6 25.7 25.8 25.9 26.0 26.1 26.2 26.3 26.4 26.5 26.6 26.7 26.8 26.9 27.0 27.1 27.2 27.3 27.4 27.5 27.6 27.7 27.8 27.9 28.0 28.1 28.2 28.3 28.4 28.5 28.6 28.7 28.8 28.9 29.0 29.1 29.2 29.3 29.4 29.5 29.6 29.7 29.8 29.9 30.0 30.1 30.2 30.3 30.4 30.5 30.6 30.7 30.8 30.9 31.0 31.1 31.2 31.3 31.4 31.5 31.6 31.7 31.8 31.9 32.0 32.1 32.2 32.3 32.4 32.5 32.6 32.7 32.8 32.9 33.0 33.1 33.2 33.3 33.4 33.5 33.6 33.7 33.8 33.9 34.0 34.1 34.2 34.3 34.4 34.5 34.6 34.7 34.8 34.9 35.0 35.1 35.2 35.3 35.4 35.5 35.6 35.7 35.8 35.9 36.0 36.1 36.2 36.3 36.4 36.5 36.6 36.7 36.8 36.9 37.0 37.1 37.2 37.3 37.4 37.5 37.6 37.7 37.8 37.9 38.0 38.1 38.2 38.3 38.4 38.5 38.6 38.7 38.8 38.9 39.0 39.1 39.2 39.3 39.4 39.5 39.6 39.7 39.8 39.9 40.0}
+
+test lseq-4.16 {bug lseq - inconsistent rounding} {
+ # using a non-integer increment, [lseq] rounding seems to be not consistent:
+ set res {}
+ lappend res [lseq 4.07 6 0.1]
+ lappend res [lseq 4.03 4.208 0.013]
+} {{4.07 4.17 4.27 4.37 4.47 4.57 4.67 4.77 4.87 4.97 5.07 5.17 5.27 5.37 5.47 5.57 5.67 5.77 5.87 5.97} {4.03 4.043 4.056 4.069 4.082 4.095 4.108 4.121 4.134 4.147 4.16 4.173 4.186 4.199}}
# cleanup
::tcltest::cleanupTests