Skip to content

Commit b676293

Browse files
committed
Move unit handling into separate file.
1 parent aa8bd0b commit b676293

File tree

5 files changed

+105
-98
lines changed

5 files changed

+105
-98
lines changed

numbers.lisp

Lines changed: 0 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -290,77 +290,3 @@ returned is the same as the number of arguments given."
290290
(zero (apply #'+ zeros)))
291291
(mapcar (op (+ _ zero))
292292
ns)))
293-
294-
(defconst si-prefixes
295-
'((-24 "yocto" "y")
296-
(-21 "zepto" "z")
297-
(-18 "atto" "a")
298-
(-15 "femto" "f")
299-
(-12 "pico" "p")
300-
( -9 "nano" "n")
301-
( -6 "micro" "μ")
302-
( -3 "milli" "m")
303-
( -2 "centi" "c")
304-
( -1 "deci" "d")
305-
( 0 "" "" )
306-
( 1 "deca" "da")
307-
( 2 "hecto" "h")
308-
( 3 "kilo" "k")
309-
( 6 "mega" "M")
310-
( 9 "giga" "G")
311-
( 12 "tera" "T")
312-
( 15 "peta" "P")
313-
( 18 "exa" "E")
314-
( 21 "zetta" "Z")
315-
( 24 "yotta" "Y"))
316-
"List as SI prefixes: power of ten, long form, short form.")
317-
318-
(defconst si-prefixes-base-1000
319-
(loop for (pow long short) in si-prefixes
320-
unless (and (not (zerop pow))
321-
(< (abs pow) 3))
322-
collect (list (truncate pow 3) long short))
323-
"The SI prefixes as powers of 1000, with centi, deci, deca and hecto omitted.")
324-
325-
(defconst iec-prefixes
326-
'(( 0 "" "")
327-
(10 "kibi" "Ki")
328-
(20 "mebi" "Mi")
329-
(30 "gibi" "Gi")
330-
(40 "tebi" "Ti")
331-
(50 "pebi" "Pi")
332-
(60 "exbi" "Ei"))
333-
"The IEC binary prefixes, as powers of 2.")
334-
335-
(defmacro si-prefix-rec (n base prefixes)
336-
(cond ((null prefixes) (error "No prefixes!"))
337-
((single prefixes)
338-
(destructuring-bind ((power long short)) prefixes
339-
`(values ,long ,short ,(expt base power))))
340-
(t
341-
(multiple-value-bind (lo hi) (halves prefixes)
342-
(let ((split (* (expt base (caar hi)))))
343-
`(if (< ,n ,split)
344-
(si-prefix-rec ,n ,base ,lo)
345-
(si-prefix-rec ,n ,base ,hi)))))))
346-
347-
(defun si-prefix (n &key (base 1000))
348-
"Given a number, return the prefix of the nearest SI unit.
349-
350-
Three values are returned: the long form, the short form, and the
351-
multiplying factor.
352-
353-
(si-prefix 1001) => \"kilo\", \"k\", 1000d0
354-
355-
BASE can be 1000, 10, 1024, or 2. 1000 is the default, and prefixes
356-
start at kilo and milli. Base 10 is mostly the same, except the
357-
prefixes centi, deci, deca and hecto are also used. Base 1024 uses the
358-
same prefixes as 1000, but with 1024 as the base, as in vulgar file
359-
sizes. Base 2 uses the IEC binary prefixes."
360-
(if (zerop n) (values "" "" 1d0)
361-
(let ((n (abs (coerce n 'double-float))))
362-
(ecase base
363-
(2 (si-prefix-rec n 2d0 #.iec-prefixes))
364-
(10 (si-prefix-rec n 10d0 #.si-prefixes))
365-
(1000 (si-prefix-rec n 1000d0 #.si-prefixes-base-1000))
366-
(1024 (si-prefix-rec n 1024d0 #.si-prefixes-base-1000))))))

serapeum.asd

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
(:file "box"
5858
:depends-on ("types" "definitions"))
5959
(:file "numbers"
60-
:depends-on ("types" "op" "definitions"))
60+
:depends-on ("types" "op"))
6161
(:file "octets"
6262
:depends-on ("types"))
6363
(:file "time")
@@ -97,7 +97,8 @@
9797
(:file "tree-case")
9898
(:file "dispatch-case")
9999
(:file "range" :depends-on ("dispatch-case"))
100-
(:file "generalized-arrays" :depends-on ("range"))))))
100+
(:file "generalized-arrays" :depends-on ("range"))
101+
(:file "units")))))
101102

102103
(defsystem "serapeum/tests"
103104
:description "Test suite for Serapeum."
@@ -148,4 +149,5 @@
148149
(:file "dispatch-case")
149150
(:file "range")
150151
(:file "generalized-arrays")
151-
(:file "quicklisp")))))
152+
(:file "quicklisp")
153+
(:file "units")))))

