racket/collects/math/private/number-theory/divisibility.rkt
Neil Toronto 1e52736089 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'
2012-11-17 21:02:37 -09:00

62 lines
1.9 KiB
Racket

#lang typed/racket/base
(provide divides? coprime? pairwise-coprime? bezout)
;;;
;;; DIVISIBILITY
;;;
(: divides? : Integer Integer -> Boolean)
; a divides b <=> exists unique k s.t. a*k=b
(define (divides? a b)
(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.
; a, b and c coprime <=> gcd(a,b,c)=1
(: coprime? : Integer Integer * -> Boolean)
(define (coprime? a . bs)
(= 1 (apply gcd (cons a bs))))
(: pairwise-coprime? : Integer Integer * -> Boolean)
(define (pairwise-coprime? a . bs)
(or (null? bs)
(and (andmap (λ: ([b : Integer]) (coprime? a b)) bs)
(apply pairwise-coprime? bs))))
; THEOREM (Bezout's identity)
; If a and b are integers (not both zero), then
; there exists integers u and v such that
; gcd(a,b) = au + bv
; Note: u and v are not unique
; (bezout-binary a b) = (list u v) <=> gcd(a,b) = au + bv
(: bezout-binary : Integer Integer -> (List Integer Integer))
(define (bezout-binary a b)
(: loop : Integer Integer Integer Integer Integer Integer -> (List Integer Integer))
(define (loop a b ua va ub vb) ; a>=b>0 , a = ua*a+ub*b, b = ub*a+ub*b
(let ([r (remainder a b)]
[q (quotient a b)])
(if (= r 0)
(list ub vb)
(loop b r ub vb (- ua (* q ub)) (- va (* q vb))))))
(if (> a b)
(loop a b 1 0 0 1)
(loop b a 0 1 1 0)))
; (bezout a b c ...) -> (list u v w ...) <=> gcd(a,b,c,...) = au + bv + cw + ...
(: bezout : Integer Integer * -> (Listof Integer))
(define (bezout a . bs)
(cond
[(null? bs) (list 1)]
[(null? (cdr bs)) (bezout-binary a (car bs))]
[else
(let ([uvs (apply bezout bs)]
[st (bezout-binary (apply gcd bs) a)])
(let ([s (car st)]
[t (cadr st)])
(cons t (map (lambda: ([u : Integer]) (* s u))
uvs))))]))