Documentation style changes

Fixes after merge weirdness from pull request (specifically, removed `bfrandom' from "mpfr.rkt" again)
Removed dependence of math/flonum on math/bigfloat (better build parallelization)
Changed `divides?' to return #f when its first argument is 0
Made return type of `quadratic-character' more precise
Made argument types more permissive:
 * second argument to `solve-chinese'
 * second argument to `next-primes'
 * second argument to `prev-primes'
This commit is contained in:
Neil Toronto 2012-11-17 22:58:49 -07:00
parent db500e8b58
commit 1e52736089
8 changed files with 465 additions and 356 deletions

View File

@ -137,6 +137,15 @@
(define bits (bf-precision)) (define bits (bf-precision))
(bf (random-bits bits) (- bits))) (bf (random-bits bits) (- bits)))
(: bigfloat->fl2 (Bigfloat -> (Values Flonum Flonum)))
(define (bigfloat->fl2 x)
(define x2 (bigfloat->flonum x))
(values x2 (bigfloat->flonum (bf- x (flonum->bigfloat x2)))))
(: fl2->bigfloat (Flonum Flonum -> Bigfloat))
(define (fl2->bigfloat x2 x1)
(bf+ (flonum->bigfloat x1) (flonum->bigfloat x2)))
(provide (provide
;; Library stuffs ;; Library stuffs
mpfr-available? mpfr-available?
@ -159,10 +168,12 @@
integer->bigfloat integer->bigfloat
rational->bigfloat rational->bigfloat
real->bigfloat real->bigfloat
fl2->bigfloat
bigfloat->flonum bigfloat->flonum
bigfloat->integer bigfloat->integer
bigfloat->rational bigfloat->rational
bigfloat->real bigfloat->real
bigfloat->fl2
;; String conversion ;; String conversion
bigfloat->string bigfloat->string
string->bigfloat string->bigfloat

View File

@ -1001,24 +1001,6 @@
(set! 0ary-funs (list* #'phi.bf #'epsilon.bf #'-max.bf #'-min.bf #'+min.bf #'+max.bf (set! 0ary-funs (list* #'phi.bf #'epsilon.bf #'-max.bf #'-min.bf #'+min.bf #'+max.bf
0ary-funs))) 0ary-funs)))
;; ===================================================================================================
;; Extra functions
(define (random-bits bits)
(let loop ([bits bits] [acc 0])
(cond [(= 0 bits) acc]
[else
(define new-bits (min 24 bits))
(loop (- bits new-bits)
(bitwise-ior (random (arithmetic-shift 1 new-bits))
(arithmetic-shift acc new-bits)))])))
(define (bfrandom)
(define bits (bf-precision))
(bf (random-bits bits) (- bits)))
(provide bfrandom)
;; =================================================================================================== ;; ===================================================================================================
;; Number Theoretic Functions ;; Number Theoretic Functions
;; http://gmplib.org/manual/Number-Theoretic-Functions.html#Number-Theoretic-Functions ;; http://gmplib.org/manual/Number-Theoretic-Functions.html#Number-Theoretic-Functions

View File

