commit c1eae16cdbb2c1913f99e94d043d9e859246959c Author: Michael Fiano Date: Thu Apr 21 05:27:08 2022 -0400 First commit. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a5353af --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Michael Fiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a53d017 --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# dynamic-array + +An implementation of the AVL tree data structure. + +An optimized 1-dimensional array of fixnums that automatically re-adjusts in size. + +## Overview + +An optimized 1-dimensional array type that can only store fixnums, and which is able to +automatically grow when pushing new elements to the end. It is not very useful in most situations, +as it doesn't implement the Common Lisp sequences protocol, nor does it conform to the usual +interface of Common Lisp arrays for PUSH and POP. + +## Install + +```lisp +(ql:quickload :dynamic-array) +``` + +## License + +Copyright © 2019-2022 Michael Fiano + +Licensed under the MIT License. diff --git a/dynamic-array.asd b/dynamic-array.asd new file mode 100644 index 0000000..6daffd2 --- /dev/null +++ b/dynamic-array.asd @@ -0,0 +1,13 @@ +(asdf:defsystem #:dynamic-array + :description "An optimized 1-dimensional array of fixnums that automatically re-adjusts in size." + :author "Michael Fiano " + :license "MIT" + :homepage "https://github.com/mfiano/dynamic-array" + :version "0.1.0" + :encoding :utf-8 + :depends-on (#:mfiano-utils) + :pathname "src" + :serial t + :components + ((:file "package") + (:file "dynamic-array"))) diff --git a/src/dynamic-array.lisp b/src/dynamic-array.lisp new file mode 100755 index 0000000..8e0c443 --- /dev/null +++ b/src/dynamic-array.lisp @@ -0,0 +1,92 @@ +(in-package #:dynamic-array) + +(declaim (inline %make-array)) +(defstruct (dynamic-array + (:constructor %make-array) + (:conc-name nil) + (:predicate nil) + (:copier nil)) + (data (cl:make-array 0 :element-type t) :type simple-vector) + (initial-element 0) + (fill-pointer 0 :type fixnum)) + +(u:define-printer (dynamic-array stream :type nil) + (format stream "~{~a~^ ~}" + (coerce (subseq (data dynamic-array) 0 (fill-pointer dynamic-array)) 'list))) + +(defun make-array (&key (size 0) (capacity 128) (element-type t) + initial-element) + (assert (<= size capacity)) + (let ((data (cl:make-array capacity :element-type element-type :initial-element initial-element))) + (%make-array :data data :initial-element initial-element :fill-pointer size))) + +(u:fn-> copy (dynamic-array) dynamic-array) +(defun copy (dynamic-array) + (declare (optimize speed)) + (%make-array :data (u:copy-array (data dynamic-array)) + :initial-element (initial-element dynamic-array) + :fill-pointer (fill-pointer dynamic-array))) + +(u:fn-> length (dynamic-array) fixnum) +(declaim (inline length)) +(defun length (dynamic-array) + (fill-pointer dynamic-array)) + +(u:fn-> aref (dynamic-array fixnum) t) +(declaim (inline aref)) +(defun aref (dynamic-array index) + (declare (optimize speed)) + (if (< index (fill-pointer dynamic-array)) + (locally (declare (optimize (safety 0))) + (cl:aref (data dynamic-array) index)) + (error "Index out of bounds."))) + +(u:fn-> (setf aref) (t dynamic-array fixnum) t) +(declaim (inline (setf aref))) +(defun (setf aref) (value dynamic-array index) + (declare (optimize speed)) + (if (< index (fill-pointer dynamic-array)) + (locally (declare (optimize (safety 0))) + (setf (cl:aref (data dynamic-array) index) value)) + (error "Index out of bounds."))) + +(u:fn-> pop (dynamic-array &optional boolean) t) +(declaim (inline pop)) +(defun pop (dynamic-array &optional delete-p) + (declare (optimize speed)) + (let ((data (data dynamic-array)) + (length (fill-pointer dynamic-array))) + (unless (zerop length) + (prog1 (cl:aref data (decf (fill-pointer dynamic-array))) + (when delete-p + (setf (cl:aref data (1- length)) nil)))))) + +(u:fn-> push (dynamic-array t) dynamic-array) +(defun push (dynamic-array value) + (declare (optimize speed)) + (let* ((data (data dynamic-array)) + (length (cl:length data)) + (fill-pointer (fill-pointer dynamic-array))) + (when (= fill-pointer length) + (let ((data (adjust-array + data + (max 16 (min (* length 2) most-positive-fixnum)) + :initial-element (initial-element dynamic-array)))) + (setf (data dynamic-array) data))) + (locally (declare (optimize (safety 0))) + (setf (cl:aref (data dynamic-array) fill-pointer) value) + (incf (fill-pointer dynamic-array))) + dynamic-array)) + +(u:fn-> map (dynamic-array function) null) +(defun map (dynamic-array func) + (declare (optimize speed)) + (loop :for i :below (length dynamic-array) + :for element = (aref dynamic-array i) + :do (funcall func element))) + +(u:fn-> find (dynamic-array t &key (:test function) (:key function)) t) +(declaim (inline find)) +(defun find (dynamic-array item &key (test #'eql) key) + (declare (optimize speed)) + (cl:find item (data dynamic-array) :key key :test test)) diff --git a/src/package.lisp b/src/package.lisp new file mode 100644 index 0000000..0e8add5 --- /dev/null +++ b/src/package.lisp @@ -0,0 +1,25 @@ +(in-package #:cl-user) + +(defpackage #:dynamic-array + (:local-nicknames + (#:u #:mfiano-utils)) + (:use #:cl) + (:shadow + #:aref + #:fill-pointer + #:find + #:length + #:make-array + #:map + #:pop + #:push) + (:export + #:aref + #:copy + #:dynamic-array + #:find + #:length + #:make-array + #:map + #:pop + #:push))