summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorapnadkarni <apnmbx-wits@yahoo.com>2022-11-05 11:49:08 (GMT)
committerapnadkarni <apnmbx-wits@yahoo.com>2022-11-05 11:49:08 (GMT)
commitc3c5a80a02a02427696394cb0ed1f8adeab1099d (patch)
tree2a821319db65ee920a8d0fb027a68ddcb51c903d
parent6559f4084e844e187198c5471bfd15f19c8dfecc (diff)
parentd9033672db616bb406894a480e90410666ff4545 (diff)
downloadtcl-c3c5a80a02a02427696394cb0ed1f8adeab1099d.zip
tcl-c3c5a80a02a02427696394cb0ed1f8adeab1099d.tar.gz
tcl-c3c5a80a02a02427696394cb0ed1f8adeab1099d.tar.bz2
Merge 8.7. lreplace4 bcc instruction and FLT_MAX fix
-rw-r--r--generic/tclBasic.c4
-rw-r--r--generic/tclBinary.c4
-rw-r--r--generic/tclCompCmdsGR.c206
-rw-r--r--generic/tclCompile.c7
-rw-r--r--generic/tclCompile.h8
-rw-r--r--generic/tclExecute.c103
-rw-r--r--tests/binary.test81
7 files changed, 227 insertions, 186 deletions
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index 5ab12d4..cd1bfc8 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -297,6 +297,7 @@ static const CmdInfo builtInCmds[] = {
{"join", Tcl_JoinObjCmd, NULL, NULL, CMD_IS_SAFE},
{"lappend", Tcl_LappendObjCmd, TclCompileLappendCmd, NULL, CMD_IS_SAFE},
{"lassign", Tcl_LassignObjCmd, TclCompileLassignCmd, NULL, CMD_IS_SAFE},
+ {"ledit", Tcl_LeditObjCmd, NULL, NULL, CMD_IS_SAFE},
{"lindex", Tcl_LindexObjCmd, TclCompileLindexCmd, NULL, CMD_IS_SAFE},
{"linsert", Tcl_LinsertObjCmd, TclCompileLinsertCmd, NULL, CMD_IS_SAFE},
{"list", Tcl_ListObjCmd, TclCompileListCmd, NULL, CMD_IS_SAFE|CMD_COMPILES_EXPANDED},
@@ -309,10 +310,9 @@ static const CmdInfo builtInCmds[] = {
{"lreplace", Tcl_LreplaceObjCmd, TclCompileLreplaceCmd, NULL, CMD_IS_SAFE},
{"lreverse", Tcl_LreverseObjCmd, NULL, NULL, CMD_IS_SAFE},
{"lsearch", Tcl_LsearchObjCmd, NULL, NULL, CMD_IS_SAFE},
- {"lseq", Tcl_LseqObjCmd, NULL, NULL, CMD_IS_SAFE},
+ {"lseq", Tcl_LseqObjCmd, NULL, NULL, CMD_IS_SAFE},
{"lset", Tcl_LsetObjCmd, TclCompileLsetCmd, NULL, CMD_IS_SAFE},
{"lsort", Tcl_LsortObjCmd, NULL, NULL, CMD_IS_SAFE},
- {"ledit", Tcl_LeditObjCmd, NULL, NULL, CMD_IS_SAFE},
{"package", Tcl_PackageObjCmd, NULL, TclNRPackageObjCmd, CMD_IS_SAFE},
{"proc", procObjCmd, NULL, NULL, CMD_IS_SAFE},
{"regexp", Tcl_RegexpObjCmd, TclCompileRegexpCmd, NULL, CMD_IS_SAFE},
diff --git a/generic/tclBinary.c b/generic/tclBinary.c
index a7d6617..f27bb93 100644
--- a/generic/tclBinary.c
+++ b/generic/tclBinary.c
@@ -2051,7 +2051,11 @@ FormatNumber(
*/
if (fabs(dvalue) > (double) FLT_MAX) {
+ if (fabs(dvalue) > (FLT_MAX + pow(2, (FLT_MAX_EXP - FLT_MANT_DIG - 1)))) {
+ fvalue = (dvalue >= 0.0) ? INFINITY : -INFINITY; // c99
+ } else {
fvalue = (dvalue >= 0.0) ? FLT_MAX : -FLT_MAX;
+ }
} else {
fvalue = (float) dvalue;
}
diff --git a/generic/tclCompCmdsGR.c b/generic/tclCompCmdsGR.c
index 2ea3b77..efa36ad 100644
--- a/generic/tclCompCmdsGR.c
+++ b/generic/tclCompCmdsGR.c
@@ -1356,84 +1356,34 @@ TclCompileLinsertCmd(
CompileEnv *envPtr) /* Holds the resulting instructions. */
{
DefineLineInformation; /* TIP #280 */
- Tcl_Token *tokenPtr, *listTokenPtr;
- int idx, i;
+ Tcl_Token *tokenPtr;
+ int i;
if ((int)parsePtr->numWords < 3) {
return TCL_ERROR;
}
- listTokenPtr = TokenAfter(parsePtr->tokenPtr);
-
- /*
- * Parse the index. Will only compile if it is constant and not an
- * _integer_ less than zero (since we reserve negative indices here for
- * end-relative indexing) or an end-based index greater than 'end' itself.
- */
-
- tokenPtr = TokenAfter(listTokenPtr);
-
- /*
- * NOTE: This command treats all inserts at indices before the list
- * the same as inserts at the start of the list, and all inserts
- * after the list the same as inserts at the end of the list. We
- * make that transformation here so we can use the optimized bytecode
- * as much as possible.
- */
- if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_START, TCL_INDEX_END,
- &idx) != TCL_OK) {
- return TCL_ERROR;
- }
-
- /*
- * There are four main cases. If there are no values to insert, this is
- * just a confirm-listiness check. If the index is '0', this is a prepend.
- * If the index is 'end' (== TCL_INDEX_END), this is an append. Otherwise,
- * this is a splice (== split, insert values as list, concat-3).
- */
-
- CompileWord(envPtr, listTokenPtr, interp, 1);
- if (parsePtr->numWords == 3) {
- TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
- TclEmitInt4( (int)TCL_INDEX_END, envPtr);
- return TCL_OK;
- }
+
+ /* Push list, insertion index onto the stack */
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, 1);
+ tokenPtr = TokenAfter(tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, 2);
+ /* Push new elements to be inserted */
for (i=3 ; i<(int)parsePtr->numWords ; i++) {
tokenPtr = TokenAfter(tokenPtr);
CompileWord(envPtr, tokenPtr, interp, i);
}
- TclEmitInstInt4( INST_LIST, i - 3, envPtr);
- if (idx == (int)TCL_INDEX_START) {
- TclEmitInstInt4( INST_REVERSE, 2, envPtr);
- TclEmitOpcode( INST_LIST_CONCAT, envPtr);
- } else if (idx == (int)TCL_INDEX_END) {
- TclEmitOpcode( INST_LIST_CONCAT, envPtr);
- } else {
- /*
- * Here we handle two ranges for idx. First when idx > 0, we
- * want the first half of the split to end at index idx-1 and
- * the second half to start at index idx.
- * Second when idx < TCL_INDEX_END, indicating "end-N" indexing,
- * we want the first half of the split to end at index end-N and
- * the second half to start at index end-N+1. We accomplish this
- * with a pre-adjustment of the end-N value.
- * The root of this is that the commands [lrange] and [linsert]
- * differ in their interpretation of the "end" index.
- */
-
- if (idx < (int)TCL_INDEX_END) {
- idx++;
- }
- TclEmitInstInt4( INST_OVER, 1, envPtr);
- TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
- TclEmitInt4( idx - 1, envPtr);
- TclEmitInstInt4( INST_REVERSE, 3, envPtr);
- TclEmitInstInt4( INST_LIST_RANGE_IMM, idx, envPtr);
- TclEmitInt4( (int)TCL_INDEX_END, envPtr);
- TclEmitOpcode( INST_LIST_CONCAT, envPtr);
- TclEmitOpcode( INST_LIST_CONCAT, envPtr);
- }
+ /* First operand is count of arguments */
+ TclEmitInstInt4(INST_LREPLACE4, parsePtr->numWords - 1, envPtr);
+ /*
+ * Second operand is bitmask
+ * TCL_LREPLACE4_END_IS_LAST - end refers to last element
+ * TCL_LREPLACE4_SINGLE_INDEX - second index is not present
+ * indicating this is a pure insert
+ */
+ TclEmitInt1(TCL_LREPLACE4_SINGLE_INDEX, envPtr);
return TCL_OK;
}
@@ -1458,116 +1408,34 @@ TclCompileLreplaceCmd(
CompileEnv *envPtr) /* Holds the resulting instructions. */
{
DefineLineInformation; /* TIP #280 */
- Tcl_Token *tokenPtr, *listTokenPtr;
- int idx1, idx2, i;
- int emptyPrefix=1, suffixStart = 0;
-
- if ((int)parsePtr->numWords < 4) {
- return TCL_ERROR;
- }
- listTokenPtr = TokenAfter(parsePtr->tokenPtr);
+ Tcl_Token *tokenPtr;
+ int i;
- tokenPtr = TokenAfter(listTokenPtr);
- if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_START, TCL_INDEX_NONE,
- &idx1) != TCL_OK) {
+ if (parsePtr->numWords < 4) {
return TCL_ERROR;
}
+ /* Push list, first, last onto the stack */
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, 1);
tokenPtr = TokenAfter(tokenPtr);
- if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_NONE, TCL_INDEX_END,
- &idx2) != TCL_OK) {
- return TCL_ERROR;
- }
-
- /*
- * General structure of the [lreplace] result is
- * prefix replacement suffix
- * In a few cases we can predict various parts will be empty and
- * take advantage.
- *
- * The proper suffix begins with the greater of indices idx1 or
- * idx2 + 1. If we cannot tell at compile time which is greater,
- * we must defer to direct evaluation.
- */
-
- if (idx1 == (int)TCL_INDEX_NONE) {
- suffixStart = (int)TCL_INDEX_NONE;
- } else if (idx2 == (int)TCL_INDEX_NONE) {
- suffixStart = idx1;
- } else if (idx2 == (int)TCL_INDEX_END) {
- suffixStart = (int)TCL_INDEX_NONE;
- } else if (((idx2 < (int)TCL_INDEX_END) && (idx1 <= (int)TCL_INDEX_END))
- || ((idx2 >= (int)TCL_INDEX_START) && (idx1 >= (int)TCL_INDEX_START))) {
- suffixStart = (idx1 > idx2 + 1) ? idx1 : idx2 + 1;
- } else {
- return TCL_ERROR;
- }
-
- /* All paths start with computing/pushing the original value. */
- CompileWord(envPtr, listTokenPtr, interp, 1);
+ CompileWord(envPtr, tokenPtr, interp, 2);
+ tokenPtr = TokenAfter(tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, 3);
- /*
- * Push all the replacement values next so any errors raised in
- * creating them get raised first.
- */
- if ((int)parsePtr->numWords > 4) {
- /* Push the replacement arguments */
+ /* Push new elements to be inserted */
+ for (i=4 ; i< (int) parsePtr->numWords ; i++) {
tokenPtr = TokenAfter(tokenPtr);
- for (i=4 ; i<(int)parsePtr->numWords ; i++) {
- CompileWord(envPtr, tokenPtr, interp, i);
- tokenPtr = TokenAfter(tokenPtr);
- }
-
- /* Make a list of them... */
- TclEmitInstInt4( INST_LIST, i - 4, envPtr);
-
- emptyPrefix = 0;
- }
-
- if ((idx1 == suffixStart) && (parsePtr->numWords == 4)) {
- /*
- * This is a "no-op". Example: [lreplace {a b c} 2 0]
- * We still do a list operation to get list-verification
- * and canonicalization side effects.
- */
- TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
- TclEmitInt4( (int)TCL_INDEX_END, envPtr);
- return TCL_OK;
- }
-
- if (idx1 != (int)TCL_INDEX_START) {
- /* Prefix may not be empty; generate bytecode to push it */
- if (emptyPrefix) {
- TclEmitOpcode( INST_DUP, envPtr);
- } else {
- TclEmitInstInt4( INST_OVER, 1, envPtr);
- }
- TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
- TclEmitInt4( idx1 - 1, envPtr);
- if (!emptyPrefix) {
- TclEmitInstInt4( INST_REVERSE, 2, envPtr);
- TclEmitOpcode( INST_LIST_CONCAT, envPtr);
- }
- emptyPrefix = 0;
- }
-
- if (!emptyPrefix) {
- TclEmitInstInt4( INST_REVERSE, 2, envPtr);
+ CompileWord(envPtr, tokenPtr, interp, i);
}
- if (suffixStart == (int)TCL_INDEX_NONE) {
- TclEmitOpcode( INST_POP, envPtr);
- if (emptyPrefix) {
- PushStringLiteral(envPtr, "");
- }
- } else {
- /* Suffix may not be empty; generate bytecode to push it */
- TclEmitInstInt4( INST_LIST_RANGE_IMM, suffixStart, envPtr);
- TclEmitInt4( (int)TCL_INDEX_END, envPtr);
- if (!emptyPrefix) {
- TclEmitOpcode( INST_LIST_CONCAT, envPtr);
- }
- }
+ /* First operand is count of arguments */
+ TclEmitInstInt4(INST_LREPLACE4, parsePtr->numWords - 1, envPtr);
+ /*
+ * Second operand is bitmask
+ * TCL_LREPLACE4_END_IS_LAST - end refers to last element
+ */
+ TclEmitInt1(TCL_LREPLACE4_END_IS_LAST, envPtr);
return TCL_OK;
}
diff --git a/generic/tclCompile.c b/generic/tclCompile.c
index a57743c..b38a657 100644
--- a/generic/tclCompile.c
+++ b/generic/tclCompile.c
@@ -657,6 +657,13 @@ InstructionDesc const tclInstructionTable[] = {
/* String Less or equal: push (stknext <= stktop) */
{"strge", 1, -1, 0, {OPERAND_NONE}},
/* String Greater or equal: push (stknext >= stktop) */
+ {"lreplace4", 6, INT_MIN, 2, {OPERAND_UINT4, OPERAND_UINT1}},
+ /* Operands: number of arguments, flags
+ * flags: Combination of TCL_LREPLACE4_* flags
+ * Stack: ... listobj index1 ?index2? new1 ... newN => ... newlistobj
+ * where index2 is present only if TCL_LREPLACE_SINGLE_INDEX is not
+ * set in flags.
+ */
{NULL, 0, 0, 0, {OPERAND_NONE}}
};
diff --git a/generic/tclCompile.h b/generic/tclCompile.h
index 30b1819..035edac 100644
--- a/generic/tclCompile.h
+++ b/generic/tclCompile.h
@@ -835,6 +835,8 @@ enum TclInstruction {
INST_STR_LE,
INST_STR_GE,
+ INST_LREPLACE4,
+
/* The last opcode */
LAST_INST_OPCODE
};
@@ -1673,6 +1675,12 @@ MODULE_SCOPE int TclPushProcCallFrame(void *clientData,
#define TCL_NO_ELEMENT 2 /* Do not push the array element. */
/*
+ * Flags bits used by lreplace4 instruction
+ */
+#define TCL_LREPLACE4_END_IS_LAST 1 /* "end" refers to last element */
+#define TCL_LREPLACE4_SINGLE_INDEX 2 /* Second index absent (pure insert) */
+
+/*
* DTrace probe macros (NOPs if DTrace support is not enabled).
*/
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index 444f9aa..e2a2705 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.c
@@ -5034,11 +5034,104 @@ TEBCresume(
NEXT_INST_F(1, 1, 0);
}
- /*
- * End of INST_LIST and related instructions.
- * -----------------------------------------------------------------
- * Start of string-related instructions.
- */
+ case INST_LREPLACE4:
+ {
+ Tcl_Size numToDelete, numNewElems;
+ int end_indicator;
+ int haveSecondIndex, flags;
+ Tcl_Obj *fromIdxObj, *toIdxObj;
+ opnd = TclGetInt4AtPtr(pc + 1);
+ flags = TclGetInt1AtPtr(pc + 5);
+
+ /* Stack: ... listobj index1 ?index2? new1 ... newN */
+ valuePtr = OBJ_AT_DEPTH(opnd-1);
+
+ /* haveSecondIndex==0 => pure insert */
+ haveSecondIndex = (flags & TCL_LREPLACE4_SINGLE_INDEX) == 0;
+ numNewElems = opnd - 2 - haveSecondIndex;
+
+ /* end_indicator==1 => "end" is last element's index, 0=>index beyond */
+ end_indicator = (flags & TCL_LREPLACE4_END_IS_LAST) != 0;
+ fromIdxObj = OBJ_AT_DEPTH(opnd - 2);
+ toIdxObj = haveSecondIndex ? OBJ_AT_DEPTH(opnd - 3) : NULL;
+ if (Tcl_ListObjLength(interp, valuePtr, &length) != TCL_OK) {
+ TRACE_ERROR(interp);
+ goto gotError;
+ }
+
+ DECACHE_STACK_INFO();
+
+ if (TclGetIntForIndexM(
+ interp, fromIdxObj, length - end_indicator, &fromIdx)
+ != TCL_OK) {
+ CACHE_STACK_INFO();
+ TRACE_ERROR(interp);
+ goto gotError;
+ }
+ if (fromIdx == TCL_INDEX_NONE) {
+ fromIdx = 0;
+ }
+ else if (fromIdx > length) {
+ fromIdx = length;
+ }
+ numToDelete = 0;
+ if (toIdxObj) {
+ if (TclGetIntForIndexM(
+ interp, toIdxObj, length - end_indicator, &toIdx)
+ != TCL_OK) {
+ CACHE_STACK_INFO();
+ TRACE_ERROR(interp);
+ goto gotError;
+ }
+ if (toIdx != TCL_INDEX_NONE) {
+ if (toIdx > length) {
+ toIdx = length;
+ }
+ if (toIdx >= fromIdx) {
+ numToDelete = toIdx - fromIdx + 1;
+ }
+ }
+ }
+
+ CACHE_STACK_INFO();
+
+ if (Tcl_IsShared(valuePtr)) {
+ objResultPtr = Tcl_DuplicateObj(valuePtr);
+ if (Tcl_ListObjReplace(interp,
+ objResultPtr,
+ fromIdx,
+ numToDelete,
+ numNewElems,
+ &OBJ_AT_DEPTH(numNewElems - 1))
+ != TCL_OK) {
+ TRACE_ERROR(interp);
+ Tcl_DecrRefCount(objResultPtr);
+ goto gotError;
+ }
+ TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr)));
+ NEXT_INST_V(6, opnd, 1);
+ }
+ else {
+ if (Tcl_ListObjReplace(interp,
+ valuePtr,
+ fromIdx,
+ numToDelete,
+ numNewElems,
+ &OBJ_AT_DEPTH(numNewElems - 1))
+ != TCL_OK) {
+ TRACE_ERROR(interp);
+ goto gotError;
+ }
+ TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr)));
+ NEXT_INST_V(6, opnd - 1, 0);
+ }
+ }
+
+ /*
+ * End of INST_LIST and related instructions.
+ * -----------------------------------------------------------------
+ * Start of string-related instructions.
+ */
case INST_STR_EQ:
case INST_STR_NEQ: /* String (in)equality check */
diff --git a/tests/binary.test b/tests/binary.test
index 1d0e36d..a947410 100644
--- a/tests/binary.test
+++ b/tests/binary.test
@@ -512,10 +512,10 @@ test binary-13.11 {Tcl_BinaryObjCmd: format} littleEndian {
} \xCD\xCC\xCC\x3F\x9A\x99\x59\x40
test binary-13.12 {Tcl_BinaryObjCmd: float overflow} bigEndian {
binary format f -3.402825e+38
-} \xFF\x7F\xFF\xFF
+} \xFF\x80\x00\x00
test binary-13.13 {Tcl_BinaryObjCmd: float overflow} littleEndian {
binary format f -3.402825e+38
-} \xFF\xFF\x7F\xFF
+} \x00\x00\x80\xFF
test binary-13.14 {Tcl_BinaryObjCmd: float underflow} bigEndian {
binary format f -3.402825e-100
} \x80\x00\x00\x00
@@ -537,6 +537,18 @@ test binary-13.19 {Tcl_BinaryObjCmd: format} littleEndian {
set a {1.6 3.4}
binary format f1 $a
} \xCD\xCC\xCC\x3F
+test binary-13.20 {Tcl_BinaryObjCmd: format float Inf} bigEndian {
+ binary format f Inf
+} \x7F\x80\x00\x00
+test binary-13.21 {Tcl_BinaryObjCmd: format float Inf} littleEndian {
+ binary format f Inf
+} \x00\x00\x80\x7F
+test binary-13.22 {Tcl_BinaryObjCmd: format float -Inf} bigEndian {
+ binary format f -Inf
+} \xFF\x80\x00\x00
+test binary-13.23 {Tcl_BinaryObjCmd: format float -Inf} littleEndian {
+ binary format f -Inf
+} \x00\x00\x80\xFF
test binary-14.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
binary format d
@@ -1975,10 +1987,10 @@ test binary-53.11 {Tcl_BinaryObjCmd: format} {} {
} \xCD\xCC\xCC\x3F\x9A\x99\x59\x40
test binary-53.12 {Tcl_BinaryObjCmd: float overflow} {} {
binary format R -3.402825e+38
-} \xFF\x7F\xFF\xFF
+} \xFF\x80\x00\x00
test binary-53.13 {Tcl_BinaryObjCmd: float overflow} {} {
binary format r -3.402825e+38
-} \xFF\xFF\x7F\xFF
+} \x00\x00\x80\xFF
test binary-53.14 {Tcl_BinaryObjCmd: float underflow} {} {
binary format R -3.402825e-100
} \x80\x00\x00\x00
@@ -2000,6 +2012,39 @@ test binary-53.19 {Tcl_BinaryObjCmd: format} {} {
set a {1.6 3.4}
binary format r1 $a
} \xCD\xCC\xCC\x3F
+test binary-53.20 {Tcl_BinaryObjCmd: float Inf} {} {
+ binary format R Inf
+} \x7f\x80\x00\x00
+test binary-53.21 {Tcl_BinaryObjCmd: float Inf} {} {
+ binary format r Inf
+} \x00\x00\x80\x7f
+test binary-53.22 {Binary float Inf round trip} -body {
+ binary scan [binary format R Inf] R inf
+ binary scan [binary format R -Inf] R inf_
+ list $inf $inf_
+} -result {Inf -Inf}
+test binary-53.23 {Binary float round to FLT_MAX} -body {
+ binary scan [binary format H* 7f7fffff] R fltmax
+ binary scan [binary format H* 47effffff0000000] Q round_to_fltmax
+ binary scan [binary format R $round_to_fltmax] R fltmax1
+ expr {$fltmax eq $fltmax1}
+} -result 1
+test binary-53.24 {Binary float round to -FLT_MAX} -body {
+ binary scan [binary format H* ff7fffff] R fltmax
+ binary scan [binary format H* c7effffff0000000] Q round_to_fltmax
+ binary scan [binary format R $round_to_fltmax] R fltmax1
+ expr {$fltmax eq $fltmax1}
+} -result 1
+test binary-53.25 {Binary float round to Inf} -body {
+ binary scan [binary format H* 47effffff0000001] Q round_to_inf
+ binary scan [binary format R $round_to_inf] R inf1
+ expr {$inf1 eq Inf}
+} -result 1
+test binary-53.26 {Binary float round to -Inf} -body {
+ binary scan [binary format H* c7effffff0000001] Q round_to_inf
+ binary scan [binary format R $round_to_inf] R inf1
+ expr {$inf1 eq -Inf}
+} -result 1
# scan t (s)
test binary-54.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
@@ -2396,11 +2441,27 @@ test binary-62.4 {infinity} ieeeFloatingPoint {
format 0x%016lx $w
} 0xfff0000000000000
test binary-62.5 {infinity} ieeeFloatingPoint {
- binary scan [binary format w 0x7ff0000000000000] q d
+ binary scan [binary format w 0x7FF0000000000000] q d
set d
} Inf
test binary-62.6 {infinity} ieeeFloatingPoint {
- binary scan [binary format w 0xfff0000000000000] q d
+ binary scan [binary format w 0xFFF0000000000000] q d
+ set d
+} -Inf
+test binary-62.7 {infinity} ieeeFloatingPoint {
+ binary scan [binary format r Inf] iu i
+ format 0x%08x $i
+} 0x7f800000
+test binary-62.8 {infinity} ieeeFloatingPoint {
+ binary scan [binary format r -Inf] iu i
+ format 0x%08x $i
+} 0xff800000
+test binary-62.9 {infinity} ieeeFloatingPoint {
+ binary scan [binary format i 0x7F800000] r d
+ set d
+} Inf
+test binary-62.10 {infinity} ieeeFloatingPoint {
+ binary scan [binary format i 0xFF800000] r d
set d
} -Inf
@@ -2408,19 +2469,19 @@ test binary-62.6 {infinity} ieeeFloatingPoint {
test binary-63.1 {NaN} ieeeFloatingPoint {
binary scan [binary format q NaN] w w
- format 0x%016lx [expr {$w & 0xfff3ffffffffffff}]
+ format 0x%016lx [expr {$w & 0xFFF3FFFFFFFFFFFF}]
} 0x7ff0000000000000
test binary-63.2 {NaN} ieeeFloatingPoint {
binary scan [binary format q -NaN] w w
- format 0x%016lx [expr {$w & 0xfff3ffffffffffff}]
+ format 0x%016lx [expr {$w & 0xFFF3FFFFFFFFFFFF}]
} 0xfff0000000000000
test binary-63.3 {NaN} ieeeFloatingPoint {
binary scan [binary format q NaN(3123456789aBc)] w w
- format 0x%016lx [expr {$w & 0xfff3ffffffffffff}]
+ format 0x%016lx [expr {$w & 0xFFF3FFFFFFFFFFFF}]
} 0x7ff3123456789abc
test binary-63.4 {NaN} ieeeFloatingPoint {
binary scan [binary format q {NaN( 3123456789aBc)}] w w
- format 0x%016lx [expr {$w & 0xfff3ffffffffffff}]
+ format 0x%016lx [expr {$w & 0xFFF3FFFFFFFFFFFF}]
} 0x7ff3123456789abc
# Make sure TclParseNumber() rejects invalid nan-hex formats [Bug 3402540]