nit: Added link to `CONTRIBUTING.md` from the README
[nit.git] / lib / core / collection / array.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2004-2008 Jean Privat <jean@pryen.org>
4 # Copyright 2008 Floréal Morandat <morandat@lirmm.fr>
5 #
6 # This file is free software, which comes along with NIT. This software is
7 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
8 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
9 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
10 # is kept unaltered, and a notification of the changes is added.
11 # You are allowed to redistribute it and sell it, alone or is a part of
12 # another product.
13
14 # This module introduces the standard array structure.
15 # It also implements two other abstract collections : ArrayMap and ArraySet
16 module array is
17 no_warning "useless-type-test" # to avoid warning with nitc while compiling with c_src
18 end
19
20 import abstract_collection
21
22 # One dimension array of objects.
23 abstract class AbstractArrayRead[E]
24 super SequenceRead[E]
25
26 redef var length = 0
27
28 redef fun is_empty do return _length == 0
29
30 redef fun has(item)
31 do
32 var i = 0
33 var l = length
34 while i < l do
35 if self[i] == item then return true
36 i += 1
37 end
38 return false
39 end
40
41 redef fun has_only(item)
42 do
43 var i = 0
44 var l = length
45 while i < l do
46 if self[i] != item then return false
47 i += 1
48 end
49 return true
50 end
51
52 redef fun count(item)
53 do
54 var res = 0
55 var i = 0
56 var l = length
57 while i < l do
58 if self[i] == item then res += 1
59 i += 1
60 end
61 return res
62 end
63
64 redef fun index_of(item) do return index_of_from(item, 0)
65
66 redef fun last_index_of(item) do return last_index_of_from(item, length-1)
67
68 redef fun index_of_from(item, pos) do
69 var i = pos
70 var len = length
71 while i < len do
72 if self[i] == item then
73 return i
74 end
75 i += 1
76 end
77 return -1
78 end
79
80 redef fun last_index_of_from(item, pos) do
81 var i = pos
82 while i >= 0 do
83 if self[i] == item then
84 return i
85 else
86 i -= 1
87 end
88 end
89 return -1
90 end
91
92 # Return a new array that is the reverse of `self`
93 #
94 # assert [1,2,3].reversed == [3, 2, 1]
95 fun reversed: Array[E]
96 do
97 var cmp = _length
98 var result = new Array[E].with_capacity(cmp)
99 while cmp > 0 do
100 cmp -= 1
101 result.add(self[cmp])
102 end
103 return result
104 end
105
106 # Copy a portion of `self` to an other array.
107 #
108 # var a = [1, 2, 3, 4]
109 # var b = [10, 20, 30, 40, 50]
110 # a.copy_to(1, 2, b, 2)
111 # assert b == [10, 20, 2, 3, 50]
112 fun copy_to(start: Int, len: Int, dest: AbstractArray[E], new_start: Int)
113 do
114 if start < new_start then
115 var i = len
116 while i > 0 do
117 i -= 1
118 dest[new_start+i] = self[start+i]
119 end
120 else
121 var i = 0
122 while i < len do
123 dest[new_start+i] = self[start+i]
124 i += 1
125 end
126 end
127 end
128
129 redef fun output
130 do
131 var i = 0
132 var l = length
133 while i < l do
134 var e = self[i]
135 if e != null then e.output
136 i += 1
137 end
138 end
139
140 redef fun iterator: IndexedIterator[E] do
141 var res = _free_iterator
142 if res == null then return new ArrayIterator[E](self)
143 res._index = 0
144 _free_iterator = null
145 return res
146 end
147
148 # An old iterator, free to reuse.
149 # Once an iterator is `finish`, it become reusable.
150 # Since some arrays are iterated a lot, this avoid most of the
151 # continuous allocation/garbage-collection of the needed iterators.
152 private var free_iterator: nullable ArrayIterator[E] = null
153
154 redef fun reverse_iterator do return new ArrayReverseIterator[E](self)
155
156 # Returns a sub-array containing `count` elements starting from `from`.
157 #
158 # For most cases (see other case bellow),
159 # the first element is `from` and
160 # the last element is `from+count-1`.
161 #
162 # ~~~
163 # var a = [10, 20, 30, 40, 50]
164 # assert a.sub(0, 3) == [10, 20, 30]
165 # assert a.sub(3, 2) == [40, 50]
166 # assert a.sub(3, 1) == [40]
167 # ~~~
168 #
169 # If `count` is 0 or negative then an empty array is returned
170 #
171 # ~~~
172 # assert a.sub(3,0).is_empty
173 # assert a.sub(3,-1).is_empty
174 # ~~~
175 #
176 # If `from < 0` or `from+count>length` then inexistent elements are ignored.
177 # In this case the length of the result is lower than count.
178 #
179 # ~~~
180 # assert a.sub(-2, 4) == [10, 20]
181 # assert a.sub(4, 99) == [50]
182 # assert a.sub(-9, 99) == [10,20,30,40,50]
183 # assert a.sub(-99, 9).is_empty
184 # ~~~
185 fun sub(from: Int, count: Int): Array[E] do
186 if from < 0 then
187 count += from
188 from = 0
189 end
190 if count < 0 then
191 count = 0
192 end
193 var to = from + count
194 if to > length then
195 to = length
196 end
197 var res = new Array[E].with_capacity(to - from)
198 while from < to do
199 res.add(self[from])
200 from += 1
201 end
202 return res
203 end
204 end
205
206 # Resizable one dimension array of objects.
207 abstract class AbstractArray[E]
208 super AbstractArrayRead[E]
209 super Sequence[E]
210
211 # Force the capacity to be at least `cap`.
212 # The capacity of the array is an internal information.
213 # However, this method can be used to prepare a large amount of add
214 fun enlarge(cap: Int) is abstract
215
216 redef fun push(item) do add(item)
217
218 redef fun pop
219 do
220 assert not_empty: not is_empty
221 var r = last
222 _length -= 1
223 return r
224 end
225
226 redef fun shift
227 do
228 assert not_empty: not is_empty
229 var r = first
230 var l = length-1
231 copy_to(1, l, self, 0)
232 _length = l
233 return r
234 end
235
236 redef fun unshift(item)
237 do
238 var l = length
239 if l > 0 then
240 enlarge(l + 1)
241 copy_to(0, l, self, 1)
242 end
243 self[0] = item
244 end
245
246 redef fun insert(item, pos) do
247 enlarge(length + 1)
248 copy_to(pos, length-pos, self, pos + 1)
249 self[pos] = item
250 end
251
252 redef fun insert_all(coll, pos)
253 do
254 var l = coll.length
255 if l == 0 then return
256 enlarge(length + l)
257 _length += l
258 copy_to(pos, length-pos-l, self, pos + l)
259 for c in coll do
260 self[pos] = c
261 pos += 1
262 end
263 end
264
265 redef fun add(item) do self[length] = item
266
267 redef fun clear do _length = 0
268
269 redef fun remove(item) do remove_at(index_of(item))
270
271 redef fun remove_all(item)
272 do
273 var i = index_of(item)
274 while i >= 0 do
275 remove_at(i)
276 i = index_of_from(item, i)
277 end
278 end
279
280 redef fun remove_at(i)
281 do
282 var l = length
283 if i >= 0 and i < l then
284 var j = i + 1
285 while j < l do
286 self[j-1] = self[j]
287 j += 1
288 end
289 _length = l - 1
290 end
291 end
292
293 # Invert two elements in the array
294 #
295 # var a = [10, 20, 30, 40]
296 # a.swap_at(1, 3)
297 # assert a == [10, 40, 30, 20]
298 fun swap_at(a: Int,b: Int)
299 do
300 var e = self[a]
301 self[a] = self[b]
302 self[b] = e
303 end
304 end
305
306 # Resizable one dimension array of objects.
307 #
308 # Arrays have a literal representation.
309 #
310 # var a = [12, 32, 8]
311 # # is equivalent with:
312 # var b = new Array[Int]
313 # b.push(12)
314 # b.push(32)
315 # b.push(8)
316 # assert a == b
317 class Array[E]
318 super AbstractArray[E]
319 super Cloneable
320
321 redef fun [](index)
322 do
323 assert index: index >= 0 and index < _length
324 return _items[index]
325 end
326
327 redef fun []=(index, item)
328 do
329 assert index: index >= 0 and index < _length + 1
330 if _capacity <= index then
331 enlarge(index + 1)
332 end
333 if _length <= index then
334 _length = index + 1
335 end
336 _items[index] = item
337 end
338
339 redef fun add(item)
340 do
341 var l = _length
342 if _capacity <= l then
343 enlarge(l + 1)
344 end
345 _length = l + 1
346 _items[l] = item
347 end
348
349 # Slight optimization for arrays
350 redef fun add_all(items)
351 do
352 var l = _length
353 var nl = l + items.length
354 if _capacity < nl then
355 enlarge nl
356 end
357
358 if items isa Array[E] then
359 var k = 0
360 while l < nl do
361 _items[l] = items._items[k]
362 l += 1
363 k += 1
364 end
365 else
366 for item in items do
367 _items[l] = item
368 l += 1
369 end
370 end
371
372 _length = nl
373 end
374
375 redef fun copy_to(start, len, dest, new_start)
376 do
377 # Fast code when source and destination are two arrays
378
379 if not dest isa Array[E] then
380 super
381 return
382 end
383
384 # Enlarge dest if required
385 var dest_len = new_start + len
386 if dest_len > dest.length then
387 dest.enlarge(dest_len)
388 dest.length = dest_len
389 end
390
391 # Get underlying native arrays
392 var items = self.items
393 if items == null then return
394 var dest_items = dest.items
395 assert dest_items != null
396
397 # Native copy
398 items.memmove(start, len, dest_items, new_start)
399 end
400
401 redef fun enlarge(cap)
402 do
403 var c = _capacity
404 if cap <= c then return
405 while c <= cap do c = c * 2 + 2
406 var a = new NativeArray[E](c)
407 if _capacity > 0 then _items.copy_to(a, _length)
408 _items = a
409 _capacity = c
410 end
411
412 # Create an empty array.
413 init
414 do
415 _capacity = 0
416 _length = 0
417 end
418
419 # Create an array from a collection.
420 init from(items: Collection[E]) do
421 with_capacity(items.length)
422 self.add_all(items)
423 end
424
425 # Create an array with some `objects`.
426 init with_items(objects: E...)
427 do
428 _items = objects._items
429 _capacity = objects._capacity
430 _length = objects.length
431 end
432
433 # Create an empty array with a given capacity.
434 init with_capacity(cap: Int)
435 do
436 assert positive: cap >= 0
437 _items = new NativeArray[E](cap)
438 _capacity = cap
439 _length = 0
440 end
441
442 # Create an array of `count` elements
443 init filled_with(value: E, count: Int)
444 do
445 assert positive: count >= 0
446 _items = new NativeArray[E](count)
447 _capacity = count
448 _length = count
449 var i = 0
450 while i < count do
451 self[i] = value
452 i += 1
453 end
454 end
455
456 # Create a array filled with a given native array.
457 init with_native(nat: NativeArray[E], size: Int)
458 do
459 assert positive: size >= 0
460 _items = nat
461 _capacity = size
462 _length = size
463 end
464
465 # The internal storage.
466 private var items: nullable NativeArray[E] = null
467
468 # The size of `_items`.
469 private var capacity: Int = 0
470
471 redef fun ==(o)
472 do
473 if not o isa Array[nullable Object] then return super
474 # Efficient implementation
475 var l = length
476 if l != o.length then return false
477 var i = 0
478 var it = _items
479 var oit = o._items
480 while i < l do
481 if it[i] != oit[i] then return false
482 i += 1
483 end
484 return true
485 end
486
487 # Shallow clone of `self`
488 #
489 # ~~~
490 # var a = [1,2,3]
491 # var b = a.clone
492 # assert a == b
493 # a.add 4
494 # assert a != b
495 # b.add 4
496 # assert a == b
497 # ~~~
498 #
499 # Note that the clone is shallow and elements are shared between `self` and the result.
500 #
501 # ~~~
502 # var aa = [a]
503 # var bb = aa.clone
504 # assert aa == bb
505 # aa.first.add 5
506 # assert aa == bb
507 # ~~~
508 redef fun clone do return to_a
509
510 # Concatenation of arrays.
511 #
512 # Returns a new array built by concatenating `self` and `other` together.
513 #
514 # var a1 = [1,2,3]
515 # var a2 = [4,5,6]
516 # var a3 = a1 + a2
517 # assert a3 == [1,2,3,4,5,6]
518 #
519 # Because a new array is always created, future modification on `self` and `other`
520 # does not impact the previously computed result.
521 #
522 # a1.add(30)
523 # a2.add(60)
524 # assert a3 == [1,2,3,4,5,6] # unchanged
525 # assert a1 + a2 == [1,2,3,30,4,5,6,60]
526 fun +(other: Array[E]): Array[E]
527 do
528 var res = new Array[E].with_capacity(length + other.length)
529 res.append(self)
530 res.append(other)
531 return res
532 end
533
534 # Repetition of arrays.
535 #
536 # returns a new array built by concatenating `self` `repeat` times.
537 #
538 # var a = [1,2,3]
539 # assert (a * 0).is_empty
540 # assert a * 1 == [1,2,3]
541 # assert a * 2 == [1,2,3,1,2,3]
542 # assert (a * 10).length == 30
543 fun *(repeat: Int): Array[E]
544 do
545 assert repeat >= 0
546 var res = new Array[E].with_capacity(length * repeat)
547 while repeat > 0 do
548 res.add_all(self)
549 repeat -= 1
550 end
551 return res
552 end
553 end
554
555 # An `Iterator` on `AbstractArray`
556 private class ArrayIterator[E]
557 super IndexedIterator[E]
558
559 redef fun item do return _array[_index]
560
561 # redef fun item=(e) do _array[_index] = e
562
563 redef fun is_ok do return _index < _array.length
564
565 redef fun next do _index += 1
566
567 redef var index = 0
568
569 var array: AbstractArrayRead[E]
570
571 redef fun finish do _array._free_iterator = self
572 end
573
574 private class ArrayReverseIterator[E]
575 super ArrayIterator[E]
576
577 redef fun is_ok do return _index >= 0
578
579 redef fun next do _index -= 1
580
581 init
582 do
583 _index = _array.length - 1
584 end
585
586 # Do not cache `self`
587 redef fun finish do end
588 end
589
590 # Others collections ##########################################################
591
592 # A set implemented with an Array.
593 class ArraySet[E]
594 super Set[E]
595
596 # The stored elements.
597 private var array: Array[E] is noinit
598
599 redef fun has(e) do return _array.has(e)
600
601 redef fun add(e) do if not _array.has(e) then _array.add(e)
602
603 redef fun is_empty do return _array.is_empty
604
605 redef fun length do return _array.length
606
607 redef fun first
608 do
609 assert _array.length > 0
610 return _array.first
611 end
612
613 redef fun remove(item)
614 do
615 var i = _array.index_of(item)
616 if i >= 0 then remove_at(i)
617 end
618
619 redef fun remove_all(item) do remove(item)
620
621 redef fun clear do _array.clear
622
623 redef fun iterator do return new ArraySetIterator[E](_array.iterator)
624
625 # Assume the capacity is at least `cap`.
626 fun enlarge(cap: Int) do _array.enlarge(cap)
627
628 private fun remove_at(i: Int)
629 do
630 _array[i] = _array.last
631 _array.pop
632 end
633
634 # Create an empty set
635 init do _array = new Array[E]
636
637 # Create an empty set with a given capacity.
638 init with_capacity(i: Int) do _array = new Array[E].with_capacity(i)
639
640 redef fun new_set do return new ArraySet[E]
641
642 # Shallow clone of `self`
643 #
644 # ~~~
645 # var a = new ArraySet[Int]
646 # a.add 1
647 # a.add 2
648 # var b = a.clone
649 # assert a == b
650 # a.add 3
651 # assert a != b
652 # b.add 3
653 # assert a == b
654 # ~~~
655 #
656 # Note that the clone is shallow and keys and values are shared between `self` and the result.
657 #
658 # ~~~
659 # var aa = new ArraySet[Array[Int]]
660 # aa.add([1,2])
661 # var bb = aa.clone
662 # assert aa == bb
663 # aa.first.add 5
664 # assert aa == bb
665 # ~~~
666 redef fun clone
667 do
668 var res = new ArraySet[E]
669 res.add_all self
670 return res
671 end
672 end
673
674 # Iterators on sets implemented with arrays.
675 private class ArraySetIterator[E]
676 super Iterator[E]
677
678 redef fun is_ok do return _iter.is_ok
679
680 redef fun next do _iter.next
681
682 redef fun item: E do return _iter.item
683
684 var iter: Iterator[E]
685 end
686
687
688 # Associative arrays implemented with an array of (key, value) pairs.
689 class ArrayMap[K, E]
690 super CoupleMap[K, E]
691 super Cloneable
692
693 # O(n)
694 redef fun [](key)
695 do
696 var i = index(key)
697 if i >= 0 then
698 return _items[i].second
699 else
700 return provide_default_value(key)
701 end
702 end
703
704 # O(n)
705 redef fun []=(key, item)
706 do
707 var i = index(key)
708 if i >= 0 then
709 _items[i].second = item
710 else
711 _items.push(new Couple[K,E](key, item))
712 end
713 end
714
715 redef var keys: RemovableCollection[K] = new ArrayMapKeys[K, E](self) is lazy
716 redef var values: RemovableCollection[E] = new ArrayMapValues[K, E](self) is lazy
717
718 # O(1)
719 redef fun length do return _items.length
720
721 redef fun couple_iterator do return _items.iterator
722
723 redef fun is_empty do return _items.is_empty
724
725 redef fun clear do _items.clear
726
727 # Assume the capacity to be at least `cap`.
728 fun enlarge(cap: Int) do _items.enlarge(cap)
729
730 redef fun couple_at(key)
731 do
732 var i = index(key)
733 if i >= 0 then
734 return _items[i]
735 else
736 return null
737 end
738 end
739
740 # Internal storage.
741 private var items = new Array[Couple[K,E]]
742
743 # fast remove the ith element of the array
744 private fun remove_at_index(i: Int)
745 do
746 _items[i] = _items.last
747 _items.pop
748 end
749
750 # The last positive result given by a index(1) call
751 private var last_index: Int = 0
752
753 # Where is the `key` in `_item`?
754 # return -1 if not found
755 private fun index(key: K): Int
756 do
757 var l = _last_index
758 if l < _items.length and _items[l].first == key then return l
759
760 var i = 0
761 while i < _items.length do
762 if _items[i].first == key then
763 _last_index = i
764 return i
765 end
766 i += 1
767 end
768 return -1
769 end
770
771 # Shallow clone of `self`
772 #
773 # ~~~
774 # var a = new ArrayMap[String,Int]
775 # a["one"] = 1
776 # a["two"] = 2
777 # var b = a.clone
778 # assert a == b
779 # a["zero"] = 0
780 # assert a != b
781 # ~~~
782 #
783 # Note that the clone is shallow and keys and values are shared between `self` and the result.
784 #
785 # ~~~
786 # var aa = new ArrayMap[String, Array[Int]]
787 # aa["two"] = [1,2]
788 # var bb = aa.clone
789 # assert aa == bb
790 # aa["two"].add 5
791 # assert aa == bb
792 # ~~~
793 redef fun clone
794 do
795 var res = new ArrayMap[K,E]
796 res.add_all self
797 return res
798 end
799 end
800
801 private class ArrayMapKeys[K, E]
802 super RemovableCollection[K]
803 # The original map
804 var map: ArrayMap[K, E]
805 redef fun count(k) do if self.has(k) then return 1 else return 0
806 redef fun first do return self.map._items.first.first
807 redef fun has(k) do return self.map.index(k) >= 0
808 redef fun has_only(k) do return (self.has(k) and self.length == 1) or self.is_empty
809 redef fun is_empty do return self.map.is_empty
810 redef fun length do return self.map.length
811 redef fun iterator do return new MapKeysIterator[K, E](self.map.iterator)
812 redef fun clear do self.map.clear
813 redef fun remove(key)
814 do
815 var i = self.map.index(key)
816 if i >= 0 then self.map.remove_at_index(i)
817 end
818 redef fun remove_all(key) do self.remove(key)
819 end
820
821 private class ArrayMapValues[K, E]
822 super RemovableCollection[E]
823 # The original map
824 var map: ArrayMap[K, E]
825 redef fun first do return self.map._items.first.second
826 redef fun is_empty do return self.map.is_empty
827 redef fun length do return self.map.length
828 redef fun iterator do return new MapValuesIterator[K, E](self.map.iterator)
829
830 # O(n)
831 redef fun has(item)
832 do
833 for i in self.map._items do if i.second == item then return true
834 return false
835 end
836
837 # O(n)
838 redef fun has_only(item)
839 do
840 for i in self.map._items do if i.second != item then return false
841 return true
842 end
843
844 # O(n)
845 redef fun count(item)
846 do
847 var nb = 0
848 for i in self.map._items do if i.second == item then nb += 1
849 return nb
850 end
851
852 redef fun clear do self.map.clear
853
854 redef fun remove(item)
855 do
856 var map = self.map
857 var i = map._items.length - 1
858 while i >= 0 do
859 if map._items[i].second == item then
860 map.remove_at_index(i)
861 return
862 end
863 i -= 1
864 end
865 end
866
867 redef fun remove_all(item)
868 do
869 var map = self.map
870 var i = map._items.length - 1
871 while i >= 0 do
872 if map._items[i].second == item then
873 map.remove_at_index(i)
874 end
875 i -= 1
876 end
877 end
878 end
879
880 # Comparable array for comparable elements.
881 #
882 # For two arrays, if one is a prefix, then it is lower.
883 #
884 # ~~~
885 # var a12 = new ArrayCmp[nullable Int].with_items(1,2)
886 # var a123 = new ArrayCmp[nullable Int].with_items(1,2,3)
887 # assert a12 < a123
888 # ~~~
889 #
890 # Otherwise, the first element just after the longest
891 # common prefix gives the order between the two arrays.
892 #
893 # ~~~
894 # var a124 = new ArrayCmp[nullable Int].with_items(1,2,4)
895 # var a13 = new ArrayCmp[nullable Int].with_items(1,3)
896 # assert a12 < a123
897 # assert a123 < a13
898 # ~~~
899 #
900 # Obviously, two equal arrays are equal.
901 #
902 # ~~~
903 # var b12 = new ArrayCmp[nullable Int].with_items(1,2)
904 # assert (a12 <=> b12) == 0
905 # ~~~
906 #
907 # `null` is considered lower than any other elements.
908 # But is still greater than no element.
909 #
910 # ~~~
911 # var a12n = new ArrayCmp[nullable Int].with_items(1,2,null)
912 # assert a12n < a123
913 # assert a12 < a12n
914 # ~~~
915 class ArrayCmp[E: nullable Comparable]
916 super Array[E]
917 super Comparable
918 redef type OTHER: ArrayCmp[E] is fixed
919
920 redef fun <(o) do return (self <=> o) < 0
921
922 redef fun <=>(o)
923 do
924 var it = _items
925 var oit = o._items
926 var i = 0
927 var l = length
928 var ol = o.length
929 var len
930 if l < ol then len = l else len = ol
931 while i < len do
932 var a = it[i]
933 var b = oit[i]
934 if a != null then
935 if b == null then return 1
936 var d = a <=> b
937 if d != 0 then return d
938 else
939 if b != null then return -1
940 end
941 i += 1
942 end
943 return l <=> ol
944 end
945 end
946
947 # Others tools ################################################################
948
949 redef class Iterator[E]
950 # Interate on `self` and build an array
951 fun to_a: Array[E]
952 do
953 var res = new Array[E]
954 while is_ok do
955 res.add(item)
956 next
957 end
958 finish
959 return res
960 end
961 end
962
963 redef class Collection[E]
964 # Build a new array from a collection
965 fun to_a: Array[E]
966 do
967 var res = new Array[E].with_capacity(length)
968 res.add_all(self)
969 return res
970 end
971 end
972
973 # Native classes ##############################################################
974
975 # Native Nit array
976 # Access are unchecked and it has a fixed size
977 # Not for public use: may become private.
978 universal NativeArray[E]
979 # Creates a new NativeArray of capacity `length`
980 new(length: Int) is intern
981 # The length of the array
982 fun length: Int is intern
983 # Use `self` to initialize a standard Nit Array.
984 fun to_a: Array[E] do return new Array[E].with_native(self, length)
985
986 # Get item at `index`.
987 fun [](index: Int): E is intern
988
989 # Set `item` at `index`.
990 fun []=(index: Int, item: E) is intern
991
992 # Copy `length` items to `dest`.
993 fun copy_to(dest: NativeArray[E], length: Int) is intern
994
995 # Copy `length` items to `dest` starting from `dest`.
996 fun memmove(start: Int, length: Int, dest: NativeArray[E], dest_start: Int) is intern do
997 if start < dest_start then
998 var i = length
999 while i > 0 do
1000 i -= 1
1001 dest[dest_start+i] = self[start+i]
1002 end
1003 else
1004 var i = 0
1005 while i < length do
1006 dest[dest_start+i] = self[start+i]
1007 i += 1
1008 end
1009 end
1010 end
1011
1012 #fun =(o: NativeArray[E]): Bool is intern
1013 #fun !=(o: NativeArray[E]): Bool is intern
1014 end