Continued fraction/Arithmetic/G(matrix ng, continued fraction n): Difference between revisions

Content added Content deleted
Line 4,724: Line 4,724:


=={{header|Scheme}}==
=={{header|Scheme}}==
===Translated from Racket===
{{trans|Racket}}
{{trans|Racket}}
{{works with|Gauche Scheme|0.9.12}}
{{works with|Gauche Scheme|0.9.12}}
Line 5,001: Line 5,002:
(1+sqrt(2))/2 => [1;4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,...]
(1+sqrt(2))/2 => [1;4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,...]
(2+sqrt(2))/4 = (1+1/sqrt(2))/2 => [0;1,5,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,...]</pre>
(2+sqrt(2))/4 = (1+1/sqrt(2))/2 => [0;1,5,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,...]</pre>

===Translated from ATS===
{{trans|ATS}}
{{works with|Gauche Scheme|0.9.12}}
{{works with|CHICKEN Scheme|5.3.0}}

For CHICKEN Scheme you need the '''r7rs''' egg.

This implementation memoizes terms of a continued fraction.

<syntaxhighlight lang="scheme">(cond-expand
(r7rs)
(chicken (import (r7rs))))

(define-library (continued-fraction)

(export make-continued-fraction
continued-fraction?
continued-fraction-ref
continued-fraction->thunk)
(export continued-fraction->string
continued-fraction-max-terms)

(import (scheme base)
(scheme case-lambda))

(begin

(define-record-type <cf-record>
;; terminated? -- are these all the terms there are?
;; m -- how many terms are memoized so far?
;; memo -- where terms are memoized.
;; gen -- a thunk that generates terms.
(cf-record terminated? m memo gen)
cf-record?
(terminated? cf-record-terminated?
set-cf-record-terminated?!)
(m cf-record-m set-cf-record-m!)
(memo cf-record-memo set-cf-record-memo!)
(gen cf-record-gen set-cf-record-gen!))

(define cf-record-memo-start-size 8)

(define (make-continued-fraction gen)
(cf-record #f 0 (make-vector cf-record-memo-start-size) gen))

(define continued-fraction? cf-record?)

;; The following is an updating operation, but nevertheless I
;; leave out the "!" from the name.
(define (continued-fraction-ref cf i)
(cf-update! cf (+ i 1))
(and (< i (cf-record-m cf))
(vector-ref (cf-record-memo cf) i)))

(define (cf-get-more-terms! cf needed)
(define (loop i)
(if (= i needed)
(begin
(set-cf-record-terminated?! cf #f)
(set-cf-record-m! cf needed))
(let ((term ((cf-record-gen cf))))
(if term
(begin
(vector-set! (cf-record-memo cf) i term)
(loop (+ i 1)))
(begin
(set-cf-record-terminated?! cf #t)
(set-cf-record-m! cf i))))))
(loop (cf-record-m cf)))

(define (cf-update! cf needed)
(cond ((cf-record-terminated? cf) cf)
((<= needed (cf-record-m cf)) cf)
((<= needed (vector-length (cf-record-memo cf)))
(cf-get-more-terms! cf needed))
(else
;; Provide twice the room that might be needed.
(let* ((n1 (+ needed needed))
(memo1 (make-vector n1)))
(vector-copy! memo1 0 (cf-record-memo cf))
(set-cf-record-memo! cf memo1)
(cf-get-more-terms! cf needed)))))

(define (continued-fraction->thunk cf)
;; Make a generator from a continued fraction.
(define i 0)
(lambda ()
(let ((term (continued-fraction-ref cf i)))
(set! i (+ i 1))
term)))

(define continued-fraction-max-terms (make-parameter 20))

;; The following is an updating operation, but nevertheless I
;; leave out the "!" from the name.
(define continued-fraction->string
(case-lambda
((cf) (continued-fraction->string
cf (continued-fraction-max-terms)))
((cf max-terms)
(let loop ((i 0)
(sep 0)
(accum "["))
(if (= i max-terms)
(string-append accum ",...]")
(let ((term (continued-fraction-ref cf i)))
(if (not term)
(string-append accum "]")
(let* ((term-str (number->string term))
(sep-str (case sep
((0) "")
((1) ";")
((2) ",")))
(accum (string-append accum sep-str
term-str))
(sep (min (+ sep 1) 2)))
(loop (+ i 1) sep accum)))))))))

)) ;; end library (continued-fraction)

(define-library (number->continued-fraction)

(export number->continued-fraction)

(import (scheme base))
(import (continued-fraction))

(begin

(define (number->continued-fraction x)
;; This algorithm works directly with exact rationals, rather
;; than numerator and denominator separately.
(unless (real? x)
(error "number->continued-fraction: argument must be real" x))
(let ((ratnum (exact x))
(terminated? #f))
(make-continued-fraction
(lambda ()
(and (not terminated?)
(let* ((q (floor ratnum))
(diff (- ratnum q)))
(if (zero? diff)
(set! terminated? #t)
(set! ratnum (/ diff)))
q))))))

)) ;; end library (number->continued-fraction)

(define-library (homographic-function)

(export make-homographic-function
homographic-function?
homographic-function-ref
homographic-function-set!
homographic-function-copy
apply-homographic-function
make-homographic-function-operator)

(import (scheme base)
(scheme case-lambda))
(import (continued-fraction))

(begin

(define-record-type <homographic-function>
(make-homographic-function a1 a b1 b)
homographic-function?
(a1 homographic-function-a1 set-homographic-function-a1!)
(a homographic-function-a set-homographic-function-a!)
(b1 homographic-function-b1 set-homographic-function-b1!)
(b homographic-function-b set-homographic-function-b!))

(define (homographic-function-ref hfunc i)
(case i
((0) (homographic-function-a1 hfunc))
((1) (homographic-function-a hfunc))
((2) (homographic-function-b1 hfunc))
((3) (homographic-function-b hfunc))
(else
(error "homographic-function-ref: index out of range" i))))

(define (homographic-function-set! hfunc i x)
(case i
((0) (set-homographic-function-a1! hfunc x))
((1) (set-homographic-function-a! hfunc x))
((2) (set-homographic-function-b1! hfunc x))
((3) (set-homographic-function-b! hfunc x))
(else
(error "homographic-function-set!: index out of range" i))))

(define (homographic-function-copy hfunc)
(make-homographic-function (homographic-function-ref hfunc 0)
(homographic-function-ref hfunc 1)
(homographic-function-ref hfunc 2)
(homographic-function-ref hfunc 3)))

(define (apply-homographic-function hfunc cf)
(define gen (continued-fraction->thunk cf))
(define state (homographic-function-copy hfunc))
(make-continued-fraction
(lambda ()
(let loop ()
(let ((a1 (homographic-function-ref state 0))
(a (homographic-function-ref state 1))
(b1 (homographic-function-ref state 2))
(b (homographic-function-ref state 3)))
(define (take-term)
(let ((term (gen)))
(if term
(set! state
(make-homographic-function
(+ a (* a1 term)) a1 (+ b (* b1 term)) b1))
(begin
(homographic-function-set! state 1 a1)
(homographic-function-set! state 3 b1)))))
(cond
((and (zero? b1) (zero? b)) #f)
((and (not (zero? b1)) (not (zero? b)))
(let ((q1 (floor-quotient a1 b1))
(q (floor-quotient a b)))
(if (= q1 q)
(begin
(set! state
(make-homographic-function
b1 b (- a1 (* b1 q)) (- a (* b q))))
q)
(begin
(take-term)
(loop)))))
(else
(take-term)
(loop))))))))

(define make-homographic-function-operator
(case-lambda
((hfunc) (lambda (cf)
(apply-homographic-function hfunc cf)))
((a1 a b1 b) (make-homographic-function-operator
(make-homographic-function a1 a b1 b)))))

)) ;; end library (number->continued-fraction)

(define-library (demonstration)

(export run-demonstration)

(import (scheme base)
(scheme write))
(import (continued-fraction)
(number->continued-fraction)
(homographic-function))

(begin

(define (run-demonstration)

(define cf+1/2 (make-homographic-function-operator 2 1 0 2))
(define cf/2 (make-homographic-function-operator 1 0 0 2))
(define cf/4 (make-homographic-function-operator 1 0 0 4))
(define 1/cf (make-homographic-function-operator 0 1 1 0))
(define 2+cf./4 (make-homographic-function-operator 1 2 0 4))
(define 1+cf./2 (make-homographic-function-operator 1 1 0 2))

(define cf:13/11 (number->continued-fraction 13/11))
(define cf:22/7 (number->continued-fraction 22/7))
(define cf:sqrt2
(let ((next-term 1))
(make-continued-fraction
(lambda ()
(let ((term next-term))
(set! next-term 2)
term)))))

(display-cf "13/11" cf:13/11)
(display-cf "22/7" cf:22/7)
(display-cf "sqrt(2)" cf:sqrt2)
(display-cf "13/11 + 1/2" (cf+1/2 cf:13/11))
(display-cf "22/7 + 1/2" (cf+1/2 cf:22/7))
(display-cf "(22/7)/4" (cf/4 cf:22/7))
(display-cf "sqrt(2)/2" (cf/2 cf:sqrt2))
(display-cf "1/sqrt(2)" (1/cf cf:sqrt2))
(display-cf "(2 + sqrt(2))/4" (2+cf./4 cf:sqrt2))
(display-cf "(1 + 1/sqrt(2))/2" (1+cf./2 (1/cf cf:sqrt2)))
(display-cf "sqrt(2)/4 + 1/2" (cf+1/2 (cf/4 cf:sqrt2)))
(display-cf "(sqrt(2)/2)/2 + 1/2" (cf+1/2 (cf/2 (cf/2 cf:sqrt2))))
(display-cf "(1/sqrt(2))/2 + 1/2" (cf+1/2 (cf/2 (1/cf cf:sqrt2)))))

(define (display-cf expr cf)
(display expr)
(display " => ")
(display (continued-fraction->string cf))
(newline))

)) ;; end library (demonstration)

(import (demonstration))
(run-demonstration)
</syntaxhighlight>

{{out}}
<pre>$ gosh univariate-continued-fraction-task.scm
13/11 + 1/2 => [1;1,2,7]
22/7 + 1/2 => [3;1,1,1,4]
(22/7)/4 => [0;1,3,1,2]
sqrt(2)/2 => [0;1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,...]
1/sqrt(2) => [0;1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,...]
(2 + sqrt(2))/4 => [0;1,5,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,...]
(1 + 1/sqrt(2))/2 => [0;1,5,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,...]
sqrt(2)/4 + 1/2 => [0;1,5,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,...]
(sqrt(2)/2)/2 + 1/2 => [0;1,5,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,...]
(1/sqrt(2))/2 + 1/2 => [0;1,5,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,...]</pre>


=={{header|Tcl}}==
=={{header|Tcl}}==