Skip to content

Commit e51fce2

Browse files
committed
Merge branch 'master' of github.com:0x10c-dev/stdlib
2 parents 065600f + 48a99d2 commit e51fce2

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed

math/ilog.dasm

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
;; Integer Logarithms for Various Bases
2+
;; by Kang Seonghoon (lifthrasiir, @senokay)
3+
;; licensed under WTFPL. feel free to use.
4+
;;
5+
;; declares: ilog2, ilog10, ilog10s
6+
7+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8+
;; ilog2
9+
10+
; calculates ilog2(A) where:
11+
; ilog2(x) = floor(log_2(x)) if x > 0
12+
; = 0 if x = 0.
13+
;
14+
; cycles: 25
15+
; receives: A
16+
; clobbers: A, B
17+
; returns: A
18+
:ilog2
19+
SET B, A ; A = A | (A<<1)
20+
SHR B, 1
21+
BOR A, B
22+
SET B, A ; A = A | (A<<2)
23+
SHR B, 2
24+
BOR A, B
25+
SET B, A ; A = A | (A<<4)
26+
SHR B, 4
27+
BOR A, B
28+
SET B, A ; A = A | (A<<8)
29+
SHR B, 8
30+
BOR A, B
31+
MUL A, 0xf2d ; A = ilog2_debruijn[(A*0xf2d)>>12]
32+
SHR A, 12
33+
SET A, [A+ilog2_debruijn]
34+
SET PC, POP
35+
:ilog2_debruijn
36+
DAT 0, 7, 1, 13, 8, 10, 2, 14
37+
DAT 6, 12, 9, 5, 11, 4, 3, 15
38+
39+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
40+
;; ilog10 (in two variants)
41+
42+
; calculates ilog10(A) where:
43+
; ilog10(x) = floor(log_10(x)) if x > 0
44+
; = 0 if x = 0.
45+
;
46+
; takes 13 cycles when 0 <= A < 100,
47+
; 16 cycles when 100 <= A < 10000,
48+
; 8 cycles when 10000 <= A < 65536.
49+
; use this if your input is uniformly distributed.
50+
;
51+
; cycles: <= 16, 9.2 average
52+
; receives: A
53+
; clobbers: A
54+
; returns: A
55+
:ilog10
56+
IFG A, 9999
57+
ADD PC, 7 ; jumps to ilog10_above9999
58+
IFG A, 99
59+
ADD PC, 6 ; jumps to ilog10_above99
60+
ADD 0xfff6, A ; 0xfff6 = 0x10000 - 10
61+
SET A, O ; now O = (A >= 10)
62+
SET PC, POP
63+
:ilog10_above9999
64+
SET A, 4
65+
SET PC, POP
66+
:ilog10_above99
67+
ADD 0xfc18, A ; 0xfc18 = 0x10000 - 1000
68+
SET A, 2 ; now O = (A >= 1000)
69+
BOR A, O
70+
SET PC, POP
71+
72+
; same as ilog10 but optimized for smaller inputs.
73+
;
74+
; takes 10 cycles when 0 <= A < 100,
75+
; 16 cycles when 100 <= A < 10000,
76+
; 11 cycles when 10000 <= A < 65536.
77+
;
78+
; cycles: <= 16, 11.8 average
79+
; receives: A
80+
; clobbers: A
81+
; returns: A
82+
:ilog10s
83+
IFG 100, A
84+
ADD PC, 5 ; jumps to ilog10_below100
85+
IFG 10000, A
86+
ADD PC, 6 ; jumps to ilog10_below10000
87+
SET A, 4
88+
SET PC, POP
89+
:ilog10_below100
90+
ADD 0xfff6, A ; 0xfff6 = 0x10000 - 10
91+
SET A, O ; now O = (A >= 10)
92+
SET PC, POP
93+
:ilog10_below10000
94+
ADD 0xfc18, A ; 0xfc18 = 0x10000 - 1000
95+
SET A, 2 ; now O = (A >= 1000)
96+
BOR A, O
97+
SET PC, POP
98+

0 commit comments

Comments
 (0)