Tk Library Source Code

Artifact [9890211853]
Login

Artifact 98902118535488704ea9da5e92b2182d46886c33:

Attachment "combinatorics.patch" to ticket [484850ffff] added by kennykb 2001-12-15 04:49:57.
Index: modules/math/combinatorics.tcl
===================================================================
RCS file: combinatorics.tcl
diff -N combinatorics.tcl
--- /dev/null	Thu May 24 22:33:05 2001
+++ combinatorics.tcl	Fri Dec 14 13:08:23 2001
@@ -0,0 +1,436 @@
+#----------------------------------------------------------------------
+#
+# math/combinatorics.tcl --
+#
+#	This file contains definitions of mathematical functions
+#	useful in combinatorial problems.  
+#
+# Copyright (c) 2001, by Kevin B. Kenny.  All rights reserved.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+# 
+# RCS: @(#) $Id: $
+#
+#----------------------------------------------------------------------
+
+package require Tcl 8.0
+
+namespace eval ::math {
+
+    # Commonly used combinatorial functions
+
+    namespace export ln_Gamma;		# Logarithm of the Gamma function
+    namespace export factorial;		# Factorial
+    namespace export choose;		# Binomial coefficient
+    namespace export Beta;		# Beta function
+
+}
+
+#----------------------------------------------------------------------
+#
+# ::math::initializeFactorial --
+#
+#	Initialize a table of factorials for small integer arguments.
+#
+# Parameters:
+#	None.
+#
+# Results:
+#	None.
+#
+# Side effects:
+#	The variable, ::math::factorialList, is initialized to hold
+#	a table of factorial n for 0 <= n <= 170.
+#
+# This procedure is called once when the 'factorial' procedure is
+# being loaded.
+#
+#----------------------------------------------------------------------
+
+proc ::math::initializeFactorial {} {
+
+    variable [namespace current]::factorialList
+
+    set factorialList [list 1]
+    set f 1
+    for { set i 1 } { $i < 171 } { incr i } {
+	if { $i > 12. } {
+	    set f [expr { $f * double($i)}]
+	} else {
+	    set f [expr { $f * $i }]
+	}
+	lappend factorialList $f
+    }
+
+}
+
+#----------------------------------------------------------------------
+#
+# ::math::initializePascal --
+#
+#	Precompute the first few rows of Pascal's triangle and store
+#	them in the variable ::math::pascal
+#
+# Parameters:
+#	None.
+#
+# Results:
+#	None.
+#
+# Side effects:
+#	::math::pascal is initialized to a flat list containing 
+#	the first 34 rows of Pascal's triangle.	 C(n,k) is to be found
+#	at [lindex $pascal $i] where i = n * ( n + 1 ) + k.  No attempt
+#	is made to exploit symmetry.
+#
+#----------------------------------------------------------------------
+
+proc ::math::initializePascal {} {
+
+    variable pascal
+
+    set pascal [list 1]
+    for { set n 1 } { $n < 34 } { incr n } {
+	lappend pascal 1
+	set l2 [list 1]
+	for { set k 1 } { $k < $n } { incr k } {
+	    set km1 [expr { $k - 1 }]
+	    set c [expr { [lindex $l $km1] + [lindex $l $k] }]
+	    lappend pascal $c
+	    lappend l2 $c
+	}
+	lappend pascal 1
+	lappend l2 1
+	set l $l2
+    }
+
+}
+
+#----------------------------------------------------------------------
+#
+# ::math::ln_Gamma --
+#
+#	Returns ln(Gamma(x)), where x >= 0
+#
+# Parameters:
+#	x - Argument to the Gamma function.
+#
+# Results:
+#	Returns the natural logarithm of Gamma(x).
+#
+# Side effects:
+#	None.
+#
+# Gamma(x) is defined as:
+#
+#		  +inf
+#		    _
+#		   |	x-1  -t
+#	Gamma(x)= _|   t    e	dt
+#
+#		   0
+#
+# The approximation used here is from Lanczos, SIAM J. Numerical Analysis,
+# series B, volume 1, p. 86.  For x > 1, the absolute error of the
+# result is claimed to be smaller than 5.5 * 10**-10 -- that is, the
+# resulting value of Gamma when exp( ln_Gamma( x ) ) is computed is
+# expected to be precise to better than nine significant figures.
+#
+#----------------------------------------------------------------------
+
+proc ::math::ln_Gamma { x } {
+
+    # Handle the common case of a real argument that's within the
+    # permissible range.
+
+    if { [string is double $x]
+	 && ( $x > 0 )
+	 && ( $x <= 2.5563481638716906e+305 )
+     } {
+	set x [expr { $x - 1.0 }]
+	set tmp [expr { $x + 5.5 }]
+	set tmp [ expr { ( $x + 0.5 ) * log( $tmp ) - $tmp }]
+	set ser 1.0
+	foreach cof {
+	    76.18009173 -86.50532033 24.01409822
+	    -1.231739516 .00120858003 -5.36382e-6
+	} {
+	    set x [expr { $x + 1.0 }]
+	    set ser [expr { $ser + $cof / $x }]
+	}
+	return [expr { $tmp + log( 2.50662827465 * $ser ) }]
+    } 
+
+    # Handle the error cases.
+
+    if { ![string is double $x] } {
+	return -code error [expectDouble $x]
+    }
+
+    if { $x <= 0.0 } {
+	set proc [lindex [info level 0] 0]
+	return -code error \
+	    -errorcode [list ARITH DOMAIN \
+			"argument to $proc must be positive"] \
+	    "argument to $proc must be positive"
+    }
+
+    return -code error \
+	-errorcode [list ARITH RANGE \
+		    "floating-point value too large to represent"] \
+	"floating-point value too large to represent"
+	
+}
+
+#----------------------------------------------------------------------
+#
+# math::factorial --
+#
+#	Returns the factorial of the argument x.
+#
+# Parameters:
+#	x -- Number whose factorial is to be computed.
+#
+# Results:
+#	Returns x!, the factorial of x.
+#
+# Side effects:
+#	None.
+#
+# For integer x, 0 <= x <= 12, an exact integer result is returned.
+#
+# For integer x, 13 <= x <= 21, an exact floating-point result is returned
+# on machines with IEEE floating point.
+#
+# For integer x, 22 <= x <= 170, the result is exact to 1 ULP.
+#
+# For real x, x >= 0, the result is approxumated by computing
+# Gamma(x+1) using the ::math::ln_Gamma function, and the result is
+# expected to be precise to better than nine significant figures.
+#
+# It is an error to present x <= -1 or x > 170, or a value of x that
+# is not numeric.
+#
+#----------------------------------------------------------------------
+
+proc ::math::factorial { x } {
+
+    variable [namespace current]::factorialList
+
+    # Common case: factorial of a small integer
+
+    if { [string is integer $x]
+	 && $x >= 0
+	 && $x <= [llength $factorialList] } {
+	return [lindex $factorialList $x]
+    } 
+
+    # Error case: not a number
+
+    if { ![string is double $x] } {
+	return -code error [expectDouble $x]
+    } 
+
+    # Error case: gamma in the left half plane
+
+    if { $x <= -1.0 } {
+	set proc [lindex [info level 0] 0]
+	set message "argument to $proc must be greater than -1.0"
+	return -code error -errorcode [list ARITH DOMAIN $message] $message
+    } 
+
+    # Error case - gamma fails
+
+    if { [catch { expr exp( [ln_Gamma [expr { $x + 1 }]] ) } result] } {
+	return -code error -errorcode $::errorCode $result
+    } 
+
+    # Success - computed factorial n as Gamma(n+1)
+
+    return $result
+
+}
+
+#----------------------------------------------------------------------
+#
+# ::math::choose --
+#
+#	Returns the binomial coefficient C(n,k) = n!/k!(n-k)!
+#
+# Parameters:
+#	n -- Number of objects in the sampling pool
+#	k -- Number of objects to be chosen.
+#
+# Results:
+#	Returns C(n,k).	 
+#
+# Side effects:
+#	None.
+#
+# Results are expected to be accurate to ten significant figures.
+# If both parameters are integers and the result fits in 32 bits, 
+# the result is rounded to an integer.
+#
+# Integer results are exact up to at least n = 34.
+# Floating point results are precise to better than nine significant 
+# figures.
+#
+#----------------------------------------------------------------------
+
+proc ::math::choose { n k } {
+
+    variable pascal
+
+    # Use a precomputed table for small integer args
+
+    if { [string is integer $n]
+	 && $n >= 0 && $n < 34
+	 && [string is integer $k]
+	 && $k >= 0 && $k <= $n } {
+
+	set i [expr { ( ( $n * ($n + 1) ) / 2 ) + $k }]
+
+	return [lindex $pascal $i]
+
+    }
+
+    # Test bogus arguments
+
+    if { ![string is double $n] } {
+	return -code error [expectDouble $n]
+    }
+    if { ![string is double $k] } {
+	return -code error [expectDouble $k]
+    }
+
+    # Forbid negative n
+
+    if { $n < 0. } {
+	set proc [lindex [info level 0] 0]
+	set msg "first argument to $proc must be non-negative"
+	return -code error -errorcode [list ARITH DOMAIN $msg] $msg
+    }
+
+    # Handle k out of range
+
+    if { [string is integer $k] && [string is integer $n]
+	 && ( $k < 0 || $k > $n ) } {
+	return 0
+    }
+
+    if { $k < 0. } {
+	set proc [lindex [info level 0] 0]
+	set msg "second argument to $proc must be non-negative,\
+                 or both must be integers"
+	return -code error -errorcode [list ARITH DOMAIN $msg] $msg
+    }
+
+    # Compute the logarithm of the desired binomial coefficient.
+
+    if { [catch { expr { [ln_Gamma [expr { $n + 1 }]]
+			 - [ln_Gamma [expr { $k + 1 }]]
+			 - [ln_Gamma [expr { $n - $k + 1 }]] } } r] } {
+	return -code error -errorcode $::errorCode $r
+    }
+
+    # Compute the binomial coefficient itself
+
+    if { [catch { expr { exp( $r ) } } r] } {
+	return -code error -errorcode $::errorCode $r
+    }
+
+    # Round to integer if both args are integers and the result fits
+
+    if { $r <= 2147483647.5 
+	       && [string is integer $n]
+	       && [string is integer $k] } {
+	return [expr { round( $r ) }]
+    }
+
+    return $r
+
+}
+
+#----------------------------------------------------------------------
+#
+# ::math::Beta --
+#
+#	Return the value of the Beta function of paramters z and w.
+#
+# Parameters:
+#	z, w : Two real parameters to the Beta function
+#
+# Results:
+#	Returns the value of the Beta function.
+#
+# Side effects:
+#	None.
+#
+# Beta( w, z ) is defined as:
+#
+#				  1_
+#				  |  (z-1)     (w-1)
+# Beta( w, z ) = Beta( z, w ) =	  | t	  (1-t)	     dt
+#				 _|
+#				  0
+#
+#	       = Gamma( z ) Gamma( w ) / Gamma( z + w )
+#
+# Results are returned as a floating point number precise to better
+# than nine significant figures for w, z > 1.
+#
+#----------------------------------------------------------------------
+
+proc ::math::Beta { z w } {
+
+    # Check form of both args so that domain check can be made
+
+    if { ![string is double $z] } {
+	return -code error [expectDouble $z]
+    }
+    if { ![string is double $w] } {
+	return -code error [expectDouble $w]
+    }
+
+    # Check sign of both args
+
+    if { $z <= 0.0 } {
+	set proc [lindex [info level 0] 0]
+	set msg "first argument to $proc must be positive"
+	return -code error -errorcode [list ARITH DOMAIN $msg] $msg
+    }
+    if { $w <= 0.0 } {
+	set proc [lindex [info level 0] 0]
+	set msg "second argument to $proc must be positive"
+	return -code error -errorcode [list ARITH DOMAIN $msg] $msg
+    }
+
+    # Compute beta using gamma function, keeping stack trace clean.
+
+    if { [catch { expr { exp( [ln_Gamma $z] + [ln_Gamma $w]
+			      - [ln_Gamma [ expr { $z + $w }]] ) } } beta] } {
+
+	return -code error -errorcode $::errorCode $beta
+
+    } 
+
+    return $beta
+
+}
+
+#----------------------------------------------------------------------
+#
+# Initialization of this file:
+#
+#	Initialize the precomputed tables of factorials and binomial
+#	coefficients.
+#
+#----------------------------------------------------------------------
+
+namespace eval ::math {
+    initializeFactorial
+    initializePascal
+}
+
+package provide math 1.1
Index: modules/math/combinatorics.test
===================================================================
RCS file: combinatorics.test
diff -N combinatorics.test
--- /dev/null	Thu May 24 22:33:05 2001
+++ combinatorics.test	Fri Dec 14 13:08:23 2001
@@ -0,0 +1,294 @@
+# Tests for combinatorics functions in math library  -*- tcl -*-
+#
+# This file contains a collection of tests for one or more of the Tcllib
+# procedures.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 2001 by Kevin B. Kenny
+# All rights reserved.
+#
+# RCS: @(#) $Id: math.test,v 1.7 2000/10/06 21:10:41 ericm Exp $
+
+if {[lsearch [namespace children] ::tcltest] == -1} {
+    package require tcltest
+    namespace import ::tcltest::*
+}
+
+source [file join [file dirname [info script]] math.tcl]
+source [file join [file dirname [info script]] combinatorics.tcl]
+
+package require math
+
+# Fake [lset] for Tcl releases that don't have it.  We need only
+# lset into a flat list.
+
+if { [string compare lset [info commands lset]] } {
+    proc K { x y } { set x }
+    proc lset { listVar index var } {
+	upvar 1 $listVar list
+	set list [lreplace [K $list [set list {}]] $index $index $var]
+    }
+}
+
+# Service procedure to develop the error message for "wrong # args"
+
+proc wrongNumArgs {name arglist count} {
+    set ver [info patchlevel]
+    # strip "a1", etc. designations
+    regsub {(a|b)[1-9]$} $ver {} ver
+    if {[package vcompare $ver 8.4] < 0} {
+	set arg [lindex $arglist $count]
+	set msg "no value given for parameter \"$arg\" to \"$name\""
+    } else {
+	set msg "wrong # args: should be \"$name $arglist\""
+    }
+    return $msg
+}
+
+test combinatorics-1.1 { math::ln_Gamma, wrong num args } {
+    catch { math::ln_Gamma } msg
+    set msg
+} [wrongNumArgs math::ln_Gamma x 0]
+
+test combinatorics-1.2 { math::ln_Gamma, main line code } {
+    set maxerror 0.
+    set f 1.
+    for { set i 1 } { $i < 171 } { set i $ip1 } {
+	set f [expr { $f * $i }]
+	set ip1 [expr { $i + 1 }]
+	set f2 [expr { exp( [math::ln_Gamma $ip1] ) }]
+	set error [expr { abs( $f2 - $f ) / $f }]
+	if { $error > $maxerror } {
+	    set maxerror $error
+	}
+    }
+    if { $maxerror > 5e-10 } {
+	error "max error of factorials computed using math::ln_Gamma\
+               specified to be 5e-10, was $maxerror"
+    }
+    concat
+} {}
+
+test combinatorics-1.3 { math::ln_Gamma, half integer args } {
+    set maxerror 0.
+    set z 0.5
+    set pi 3.1415926535897932
+    set g [expr { sqrt( $pi ) }]
+    while { $z < 170. } {
+	set g2 [expr { exp( [::math::ln_Gamma $z] ) }]
+	set error [expr { abs( $g2 - $g ) / $g }]
+	if { $error > $maxerror } {
+	    set maxerror $error
+	}
+	set g [expr { $g * $z }]
+	set z [expr { $z + 1. }]
+    }
+    if { $maxerror > 5e-10 } {
+	error "max error of half integer gamma computed using math::ln_Gamma\
+               specified to be 5e-10, was $maxerror"
+    }
+    concat
+} {}
+
+test combinatorics-1.4 { math::ln_Gamma, bogus arg } {
+    catch { math::ln_Gamma bogus } msg
+    set msg
+} {expected a floating-point number but found "bogus"}
+
+test combinatorics-1.5 { math::ln_Gamma, evaluate at pole } {
+    catch { math::ln_Gamma 0.0 } msg
+    list $msg $::errorCode
+} {{argument to math::ln_Gamma must be positive} {ARITH DOMAIN {argument to math::ln_Gamma must be positive}}}
+
+test combinatorics-1.6 { math::ln_Gamma, exponent overflow } {
+    catch { math::ln_Gamma 2.556348163871691e+305 } msg
+    list $msg $::errorCode
+} {{floating-point value too large to represent} {ARITH RANGE {floating-point value too large to represent}}}
+
+test combinatorics-2.1 { math::factorial, wrong num args } {
+    catch { math::factorial } msg
+    set msg
+} [wrongNumArgs math::factorial x 0]
+
+test combinatorics-2.2 { math::factorial 0 } {
+    math::factorial 0
+} 1
+
+test combinatorics-2.3 { math::factorial, main line } {
+    set maxerror 0.
+    set f 1.
+    for { set i 1 } { $i < 171 } { set i $ip1 } {
+	set f [expr { $f * $i }]
+	set ip1 [expr { $i + 1 }]
+	set f2 [math::factorial $i]
+	set error [expr { abs( $f2 - $f ) / $f }]
+	if { $error > $maxerror } {
+	    set maxerror $error
+	}
+    }
+    if { $maxerror > 1e-16 } {
+	error "max error of factorials computed using math::factorial\
+               specified to be 1e-16, was $maxerror"
+    }
+    concat
+} {}
+
+test combinatorics-2.4 { math::factorial, half integer args } {
+    set maxerror 0.
+    set z -0.5
+    set pi 3.1415926535897932
+    set g [expr { sqrt( $pi ) }]
+    while { $z < 169. } {
+	set g2 [math::factorial $z]
+	set error [expr { abs( $g2 - $g ) / $g }]
+	if { $error > $maxerror } {
+	    set maxerror $error
+	}
+	set z [expr { $z + 1. }]
+	set g [expr { $g * $z }]
+    }
+    if { $maxerror > 1e-9 } {
+	error "max error of half integer factorial\
+               specified to be 1e-9, was $maxerror"
+    }
+    concat
+} {}
+
+test combinatorics-2.5 { math::factorial, bogus arg } {
+    catch { math::factorial bogus } msg
+    set msg
+} {expected a floating-point number but found "bogus"}
+
+test combinatorics-2.6 { math::factorial, evaluate at pole } {
+    catch { math::factorial -1.0 } msg
+    list $msg $::errorCode
+} {{argument to math::factorial must be greater than -1.0} {ARITH DOMAIN {argument to math::factorial must be greater than -1.0}}}
+
+test combinatorics-2.7 { math::factorial, exponent overflow } {
+    catch { math::factorial 172 } msg
+    list $msg $::errorCode
+} {{floating-point value too large to represent} {ARITH OVERFLOW {floating-point value too large to represent}}}
+
+test combinatorics-3.1 { math::choose, wrong num args } {
+    catch { math::choose } msg
+    set msg
+} [wrongNumArgs math::choose {n k} 0]
+
+test combinatorics-3.2 { math::choose, wrong num args } {
+    catch { math::choose 1 } msg
+    set msg
+} [wrongNumArgs math::choose {n k} 1]
+
+test combinatorics-3.3 { math::choose, precomputed table and gamma evals } {
+    set maxError 0
+    set l {}
+    for { set n 0 } { $n < 100 } { incr n } {
+	lappend l 1.
+	for { set k [expr { $n - 1 }] } { $k > 0 } { set k $km1 } {
+	    set km1 [expr { $k - 1 }]
+	    set cnk [expr { [lindex $l $k] + [lindex $l $km1] }]
+	    lset l $k $cnk
+	    set ccnk [math::choose $n $k]
+	    set error [expr { abs( $ccnk - $cnk ) / $cnk }]
+	    if { $error > $maxError } {
+		set maxError $error
+	    }
+	}
+    }
+    if { $maxError > 5e-10 } {
+	error "max error in math::choose was $maxError, specified to be 5e-10"
+    }
+    concat
+} {}
+
+test combinatorics-3.4 { math::choose, bogus n } {
+    catch { math::choose bogus 0 } msg
+    set msg
+} {expected a floating-point number but found "bogus"}
+
+test combinatorics-3.5 { math::choose bogus k } {
+    catch { math::choose 0 bogus } msg
+    set msg
+} {expected a floating-point number but found "bogus"}
+
+test combinatorics-3.6 { match::choose negative n } {
+    catch { math::choose -1 0 } msg
+    list $msg $::errorCode
+} {{first argument to math::choose must be non-negative} {ARITH DOMAIN {first argument to math::choose must be non-negative}}}
+
+test combinatorics-3.7 { math::choose negative k } {
+    math::choose 17 -1
+} 0
+
+test combinatorics-3.8 { math::choose excess k } {
+    math::choose 17 18
+} 0
+
+test combinatorics-3.9 {math::choose negative fraction } {
+    catch { math::choose 17 -0.5 } msg
+    list $msg $::errorCode
+} {{second argument to math::choose must be non-negative, or both must be integers} {ARITH DOMAIN {second argument to math::choose must be non-negative, or both must be integers}}}
+
+test combinatorics-3.10 { math::choose big args } {
+    catch { math::choose 1500 750 } msg
+    list $msg $::errorCode
+} {{floating-point value too large to represent} {ARITH OVERFLOW {floating-point value too large to represent}}}
+
+test combinatorics-4.1 { math::Beta, wrong num args } {
+    catch { math::Beta } msg
+    set msg
+} [wrongNumArgs math::Beta {z w} 0]
+
+test combinatorics-4.2 { math::Beta, wrong num args } {
+    catch { math::Beta 1 } msg
+    set msg
+} [wrongNumArgs math::Beta {z w} 1]
+
+test combinatorics-4.3 { math::Beta, bogus z } {
+    catch { math::Beta bogus 1 } msg
+    set msg
+} {expected a floating-point number but found "bogus"}
+
+test combinatorics-4.4 { math::Beta, bogus w } {
+    catch { math::Beta 1 bogus } msg
+    set msg
+} {expected a floating-point number but found "bogus"}
+
+test combinatorics-4.5 { math::Beta, negative z } {
+    catch { math::Beta 0 1 } msg
+    list $msg $::errorCode
+} {{first argument to math::Beta must be positive} {ARITH DOMAIN {first argument to math::Beta must be positive}}}
+
+test combinatorics-4.6 { math::Beta, negative w } {
+    catch { math::Beta 1 0 } msg
+    list $msg $::errorCode
+} {{second argument to math::Beta must be positive} {ARITH DOMAIN {second argument to math::Beta must be positive}}}
+
+test combinatorics-4.7 { math::Beta, test with Pascal } {
+    set maxError 0
+    set l {}
+    for { set n 0 } { $n < 100 } { incr n } {
+	lappend l 1.
+	for { set k [expr { $n - 1 }] } { $k > 0 } { set k $km1 } {
+	    set km1 [expr { $k - 1 }]
+	    set cnk [expr { [lindex $l $k] + [lindex $l $km1] }]
+	    lset l $k $cnk
+	    set w [expr { $k + 1 }]
+	    set z [expr { $n - $k + 1 }]
+	    set beta [expr { 1.0 / $cnk / ( $z + $w - 1 )}]
+	    set cbeta [math::Beta $z $w]
+	    set error [expr { abs( $cbeta - $beta ) / $beta }]
+	    if { $error > $maxError } {
+		set maxError $error
+	    }
+	}
+    }
+    if { $maxError > 5e-10 } {
+	error "max error in math::Beta was $maxError, specified to be 5e-10"
+    }
+    concat
+} {}
+
+    
+::tcltest::cleanupTests
+
Index: modules/math/math.tcl
===================================================================
RCS file: /cvsroot/tcllib/tcllib/modules/math/math.tcl,v
retrieving revision 1.9
diff -u -r1.9 math.tcl
--- modules/math/math.tcl	2001/08/02 16:38:06	1.9
+++ modules/math/math.tcl	2001/12/14 21:08:23
@@ -335,4 +335,26 @@
     set sum
 }
 
