Moving all of my Emacs-related files into their own directory at the root of this repository.
		
			
				
	
	
		
			153 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			EmacsLisp
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			EmacsLisp
		
	
	
	
	
	
;;; number.el --- Functions for working with numbers -*- lexical-binding: t -*-
 | 
						|
;; Author: William Carroll <wpcarro@gmail.com>
 | 
						|
 | 
						|
;;; Commentary:
 | 
						|
;;
 | 
						|
;; Classifications of numbers:
 | 
						|
;; - Natural: (a.k.a positive integers, counting numbers); {1, 2, 3, ... }
 | 
						|
;;
 | 
						|
;; - Whole: Natural Numbers, plus zero; {0, 1, 2, 3, ...}
 | 
						|
;;
 | 
						|
;; - Integers: Whole numbers plus all the negatives of the natural numbers;
 | 
						|
;;   {... , -2, -1, 0, 1, 2, ...}
 | 
						|
;;
 | 
						|
;; - Rational numbers: (a.k.a. fractions) where the top and bottom numbers are
 | 
						|
;;   integers; e.g., 1/2, 3/4, 7/2, ⁻4/3, 4/1.  Note: The denominator cannot be
 | 
						|
;;   0, but the numerator can be.
 | 
						|
;;
 | 
						|
;; - Real numbers: All numbers that can be written as a decimal.  This includes
 | 
						|
;;   fractions written in decimal form e.g., 0.5, 0.75 2.35, ⁻0.073, 0.3333, or
 | 
						|
;;   2.142857. It also includes all the irrational numbers such as π, √2 etc.
 | 
						|
;;   Every real number corresponds to a point on the number line.
 | 
						|
;;
 | 
						|
;; The functions defined herein attempt to capture the mathematical definitions
 | 
						|
;; of numbers and their classifications as defined above.
 | 
						|
 | 
						|
;;; Code:
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
;; Dependencies
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
(require 'prelude)
 | 
						|
(require 'dash)
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
;; Library
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
(defconst number/test? t
 | 
						|
  "When t, run the test suite defined herein.")
 | 
						|
 | 
						|
;; TODO: What about int.el?
 | 
						|
 | 
						|
;; TODO: How do we handle a number typeclass?
 | 
						|
 | 
						|
(defun number/positive? (x)
 | 
						|
  "Return t if `X' is a positive number."
 | 
						|
  (> x 0))
 | 
						|
 | 
						|
(defun number/negative? (x)
 | 
						|
  "Return t if `X' is a positive number."
 | 
						|
  (< x 0))
 | 
						|
 | 
						|
;; TODO: Don't rely on this. Need to have 10.0 and 10 behave similarly.
 | 
						|
(defun number/float? (x)
 | 
						|
  "Return t if `X' is a floating point number."
 | 
						|
  (floatp x))
 | 
						|
 | 
						|
(defun number/natural? (x)
 | 
						|
  "Return t if `X' is a natural number."
 | 
						|
  (and (number/positive? x)
 | 
						|
       (not (number/float? x))))
 | 
						|
 | 
						|
(defun number/whole? (x)
 | 
						|
  "Return t if `X' is a whole number."
 | 
						|
  (or (= 0 x)
 | 
						|
      (number/natural? x)))
 | 
						|
 | 
						|
(defun number/integer? (x)
 | 
						|
  "Return t if `X' is an integer."
 | 
						|
  (or (number/whole? x)
 | 
						|
      (number/natural? (- x))))
 | 
						|
 | 
						|
;; TODO: How defensive should these guards be?  Should we assert that the inputs
 | 
						|
;; are integers before checking evenness or oddness?
 | 
						|
 | 
						|
;; TODO: Look up Runar (from Unison) definition of handling zero as even or odd.
 | 
						|
 | 
						|
;; TODO: How should rational numbers be handled? Lisp is supposedly famous for
 | 
						|
;; its handling of rational numbers.
 | 
						|
;; TODO: `calc-mode' supports rational numbers as "1:2" meaning "1/2"
 | 
						|
;; (defun number/rational? (x))
 | 
						|
 | 
						|
;; TODO: Can or should I support real numbers?
 | 
						|
;; (defun number/real? (x))
 | 
						|
 | 
						|
(defun number/even? (x)
 | 
						|
  "Return t if `X' is an even number."
 | 
						|
  (or (= 0 x)
 | 
						|
      (= 0 (mod x 2))))
 | 
						|
 | 
						|
(defun number/odd? (x)
 | 
						|
  "Return t if `X' is an odd number."
 | 
						|
  (not (number/even? x)))
 | 
						|
 | 
						|
(defun number/dec (x)
 | 
						|
  "Subtract one from `X'.
 | 
						|
While this function is undeniably trivial, I have unintentionally done (- 1 x)
 | 
						|
  when in fact I meant to do (- x 1) that I figure it's better for this function
 | 
						|
  to exist, and for me to train myself to reach for it and its inc counterpart."
 | 
						|
  (- x 1))
 | 
						|
 | 
						|
(defun number/inc (x)
 | 
						|
  "Add one to `X'."
 | 
						|
  (+ x 1))
 | 
						|
 | 
						|
;; TODO: Does this belong in a math module?  Is math too vague?  Or is number
 | 
						|
;; too vague?
 | 
						|
;; TODO: Resolve the circular dependency that this introduces with series.el,
 | 
						|
;; and then re-enable this function and its tests below.
 | 
						|
;; (defun number/factorial (x)
 | 
						|
;;   "Return factorial of `X'."
 | 
						|
;;   (cond
 | 
						|
;;    ((number/negative? x) (error "Will not take factorial of negative numbers"))
 | 
						|
;;    ((= 0 x) 1)
 | 
						|
;;    ;; NOTE: Using `series/range' introduces a circular dependency because:
 | 
						|
;;    ;; series -> number -> series.  Conceptually, however, this should be
 | 
						|
;;    ;; perfectly acceptable.
 | 
						|
;;    (t (->> (series/range 1 x)
 | 
						|
;;            (list/reduce 1 #'*)))))
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
;; Tests
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
(when number/test?
 | 
						|
  (prelude/assert
 | 
						|
   (number/positive? 10))
 | 
						|
  (prelude/assert
 | 
						|
   (number/natural? 10))
 | 
						|
  (prelude/assert
 | 
						|
   (number/whole? 10))
 | 
						|
  (prelude/assert
 | 
						|
   (number/whole? 0))
 | 
						|
  (prelude/assert
 | 
						|
   (number/integer? 10))
 | 
						|
  ;; (prelude/assert
 | 
						|
  ;;  (= 120 (number/factorial 5)))
 | 
						|
  (prelude/assert
 | 
						|
   (number/even? 6))
 | 
						|
  (prelude/refute
 | 
						|
   (number/odd? 6))
 | 
						|
  (prelude/refute
 | 
						|
   (number/positive? -10))
 | 
						|
  (prelude/refute
 | 
						|
   (number/natural? 10.0))
 | 
						|
  (prelude/refute
 | 
						|
   (number/natural? -10))
 | 
						|
  (prelude/refute
 | 
						|
   (number/natural? -10.0)))
 | 
						|
 | 
						|
(provide 'number)
 | 
						|
;;; number.el ends here
 |