
renamed `partition-count' to `partitions' to be consistent with `permutations', and gave better examples in `multinomial' docs * (flulp-error +inf.0 +nan.0) was returning +nan.0 instead of +inf.0 * Type of `multinomial' didn't match its docs or `flmultinomial' * Reworded docs for `diagonal-array' * Reworked/reordered quite a few things in docs for `math/bigfloat' * Fixed first identity given in `gamma-inc' docs * Fixed descrption for `+max.0', etc.
890 lines
35 KiB
Racket
890 lines
35 KiB
Racket
#lang scribble/manual
|
|
@(require (for-label racket/flonum
|
|
racket/fixnum
|
|
racket/unsafe/ops
|
|
racket/require
|
|
racket/base
|
|
(only-in typed/racket/base
|
|
Integer Exact-Rational Boolean Listof Natural U List
|
|
Positive-Integer)
|
|
math)
|
|
scribble/extract
|
|
scribble/eval
|
|
scribble/base
|
|
scribble/manual
|
|
racket/sandbox
|
|
racket/math
|
|
"utils.rkt")
|
|
|
|
@(define untyped-eval (make-untyped-math-eval))
|
|
@interaction-eval[#:eval untyped-eval (require racket/list
|
|
racket/function)]
|
|
|
|
@(define math-style tt)
|
|
|
|
@title[#:tag "number-theory"]{Number Theory}
|
|
@(author-jens-axel)
|
|
|
|
@defmodule[math/number-theory]
|
|
|
|
@local-table-of-contents[]
|
|
|
|
@; ----------------------------------------
|
|
@section[#:tag "congruences"]{Congruences and Modular Arithmetic}
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Divisor"]{Divisor}}
|
|
@defproc[(divides? [m Integer] [n Integer]) Boolean]{
|
|
Returns @racket[#t] if @racket[m] divides @racket[n], @racket[#f] otherwise.
|
|
|
|
Formally, an integer @racket[m] divides an integer @racket[n] when there
|
|
exists a unique integer @racket[k] such that @racket[(* m k) = n].
|
|
|
|
@examples[#:eval untyped-eval
|
|
(divides? 2 9)
|
|
(divides? 2 8)]
|
|
|
|
Note that @racket[0] cannot divide anything:
|
|
@interaction[#:eval untyped-eval
|
|
(divides? 0 5)
|
|
(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}}
|
|
@defproc[(bezout [a Integer] [b Integer] [c Integer] ...) (Listof Integer)]{
|
|
Given integers @racket[a b c ...] returns a list of integers @racket[(list u v w ...)]
|
|
such that @racket[(gcd a b c ...) = (+ (* a u) (* b v) (* c w) ...)].
|
|
|
|
@examples[#:eval untyped-eval
|
|
(bezout 6 15)
|
|
(+ (* -2 6) (* 1 15))
|
|
(gcd 6 15)]
|
|
}
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Coprime"]{Coprime}}
|
|
@defproc[(coprime? [a Integer] [b Integer] ...) Boolean]{
|
|
Returns @racket[#t] if the integers @racket[a b ...] are coprime.
|
|
Formally, a set of integers is considered coprime (also called relatively prime)
|
|
if their greatest common divisor is 1.
|
|
|
|
@examples[#:eval untyped-eval
|
|
(coprime? 2 6 15)]
|
|
}
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Pairwise_coprime"]{Pairwise Coprime}}
|
|
@defproc[(pairwise-coprime? [a Integer] [b Integer] ...) Boolean]{
|
|
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 coprime, but not @italic{pairwise} coprime, because 2 and 6 share the
|
|
factor 3:
|
|
@interaction[#:eval untyped-eval
|
|
(pairwise-coprime? 2 6 15)]
|
|
}
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Chinese_remainder_theorem"]{Chinese Remainder Theorem}}
|
|
@defproc[(solve-chinese [as (Listof Integer)] [ns (Listof Integer)]) Natural]{
|
|
Given a length-@racket[k] list of integers @racket[as] and a length-@racket[k] list of coprime
|
|
moduli @racket[ns], @racket[(solve-chinese as ns)] returns the least natural number @racket[x]
|
|
that is a solution to the equations
|
|
|
|
@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]} ")")]
|
|
|
|
The solution @racket[x] is less than
|
|
@racket[(* #,(elem @racket[n] @subscript{1}) ... #,(elem @racket[n] @subscript{@racket[k]}))].
|
|
|
|
The moduli @racket[ns] must all be positive.
|
|
|
|
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
|
|
when divided by 7 leaves a remainder of 2?
|
|
@interaction[#:eval untyped-eval
|
|
(solve-chinese '(2 3 2) '(3 5 7))]
|
|
}
|
|
|
|
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Quadratic_residue"]{Quadratic Residue}}
|
|
@defproc[(quadratic-residue? [a Integer] [n Integer]) Boolean]{
|
|
Returns @racket[#t] if @racket[a] is a quadratic residue modulo @racket[n], otherwise @racket[#f].
|
|
The modulus @racket[n] must be positive, and @racket[a] must be nonnegative.
|
|
|
|
Formally, @racket[a] is a quadratic residue modulo @racket[n] if there
|
|
exists a number @racket[x] such that @racket[(* x x) = a] (mod @racket[n]).
|
|
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? 1 4)
|
|
(quadratic-residue? 2 4)
|
|
(quadratic-residue? 3 4)]
|
|
}
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Legendre_symbol"]{Legendre Symbol}}
|
|
@defproc[(quadratic-character [a Integer] [p Integer]) (U -1 0 1)]{
|
|
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
|
|
@racket[a] is a quadratic 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 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.
|
|
|
|
This function is also known as the @emph{Legendre symbol}.
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(quadratic-character 0 5)
|
|
(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}
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Modular_arithmetic"]{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 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}
|
|
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Prime_number"]{Prime Number}}
|
|
@defproc[(prime? [z Integer]) Boolean]{
|
|
Returns @racket[#t] if @racket[z] is a prime, @racket[#f] otherwise.
|
|
|
|
Formally, an integer @racket[z] is prime when the only positive divisors of @racket[z]
|
|
are @racket[1] and @racket[(abs z)].
|
|
|
|
The positive primes below 20 are:
|
|
@interaction[#:eval untyped-eval
|
|
(filter prime? (range 1 21))]
|
|
The corresponding negative primes are:
|
|
@interaction[#:eval untyped-eval
|
|
(filter prime? (range 1 -21 -1))]
|
|
}
|
|
|
|
@defproc[(odd-prime? [z Integer]) Boolean]{
|
|
Returns @racket[#t] if @racket[z] is a odd prime,
|
|
@racket[#f] otherwise.
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(odd-prime? 2)
|
|
(odd-prime? 3)]
|
|
}
|
|
|
|
@defproc[(nth-prime [n Integer]) Natural]{
|
|
Returns the @racket[n]th positive prime; @racket[n] must be nonnegative.
|
|
@interaction[#:eval untyped-eval
|
|
(nth-prime 0)
|
|
(nth-prime 1)
|
|
(nth-prime 2)]
|
|
}
|
|
|
|
@defproc[(random-prime [n Integer]) Natural]{
|
|
Returns a random prime smaller than @racket[n], which must be greater than @racket[2].
|
|
|
|
The function @racket[random-prime] picks random numbers
|
|
below @racket[n] until a prime is found.
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(random-prime 10)
|
|
(random-prime 10)
|
|
(random-prime 10)]
|
|
}
|
|
|
|
@defproc[(next-prime [z Integer]) Integer]{
|
|
Returns the first prime larger than @racket[z].
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(next-prime 4)
|
|
(next-prime 5)]
|
|
}
|
|
|
|
@defproc[(prev-prime [z Integer]) Integer]{
|
|
Returns the first prime smaller than @racket[z].
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(prev-prime 4)
|
|
(prev-prime 5)]
|
|
}
|
|
|
|
@defproc[(next-primes [z Integer] [n Integer]) (Listof Integer)]{
|
|
Returns list of the next @racket[n] primes larger than @racket[z]; @racket[n] must be nonnegative.
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(next-primes 2 4)]
|
|
}
|
|
|
|
@defproc[(prev-primes [z Integer] [n Integer]) (Listof Integer)]{
|
|
Returns list of the next @racket[n] primes smaller than @racket[z]; @racket[n] must be nonnegative.
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(prev-primes 13 4)]
|
|
}
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Integer_factorization"]{Integer Factorization}}
|
|
@defproc[(factorize [n Natural]) (Listof (List Natural Natural))]{
|
|
Returns the factorization of a natural number @racket[n].
|
|
The factorization consists of a list of corresponding
|
|
primes and exponents. The primes will be in ascending order.
|
|
|
|
The prime factorization of 600 = 2^3 * 3^1 * 5^2:
|
|
@interaction[#:eval untyped-eval
|
|
(factorize 600)]
|
|
}
|
|
|
|
@defproc[(defactorize [f (Listof (List Natural Natural))]) Natural]{
|
|
Returns the natural number, whose factorization is given
|
|
by @racket[f]. The factorization @racket[f] is represented
|
|
as described in @racket[factorize].
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(defactorize '((2 3) (3 1) (5 2)))]
|
|
}
|
|
|
|
@defproc[(divisors [z Integer]) (Listof Natural)]{
|
|
Returns a list of all positive divisors of the integer @racket[z].
|
|
The divisors appear in ascending order.
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(divisors 120)
|
|
(divisors -120)]
|
|
}
|
|
|
|
@defproc[(prime-divisors [z Natural]) (Listof Natural)]{
|
|
Returns a list of all positive prime divisors of the integer
|
|
@racket[z]. The divisors appear in ascending order.
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(prime-divisors 120)]
|
|
}
|
|
|
|
@defproc[(prime-exponents [z Natural]) (Listof Natural)]{
|
|
Returns a list of the exponents of in a factorization of the integer
|
|
@racket[z].
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(define z (* 2 2 2 3 5 5))
|
|
(prime-divisors z)
|
|
(prime-exponents z)]
|
|
}
|
|
|
|
@; ----------------------------------------
|
|
@section[#:tag "roots"]{Roots}
|
|
|
|
@defproc[(integer-root [n Natural] [m Natural]) Natural]{
|
|
Returns the @racket[m]th integer root of @racket[n].
|
|
This is the largest integer @racket[r] such that
|
|
@racket[(expt r m) <= n].
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(integer-root (expt 3 4) 4)
|
|
(integer-root (+ (expt 3 4) 1) 4)]
|
|
}
|
|
|
|
@defproc[(integer-root/remainder [n Natural] [m Natural])
|
|
(values Natural Natural)]{
|
|
Returns two values. The first, @racket[r], is the @racket[m]th
|
|
integer root of @racket[n]. The second is @racket[n-r^m].
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(integer-root/remainder (expt 3 4) 4)
|
|
(integer-root/remainder (+ (expt 3 4) 1) 4)]
|
|
}
|
|
|
|
|
|
@; ----------------------------------------
|
|
@section[#:tag "powers"]{Powers}
|
|
|
|
@defproc[(max-dividing-power [a Integer] [b Integer]) Natural]{
|
|
Returns the largest exponent, @racket[n], of a power with
|
|
base @racket[a] that divides @racket[b].
|
|
|
|
That is, @racket[(expt a n)] divides @racket[b] but @racket[(expt a (+ n 1))] does not divide
|
|
@racket[b].
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(max-dividing-power 3 (expt 3 4))
|
|
(max-dividing-power 3 5)]
|
|
}
|
|
|
|
@defproc[(perfect-power [m Integer])
|
|
(U (List Natural Natural) #f)]{
|
|
If @racket[m] is a perfect power, a list with two elements
|
|
@racket[b] and @racket[n] such that @racket[(expt b n) = m]
|
|
is returned, otherwise @racket[#f] is returned.
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(perfect-power (expt 3 4))
|
|
(perfect-power (+ (expt 3 4) 1))]
|
|
}
|
|
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Perfect_power"]{Perfect Power}}
|
|
@defproc[(perfect-power? [m Integer]) Boolean]{
|
|
Returns @racket[#t] if @racket[m] is a perfect power,
|
|
otherwise @racket[#f].
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(perfect-power? (expt 3 4))
|
|
(perfect-power? (+ (expt 3 4) 1))]
|
|
}
|
|
|
|
|
|
@defproc[(prime-power [m Natural])
|
|
(U (List Natural Natural) #f)]{
|
|
If @racket[m] is a power of the form @racket[(expt p n)]
|
|
where @racket[p] is prime, then a list with the
|
|
prime and the exponent is returned, otherwise
|
|
@racket[#f] is returned.
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(prime-power (expt 3 4))
|
|
(prime-power (expt 6 4))]
|
|
}
|
|
|
|
@defproc[(prime-power? [m Natural]) Boolean]{
|
|
Returns @racket[#t] if @racket[m] is a prime power,
|
|
otherwise @racket[#f].
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(prime-power? (expt 3 4))
|
|
(prime-power? (expt 6 4))
|
|
(prime-power? 1)
|
|
(prime-power? 0)]
|
|
}
|
|
|
|
@defproc[(odd-prime-power? [m Natural]) Boolean]{
|
|
Returns @racket[#t] if @racket[m] is a power of an odd prime,
|
|
otherwise @racket[#f].
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(odd-prime-power? (expt 2 4))
|
|
(odd-prime-power? (expt 3 4))
|
|
(odd-prime-power? (expt 15 4))]
|
|
}
|
|
|
|
@defproc[(as-power [m Positive-Integer])
|
|
(values Natural Natural)]{
|
|
Returns two values @racket[b] and @racket[n]
|
|
such that @racket[m = (expt b n)] and @racket[n] is maximal.
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(as-power (* (expt 2 4) (expt 3 4)))
|
|
(expt 6 4)
|
|
(* (expt 2 4) (expt 3 4))
|
|
(as-power (* (expt 2 4) (expt 3 5)))]
|
|
}
|
|
|
|
@defproc[(perfect-square [m Natural])
|
|
(U Natural #f)]{
|
|
Returns @racket[(sqrt m)] if @racket[m] is perfect
|
|
square, otherwise @racket[#f].
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(perfect-square 9)
|
|
(perfect-square 10)]
|
|
}
|
|
|
|
@; ----------------------------------------
|
|
@section[#:tag "multiplicative"]{Multiplicative Functions}
|
|
|
|
The functions in this section are @deftech{multiplicative}.
|
|
In number theory, a multiplicative function is a function @racket[f] such that
|
|
@racket[(f a b) = (* (f a) (f b))] for all coprime natural numbers @racket[a] and @racket[b].
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Euler%27s_totient_function"]{Euler's Totient}}
|
|
@defproc[(totient [n Natural]) Natural]{
|
|
Returns the number of integers from 1 to @racket[n]
|
|
that are coprime with @racket[n].
|
|
|
|
This function is known as Eulers totient or phi function.
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(totient 9)
|
|
(length (filter (curry coprime? 9) (range 10)))]
|
|
}
|
|
|
|
@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:
|
|
@itemlist[@item{@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}]
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(moebius-mu (* 2 3 5))
|
|
(moebius-mu (* 2 3 5 7))
|
|
(moebius-mu (* 2 2 3 5 7))]
|
|
}
|
|
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Divisor_function"]{Divisor Function}}
|
|
@defproc[(divisor-sum [n Natural] [k Natural]) Natural]{
|
|
Returns sum of the @racket[k]th powers of
|
|
all divisors of @racket[n].
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(divisor-sum 12 2)
|
|
(apply + (map sqr (divisors 12)))]
|
|
}
|
|
|
|
@margin-note{OEIS: @hyperlink["http://oeis.org/A001222"]{Big Omega}}
|
|
@defproc[(prime-omega [n Natural]) natural?]{
|
|
Counting multiplicities the number of prime factors of @racket[n] is returned.
|
|
|
|
Note: The function @racket[prime-omega] is multiplicative.
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(prime-omega (* 2 2 2 3 3 5))]
|
|
}
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Von_Mangoldt_function"]{Von Mangoldt Function}}
|
|
@defproc[(mangoldt-lambda [n Natural]) Real]{
|
|
The von Mangoldt function.
|
|
If @racket[n=p^k] for a prime @racket[p] and an integer @racket[k>=1] then @racket[(log n)] is returned.
|
|
Otherwise 0 is returned.
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(mangoldt-lambda (* 3 3))
|
|
(log 3)]
|
|
}
|
|
|
|
|
|
|
|
@; ----------------------------------------
|
|
@section[#:tag "number-sequences"]{Number Sequences}
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Bernoulli_number"]{Bernoulli Number}}
|
|
@defproc[(bernoulli-number [n Integer]) Exact-Rational]{
|
|
Returns the @racket[n]th Bernoulli number; @racket[n] must be nonnegative.
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(map bernoulli-number (range 9))]
|
|
|
|
Note that these are the @italic{first} Bernoulli numbers, since @racket[(bernoulli-number 1) = -1/2].
|
|
}
|
|
|
|
@margin-note{MathWorld: @hyperlink["http://mathworld.wolfram.com/EulerianNumber.html"]{Eulerian Number}}
|
|
@defproc[(eulerian-number [n Integer] [k Integer]) Natural]{
|
|
Returns the Eulerian number @math-style{<n,k>}; both arguments must be nonnegative.
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(eulerian-number 5 2)]
|
|
}
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Fibonacci_number"]{Fibonacci Number}}
|
|
@defproc[(fibonacci [n Integer]) Natural]{
|
|
Returns the @racket[n]th Fibonacci number; @racket[n] must be nonnegative.
|
|
|
|
The ten first Fibonacci numbers.
|
|
@interaction[#:eval untyped-eval
|
|
(map fibonacci (range 10))]
|
|
}
|
|
|
|
@defproc[(make-fibonacci [a Integer] [b Integer]) (Integer -> Integer)]{
|
|
Returns a function representing @italic{a} Fibonacci sequence with the first two numbers
|
|
@racket[a] and @racket[b]. The @racket[fibonacci] function is defined as
|
|
@racket[(make-fibonacci 0 1)].
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://wikipedia.org/wiki/Lucas_number"]{Lucas Number}}
|
|
The Lucas numbers are defined as a Fibonacci sequence starting with 2 and 1:
|
|
@interaction[#:eval untyped-eval
|
|
(map (make-fibonacci 2 1) (range 10))]
|
|
}
|
|
|
|
@defproc[(modular-fibonacci [n Integer] [m Integer]) Natural]{
|
|
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.
|
|
@interaction[#:eval untyped-eval
|
|
(map (λ (n) (modular-fibonacci n 5)) (range 10))]
|
|
}
|
|
|
|
@defproc[(make-modular-fibonacci [a Integer] [b Integer]) (Integer Integer -> Integer)]{
|
|
Like @racket[make-fibonacci], but makes a modular Fibonacci sequence.
|
|
}
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Farey_sequence"]{Farey Sequence}}
|
|
@defproc[(farey-sequence [n Integer]) (Listof Exact-Rational)]{
|
|
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
|
|
completely reduced rational numbers from 0 to 1 which denominators
|
|
are less than or equal to @racket[n].
|
|
@interaction[#:eval untyped-eval
|
|
(farey-sequence 1)
|
|
(farey-sequence 2)
|
|
(farey-sequence 3)]
|
|
}
|
|
|
|
@margin-note{MathWorld: @hyperlink["http://mathworld.wolfram.com/TangentNumber.html"]{Tangent Number}}
|
|
@defproc[(tangent-number [n Integer]) Integer]{
|
|
Returns the @racket[n]th tangent number; @racket[n] must be nonnegative.
|
|
|
|
@interaction[#:eval untyped-eval
|
|
(tangent-number 1)
|
|
(tangent-number 2)
|
|
(tangent-number 3)]
|
|
}
|
|
|
|
|
|
@; ----------------------------------------
|
|
@section[#:tag "combinatorics"]{Combinatorics}
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Factorial"]{Factorial}}
|
|
@defproc[(factorial [n Integer]) Natural]{
|
|
Returns the factorial of @racket[n], which must be nonnegative.
|
|
The factorial of @racket[n] is the number @racket[(* n (- n 1) (- n 2) ... 1)].
|
|
@interaction[#:eval untyped-eval
|
|
(factorial 3)
|
|
(factorial 0)]
|
|
}
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Binomial_coefficient"]{Binomial Coefficient}}
|
|
@defproc[(binomial [n Integer] [k Integer]) Natural]{
|
|
Returns the number of ways to choose a @italic{set} of @racket[k] items from a set of
|
|
@racket[n] items; i.e. the order of the @racket[k] items is not significant.
|
|
Both arguments must be nonnegative.
|
|
|
|
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)]
|
|
}
|
|
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Permutation#Permutations_in_combinatorics"]{
|
|
Permutations}}
|
|
@defproc[(permutations [n Integer] [k Integer]) Natural]{
|
|
Returns the number of ways to choose a @italic{sequence} of @racket[k] items from a set of
|
|
@racket[n] items; i.e. the order of the @racket[k] items is significant.
|
|
Both arguments must be nonnegative.
|
|
|
|
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)]
|
|
}
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Multinomial_theorem#Multinomial_coefficients"]{Multinomial Coeffecient}}
|
|
@defproc[(multinomial [n Integer] [ks (Listof Integer)]) Natural]{
|
|
A generalization of @racket[binomial] to multiple sets of choices; e.g.
|
|
@racket[(multinomial n (list k0 k1 k2))] is the number of ways to choose a set of @racket[k0] items,
|
|
a set of @racket[k1] items, and a set of @racket[k2] items from a set of @racket[n] items.
|
|
All arguments must be nonnegative.
|
|
|
|
When @racket[(apply + ks) = n], this is equivalent to
|
|
@racket[(apply / (factorial n) (map factorial ks))]. Otherwise, @racket[multinomial] returns @racket[0].
|
|
@interaction[#:eval untyped-eval
|
|
(multinomial 5 '(3 2))
|
|
(= (multinomial 8 '(5 3))
|
|
(binomial 8 5)
|
|
(binomial 8 3))
|
|
(multinomial 10 '(5 3 2))
|
|
(multinomial 0 '())
|
|
(multinomial 4 '(1 1))]
|
|
}
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Partition_(number_theory)"]{Partition}}
|
|
@defproc[(partitions [n Integer]) Natural]{
|
|
Returns the number of partitions of @racket[n], which must be nonnegative.
|
|
A partition of a positive integer @racket[n] is a way
|
|
of writing @racket[n] as a sum of positive integers.
|
|
The number 3 has the partitions @racket[(+ 1 1 1)], @racket[(+ 1 2)] and @racket[(+ 3)].
|
|
@interaction[#:eval untyped-eval
|
|
(partitions 3)
|
|
(partitions 4)]
|
|
}
|
|
|
|
|
|
@; ----------------------------------------
|
|
@section[#:tag "special_numbers"]{Special Numbers}
|
|
|
|
@subsection{Polygonal Numbers}
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Polygonal_number"]{Polygonal Number}}
|
|
@deftogether[
|
|
(@defproc[(triangle-number? [n Natural]) Boolean]
|
|
@defproc[(square-number? [n Natural]) Boolean]
|
|
@defproc[(pentagonal-number? [n Natural]) Boolean]
|
|
@defproc[(hexagonal-number? [n Natural]) Boolean]
|
|
@defproc[(heptagonal-number? [n Natural]) Boolean]
|
|
@defproc[(octagonal-number? [n Natural]) Boolean])]{
|
|
These functions check whether the input is a polygonal number of the types
|
|
triangle, square, pentagonal, hexagonal, heptagonal and octogonal
|
|
respectively.
|
|
}
|
|
|
|
@deftogether[
|
|
(@defproc[(triangle-number [n Natural]) Natural]
|
|
@defproc[(sqr [n Natural]) Natural]
|
|
@defproc[(pentagonal-number [n Natural]) Natural]
|
|
@defproc[(hexagonal-number [n Natural]) Natural]
|
|
@defproc[(heptagonal-number [n Natural]) Natural]
|
|
@defproc[(octagonal-number [n Natural]) Natural])]{
|
|
These functions return the @racket[n]th polygonal number
|
|
of the corresponding type of polygonal number.
|
|
}
|
|
|
|
|
|
@; ----------------------------------------
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Mediant_(mathematics)"]{Mediant}}
|
|
@section[#:tag "fractions"]{Fractions}
|
|
@defproc[(mediant [x Exact-Rational] [y Exact-Rational]) Exact-Rational]{
|
|
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
|
|
lowest term is the number @math-style{(p+r)/(q+s)}.
|
|
@interaction[#:eval untyped-eval
|
|
(mediant 1/2 5/6)]
|
|
}
|
|
|
|
|
|
|
|
@; ----------------------------------------
|
|
@section[#:tag "quadratics"]{The Quadratic Equation}
|
|
|
|
@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}.
|
|
@interaction[#:eval untyped-eval
|
|
(quadratic-solutions 1 0 -1)
|
|
(quadratic-solutions 1 2 1)
|
|
(quadratic-solutions 1 0 1)]
|
|
}
|
|
|
|
@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}.
|
|
@interaction[#:eval untyped-eval
|
|
(quadratic-integer-solutions 1 0 -1)
|
|
(quadratic-integer-solutions 1 0 -2)]
|
|
}
|
|
|
|
@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}.
|
|
@interaction[#:eval untyped-eval
|
|
(quadratic-natural-solutions 1 0 -1)
|
|
(quadratic-natural-solutions 1 0 -2)]
|
|
}
|
|
|
|
|
|
|
|
@; ----------------------------------------
|
|
@section[#:tag "primitive_roots"]{The group Zn and Primitive Roots}
|
|
|
|
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Multiplicative_group_of_integers_modulo_n"]{
|
|
The Group Zn}}
|
|
The numbers @math-style{0, 1, ..., n-1} with addition and multiplication
|
|
modulo @racket[n] is a ring called @math-style{Zn}.
|
|
|
|
The group of units in @math-style{Zn} with respect to multiplication
|
|
modulo @racket[n] is called @math-style{Un}.
|
|
|
|
The order of an element @math-style{x} in @math-style{Un}
|
|
is the least @math-style{k>0} such that @math-style{x^k=1 mod n}.
|
|
|
|
A generator the group @math-style{Un} is called a @emph{primitive root} modolo @racket[n].
|
|
Note that @math-style{g} is a primitive root if and only if @math-style{order(g)=phi(n)},
|
|
where @math-style{phi} is Eulers totient. A group with a generator is called @emph{cyclic}.
|
|
|
|
|
|
@defproc[(unit-group [n Integer]) (Listof Positive-Integer)]{
|
|
Returns a list of all elements of @math-style{Un}, the unit group modulo @racket[n]. The
|
|
modulus @racket[n] must be positive.
|
|
@interaction[#:eval untyped-eval
|
|
(unit-group 5)
|
|
(unit-group 6)]
|
|
}
|
|
|
|
@defproc[(unit-group-order [x Integer] [n Integer]) Positive-Integer]{
|
|
Returns the order of @racket[x] in the group @math-style{Un}; both arguments must be positive.
|
|
If @racket[x] and @racket[n] are not coprime, @racket[(unit-group-order x n)] raises an error.
|
|
@interaction[#:eval untyped-eval
|
|
(unit-group-order 2 5)
|
|
(unit-group-order 2 6)]
|
|
}
|
|
|
|
@defproc[(unit-group-orders [n Integer]) (Listf Positive-Integer)]{
|
|
Returns a list @racket[(list (unit-group-order x0 n) (unit-group-order x1 n) ...)] where
|
|
@racket[x0], @racket[x1], ... are the elements of @math-style{Un}.
|
|
The modulus @racket[n] must be positive.
|
|
@interaction[#:eval untyped-eval
|
|
(unit-group-orders 5)
|
|
(map (curryr unit-group-order 5) (unit-group 5))]
|
|
}
|
|
|
|
@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],
|
|
otherwise @racket[#f] is returned. An error is signaled if @racket[x] is not a member of @math-style{Un}.
|
|
Both arguments must be positive.
|
|
@interaction[#:eval untyped-eval
|
|
(primitive-root? 1 5)
|
|
(primitive-root? 2 5)
|
|
(primitive-root? 5 5)]
|
|
}
|
|
|
|
@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),
|
|
otherwise @racket[#f] is returned.
|
|
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,
|
|
and @racket[#f] otherwise.
|
|
The modulus @racket[n] must be positive.
|
|
@interaction[#:eval untyped-eval
|
|
(exists-primitive-root? 5)
|
|
(exists-primitive-root? 6)
|
|
(exists-primitive-root? 12)]
|
|
}
|
|
|
|
@defproc[(primitive-root [n Integer]) (Union Natural #f)]{
|
|
Returns a primitive root of @math-style{Un} if one exists,
|
|
otherwise @racket[#f] is returned. The modulus @racket[n] must be positive.
|
|
@interaction[#:eval untyped-eval
|
|
(primitive-root 5)
|
|
(primitive-root 6)]
|
|
}
|
|
|
|
@defproc[(primitive-roots [n Integer]) (Listof Natural)]{
|
|
Returns a list of all primitive roots of @math-style{Un}. The modulus @racket[n] must be positive.
|
|
@interaction[#:eval untyped-eval
|
|
(primitive-roots 3)
|
|
(primitive-roots 5)
|
|
(primitive-roots 6)]
|
|
}
|
|
|
|
|
|
@(close-eval untyped-eval)
|
|
|