deprecate SCViewHolder-layRight
[supercollider.git] / SCClassLibrary / Common / Collections / ArrayedCollection.sc
blob281ea4f879517e8200491360d878709d83e8c7e1
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.reciprocal)
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         }
307         clipExtend { arg length;
308                 ^this.extend(length, this.last)
309         }
311         // concepts borrowed from J programming language
312         rank {
313                 // rank is the number of dimensions in a multidimensional array.
314                 // see also Object-rank
315                 // this assumes every element has the same rank
316                 ^ 1 + this.first.rank
317         }
318         shape {
319                 // this assumes every element has the same shape
320                 ^[this.size] ++ this[0].shape
321         }
322         reshape { arg ... shape;
323                 var size = shape.product;
324                 var result = this.flat.wrapExtend(size);
325                 shape[1..].reverseDo {|n| result = result.clump(n) };
326                 ^result
327         }
328         deepCollect { arg depth = 1, function;
329                 if (depth <= 0) {
330                         ^function.value(this, 0)
331                 };
332                 depth = depth-1;
333                 ^this.collect {|item| item.deepCollect(depth, function) }
334         }
335         reshapeLike { arg another, indexing=\wrapAt;
336                 var index = 0;
337                 var flat = this.flat;
338                 ^another.deepCollect(0x7FFFFFFF) {
339                         var item = flat.perform(indexing, index);
340                         index = index + 1;
341                         item;
342                 };
343         }
345         unbubble { arg depth=0, levels=1;
346                 if (depth <= 0) {
347                         // converts a size 1 array to the item.
348                         if (this.size > 1) { ^this };
349                         if (levels <= 1) { ^this[0] }
350                         ^this[0].unbubble(depth, levels-1)
351                 };
352                 ^this.collect {|item| item.unbubble(depth-1) }
353         }
354         bubble { arg depth=0, levels=1;
355                 if (depth <= 0) {
356                         if (levels <= 1) { ^[this] }
357                         ^[this.bubble(depth,levels-1)]
358                 };
359                 ^this.collect {|item| item.bubble(depth-1, levels) }
360         }
363         slice { arg ... cuts;
364                 var firstCut, index, list;
365                 if (cuts.size == 0) { ^this.copy };
367                 firstCut = cuts[0];
368                 if (firstCut.isNil) { list = this.copy } { list = this[firstCut.asArray] };
369                 if (cuts.size == 1) {
370                         ^list.unbubble
371                 }{
372                         cuts = cuts[1..];
373                         ^list.collect {|item| item.slice(*cuts) }.unbubble
374                 }
375         }
376         *iota { arg ... sizes;
377                 ^(0..sizes.product-1).reshape(*sizes)
378         }
379         *fill2D { arg rows, cols, function;
380                 var array = this.new(rows);
381                 rows.do{|row|
382                         var array2 = this.new(cols);
383                         cols.do{|col|
384                                 array2 = array2.add(function.(row, col))
385                         };
386                         array = array.add(array2);
387                 };
388                 ^array
389         }
390         *fill3D { arg planes, rows, cols, function;
391                 var array = this.new(planes);
392                 planes.do{|plane|
393                         var array2 = this.new(rows);
394                         rows.do{|row|
395                                 var array3 = this.new(cols);
396                                 cols.do{|col|
397                                         array3 = array3.add(function.(plane, row, col))
398                                 };
399                                 array2 = array2.add(array3);
400                         };
401                         array = array.add(array2);
402                 };
403                 ^array
404         }
405         *fillND { arg dimensions, function, args=[]; // args are private
406                 var n = dimensions.first;
407                 var array = this.new(n);
408                 var argIndex = args.size;
409                 args = args ++ 0;
410                 if(dimensions.size <= 1) {
411                         n.do { |i| array.add(function.valueArray(args.put(argIndex, i))) };
412                 } {
413                         dimensions = dimensions.drop(1);
414                         n.do { |i|
415                                 var array2 = this.fillND(dimensions, function, args.put(argIndex, i));
416                                 array = array.add(array2);
417                         }
418                 };
419                 ^array
420         }
423         // random distribution table
425         asRandomTable { arg size;
426                 var a=this, b;
427                 if(size.isNil) { size = this.size } { a = a.resamp1(size) };
428                 a = a.integrate; // incrementally integrate
429                 a = a.normalize(0, size-1); // normalize and scale by max index
430                 b = Array.fill(size, { arg i; a.indexInBetween(i) });  // flip array
431                 b = b / size // rescale to 0..1
432                 ^b
433         }
435         tableRand {
436                 ^this.blendAt((this.size - 1).asFloat.rand)
437         }
439         // osc bundle support
441         msgSize {
442                 _NetAddr_MsgSize;
443                 ^this.primitiveFailed
444         }
445         bundleSize {
446                 // array of messages
447                 ^([nil] ++ this).prBundleSize;
448         }
449         clumpBundles {
450                 var size=0, res, clumps, count=0, bundleSizes;
451                 bundleSizes = this.collect {|item| [item].bundleSize };
452                 bundleSizes.do { |a, i|
453                         size = size + a;
454                         if(size >= 8192) { clumps = clumps.add(count); count = 0; size = a };
455                         count = count + 1;
456                 };
457                 ^this.clumps(clumps);
458         }
460         prBundleSize {
461                 _NetAddr_BundleSize;
462                 ^this.primitiveFailed
463         }
464         includes { |item| ^this.indexOf(item).notNil }
467 RawArray : ArrayedCollection {
468         // species { ^this.class }
469         archiveAsCompileString { ^true }
470         archiveAsObject { ^true }
472         rate { ^\scalar }
474         readFromStream { |stream, method|
475                 if(method.notNil) {
476                         this.size.do({ |i|
477                                 this.put(i, stream.perform(method));
478                         })
479                 } {
480                         this.shouldNotImplement(thisMethod);
481                 }
482         }
484         powerset {
485                 ^this.as(Array).powerset
486         }
489 Int8Array[int8] : RawArray {
490         unarchive {
491                 _Unarchive
492                 ^this.primitiveFailed
493         }
495         readFromStream { |stream|
496                 super.readFromStream(stream, \getInt8);
497         }
500 Int16Array[int16] : RawArray {
501         readFromStream { |stream|
502                 super.readFromStream(stream, \getInt16);
503         }
506 Int32Array[int32] : RawArray {
507         readFromStream { |stream|
508                 super.readFromStream(stream, \getInt32);
509         }
512 FloatArray[float] : RawArray {
513         readFromStream { |stream|
514                 super.readFromStream(stream, \getFloat);
515         }
518 DoubleArray[double] : RawArray {
519         readFromStream { |stream|
520                 super.readFromStream(stream, \getDouble);
521         }
524         // readFromStream not implemented yet
525 SymbolArray[symbol] : RawArray {