
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'
62 lines
1.9 KiB
Racket
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))))]))
|