Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch tip-521 Excluding Merge-Ins
This is equivalent to a diff from 09c6338b2f to c58f52a94c
2019-06-16
| ||
09:42 | TIP 521: Float classification functions check-in: d465e9717d user: dkf tags: core-8-branch | |
2019-06-15
| ||
21:24 | A neater way to write it that doesn't depend on detecting a specfic compiler version. For now. Closed-Leaf check-in: c58f52a94c user: dkf tags: tip-521 | |
21:03 | Try to work around MSVC6's lack of fpclassify()... check-in: 35debdf339 user: dkf tags: tip-521 | |
2019-06-10
| ||
20:02 | merge more expr doc tweaks check-in: 6047e60fec user: dkf tags: core-8-branch | |
19:42 | merge 8.7 check-in: 4feba7477a user: dgp tags: tip-521 | |
19:24 | merge 8.7 check-in: f8d415a72b user: dgp tags: trunk | |
19:09 | merge 8.7 check-in: b81e8ad1c0 user: dgp tags: tip-461 | |
19:09 | more formatting check-in: 09c6338b2f user: dgp tags: core-8-branch | |
18:58 | Doc formatting and advice about double substitution in expressions. check-in: ccffc2575c user: dgp tags: core-8-branch | |
Changes to doc/expr.n.
︙ | ︙ | |||
447 448 449 450 451 452 453 | .SH "SEE ALSO" array(n), for(n), if(n), mathfunc(n), mathop(n), namespace(n), proc(n), string(n), Tcl(n), while(n) .SH KEYWORDS arithmetic, boolean, compare, expression, fuzzy comparison .SH COPYRIGHT .nf | | | | | 447 448 449 450 451 452 453 454 455 456 457 458 459 460 | .SH "SEE ALSO" array(n), for(n), if(n), mathfunc(n), mathop(n), namespace(n), proc(n), string(n), Tcl(n), while(n) .SH KEYWORDS arithmetic, boolean, compare, expression, fuzzy comparison .SH COPYRIGHT .nf Copyright \(co 1993 The Regents of the University of California. Copyright \(co 1994-2000 Sun Microsystems Incorporated. Copyright \(co 2005 by Kevin B. Kenny <[email protected]>. All rights reserved. .fi '\" Local Variables: '\" mode: nroff '\" End: |
Added doc/fpclassify.n.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | '\" '\" Copyright (c) 2018 by Kevin B. Kenny <[email protected]>. All rights reserved '\" Copyright (c) 2019 by Donal Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH fpclassify n 8.7 Tcl "Tcl Float Classifier" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME fpclassify \- Floating point number classification of Tcl values .SH SYNOPSIS package require \fBTcl 8.7\fR .sp \fBfpclassify \fIvalue\fR .BE .SH DESCRIPTION The \fBfpclassify\fR command takes a floating point number, \fIvalue\fR, and returns one of the following strings that describe it: .TP \fBzero\fR . \fIvalue\fR is a floating point zero. .TP \fBsubnormal\fR . \fIvalue\fR is the result of a gradual underflow. .TP \fBnormal\fR . \fIvalue\fR is an ordinary floating-point number (not zero, subnormal, infinite, nor NaN). .TP \fBinfinite\fR . \fIvalue\fR is a floating-point infinity. .TP \fBnan\fR . \fIvalue\fR is Not-a-Number. .PP The \fBfpclassify\fR command throws an error if value is not a floating-point value and cannot be converted to one. .SH EXAMPLE .PP This shows how to check whether the result of a computation is numerically safe or not. (Note however that it does not guard against numerical errors; just against representational problems.) .PP .CS set value [command-that-computes-a-value] switch [\fBfpclassify\fR $value] { normal - zero { puts "Result is $value" } infinite { puts "Result is infinite" } subnormal { puts "Result is $value - WARNING! precision lost" } nan { puts "Computation completely failed" } } .CE .SH "SEE ALSO" expr(n), mathfunc(n) .SH KEYWORDS floating point .SH STANDARDS This command depends on the \fBfpclassify\fR() C macro conforming to .QW "ISO C99" (i.e., to ISO/IEC 9899:1999). .SH COPYRIGHT .nf Copyright \(co 2018 by Kevin B. Kenny <[email protected]>. All rights reserved .fi '\" Local Variables: '\" mode: nroff '\" End: |
Changes to doc/mathfunc.n.
︙ | ︙ | |||
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | \fB::tcl::mathfunc::floor\fR \fIarg\fR .br \fB::tcl::mathfunc::fmod\fR \fIx\fR \fIy\fR .br \fB::tcl::mathfunc::hypot\fR \fIx\fR \fIy\fR .br \fB::tcl::mathfunc::int\fR \fIarg\fR .br \fB::tcl::mathfunc::isqrt\fR \fIarg\fR .br \fB::tcl::mathfunc::log\fR \fIarg\fR .br \fB::tcl::mathfunc::log10\fR \fIarg\fR .br \fB::tcl::mathfunc::max\fR \fIarg\fR ?\fIarg\fR ...? .br | > > > > > > > > > > > > > > > > | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | \fB::tcl::mathfunc::floor\fR \fIarg\fR .br \fB::tcl::mathfunc::fmod\fR \fIx\fR \fIy\fR .br \fB::tcl::mathfunc::hypot\fR \fIx\fR \fIy\fR .br \fB::tcl::mathfunc::int\fR \fIarg\fR .br .VS "8.7, TIP 521" \fB::tcl::mathfunc::isfinite\fR \fIarg\fR .br \fB::tcl::mathfunc::isinf\fR \fIarg\fR .br \fB::tcl::mathfunc::isnan\fR \fIarg\fR .br \fB::tcl::mathfunc::isnormal\fR \fIarg\fR .VE "8.7, TIP 521" .br \fB::tcl::mathfunc::isqrt\fR \fIarg\fR .br .VS "8.7, TIP 521" \fB::tcl::mathfunc::issubnormal\fR \fIarg\fR .br \fB::tcl::mathfunc::isunordered\fR \fIx y\fR .VE "8.7, TIP 521" .br \fB::tcl::mathfunc::log\fR \fIarg\fR .br \fB::tcl::mathfunc::log10\fR \fIarg\fR .br \fB::tcl::mathfunc::max\fR \fIarg\fR ?\fIarg\fR ...? .br |
︙ | ︙ | |||
88 89 90 91 92 93 94 | namespace \fB::tcl::mathfunc\fR; these functions are also available for code apart from \fBexpr\fR, by invoking the given commands directly. .PP Tcl supports the following mathematical functions in expressions, all of which work solely with floating-point numbers unless otherwise noted: .DS | | > > | | | | | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | namespace \fB::tcl::mathfunc\fR; these functions are also available for code apart from \fBexpr\fR, by invoking the given commands directly. .PP Tcl supports the following mathematical functions in expressions, all of which work solely with floating-point numbers unless otherwise noted: .DS .ta 3.2c 6.4c 9.6c \fBabs\fR \fBacos\fR \fBasin\fR \fBatan\fR \fBatan2\fR \fBbool\fR \fBceil\fR \fBcos\fR \fBcosh\fR \fBdouble\fR \fBentier\fR \fBexp\fR \fBfloor\fR \fBfmod\fR \fBhypot\fR \fBint\fR \fBisfinite\fR \fBisinf\fR \fBisnan\fR \fBisnormal\fR \fBisqrt\fR \fBissubnormal\fR \fBisunordered\fR \fBlog\fR \fBlog10\fR \fBmax\fR \fBmin\fR \fBpow\fR \fBrand\fR \fBround\fR \fBsin\fR \fBsinh\fR \fBsqrt\fR \fBsrand\fR \fBtan\fR \fBtanh\fR \fBwide\fR .DE .PP In addition to these predefined functions, applications may define additional functions by using \fBproc\fR (or any other method, such as \fBinterp alias\fR or \fBTcl_CreateObjCommand\fR) to define new commands in the \fBtcl::mathfunc\fR namespace. In addition, an obsolete interface named \fBTcl_CreateMathFunc\fR() is available to |
︙ | ︙ | |||
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | . The argument may be any numeric value. The integer part of \fIarg\fR is determined, and then the low order bits of that integer value up to the machine word size are returned as an integer value. For reference, the number of bytes in the machine word are stored in the \fBwordSize\fR element of the \fBtcl_platform\fR array. .TP \fBisqrt \fIarg\fR . Computes the integer part of the square root of \fIarg\fR. \fIArg\fR must be a positive value, either an integer or a floating point number. Unlike \fBsqrt\fR, which is limited to the precision of a floating point number, \fIisqrt\fR will return a result of arbitrary precision. .TP \fBlog \fIarg\fR . Returns the natural logarithm of \fIarg\fR. \fIArg\fR must be a positive value. .TP \fBlog10 \fIarg\fR | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | . The argument may be any numeric value. The integer part of \fIarg\fR is determined, and then the low order bits of that integer value up to the machine word size are returned as an integer value. For reference, the number of bytes in the machine word are stored in the \fBwordSize\fR element of the \fBtcl_platform\fR array. .TP \fBisfinite \fIarg\fR .VS "8.7, TIP 521" Returns 1 if the floating-point number \fIarg\fR is finite. That is, if it is zero, subnormal, or normal. Returns 0 if the number is infinite or NaN. Throws an error if \fIarg\fR cannot be promoted to a floating-point value. .VE "8.7, TIP 521" .TP \fBisinf \fIarg\fR .VS "8.7, TIP 521" Returns 1 if the floating-point number \fIarg\fR is infinite. Returns 0 if the number is finite or NaN. Throws an error if \fIarg\fR cannot be promoted to a floating-point value. .VE "8.7, TIP 521" .TP \fBisnan \fIarg\fR .VS "8.7, TIP 521" Returns 1 if the floating-point number \fIarg\fR is Not-a-Number. Returns 0 if the number is finite or infinite. Throws an error if \fIarg\fR cannot be promoted to a floating-point value. .VE "8.7, TIP 521" .TP \fBisnormal \fIarg\fR .VS "8.7, TIP 521" Returns 1 if the floating-point number \fIarg\fR is normal. Returns 0 if the number is zero, subnormal, infinite or NaN. Throws an error if \fIarg\fR cannot be promoted to a floating-point value. .VE "8.7, TIP 521" .TP \fBisqrt \fIarg\fR . Computes the integer part of the square root of \fIarg\fR. \fIArg\fR must be a positive value, either an integer or a floating point number. Unlike \fBsqrt\fR, which is limited to the precision of a floating point number, \fIisqrt\fR will return a result of arbitrary precision. .TP \fBissubnormal \fIarg\fR .VS "8.7, TIP 521" Returns 1 if the floating-point number \fIarg\fR is subnormal, i.e., the result of gradual underflow. Returns 0 if the number is zero, normal, infinite or NaN. Throws an error if \fIarg\fR cannot be promoted to a floating-point value. .VE "8.7, TIP 521" .TP \fBisunordered \fIx y\fR .VS "8.7, TIP 521" Returns 1 if \fIx\fR and \fIy\fR cannot be compared for ordering, that is, if either one is NaN. Returns 0 if both values can be ordered, that is, if they are both chosen from among the set of zero, subnormal, normal and infinite values. Throws an error if either \fIx\fR or \fIy\fR cannot be promoted to a floating-point value. .VE "8.7, TIP 521" .TP \fBlog \fIarg\fR . Returns the natural logarithm of \fIarg\fR. \fIArg\fR must be a positive value. .TP \fBlog10 \fIarg\fR |
︙ | ︙ | |||
288 289 290 291 292 293 294 | .TP \fBwide \fIarg\fR . The argument may be any numeric value. The integer part of \fIarg\fR is determined, and then the low order 64 bits of that integer value are returned as an integer value. .SH "SEE ALSO" | | | | | | 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 | .TP \fBwide \fIarg\fR . The argument may be any numeric value. The integer part of \fIarg\fR is determined, and then the low order 64 bits of that integer value are returned as an integer value. .SH "SEE ALSO" expr(n), fpclassify(n), mathop(n), namespace(n) .SH "COPYRIGHT" .nf Copyright \(co 1993 The Regents of the University of California. Copyright \(co 1994-2000 Sun Microsystems Incorporated. Copyright \(co 2005, 2006 by Kevin B. Kenny <[email protected]>. .fi '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: |
Changes to generic/tclBasic.c.
︙ | ︙ | |||
19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #include "tclInt.h" #include "tclOOInt.h" #include "tclCompile.h" #include "tommath.h" #include <math.h> #include <assert.h> #define INTERP_STACK_INITIAL_SIZE 2000 #define CORO_STACK_INITIAL_SIZE 200 /* * Determine whether we're using IEEE floating point */ | > > > | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #include "tclInt.h" #include "tclOOInt.h" #include "tclCompile.h" #include "tommath.h" #include <math.h> #include <assert.h> #ifndef fpclassify /* Older MSVC */ #include <float.h> #endif /* !fpclassify */ #define INTERP_STACK_INITIAL_SIZE 2000 #define CORO_STACK_INITIAL_SIZE 200 /* * Determine whether we're using IEEE floating point */ |
︙ | ︙ | |||
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | static Tcl_ObjCmdProc ExprBinaryFunc; static Tcl_ObjCmdProc ExprBoolFunc; static Tcl_ObjCmdProc ExprCeilFunc; static Tcl_ObjCmdProc ExprDoubleFunc; static Tcl_ObjCmdProc ExprFloorFunc; static Tcl_ObjCmdProc ExprIntFunc; static Tcl_ObjCmdProc ExprIsqrtFunc; static Tcl_ObjCmdProc ExprMaxFunc; static Tcl_ObjCmdProc ExprMinFunc; static Tcl_ObjCmdProc ExprRandFunc; static Tcl_ObjCmdProc ExprRoundFunc; static Tcl_ObjCmdProc ExprSqrtFunc; static Tcl_ObjCmdProc ExprSrandFunc; static Tcl_ObjCmdProc ExprUnaryFunc; static Tcl_ObjCmdProc ExprWideFunc; static void MathFuncWrongNumArgs(Tcl_Interp *interp, int expected, int actual, Tcl_Obj *const *objv); static Tcl_NRPostProc NRCoroutineCallerCallback; static Tcl_NRPostProc NRCoroutineExitCallback; static Tcl_NRPostProc NRCommand; #if !defined(TCL_NO_DEPRECATED) | > > > > > > > | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | static Tcl_ObjCmdProc ExprBinaryFunc; static Tcl_ObjCmdProc ExprBoolFunc; static Tcl_ObjCmdProc ExprCeilFunc; static Tcl_ObjCmdProc ExprDoubleFunc; static Tcl_ObjCmdProc ExprFloorFunc; static Tcl_ObjCmdProc ExprIntFunc; static Tcl_ObjCmdProc ExprIsqrtFunc; static Tcl_ObjCmdProc ExprIsFiniteFunc; static Tcl_ObjCmdProc ExprIsInfinityFunc; static Tcl_ObjCmdProc ExprIsNaNFunc; static Tcl_ObjCmdProc ExprIsNormalFunc; static Tcl_ObjCmdProc ExprIsSubnormalFunc; static Tcl_ObjCmdProc ExprIsUnorderedFunc; static Tcl_ObjCmdProc ExprMaxFunc; static Tcl_ObjCmdProc ExprMinFunc; static Tcl_ObjCmdProc ExprRandFunc; static Tcl_ObjCmdProc ExprRoundFunc; static Tcl_ObjCmdProc ExprSqrtFunc; static Tcl_ObjCmdProc ExprSrandFunc; static Tcl_ObjCmdProc ExprUnaryFunc; static Tcl_ObjCmdProc ExprWideFunc; static Tcl_ObjCmdProc FloatClassifyObjCmd; static void MathFuncWrongNumArgs(Tcl_Interp *interp, int expected, int actual, Tcl_Obj *const *objv); static Tcl_NRPostProc NRCoroutineCallerCallback; static Tcl_NRPostProc NRCoroutineExitCallback; static Tcl_NRPostProc NRCommand; #if !defined(TCL_NO_DEPRECATED) |
︙ | ︙ | |||
252 253 254 255 256 257 258 259 260 261 262 263 264 265 | {"coroutine", NULL, NULL, TclNRCoroutineObjCmd, CMD_IS_SAFE}, {"error", Tcl_ErrorObjCmd, TclCompileErrorCmd, NULL, CMD_IS_SAFE}, {"eval", Tcl_EvalObjCmd, NULL, TclNREvalObjCmd, CMD_IS_SAFE}, {"expr", Tcl_ExprObjCmd, TclCompileExprCmd, TclNRExprObjCmd, CMD_IS_SAFE}, {"for", Tcl_ForObjCmd, TclCompileForCmd, TclNRForObjCmd, CMD_IS_SAFE}, {"foreach", Tcl_ForeachObjCmd, TclCompileForeachCmd, TclNRForeachCmd, CMD_IS_SAFE}, {"format", Tcl_FormatObjCmd, TclCompileFormatCmd, NULL, CMD_IS_SAFE}, {"global", Tcl_GlobalObjCmd, TclCompileGlobalCmd, NULL, CMD_IS_SAFE}, {"if", Tcl_IfObjCmd, TclCompileIfCmd, TclNRIfObjCmd, CMD_IS_SAFE}, {"incr", Tcl_IncrObjCmd, TclCompileIncrCmd, NULL, CMD_IS_SAFE}, {"join", Tcl_JoinObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lappend", Tcl_LappendObjCmd, TclCompileLappendCmd, NULL, CMD_IS_SAFE}, {"lassign", Tcl_LassignObjCmd, TclCompileLassignCmd, NULL, CMD_IS_SAFE}, {"lindex", Tcl_LindexObjCmd, TclCompileLindexCmd, NULL, CMD_IS_SAFE}, | > | 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 | {"coroutine", NULL, NULL, TclNRCoroutineObjCmd, CMD_IS_SAFE}, {"error", Tcl_ErrorObjCmd, TclCompileErrorCmd, NULL, CMD_IS_SAFE}, {"eval", Tcl_EvalObjCmd, NULL, TclNREvalObjCmd, CMD_IS_SAFE}, {"expr", Tcl_ExprObjCmd, TclCompileExprCmd, TclNRExprObjCmd, CMD_IS_SAFE}, {"for", Tcl_ForObjCmd, TclCompileForCmd, TclNRForObjCmd, CMD_IS_SAFE}, {"foreach", Tcl_ForeachObjCmd, TclCompileForeachCmd, TclNRForeachCmd, CMD_IS_SAFE}, {"format", Tcl_FormatObjCmd, TclCompileFormatCmd, NULL, CMD_IS_SAFE}, {"fpclassify", FloatClassifyObjCmd, NULL, NULL, CMD_IS_SAFE}, {"global", Tcl_GlobalObjCmd, TclCompileGlobalCmd, NULL, CMD_IS_SAFE}, {"if", Tcl_IfObjCmd, TclCompileIfCmd, TclNRIfObjCmd, CMD_IS_SAFE}, {"incr", Tcl_IncrObjCmd, TclCompileIncrCmd, NULL, CMD_IS_SAFE}, {"join", Tcl_JoinObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lappend", Tcl_LappendObjCmd, TclCompileLappendCmd, NULL, CMD_IS_SAFE}, {"lassign", Tcl_LassignObjCmd, TclCompileLassignCmd, NULL, CMD_IS_SAFE}, {"lindex", Tcl_LindexObjCmd, TclCompileLindexCmd, NULL, CMD_IS_SAFE}, |
︙ | ︙ | |||
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 | { "double", ExprDoubleFunc, NULL }, { "entier", ExprIntFunc, NULL }, { "exp", ExprUnaryFunc, (ClientData) exp }, { "floor", ExprFloorFunc, NULL }, { "fmod", ExprBinaryFunc, (ClientData) fmod }, { "hypot", ExprBinaryFunc, (ClientData) hypot }, { "int", ExprIntFunc, NULL }, { "isqrt", ExprIsqrtFunc, NULL }, { "log", ExprUnaryFunc, (ClientData) log }, { "log10", ExprUnaryFunc, (ClientData) log10 }, { "max", ExprMaxFunc, NULL }, { "min", ExprMinFunc, NULL }, { "pow", ExprBinaryFunc, (ClientData) pow }, { "rand", ExprRandFunc, NULL }, { "round", ExprRoundFunc, NULL }, | > > > > > > | 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 | { "double", ExprDoubleFunc, NULL }, { "entier", ExprIntFunc, NULL }, { "exp", ExprUnaryFunc, (ClientData) exp }, { "floor", ExprFloorFunc, NULL }, { "fmod", ExprBinaryFunc, (ClientData) fmod }, { "hypot", ExprBinaryFunc, (ClientData) hypot }, { "int", ExprIntFunc, NULL }, { "isfinite", ExprIsFiniteFunc, NULL }, { "isinf", ExprIsInfinityFunc, NULL }, { "isnan", ExprIsNaNFunc, NULL }, { "isnormal", ExprIsNormalFunc, NULL }, { "isqrt", ExprIsqrtFunc, NULL }, { "issubnormal", ExprIsSubnormalFunc, NULL, }, { "isunordered", ExprIsUnorderedFunc, NULL, }, { "log", ExprUnaryFunc, (ClientData) log }, { "log10", ExprUnaryFunc, (ClientData) log10 }, { "max", ExprMaxFunc, NULL }, { "min", ExprMinFunc, NULL }, { "pow", ExprBinaryFunc, (ClientData) pow }, { "rand", ExprRandFunc, NULL }, { "round", ExprRoundFunc, NULL }, |
︙ | ︙ | |||
8275 8276 8277 8278 8279 8280 8281 8282 8283 8284 8285 8286 8287 8288 | * To avoid duplicating the random number generation code we simply clean * up our state and call the real random number function. That function * will always succeed. */ return ExprRandFunc(clientData, interp, 1, objv); } /* *---------------------------------------------------------------------- * * MathFuncWrongNumArgs -- * * Generate an error message when a math function presents the wrong | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 8292 8293 8294 8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 8309 8310 8311 8312 8313 8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332 8333 8334 8335 8336 8337 8338 8339 8340 8341 8342 8343 8344 8345 8346 8347 8348 8349 8350 8351 8352 8353 8354 8355 8356 8357 8358 8359 8360 8361 8362 8363 8364 8365 8366 8367 8368 8369 8370 8371 8372 8373 8374 8375 8376 8377 8378 8379 8380 8381 8382 8383 8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 8402 8403 8404 8405 8406 8407 8408 8409 8410 8411 8412 8413 8414 8415 8416 8417 8418 8419 8420 8421 8422 8423 8424 8425 8426 8427 8428 8429 8430 8431 8432 8433 8434 8435 8436 8437 8438 8439 8440 8441 8442 8443 8444 8445 8446 8447 8448 8449 8450 8451 8452 8453 8454 8455 8456 8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 8469 8470 8471 8472 8473 8474 8475 8476 8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 8518 8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530 8531 8532 8533 8534 8535 8536 8537 8538 8539 8540 8541 8542 8543 8544 8545 8546 8547 8548 8549 8550 8551 8552 8553 8554 8555 8556 8557 8558 8559 8560 8561 8562 8563 8564 8565 8566 8567 8568 8569 8570 8571 8572 8573 8574 8575 8576 8577 8578 8579 8580 8581 8582 8583 8584 8585 8586 8587 8588 8589 8590 8591 8592 8593 8594 8595 8596 8597 8598 8599 8600 8601 8602 8603 8604 8605 8606 8607 8608 8609 8610 8611 8612 8613 8614 | * To avoid duplicating the random number generation code we simply clean * up our state and call the real random number function. That function * will always succeed. */ return ExprRandFunc(clientData, interp, 1, objv); } /* *---------------------------------------------------------------------- * * Double Classification Functions -- * * This page contains the functions that implement all of the built-in * math functions for classifying IEEE doubles. * * These have to be a little bit careful while Tcl_GetDoubleFromObj() * rejects NaN values, which these functions *explicitly* accept. * * Results: * Each function returns TCL_OK if it succeeds and pushes an Tcl object * holding the result. If it fails it returns TCL_ERROR and leaves an * error message in the interpreter's result. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* * Older MSVC is supported by Tcl, but doesn't have fpclassify(). Of course. * But it does have _fpclass() which does almost the same job. * * This makes it conform to the C99 standard API, and just delegates to the * standard macro on platforms that do it correctly. */ static inline int ClassifyDouble( double d) { #ifdef fpclassify return fpclassify(d); #else /* !fpclassify */ #define FP_ZERO 0 #define FP_NORMAL 1 #define FP_SUBNORMAL 2 #define FP_INFINITE 3 #define FP_NAN 4 switch (_fpclass(d)) { case _FPCLASS_NZ: case _FPCLASS_PZ: return FP_ZERO; case _FPCLASS_NN: case _FPCLASS_PN: return FP_NORMAL; case _FPCLASS_ND: case _FPCLASS_PD: return FP_SUBNORMAL; case _FPCLASS_NINF: case _FPCLASS_PINF: return FP_INFINITE; default: Tcl_Panic("result of _fpclass() outside documented range!"); case _FPCLASS_QNAN: case _FPCLASS_SNAN: return FP_NAN; } #endif /* fpclassify */ } static int ExprIsFiniteFunc( ClientData ignored, Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; ClientData ptr; int type, result = 0; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; } type = ClassifyDouble(d); result = (type != FP_INFINITE && type != FP_NAN); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int ExprIsInfinityFunc( ClientData ignored, Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; ClientData ptr; int type, result = 0; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; } result = (ClassifyDouble(d) == FP_INFINITE); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int ExprIsNaNFunc( ClientData ignored, Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; ClientData ptr; int type, result = 1; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; } result = (ClassifyDouble(d) == FP_NAN); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int ExprIsNormalFunc( ClientData ignored, Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; ClientData ptr; int type, result = 0; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; } result = (ClassifyDouble(d) == FP_NORMAL); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int ExprIsSubnormalFunc( ClientData ignored, Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; ClientData ptr; int type, result = 0; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; } result = (ClassifyDouble(d) == FP_SUBNORMAL); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int ExprIsUnorderedFunc( ClientData ignored, Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; ClientData ptr; int type, result = 0; if (objc != 3) { MathFuncWrongNumArgs(interp, 3, objc, objv); return TCL_ERROR; } if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_NAN) { result = 1; } else { d = *((const double *) ptr); result = (ClassifyDouble(d) == FP_NAN); } if (TclGetNumberFromObj(interp, objv[2], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_NAN) { result |= 1; } else { d = *((const double *) ptr); result |= (ClassifyDouble(d) == FP_NAN); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int FloatClassifyObjCmd( ClientData ignored, Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; Tcl_Obj *objPtr; ClientData ptr; int type; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "floatValue"); return TCL_ERROR; } if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_NAN) { goto gotNaN; } else if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; } switch (ClassifyDouble(d)) { case FP_INFINITE: TclNewLiteralStringObj(objPtr, "infinite"); break; case FP_NAN: gotNaN: TclNewLiteralStringObj(objPtr, "nan"); break; case FP_NORMAL: TclNewLiteralStringObj(objPtr, "normal"); break; case FP_SUBNORMAL: TclNewLiteralStringObj(objPtr, "subnormal"); break; case FP_ZERO: TclNewLiteralStringObj(objPtr, "zero"); break; default: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unable to classify number: %f", d)); return TCL_ERROR; } Tcl_SetObjResult(interp, objPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * MathFuncWrongNumArgs -- * * Generate an error message when a math function presents the wrong |
︙ | ︙ |
Changes to tests/expr.test.
︙ | ︙ | |||
129 130 131 132 133 134 135 | global xxx set xxx "" 12days 1 1 1 set result [string length $xxx] unset xxx return $result } | | | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | global xxx set xxx "" 12days 1 1 1 set result [string length $xxx] unset xxx return $result } # start of tests catch {unset a b i x} test expr-1.1 {TclCompileExprCmd: no expression} { list [catch {expr } msg] $msg } {1 {wrong # args: should be "expr arg ?arg ...?"}} |
︙ | ︙ | |||
7158 7159 7160 7161 7162 7163 7164 | } { set a [list one two three] list [expr {$a eq {}}] [expr {$a < {}}] [expr {$a > {}}] [ string match {*no string representation*} [ ::tcl::unsupported::representation $a]] } {0 0 1 1} | > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > | > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > | > > | > | > > | 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 | } { set a [list one two three] list [expr {$a eq {}}] [expr {$a < {}}] [expr {$a > {}}] [ string match {*no string representation*} [ ::tcl::unsupported::representation $a]] } {0 0 1 1} foreach func {isfinite isinf isnan isnormal issubnormal} { test expr-53.1.$func {float classification: basic arg handling} -body { expr ${func}() } -returnCodes error -result "too few arguments for math function \"$func\"" test expr-53.2.$func {float classification: basic arg handling} -body { expr ${func}(1,2) } -returnCodes error -result "too many arguments for math function \"$func\"" test expr-53.3.$func {float classification: basic arg handling} -body { expr ${func}(true) } -returnCodes error -result {expected number but got "true"} test expr-53.4.$func {float classification: basic arg handling} -body { expr ${func}("gorp") } -returnCodes error -result {expected number but got "gorp"} test expr-53.5.$func {float classification: basic arg handling} -body { expr ${func}(1.0) } -match glob -result * test expr-53.6.$func {float classification: basic arg handling} -body { expr ${func}(0x123) } -match glob -result * } test expr-54.0 {float classification: isfinite} {expr {isfinite(1.0)}} 1 test expr-54.1 {float classification: isfinite} {expr {isfinite(-1.0)}} 1 test expr-54.2 {float classification: isfinite} {expr {isfinite(0.0)}} 1 test expr-54.3 {float classification: isfinite} {expr {isfinite(-0.0)}} 1 test expr-54.4 {float classification: isfinite} {expr {isfinite(1/Inf)}} 1 test expr-54.5 {float classification: isfinite} {expr {isfinite(-1/Inf)}} 1 test expr-54.6 {float classification: isfinite} {expr {isfinite(1e-314)}} 1 test expr-54.7 {float classification: isfinite} {expr {isfinite(inf)}} 0 test expr-54.8 {float classification: isfinite} {expr {isfinite(-inf)}} 0 test expr-54.9 {float classification: isfinite} {expr {isfinite(NaN)}} 0 test expr-55.0 {float classification: isinf} {expr {isinf(1.0)}} 0 test expr-55.1 {float classification: isinf} {expr {isinf(-1.0)}} 0 test expr-55.2 {float classification: isinf} {expr {isinf(0.0)}} 0 test expr-55.3 {float classification: isinf} {expr {isinf(-0.0)}} 0 test expr-55.4 {float classification: isinf} {expr {isinf(1/Inf)}} 0 test expr-55.5 {float classification: isinf} {expr {isinf(-1/Inf)}} 0 test expr-55.6 {float classification: isinf} {expr {isinf(1e-314)}} 0 test expr-55.7 {float classification: isinf} {expr {isinf(inf)}} 1 test expr-55.8 {float classification: isinf} {expr {isinf(-inf)}} 1 test expr-55.9 {float classification: isinf} {expr {isinf(NaN)}} 0 test expr-56.0 {float classification: isnan} {expr {isnan(1.0)}} 0 test expr-56.1 {float classification: isnan} {expr {isnan(-1.0)}} 0 test expr-56.2 {float classification: isnan} {expr {isnan(0.0)}} 0 test expr-56.3 {float classification: isnan} {expr {isnan(-0.0)}} 0 test expr-56.4 {float classification: isnan} {expr {isnan(1/Inf)}} 0 test expr-56.5 {float classification: isnan} {expr {isnan(-1/Inf)}} 0 test expr-56.6 {float classification: isnan} {expr {isnan(1e-314)}} 0 test expr-56.7 {float classification: isnan} {expr {isnan(inf)}} 0 test expr-56.8 {float classification: isnan} {expr {isnan(-inf)}} 0 test expr-56.9 {float classification: isnan} {expr {isnan(NaN)}} 1 test expr-57.0 {float classification: isnormal} {expr {isnormal(1.0)}} 1 test expr-57.1 {float classification: isnormal} {expr {isnormal(-1.0)}} 1 test expr-57.2 {float classification: isnormal} {expr {isnormal(0.0)}} 0 test expr-57.3 {float classification: isnormal} {expr {isnormal(-0.0)}} 0 test expr-57.4 {float classification: isnormal} {expr {isnormal(1/Inf)}} 0 test expr-57.5 {float classification: isnormal} {expr {isnormal(-1/Inf)}} 0 test expr-57.6 {float classification: isnormal} {expr {isnormal(1e-314)}} 0 test expr-57.7 {float classification: isnormal} {expr {isnormal(inf)}} 0 test expr-57.8 {float classification: isnormal} {expr {isnormal(-inf)}} 0 test expr-57.9 {float classification: isnormal} {expr {isnormal(NaN)}} 0 test expr-58.0 {float classification: issubnormal} {expr {issubnormal(1.0)}} 0 test expr-58.1 {float classification: issubnormal} {expr {issubnormal(-1.0)}} 0 test expr-58.2 {float classification: issubnormal} {expr {issubnormal(0.0)}} 0 test expr-58.3 {float classification: issubnormal} {expr {issubnormal(-0.0)}} 0 test expr-58.4 {float classification: issubnormal} {expr {issubnormal(1/Inf)}} 0 test expr-58.5 {float classification: issubnormal} {expr {issubnormal(-1/Inf)}} 0 test expr-58.6 {float classification: issubnormal} {expr {issubnormal(1e-314)}} 1 test expr-58.7 {float classification: issubnormal} {expr {issubnormal(inf)}} 0 test expr-58.8 {float classification: issubnormal} {expr {issubnormal(-inf)}} 0 test expr-58.9 {float classification: issubnormal} {expr {issubnormal(NaN)}} 0 test expr-59.0 {float classification: fpclassify} {fpclassify 1.0} normal test expr-59.1 {float classification: fpclassify} {fpclassify -1.0} normal test expr-59.2 {float classification: fpclassify} {fpclassify 0.0} zero test expr-59.3 {float classification: fpclassify} {fpclassify -0.0} zero test expr-59.4 {float classification: fpclassify} {fpclassify [expr 1/Inf]} zero test expr-59.5 {float classification: fpclassify} {fpclassify [expr -1/Inf]} zero test expr-59.6 {float classification: fpclassify} {fpclassify 1e-314} subnormal test expr-59.7 {float classification: fpclassify} {fpclassify inf} infinite test expr-59.8 {float classification: fpclassify} {fpclassify -inf} infinite test expr-59.9 {float classification: fpclassify} {fpclassify NaN} nan test expr-59.10 {float classification: fpclassify} -returnCodes error -body { fpclassify } -result {wrong # args: should be "fpclassify floatValue"} test expr-59.11 {float classification: fpclassify} -returnCodes error -body { fpclassify a b } -result {wrong # args: should be "fpclassify floatValue"} test expr-59.12 {float classification: fpclassify} -returnCodes error -body { fpclassify gorp } -result {expected number but got "gorp"} test expr-60.1 {float classification: basic arg handling} -body { expr isunordered() } -returnCodes error -result {too few arguments for math function "isunordered"} test expr-60.2 {float classification: basic arg handling} -body { expr isunordered(1) } -returnCodes error -result {too few arguments for math function "isunordered"} test expr-60.3 {float classification: basic arg handling} -body { expr {isunordered(1, 2, 3)} } -returnCodes error -result {too many arguments for math function "isunordered"} test expr-60.4 {float classification: basic arg handling} -body { expr {isunordered(true, 1.0)} } -returnCodes error -result {expected number but got "true"} test expr-60.5 {float classification: basic arg handling} -body { expr {isunordered("gorp", 1.0)} } -returnCodes error -result {expected number but got "gorp"} test expr-60.6 {float classification: basic arg handling} -body { expr {isunordered(0x123, 1.0)} } -match glob -result * test expr-60.7 {float classification: basic arg handling} -body { expr {isunordered(1.0, true)} } -returnCodes error -result {expected number but got "true"} test expr-60.8 {float classification: basic arg handling} -body { expr {isunordered(1.0, "gorp")} } -returnCodes error -result {expected number but got "gorp"} test expr-60.9 {float classification: basic arg handling} -body { expr {isunordered(1.0, 0x123)} } -match glob -result * # Big matrix of comparisons, but it's just a binary isinf() set values {1.0 -1.0 0.0 -0.0 1e-314 Inf -Inf NaN} set results {0 0 0 0 0 0 0 1} set ctr 0 foreach v1 $values r1 $results { foreach v2 $values r2 $results { test expr-61.[incr ctr] "float classification: isunordered($v1,$v2)" { expr {isunordered($v1, $v2)} } [expr {$r1 || $r2}] } } unset -nocomplain values results ctr # cleanup unset -nocomplain a unset -nocomplain min unset -nocomplain max ::tcltest::cleanupTests return # Local Variables: # mode: tcl # End: |
Changes to tests/info.test.
︙ | ︙ | |||
651 652 653 654 655 656 657 | catch {namespace delete x} } -body { namespace eval x info vars foo } -cleanup { namespace delete x } -result {} | | | 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 | catch {namespace delete x} } -body { namespace eval x info vars foo } -cleanup { namespace delete x } -result {} set functions {abs acos asin atan atan2 bool ceil cos cosh double entier exp floor fmod hypot int isfinite isinf isnan isnormal isqrt issubnormal isunordered log log10 max min pow rand round sin sinh sqrt srand tan tanh wide} # Check whether the extra testing functions are defined... if {!([catch {expr T1()} msg] && ($msg eq {invalid command name "tcl::mathfunc::T1"}))} { set functions "T1 T2 T3 $functions" ;# A lazy way of prepending! } test info-20.1 {info functions option} {info functions sin} sin test info-20.2 {info functions option} {lsort [info functions]} $functions test info-20.3 {info functions option} { |
︙ | ︙ |