(in-package "RTL")

(include-book "projects/shnf/top" :dir :system)

(include-book "tripp")

;; Utility functions:

(defthm distinct-symbols-atom
  (implies (and (distinct-symbols vars)
                (member x vars))
           (atom x)))

(defthm all-integers-integer
  (implies (and (all-integers vals)
                (natp i)
                (< i (len vals)))
           (integerp (nth i vals)))
  :rule-classes (:type-prescription :rewrite))

(defthm all-integers-nthcdr
  (implies (all-integers vals)
           (all-integers (nthcdr n vals))))

(defthm nthcdr+
  (implies (and (natp m) (natp n))
           (equal (nthcdr m (nthcdr n x))
                  (nthcdr (+ m n) x))))

(defthm car-nthcdr
  (equal (car (nthcdr i l))
         (nth i l)))

(defthm consp-nthcdr
  (implies (and (natp i)
                (< i (len l)))
           (consp (nthcdr i l))))

(defthm member-len-pos
  (implies (= (len l) 0)
           (not (member x l))))

;;*********************************************************************************
;;                              Reducing SHNFs
;;*********************************************************************************

;; We now focus on the case of a polynomial in x0, y0, x1, y1, x2, and y2
;; under the assumption that for i = 0, 1, 2,

;;   mod(yi^2, p) = mod(xi^3 + a * xi^2 + xi, p)

;; In order to maximize the efficiency of rewrite, we order the variables
;; as follows:

