17db96d56Sopenharmony_ci;
27db96d56Sopenharmony_ci; Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
37db96d56Sopenharmony_ci;
47db96d56Sopenharmony_ci; Redistribution and use in source and binary forms, with or without
57db96d56Sopenharmony_ci; modification, are permitted provided that the following conditions
67db96d56Sopenharmony_ci; are met:
77db96d56Sopenharmony_ci;
87db96d56Sopenharmony_ci; 1. Redistributions of source code must retain the above copyright
97db96d56Sopenharmony_ci;    notice, this list of conditions and the following disclaimer.
107db96d56Sopenharmony_ci;
117db96d56Sopenharmony_ci; 2. Redistributions in binary form must reproduce the above copyright
127db96d56Sopenharmony_ci;    notice, this list of conditions and the following disclaimer in the
137db96d56Sopenharmony_ci;    documentation and/or other materials provided with the distribution.
147db96d56Sopenharmony_ci;
157db96d56Sopenharmony_ci; THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
167db96d56Sopenharmony_ci; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
177db96d56Sopenharmony_ci; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
187db96d56Sopenharmony_ci; ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
197db96d56Sopenharmony_ci; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
207db96d56Sopenharmony_ci; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
217db96d56Sopenharmony_ci; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
227db96d56Sopenharmony_ci; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
237db96d56Sopenharmony_ci; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
247db96d56Sopenharmony_ci; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
257db96d56Sopenharmony_ci; SUCH DAMAGE.
267db96d56Sopenharmony_ci;
277db96d56Sopenharmony_ci
287db96d56Sopenharmony_ci
297db96d56Sopenharmony_ci(in-package "ACL2")
307db96d56Sopenharmony_ci
317db96d56Sopenharmony_ci(include-book "arithmetic/top-with-meta" :dir :system)
327db96d56Sopenharmony_ci(include-book "arithmetic-2/floor-mod/floor-mod" :dir :system)
337db96d56Sopenharmony_ci
347db96d56Sopenharmony_ci
357db96d56Sopenharmony_ci;; =====================================================================
367db96d56Sopenharmony_ci;;            Proofs for several functions in umodarith.h
377db96d56Sopenharmony_ci;; =====================================================================
387db96d56Sopenharmony_ci
397db96d56Sopenharmony_ci
407db96d56Sopenharmony_ci
417db96d56Sopenharmony_ci;; =====================================================================
427db96d56Sopenharmony_ci;;                          Helper theorems
437db96d56Sopenharmony_ci;; =====================================================================
447db96d56Sopenharmony_ci
457db96d56Sopenharmony_ci(defthm elim-mod-m
467db96d56Sopenharmony_ci  (implies (and (<= m x)
477db96d56Sopenharmony_ci                (< x (* 2 m))
487db96d56Sopenharmony_ci                (rationalp x) (rationalp m))
497db96d56Sopenharmony_ci           (equal (mod x m)
507db96d56Sopenharmony_ci                  (+ x (- m)))))
517db96d56Sopenharmony_ci
527db96d56Sopenharmony_ci(defthm modaux-1a
537db96d56Sopenharmony_ci  (implies (and (< x m) (< 0 x) (< 0 m)
547db96d56Sopenharmony_ci                (rationalp x) (rationalp m))
557db96d56Sopenharmony_ci           (equal (mod (- x) m)
567db96d56Sopenharmony_ci                  (+ (- x) m))))
577db96d56Sopenharmony_ci
587db96d56Sopenharmony_ci(defthm modaux-1b
597db96d56Sopenharmony_ci  (implies (and (< (- x) m) (< x 0) (< 0 m)
607db96d56Sopenharmony_ci                (rationalp x) (rationalp m))
617db96d56Sopenharmony_ci           (equal (mod x m)
627db96d56Sopenharmony_ci                  (+ x m)))
637db96d56Sopenharmony_ci  :hints (("Goal" :use ((:instance modaux-1a
647db96d56Sopenharmony_ci                                   (x (- x)))))))
657db96d56Sopenharmony_ci
667db96d56Sopenharmony_ci(defthm modaux-1c
677db96d56Sopenharmony_ci  (implies (and (< x m) (< 0 x) (< 0 m)
687db96d56Sopenharmony_ci                (rationalp x) (rationalp m))
697db96d56Sopenharmony_ci           (equal (mod x m)
707db96d56Sopenharmony_ci                  x)))
717db96d56Sopenharmony_ci
727db96d56Sopenharmony_ci(defthm modaux-2a
737db96d56Sopenharmony_ci  (implies (and (< 0 b) (< b m)
747db96d56Sopenharmony_ci                (natp x) (natp b) (natp m)
757db96d56Sopenharmony_ci                (< (mod (+ b x) m) b))
767db96d56Sopenharmony_ci           (equal (mod (+ (- m) b x) m)
777db96d56Sopenharmony_ci                  (+ (- m) b (mod x m)))))
787db96d56Sopenharmony_ci
797db96d56Sopenharmony_ci(defthm modaux-2b
807db96d56Sopenharmony_ci  (implies (and (< 0 b) (< b m)
817db96d56Sopenharmony_ci                (natp x) (natp b) (natp m)
827db96d56Sopenharmony_ci                (< (mod (+ b x) m) b))
837db96d56Sopenharmony_ci           (equal (mod (+ b x) m)
847db96d56Sopenharmony_ci                  (+ (- m) b (mod x m))))
857db96d56Sopenharmony_ci  :hints (("Goal" :use (modaux-2a))))
867db96d56Sopenharmony_ci
877db96d56Sopenharmony_ci(defthm linear-mod-1
887db96d56Sopenharmony_ci  (implies (and (< x m) (< b m)
897db96d56Sopenharmony_ci                (natp x) (natp b)
907db96d56Sopenharmony_ci                (rationalp m))
917db96d56Sopenharmony_ci         (equal (< x (mod (+ (- b) x) m))
927db96d56Sopenharmony_ci                (< x b)))
937db96d56Sopenharmony_ci  :hints (("Goal" :use ((:instance modaux-1a
947db96d56Sopenharmony_ci                                   (x (+ b (- x))))))))
957db96d56Sopenharmony_ci
967db96d56Sopenharmony_ci(defthm linear-mod-2
977db96d56Sopenharmony_ci  (implies (and (< 0 b) (< b m)
987db96d56Sopenharmony_ci                (natp x) (natp b)
997db96d56Sopenharmony_ci                (natp m))
1007db96d56Sopenharmony_ci           (equal (< (mod x m)
1017db96d56Sopenharmony_ci                     (mod (+ (- b) x) m))
1027db96d56Sopenharmony_ci                  (< (mod x m) b))))
1037db96d56Sopenharmony_ci
1047db96d56Sopenharmony_ci(defthm linear-mod-3
1057db96d56Sopenharmony_ci  (implies (and (< x m) (< b m)
1067db96d56Sopenharmony_ci                (natp x) (natp b)
1077db96d56Sopenharmony_ci                (rationalp m))
1087db96d56Sopenharmony_ci           (equal (<= b (mod (+ b x) m))
1097db96d56Sopenharmony_ci                  (< (+ b x) m)))
1107db96d56Sopenharmony_ci  :hints (("Goal" :use ((:instance elim-mod-m
1117db96d56Sopenharmony_ci                                   (x (+ b x)))))))
1127db96d56Sopenharmony_ci
1137db96d56Sopenharmony_ci(defthm modaux-2c
1147db96d56Sopenharmony_ci  (implies (and (< 0 b) (< b m)
1157db96d56Sopenharmony_ci                (natp x) (natp b) (natp m)
1167db96d56Sopenharmony_ci                (<= b (mod (+ b x) m)))
1177db96d56Sopenharmony_ci           (equal (mod (+ b x) m)
1187db96d56Sopenharmony_ci                  (+ b (mod x m))))
1197db96d56Sopenharmony_ci  :hints (("Subgoal *1/8''" :use (linear-mod-3))))
1207db96d56Sopenharmony_ci
1217db96d56Sopenharmony_ci(defthmd modaux-2d
1227db96d56Sopenharmony_ci  (implies (and (< x m) (< 0 x) (< 0 m)
1237db96d56Sopenharmony_ci                (< (- m) b) (< b 0) (rationalp m)
1247db96d56Sopenharmony_ci                (<= x (mod (+ b x) m))
1257db96d56Sopenharmony_ci                (rationalp x) (rationalp b))
1267db96d56Sopenharmony_ci           (equal (+ (- m) (mod (+ b x) m))
1277db96d56Sopenharmony_ci                  (+ b x)))
1287db96d56Sopenharmony_ci  :hints (("Goal" :cases ((<= 0 (+ b x))))
1297db96d56Sopenharmony_ci          ("Subgoal 2'" :use ((:instance modaux-1b
1307db96d56Sopenharmony_ci                                        (x (+ b x)))))))
1317db96d56Sopenharmony_ci
1327db96d56Sopenharmony_ci(defthm mod-m-b
1337db96d56Sopenharmony_ci  (implies (and (< 0 x) (< 0 b) (< 0 m)
1347db96d56Sopenharmony_ci                (< x b) (< b m)
1357db96d56Sopenharmony_ci                (natp x) (natp b) (natp m))
1367db96d56Sopenharmony_ci           (equal (mod (+ (mod (- x) m) b) m)
1377db96d56Sopenharmony_ci                  (mod (- x) b))))
1387db96d56Sopenharmony_ci
1397db96d56Sopenharmony_ci
1407db96d56Sopenharmony_ci;; =====================================================================
1417db96d56Sopenharmony_ci;;                          addmod, submod
1427db96d56Sopenharmony_ci;; =====================================================================
1437db96d56Sopenharmony_ci
1447db96d56Sopenharmony_ci(defun addmod (a b m base)
1457db96d56Sopenharmony_ci  (let* ((s (mod (+ a b) base))
1467db96d56Sopenharmony_ci         (s (if (< s a) (mod (- s m) base) s))
1477db96d56Sopenharmony_ci         (s (if (>= s m) (mod (- s m) base) s)))
1487db96d56Sopenharmony_ci        s))
1497db96d56Sopenharmony_ci
1507db96d56Sopenharmony_ci(defthmd addmod-correct
1517db96d56Sopenharmony_ci  (implies (and (< 0 m) (< m base)
1527db96d56Sopenharmony_ci                (< a m) (<= b m)
1537db96d56Sopenharmony_ci                (natp m) (natp base)
1547db96d56Sopenharmony_ci                (natp a) (natp b))
1557db96d56Sopenharmony_ci           (equal (addmod a b m base)
1567db96d56Sopenharmony_ci                  (mod (+ a b) m)))
1577db96d56Sopenharmony_ci  :hints (("Goal" :cases ((<= base (+ a b))))
1587db96d56Sopenharmony_ci          ("Subgoal 2.1'" :use ((:instance elim-mod-m
1597db96d56Sopenharmony_ci                                           (x (+ a b)))))))
1607db96d56Sopenharmony_ci
1617db96d56Sopenharmony_ci(defun submod (a b m base)
1627db96d56Sopenharmony_ci  (let* ((d (mod (- a b) base))
1637db96d56Sopenharmony_ci         (d (if (< a d) (mod (+ d m) base) d)))
1647db96d56Sopenharmony_ci        d))
1657db96d56Sopenharmony_ci
1667db96d56Sopenharmony_ci(defthmd submod-aux1
1677db96d56Sopenharmony_ci  (implies (and (< a (mod (+ a (- b)) base))
1687db96d56Sopenharmony_ci                (< 0 base) (< a base) (<= b base)
1697db96d56Sopenharmony_ci                (natp base) (natp a) (natp b))
1707db96d56Sopenharmony_ci           (< a b))
1717db96d56Sopenharmony_ci  :rule-classes :forward-chaining)
1727db96d56Sopenharmony_ci
1737db96d56Sopenharmony_ci(defthmd submod-aux2
1747db96d56Sopenharmony_ci  (implies (and (<= (mod (+ a (- b)) base) a)
1757db96d56Sopenharmony_ci                (< 0 base) (< a base) (< b base)
1767db96d56Sopenharmony_ci                (natp base) (natp a) (natp b))
1777db96d56Sopenharmony_ci           (<= b a))
1787db96d56Sopenharmony_ci  :rule-classes :forward-chaining)
1797db96d56Sopenharmony_ci
1807db96d56Sopenharmony_ci(defthmd submod-correct
1817db96d56Sopenharmony_ci  (implies (and (< 0 m) (< m base)
1827db96d56Sopenharmony_ci                (< a m) (<= b m)
1837db96d56Sopenharmony_ci                (natp m) (natp base)
1847db96d56Sopenharmony_ci                (natp a) (natp b))
1857db96d56Sopenharmony_ci           (equal (submod a b m base)
1867db96d56Sopenharmony_ci                  (mod (- a b) m)))
1877db96d56Sopenharmony_ci  :hints (("Goal" :cases ((<= base (+ a b))))
1887db96d56Sopenharmony_ci          ("Subgoal 2.2" :use ((:instance submod-aux1)))
1897db96d56Sopenharmony_ci          ("Subgoal 2.2'''" :cases ((and (< 0 (+ a (- b) m))
1907db96d56Sopenharmony_ci                                         (< (+ a (- b) m) m))))
1917db96d56Sopenharmony_ci          ("Subgoal 2.1" :use ((:instance submod-aux2)))
1927db96d56Sopenharmony_ci          ("Subgoal 1.2" :use ((:instance submod-aux1)))
1937db96d56Sopenharmony_ci          ("Subgoal 1.1" :use ((:instance submod-aux2)))))
1947db96d56Sopenharmony_ci
1957db96d56Sopenharmony_ci
1967db96d56Sopenharmony_ci(defun submod-2 (a b m base)
1977db96d56Sopenharmony_ci  (let* ((d (mod (- a b) base))
1987db96d56Sopenharmony_ci         (d (if (< a b) (mod (+ d m) base) d)))
1997db96d56Sopenharmony_ci        d))
2007db96d56Sopenharmony_ci
2017db96d56Sopenharmony_ci(defthm submod-2-correct
2027db96d56Sopenharmony_ci  (implies (and (< 0 m) (< m base)
2037db96d56Sopenharmony_ci                (< a m) (<= b m)
2047db96d56Sopenharmony_ci                (natp m) (natp base)
2057db96d56Sopenharmony_ci                (natp a) (natp b))
2067db96d56Sopenharmony_ci           (equal (submod-2 a b m base)
2077db96d56Sopenharmony_ci                  (mod (- a b) m)))
2087db96d56Sopenharmony_ci  :hints (("Subgoal 2'" :cases ((and (< 0 (+ a (- b) m))
2097db96d56Sopenharmony_ci                                     (< (+ a (- b) m) m))))))
2107db96d56Sopenharmony_ci
2117db96d56Sopenharmony_ci
2127db96d56Sopenharmony_ci;; =========================================================================
2137db96d56Sopenharmony_ci;;                         ext-submod is correct
2147db96d56Sopenharmony_ci;; =========================================================================
2157db96d56Sopenharmony_ci
2167db96d56Sopenharmony_ci; a < 2*m, b < 2*m
2177db96d56Sopenharmony_ci(defun ext-submod (a b m base)
2187db96d56Sopenharmony_ci  (let* ((a (if (>= a m) (- a m) a))
2197db96d56Sopenharmony_ci         (b (if (>= b m) (- b m) b))
2207db96d56Sopenharmony_ci         (d (mod (- a b) base))
2217db96d56Sopenharmony_ci         (d (if (< a b) (mod (+ d m) base) d)))
2227db96d56Sopenharmony_ci        d))
2237db96d56Sopenharmony_ci
2247db96d56Sopenharmony_ci; a < 2*m, b < 2*m
2257db96d56Sopenharmony_ci(defun ext-submod-2 (a b m base)
2267db96d56Sopenharmony_ci  (let* ((a (mod a m))
2277db96d56Sopenharmony_ci         (b (mod b m))
2287db96d56Sopenharmony_ci         (d (mod (- a b) base))
2297db96d56Sopenharmony_ci         (d (if (< a b) (mod (+ d m) base) d)))
2307db96d56Sopenharmony_ci        d))
2317db96d56Sopenharmony_ci
2327db96d56Sopenharmony_ci(defthmd ext-submod-ext-submod-2-equal
2337db96d56Sopenharmony_ci  (implies (and (< 0 m) (< m base)
2347db96d56Sopenharmony_ci                (< a (* 2 m)) (< b (* 2 m))
2357db96d56Sopenharmony_ci                (natp m) (natp base)
2367db96d56Sopenharmony_ci                (natp a) (natp b))
2377db96d56Sopenharmony_ci           (equal (ext-submod a b m base)
2387db96d56Sopenharmony_ci                  (ext-submod-2 a b m base))))
2397db96d56Sopenharmony_ci
2407db96d56Sopenharmony_ci(defthmd ext-submod-2-correct
2417db96d56Sopenharmony_ci  (implies (and (< 0 m) (< m base)
2427db96d56Sopenharmony_ci                (< a (* 2 m)) (< b (* 2 m))
2437db96d56Sopenharmony_ci                (natp m) (natp base)
2447db96d56Sopenharmony_ci                (natp a) (natp b))
2457db96d56Sopenharmony_ci           (equal (ext-submod-2 a b m base)
2467db96d56Sopenharmony_ci                  (mod (- a b) m))))
2477db96d56Sopenharmony_ci
2487db96d56Sopenharmony_ci
2497db96d56Sopenharmony_ci;; =========================================================================
2507db96d56Sopenharmony_ci;;                            dw-reduce is correct
2517db96d56Sopenharmony_ci;; =========================================================================
2527db96d56Sopenharmony_ci
2537db96d56Sopenharmony_ci(defun dw-reduce (hi lo m base)
2547db96d56Sopenharmony_ci  (let* ((r1 (mod hi m))
2557db96d56Sopenharmony_ci         (r2 (mod (+ (* r1 base) lo) m)))
2567db96d56Sopenharmony_ci        r2))
2577db96d56Sopenharmony_ci
2587db96d56Sopenharmony_ci(defthmd dw-reduce-correct
2597db96d56Sopenharmony_ci  (implies (and (< 0 m) (< m base)
2607db96d56Sopenharmony_ci                (< hi base) (< lo base)
2617db96d56Sopenharmony_ci                (natp m) (natp base)
2627db96d56Sopenharmony_ci                (natp hi) (natp lo))
2637db96d56Sopenharmony_ci           (equal (dw-reduce hi lo m base)
2647db96d56Sopenharmony_ci                  (mod (+ (* hi base) lo) m))))
2657db96d56Sopenharmony_ci
2667db96d56Sopenharmony_ci(defthmd <=-multiply-both-sides-by-z
2677db96d56Sopenharmony_ci  (implies (and (rationalp x) (rationalp y)
2687db96d56Sopenharmony_ci                (< 0 z) (rationalp z))
2697db96d56Sopenharmony_ci           (equal (<= x y)
2707db96d56Sopenharmony_ci                  (<= (* z x) (* z y)))))
2717db96d56Sopenharmony_ci
2727db96d56Sopenharmony_ci(defthmd dw-reduce-aux1
2737db96d56Sopenharmony_ci  (implies (and (< 0 m) (< m base)
2747db96d56Sopenharmony_ci                (natp m) (natp base)
2757db96d56Sopenharmony_ci                (< lo base) (natp lo)
2767db96d56Sopenharmony_ci                (< x m) (natp x))
2777db96d56Sopenharmony_ci           (< (+ lo (* base x)) (* base m)))
2787db96d56Sopenharmony_ci  :hints (("Goal" :cases ((<= (+ x 1) m)))
2797db96d56Sopenharmony_ci          ("Subgoal 1''" :cases ((<= (* base (+ x 1)) (* base m))))
2807db96d56Sopenharmony_ci          ("subgoal 1.2" :use ((:instance <=-multiply-both-sides-by-z
2817db96d56Sopenharmony_ci                                          (x (+ 1 x))
2827db96d56Sopenharmony_ci                                          (y m)
2837db96d56Sopenharmony_ci                                          (z base))))))
2847db96d56Sopenharmony_ci
2857db96d56Sopenharmony_ci(defthm dw-reduce-aux2
2867db96d56Sopenharmony_ci  (implies (and (< x (* base m))
2877db96d56Sopenharmony_ci                (< 0 m) (< m base)
2887db96d56Sopenharmony_ci                (natp m) (natp base) (natp x))
2897db96d56Sopenharmony_ci           (< (floor x m) base)))
2907db96d56Sopenharmony_ci
2917db96d56Sopenharmony_ci;; This is the necessary condition for using _mpd_div_words().
2927db96d56Sopenharmony_ci(defthmd dw-reduce-second-quotient-fits-in-single-word
2937db96d56Sopenharmony_ci  (implies (and (< 0 m) (< m base)
2947db96d56Sopenharmony_ci                (< hi base) (< lo base)
2957db96d56Sopenharmony_ci                (natp m) (natp base)
2967db96d56Sopenharmony_ci                (natp hi) (natp lo)
2977db96d56Sopenharmony_ci                (equal r1 (mod hi m)))
2987db96d56Sopenharmony_ci           (< (floor (+ (* r1 base) lo) m)
2997db96d56Sopenharmony_ci              base))
3007db96d56Sopenharmony_ci  :hints (("Goal" :cases ((< r1 m)))
3017db96d56Sopenharmony_ci          ("Subgoal 1''" :cases ((< (+ lo (* base (mod hi m))) (* base m))))
3027db96d56Sopenharmony_ci          ("Subgoal 1.2" :use ((:instance dw-reduce-aux1
3037db96d56Sopenharmony_ci                                          (x (mod hi m)))))))
3047db96d56Sopenharmony_ci
3057db96d56Sopenharmony_ci
3067db96d56Sopenharmony_ci;; =========================================================================
3077db96d56Sopenharmony_ci;;                            dw-submod is correct
3087db96d56Sopenharmony_ci;; =========================================================================
3097db96d56Sopenharmony_ci
3107db96d56Sopenharmony_ci(defun dw-submod (a hi lo m base)
3117db96d56Sopenharmony_ci  (let* ((r (dw-reduce hi lo m base))
3127db96d56Sopenharmony_ci         (d (mod (- a r) base))
3137db96d56Sopenharmony_ci         (d (if (< a r) (mod (+ d m) base) d)))
3147db96d56Sopenharmony_ci        d))
3157db96d56Sopenharmony_ci
3167db96d56Sopenharmony_ci(defthmd dw-submod-aux1
3177db96d56Sopenharmony_ci  (implies (and (natp a) (< 0 m) (natp m)
3187db96d56Sopenharmony_ci                (natp x) (equal r (mod x m)))
3197db96d56Sopenharmony_ci           (equal (mod (- a x) m)
3207db96d56Sopenharmony_ci                  (mod (- a r) m))))
3217db96d56Sopenharmony_ci
3227db96d56Sopenharmony_ci(defthmd dw-submod-correct
3237db96d56Sopenharmony_ci  (implies (and (< 0 m) (< m base)
3247db96d56Sopenharmony_ci                (natp a) (< a m)
3257db96d56Sopenharmony_ci                (< hi base) (< lo base)
3267db96d56Sopenharmony_ci                (natp m) (natp base)
3277db96d56Sopenharmony_ci                (natp hi) (natp lo))
3287db96d56Sopenharmony_ci           (equal (dw-submod a hi lo m base)
3297db96d56Sopenharmony_ci                  (mod (- a (+ (* base hi) lo)) m)))
3307db96d56Sopenharmony_ci  :hints (("Goal" :in-theory (disable dw-reduce)
3317db96d56Sopenharmony_ci                  :use ((:instance dw-submod-aux1
3327db96d56Sopenharmony_ci                                   (x (+ lo (* base hi)))
3337db96d56Sopenharmony_ci                                   (r (dw-reduce hi lo m base)))
3347db96d56Sopenharmony_ci                        (:instance dw-reduce-correct)))))
3357db96d56Sopenharmony_ci
3367db96d56Sopenharmony_ci
3377db96d56Sopenharmony_ci;; =========================================================================
3387db96d56Sopenharmony_ci;;                      ANSI C arithmetic for uint64_t
3397db96d56Sopenharmony_ci;; =========================================================================
3407db96d56Sopenharmony_ci
3417db96d56Sopenharmony_ci(defun add (a b)
3427db96d56Sopenharmony_ci  (mod (+ a b)
3437db96d56Sopenharmony_ci       (expt 2 64)))
3447db96d56Sopenharmony_ci
3457db96d56Sopenharmony_ci(defun sub (a b)
3467db96d56Sopenharmony_ci  (mod (- a b)
3477db96d56Sopenharmony_ci       (expt 2 64)))
3487db96d56Sopenharmony_ci
3497db96d56Sopenharmony_ci(defun << (w n)
3507db96d56Sopenharmony_ci  (mod (* w (expt 2 n))
3517db96d56Sopenharmony_ci       (expt 2 64)))
3527db96d56Sopenharmony_ci
3537db96d56Sopenharmony_ci(defun >> (w n)
3547db96d56Sopenharmony_ci  (floor w (expt 2 n)))
3557db96d56Sopenharmony_ci
3567db96d56Sopenharmony_ci;; join upper and lower half of a double word, yielding a 128 bit number
3577db96d56Sopenharmony_ci(defun join (hi lo)
3587db96d56Sopenharmony_ci  (+ (* (expt 2 64) hi) lo))
3597db96d56Sopenharmony_ci
3607db96d56Sopenharmony_ci
3617db96d56Sopenharmony_ci;; =============================================================================
3627db96d56Sopenharmony_ci;;                           Fast modular reduction
3637db96d56Sopenharmony_ci;; =============================================================================
3647db96d56Sopenharmony_ci
3657db96d56Sopenharmony_ci;; These are the three primes used in the Number Theoretic Transform.
3667db96d56Sopenharmony_ci;; A fast modular reduction scheme exists for all of them.
3677db96d56Sopenharmony_ci(defmacro p1 ()
3687db96d56Sopenharmony_ci  (+ (expt 2 64) (- (expt 2 32)) 1))
3697db96d56Sopenharmony_ci
3707db96d56Sopenharmony_ci(defmacro p2 ()
3717db96d56Sopenharmony_ci  (+ (expt 2 64) (- (expt 2 34)) 1))
3727db96d56Sopenharmony_ci
3737db96d56Sopenharmony_ci(defmacro p3 ()
3747db96d56Sopenharmony_ci  (+ (expt 2 64) (- (expt 2 40)) 1))
3757db96d56Sopenharmony_ci
3767db96d56Sopenharmony_ci
3777db96d56Sopenharmony_ci;; reduce the double word number hi*2**64 + lo (mod p1)
3787db96d56Sopenharmony_ci(defun simple-mod-reduce-p1 (hi lo)
3797db96d56Sopenharmony_ci  (+ (* (expt 2 32) hi) (- hi) lo))
3807db96d56Sopenharmony_ci
3817db96d56Sopenharmony_ci;; reduce the double word number hi*2**64 + lo (mod p2)
3827db96d56Sopenharmony_ci(defun simple-mod-reduce-p2 (hi lo)
3837db96d56Sopenharmony_ci  (+ (* (expt 2 34) hi) (- hi) lo))
3847db96d56Sopenharmony_ci
3857db96d56Sopenharmony_ci;; reduce the double word number hi*2**64 + lo (mod p3)
3867db96d56Sopenharmony_ci(defun simple-mod-reduce-p3 (hi lo)
3877db96d56Sopenharmony_ci  (+ (* (expt 2 40) hi) (- hi) lo))
3887db96d56Sopenharmony_ci
3897db96d56Sopenharmony_ci
3907db96d56Sopenharmony_ci; ----------------------------------------------------------
3917db96d56Sopenharmony_ci;      The modular reductions given above are correct
3927db96d56Sopenharmony_ci; ----------------------------------------------------------
3937db96d56Sopenharmony_ci
3947db96d56Sopenharmony_ci(defthmd congruence-p1-aux
3957db96d56Sopenharmony_ci  (equal (* (expt 2 64) hi)
3967db96d56Sopenharmony_ci         (+ (* (p1) hi)
3977db96d56Sopenharmony_ci            (* (expt 2 32) hi)
3987db96d56Sopenharmony_ci            (- hi))))
3997db96d56Sopenharmony_ci
4007db96d56Sopenharmony_ci(defthmd congruence-p2-aux
4017db96d56Sopenharmony_ci  (equal (* (expt 2 64) hi)
4027db96d56Sopenharmony_ci         (+ (* (p2) hi)
4037db96d56Sopenharmony_ci            (* (expt 2 34) hi)
4047db96d56Sopenharmony_ci            (- hi))))
4057db96d56Sopenharmony_ci
4067db96d56Sopenharmony_ci(defthmd congruence-p3-aux
4077db96d56Sopenharmony_ci  (equal (* (expt 2 64) hi)
4087db96d56Sopenharmony_ci         (+ (* (p3) hi)
4097db96d56Sopenharmony_ci            (* (expt 2 40) hi)
4107db96d56Sopenharmony_ci            (- hi))))
4117db96d56Sopenharmony_ci
4127db96d56Sopenharmony_ci(defthmd mod-augment
4137db96d56Sopenharmony_ci  (implies (and (rationalp x)
4147db96d56Sopenharmony_ci                (rationalp y)
4157db96d56Sopenharmony_ci                (rationalp m))
4167db96d56Sopenharmony_ci           (equal (mod (+ x y) m)
4177db96d56Sopenharmony_ci                  (mod (+ x (mod y m)) m))))
4187db96d56Sopenharmony_ci
4197db96d56Sopenharmony_ci(defthmd simple-mod-reduce-p1-congruent
4207db96d56Sopenharmony_ci  (implies (and (integerp hi)
4217db96d56Sopenharmony_ci                (integerp lo))
4227db96d56Sopenharmony_ci           (equal (mod (simple-mod-reduce-p1 hi lo) (p1))
4237db96d56Sopenharmony_ci                  (mod (join hi lo) (p1))))
4247db96d56Sopenharmony_ci  :hints (("Goal''" :use ((:instance congruence-p1-aux)
4257db96d56Sopenharmony_ci                          (:instance mod-augment
4267db96d56Sopenharmony_ci                                     (m (p1))
4277db96d56Sopenharmony_ci                                     (x (+ (- hi) lo (* (expt 2 32) hi)))
4287db96d56Sopenharmony_ci                                     (y (* (p1) hi)))))))
4297db96d56Sopenharmony_ci
4307db96d56Sopenharmony_ci(defthmd simple-mod-reduce-p2-congruent
4317db96d56Sopenharmony_ci  (implies (and (integerp hi)
4327db96d56Sopenharmony_ci                (integerp lo))
4337db96d56Sopenharmony_ci           (equal (mod (simple-mod-reduce-p2 hi lo) (p2))
4347db96d56Sopenharmony_ci                  (mod (join hi lo) (p2))))
4357db96d56Sopenharmony_ci  :hints (("Goal''" :use ((:instance congruence-p2-aux)
4367db96d56Sopenharmony_ci                          (:instance mod-augment
4377db96d56Sopenharmony_ci                                     (m (p2))
4387db96d56Sopenharmony_ci                                     (x (+ (- hi) lo (* (expt 2 34) hi)))
4397db96d56Sopenharmony_ci                                     (y (* (p2) hi)))))))
4407db96d56Sopenharmony_ci
4417db96d56Sopenharmony_ci(defthmd simple-mod-reduce-p3-congruent
4427db96d56Sopenharmony_ci  (implies (and (integerp hi)
4437db96d56Sopenharmony_ci                (integerp lo))
4447db96d56Sopenharmony_ci           (equal (mod (simple-mod-reduce-p3 hi lo) (p3))
4457db96d56Sopenharmony_ci                  (mod (join hi lo) (p3))))
4467db96d56Sopenharmony_ci  :hints (("Goal''" :use ((:instance congruence-p3-aux)
4477db96d56Sopenharmony_ci                          (:instance mod-augment
4487db96d56Sopenharmony_ci                                     (m (p3))
4497db96d56Sopenharmony_ci                                     (x (+ (- hi) lo (* (expt 2 40) hi)))
4507db96d56Sopenharmony_ci                                     (y (* (p3) hi)))))))
4517db96d56Sopenharmony_ci
4527db96d56Sopenharmony_ci
4537db96d56Sopenharmony_ci; ---------------------------------------------------------------------
4547db96d56Sopenharmony_ci;  We need a number less than 2*p, so that we can use the trick from
4557db96d56Sopenharmony_ci;  elim-mod-m<x<2*m for the final reduction.
4567db96d56Sopenharmony_ci;  For p1, two modular reductions are sufficient, for p2 and p3 three.
4577db96d56Sopenharmony_ci; ---------------------------------------------------------------------
4587db96d56Sopenharmony_ci
4597db96d56Sopenharmony_ci;; p1: the first reduction is less than 2**96
4607db96d56Sopenharmony_ci(defthmd simple-mod-reduce-p1-<-2**96
4617db96d56Sopenharmony_ci  (implies (and (< hi (expt 2 64))
4627db96d56Sopenharmony_ci                (< lo (expt 2 64))
4637db96d56Sopenharmony_ci                (natp hi) (natp lo))
4647db96d56Sopenharmony_ci           (< (simple-mod-reduce-p1 hi lo)
4657db96d56Sopenharmony_ci              (expt 2 96))))
4667db96d56Sopenharmony_ci
4677db96d56Sopenharmony_ci;; p1: the second reduction is less than 2*p1
4687db96d56Sopenharmony_ci(defthmd simple-mod-reduce-p1-<-2*p1
4697db96d56Sopenharmony_ci  (implies (and (< hi (expt 2 64))
4707db96d56Sopenharmony_ci                (< lo (expt 2 64))
4717db96d56Sopenharmony_ci                (< (join hi lo) (expt 2 96))
4727db96d56Sopenharmony_ci                (natp hi) (natp lo))
4737db96d56Sopenharmony_ci           (< (simple-mod-reduce-p1 hi lo)
4747db96d56Sopenharmony_ci              (* 2 (p1)))))
4757db96d56Sopenharmony_ci
4767db96d56Sopenharmony_ci
4777db96d56Sopenharmony_ci;; p2: the first reduction is less than 2**98
4787db96d56Sopenharmony_ci(defthmd simple-mod-reduce-p2-<-2**98
4797db96d56Sopenharmony_ci  (implies (and (< hi (expt 2 64))
4807db96d56Sopenharmony_ci                (< lo (expt 2 64))
4817db96d56Sopenharmony_ci                (natp hi) (natp lo))
4827db96d56Sopenharmony_ci           (< (simple-mod-reduce-p2 hi lo)
4837db96d56Sopenharmony_ci              (expt 2 98))))
4847db96d56Sopenharmony_ci
4857db96d56Sopenharmony_ci;; p2: the second reduction is less than 2**69
4867db96d56Sopenharmony_ci(defthmd simple-mod-reduce-p2-<-2*69
4877db96d56Sopenharmony_ci  (implies (and (< hi (expt 2 64))
4887db96d56Sopenharmony_ci                (< lo (expt 2 64))
4897db96d56Sopenharmony_ci                (< (join hi lo) (expt 2 98))
4907db96d56Sopenharmony_ci                (natp hi) (natp lo))
4917db96d56Sopenharmony_ci           (< (simple-mod-reduce-p2 hi lo)
4927db96d56Sopenharmony_ci              (expt 2 69))))
4937db96d56Sopenharmony_ci
4947db96d56Sopenharmony_ci;; p3: the third reduction is less than 2*p2
4957db96d56Sopenharmony_ci(defthmd simple-mod-reduce-p2-<-2*p2
4967db96d56Sopenharmony_ci  (implies (and (< hi (expt 2 64))
4977db96d56Sopenharmony_ci                (< lo (expt 2 64))
4987db96d56Sopenharmony_ci                (< (join hi lo) (expt 2 69))
4997db96d56Sopenharmony_ci                (natp hi) (natp lo))
5007db96d56Sopenharmony_ci           (< (simple-mod-reduce-p2 hi lo)
5017db96d56Sopenharmony_ci              (* 2 (p2)))))
5027db96d56Sopenharmony_ci
5037db96d56Sopenharmony_ci
5047db96d56Sopenharmony_ci;; p3: the first reduction is less than 2**104
5057db96d56Sopenharmony_ci(defthmd simple-mod-reduce-p3-<-2**104
5067db96d56Sopenharmony_ci  (implies (and (< hi (expt 2 64))
5077db96d56Sopenharmony_ci                (< lo (expt 2 64))
5087db96d56Sopenharmony_ci                (natp hi) (natp lo))
5097db96d56Sopenharmony_ci           (< (simple-mod-reduce-p3 hi lo)
5107db96d56Sopenharmony_ci              (expt 2 104))))
5117db96d56Sopenharmony_ci
5127db96d56Sopenharmony_ci;; p3: the second reduction is less than 2**81
5137db96d56Sopenharmony_ci(defthmd simple-mod-reduce-p3-<-2**81
5147db96d56Sopenharmony_ci  (implies (and (< hi (expt 2 64))
5157db96d56Sopenharmony_ci                (< lo (expt 2 64))
5167db96d56Sopenharmony_ci                (< (join hi lo) (expt 2 104))
5177db96d56Sopenharmony_ci                (natp hi) (natp lo))
5187db96d56Sopenharmony_ci           (< (simple-mod-reduce-p3 hi lo)
5197db96d56Sopenharmony_ci              (expt 2 81))))
5207db96d56Sopenharmony_ci
5217db96d56Sopenharmony_ci;; p3: the third reduction is less than 2*p3
5227db96d56Sopenharmony_ci(defthmd simple-mod-reduce-p3-<-2*p3
5237db96d56Sopenharmony_ci  (implies (and (< hi (expt 2 64))
5247db96d56Sopenharmony_ci                (< lo (expt 2 64))
5257db96d56Sopenharmony_ci                (< (join hi lo) (expt 2 81))
5267db96d56Sopenharmony_ci                (natp hi) (natp lo))
5277db96d56Sopenharmony_ci           (< (simple-mod-reduce-p3 hi lo)
5287db96d56Sopenharmony_ci              (* 2 (p3)))))
5297db96d56Sopenharmony_ci
5307db96d56Sopenharmony_ci
5317db96d56Sopenharmony_ci; -------------------------------------------------------------------------
5327db96d56Sopenharmony_ci;      The simple modular reductions, adapted for compiler friendly C
5337db96d56Sopenharmony_ci; -------------------------------------------------------------------------
5347db96d56Sopenharmony_ci
5357db96d56Sopenharmony_ci(defun mod-reduce-p1 (hi lo)
5367db96d56Sopenharmony_ci  (let* ((y hi)
5377db96d56Sopenharmony_ci         (x y)
5387db96d56Sopenharmony_ci         (hi (>> hi 32))
5397db96d56Sopenharmony_ci         (x (sub lo x))
5407db96d56Sopenharmony_ci         (hi (if (> x lo) (+ hi -1) hi))
5417db96d56Sopenharmony_ci         (y (<< y 32))
5427db96d56Sopenharmony_ci         (lo (add y x))
5437db96d56Sopenharmony_ci         (hi (if (< lo y) (+ hi 1) hi)))
5447db96d56Sopenharmony_ci        (+ (* hi (expt 2 64)) lo)))
5457db96d56Sopenharmony_ci
5467db96d56Sopenharmony_ci(defun mod-reduce-p2 (hi lo)
5477db96d56Sopenharmony_ci  (let* ((y hi)
5487db96d56Sopenharmony_ci         (x y)
5497db96d56Sopenharmony_ci         (hi (>> hi 30))
5507db96d56Sopenharmony_ci         (x (sub lo x))
5517db96d56Sopenharmony_ci         (hi (if (> x lo) (+ hi -1) hi))
5527db96d56Sopenharmony_ci         (y (<< y 34))
5537db96d56Sopenharmony_ci         (lo (add y x))
5547db96d56Sopenharmony_ci         (hi (if (< lo y) (+ hi 1) hi)))
5557db96d56Sopenharmony_ci        (+ (* hi (expt 2 64)) lo)))
5567db96d56Sopenharmony_ci
5577db96d56Sopenharmony_ci(defun mod-reduce-p3 (hi lo)
5587db96d56Sopenharmony_ci  (let* ((y hi)
5597db96d56Sopenharmony_ci         (x y)
5607db96d56Sopenharmony_ci         (hi (>> hi 24))
5617db96d56Sopenharmony_ci         (x (sub lo x))
5627db96d56Sopenharmony_ci         (hi (if (> x lo) (+ hi -1) hi))
5637db96d56Sopenharmony_ci         (y (<< y 40))
5647db96d56Sopenharmony_ci         (lo (add y x))
5657db96d56Sopenharmony_ci         (hi (if (< lo y) (+ hi 1) hi)))
5667db96d56Sopenharmony_ci        (+ (* hi (expt 2 64)) lo)))
5677db96d56Sopenharmony_ci
5687db96d56Sopenharmony_ci
5697db96d56Sopenharmony_ci; -------------------------------------------------------------------------
5707db96d56Sopenharmony_ci;     The compiler friendly versions are equal to the simple versions
5717db96d56Sopenharmony_ci; -------------------------------------------------------------------------
5727db96d56Sopenharmony_ci
5737db96d56Sopenharmony_ci(defthm mod-reduce-aux1
5747db96d56Sopenharmony_ci  (implies (and (<= 0 a) (natp a) (natp m)
5757db96d56Sopenharmony_ci                (< (- m) b) (<= b 0)
5767db96d56Sopenharmony_ci                (integerp b)
5777db96d56Sopenharmony_ci                (< (mod (+ b a) m)
5787db96d56Sopenharmony_ci                   (mod a m)))
5797db96d56Sopenharmony_ci           (equal (mod (+ b a) m)
5807db96d56Sopenharmony_ci                  (+ b (mod a m))))
5817db96d56Sopenharmony_ci  :hints (("Subgoal 2" :use ((:instance modaux-1b
5827db96d56Sopenharmony_ci                                        (x (+ a b)))))))
5837db96d56Sopenharmony_ci
5847db96d56Sopenharmony_ci(defthm mod-reduce-aux2
5857db96d56Sopenharmony_ci  (implies (and (<= 0 a) (natp a) (natp m)
5867db96d56Sopenharmony_ci                (< b m) (natp b)
5877db96d56Sopenharmony_ci                (< (mod (+ b a) m)
5887db96d56Sopenharmony_ci                   (mod a m)))
5897db96d56Sopenharmony_ci           (equal (+ m (mod (+ b a) m))
5907db96d56Sopenharmony_ci                  (+ b (mod a m)))))
5917db96d56Sopenharmony_ci
5927db96d56Sopenharmony_ci
5937db96d56Sopenharmony_ci(defthm mod-reduce-aux3
5947db96d56Sopenharmony_ci  (implies (and (< 0 a) (natp a) (natp m)
5957db96d56Sopenharmony_ci                (< (- m) b) (< b 0)
5967db96d56Sopenharmony_ci                (integerp b)
5977db96d56Sopenharmony_ci                (<= (mod a m)
5987db96d56Sopenharmony_ci                    (mod (+ b a) m)))
5997db96d56Sopenharmony_ci           (equal (+ (- m) (mod (+ b a) m))
6007db96d56Sopenharmony_ci                  (+ b (mod a m))))
6017db96d56Sopenharmony_ci  :hints (("Subgoal 1.2'" :use ((:instance modaux-1b
6027db96d56Sopenharmony_ci                                           (x b))))
6037db96d56Sopenharmony_ci          ("Subgoal 1''" :use ((:instance modaux-2d
6047db96d56Sopenharmony_ci                                          (x I))))))
6057db96d56Sopenharmony_ci
6067db96d56Sopenharmony_ci
6077db96d56Sopenharmony_ci(defthm mod-reduce-aux4
6087db96d56Sopenharmony_ci  (implies (and (< 0 a) (natp a) (natp m)
6097db96d56Sopenharmony_ci                (< b m) (natp b)
6107db96d56Sopenharmony_ci                (<= (mod a m)
6117db96d56Sopenharmony_ci                    (mod (+ b a) m)))
6127db96d56Sopenharmony_ci           (equal (mod (+ b a) m)
6137db96d56Sopenharmony_ci                  (+ b (mod a m)))))
6147db96d56Sopenharmony_ci
6157db96d56Sopenharmony_ci
6167db96d56Sopenharmony_ci(defthm mod-reduce-p1==simple-mod-reduce-p1
6177db96d56Sopenharmony_ci  (implies (and (< hi (expt 2 64))
6187db96d56Sopenharmony_ci                (< lo (expt 2 64))
6197db96d56Sopenharmony_ci                (natp hi) (natp lo))
6207db96d56Sopenharmony_ci           (equal (mod-reduce-p1 hi lo)
6217db96d56Sopenharmony_ci                  (simple-mod-reduce-p1 hi lo)))
6227db96d56Sopenharmony_ci  :hints (("Goal" :in-theory (disable expt)
6237db96d56Sopenharmony_ci                  :cases ((< 0 hi)))
6247db96d56Sopenharmony_ci          ("Subgoal 1.2.2'" :use ((:instance mod-reduce-aux1
6257db96d56Sopenharmony_ci                                             (m (expt 2 64))
6267db96d56Sopenharmony_ci                                             (b (+ (- HI) LO))
6277db96d56Sopenharmony_ci                                             (a (* (expt 2 32) hi)))))
6287db96d56Sopenharmony_ci          ("Subgoal 1.2.1'" :use ((:instance mod-reduce-aux3
6297db96d56Sopenharmony_ci                                             (m (expt 2 64))
6307db96d56Sopenharmony_ci                                             (b (+ (- HI) LO))
6317db96d56Sopenharmony_ci                                             (a (* (expt 2 32) hi)))))
6327db96d56Sopenharmony_ci          ("Subgoal 1.1.2'" :use ((:instance mod-reduce-aux2
6337db96d56Sopenharmony_ci                                             (m (expt 2 64))
6347db96d56Sopenharmony_ci                                             (b (+ (- HI) LO))
6357db96d56Sopenharmony_ci                                             (a (* (expt 2 32) hi)))))
6367db96d56Sopenharmony_ci          ("Subgoal 1.1.1'" :use ((:instance mod-reduce-aux4
6377db96d56Sopenharmony_ci                                             (m (expt 2 64))
6387db96d56Sopenharmony_ci                                             (b (+ (- HI) LO))
6397db96d56Sopenharmony_ci                                             (a (* (expt 2 32) hi)))))))
6407db96d56Sopenharmony_ci
6417db96d56Sopenharmony_ci
6427db96d56Sopenharmony_ci(defthm mod-reduce-p2==simple-mod-reduce-p2
6437db96d56Sopenharmony_ci  (implies (and (< hi (expt 2 64))
6447db96d56Sopenharmony_ci                (< lo (expt 2 64))
6457db96d56Sopenharmony_ci                (natp hi) (natp lo))
6467db96d56Sopenharmony_ci           (equal (mod-reduce-p2 hi lo)
6477db96d56Sopenharmony_ci                  (simple-mod-reduce-p2 hi lo)))
6487db96d56Sopenharmony_ci  :hints (("Goal" :cases ((< 0 hi)))
6497db96d56Sopenharmony_ci          ("Subgoal 1.2.2'" :use ((:instance mod-reduce-aux1
6507db96d56Sopenharmony_ci                                             (m (expt 2 64))
6517db96d56Sopenharmony_ci                                             (b (+ (- HI) LO))
6527db96d56Sopenharmony_ci                                             (a (* (expt 2 34) hi)))))
6537db96d56Sopenharmony_ci          ("Subgoal 1.2.1'" :use ((:instance mod-reduce-aux3
6547db96d56Sopenharmony_ci                                             (m (expt 2 64))
6557db96d56Sopenharmony_ci                                             (b (+ (- HI) LO))
6567db96d56Sopenharmony_ci                                             (a (* (expt 2 34) hi)))))
6577db96d56Sopenharmony_ci          ("Subgoal 1.1.2'" :use ((:instance mod-reduce-aux2
6587db96d56Sopenharmony_ci                                             (m (expt 2 64))
6597db96d56Sopenharmony_ci                                             (b (+ (- HI) LO))
6607db96d56Sopenharmony_ci                                             (a (* (expt 2 34) hi)))))
6617db96d56Sopenharmony_ci          ("Subgoal 1.1.1'" :use ((:instance mod-reduce-aux4
6627db96d56Sopenharmony_ci                                             (m (expt 2 64))
6637db96d56Sopenharmony_ci                                             (b (+ (- HI) LO))
6647db96d56Sopenharmony_ci                                             (a (* (expt 2 34) hi)))))))
6657db96d56Sopenharmony_ci
6667db96d56Sopenharmony_ci
6677db96d56Sopenharmony_ci(defthm mod-reduce-p3==simple-mod-reduce-p3
6687db96d56Sopenharmony_ci  (implies (and (< hi (expt 2 64))
6697db96d56Sopenharmony_ci                (< lo (expt 2 64))
6707db96d56Sopenharmony_ci                (natp hi) (natp lo))
6717db96d56Sopenharmony_ci           (equal (mod-reduce-p3 hi lo)
6727db96d56Sopenharmony_ci                  (simple-mod-reduce-p3 hi lo)))
6737db96d56Sopenharmony_ci  :hints (("Goal" :cases ((< 0 hi)))
6747db96d56Sopenharmony_ci          ("Subgoal 1.2.2'" :use ((:instance mod-reduce-aux1
6757db96d56Sopenharmony_ci                                             (m (expt 2 64))
6767db96d56Sopenharmony_ci                                             (b (+ (- HI) LO))
6777db96d56Sopenharmony_ci                                             (a (* (expt 2 40) hi)))))
6787db96d56Sopenharmony_ci          ("Subgoal 1.2.1'" :use ((:instance mod-reduce-aux3
6797db96d56Sopenharmony_ci                                             (m (expt 2 64))
6807db96d56Sopenharmony_ci                                             (b (+ (- HI) LO))
6817db96d56Sopenharmony_ci                                             (a (* (expt 2 40) hi)))))
6827db96d56Sopenharmony_ci          ("Subgoal 1.1.2'" :use ((:instance mod-reduce-aux2
6837db96d56Sopenharmony_ci                                             (m (expt 2 64))
6847db96d56Sopenharmony_ci                                             (b (+ (- HI) LO))
6857db96d56Sopenharmony_ci                                             (a (* (expt 2 40) hi)))))
6867db96d56Sopenharmony_ci          ("Subgoal 1.1.1'" :use ((:instance mod-reduce-aux4
6877db96d56Sopenharmony_ci                                             (m (expt 2 64))
6887db96d56Sopenharmony_ci                                             (b (+ (- HI) LO))
6897db96d56Sopenharmony_ci                                             (a (* (expt 2 40) hi)))))))
6907db96d56Sopenharmony_ci
6917db96d56Sopenharmony_ci
6927db96d56Sopenharmony_ci
693