# sicp-ex-1.29

``` (define (round-to-next-even x)
(+ x (remainder x 2)))
```
``` (define (simpson f a b n)
(define fixed-n (round-to-next-even n))
(define h (/ (- b a) fixed-n))
(define (simpson-term k)
(define y (f (+ a (* k h))))
(if (or (= k 0) (= k fixed-n))
(* 1 y)
(if (even? k)
(* 2 y)
(* 4 y))))
(* (/ h 3) (sum simpson-term 0 inc fixed-n)))
```

This is a similar solution, complete with testing code. There is no rounding of n to the next even number, because the exercise assumes n to be even.

``` ;; ex 1.29

(define (cube x) (* x x x))

(define (inc n) (+ n 1))

(define (sum term a next b)
(if (> a b)
0
(+ (term a)
(sum term (next a) next b))))

(define (simpson-integral f a b n)
(define h (/ (- b a) n))
(define (yk k) (f (+ a (* h k))))
(define (simpson-term k)
(* (cond ((or (= k 0) (= k n)) 1)
((odd? k) 4)
(else 2))
(yk k)))
(* (/ h 3) (sum simpson-term 0 inc n)))

;; Testing
(simpson-integral cube 0 1 100)
(simpson-integral cube 0 1 1000)
```

There is a third way which approaches the solution by breaking the problem into four parts: (f y0), (f yn) and two sums,one over even k and another over odd k.

```
(define (another-simpson-integral f a b n)
(define h (/ (- b a) n))
(define (add-2h x) (+ x (* 2 h)))
(* (/ h 3.0) (+ (f a)
(* 4.0 (sum f (+ a h) add-2h b))
(f b))))
```

Here's a version that sums over pairs of terms (2 y_k + 4 y_k+1). No conditionals or special cases are needed anywhere, but there's an extra term [f(b) - f(a)] to be added to the final count.

``` (define (simpson f a b n)
(define h (/ (- b a) n))

(define (y k)
(f (+ a (* k h))))

(define (ypair k)
(+ (* 2 (y k))
(* 4 (y (+ k 1)))))

(+ k 2))

(* (/ h 3) (+ (sum ypair 0 add-2 (- n 1))
(- (f b) (f a)))))
```
``` (define (sim-integral f a b n)
(define h (/ (- a b) n))
(define (y k) (f (+ a (* k h))))
(define (coeff k) (if (is-even? k) 2 4))
(define (part-term k) (* (coeff k) (y k)))
(define part-value (sum part-term 1 inc (- n 1)))
(* (/ h 3) (+ (y 0) (y n) part-value)))
```

Another solution in GNU Guile:

``` ;;;; Under Creative Commons Attribution-ShareAlike 4.0
;;;; International. See

(define-module (net ricketyspace sicp one twentynine)
#:export (simpson))

(define (sum term a next b)
(if (> a b)
0
(+ (term a)
(sum term (next a) next b))))

(define (simpson f a b n)
(let* ((h (/ (- b a) (* 1.0 n)))
(y (lambda (k) (+ a (* k h))))
(ce (lambda (k) ;coefficient
(cond ((or (= k 0) (= k n)) 1)
((even? k) 2)
(else 4))))
(term (lambda (k)
(* (ce k) (f (y k)))))
(next (lambda (k) (1+ k))))
(* (/ h 3.0)
(sum term 0 next n))))

;;; Guile REPL
;;; scheme@(guile-user)> ,use (net ricketyspace sicp one twentynine)
;;; scheme@(guile-user)> (define (cube x) (* x x x))
;;; scheme@(guile-user)> (simpson cube 0 1 100)
;;; \$23 = 0.24999999999999992
;;; scheme@(guile-user)> (simpson cube 0 1 1000)
;;; \$24 = 0.2500000000000003
```

While testing the integral example presented before the ex 1.29 I had some problems for small dx [;Aborting!: maximum recursion depth exceeded]. So I tried a iterative version :

``` (define (sum-iter ans foo a next b)
(if (> a b)
ans
(sum-iter (+ ans (foo a)) foo (next a) next b)))
```

Using sum-iter in Simpson Integral definition:

``` (define (simpson-integral foo a b n)
(define  h (/ (- b a) n))
(define (y k) (foo (+ a (* k h))))
(define (intersimp k) (* (cond ((or (= k 0) (= k n)) 1)
((even? k) 2)
(else 4))
(y k)))
(define (inc a) (+ a 1))
(* (sum-iter 0 intersimp 0 inc n ) (/ h 3.0))
)
```