tests/numbers.lisp

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,24 +52,3 @@
5252
most-positive-double-float)))))
5353
(values results1 results2))
5454
(is (every #'= results1 results2))))
55-
56-
(test si-prefix
57-
(is (equal "yocto" (si-prefix least-positive-double-float)))
58-
(is (equal "yotta" (si-prefix most-positive-double-float)))
59-
(is-true (every (equals "") (mapcar #'si-prefix '(0 1 0s0 1s0 0d0 1d0))))
60-
(is (equal "deca" (si-prefix 10 :base 10)))
61-
(is (equal "deca" (si-prefix 12 :base 10)))
62-
(is (equal "kilo" (si-prefix 1001)))
63-
(is (equal "kibi" (si-prefix 2048 :base 2)))
64-
(is (equal "kibi" (si-prefix 1024 :base 2)))
65-
(is (equal "" (si-prefix 1000 :base 2)))
66-
(is (equal "" (si-prefix 1000 :base 1024)))
67-
(is (equal "kilo" (si-prefix 1024)))
68-
(is (equal "kilo" (si-prefix 1000)))
69-
(is (equal "pico" (si-prefix 1s-9)))
70-
(is (equal "nano" (si-prefix 1s-9 :base 1024)))
71-
(is (equal "kilo" (si-prefix -20000)))
72-
(is (equal "" (si-prefix -20)))
73-
(is (equal "kilo" (si-prefix (expt 2 10))))
74-
(is (equal "kibi" (si-prefix (expt 2 10) :base 2)))
75-
(is (equal "yocto" (si-prefix (expt 10 -23)))))

tests/units.lisp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
(in-package :serapeum.tests)
2+
3+
(def-suite units :in serapeum)
4+
(in-suite units)
5+
6+
(test si-prefix
7+
(is (equal "yocto" (si-prefix least-positive-double-float)))
8+
(is (equal "yotta" (si-prefix most-positive-double-float)))
9+
(is-true (every (equals "") (mapcar #'si-prefix '(0 1 0s0 1s0 0d0 1d0))))
10+
(is (equal "deca" (si-prefix 10 :base 10)))
11+
(is (equal "deca" (si-prefix 12 :base 10)))
12+
(is (equal "kilo" (si-prefix 1001)))
13+
(is (equal "kibi" (si-prefix 2048 :base 2)))
14+
(is (equal "kibi" (si-prefix 1024 :base 2)))
15+
(is (equal "" (si-prefix 1000 :base 2)))
16+
(is (equal "" (si-prefix 1000 :base 1024)))
17+
(is (equal "kilo" (si-prefix 1024)))
18+
(is (equal "kilo" (si-prefix 1000)))
19+
(is (equal "pico" (si-prefix 1s-9)))
20+
(is (equal "nano" (si-prefix 1s-9 :base 1024)))
21+
(is (equal "kilo" (si-prefix -20000)))
22+
(is (equal "" (si-prefix -20)))
23+
(is (equal "kilo" (si-prefix (expt 2 10))))
24+
(is (equal "kibi" (si-prefix (expt 2 10) :base 2)))
25+
(is (equal "yocto" (si-prefix (expt 10 -23)))))

units.lisp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
(in-package :serapeum)
2+
3+
(defconst si-prefixes
4+
'((-24 "yocto" "y")
5+
(-21 "zepto" "z")
6+
(-18 "atto" "a")
7+
(-15 "femto" "f")
8+
(-12 "pico" "p")
9+
( -9 "nano" "n")
10+
( -6 "micro" "μ")
11+
( -3 "milli" "m")
12+
( -2 "centi" "c")
13+
( -1 "deci" "d")
14+
( 0 "" "" )
15+
( 1 "deca" "da")
16+
( 2 "hecto" "h")
17+
( 3 "kilo" "k")
18+
( 6 "mega" "M")
19+
( 9 "giga" "G")
20+
( 12 "tera" "T")
21+
( 15 "peta" "P")
22+
( 18 "exa" "E")
23+
( 21 "zetta" "Z")
24+
( 24 "yotta" "Y"))
25+
"List as SI prefixes: power of ten, long form, short form.")
26+
27+
(defconst si-prefixes-base-1000
28+
(loop for (pow long short) in si-prefixes
29+
unless (and (not (zerop pow))
30+
(< (abs pow) 3))
31+
collect (list (truncate pow 3) long short))
32+
"The SI prefixes as powers of 1000, with centi, deci, deca and hecto omitted.")
33+
34+
(defconst iec-prefixes
35+
'(( 0 "" "")
36+
(10 "kibi" "Ki")
37+
(20 "mebi" "Mi")
38+
(30 "gibi" "Gi")
39+
(40 "tebi" "Ti")
40+
(50 "pebi" "Pi")
41+
(60 "exbi" "Ei"))
42+
"The IEC binary prefixes, as powers of 2.")
43+
44+
(defmacro si-prefix-rec (n base prefixes)
45+
(cond ((null prefixes) (error "No prefixes!"))
46+
((single prefixes)
47+
(destructuring-bind ((power long short)) prefixes
48+
`(values ,long ,short ,(expt base power))))
49+
(t
50+
(multiple-value-bind (lo hi) (halves prefixes)
51+
(let ((split (* (expt base (caar hi)))))
52+
`(if (< ,n ,split)
53+
(si-prefix-rec ,n ,base ,lo)
54+
(si-prefix-rec ,n ,base ,hi)))))))
55+
56+
(defun si-prefix (n &key (base 1000))
57+
"Given a number, return the prefix of the nearest SI unit.
58+
59+
Three values are returned: the long form, the short form, and the
60+
multiplying factor.
61+
62+
(si-prefix 1001) => \"kilo\", \"k\", 1000d0
63+
64+
BASE can be 1000, 10, 1024, or 2. 1000 is the default, and prefixes
65+
start at kilo and milli. Base 10 is mostly the same, except the
66+
prefixes centi, deci, deca and hecto are also used. Base 1024 uses the
67+
same prefixes as 1000, but with 1024 as the base, as in vulgar file
68+
sizes. Base 2 uses the IEC binary prefixes."
69+
(if (zerop n) (values "" "" 1d0)
70+
(let ((n (abs (coerce n 'double-float))))
71+
(ecase base
72+
(2 (si-prefix-rec n 2d0 #.iec-prefixes))
73+
(10 (si-prefix-rec n 10d0 #.si-prefixes))
74+
(1000 (si-prefix-rec n 1000d0 #.si-prefixes-base-1000))
75+
(1024 (si-prefix-rec n 1024d0 #.si-prefixes-base-1000))))))

0 commit comments

Comments
 (0)