+#----------------------------------------------------------------------
+#
+# ::math::expectDouble --
+#
+#	Format an error message that an argument was expected to be
+#	double and wasn't
+#
+# Parameters:
+#	arg -- Misformatted argument
+#
+# Results:
+#	Returns an appropriate error message
+#
+# Side effects:
+#	None.
+#
+#----------------------------------------------------------------------
+
+proc ::math::expectDouble { arg } {
+    return [format "expected a floating-point number but found \"%.50s\"" $arg]
+}
+
 package provide math 1.1
Index: modules/math/pkgIndex.tcl
===================================================================
RCS file: /cvsroot/tcllib/tcllib/modules/math/pkgIndex.tcl,v
retrieving revision 1.4
diff -u -r1.4 pkgIndex.tcl
--- modules/math/pkgIndex.tcl	2001/12/12 18:42:16	1.4
+++ modules/math/pkgIndex.tcl	2001/12/14 21:08:23
@@ -9,6 +9,5 @@
 # full path name of this file's directory.
 
 if {![package vsatisfies [package provide Tcl] 8.2]} {return}
-package ifneeded math 1.1 [list source [file join $dir math.tcl]]
+package ifneeded math 1.1 [list source [file join $dir combinatorics.tcl]]\n[list source [file join $dir math.tcl]]
 package ifneeded math::geometry 1.0 [list source [file join $dir geometry.tcl]]
-