(define (make-complex a b)
  (if (and (real? a) (real? b))
      (cons "complex" (cons a b))
      'error ) )

(define (complex? x)
  (if (pair? x)
      (if (eqv? (first x) "complex")
          #t
          #f )
      #f ) )

(define (real-part x)
  (if (complex? x)
      (cadr x)
      'error ) )

(define (imaginary-part x)
  (if (complex? x)
      (cddr x)
      'error ) )

(define (pure-real? x)
  (if (and (complex? x)
           (= (imaginary-part x) 0.0) )
      #t
      #f ) )

(define (pure-imaginary? x)
  (if (and (complex? x) 
           (= (real-part x) 0.0) )
      #t
      #f ) )

(define (conjugate x)
  (if (complex? x)
      (make-complex (real-part x)
                    (- (imaginary-part x)))
      'error ) )

(define (add-complex x y)
  (if (and (complex? x) (complex? y))
      (make-complex (+ (real-part x)
                       (real-part y))
                    (+ (imaginary-part x)
                       (imaginary-part y)) )
      'error ) )

(define (sub-complex x y)
  (if (and (complex? x) (complex? y))
      (make-complex (- (real-part x)
                       (real-part y))
                    (- (imaginary-part x)
                       (imaginary-part y)) )
      'error ) )

(define (mul-complex x y)
  (if (and (complex? x) (complex? y))
      (make-complex (- (* (real-part x)
                          (real-part y))
                       (* (imaginary-part x)
                          (imaginary-part y)) )
                    (+ (* (real-part x)
                          (imaginary-part y))
                       (* (imaginary-part x)
                          (real-part y)) ) )
      'error ) )

(define (div-complex x y)
  (let ((m (modulus y)))
       (if (and (complex? x) (complex? y) (not (= m 0.0)))
           (make-complex (/ (+ (* (real-part x)
                                  (real-part y))
                               (* (imaginary-part x)
                                  (imaginary-part y)) )
                            (square m) )
                         (/ (- (* (imaginary-part x)
                                  (real-part y))
                               (* (real-part x)
                                  (imaginary-part y)) )
                            (square m) ) )
           'error ) ) )

(define (modulus x)
  (sqrt (real-part (mul-complex x (conjugate x)))) )

(define (eqv-complex? x y)
  (if (and (complex? x) (complex? y))
      (and (eqv? (real-part x) (real-part y))
           (eqv? (imaginary-part x) (imaginary-part y)) )
      'error ) )

(define (print-complex x)
  (if (complex? x)
      (begin (print (string->symbol "[ "))
             (print (real-part x))
             (print (string->symbol " + "))
             (print (imaginary-part x))
             (print (string->symbol " I]"))
             (newline) )
      'error ) )

(define I (make-complex 0.0 1.0))

(define (real->complex x)
  (if (real? x)
      (make-complex x 0.0)
      'error ) )

(define (complex->real x)
  (if (and (complex? x) (pure-real? x))
      (real-part x)
      'error ) )
