HelpBrowser: path box becomes a more conventional search box
[supercollider.git] / SCClassLibrary / Common / Collections / ArrayedCollection.sc
blob74673dfb69c5a679341b1ed15c36803afd633d3f
1 ArrayedCollection : SequenceableCollection {
2         *newClear { arg indexedSize = 0;
3                 _BasicNewClear
4                 ^this.primitiveFailed
5                 // creates a new instance with indexedSize indexable slots.
6                 // the slots are filled with nil, zero or something else
7                 // appropriate to the type of indexable slots in the
8                 // object.
9         }
11         // ArrayedCollections are vectors which have a
12         // fixed maximum capacity.
14         indexedSize { _BasicSize }
15         size { _BasicSize }
16         maxSize { _BasicMaxSize }
18         swap { arg i, j; var temp;
19                 _BasicSwap;
20                 ^this.primitiveFailed;
21         }
23         at { arg index;
24                 _BasicAt;
25                 ^this.primitiveFailed;
26         }
27         clipAt { arg index;
28                 _BasicClipAt;
29                 ^this.primitiveFailed;
30         }
31         wrapAt { arg index;
32                 _BasicWrapAt;
33                 ^this.primitiveFailed;
34         }
35         foldAt { arg index;
36                 _BasicFoldAt;
37                 ^this.primitiveFailed;
38         }
39         put { arg index, item;
40                 _BasicPut;
41                 ^this.primitiveFailed;
42         }
43         clipPut { arg index, item;
44                 _BasicClipPut;
45                 ^this.primitiveFailed;
46         }
47         wrapPut { arg index, item;
48                 _BasicWrapPut;
49                 ^this.primitiveFailed;
50         }
51         foldPut { arg index, item;
52                 _BasicFoldPut;
53                 ^this.primitiveFailed;
54         }
55         removeAt { arg index;
56                 _BasicRemoveAt;
57                 ^this.primitiveFailed;
58         }
59         takeAt { arg index;
60                 _BasicTakeAt;
61                 ^this.primitiveFailed;
62         }
64         indexOf { arg item;
65                 _ArrayIndexOf
66                 ^this.primitiveFailed;
67         }
68         indexOfGreaterThan { arg val;
69                 _ArrayIndexOfGreaterThan
70                 ^super.indexOfGreaterThan(val)
71         }
73         takeThese { arg func;
74                 var i = 0;
75                 while { i < this.size }
76                 {
77                         if (func.value(this[i], i)) {
78                                 this.takeAt(i)
79                         }{
80                                 i = i + 1
81                         }
82                 }
83         }
85         replace { arg find, replace;
86                 var index, out = [], array = this;
87                 find = find.asArray;
88                 replace = replace.asArray;
89                 while {
90                         (index = array.find(find)).notNil
91                 }{
92                         out = out ++ array.keep(index) ++ replace;
93                         array = array.drop(index + find.size);
94                 };
95                 ^out ++ array
96         }
98         // see counterparts to these in Object
99         slotSize {
100                 ^this.size;
101         }
102         slotAt { arg index;
103                 ^this.at(index);
104         }
105         slotPut { arg index, value;
106                 ^this.put(index, value);
107         }
108         slotKey { arg index;
109                 ^index
110         }
111         slotIndex { arg key;
112                 ^nil
113         }
114         getSlots {
115                 ^this.copy
116         }
117         setSlots { arg array;
118                 this.overWrite(array)
119         }
121         atModify { arg index, function; this.put(index, function.value(this.at(index), index)) }
122         atInc { arg index, inc=1; this.put(index, this.at(index)+inc); }
123         atDec { arg index, dec=1; this.put(index, this.at(index)-dec); }
125         isArray { ^true }
126         asArray { ^this }
128         copyRange { arg start, end;
129                 // copies the fixed part of an object and the indexed slots
130                 // from start to end.
131                 _ObjectCopyRange;
132                 ^this.primitiveFailed
133         }
134         copySeries { arg first, second, last;
135                 // copies elements from first to last, stepping by (second-first)
136                 // copySeries(3,5,11) copies elements 3,5,7,9,11
137                 // if second is nil then the step is 1.
138                 // copySeries(3,nil,11) copies elements 3,4,5,6,7,8,9,10,11
139                 _ObjectCopySeries;
140                 ^this.primitiveFailed
141         }
142         putSeries { arg first, second, last, value;
143                 // puts value into array at indices defined by the series. see copySeries.
144                 _ArrayPutSeries;
145                 ^this.primitiveFailed
146         }
148         add { arg item;
149                 // add item to end of array.
150                 // if the capacity is exceeded, this returns a new
151                 // ArrayedCollection.
152                 _ArrayAdd
153                 ^this.primitiveFailed;
154         }
155         addAll { arg aCollection;
156                 var array;
157                 _ArrayAddAll
158                 array = this;
159                 aCollection.asCollection.do({ arg item; array = array.add(item) }) ;
160                 ^array
161         }
162         putEach { arg keys, values;
163                 _ArrayPutEach
164                 ^super.putEach(keys, values)
165         }
166         extend { arg size, item;
167                 _ArrayExtend
168                 ^this.primitiveFailed
169         }
170         insert { arg index, item;
171                 // add item at specified index.
172                 // if the capacity is exceeded, this returns a new
173                 // ArrayedCollection.
174                 _ArrayInsert
175                 ^this.primitiveFailed;
176         }
177         addFirst { arg item; ^this.insert(0, item) }
178         addIfNotNil { arg item; if(item.notNil,{ ^this.add(item) }) }
179         pop {
180                 // remove and return last item in array
181                 _ArrayPop
182                 ^nil;
183         }
184         ++ { arg anArray;
185                 // concatenate two arrays of the same type
186                 // this primitive will handle all array element types
187                 _ArrayCat;
188                 // primitive fails if arrays are different types
189                 ^super ++ anArray
190         }
191         overWrite { arg aCollection, pos=0;
192                 var array, grow;
193                 _ArrayOverwrite
194                 ^this.primitiveFailed
195                 //array = this.growClear(pos + aCollection.size - this.size);
196                 //grow = pos + aCollection.size - this.size;
197                 //if (grow > 0, { array = this ++ this.class.newClear(grow); },{ array = this });
198                 //aCollection.do({ arg item, i; array.put(pos + i, item); });
199                 //^array
200         }
201         grow { arg sizeIncrease;
202                 // returns an array of sufficient capacity.
203                 // may return same object if it still has enough space or if sizeIncrease <= 0.
204                 _ArrayGrow
205                 ^this.primitiveFailed
206         }
207         growClear { arg sizeIncrease;
208                 // returns an array of sufficient capacity.
209                 // may return same object if it still has enough space or if sizeIncrease <= 0.
210                 // clears new space
211                 _ArrayGrowClear
212                 ^this.primitiveFailed
213         }
214         seriesFill { arg start, step;
215                 this.size.do({ arg i;
216                         this.put(i, start);
217                         start = start + step;
218                 });
219         }
221         fill { arg value;
222                 _ArrayFill
223                 ^this.primitiveFailed
224                 /* replaced by primitive
225                 var i = 0, size;
226                 size = this.size;
227                 while ({ i < size }, {
228                         this.put(i, val);
229                         i = i + 1;
230                 });
231                 */
232         }
233         do { arg function;
234                 // special byte codes inserted by compiler for this method
235                 var i=0;
236                 while ({ i < this.size }, {
237                         function.value(this.at(i), i);
238                         i = i + 1;
239                 })
240         }
241         reverseDo { arg function;
242                 // special byte codes inserted by compiler for this method
243                 var i=0, j=0;
244                 i = this.size - 1;
245                 while ({ i >= 0 },{
246                         function.value(this.at(i), j);
247                         i = i - 1;
248                         j = j + 1;
249                 })
250         }
251         reverse {
252                 var i = 0;
253                 var res = this.copy;
254                 var size1 = res.size - 1;
255                 var halfsize = res.size div: 2;
256                 halfsize.do({ arg i;
257                         res.swap(i, size1 - i);
258                 });
259                 ^res
260         }
262         windex {
263                 _ArrayWIndex
264                 ^this.primitiveFailed
265                 //              var r, sum = 0.0, index;
266                 //              r = 1.0.rand;
267                 //              this.detect({ arg weight, i;
268                 //                      sum = sum + weight;
269                 //                      if (sum >= r, {
270                 //                              index = i;
271                 //                              true;
272                 //                      },{ false });
273                 //              });
274                 //              ^index;
275         }
276         normalizeSum {
277                 _ArrayNormalizeSum
278                 ^(this / this.sum)
279         }
280         normalize { arg min=0.0, max=1.0;
281                 var minItem = this.minItem;
282                 var maxItem = this.maxItem;
283                 ^this.collect { |el| el.linlin(minItem, maxItem, min, max) };
284         }
286         asciiPlot {
287                 // draw the waveform down the page as asterisks
288                 var lo = this.minItem;
289                 var hi = this.maxItem;
290                 var scale = 80 / (hi - lo);
291                 this.size.do { |i|
292                         var pt = ((this[i] - lo) * scale).asInteger;
293                         pt.do({ " ".post; });
294                         "*\n".post;
295                 };
296         }
298         perfectShuffle {
299                 if(this.size < 2) { ^this.copy };
300                 ^this[(0 .. this.size div: 2 - 1).stutter + [0, this.size + 1 div: 2]]
301         }
303         performInPlace { arg selector, from, to, argList;
304                 ^this.overWrite(this.copyRange(from, to).performList(selector, argList), from)
305         }
308         // concepts borrowed from J programming language
309         rank {
310                 // rank is the number of dimensions in a multidimensional array.
311                 // see also Object-rank
312                 // this assumes every element has the same rank
313                 ^ 1 + this.first.rank
314         }
315         shape {
316                 // this assumes every element has the same shape
317                 ^[this.size] ++ this[0].shape
318         }
319         reshape { arg ... shape;
320                 var size = shape.product;
321                 var result = this.flat.wrapExtend(size);
322                 shape[1..].reverseDo {|n| result = result.clump(n) };
323                 ^result
324         }
325         deepCollect { arg depth = 1, function;
326                 if (depth <= 0) {
327                         ^function.value(this, 0)
328                 };
329                 depth = depth-1;
330                 ^this.collect {|item| item.deepCollect(depth, function) }
331         }
332         reshapeLike { arg another, indexing=\wrapAt;
333                 var index = 0;
334                 var flat = this.flat;
335                 ^another.deepCollect(0x7FFFFFFF) {
336                         var item = flat.perform(indexing, index);
337                         index = index + 1;
338                         item;
339                 };
340         }
342         unbubble { arg depth=0, levels=1;
343                 if (depth <= 0) {
344                         // converts a size 1 array to the item.
345                         if (this.size > 1) { ^this };
346                         if (levels <= 1) { ^this[0] }
347                         ^this[0].unbubble(depth, levels-1)
348                 };
349                 ^this.collect {|item| item.unbubble(depth-1) }
350         }
351         bubble { arg depth=0, levels=1;
352                 if (depth <= 0) {
353                         if (levels <= 1) { ^[this] }
354                         ^[this.bubble(depth,levels-1)]
355                 };
356                 ^this.collect {|item| item.bubble(depth-1, levels) }
357         }
360         slice { arg ... cuts;
361                 var firstCut, index, list;
362                 if (cuts.size == 0) { ^this.copy };
364                 firstCut = cuts[0];
365                 if (firstCut.isNil) { list = this.copy } { list = this[firstCut.asArray] };
366                 if (cuts.size == 1) {
367                         ^list.unbubble
368                 }{
369                         cuts = cuts[1..];
370                         ^list.collect {|item| item.slice(*cuts) }.unbubble
371                 }
372         }
373         *iota { arg ... sizes;
374                 ^(0..sizes.product-1).reshape(*sizes)
375         }
376         *fill2D { arg rows, cols, function;
377                 var array = this.new(rows);
378                 rows.do{|row|
379                         var array2 = this.new(cols);
380                         cols.do{|col|
381                                 array2 = array2.add(function.(row, col))
382                         };
383                         array = array.add(array2);
384                 };
385                 ^array
386         }
387         *fill3D { arg planes, rows, cols, function;
388                 var array = this.new(planes);
389                 planes.do{|plane|
390                         var array2 = this.new(rows);
391                         rows.do{|row|
392                                 var array3 = this.new(cols);
393                                 cols.do{|col|
394                                         array3 = array3.add(function.(plane, row, col))
395                                 };
396                                 array2 = array2.add(array3);
397                         };
398                         array = array.add(array2);
399                 };
400                 ^array
401         }
402         *fillND { arg dimensions, function, args=[]; // args are private
403                 var n = dimensions.first;
404                 var array = this.new(n);
405                 var argIndex = args.size;
406                 args = args ++ 0;
407                 if(dimensions.size <= 1) {
408                         n.do { |i| array.add(function.valueArray(args.put(argIndex, i))) };
409                 } {
410                         dimensions = dimensions.drop(1);
411                         n.do { |i|
412                                 var array2 = this.fillND(dimensions, function, args.put(argIndex, i));
413                                 array = array.add(array2);
414                         }
415                 };
416                 ^array
417         }
420         // random distribution table
422         asRandomTable { arg size;
423                 var a=this, b;
424                 if(size.isNil) { size = this.size } { a = a.resamp1(size) };
425                 a = a.integrate; // incrementally integrate
426                 a = a.normalize(0, size-1); // normalize and scale by max index
427                 b = Array.fill(size, { arg i; a.indexInBetween(i) });  // flip array
428                 b = b / size // rescale to 0..1
429                 ^b
430         }
432         tableRand {
433                 ^this.blendAt((this.size - 1).asFloat.rand)
434         }
436         // osc bundle support
438         msgSize {
439                 _NetAddr_MsgSize;
440                 ^this.primitiveFailed
441         }
442         bundleSize {
443                 // array of messages
444                 ^([nil] ++ this).prBundleSize;
445         }
446         clumpBundles {
447                 var size=0, res, clumps, count=0, bundleSizes;
448                 bundleSizes = this.collect {|item| [item].bundleSize };
449                 bundleSizes.do { |a, i|
450                         size = size + a;
451                         if(size >= 8192) { clumps = clumps.add(count); count = 0; size = a };
452                         count = count + 1;
453                 };
454                 ^this.clumps(clumps);
455         }
457         prBundleSize {
458                 _NetAddr_BundleSize;
459                 ^this.primitiveFailed
460         }
461         includes { |item| ^this.indexOf(item).notNil }
464 RawArray : ArrayedCollection {
465         // species { ^this.class }
466         archiveAsCompileString { ^true }
467         archiveAsObject { ^true }
469         rate { ^\scalar }
471         readFromStream { |stream, method|
472                 if(method.notNil) {
473                         this.size.do({ |i|
474                                 this.put(i, stream.perform(method));
475                         })
476                 } {
477                         this.shouldNotImplement(thisMethod);
478                 }
479         }
482 Int8Array[int8] : RawArray {
483         unarchive {
484                 _Unarchive
485                 ^this.primitiveFailed
486         }
488         readFromStream { |stream|
489                 super.readFromStream(stream, \getInt8);
490         }
493 Int16Array[int16] : RawArray {
494         readFromStream { |stream|
495                 super.readFromStream(stream, \getInt16);
496         }
499 Int32Array[int32] : RawArray {
500         readFromStream { |stream|
501                 super.readFromStream(stream, \getInt32);
502         }
505 FloatArray[float] : RawArray {
506         readFromStream { |stream|
507                 super.readFromStream(stream, \getFloat);
508         }
511 DoubleArray[double] : RawArray {
512         readFromStream { |stream|
513                 super.readFromStream(stream, \getDouble);
514         }
517         // readFromStream not implemented yet
518 SymbolArray[symbol] : RawArray {