# Copyright (c) 2023 Yuki Kimoto # MIT License class FloatList { use Fn; use Array; # Enumerations enum { DEFAULT_CAPACITY = 4, } # Fields has capacity : ro int; has length : ro int; has values : ro float[]; # Class methods static method new : FloatList ($array = undef : float[], $capacity = -1 : int) { my $length : int; if ($array) { $length = @$array; } else { $length = 0; } my $self = &new_len($length, $capacity); if ($array) { Array->memcpy_float($self->{values}, 0, $array, 0, $length); } return $self; } static method new_len : FloatList ($length : int, $capacity = -1 : int) { my $self = new FloatList; unless ($length >= 0) { die "The \$length must be greater than or equal to 0"; } if ($capacity < 0) { $capacity = &DEFAULT_CAPACITY; } if ($length > $capacity) { $capacity = $length; } $self->{capacity} = $capacity; $self->{length} = $length; $self->{values} = new float[$capacity]; return $self; } # Instance methods method get : float ($index : int) { my $length = $self->length; unless ($index >= 0) { die "The \$index must be greater than or equal to 0"; } unless ($index < $length) { die "The \$index must be less than the length of the \$list"; } my $element = $self->{values}[$index]; return $element; } method insert : void ($index : int, $element : float) { my $length = $self->{length}; unless ($index >= 0) { die "The \$index must be greater than or equal to 0"; } unless ($index <= $length) { die "The \$index must be less than or equal to the length of the \$list"; } my $new_length = $length + 1; $self->_maybe_extend($new_length); my $elements = $self->{values}; if ($index != $length) { my $dist_index = $index + 1; my $move_length = $length - $index; Array->memmove_float($elements, $dist_index, $elements, $index, $move_length); } $elements->[$index] = $element; $self->{length} = $new_length; } method pop : float () { my $length = $self->length; unless ($length > 0) { die "The length of the \$list must be greater than 0"; } my $element = $self->{values}[$length - 1]; $self->{values}[$length - 1] = 0; $self->{length}--; return $element; } method push : void ($element : float) { my $length = $self->{length}; my $new_length = $length + 1; $self->_maybe_extend($new_length); $self->{values}[$length] = $element; $self->{length} = $new_length; } method remove : float ($index : int) { my $length = $self->{length}; unless ($index >= 0) { die "The \$index must be greater than or equal to 0"; } unless ($index < $length) { die "The \$index must be less than the length of the \$list"; } my $elements = $self->{values}; my $remove_value = $elements->[$index]; my $dist_index = $index; my $src_index = $index + 1; my $move_length = $length - $index - 1; Array->memmove_float($elements, $dist_index, $elements, $src_index, $move_length); $self->{length}--; return $remove_value; } method replace : void ($offset : int, $remove_length : int, $replace : float[]) { unless ($offset >= 0) { die("The \$offset must be greater than or equal to 0"); } unless ($remove_length >= 0) { die("The \$remove_length must be greater than or equal to 0"); } unless ($offset + $remove_length <= $self->{length}) { die("The \$offset + the \$removing lenght must be less than or equal to the length of the \$list"); } my $replace_length = 0; if ($replace) { $replace_length = @$replace; } my $new_length = $self->{length} - $remove_length + $replace_length; $self->_maybe_extend($new_length); my $move_length = $self->{length} - $offset - $remove_length; Array->memmove_float($self->{values}, $offset + $replace_length, $self->{values}, $offset + $remove_length, $move_length); if ($replace) { Array->memcpy_float($self->{values}, $offset, $replace, 0, $replace_length); } $self->{length} = $new_length; } method reserve : void ($new_capacity : int) { unless ($new_capacity >= 0) { die "The \$new_capacity must be greater than or equal to 0"; } my $capacity = $self->{capacity}; if ($new_capacity > $capacity) { my $length = $self->{length}; my $new_values = new float[$new_capacity]; Array->memcpy_float($new_values, 0, $self->{values}, 0, $length); $self->{values} = $new_values; $self->{capacity} = $new_capacity; } } method resize : void ($new_length : int) { unless ($new_length >= 0) { die "The \$new_length must be greater than or equal to 0"; } my $length = $self->{length}; if ($new_length > $length) { $self->_maybe_extend($new_length); Array->memset_float($self->{values}, 0, $length, $new_length - $length); } elsif ($new_length < $length) { Array->memset_float($self->{values}, 0, $new_length, $length - $new_length); } $self->{length} = $new_length; } method set : void ($index : int, $element : float) { my $length = $self->length; unless ($index >= 0) { die "The \$index must be greater than or equal to 0"; } unless ($index < $length) { die "The \$index must be less than the length of the \$list"; } $self->{values}[$index] = $element; } method set_array : void ($array : float[]) { unless ($array) { die "The \$array must be defined"; } my $cur_length = $self->length; my $set_length = @$array; unless ($set_length == $cur_length) { die "The length of the \$array must be the \$same as the length of the \$list"; } Array->memcpy_float($self->{values}, 0, $array, 0, $cur_length); } method shift : float () { my $length = $self->{length}; unless ($length > 0) { die "The length of the \$list must be greater than 0"; } my $elements = $self->{values}; my $element = $elements->[0]; Array->memmove_float($elements, 0, $elements, 1, $length - 1); $elements->[$length - 1] = 0; $self->{length}--; return $element; } method to_array : float[] () { my $length = $self->length; my $array = new float[$length]; my $elements = $self->{values}; Array->memcpy_float($array, 0, $elements, 0, $length); return $array; } method unshift : void ($element : float) { my $length = $self->{length}; my $new_length = $length + 1; $self->_maybe_extend($new_length); my $elements = $self->{values}; Array->memmove_float($elements, 1, $elements, 0, $length); $elements->[0] = $element; $self->{length} = $new_length; } private method _maybe_extend : void ($min_capacity : int) { my $capacity = $self->{capacity}; unless ($min_capacity > $capacity) { return; } if ($capacity < $min_capacity) { $capacity = $min_capacity; } my $new_capacity = $capacity * 2; my $new_values = new float[$new_capacity]; my $length = $self->{length}; my $elements = $self->{values}; Array->memcpy_float($new_values, 0, $elements, 0, $length); $self->{values} = $new_values; $self->{capacity} = $new_capacity; } }