(defun vars () '(y0 y1 y2 x0 x1 x2))

(defund vals () (list (y0) (y1) (y2) (x0) (x1) (x2)))

(defund vlist () (pairlis$ (vars) (vals)))

(in-theory (disable (vals) (vlist)))

(defthm all-integers-vals
  (all-integers (vals))
  :hints (("Goal" :in-theory (enable vals))))

(defthm len-vals
  (equal (len (vals)) 6)
  :hints (("Goal" :in-theory (enable vals))))

(defun evalp$ (x) (evalp x (vlist)))

(defun evalh$ (x) (evalh x (vals)))

;; We shall define a function reduce that converts such a polynomial to 
;; a SHNF and systematically rewrites the result according to these 
;; assumptions.

;; The guts of reduce is the function split.  Its arguments are as follows:
;;   (1) h is a SHNF
;;   (2) j is in {0,1,2), representing Yj
;;   (3) k is a nat
;; It returns a multiple value (mv h0 h1), where h0 and h1 are SHNFs that are
;; independent of Yj such that under the assumptions noted above,

;;     evalh(h, vals) = evalh(h0, vals) + evalh(Yj, vals) * evalh(h1, vals).

;; Note that according to the definition, when y is at the head of vars, split
;; effectively replaces y^2 with the value of

;;     (pop 3 (pow 1 (pow 1 (pow 1 1 486662) 1) 0),

;; which is xi^3 + a * xi^2 + xi when y = yi.

(defund theta () `(pop 3 (pow 1 (pow 1 (pow 1 1 ,(a)) 1) 0)))

(in-theory (disable (theta)))

(defthm shnfp-theta
  (shnfp (theta))
  :hints (("Goal" :in-theory (enable shnfp theta))))

(defthmd evalh-theta-0
  (equal (evalh (theta) (vals))
         (+ (expt (x0) 3)
            (* (a) (expt (x0) 2))
            (x0)))
  :hints (("Goal" :in-theory (enable theta vals) :expand ((:free (x v) (evalh x v))))))

(defthmd evalh-theta-1
  (equal (evalh (theta) (cdr (vals)))
         (+ (expt (x1) 3)
            (* (a) (expt (x1) 2))
            (x1)))
  :hints (("Goal" :in-theory (enable theta vals) :expand ((:free (x v) (evalh x v))))))

(defthmd evalh-theta-2
  (equal (evalh (theta) (cddr (vals)))
         (+ (expt (x2) 3)
            (* (a) (expt (x2) 2))
            (x2)))
  :hints (("Goal" :in-theory (enable theta vals) :expand ((:free (x v) (evalh x v))))))

(defthmd ecp-mod
  (implies (ecp r)
           (equal (mod (expt (y r) 2) (p))
                  (mod (+ (expt (x r) 3)
                          (* (a) (expt (x r) 2))
                          (x r))
                       (p))))
  :hints (("Goal" :in-theory (enable ecp))))

(defthmd theta-0-mod
  (equal (mod (evalh (theta) (vals)) (p))
         (mod (expt (y0) 2) (p)))
  :hints (("Goal" :expand ((:free (x v) (evalh x v)))
                  :in-theory (enable theta vals) 
                  :use (ecp-assumption
                        (:instance ecp-mod (r (p0)))))))

(defthmd theta-1-mod
  (equal (mod (evalh (theta) (cdr (vals))) (p))
         (mod (expt (y1) 2) (p)))
  :hints (("Goal" :expand ((:free (x v) (evalh x v)))
                  :in-theory (enable theta vals) 
                  :use (ecp-assumption
                        (:instance ecp-mod (r (p1)))))))

(defthmd theta-2-mod
  (equal (mod (evalh (theta) (cddr (vals))) (p))
         (mod (expt (y2) 2) (p)))
  :hints (("Goal" :expand ((:free (x v) (evalh x v)))
                  :in-theory (enable theta vals) 
                  :use (ecp-assumption
                        (:instance ecp-mod (r (p2)))))))
         
(defun split$ (h j k)
  (if (or (atom h) (< j k))
      (mv h 0)
    (if (eql (car h) 'pop)
        (let ((i (cadr h)) (p (caddr h)))
          (mv-let (p0 p1) (split$ p j (+ i k))
            (mv (norm-pop i p0) (norm-pop i p1))))
      (let ((i (cadr h)) (p (caddr h)) (q (cadddr h)))
        (mv-let (p0 p1) (split$ p j k)
          (mv-let (q0 q1) (split$ q j (1+ k))
            (if (= j k)
                (if (evenp i)
                    (mv (norm-add (norm-mul (norm-expt (theta) (/ i 2)) p0)
                                  (norm-pop 1 q0))
                        (norm-add (norm-mul (norm-expt (theta) (/ i 2)) p1)
                                  (norm-pop 1 q1)))
                  (mv (norm-add (norm-mul (norm-expt (theta) (/ (1+ i) 2)) p1)
                                (norm-pop 1 q0))
                      (norm-add (norm-mul (norm-expt (theta) (/ (1- i) 2)) p0) 
                                (norm-pop 1 q1))))
              (mv (norm-pow i p0 q0)
                  (norm-pow i p1 q1)))))))))

(local-defthmd split$-case-5-1
  (implies (and (natp k)
                (shnfp h)
                (consp h)
                (eql (car h) 'pow))
           (not (zp (cadr h))))
  :hints (("Goal" :use ((:instance shfp (x h))
                        (:instance shf-normp (x h)))
                  :in-theory (disable shfp shf-normp))))

(local-defthm split$-case-5-2
  (implies (and (shnfp h)
                (consp h)
                (eql (car h) 'pow))
           (natp (cadr h)))
  :hints (("Goal" :use ((:instance shfp (x h))
                        (:instance shf-normp (x h)))
                  :in-theory (disable shfp shf-normp)))
  :rule-classes (:type-prescription :rewrite))

(local-defthm split$-case-5-3
  (implies (and (natp k)
                (shnfp h)
                (consp h)
                (eql (car h) 'pow))
           (let ((p (caddr h)) (q (cadddr h)))
             (and (shnfp p)
                  (shnfp q))))
  :hints (("Goal" :use ((:instance shfp (x h))
                        (:instance shnfp (x h))
                        (:instance shf-normp (x h)))
                  :in-theory (disable shfp shf-normp))))

(local-defthm nthcdr-cdr
  (equal (nthcdr i (cdr l))
         (cdr (nthcdr i l))))

(local-defthmd cdr-nthcdr
  (implies (natp i)
           (equal (cdr (nthcdr i l))
                  (nthcdr (1+ i) l))))

(defun car0 (vals)
  (if (consp vals) (car vals) 0))

(defthm evalh-pow-rewrite
  (implies (eql (car x) 'pow)
           (equal (evalh x vals)
                  (+ (* (expt (car0 vals) (cadr x))
                        (evalh (caddr x) vals))
                     (evalh (cadddr x) (cdr vals))))))

(local-defthmd split$-case-5-4
  (implies (and (natp k)
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h)) (yk (car0 (nthcdr k (vals))))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
             (equal (evalh h (nthcdr k (vals)))
                    (+ (* (expt yk i) (evalh p nk))
                       (evalh q nk1)))))
  :hints (("Goal" :use ((:instance evalh-pow-rewrite (x h) (vals (nthcdr k (vals)))))
                  :in-theory (e/d (cdr-nthcdr) (evalh-pow-rewrite evalh)))))

(local-defthmd split$-case-5-5
  (implies (and (natp k)
                (< k 6)
                (shnfp h)
                (consp h)
                (eql (car h) 'pow))
           (integerp (car0 (nthcdr k (vals))))))

(local-defthm split$-case-5-6
  (implies (and (natp k)
                (< k 6)
                (shnfp h)
                (consp h)
                (eql (car h) 'pow))
           (integerp (expt (nth k (vals)) (cadr h))))
  :rule-classes (:type-prescription :rewrite)
  :hints (("Goal" :use (split$-case-5-5)
                  :in-theory (disable ALL-INTEGERS-INTEGER ALL-INTEGERS-VALS))))

(local-defthm split$-case-5-7
  (implies (and (natp k)
                (shnfp h)
                (consp h)
                (eql (car h) 'pow))
           (let ((p (caddr h)) (nk (nthcdr k (vals))))
             (integerp (evalh p nk))))
  :rule-classes (:type-prescription :rewrite))

(local-defthm split$-case-5-8
  (implies (and (natp k1)
                (shnfp h)
                (consp h)
                (eql (car h) 'pow))
           (let ((q (cadddr h)) (nk1 (nthcdr k1 (vals))))
             (integerp (evalh q nk1))))
  :rule-classes (:type-prescription :rewrite))

(local-defthmd split$-case-9
  (implies (and (natp k)
                (< k 6)
                (shnfp h)
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (p (caddr h)) (yk (car0 (nthcdr k (vals))))
                 (nk (nthcdr k (vals))))
             (integerp (* (expt yk i) (evalh p nk)))))
  :rule-classes (:type-prescription :rewrite))

(local-defthmd split$-case-5-10
  (implies (and (natp k)
                (< k 6)
                (shnfp h)
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h)) (yk (car0 (nthcdr k (vals))))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
             (equal (mod (evalh h nk) (p))
                    (mod (+ (mod (* (expt yk i) (mod (evalh p nk) (p))) (p))
                            (mod (evalh q nk1) (p)))
                         (p)))))
  :hints (("Goal" :in-theory (enable cdr-nthcdr) :use (split$-case-5-3))))

(local-defthmd split$-case-5-11
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (< k 6)
                (shnfp h)
                (not (< j k))
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h)) (yk (car0 (nthcdr k (vals))))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (implies (and (shnfp p0)
                                 (shnfp p1)
                                 (shnfp q0)
                                 (shnfp q1)
                                 (equal (mod (evalh p nk) (p))
                                        (mod (+ (evalh p0 nk)
                                                (* (nth j (vals))
                                                   (evalh p1 nk)))
                                             (p)))
                                 (equal (mod (evalh q nk1) (p))
                                        (mod (+ (evalh q0 nk1)
                                                (* (nth j (vals))
                                                   (evalh q1 nk1)))
                                             (p))))
                           (equal (mod (evalh h (nthcdr k (vals))) (p))
                                  (mod (+ (mod (* (expt yk i) (mod (+ (evalh p0 nk) (* (nth j (vals)) (evalh p1 nk))) (p))) (p))
                                          (mod (+ (evalh q0 nk1) (* (nth j (vals)) (evalh q1 nk1))) (p)))
                                       (p))))))))
  :hints (("Goal" :use (split$-case-5-10)
                  :in-theory (theory 'minimal-theory))))

(local-defthmd split$-case-5-12
  (implies (and (natp j)
                (<= j 2)
                (natp k)
                (< k 6)
                (shnfp h)
                (not (< j k))
                (consp h)
                (eql (car h) 'pow))
           (let ((p (caddr h)) (q (cadddr h)) (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (implies (and (shnfp p0)
                                 (shnfp p1)
                                 (shnfp q0)
                                 (shnfp q1))
                            (and (integerp (evalh p0 nk))
                                 (integerp (evalh p1 nk))
                                 (integerp (evalh q0 nk1))
                                 (integerp (evalh q1 nk1)))))))))

(local-defthmd split$-case-5-13
  (implies (and (natp j)
                (<= j 2))
           (integerp (nth j (vals)))))

(local-defthmd split$-case-5-14
  (implies (and (natp j)
                (<= j 2)
                (natp k)
                (< k 6)
                (shnfp h)
                (not (< j k))
                (consp h)
                (eql (car h) 'pow))
           (let ((p (caddr h)) (q (cadddr h)) (nk (nthcdr k (vals))))
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (implies (and (shnfp p0)
                                 (shnfp p1)
                                 (shnfp q0)
                                 (shnfp q1))
                            (integerp (+ (evalh p0 nk) (* (nth j (vals)) (evalh p1 nk)))))))))
  :hints (("Goal" :use (split$-case-5-12 split$-case-5-13)
                  :in-theory (disable integerp-evalh all-integers-vals))))

(local-defthmd split$-case-5-15
  (implies (and (natp k)
                (< k 6)
                (shnfp h)
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (yk (car0 (nthcdr k (vals)))))
             (integerp (expt yk i)))))

(local-defthm split$-case-5-16
  (implies (and (integerp x) (integerp y))
           (integerp (* x y)))
  :rule-classes ())

(local-defthmd split$-case-5-17
  (implies (and (natp j)
                (<= j 2)
                (natp k)
                (< k 6)
                (not (< j k))
                (shnfp h)
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h)) (yk (car0 (nthcdr k (vals)))) (nk (nthcdr k (vals))))
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (implies (and (shnfp p0)
                                 (shnfp p1)
                                 (shnfp q0)
                                 (shnfp q1))
                            (integerp (* (expt yk i) (+ (evalh p0 nk) (* (nth j (vals)) (evalh p1 nk))))))))))
  :hints (("Goal" :use (split$-case-5-14 split$-case-5-15
                        (:instance split$-case-5-16 (x (expt yk i)) (y (+ (evalh p0 nk) (* (nth j (vals)) (evalh p1 nk))))))
                  :in-theory (theory 'minimal-theory))))

(local-defthmd split$-case-5-18
  (implies (and (natp j)
                (<= j 2)
                (natp k)
                (< k 6)
                (shnfp h)
                (not (< j k))
                (consp h)
                (eql (car h) 'pow))
           (let ((p (caddr h)) (q (cadddr h)) (nk1 (nthcdr (1+ k) (vals))))
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (implies (and (shnfp p0)
                                 (shnfp p1)
                                 (shnfp q0)
                                 (shnfp q1))
                            (integerp (+ (evalh q0 nk1) (* (nth j (vals)) (evalh q1 nk1)))))))))
  :hints (("Goal" :use (split$-case-5-12 split$-case-5-13)
                  :in-theory (disable integerp-evalh all-integers-vals))))

(local-defthm split$-case-5-19
  (implies (and (integerp x) (integerp y) (integerp z))
           (equal (mod (+ (mod (* x (mod y (p))) (p))
                          (mod z (p)))
                       (p))
                  (mod (+ (* x y) z) (p))))
:rule-classes ())

(local-defthm split$-case-5-20
  (implies (and (natp j)
                (<= j 2)
                (natp k)
                (< k 6)
                (shnfp h)
                (not (< j k))
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h)) (yk (car0 (nthcdr k (vals))))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (implies (and (shnfp p0)
                                 (shnfp p1)
                                 (shnfp q0)
                                 (shnfp q1))
                           (equal (mod (+ (mod (* (expt yk i) (mod (+ (evalh p0 nk) (* (nth j (vals)) (evalh p1 nk))) (p))) (p))
                                          (mod (+ (evalh q0 nk1) (* (nth j (vals)) (evalh q1 nk1))) (p)))
                                       (p))
                                  (mod (+ (* (expt yk i) (+ (evalh p0 nk) (* (nth j (vals)) (evalh p1 nk))))
                                          (+ (evalh q0 nk1) (* (nth j (vals)) (evalh q1 nk1))))
                                       (p))))))))
  :hints (("Goal" :use (split$-case-5-14 split$-case-5-15 split$-case-5-17 split$-case-5-18
                        (:instance split$-case-5-19 (x (expt (car0 (nthcdr k (vals))) (cadr h)))
                                                    (y (+ (evalh (mv-nth 0 (split$ (caddr h) j k)) (nthcdr k (vals)))
                                                          (* (nth j (vals)) (evalh (mv-nth 1 (split$ (caddr h) j k)) (nthcdr k (vals))))))
                                                    (z (+ (evalh (mv-nth 0 (split$ (cadddr h) j (1+ k))) (nthcdr (1+ k) (vals)))
                                                          (* (nth j (vals))
                                                             (evalh (mv-nth 1 (split$ (cadddr h) j (1+ k))) (nthcdr (1+ k) (vals))))))))
                  :in-theory (theory 'minimal-theory))))

(local-defthmd split$-case-5-21
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (< k 6)
                (shnfp h)
                (not (< j k))
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h)) (yk (car0 (nthcdr k (vals))))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (implies (and (shnfp p0)
                                 (shnfp p1)
                                 (shnfp q0)
                                 (shnfp q1)
                                 (equal (mod (evalh p nk) (p))
                                        (mod (+ (evalh p0 nk)
                                                (* (nth j (vals))
                                                   (evalh p1 nk)))
                                             (p)))
                                 (equal (mod (evalh q nk1) (p))
                                        (mod (+ (evalh q0 nk1)
                                                (* (nth j (vals))
                                                   (evalh q1 nk1)))
                                             (p))))
                           (equal (mod (evalh h (nthcdr k (vals))) (p))
                                  (mod (+ (* (expt yk i) (+ (evalh p0 nk) (* (nth j (vals)) (evalh p1 nk))))
                                          (+ (evalh q0 nk1) (* (nth j (vals)) (evalh q1 nk1))))
                                       (p))))))))
  :hints (("Goal" :use (split$-case-5-11 split$-case-5-20)
                  :in-theory (theory 'minimal-theory))))

(local-defthm split$-case-5-22
  (implies (and (integerp x)
                (integerp y)
                (integerp p0)
                (integerp p1)
                (integerp q0)
                (integerp q1))
          (equal (+ (* x (+ p0 (* y p1))) (+ q0 (* y q1)))
                 (+ (+ (* x p0) q0)
                    (* y (+ (* x p1) q1)))))
  :rule-classes ())

(local-defthmd split$-case-5-23
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (< k 6)
                (shnfp h)
                (not (< j k))
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h)) (yk (car0 (nthcdr k (vals))))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (implies (and (shnfp p0)
                                 (shnfp p1)
                                 (shnfp q0)
                                 (shnfp q1)
                                 (equal (mod (evalh p nk) (p))
                                        (mod (+ (evalh p0 nk)
                                                (* (nth j (vals))
                                                   (evalh p1 nk)))
                                             (p)))
                                 (equal (mod (evalh q nk1) (p))
                                        (mod (+ (evalh q0 nk1)
                                                (* (nth j (vals))
                                                   (evalh q1 nk1)))
                                             (p))))
                           (equal (mod (evalh h (nthcdr k (vals))) (p))
                                  (mod (+ (+ (* (expt yk i) (evalh p0 nk)) (evalh q0 nk1))
                                          (* (nth j (vals)) 
                                             (+ (* (expt yk i) (evalh p1 nk)) (evalh q1 nk1))))
                                       (p))))))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-5-12 split$-case-5-13 split$-case-5-15 split$-case-5-21
                        (:instance split$-case-5-22 (x (expt (car0 (nthcdr k (vals))) (cadr h)))
                                                    (y (nth j (vals)))
                                                    (p0 (evalh (mv-nth 0 (split$ (caddr h) j k)) (nthcdr k (vals))))
                                                    (p1 (evalh (mv-nth 1 (split$ (caddr h) j k)) (nthcdr k (vals))))
                                                    (q0 (evalh (mv-nth 0 (split$ (cadddr h) j (1+ k))) (nthcdr (1+ k) (vals))))
                                                    (q1 (evalh (mv-nth 1 (split$ (cadddr h) j (1+ k))) (nthcdr (1+ k) (vals)))))))))

(local-defthmd split$-case-5-24
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (shnfp h)
                (not (< j k))
                (not (= j k))
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h)) (yk (car0 (nthcdr k (vals))))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
             (mv-let (h0 h1) (split$ h j k)
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (implies (and (shnfp p0)
                                 (shnfp p1)
                                 (shnfp q0)
                                 (shnfp q1))
                            (and (equal (+ (* (expt yk i) (evalh p0 nk)) (evalh q0 nk1))
                                        (evalh h0 nk))
                                 (equal (+ (* (expt yk i) (evalh p1 nk)) (evalh q1 nk1))
                                        (evalh h1 nk)))))))))
  :hints (("Goal" :use (split$-case-5-1) :in-theory (enable split$-case-5-4))))

(local-defthmd split$-case-5-25
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (shnfp h)
                (not (< j k))
                (consp h)
                (not (eql (car h) 'pop)))
           (let ((p (caddr h)) (q (cadddr h)))
             (mv-let (h0 h1) (split$ h j k)
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (and (eql (car h) 'pow)
                        (natp (+ 1 k))
                        (shnfp p)
                        (shnfp q)
                        (implies (and (shnfp p0)
                                      (shnfp p1)
                                      (shnfp q0)
                                      (shnfp q1))
                                 (and (shnfp h0)
                                      (shnfp h1)))))))))
  :hints (("goal" :expand ((shnfp h)) :use (split$-case-5-1))))

(local-defthm split$-case-5
  (implies (and (natp j)
                (<= j 2)
                (natp k)
                (shnfp h)
                (not (< j k))
                (not (= j k))
                (consp h)
                (not (eql (car h) 'pop)))
           (let ((p (caddr h)) (q (cadddr h))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
             (mv-let (h0 h1) (split$ h j k)
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (and (natp (+ 1 k))
                        (shnfp p)
                        (shnfp q)
                        (implies (and (shnfp p0)
                                      (shnfp p1)
                                      (shnfp q0)
                                      (shnfp q1)
                                      (equal (mod (evalh p nk) (p))
                                             (mod (+ (evalh p0 nk)
                                                     (* (nth j (vals))
                                                        (evalh p1 nk)))
                                                  (p)))
                                      (equal (mod (evalh q nk1) (p))
                                             (mod (+ (evalh q0 nk1)
                                                     (* (nth j (vals))
                                                        (evalh q1 nk1)))
                                                  (p))))
                                 (and (shnfp h0)
                                      (shnfp h1)
                                      (equal (mod (evalh h nk) (p))
                                             (mod (+ (evalh h0 nk)
                                                     (* (nth j (vals)) (evalh h1 nk)))
                                                  (p)))))))))))
  :hints (("Goal" :use (split$-case-5-23 split$-case-5-24 split$-case-5-25)
                  :expand ((split$ h j k))
                  :in-theory (theory 'minimal-theory))))

(local-defthm split$-case-4-1
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (shnfp h)
                (= j k))
           (equal (car0 (nthcdr k (vals)))
                  (nth j (vals)))))

(local (in-theory (disable car0)))

(local-defthm split$-case-4-2
  (implies (and (natp i)
                (not (evenp i))
                (integerp y)
                (integerp p0)
                (integerp p1)
                (integerp q0)
                (integerp q1))
           (equal (+ (+ (* (expt y i) p0) q0)
                     (* y (+ (* (expt y i) p1) q1)))
                  (+ (+ (* (expt y (1+ i)) p1) q0)
                     (* y (+ (* (expt y (1- i)) p0) q1)))))
  :rule-classes ())

(local-defthmd split$-case-4-3
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (shnfp h)
                (= j k)
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h)) (yk (car0 (nthcdr k (vals))))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (implies (and (shnfp p0)
                                 (shnfp p1)
                                 (shnfp q0)
                                 (shnfp q1)
                                 (not (evenp i))
                                 (equal (mod (evalh p nk) (p))
                                        (mod (+ (evalh p0 nk)
                                                (* (nth j (vals))
                                                   (evalh p1 nk)))
                                             (p)))
                                 (equal (mod (evalh q nk1) (p))
                                        (mod (+ (evalh q0 nk1)
                                                (* (nth j (vals))
                                                   (evalh q1 nk1)))
                                             (p))))
                           (equal (mod (evalh h (nthcdr k (vals))) (p))
                                  (mod (+ (+ (* (expt yk (1+ i)) (evalh p1 nk)) (evalh q0 nk1))
                                          (* (nth j (vals)) 
                                             (+ (* (expt yk (1- i)) (evalh p0 nk)) (evalh q1 nk1))))
                                       (p))))))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-5-23 split$-case-4-1 split$-case-5-2 split$-case-5-12 split$-case-5-5
                        (:instance split$-case-4-2 (i (cadr h))
                                                   (y (nth j (vals)))
                                                   (p0 (evalh (mv-nth 0 (split$ (caddr h) j k)) (nthcdr k (vals))))
                                                   (p1 (evalh (mv-nth 1 (split$ (caddr h) j k)) (nthcdr k (vals))))
                                                   (q0 (evalh (mv-nth 0 (split$ (cadddr h) j (1+ k))) (nthcdr (1+ k) (vals))))
                                                   (q1 (evalh (mv-nth 1 (split$ (cadddr h) j (1+ k))) (nthcdr (1+ k) (vals)))))))))

(local-defthm split$-case-4-4
  (implies (and (integerp y)
                (integerp y1)
                (integerp y2)
                (integerp p0)
                (integerp p1)
                (integerp q0)
                (integerp q1))
           (equal (mod (+ (+ (* y1 p1) q0)
                          (* y (+ (* y2 p0) q1)))
                       (p))
                  (mod (+ (+ (* (mod y1 (p)) p1) q0)
                          (* y (+ (* (mod y2 (p)) p0) q1)))
                       (p))))
  :rule-classes ())

(local-defthm split$-case-4-5
  (implies (and (natp i)
                (not (evenp i))
                (integerp y)
                (integerp p0)
                (integerp p1)
                (integerp q0)
                (integerp q1))
           (equal (mod (+ (+ (* (expt y (1+ i)) p1) q0)
                          (* y (+ (* (expt y (1- i)) p0) q1)))
                       (p))
                  (mod (+ (+ (* (mod (expt y (1+ i)) (p)) p1) q0)
                          (* y (+ (* (mod (expt y (1- i)) (p)) p0) q1)))
                       (p))))
  :rule-classes ()
  :hints (("Goal" :cases ((> i 0))
                  :use ((:instance split$-case-4-4 (y1 (expt y (1+ i))) (y2 (expt y (1- i))))))))

(local-defthmd split$-case-4-6
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (shnfp h)
                (= j k)
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h)) (yk (car0 (nthcdr k (vals))))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (implies (and (shnfp p0)
                                 (shnfp p1)
                                 (shnfp q0)
                                 (shnfp q1)
                                 (not (evenp i))
                                 (equal (mod (evalh p nk) (p))
                                        (mod (+ (evalh p0 nk)
                                                (* (nth j (vals))
                                                   (evalh p1 nk)))
                                             (p)))
                                 (equal (mod (evalh q nk1) (p))
                                        (mod (+ (evalh q0 nk1)
                                                (* (nth j (vals))
                                                   (evalh q1 nk1)))
                                             (p))))
                           (equal (mod (evalh h (nthcdr k (vals))) (p))
                                  (mod (+ (+ (* (mod (expt yk (1+ i)) (p)) (evalh p1 nk)) (evalh q0 nk1))
                                          (* (nth j (vals)) 
                                             (+ (* (mod (expt yk (1- i)) (p)) (evalh p0 nk)) (evalh q1 nk1))))
                                       (p))))))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-5-5 split$-case-4-1 split$-case-5-2 split$-case-5-12 split$-case-4-3
                        (:instance split$-case-4-5 (i (cadr h))
                                                   (y (nth j (vals)))
                                                   (p0 (evalh (mv-nth 0 (split$ (caddr h) j k)) (nthcdr k (vals))))
                                                   (p1 (evalh (mv-nth 1 (split$ (caddr h) j k)) (nthcdr k (vals))))
                                                   (q0 (evalh (mv-nth 0 (split$ (cadddr h) j (1+ k))) (nthcdr (1+ k) (vals))))
                                                   (q1 (evalh (mv-nth 1 (split$ (cadddr h) j (1+ k))) (nthcdr (1+ k) (vals)))))))))

(local-defthmd split$-case-4-7
  (implies (and (natp i)
                (not (evenp i)))
           (and (natp (/ (1+ i) 2))
                (natp (/ (1- i) 2)))))

(local-defthmd split$-case-4-8
  (implies (and (natp i)
                (not (evenp i))
                (integerp y))
           (equal (expt y (1+ i))
                  (expt (expt y 2) (/ (1+ i) 2)))))

(local-defthmd split$-case-4-9
  (implies (and (natp i)
                (not (evenp i))
                (integerp y))
           (equal (mod (expt y (1+ i)) (p))
                  (mod (expt (mod (expt y 2) (p)) (/ (1+ i) 2)) (p)))))

(local-defthmd split$-case-4-10
  (implies (and (natp i)
                (not (evenp i))
                (integerp y))
           (equal (expt y (1- i))
                  (expt (expt y 2) (/ (1- i) 2)))))

(local-defthmd split$-case-4-11
  (implies (and (natp i)
                (integerp (expt y 2))
                (natp (/ (1- i) 2))
                (not (evenp i))
                (integerp y))
           (equal (mod (expt (expt y 2) (/ (1- i) 2)) (p))
                  (mod (expt (mod (expt y 2) (p)) (/ (1- i) 2)) (p))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use ((:instance mod-expt-rewrite (n (expt y 2)) (k (/ (1- i) 2)))))))

(local-defthmd split$-case-4-12
  (implies (and (natp i)
                (not (evenp i))
                (integerp y))
           (and (integerp (expt y 2))
                (natp (/ (1- i) 2)))))

(local-defthmd split$-case-4-13
  (implies (and (natp i)
                (not (evenp i))
                (integerp y))
           (equal (mod (expt y (1- i)) (p))
                  (mod (expt (mod (expt y 2) (p)) (/ (1- i) 2)) (p))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-4-10 split$-case-4-11 split$-case-4-12))))

(local-defthmd split$-case-4-14
  (implies (and (natp j) 
                (<= j 2))
           (equal (mod (expt (nth j (vals)) 2) (p))
                  (mod (evalh (theta) (nthcdr j (vals))) (p))))
  :hints (("Goal" :cases ((= j 0) (= j 1) (= j 2))
                  :in-theory (enable vals)
                  :use (theta-0-mod theta-1-mod theta-2-mod))))

(local-defthm split$-case-4-15
  (integerp (evalh (theta) (nthcdr j (vals)))))

(local-defthmd split$-case-4-16
  (implies (and (natp i)
                (natp (/ (1+ i) 2))
                (not (evenp i)))
           (equal (mod (expt (evalh (theta) (nthcdr j (vals))) (/ (1+ i) 2)) (p))
                  (mod (expt (mod (evalh (theta) (nthcdr j (vals))) (p)) (/ (1+ i) 2)) (p))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-4-15
                        (:instance mod-expt-rewrite (n (evalh (theta) (nthcdr j (vals)))) (k (/ (1+ i) 2)))))))

(local-defthmd split$-case-4-17
  (implies (and (natp i)
                (not (evenp i)))
           (natp (/ (1+ i) 2))))

(local-defthmd split$-case-4-18
  (implies (and (natp j)
                (<= j 2)
                (natp i)
                (not (evenp i)))
           (equal (mod (expt (nth j (vals)) (1+ i)) (p))
                  (mod (evalh (norm-expt (theta) (/ (1+ i) 2)) (nthcdr j (vals))) (p))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-5-13 split$-case-4-14 split$-case-4-16 split$-case-4-17 shnfp-theta all-integers-vals
                        (:instance all-integers-nthcdr (vals (vals)) (n j))
                        (:instance evalh-norm-expt (x (theta)) (vals (nthcdr j (vals))) (k (/ (1+ i) 2)))
                        (:instance split$-case-4-9 (y (nth j (vals))))))))

(local-defthmd split$-case-4-19
  (implies (and (natp i)
                (natp (/ (1- i) 2))
                (not (evenp i)))
           (equal (mod (expt (evalh (theta) (nthcdr j (vals))) (/ (1- i) 2)) (p))
                  (mod (expt (mod (evalh (theta) (nthcdr j (vals))) (p)) (/ (1- i) 2)) (p))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-4-15
                        (:instance mod-expt-rewrite (n (evalh (theta) (nthcdr j (vals)))) (k (/ (1- i) 2)))))))

(local-defthmd split$-case-4-20
  (implies (and (natp j)
                (<= j 2)
                (natp i)
                (not (evenp i)))
           (equal (mod (expt (nth j (vals)) (1- i)) (p))
                  (mod (evalh (norm-expt (theta) (/ (1- i) 2)) (nthcdr j (vals))) (p))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-5-13 split$-case-4-14 split$-case-4-19  shnfp-theta all-integers-vals
                        (:instance split$-case-4-12 (y 0))
                        (:instance all-integers-nthcdr (vals (vals)) (n j))
                        (:instance evalh-norm-expt (x (theta)) (vals (nthcdr j (vals))) (k (/ (1- i) 2)))
                        (:instance split$-case-4-13 (y (nth j (vals))))))))

(local-defthmd split$-case-4-21
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (shnfp h)
                (= j k)
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (implies (and (shnfp p0)
                                 (shnfp p1)
                                 (shnfp q0)
                                 (shnfp q1)
                                 (not (evenp i))
                                 (equal (mod (evalh p nk) (p))
                                        (mod (+ (evalh p0 nk)
                                                (* (nth j (vals))
                                                   (evalh p1 nk)))
                                             (p)))
                                 (equal (mod (evalh q nk1) (p))
                                        (mod (+ (evalh q0 nk1)
                                                (* (nth j (vals))
                                                   (evalh q1 nk1)))
                                             (p))))
                           (equal (mod (evalh h (nthcdr k (vals))) (p))
                                  (mod (+ (+ (* (mod (evalh (norm-expt (theta) (/ (1+ i) 2)) (nthcdr j (vals))) (p))
                                                (evalh p1 nk))
                                             (evalh q0 nk1))
                                          (* (nth j (vals)) 
                                             (+ (* (mod (evalh (norm-expt (theta) (/ (1- i) 2)) (nthcdr j (vals))) (p))
                                                   (evalh p0 nk))
                                                (evalh q1 nk1))))
                                       (p))))))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-4-1 split$-case-4-6 split$-case-5-2
                        (:instance split$-case-4-18 (i (cadr h)))
                        (:instance split$-case-4-20 (i (cadr h)))))))

(local-defthmd split$-case-4-22
  (implies (and (natp i)
                (not (evenp i)))
           (integerp (evalh (norm-expt (theta) (/ (1+ i) 2)) (nthcdr j (vals))))))

(local-defthmd split$-case-4-23
  (implies (and (natp i)
                (not (evenp i)))
           (integerp (evalh (norm-expt (theta) (/ (1- i) 2)) (nthcdr j (vals))))))

(local-defthmd split$-case-4-24
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (shnfp h)
                (= j k)
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (implies (and (shnfp p0)
                                 (shnfp p1)
                                 (shnfp q0)
                                 (shnfp q1)
                                 (not (evenp i))
                                 (equal (mod (evalh p nk) (p))
                                        (mod (+ (evalh p0 nk)
                                                (* (nth j (vals))
                                                   (evalh p1 nk)))
                                             (p)))
                                 (equal (mod (evalh q nk1) (p))
                                        (mod (+ (evalh q0 nk1)
                                                (* (nth j (vals))
                                                   (evalh q1 nk1)))
                                             (p))))
                           (equal (mod (evalh h (nthcdr k (vals))) (p))
                                  (mod (+ (+ (* (evalh (norm-expt (theta) (/ (1+ i) 2)) (nthcdr j (vals)))
                                                (evalh p1 nk))
                                             (evalh q0 nk1))
                                          (* (nth j (vals)) 
                                             (+ (* (evalh (norm-expt (theta) (/ (1- i) 2)) (nthcdr j (vals)))
                                                   (evalh p0 nk))
                                                (evalh q1 nk1))))
                                       (p))))))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-4-21 split$-case-5-2 split$-case-5-13 split$-case-5-12
                        (:instance split$-case-4-22 (i (cadr h)))
                        (:instance split$-case-4-23 (i (cadr h)))
                        (:instance split$-case-4-4 (y1 (evalh (norm-expt (theta) (/ (1+ (cadr h)) 2)) (nthcdr j (vals))))
                                                   (y2 (evalh (norm-expt (theta) (/ (1- (cadr h)) 2)) (nthcdr j (vals))))
                                                   (y (nth j (vals)))
                                                   (p0 (evalh (mv-nth 0 (split$ (caddr h) j k)) (nthcdr k (vals))))
                                                   (p1 (evalh (mv-nth 1 (split$ (caddr h) j k)) (nthcdr k (vals))))
                                                   (q0 (evalh (mv-nth 0 (split$ (cadddr h) j (1+ k))) (nthcdr (1+ k) (vals))))
                                                   (q1 (evalh (mv-nth 1 (split$ (cadddr h) j (1+ k))) (nthcdr (1+ k) (vals)))))))))

(local-defthmd split$-case-4-25
  (implies (and (natp j) 
                (<= j 2)
                (shnfp p0)
                (shnfp p1)
                (shnfp q0)
                (shnfp q1))
          (and (equal (+ (* (evalh (norm-expt (theta) (/ (1+ i) 2)) (nthcdr j (vals)))
                            (evalh p1 (nthcdr j (vals))))
                         (evalh q0 (nthcdr (1+ j) (vals))))
                      (evalh (norm-add (norm-mul (norm-expt (theta) (/ (1+ i) 2))
                                                 p1)
                                       (norm-pop 1 q0))
                             (nthcdr j (vals))))
               (equal (+ (* (evalh (norm-expt (theta) (/ (1- i) 2)) (nthcdr j (vals)))
                            (evalh p0 (nthcdr j (vals))))
                         (evalh q1 (nthcdr (1+ j) (vals))))
                      (evalh (norm-add (norm-mul (norm-expt (theta) (/ (1- i) 2))
                                                 p0)
                                       (norm-pop 1 q1))
                             (nthcdr j (vals))))))
  :hints (("Goal" :expand (:free (q v) (evalh (list 'pop 1 q) v)))))

(local-defthmd split$-case-4-26
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (shnfp h)
                (= j k)
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (implies (and (shnfp p0)
                                 (shnfp p1)
                                 (shnfp q0)
                                 (shnfp q1)
                                 (not (evenp i))
                                 (equal (mod (evalh p nk) (p))
                                        (mod (+ (evalh p0 nk)
                                                (* (nth j (vals))
                                                   (evalh p1 nk)))
                                             (p)))
                                 (equal (mod (evalh q nk1) (p))
                                        (mod (+ (evalh q0 nk1)
                                                (* (nth j (vals))
                                                   (evalh q1 nk1)))
                                             (p))))
                           (equal (mod (evalh h (nthcdr k (vals))) (p))
                                  (mod (+ (evalh (norm-add (norm-mul (norm-expt (theta) (/ (1+ i) 2))
                                                                     p1)
                                                           (norm-pop 1 q0))
                                                 (nthcdr k (vals)))
                                          (* (nth j (vals)) 
                                             (evalh (norm-add (norm-mul (norm-expt (theta) (/ (1- i) 2))
                                                                        p0)
                                                              (norm-pop 1 q1))
                                                    (nthcdr j (vals)))))
                                       (p))))))))
:hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-4-24
                        (:instance split$-case-4-25 (i (cadr h))
                                                    (p0 (mv-nth 0 (split$ (caddr h) j k)))
                                                    (p1 (mv-nth 1 (split$ (caddr h) j k)))
                                                    (q0 (mv-nth 0 (split$ (cadddr h) j (1+ k))))
                                                    (q1 (mv-nth 1 (split$ (cadddr h) j (1+ k)))))))))

(local-defthmd split$-case-4
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (< k 6)
                (shnfp h)
                (not (< j k))
                (= j k)
                (consp h)
                (not (eql (car h) 'pop)))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
             (mv-let (h0 h1) (split$ h j k)
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (and (natp (+ 1 k))
                        (shnfp p)
                        (shnfp q)
                       (implies (and (shnfp p0)
                                     (shnfp p1)
                                     (shnfp q0)
                                     (shnfp q1)
                                     (not (evenp i))
                                     (equal (mod (evalh p nk) (p))
                                            (mod (+ (evalh p0 nk)
                                                    (* (nth j (vals))
                                                       (evalh p1 nk)))
                                                 (p)))
                                     (equal (mod (evalh q nk1) (p))
                                            (mod (+ (evalh q0 nk1)
                                                    (* (nth j (vals))
                                                       (evalh q1 nk1)))
                                                 (p))))
                               (and (shnfp h0)
                                    (shnfp h1)
                                    (equal (mod (evalh h (nthcdr k (vals))) (p))
                                           (mod (+ (evalh h0 (nthcdr k (vals)))
                                                   (* (nth j (vals)) 
                                                      (evalh h1 (nthcdr j (vals)))))
                                                (p)))))))))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :expand (:free (j k) (split$ h j k))
                  :use (split$-case-4-26 split$-case-5-25))))

(local-defthm split$-case-3-1
  (implies (and (natp i)
                (integerp y)
                (integerp p0)
                (integerp p1)
                (integerp q0)
                (integerp q1))
           (equal (mod (+ (+ (* (expt y i) p0) q0)
                          (* y (+ (* (expt y i) p1) q1)))
                       (p))
                  (mod (+ (+ (* (mod (expt y i) (p)) p0) q0)
                          (* y (+ (* (mod (expt y i) (p)) p1) q1)))
                       (p))))
  :rule-classes ()
  :hints (("Goal" :cases ((> i 0))
                  :use ((:instance split$-case-4-4 (p0 p1) (p1 p0) (y1 (expt y i)) (y2 (expt y i)))))))

(local-defthmd split$-case-3-2
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (shnfp h)
                (= j k)
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h)) (yk (car0 (nthcdr k (vals))))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (implies (and (shnfp p0)
                                 (shnfp p1)
                                 (shnfp q0)
                                 (shnfp q1)
                                 (equal (mod (evalh p nk) (p))
                                        (mod (+ (evalh p0 nk)
                                                (* (nth j (vals))
                                                   (evalh p1 nk)))
                                             (p)))
                                 (equal (mod (evalh q nk1) (p))
                                        (mod (+ (evalh q0 nk1)
                                                (* (nth j (vals))
                                                   (evalh q1 nk1)))
                                             (p))))
                           (equal (mod (evalh h (nthcdr k (vals))) (p))
                                  (mod (+ (+ (* (mod (expt yk i) (p)) (evalh p0 nk)) (evalh q0 nk1))
                                          (* (nth j (vals)) 
                                             (+ (* (mod (expt yk i) (p)) (evalh p1 nk)) (evalh q1 nk1))))
                                       (p))))))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-5-5 split$-case-4-1 split$-case-5-2 split$-case-5-12 split$-case-5-23
                        (:instance split$-case-3-1 (i (cadr h))
                                                   (y (nth j (vals)))
                                                   (p0 (evalh (mv-nth 0 (split$ (caddr h) j k)) (nthcdr k (vals))))
                                                   (p1 (evalh (mv-nth 1 (split$ (caddr h) j k)) (nthcdr k (vals))))
                                                   (q0 (evalh (mv-nth 0 (split$ (cadddr h) j (1+ k))) (nthcdr (1+ k) (vals))))
                                                   (q1 (evalh (mv-nth 1 (split$ (cadddr h) j (1+ k))) (nthcdr (1+ k) (vals)))))))))

(local-defthmd split$-case-3-3
  (implies (and (natp i)
                (evenp i))
           (natp (/ i 2))))

(local-defthmd split$-case-3-4
  (implies (and (natp i)
                (evenp i)
                (integerp y))
           (equal (expt y i)
                  (expt (expt y 2) (/ i 2)))))

(local-defthmd split$-case-3-5
  (implies (and (natp i)
                (evenp i)
                (integerp y))
           (equal (mod (expt y i) (p))
                  (mod (expt (mod (expt y 2) (p)) (/ i 2)) (p)))))

(local-defthmd split$-case-3-6
  (implies (and (natp i)
                (natp (/ i 2))
                (evenp i))
           (equal (mod (expt (evalh (theta) (nthcdr j (vals))) (/ i 2)) (p))
                  (mod (expt (mod (evalh (theta) (nthcdr j (vals))) (p)) (/ i 2)) (p))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-4-15
                        (:instance mod-expt-rewrite (n (evalh (theta) (nthcdr j (vals)))) (k (/ i 2)))))))

(local-defthmd split$-case-3-7
  (implies (and (natp j)
                (<= j 2)
                (natp i)
                (evenp i))
           (equal (mod (expt (nth j (vals)) i) (p))
                  (mod (evalh (norm-expt (theta) (/ i 2)) (nthcdr j (vals))) (p))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-5-13 split$-case-4-14 split$-case-3-6 split$-case-3-3 shnfp-theta all-integers-vals
                        (:instance all-integers-nthcdr (vals (vals)) (n j))
                        (:instance evalh-norm-expt (x (theta)) (vals (nthcdr j (vals))) (k (/ i 2)))
                        (:instance split$-case-3-5 (y (nth j (vals))))))))

(local-defthmd split$-case-3-8
  (implies (and (natp i)
                (natp (/ i 2))
                (evenp i))
           (equal (mod (expt (evalh (theta) (nthcdr j (vals))) (/ i 2)) (p))
                  (mod (expt (mod (evalh (theta) (nthcdr j (vals))) (p)) (/ i 2)) (p))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-4-15
                        (:instance mod-expt-rewrite (n (evalh (theta) (nthcdr j (vals)))) (k (/ i 2)))))))

(local-defthmd split$-case-3-9
  (implies (and (natp j)
                (<= j 2)
                (natp i)
                (evenp i))
           (equal (mod (expt (nth j (vals)) i) (p))
                  (mod (evalh (norm-expt (theta) (/ i 2)) (nthcdr j (vals))) (p))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-5-13 split$-case-4-14 split$-case-3-8  shnfp-theta all-integers-vals split$-case-3-3
                        (:instance all-integers-nthcdr (vals (vals)) (n j))
                        (:instance evalh-norm-expt (x (theta)) (vals (nthcdr j (vals))) (k (/ i 2)))
                        (:instance split$-case-3-5 (y (nth j (vals))))))))

(local-defthmd split$-case-3-10
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (shnfp h)
                (not (< j k))
                (= j k)
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (implies (and (shnfp p0)
                                 (shnfp p1)
                                 (shnfp q0)
                                 (shnfp q1)
                                 (evenp i)
                                 (equal (mod (evalh p nk) (p))
                                        (mod (+ (evalh p0 nk)
                                                (* (nth j (vals))
                                                   (evalh p1 nk)))
                                             (p)))
                                 (equal (mod (evalh q nk1) (p))
                                        (mod (+ (evalh q0 nk1)
                                                (* (nth j (vals))
                                                   (evalh q1 nk1)))
                                             (p))))
                           (equal (mod (evalh h (nthcdr k (vals))) (p))
                                  (mod (+ (+ (* (mod (evalh (norm-expt (theta) (/ i 2)) (nthcdr j (vals))) (p))
                                                (evalh p0 nk))
                                             (evalh q0 nk1))
                                          (* (nth j (vals)) 
                                             (+ (* (mod (evalh (norm-expt (theta) (/ i 2)) (nthcdr j (vals))) (p))
                                                   (evalh p1 nk))
                                                (evalh q1 nk1))))
                                       (p))))))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-4-1 split$-case-5-2 split$-case-3-2
                        (:instance split$-case-3-9 (i (cadr h)))))))

(local-defthmd split$-case-3-11
  (implies (and (natp i)
                (evenp i))
           (integerp (evalh (norm-expt (theta) (/ i 2)) (nthcdr j (vals))))))

(local-defthmd split$-case-3-12
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (shnfp h)
                (= j k)
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (implies (and (shnfp p0)
                                 (shnfp p1)
                                 (shnfp q0)
                                 (shnfp q1)
                                 (evenp i)
                                 (equal (mod (evalh p nk) (p))
                                        (mod (+ (evalh p0 nk)
                                                (* (nth j (vals))
                                                   (evalh p1 nk)))
                                             (p)))
                                 (equal (mod (evalh q nk1) (p))
                                        (mod (+ (evalh q0 nk1)
                                                (* (nth j (vals))
                                                   (evalh q1 nk1)))
                                             (p))))
                           (equal (mod (evalh h (nthcdr k (vals))) (p))
                                  (mod (+ (+ (* (evalh (norm-expt (theta) (/ i 2)) (nthcdr j (vals)))
                                                (evalh p0 nk))
                                             (evalh q0 nk1))
                                          (* (nth j (vals)) 
                                             (+ (* (evalh (norm-expt (theta) (/ i 2)) (nthcdr j (vals)))
                                                   (evalh p1 nk))
                                                (evalh q1 nk1))))
                                       (p))))))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-3-10 split$-case-5-2 split$-case-5-13 split$-case-5-12
                        (:instance split$-case-3-11 (i (cadr h)))
                        (:instance split$-case-4-4 (y1 (evalh (norm-expt (theta) (/ (cadr h) 2)) (nthcdr j (vals))))
                                                   (y2 (evalh (norm-expt (theta) (/ (cadr h) 2)) (nthcdr j (vals))))
                                                   (y (nth j (vals)))
                                                   (p1 (evalh (mv-nth 0 (split$ (caddr h) j k)) (nthcdr k (vals))))
                                                   (p0 (evalh (mv-nth 1 (split$ (caddr h) j k)) (nthcdr k (vals))))
                                                   (q0 (evalh (mv-nth 0 (split$ (cadddr h) j (1+ k))) (nthcdr (1+ k) (vals))))
                                                   (q1 (evalh (mv-nth 1 (split$ (cadddr h) j (1+ k))) (nthcdr (1+ k) (vals)))))))))

(local-defthmd split$-case-3-13
  (implies (and (natp j) 
                (<= j 2)
                (shnfp p0)
                (shnfp p1)
                (shnfp q0)
                (shnfp q1))
          (and (equal (+ (* (evalh (norm-expt (theta) (/ i 2)) (nthcdr j (vals)))
                            (evalh p0 (nthcdr j (vals))))
                         (evalh q0 (nthcdr (1+ j) (vals))))
                      (evalh (norm-add (norm-mul (norm-expt (theta) (/ i 2))
                                                 p0)
                                       (norm-pop 1 q0))
                             (nthcdr j (vals))))
               (equal (+ (* (evalh (norm-expt (theta) (/ i 2)) (nthcdr j (vals)))
                            (evalh p1 (nthcdr j (vals))))
                         (evalh q1 (nthcdr (1+ j) (vals))))
                      (evalh (norm-add (norm-mul (norm-expt (theta) (/ i 2))
                                                 p1)
                                       (norm-pop 1 q1))
                             (nthcdr j (vals))))))
  :hints (("Goal" :expand (:free (q v) (evalh (list 'pop 1 q) v)))))

(local-defthmd split$-case-3-14
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (shnfp h)
                (= j k)
                (consp h)
                (eql (car h) 'pow))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (implies (and (shnfp p0)
                                 (shnfp p1)
                                 (shnfp q0)
                                 (shnfp q1)
                                 (evenp i)
                                 (equal (mod (evalh p nk) (p))
                                        (mod (+ (evalh p0 nk)
                                                (* (nth j (vals))
                                                   (evalh p1 nk)))
                                             (p)))
                                 (equal (mod (evalh q nk1) (p))
                                        (mod (+ (evalh q0 nk1)
                                                (* (nth j (vals))
                                                   (evalh q1 nk1)))
                                             (p))))
                           (equal (mod (evalh h (nthcdr k (vals))) (p))
                                  (mod (+ (evalh (norm-add (norm-mul (norm-expt (theta) (/ i 2))
                                                                     p0)
                                                           (norm-pop 1 q0))
                                                 (nthcdr k (vals)))
                                          (* (nth j (vals)) 
                                             (evalh (norm-add (norm-mul (norm-expt (theta) (/ i 2))
                                                                        p1)
                                                              (norm-pop 1 q1))
                                                    (nthcdr j (vals)))))
                                       (p))))))))
:hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-3-12
                        (:instance split$-case-3-13 (i (cadr h))
                                                    (p0 (mv-nth 0 (split$ (caddr h) j k)))
                                                    (p1 (mv-nth 1 (split$ (caddr h) j k)))
                                                    (q0 (mv-nth 0 (split$ (cadddr h) j (1+ k))))
                                                    (q1 (mv-nth 1 (split$ (cadddr h) j (1+ k)))))))))

(local-defthmd split$-case-3
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (< k 6)
                (shnfp h)
                (not (< j k))
                (= j k)
                (consp h)
                (not (eql (car h) 'pop)))
           (let ((i (cadr h)) (p (caddr h)) (q (cadddr h))
                 (nk (nthcdr k (vals))) (nk1 (nthcdr (1+ k) (vals))))
             (mv-let (h0 h1) (split$ h j k)
               (mv-let (p0 p1) (split$ p j k)
                 (mv-let (q0 q1) (split$ q j (1+ k))
                   (and (natp (+ 1 k))
                        (shnfp p)
                        (shnfp q)
                       (implies (and (shnfp p0)
                                     (shnfp p1)
                                     (shnfp q0)
                                     (shnfp q1)
                                     (evenp i)
                                     (equal (mod (evalh p nk) (p))
                                            (mod (+ (evalh p0 nk)
                                                    (* (nth j (vals))
                                                       (evalh p1 nk)))
                                                 (p)))
                                     (equal (mod (evalh q nk1) (p))
                                            (mod (+ (evalh q0 nk1)
                                                    (* (nth j (vals))
                                                       (evalh q1 nk1)))
                                                 (p))))
                               (and (shnfp h0)
                                    (shnfp h1)
                                    (equal (mod (evalh h (nthcdr k (vals))) (p))
                                           (mod (+ (evalh h0 (nthcdr k (vals)))
                                                   (* (nth j (vals)) 
                                                      (evalh h1 (nthcdr j (vals)))))
                                                (p)))))))))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :expand (:free (j k) (split$ h j k))
                  :use (split$-case-5-25 split$-case-3-14))))

(local-defthmd split$-case-2-1
  (implies (and (natp k)
                (shnfp h)
                (consp h)
                (eql (car h) 'pop))
           (not (zp (cadr h))))
  :hints (("Goal" :use ((:instance shfp (x h))
                        (:instance shf-normp (x h)))
                  :in-theory (disable shfp shf-normp))))

(local-defthm split$-case-2-2
  (implies (and (shnfp h)
                (consp h)
                (eql (car h) 'pop))
           (natp (cadr h)))
  :hints (("Goal" :use ((:instance shfp (x h))
                        (:instance shf-normp (x h)))
                  :in-theory (disable shfp shf-normp)))
  :rule-classes (:type-prescription :rewrite))

(local-defthm split$-case-2-3
  (implies (and (natp k)
                (shnfp h)
                (consp h)
                (eql (car h) 'pop))
           (shnfp (caddr h)))
  :hints (("Goal" :use ((:instance shfp (x h))
                        (:instance shnfp (x h))
                        (:instance shf-normp (x h)))
                  :in-theory (disable shfp shf-normp))))

(local-defthmd split$-case-2-4
  (implies (and (natp k)
                (shnfp h)
                (consp h)
                (eql (car h) 'pop))
           (let* ((i (cadr h)) (p (caddr h))
                  (nk (nthcdr k (vals))) (nki (nthcdr (+ i k) (vals))))
             (equal (evalh h nk)
                    (evalh p nki))))
  :hints (("Goal" :expand ((evalh h (nthcdr k (vals)))) :in-theory (enable cdr-nthcdr))))

(local-defthmd split$-case-2-5
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (< k 6)
                (shnfp h)
                (not (< j k))
                (consp h)
                (eql (car h) 'pop))
           (let* ((i (cadr h)) (p (caddr h))
                  (nk (nthcdr k (vals))) (nki (nthcdr (+ i k) (vals))))
             (mv-let (p0 p1) (split$ p j (+ i k))
               (and (natp (+ i k))
                    (implies (and (shnfp p0)
                                  (shnfp p1)
                                  (equal (mod (evalh p nki) (p))
                                         (mod (+ (evalh p0 nki)
                                                 (* (nth j (vals))
                                                    (evalh p1 nki)))
                                              (p))))
                             (equal (mod (evalh h nk) (p))
                                    (mod (+ (evalh p0 nki)
                                            (* (nth j (vals))
                                               (evalh p1 nki)))
                                         (p))))))))
  :hints (("Goal" :in-theory (enable split$-case-2-4))))

(local-defthmd split$-case-2-6
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (< k 6)
                (not (< j k))
                (shnfp p0)
                (shnfp h)
                (consp h)
                (eql (car h) 'pop))
           (let* ((i (cadr h))
                  (nk (nthcdr k (vals))) (nki (nthcdr (+ i k) (vals))))
             (equal (evalh p0 nki)
                    (evalh (norm-pop i p0) nk))))
  :hints (("Goal" :expand (:free (i p v) (evalh (list 'pop i p) v)))))

(local-defthmd split$-case-2-7
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (< k 6)
                (shnfp h)
                (not (< j k))
                (consp h)
                (eql (car h) 'pop))
           (let* ((i (cadr h)) (p (caddr h))
                  (nk (nthcdr k (vals))) (nki (nthcdr (+ i k) (vals))))
             (mv-let (p0 p1) (split$ p j (+ i k))
               (and (natp (+ i k))
                    (implies (and (shnfp p0)
                                  (shnfp p1)
                                  (equal (mod (evalh p nki) (p))
                                         (mod (+ (evalh p0 nki)
                                                 (* (nth j (vals))
                                                    (evalh p1 nki)))
                                              (p))))
                             (equal (mod (evalh h nk) (p))
                                    (mod (+ (evalh (norm-pop i p0) nk)
                                            (* (nth j (vals))
                                               (evalh (norm-pop i p1) nk)))
                                         (p))))))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-2-5
                        (:instance split$-case-2-6 (p0 (mv-nth 0 (split$ (caddr h) j (+ (cadr h) k)))))
                        (:instance split$-case-2-6 (p0 (mv-nth 1 (split$ (caddr h) j (+ (cadr h) k)))))))))

(local-defthmd split$-case-2-8
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (shnfp h)
                (not (< j k))
                (consp h)
                (eql (car h) 'pop))
           (let ((i (cadr h)) (p (caddr h)))
             (mv-let (h0 h1) (split$ h j k)
               (mv-let (p0 p1) (split$ p j (+ i k))
                   (and (shnfp p)
                        (implies (and (shnfp p0)
                                      (shnfp p1))
                                 (and (equal h0 (norm-pop i p0))
                                      (shnfp h0)
                                      (equal h1 (norm-pop i p1))
                                      (shnfp h1))))))))
  :hints (("goal" :expand ((split$ h j k)) :use (split$-case-2-1))))

(local-defthmd split$-case-2
  (implies (and (natp j) 
                (<= j 2)
                (natp k)
                (< k 6)
                (shnfp h)
                (not (< j k))
                (consp h)
                (eql (car h) 'pop))
           (let* ((i (cadr h)) (p (caddr h))
                  (nk (nthcdr k (vals))) (nki (nthcdr (+ i k) (vals))))
             (mv-let (h0 h1) (split$ h j k)
               (mv-let (p0 p1) (split$ p j (+ i k))
                 (and (natp (+ i k))
                      (shnfp p)
                      (implies (and (shnfp p0)
                                    (shnfp p1)
                                    (equal (mod (evalh p nki) (p))
                                           (mod (+ (evalh p0 nki)
                                                   (* (nth j (vals))
                                                      (evalh p1 nki)))
                                                (p))))
                               (and (shnfp h0)
                                    (shnfp h1)
                                    (equal (mod (evalh h nk) (p))
                                           (mod (+ (evalh h0 nk)
                                                   (* (nth j (vals)) 
                                                      (evalh h1 nk)))
                                                (p))))))))))
  :hints (("Goal" :in-theory (theory 'minimal-theory)
                  :use (split$-case-2-7 split$-case-2-8))))

(defthm split$-lemma
  (implies (and (natp j)
                (<= j 2)
                (natp k)
                (shnfp h))
           (mv-let (h0 h1) (split$ h j k)
             (and (shnfp h0)
                  (shnfp h1)
                  (equal (mod (evalh h (nthcdr k (vals))) (p))
                         (mod (+ (evalh h0 (nthcdr k (vals)))
                                 (* (nth j (vals))
                                    (evalh h1 (nthcdr k (vals)))))
                              (p))))))
  :hints (("Subgoal *1/5" :use (split$-case-5) :in-theory (theory 'minimal-theory))
          ("Subgoal *1/4" :use (split$-case-4) :in-theory (theory 'minimal-theory))
          ("Subgoal *1/3" :use (split$-case-3) :in-theory (theory 'minimal-theory))
          ("Subgoal *1/2" :use (split$-case-2) :in-theory (theory 'minimal-theory))))

;; Thus, evalh(rewrite(h, j), (vars)) = evalh(h, vars):

(defun rewrite$ (h j)
  (mv-let (h0 h1) (split$ h j 0)
    (norm-add h0 (norm-mul h1 (norm (nth j (vars)) (vars))))))

(local (in-theory (enable car0)))

(local-defthm evalh$-norm-var
  (implies (and (natp j)
                (<= j 2))
           (equal (evalh$ (norm (nth j (vars)) (vars)))
                  (nth j (vals))))
  :hints (("Goal" :in-theory (enable vals)
                  :expand (:free (h v) (evalh h v))
                  :cases ((= j 0) (= j 1) (= j 2)))))

(defthm rewrite$-lemma
  (implies (and (natp j)
                (<= j 2)
                (shnfp h))
           (let ((r (rewrite$ h j)))
             (and (shnfp r)
                  (equal (mod (evalh$ r) (p))
                         (mod (evalh$ h) (p))))))
  :hints (("Goal" :cases ((= j 0) (= j 1) (= j 2))
                  :use (evalh$-norm-var (:instance split$-lemma (k 0))))))

;; reduce successively rewrites powers of Y0, Y1, and Y2:

(defun reduce$ (x)
  (rewrite$ (rewrite$ (rewrite$ (norm x (vars)) 0) 1) 2))

(defun polyp$ (x) (polyp x (vars)))

(local-defthm evalh$-evalp$
  (implies (polyp$ x)
           (equal (evalh$ (norm x (vars)))
                  (evalp$ x)))
  :hints (("Goal" :in-theory (enable vlist))))

(local-defthm shnfp-norm-polyp
  (IMPLIES (POLYP X (VARS)) (SHNFP (NORM X (VARS)))))

(defthm reduce$-correct
  (implies (polyp$ x)
           (and (shnfp (reduce$ x))
                (equal (mod (evalh$ (reduce$ x)) (p))
                       (mod (evalp$ x) (p)))))
  :hints (("Goal" :in-theory (disable vars (vars) rewrite$ evalh$))))


