;;; The MIT License (MIT) ;;; ;;; Copyright (c) 2014 Daniel P. Friedman, Oleg Kiselyov, and William E. Byrd ;;; Modifications Copyright (c) 2021 Jeremy Steward ;;; ;;; Permission is hereby granted, free of charge, to any person obtaining a copy ;;; of this software and associated documentation files (the "Software"), to deal ;;; in the Software without restriction, including without limitation the rights ;;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ;;; copies of the Software, and to permit persons to whom the Software is ;;; furnished to do so, subject to the following conditions: ;;; ;;; The above copyright notice and this permission notice shall be included in all ;;; copies or substantial portions of the Software. ;;; ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ;;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ;;; SOFTWARE. ;;; ;;; Taken from https://github.com/miniKanren/miniKanren and modified to work ;;; with CHICKEN Scheme by Jeremy Steward on 2021-08-28 (define (build-num n) (cond ((odd? n) (cons 1 (build-num (quotient (- n 1) 2)))) ((and (not (zero? n)) (even? n)) (cons 0 (build-num (quotient n 2)))) ((zero? n) '()))) (define (little-endian->number le-num) (let loop ((power 1) (num le-num) (acc 0)) (if (null? num) acc (loop (* 2 power) (cdr num) (+ acc (* power (car num))))))) (define (zeroo n) (== '() n)) (define (poso n) (fresh (a d) (== `(,a . ,d) n))) (define (>1o n) (fresh (a ad dd) (== `(,a ,ad . ,dd) n))) (define (full-addero b x y r c) (conde ((== 0 b) (== 0 x) (== 0 y) (== 0 r) (== 0 c)) ((== 1 b) (== 0 x) (== 0 y) (== 1 r) (== 0 c)) ((== 0 b) (== 1 x) (== 0 y) (== 1 r) (== 0 c)) ((== 1 b) (== 1 x) (== 0 y) (== 0 r) (== 1 c)) ((== 0 b) (== 0 x) (== 1 y) (== 1 r) (== 0 c)) ((== 1 b) (== 0 x) (== 1 y) (== 0 r) (== 1 c)) ((== 0 b) (== 1 x) (== 1 y) (== 0 r) (== 1 c)) ((== 1 b) (== 1 x) (== 1 y) (== 1 r) (== 1 c)))) (define (addero d n m r) (conde ((== 0 d) (== '() m) (== n r)) ((== 0 d) (== '() n) (== m r) (poso m)) ((== 1 d) (== '() m) (addero 0 n '(1) r)) ((== 1 d) (== '() n) (poso m) (addero 0 '(1) m r)) ((== '(1) n) (== '(1) m) (fresh (a c) (== `(,a ,c) r) (full-addero d 1 1 a c))) ((== '(1) n) (gen-addero d n m r)) ((== '(1) m) (>1o n) (>1o r) (addero d '(1) n r)) ((>1o n) (gen-addero d n m r)))) (define (gen-addero d n m r) (fresh (a b c e x y z) (== `(,a . ,x) n) (== `(,b . ,y) m) (poso y) (== `(,c . ,z) r) (poso z) (full-addero d a b c e) (addero e x y z))) (define (pluso n m k) (addero 0 n m k)) (define +o pluso) (define (minuso n m k) (pluso m k n)) (define -o minuso) (define (*o n m p) (conde ((== '() n) (== '() p)) ((poso n) (== '() m) (== '() p)) ((== '(1) n) (poso m) (== m p)) ((>1o n) (== '(1) m) (== n p)) ((fresh (x z) (== `(0 . ,x) n) (poso x) (== `(0 . ,z) p) (poso z) (>1o m) (*o x m z))) ((fresh (x y) (== `(1 . ,x) n) (poso x) (== `(0 . ,y) m) (poso y) (*o m n p))) ((fresh (x y) (== `(1 . ,x) n) (poso x) (== `(1 . ,y) m) (poso y) (odd-*o x n m p))))) (define (odd-*o x n m p) (fresh (q) (bound-*o q p n m) (*o x m q) (pluso `(0 . ,q) m p))) (define (bound-*o q p n m) (conde ((== '() q) (poso p)) ((fresh (a0 a1 a2 a3 x y z) (== `(,a0 . ,x) q) (== `(,a1 . ,y) p) (conde ((== '() n) (== `(,a2 . ,z) m) (bound-*o x y z '())) ((== `(,a3 . ,z) n) (bound-*o x y z m))))))) (define (=lo n m) (conde ((== '() n) (== '() m)) ((== '(1) n) (== '(1) m)) ((fresh (a x b y) (== `(,a . ,x) n) (poso x) (== `(,b . ,y) m) (poso y) (=lo x y))))) (define (1o m)) ((fresh (a x b y) (== `(,a . ,x) n) (poso x) (== `(,b . ,y) m) (poso y) (1o b) (=lo n b) (pluso r b n)) ((== '(1) b) (poso q) (pluso r '(1) n)) ((== '() b) (poso q) (== r n)) ((== '(0 1) b) (fresh (a ad dd) (poso dd) (== `(,a ,ad . ,dd) n) (exp2 n '() q) (fresh (s) (splito n dd r s)))) ((fresh (a ad add ddd) (conde ((== '(1 1) b)) ((== `(,a ,ad ,add . ,ddd) b)))) (1o n) (== '(1) q) (fresh (s) (splito n b s '(1)))) ((fresh (q1 b2) (== `(0 . ,q1) q) (poso q1) (1o q) (fresh (q1 nq1) (pluso q1 '(1) q) (repeated-mul n q1 nq1) (*o nq1 n nq))))) (define (expo b q n) (logo n b q '()))