package SPVM::ArrayUtil : precompile { use SPVM::Cloner; use SPVM::EqualityChecker; use SPVM::StringUtil; use SPVM::Comparator::Byte; use SPVM::Comparator::Short; use SPVM::Comparator::Int; use SPVM::Comparator::Long; use SPVM::Comparator::Float; use SPVM::Comparator::Double; use SPVM::Comparator::String; use SPVM::Comparator::Object; sub copy_array_byte : byte[] ($nums : byte[]) { if ($nums == undef) { return undef; } my $length = @$nums; my $new_nums = new byte[$length]; for (my $i = 0; $i < $length; $i++) { $new_nums->[$i] = $nums->[$i]; } return $new_nums; } sub copy_array_short : short[] ($nums : short[]) { if ($nums == undef) { return undef; } my $length = @$nums; my $new_nums = new short[$length]; for (my $i = 0; $i < $length; $i++) { $new_nums->[$i] = $nums->[$i]; } return $new_nums; } sub copy_array_int : int[] ($nums : int[]) { if ($nums == undef) { return undef; } my $length = @$nums; my $new_nums = new int[$length]; for (my $i = 0; $i < $length; $i++) { $new_nums->[$i] = $nums->[$i]; } return $new_nums; } sub copy_array_long : long[] ($nums : long[]) { if ($nums == undef) { return undef; } my $length = @$nums; my $new_nums = new long[$length]; for (my $i = 0; $i < $length; $i++) { $new_nums->[$i] = $nums->[$i]; } return $new_nums; } sub copy_array_float : float[] ($nums : float[]) { if ($nums == undef) { return undef; } my $length = @$nums; my $new_nums = new float[$length]; for (my $i = 0; $i < $length; $i++) { $new_nums->[$i] = $nums->[$i]; } return $new_nums; } sub copy_array_double : double[] ($nums : double[]) { if ($nums == undef) { return undef; } my $length = @$nums; my $new_nums = new double[$length]; for (my $i = 0; $i < $length; $i++) { $new_nums->[$i] = $nums->[$i]; } return $new_nums; } sub copy_array_string : string[] ($strings : string[]) { if ($strings == undef) { return undef; } my $length = @$strings; my $new_strings = new string[$length]; for (my $i = 0; $i < $length; $i++) { $new_strings->[$i] = SPVM::StringUtil->copy_string($strings->[$i]); } return $new_strings; } sub copy_array_object : object[] ($objects : object[], $cloner : SPVM::Cloner) { if ($objects == undef) { return undef; } my $length = @$objects; my $new_objects = new object[$length]; for (my $i = 0; $i < $length; $i++) { $new_objects->[$i] = $cloner->($objects->[$i]); } return $new_objects; } sub copy_array_range_byte : byte[] ($nums : byte[], $offset : int, $length : int) { if ($nums == undef) { die "The argument array must be defined"; } my $array_length = @$nums; if ($offset < 0 || $offset > $array_length - 1) { die "Offset must be in the array range"; } if ($length < 0) { die "Length must be more than or equals to 0"; } if ($offset + $length > $array_length) { die "Offset + length must be in the array range"; } my $range = new byte[$length]; my $pos = 0; for (my $i = $offset; $i < $offset + $length; $i++) { $range->[$pos] = $nums->[$i]; $pos++; } return $range; } sub copy_array_range_short : short[] ($nums : short[], $offset : int, $length : int) { if ($nums == undef) { die "The argument array must be defined"; } my $array_length = @$nums; if ($offset < 0 || $offset > $array_length - 1) { die "Offset must be in the array range"; } if ($length < 0) { die "Length must be more than or equals to 0"; } if ($offset + $length > $array_length) { die "Offset + length must be in the array range"; } my $range = new short[$length]; my $pos = 0; for (my $i = $offset; $i < $offset + $length; $i++) { $range->[$pos] = $nums->[$i]; $pos++; } return $range; } sub copy_array_range_int : int[] ($nums : int[], $offset : int, $length : int) { if ($nums == undef) { die "The argument array must be defined"; } my $array_length = @$nums; if ($offset < 0 || $offset > $array_length - 1) { die "Offset must be in the array range"; } if ($length < 0) { die "Length must be more than or equals to 0"; } if ($offset + $length > $array_length) { die "Offset + length must be in the array range"; } my $range = new int[$length]; my $pos = 0; for (my $i = $offset; $i < $offset + $length; $i++) { $range->[$pos] = $nums->[$i]; $pos++; } return $range; } sub copy_array_range_long : long[] ($nums : long[], $offset : int, $length : int) { if ($nums == undef) { die "The argument array must be defined"; } my $array_length = @$nums; if ($offset < 0 || $offset > $array_length - 1) { die "Offset must be in the array range"; } if ($length < 0) { die "Length must be more than or equals to 0"; } if ($offset + $length > $array_length) { die "Offset + length must not be in the array range"; } my $range = new long[$length]; my $pos = 0; for (my $i = $offset; $i < $offset + $length; $i++) { $range->[$pos] = $nums->[$i]; $pos++; } return $range; } sub copy_array_range_float : float[] ($nums : float[], $offset : int, $length : int) { if ($nums == undef) { die "The argument array must be defined"; } my $array_length = @$nums; if ($offset < 0 || $offset > $array_length - 1) { die "Offset must be in the array range"; } if ($length < 0) { die "Length must be more than or equals to 0"; } if ($offset + $length > $array_length) { die "Offset + length must not be in the array range"; } my $range = new float[$length]; my $pos = 0; for (my $i = $offset; $i < $offset + $length; $i++) { $range->[$pos] = $nums->[$i]; $pos++; } return $range; } sub copy_array_range_double : double[] ($nums : double[], $offset : int, $length : int) { if ($nums == undef) { die "The argument array must be defined"; } my $array_length = @$nums; if ($offset < 0 || $offset > $array_length - 1) { die "Offset must be in the array range"; } if ($length < 0) { die "Length must be more than or equals to 0"; } if ($offset + $length > $array_length) { die "Offset + length must not be in the array range"; } my $range = new double[$length]; my $pos = 0; for (my $i = $offset; $i < $offset + $length; $i++) { $range->[$pos] = $nums->[$i]; $pos++; } return $range; } sub copy_array_range_string : string[] ($strings : string[], $offset : int, $length : int) { if ($strings == undef) { die "The argument array must be defined"; } my $array_length = @$strings; if ($offset < 0 || $offset > $array_length - 1) { die "Offset must be in the array range"; } if ($length < 0) { die "Length must be more than or equals to 0"; } if ($offset + $length > $array_length) { die "Offset + length must not be in the array range"; } my $range = new string[$length]; my $pos = 0; for (my $i = $offset; $i < $offset + $length; $i++) { $range->[$pos] = $strings->[$i]; $pos++; } return $range; } sub copy_array_range_object : oarray ($objects : oarray, $offset : int, $length : int) { if ($objects == undef) { die "The argument array must be defined"; } my $array_length = @$objects; if ($offset < 0 || $offset > $array_length - 1) { die "Offset must be in the array range"; } if ($length < 0) { die "Length must be more than or equals to 0"; } if ($offset + $length > $array_length) { die "Offset + length must not be in the array range"; } my $range = new_array_proto($objects, $length); my $pos = 0; for (my $i = $offset; $i < $offset + $length; $i++) { $range->[$pos] = $objects->[$i]; $pos++; } return $range; } sub equals_array_byte : int ($nums1 : byte[], $nums2 : byte[]) { if ($nums1 == undef && $nums2 == undef) { return 1; } elsif ($nums1 != undef && $nums2 == undef) { return 0; } elsif ($nums1 == undef && $nums2 != undef) { return 0; } my $is_equals = 1; if (@$nums1 == @$nums2) { for (my $i = 0; $i < @$nums1; $i++) { if ($nums1->[$i] != $nums2->[$i]) { $is_equals = 0; last; } } } else { $is_equals = 0; } return $is_equals; } sub equals_array_short : int ($nums1 : short[], $nums2 : short[]) { if ($nums1 == undef && $nums2 == undef) { return 1; } elsif ($nums1 != undef && $nums2 == undef) { return 0; } elsif ($nums1 == undef && $nums2 != undef) { return 0; } my $is_equals = 1; if (@$nums1 == @$nums2) { for (my $i = 0; $i < @$nums1; $i++) { if ($nums1->[$i] != $nums2->[$i]) { $is_equals = 0; last; } } } else { $is_equals = 0; } return $is_equals; } sub equals_array_int : int ($nums1 : int[], $nums2 : int[]) { if ($nums1 == undef && $nums2 == undef) { return 1; } elsif ($nums1 != undef && $nums2 == undef) { return 0; } elsif ($nums1 == undef && $nums2 != undef) { return 0; } my $is_equals = 1; if (@$nums1 == @$nums2) { for (my $i = 0; $i < @$nums1; $i++) { if ($nums1->[$i] != $nums2->[$i]) { $is_equals = 0; last; } } } else { $is_equals = 0; } return $is_equals; } sub equals_array_long : int ($nums1 : long[], $nums2 : long[]) { if ($nums1 == undef && $nums2 == undef) { return 1; } elsif ($nums1 != undef && $nums2 == undef) { return 0; } elsif ($nums1 == undef && $nums2 != undef) { return 0; } my $is_equals = 1; if (@$nums1 == @$nums2) { for (my $i = 0; $i < @$nums1; $i++) { if ($nums1->[$i] != $nums2->[$i]) { $is_equals = 0; last; } } } else { $is_equals = 0; } return $is_equals; } sub equals_array_float : int ($nums1 : float[], $nums2 : float[]) { if ($nums1 == undef && $nums2 == undef) { return 1; } elsif ($nums1 != undef && $nums2 == undef) { return 0; } elsif ($nums1 == undef && $nums2 != undef) { return 0; } my $is_equals = 1; if (@$nums1 == @$nums2) { for (my $i = 0; $i < @$nums1; $i++) { if ($nums1->[$i] != $nums2->[$i]) { $is_equals = 0; last; } } } else { $is_equals = 0; } return $is_equals; } sub equals_array_double : int ($nums1 : double[], $nums2 : double[]) { if ($nums1 == undef && $nums2 == undef) { return 1; } elsif ($nums1 != undef && $nums2 == undef) { return 0; } elsif ($nums1 == undef && $nums2 != undef) { return 0; } my $is_equals = 1; if (@$nums1 == @$nums2) { for (my $i = 0; $i < @$nums1; $i++) { if ($nums1->[$i] != $nums2->[$i]) { $is_equals = 0; last; } } } else { $is_equals = 0; } return $is_equals; } sub equals_array_string : int ($strings1 : string[], $strings2 : string[]) { if ($strings1 == undef && $strings2 == undef) { return 1; } elsif ($strings1 != undef && $strings2 == undef) { return 0; } elsif ($strings1 == undef && $strings2 != undef) { return 0; } my $is_equals = 1; if (@$strings1 == @$strings2) { for (my $i = 0; $i < @$strings1; $i++) { if ($strings1->[$i] ne $strings2->[$i]) { $is_equals = 0; last; } } } else { $is_equals = 0; } return $is_equals; } sub equals_array_object : int ($objects1 : oarray, $objects2 : oarray, $equality_checker : SPVM::EqualityChecker) { if ($objects1 == undef && $objects2 == undef) { return 1; } elsif ($objects1 != undef && $objects2 == undef) { return 0; } elsif ($objects1 == undef && $objects2 != undef) { return 0; } my $is_equals = 1; if (@$objects1 == @$objects2) { for (my $i = 0; $i < @$objects1; $i++) { if (!$equality_checker->($objects1->[$i], $objects2->[$i])) { $is_equals = 0; last; } } } else { $is_equals = 0; } return $is_equals; } sub dump_array_byte : string ($nums : byte[]) { if ($nums == undef) { return undef; } my $dump = "[\n"; for (my $i = 0; $i < @$nums; $i++) { my $string = (string)$nums->[$i]; $dump .= " $string"; if ($i != @$nums - 1) { $dump .= ",\n"; } else { $dump .= "\n"; } } $dump .= "]"; return $dump; } sub dump_array_short : string ($nums : short[]) { if ($nums == undef) { return undef; } my $dump = "[\n"; for (my $i = 0; $i < @$nums; $i++) { my $string = (string)$nums->[$i]; $dump .= " $string"; if ($i != @$nums - 1) { $dump .= ",\n"; } else { $dump .= "\n"; } } $dump .= "]"; return $dump; } sub dump_array_int : string ($nums : int[]) { if ($nums == undef) { return undef; } my $dump = "[\n"; for (my $i = 0; $i < @$nums; $i++) { my $string = (string)$nums->[$i]; $dump .= " $string"; if ($i != @$nums - 1) { $dump .= ",\n"; } else { $dump .= "\n"; } } $dump .= "]"; return $dump; } sub dump_array_long : string ($nums : long[]) { if ($nums == undef) { return undef; } my $dump = "[\n"; for (my $i = 0; $i < @$nums; $i++) { my $string = (string)$nums->[$i]; $dump .= " $string"; if ($i != @$nums - 1) { $dump .= ",\n"; } else { $dump .= "\n"; } } $dump .= "]"; return $dump; } sub dump_array_unsigned_byte : string ($nums : byte[]) { if ($nums == undef) { return undef; } my $dump = "[\n"; for (my $i = 0; $i < @$nums; $i++) { my $string = SPVM::StringUtil->sprintf("%u", (int)$nums->[$i] & 0xFF); $dump .= " $string"; if ($i != @$nums - 1) { $dump .= ",\n"; } else { $dump .= "\n"; } } $dump .= "]"; return $dump; } sub dump_array_unsigned_short : string ($nums : short[]) { if ($nums == undef) { return undef; } my $dump = "[\n"; for (my $i = 0; $i < @$nums; $i++) { my $string = SPVM::StringUtil->sprintf("%u", (int)$nums->[$i] & 0xFFFF); $dump .= " $string"; if ($i != @$nums - 1) { $dump .= ",\n"; } else { $dump .= "\n"; } } $dump .= "]"; return $dump; } sub dump_array_unsigned_int : string ($nums : int[]) { if ($nums == undef) { return undef; } my $dump = "[\n"; for (my $i = 0; $i < @$nums; $i++) { my $string = SPVM::StringUtil->sprintf("%u", $nums->[$i]); $dump .= " $string"; if ($i != @$nums - 1) { $dump .= ",\n"; } else { $dump .= "\n"; } } $dump .= "]"; return $dump; } sub dump_array_unsigned_long : string ($nums : long[]) { if ($nums == undef) { return undef; } my $dump = "[\n"; for (my $i = 0; $i < @$nums; $i++) { my $string = SPVM::StringUtil->sprintf("%lu", $nums->[$i]); $dump .= " $string"; if ($i != @$nums - 1) { $dump .= ",\n"; } else { $dump .= "\n"; } } $dump .= "]"; return $dump; } sub dump_array_float : string ($nums : float[]) { if ($nums == undef) { return undef; } my $dump = "[\n"; for (my $i = 0; $i < @$nums; $i++) { my $string = (string)$nums->[$i]; $dump .= " $string"; if ($i != @$nums - 1) { $dump .= ",\n"; } else { $dump .= "\n"; } } $dump .= "]"; return $dump; } sub dump_array_double : string ($nums : double[]) { if ($nums == undef) { return undef; } my $dump = "[\n"; for (my $i = 0; $i < @$nums; $i++) { my $string = (string)$nums->[$i]; $dump .= " $string"; if ($i != @$nums - 1) { $dump .= ",\n"; } else { $dump .= "\n"; } } $dump .= "]"; return $dump; } sub dump_array_string : string ($strings : string[]) { if ($strings == undef) { return undef; } my $dump = "[\n"; for (my $i = 0; $i < @$strings; $i++) { my $string = $strings->[$i]; $dump .= " $string"; if ($i != @$strings - 1) { $dump .= ",\n"; } else { $dump .= "\n"; } } $dump .= "]"; return $dump; } sub dump_array_object : string ($objects : oarray, $stringer : SPVM::Stringer) { if ($objects == undef) { return undef; } my $dump = "[\n"; for (my $i = 0; $i < @$objects; $i++) { my $string = $stringer->($objects->[$i]); $dump .= " $string"; if ($i != @$objects - 1) { $dump .= ",\n"; } else { $dump .= "\n"; } } $dump .= "]"; return $dump; } native sub memcpy_byte : void ($dest : byte[], $dest_offset : int, $source : byte[], $source_offset : int, $length : int); native sub memcpy_short : void ($dest : short[], $dest_offset : int, $source : short[], $source_offset : int, $length : int); native sub memcpy_int : void ($dest : int[], $dest_offset : int, $source : int[], $source_offset : int, $length : int); native sub memcpy_long : void ($dest : long[], $dest_offset : int, $source : long[], $source_offset : int, $length : int); native sub memcpy_float : void ($dest : float[], $dest_offset : int, $source : float[], $source_offset : int, $length : int); native sub memcpy_double : void ($dest : double[], $dest_offset : int, $source : double[], $source_offset : int, $length : int); native sub memmove_byte : void ($dest : byte[], $dest_offset : int, $source : byte[], $source_offset : int, $length : int); native sub memmove_short : void ($dest : short[], $dest_offset : int, $source : short[], $source_offset : int, $length : int); native sub memmove_int : void ($dest : int[], $dest_offset : int, $source : int[], $source_offset : int, $length : int); native sub memmove_long : void ($dest : long[], $dest_offset : int, $source : long[], $source_offset : int, $length : int); native sub memmove_float : void ($dest : float[], $dest_offset : int, $source : float[], $source_offset : int, $length : int); native sub memmove_double : void ($dest : double[], $dest_offset : int, $source : double[], $source_offset : int, $length : int); native sub new_array_proto : oarray ($proto_array : oarray, $length : int); sub sort_byte : void ($nums : byte[], $offset : int, $length : int, $comparator : SPVM::Comparator::Byte) { if ($nums == undef) { die "Array must be not undef"; } my $nums_length = @$nums; if ($offset < 0) { die "Offset must be more than or equals to 0"; } if ($length < 0) { die "Length must be more than or equals to 0"; } if ($offset + $length > $nums_length) { die "Offset + Length must be in the array range"; } if ($length == 0) { return; } my $b = new byte[$length]; _sort_byte_merge_sort($nums, $b, $offset, $offset + $length - 1, $length - 1, $comparator); } private sub _sort_byte_merge : void($a : byte[], $b : byte[], $left : int, $mid : int, $right : int, $n : int, $comparator : SPVM::Comparator::Byte) { my $i = $left; my $j = $mid + 1; my $k = 0; while ($i <= $mid && $j <= $right) { $i = $left; $j = $mid + 1; $k = 0; while ($i <= $mid && $j <= $right) { if ($comparator->($a->[$i], $a->[$j]) <= 0) { $b->[$k] = $a->[$i]; $i++; } else { $b->[$k] = $a->[$j]; $j++; } $k++; } if ($i == $mid + 1) { while ($j <= $right) { $b->[$k] = $a->[$j]; $j++; $k++; } } else { while($i <= $mid) { $b->[$k] = $a->[$i]; $i++; $k++; } } } for ($i = 0; $i < $k; $i++) { $a->[$i + $left] = $b->[$i]; } } private sub _sort_byte_merge_sort : void($a : byte[], $b : byte[], $left : int, $right : int, $n : int, $comparator : SPVM::Comparator::Byte){ if ($left >= $right) { return; } my $mid = ($left + $right) / 2; _sort_byte_merge_sort($a, $b, $left, $mid, $n, $comparator); _sort_byte_merge_sort($a, $b, $mid + 1, $right, $n, $comparator); _sort_byte_merge($a, $b, $left, $mid, $right, $n, $comparator); } sub sort_short : void ($nums : short[], $offset : int, $length : int, $comparator : SPVM::Comparator::Short) { if ($nums == undef) { die "Array must be not undef"; } my $nums_length = @$nums; if ($offset < 0) { die "Offset must be more than or equals to 0"; } if ($length < 0) { die "Length must be more than or equals to 0"; } if ($offset + $length > $nums_length) { die "Offset + Length must be in the array range"; } if ($length == 0) { return; } my $b = new short[$length]; _sort_short_merge_sort($nums, $b, $offset, $offset + $length - 1, $length - 1, $comparator); } private sub _sort_short_merge : void($a : short[], $b : short[], $left : int, $mid : int, $right : int, $n : int, $comparator : SPVM::Comparator::Short) { my $i = $left; my $j = $mid + 1; my $k = 0; while ($i <= $mid && $j <= $right) { $i = $left; $j = $mid + 1; $k = 0; while ($i <= $mid && $j <= $right) { if ($comparator->($a->[$i], $a->[$j]) <= 0) { $b->[$k] = $a->[$i]; $i++; } else { $b->[$k] = $a->[$j]; $j++; } $k++; } if ($i == $mid + 1) { while ($j <= $right) { $b->[$k] = $a->[$j]; $j++; $k++; } } else { while($i <= $mid) { $b->[$k] = $a->[$i]; $i++; $k++; } } } for ($i = 0; $i < $k; $i++) { $a->[$i + $left] = $b->[$i]; } } private sub _sort_short_merge_sort : void($a : short[], $b : short[], $left : int, $right : int, $n : int, $comparator : SPVM::Comparator::Short){ if ($left >= $right) { return; } my $mid = ($left + $right) / 2; _sort_short_merge_sort($a, $b, $left, $mid, $n, $comparator); _sort_short_merge_sort($a, $b, $mid + 1, $right, $n, $comparator); _sort_short_merge($a, $b, $left, $mid, $right, $n, $comparator); } sub sort_int : void ($nums : int[], $offset : int, $length : int, $comparator : SPVM::Comparator::Int) { if ($nums == undef) { die "Array must be not undef"; } my $nums_length = @$nums; if ($offset < 0) { die "Offset must be more than or equals to 0"; } if ($length < 0) { die "Length must be more than or equals to 0"; } if ($offset + $length > $nums_length) { die "Offset + Length must be in the array range"; } if ($length == 0) { return; } my $b = new int[$length]; _sort_int_merge_sort($nums, $b, $offset, $offset + $length - 1, $length - 1, $comparator); } private sub _sort_int_merge : void($a : int[], $b : int[], $left : int, $mid : int, $right : int, $n : int, $comparator : SPVM::Comparator::Int) { my $i = $left; my $j = $mid + 1; my $k = 0; while ($i <= $mid && $j <= $right) { $i = $left; $j = $mid + 1; $k = 0; while ($i <= $mid && $j <= $right) { if ($comparator->($a->[$i], $a->[$j]) <= 0) { $b->[$k] = $a->[$i]; $i++; } else { $b->[$k] = $a->[$j]; $j++; } $k++; } if ($i == $mid + 1) { while ($j <= $right) { $b->[$k] = $a->[$j]; $j++; $k++; } } else { while($i <= $mid) { $b->[$k] = $a->[$i]; $i++; $k++; } } } for ($i = 0; $i < $k; $i++) { $a->[$i + $left] = $b->[$i]; } } private sub _sort_int_merge_sort : void($a : int[], $b : int[], $left : int, $right : int, $n : int, $comparator : SPVM::Comparator::Int){ if ($left >= $right) { return; } my $mid = ($left + $right) / 2; _sort_int_merge_sort($a, $b, $left, $mid, $n, $comparator); _sort_int_merge_sort($a, $b, $mid + 1, $right, $n, $comparator); _sort_int_merge($a, $b, $left, $mid, $right, $n, $comparator); } sub sort_long : void ($nums : long[], $offset : int, $length : int, $comparator : SPVM::Comparator::Long) { if ($nums == undef) { die "Array must be not undef"; } my $nums_length = @$nums; if ($offset < 0) { die "Offset must be more than or equals to 0"; } if ($length < 0) { die "Length must be more than or equals to 0"; } if ($offset + $length > $nums_length) { die "Offset + Length must be in the array range"; } if ($length == 0) { return; } my $b = new long[$length]; _sort_long_merge_sort($nums, $b, $offset, $offset + $length - 1, $length - 1, $comparator); } private sub _sort_long_merge : void($a : long[], $b : long[], $left : int, $mid : int, $right : int, $n : int, $comparator : SPVM::Comparator::Long) { my $i = $left; my $j = $mid + 1; my $k = 0; while ($i <= $mid && $j <= $right) { $i = $left; $j = $mid + 1; $k = 0; while ($i <= $mid && $j <= $right) { if ($comparator->($a->[$i], $a->[$j]) <= 0) { $b->[$k] = $a->[$i]; $i++; } else { $b->[$k] = $a->[$j]; $j++; } $k++; } if ($i == $mid + 1) { while ($j <= $right) { $b->[$k] = $a->[$j]; $j++; $k++; } } else { while($i <= $mid) { $b->[$k] = $a->[$i]; $i++; $k++; } } } for ($i = 0; $i < $k; $i++) { $a->[$i + $left] = $b->[$i]; } } private sub _sort_long_merge_sort : void($a : long[], $b : long[], $left : int, $right : int, $n : int, $comparator : SPVM::Comparator::Long){ if ($left >= $right) { return; } my $mid = ($left + $right) / 2; _sort_long_merge_sort($a, $b, $left, $mid, $n, $comparator); _sort_long_merge_sort($a, $b, $mid + 1, $right, $n, $comparator); _sort_long_merge($a, $b, $left, $mid, $right, $n, $comparator); } sub sort_float : void ($nums : float[], $offset : int, $length : int, $comparator : SPVM::Comparator::Float) { if ($nums == undef) { die "Array must be not undef"; } my $nums_length = @$nums; if ($offset < 0) { die "Offset must be more than or equals to 0"; } if ($length < 0) { die "Length must be more than or equals to 0"; } if ($offset + $length > $nums_length) { die "Offset + Length must be in the array range"; } if ($length == 0) { return; } my $b = new float[$length]; _sort_float_merge_sort($nums, $b, $offset, $offset + $length - 1, $length - 1, $comparator); } private sub _sort_float_merge : void($a : float[], $b : float[], $left : int, $mid : int, $right : int, $n : int, $comparator : SPVM::Comparator::Float) { my $i = $left; my $j = $mid + 1; my $k = 0; while ($i <= $mid && $j <= $right) { $i = $left; $j = $mid + 1; $k = 0; while ($i <= $mid && $j <= $right) { if ($comparator->($a->[$i], $a->[$j]) <= 0) { $b->[$k] = $a->[$i]; $i++; } else { $b->[$k] = $a->[$j]; $j++; } $k++; } if ($i == $mid + 1) { while ($j <= $right) { $b->[$k] = $a->[$j]; $j++; $k++; } } else { while($i <= $mid) { $b->[$k] = $a->[$i]; $i++; $k++; } } } for ($i = 0; $i < $k; $i++) { $a->[$i + $left] = $b->[$i]; } } private sub _sort_float_merge_sort : void($a : float[], $b : float[], $left : int, $right : int, $n : int, $comparator : SPVM::Comparator::Float){ if ($left >= $right) { return; } my $mid = ($left + $right) / 2; _sort_float_merge_sort($a, $b, $left, $mid, $n, $comparator); _sort_float_merge_sort($a, $b, $mid + 1, $right, $n, $comparator); _sort_float_merge($a, $b, $left, $mid, $right, $n, $comparator); } sub sort_double : void ($nums : double[], $offset : int, $length : int, $comparator : SPVM::Comparator::Double) { if ($nums == undef) { die "Array must be not undef"; } my $nums_length = @$nums; if ($offset < 0) { die "Offset must be more than or equals to 0"; } if ($length < 0) { die "Length must be more than or equals to 0"; } if ($offset + $length > $nums_length) { die "Offset + Length must be in the array range"; } if ($length == 0) { return; } my $b = new double[$length]; _sort_double_merge_sort($nums, $b, $offset, $offset + $length - 1, $length - 1, $comparator); } private sub _sort_double_merge : void($a : double[], $b : double[], $left : int, $mid : int, $right : int, $n : int, $comparator : SPVM::Comparator::Double) { my $i = $left; my $j = $mid + 1; my $k = 0; while ($i <= $mid && $j <= $right) { $i = $left; $j = $mid + 1; $k = 0; while ($i <= $mid && $j <= $right) { if ($comparator->($a->[$i], $a->[$j]) <= 0) { $b->[$k] = $a->[$i]; $i++; } else { $b->[$k] = $a->[$j]; $j++; } $k++; } if ($i == $mid + 1) { while ($j <= $right) { $b->[$k] = $a->[$j]; $j++; $k++; } } else { while($i <= $mid) { $b->[$k] = $a->[$i]; $i++; $k++; } } } for ($i = 0; $i < $k; $i++) { $a->[$i + $left] = $b->[$i]; } } private sub _sort_double_merge_sort : void($a : double[], $b : double[], $left : int, $right : int, $n : int, $comparator : SPVM::Comparator::Double){ if ($left >= $right) { return; } my $mid = ($left + $right) / 2; _sort_double_merge_sort($a, $b, $left, $mid, $n, $comparator); _sort_double_merge_sort($a, $b, $mid + 1, $right, $n, $comparator); _sort_double_merge($a, $b, $left, $mid, $right, $n, $comparator); } sub sort_string : void ($strings : string[], $offset : int, $length : int, $comparator : SPVM::Comparator::String) { if ($strings == undef) { die "Array must be not undef"; } my $strings_length = @$strings; if ($offset < 0) { die "Offset must be more than or equals to 0"; } if ($length < 0) { die "Length must be more than or equals to 0"; } if ($offset + $length > $strings_length) { die "Offset + Length must be in the array range"; } my $b = new string[$length]; _sort_string_merge_sort($strings, $b, $offset, $offset + $length - 1, $length - 1, $comparator); } private sub _sort_string_merge : void($a : string[], $b : string[], $left : int, $mid : int, $right : int, $n : int, $comparator : SPVM::Comparator::String) { my $i = $left; my $j = $mid + 1; my $k = 0; while ($i <= $mid && $j <= $right) { $i = $left; $j = $mid + 1; $k = 0; while ($i <= $mid && $j <= $right) { if ($comparator->($a->[$i], $a->[$j]) <= 0) { $b->[$k] = $a->[$i]; $i++; } else { $b->[$k] = $a->[$j]; $j++; } $k++; } if ($i == $mid + 1) { while ($j <= $right) { $b->[$k] = $a->[$j]; $j++; $k++; } } else { while($i <= $mid) { $b->[$k] = $a->[$i]; $i++; $k++; } } } for ($i = 0; $i < $k; $i++) { $a->[$i + $left] = $b->[$i]; } } private sub _sort_string_merge_sort : void($a : string[], $b : string[], $left : int, $right : int, $n : int, $comparator : SPVM::Comparator::String){ if ($left >= $right) { return; } my $mid = ($left + $right) / 2; _sort_string_merge_sort($a, $b, $left, $mid, $n, $comparator); _sort_string_merge_sort($a, $b, $mid + 1, $right, $n, $comparator); _sort_string_merge($a, $b, $left, $mid, $right, $n, $comparator); } sub sort_object : void ($objects : oarray, $offset : int, $length : int, $comparator : SPVM::Comparator::Object) { if ($objects == undef) { die "Array must be not undef"; } my $objects_length = @$objects; if ($offset < 0) { die "Offset must be more than or equals to 0"; } if ($length < 0) { die "Length must be more than or equals to 0"; } if ($offset + $length > $objects_length) { die "Offset + Length must be in the array range"; } my $b = new_array_proto($objects, $length); _sort_object_merge_sort($objects, $b, $offset, $offset + $length - 1, $length - 1, $comparator); } private sub _sort_object_merge : void($a : oarray, $b : oarray, $left : int, $mid : int, $right : int, $n : int, $comparator : SPVM::Comparator::Object) { my $i = $left; my $j = $mid + 1; my $k = 0; while ($i <= $mid && $j <= $right) { $i = $left; $j = $mid + 1; $k = 0; while ($i <= $mid && $j <= $right) { if ($comparator->($a->[$i], $a->[$j]) <= 0) { $b->[$k] = $a->[$i]; $i++; } else { $b->[$k] = $a->[$j]; $j++; } $k++; } if ($i == $mid + 1) { while ($j <= $right) { $b->[$k] = $a->[$j]; $j++; $k++; } } else { while($i <= $mid) { $b->[$k] = $a->[$i]; $i++; $k++; } } } for ($i = 0; $i < $k; $i++) { $a->[$i + $left] = $b->[$i]; } } private sub _sort_object_merge_sort : void($a : oarray, $b : oarray, $left : int, $right : int, $n : int, $comparator : SPVM::Comparator::Object){ if ($left >= $right) { return; } my $mid = ($left + $right) / 2; _sort_object_merge_sort($a, $b, $left, $mid, $n, $comparator); _sort_object_merge_sort($a, $b, $mid + 1, $right, $n, $comparator); _sort_object_merge($a, $b, $left, $mid, $right, $n, $comparator); } }