4 April, 2016 ARCO Meeting, Odense Last revision: 17 October, 2018
Worst-case-efficient dynamic arrays in practice
Jyrki Katajainen
Department of Computer Science University of Copenhagen paper code slides
goto my research information system
Worst-case-efficient dynamic arrays in practice Jyrki Katajainen - - PowerPoint PPT Presentation
4 April, 2016 ARCO Meeting, Odense Last revision: 17 October, 2018 Worst-case-efficient dynamic arrays in practice Jyrki Katajainen Department of Computer Science University of Copenhagen paper code goto my research information system at
goto my research information system
A: 1 i
p
A[i] ≡ ∗(A + i)
p = A; ++p;
A: 1 i
p
A[i] ≡ ∗(A. begin( ) + i)
p = A.begin( ); ++p;
std::vector + V: value type + A: allocator type + I: iterator type + N: size type . . . + default constructor + destructor + get allocator() const → A + begin() const → I + end() const → I + size() const → N + resize(N) → void + capacity() const → N + reserve(N) → void + shrink to fit() → void + operator[ ](N) const → V const& + operator[ ](N) → V& + push back(V const&) → void + push back(V&&) → void + pop back() → void + insert(I, V const&) → I + erase(I) → I . . .
V, A = std::allocator<V>
leda::array + V: value type + I: iterator type + item: I + N: size type . . . + default constructor + copy constructor + copy assignment + destructor + first item() → I + last item() → I + next item(I) → I + prev item(I) → I + begin() → I + end() → I + low() const → N + high() const → N + size() const → N + resize(N) → void + get(N) → V& + set(N, V) → void + operator[ ](N) → V& . . .
V
cphstl::vector + V: value type + A: allocator type + K: kernel type . . . . . .
V, A = std::allocator<V>, K = std::vector<V, A>
cphleda::array + V: value type + K: kernel type . . . . . .
V, K = std::vector<V, std::allocator<V>>
array kernel + V: value type + A: allocator type + K: array kernel<V, A> + I: rank iterator<K> + J : rank iterator<K const> + N: size type – Args: any argument-pack type . . . – index to address(N) const → V* + default constructor + destructor + get allocator() const → A + swap(K&) → void + begin() const → I + end() const → I + size() const → N + capacity() const → N + operator[ ](N) const → V const& + operator[ ](N) → V& + emplace back(Args&&...) → void + push back(V const&) → void + push back(V&&) → void + pop back() → void
V, A = std::allocator<V>
# include
< algorithm > // std : : sort
# include
< cassert > // assert
# include
< iostream > // standard streams
# include
< memory > // std : : allocator
# include ”sliced array . h++” // cphstl : : sliced array # include ” s t l−vector . h++” // cphstl : : vector int main(int , char∗∗) { using V = int ; using A = std : : allocator <V > ; using S = cphstl : : vector <V , A , cphstl : : sliced_array <V , A>
> ;
S sequence = {4 , 2, 3, 1};
std : : sort( sequence . begin( ) , sequence . end( )) ; assert(std : : is_sorted ( sequence . begin( ) , sequence . end( ))) ; for (V x : sequence ) { std : : cout <
< x < < ” ”; }
std : : cout <
< ”\n”;
return 0;
}
jyrki@Janus:~/CPHSTL/Paper/Dynamic-arrays/Test$ make usage g++ -x c++ -std=c++17 -Wall -Wextra -fconcepts -I../Code usage.c++ ./a.out 1 2 3 4
// shrink to fit namespace { template <typename T > concept bool has_shrink_to_fit
=
requires(T x) {
{ x . shrink_to_fit( ) } → void ; // member function }; }
template <typename V , typename A , typename K > void vector <V , A , K > : : shrink_to_fit( ) { i f constexpr ( has_shrink_to_fit <K > ) { kernel . shrink_to_fit( ) ;
}
else { // do nothing
} }
std :: allocator <char> a; a. deallocate (a. allocate (∆),∆);
25 26 27 28 29 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 35 35 61 61 60 67 68 66 66 68 68 68 50 51 52 52 52 51 51 52 2456 2644
free(malloc(∆));
25 26 27 28 29 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 27 27 49 50 48 57 57 55 55 57 57 57 37 39 39 39 39 39 39 39 2360 2366
if (n = N)
X:
Y:
if (4n ≤ N)
X: Y:
resizable_array )
if (n = N)
X:
Y:
if (4n ≤ N)
X: Y:
push_back: move 1 from the end of X to Y at the same relative position pop_back: move 2 from the end of X to Y at the same relative position if (X empty)
1 2
1 2 3 2 2 4 8
1 2
space_efficient_array )
1 2 3
push_back | pop_back
50 100 150 200 1×106 3×106 5×106 7×106 9×106 space overhead [%] # push_back’s [n] The amount of extra space in use at a specific time resizable vector pile sliced space efficient 0.1 1.0 1×106 3×106
V &
return ∗ index_to_address (i) ;
}
V ∗ index_to_address (N i) const {
return A + i ;
}
V ∗ index_to_address (N i) const {
i f (i < X_size) { return X + i ;
}
return Y + i ;
}
N whole_number_logarithm (N x) { asm(”bsr % 0, %0\n” : ” = r”(x) : ”0” (x) ) ; return x ;
}
V ∗ index_to_address (N i) const {
i f (i < 2) { return directory [0] + i ;
}
N h = whole_number_logarithm (i) ; return directory [ h ] + i − (1 <
< h) ; }
V ∗ index_to_address (N i) const {
return directory [ i >
>
shift ] + (i bitand mask) ;
}
V ∗ index_to_address (N i) const {
i f (i < 2) { return directory [0] . index_to_address (i) ;
}
N h = whole_number_logarithm (i) ; N ∆ = i − (1 <
< h) ;
return directory [ h ] . index_to_address (∆) ;
}
goto my research information system