├── LICENSE ├── README.md └── numsectorlisp.lisp /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Hikaru Ikuta 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Numsectorlisp 2 | Numsectorlisp is a library for [SectorLISP](https://github.com/jart/sectorlisp), 3 | for scalar, vector, and matrix multiplication of fixed-point numbers. 4 | The number of bits for the fractional part and the decimal part can be easily configured. 5 | The default setting implements 16-bit fixed-point numbers with 12 bits for the fractional part, 6 | 3 bits for the integer part, and 1 bit for the sign. 7 | Instructions for configuring the bit sizes are available inside the source code. 8 | 9 | An in-depth explanation of the implementation details are available in my blog post, 10 | [Building a Neural Network in Pure Lisp Without Built-In Numbers Using Only Atoms and Lists](https://woodrush.github.io/blog/posts/2022-01-16-neural-networks-in-pure-lisp.html). 11 | 12 | Examples uses of numsectorlisp are available in these projects: 13 | 14 | - [A Neural Network written in SectorLISP](https://github.com/woodrush/sectorlisp-nn), from [Building a Neural Network in Pure Lisp Without Built-In Numbers Using Only Atoms and Lists](https://woodrush.github.io/blog/posts/2022-01-16-neural-networks-in-pure-lisp.html) 15 | - [Mandelbrot set plotter](https://github.com/woodrush/sectorlisp-examples/blob/main/lisp/mandelbrot.lisp), from [sectorlisp-examples](https://github.com/woodrush/sectorlisp-examples) 16 | -------------------------------------------------------------------------------- /numsectorlisp.lisp: -------------------------------------------------------------------------------- 1 | ((LAMBDA (_ u0 umax fracbitsize 1 2 | _ addhalf _ addfull _ uaddnofc _ uaddnof _ umultnof _ take _ drop 3 | _ ufixmult _ negate _ + _ - _ * _ isnegative _ < _ > _ << 4 | _ vdot _ vecmatmulVAT _ matmulABT _ ReLUscal _ ReLUvec 5 | _ vecadd _ vecargmax) 6 | ((LAMBDA () 7 | (+ (<< 1 (QUOTE (* * *))) 8 | (* (negate 1) (negate 1)))))) 9 | (QUOTE 10 | ;; ======================================================================== 11 | ;; Settings 12 | ;; ======================================================================== 13 | ;; The bit sizes for the fixed-point number system can be configured here. 14 | ;; 15 | ;; - The binary expression for the numbers is in reverse order, where the 16 | ;; most significant bit is at the right side. 17 | ;; - The sign bit is included in the integer part, and is the rightmost 18 | ;; bit, with `1` as negative and `0` as positive. 19 | ;; - `fracbitsize` determines the number of bits to be used for the 20 | ;; fractional part. 21 | ;; - The number of bits for the integer part for u0 and umax must be equal. 22 | ;; 23 | ;; ======================================================================== 24 | ;; Usage 25 | ;; ======================================================================== 26 | ;; - All functions after `negate` can be used as library functions. 27 | ;; - `1` is an example variable bound to the scalar fixed-point number 1. 28 | ;; - Vectors are lists of scalars, and matrices are lists of vectors. 29 | ;; - In vecmatmulVAT, matmulABT, the second operand AT and BT are 30 | ;; transposed. For example, when calculating A dot B using matmulABT, 31 | ;; B must be transposed before being provided to matmulABT. 32 | ;; - The input to `<<` is in unary. Note that `<<` works as division 33 | ;; since the binary is expressed in reverse order. 34 | ;; 35 | ) 36 | (QUOTE (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) 37 | (QUOTE (1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)) 38 | (QUOTE (1 1 1 1 1 1 1 1 1 1 1 1)) 39 | (QUOTE (0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0)) 40 | (QUOTE 41 | ;; ======================================================================== 42 | ;; addhalf : Half adder 43 | ;; Output binary is in reverse order (the msb is at the end) 44 | ;; The same applies to the entire system 45 | ) 46 | (QUOTE (LAMBDA (X Y) 47 | (COND 48 | ((EQ X (QUOTE 1)) 49 | (COND 50 | ((EQ Y (QUOTE 1)) (CONS (QUOTE 0) (QUOTE 1))) 51 | ((QUOTE T) (CONS (QUOTE 1) (QUOTE 0))))) 52 | ((QUOTE T) 53 | (CONS Y (QUOTE 0)))))) 54 | (QUOTE 55 | ;; addfull : Full adder 56 | ) 57 | (QUOTE (LAMBDA (X Y C) 58 | ((LAMBDA (HA1) 59 | ((LAMBDA (HA2) 60 | (CONS (CAR HA2) 61 | (COND 62 | ((EQ (QUOTE 1) (CDR HA1)) (QUOTE 1)) 63 | ((QUOTE T) (CDR HA2))))) 64 | (addhalf C (CAR HA1)))) 65 | (addhalf X Y)))) 66 | (QUOTE 67 | ;; uaddnofc : Unsigned N-bit add with carry 68 | ) 69 | (QUOTE (LAMBDA (X Y C) 70 | (COND 71 | ((EQ NIL X) Y) 72 | ((EQ NIL Y) X) 73 | ((QUOTE T) 74 | ((LAMBDA (XYC) 75 | (CONS (CAR XYC) (uaddnofc (CDR X) (CDR Y) (CDR XYC)))) 76 | (addfull (CAR X) (CAR Y) C)))))) 77 | (QUOTE 78 | ;; uaddnof : Unsigned N-bit add 79 | ) 80 | (QUOTE (LAMBDA (X Y) 81 | (uaddnofc X Y (QUOTE 0)))) 82 | (QUOTE 83 | ;; umultnof : Unsigned N-bit mult 84 | ) 85 | (QUOTE (LAMBDA (X Y) 86 | (COND 87 | ((EQ NIL Y) u0) 88 | ((QUOTE T) 89 | (uaddnof (COND 90 | ((EQ (QUOTE 0) (CAR Y)) u0) 91 | ((QUOTE T) X)) 92 | (umultnof (CONS (QUOTE 0) X) (CDR Y))))))) 93 | (QUOTE 94 | ;; take : Take a list of (len L) atoms from X 95 | ) 96 | (QUOTE (LAMBDA (L X) 97 | (COND 98 | ((EQ NIL L) NIL) 99 | ((QUOTE T) (CONS (CAR X) (take (CDR L) (CDR X))))))) 100 | (QUOTE 101 | ;; drop : Drop the first (len L) atoms from X 102 | ) 103 | (QUOTE (LAMBDA (L X) 104 | (COND 105 | ((EQ NIL X) NIL) 106 | ((EQ NIL L) X) 107 | ((QUOTE T) (drop (CDR L) (CDR X)))))) 108 | (QUOTE 109 | ;; ufixmult : Unsigned fixed-point multiplication 110 | ) 111 | (QUOTE (LAMBDA (X Y) 112 | (take u0 (+ u0 (drop fracbitsize (umultnof X Y)))))) 113 | (QUOTE 114 | ;; negate : Two's complement of int 115 | ) 116 | (QUOTE (LAMBDA (N) 117 | (take u0 (umultnof N umax)))) 118 | (QUOTE 119 | ;; + 120 | ) 121 | (QUOTE (LAMBDA (X Y) 122 | (take u0 (uaddnof X Y (QUOTE 0))))) 123 | (QUOTE 124 | ;; - 125 | ) 126 | (QUOTE (LAMBDA (X Y) 127 | (take u0 (uaddnof X (negate Y) (QUOTE 0))))) 128 | (QUOTE 129 | ;; * 130 | ) 131 | (QUOTE (LAMBDA (X Y) 132 | (COND 133 | ((< X u0) 134 | (COND 135 | ((< Y u0) 136 | (ufixmult (negate X) (negate Y))) 137 | ((QUOTE T) 138 | (negate (ufixmult (negate X) Y))))) 139 | ((< Y u0) 140 | (negate (ufixmult X (negate Y)))) 141 | ((QUOTE T) 142 | (ufixmult X Y))))) 143 | (QUOTE 144 | ;; isnegative 145 | ) 146 | (QUOTE (LAMBDA (X) 147 | (EQ (QUOTE 1) (CAR (drop (CDR u0) X))))) 148 | (QUOTE 149 | ;; < 150 | ) 151 | (QUOTE (LAMBDA (X Y) 152 | (COND 153 | ((isnegative X) (COND 154 | ((isnegative Y) (isnegative (- (negate Y) (negate X)))) 155 | ((QUOTE T) (QUOTE T)))) 156 | ((QUOTE T) (COND 157 | ((isnegative Y) NIL) 158 | ((QUOTE T) (isnegative (- X Y)))))))) 159 | (QUOTE 160 | ;; > 161 | ) 162 | (QUOTE (LAMBDA (X Y) 163 | (< Y X))) 164 | (QUOTE 165 | ;; << : Shift X by Y_u bits, where Y_u is in unary. 166 | ;; Note that since the bits are written in reverse order, 167 | ;; this works as division and makes the input number smaller. 168 | ) 169 | (QUOTE (LAMBDA (X Y_u) 170 | (+ (drop Y_u X) u0))) 171 | (QUOTE 172 | ;; vdot : Vector dot product 173 | ) 174 | (QUOTE (LAMBDA (X Y) 175 | (COND 176 | (X (+ (* (CAR X) (CAR Y)) (vdot (CDR X) (CDR Y)))) 177 | ((QUOTE T) u0)))) 178 | (QUOTE 179 | ;; vecmatmulVAT : vec, mat -> vec : Vector V times transposed matrix A 180 | ) 181 | (QUOTE (LAMBDA (V AT) 182 | ((LAMBDA (vecmatmulVAThelper) 183 | (vecmatmulVAThelper AT)) 184 | (QUOTE (LAMBDA (AT) 185 | (COND 186 | (AT (CONS (vdot V (CAR AT)) (vecmatmulVAThelper (CDR AT)))) 187 | ((QUOTE T) NIL))))))) 188 | (QUOTE 189 | ;; matmulABT : mat, mat -> mat : Matrix A times transposed matrix B 190 | ) 191 | (QUOTE (LAMBDA (A BT) 192 | ((LAMBDA (matmulABThelper) 193 | (matmulABThelper A)) 194 | (QUOTE (LAMBDA (A) 195 | (COND 196 | (A (CONS (vecmatmulVAT (CAR A) BT) (matmulABThelper (CDR A)))) 197 | ((QUOTE T) NIL))))))) 198 | (QUOTE 199 | ;; ReLUscal 200 | ) 201 | (QUOTE (LAMBDA (X) 202 | (COND 203 | ((isnegative X) u0) 204 | ((QUOTE T) X)))) 205 | (QUOTE 206 | ;; ReLUvec 207 | ) 208 | (QUOTE (LAMBDA (V) 209 | (COND 210 | (V (CONS (ReLUscal (CAR V)) (ReLUvec (CDR V)))) 211 | ((QUOTE T) NIL)))) 212 | (QUOTE 213 | ;; vecadd 214 | ) 215 | (QUOTE (LAMBDA (X Y) 216 | (COND 217 | (X (CONS (+ (CAR X) (CAR Y)) (vecadd (CDR X) (CDR Y)))) 218 | ((QUOTE T) NIL)))) 219 | (QUOTE 220 | ;; vecargmax : Output is provided in unary 221 | ) 222 | (QUOTE (LAMBDA (X) 223 | ((LAMBDA (vecargmaxhelper) 224 | (vecargmaxhelper (CDR X) (CAR X) () (QUOTE (*)))) 225 | (QUOTE (LAMBDA (X curmax maxind curind) 226 | (COND 227 | (X (COND 228 | ((< curmax (CAR X)) (vecargmaxhelper 229 | (CDR X) 230 | (CAR X) 231 | curind 232 | (CONS (QUOTE *) curind))) 233 | ((QUOTE T) (vecargmaxhelper 234 | (CDR X) 235 | curmax 236 | maxind 237 | (CONS (QUOTE *) curind))))) 238 | ((QUOTE T) maxind))))))) 239 | (QUOTE 240 | ;; nth : N is unary. The 0th item is the first item. 241 | ) 242 | (QUOTE (LAMBDA (N L) 243 | (COND 244 | (N (nth (CDR N) (CDR L))) 245 | ((QUOTE T) (CAR L)))))) 246 | --------------------------------------------------------------------------------