;;; -*- Mode: LISP; Syntax: Common-lisp; Package: USER -*- ;;;; Combinatorial Algorithms ;;; reference ;;; William H. Press, Brian P. Flannery, Saul A. Teukolsky, William T. Vetterling ;;; Numerical Recipes in C, The Art of Scientific Computing ;;; Cambridge University Press, 1988 ;;; cf 178 ;;; (c) Copyright Gerald Roylance 1982, 1984, 1987, 1988 ;;; All Rights Reserved. ;;; This file may be distributed noncommercially provided ;;; that this notice is not removed. ;;; Bugs and Fixes ;;; (in-package "USER") (provide "COMBINATORICS") (eval-when (compile load eval) (require "MODULES") (module-require "GAMMA-FUNCTION")) (EXPORT '(FACTORIAL CHOOSE CATALAN-NUMBER BELL-NUMBER)) ;;;; Factorial Function ;;; The number of ways to arrange n objects ;;; The bignum version. ;;; 12! < 2^31 (proclaim '(ftype (function (fixnum) integer) factorial)) (defun factorial (n) (declare (fixnum n)) (do ((i 2 (1+ i)) (fact 1 (* fact i))) ((> i n) fact) (declare (fixnum i)) )) ;;;; The Logarithm of the Factorial ;;; A table to hold precomputed values ;;; (defvar dlog-factorial-table (make-array 100 :initial-element NIL)) ;;; A function to precompute the values of the table ;;; -- not used ;;; (defun dlog-factorial-table-precompute () (dotimes (i (array-dimension dlog-factorial-table 0)) (setf (aref dlog-factorial-table i) (if (<= i 1) 0.0d0 (log-gamma-function (+ (float i 1.0d0) 1.0d0)))))) ;;; Double Precision version of the factorial ;;; (defun dlog-factorial (n) (cond ((< n 0) (error "LOG-FACTORIAL")) ((<= n 1) 0.0d0) ((< n (array-dimension dlog-factorial-table 0)) (if (aref dlog-factorial-table n) (aref dlog-factorial-table n) (setf (aref dlog-factorial-table n) (log-gamma-function (+ (float n) 1.0d0))))) (t (log-gamma-function (+ (float n) 1.0d0))))) ;;; Single Precision mooches off of the double precision ;;; (the table will have all/most of the reasonable values) ;;; (defun log-factorial (n) (float (dlog-factorial n) 1.0)) ;;;; Floating Point Factorial (defvar dfactorial-table (let* ((n 100) (array (make-array n :element-type 'double-float :initial-element 1.0d0))) (do ((i 1 (1+ i))) ((>= i n) array) (setf (aref array i) (* i (aref array (- i 1))))))) (defun dfactorial (n) (cond ((< n 0) (error "DFACTORIAL")) ((< n (array-dimension dfactorial-table 0)) (aref dfactorial-table n)) (t (values (round (exp (dlog-factorial n))))))) (defun ffactorial (n) (float (dfactorial n) 1.0)) ;;;; A Generalization of Factorial ;;; \Gamma(x+1) = x \Gamma(x) ;;; for k (1 1 2 5 15 52 203 877 ...) ;;; Bell triangle ;;; 1 ;;; 1 2 ;;; 2 3 5 ;;; 5 7 10 15 ;;; 15 20 27 37 52 ;;; 52 67 87 114 151 203 ;;; 203 255 322 409 523 674 877 (defun bellr (row col) (cond ((and (= col 1) (= row 1)) 1) ((= col 1) (bellr (1- row) (1- row))) (t (+ (bellr (1- row) (1- col)) (bellr row (1- col)))))) (defun bell-number (n) (cond ((minusp n) (error "BELL-NUMBER: bad argument" n)) ((zerop n) 1) (t (bellr n n))))