From 53b965c549d6fa0d436bf2c84dea037d23db105e Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 15 Feb 2024 20:33:17 +0000 Subject: [PATCH] Fix [578b7e273c03]: Round computed end value to match precision of given arguments --- generic/tclArithSeries.c | 13 +++++++++---- tests/lseq.test | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/generic/tclArithSeries.c b/generic/tclArithSeries.c index 34fd6355ea8..a29b589d0e5 100755 --- a/generic/tclArithSeries.c +++ b/generic/tclArithSeries.c @@ -245,7 +245,7 @@ DupArithSeriesInternalRep( ArithSeriesDbl *srcArithSeriesDblRepPtr = (ArithSeriesDbl *)srcArithSeriesRepPtr; ArithSeriesDbl *copyArithSeriesDblRepPtr = - (ArithSeriesDbl *) ckalloc(sizeof(ArithSeriesDbl)); + (ArithSeriesDbl *)ckalloc(sizeof(ArithSeriesDbl)); *copyArithSeriesDblRepPtr = *srcArithSeriesDblRepPtr; copyArithSeriesDblRepPtr->elements = NULL; copyPtr->internalRep.twoPtrValue.ptr1 = copyArithSeriesDblRepPtr; @@ -327,7 +327,7 @@ NewArithSeriesInt(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step, Tcl_Wide return arithSeriesObj; } - arithSeriesRepPtr = (ArithSeries*) ckalloc(sizeof (ArithSeries)); + arithSeriesRepPtr = (ArithSeries*)ckalloc(sizeof (ArithSeries)); arithSeriesRepPtr->isDouble = 0; arithSeriesRepPtr->start = start; arithSeriesRepPtr->end = end; @@ -381,7 +381,7 @@ NewArithSeriesDbl(double start, double end, double step, Tcl_WideInt len) return arithSeriesObj; } - arithSeriesRepPtr = (ArithSeriesDbl*) ckalloc(sizeof (ArithSeriesDbl)); + arithSeriesRepPtr = (ArithSeriesDbl*)ckalloc(sizeof (ArithSeriesDbl)); arithSeriesRepPtr->isDouble = 1; arithSeriesRepPtr->start = start; arithSeriesRepPtr->end = end; @@ -533,7 +533,11 @@ TclNewArithSeriesObj( if (!endObj) { if (useDoubles) { + // Compute precision based on given command argument values + int precision = maxPrecision(dstart,len,dstep); dend = dstart + (dstep * (len-1)); + // Make computed end value match argument(s) precision + dend = ArithRound(dend, precision); end = dend; } else { end = start + (step * (len-1)); @@ -642,6 +646,7 @@ Tcl_Size TclArithSeriesObjLength(Tcl_Obj *arithSeriesObj) * None. *---------------------------------------------------------------------- */ + Tcl_Obj * ArithSeriesObjStep( Tcl_Obj *arithSeriesObj) @@ -1094,7 +1099,7 @@ UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObjPtr) if (length > 0) arithSeriesObjPtr->bytes[length-1] = '\0'; arithSeriesObjPtr->length = length-1; } - + /* * Local Variables: * mode: c diff --git a/tests/lseq.test b/tests/lseq.test index 4c1f14bede8..2a7de670069 100644 --- a/tests/lseq.test +++ b/tests/lseq.test @@ -692,6 +692,25 @@ test lseq-bug-54329e39c7 {does not cause memory bloat} -constraints { expr {($postmem - $premem) < 10} } -result 1 +test lseq-bug-578b7e273c03-1 {Arithmetic Series Objects get wrong precision when end value is not specified} -body { + set bl [expr {2.8 in [lseq 0 count 100 by .1]}] + lappend bl [expr {2.8 in [lseq 0 count 200 by .1]}] + lappend bl [expr {0.28 in [lseq 0 count 100 by .01]}] + lappend bl [expr {0.28 in [lseq 0 count 200 by .01]}] + lappend bl [expr {0.286 in [lseq 0 count 100 by .011]}] + lappend bl [expr {0.286 in [lseq 0 count 200 by .011]}] +} -result {1 1 1 1 1 1} + +test lseq-bug-578b7e273c03-2 {Arithmetic Series Objects get wrong precision when end value is not specified} -body { + set ll [llength [lseq 0 count 100 by .1]] + lappend ll [llength [lseq 0 count 200 by .1]] + lappend ll [llength [lseq 0 count 100 by .01]] + lappend ll [llength [lseq 0 count 200 by .01]] + lappend ll [llength [lseq 0 count 100 by .011]] + lappend ll [llength [lseq 0 count 200 by .011]] +} -result {100 200 100 200 100 200} + + # cleanup ::tcltest::cleanupTests