#lang racket

;; -----------------------------------------------------------------------------
;; the macro approach 
(module macro-server racket
  
  (provide
   ;; syntax: (make-p number? (number? ...) (number? ...))
   ;; in (make-p a0 (a ...) (x ...)) must be of equal length
   ;; the result is a newton polynomial
   make-p)
  
  (define-syntax-rule
    (make-p a0 (a ...) (x ...))
    (lambda (y)
      (+ a0 (newton y 1 (a ...) (x ...)))))
  
  (define-syntax newton
    (syntax-rules ()
      [(_ y factor () ()) 0]
      [(_ y factor (a1 a ...) (x1 x ...))
       (let ((delta (* factor (- y x1))))
         (+ (* a1 delta) (newton y delta (a ...) (x ...))))])))

(module macro-client racket
  (require (submod ".." macro-server) plot rackunit)
  
  (define ((make-p-0 a0))
    (define (p x)
      (+ a0))
    p)
  
  (check-equal? [plot (function (make-p 1 () ())) #:x-min -10 #:x-max +10]
                [plot (function ((make-p-0 1))) #:x-min -10 #:x-max +10])
  
  (define ((make-p-1 a0 a1) x0)
    (define (p x)
      (+ a0
         (* a1 (- x x0))))
    p)
  
  (check-equal? [plot (function (make-p 1 (2) (3))) #:x-min -10 #:x-max +10]
                [plot (function ((make-p-1 1 2) 3)) #:x-min -10 #:x-max +10])
  
  (define ((make-p-2 a0 a1 a2) x0 x1)
    (define (p x)
      (+ a0
         (* a1 (- x x0))
         (* a2 (- x x0) (- x x1))))
    p)
  
  (check-equal?
   [plot (function (make-p 1 (2 3) (3 4))) #:x-min -10 #:x-max +10]
   [plot (function ((make-p-2 1 2 3) 3 4)) #:x-min -10 #:x-max +10])
  
  (define ((make-p-3 a0 a1 a2 a3) x0 x1 x2)
    (define (p x)
      (+ a0
         (* a1 (- x x0))
         (* a2 (- x x0) (- x x1))
         (* a3 (- x x0) (- x x1) (- x x2))))
    p)
  
  (check-equal?
   [plot (function (make-p 1 (2 3 4) (3 4 5))) #:x-min -10 #:x-max +10] 
   [plot (function ((make-p-3 1 2 3 4) 3 4 5)) #:x-min -10 #:x-max +10])
  )

;; -----------------------------------------------------------------------------
;; the functional approach

(module server racket
  (provide
   (contract-out
    (make-p
     ;; compute the newton polynomial 
     (->d ((a0 number?))
          ()
          #:rest a* (listof number?)
          (_r (->d ()
                   ()
                   #:rest x* (and/c (listof number?)
                                    (lambda (a*)
                                      (= (length x*) (length a*))))
                   (_s (-> number? number?))))))))
  
  (define ((make-p a0 . a*) . x*)
    (define (p y)
      (define-values (sum _)
        (for/fold ([sum a0][factor 1]) ([a a*][x x*])
          (define delta (* factor (- y x)))
          (values (+ sum (* a delta)) delta)))
      sum)
    p))

(module client racket
  (require (submod ".." server))
  (require plot rackunit)
  
  (define ((make-p-0 a0))
    (define (p x)
      (+ a0))
    p)
  
  (check-equal? [plot (function ((make-p 1))) #:x-min -10 #:x-max +10]
                [plot (function ((make-p-0 1))) #:x-min -10 #:x-max +10])
  
  (define ((make-p-1 a0 a1) x0)
    (define (p x)
      (+ a0
         (* a1 (- x x0))))
    p)
  
  (check-equal? [plot (function ((make-p 1 2) 3)) #:x-min -10 #:x-max +10]
                [plot (function ((make-p-1 1 2) 3)) #:x-min -10 #:x-max +10])
  
  (define ((make-p-2 a0 a1 a2) x0 x1)
    (define (p x)
      (+ a0
         (* a1 (- x x0))
         (* a2 (- x x0) (- x x1))))
    p)
  
  (check-equal?
   [plot (function ((make-p 1 2 3) 3 4)) #:x-min -10 #:x-max +10]
   [plot (function ((make-p-2 1 2 3) 3 4)) #:x-min -10 #:x-max +10])
  
  (define ((make-p-3 a0 a1 a2 a3) x0 x1 x2)
    (define (p x)
      (+ a0
         (* a1 (- x x0))
         (* a2 (- x x0) (- x x1))
         (* a3 (- x x0) (- x x1) (- x x2))))
    p)
  
  (check-equal?
   [plot (function ((make-p 1 2 3 4) 3 4 5)) #:x-min -10 #:x-max +10] 
   [plot (function ((make-p-3 1 2 3 4) 3 4 5)) #:x-min -10 #:x-max +10])
  
  )

(require 'client 'macro-client)

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to