source: project/wiki/eggref/5/numchi @ 39682

Last change on this file since 39682 was 39682, checked in by Diego, 8 weeks ago

numchi: fix docs for around

File size: 20.5 KB
Line 
1[[tags: egg]]
2[[toc:]]
3== numchi
4A mathematical library inspired by NumPy
5
6=== Introduction
7
8NumChi attempts to provide a subset of a similar API to Python's NumPy based
9on SRFI-179's arrays. All of SRFI-179's procedures are reexported. Because this
10library defines many procedures, some of which have the same names as scheme
11procedures, it's strongly recommended to prefix the module: {{(import (prefix
12numchi nc))}} or similar.
13
14=== Disclaimers
15
16This egg is not yet released, but you can find the sources at the
17following link:
18
19[[https://code.dieggsy.com/numchi]].
20
21This library should still be considered alpha software. There may be breaking
22changes in the future. Help and advice are very welcome at {{(string-append
23"dieggsy" "@" "pm" "." "me")}} or {{dieggsy}} on the {{#chicken}} IRC
24channel.
25
26Currently, the code is written for correct results rather than
27performance, and tested against NumPy itself using the pyffi egg. It's possible
28that the library could be made faster in the future by specializing for lower
29dimensions (like SRFI-179 does) and/or dropping into the Chicken C interface.
30Ideas for performance can be found in the {{bits/matrix-multiply.scm}} file
31(blas/Eigen integration) as well as in the {{fast-math}} branch (fast
32generic math routines with dispatching in C/C++)
33
34Most optional arguments are implemented as keyword arguments (except in
35certain cases like {{round}}) as these convey the purpose of the argument more
36clearly than optional arguments, and can also be used similarly to python's
37optional arguments (in any order).
38
39The library procedures should work on arrays with domains with non-zero
40lower bounds, but this is currently not well-tested.
41
42=== Mode of operation
43
44This library sets {{(specialize-array-default-safe? #t)}}. It's possible
45that setting this to {{#f}} might give you a small performance benefit.
46
47There are two basic modes of operation, determined by the value of the
48{{array-default-copy}} parameter. If its value is {{#t}} (the default), the
49library behaves more like NumPy in that array operations return specialized
50arrays. This is referred to as NumPy-like.
51
52If its value is {{#f}}, the library behaves more like SRFI-179 in that the
53results of array operations are not specialized arrays (meaning the resulting
54arrays behave more like functions defined on the input arrays). This is refered
55to as SRFI-like. This may be sort of unfamiliar since e.g. the array returned
56by {{(array-sum a #:axis 0)}} will later change if {{a}} changes. To avoid
57unexpected behavior, setting {{(array-default-copy #f)}} also sets
58{{(specialized-array-default-mutable? #f)}}, which can of course be unset
59manually if you don't want this behavior.
60
61Procedures that behave in the same way regardless of the "mode" should
62be documented as such.
63
64=== Dtypes and storage-class aliases
65
66For the purposes of this library, a "dtype" is simply an SRFI-179
67storage-class. The following aliases are provided for convenience.
68
69==== Dtype aliases
70
71<constant>gen</constant>
72<constant>c128</constant>
73<constant>c64</constant>
74<constant>f64</constant>
75<constant>f32</constant>
76<constant>s64</constant>
77<constant>u64</constant>
78<constant>s32</constant>
79<constant>u32</constant>
80<constant>s16</constant>
81<constant>u16</constant>
82<constant>s8</constant>
83<constant>u8</constant>
84<constant>u1</constant>
85Fairly self-explanatory aliases for SRFI-179 storage classes. {{gen}} is
86{{generic-storage-class}}, the remaining are the same as
87{{[dtype]-storage-class}}, where {{[dtype]}} is one of the idetifiers above.
88
89==== Dtype conversion table
90
91For generic operations on multiple arrays like add, multiply, etc., the
92resulting dtype is determined according to the following table, which is based
93on numpy's default type conversion rules:
94
95<enscript>
96      gen  c128   c64   f64   f32   s64   u64   s32   u32   s16   u16    s8    u8
97 gen  gen   gen   gen   gen   gen   gen   gen   gen   gen   gen   gen   gen   gen
98c128  gen  c128  c128  c128  c128  c128  c128  c128  c128  c128  c128  c128  c128
99 c64  gen  c128   c64  c128   c64  c128  c128  c128  c128   c64   c64   c64   c64
100 f64  gen  c128  c128   f64   f64   f64   f64   f64   f64   f64   f64   f64   f64
101 f32  gen  c128   c64   f64   f32   f64   f64   f64   f64   f32   f32   f32   f32
102 s64  gen  c128  c128   f64   f64   s64   f64   s64   s64   s64   s64   s64   s64
103 u64  gen  c128  c128   f64   f64   f64   u64   f64   u64   f64   u64   f64   u64
104 s32  gen  c128  c128   f64   f64   s64   f64   s32   s64   s32   s32   s32   s32
105 u32  gen  c128  c128   f64   f64   s64   u64   s64   u32   s64   u32   s64   u32
106 s16  gen  c128   c64   f64   f32   s64   f64   s32   s64   s16   s32   s16   s16
107 u16  gen  c128   c64   f64   f32   s64   u64   s32   u32   s32   u16   s32   u16
108  s8  gen  c128   c64   f64   f32   s64   f64   s32   s64   s16   s32    s8   s16
109  u8  gen  c128   c64   f64   f32   s64   u64   s32   u32   s16   u16   s16    u8
110</enscript>
111
112=== Basic array operations
113
114==== Mode of operation
115
116<parameter>array-default-copy</parameter>
117Unless otherwise specified by procedure documentation, if set to
118{{#t}}, the library is NumPy-like (returned arrays are specialized). If set to
119{{#f}}, the library is SRFI-like (returned arrays are functional).
120
121<syntax>(without-copy body ...)</syntax>
122Allows you to temporarily change the mode of operation for {{body ...}} to
123SRFI-like.
124
125<syntax>(with-copy body ...)</syntax>
126Allows you to temporarily change the mode of operation for {{body ...}} to
127NumPy-like.
128
129==== Constructors
130
131There are a few ways to create arrays with numchi:
132
133<enscript highlight="scheme">
134;; Using the array procedure
135(array '((1 2) ;; dtype inferred
136         (3 4)))
137(array '((1 2) ;; explicit dtype
138         (3 4))
139       dtype: s64)
140;; Using the special read syntax
141'#!a((1 2)    ;; dtype inferred
142     (3 4))
143'#!s64a((1 2) ;; explicit dtype
144        (3 4))
145</enscript>
146
147You may also prefer srfi-179's {{list->array}}:
148
149<enscript highlight="scheme">
150;; You don't have to import srfi-179 since numchi reexports it.
151(list->array '(1 2
152               3 4)
153             (domain #(2 2))
154             s64)
155</enscript>
156
157<procedure>(list->array* lst #!key dtype) → array</procedure>
158Converts an array-like nested list to an array. See {{array}}.
159
160<procedure>(array lst #!key dtype) → array</procedure>
161Main array creation procedure. Currently synonymous to {{list->array*}}.
162
163Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.array.html|numpy.array]]
164
165; lst : An array-like list, with dimensions specified by nesting.
166; dtype : An SRFI-179 storage class. Any list containing bignums, ratnums, or non-numerical scheme objects is converted into a {{gen}} array. Otherwise, the most appropriate of {{s64}}, {{f64}}, or {{c128}} is chosen.
167
168<procedure>(domain arg1 #!optional arg2) → interval</procedure>
169Like SRFI-179's {{make-interval}}, but interval bounds can be specified
170as vectors, lists, or pairs.
171
172==== Array attributes
173
174<procedure>(array-shape a) → vector</procedure>
175Return the shape of {{a}} as a vector. This equivalent to the upper bounds
176of the array domain if the domain is normalized to 0 lower bounds.
177
178Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.shape.html#numpy.ndarray.shape|ndarray.shape]]
179
180<procedure>(array-ndim a) → integer</procedure>
181Return the number of array dimensions, synonymous to SRFI-179's
182{{array-dimension}}.
183
184Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.ndim.html#numpy.ndarray.ndim|ndarray.ndim]]
185
186<procedure>(array-data a) → (or vector homogeneous-vector)</procedure>
187The same as SRFI-179's {{array-body}}.
188
189Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.data.html#numpy.ndarray.data|ndarray.data]]
190
191<procedure>(array-size a) → integer</procedure>
192Returns the total number of elements in the array.
193
194Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.size.html#numpy.ndarray.size|ndarray.size]]
195
196<procedure>(array-dtype a) → symbol</procedure>
197Returns the dtype of the array or {{#f}} if {{a}} is not a specialized array.
198
199Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.dtype.html#numpy.ndarray.dtype|ndarray.dtype]]
200
201==== Array procedures
202
203<procedure>(array->list* a) → list</procedure>
204Converts an array to an array-like nested list.
205
206Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.tolist.html|ndarray.tolist]]
207
208<procedure>(array-T a #!key axes) → array</procedure>
209Returns a transposed shared array. Equivalent to SRFI-179's
210{{array-permute}} but with an optional permutation argument with a default
211value.
212
213Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.T.html#numpy.ndarray.T|ndarray.T]]
214
215; axes : Reverses the order of {{a}}'s axes if not given. Otherwise, a vector of integers: i in the j-th place in the tuple means {{a}}’s i-th axis becomes {{(array-transpose a)}}’s j-th axis.
216
217<procedure>(array-real a) → array</procedure>
218Returns the real part of {{a}}.
219
220Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.real.html#numpy.ndarray.real|ndarray.real]]
221
222<procedure>(array-imag a) → array</procedure>
223Returns the imaginary part of {{a}}.
224
225Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.imag.html#numpy.ndarray.imag|ndarray.imag]]
226
227<procedure>(array-astype a dtype) → array</procedure>
228Copy the array, cast to the specified {{dtype}}.
229
230Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.astype.html#numpy.ndarray.astype|ndarray.astype]]
231
232; dtype : A storage class
233
234<procedure>(array-copy* a #!optional dtype new-domain mutable? safe?) → array</procedure>
235Like SRFI-179's {{array-copy}}, {{new-domain}} can be specified as for the
236{{domain}} procedure.
237
238Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.copy.html#numpy.ndarray.copy|ndarray.copy]]
239
240<procedure>(array-map* f a . as) → array</procedure>
241Like SRFI-179's {{array-map}}, but behaves differently on
242(array-default-copy #t): namely, it returns a copy of the map with the first
243argument's storage class.
244
245<procedure>(array-map! f a . as)</procedure>
246Like SRFI-179's {{array-map}}, but stores the results in {{a}}, the first
247passed array.
248
249<procedure>(array-fill! a value)</procedure>
250Fill {{a}} with {{value}}.
251
252Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.fill.html#numpy.ndarray.fill|ndarray.fill]]
253
254<procedure>(array-reshape a shape) → array</procedure>
255Returns an array containing the same data with new shape. Unaffected by
256{{array-default-copy}}.
257
258Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.reshape.html#numpy.ndarray.reshape|ndarray.reshape]]
259
260; a : A specialized array
261; shape : A domain in the same format as specified by {{domain}}
262
263<procedure>(array-transpose a #!key axes) → array</procedure>
264Synonymous to {{array-T}}.
265
266Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.transpose.html#numpy.ndarray.transpose|ndarray.transpose]]
267
268<procedure>(array-flatten array) → array</procedure>
269Returns a copy of the array collapsed into one dimension. Unaffected by
270{{array-default-copy}}.
271
272Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.flatten.html#numpy.ndarray.flatten|ndarray.flatten]]
273
274<procedure>(array-diagonal a #!key (offset 0) (axis1 0) (axis2 1)) → array</procedure>
275Return diagonals of {{a}} as a shared array. Unaffected by
276{{array-default-copy}}. Currently only works on specialized arrays.
277
278'''NOTE:''' Part of the implementation of this procedure is based on
279NumPy's C sources (translated to scheme), and is pretty gross if not
280inefficient.
281
282Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.diagonal.html#numpy.ndarray.diagonal|ndarray.diagonal]]
283
284'''DIFF''': Offsets must be within {{a}}'s bounds, since SRFI-179 does not
285support zero sized arrays/dimensions.
286
287<procedure>(array-max a #!key axis (initial -inf.0)) → (or number array)</procedure>
288Return the maximum of the array or the maximum along the given axis.
289
290Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.max.html#numpy.ndarray.max|ndarray.max]]
291
292; initial : Minimum value of an input element.
293
294<procedure>(array-min a #!key axis (initial +inf.0)) → (or number array)</procedure>
295Return the minimum of the array or the minimum along the given axis.
296
297Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.min.html#numpy.ndarray.min|ndarray.min]]
298
299; initial : Maximum value of an input element.
300
301<procedure>(array-clip a #!key min max) → array</procedure>
302Return an array whose minimum values are {{min}} and maximum values are {{max}}.
303
304Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.clip.html#numpy.ndarray.clip|ndarray.clip]]
305
306<procedure>(array-clip! a #!key min max)</procedure>
307Like {{array-clip}}, but modifies the original array.
308
309<procedure>(array-conj a) → array</procedure>
310Complex conjugate all elements of {{a}}.
311
312Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.conj.html#numpy.ndarray.conj|ndarray.conj]]
313
314<procedure>(array-round a #!optional n) → array</procedure>
315Round all elements of {{a}}.
316
317Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.round.html|ndarray.round]]
318
319; n : Decimal places to round to, can be negative to round the tens, hundreds, etc. place.
320
321<procedure>(array-trace a #!key (offset 0) (axis1 0) (axis2 1) (dtype generic-storage-class))</procedure>
322Return the sum along the diagonals of the array.
323
324'''DIFF''': See {{array-diagonal}}
325
326Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.trace.html#numpy.ndarray.trace|ndarray.trace]]
327
328<procedure>(array-sum a #!key axis (dtype generic-storage-class))</procedure>
329Return the sum of the array elements over the given axis.
330
331'''DIFF''': Because the result may overflow, on {{(array-default-copy #t)}}
332the returned array has the generic storage class by default.
333
334Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.sum.html#numpy.ndarray.sum|ndarray.sum]]
335
336<procedure>(array-mean a #!key axis (dtype generic-storage-class))</procedure>
337Returns the average of the array elements along given axis.
338
339'''DIFF''': This procedure will return averages as exact numbers where
340possible, so on {{(array-default-copy #t)}} the returned array has the generic
341storage class by default.
342
343Similar:  [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.mean.html#numpy.ndarray.mean|mean]]
344
345<procedure>(array-var a #!key axis (dtype generic-storage-class))</procedure>
346Returns the variance of the array elements, along given axis.
347
348'''DIFF''': This procedure will return variance as exact numbers where
349possible, so on {{(array-default-copy #t)}} the returned array has the generic
350storage class by default.
351
352Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.var.html#numpy.ndarray.var|ndarray.var]]
353
354<procedure>(array-std a #!key axis (dtype generic-storage-class))</procedure>
355Returns the standard deviation of the array elements along given axis.
356
357Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.std.html#numpy.ndarray.std|ndarray.std]]
358
359<procedure>(array-prod a #!key axis (dtype generic-storage-class))</procedure>
360Return the product of the array elements over the given axis
361
362'''DIFF''': Because the result may overflow, on {{(array-default-copy
363#t)}} the returned array has the generic storage class by default.
364
365Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.prod.html#numpy.ndarray.prod|ndarray.prod]]
366
367<procedure>(array-all a #!key axis (dtype generic-storage-class))</procedure>
368Returns {{#t}} if all elements are not {{#f}}.
369
370'''DIFF''': This will return slightly different results than numpy's array-all
371because while scheme and python both have "truthiness" (non #t or True
372objects evaluate as true for boolean operations), scheme does not have Python's
373"falsiness" for values like {{0}}, {{[]}}, {{""}}, etc.
374
375Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.all.html#numpy.ndarray.all|ndarray.all]]
376
377<procedure>(array-any* a #!key axis (dtype generic-storage-class))</procedure>
378Returns {{#t}} if any of the elements is not {{#f}}. Note the {{*}} in the
379name to avoid shadowing srfi-179's {{array-any}}.
380
381'''DIFF''': This will return slightly different results than numpy's
382array-all because while scheme and python both have "truthiness" (objects
383that are not #t or True evaluate as true for boolean operations), scheme does
384not have Python's "falsiness" for values like {{0}}, {{[]}}, {{""}}, etc.
385
386Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.ndarray.any.html#numpy.ndarray.any|ndarray.any]]
387
388=== Array I/O
389
390==== Read/write syntax
391
392The special read syntax {{'#!a(...)}} is an alias for {{(array '(...))}}.
393You can also specify a dtype, like so: {{'#![dtype]a(...)}} (e.g.
394{{'#!f64a(...)}}). Arrays are by default printed in the dtype syntax, with
395non-specialized arrays printed as {{'#!*a(...)}}, which currently does not have
396an equivalent read syntax.
397
398==== Procedures
399
400<procedure>(write-array a #!optional (port (current-output-port)) #!key mode summarize)</procedure>
401Writes an array to {{port}}. If {{#:summarize}} is {{#t}}, prints a
402summary of the array according to the {{array-summary-*}} parameters. The
403keyword argument {{#:mode}} is currently a no-op, but there are plans to use it
404for writing arrays in e.g. binary or ascii format.
405
406==== Parameters
407
408<constant>array-summary-maxsize</constant>
409Sets the maximum size that an array can be beyond which its printed form
410is summarized.
411
412<constant>array-summary-num-edges</constant>
413Sets the number of edges to display for a summarized array.
414
415<constant>array-summary-flonum-precision</constant>
416Sets the array flounm print precision for a summarized array.
417
418=== Constants
419
420<constant>inf</constant>
421An alias for +inf.0
422
423<constant>ninf</constant>
424An alias for -inf.0
425
426<constant>nan</constant>
427An alias for +nan.0
428
429<constant>nzero</constant>
430An alias for -0.0
431
432<constant>e</constant>
433Euler's number
434
435<constant>euler-gamma</constant>
436Euler-Mascheroni constant
437
438<constant>pi</constant>
439=== Mathematical functions
440
441<procedure>(conj a) → (or array number)</procedure>
442Returns the complex conjugate of a number or element-wise complex conjugate of
443an array.
444
445Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.conj.html|numpy.conj]]
446
447<procedure>(round a #!optional b) → (or array number)</procedure>
448Evenly rounds the number (or array, element-wise) to {{n}} decimals. If {{n}}
449is negative, rounds to nearest tens, hundreds, etc.
450
451Similar: [[https://numpy.org/doc/stable/reference/generated/numpy.around.html|numpy.around]]
452
453<procedure>(around a #!optional n)</procedure>
454The same as {{round}}.
455
456<procedure>(add a b #!key dtype) → (or array number)</procedure>
457Adds arguments element-wise. Arguments can be arrays or numbers. A
458resulting array's dtype is determined by the dtype conversion table if
459{{dtype}} is not given.
460
461=== Repository
462
463[[https://code.dieggsy.com/numchi]]
464
465=== Author
466Diego A. Mundo
467
468=== License
469BSD
470
471 Copyright (c) 2021 Diego A. Mundo
472 All rights reserved.
473 
474 Redistribution and use in source and binary forms, with or without
475 modification, are permitted (subject to the limitations in the disclaimer
476 below) provided that the following conditions are met:
477 
478      * Redistributions of source code must retain the above copyright notice,
479        this list of conditions and the following disclaimer.
480 
481      * Redistributions in binary form must reproduce the above copyright
482        notice, this list of conditions and the following disclaimer in the
483        documentation and/or other materials provided with the distribution.
484 
485      * Neither the name of the copyright holder nor the names of its
486        contributors may be used to endorse or promote products derived from
487        this software without specific prior written permission.
488 
489 NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS
490 LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
491 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
492 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
493 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
494 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
495 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
496 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
497 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
498 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
499 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Note: See TracBrowser for help on using the repository browser.