Skip to content

Instantly share code, notes, and snippets.

@spchamp
Last active July 30, 2016 19:08
Show Gist options
  • Save spchamp/053a293e07a90d1bddafa61b7b1f5d40 to your computer and use it in GitHub Desktop.
Save spchamp/053a293e07a90d1bddafa61b7b1f5d40 to your computer and use it in GitHub Desktop.
Factor ax^2 + bx + c in Common Lisp
;; Author: Sean Champ, 30 July 2016
;; License: Public Domain (#YMMV)
(defun grouping-m-n (a b c)
(let ((radic (sqrt (- (expt b 2) (* 4 a c))))
(nb (- b)))
(values (/ (+ nb radic) -2)
(/ (- nb radic) -2))))
(defun component-grouping (a b c)
(multiple-value-bind (m n) (grouping-m-n a b c)
(let* ((m_z (truncate m))
(n_z (truncate n))
(l (gcd a m_z))
(d (gcd c n_z)))
(values
;; -- ax^2 + bx + c factored --
;; for
;; n' = n_z / d
;; c' = c / d
;; rewrite ax^2 + bx + c
;; as (lx + d) + (n'x + c')
(list l d)
(list (/ n_z d) (/ c d))
;; roots: x = -d/l, -c'/n'
(list (/ (- d) l)
(/ (- c) n_z))))))
#|
Works Referenced
Calter, Paul A, and Michael A Calter. Technical Mathematics. 6th ed. Hoboken, N.J: John Wiley & Sons Inc, 2011. <https://www.safaribooksonline.com/library/view/technical-mathematics-sixth/9780470534922/>
|#
@spchamp
Copy link
Author

spchamp commented Jul 30, 2016

FIXME: Error for evaluating (component-grouping 1 15 70) : Cannot truncate complex number

i.e grouping-m-n returning complex number

component evaluation of x^2 + 15x + 70 = 0

@spchamp
Copy link
Author

spchamp commented Jul 30, 2016

FIXME: Incorrect value when evaluating (component-grouping 1 -5 6)

Synopsis: First root has inverted SIGNUM, second root valid

Test form: (component-factor-eval 1 -5 6) with f(a,b,c) :=

(defun component-factor-eval (a b c)
           (flet ((check (y)
                  (+ (* a (expt y 2)) (* b y) c)))
           (multiple-value-bind (f1 f2 roots) 
               (component-grouping a b c) 
             (declare (ignore f1 f2))
             (destructuring-bind (m n) roots
               (values roots 
                       (zerop (check m)) 
                       (zerop (check n)) 
                       (list (zerop (check (- m))) (- m) n))))))

@spchamp
Copy link
Author

spchamp commented Jul 30, 2016

UPDATE: Avoid factoring on zero return values computed in grouping-m-n

(defun component-grouping (a b c)
           (multiple-value-bind (m n) (grouping-m-n a b c)
             (let* ((m_z (truncate m))
                    (n_z (truncate n)) 
                    (l (gcd a m_z))
                    (d (gcd c n_z)))
               (values 
                ;; factored:
                ;; for 
                ;;  n' = n_z / d
                ;;  c' = c / d
                ;; rewrite ax^2 + bx + c
                ;; as (lx + d) + (n'x + c')
                (list l d)
                (list (/ n_z d) (/ c d))
                ;; roots: x = -d/l, -c'/n'
                (list (unless (zerop l) (/ (- d) l))
                      (unless (zerop n_z) (/ (- c) n_z)))))))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment