Skip to content

Commit

Permalink
New plugin tcl/math.
Browse files Browse the repository at this point in the history
Performs various mathematical tricks in Tcl.
  • Loading branch information
Roberto Reale committed Nov 11, 2016
1 parent 6e72f04 commit bbac146
Show file tree
Hide file tree
Showing 2 changed files with 276 additions and 0 deletions.
Binary file added plugins/tcl/.math.swp
Binary file not shown.
276 changes: 276 additions & 0 deletions plugins/tcl/math
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
#!/bin/bash


################################################################################
#
# | | | |
# |---.,---.,---.|---.| ,---.|--- ,---.
# | |,---|`---.| || |---'| `---.
# `---'`---^`---'` '`---'`---'`---'`---'
#
#
# Bashlets -- A modular extensible toolbox for Bash
#
# Copyright (c) 2014-6 Roberto Reale
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
################################################################################

#
# calculate (an approximation of) PI/2 with the aid of Wallis' product
#

#@method
function bashlets_tcl_math_wallis()
{
local iterations=${1:-1000000}
local tcl_text

tcl_text="
proc wallis {{n 1000000}} {
set value 1.0
set i 1
while {\$i < \$n} {
set i2 [expr {(\$i*2)**2}]
set value [expr {\$value * \$i2 / (\$i2-1)}]
incr i
}
return \$value
}
puts [expr {2 * [wallis $iterations]}]
"

tclsh <<< "$tcl_text"
}


#
# approximate the value of e using the power series expansion
#

#@method
function bashlets_tcl_math_e_power_series()
{
local iterations=${1:-20}
local tcl_text

tcl_text="
proc approx_e {{n 20}} {
set value 1
set factorial 1
set i 1
while {\$i <= \$n} {
set factorial [expr {\$factorial * \$i}]
set value [expr {\$value + 1.0/\$factorial}]
incr i
}
return \$value
}
puts [approx_e $iterations]
"

tclsh <<< "$tcl_text"
}


#
# recursively calculate Chebyshev polynomials
#
# (see http://en.wikipedia.org/wiki/Chebyshev_polynomials)
#

function __bashlets_tcl_math_chebyshev()
{
local kind=${1:-1}
local degree=${2:-10}
local tcl_text

tcl_text="
# we need Tcl 8.5 for lrepeat to be defined
package require Tcl 8.5
proc min {x y} {
if {\$x <= \$y} {return \$x} {return \$y}
}
#
# NOTE: polynomials are represented as lists, e.g. the polynomial 2x^3 + 3x + 1
# is represented as [1, 3, 0, 2]
#
#
# trim out zero term of higher degrees, e.g. 0x^4 + x^3 + 1 => x^3 + 1
#
proc poly_trim {p} {
for {set i [expr {[llength \$p] - 1}]} {\$i >= 0} {set i [expr {\$i - 1}]} {
if {[lindex \$p \$i] == 0} {
set p [lreplace \$p end end]
} else {
break
}
}
return \$p
}
#
# add two polynomials
#
proc poly_add {p q} {
set m [min [llength \$p] [llength \$q]]
set sum [list]
for {set i 0} {\$i < \$m} {incr i} {
lappend sum [expr {[lindex \$p \$i] + [lindex \$q \$i]}]
}
if {[llength \$p] > [llength \$q]} {
for {set i \$m} {\$i < [llength \$p]} {incr i} {
lappend sum [lindex \$p \$i]
}
} elseif {[llength \$p] < [llength \$q]} {
for {set i \$m} {\$i < [llength \$q]} {incr i} {
lappend sum [lindex \$q \$i]
}
}
return [poly_trim \$sum]
}
#
# multiply two polynomials
#
proc poly_multiply {p q} {
set product [lrepeat [expr {[llength \$p] + [llength \$q] - 1}] 0]
for {set i 0} {\$i < [llength \$p]} {incr i} {
for {set j 0} {\$j < [llength \$q]} {incr j} {
set k [expr {\$i + \$j}]
set product [
lreplace \$product \$k \$k [
expr {
[lindex \$product \$k]
+
[expr {[lindex \$p \$i] * [lindex \$q \$j]}]
}
]
]
}
}
return [poly_trim \$product]
}
#
# Chebyshev polynomials of the first kind
#
# these are defined recursively as follows:
#
# T_0(x) = 1
# T_1(x) = x
# T_{n+1}(x) = 2xT_n(x) - T_{n-1}(x)
#
proc chebyshev1 {n} {
if {\$n <= 0} {
return [list 1]
} elseif {\$n == 1} {
return [list 0 1]
} else {
return [
poly_add [
poly_multiply [list 0 2] [chebyshev1 [expr {\$n - 1}]]
] [
poly_multiply [list -1] [chebyshev1 [expr {\$n - 2}]]
]
]
}
}
#
# Chebyshev polynomials of the second kind
#
# these are defined recursively as follows:
#
# U_0(x) = 1
# U_1(x) = 2x
# U_{n+1}(x) = 2xU_n(x) - U_{n-1}(x)
#
proc chebyshev2 {n} {
if {\$n <= 0} {
return [list 1]
} elseif {\$n == 1} {
return [list 0 2]
} else {
return [
poly_add [
poly_multiply [list 0 2] [chebyshev2 [expr {\$n - 1}]]
] [
poly_multiply [list -1] [chebyshev2 [expr {\$n - 2}]]
]
]
}
}
#
# generic high-level wrapper
#
proc chebyshev {kind n} {
if {\$kind == 1} {
return [chebyshev1 \$n]
} elseif {\$kind == 2} {
return [chebyshev2 \$n]
}
}
puts [chebyshev $kind $degree]
"

tclsh <<< "$tcl_text"
}

#@method
function bashlets_tcl_math_chebyshev1()
{
__bashlets_tcl_math_chebyshev 1 $1
}

#@method
function bashlets_tcl_math_chebyshev2()
{
__bashlets_tcl_math_chebyshev 2 $1
}


# Local variables:
# mode: shell-script
# sh-basic-offset: 4
# sh-indent-comment: t
# indent-tabs-mode: nil
# End:
# ex: ts=4 sw=4 et filetype=sh

0 comments on commit bbac146

Please sign in to comment.