summaryrefslogtreecommitdiffstats
path: root/vendor/math/bigfloat.man
diff options
context:
space:
mode:
authorOmar Rizwan <omar@omar.website>2022-12-05 07:14:51 +0000
committerOmar Rizwan <omar@omar.website>2022-12-05 07:14:51 +0000
commit07fc041d7bc0793318dd31ebef6ab2da9bcb3fe2 (patch)
tree202d978bd50fd5dd4c3cce5c690ea3dedb0e62bf /vendor/math/bigfloat.man
parentWebSocket server (diff)
downloadfolk-07fc041d7bc0793318dd31ebef6ab2da9bcb3fe2.tar.gz
folk-07fc041d7bc0793318dd31ebef6ab2da9bcb3fe2.zip
Vendor tcllib linear algebra
Diffstat (limited to 'vendor/math/bigfloat.man')
-rw-r--r--vendor/math/bigfloat.man433
1 files changed, 433 insertions, 0 deletions
diff --git a/vendor/math/bigfloat.man b/vendor/math/bigfloat.man
new file mode 100644
index 00000000..34fe0e21
--- /dev/null
+++ b/vendor/math/bigfloat.man
@@ -0,0 +1,433 @@
+[vset VERSION 2.0.4]
+[manpage_begin math::bigfloat n [vset VERSION]]
+[keywords computations]
+[keywords floating-point]
+[keywords interval]
+[keywords math]
+[keywords multiprecision]
+[keywords tcl]
+[copyright {2004-2008, by Stephane Arnold <stephanearnold at yahoo dot fr>}]
+[moddesc {Tcl Math Library}]
+[titledesc {Arbitrary precision floating-point numbers}]
+[category Mathematics]
+[require Tcl 8.5]
+[require math::bigfloat [opt [vset VERSION]]]
+
+[description]
+
+The bigfloat package provides arbitrary precision floating-point math
+capabilities to the Tcl language. It is designed to work with Tcl 8.5,
+but for Tcl 8.4 is provided an earlier version of this package.
+See [sectref "WHAT ABOUT TCL 8.4 ?"] for more explanations.
+By convention, we will talk about the numbers treated in this library as :
+[list_begin itemized]
+[item]BigFloat for floating-point numbers of arbitrary length.
+[item]integers for arbitrary length signed integers, just as basic integers since Tcl 8.5.
+[list_end]
+Each BigFloat is an interval, namely [lb][emph "m-d, m+d"][rb],
+where [emph m] is the mantissa and [emph d] the uncertainty, representing the
+limitation of that number's precision.
+This is why we call such mathematics [emph "interval computations"].
+Just take an example in physics : when you measure a temperature, not all
+digits you read are [emph significant]. Sometimes you just cannot trust all digits - not to mention if doubles (f.p. numbers) can handle all these digits.
+BigFloat can handle this problem - trusting the digits you get - plus the ability to store numbers with an arbitrary precision.
+
+BigFloats are internally represented at Tcl lists: this
+package provides a set of procedures operating against
+the internal representation in order to :
+[list_begin itemized]
+[item]
+perform math operations on BigFloats and (optionnaly) with integers.
+
+[item]
+convert BigFloats from their internal representations to strings, and vice versa.
+
+[list_end]
+
+[section "INTRODUCTION"]
+[list_begin definitions]
+
+[call [cmd fromstr] [arg number] [opt [arg trailingZeros]]]
+Converts [emph number] into a BigFloat. Its precision
+is at least the number of digits provided by [emph number].
+If the [arg number] contains only digits and eventually a minus sign, it is considered as
+an integer. Subsequently, no conversion is done at all.
+[para]
+[arg trailingZeros] - the number of zeros to append at the end of the floating-point number
+to get more precision. It cannot be applied to an integer.
+
+[example_begin]
+# x and y are BigFloats : the first string contained a dot, and the second an e sign
+set x [lb]fromstr -1.000000[rb]
+set y [lb]fromstr 2000e30[rb]
+# let's see how we get integers
+set t 20000000000000
+# the old way (package 1.2) is still supported for backwards compatibility :
+set m [lb]fromstr 10000000000[rb]
+# but we do not need fromstr for integers anymore
+set n -39
+# t, m and n are integers
+[example_end]
+[para]
+The [emph number]'s last digit is considered by the procedure to be true at +/-1,
+For example, 1.00 is the interval [lb]0.99, 1.01[rb],
+and 0.43 the interval [lb]0.42, 0.44[rb].
+The Pi constant may be approximated by the number "3.1415".
+This string could be considered as the interval [lb]3.1414 , 3.1416[rb] by [cmd fromstr].
+So, when you mean 1.0 as a double, you may have to write 1.000000 to get enough precision.
+To learn more about this subject, see [sectref PRECISION].
+[para]
+For example :
+[example_begin]
+set x [lb]fromstr 1.0000000000[rb]
+# the next line does the same, but smarter
+set y [lb]fromstr 1. 10[rb]
+[example_end]
+
+[call [cmd tostr] [opt [option -nosci]] [arg number]]
+Returns a string form of a BigFloat, in which all digits are exacts.
+[emph "All exact digits"] means a rounding may occur, for example to zero,
+if the uncertainty interval does not clearly show the true digits.
+[emph number] may be an integer, causing the command to return exactly the input argument.
+With the [option -nosci] option, the number returned is never shown in scientific
+notation, i.e. not like '3.4523e+5' but like '345230.'.
+[example_begin]
+puts [lb]tostr [lb]fromstr 0.99999[rb][rb] ;# 1.0000
+puts [lb]tostr [lb]fromstr 1.00001[rb][rb] ;# 1.0000
+puts [lb]tostr [lb]fromstr 0.002[rb][rb] ;# 0.e-2
+[example_end]
+See [sectref PRECISION] for that matter.
+
+See also [cmd iszero] for how to detect zeros, which is useful when performing a division.
+
+[call [cmd fromdouble] [arg double] [opt [arg decimals]]]
+
+Converts a double (a simple floating-point value) to a BigFloat, with
+exactly [arg decimals] digits. Without the [arg decimals] argument,
+it behaves like [cmd fromstr].
+Here, the only important feature you might care of is the ability
+to create BigFloats with a fixed number of [arg decimals].
+
+[example_begin]
+tostr [lb]fromstr 1.111 4[rb]
+# returns : 1.111000 (3 zeros)
+tostr [lb]fromdouble 1.111 4[rb]
+# returns : 1.111
+[example_end]
+
+[call [cmd todouble] [arg number]]
+Returns a double, that may be used in [emph expr],
+from a BigFloat.
+
+[call [cmd isInt] [arg number]]
+Returns 1 if [emph number] is an integer, 0 otherwise.
+
+[call [cmd isFloat] [arg number]]
+Returns 1 if [emph number] is a BigFloat, 0 otherwise.
+
+[call [cmd int2float] [arg integer] [opt [arg decimals]]]
+Converts an integer to a BigFloat with [emph decimals] trailing zeros.
+The default, and minimal, number of [emph decimals] is 1.
+When converting back to string, one decimal is lost:
+[example_begin]
+set n 10
+set x [lb]int2float $n[rb]; # like fromstr 10.0
+puts [lb]tostr $x[rb]; # prints "10."
+set x [lb]int2float $n 3[rb]; # like fromstr 10.000
+puts [lb]tostr $x[rb]; # prints "10.00"
+[example_end]
+
+[list_end]
+
+[section "ARITHMETICS"]
+[list_begin definitions]
+
+[call [cmd add] [arg x] [arg y]]
+[call [cmd sub] [arg x] [arg y]]
+[call [cmd mul] [arg x] [arg y]]
+Return the sum, difference and product of [emph x] by [emph y].
+[arg x] - may be either a BigFloat or an integer
+[arg y] - may be either a BigFloat or an integer
+When both are integers, these commands behave like [cmd expr].
+
+[call [cmd div] [arg x] [arg y]]
+[call [cmd mod] [arg x] [arg y]]
+Return the quotient and the rest of [emph x] divided by [emph y].
+Each argument ([emph x] and [emph y]) can be either a BigFloat or an integer,
+but you cannot divide an integer by a BigFloat
+Divide by zero throws an error.
+
+[call [cmd abs] [arg x]]
+Returns the absolute value of [emph x]
+
+[call [cmd opp] [arg x]]
+Returns the opposite of [emph x]
+
+[call [cmd pow] [arg x] [arg n]]
+Returns [emph x] taken to the [emph n]th power.
+It only works if [emph n] is an integer.
+[emph x] might be a BigFloat or an integer.
+
+[list_end]
+
+[section COMPARISONS]
+[list_begin definitions]
+[call [cmd iszero] [arg x]]
+
+Returns 1 if [emph x] is :
+[list_begin itemized]
+[item]a BigFloat close enough to zero to raise "divide by zero".
+[item]the integer 0.
+[list_end]
+See here how numbers that are close to zero are converted to strings:
+[example_begin]
+tostr [lb]fromstr 0.001[rb] ; # -> 0.e-2
+tostr [lb]fromstr 0.000000[rb] ; # -> 0.e-5
+tostr [lb]fromstr -0.000001[rb] ; # -> 0.e-5
+tostr [lb]fromstr 0.0[rb] ; # -> 0.
+tostr [lb]fromstr 0.002[rb] ; # -> 0.e-2
+
+set a [lb]fromstr 0.002[rb] ; # uncertainty interval : 0.001, 0.003
+tostr $a ; # 0.e-2
+iszero $a ; # false
+
+set a [lb]fromstr 0.001[rb] ; # uncertainty interval : 0.000, 0.002
+tostr $a ; # 0.e-2
+iszero $a ; # true
+[example_end]
+
+[call [cmd equal] [arg x] [arg y]]
+
+Returns 1 if [emph x] and [emph y] are equal, 0 elsewhere.
+
+[call [cmd compare] [arg x] [arg y]]
+
+Returns 0 if both BigFloat arguments are equal,
+1 if [emph x] is greater than [emph y],
+and -1 if [emph x] is lower than [emph y].
+You would not be able to compare an integer to a BigFloat :
+the operands should be both BigFloats, or both integers.
+
+[list_end]
+
+[section ANALYSIS]
+[list_begin definitions]
+[call [cmd sqrt] [arg x]]
+[call [cmd log] [arg x]]
+[call [cmd exp] [arg x]]
+[call [cmd cos] [arg x]]
+[call [cmd sin] [arg x]]
+[call [cmd tan] [arg x]]
+[call [cmd cotan] [arg x]]
+[call [cmd acos] [arg x]]
+[call [cmd asin] [arg x]]
+[call [cmd atan] [arg x]]
+[call [cmd cosh] [arg x]]
+[call [cmd sinh] [arg x]]
+[call [cmd tanh] [arg x]]
+
+The above functions return, respectively, the following :
+square root, logarithm, exponential, cosine, sine,
+tangent, cotangent, arc cosine, arc sine, arc tangent, hyperbolic
+cosine, hyperbolic sine, hyperbolic tangent, of a BigFloat named [emph x].
+
+[call [cmd pi] [arg n]]
+Returns a BigFloat representing the Pi constant with [emph n] digits after the dot.
+[emph n] is a positive integer.
+
+[call [cmd rad2deg] [arg radians]]
+[call [cmd deg2rad] [arg degrees]]
+[arg radians] - angle expressed in radians (BigFloat)
+[para]
+[arg degrees] - angle expressed in degrees (BigFloat)
+[para]
+Convert an angle from radians to degrees, and [emph "vice versa"].
+
+[list_end]
+
+[section ROUNDING]
+[list_begin definitions]
+[call [cmd round] [arg x]]
+[call [cmd ceil] [arg x]]
+[call [cmd floor] [arg x]]
+
+The above functions return the [emph x] BigFloat,
+rounded like with the same mathematical function in [emph expr],
+and returns it as an integer.
+[list_end]
+
+[section PRECISION]
+
+How do conversions work with precision ?
+
+[list_begin itemized]
+[item] When a BigFloat is converted from string, the internal representation
+holds its uncertainty as 1 at the level of the last digit.
+[item] During computations, the uncertainty of each result
+is internally computed the closest to the reality, thus saving the memory used.
+[item] When converting back to string, the digits that are printed
+are not subject to uncertainty. However, some rounding is done, as not doing so
+causes severe problems.
+[list_end]
+Uncertainties are kept in the internal representation of the number ;
+it is recommended to use [cmd tostr] only for outputting data (on the screen or in a file),
+and NEVER call [cmd fromstr] with the result of [cmd tostr].
+It is better to always keep operands in their internal representation.
+Due to the internals of this library, the uncertainty interval may be slightly
+wider than expected, but this should not cause false digits.
+[para]
+
+Now you may ask this question : What precision am I going to get
+after calling add, sub, mul or div?
+First you set a number from the string representation and,
+by the way, its uncertainty is set:
+[example_begin]
+set a [lb]fromstr 1.230[rb]
+# $a belongs to [lb]1.229, 1.231[rb]
+set a [lb]fromstr 1.000[rb]
+# $a belongs to [lb]0.999, 1.001[rb]
+# $a has a relative uncertainty of 0.1% : 0.001(the uncertainty)/1.000(the medium value)
+[example_end]
+The uncertainty of the sum, or the difference, of two numbers, is the sum
+of their respective uncertainties.
+
+[example_begin]
+set a [lb]fromstr 1.230[rb]
+set b [lb]fromstr 2.340[rb]
+set sum [lb]add $a $b[rb][rb]
+# the result is : [lb]3.568, 3.572[rb] (the last digit is known with an uncertainty of 2)
+tostr $sum ; # 3.57
+[example_end]
+But when, for example, we add or substract an integer to a BigFloat,
+the relative uncertainty of the result is unchanged. So it is desirable
+not to convert integers to BigFloats:
+
+[example_begin]
+set a [lb]fromstr 0.999999999[rb]
+# now something dangerous
+set b [lb]fromstr 2.000[rb]
+# the result has only 3 digits
+tostr [lb]add $a $b[rb]
+
+# how to keep precision at its maximum
+puts [lb]tostr [lb]add $a 2[rb][rb]
+[example_end]
+[para]
+
+For multiplication and division, the relative uncertainties of the product
+or the quotient, is the sum of the relative uncertainties of the operands.
+Take care of division by zero : check each divider with [cmd iszero].
+
+[example_begin]
+set num [lb]fromstr 4.00[rb]
+set denom [lb]fromstr 0.01[rb]
+
+puts [lb]iszero $denom[rb];# true
+set quotient [lb]div $num $denom[rb];# error : divide by zero
+
+# opposites of our operands
+puts [lb]compare $num [lb]opp $num[rb][rb]; # 1
+puts [lb]compare $denom [lb]opp $denom[rb][rb]; # 0 !!!
+# No suprise ! 0 and its opposite are the same...
+[example_end]
+
+Effects of the precision of a number considered equal to zero
+to the cos function:
+[example_begin]
+puts [lb]tostr [lb]cos [lb]fromstr 0. 10[rb][rb][rb]; # -> 1.000000000
+puts [lb]tostr [lb]cos [lb]fromstr 0. 5[rb][rb][rb]; # -> 1.0000
+puts [lb]tostr [lb]cos [lb]fromstr 0e-10[rb][rb][rb]; # -> 1.000000000
+puts [lb]tostr [lb]cos [lb]fromstr 1e-10[rb][rb][rb]; # -> 1.000000000
+[example_end]
+
+BigFloats with different internal representations may be converted
+to the same string.
+
+[para]
+
+For most analysis functions (cosine, square root, logarithm, etc.), determining the precision
+of the result is difficult.
+It seems however that in many cases, the loss of precision in the result
+is of one or two digits.
+There are some exceptions : for example,
+[example_begin]
+tostr [lb]exp [lb]fromstr 100.0 10[rb][rb]
+# returns : 2.688117142e+43 which has only 10 digits of precision, although the entry
+# has 14 digits of precision.
+[example_end]
+
+[section "WHAT ABOUT TCL 8.4 ?"]
+If your setup do not provide Tcl 8.5 but supports 8.4, the package can still be loaded,
+switching back to [emph math::bigfloat] 1.2. Indeed, an important function introduced in Tcl 8.5
+is required - the ability to handle bignums, that we can do with [cmd expr].
+Before 8.5, this ability was provided by several packages,
+including the pure-Tcl [emph math::bignum] package provided by [emph tcllib].
+In this case, all you need to know, is that arguments to the commands explained here,
+are expected to be in their internal representation.
+So even with integers, you will need to call [cmd fromstr]
+and [cmd tostr] in order to convert them between string and internal representations.
+[example_begin]
+#
+# with Tcl 8.5
+# ============
+set a [lb]pi 20[rb]
+# round returns an integer and 'everything is a string' applies to integers
+# whatever big they are
+puts [lb]round [lb]mul $a 10000000000[rb][rb]
+#
+# the same with Tcl 8.4
+# =====================
+set a [lb]pi 20[rb]
+# bignums (arbitrary length integers) need a conversion hook
+set b [lb]fromstr 10000000000[rb]
+# round returns a bignum:
+# before printing it, we need to convert it with 'tostr'
+puts [lb]tostr [lb]round [lb]mul $a $b[rb][rb][rb]
+[example_end]
+[section "NAMESPACES AND OTHER PACKAGES"]
+We have not yet discussed about namespaces
+because we assumed that you had imported public commands into the global namespace,
+like this:
+[example_begin]
+namespace import ::math::bigfloat::*
+[example_end]
+If you matter much about avoiding names conflicts,
+I considere it should be resolved by the following :
+[example_begin]
+package require math::bigfloat
+# beware: namespace ensembles are not available in Tcl 8.4
+namespace eval ::math::bigfloat {namespace ensemble create -command ::bigfloat}
+# from now, the bigfloat command takes as subcommands all original math::bigfloat::* commands
+set a [lb]bigfloat sub [lb]bigfloat fromstr 2.000[rb] [lb]bigfloat fromstr 0.530[rb][rb]
+puts [lb]bigfloat tostr $a[rb]
+[example_end]
+[section "EXAMPLES"]
+Guess what happens when you are doing some astronomy. Here is an example :
+[example_begin]
+# convert acurrate angles with a millisecond-rated accuracy
+proc degree-angle {degrees minutes seconds milliseconds} {
+ set result 0
+ set div 1
+ foreach factor {1 1000 60 60} var [lb]list $milliseconds $seconds $minutes $degrees[rb] {
+ # we convert each entry var into milliseconds
+ set div [lb]expr {$div*$factor}[rb]
+ incr result [lb]expr {$var*$div}[rb]
+ }
+ return [lb]div [lb]int2float $result[rb] $div[rb]
+}
+# load the package
+package require math::bigfloat
+namespace import ::math::bigfloat::*
+# work with angles : a standard formula for navigation (taking bearings)
+set angle1 [lb]deg2rad [lb]degree-angle 20 30 40 0[rb][rb]
+set angle2 [lb]deg2rad [lb]degree-angle 21 0 50 500[rb][rb]
+set opposite3 [lb]deg2rad [lb]degree-angle 51 0 50 500[rb][rb]
+set sinProduct [lb]mul [lb]sin $angle1[rb] [lb]sin $angle2[rb][rb]
+set cosProduct [lb]mul [lb]cos $angle1[rb] [lb]cos $angle2[rb][rb]
+set angle3 [lb]asin [lb]add [lb]mul $sinProduct [lb]cos $opposite3[rb][rb] $cosProduct[rb][rb]
+puts "angle3 : [lb]tostr [lb]rad2deg $angle3[rb][rb]"
+[example_end]
+
+[vset CATEGORY {math :: bignum :: float}]
+[include ../common-text/feedback.inc]
+[manpage_end]