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))
(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
;; Library stuffs
mpfr-available?
@ -159,10 +168,12 @@
integer->bigfloat
rational->bigfloat
real->bigfloat
fl2->bigfloat
bigfloat->flonum
bigfloat->integer
bigfloat->rational
bigfloat->real
bigfloat->fl2
;; String conversion
bigfloat->string
string->bigfloat

View File

@ -1001,24 +1001,6 @@
(set! 0ary-funs (list* #'phi.bf #'epsilon.bf #'-max.bf #'-min.bf #'+min.bf #'+max.bf
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
;; 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"
"../flonum-syntax.rkt"
"../../bigfloat/bigfloat-struct.rkt")
"../flonum-syntax.rkt")
(provide fl2 bigfloat->fl2 fl2->real fl2->bigfloat
(provide fl2 fl2->real
fl2+ fl2- fl2*split-fl fl2* fl2/
flsqrt/error fl2sqrt)
@ -31,11 +30,6 @@ Discrete & Computational Geometry 18(3):305363, October 1997
[(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))
(define (fl2->real x2 x1)
(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))]
[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)))
(define (fl3->fl2 e3 e2 e1)
(values e3 (fl+ e2 e1)))

View File

@ -7,9 +7,10 @@
;;;
(: 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)
(= (remainder b a) 0))
(cond [(zero? a) #f]
[else (= (remainder b a) 0)]))
; DEF (Coprime, relatively prime)
; Two or more integers are called coprime, if their greatest common divisor is 1.

View File

