Skip to content

Commit 027a2dc

Browse files
author
Symbolics
committed
Add optional type argument to array generating functions
This commit also resolves issue #1 and issue #3.
1 parent 0a8ef6c commit 027a2dc

File tree

6 files changed

+76
-62
lines changed

6 files changed

+76
-62
lines changed

LICENSE.md

+4
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,7 @@ A "contributor" is any person that distributes its contribution under this licen
2929
(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
3030

3131
(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
32+
33+
34+
35+
Original portions of the code are licensed under the MIT license

README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,12 @@ Contributions are what make the open source community such an amazing place to b
158158
<!-- LICENSE -->
159159
## License
160160

161-
Distributed under the MS-PL License. See [LICENSE](LICENSE.md) for more information.
161+
The original code from Tamas Papp and Ben Dudson is licensed under the MIT license. Modifications by Symbolics are
162+
distributed under the MS-PL License. See [LICENSE](LICENSE.md) for more information.
162163

163164
## Notes
164165

165-
Expect spurious warnings from SBCL related to 'deleting unreachable code' when running the tests. The tests it's warning about _do_ run and we haven't had the time to debug SBCL's warnings.
166+
Expect spurious warnings from SBCL related to 'deleting unreachable code' when running the tests. The tests it's warning about _do_ run and we haven't had the time to debug SBCL's warnings. See issue #4.
166167

167168
<!-- CONTACT -->
168169
## Contact

array-operations.asd

+9-9
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,33 @@
22
;;; Copyright (c) 2012-2018 by Tamas Papp. All rights reserved.
33
;;; Copyright (c) 2019-2022 by Ben Dudson. All rights reserved.
44
;;; Copyright (c) 2021-2023 by Symbolics Pte. Ltd. All rights reserved.
5+
;;; SPDX-License-identifier: MS-PL
56

6-
(defsystem #:array-operations
7-
:version "1.1.0"
7+
(defsystem "array-operations"
8+
:version "1.2.0"
89
:description "Array operations library for Common Lisp"
910
:long-description #.(uiop:read-file-string
1011
(uiop:subpathname *load-pathname* "description.text"))
1112
:author "Tamas K. Papp <[email protected]>"
12-
:maintainer "Steve Nunez"
13-
:version "1.0.0"
13+
:maintainer "Steve Nunez <[email protected]>"
1414
:long-name "Array operations for array-like data structures"
1515
:homepage "https://lisp-stat.dev/docs/manuals/array-operations"
1616
:bug-tracker "https://github.com/Lisp-Stat/array-operations/issues"
1717
:license :MS-PL
1818
:class :package-inferred-system
1919
:pathname "src/"
20-
:depends-on (#:let-plus
21-
:array-operations/all)
20+
:depends-on ("let-plus"
21+
"array-operations/all")
2222
:in-order-to ((test-op (test-op :array-operations/tests))))
2323

2424
(defsystem #:array-operations/tests
2525
:description "Unit tests for the ARRAY-OPERATIONS library."
2626
:author "Tamas K. Papp <[email protected]>"
2727
:maintainer "Steve Nunez"
2828
:license :MS-PL
29-
:depends-on (:array-operations ; loads everything else
30-
:alexandria
31-
:clunit2)
29+
:depends-on ("array-operations"
30+
"alexandria"
31+
"clunit2")
3232
:pathname "tests/"
3333
:components ((:file "tests"))
3434
:perform (test-op (o c)

description.text

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
The array-operations system is a collection of functions and macros for manipulating Common Lisp arrays and performing numerical calculations with them.
1+
The array-operations system is a collection of functions and macros for manipulating Common Lisp arrays and performing numerical calculations with them. It is extendible to array-like data structures, such as data frames. It is a core system for solving linear systems of equations in common lisp.
22

33
Array-operations is a 'generic' way of operating on array like data structures using a syntax that is natural for Common Lisp. Several aops functions have been implemented for data-frame. For those that haven't, you can transform arrays to data frames using the df:matrix-df function, and a data-frame to an array using df:as-array. This make it convenient to work with the data sets using either system.

src/creating.lisp

+50-43
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
;;; -*- Mode: LISP; Base: 10; Syntax: ANSI-Common-lisp; Package: ARRAY-OPERATIONS/CREATING -*-
22
;;; Copyright (c) 2012-2018 by Tamas Papp. All rights reserved.
33
;;; Copyright (c) 2018-2022 by Ben Dudson. All rights reserved.
4-
;;; Copyright (c) 2021-2022 by Symbolics Pte. Ltd. All rights reserved.
4+
;;; Copyright (c) 2021-2023 by Symbolics Pte. Ltd. All rights reserved.
5+
;;; SPDX-License-identifier: MS-PL
56

67
(defpackage :array-operations/creating
78
(:use :cl :array-operations/generic
@@ -39,10 +40,14 @@ Returns ARRAY."
3940
:element-type element-type
4041
:initial-element (coerce 0 element-type)))
4142

42-
(defun zeros (dimensions)
43-
"Makes an array of shape DIMENSIONS and type T, filled with zeros"
44-
(make-array (ensure-dimensions dimensions)
45-
:initial-element 0))
43+
(defun zeros (dimensions &optional element-type)
44+
"Make an array of shape DIMENSIONS filled with zeros. Elements are of type T, unless ELEMENT-TYPE is given."
45+
(assert (subtypep element-type 'number)
46+
(element-type)
47+
"Cannot create a ZEROS array because ~A is not a numeric type." element-type)
48+
(if element-type
49+
(zeros* element-type dimensions)
50+
(make-array (ensure-dimensions dimensions) :initial-element 0)))
4651

4752
(defun ones! (array)
4853
"Fills the given ARRAY with 1's, coerced to the element type. Returns ARRAY."
@@ -55,10 +60,14 @@ Returns ARRAY."
5560
:element-type element-type
5661
:initial-element (coerce 1 element-type)))
5762

58-
(defun ones (dimensions)
59-
"Makes an array of shape DIMENSIONS and type T, filled with ones"
60-
(make-array (ensure-dimensions dimensions)
61-
:initial-element 1))
63+
(defun ones (dimensions &optional element-type)
64+
"Makes an array of shape DIMENSIONS filled with ones. Elements are of type T, unless ELEMENT-TYPE is given."
65+
(assert (subtypep element-type 'number)
66+
(element-type)
67+
"Cannot create a ONES array because ~A is not a numeric type." element-type)
68+
(if element-type
69+
(ones* element-type dimensions)
70+
(make-array (ensure-dimensions dimensions) :initial-element 1)))
6271

6372
(defun rand! (array)
6473
"Fills a given ARRAY with random numbers, uniformly distributed between 0 and 1. Uses the built-in RANDOM function.
@@ -77,36 +86,32 @@ Returns ARRAY."
7786
(rand 3) -> #(0.39319038 0.69693553 0.5021677)
7887
(rand '(2 2)) -> #2A((0.91003513 0.23208928) (0.5577954 0.94657767))
7988
80-
NOTE: If it's important that these numbers are really random
81-
(e.g. cryptographic applications), then you should probably
82-
not use this function.
83-
"
89+
NOTE: If it's important that these numbers are really random (e.g. cryptographic applications), then you should probably not use this function. "
8490
(rand! (make-array (ensure-dimensions dimensions)
8591
:element-type element-type)))
8692

87-
(defun rand (dimensions)
88-
"Makes an array of shape DIMENSIONS and type T, filled with random numbers uniformly distributed between 0 and 1.
93+
(defun rand (dimensions &optional element-type)
94+
"Makes an array of shape DIMENSIONS filled with random numbers uniformly distributed between 0 and 1. Elements are of type T, unless ELEMENT-TYPE is given.
8995
9096
Uses the built-in RANDOM function.
9197
9298
(rand 3) -> #(0.39319038 0.69693553 0.5021677)
9399
(rand '(2 2)) -> #2A((0.91003513 0.23208928) (0.5577954 0.94657767))
94100
95-
NOTE: If it's important that these numbers are really random
96-
(e.g. cryptographic applications), then you should probably
97-
not use this function.
98-
"
99-
(rand* t dimensions))
101+
NOTE: If it's important that these numbers are really random (e.g. cryptographic applications), then you should probably not use this function."
102+
(assert (subtypep element-type 'number)
103+
(element-type)
104+
"Cannot create a RAND array because ~A is not a numeric type." element-type)
105+
(if element-type
106+
(rand* element-type dimensions)
107+
(rand* t dimensions)))
100108

101109
(defun randn! (array)
102110
"Fills ARRAY with normally distributed numbers with a mean of zero and standard deviation of 1
103111
104112
Uses the Box-Muller algorithm and built-in random number generator.
105113
106-
NOTE: If it's important that these numbers are really random
107-
(e.g. cryptographic applications), then you should probably
108-
not use this function.
109-
"
114+
NOTE: If it's important that these numbers are really random (e.g. cryptographic applications), then you should probably not use this function."
110115
(let ((element-type (array-element-type array))
111116
(size (array-total-size array)))
112117
(do ((i 0 (+ 2 i)))
@@ -146,24 +151,25 @@ Returns ARRAY."
146151
(randn! (make-array (ensure-dimensions dimensions)
147152
:element-type element-type)))
148153

149-
(defun randn (dimensions)
154+
(defun randn (dimensions &optional element-type)
150155
"Creates an array of shape DIMENSIONS and type T, and fills with normally distributed numbers with a mean of zero and standard deviation of 1
151156
152157
Uses the Box-Muller algorithm and built-in random number generator.
153158
154159
(rand 3) -> #(-0.82067037 -0.60068226 -0.21494178)
155160
(randn '(2 2)) -> #2A((1.6905352 -2.5379088) (0.8461403 -1.505984))
156161
157-
NOTE: If it's important that these numbers are really random
158-
(e.g. cryptographic applications), then you should probably
159-
not use this function.
160-
"
161-
(randn* t dimensions))
162+
NOTE: If it's important that these numbers are really random (e.g. cryptographic applications), then you should probably not use this function."
163+
(assert (subtypep element-type 'number)
164+
(element-type)
165+
"Cannot create a normal random array because ~A is not a numeric type." element-type)
166+
(if element-type
167+
(randn* element-type dimensions)
168+
(randn* t dimensions)))
169+
162170

163171
(defun linspace! (array start stop)
164-
"Fill an array with evenly spaced numbers over an interval.
165-
The first element is equal to START and last element STOP,
166-
with constant difference between consecutive elements in ROW-MAJOR-INDEX."
172+
"Fill an array with evenly spaced numbers over an interval. The first element is equal to START and last element STOP, with constant difference between consecutive elements in ROW-MAJOR-INDEX."
167173
(assert (> stop start) (start stop) "Stop must be greater than start.")
168174
(let* ((size (array-total-size array))
169175
(element-type (array-element-type array))
@@ -174,21 +180,22 @@ Returns ARRAY."
174180
array))
175181

176182
(defun linspace* (element-type start stop n)
177-
"Make a vector of N elements and type ELEMENT-TYPE, containing evenly spaced numbers over an interval.
178-
The first element is equal to START and last element STOP,
179-
with constant difference between consecutive elements."
183+
"Make a vector of N elements and type ELEMENT-TYPE, containing evenly spaced numbers over an interval. The first element is equal to START and last element STOP, with constant difference between consecutive elements."
180184
(linspace! (make-array n :element-type element-type) start stop))
181185

182-
(defun linspace (start stop n)
183-
"Make a vector of N elements and type T, containing evenly spaced numbers over an interval.
184-
The first element is equal to START and last element STOP,
185-
with constant difference between consecutive elements.
186+
(defun linspace (start stop n &optional element-type)
187+
"Make a vector of N elements containing evenly spaced numbers over an interval. The first element is equal to START and last element STOP, with constant difference between consecutive elements. Elements are of type T, unless ELEMENT-TYPE is given
186188
187189
(linspace 0 4 5) -> #(0 1 2 3 4)
188190
(linspace 1 3 5) -> #(0 1/2 1 3/2 2)
189-
(linspace 0 4d0 3) -> #(0.0d0 2.0d0 4.0d0)
190-
"
191-
(linspace* t start stop n))
191+
(linspace 0 4d0 3) -> #(0.0d0 2.0d0 4.0d0)"
192+
(assert (subtypep element-type 'number)
193+
(element-type)
194+
"Cannot create a linear sequence of numbers because ~A is not a numeric type." element-type)
195+
(if element-type
196+
(linspace* element-type start stop n)
197+
(linspace* t start stop n)))
198+
192199

193200
(defun similar-array (array &key (dimensions (dims array))
194201
(adjustable (adjustable-array-p array))

src/transforming.lisp

+9-7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
;;; Copyright (c) 2012-2018 by Tamas Papp. All rights reserved.
33
;;; Copyright (c) 2018-2022 by Ben Dudson. All rights reserved.
44
;;; Copyright (c) 2021-2023 by Symbolics Pte. Ltd. All rights reserved.
5+
;;; SPDX-License-identifier: MS-PL
56

67
(defpackage :array-operations/transforming
78
(:use :cl :array-operations/generic
@@ -27,7 +28,8 @@
2728
:permutation-incompatible-rank
2829
:permute
2930
:recycle
30-
:map-array
31+
:map-array
32+
:array-index-row-major
3133
:turn)
3234
(:documentation "Functions for transforming arrays in various ways."))
3335

@@ -315,14 +317,14 @@ Array element type is preserved."
315317

316318
;;; turning
317319

318-
;; https://groups.google.com/g/comp.lang.lisp/c/CM3MQkyOTHk/m/Pl4KPUqfobwJ
319-
;; Modified into a destructive, non-consing version. RESULT, if provided,
320-
;; must be a list of length equal to the rank of the array; it is modified to
321-
;; contain the result of the function. This way, the result list can be
322-
;; allocated only once and additionally be DX for zero consing. If RESULT is
323-
;; not provided, then it is consed and then returned.
324320
(declaim (inline array-index-row-major))
325321
(defun array-index-row-major (array rmi &optional result)
322+
"https://groups.google.com/g/comp.lang.lisp/c/CM3MQkyOTHk/m/Pl4KPUqfobwJ
323+
Modified into a destructive, non-consing version. RESULT, if provided,
324+
must be a list of length equal to the rank of the array; it is modified to
325+
contain the result of the function. This way, the result list can be
326+
allocated only once and additionally be DX for zero consing. If RESULT is
327+
not provided, then it is consed and then returned."
326328
(declare (optimize speed))
327329
(let* ((rank (array-rank array))
328330
(dimensions (make-list rank)))

0 commit comments

Comments
 (0)