#lang racket
(require racket/math)
(provide deriv 2pi -2pi integrate)
(module+ test
(require rackunit)
(define epsilon .001))
(define dx 0.001)
(define -2pi (* -2 pi))
(define 2pi (* 2 pi))
;; compute the derivative of `f' at the given point `x'
(define (deriv f x)
(/ (- (f (+ x dx)) (f x)) dx))
;; Integrate a function from 0 to x (using tail recursion)
(define (integrate f x)
(define (loop y acc)
(if (> y x)
(* acc dx)
(loop (+ y dx) (+ acc (f y)))))
(loop 0 0))
(module+ test
(check-= (integrate cos (/ pi 4)) (sin (/ pi 4)) epsilon))
;; Generate a bunch of numerical tests
;; use a for loop (generalizes let)
(module+ test
(define test-points (build-list 20 (lambda (x) (* 2 pi (random)))))
(define (sin2 x) (integrate cos x))
(define (cos2 x) (deriv sin x))
(for ([x test-points])
(check-= (sin x) (sin2 x) epsilon)
(check-= (cos x) (cos2 x) epsilon)))
(define (integrate2 f x)
(* dx
(for/fold
([acc 0])
([y (in-range 0 x dx)])
(+ acc (f y)))))
(module+ test
(for ([x test-points])
(check-= (integrate cos x) (integrate2 cos x) epsilon)))