@ -9,10 +9,9 @@ Discrete & Computational Geometry 18(3):305363, October 1997
|# |#
(require "../flonum-functions.rkt" (require "../flonum-functions.rkt"
"../flonum-syntax.rkt" "../flonum-syntax.rkt")
"../../bigfloat/bigfloat-struct.rkt")
(provide fl2 bigfloat->fl2 fl2->real fl2->bigfloat (provide fl2 fl2->real
fl2+ fl2- fl2*split-fl fl2* fl2/ fl2+ fl2- fl2*split-fl fl2* fl2/
flsqrt/error fl2sqrt) flsqrt/error fl2sqrt)
@ -31,11 +30,6 @@ Discrete & Computational Geometry 18(3):305363, October 1997
[(x y) [(x y)
(fast-fl+/error x y)])) (fast-fl+/error x y)]))
(: bigfloat->fl2 (Bigfloat -> (Values Flonum Flonum)))
(define (bigfloat->fl2 x)
(define x2 (bigfloat->flonum x))
(values x2 (bigfloat->flonum (bf- x (bf x2)))))
(: fl2->real (Flonum Flonum -> Real)) (: fl2->real (Flonum Flonum -> Real))
(define (fl2->real x2 x1) (define (fl2->real x2 x1)
(cond [(and (x1 . fl> . -inf.0) (x1 . fl< . +inf.0) (cond [(and (x1 . fl> . -inf.0) (x1 . fl< . +inf.0)
@ -43,10 +37,6 @@ Discrete & Computational Geometry 18(3):305363, October 1997
(+ (inexact->exact x2) (inexact->exact x1))] (+ (inexact->exact x2) (inexact->exact x1))]
[else (fl+ x1 x2)])) [else (fl+ x1 x2)]))
(: fl2->bigfloat (Flonum Flonum -> Bigfloat))
(define (fl2->bigfloat x2 x1)
(bf+ (bf x1) (bf x2)))
(: fl3->fl2 (Flonum Flonum Flonum -> (Values Flonum Flonum))) (: fl3->fl2 (Flonum Flonum Flonum -> (Values Flonum Flonum)))
(define (fl3->fl2 e3 e2 e1) (define (fl3->fl2 e3 e2 e1)
(values e3 (fl+ e2 e1))) (values e3 (fl+ e2 e1)))

View File

@ -7,9 +7,10 @@
;;; ;;;
(: divides? : Integer Integer -> Boolean) (: divides? : Integer Integer -> Boolean)
; For b<>0: ( a divides b <=> exists k s.t. a*k=b ) ; a divides b <=> exists unique k s.t. a*k=b
(define (divides? a b) (define (divides? a b)
(= (remainder b a) 0)) (cond [(zero? a) #f]
[else (= (remainder b a) 0)]))
; DEF (Coprime, relatively prime) ; DEF (Coprime, relatively prime)
; Two or more integers are called coprime, if their greatest common divisor is 1. ; Two or more integers are called coprime, if their greatest common divisor is 1.

View File

@ -23,8 +23,12 @@
(provide (all-defined-out)) (provide (all-defined-out))
(: current-modulus-param (Parameterof Positive-Integer)) (: current-modulus-param (Parameterof Integer Positive-Integer))
(define current-modulus-param (make-parameter 1)) (define current-modulus-param
(make-parameter
1 (λ: ([n : Integer])
(cond [(n . <= . 0) (raise-argument-error 'with-modulus "Positive-Integer" n)]
[else n]))))
(: current-modulus (-> Positive-Integer)) (: current-modulus (-> Positive-Integer))
(begin-encourage-inline (begin-encourage-inline

View File

@ -107,8 +107,10 @@
; Example : (solve-chinese '(2 3 2) '(3 5 7)) = 23 ; Example : (solve-chinese '(2 3 2) '(3 5 7)) = 23
(: solve-chinese : Zs (Listof N+) -> N) (: solve-chinese : Zs (Listof Z) -> N)
(define (solve-chinese as ns) (define (solve-chinese as ns)
(unless (andmap positive? ns)
(raise-argument-error 'solve-chinese "(Listof Positive-Integer)" 1 as ns))
; the ns should be coprime ; the ns should be coprime
(let* ([n (apply * ns)] (let* ([n (apply * ns)]
[cs (map (λ: ([ni : Z]) (quotient n ni)) ns)] [cs (map (λ: ([ni : Z]) (quotient n ni)) ns)]
@ -245,8 +247,11 @@
(prev-prime n-2)))])) (prev-prime n-2)))]))
(: next-primes : Z N -> Zs) (: next-primes : Z Z -> Zs)
(define (next-primes m primes-wanted) (define (next-primes m primes-wanted)
(cond
[(primes-wanted . < . 0) (raise-argument-error 'next-primes "Natural" 1 m primes-wanted)]
[else
(: loop : Z Z -> Zs) (: loop : Z Z -> Zs)
(define (loop n primes-wanted) (define (loop n primes-wanted)
(if (= primes-wanted 0) (if (= primes-wanted 0)
@ -255,10 +260,13 @@
(if next (if next
(cons next (loop next (sub1 primes-wanted))) (cons next (loop next (sub1 primes-wanted)))
'())))) '()))))
(loop m primes-wanted)) (loop m primes-wanted)]))
(: prev-primes : Z N -> Zs) (: prev-primes : Z Z -> Zs)
(define (prev-primes m primes-wanted) (define (prev-primes m primes-wanted)
(cond
[(primes-wanted . < . 0) (raise-argument-error 'prev-primes "Natural" 1 m primes-wanted)]
[else
(: loop : Z Z -> Zs) (: loop : Z Z -> Zs)
(define (loop n primes-wanted) (define (loop n primes-wanted)
(if (= primes-wanted 0) (if (= primes-wanted 0)
@ -267,13 +275,15 @@
(if prev (if prev
(cons prev (loop prev (sub1 primes-wanted))) (cons prev (loop prev (sub1 primes-wanted)))
'())))) '()))))
(loop m primes-wanted)) (loop m primes-wanted)]))
(: nth-prime : N -> Prime) (: nth-prime : Z -> Prime)
(define (nth-prime n) (define (nth-prime n)
(cond [(n . < . 0) (raise-argument-error 'nth-prime "Natural" n)]
[else
(for/fold: ([p : Prime 2]) ([m (in-range n)]) (for/fold: ([p : Prime 2]) ([m (in-range n)])
(next-prime p))) (next-prime p))]))
;;; ;;;

View File

@ -13,12 +13,13 @@
; The number s is called a squre root of a modulo n. ; The number s is called a squre root of a modulo n.
; p is prime ; p is prime
(: quadratic-character : Integer Integer -> Integer) (: quadratic-character : Integer Integer -> (U -1 0 1))
(define (quadratic-character a p) (define (quadratic-character a p)
(cond [(a . < . 0) (raise-argument-error 'quadratic-character "Natural" 0 a p)] (cond [(a . < . 0) (raise-argument-error 'quadratic-character "Natural" 0 a p)]
[(p . <= . 0) (raise-argument-error 'quadratic-character "Positive-Integer" 1 a p)] [(p . <= . 0) (raise-argument-error 'quadratic-character "Positive-Integer" 1 a p)]
[else (let ([l (modular-expt a (quotient (- p 1) 2) p)]) [else (let ([l (modular-expt a (quotient (- p 1) 2) p)])
(if (<= 0 l 1) l -1))])) (cond [(or (eqv? l 0) (eqv? l 1)) l]
[else -1]))]))
(: quadratic-residue? : Integer Integer -> Boolean) (: quadratic-residue? : Integer Integer -> Boolean)
(define (quadratic-residue? a n) (define (quadratic-residue? a n)

View File

@ -1,8 +1,12 @@
#lang scribble/doc #lang scribble/manual
@(require (for-label racket/flonum @(require (for-label racket/flonum
racket/fixnum racket/fixnum
racket/unsafe/ops racket/unsafe/ops
racket/require racket/require
racket/base
(only-in typed/racket/base
Integer Exact-Rational Boolean Listof Natural U List
Positive-Integer)
math) math)
scribble/extract scribble/extract
scribble/eval scribble/eval
@ -13,107 +17,88 @@
"utils.rkt") "utils.rkt")
@(define untyped-eval (make-untyped-math-eval)) @(define untyped-eval (make-untyped-math-eval))
@interaction-eval[#:eval untyped-eval (require racket/list
racket/function)]
@(define math-style tt) @(define math-style tt)
@(define math-eval @title[#:tag "number-theory"]{Number Theory}
(parameterize ([sandbox-output 'string]
[sandbox-error-output 'string])
(make-evaluator 'racket)))
@;(interaction-eval #:eval math-eval (require racket math))
@title[#:tag "number-theory" #:style '(toc)]{Number Theory}
@(author-jens-axel) @(author-jens-axel)
@defmodule[math/number-theory]
@local-table-of-contents[] @local-table-of-contents[]
@; ---------------------------------------- @; ----------------------------------------
@section[#:tag "congruences"]{Congruences and Modular Arithmetic} @section[#:tag "congruences"]{Congruences and Modular Arithmetic}
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Divisor"]{Divisor}} @margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Divisor"]{Divisor}}
@defproc[(divides? [m Integer] [n Integer]) boolean?]{ @defproc[(divides? [m Integer] [n Integer]) Boolean]{
Returns @racket[#t] if @racket[m] divides @racket[n], Returns @racket[#t] if @racket[m] divides @racket[n], @racket[#f] otherwise.
@racket[#f] otherwise.
Note: That a non-zero integer @racket[m] divides an integer @racket[n] Formally, an integer @racket[m] divides an integer @racket[n] when there
means there exists an integer @racket[k] such that m*k=n. exists a unique integer @racket[k] such that @racket[(* m k) = n].
Test whether 2 divides 9: @examples[#:eval untyped-eval
(divides? 2 9)
(divides? 2 8)]
Note that @racket[0] cannot divide anything:
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
(require math) (divides? 0 5)
(divides? 2 9)] (divides? 0 0)]
Practically, if @racket[(divides? m n)] is @racket[#t], then @racket[(/ n m)] will return
an integer and will not raise @racket[exn:fail:contract:divide-by-zero].
} }
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/B%C3%A9zout's_identity"]{Bezout's Identity}} @margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/B%C3%A9zout's_identity"]{Bezout's Identity}}
@defproc[(bezout [a Integer] [b Integer] [c Integer] ...) (Listof Integer)]{ @defproc[(bezout [a Integer] [b Integer] [c Integer] ...) (Listof Integer)]{
Given integers @racket[a], @racket[b], @racket[c] ... Given integers @racket[a b c ...] returns a list of integers @racket[(list u v w ...)]
returns a list of integers @racket[u], @racket[v], @racket[q] ... such that @racket[(gcd a b c ...) = (+ (* a u) (* b v) (* c w) ...)].
such that @racket[gcd](@racket[a],@racket[b],@racket[c],...)
= @racket[au + bv + cw + ...]
The greatest common divisor of 6 and 15 is 3. @examples[#:eval untyped-eval
@interaction[#:eval untyped-eval
(bezout 6 15) (bezout 6 15)
(+ (* -2 6) (* 1 15))] (+ (* -2 6) (* 1 15))
(gcd 6 15)]
} }
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Coprime"]{Coprime}} @margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Coprime"]{Coprime}}
@defproc[(coprime? [a Integer] [b Integer] ...) boolean?]{ @defproc[(coprime? [a Integer] [b Integer] ...) Boolean]{
Returns @racket[#t] if the integers @racket[a],@racket[b],... are coprime. Returns @racket[#t] if the integers @racket[a b ...] are coprime.
Formally, a set of integers is considered coprime (also called relatively prime)
Note: A set of integers are considered coprime (also called relatively prime)
if their greatest common divisor is 1. if their greatest common divisor is 1.
The numbers 2, 6, and, 15 are coprime. @examples[#:eval untyped-eval
@interaction[#:eval untyped-eval
(coprime? 2 6 15)] (coprime? 2 6 15)]
} }
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Pairwise_coprime"]{Pairwise Coprime}} @margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Pairwise_coprime"]{Pairwise Coprime}}
@defproc[(pairwise-coprime? [a Integer] [b Integer] ...) boolean?]{ @defproc[(pairwise-coprime? [a Integer] [b Integer] ...) Boolean]{
Returns @racket[#t] if the integers @racket[a],@racket[b],... are pairwise coprime. Returns @racket[#t] if the integers @racket[a b ...] are @italic{pairwise} coprime, meaning
that each adjacent pair of integers is coprime.
The numbers 2, 6, and, 15 are not pairwise coprime, since 2 and 6 share the factor 3. The numbers 2, 6 and 15 are coprime, but not @italic{pairwise} coprime, because 2 and 6 share the
factor 3:
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
(pairwise-coprime? 2 6 15)] (pairwise-coprime? 2 6 15)]
} }
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Modular_multiplicative_inverse"]{Multiplicative Inverse}}
@defproc[(modular-inverse [a Integer] [n Integer]) natural?]{
Returns the inverse of @racket[a] module @racket[n],
if @racket[a] and @racket[n] are coprime,
otherwise @racket[#f] is returned.
Note: If @racket[a] and @racket[n] are coprime, then
the inverse, @racket[b], is a number in the set @racket[{0,...,n-1}]
such that @racket[ab=1 mod n].
The number 3 is an inverse to 2 modulo 5.
@interaction[(require math)
(modular-inverse 2 5)
(modulo (* 2 3) 5)]
The number 0 has no inverse modulo 5.
@interaction[(require math)
(modular-inverse 0 5)]
}
@defproc[(solve-chinese [as (Listof Integer)] [bs (Listof Integer)]) natural?]{
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Chinese_remainder_theorem"]{Chinese Remainder Theorem}} @margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Chinese_remainder_theorem"]{Chinese Remainder Theorem}}
Given a list of integers @racket[as] and a list of coprime moduli @racket[ns] @defproc[(solve-chinese [as (Listof Integer)] [ns (Listof Integer)]) Natural]{
the function @racket[solve-chinese] will return Given a length-@racket[k] list of integers @racket[as] and a length-@racket[k] list of coprime
the single natural solution @racket[x] in @racket[{0,...,n-1}] moduli @racket[ns], @racket[(solve-chinese as ns)] returns the least natural number @racket[x]
to the equations that is a solution to the equations
@racket[x=a1 mod n1, ..., x=ak mod nk] @racketblock[x = #,(elem @racket[a] @subscript{1}) #,(elem "(mod " @racket[n] @subscript{1} ")")
...
x = #,(elem @racket[a] @subscript{@racket[k]}) #,(elem "(mod " @racket[x] @subscript{@racket[k]} ")")]
where @racket[a1], ... are the elements of @racket[as], The solution @racket[x] is less than
and @racket[n1], ... are the elements of @racket[ns], @racket[(* #,(elem @racket[n] @subscript{1}) ... #,(elem @racket[n] @subscript{@racket[k]}))].
and @racket[n=n1*...*nk].
The moduli @racket[ns] must all be positive.
What is the least number @racket[x] that when divided by 3 leaves What is the least number @racket[x] that when divided by 3 leaves
a remainder of 2, when divided by 5 leaves a remainder of 3, and a remainder of 2, when divided by 5 leaves a remainder of 3, and
@ -122,57 +107,187 @@
(solve-chinese '(2 3 2) '(3 5 7))] (solve-chinese '(2 3 2) '(3 5 7))]
} }
@defproc[(quadratic-residue? [a natural?] [n natural?]) boolean?]{ @defproc[(quadratic-residue? [a Integer] [n Integer]) Boolean]{
Returns @racket[#t] if @racket[a] is a quadratic residue modulo @racket[n], Returns @racket[#t] if @racket[a] is a quadratic residue modulo @racket[n], otherwise @racket[#f].
otherwise @racket[#f] is returned. The modulus @racket[n] must be positive, and @racket[a] must be nonnegative.
A number @racket[a] is a quadratic residue modulo @racket[n], if there Formally, @racket[a] is a quadratic residue modulo @racket[n] if there
exists a number @racket[x] such that @math-style{x^2=a mod n}. exists a number @racket[x] such that @racket[(* x x) = a] (mod @racket[n]).
@interaction[(require math) In other words, @racket[(quadratic-residue? a n)] is @racket[#t] when
@racket[a] is a perfect square modulo @racket[n].
@examples[#:eval untyped-eval
(quadratic-residue? 0 4) (quadratic-residue? 0 4)
(quadratic-residue? 1 4) (quadratic-residue? 1 4)
(quadratic-residue? 2 4) (quadratic-residue? 2 4)
(quadratic-residue? 3 4)] (quadratic-residue? 3 4)]
} }
@defproc[(quadratic-character [a natural?] [p prime?]) (union -1 1)]{ @defproc[(quadratic-character [a Integer] [p Integer]) (U -1 0 1)]{
Returns the values of the quadratic character modulo the prime @racket[p]. Returns the value of the quadratic character modulo the prime @racket[p].
That is, for a non-zero @racket[a] the number @racket[1] is returned when That is, for a non-zero @racket[a] the number @racket[1] is returned when
@racket[a] is a quadratic residue, @racket[a] is a quadratic residue,
and @racket[-1] is returned when @racket[a] is a non-residue. and @racket[-1] is returned when @racket[a] is a non-residue.
If @racket[a] is zero, then @racket[0] is returned. If @racket[a] is zero, then @racket[0] is returned.
This function is also known as the @emph{Legendre Symbol}. If @racket[a] is negative or @racket[p] is not positive, @racket[quadratic-character] raises an error.
If @racket[p] is not prime, @racket[(quadratic-character a p)] is indeterminate.
@interaction[(require math) This function is also known as the @emph{Legendre symbol}.
(quadratic-character 0 4)
(quadratic-character 1 4) @interaction[#:eval untyped-eval
(quadratic-character 2 4) (quadratic-character 0 5)
(quadratic-character 3 4)] (quadratic-character 1 5)
(quadratic-character 2 5)
(quadratic-character 3 5)]
} }
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Modular_multiplicative_inverse"]{Multiplicative Inverse}}
@defproc[(modular-inverse [a Integer] [n Integer]) Natural]{
Returns the inverse of @racket[a] modulo @racket[n] if @racket[a] and @racket[n] are coprime,
otherwise raises an error. The modulus @racket[n] must be positive, and @racket[a] must be nonzero.
Formally, if @racket[a] and @racket[n] are coprime, @racket[b = (modular-inverse a n)] is the
unique natural number less than @racket[n] such that @racket[(* a b) = 1] (mod @racket[n]).
@interaction[#:eval untyped-eval
(modular-inverse 2 5)
(modulo (* 2 3) 5)]
}
@defproc[(modular-expt [a Integer] [b Integer] [n Integer]) Natural]{
Computes @racket[(modulo (expt a b) n)], but much more efficiently. The modulus @racket[n] must
be positive, and the exponent @racket[b] must be nonnegative.
@examples[#:eval untyped-eval
(modulo (expt -6 523) 19)
(modular-expt -6 523 19)
(modular-expt 9 158235208 19)
(eval:alts (code:line (code:comment "don't try this at home!")
(modulo (expt 9 158235208) 19))
(eval:result @racketresultfont{4}))
]
}
@subsection[#:tag "modular"]{Parameterized Modular Arithmetic}
The @racketmodname[math/number-theory] library supports modular arithmetic parameterized on a current
modulus. For example, the code
@racketblock[(with-modulus n
((modexpt a b) . mod= . c))]
corresponds with the mathematical statement
@italic{a}@superscript{@italic{b}} = @italic{c} (mod @italic{n}).
The current modulus is stored in a @tech{parameter} that, for performance reasons, can only be
set using @racket[with-modulus]. (The basic modular operators cache parameter reads, and this
restriction guarantees that the cached values are current.)
@defform[(with-modulus n body ...)
#:contracts ([n Integer])]{
Alters the current modulus within the dynamic extent of @racket[body].
The expression @racket[n] must evaluate to a positive integer.
By default, the current modulus is @racket[1], meaning that every modular arithmetic expression
that does not raise an error returns @racket[0].
}
@defproc[(current-modulus) Positive-Integer]{
Returns the current modulus.
@examples[#:eval untyped-eval
(current-modulus)
(with-modulus 5 (current-modulus))]
}
@defproc[(mod [x Exact-Rational]) Natural]{
Converts a rational number @racket[x] to a natural number less than the current modulus.
If @racket[x] is an integer, this is equivalent to @racket[(modulo x n)].
If @racket[x] is a fraction, an integer input is generated by multiplying its numerator
by its denominator's modular inverse.
@examples[#:eval untyped-eval
(with-modulus 7 (mod (* 218 7)))
(with-modulus 7 (mod 3/2))
(with-modulus 7 (mod/ 3 2))
(with-modulus 7 (mod 3/7))]
}
@deftogether[(@defproc[(mod+ [a Integer] ...) Natural]
@defproc[(mod* [a Integer] ...) Natural])]{
Equivalent to @racket[(modulo (+ a ...) (current-modulus))] and
@racket[(modulo (* a ...) (current-modulus))], respectively, but generate smaller intermediate
values.
}
@deftogether[(@defproc[(modsqr [a Integer]) Natural]
@defproc[(modexpt [a Integer] [b Integer]) Natural])]{
Equivalent to @racket[(mod* a a)] and @racket[(modular-expt a b (current-modulus))], respectively.
}
@defproc[(mod- [a Integer] [b Integer] ...) Natural]{
Equivalent to @racket[(modulo (- a b ...) (current-modulus))], but generates smaller intermediate
values. Note that @racket[(mod- a) = (mod (- a))].
}
@defproc[(mod/ [a Integer] [b Integer] ...) Natural]{
Divides @racket[a] by @racket[(* b ...)], by multiplying @racket[a] by the multiplicative inverse
of @racket[(* b ...)]. The one-argument variant returns the modular inverse of @racket[a].
Note that @racket[(mod/ a b ...)] is @bold{not} equivalent to
@racket[(modulo (/ a b ...) (current-modulus))]; see @racket[mod=] for a demonstration.
}
@deftogether[(@defproc[(mod= [a Integer] [b Integer] ...) Boolean]
@defproc[(mod< [a Integer] [b Integer] ...) Boolean]
@defproc[(mod<= [a Integer] [b Integer] ...) Boolean]
@defproc[(mod> [a Integer] [b Integer] ...) Boolean]
@defproc[(mod>= [a Integer] [b Integer] ...) Boolean])]{
Each of these is equivalent to @racket[(op (mod a) (mod b) ...)], where @racket[op] is the
corresponding numeric comparison function. Additionally, when given one argument, the inequality
tests always return @racket[#t].
Suppose we wanted to know why 17/4 = 8 (mod 15), but 51/12 (mod 15) is undefined, even though
normally 51/12 = 17/4. In code,
@interaction[#:eval untyped-eval
(with-modulus 15 (mod/ 17 4))
(/ 51 12)
(with-modulus 15 (mod/ 51 12))]
We could try to divide by brute force: find, modulo 15, all the numbers @racket[a]
for which @racket[(mod* a 4)] is @racket[17], then find all the numbers @racket[b] for which
@racket[(mod* a 12)] is @racket[51].
@interaction[#:eval untyped-eval
(with-modulus 15
(for/list ([a (in-range 15)]
#:when (mod= (mod* a 4) 17))
a))
(with-modulus 15
(for/list ([b (in-range 15)]
#:when (mod= (mod* b 12) 51))
b))]
So the problem isn't that @racket[b] doesn't exist, it's that @racket[b] isn't @italic{unique}.
}
@; ---------------------------------------- @; ----------------------------------------
@section[#:tag "primes"]{Primes} @section[#:tag "primes"]{Primes}
@defproc[(prime? [z Integer]) boolean?]{ @defproc[(prime? [z Integer]) Boolean]{
Returns @racket[#t] if @racket[z] is a prime, Returns @racket[#t] if @racket[z] is a prime, @racket[#f] otherwise.
@racket[#f] otherwise.
Note: An integer @racket[z] is considered a prime, if the only Formally, an integer @racket[z] is prime when the only positive divisors of @racket[z]
positive divisors of @racket[z] are @racket[1] and @racket[|z|]. are @racket[1] and @racket[(abs z)].
The positive primes below 20 are: The positive primes below 20 are:
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
(require racket/list)
(filter prime? (range 1 21))] (filter prime? (range 1 21))]
The corresponding negative primes are: The corresponding negative primes are:
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
(filter prime? (range 1 -21 -1))] (filter prime? (range 1 -21 -1))]
} }
@defproc[(odd-prime? [z Integer]) boolean?]{ @defproc[(odd-prime? [z Integer]) Boolean]{
Returns @racket[#t] if @racket[z] is a odd prime, Returns @racket[#t] if @racket[z] is a odd prime,
@racket[#f] otherwise. @racket[#f] otherwise.
@ -181,15 +296,15 @@ Returns @racket[#t] if @racket[z] is a odd prime,
(odd-prime? 3)] (odd-prime? 3)]
} }
@defproc[(nth-prime [n Natural]) natural?]{ @defproc[(nth-prime [n Integer]) Natural]{
Returns the n'th positive prime. Returns the @racket[n]th positive prime; @racket[n] must be nonnegative.
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
(nth-prime 0) (nth-prime 0)
(nth-prime 1) (nth-prime 1)
(nth-prime 2)] (nth-prime 2)]
} }
@defproc[(next-prime [z Integer]) prime?]{ @defproc[(next-prime [z Integer]) Integer]{
Returns the first prime larger than @racket[z]. Returns the first prime larger than @racket[z].
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
@ -197,7 +312,7 @@ Returns the first prime larger than @racket[z].
(next-prime 5)] (next-prime 5)]
} }
@defproc[(prev-prime [z Integer]) prime?]{ @defproc[(prev-prime [z Integer]) Integer]{
Returns the first prime smaller than @racket[z]. Returns the first prime smaller than @racket[z].
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
@ -205,21 +320,21 @@ Returns the first prime smaller than @racket[z].
(prev-prime 5)] (prev-prime 5)]
} }
@defproc[(next-primes [z Integer] [n Natural]) (Listof prime?)]{ @defproc[(next-primes [z Integer] [n Integer]) (Listof Integer)]{
Returns list of the next @racket[n] primes larger than @racket[z]. Returns list of the next @racket[n] primes larger than @racket[z]; @racket[n] must be nonnegative.
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
(next-primes 2 4)] (next-primes 2 4)]
} }
@defproc[(prev-primes [z Integer] [n Natural]) (Listof prime?)]{ @defproc[(prev-primes [z Integer] [n Integer]) (Listof Integer)]{
Returns list of the next @racket[n] primes smaller than @racket[z]. Returns list of the next @racket[n] primes smaller than @racket[z]; @racket[n] must be nonnegative.
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
(prev-primes 13 4)] (prev-primes 13 4)]
} }
@defproc[(factorize [n Natural]) (Listof (List prime? natural?))]{ @defproc[(factorize [n Natural]) (Listof (List Natural Natural))]{
Returns the factorization of a natural number @racket[n]. Returns the factorization of a natural number @racket[n].
The factorization consists of a list of corresponding The factorization consists of a list of corresponding
primes and exponents. The primes will be in ascending order. primes and exponents. The primes will be in ascending order.
@ -229,7 +344,7 @@ The prime factorization of 600 = 2^3 * 3^1 * 5^2:
(factorize 600)] (factorize 600)]
} }
@defproc[(defactorize [f (Listof (List prime? natural?))]) natural?]{ @defproc[(defactorize [f (Listof (List Natural Natural))]) Natural]{
Returns the natural number, whose factorization is given Returns the natural number, whose factorization is given
by @racket[f]. The factorization @racket[f] is represented by @racket[f]. The factorization @racket[f] is represented
as described in @racket[factorize]. as described in @racket[factorize].
@ -247,7 +362,7 @@ The divisors appear in ascending order.
(divisors -120)] (divisors -120)]
} }
@defproc[(prime-divisors [z Integer]) (Listof Natural)]{ @defproc[(prime-divisors [z Natural]) (Listof Natural)]{
Returns a list of all positive prime divisors of the integer Returns a list of all positive prime divisors of the integer
@racket[z]. The divisors appear in ascending order. @racket[z]. The divisors appear in ascending order.
@ -255,7 +370,7 @@ Returns a list of all positive prime divisors of the integer
(prime-divisors 120)] (prime-divisors 120)]
} }
@defproc[(prime-exponents [z Integer]) (Listof Natural)]{ @defproc[(prime-exponents [z Natural]) (Listof Natural)]{
Returns a list of the exponents of in a factorization of the integer Returns a list of the exponents of in a factorization of the integer
@racket[z]. @racket[z].
@ -268,11 +383,10 @@ Returns a list of the exponents of in a factorization of the integer
@; ---------------------------------------- @; ----------------------------------------
@section[#:tag "roots"]{Roots} @section[#:tag "roots"]{Roots}
@defproc[(integer-root [n Natural] [m Natural]) Natural]{
@defproc[(integer-root [n Natural] [m Natural]) natural?]{ Returns the @racket[m]th integer root of @racket[n].
Returns the @racket[m]'th integer root of @racket[n].
This is the largest number @racket[r] such that This is the largest number @racket[r] such that
@racket[r^m<=n]. @racket[(expt r m) <= n].
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
(integer-root (expt 3 4) 4) (integer-root (expt 3 4) 4)
@ -280,8 +394,8 @@ This is the largest number @racket[r] such that
} }
@defproc[(integer-root/remainder [n Natural] [m Natural]) @defproc[(integer-root/remainder [n Natural] [m Natural])
(values natural? natural?)]{ (values Natural Natural)]{
Returns two values. The first, @racket[r], is the @racket[m]'th Returns two values. The first, @racket[r], is the @racket[m]th
integer root of @racket[n]. The second is @racket[n-r^m]. integer root of @racket[n]. The second is @racket[n-r^m].
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
@ -293,11 +407,11 @@ integer root of @racket[n]. The second is @racket[n-r^m].
@; ---------------------------------------- @; ----------------------------------------
@section[#:tag "powers"]{Powers} @section[#:tag "powers"]{Powers}
@defproc[(max-dividing-power [a Integer] [b Integer]) natural?]{ @defproc[(max-dividing-power [a Integer] [b Integer]) Natural]{
Returns the largest exponent, @racket[n], of a power with Returns the largest exponent, @racket[n], of a power with
base @racket[a] that divides @racket[b]. base @racket[a] that divides @racket[b].
That is, @racket[a^n] divides @racket[b] but @racket[a^(n+1)] does not divide That is, @racket[(expt a n)] divides @racket[b] but @racket[(expt a (+ n 1))] does not divide
@racket[b]. @racket[b].
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
@ -306,9 +420,9 @@ That is, @racket[a^n] divides @racket[b] but @racket[a^(n+1)] does not divide
} }
@defproc[(perfect-power [m Integer]) @defproc[(perfect-power [m Integer])
(Union (List natural? natural?) #f)]{ (U (List Natural Natural) #f)]{
If @racket[m] is a perfect power, a list with two elements If @racket[m] is a perfect power, a list with two elements
@racket[b] and @racket[n] such that @racket[b^n = m] @racket[b] and @racket[n] such that @racket[(expt b n) = m]
is returned, otherwise @racket[#f] is returned. is returned, otherwise @racket[#f] is returned.
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
@ -317,7 +431,7 @@ is returned, otherwise @racket[#f] is returned.
} }
@defproc[(perfect-power? [m Integer]) boolean?]{ @defproc[(perfect-power? [m Integer]) Boolean]{
Returns @racket[#t] if @racket[m] is a perfect power, Returns @racket[#t] if @racket[m] is a perfect power,
otherwise @racket[#f]. otherwise @racket[#f].
@ -328,8 +442,8 @@ otherwise @racket[#f].
@defproc[(prime-power [m Natural]) @defproc[(prime-power [m Natural])
(Union (List prime? natural?) #f)]{ (U (List Natural Natural) #f)]{
If @racket[m] is a power of the form @racket[p^n] If @racket[m] is a power of the form @racket[(expt p n)]
where @racket[p] is prime, then a list with the where @racket[p] is prime, then a list with the
prime and the exponent is returned, otherwise prime and the exponent is returned, otherwise
@racket[#f] is returned. @racket[#f] is returned.
@ -339,7 +453,7 @@ prime and the exponent is returned, otherwise
(prime-power (expt 6 4))] (prime-power (expt 6 4))]
} }
@defproc[(prime-power? [m Natural]) boolean?]{ @defproc[(prime-power? [m Natural]) Boolean]{
Returns @racket[#t] if @racket[m] is a prime power, Returns @racket[#t] if @racket[m] is a prime power,
otherwise @racket[#f]. otherwise @racket[#f].
@ -350,7 +464,7 @@ otherwise @racket[#f].
(prime-power? 0)] (prime-power? 0)]
} }
@defproc[(odd-prime-power? [m Natural]) boolean?]{ @defproc[(odd-prime-power? [m Natural]) Boolean]{
Returns @racket[#t] if @racket[m] is a power of an odd prime, Returns @racket[#t] if @racket[m] is a power of an odd prime,
otherwise @racket[#f]. otherwise @racket[#f].
@ -361,9 +475,9 @@ otherwise @racket[#f].
} }
@defproc[(as-power [m Positive-Integer]) @defproc[(as-power [m Positive-Integer])
(values natural? natural?)]{ (values Natural Natural)]{
Returns two values @racket[b] and @racket[n] Returns two values @racket[b] and @racket[n]
such that @racket[m=b^r] and @racket[n] is maximal. such that @racket[m = (expt b n)] and @racket[n] is maximal.
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
(as-power (* (expt 2 4) (expt 3 4))) (as-power (* (expt 2 4) (expt 3 4)))
@ -373,8 +487,8 @@ such that @racket[m=b^r] and @racket[n] is maximal.
} }
@defproc[(perfect-square [m Natural]) @defproc[(perfect-square [m Natural])
(Union natural? #f)]{ (U Natural #f)]{
Returns @racket[sqrt(m)] if @racket[m] is perfect Returns @racket[(sqrt m)] if @racket[m] is perfect
square, otherwise @racket[#f]. square, otherwise @racket[#f].
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
@ -385,42 +499,28 @@ square, otherwise @racket[#f].
@; ---------------------------------------- @; ----------------------------------------
@section[#:tag "multiplicative"]{Multiplicative Functions} @section[#:tag "multiplicative"]{Multiplicative Functions}
In number theory a multiplicative function is a The functions in this section are @deftech{multiplicative}.
function @racket[f] such that @racket[f(a b) = f(a) f(b)] In number theory, a multiplicative function is a function @racket[f] such that
for all coprime natural numbers @racket[a] and @racket[b]. @racket[(f a b) = (* (f a) (f b))] for all coprime natural numbers @racket[a] and @racket[b].
The functions @racket[totient], @racket[moebius-mu], and,
@racket[divisor-sum] are multiplicative.
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Euler%27s_totient_function"]{Euler's Totient}} @margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Euler%27s_totient_function"]{Euler's Totient}}
@defproc[(totient [n Natural]) natural?]{ @defproc[(totient [n Natural]) Natural]{
Returns the number of integers from 1 to @racket[n] Returns the number of integers from 1 to @racket[n]
that are coprime with @racket[n]. that are coprime with @racket[n].
This function is known as Eulers totient or phi function. This function is known as Eulers totient or phi function.
Note: The function @racket[totient] is multiplicative.
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
(require racket/function) ; for curry
(totient 9) (totient 9)
(length (filter (curry coprime? 9) (range 10)))] (length (filter (curry coprime? 9) (range 10)))]
} }
@defproc[(moebius-mu [n Natural]) (Union -1 0 1)]{
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/M%C3%B6bius_function"]{Moebius Function}} @margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/M%C3%B6bius_function"]{Moebius Function}}
@defproc[(moebius-mu [n Natural]) (U -1 0 1)]{
Returns: Returns:
@itemlist[@item{@racket[1] if @racket[n] is a product of an even number of primes}
@racket[1] if @racket[n] is a product of an even number of primes @item{@racket[-1] if @racket[n] is a product of an odd number of primes}
@item{@racket[0] if @racket[n] has a multiple prime factor}]
@racket[-1] if @racket[n] is a product of an odd number of primes
@racket[0] if @racket[n] has a multiple prime factor
Note: The function @racket[moebius-mu] is multiplicative.
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
(moebius-mu (* 2 3 5)) (moebius-mu (* 2 3 5))
@ -430,12 +530,10 @@ Note: The function @racket[moebius-mu] is multiplicative.
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Divisor_function"]{Divisor Function}} @margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Divisor_function"]{Divisor Function}}
@defproc[(divisor-sum [n Natural] [k Natural]) natural?]{ @defproc[(divisor-sum [n Natural] [k Natural]) Natural]{
Returns sum of the @racket[k]th powers of Returns sum of the @racket[k]th powers of
all divisors of @racket[n]. all divisors of @racket[n].
Note: The function @racket[divisor-sum] is multiplicative.
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
(divisor-sum 12 2) (divisor-sum 12 2)
(apply + (map sqr (divisors 12)))] (apply + (map sqr (divisors 12)))]
@ -446,55 +544,58 @@ Note: The function @racket[divisor-sum] is multiplicative.
@section[#:tag "number-sequences"]{Number Sequences} @section[#:tag "number-sequences"]{Number Sequences}
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Bernoulli_number"]{Bernoulli Number}} @margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Bernoulli_number"]{Bernoulli Number}}
@defproc[(bernoulli [n Natural]) exact-rational?]{ @defproc[(bernoulli [n Integer]) Exact-Rational]{
Returns the @racket[n]th Bernoulli number. Returns the @racket[n]th Bernoulli number; @racket[n] must be nonnegative.
@interaction[#:eval untyped-eval @interaction[#:eval untyped-eval
(map bernoulli (range 9))] (map bernoulli (range 9))]
Note that these are the @italic{first} Bernoulli numbers, since @racket[(bernoulli 1) = -1/2].
} }
@margin-note{MathWorld: @hyperlink["http://mathworld.wolfram.com/EulerianNumber.html"]{Eulerian Number}} @margin-note{MathWorld: @hyperlink["http://mathworld.wolfram.com/EulerianNumber.html"]{Eulerian Number}}
@defproc[(eulerian-number [n Natural] [k Natural]) natural?]{ @defproc[(eulerian-number [n Integer] [k Integer]) Natural]{
Returns the Eulerian number @math-style{<n,k>}. Returns the Eulerian number @math-style{<n,k>}; both arguments must be nonnegative.
@interaction[(require math racket) @interaction[#:eval untyped-eval
(eulerian-number 5 2)] (eulerian-number 5 2)]
} }
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Fibonacci_number"]{Fibonacci Number}} @margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Fibonacci_number"]{Fibonacci Number}}
@defproc[(fibonacci [n Natural]) natural?]{ @defproc[(fibonacci [n Integer]) Natural]{
Returns the @racket[n]th Fibonacci number. Returns the @racket[n]th Fibonacci number; @racket[n] must be nonnegative.
The ten first Fibonacci numbers. The ten first Fibonacci numbers.
@interaction[(require math racket) @interaction[#:eval untyped-eval
(map fibonacci (range 10))] (map fibonacci (range 10))]
} }
@defproc[(fibonacci/mod [n Natural] [m Natural]) natural?]{ @defproc[(fibonacci/mod [n Integer] [m Integer]) Natural]{
Returns the @racket[n]th Fibonacci number modulo @racket[m]. Returns the @racket[n]th Fibonacci number modulo @racket[m]; @racket[n] must be nonnegative
and @racket[m] must be positive.
The ten first Fibonacci numbers modulo 5. The ten first Fibonacci numbers modulo 5.
@interaction[(require math racket) @interaction[#:eval untyped-eval
(map (λ (n) (fibonacci/mod n 5)) (range 10))] (map (λ (n) (fibonacci/mod n 5)) (range 10))]
} }
@defproc[(farey [n Natural]) (listof rational?)]{ @defproc[(farey [n Integer]) (Listof Exact-Rational)]{
Returns a list of the numbers in the @racket[n]th Farey sequence. Returns a list of the numbers in the @racket[n]th Farey sequence; @racket[n] must be positive.
The @racket[n]th Farey sequence is the sequence of all The @racket[n]th Farey sequence is the sequence of all
completely reduced rational numbers from 0 to 1 which denominators completely reduced rational numbers from 0 to 1 which denominators
are less than or equal to @racket[n]. are less than or equal to @racket[n].
@interaction[(require math) @interaction[#:eval untyped-eval
(farey 1) (farey 1)
(farey 2) (farey 2)
(farey 3)] (farey 3)]
} }
@margin-note{MathWorld: @hyperlink["http://mathworld.wolfram.com/TangentNumber.html"]{Tangent Number}} @margin-note{MathWorld: @hyperlink["http://mathworld.wolfram.com/TangentNumber.html"]{Tangent Number}}
@defproc[(tangent-number [n integer?]) integer?]{ @defproc[(tangent-number [n Integer]) Integer]{
Returns the @racket[n]th tangent number. Returns the @racket[n]th tangent number; @racket[n] must be nonnegative.
@interaction[(require math) @interaction[#:eval untyped-eval
(tangent-number 1) (tangent-number 1)
(tangent-number 2) (tangent-number 2)
(tangent-number 3)] (tangent-number 3)]
@ -504,50 +605,55 @@ Returns the @racket[n]th tangent number.
@; ---------------------------------------- @; ----------------------------------------
@section[#:tag "combinatorics"]{Combinatorics} @section[#:tag "combinatorics"]{Combinatorics}
@defproc[(factorial [n Natural]) natural?]{ @defproc[(factorial [n Integer]) Natural]{
Returns the factorial of @racket[n]. Returns the factorial of @racket[n], which must be nonnegative.
The factorial of @racket[n] is the The factorial of @racket[n] is the number @racket[(* n (- n 1) (- n 2) ... 1)].
number @math-style{n!=n*(n-1)*(n-2)*...*1}. @interaction[#:eval untyped-eval
@interaction[(require math racket)
(factorial 3) (factorial 3)
(factorial 0)] (factorial 0)]
} }
@defproc[(binomial [n Natural] [k Natural]) natural?]{ @defproc[(binomial [n Integer] [k Integer]) Natural]{
Returns @racket[n] choose @racket[k]. Returns the number of ways to choose a @italic{set} of @racket[k] items from a set of
The binomial coeffecient is given by @racket[n] items; i.e. the order of the @racket[k] items is not significant.
@math-style{C(n,k)=n!/(n!(n-k)!)}. Both arguments must be nonnegative.
@interaction[(require math racket)
When @racket[k > n], @racket[(binomial n k) = 0]. Otherwise, @racket[(binomial n k)] is
equivalent to @racket[(/ (factorial n) (factorial k) (factorial (- n k)))], but computed more
quickly.
@interaction[#:eval untyped-eval
(binomial 5 3)] (binomial 5 3)]
} }
@defproc[(permutations [n Natural] [k Natural]) natural?]{ @defproc[(permutations [n Integer] [k Integer]) Natural]{
Returns the number of @racket[k]-permutations of @racket[n]. Returns the number of ways to choose a @italic{sequence} of @racket[k] items from a set of
That is the number of sequences of length @racket[k] where the @racket[n] items; i.e. the order of the @racket[k] items is significant.
elements are drawn from a set with @racket[n] elements. Both arguments must be nonnegative.
@math-style{P(n,k)=n!/(n-k)!}.
@interaction[(require math racket) When @racket[k > n], @racket[(permutations n k) = 0]. Otherwise, @racket[(permutations n k)] is
equivalent to @racket[(/ (factorial n) (factorial (- n k)))].
@interaction[#:eval untyped-eval
(permutations 5 3)] (permutations 5 3)]
} }
@defproc[(multinomial [n Natural] [ks (Listof Natural)]) natural?]{ @defproc[(multinomial [n Integer] [ks (Listof Integer)]) Natural]{
Returns the multinomial coeffecient. A generalization of @racket[binomial] to multiple sets of choices; i.e.
The expression @racket[(multinomial n (list k0 k1 ...))] @racket[(multinomial n (list k0 k1))] is the number of ways to choose a set of @racket[k0] items
returns the number @math-style{n! / (k0! * k1! * ...)}. and a set of @racket[k1] items from a set of @racket[n] items. All arguments must be nonnegative.
@interaction[(require math racket) When @racket[(apply + ks) = n], this is equivalent to
@racket[(apply / (factorial n) (map factorial ks))]. Otherwise, it returns @racket[0].
@interaction[#:eval untyped-eval
(multinomial 5 3 2)] (multinomial 5 3 2)]
} }
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Partition_(number_theory)"]{Partition}} @margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Partition_(number_theory)"]{Partition}}
@defproc[(partition-count [n Natural]) natural?]{ @defproc[(partition-count [n Integer]) Natural]{
Returns the number of partitions of @racket[n]. Returns the number of partitions of @racket[n], which must be nonnegative.
A partition of a positive integer @racket[n] is a way A partition of a positive integer @racket[n] is a way
of writing @racket[n] as a sum of positive integers. of writing @racket[n] as a sum of positive integers.
The number 3 has the partitions @math-style{1+1+1, 1+2, 3}. The number 3 has the partitions @racket[(+ 1 1 1)], @racket[(+ 1 2)] and @racket[(+ 3)].
@interaction[(require math racket) @interaction[#:eval untyped-eval
(partition-count 3) (partition-count 3)
(partition-count 4)] (partition-count 4)]
} }
@ -558,12 +664,12 @@ Returns the @racket[n]th tangent number.
@subsection{Polygonal Numbers} @subsection{Polygonal Numbers}
@defproc[(triangle? [n Natural]) boolean?]{} @defproc[(triangle? [n Natural]) Boolean]{}
@defproc[(square? [n Natural]) boolean?]{} @defproc[(square? [n Natural]) Boolean]{}
@defproc[(pentagonal? [n Natural]) boolean?]{} @defproc[(pentagonal? [n Natural]) Boolean]{}
@defproc[(hexagonal? [n Natural]) boolean?]{} @defproc[(hexagonal? [n Natural]) Boolean]{}
@defproc[(heptagonal? [n Natural]) boolean?]{} @defproc[(heptagonal? [n Natural]) Boolean]{}
@defproc[(octagonal? [n Natural]) boolean?]{ @defproc[(octagonal? [n Natural]) Boolean]{
The functions The functions
@racket[triangle?], @racket[square?], @racket[pentagonal?], @racket[triangle?], @racket[square?], @racket[pentagonal?],
@racket[hexagonal?],@racket[heptagonal?] and @racket[octagonal?] @racket[hexagonal?],@racket[heptagonal?] and @racket[octagonal?]
@ -572,12 +678,12 @@ triangle, square, pentagonal, hexagonal, heptagonal and octogonal
respectively. respectively.
} }
@defproc[(triangle [n Natural]) natural?]{} @defproc[(triangle [n Natural]) Natural]{}
@defproc[(sqr [n Natural]) natural?]{} @defproc[(sqr [n Natural]) Natural]{}
@defproc[(pentagonal [n Natural]) natural?]{} @defproc[(pentagonal [n Natural]) Natural]{}
@defproc[(hexagonal [n Natural]) natural?]{} @defproc[(hexagonal [n Natural]) Natural]{}
@defproc[(heptagonal [n Natural]) natural?]{} @defproc[(heptagonal [n Natural]) Natural]{}
@defproc[(octagonal [n Natural]) natural?]{ @defproc[(octagonal [n Natural]) Natural]{
The functions @racket[triangle], @racket[sqr], @racket[pentagonal], The functions @racket[triangle], @racket[sqr], @racket[pentagonal],
@racket[hexagonal],@racket[heptagonal] and @racket[octagonal] @racket[hexagonal],@racket[heptagonal] and @racket[octagonal]
return the @racket[n]th polygonal number of the corresponding return the @racket[n]th polygonal number of the corresponding
@ -588,11 +694,11 @@ type of polygonal number.
@; ---------------------------------------- @; ----------------------------------------
@section[#:tag "fractions"]{Fractions} @section[#:tag "fractions"]{Fractions}
@defproc[(mediant [x Rational] [y Rational]) rational?]{ @defproc[(mediant [x Exact-Rational] [y Exact-Rational]) Exact-Rational]{
Computes the @racket[mediant] of the numbers @racket[x] and @racket[y]. Computes the @racket[mediant] of the numbers @racket[x] and @racket[y].
The mediant of two fractions @math-style{p/q} and @math-style{r/s} in their The mediant of two fractions @math-style{p/q} and @math-style{r/s} in their
lowest term is the number @math-style{(p+r)/(q+s)}. lowest term is the number @math-style{(p+r)/(q+s)}.
@interaction[(require math) @interaction[#:eval untyped-eval
(mediant 1/2 5/6)] (mediant 1/2 5/6)]
} }
@ -601,24 +707,24 @@ lowest term is the number @math-style{(p+r)/(q+s)}.
@; ---------------------------------------- @; ----------------------------------------
@section[#:tag "quadratics"]{The Quadratic Equation} @section[#:tag "quadratics"]{The Quadratic Equation}
@defproc[(quadratic-solutions [a Real] [b Real] [c Real]) (listof Real)]{ @defproc[(quadratic-solutions [a Real] [b Real] [c Real]) (Listof Real)]{
Returns a list of all real solutions to the equation @math-style{a x^2 + b x +c = 0}. Returns a list of all real solutions to the equation @math-style{a x^2 + b x +c = 0}.
@interaction[(require math) @interaction[#:eval untyped-eval
(quadratic-solutions 1 0 -1) (quadratic-solutions 1 0 -1)
(quadratic-solutions 1 2 1) (quadratic-solutions 1 2 1)
(quadratic-solutions 1 0 1)] (quadratic-solutions 1 0 1)]
} }
@defproc[(quadratic-integer-solutions [a Real] [b Real] [c Real]) (listof Integer)]{ @defproc[(quadratic-integer-solutions [a Real] [b Real] [c Real]) (Listof Integer)]{
Returns a list of all integer solutions to the equation @math-style{a x^2 + b x +c = 0}. Returns a list of all integer solutions to the equation @math-style{a x^2 + b x +c = 0}.
@interaction[(require math) @interaction[#:eval untyped-eval
(quadratic-integer-solutions 1 0 -1) (quadratic-integer-solutions 1 0 -1)
(quadratic-integer-solutions 1 0 -2)] (quadratic-integer-solutions 1 0 -2)]
} }
@defproc[(quadratic-natural-solutions [a Real] [b Real] [c Real]) (listof Natural)]{ @defproc[(quadratic-natural-solutions [a Real] [b Real] [c Real]) (Listof Natural)]{
Returns a list of all natural solutions to the equation @math-style{a x^2 + b x +c = 0}. Returns a list of all natural solutions to the equation @math-style{a x^2 + b x +c = 0}.
@interaction[(require math) @interaction[#:eval untyped-eval
(quadratic-natural-solutions 1 0 -1) (quadratic-natural-solutions 1 0 -1)
(quadratic-natural-solutions 1 0 -2)] (quadratic-natural-solutions 1 0 -2)]
} }
@ -642,61 +748,65 @@ Note that @math-style{g} is a primitive root if and only if @math-style{order(g)
where @math-style{phi} is Eulers totient. A group with a generator is called @emph{cyclic}. where @math-style{phi} is Eulers totient. A group with a generator is called @emph{cyclic}.
@defproc[(unit-group [n Natrual]) (listof Natural)]{ @defproc[(unit-group [n Integer]) (Listof Positive-Integer)]{
Returns a list of all elements of @math-style{Un}, the unit group modulo @racket[n]. Returns a list of all elements of @math-style{Un}, the unit group modulo @racket[n]. The
@interaction[(require math) modulus @racket[n] must be positive.
@interaction[#:eval untyped-eval
(unit-group 5) (unit-group 5)
(unit-group 6)] (unit-group 6)]
} }
@defproc[(order [x Natural] [n Natural]) natural?]{ @defproc[(order [x Integer] [n Integer]) Positive-Integer]{
Returns the order of @racket[x] in the group @math-style{Un}. Returns the order of @racket[x] in the group @math-style{Un}; both arguments must be positive.
Note: @racket[x] is in @math-style{Un} if and only if @racket[(gcd x n)] is 1. If @racket[x] and @racket[n] are not coprime, @racket[(order x n)] raises an error.
@interaction[(require math) @interaction[#:eval untyped-eval
(order 2 5) (order 2 5)
(order 2 6)] (order 2 6)]
} }
@defproc[(orders [n Natural]) (listof natural?)]{ @defproc[(orders [n Integer]) (Listf Positive-Integer)]{
Returns a list @racket[(list (order x0) (order x1) ...)] where Returns a list @racket[(list (order x0 n) (order x1 n) ...)] where
@racket[x0], @racket[x1], ... are the elements of @math-style{Un}. @racket[x0], @racket[x1], ... are the elements of @math-style{Un}.
@interaction[(require math racket) The modulus @racket[n] must be positive.
@interaction[#:eval untyped-eval
(orders 5) (orders 5)
(map (curryr order 5) (unit-group 5))] (map (curryr order 5) (unit-group 5))]
} }
@defproc[(primitive-root? [x Natural] [n Natural]) boolean?]{ @defproc[(primitive-root? [x Integer] [n Integer]) Boolean]{
Returns @racket[#t] if the element @racket[x] in @math-style{Un} is a primitive root modulo @racket[n], Returns @racket[#t] if the element @racket[x] in @math-style{Un} is a primitive root modulo @racket[n],
otherwise @racket[#f] is returned. An error is signaled if @racket[x] is not a member of @math-style{Un}. otherwise @racket[#f] is returned. An error is signaled if @racket[x] is not a member of @math-style{Un}.
@interaction[(require math) Both arguments must be positive.
@interaction[#:eval untyped-eval
(primitive-root? 1 5) (primitive-root? 1 5)
(primitive-root? 2 5) (primitive-root? 2 5)
(primitive-root? 5 5)] (primitive-root? 5 5)]
} }
@defproc[(exists-primitive-root? [n Natural]) boolean?]{ @defproc[(exists-primitive-root? [n Integer]) Boolean]{
Returns @racket[#t] if the group @math-style{Un} has a primitive root (i.e. it is cyclic), Returns @racket[#t] if the group @math-style{Un} has a primitive root (i.e. it is cyclic),
otherwise @racket[#f] is returned. otherwise @racket[#f] is returned.
In other words, @racket[#t] is returned if @racket[n] is one of In other words, @racket[#t] is returned if @racket[n] is one of
@math-style{1, 2, 4, p^e, 2*p^e} where @math-style{p} is an odd prime, @math-style{1, 2, 4, p^e, 2*p^e} where @math-style{p} is an odd prime,
and @racket[#f] otherwise. and @racket[#f] otherwise.
@interaction[(require math) The modulus @racket[n] must be positive.
@interaction[#:eval untyped-eval
(exists-primitive-root? 5) (exists-primitive-root? 5)
(exists-primitive-root? 6) (exists-primitive-root? 6)
(exists-primitive-root? 12)] (exists-primitive-root? 12)]
} }
@defproc[(primitive-root [n Natural]) (Union natural? #f)]{ @defproc[(primitive-root [n Integer]) (Union Natural #f)]{
Returns a primitive root of @math-style{Un} if one exists, Returns a primitive root of @math-style{Un} if one exists,
otherwise @racket[#f] is returned. otherwise @racket[#f] is returned. The modulus @racket[n] must be positive.
@interaction[(require math) @interaction[#:eval untyped-eval
(primitive-root 5) (primitive-root 5)
(primitive-root 6)] (primitive-root 6)]
} }
@defproc[(primitive-roots [n Natural]) (Listof natural?)]{ @defproc[(primitive-roots [n Integer]) (Listof Natural)]{
Returns a list of all primitive roots of @math-style{Un}. Returns a list of all primitive roots of @math-style{Un}. The modulus @racket[n] must be positive.
@interaction[(require math) @interaction[#:eval untyped-eval
(primitive-roots 3) (primitive-roots 3)
(primitive-roots 5) (primitive-roots 5)
(primitive-roots 6)] (primitive-roots 6)]