@ -23,8 +23,12 @@
(provide (all-defined-out))
(: current-modulus-param (Parameterof Positive-Integer))
(define current-modulus-param (make-parameter 1))
(: current-modulus-param (Parameterof Integer Positive-Integer))
(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))
(begin-encourage-inline

View File

@ -107,8 +107,10 @@
; 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)
(unless (andmap positive? ns)
(raise-argument-error 'solve-chinese "(Listof Positive-Integer)" 1 as ns))
; the ns should be coprime
(let* ([n (apply * ns)]
[cs (map (λ: ([ni : Z]) (quotient n ni)) ns)]
@ -245,8 +247,11 @@
(prev-prime n-2)))]))
(: next-primes : Z N -> Zs)
(: next-primes : Z Z -> Zs)
(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)
(define (loop n primes-wanted)
(if (= primes-wanted 0)
@ -255,10 +260,13 @@
(if next
(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)
(cond
[(primes-wanted . < . 0) (raise-argument-error 'prev-primes "Natural" 1 m primes-wanted)]
[else
(: loop : Z Z -> Zs)
(define (loop n primes-wanted)
(if (= primes-wanted 0)
@ -267,13 +275,15 @@
(if prev
(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)
(cond [(n . < . 0) (raise-argument-error 'nth-prime "Natural" n)]
[else
(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.
; p is prime
(: quadratic-character : Integer Integer -> Integer)
(: quadratic-character : Integer Integer -> (U -1 0 1))
(define (quadratic-character 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)]
[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)
(define (quadratic-residue? a n)

View File

@ -1,8 +1,12 @@
#lang scribble/doc
#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
@ -13,107 +17,88 @@
"utils.rkt")
@(define untyped-eval (make-untyped-math-eval))
@interaction-eval[#:eval untyped-eval (require racket/list
racket/function)]
@(define math-style tt)
@(define math-eval
(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}
@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.
@defproc[(divides? [m Integer] [n Integer]) Boolean]{
Returns @racket[#t] if @racket[m] divides @racket[n], @racket[#f] otherwise.
Note: That a non-zero integer @racket[m] divides an integer @racket[n]
means there exists an integer @racket[k] such that m*k=n.
Formally, an integer @racket[m] divides an integer @racket[n] when there
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
(require math)
(divides? 2 9)]
(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], @racket[b], @racket[c] ...
returns a list of integers @racket[u], @racket[v], @racket[q] ...
such that @racket[gcd](@racket[a],@racket[b],@racket[c],...)
= @racket[au + bv + cw + ...]
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) ...)].
The greatest common divisor of 6 and 15 is 3.
@interaction[#:eval untyped-eval
@examples[#:eval untyped-eval
(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}}
@defproc[(coprime? [a Integer] [b Integer] ...) boolean?]{
Returns @racket[#t] if the integers @racket[a],@racket[b],... are coprime.
Note: A set of integers are considered coprime (also called relatively prime)
@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.
The numbers 2, 6, and, 15 are coprime.
@interaction[#:eval untyped-eval
@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],@racket[b],... are 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 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
(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}}
Given a list of integers @racket[as] and a list of coprime moduli @racket[ns]
the function @racket[solve-chinese] will return
the single natural solution @racket[x] in @racket[{0,...,n-1}]
to the equations
@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
@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],
and @racket[n1], ... are the elements of @racket[ns],
and @racket[n=n1*...*nk].
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
@ -122,57 +107,187 @@
(solve-chinese '(2 3 2) '(3 5 7))]
}
@defproc[(quadratic-residue? [a natural?] [n natural?]) boolean?]{
Returns @racket[#t] if @racket[a] is a quadratic residue modulo @racket[n],
otherwise @racket[#f] is returned.
@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.
A number @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}.
@interaction[(require math)
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)]
}
@defproc[(quadratic-character [a natural?] [p prime?]) (union -1 1)]{
Returns the values of the quadratic character modulo the prime @racket[p].
@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.
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)
(quadratic-character 0 4)
(quadratic-character 1 4)
(quadratic-character 2 4)
(quadratic-character 3 4)]
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}
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}
@defproc[(prime? [z Integer]) boolean?]{
Returns @racket[#t] if @racket[z] is a prime,
@racket[#f] otherwise.
@defproc[(prime? [z Integer]) Boolean]{
Returns @racket[#t] if @racket[z] is a prime, @racket[#f] otherwise.
Note: An integer @racket[z] is considered a prime, if the only
positive divisors of @racket[z] are @racket[1] and @racket[|z|].
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
(require racket/list)
(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?]{
@defproc[(odd-prime? [z Integer]) Boolean]{
Returns @racket[#t] if @racket[z] is a odd prime,
@racket[#f] otherwise.
@ -181,15 +296,15 @@ Returns @racket[#t] if @racket[z] is a odd prime,
(odd-prime? 3)]
}
@defproc[(nth-prime [n Natural]) natural?]{
Returns the n'th positive prime.
@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[(next-prime [z Integer]) prime?]{
@defproc[(next-prime [z Integer]) Integer]{
Returns the first prime larger than @racket[z].
@interaction[#:eval untyped-eval
@ -197,7 +312,7 @@ Returns the first prime larger than @racket[z].
(next-prime 5)]
}
@defproc[(prev-prime [z Integer]) prime?]{
@defproc[(prev-prime [z Integer]) Integer]{
Returns the first prime smaller than @racket[z].
@interaction[#:eval untyped-eval
@ -205,21 +320,21 @@ Returns the first prime smaller than @racket[z].
(prev-prime 5)]
}
@defproc[(next-primes [z Integer] [n Natural]) (Listof prime?)]{
Returns list of the next @racket[n] primes larger than @racket[z].
@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 Natural]) (Listof prime?)]{
Returns list of the next @racket[n] primes smaller than @racket[z].
@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)]
}
@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].
The factorization consists of a list of corresponding
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)]
}
@defproc[(defactorize [f (Listof (List prime? natural?))]) natural?]{
@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].
@ -247,7 +362,7 @@ The divisors appear in ascending order.
(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
@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)]
}
@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
@racket[z].
@ -268,11 +383,10 @@ Returns a list of the exponents of in a factorization of the integer
@; ----------------------------------------
@section[#:tag "roots"]{Roots}
@defproc[(integer-root [n Natural] [m Natural]) natural?]{
Returns the @racket[m]'th integer root of @racket[n].
@defproc[(integer-root [n Natural] [m Natural]) Natural]{
Returns the @racket[m]th integer root of @racket[n].
This is the largest number @racket[r] such that
@racket[r^m<=n].
@racket[(expt r m) <= n].
@interaction[#:eval untyped-eval
(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])
(values natural? natural?)]{
Returns two values. The first, @racket[r], is the @racket[m]'th
(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
@ -293,11 +407,11 @@ integer root of @racket[n]. The second is @racket[n-r^m].
@; ----------------------------------------
@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
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].
@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])
(Union (List natural? natural?) #f)]{
(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[b^n = m]
@racket[b] and @racket[n] such that @racket[(expt b n) = m]
is returned, otherwise @racket[#f] is returned.
@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,
otherwise @racket[#f].
@ -328,8 +442,8 @@ otherwise @racket[#f].
@defproc[(prime-power [m Natural])
(Union (List prime? natural?) #f)]{
If @racket[m] is a power of the form @racket[p^n]
(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.
@ -339,7 +453,7 @@ prime and the exponent is returned, otherwise
(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,
otherwise @racket[#f].
@ -350,7 +464,7 @@ otherwise @racket[#f].
(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,
otherwise @racket[#f].
@ -361,9 +475,9 @@ otherwise @racket[#f].
}
@defproc[(as-power [m Positive-Integer])
(values natural? natural?)]{
(values Natural Natural)]{
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
(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])
(Union natural? #f)]{
Returns @racket[sqrt(m)] if @racket[m] is perfect
(U Natural #f)]{
Returns @racket[(sqrt m)] if @racket[m] is perfect
square, otherwise @racket[#f].
@interaction[#:eval untyped-eval
@ -385,42 +499,28 @@ square, otherwise @racket[#f].
@; ----------------------------------------
@section[#:tag "multiplicative"]{Multiplicative Functions}
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].
The functions @racket[totient], @racket[moebius-mu], and,
@racket[divisor-sum] are multiplicative.
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?]{
@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.
Note: The function @racket[totient] is multiplicative.
@interaction[#:eval untyped-eval
(require racket/function) ; for curry
(totient 9)
(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}}
@defproc[(moebius-mu [n Natural]) (U -1 0 1)]{
Returns:
@racket[1] if @racket[n] is a product of an even number of primes
@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.
@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))
@ -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}}
@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
all divisors of @racket[n].
Note: The function @racket[divisor-sum] is multiplicative.
@interaction[#:eval untyped-eval
(divisor-sum 12 2)
(apply + (map sqr (divisors 12)))]
@ -446,55 +544,58 @@ Note: The function @racket[divisor-sum] is multiplicative.
@section[#:tag "number-sequences"]{Number Sequences}
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Bernoulli_number"]{Bernoulli Number}}
@defproc[(bernoulli [n Natural]) exact-rational?]{
Returns the @racket[n]th Bernoulli number.
@defproc[(bernoulli [n Integer]) Exact-Rational]{
Returns the @racket[n]th Bernoulli number; @racket[n] must be nonnegative.
@interaction[#:eval untyped-eval
(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}}
@defproc[(eulerian-number [n Natural] [k Natural]) natural?]{
Returns the Eulerian number @math-style{<n,k>}.
@defproc[(eulerian-number [n Integer] [k Integer]) Natural]{
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)]
}
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Fibonacci_number"]{Fibonacci Number}}
@defproc[(fibonacci [n Natural]) natural?]{
Returns the @racket[n]th 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[(require math racket)
@interaction[#:eval untyped-eval
(map fibonacci (range 10))]
}
@defproc[(fibonacci/mod [n Natural] [m Natural]) natural?]{
Returns the @racket[n]th Fibonacci number modulo @racket[m].
@defproc[(fibonacci/mod [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[(require math racket)
@interaction[#:eval untyped-eval
(map (λ (n) (fibonacci/mod n 5)) (range 10))]
}
@defproc[(farey [n Natural]) (listof rational?)]{
Returns a list of the numbers in the @racket[n]th Farey sequence.
@defproc[(farey [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[(require math)
@interaction[#:eval untyped-eval
(farey 1)
(farey 2)
(farey 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.
@defproc[(tangent-number [n Integer]) Integer]{
Returns the @racket[n]th tangent number; @racket[n] must be nonnegative.
@interaction[(require math)
@interaction[#:eval untyped-eval
(tangent-number 1)
(tangent-number 2)
(tangent-number 3)]
@ -504,50 +605,55 @@ Returns the @racket[n]th tangent number.
@; ----------------------------------------
@section[#:tag "combinatorics"]{Combinatorics}
@defproc[(factorial [n Natural]) natural?]{
Returns the factorial of @racket[n].
The factorial of @racket[n] is the
number @math-style{n!=n*(n-1)*(n-2)*...*1}.
@interaction[(require math racket)
@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)]
}
@defproc[(binomial [n Natural] [k Natural]) natural?]{
Returns @racket[n] choose @racket[k].
The binomial coeffecient is given by
@math-style{C(n,k)=n!/(n!(n-k)!)}.
@interaction[(require math racket)
@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)]
}
@defproc[(permutations [n Natural] [k Natural]) natural?]{
Returns the number of @racket[k]-permutations of @racket[n].
That is the number of sequences of length @racket[k] where the
elements are drawn from a set with @racket[n] elements.
@math-style{P(n,k)=n!/(n-k)!}.
@interaction[(require math racket)
@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)]
}
@defproc[(multinomial [n Natural] [ks (Listof Natural)]) natural?]{
Returns the multinomial coeffecient.
The expression @racket[(multinomial n (list k0 k1 ...))]
returns the number @math-style{n! / (k0! * k1! * ...)}.
@defproc[(multinomial [n Integer] [ks (Listof Integer)]) Natural]{
A generalization of @racket[binomial] to multiple sets of choices; i.e.
@racket[(multinomial n (list k0 k1))] is the number of ways to choose a set of @racket[k0] items
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)]
}
@margin-note{Wikipedia: @hyperlink["http://en.wikipedia.org/wiki/Partition_(number_theory)"]{Partition}}
@defproc[(partition-count [n Natural]) natural?]{
Returns the number of partitions of @racket[n].
@defproc[(partition-count [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 @math-style{1+1+1, 1+2, 3}.
@interaction[(require math racket)
The number 3 has the partitions @racket[(+ 1 1 1)], @racket[(+ 1 2)] and @racket[(+ 3)].
@interaction[#:eval untyped-eval
(partition-count 3)
(partition-count 4)]
}
@ -558,12 +664,12 @@ Returns the @racket[n]th tangent number.
@subsection{Polygonal Numbers}
@defproc[(triangle? [n Natural]) boolean?]{}
@defproc[(square? [n Natural]) boolean?]{}
@defproc[(pentagonal? [n Natural]) boolean?]{}
@defproc[(hexagonal? [n Natural]) boolean?]{}
@defproc[(heptagonal? [n Natural]) boolean?]{}
@defproc[(octagonal? [n Natural]) boolean?]{
@defproc[(triangle? [n Natural]) Boolean]{}
@defproc[(square? [n Natural]) Boolean]{}
@defproc[(pentagonal? [n Natural]) Boolean]{}
@defproc[(hexagonal? [n Natural]) Boolean]{}
@defproc[(heptagonal? [n Natural]) Boolean]{}
@defproc[(octagonal? [n Natural]) Boolean]{
The functions
@racket[triangle?], @racket[square?], @racket[pentagonal?],
@racket[hexagonal?],@racket[heptagonal?] and @racket[octagonal?]
@ -572,12 +678,12 @@ triangle, square, pentagonal, hexagonal, heptagonal and octogonal
respectively.
}
@defproc[(triangle [n Natural]) natural?]{}
@defproc[(sqr [n Natural]) natural?]{}
@defproc[(pentagonal [n Natural]) natural?]{}
@defproc[(hexagonal [n Natural]) natural?]{}
@defproc[(heptagonal [n Natural]) natural?]{}
@defproc[(octagonal [n Natural]) natural?]{
@defproc[(triangle [n Natural]) Natural]{}
@defproc[(sqr [n Natural]) Natural]{}
@defproc[(pentagonal [n Natural]) Natural]{}
@defproc[(hexagonal [n Natural]) Natural]{}
@defproc[(heptagonal [n Natural]) Natural]{}
@defproc[(octagonal [n Natural]) Natural]{
The functions @racket[triangle], @racket[sqr], @racket[pentagonal],
@racket[hexagonal],@racket[heptagonal] and @racket[octagonal]
return the @racket[n]th polygonal number of the corresponding
@ -588,11 +694,11 @@ type of polygonal number.
@; ----------------------------------------
@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].
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[(require math)
@interaction[#:eval untyped-eval
(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}
@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}.
@interaction[(require math)
@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)]{
@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[(require math)
@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)]{
@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[(require math)
@interaction[#:eval untyped-eval
(quadratic-natural-solutions 1 0 -1)
(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}.
@defproc[(unit-group [n Natrual]) (listof Natural)]{
Returns a list of all elements of @math-style{Un}, the unit group modulo @racket[n].
@interaction[(require math)
@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[(order [x Natural] [n Natural]) natural?]{
Returns the order of @racket[x] in the group @math-style{Un}.
Note: @racket[x] is in @math-style{Un} if and only if @racket[(gcd x n)] is 1.
@interaction[(require math)
@defproc[(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[(order x n)] raises an error.
@interaction[#:eval untyped-eval
(order 2 5)
(order 2 6)]
}
@defproc[(orders [n Natural]) (listof natural?)]{
Returns a list @racket[(list (order x0) (order x1) ...)] where
@defproc[(orders [n Integer]) (Listf Positive-Integer)]{
Returns a list @racket[(list (order x0 n) (order x1 n) ...)] where
@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)
(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],
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? 2 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),
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.
@interaction[(require math)
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 Natural]) (Union natural? #f)]{
@defproc[(primitive-root [n Integer]) (Union Natural #f)]{
Returns a primitive root of @math-style{Un} if one exists,
otherwise @racket[#f] is returned.
@interaction[(require math)
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 Natural]) (Listof natural?)]{
Returns a list of all primitive roots of @math-style{Un}.
@interaction[(require math)
@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)]