File 3902-Increase-bucket-size-to-16.patch of Package erlang
From c86efe8f71255c79a7e063e7ea9233c53db61b5c Mon Sep 17 00:00:00 2001
From: Dan Gudmundsson <dgud@erlang.org>
Date: Fri, 23 Jan 2026 09:42:40 +0100
Subject: [PATCH 2/5] Increase bucket size to 16
Measurements gives that a bucket size of 16 seems to be the best size
nowadays. Measurements where done on size 8, 10, 16 and 32.
The power of 2 size also enables us to use bit operations
instead of rem/div, that gave even more performance
even if the div/rem operations where optimized.
Also removes the size field in the internal nodes, so they are the
same size as leaf nodes. Keep the size information in meta-data only,
and forward recursively. Reduces memory and removes one bit shift on
recursions.
Also done some cleaning:
- Cleanup (remove tests in source) and whitespace
- Fixed coverage and removed some dead code.
- array_SUITE: whitespace; use standard asserts
- Fix dialyzer tests
---
.../indent2_SUITE_data/results/arr.license | 7 +
.../test/opaque_SUITE_data/results/array | 4 +-
.../opaque_SUITE_data/src/array/array_use.erl | 9 +-
lib/stdlib/src/array.erl | 1391 +++++------------
lib/stdlib/test/array_SUITE.erl | 1211 +++++++-------
5 files changed, 970 insertions(+), 1652 deletions(-)
create mode 100644 lib/dialyzer/test/indent2_SUITE_data/results/arr.license
diff --git a/lib/dialyzer/test/indent2_SUITE_data/results/arr.license b/lib/dialyzer/test/indent2_SUITE_data/results/arr.license
new file mode 100644
index 0000000000..874e3d1e6c
--- /dev/null
+++ b/lib/dialyzer/test/indent2_SUITE_data/results/arr.license
@@ -0,0 +1,7 @@
+%CopyrightBegin%
+
+SPDX-License-Identifier: Apache-2.0
+
+Copyright Ericsson AB 2019-2026. All Rights Reserved.
+
+%CopyrightEnd%
diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/array b/lib/dialyzer/test/opaque_SUITE_data/results/array
index 08bf74c853..f8c7122635 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/results/array
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/array
@@ -1,3 +1,3 @@
-array_use.erl:12:8: The type test is_tuple(array:array(_)) breaks the opacity of the term array:array(_)
-array_use.erl:9:3: The attempt to match a term of type array:array(_) against the pattern {'array', _, _, 'undefined', _} breaks the opacity of the term
+array_use.erl:16:3: The attempt to match a term of type array:array(_) against the pattern {'array', _, _, 'undefined', _} breaks the opacity of the term
+array_use.erl:21:8: The type test is_tuple(array:array(_)) breaks the opacity of the term array:array(_)
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/array/array_use.erl b/lib/dialyzer/test/opaque_SUITE_data/src/array/array_use.erl
index 1702dc8f03..e120cb66bf 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/src/array/array_use.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/array/array_use.erl
@@ -1,3 +1,10 @@
+%% %CopyrightBegin%
+%%
+%% SPDX-License-Identifier: Apache-2.0
+%%
+%% Copyright Ericsson AB 2025. All Rights Reserved.
+%%
+%% %CopyrightEnd%
-module(array_use).
-export([ok1/0, wrong1/0, wrong2/0]).
@@ -6,7 +13,7 @@ ok1() ->
array:set(17, gazonk, array:new()).
wrong1() ->
- {array, _, _, undefined, _} = array:new(42).
+ {array, _, _, _, undefined, _, _, _, _} = array:new(42).
wrong2() ->
case is_tuple(array:new(42)) of
diff --git a/lib/stdlib/src/array.erl b/lib/stdlib/src/array.erl
index 546526fe72..055a75711d 100644
--- a/lib/stdlib/src/array.erl
+++ b/lib/stdlib/src/array.erl
@@ -111,20 +111,8 @@ beyond the last set entry:
-moduledoc(#{ authors => [~"Richard Carlsson <carlsson.richard@gmail.com>",
~"Dan Gudmundsson <dgud@erix.ericsson.se>"] }).
--include_lib("stdlib/include/assert.hrl").
-%%-define(TEST,1).
--ifdef(TEST).
--include_lib("eunit/include/eunit.hrl").
--endif.
-
-
-%% Developers:
-%%
-%% For OTP devs: Both tests and documentation is extracted from this
-%% file, keep and update this file,
-%% test are extracted with array_SUITE:extract_tests().
-%% Doc with docb_gen array.erl
-%%
+%% Developers:
+%%
%% The key to speed is to minimize the number of tests, on
%% large input. Always make the most probable path as short as possible.
%% In particular, keep in mind that for large trees, the probability of
@@ -137,17 +125,17 @@ beyond the last set entry:
%% Representation:
%%
%% A tree is either a leaf, with LEAFSIZE elements (the "base"), an
-%% internal node with LEAFSIZE+1 elements, or an unexpanded tree,
+%% internal node with LEAFSIZE elements, or an unexpanded tree,
%% represented by a single integer: the number of elements that may be
-%% stored in the tree when it is expanded. The last element of an
-%% internal node caches the number of elements that may be stored in
-%% each of its subtrees.
-%%
+%% stored in the tree when it is expanded.
+%%
%% Note that to update an entry in a tree of height h = log[b] n, the
%% total number of written words is (b+1)+(h-1)*(b+2), since tuples use
%% a header word on the heap. 4 is the optimal base for minimizing the
%% number of words written, but causes higher trees, which takes time.
-%% The best compromise between speed and memory usage seems to lie
+%% Current measurements gives a size of 16 as the best.
+%%
+%% Old comment: The best compromise between speed and memory usage seems to lie
%% around 8-10. Measurements indicate that the optimum base for speed is
%% 24 - above that, it gets slower again due to the high memory usage.
%% Base 10 is a good choice, giving 2/3 of the possible speedup from
@@ -155,29 +143,29 @@ beyond the last set entry:
%% per write than base 10, but the speedup is only 21%.)
-define(DEFAULT, undefined).
--define(LEAFSIZE, 10). % the "base" (assumed to be > 1)
--define(NODESIZE, ?LEAFSIZE). % must not be LEAFSIZE-1; keep same as leaf
--define(NODEPATTERN(S), {_,_,_,_,_,_,_,_,_,_,S}). % NODESIZE+1 elements!
--define(NEW_NODE(E,S), % general case (currently unused)
- setelement((?NODESIZE+1),erlang:make_tuple((?NODESIZE+1),(E)),(S))).
--define(NEW_NODE(S), erlang:make_tuple((?NODESIZE+1),(S))). % when E = S
+-define(SHIFT, 4). % log2(LEAFSIZE), for bitwise div operation
+-define(LEAFSIZE, (1 bsl ?SHIFT)). % the "base" (assumed to be > 1)
+-define(MASK, (?LEAFSIZE-1)). % LEAFSIZE - 1, for bitwise rem operation
+-define(MASK(X), ((1 bsl (X))-1)).
+-define(SIZE(M), (1 bsl (M))).
+-define(NODESIZE, ?LEAFSIZE). % must not be LEAFSIZE-1; keep same as leaf
+-define(NEW_NODE(S), erlang:make_tuple((?NODESIZE),(S))). % when E = S
-define(NEW_LEAF(D), erlang:make_tuple(?LEAFSIZE,(D))).
--define(NODELEAFS, ?NODESIZE*?LEAFSIZE).
-define(NEW_CACHE(D), ?NEW_LEAF(D)).
-%% These make the code a little easier to experiment with.
-%% It turned out that using shifts (when NODESIZE=2^n) was not faster.
--define(reduce(X), ((X) div (?NODESIZE))).
--define(extend(X), ((X) * (?NODESIZE))).
+-define(reduce(X), ((X) - ?SHIFT)).
+-define(extend(X), ((X) + ?SHIFT)).
%%--------------------------------------------------------------------------
--type leaf_tuple(T) :: {T, T, T, T, T, T, T, T, T, T}.
+-type leaf_tuple(T) :: {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}.
-type element_tuple(T) ::
leaf_tuple(T)
| {element_tuple(T), element_tuple(T), element_tuple(T),
+ element_tuple(T), element_tuple(T), element_tuple(T),
+ element_tuple(T), element_tuple(T), element_tuple(T),
element_tuple(T), element_tuple(T), element_tuple(T),
element_tuple(T), element_tuple(T), element_tuple(T),
element_tuple(T), non_neg_integer()}.
@@ -193,7 +181,8 @@ beyond the last set entry:
default, %% the default value (usually 'undefined')
cache :: cache(), %% cached leaf tuple
cache_index :: non_neg_integer(),
- elements :: elements(_) %% the tuple tree
+ elements :: elements(_), %% the tuple tree
+ bits :: integer() %% in bits
}).
-type array() :: array(term()).
@@ -335,26 +324,18 @@ new_1(_Options, _Size, _Fixed, _Default) ->
erlang:error(badarg).
new(Size, Fixed, Default) ->
- E = find_max(Size - 1, ?LEAFSIZE),
+ E = find_max(Size - 1, ?SHIFT),
C = ?NEW_CACHE(Default),
#array{size = Size, fix = Fixed, cache = C, cache_index = 0,
- default = Default, elements = E}.
+ default = Default, elements = E, bits = ?reduce(E)}.
-spec find_max(integer(), non_neg_integer()) -> non_neg_integer().
-find_max(I, M) when I >= M ->
+find_max(I, M) when I >= ?SIZE(M) ->
find_max(I, ?extend(M));
find_max(_I, M) ->
M.
--spec get_max(elements(_)) -> non_neg_integer().
-
-get_max(?NODEPATTERN(M)) ->
- ?extend(M);
-get_max(M) when is_integer(M) ->
- M;
-get_max(_) -> ?LEAFSIZE.
-
-doc """
Returns `true` if `X` is an array, otherwise `false`.
@@ -395,79 +376,6 @@ default(#array{default = D}) -> D;
default(_) -> erlang:error(badarg).
--ifdef(EUNIT).
-new_test_() ->
- N0 = ?LEAFSIZE,
- N01 = N0+1,
- N1 = ?NODESIZE*N0,
- N11 = N1+1,
- N2 = ?NODESIZE*N1,
- [?_test(new()),
-
- ?_test(new([])),
- ?_test(new(10)),
- ?_test(new({size,10})),
- ?_test(new(fixed)),
- ?_test(new({fixed,true})),
- ?_test(new({fixed,false})),
- ?_test(new({default,undefined})),
- ?_test(new([{size,100},{fixed,false},{default,undefined}])),
- ?_test(new([100,fixed,{default,0}])),
-
- ?_assert(new() =:= new([])),
- ?_assert(new() =:= new([{size,0},{default,undefined},{fixed,false}])),
- ?_assert(new() =:= new(0, {fixed,false})),
- ?_assert(new(fixed) =:= new(0)),
- ?_assert(new(fixed) =:= new(0, [])),
- ?_assert(new(10) =:= new([{size,0},{size,5},{size,10}])),
- ?_assert(new(10) =:= new(0, {size,10})),
- ?_assert(new(10, []) =:= new(10, [{default,undefined},{fixed,true}])),
-
- ?_assertError(badarg, new(-1)),
- ?_assertError(badarg, new(10.0)),
- ?_assertError(badarg, new(undefined)),
- ?_assertError(badarg, new([undefined])),
- ?_assertError(badarg, new([{default,0} | fixed])),
-
- ?_assertError(badarg, new(-1, [])),
- ?_assertError(badarg, new(10.0, [])),
- ?_assertError(badarg, new(undefined, [])),
-
- ?_assertMatch(#array{size=0,max=N0,default=undefined,elements=N0},
- new()),
- ?_assertMatch(#array{size=0,max=0,default=undefined,elements=N0},
- new(fixed)),
- ?_assertMatch(#array{size=N0,max=N0,elements=N0},
- new(N0, {fixed,false})),
- ?_assertMatch(#array{size=N01,max=N1,elements=N1},
- new(N01, {fixed,false})),
- ?_assertMatch(#array{size=N1,max=N1,elements=N1},
- new(N1, {fixed,false})),
- ?_assertMatch(#array{size=N11,max=N2,elements=N2},
- new(N11, {fixed,false})),
- ?_assertMatch(#array{size=N2, max=N2, default=42,elements=N2},
- new(N2, [{fixed,false},{default,42}])),
-
- ?_assert(0 =:= array:size(new())),
- ?_assert(17 =:= array:size(new(17))),
- ?_assert(100 =:= array:size(array:set(99,0,new()))),
- ?_assertError(badarg, array:size({bad_data,gives_error})),
-
- ?_assert(undefined =:= default(new())),
- ?_assert(4711 =:= default(new({default,4711}))),
- ?_assert(0 =:= default(new(10, {default,0}))),
- ?_assertError(badarg, default({bad_data,gives_error})),
-
- ?_assert(is_array(new())),
- ?_assert(false =:= is_array({foobar, 23, 23})),
- ?_assert(false =:= is_array(#array{size=bad})),
- ?_assert(false =:= is_array(#array{max=bad})),
- ?_assert(is_array(new(10))),
- ?_assert(is_array(new(10, {fixed,false})))
- ].
--endif.
-
-
-doc """
Fixes the array size. This prevents it from growing automatically upon
insertion.
@@ -480,23 +388,21 @@ fix(#array{}=A) ->
A#array{fix = true}.
%% similar to set_1()
-set_leaf(I, E=?NODEPATTERN(S), C) ->
- I1 = I div S + 1,
- setelement(I1, E, set_leaf(I rem S, element(I1, E), C));
-set_leaf(I, E, C) when is_integer(E) ->
- set_leaf_1(I, E, C);
-set_leaf(_I, _E, C) ->
- C.
-
-%% similar to expand()
-set_leaf_1(I, S, C) when S > ?LEAFSIZE ->
- S1 = ?reduce(S),
- setelement(I div S1 + 1, ?NEW_NODE(S1),
- set_leaf_1(I rem S1, S1, C));
+set_leaf(_I, 0, _E, C) ->
+ C;
+set_leaf(I, S, E, C) when is_integer(E) ->
+ set_leaf_1(I, S, C);
+set_leaf(I, S, E, C) when S > 0 ->
+ IDiv = (I bsr S) band ?MASK,
+ I1 = IDiv+1,
+ setelement(I1, E, set_leaf(I, ?reduce(S), element(I1, E), C)).
+
+set_leaf_1(I, S, C) when S > 0 ->
+ IDiv = (I bsr S) band ?MASK,
+ setelement(IDiv+1, ?NEW_NODE(S), set_leaf_1(I, ?reduce(S), C));
set_leaf_1(_I, _S, C) ->
C.
-
-doc """
Checks if the array has fixed size. Returns `true` if the array is fixed,
otherwise `false`.
@@ -509,34 +415,6 @@ is_fix(#array{fix = true}) -> true;
is_fix(#array{}) -> false.
--ifdef(EUNIT).
-fix_test_() ->
- [?_assert(is_array(fix(new()))),
- ?_assert(fix(new()) =:= new(fixed)),
-
- ?_assertNot(is_fix(new())),
- ?_assertNot(is_fix(new([]))),
- ?_assertNot(is_fix(new({fixed,false}))),
- ?_assertNot(is_fix(new(10, {fixed,false}))),
- ?_assert(is_fix(new({fixed,true}))),
- ?_assert(is_fix(new(fixed))),
- ?_assert(is_fix(new(10))),
- ?_assert(is_fix(new(10, []))),
- ?_assert(is_fix(new(10, {fixed,true}))),
- ?_assert(is_fix(fix(new()))),
- ?_assert(is_fix(fix(new({fixed,false})))),
-
- ?_test(set(0, 17, new())),
- ?_assertError(badarg, set(0, 17, new(fixed))),
- ?_assertError(badarg, set(1, 42, fix(set(0, 17, new())))),
-
- ?_test(set(9, 17, new(10))),
- ?_assertError(badarg, set(10, 17, new(10))),
- ?_assertError(badarg, set(10, 17, fix(new(10, {fixed,false}))))
- ].
--endif.
-
-
-doc """
Makes the array resizable. (Reverses the effects of `fix/1`.)
@@ -544,35 +422,18 @@ See also `fix/1`.
""".
-spec relax(Array :: array(Type)) -> array(Type).
-relax(#array{size = N, elements = E, default = D}=A) when is_integer(N), N >= 0 ->
- CI = 0,
- C = get_leaf(CI, E, D),
- A#array{fix = false, cache = C, cache_index = CI}.
+relax(#array{size = N}=A) when is_integer(N), N >= 0 ->
+ A#array{fix = false}.
+
%% similar to get_1
-get_leaf(I, E=?NODEPATTERN(S), D) ->
- get_leaf(I rem S, element(I div S + 1, E), D);
-get_leaf(_I, E, D) when is_integer(E) ->
+get_leaf(_I, _, E, D) when is_integer(E) ->
?NEW_CACHE(D);
-get_leaf(_I, E, _D) ->
- E.
-
-
-
--ifdef(EUNIT).
-relax_test_() ->
- [?_assert(is_array(relax(new(fixed)))),
- ?_assertNot(is_fix(relax(fix(new())))),
- ?_assertNot(is_fix(relax(new(fixed)))),
-
- ?_assert(new() =:= relax(new(fixed))),
- ?_assert(new() =:= relax(new(0))),
- ?_assert(new(17, {fixed,false}) =:= relax(new(17))),
- ?_assert(new(100, {fixed,false})
- =:= relax(fix(new(100, {fixed,false}))))
- ].
--endif.
-
+get_leaf(_I, 0, E, _D) ->
+ E;
+get_leaf(I, S, E, D) ->
+ IDiv = (I bsr S) band ?MASK,
+ get_leaf(I, ?reduce(S), element(IDiv + 1, E), D).
-doc """
Change the array size.
@@ -583,18 +444,18 @@ the specified array has fixed size, also the resulting array has fixed size.
-spec resize(Size :: non_neg_integer(), Array :: array(Type)) ->
array(Type).
-resize(Size, #array{size = N, fix = Fix, cache = C, cache_index = CI, elements = E, default = D}=A)
- when is_integer(Size), Size >= 0,
- is_integer(N), N >= 0,
- is_boolean(Fix) ->
+resize(Size, #array{size = N, fix = Fix, cache = C, cache_index = CI, elements = E, default = D, bits = S}=A)
+ when is_integer(Size), Size >= 0, is_integer(N), N >= 0,
+ is_boolean(Fix), is_integer(CI), is_integer(S) ->
if Size > N ->
- A#array{size = Size, elements = grow(Size-1, E, get_max(E))};
+ {E1, S1} = grow(Size-1, E, S),
+ A#array{size = Size, elements = E1, bits = S1};
Size < N ->
- E1 = set_leaf(CI, E, C),
- E2 = shrink(Size-1, E1, D),
+ E1 = set_leaf(CI, S, E, C),
+ {E2, S1} = shrink(Size-1, S, E1, D),
CI1 = 0,
- C1 = get_leaf(CI1, E2, D),
- A#array{size = Size, elements = E2, cache = C1, cache_index = CI1};
+ C1 = get_leaf(CI1, S1, E2, D),
+ A#array{size = Size, elements = E2, cache = C1, cache_index = CI1, bits = S1};
true ->
A
end;
@@ -602,38 +463,51 @@ resize(_Size, _) ->
erlang:error(badarg).
%% like grow(), but only used when explicitly resizing down
-shrink(I, _E, D) when I < 0 ->
- ?NEW_LEAF(D);
-shrink(I, E, _D) when is_integer(E) ->
- find_max(I, ?LEAFSIZE);
-shrink(I, E, D) ->
- shrink_1(I, E, D).
+shrink(I, _S, _E, _D) when I < 0 ->
+ S = find_max(I, ?SHIFT),
+ {S, ?reduce(S)};
+shrink(I, S, E, D) ->
+ shrink_1(I, S, E, D).
%% I is the largest index, 0 or more (empty arrays handled above)
-shrink_1(I, E=?NODEPATTERN(S), D) when I < S ->
- shrink_1(I rem S, element(1, E), D);
-shrink_1(I, E=?NODEPATTERN(S), D) ->
- E1 = prune(E, I div S, ?NODESIZE, S),
- I1 = I div S + 1,
- case element(I1, E1) of
- E2 when is_integer(E2) ->
- E1;
- E2 ->
- setelement(I1, E1, shrink_1(I rem S, E2, D))
- end;
-shrink_1(I, E, D) ->
- prune(E, I, ?LEAFSIZE, D).
-
-%% the M limiter is needed for the extra data at the end of nodes
-prune(E, N, M, D) ->
- list_to_tuple(prune(0, N, M, D, tuple_to_list(E))).
+%% This first discards any unnecessary tuples from the top
+shrink_1(I, _S, E, _D) when is_integer(E) ->
+ S = find_max(I, ?SHIFT),
+ {S, ?reduce(S)};
+shrink_1(I, 0, E, D) ->
+ {prune(E, I, D), 0};
+shrink_1(I, S, E, D) when I < ?SIZE(S) ->
+ shrink_1(I, ?reduce(S), element(1, E), D);
+shrink_1(I, S, E, D) ->
+ shrink_2(I, S, E, D).
+
+%% Here we have at least one top tuple that should be kept
+%% and we must not discard any intermediate levels
+shrink_2(_I, S, E, _D) when is_integer(E) ->
+ {E, S};
+shrink_2(I, 0, E, D) ->
+ {prune(E, I, D), 0};
+shrink_2(I, S, E, D) ->
+ IDiv = I bsr S,
+ IRem = I band ?MASK(S),
+ E1 = prune(E, IDiv, S),
+ I1 = IDiv + 1,
+ {E2,_} = shrink_2(IRem, ?reduce(S), element(I1, E1), D),
+ {setelement(I1, E1, E2), S}.
+
+prune(E, N, D) when is_tuple(E) ->
+ if N < tuple_size(E) - 1 ->
+ list_to_tuple(prune(0, N, D, tuple_to_list(E)));
+ true ->
+ E
+ end.
-prune(I, N, M, D, [E|Es]) when I =< N ->
- [E | prune(I+1, N, M, D, Es)];
-prune(I, N, M, D, [_|Es]) when I < M ->
- [D | prune(I+1, N, M, D, Es)];
-prune(_I, _N, _M, _D, Es) ->
- Es.
+prune(I, N, D, [E|Es]) when I =< N ->
+ [E | prune(I+1, N, D, Es)];
+prune(I, N, D, [_|Es]) ->
+ [D | prune(I+1, N, D, Es)];
+prune(_I, _N, _D, []) ->
+ [].
-doc """
@@ -647,41 +521,6 @@ See also `resize/2`, `sparse_size/1`.
resize(Array) ->
resize(sparse_size(Array), Array).
-
--ifdef(EUNIT).
-resize_test_() ->
- [?_assert(resize(0, new()) =:= new()),
- ?_assert(resize(99, new(99)) =:= new(99)),
- ?_assert(resize(99, relax(new(99))) =:= relax(new(99))),
- ?_assert(is_fix(resize(100, new(10)))),
- ?_assertNot(is_fix(resize(100, relax(new(10))))),
-
- ?_assert(array:size(resize(100, new())) =:= 100),
- ?_assert(array:size(resize(0, new(100))) =:= 0),
- ?_assert(array:size(resize(99, new(10))) =:= 99),
- ?_assert(array:size(resize(99, new(1000))) =:= 99),
-
- ?_assertError(badarg, set(99, 17, new(10))),
- ?_test(set(99, 17, resize(100, new(10)))),
- ?_assertError(badarg, set(100, 17, resize(100, new(10)))),
-
- ?_assert(array:size(resize(new())) =:= 0),
- ?_assert(array:size(resize(new(8))) =:= 0),
- ?_assert(array:size(resize(array:set(7, 0, new()))) =:= 8),
- ?_assert(array:size(resize(array:set(7, 0, new(10)))) =:= 8),
- ?_assert(array:size(resize(array:set(99, 0, new(10,{fixed,false}))))
- =:= 100),
- ?_assert(array:size(resize(array:set(7, undefined, new()))) =:= 0),
- ?_assert(array:size(resize(array:from_list([1,2,3,undefined])))
- =:= 3),
- ?_assert(array:size(
- resize(array:from_orddict([{3,0},{17,0},{99,undefined}])))
- =:= 18),
- ?_assertError(badarg, resize(foo, bad_argument))
- ].
--endif.
-
-
-doc """
Sets entry `I` of the array to `Value`.
@@ -695,29 +534,30 @@ See also `get/2`, `reset/2`.
""".
-spec set(I :: array_indx(), Value :: Type, Array :: array(Type)) -> array(Type).
-set(I, Value, #array{size = N, fix = Fix, cache = C, cache_index = CI, default = D, elements = E}=A)
- when is_integer(I), I >= 0, is_integer(N), is_boolean(Fix) ->
+set(I, Value, #array{size = N, fix = Fix, cache = C, cache_index = CI,
+ default = D, elements = E, bits = S}=A)
+ when is_integer(I), I >= 0, is_integer(N), is_integer(CI), is_integer(S) ->
if I < N ->
if I >= CI, I < CI + ?LEAFSIZE ->
A#array{cache = setelement(1 + I - CI, C, Value)};
true ->
- R = I rem ?LEAFSIZE,
+ R = I band ?MASK,
CI1 = I - R,
- E1 = set_leaf(CI, E, C),
- C1 = get_leaf(CI1, E1, D),
+ E1 = set_leaf(CI, S, E, C),
+ C1 = get_leaf(CI1, S, E1, D),
C2 = setelement(1 + I - CI1, C1, Value),
A#array{elements = E1, cache = C2, cache_index = CI1}
end;
Fix ->
erlang:error(badarg);
true ->
- M = get_max(E),
+ M = ?SIZE(?extend(S)),
if I < M ->
- R = I rem ?LEAFSIZE,
+ R = I band ?MASK,
CI1 = I - R,
if CI1 =/= CI ->
- E1 = set_leaf(CI, E, C),
- C1 = get_leaf(CI1, E1, D),
+ E1 = set_leaf(CI, S, E, C),
+ C1 = get_leaf(CI1, S, E1, D),
C2 = setelement(1 + R, C1, Value),
A#array{size = I+1, elements = E1,
cache = C2, cache_index = CI1};
@@ -726,51 +566,37 @@ set(I, Value, #array{size = N, fix = Fix, cache = C, cache_index = CI, default =
A#array{size = I+1, cache = C1, cache_index = CI1}
end;
true ->
- E1 = grow(I, E, M),
- E2 = set_leaf(CI, E1, C),
- R = I rem ?LEAFSIZE,
+ R = I band ?MASK,
CI1 = I - R,
- C1 = get_leaf(CI1, E2, D),
+ {E1,S1} = grow(I, E, S),
+ E2 = set_leaf(CI, S1, E1, C),
+ C1 = get_leaf(CI1, S1, E2, D),
C2 = setelement(1 + R, C1, Value),
A#array{size = I+1, elements = E2,
- cache = C2, cache_index = CI1}
+ cache = C2, cache_index = CI1, bits = S1}
end
end;
set(_I, _V, _A) ->
erlang:error(badarg).
-%% Currently unused because set_leaf() handles all tree updates
-%% %% See get_1/3 for details about switching and the NODEPATTERN macro.
-%% set_1(I, E=?NODEPATTERN(S), X, D) ->
-%% I1 = I div S + 1,
-%% setelement(I1, E, set_1(I rem S, element(I1, E), X, D));
-%% set_1(I, E, X, D) when is_integer(E) ->
-%% expand(I, E, X, D);
-%% set_1(I, E, X, _D) ->
-%% setelement(I+1, E, X).
-
-
-%% %% Insert an element in an unexpanded node, expanding it as necessary.
-%% expand(I, S, X, D) when S > ?LEAFSIZE ->
-%% S1 = ?reduce(S),
-%% setelement(I div S1 + 1, ?NEW_NODE(S1),
-%% expand(I rem S1, S1, X, D));
-%% expand(I, _S, X, D) ->
-%% setelement(I+1, ?NEW_LEAF(D), X).
-
-
%% Enlarging the array upwards to accommodate an index `I'
-grow(I, E, _M) when is_integer(I), is_integer(E) ->
- find_max(I, E);
+grow(I, E, M) when is_integer(I), is_integer(E) ->
+ S = find_max(I, M),
+ {S, ?reduce(S)};
+grow(I, E, 0) ->
+ grow_1(I, E, 0);
grow(I, E, M) ->
grow_1(I, E, M).
-grow_1(I, E, M) when I >= M ->
- grow_1(I, setelement(1, ?NEW_NODE(M), E), ?extend(M));
-grow_1(_I, E, _M) ->
- E.
-
+grow_1(I, E, M0) ->
+ M = ?extend(M0),
+ case I >= ?SIZE(M) of
+ true ->
+ grow_1(I, setelement(1, ?NEW_NODE(M), E), M);
+ false ->
+ {E, M0}
+ end.
-doc """
Gets the value of entry `I`.
@@ -785,13 +611,13 @@ See also `set/3`.
""".
-spec get(I :: array_indx(), Array :: array(Type)) -> Value :: Type.
-get(I, #array{size = N, fix = Fix, cache = C, cache_index = CI, elements = E, default = D})
- when is_integer(I), I >= 0, is_integer(N), is_boolean(Fix) ->
+get(I, #array{size = N, fix = Fix, cache = C, cache_index = CI, elements = E, default = D, bits = S})
+ when is_integer(I), I >= 0, is_integer(N), is_integer(CI), is_integer(S) ->
if I < N ->
if I >= CI, I < CI + ?LEAFSIZE ->
element(1 + I - CI, C);
true ->
- get_1(I, E, D)
+ get_1(I, S, E, D)
end;
Fix ->
erlang:error(badarg);
@@ -801,17 +627,13 @@ get(I, #array{size = N, fix = Fix, cache = C, cache_index = CI, elements = E, de
get(_I, _A) ->
erlang:error(badarg).
-%% The use of NODEPATTERN(S) to select the right clause is just a hack,
-%% but it is the only way to get the maximum speed out of this loop
-%% (using the Beam compiler in OTP 11).
-
-get_1(I, E=?NODEPATTERN(S), D) ->
- get_1(I rem S, element(I div S + 1, E), D);
-get_1(_I, E, D) when is_integer(E) ->
+get_1(_I, _S, E, D) when is_integer(E) ->
D;
-get_1(I, E, _D) ->
- element(I+1, E).
-
+get_1(I, 0, E, _D) ->
+ element((I band ?MASK)+1, E);
+get_1(I, S, E, D) ->
+ IDiv = (I bsr S) band ?MASK,
+ get_1(I, ?reduce(S), element(IDiv + 1, E), D).
%% TODO: a reset_range function
@@ -830,13 +652,13 @@ See also `new/2`, `set/3`.
""".
-spec reset(I :: array_indx(), Array :: array(Type)) -> array(Type).
-reset(I, #array{size = N, fix = Fix, cache = C, cache_index = CI, default = D, elements = E}=A)
- when is_integer(I), I >= 0, is_integer(N), is_boolean(Fix) ->
+reset(I, #array{size = N, fix = Fix, cache = C, cache_index = CI, default = D, elements = E, bits = S}=A)
+ when is_integer(I), I >= 0, is_integer(N), is_boolean(Fix), is_integer(CI) ->
if I < N ->
if I >= CI, I < CI + ?LEAFSIZE ->
A#array{cache = setelement(1 + I - CI, C, D)};
true ->
- try A#array{elements = reset_1(I, E, D)}
+ try A#array{elements = reset_1(I, S, E, D)}
catch throw:default -> A
end
end;
@@ -848,70 +670,18 @@ reset(I, #array{size = N, fix = Fix, cache = C, cache_index = CI, default = D, e
reset(_I, _A) ->
erlang:error(badarg).
-reset_1(I, E=?NODEPATTERN(S), D) ->
- I1 = I div S + 1,
- setelement(I1, E, reset_1(I rem S, element(I1, E), D));
-reset_1(_I, E, _D) when is_integer(E) ->
+reset_1(_I, _, E, _D) when is_integer(E) ->
throw(default);
-reset_1(I, E, D) ->
- Indx = I+1,
+reset_1(I, 0, E, D) ->
+ Indx = (I band ?MASK)+1,
case element(Indx, E) of
D -> throw(default);
- _ -> setelement(I+1, E, D)
- end.
-
-
--ifdef(EUNIT).
-set_get_test_() ->
- N0 = ?LEAFSIZE,
- N1 = ?NODESIZE*N0,
- [?_assert(array:get(0, new()) =:= undefined),
- ?_assert(array:get(1, new()) =:= undefined),
- ?_assert(array:get(99999, new()) =:= undefined),
-
- ?_assert(array:get(0, new(1)) =:= undefined),
- ?_assert(array:get(0, new(1,{default,0})) =:= 0),
- ?_assert(array:get(9, new(10)) =:= undefined),
-
- ?_assertError(badarg, array:get(0, new(fixed))),
- ?_assertError(badarg, array:get(1, new(1))),
- ?_assertError(badarg, array:get(-1, new(1))),
- ?_assertError(badarg, array:get(10, new(10))),
- ?_assertError(badarg, array:set(-1, foo, new(10))),
- ?_assertError(badarg, array:set(10, foo, no_array)),
-
- ?_assert(array:size(set(0, 17, new())) =:= 1),
- ?_assert(array:size(set(N1-1, 17, new())) =:= N1),
- ?_assert(array:size(set(0, 42, set(0, 17, new()))) =:= 1),
- ?_assert(array:size(set(9, 42, set(0, 17, new()))) =:= 10),
-
- ?_assert(array:get(0, set(0, 17, new())) =:= 17),
- ?_assert(array:get(0, set(1, 17, new())) =:= undefined),
- ?_assert(array:get(1, set(1, 17, new())) =:= 17),
-
- ?_assert(array:get(0, fix(set(0, 17, new()))) =:= 17),
- ?_assertError(badarg, array:get(1, fix(set(0, 17, new())))),
-
- ?_assert(array:get(N1-2, set(N1-1, 17, new())) =:= undefined),
- ?_assert(array:get(N1-1, set(N1-1, 17, new())) =:= 17),
- ?_assertError(badarg, array:get(N1, fix(set(N1-1, 17, new())))),
-
- ?_assert(array:get(0, set(0, 42, set(0, 17, new()))) =:= 42),
-
- ?_assertError(badarg, array:get(0, reset(11, new([{size,10}])))),
- ?_assertError(badarg, array:get(0, reset(-1, new([{size,10}])))),
- ?_assert(array:get(0, reset(0, new())) =:= undefined),
- ?_assert(array:get(0, reset(0, set(0, 17, new()))) =:= undefined),
- ?_assert(array:get(0, reset(9, set(9, 17, new()))) =:= undefined),
- ?_assert(array:get(0, reset(11, set(11, 17, new()))) =:= undefined),
- ?_assert(array:get(0, reset(11, set(12, 17, new()))) =:= undefined),
- ?_assert(array:get(0, reset(1, set(12, 17, new()))) =:= undefined),
- ?_assert(array:get(0, reset(11, new())) =:= undefined),
- ?_assert(array:get(0, reset(0, set(0, 17, new({default,42})))) =:= 42),
- ?_assert(array:get(0, reset(0, new({default,42}))) =:= 42)
- ].
--endif.
-
+ _ -> setelement(Indx, E, D)
+ end;
+reset_1(I, S, E, D) ->
+ IDiv = (I bsr S) band ?MASK,
+ I1 = IDiv + 1,
+ setelement(I1, E, reset_1(I, ?reduce(S), element(I1, E), D)).
-doc """
Converts the array to a list.
@@ -922,35 +692,37 @@ See also `from_list/2`, `sparse_to_list/1`.
to_list(#array{size = 0}) ->
[];
-to_list(#array{size = N, cache = C, cache_index = CI, elements = E, default = D}) when is_integer(N) ->
- E1 = set_leaf(CI, E, C),
- to_list_1(E1, D, N - 1);
+to_list(#array{size = N, cache = C, cache_index = CI, elements = E, default = D, bits = M})
+ when is_integer(N), is_integer(CI), is_integer(M) ->
+ E1 = set_leaf(CI, M, E, C),
+ to_list_1(E1, M, D, N - 1);
to_list(_) ->
erlang:error(badarg).
%% this part handles the rightmost subtrees
-to_list_1(E=?NODEPATTERN(S), D, I) ->
- N = I div S,
- to_list_3(N, D, to_list_1(element(N+1, E), D, I rem S), E);
-to_list_1(E, D, I) when is_integer(E) ->
+to_list_1(E, _S, D, I) when is_integer(E) ->
push(I+1, D, []);
-to_list_1(E, _D, I) ->
- push_tuple(I+1, E, []).
+to_list_1(E, 0, _D, I) ->
+ push_tuple(I+1, E, []);
+to_list_1(E, S, D, I) ->
+ N = I bsr S,
+ IRem = I band ?MASK(S),
+ to_list_3(N, S, D, to_list_1(element(N+1, E), ?reduce(S), D, IRem), E).
%% this part handles full trees only
-to_list_2(E=?NODEPATTERN(_S), D, L) ->
- to_list_3(?NODESIZE, D, L, E);
-to_list_2(E, D, L) when is_integer(E) ->
- push(E, D, L);
-to_list_2(E, _D, L) ->
- push_tuple(?LEAFSIZE, E, L).
+to_list_2(E, _S, D, L) when is_integer(E) ->
+ push(?SIZE(E), D, L);
+to_list_2(E, 0, _D, L) ->
+ push_tuple(?LEAFSIZE, E, L);
+to_list_2(E, S, D, L) ->
+ to_list_3(?NODESIZE, S, D, L, E).
-to_list_3(0, _D, L, _E) ->
+to_list_3(0, _S, _D, L, _E) ->
L;
-to_list_3(N, D, L, E) ->
- to_list_3(N-1, D, to_list_2(element(N, E), D, L), E).
+to_list_3(N, S, D, L, E) ->
+ to_list_3(N-1, S, D, to_list_2(element(N, E), ?reduce(S), D, L), E).
push(0, _E, L) ->
L;
@@ -962,32 +734,6 @@ push_tuple(0, _T, L) ->
push_tuple(N, T, L) ->
push_tuple(N - 1, T, [element(N, T) | L]).
-
--ifdef(EUNIT).
-to_list_test_() ->
- N0 = ?LEAFSIZE,
- [?_assert([] =:= to_list(new())),
- ?_assert([undefined] =:= to_list(new(1))),
- ?_assert([undefined,undefined] =:= to_list(new(2))),
- ?_assert(lists:duplicate(N0,0) =:= to_list(new(N0,{default,0}))),
- ?_assert(lists:duplicate(N0+1,1) =:= to_list(new(N0+1,{default,1}))),
- ?_assert(lists:duplicate(N0+2,2) =:= to_list(new(N0+2,{default,2}))),
- ?_assert(lists:duplicate(666,6) =:= to_list(new(666,{default,6}))),
- ?_assert([1,2,3] =:= to_list(set(2,3,set(1,2,set(0,1,new()))))),
- ?_assert([3,2,1] =:= to_list(set(0,3,set(1,2,set(2,1,new()))))),
- ?_assert([1|lists:duplicate(N0-2,0)++[1]] =:=
- to_list(set(N0-1,1,set(0,1,new({default,0}))))),
- ?_assert([1|lists:duplicate(N0-1,0)++[1]] =:=
- to_list(set(N0,1,set(0,1,new({default,0}))))),
- ?_assert([1|lists:duplicate(N0,0)++[1]] =:=
- to_list(set(N0+1,1,set(0,1,new({default,0}))))),
- ?_assert([1|lists:duplicate(N0*3,0)++[1]] =:=
- to_list(set((N0*3)+1,1,set(0,1,new({default,0}))))),
- ?_assertError(badarg, to_list(no_array))
- ].
--endif.
-
-
-doc """
Converts the array to a list, skipping default-valued entries.
@@ -997,35 +743,37 @@ See also `to_list/1`.
sparse_to_list(#array{size = 0}) ->
[];
-sparse_to_list(#array{size = N, cache = C, cache_index = CI, elements = E, default = D}) when is_integer(N) ->
- E1 = set_leaf(CI, E, C),
- sparse_to_list_1(E1, D, N - 1);
+sparse_to_list(#array{size = N, cache = C, cache_index = CI, elements = E, default = D, bits = M})
+ when is_integer(N), is_integer(CI), is_integer(M) ->
+ E1 = set_leaf(CI, M, E, C),
+ sparse_to_list_1(E1, M, D, N - 1);
sparse_to_list(_) ->
erlang:error(badarg).
%% see to_list/1 for details
-sparse_to_list_1(E=?NODEPATTERN(S), D, I) ->
- N = I div S,
- sparse_to_list_3(N, D,
- sparse_to_list_1(element(N+1, E), D, I rem S),
- E);
-sparse_to_list_1(E, _D, _I) when is_integer(E) ->
+sparse_to_list_1(E, _S, _D, _I) when is_integer(E) ->
[];
-sparse_to_list_1(E, D, I) ->
- sparse_push_tuple(I+1, D, E, []).
-
-sparse_to_list_2(E=?NODEPATTERN(_S), D, L) ->
- sparse_to_list_3(?NODESIZE, D, L, E);
-sparse_to_list_2(E, _D, L) when is_integer(E) ->
+sparse_to_list_1(E, 0, D, I) ->
+ sparse_push_tuple(I+1, D, E, []);
+sparse_to_list_1(E, S, D, I) ->
+ N = I bsr S,
+ IRem = I band ?MASK(S),
+ sparse_to_list_3(N, S, D,
+ sparse_to_list_1(element(N+1, E), ?reduce(S), D, IRem),
+ E).
+
+sparse_to_list_2(E, _S, _D, L) when is_integer(E) ->
L;
-sparse_to_list_2(E, D, L) ->
- sparse_push_tuple(?LEAFSIZE, D, E, L).
+sparse_to_list_2(E, 0, D, L) ->
+ sparse_push_tuple(?LEAFSIZE, D, E, L);
+sparse_to_list_2(E, S, D, L) ->
+ sparse_to_list_3(?NODESIZE, S, D, L, E).
-sparse_to_list_3(0, _D, L, _E) ->
+sparse_to_list_3(0, _S, _D, L, _E) ->
L;
-sparse_to_list_3(N, D, L, E) ->
- sparse_to_list_3(N-1, D, sparse_to_list_2(element(N, E), D, L), E).
+sparse_to_list_3(N, S, D, L, E) ->
+ sparse_to_list_3(N-1, S, D, sparse_to_list_2(element(N, E), ?reduce(S), D, L), E).
sparse_push_tuple(0, _D, _T, L) ->
L;
@@ -1035,30 +783,6 @@ sparse_push_tuple(N, D, T, L) ->
E -> sparse_push_tuple(N - 1, D, T, [E | L])
end.
-
--ifdef(EUNIT).
-sparse_to_list_test_() ->
- N0 = ?LEAFSIZE,
- [?_assert([] =:= sparse_to_list(new())),
- ?_assert([] =:= sparse_to_list(new(1))),
- ?_assert([] =:= sparse_to_list(new(1,{default,0}))),
- ?_assert([] =:= sparse_to_list(new(2))),
- ?_assert([] =:= sparse_to_list(new(2,{default,0}))),
- ?_assert([] =:= sparse_to_list(new(N0,{default,0}))),
- ?_assert([] =:= sparse_to_list(new(N0+1,{default,1}))),
- ?_assert([] =:= sparse_to_list(new(N0+2,{default,2}))),
- ?_assert([] =:= sparse_to_list(new(666,{default,6}))),
- ?_assert([1,2,3] =:= sparse_to_list(set(2,3,set(1,2,set(0,1,new()))))),
- ?_assert([3,2,1] =:= sparse_to_list(set(0,3,set(1,2,set(2,1,new()))))),
- ?_assert([0,1] =:= sparse_to_list(set(N0-1,1,set(0,0,new())))),
- ?_assert([0,1] =:= sparse_to_list(set(N0,1,set(0,0,new())))),
- ?_assert([0,1] =:= sparse_to_list(set(N0+1,1,set(0,0,new())))),
- ?_assert([0,1,2] =:= sparse_to_list(set(N0*10+1,2,set(N0*2+1,1,set(0,0,new()))))),
- ?_assertError(badarg, sparse_to_list(no_array))
- ].
--endif.
-
-
%% @equiv from_list(List, undefined)
-doc "Equivalent to [`from_list(List, undefined)`](`from_list/2`).".
@@ -1080,10 +804,12 @@ See also `new/2`, `to_list/1`.
from_list([], Default) ->
new({default,Default});
from_list(List, Default) when is_list(List) ->
- {E, N, _M} = from_list_1(?LEAFSIZE, List, Default, 0, [], []),
+ {E, N, M0} = from_list_1(?LEAFSIZE, List, Default, 0, [], []),
CI = 0,
- C = get_leaf(CI, E, Default),
- #array{size = N, fix = false, cache = C, cache_index = CI, default = Default, elements = E};
+ M = ?reduce(M0),
+ C = get_leaf(CI, M, E, Default),
+ #array{size = N, fix = false, cache = C, cache_index = CI,
+ default = Default, elements = E, bits = M};
from_list(_, _) ->
erlang:error(badarg).
@@ -1100,9 +826,9 @@ from_list_1(0, Xs, D, N, As, Es) ->
[] ->
case Es of
[] ->
- {E, N, ?LEAFSIZE};
+ {E, N, ?SHIFT};
_ ->
- from_list_2_0(N, [E | Es], ?LEAFSIZE)
+ from_list_2_0(N, [E | Es], ?SHIFT)
end;
[_|_] ->
from_list_1(?LEAFSIZE, Xs, D, N, [], [E | Es]);
@@ -1119,8 +845,8 @@ from_list_1(I, Xs, D, N, As, Es) ->
%% Building the internal nodes (note that the input is reversed).
from_list_2_0(N, Es, S) ->
- from_list_2(?NODESIZE, pad((N-1) div S + 1, ?NODESIZE, S, Es),
- S, N, [S], []).
+ from_list_2(?NODESIZE, pad(((N-1) bsr S) + 1, ?NODESIZE, S, Es),
+ S, N, [], []).
from_list_2(0, Xs, S, N, As, Es) ->
E = list_to_tuple(As),
@@ -1134,7 +860,7 @@ from_list_2(0, Xs, S, N, As, Es) ->
?extend(S))
end;
_ ->
- from_list_2(?NODESIZE, Xs, S, N, [S], [E | Es])
+ from_list_2(?NODESIZE, Xs, S, N, [], [E | Es])
end;
from_list_2(I, [X | Xs], S, N, As, Es) ->
from_list_2(I-1, Xs, S, N, [X | As], Es).
@@ -1146,31 +872,6 @@ pad(N, K, P, Es) ->
push((K - (N rem K)) rem K, P, Es).
--ifdef(EUNIT).
-from_list_test_() ->
- N0 = ?LEAFSIZE,
- N1 = ?NODESIZE*N0,
- N2 = ?NODESIZE*N1,
- N3 = ?NODESIZE*N2,
- N4 = ?NODESIZE*N3,
- [?_assert(array:size(from_list([])) =:= 0),
- ?_assert(array:is_fix(from_list([])) =:= false),
- ?_assert(array:size(from_list([undefined])) =:= 1),
- ?_assert(array:is_fix(from_list([undefined])) =:= false),
- ?_assert(array:size(from_list(lists:seq(1,N1))) =:= N1),
- ?_assert(to_list(from_list(lists:seq(1,N0))) =:= lists:seq(1,N0)),
- ?_assert(to_list(from_list(lists:seq(1,N0+1))) =:= lists:seq(1,N0+1)),
- ?_assert(to_list(from_list(lists:seq(1,N0+2))) =:= lists:seq(1,N0+2)),
- ?_assert(to_list(from_list(lists:seq(1,N2))) =:= lists:seq(1,N2)),
- ?_assert(to_list(from_list(lists:seq(1,N2+1))) =:= lists:seq(1,N2+1)),
- ?_assert(to_list(from_list(lists:seq(0,N3))) =:= lists:seq(0,N3)),
- ?_assert(to_list(from_list(lists:seq(0,N4))) =:= lists:seq(0,N4)),
- ?_assertError(badarg, from_list([a,b,a,c|d])),
- ?_assertError(badarg, from_list(no_array))
- ].
--endif.
-
-
-doc "Equivalent to [`from(Fun, State, undefined)`](`from/3`).".
-doc(#{since => <<"OTP 29.0">>}).
-spec from(Function, State :: term()) -> array(Type) when
@@ -1219,10 +920,12 @@ See also `new/2`, `from_list/1`, `foldl/3`.
from(Fun, S0, Default) when is_function(Fun, 1) ->
VS = Fun(S0),
- {E, N, _M} = from_fun_1(?LEAFSIZE, Default, Fun, VS, 0, [], []),
+ {E, N, M0} = from_fun_1(?LEAFSIZE, Default, Fun, VS, 0, [], []),
CI = 0,
- C = get_leaf(CI, E, Default),
- #array{size = N, fix = false, cache = C, cache_index = CI, default = Default, elements = E};
+ M = ?reduce(M0),
+ C = get_leaf(CI, M, E, Default),
+ #array{size = N, fix = false, cache = C, cache_index = CI,
+ default = Default, elements = E, bits = M};
from(_, _, _) ->
error(badarg).
@@ -1233,9 +936,9 @@ from_fun_1(0, D, Fun, VS, N, As, Es) ->
done ->
case Es of
[] ->
- {E, N, ?LEAFSIZE};
+ {E, N, ?SHIFT};
_ ->
- from_list_2_0(N, [E | Es], ?LEAFSIZE)
+ from_list_2_0(N, [E | Es], ?SHIFT)
end;
_ ->
from_fun_1(?LEAFSIZE, D, Fun, VS, N, [], [E | Es])
@@ -1257,38 +960,39 @@ See also `from_orddict/2`, `sparse_to_orddict/1`.
to_orddict(#array{size = 0}) ->
[];
-to_orddict(#array{size = N, cache = C, cache_index = CI, elements = E, default = D}) when is_integer(N) ->
- E1 = set_leaf(CI, E, C),
+to_orddict(#array{size = N, cache = C, cache_index = CI, elements = E, default = D, bits = M})
+ when is_integer(N), is_integer(CI), is_integer(M) ->
+ E1 = set_leaf(CI, M, E, C),
I = N - 1,
- to_orddict_1(E1, I, D, I);
+ to_orddict_1(E1, I, D, I, M);
to_orddict(_) ->
erlang:error(badarg).
%% see to_list/1 for comparison
-to_orddict_1(E=?NODEPATTERN(S), R, D, I) ->
- N = I div S,
- I1 = I rem S,
- to_orddict_3(N, R - I1 - 1, D,
- to_orddict_1(element(N+1, E), R, D, I1),
- E, S);
-to_orddict_1(E, R, D, I) when is_integer(E) ->
+to_orddict_1(E, R, D, I, _S) when is_integer(E) ->
push_pairs(I+1, R, D, []);
-to_orddict_1(E, R, _D, I) ->
- push_tuple_pairs(I+1, R, E, []).
+to_orddict_1(E, R, _D, I, 0) ->
+ push_tuple_pairs(I+1, R, E, []);
+to_orddict_1(E, R, D, I, S) ->
+ N = I bsr S,
+ I1 = I band ?MASK(S),
+ to_orddict_3(N, R - I1 - 1, D,
+ to_orddict_1(element(N+1, E), R, D, I1, ?reduce(S)),
+ E, S).
-to_orddict_2(E=?NODEPATTERN(S), R, D, L) when is_integer(S) ->
- to_orddict_3(?NODESIZE, R, D, L, E, S);
-to_orddict_2(E, R, D, L) when is_integer(E) ->
- push_pairs(E, R, D, L);
-to_orddict_2(E, R, _D, L) ->
- push_tuple_pairs(?LEAFSIZE, R, E, L).
+to_orddict_2(E, R, D, L, _S) when is_integer(E) ->
+ push_pairs(?SIZE(E), R, D, L);
+to_orddict_2(E, R, _D, L, 0) ->
+ push_tuple_pairs(?LEAFSIZE, R, E, L);
+to_orddict_2(E, R, D, L, S) ->
+ to_orddict_3(?NODESIZE, R, D, L, E, S).
to_orddict_3(0, _R, _D, L, _E, _S) -> %% when is_integer(R) ->
L;
to_orddict_3(N, R, D, L, E, S) ->
- to_orddict_3(N-1, R - S, D,
- to_orddict_2(element(N, E), R, D, L),
+ to_orddict_3(N-1, R - ?SIZE(S), D,
+ to_orddict_2(element(N, E), R, D, L, ?reduce(S)),
E, S).
-spec push_pairs(non_neg_integer(), array_indx(), term(), indx_pairs(Type)) ->
@@ -1308,39 +1012,6 @@ push_tuple_pairs(N, I, T, L) ->
push_tuple_pairs(N-1, I-1, T, [{I, element(N, T)} | L]).
--ifdef(EUNIT).
-to_orddict_test_() ->
- N0 = ?LEAFSIZE,
- [?_assert([] =:= to_orddict(new())),
- ?_assert([{0,undefined}] =:= to_orddict(new(1))),
- ?_assert([{0,undefined},{1,undefined}] =:= to_orddict(new(2))),
- ?_assert([{N,0}||N<-lists:seq(0,N0-1)]
- =:= to_orddict(new(N0,{default,0}))),
- ?_assert([{N,1}||N<-lists:seq(0,N0)]
- =:= to_orddict(new(N0+1,{default,1}))),
- ?_assert([{N,2}||N<-lists:seq(0,N0+1)]
- =:= to_orddict(new(N0+2,{default,2}))),
- ?_assert([{N,6}||N<-lists:seq(0,665)]
- =:= to_orddict(new(666,{default,6}))),
- ?_assert([{0,1},{1,2},{2,3}] =:=
- to_orddict(set(2,3,set(1,2,set(0,1,new()))))),
- ?_assert([{0,3},{1,2},{2,1}] =:=
- to_orddict(set(0,3,set(1,2,set(2,1,new()))))),
- ?_assert([{0,1}|[{N,0}||N<-lists:seq(1,N0-2)]++[{N0-1,1}]]
- =:= to_orddict(set(N0-1,1,set(0,1,new({default,0}))))),
- ?_assert([{0,1}|[{N,0}||N<-lists:seq(1,N0-1)]++[{N0,1}]]
- =:= to_orddict(set(N0,1,set(0,1,new({default,0}))))),
- ?_assert([{0,1}|[{N,0}||N<-lists:seq(1,N0)]++[{N0+1,1}]]
- =:= to_orddict(set(N0+1,1,set(0,1,new({default,0}))))),
- ?_assert([{0,0} | [{N,undefined}||N<-lists:seq(1,N0*2)]] ++
- [{N0*2+1,1} | [{N,undefined}||N<-lists:seq(N0*2+2,N0*10)]] ++
- [{N0*10+1,2}] =:=
- to_orddict(set(N0*10+1,2,set(N0*2+1,1,set(0,0,new()))))),
- ?_assertError(badarg, to_orddict(no_array))
- ].
--endif.
-
-
-doc """
Converts the array to an ordered list of pairs `{Index, Value}`, skipping
default-valued entries.
@@ -1351,40 +1022,39 @@ See also `to_orddict/1`.
sparse_to_orddict(#array{size = 0}) ->
[];
-sparse_to_orddict(#array{size = N, cache = C, cache_index = CI, elements = E, default = D})
- when is_integer(N) ->
- E1 = set_leaf(CI, E, C),
+sparse_to_orddict(#array{size = N, cache = C, cache_index = CI, elements = E, default = D, bits = M})
+ when is_integer(N), is_integer(CI), is_integer(M) ->
+ E1 = set_leaf(CI, M, E, C),
I = N - 1,
- sparse_to_orddict_1(E1, I, D, I);
+ sparse_to_orddict_1(E1, I, D, I, M);
sparse_to_orddict(_) ->
erlang:error(badarg).
%% see to_orddict/1 for details
-
-sparse_to_orddict_1(E=?NODEPATTERN(S), R, D, I) ->
- N = I div S,
- I1 = I rem S,
- sparse_to_orddict_3(N, R - I1 - 1, D,
- sparse_to_orddict_1(element(N+1, E), R, D, I1),
- E, S);
-sparse_to_orddict_1(E, _R, _D, _I) when is_integer(E) ->
+sparse_to_orddict_1(E, _R, _D, _I,_S) when is_integer(E) ->
[];
-sparse_to_orddict_1(E, R, D, I) ->
- sparse_push_tuple_pairs(I+1, R, D, E, []).
+sparse_to_orddict_1(E, R, D, I, 0) ->
+ sparse_push_tuple_pairs(I+1, R, D, E, []);
+sparse_to_orddict_1(E, R, D, I, S) ->
+ N = I bsr S,
+ I1 = I band ?MASK(S),
+ sparse_to_orddict_3(N, R - I1 - 1, D,
+ sparse_to_orddict_1(element(N+1, E), R, D, I1, ?reduce(S)),
+ E, S).
-sparse_to_orddict_2(E=?NODEPATTERN(S), R, D, L) when is_integer(S) ->
- sparse_to_orddict_3(?NODESIZE, R, D, L, E, S);
-sparse_to_orddict_2(E, _R, _D, L) when is_integer(E) ->
+sparse_to_orddict_2(E, _R, _D, L, _S) when is_integer(E) ->
L;
-sparse_to_orddict_2(E, R, D, L) ->
- sparse_push_tuple_pairs(?LEAFSIZE, R, D, E, L).
+sparse_to_orddict_2(E, R, D, L, 0) ->
+ sparse_push_tuple_pairs(?LEAFSIZE, R, D, E, L);
+sparse_to_orddict_2(E, R, D, L, S) ->
+ sparse_to_orddict_3(?NODESIZE, R, D, L, E, S).
sparse_to_orddict_3(0, _R, _D, L, _E, _S) -> % when is_integer(R) ->
L;
sparse_to_orddict_3(N, R, D, L, E, S) ->
- sparse_to_orddict_3(N-1, R - S, D,
- sparse_to_orddict_2(element(N, E), R, D, L),
- E, S).
+ sparse_to_orddict_3(N-1, R - ?SIZE(S), D,
+ sparse_to_orddict_2(element(N, E), R, D, L,?reduce(S)),
+ E, S).
-spec sparse_push_tuple_pairs(non_neg_integer(), array_indx(),
_, _, indx_pairs(Type)) -> indx_pairs(Type).
@@ -1397,36 +1067,6 @@ sparse_push_tuple_pairs(N, I, D, T, L) ->
E -> sparse_push_tuple_pairs(N-1, I-1, D, T, [{I, E} | L])
end.
-
--ifdef(EUNIT).
-sparse_to_orddict_test_() ->
- N0 = ?LEAFSIZE,
- [?_assert([] =:= sparse_to_orddict(new())),
- ?_assert([] =:= sparse_to_orddict(new(1))),
- ?_assert([] =:= sparse_to_orddict(new(1,{default,0}))),
- ?_assert([] =:= sparse_to_orddict(new(2))),
- ?_assert([] =:= sparse_to_orddict(new(2,{default,0}))),
- ?_assert([] =:= sparse_to_orddict(new(N0,{default,0}))),
- ?_assert([] =:= sparse_to_orddict(new(N0+1,{default,1}))),
- ?_assert([] =:= sparse_to_orddict(new(N0+2,{default,2}))),
- ?_assert([] =:= sparse_to_orddict(new(666,{default,6}))),
- ?_assert([{0,1},{1,2},{2,3}] =:=
- sparse_to_orddict(set(2,3,set(1,2,set(0,1,new()))))),
- ?_assert([{0,3},{1,2},{2,1}] =:=
- sparse_to_orddict(set(0,3,set(1,2,set(2,1,new()))))),
- ?_assert([{0,1},{N0-1,1}] =:=
- sparse_to_orddict(set(N0-1,1,set(0,1,new({default,0}))))),
- ?_assert([{0,1},{N0,1}] =:=
- sparse_to_orddict(set(N0,1,set(0,1,new({default,0}))))),
- ?_assert([{0,1},{N0+1,1}] =:=
- sparse_to_orddict(set(N0+1,1,set(0,1,new({default,0}))))),
- ?_assert([{0,0},{N0*2+1,1},{N0*10+1,2}] =:=
- sparse_to_orddict(set(N0*10+1,2,set(N0*2+1,1,set(0,0,new()))))),
- ?_assertError(badarg, sparse_to_orddict(no_array))
- ].
--endif.
-
-
-doc "Equivalent to [`from_orddict(Orddict, undefined)`](`from_orddict/2`).".
-spec from_orddict(Orddict :: indx_pairs(Value :: Type)) -> array(Type).
@@ -1448,41 +1088,43 @@ See also `new/2`, `to_orddict/1`.
from_orddict([], Default) ->
new({default,Default});
from_orddict(List, Default) when is_list(List) ->
- {E, N, _M} = from_orddict_0(List, 0, ?LEAFSIZE, Default, []),
+ {E, N, M0} = from_orddict_0(List, 0, ?LEAFSIZE, Default, []),
CI = 0,
- C = get_leaf(CI, E, Default),
- #array{size = N, fix = false, cache = C, cache_index = CI, default = Default, elements = E};
+ M = ?reduce(M0),
+ C = get_leaf(CI, M, E, Default),
+ #array{size = N, fix = false, cache = C, cache_index = CI,
+ default = Default, elements = E, bits = M};
from_orddict(_, _) ->
erlang:error(badarg).
%% 2 pass implementation, first pass builds the needed leaf nodes
%% and adds hole sizes.
-%% (inserts default elements for missing list entries in the leafs
+%% (inserts default elements for missing list entries in the leafs
%% and pads the last tuple if necessary).
%% Second pass builds the tree from the leafs and the holes.
%%
%% Doesn't build/expand unnecessary leaf nodes which costs memory
%% and time for sparse arrays.
-from_orddict_0([], N, _Max, _D, Es) ->
+from_orddict_0([], N, _Bits, _D, Es) ->
%% Finished, build the resulting tree
case Es of
- [E] ->
- {E, N, ?LEAFSIZE};
- _ ->
- collect_leafs(N, Es, ?LEAFSIZE)
+ [E] ->
+ {E, N, ?SHIFT};
+ _ ->
+ collect_leafs(N, Es, ?SHIFT)
end;
-from_orddict_0(Xs=[{Ix1, _}|_], Ix, Max0, D, Es0)
- when is_integer(Ix1), Ix1 > Max0 ->
+from_orddict_0(Xs=[{Ix1, _}|_], Ix, S0, D, Es0)
+ when is_integer(Ix1), Ix1 > S0 ->
%% We have a hole larger than a leaf
Hole = Ix1-Ix,
- Step = Hole - (Hole rem ?LEAFSIZE),
+ Step = Hole - (Hole band ?MASK),
Next = Ix+Step,
from_orddict_0(Xs, Next, Next+?LEAFSIZE, D, [Step|Es0]);
-from_orddict_0(Xs0=[{_, _}|_], Ix0, Max, D, Es) ->
- %% Fill a leaf
- {Xs,E,Ix} = from_orddict_1(Ix0, Max, Xs0, Ix0, D, []),
+from_orddict_0(Xs0=[{_, _}|_], Ix0, S, D, Es) ->
+ %% Fill a leaf
+ {Xs,E,Ix} = from_orddict_1(Ix0, S, Xs0, Ix0, D, []),
from_orddict_0(Xs, Ix, Ix+?LEAFSIZE, D, [E|Es]);
from_orddict_0(Xs, _, _, _,_) ->
erlang:error({badarg, Xs}).
@@ -1491,29 +1133,29 @@ from_orddict_1(Ix, Ix, Xs, N, _D, As) ->
%% Leaf is full
E = list_to_tuple(lists:reverse(As)),
{Xs, E, N};
-from_orddict_1(Ix, Max, Xs, N0, D, As) ->
+from_orddict_1(Ix, S, Xs, N0, D, As) ->
case Xs of
[{Ix, Val} | Xs1] ->
N = Ix+1,
- from_orddict_1(N, Max, Xs1, N, D, [Val | As]);
+ from_orddict_1(N, S, Xs1, N, D, [Val | As]);
[{Ix1, _} | _] when is_integer(Ix1), Ix1 > Ix ->
N = Ix+1,
- from_orddict_1(N, Max, Xs, N, D, [D | As]);
+ from_orddict_1(N, S, Xs, N, D, [D | As]);
[_ | _] ->
erlang:error({badarg, Xs});
_ ->
- from_orddict_1(Ix+1, Max, Xs, N0, D, [D | As])
+ from_orddict_1(Ix+1, S, Xs, N0, D, [D | As])
end.
%% Es is reversed i.e. starting from the largest leafs
-collect_leafs(N, Es, S) ->
- I = (N-1) div S + 1,
- Pad = ((?NODESIZE - (I rem ?NODESIZE)) rem ?NODESIZE) * S,
+collect_leafs(N, Es, S) ->
+ I = ((N-1) bsr S) + 1,
+ Pad = ((?NODESIZE - (I rem ?NODESIZE)) rem ?NODESIZE) * ?SIZE(S),
case Pad of
- 0 ->
- collect_leafs(?NODESIZE, Es, S, N, [S], []);
+ 0 ->
+ collect_leafs(?NODESIZE, Es, S, N, [], []);
_ -> %% Pad the end
- collect_leafs(?NODESIZE, [Pad|Es], S, N, [S], [])
+ collect_leafs(?NODESIZE, [Pad|Es], S, N, [], [])
end.
collect_leafs(0, Xs, S, N, As, Es) ->
@@ -1528,13 +1170,13 @@ collect_leafs(0, Xs, S, N, As, Es) ->
?extend(S))
end;
_ ->
- collect_leafs(?NODESIZE, Xs, S, N, [S], [E | Es])
+ collect_leafs(?NODESIZE, Xs, S, N, [], [E | Es])
end;
-collect_leafs(I, [X | Xs], S, N, As0, Es0)
+collect_leafs(I, [X | Xs], S, N, As0, Es0)
when is_integer(X) ->
%% A hole, pad accordingly.
- Step0 = (X div S),
- if
+ Step0 = (X bsr S),
+ if
Step0 < I ->
As = push(Step0, S, As0),
collect_leafs(I-Step0, Xs, S, N, As, Es0);
@@ -1548,89 +1190,13 @@ collect_leafs(I, [X | Xs], S, N, As0, Es0)
true ->
As = push(I, S, As0),
Step = Step0 - I,
- collect_leafs(0, [Step*S|Xs], S, N, As, Es0)
+ collect_leafs(0, [Step bsl S|Xs], S, N, As, Es0)
end;
collect_leafs(I, [X | Xs], S, N, As, Es) ->
collect_leafs(I-1, Xs, S, N, [X | As], Es);
-collect_leafs(?NODESIZE, [], S, N, [_], Es) ->
+collect_leafs(?NODESIZE, [], S, N, [], Es) ->
collect_leafs(N, lists:reverse(Es), ?extend(S)).
--ifdef(EUNIT).
-from_orddict_test_() ->
- N0 = ?LEAFSIZE,
- N1 = ?NODESIZE*N0,
- N2 = ?NODESIZE*N1,
- N3 = ?NODESIZE*N2,
- N4 = ?NODESIZE*N3,
- [?_assert(array:size(from_orddict([])) =:= 0),
- ?_assert(array:is_fix(from_orddict([])) =:= false),
- ?_assert(array:size(from_orddict([{0,undefined}])) =:= 1),
- ?_assert(array:is_fix(from_orddict([{0,undefined}])) =:= false),
- ?_assert(array:size(from_orddict([{N0-1,undefined}])) =:= N0),
- ?_assert(array:size(from_orddict([{N,0}||N<-lists:seq(0,N1-1)]))
- =:= N1),
- ?_assertError({badarg,_}, from_orddict([foo])),
- ?_assertError({badarg,_}, from_orddict([{200,foo},{1,bar}])),
- ?_assertError({badarg,_}, from_orddict([{N,0}||N<-lists:seq(0,N0-1)] ++ not_a_list)),
- ?_assertError(badarg, from_orddict(no_array)),
-
-
- ?_assert(?LET(L, [{N,0}||N<-lists:seq(0,N0-1)],
- L =:= to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N,0}||N<-lists:seq(0,N0)],
- L =:= to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N,0}||N<-lists:seq(0,N2-1)],
- L =:= to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N,0}||N<-lists:seq(0,N2)],
- L =:= to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N,0}||N<-lists:seq(0,N3-1)],
- L =:= to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N,0}||N<-lists:seq(0,N4-1)],
- L =:= to_orddict(from_orddict(L)))),
-
- %% Hole in the begining
- ?_assert(?LET(L, [{0,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N0,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N1,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N3,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N4,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N0-1,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N1-1,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N3-1,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N4-1,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
-
- %% Hole in middle
-
- ?_assert(?LET(L, [{0,0},{N0,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{0,0},{N1,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{0,0},{N3,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{0,0},{N4,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{0,0},{N0-1,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{0,0},{N1-1,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{0,0},{N3-1,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{0,0},{N4-1,0}],
- L =:= sparse_to_orddict(from_orddict(L))))
-
- ].
--endif.
-
-
%% Function = (Index::integer(), Value::term()) -> term()
-doc """
@@ -1644,14 +1210,14 @@ See also `foldl/3`, `foldr/3`, `sparse_map/2`.
-spec map(Function, Array :: array(Type1)) -> array(Type2) when
Function :: fun((Index :: array_indx(), Type1) -> Type2).
-map(Function, Array=#array{size = N, cache = C, cache_index = CI, elements = E, default = D})
- when is_function(Function, 2), is_integer(N) ->
+map(Function, Array=#array{size = N, cache = C, cache_index = CI, elements = E, default = D, bits = M})
+ when is_function(Function, 2), is_integer(N), is_integer(CI), is_integer(M) ->
if N > 0 ->
- E1 = set_leaf(CI, E, C),
+ E1 = set_leaf(CI, M, E, C),
A = Array#array{elements = []}, % kill reference, for GC
- E2 = map_1(N-1, E1, 0, Function, D),
+ E2 = map_1(N-1, E1, M, 0, Function, D),
CI1 = 0,
- C1 = get_leaf(CI1, E2, D),
+ C1 = get_leaf(CI1, M, E2, D),
A#array{elements = E2, cache = C1, cache_index = CI1};
true ->
Array
@@ -1664,20 +1230,22 @@ map(_, _) ->
%% left-to-right application over the elements - that is more likely to
%% be a generally useful property.
-map_1(N, E=?NODEPATTERN(S), Ix, F, D) ->
- list_to_tuple(lists:reverse([S | map_2(1, E, Ix, F, D, [],
- N div S + 1, N rem S, S)]));
-map_1(N, E, Ix, F, D) when is_integer(E) ->
- map_1(N, unfold(E, D), Ix, F, D);
-map_1(N, E, Ix, F, D) ->
- list_to_tuple(lists:reverse(map_3(1, E, Ix, F, D, N+1, []))).
-
-map_2(I, E, Ix, F, D, L, I, R, _S) ->
- map_2_1(I+1, E, [map_1(R, element(I, E), Ix, F, D) | L]);
-map_2(I, E, Ix, F, D, L, N, R, S) ->
- map_2(I+1, E, Ix + S, F, D,
- [map_1(S-1, element(I, E), Ix, F, D) | L],
- N, R, S).
+map_1(N, E, S, Ix, F, D) when is_integer(E) ->
+ map_1(N, unfold(E, D), S, Ix, F, D);
+map_1(N, E, 0, Ix, F, D) ->
+ list_to_tuple(lists:reverse(map_3(1, E, Ix, F, D, N+1, [])));
+map_1(N, E, S, Ix, F, D) ->
+ List = map_2(1, E, S, Ix, F, D, [],
+ (N bsr S) + 1, N band ?MASK(S)),
+ list_to_tuple(lists:reverse([S | List])).
+
+map_2(I, E, S, Ix, F, D, L, I, R) ->
+ map_2_1(I+1, E, [map_1(R, element(I, E), ?reduce(S), Ix, F, D) | L]);
+map_2(I, E, S, Ix, F, D, L, N, R) ->
+ Sz = ?SIZE(S),
+ map_2(I+1, E, S, Ix + Sz, F, D,
+ [map_1(Sz-1, element(I, E), ?reduce(S), Ix, F, D) | L],
+ N, R).
map_2_1(I, E, L) when I =< ?NODESIZE ->
map_2_1(I+1, E, [element(I, E) | L]);
@@ -1695,39 +1263,10 @@ map_3(_I, _E, _Ix, _F, _D, _N, L) ->
L.
-unfold(S, _D) when S > ?LEAFSIZE ->
+unfold(S, _D) when ?SIZE(S) > ?LEAFSIZE ->
?NEW_NODE(?reduce(S));
unfold(_S, D) ->
?NEW_LEAF(D).
-
-
--ifdef(EUNIT).
-map_test_() ->
- N0 = ?LEAFSIZE,
- Id = fun (_,X) -> X end,
- Plus = fun(N) -> fun (_,X) -> X+N end end,
- Default = fun(_K,undefined) -> no_value;
- (K,V) -> K+V
- end,
- [?_assertError(badarg, map([], new())),
- ?_assertError(badarg, map([], new(10))),
- ?_assert(to_list(map(Id, new())) =:= []),
- ?_assert(to_list(map(Id, new(1))) =:= [undefined]),
- ?_assert(to_list(map(Id, new(5,{default,0}))) =:= [0,0,0,0,0]),
- ?_assert(to_list(map(Id, from_list([1,2,3,4]))) =:= [1,2,3,4]),
- ?_assert(to_list(map(Plus(1), from_list([0,1,2,3]))) =:= [1,2,3,4]),
- ?_assert(to_list(map(Plus(-1), from_list(lists:seq(1,11))))
- =:= lists:seq(0,10)),
- ?_assert(to_list(map(Plus(11), from_list(lists:seq(0,99999))))
- =:= lists:seq(11,100010)),
- ?_assert([{0,0},{N0*2+1,N0*2+1+1},{N0*100+1,N0*100+1+2}] =:=
- sparse_to_orddict((map(Default,
- set(N0*100+1,2,
- set(N0*2+1,1,
- set(0,0,new())))))#array{default = no_value}))
- ].
--endif.
-
-doc """
Maps the specified function onto each array element, skipping default-valued
@@ -1740,14 +1279,14 @@ See also `map/2`.
-spec sparse_map(Function, Array :: array(Type1)) -> array(Type2) when
Function :: fun((Index :: array_indx(), Type1) -> Type2).
-sparse_map(Function, Array=#array{size = N, cache = C, cache_index = CI, elements = E, default = D})
- when is_function(Function, 2), is_integer(N) ->
+sparse_map(Function, Array=#array{size = N, cache = C, cache_index = CI, elements = E, default = D, bits = M})
+ when is_function(Function, 2), is_integer(N), is_integer(CI), is_integer(M) ->
if N > 0 ->
- E1 = set_leaf(CI, E, C),
+ E1 = set_leaf(CI, M, E, C),
A = Array#array{elements = []}, % kill reference, for GC
- E2 = sparse_map_1(N-1, E1, 0, Function, D),
+ E2 = sparse_map_1(N-1, E1, M, 0, Function, D),
CI1 = 0,
- C1 = get_leaf(CI1, E2, D),
+ C1 = get_leaf(CI1, M, E2, D),
A#array{elements = E2, cache = C1, cache_index = CI1};
true ->
Array
@@ -1758,22 +1297,22 @@ sparse_map(_, _) ->
%% see map/2 for details
%% TODO: we can probably optimize away the use of div/rem here
-sparse_map_1(N, E=?NODEPATTERN(S), Ix, F, D) ->
- list_to_tuple(lists:reverse([S | sparse_map_2(1, E, Ix, F, D, [],
- N div S + 1,
- N rem S, S)]));
-sparse_map_1(_N, E, _Ix, _F, _D) when is_integer(E) ->
+sparse_map_1(_N, E, _S, _Ix, _F, _D) when is_integer(E) ->
E;
-sparse_map_1(_N, E, Ix, F, D) ->
- list_to_tuple(lists:reverse(sparse_map_3(1, E, Ix, F, D, []))).
+sparse_map_1(_N, E, 0, Ix, F, D) ->
+ list_to_tuple(lists:reverse(sparse_map_3(1, E, Ix, F, D, [])));
+sparse_map_1(N, E, S, Ix, F, D) ->
+ List = sparse_map_2(1, E, S, Ix, F, D, [], (N bsr S) + 1, N band ?MASK(S)),
+ list_to_tuple(lists:reverse([S | List])).
-sparse_map_2(I, E, Ix, F, D, L, I, R, _S) ->
+sparse_map_2(I, E, S, Ix, F, D, L, N, R) when N =:= I ->
sparse_map_2_1(I+1, E,
- [sparse_map_1(R, element(I, E), Ix, F, D) | L]);
-sparse_map_2(I, E, Ix, F, D, L, N, R, S) ->
- sparse_map_2(I+1, E, Ix + S, F, D,
- [sparse_map_1(S-1, element(I, E), Ix, F, D) | L],
- N, R, S).
+ [sparse_map_1(R, element(I, E), ?reduce(S), Ix, F, D) | L]);
+sparse_map_2(I, E, S, Ix, F, D, L, N, R) ->
+ Sz = ?SIZE(S),
+ sparse_map_2(I+1, E, S, Ix + Sz, F, D,
+ [sparse_map_1(Sz-1, element(I, E), ?reduce(S), Ix, F, D) | L],
+ N, R).
sparse_map_2_1(I, E, L) when I =< ?NODESIZE ->
sparse_map_2_1(I+1, E, [element(I, E) | L]);
@@ -1791,43 +1330,6 @@ sparse_map_3(I, T, Ix, F, D, L) when I =< ?LEAFSIZE ->
sparse_map_3(_I, _E, _Ix, _F, _D, L) ->
L.
-
--ifdef(EUNIT).
-sparse_map_test_() ->
- N0 = ?LEAFSIZE,
- Id = fun (_,X) -> X end,
- Plus = fun(N) -> fun (_,X) -> X+N end end,
- KeyPlus = fun (K,X) -> K+X end,
- [?_assertError(badarg, sparse_map([], new())),
- ?_assertError(badarg, sparse_map([], new(10))),
- ?_assert(to_list(sparse_map(Id, new())) =:= []),
- ?_assert(to_list(sparse_map(Id, new(1))) =:= [undefined]),
- ?_assert(to_list(sparse_map(Id, new(5,{default,0}))) =:= [0,0,0,0,0]),
- ?_assert(to_list(sparse_map(Id, from_list([1,2,3,4]))) =:= [1,2,3,4]),
- ?_assert(to_list(sparse_map(Plus(1), from_list([0,1,2,3])))
- =:= [1,2,3,4]),
- ?_assert(to_list(sparse_map(Plus(-1), from_list(lists:seq(1,11))))
- =:= lists:seq(0,10)),
- ?_assert(to_list(sparse_map(Plus(11), from_list(lists:seq(0,99999))))
- =:= lists:seq(11,100010)),
- ?_assert(to_list(sparse_map(Plus(1), set(1,1,new({default,0}))))
- =:= [0,2]),
- ?_assert(to_list(sparse_map(Plus(1),
- set(3,4,set(0,1,new({default,0})))))
- =:= [2,0,0,5]),
- ?_assert(to_list(sparse_map(Plus(1),
- set(9,9,set(1,1,new({default,0})))))
- =:= [0,2,0,0,0,0,0,0,0,10]),
- ?_assert([{0,0},{N0*2+1,N0*2+1+1},{N0*100+1,N0*100+1+2}] =:=
- sparse_to_orddict(sparse_map(KeyPlus,
- set(N0*100+1,2,
- set(N0*2+1,1,
- set(0,0,new()))))))
-
- ].
--endif.
-
-
-doc """
Folds the array elements using the specified function and initial accumulator
value. The elements are visited in order from the lowest index to the highest.
@@ -1839,29 +1341,30 @@ See also `foldr/3`, `map/2`, `sparse_foldl/3`.
-spec foldl(Function, InitialAcc :: A, Array :: array(Type)) -> B when
Function :: fun((Index :: array_indx(), Value :: Type, Acc :: A) -> B).
-foldl(Function, A, #array{size = N, cache = C, cache_index = CI, elements = E, default = D})
- when is_function(Function, 3), is_integer(N) ->
+foldl(Function, A, #array{size = N, cache = C, cache_index = CI, elements = E, default = D, bits = M})
+ when is_function(Function, 3), is_integer(N), is_integer(CI), is_integer(M) ->
if N > 0 ->
- E1 = set_leaf(CI, E, C),
- foldl_1(N-1, E1, A, 0, Function, D);
+ E1 = set_leaf(CI, M, E, C),
+ foldl_1(N-1, E1, M, A, 0, Function, D);
true ->
A
end;
foldl(_, _, _) ->
erlang:error(badarg).
-foldl_1(N, E=?NODEPATTERN(S), A, Ix, F, D) ->
- foldl_2(1, E, A, Ix, F, D, N div S + 1, N rem S, S);
-foldl_1(N, E, A, Ix, F, D) when is_integer(E) ->
- foldl_1(N, unfold(E, D), A, Ix, F, D);
-foldl_1(N, E, A, Ix, F, _D) ->
- foldl_3(1, E, A, Ix, F, N+1).
+foldl_1(N, E, S, A, Ix, F, D) when is_integer(E) ->
+ foldl_1(N, unfold(E, D), S, A, Ix, F, D);
+foldl_1(N, E, 0, A, Ix, F, _D) ->
+ foldl_3(1, E, A, Ix, F, N+1);
+foldl_1(N, E, S, A, Ix, F, D) ->
+ foldl_2(1, E, S, A, Ix, F, D, (N bsr S) + 1, N band ?MASK(S)).
-foldl_2(I, E, A, Ix, F, D, I, R, _S) ->
- foldl_1(R, element(I, E), A, Ix, F, D);
-foldl_2(I, E, A, Ix, F, D, N, R, S) ->
- foldl_2(I+1, E, foldl_1(S-1, element(I, E), A, Ix, F, D),
- Ix + S, F, D, N, R, S).
+foldl_2(I, E, S, A, Ix, F, D, I, R) ->
+ foldl_1(R, element(I, E), ?reduce(S), A, Ix, F, D);
+foldl_2(I, E, S, A, Ix, F, D, N, R) ->
+ Sz = ?SIZE(S),
+ Acc = foldl_1(Sz-1, element(I, E), ?reduce(S), A, Ix, F, D),
+ foldl_2(I+1, E, S, Acc, Ix + Sz, F, D, N, R).
-spec foldl_3(pos_integer(), _, A, array_indx(),
fun((array_indx(), _, A) -> B), integer()) -> B.
@@ -1872,35 +1375,6 @@ foldl_3(_I, _E, A, _Ix, _F, _N) ->
A.
--ifdef(EUNIT).
-foldl_test_() ->
- N0 = ?LEAFSIZE,
- Count = fun (_,_,N) -> N+1 end,
- Sum = fun (_,X,N) -> N+X end,
- Reverse = fun (_,X,L) -> [X|L] end,
- Vals = fun(_K,undefined,{C,L}) -> {C+1,L};
- (K,X,{C,L}) -> {C,[K+X|L]}
- end,
- [?_assertError(badarg, foldl([], 0, new())),
- ?_assertError(badarg, foldl([], 0, new(10))),
- ?_assert(foldl(Count, 0, new()) =:= 0),
- ?_assert(foldl(Count, 0, new(1)) =:= 1),
- ?_assert(foldl(Count, 0, new(10)) =:= 10),
- ?_assert(foldl(Count, 0, from_list([1,2,3,4])) =:= 4),
- ?_assert(foldl(Count, 10, from_list([0,1,2,3,4,5,6,7,8,9])) =:= 20),
- ?_assert(foldl(Count, 1000, from_list(lists:seq(0,999))) =:= 2000),
- ?_assert(foldl(Sum, 0, from_list(lists:seq(0,10))) =:= 55),
- ?_assert(foldl(Reverse, [], from_list(lists:seq(0,1000)))
- =:= lists:reverse(lists:seq(0,1000))),
- ?_assertEqual({N0*100+1-2,[N0*100+1+2,N0*2+1+1,0]},
- foldl(Vals, {0,[]},
- set(N0*100+1,2,
- set(N0*2+1,1,
- set(0,0,new())))))
- ].
--endif.
-
-
-doc """
Folds the array elements using the specified function and initial accumulator
value, skipping default-valued entries. The elements are visited in order from
@@ -1913,11 +1387,12 @@ See also `foldl/3`, `sparse_foldr/3`.
-spec sparse_foldl(Function, InitialAcc :: A, Array :: array(Type)) -> B when
Function :: fun((Index :: array_indx(), Value :: Type, Acc :: A) -> B).
-sparse_foldl(Function, A, #array{size = N, cache = C, cache_index = CI, elements = E, default = D})
- when is_function(Function, 3), is_integer(N) ->
+sparse_foldl(Function, A, #array{size = N, cache = C, cache_index = CI,
+ elements = E, default = D, bits = M})
+ when is_function(Function, 3), is_integer(N), is_integer(CI), is_integer(M) ->
if N > 0 ->
- E1 = set_leaf(CI, E, C),
- sparse_foldl_1(N-1, E1, A, 0, Function, D);
+ E1 = set_leaf(CI, M, E, C),
+ sparse_foldl_1(N-1, E1, M, A, 0, Function, D);
true ->
A
end;
@@ -1927,18 +1402,20 @@ sparse_foldl(_, _, _) ->
%% see foldl/3 for details
%% TODO: this can be optimized
-sparse_foldl_1(N, E=?NODEPATTERN(S), A, Ix, F, D) ->
- sparse_foldl_2(1, E, A, Ix, F, D, N div S + 1, N rem S, S);
-sparse_foldl_1(_N, E, A, _Ix, _F, _D) when is_integer(E) ->
+sparse_foldl_1(_N, E, _S, A, _Ix, _F, _D) when is_integer(E) ->
A;
-sparse_foldl_1(N, E, A, Ix, F, D) ->
- sparse_foldl_3(1, E, A, Ix, F, D, N+1).
-
-sparse_foldl_2(I, E, A, Ix, F, D, I, R, _S) ->
- sparse_foldl_1(R, element(I, E), A, Ix, F, D);
-sparse_foldl_2(I, E, A, Ix, F, D, N, R, S) ->
- sparse_foldl_2(I+1, E, sparse_foldl_1(S-1, element(I, E), A, Ix, F, D),
- Ix + S, F, D, N, R, S).
+sparse_foldl_1(N, E, 0, A, Ix, F, D) ->
+ sparse_foldl_3(1, E, A, Ix, F, D, N+1);
+sparse_foldl_1(N, E, S, A, Ix, F, D) ->
+ sparse_foldl_2(1, E, S, A, Ix, F, D, (N bsr S) + 1, N band ?MASK(S)).
+
+sparse_foldl_2(I, E, S, A, Ix, F, D, I, R) ->
+ sparse_foldl_1(R, element(I, E), ?reduce(S), A, Ix, F, D);
+sparse_foldl_2(I, E, S, A, Ix, F, D, N, R) ->
+ Sz = ?SIZE(S),
+ sparse_foldl_2(I+1, E, S,
+ sparse_foldl_1(Sz-1, element(I, E), ?reduce(S), A, Ix, F, D),
+ Ix + Sz, F, D, N, R).
sparse_foldl_3(I, T, A, Ix, F, D, N) when I =< N ->
case element(I, T) of
@@ -1949,37 +1426,6 @@ sparse_foldl_3(_I, _T, A, _Ix, _F, _D, _N) ->
A.
--ifdef(EUNIT).
-sparse_foldl_test_() ->
- N0 = ?LEAFSIZE,
- Count = fun (_,_,N) -> N+1 end,
- Sum = fun (_,X,N) -> N+X end,
- Reverse = fun (_,X,L) -> [X|L] end,
- Vals = fun(_K,undefined,{C,L}) -> {C+1,L};
- (K,X,{C,L}) -> {C,[K+X|L]}
- end,
- [?_assertError(badarg, sparse_foldl([], 0, new())),
- ?_assertError(badarg, sparse_foldl([], 0, new(10))),
- ?_assert(sparse_foldl(Count, 0, new()) =:= 0),
- ?_assert(sparse_foldl(Count, 0, new(1)) =:= 0),
- ?_assert(sparse_foldl(Count, 0, new(10,{default,1})) =:= 0),
- ?_assert(sparse_foldl(Count, 0, from_list([0,1,2,3,4],0)) =:= 4),
- ?_assert(sparse_foldl(Count, 0, from_list([0,1,2,3,4,5,6,7,8,9,0],0))
- =:= 9),
- ?_assert(sparse_foldl(Count, 0, from_list(lists:seq(0,999),0))
- =:= 999),
- ?_assert(sparse_foldl(Sum, 0, from_list(lists:seq(0,10), 5)) =:= 50),
- ?_assert(sparse_foldl(Reverse, [], from_list(lists:seq(0,1000), 0))
- =:= lists:reverse(lists:seq(1,1000))),
- ?_assert({0,[N0*100+1+2,N0*2+1+1,0]} =:=
- sparse_foldl(Vals, {0,[]},
- set(N0*100+1,2,
- set(N0*2+1,1,
- set(0,0,new())))))
- ].
--endif.
-
-
-doc """
Folds the array elements right-to-left using the specified function and initial
accumulator value. The elements are visited in order from the highest index to
@@ -1992,12 +1438,12 @@ See also `foldl/3`, `map/2`.
-spec foldr(Function, InitialAcc :: A, Array :: array(Type)) -> B when
Function :: fun((Index :: array_indx(), Value :: Type, Acc :: A) -> B).
-foldr(Function, A, #array{size = N, cache = C, cache_index = CI, elements = E, default = D})
- when is_function(Function, 3), is_integer(N) ->
+foldr(Function, A, #array{size = N, cache = C, cache_index = CI, elements = E, default = D, bits = M})
+ when is_function(Function, 3), is_integer(N), is_integer(CI), is_integer(M) ->
if N > 0 ->
I = N - 1,
- E1 = set_leaf(CI, E, C),
- foldr_1(I, E1, I, A, Function, D);
+ E1 = set_leaf(CI, M, E, C),
+ foldr_1(I, E1, M, I, A, Function, D);
true ->
A
end;
@@ -2005,20 +1451,19 @@ foldr(_, _, _) ->
erlang:error(badarg).
%% this is based on to_orddict/1
-
-foldr_1(I, E=?NODEPATTERN(S), Ix, A, F, D) ->
- foldr_2(I div S + 1, E, Ix, A, F, D, I rem S, S-1);
-foldr_1(I, E, Ix, A, F, D) when is_integer(E) ->
- foldr_1(I, unfold(E, D), Ix, A, F, D);
-foldr_1(I, E, Ix, A, F, _D) ->
+foldr_1(I, E, S, Ix, A, F, D) when is_integer(E) ->
+ foldr_1(I, unfold(E, D), S, Ix, A, F, D);
+foldr_1(I, E, 0, Ix, A, F, _D) ->
I1 = I+1,
- foldr_3(I1, E, Ix-I1, A, F).
+ foldr_3(I1, E, Ix-I1, A, F);
+foldr_1(I, E, S, Ix, A, F, D) ->
+ foldr_2((I bsr S) + 1, E, S, Ix, A, F, D, I band ?MASK(S), ?SIZE(S)-1).
-foldr_2(0, _E, _Ix, A, _F, _D, _R, _R0) ->
+foldr_2(0, _E, _S, _Ix, A, _F, _D, _R, _R0) ->
A;
-foldr_2(I, E, Ix, A, F, D, R, R0) ->
- foldr_2(I-1, E, Ix - R - 1,
- foldr_1(R, element(I, E), Ix, A, F, D),
+foldr_2(I, E, S, Ix, A, F, D, R, R0) ->
+ foldr_2(I-1, E, S, Ix - R - 1,
+ foldr_1(R, element(I, E), ?reduce(S), Ix, A, F, D),
F, D, R0, R0).
-spec foldr_3(array_indx(), term(), integer(), A,
@@ -2030,35 +1475,6 @@ foldr_3(I, E, Ix, A, F) ->
foldr_3(I-1, E, Ix, F(Ix+I, element(I, E), A), F).
--ifdef(EUNIT).
-foldr_test_() ->
- N0 = ?LEAFSIZE,
- Count = fun (_,_,N) -> N+1 end,
- Sum = fun (_,X,N) -> N+X end,
- List = fun (_,X,L) -> [X|L] end,
- Vals = fun(_K,undefined,{C,L}) -> {C+1,L};
- (K,X,{C,L}) -> {C,[K+X|L]}
- end,
- [?_assertError(badarg, foldr([], 0, new())),
- ?_assertError(badarg, foldr([], 0, new(10))),
- ?_assert(foldr(Count, 0, new()) =:= 0),
- ?_assert(foldr(Count, 0, new(1)) =:= 1),
- ?_assert(foldr(Count, 0, new(10)) =:= 10),
- ?_assert(foldr(Count, 0, from_list([1,2,3,4])) =:= 4),
- ?_assert(foldr(Count, 10, from_list([0,1,2,3,4,5,6,7,8,9])) =:= 20),
- ?_assert(foldr(Count, 1000, from_list(lists:seq(0,999))) =:= 2000),
- ?_assert(foldr(Sum, 0, from_list(lists:seq(0,10))) =:= 55),
- ?_assert(foldr(List, [], from_list(lists:seq(0,1000)))
- =:= lists:seq(0,1000)),
- ?_assertEqual({N0*100+1-2,[0,N0*2+1+1,N0*100+1+2]},
- foldr(Vals, {0,[]},
- set(N0*100+1,2,
- set(N0*2+1,1,
- set(0,0,new())))))
- ].
--endif.
-
-
-doc """
Folds the array elements right-to-left using the specified function and initial
accumulator value, skipping default-valued entries. The elements are visited in
@@ -2071,12 +1487,12 @@ See also `foldr/3`, `sparse_foldl/3`.
-spec sparse_foldr(Function, InitialAcc :: A, Array :: array(Type)) -> B when
Function :: fun((Index :: array_indx(), Value :: Type, Acc :: A) -> B).
-sparse_foldr(Function, A, #array{size = N, cache = C, cache_index = CI, elements = E, default = D})
- when is_function(Function, 3), is_integer(N) ->
+sparse_foldr(Function, A, #array{size = N, cache = C, cache_index = CI, elements = E, default = D, bits = M})
+ when is_function(Function, 3), is_integer(N), is_integer(CI), is_integer(M) ->
if N > 0 ->
I = N - 1,
- E1 = set_leaf(CI, E, C),
- sparse_foldr_1(I, E1, I, A, Function, D);
+ E1 = set_leaf(CI, M, E, C),
+ sparse_foldr_1(I, E1, M, I, A, Function, D);
true ->
A
end;
@@ -2086,20 +1502,20 @@ sparse_foldr(_, _, _) ->
%% see foldr/3 for details
%% TODO: this can be optimized
-sparse_foldr_1(I, E=?NODEPATTERN(S), Ix, A, F, D) ->
- sparse_foldr_2(I div S + 1, E, Ix, A, F, D, I rem S, S-1);
-sparse_foldr_1(_I, E, _Ix, A, _F, _D) when is_integer(E) ->
+sparse_foldr_1(_I, E, _S, _Ix, A, _F, _D) when is_integer(E) ->
A;
-sparse_foldr_1(I, E, Ix, A, F, D) ->
+sparse_foldr_1(I, E, 0, Ix, A, F, D) ->
I1 = I+1,
- sparse_foldr_3(I1, E, Ix-I1, A, F, D).
+ sparse_foldr_3(I1, E, Ix-I1, A, F, D);
+sparse_foldr_1(I, E, S, Ix, A, F, D) ->
+ sparse_foldr_2((I bsr S) + 1, E, S, Ix, A, F, D, I band ?MASK(S), ?SIZE(S)-1).
-sparse_foldr_2(0, _E, _Ix, A, _F, _D, _R, _R0) ->
+sparse_foldr_2(0, _E, _S, _Ix, A, _F, _D, _R, _R0) ->
A;
-sparse_foldr_2(I, E, Ix, A, F, D, R, R0) ->
- sparse_foldr_2(I-1, E, Ix - R - 1,
- sparse_foldr_1(R, element(I, E), Ix, A, F, D),
- F, D, R0, R0).
+sparse_foldr_2(I, E, S, Ix, A, F, D, R, R0) ->
+ sparse_foldr_2(I-1, E, S, Ix - R - 1,
+ sparse_foldr_1(R, element(I, E), ?reduce(S), Ix, A, F, D),
+ F, D, R0, R0).
-spec sparse_foldr_3(array_indx(), _, array_indx(), A,
fun((array_indx(), _, A) -> B), _) -> B.
@@ -2130,46 +1546,3 @@ sparse_size(A) ->
{value, I} when is_integer(I) ->
I + 1
end.
-
-
--ifdef(EUNIT).
-sparse_foldr_test_() ->
- N0 = ?LEAFSIZE,
- Count = fun (_,_,N) -> N+1 end,
- Sum = fun (_,X,N) -> N+X end,
- List = fun (_,X,L) -> [X|L] end,
- Vals = fun(_K,undefined,{C,L}) -> {C+1,L};
- (K,X,{C,L}) -> {C,[K+X|L]}
- end,
-
- [?_assertError(badarg, sparse_foldr([], 0, new())),
- ?_assertError(badarg, sparse_foldr([], 0, new(10))),
- ?_assert(sparse_foldr(Count, 0, new()) =:= 0),
- ?_assert(sparse_foldr(Count, 0, new(1)) =:= 0),
- ?_assert(sparse_foldr(Count, 0, new(10,{default,1})) =:= 0),
- ?_assert(sparse_foldr(Count, 0, from_list([0,1,2,3,4],0)) =:= 4),
- ?_assert(sparse_foldr(Count, 0, from_list([0,1,2,3,4,5,6,7,8,9,0],0))
- =:= 9),
- ?_assert(sparse_foldr(Count, 0, from_list(lists:seq(0,999),0))
- =:= 999),
- ?_assert(sparse_foldr(Sum, 0, from_list(lists:seq(0,10),5)) =:= 50),
- ?_assert(sparse_foldr(List, [], from_list(lists:seq(0,1000),0))
- =:= lists:seq(1,1000)),
-
- ?_assert(sparse_size(new()) =:= 0),
- ?_assert(sparse_size(new(8)) =:= 0),
- ?_assert(sparse_size(array:set(7, 0, new())) =:= 8),
- ?_assert(sparse_size(array:set(7, 0, new(10))) =:= 8),
- ?_assert(sparse_size(array:set(99, 0, new(10,{fixed,false})))
- =:= 100),
- ?_assert(sparse_size(array:set(7, undefined, new())) =:= 0),
- ?_assert(sparse_size(array:from_list([1,2,3,undefined])) =:= 3),
- ?_assert(sparse_size(array:from_orddict([{3,0},{17,0},{99,undefined}]))
- =:= 18),
- ?_assert({0,[0,N0*2+1+1,N0*100+1+2]} =:=
- sparse_foldr(Vals, {0,[]},
- set(N0*100+1,2,
- set(N0*2+1,1,
- set(0,0,new())))))
- ].
--endif.
diff --git a/lib/stdlib/test/array_SUITE.erl b/lib/stdlib/test/array_SUITE.erl
index 07eac40ae9..ab1fee088e 100644
--- a/lib/stdlib/test/array_SUITE.erl
+++ b/lib/stdlib/test/array_SUITE.erl
@@ -23,46 +23,47 @@
-module(array_SUITE).
-include_lib("common_test/include/ct.hrl").
+-include_lib("stdlib/include/assert.hrl").
%% Test server specific exports
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2]).
-export([init_per_testcase/2, end_per_testcase/2]).
-export([
- new_test/1,
- fix_test/1,
- relax_test/1,
- resize_test/1,
- set_get_test/1,
- to_list_test/1,
- sparse_to_list_test/1,
- from_list_test/1,
+ new_test/1,
+ fix_test/1,
+ relax_test/1,
+ resize_test/1,
+ set_get_test/1,
+ to_list_test/1,
+ sparse_to_list_test/1,
+ from_list_test/1,
from_test/1,
- to_orddict_test/1,
- sparse_to_orddict_test/1,
- from_orddict_test/1,
- map_test/1,
- sparse_map_test/1,
- foldl_test/1,
- sparse_foldl_test/1,
- foldr_test/1,
- sparse_foldr_test/1,
+ to_orddict_test/1,
+ sparse_to_orddict_test/1,
+ from_orddict_test/1,
+ map_test/1,
+ sparse_map_test/1,
+ foldl_test/1,
+ sparse_foldl_test/1,
+ foldr_test/1,
+ sparse_foldr_test/1,
import_export/1,
doctests/1
- ]).
+ ]).
--export([t/0,t/1,extract_tests/0]).
+-export([t/0,t/1]).
-import(array,
- [new/0, new/1, new/2, is_array/1, set/3, get/2, %size/1,
- sparse_size/1, default/1, reset/2, to_list/1, sparse_to_list/1,
+ [new/0, new/1, new/2, is_array/1, set/3, get/2, %size/1,
+ sparse_size/1, default/1, reset/2, to_list/1, sparse_to_list/1,
from/2, from/3,
- from_list/1, from_list/2, to_orddict/1, sparse_to_orddict/1,
- from_orddict/1, from_orddict/2, map/2, sparse_map/2, foldl/3,
- foldr/3, sparse_foldl/3, sparse_foldr/3, fix/1, relax/1, is_fix/1,
- resize/1, resize/2]).
+ from_list/1, from_list/2, to_orddict/1, sparse_to_orddict/1,
+ from_orddict/1, from_orddict/2, map/2, sparse_map/2, foldl/3,
+ foldr/3, sparse_foldl/3, sparse_foldr/3, fix/1, relax/1, is_fix/1,
+ resize/1, resize/2]).
%%
%% all/1
@@ -102,382 +103,334 @@ init_per_testcase(_Case, Config) ->
end_per_testcase(_Case, _Config) ->
ok.
--define(LEAFSIZE,10).
+-define(LEAFSIZE,8).
-define(NODESIZE,?LEAFSIZE).
--record(array, {size, %% number of defined entries
- fix, %% not automatically growing
- default, %% the default value (usually 'undefined')
+-record(array, {size, %% number of defined entries
+ fix, %% not automatically growing
+ default, %% the default value (usually 'undefined')
cache, %% cached leaf tuple
cache_index, %% low index of cache
- elements %% the tuple tree
- }).
-
--define(_assert(What),
- begin true = What end
- ).
--define(_assertNot(What),
- begin false = What end
- ).
-
--define(_assertMatch(Res,What),
- begin
- case What of Res -> ok end
- end
- ).
--define(_assertError(Reas,What),
- begin fun() ->
- try What of
- A_Success -> exit({test_error, A_Success})
- catch error:Reas -> ok end
- end()
- end
- ).
-
--define(LET(Var,Expr, Test), begin fun() -> Var = Expr, Test end() end).
-
--define(_test(Expr), begin Expr end).
+ elements, %% the tuple tree
+ max
+ }).
+
+-define(test(Expr), begin Expr end).
+
+-define(LET(Var,Expr, Test), begin (fun(Var) -> Test end)(Expr) end).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Some helpers to be able to run the tests without testserver
%%%%%%%%%%%%%%%%%%%%%%%%%
-t() -> t([all]).
+t() -> t(all()--[doctests]).
t(What) when not is_list(What) ->
t([What]);
t(What) ->
lists:foreach(fun(T) ->
- io:format("Test ~p ~n",[T]),
- try
- ?MODULE:T([])
- catch _E:_R:_S ->
- Line = get(test_server_loc),
- io:format("Failed ~p:~p ~p ~p~n ~p~n",
- [T,Line,_E,_R,_S])
- end
- end, What).
-
-%%%%% extract tests
-
-extract_tests() ->
- {ok, In} = file:open("../src/array.erl", [read]),
- {ok, Out} = file:open("array_temp.erl", [write]),
- try
- Tests = extract_tests(In,Out,[]),
- Call = fun(Test) ->
- io:format(Out, "~s(Config) when is_list(Config) -> ~s_(), ok.~n",
- [Test, Test])
- end,
- [Call(Test) || Test <- Tests],
- io:format("Tests ~p~n", [Tests])
- catch _:Err:Stacktrace ->
- io:format("Error: ~p ~p~n", [Err, Stacktrace])
- end,
- file:close(In),
- file:close(Out).
-
-extract_tests(In,Out,Tests) ->
- case io:get_line(In,"") of
- eof -> lists:reverse(Tests);
- "-ifdef(EUNIT)" ++ _ ->
- Test = write_test(In,Out),
- extract_tests(In,Out, [Test|Tests]);
- _E ->
- extract_tests(In,Out,Tests)
- end.
-
-write_test(In,Out) ->
- Line = io:get_line(In,""),
- io:put_chars(Out, Line),
- [$_|Test] = lists:dropwhile(fun($_) -> false;(_) -> true end,lists:reverse(Line)),
- write_test_1(In,Out),
- lists:reverse(Test).
-
-write_test_1(In,Out) ->
- case io:get_line(In,"") of
- "-endif" ++ _ ->
- io:nl(Out),
- ok;
- Line ->
- io:put_chars(Out, Line),
- write_test_1(In,Out)
- end.
+ io:format("Test ~p ~n",[T]),
+ try
+ ?MODULE:T([])
+ catch _E:_R:_S ->
+ Line = get(test_server_loc),
+ io:format("Failed ~p:~p ~p ~p~n ~p~n",
+ [T,Line,_E,_R,_S])
+ end
+ end, What).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Actual tests
-new_test_() ->
+new_test(_Config) ->
N0 = ?LEAFSIZE,
N01 = N0+1,
N1 = ?NODESIZE*N0,
N11 = N1+1,
N2 = ?NODESIZE*N1,
- [?_test(new()),
-
- ?_test(new([])),
- ?_test(new(10)),
- ?_test(new({size,10})),
- ?_test(new(fixed)),
- ?_test(new({fixed,true})),
- ?_test(new({fixed,false})),
- ?_test(new({default,undefined})),
- ?_test(new([{size,100},{fixed,false},{default,undefined}])),
- ?_test(new([100,fixed,{default,0}])),
-
- ?_assert(new() =:= new([])),
- ?_assert(new() =:= new([{size,0},{default,undefined},{fixed,false}])),
- ?_assert(new() =:= new(0, {fixed,false})),
- ?_assert(new(fixed) =:= new(0)),
- ?_assert(new(fixed) =:= new(0, [])),
- ?_assert(new(10) =:= new([{size,0},{size,5},{size,10}])),
- ?_assert(new(10) =:= new(0, {size,10})),
- ?_assert(new(10, []) =:= new(10, [{default,undefined},{fixed,true}])),
-
- ?_assertError(badarg, new(-1)),
- ?_assertError(badarg, new(10.0)),
- ?_assertError(badarg, new(undefined)),
- ?_assertError(badarg, new([undefined])),
- ?_assertError(badarg, new([{default,0} | fixed])),
-
- ?_assertError(badarg, new(-1, [])),
- ?_assertError(badarg, new(10.0, [])),
- ?_assertError(badarg, new(undefined, [])),
-
- ?_assertMatch(#array{size=0,fix=false,default=undefined,elements=N0},
- new()),
- ?_assertMatch(#array{size=0,fix=true,default=undefined,elements=N0},
- new(fixed)),
- ?_assertMatch(#array{size=N0,fix=false,elements=N0},
- new(N0, {fixed,false})),
- ?_assertMatch(#array{size=N01,fix=false,elements=N1},
- new(N01, {fixed,false})),
- ?_assertMatch(#array{size=N1,fix=false,elements=N1},
- new(N1, {fixed,false})),
- ?_assertMatch(#array{size=N11,fix=false,elements=N2},
- new(N11, {fixed,false})),
- ?_assertMatch(#array{size=N2, fix=false, default=42,elements=N2},
- new(N2, [{fixed,false},{default,42}])),
-
- ?_assert(0 =:= array:size(new())),
- ?_assert(17 =:= array:size(new(17))),
- ?_assert(8 =:= array:size(array:set(7,0,new()))),
- ?_assert(100 =:= array:size(array:set(99,0,new()))),
- ?_assert(100 =:= array:size(array:set(7,0,array:set(99,0,new())))),
- ?_assert(100 =:= array:size(array:set(99,0,array:set(7,0,new())))),
- ?_assertError(badarg, array:size({bad_data,gives_error})),
-
- ?_assert(undefined =:= default(new())),
- ?_assert(4711 =:= default(new({default,4711}))),
- ?_assert(0 =:= default(new(10, {default,0}))),
- ?_assertError(badarg, default({bad_data,gives_error})),
-
- ?_assert(is_array(new())),
- ?_assert(false =:= is_array({foobar, 23, 23})),
- ?_assert(false =:= is_array(#array{size=bad})),
- %?_assert(false =:= is_array(#array{fix=bad})),
- ?_assert(is_array(new(10))),
- ?_assert(is_array(new(10, {fixed,false})))
+ ?test(new()),
+
+ ?test(new([])),
+ ?test(new(10)),
+ ?test(new({size,10})),
+ ?test(new(fixed)),
+ ?test(new({fixed,true})),
+ ?test(new({fixed,false})),
+ ?test(new({default,undefined})),
+ ?test(new([{size,100},{fixed,false},{default,undefined}])),
+ ?test(new([100,fixed,{default,0}])),
+
+ ?assert(new() =:= new([])),
+ ?assert(new() =:= new([{size,0},{default,undefined},{fixed,false}])),
+ ?assert(new() =:= new(0, {fixed,false})),
+ ?assert(new(fixed) =:= new(0)),
+ ?assert(new(fixed) =:= new(0, [])),
+ ?assert(new(10) =:= new([{size,0},{size,5},{size,10}])),
+ ?assert(new(10) =:= new(0, {size,10})),
+ ?assert(new(10, []) =:= new(10, [{default,undefined},{fixed,true}])),
+
+ ?assertError(badarg, new(-1)),
+ ?assertError(badarg, new(10.0)),
+ ?assertError(badarg, new(undefined)),
+ ?assertError(badarg, new([undefined])),
+ ?assertError(badarg, new([{default,0} | fixed])),
+
+ ?assertError(badarg, new(-1, [])),
+ ?assertError(badarg, new(10.0, [])),
+ ?assertError(badarg, new(undefined, [])),
+
+ ?assertMatch(#array{size=0,fix=false,default=undefined},
+ new()),
+ ?assertMatch(#array{size=0,fix=true,default=undefined},
+ new(fixed)),
+ ?assertMatch(#array{size=N0,fix=false},
+ new(N0, {fixed,false})),
+ ?assertMatch(#array{size=N01,fix=false},
+ new(N01, {fixed,false})),
+ ?assertMatch(#array{size=N1,fix=false},
+ new(N1, {fixed,false})),
+ ?assertMatch(#array{size=N11,fix=false},
+ new(N11, {fixed,false})),
+ ?assertMatch(#array{size=N2, fix=false, default=42},
+ new(N2, [{fixed,false},{default,42}])),
+
+ ?assert(0 =:= array:size(new())),
+ ?assert(17 =:= array:size(new(17))),
+ ?assert(8 =:= array:size(array:set(7,0,new()))),
+ ?assert(100 =:= array:size(array:set(99,0,new()))),
+ ?assert(100 =:= array:size(array:set(7,0,array:set(99,0,new())))),
+ ?assert(100 =:= array:size(array:set(99,0,array:set(7,0,new())))),
+ ?assertError(badarg, array:size({bad_data,gives_error})),
+
+ ?assert(undefined =:= default(new())),
+ ?assert(4711 =:= default(new({default,4711}))),
+ ?assert(0 =:= default(new(10, {default,0}))),
+ ?assertError(badarg, default({bad_data,gives_error})),
+
+ ?assert(is_array(new())),
+ ?assert(false =:= is_array({foobar, 23, 23})),
+ ?assert(false =:= is_array(#array{size=bad})),
+ %%?assert(false =:= is_array(#array{fix=bad})),
+ ?assert(is_array(new(10))),
+ ?assert(is_array(new(10, {fixed,false}))).
+
+fix_test(_Config) ->
+ ?assert(is_array(fix(new()))),
+ %%?assert(fix(new()) =:= new(fixed)),
+
+ ?assertNot(is_fix(new())),
+ ?assertNot(is_fix(new([]))),
+ ?assertNot(is_fix(new({fixed,false}))),
+ ?assertNot(is_fix(new(10, {fixed,false}))),
+ ?assert(is_fix(new({fixed,true}))),
+ ?assert(is_fix(new(fixed))),
+ ?assert(is_fix(new(10))),
+ ?assert(is_fix(new(10, []))),
+ ?assert(is_fix(new(10, {fixed,true}))),
+ ?assert(is_fix(fix(new()))),
+ ?assert(is_fix(fix(new({fixed,false})))),
+
+ ?test(set(0, 17, new())),
+ ?assertError(badarg, set(0, 17, new(fixed))),
+ ?assertError(badarg, set(1, 42, fix(set(0, 17, new())))),
+
+ ?test(set(9, 17, new(10))),
+ ?assertError(badarg, set(10, 17, new(10))),
+ ?assertError(badarg, set(10, 17, fix(new(10, {fixed,false})))).
+
+relax_test(_Config) ->
+ [?assert(is_array(relax(new(fixed)))),
+ ?assertNot(is_fix(relax(fix(new())))),
+ ?assertNot(is_fix(relax(new(fixed)))),
+
+ ?assert(new() =:= relax(new(fixed))),
+ ?assert(new() =:= relax(new(0))),
+ ?assert(new(17, {fixed,false}) =:= relax(new(17)))
+ %, ?assert(new(100, {fixed,false})
+ % =:= relax(fix(new(100, {fixed,false}))))
].
-fix_test_() ->
- [?_assert(is_array(fix(new()))),
- %?_assert(fix(new()) =:= new(fixed)),
-
- ?_assertNot(is_fix(new())),
- ?_assertNot(is_fix(new([]))),
- ?_assertNot(is_fix(new({fixed,false}))),
- ?_assertNot(is_fix(new(10, {fixed,false}))),
- ?_assert(is_fix(new({fixed,true}))),
- ?_assert(is_fix(new(fixed))),
- ?_assert(is_fix(new(10))),
- ?_assert(is_fix(new(10, []))),
- ?_assert(is_fix(new(10, {fixed,true}))),
- ?_assert(is_fix(fix(new()))),
- ?_assert(is_fix(fix(new({fixed,false})))),
-
- ?_test(set(0, 17, new())),
- ?_assertError(badarg, set(0, 17, new(fixed))),
- ?_assertError(badarg, set(1, 42, fix(set(0, 17, new())))),
-
- ?_test(set(9, 17, new(10))),
- ?_assertError(badarg, set(10, 17, new(10))),
- ?_assertError(badarg, set(10, 17, fix(new(10, {fixed,false}))))
- ].
-
-relax_test_() ->
- [?_assert(is_array(relax(new(fixed)))),
- ?_assertNot(is_fix(relax(fix(new())))),
- ?_assertNot(is_fix(relax(new(fixed)))),
-
- ?_assert(new() =:= relax(new(fixed))),
- ?_assert(new() =:= relax(new(0))),
- ?_assert(new(17, {fixed,false}) =:= relax(new(17)))
- %, ?_assert(new(100, {fixed,false})
- % =:= relax(fix(new(100, {fixed,false}))))
- ].
+resize_test(_Config) ->
+ ?assert(resize(0, new()) =:= new()),
+ ?assert(resize(99, new(99)) =:= new(99)),
+ ?assert(resize(99, relax(new(99))) =:= relax(new(99))),
+ ?assert(is_fix(resize(100, new(10)))),
+ ?assertNot(is_fix(resize(100, relax(new(10))))),
+
+ ?assert(array:size(resize(100, new())) =:= 100),
+ ?assert(array:size(resize(0, new(100))) =:= 0),
+ ?assert(array:size(resize(1, new(100))) =:= 1),
+ ?assert(array:size(resize(99, new(10))) =:= 99),
+ ?assert(array:size(resize(99, new(1000))) =:= 99),
+
+ ?assertError(badarg, set(99, 17, new(10))),
+ ?test(set(99, 17, resize(100, new(10)))),
+ ?assertError(badarg, set(100, 17, resize(100, new(10)))),
+
+ ?test(set(9, 17, resize(10, new(100)))),
+ ?assertError(badarg, set(10, 17, resize(10, new(100)))),
+
+ ?test(set(9, 17, resize(10, fix(set(99, 17, new()))))),
+ ?assertError(badarg, set(10, 17, resize(10, fix(set(99, 17, new()))))),
+
+ ?assert(17 =:= get(99, resize(100, set(99, 17, set(999, 17, new(1000)))))),
+
+ ?assert(undefined =:= get(55, resize(100, resize(10, set(55, 17, new()))))),
+ ?assert(17 =:= get(55, resize(100, resize(56, set(55, 17, new()))))),
+ ?assert(undefined =:= get(55, resize(100, resize(55, set(55, 17, new()))))),
+
+ ?assertError(badarg, get(0, resize(0, set(0, 17, new(100))))),
+ ?assert(undefined =:= get(0, resize(0, set(0, 17, set(99, 17, new()))))),
+
+ ?assert(array:size(resize(new())) =:= 0),
+ ?assert(array:size(resize(new(8))) =:= 0),
+ ?assert(array:size(resize(array:set(7, 0, new()))) =:= 8),
+ ?assert(array:size(resize(array:set(7, 0, new(10)))) =:= 8),
+ ?assert(array:size(resize(array:set(99, 0, new(10,{fixed,false}))))
+ =:= 100),
+ ?assert(array:size(resize(array:set(7, undefined, new()))) =:= 0),
+ ?assert(array:size(resize(array:from_list([1,2,3,undefined])))
+ =:= 3),
+ ?assert(array:size(
+ resize(array:from_orddict([{3,0},{17,0},{99,undefined}])))
+ =:= 18),
+ ?assertError(badarg, resize(foo, bad_argument)),
+
+ %% Regression test for shrink bugs
+ A258 = array:from_list(lists:seq(1,258)),
+ ?assert(244 =:= array:get(0, array:resize(1, array:set(1, 1744, array:set(0, 244, array:new()))))),
+ ?assert(258 =:= array:get(257, array:resize(261, array:set(261, foo, A258)))),
+ ?assert(258 =:= array:get(257, array:resize(315, array:set(0, x, array:set(600, foo, A258))))),
+ %% Test multi-level collapse wrapping
+ ?test(begin
+ A0 = array:new(),
+ A1 = lists:foldl(fun(I, Acc) -> array:set(I, I, Acc) end, A0, lists:seq(0, 300)),
+ A2 = array:resize(50, A1),
+ ?assert(49 =:= array:get(49, A2)),
+ A3 = array:resize(300, A2),
+ ?assert(49 =:= array:get(49, A3)),
+ ?assert(undefined =:= array:get(299, A3))
+ end),
-resize_test_() ->
- [?_assert(resize(0, new()) =:= new()),
- ?_assert(resize(99, new(99)) =:= new(99)),
- ?_assert(resize(99, relax(new(99))) =:= relax(new(99))),
- ?_assert(is_fix(resize(100, new(10)))),
- ?_assertNot(is_fix(resize(100, relax(new(10))))),
-
- ?_assert(array:size(resize(100, new())) =:= 100),
- ?_assert(array:size(resize(0, new(100))) =:= 0),
- ?_assert(array:size(resize(99, new(10))) =:= 99),
- ?_assert(array:size(resize(99, new(1000))) =:= 99),
-
- ?_assertError(badarg, set(99, 17, new(10))),
- ?_test(set(99, 17, resize(100, new(10)))),
- ?_assertError(badarg, set(100, 17, resize(100, new(10)))),
-
- ?_test(set(9, 17, resize(10, new(100)))),
- ?_assertError(badarg, set(10, 17, resize(10, new(100)))),
-
- ?_test(set(9, 17, resize(10, fix(set(99, 17, new()))))),
- ?_assertError(badarg, set(10, 17, resize(10, fix(set(99, 17, new()))))),
-
- ?_assert(17 =:= get(99, resize(100, set(99, 17, set(999, 17, new(1000)))))),
-
- ?_assert(undefined =:= get(55, resize(100, resize(10, set(55, 17, new()))))),
- ?_assert(17 =:= get(55, resize(100, resize(56, set(55, 17, new()))))),
- ?_assert(undefined =:= get(55, resize(100, resize(55, set(55, 17, new()))))),
-
- ?_assertError(badarg, get(0, resize(0, set(0, 17, new(100))))),
- ?_assert(undefined =:= get(0, resize(0, set(0, 17, set(99, 17, new()))))),
-
- ?_assert(array:size(resize(new())) =:= 0),
- ?_assert(array:size(resize(new(8))) =:= 0),
- ?_assert(array:size(resize(array:set(7, 0, new()))) =:= 8),
- ?_assert(array:size(resize(array:set(7, 0, new(10)))) =:= 8),
- ?_assert(array:size(resize(array:set(99, 0, new(10,{fixed,false}))))
- =:= 100),
- ?_assert(array:size(resize(array:set(7, undefined, new()))) =:= 0),
- ?_assert(array:size(resize(array:from_list([1,2,3,undefined])))
- =:= 3),
- ?_assert(array:size(
- resize(array:from_orddict([{3,0},{17,0},{99,undefined}])))
- =:= 18),
- ?_assertError(badarg, resize(foo, bad_argument))
- ].
+ ok.
-set_get_test_() ->
+set_get_test(_Config) ->
N0 = ?LEAFSIZE,
N1 = ?NODESIZE*N0,
- [?_assert(array:get(0, new()) =:= undefined),
- ?_assert(array:get(1, new()) =:= undefined),
- ?_assert(array:get(99999, new()) =:= undefined),
+ [?assert(array:get(0, new()) =:= undefined),
+ ?assert(array:get(1, new()) =:= undefined),
+ ?assert(array:get(99999, new()) =:= undefined),
- ?_assert(array:get(0, new(1)) =:= undefined),
- ?_assert(array:get(0, new(1,{default,0})) =:= 0),
- ?_assert(array:get(9, new(10)) =:= undefined),
+ ?assert(array:get(0, new(1)) =:= undefined),
+ ?assert(array:get(0, new(1,{default,0})) =:= 0),
+ ?assert(array:get(9, new(10)) =:= undefined),
- ?_assertError(badarg, array:get(0, new(fixed))),
- ?_assertError(badarg, array:get(1, new(1))),
- ?_assertError(badarg, array:get(-1, new(1))),
- ?_assertError(badarg, array:get(10, new(10))),
- ?_assertError(badarg, array:set(-1, foo, new(10))),
- ?_assertError(badarg, array:set(10, foo, no_array)),
+ ?assertError(badarg, array:get(0, new(fixed))),
+ ?assertError(badarg, array:get(1, new(1))),
+ ?assertError(badarg, array:get(-1, new(1))),
+ ?assertError(badarg, array:get(10, new(10))),
+ ?assertError(badarg, array:set(-1, foo, new(10))),
+ ?assertError(badarg, array:set(10, foo, no_array)),
- ?_assert(array:size(set(0, 17, new())) =:= 1),
- ?_assert(array:size(set(N1-1, 17, new())) =:= N1),
- ?_assert(array:size(set(0, 42, set(0, 17, new()))) =:= 1),
- ?_assert(array:size(set(9, 42, set(0, 17, new()))) =:= 10),
+ ?assert(array:size(set(0, 17, new())) =:= 1),
+ ?assert(array:size(set(N1-1, 17, new())) =:= N1),
+ ?assert(array:size(set(0, 42, set(0, 17, new()))) =:= 1),
+ ?assert(array:size(set(9, 42, set(0, 17, new()))) =:= 10),
- ?_assert(array:get(0, set(0, 17, new())) =:= 17),
- ?_assert(array:get(0, set(1, 17, new())) =:= undefined),
- ?_assert(array:get(1, set(1, 17, new())) =:= 17),
+ ?assert(array:get(0, set(0, 17, new())) =:= 17),
+ ?assert(array:get(0, set(1, 17, new())) =:= undefined),
+ ?assert(array:get(1, set(1, 17, new())) =:= 17),
- ?_assert(array:get(0, fix(set(0, 17, new()))) =:= 17),
- ?_assertError(badarg, array:get(1, fix(set(0, 17, new())))),
+ ?assert(array:get(0, fix(set(0, 17, new()))) =:= 17),
+ ?assertError(badarg, array:get(1, fix(set(0, 17, new())))),
- ?_assert(array:get(N1-2, set(N1-1, 17, new())) =:= undefined),
- ?_assert(array:get(N1-1, set(N1-1, 17, new())) =:= 17),
- ?_assertError(badarg, array:get(N1, fix(set(N1-1, 17, new())))),
+ ?assert(array:get(N1-2, set(N1-1, 17, new())) =:= undefined),
+ ?assert(array:get(N1-1, set(N1-1, 17, new())) =:= 17),
+ ?assertError(badarg, array:get(N1, fix(set(N1-1, 17, new())))),
- ?_assert(array:get(0, set(0, 42, set(0, 17, new()))) =:= 42),
+ ?assert(array:get(0, set(0, 42, set(0, 17, new()))) =:= 42),
array:get(12, array:set(12, foo, array:from_list(lists:seq(1, 12)))),
- ?_assertError(badarg, array:get(0, reset(11, new([{size,10}])))),
- ?_assertError(badarg, array:get(0, reset(-1, new([{size,10}])))),
- ?_assert(array:get(0, reset(0, new())) =:= undefined),
- ?_assert(array:get(0, reset(0, set(0, 17, new()))) =:= undefined),
- ?_assert(array:get(0, reset(9, set(9, 17, new()))) =:= undefined),
- ?_assert(array:get(0, reset(11, set(11, 17, new()))) =:= undefined),
- ?_assert(array:get(0, reset(11, set(12, 17, new()))) =:= undefined),
- ?_assert(array:get(0, reset(1, set(12, 17, new()))) =:= undefined),
- ?_assert(array:get(0, reset(11, new())) =:= undefined),
- ?_assert(array:get(0, reset(0, set(0, 17, new({default,42})))) =:= 42),
- ?_assert(array:get(0, reset(0, new({default,42}))) =:= 42)
+ ?assertError(badarg, array:get(0, reset(11, new([{size,10}])))),
+ ?assertError(badarg, array:get(0, reset(-1, new([{size,10}])))),
+ ?assert(array:get(0, reset(0, new())) =:= undefined),
+ ?assert(array:get(0, reset(0, set(127, set_cache, set(0, 17, new())))) =:= undefined),
+ ?assert(array:get(9, reset(9, set(127, set_cache, set(9, 17, new())))) =:= undefined),
+ ?assert(array:get(21, reset(21, set(127, set_cache, set(21, 17, new())))) =:= undefined),
+ ?assert(array:get(0, reset(32, set(127, set_cache, set(22, 17, new())))) =:= undefined),
+ ?assert(array:get(1, reset(1, set(22, 17, new()))) =:= undefined),
+ ?assert(array:get(0, reset(11, new())) =:= undefined),
+ ?assert(array:get(0, reset(11, new(31))) =:= undefined),
+ ?assert(array:get(0, reset(0, set(127, set_cache, set(0, 17, new({default,42}))))) =:= 42),
+ ?assert(array:get(0, reset(0, set(127, set_cache, new({default,42})))) =:= 42)
].
-to_list_test_() ->
+to_list_test(_Config) ->
N0 = ?LEAFSIZE,
- [?_assert([] =:= to_list(new())),
- ?_assert([undefined] =:= to_list(new(1))),
- ?_assert([undefined,undefined] =:= to_list(new(2))),
- ?_assert(lists:duplicate(N0,0) =:= to_list(new(N0,{default,0}))),
- ?_assert(lists:duplicate(N0+1,1) =:= to_list(new(N0+1,{default,1}))),
- ?_assert(lists:duplicate(N0+2,2) =:= to_list(new(N0+2,{default,2}))),
- ?_assert(lists:duplicate(666,6) =:= to_list(new(666,{default,6}))),
- ?_assert([1,2,3] =:= to_list(set(2,3,set(1,2,set(0,1,new()))))),
- ?_assert([3,2,1] =:= to_list(set(0,3,set(1,2,set(2,1,new()))))),
- ?_assert([1|lists:duplicate(N0-2,0)++[1]] =:=
- to_list(set(N0-1,1,set(0,1,new({default,0}))))),
- ?_assert([1|lists:duplicate(N0-1,0)++[1]] =:=
- to_list(set(N0,1,set(0,1,new({default,0}))))),
- ?_assert([1|lists:duplicate(N0,0)++[1]] =:=
- to_list(set(N0+1,1,set(0,1,new({default,0}))))),
- ?_assert([1|lists:duplicate(N0*3,0)++[1]] =:=
- to_list(set((N0*3)+1,1,set(0,1,new({default,0}))))),
- ?_assertError(badarg, to_list(no_array))
+ [?assert([] =:= to_list(new())),
+ ?assert([undefined] =:= to_list(new(1))),
+ ?assert([undefined,undefined] =:= to_list(new(2))),
+ ?assert(lists:duplicate(N0,0) =:= to_list(new(N0,{default,0}))),
+ ?assert(lists:duplicate(N0+1,1) =:= to_list(new(N0+1,{default,1}))),
+ ?assert(lists:duplicate(N0+2,2) =:= to_list(new(N0+2,{default,2}))),
+ ?assert(lists:duplicate(666,6) =:= to_list(new(666,{default,6}))),
+ ?assert([1,2,3] =:= to_list(set(2,3,set(1,2,set(0,1,new()))))),
+ ?assert([3,2,1] =:= to_list(set(0,3,set(1,2,set(2,1,new()))))),
+ ?assert([1|lists:duplicate(N0-2,0)++[1]] =:=
+ to_list(set(N0-1,1,set(0,1,new({default,0}))))),
+ ?assert([1|lists:duplicate(N0-1,0)++[1]] =:=
+ to_list(set(N0,1,set(0,1,new({default,0}))))),
+ ?assert([1|lists:duplicate(N0,0)++[1]] =:=
+ to_list(set(N0+1,1,set(0,1,new({default,0}))))),
+ ?assert([1|lists:duplicate(N0*3,0)++[1]] =:=
+ to_list(set((N0*3)+1,1,set(0,1,new({default,0}))))),
+ ?assertError(badarg, to_list(no_array))
].
-sparse_to_list_test_() ->
+sparse_to_list_test(_Config) ->
N0 = ?LEAFSIZE,
- [?_assert([] =:= sparse_to_list(new())),
- ?_assert([] =:= sparse_to_list(new(1))),
- ?_assert([] =:= sparse_to_list(new(1,{default,0}))),
- ?_assert([] =:= sparse_to_list(new(2))),
- ?_assert([] =:= sparse_to_list(new(2,{default,0}))),
- ?_assert([] =:= sparse_to_list(new(N0,{default,0}))),
- ?_assert([] =:= sparse_to_list(new(N0+1,{default,1}))),
- ?_assert([] =:= sparse_to_list(new(N0+2,{default,2}))),
- ?_assert([] =:= sparse_to_list(new(666,{default,6}))),
- ?_assert([1,2,3] =:= sparse_to_list(set(2,3,set(1,2,set(0,1,new()))))),
- ?_assert([3,2,1] =:= sparse_to_list(set(0,3,set(1,2,set(2,1,new()))))),
- ?_assert([0,1] =:= sparse_to_list(set(N0-1,1,set(0,0,new())))),
- ?_assert([0,1] =:= sparse_to_list(set(N0,1,set(0,0,new())))),
- ?_assert([0,1] =:= sparse_to_list(set(N0+1,1,set(0,0,new())))),
- ?_assert([0,1,2] =:= sparse_to_list(set(N0*10+1,2,set(N0*2+1,1,set(0,0,new()))))),
- ?_assertError(badarg, sparse_to_list(no_array))
+ [?assert([] =:= sparse_to_list(new())),
+ ?assert([] =:= sparse_to_list(new(1))),
+ ?assert([] =:= sparse_to_list(new(1,{default,0}))),
+ ?assert([] =:= sparse_to_list(new(2))),
+ ?assert([] =:= sparse_to_list(new(2,{default,0}))),
+ ?assert([] =:= sparse_to_list(new(N0,{default,0}))),
+ ?assert([] =:= sparse_to_list(new(N0+1,{default,1}))),
+ ?assert([] =:= sparse_to_list(new(N0+2,{default,2}))),
+ ?assert([] =:= sparse_to_list(new(666,{default,6}))),
+ ?assert([1,2,3] =:= sparse_to_list(set(2,3,set(1,2,set(0,1,new()))))),
+ ?assert([3,2,1] =:= sparse_to_list(set(0,3,set(1,2,set(2,1,new()))))),
+ ?assert([0,1] =:= sparse_to_list(set(N0-1,1,set(0,0,new())))),
+ ?assert([0,1] =:= sparse_to_list(set(N0,1,set(0,0,new())))),
+ ?assert([0,1] =:= sparse_to_list(set(N0+1,1,set(0,0,new())))),
+ ?assert([0,1,2] =:= sparse_to_list(set(N0*10+1,2,set(N0*2+1,1,set(0,0,new()))))),
+ ?assertError(badarg, sparse_to_list(no_array))
].
-from_list_test_() ->
+from_list_test(_Config) ->
N0 = ?LEAFSIZE,
N1 = ?NODESIZE*N0,
N2 = ?NODESIZE*N1,
N3 = ?NODESIZE*N2,
N4 = ?NODESIZE*N3,
- [?_assert(array:size(from_list([])) =:= 0),
- ?_assert(array:is_fix(from_list([])) =:= false),
- ?_assert(array:size(from_list([undefined])) =:= 1),
- ?_assert(array:is_fix(from_list([undefined])) =:= false),
- ?_assert(array:size(from_list(lists:seq(1,N1))) =:= N1),
- ?_assert(to_list(from_list(lists:seq(1,N0))) =:= lists:seq(1,N0)),
- ?_assert(to_list(from_list(lists:seq(1,N0+1))) =:= lists:seq(1,N0+1)),
- ?_assert(to_list(from_list(lists:seq(1,N0+2))) =:= lists:seq(1,N0+2)),
- ?_assert(to_list(from_list(lists:seq(1,N2))) =:= lists:seq(1,N2)),
- ?_assert(to_list(from_list(lists:seq(1,N2+1))) =:= lists:seq(1,N2+1)),
- ?_assert(to_list(from_list(lists:seq(0,N3))) =:= lists:seq(0,N3)),
- ?_assert(to_list(from_list(lists:seq(0,N4))) =:= lists:seq(0,N4)),
- ?_assertError(badarg, from_list([a,b,a,c|d])),
- ?_assertError(badarg, from_list(no_array))
+ [?assert(array:size(from_list([])) =:= 0),
+ ?assert(array:is_fix(from_list([])) =:= false),
+ ?assert(array:size(from_list([undefined])) =:= 1),
+ ?assert(array:is_fix(from_list([undefined])) =:= false),
+ ?assert(array:size(from_list(lists:seq(1,N1))) =:= N1),
+ ?assert(to_list(from_list(lists:seq(1,N0))) =:= lists:seq(1,N0)),
+ ?assert(to_list(from_list(lists:seq(1,N0+1))) =:= lists:seq(1,N0+1)),
+ ?assert(to_list(from_list(lists:seq(1,N0+2))) =:= lists:seq(1,N0+2)),
+ ?assert(to_list(from_list(lists:seq(1,N2))) =:= lists:seq(1,N2)),
+ ?assert(to_list(from_list(lists:seq(1,N2+1))) =:= lists:seq(1,N2+1)),
+ ?assert(to_list(from_list(lists:seq(0,N3))) =:= lists:seq(0,N3)),
+ ?assert(to_list(from_list(lists:seq(0,N4))) =:= lists:seq(0,N4)),
+ ?assertError(badarg, from_list([a,b,a,c|d])),
+ ?assertError(badarg, from_list(no_array))
].
-from_test_() ->
+from_test(_Config) ->
Seq = fun({N,Max}) ->
if N =< Max -> {N, {N+1, Max}};
true -> done
@@ -488,332 +441,330 @@ from_test_() ->
N2 = ?NODESIZE*N1,
N3 = ?NODESIZE*N2,
N4 = ?NODESIZE*N3,
- [?_assert(array:size(from(Seq, {1,0})) =:= 0),
- ?_assert(array:is_fix(from(Seq, {1,0})) =:= false),
- ?_assert(array:size(from(Seq, {1,1})) =:= 1),
- ?_assert(array:is_fix(from(Seq, {1,1})) =:= false),
- ?_assert(to_list(from(Seq, {1,N0-1})) =:= lists:seq(1,N0-1)),
- ?_assert(to_list(from(Seq, {1,N0})) =:= lists:seq(1,N0)),
- ?_assert(to_list(from(Seq, {1,N0+1})) =:= lists:seq(1,N0+1)),
- ?_assert(to_list(from(Seq, {1,N0+2})) =:= lists:seq(1,N0+2)),
- ?_assert(to_list(from(Seq, {1,N2-1})) =:= lists:seq(1,N2-1)),
- ?_assert(to_list(from(Seq, {1,N2})) =:= lists:seq(1,N2)),
- ?_assert(to_list(from(Seq, {1,N2+1})) =:= lists:seq(1,N2+1)),
- ?_assert(to_list(from(Seq, {0,N3})) =:= lists:seq(0,N3)),
- ?_assert(to_list(from(Seq, {0,N4})) =:= lists:seq(0,N4)),
- ?_assert(array:size(from(Seq, {1,N1})) =:= N1),
- ?_assertError(badarg, from(fun(A) -> A end, foo)),
- ?_assertError(badarg, from(no_fun, foo))
+ [?assert(array:size(from(Seq, {1,0})) =:= 0),
+ ?assert(array:is_fix(from(Seq, {1,0})) =:= false),
+ ?assert(array:size(from(Seq, {1,1})) =:= 1),
+ ?assert(array:is_fix(from(Seq, {1,1})) =:= false),
+ ?assert(to_list(from(Seq, {1,N0-1})) =:= lists:seq(1,N0-1)),
+ ?assert(to_list(from(Seq, {1,N0})) =:= lists:seq(1,N0)),
+ ?assert(to_list(from(Seq, {1,N0+1})) =:= lists:seq(1,N0+1)),
+ ?assert(to_list(from(Seq, {1,N0+2})) =:= lists:seq(1,N0+2)),
+ ?assert(to_list(from(Seq, {1,N2-1})) =:= lists:seq(1,N2-1)),
+ ?assert(to_list(from(Seq, {1,N2})) =:= lists:seq(1,N2)),
+ ?assert(to_list(from(Seq, {1,N2+1})) =:= lists:seq(1,N2+1)),
+ ?assert(to_list(from(Seq, {0,N3})) =:= lists:seq(0,N3)),
+ ?assert(to_list(from(Seq, {0,N4})) =:= lists:seq(0,N4)),
+ ?assert(array:size(from(Seq, {1,N1})) =:= N1),
+ ?assertError(badarg, from(fun(A) -> A end, foo)),
+ ?assertError(badarg, from(no_fun, foo))
].
-to_orddict_test_() ->
+to_orddict_test(_Config) ->
N0 = ?LEAFSIZE,
- [?_assert([] =:= to_orddict(new())),
- ?_assert([{0,undefined}] =:= to_orddict(new(1))),
- ?_assert([{0,undefined},{1,undefined}] =:= to_orddict(new(2))),
- ?_assert([{N,0}||N<-lists:seq(0,N0-1)]
- =:= to_orddict(new(N0,{default,0}))),
- ?_assert([{N,1}||N<-lists:seq(0,N0)]
- =:= to_orddict(new(N0+1,{default,1}))),
- ?_assert([{N,2}||N<-lists:seq(0,N0+1)]
- =:= to_orddict(new(N0+2,{default,2}))),
- ?_assert([{N,6}||N<-lists:seq(0,665)]
- =:= to_orddict(new(666,{default,6}))),
- ?_assert([{0,1},{1,2},{2,3}] =:=
- to_orddict(set(2,3,set(1,2,set(0,1,new()))))),
- ?_assert([{0,3},{1,2},{2,1}] =:=
- to_orddict(set(0,3,set(1,2,set(2,1,new()))))),
- ?_assert([{0,1}|[{N,0}||N<-lists:seq(1,N0-2)]++[{N0-1,1}]]
- =:= to_orddict(set(N0-1,1,set(0,1,new({default,0}))))),
- ?_assert([{0,1}|[{N,0}||N<-lists:seq(1,N0-1)]++[{N0,1}]]
- =:= to_orddict(set(N0,1,set(0,1,new({default,0}))))),
- ?_assert([{0,1}|[{N,0}||N<-lists:seq(1,N0)]++[{N0+1,1}]]
- =:= to_orddict(set(N0+1,1,set(0,1,new({default,0}))))),
- ?_assert([{0,0} | [{N,undefined}||N<-lists:seq(1,N0*2)]] ++
- [{N0*2+1,1} | [{N,undefined}||N<-lists:seq(N0*2+2,N0*10)]] ++
- [{N0*10+1,2}] =:=
- to_orddict(set(N0*10+1,2,set(N0*2+1,1,set(0,0,new()))))),
- ?_assertError(badarg, to_orddict(no_array))
+ [?assert([] =:= to_orddict(new())),
+ ?assert([{0,undefined}] =:= to_orddict(new(1))),
+ ?assert([{0,undefined},{1,undefined}] =:= to_orddict(new(2))),
+ ?assert([{N,0}||N<-lists:seq(0,N0-1)]
+ =:= to_orddict(new(N0,{default,0}))),
+ ?assert([{N,1}||N<-lists:seq(0,N0)]
+ =:= to_orddict(new(N0+1,{default,1}))),
+ ?assert([{N,2}||N<-lists:seq(0,N0+1)]
+ =:= to_orddict(new(N0+2,{default,2}))),
+ ?assert([{N,6}||N<-lists:seq(0,665)]
+ =:= to_orddict(new(666,{default,6}))),
+ ?assert([{0,1},{1,2},{2,3}] =:=
+ to_orddict(set(2,3,set(1,2,set(0,1,new()))))),
+ ?assert([{0,3},{1,2},{2,1}] =:=
+ to_orddict(set(0,3,set(1,2,set(2,1,new()))))),
+ ?assert([{0,1}|[{N,0}||N<-lists:seq(1,N0-2)]++[{N0-1,1}]]
+ =:= to_orddict(set(N0-1,1,set(0,1,new({default,0}))))),
+ ?assert([{0,1}|[{N,0}||N<-lists:seq(1,N0-1)]++[{N0,1}]]
+ =:= to_orddict(set(N0,1,set(0,1,new({default,0}))))),
+ ?assert([{0,1}|[{N,0}||N<-lists:seq(1,N0)]++[{N0+1,1}]]
+ =:= to_orddict(set(N0+1,1,set(0,1,new({default,0}))))),
+ ?assert([{0,0} | [{N,undefined}||N<-lists:seq(1,N0*2)]] ++
+ [{N0*2+1,1} | [{N,undefined}||N<-lists:seq(N0*2+2,N0*10)]] ++
+ [{N0*10+1,2}] =:=
+ to_orddict(set(N0*10+1,2,set(N0*2+1,1,set(0,0,new()))))),
+ ?assertError(badarg, to_orddict(no_array))
].
-sparse_to_orddict_test_() ->
+sparse_to_orddict_test(_Config) ->
N0 = ?LEAFSIZE,
- [?_assert([] =:= sparse_to_orddict(new())),
- ?_assert([] =:= sparse_to_orddict(new(1))),
- ?_assert([] =:= sparse_to_orddict(new(1,{default,0}))),
- ?_assert([] =:= sparse_to_orddict(new(2))),
- ?_assert([] =:= sparse_to_orddict(new(2,{default,0}))),
- ?_assert([] =:= sparse_to_orddict(new(N0,{default,0}))),
- ?_assert([] =:= sparse_to_orddict(new(N0+1,{default,1}))),
- ?_assert([] =:= sparse_to_orddict(new(N0+2,{default,2}))),
- ?_assert([] =:= sparse_to_orddict(new(666,{default,6}))),
- ?_assert([{0,1},{1,2},{2,3}] =:=
- sparse_to_orddict(set(2,3,set(1,2,set(0,1,new()))))),
- ?_assert([{0,3},{1,2},{2,1}] =:=
- sparse_to_orddict(set(0,3,set(1,2,set(2,1,new()))))),
- ?_assert([{0,1},{N0-1,1}] =:=
- sparse_to_orddict(set(N0-1,1,set(0,1,new({default,0}))))),
- ?_assert([{0,1},{N0,1}] =:=
- sparse_to_orddict(set(N0,1,set(0,1,new({default,0}))))),
- ?_assert([{0,1},{N0+1,1}] =:=
- sparse_to_orddict(set(N0+1,1,set(0,1,new({default,0}))))),
- ?_assert([{0,0},{N0*2+1,1},{N0*10+1,2}] =:=
- sparse_to_orddict(set(N0*10+1,2,set(N0*2+1,1,set(0,0,new()))))),
- ?_assertError(badarg, sparse_to_orddict(no_array))
+ [?assert([] =:= sparse_to_orddict(new())),
+ ?assert([] =:= sparse_to_orddict(new(1))),
+ ?assert([] =:= sparse_to_orddict(new(1,{default,0}))),
+ ?assert([] =:= sparse_to_orddict(new(2))),
+ ?assert([] =:= sparse_to_orddict(new(2,{default,0}))),
+ ?assert([] =:= sparse_to_orddict(new(N0,{default,0}))),
+ ?assert([] =:= sparse_to_orddict(new(N0+1,{default,1}))),
+ ?assert([] =:= sparse_to_orddict(new(N0+2,{default,2}))),
+ ?assert([] =:= sparse_to_orddict(new(666,{default,6}))),
+ ?assert([{0,1},{1,2},{2,3}] =:=
+ sparse_to_orddict(set(2,3,set(1,2,set(0,1,new()))))),
+ ?assert([{0,3},{1,2},{2,1}] =:=
+ sparse_to_orddict(set(0,3,set(1,2,set(2,1,new()))))),
+ ?assert([{0,1},{N0-1,1}] =:=
+ sparse_to_orddict(set(N0-1,1,set(0,1,new({default,0}))))),
+ ?assert([{0,1},{N0,1}] =:=
+ sparse_to_orddict(set(N0,1,set(0,1,new({default,0}))))),
+ ?assert([{0,1},{N0+1,1}] =:=
+ sparse_to_orddict(set(N0+1,1,set(0,1,new({default,0}))))),
+ ?assert([{0,0},{N0*2+1,1},{N0*10+1,2}] =:=
+ sparse_to_orddict(set(N0*10+1,2,set(N0*2+1,1,set(0,0,new()))))),
+ ?assertError(badarg, sparse_to_orddict(no_array))
].
-from_orddict_test_() ->
+from_orddict_test(_Config) ->
N0 = ?LEAFSIZE,
N1 = ?NODESIZE*N0,
N2 = ?NODESIZE*N1,
N3 = ?NODESIZE*N2,
N4 = ?NODESIZE*N3,
- [?_assert(array:size(from_orddict([])) =:= 0),
- ?_assert(array:is_fix(from_orddict([])) =:= false),
- ?_assert(array:size(from_orddict([{0,undefined}])) =:= 1),
- ?_assert(array:is_fix(from_orddict([{0,undefined}])) =:= false),
- ?_assert(array:size(from_orddict([{N0-1,undefined}])) =:= N0),
- ?_assert(array:size(from_orddict([{N,0}||N<-lists:seq(0,N1-1)]))
- =:= N1),
- ?_assertError({badarg,_}, from_orddict([foo])),
- ?_assertError({badarg,_}, from_orddict([{200,foo},{1,bar}])),
- ?_assertError({badarg,_}, from_orddict([{N,0}||N<-lists:seq(0,N0-1)] ++ not_a_list)),
- ?_assertError(badarg, from_orddict(no_array)),
-
-
- ?_assert(?LET(L, [{N,0}||N<-lists:seq(0,N0-1)],
- L =:= to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N,0}||N<-lists:seq(0,N0)],
- L =:= to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N,0}||N<-lists:seq(0,N2-1)],
- L =:= to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N,0}||N<-lists:seq(0,N2)],
- L =:= to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N,0}||N<-lists:seq(0,N3-1)],
- L =:= to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N,0}||N<-lists:seq(0,N4-1)],
- L =:= to_orddict(from_orddict(L)))),
+ [?assert(array:size(from_orddict([])) =:= 0),
+ ?assert(array:is_fix(from_orddict([])) =:= false),
+ ?assert(array:size(from_orddict([{0,undefined}])) =:= 1),
+ ?assert(array:is_fix(from_orddict([{0,undefined}])) =:= false),
+ ?assert(array:size(from_orddict([{N0-1,undefined}])) =:= N0),
+ ?assert(array:size(from_orddict([{N,0}||N<-lists:seq(0,N1-1)]))
+ =:= N1),
+ ?assertError({badarg,_}, from_orddict([foo])),
+ ?assertError({badarg,_}, from_orddict([{200,foo},{1,bar}])),
+ ?assertError({badarg,_}, from_orddict([{N,0}||N<-lists:seq(0,N0-1)] ++ not_a_list)),
+ ?assertError(badarg, from_orddict(no_array)),
+
+
+ ?assert(?LET(L, [{N,0}||N<-lists:seq(0,N0-1)],
+ L =:= to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{N,0}||N<-lists:seq(0,N0)],
+ L =:= to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{N,0}||N<-lists:seq(0,N2-1)],
+ L =:= to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{N,0}||N<-lists:seq(0,N2)],
+ L =:= to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{N,0}||N<-lists:seq(0,N3-1)],
+ L =:= to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{N,0}||N<-lists:seq(0,N4-1)],
+ L =:= to_orddict(from_orddict(L)))),
%% Hole in the begining
- ?_assert(?LET(L, [{0,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N0,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N1,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N3,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N4,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N0-1,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N1-1,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N3-1,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{N4-1,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
-
- %% Hole in middle
-
- ?_assert(?LET(L, [{0,0},{N0,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{0,0},{N1,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{0,0},{N3,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{0,0},{N4,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{0,0},{N0-1,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{0,0},{N1-1,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{0,0},{N3-1,0}],
- L =:= sparse_to_orddict(from_orddict(L)))),
- ?_assert(?LET(L, [{0,0},{N4-1,0}],
- L =:= sparse_to_orddict(from_orddict(L))))
-
+ ?assert(?LET(L, [{0,0}],
+ L =:= sparse_to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{N0,0}],
+ L =:= sparse_to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{N1,0}],
+ L =:= sparse_to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{N3,0}],
+ L =:= sparse_to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{N4,0}],
+ L =:= sparse_to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{N0-1,0}],
+ L =:= sparse_to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{N1-1,0}],
+ L =:= sparse_to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{N3-1,0}],
+ L =:= sparse_to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{N4-1,0}],
+ L =:= sparse_to_orddict(from_orddict(L)))),
+
+ %% Hole in middle
+
+ ?assert(?LET(L, [{0,0},{N0,0}],
+ L =:= sparse_to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{0,0},{N1,0}],
+ L =:= sparse_to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{0,0},{N3,0}],
+ L =:= sparse_to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{0,0},{N4,0}],
+ L =:= sparse_to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{0,0},{N0-1,0}],
+ L =:= sparse_to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{0,0},{N1-1,0}],
+ L =:= sparse_to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{0,0},{N3-1,0}],
+ L =:= sparse_to_orddict(from_orddict(L)))),
+ ?assert(?LET(L, [{0,0},{N4-1,0}],
+ L =:= sparse_to_orddict(from_orddict(L))))
+
].
-map_test_() ->
+map_test(_Config) ->
N0 = ?LEAFSIZE,
Id = fun (_,X) -> X end,
Plus = fun(N) -> fun (_,X) -> X+N end end,
Default = fun(_K,undefined) -> no_value;
- (K,V) -> K+V
- end,
- [?_assertError(badarg, map([], new())),
- ?_assertError(badarg, map([], new(10))),
- ?_assert(to_list(map(Id, new())) =:= []),
- ?_assert(to_list(map(Id, new(1))) =:= [undefined]),
- ?_assert(to_list(map(Id, new(5,{default,0}))) =:= [0,0,0,0,0]),
- ?_assert(to_list(map(Id, from_list([1,2,3,4]))) =:= [1,2,3,4]),
- ?_assert(to_list(map(Plus(1), from_list([0,1,2,3]))) =:= [1,2,3,4]),
- ?_assert(to_list(map(Plus(-1), from_list(lists:seq(1,11))))
- =:= lists:seq(0,10)),
- ?_assert(to_list(map(Plus(11), from_list(lists:seq(0,99999))))
- =:= lists:seq(11,100010)),
- ?_assert([{0,0},{N0*2+1,N0*2+1+1},{N0*100+1,N0*100+1+2}] =:=
- sparse_to_orddict((map(Default,
- set(N0*100+1,2,
- set(N0*2+1,1,
- set(0,0,new())))))#array{default = no_value}))
+ (K,V) -> K+V
+ end,
+ [?assertError(badarg, map([], new())),
+ ?assertError(badarg, map([], new(10))),
+ ?assert(to_list(map(Id, new())) =:= []),
+ ?assert(to_list(map(Id, new(1))) =:= [undefined]),
+ ?assert(to_list(map(Id, new(5,{default,0}))) =:= [0,0,0,0,0]),
+ ?assert(to_list(map(Id, from_list([1,2,3,4]))) =:= [1,2,3,4]),
+ ?assert(to_list(map(Plus(1), from_list([0,1,2,3]))) =:= [1,2,3,4]),
+ ?assert(to_list(map(Plus(-1), from_list(lists:seq(1,11))))
+ =:= lists:seq(0,10)),
+ ?assert(to_list(map(Plus(11), from_list(lists:seq(0,99999))))
+ =:= lists:seq(11,100010)),
+ ?assert([{0,0},{N0*2+1,N0*2+1+1},{N0*100+1,N0*100+1+2}] =:=
+ sparse_to_orddict((map(Default,
+ set(N0*100+1,2,
+ set(N0*2+1,1,
+ set(0,0,new())))))#array{default = no_value}))
].
-sparse_map_test_() ->
+sparse_map_test(_Config) ->
N0 = ?LEAFSIZE,
Id = fun (_,X) -> X end,
Plus = fun(N) -> fun (_,X) -> X+N end end,
KeyPlus = fun (K,X) -> K+X end,
- [?_assertError(badarg, sparse_map([], new())),
- ?_assertError(badarg, sparse_map([], new(10))),
- ?_assert(to_list(sparse_map(Id, new())) =:= []),
- ?_assert(to_list(sparse_map(Id, new(1))) =:= [undefined]),
- ?_assert(to_list(sparse_map(Id, new(5,{default,0}))) =:= [0,0,0,0,0]),
- ?_assert(to_list(sparse_map(Id, from_list([1,2,3,4]))) =:= [1,2,3,4]),
- ?_assert(to_list(sparse_map(Plus(1), from_list([0,1,2,3])))
- =:= [1,2,3,4]),
- ?_assert(to_list(sparse_map(Plus(-1), from_list(lists:seq(1,11))))
- =:= lists:seq(0,10)),
- ?_assert(to_list(sparse_map(Plus(11), from_list(lists:seq(0,99999))))
- =:= lists:seq(11,100010)),
- ?_assert(to_list(sparse_map(Plus(1), set(1,1,new({default,0}))))
- =:= [0,2]),
- ?_assert(to_list(sparse_map(Plus(1),
- set(3,4,set(0,1,new({default,0})))))
- =:= [2,0,0,5]),
- ?_assert(to_list(sparse_map(Plus(1),
- set(9,9,set(1,1,new({default,0})))))
- =:= [0,2,0,0,0,0,0,0,0,10]),
- ?_assert([{0,0},{N0*2+1,N0*2+1+1},{N0*100+1,N0*100+1+2}] =:=
- sparse_to_orddict(sparse_map(KeyPlus,
- set(N0*100+1,2,
- set(N0*2+1,1,
- set(0,0,new()))))))
+ [?assertError(badarg, sparse_map([], new())),
+ ?assertError(badarg, sparse_map([], new(10))),
+ ?assert(to_list(sparse_map(Id, new())) =:= []),
+ ?assert(to_list(sparse_map(Id, new(1))) =:= [undefined]),
+ ?assert(to_list(sparse_map(Id, new(5,{default,0}))) =:= [0,0,0,0,0]),
+ ?assert(to_list(sparse_map(Id, from_list([1,2,3,4]))) =:= [1,2,3,4]),
+ ?assert(to_list(sparse_map(Plus(1), from_list([0,1,2,3])))
+ =:= [1,2,3,4]),
+ ?assert(to_list(sparse_map(Plus(-1), from_list(lists:seq(1,11))))
+ =:= lists:seq(0,10)),
+ ?assert(to_list(sparse_map(Plus(11), from_list(lists:seq(0,99999))))
+ =:= lists:seq(11,100010)),
+ ?assert(to_list(sparse_map(Plus(1), set(1,1,new({default,0}))))
+ =:= [0,2]),
+ ?assert(to_list(sparse_map(Plus(1),
+ set(3,4,set(0,1,new({default,0})))))
+ =:= [2,0,0,5]),
+ ?assert(to_list(sparse_map(Plus(1),
+ set(9,9,set(1,1,new({default,0})))))
+ =:= [0,2,0,0,0,0,0,0,0,10]),
+ ?assert([{0,0},{N0*2+1,N0*2+1+1},{N0*100+1,N0*100+1+2}] =:=
+ sparse_to_orddict(sparse_map(KeyPlus,
+ set(N0*100+1,2,
+ set(N0*2+1,1,
+ set(0,0,new()))))))
].
-foldl_test_() ->
+foldl_test(_Config) ->
N0 = ?LEAFSIZE,
Count = fun (_,_,N) -> N+1 end,
Sum = fun (_,X,N) -> N+X end,
Reverse = fun (_,X,L) -> [X|L] end,
Vals = fun(_K,undefined,{C,L}) -> {C+1,L};
- (K,X,{C,L}) -> {C,[K+X|L]}
- end,
- [?_assertError(badarg, foldl([], 0, new())),
- ?_assertError(badarg, foldl([], 0, new(10))),
- ?_assert(foldl(Count, 0, new()) =:= 0),
- ?_assert(foldl(Count, 0, new(1)) =:= 1),
- ?_assert(foldl(Count, 0, new(10)) =:= 10),
- ?_assert(foldl(Count, 0, from_list([1,2,3,4])) =:= 4),
- ?_assert(foldl(Count, 10, from_list([0,1,2,3,4,5,6,7,8,9])) =:= 20),
- ?_assert(foldl(Count, 1000, from_list(lists:seq(0,999))) =:= 2000),
- ?_assert(foldl(Sum, 0, from_list(lists:seq(0,10))) =:= 55),
- ?_assert(foldl(Reverse, [], from_list(lists:seq(0,1000)))
- =:= lists:reverse(lists:seq(0,1000))),
- ?_assert({999,[N0*100+1+2,N0*2+1+1,0]} =:=
- foldl(Vals, {0,[]},
- set(N0*100+1,2,
- set(N0*2+1,1,
- set(0,0,new())))))
-
+ (K,X,{C,L}) -> {C,[K+X|L]}
+ end,
+ [?assertError(badarg, foldl([], 0, new())),
+ ?assertError(badarg, foldl([], 0, new(10))),
+ ?assert(foldl(Count, 0, new()) =:= 0),
+ ?assert(foldl(Count, 0, new(1)) =:= 1),
+ ?assert(foldl(Count, 0, new(10)) =:= 10),
+ ?assert(foldl(Count, 0, from_list([1,2,3,4])) =:= 4),
+ ?assert(foldl(Count, 10, from_list([0,1,2,3,4,5,6,7,8,9])) =:= 20),
+ ?assert(foldl(Count, 1000, from_list(lists:seq(0,999))) =:= 2000),
+ ?assert(foldl(Sum, 0, from_list(lists:seq(0,10))) =:= 55),
+ ?assert(foldl(Reverse, [], from_list(lists:seq(0,1000)))
+ =:= lists:reverse(lists:seq(0,1000))),
+ ?assert({N0*100-1,[N0*100+1+2,N0*2+1+1,0]} =:=
+ foldl(Vals, {0,[]},
+ set(N0*100+1,2,
+ set(N0*2+1,1,
+ set(0,0,new())))))
].
-sparse_foldl_test_() ->
+sparse_foldl_test(_Config) ->
N0 = ?LEAFSIZE,
Count = fun (_,_,N) -> N+1 end,
Sum = fun (_,X,N) -> N+X end,
Reverse = fun (_,X,L) -> [X|L] end,
Vals = fun(_K,undefined,{C,L}) -> {C+1,L};
- (K,X,{C,L}) -> {C,[K+X|L]}
- end,
- [?_assertError(badarg, sparse_foldl([], 0, new())),
- ?_assertError(badarg, sparse_foldl([], 0, new(10))),
- ?_assert(sparse_foldl(Count, 0, new()) =:= 0),
- ?_assert(sparse_foldl(Count, 0, new(1)) =:= 0),
- ?_assert(sparse_foldl(Count, 0, new(10,{default,1})) =:= 0),
- ?_assert(sparse_foldl(Count, 0, from_list([0,1,2,3,4],0)) =:= 4),
- ?_assert(sparse_foldl(Count, 0, from_list([0,1,2,3,4,5,6,7,8,9,0],0))
- =:= 9),
- ?_assert(sparse_foldl(Count, 0, from_list(lists:seq(0,999),0))
- =:= 999),
- ?_assert(sparse_foldl(Sum, 0, from_list(lists:seq(0,10), 5)) =:= 50),
- ?_assert(sparse_foldl(Reverse, [], from_list(lists:seq(0,1000), 0))
- =:= lists:reverse(lists:seq(1,1000))),
- ?_assert({0,[N0*100+1+2,N0*2+1+1,0]} =:=
- sparse_foldl(Vals, {0,[]},
- set(N0*100+1,2,
- set(N0*2+1,1,
- set(0,0,new())))))
+ (K,X,{C,L}) -> {C,[K+X|L]}
+ end,
+ [?assertError(badarg, sparse_foldl([], 0, new())),
+ ?assertError(badarg, sparse_foldl([], 0, new(10))),
+ ?assert(sparse_foldl(Count, 0, new()) =:= 0),
+ ?assert(sparse_foldl(Count, 0, new(1)) =:= 0),
+ ?assert(sparse_foldl(Count, 0, new(10,{default,1})) =:= 0),
+ ?assert(sparse_foldl(Count, 0, from_list([0,1,2,3,4],0)) =:= 4),
+ ?assert(sparse_foldl(Count, 0, from_list([0,1,2,3,4,5,6,7,8,9,0],0))
+ =:= 9),
+ ?assert(sparse_foldl(Count, 0, from_list(lists:seq(0,999),0))
+ =:= 999),
+ ?assert(sparse_foldl(Sum, 0, from_list(lists:seq(0,10), 5)) =:= 50),
+ ?assert(sparse_foldl(Reverse, [], from_list(lists:seq(0,1000), 0))
+ =:= lists:reverse(lists:seq(1,1000))),
+ ?assert({0,[N0*100+1+2,N0*2+1+1,0]} =:=
+ sparse_foldl(Vals, {0,[]},
+ set(N0*100+1,2,
+ set(N0*2+1,1,
+ set(0,0,new())))))
].
-foldr_test_() ->
+foldr_test(_Config) ->
N0 = ?LEAFSIZE,
Count = fun (_,_,N) -> N+1 end,
Sum = fun (_,X,N) -> N+X end,
List = fun (_,X,L) -> [X|L] end,
Vals = fun(_K,undefined,{C,L}) -> {C+1,L};
- (K,X,{C,L}) -> {C,[K+X|L]}
- end,
- [?_assertError(badarg, foldr([], 0, new())),
- ?_assertError(badarg, foldr([], 0, new(10))),
- ?_assert(foldr(Count, 0, new()) =:= 0),
- ?_assert(foldr(Count, 0, new(1)) =:= 1),
- ?_assert(foldr(Count, 0, new(10)) =:= 10),
- ?_assert(foldr(Count, 0, from_list([1,2,3,4])) =:= 4),
- ?_assert(foldr(Count, 10, from_list([0,1,2,3,4,5,6,7,8,9])) =:= 20),
- ?_assert(foldr(Count, 1000, from_list(lists:seq(0,999))) =:= 2000),
- ?_assert(foldr(Sum, 0, from_list(lists:seq(0,10))) =:= 55),
- ?_assert(foldr(List, [], from_list(lists:seq(0,1000)))
- =:= lists:seq(0,1000)),
- ?_assert({999,[0,N0*2+1+1,N0*100+1+2]} =:=
- foldr(Vals, {0,[]},
- set(N0*100+1,2,
- set(N0*2+1,1,
- set(0,0,new())))))
-
+ (K,X,{C,L}) -> {C,[K+X|L]}
+ end,
+ [?assertError(badarg, foldr([], 0, new())),
+ ?assertError(badarg, foldr([], 0, new(10))),
+ ?assert(foldr(Count, 0, new()) =:= 0),
+ ?assert(foldr(Count, 0, new(1)) =:= 1),
+ ?assert(foldr(Count, 0, new(10)) =:= 10),
+ ?assert(foldr(Count, 0, from_list([1,2,3,4])) =:= 4),
+ ?assert(foldr(Count, 10, from_list([0,1,2,3,4,5,6,7,8,9])) =:= 20),
+ ?assert(foldr(Count, 1000, from_list(lists:seq(0,999))) =:= 2000),
+ ?assert(foldr(Sum, 0, from_list(lists:seq(0,10))) =:= 55),
+ ?assert(foldr(List, [], from_list(lists:seq(0,1000)))
+ =:= lists:seq(0,1000)),
+ ?assert({N0*100-1,[0,N0*2+1+1,N0*100+1+2]} =:=
+ foldr(Vals, {0,[]},
+ set(N0*100+1,2,
+ set(N0*2+1,1,
+ set(0,0,new())))))
].
-sparse_foldr_test_() ->
+sparse_foldr_test(_Config) ->
N0 = ?LEAFSIZE,
Count = fun (_,_,N) -> N+1 end,
Sum = fun (_,X,N) -> N+X end,
List = fun (_,X,L) -> [X|L] end,
Vals = fun(_K,undefined,{C,L}) -> {C+1,L};
- (K,X,{C,L}) -> {C,[K+X|L]}
- end,
- [?_assertError(badarg, sparse_foldr([], 0, new())),
- ?_assertError(badarg, sparse_foldr([], 0, new(10))),
- ?_assert(sparse_foldr(Count, 0, new()) =:= 0),
- ?_assert(sparse_foldr(Count, 0, new(1)) =:= 0),
- ?_assert(sparse_foldr(Count, 0, new(10,{default,1})) =:= 0),
- ?_assert(sparse_foldr(Count, 0, from_list([0,1,2,3,4],0)) =:= 4),
- ?_assert(sparse_foldr(Count, 0, from_list([0,1,2,3,4,5,6,7,8,9,0],0))
- =:= 9),
- ?_assert(sparse_foldr(Count, 0, from_list(lists:seq(0,999),0))
- =:= 999),
- ?_assert(sparse_foldr(Sum, 0, from_list(lists:seq(0,10),5)) =:= 50),
- ?_assert(sparse_foldr(List, [], from_list(lists:seq(0,1000),0))
- =:= lists:seq(1,1000)),
-
- ?_assert(sparse_size(new()) =:= 0),
- ?_assert(sparse_size(new(8)) =:= 0),
- ?_assert(sparse_size(array:set(7, 0, new())) =:= 8),
- ?_assert(sparse_size(array:set(7, 0, new(10))) =:= 8),
- ?_assert(sparse_size(array:set(99, 0, new(10,{fixed,false})))
- =:= 100),
- ?_assert(sparse_size(array:set(7, undefined, new())) =:= 0),
- ?_assert(sparse_size(array:from_list([1,2,3,undefined])) =:= 3),
- ?_assert(sparse_size(array:from_orddict([{3,0},{17,0},{99,undefined}]))
- =:= 18),
- ?_assert({0,[0,N0*2+1+1,N0*100+1+2]} =:=
- sparse_foldr(Vals, {0,[]},
- set(N0*100+1,2,
- set(N0*2+1,1,
- set(0,0,new())))))
+ (K,X,{C,L}) -> {C,[K+X|L]}
+ end,
+ [?assertError(badarg, sparse_foldr([], 0, new())),
+ ?assertError(badarg, sparse_foldr([], 0, new(10))),
+ ?assert(sparse_foldr(Count, 0, new()) =:= 0),
+ ?assert(sparse_foldr(Count, 0, new(1)) =:= 0),
+ ?assert(sparse_foldr(Count, 0, new(10,{default,1})) =:= 0),
+ ?assert(sparse_foldr(Count, 0, from_list([0,1,2,3,4],0)) =:= 4),
+ ?assert(sparse_foldr(Count, 0, from_list([0,1,2,3,4,5,6,7,8,9,0],0))
+ =:= 9),
+ ?assert(sparse_foldr(Count, 0, from_list(lists:seq(0,999),0))
+ =:= 999),
+ ?assert(sparse_foldr(Sum, 0, from_list(lists:seq(0,10),5)) =:= 50),
+ ?assert(sparse_foldr(List, [], from_list(lists:seq(0,1000),0))
+ =:= lists:seq(1,1000)),
+
+ ?assert(sparse_size(new()) =:= 0),
+ ?assert(sparse_size(new(8)) =:= 0),
+ ?assert(sparse_size(array:set(7, 0, new())) =:= 8),
+ ?assert(sparse_size(array:set(7, 0, new(10))) =:= 8),
+ ?assert(sparse_size(array:set(99, 0, new(10,{fixed,false})))
+ =:= 100),
+ ?assert(sparse_size(array:set(7, undefined, new())) =:= 0),
+ ?assert(sparse_size(array:from_list([1,2,3,undefined])) =:= 3),
+ ?assert(sparse_size(array:from_orddict([{3,0},{17,0},{99,undefined}]))
+ =:= 18),
+ ?assert({0,[0,N0*2+1+1,N0*100+1+2]} =:=
+ sparse_foldr(Vals, {0,[]},
+ set(N0*100+1,2,
+ set(N0*2+1,1,
+ set(0,0,new())))))
].
import_export(_Config) ->
@@ -828,7 +779,7 @@ import_export(_Config) ->
done
end,
- ?_assert(FloatBin =:= array:foldl(ToFloat32, <<>>, array:from(FromFloat32, FloatBin))),
+ ?assert(FloatBin =:= array:foldl(ToFloat32, <<>>, array:from(FromFloat32, FloatBin))),
RGBBin = << <<N:8, N:8, N:8>> || N <- lists:seq(1, 256)>>,
RGB2Bin = fun(_K, {R,G,B}, Acc) ->
<<Acc/binary, R:8, G:8, B:8>>
@@ -838,29 +789,9 @@ import_export(_Config) ->
(<<>>) ->
done
end,
- ?_assert(RGBBin =:= array:foldl(RGB2Bin, <<>>, array:from(Bin2RGB, RGBBin))),
+ ?assert(RGBBin =:= array:foldl(RGB2Bin, <<>>, array:from(Bin2RGB, RGBBin))),
ok.
doctests(Config) when is_list(Config) ->
shell_docs:test(array, []).
-
-
-new_test(Config) when is_list(Config) -> new_test_(), ok.
-fix_test(Config) when is_list(Config) -> fix_test_(), ok.
-relax_test(Config) when is_list(Config) -> relax_test_(), ok.
-resize_test(Config) when is_list(Config) -> resize_test_(), ok.
-set_get_test(Config) when is_list(Config) -> set_get_test_(), ok.
-to_list_test(Config) when is_list(Config) -> to_list_test_(), ok.
-sparse_to_list_test(Config) when is_list(Config) -> sparse_to_list_test_(), ok.
-from_list_test(Config) when is_list(Config) -> from_list_test_(), ok.
-to_orddict_test(Config) when is_list(Config) -> to_orddict_test_(), ok.
-sparse_to_orddict_test(Config) when is_list(Config) -> sparse_to_orddict_test_(), ok.
-from_orddict_test(Config) when is_list(Config) -> from_orddict_test_(), ok.
-map_test(Config) when is_list(Config) -> map_test_(), ok.
-sparse_map_test(Config) when is_list(Config) -> sparse_map_test_(), ok.
-foldl_test(Config) when is_list(Config) -> foldl_test_(), ok.
-sparse_foldl_test(Config) when is_list(Config) -> sparse_foldl_test_(), ok.
-foldr_test(Config) when is_list(Config) -> foldr_test_(), ok.
-sparse_foldr_test(Config) when is_list(Config) -> sparse_foldr_test_(), ok.
-from_test(Config) when is_list(Config) -> from_test_(), ok.
--
2.51.0