<commit_before>%  @copyright 2007-2011 Zuse Institute Berlin
%             2008 onScale solutions GmbH

%   Licensed under the Apache License, Version 2.0 (the "License");
%   you may not use this file except in compliance with the License.
%   You may obtain a copy of the License at
%
%       http://www.apache.org/licenses/LICENSE-2.0
%
%   Unless required by applicable law or agreed to in writing, software
%   distributed under the License is distributed on an "AS IS" BASIS,
%   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%   See the License for the specific language governing permissions and
%   limitations under the License.

%% @author <NAME> <<EMAIL>>
%% @author <NAME> <<EMAIL>>
%% @author <NAME> <<EMAIL>>
%% @doc Interval data structure and handling functions.
%%
%% All intervals created by methods of this module are normalized, i.e. simple
%% intervals having unambiguous representations and complex intervals being
%% lists of simple intervals sorted by the order given by interval_sort/2.
%% Such a list contains no adjacent intervals except for those wrapping around,
%% i.e. the first and the last element of the list. This representation is
%% thus unambiguous as well.
%% @end
%% @version $Id$
-module(intervals).
-author('<EMAIL>').
-vsn('$Id$').

-include("scalaris.hrl").

-export([empty/0, new/1, new/4, all/0, from_elements/1,
         % testing / comparing intervals
         is_empty/1, is_all/1, is_subset/2, is_continuous/1,
         is_adjacent/2, in/2,
         is_left_of/2, is_right_of/2,
         split/2,
         % operations for intervals
         intersection/2, union/2, minus/2, 
         % getters for certain intervals
         get_bounds/1, get_elements/1,
         %
         % for unit testing only
         is_well_formed/1, normalize/1
        ]).

-ifdef(with_export_type_support).
-export_type([interval/0, key/0, left_bracket/0, right_bracket/0]).
-endif.

-type left_bracket() :: '(' | '['.
-type right_bracket() :: ')' | ']'.
-type key() :: ?RT:key() | ?MINUS_INFINITY_TYPE. % ?MINUS_INFINITY_TYPE unnecessary (should be included in ?RT:key()) but needed for fewer dialyzer warnings
-type simple_interval2() :: {interval, left_bracket(), key(), key(), right_bracket()} | {interval, left_bracket(), key(), ?PLUS_INFINITY_TYPE, ')'}.
-type simple_interval() :: {element, key()} | all | simple_interval2().
-opaque interval() :: [simple_interval()].

% @type interval() = [simple_interval()].
% [] -> empty interval
% [simple_interval(),...] -> union of the simple intervals
% @type simple_interval() = {element, key()} | {interval, left_bracket(), key(), key(), right_bracket()} | all.
% {element, term()} -> one element interval
% {interval, '[', A::term(), B::term(), ']'} -> closed interval [A, B]
% {interval, '(', A::term(), B::term(), ']'} -> half-open interval (A, B], aka ]A, B]
% {interval, '[', A::term(), B::term(), ')'} -> half-open interval [A, B), aka [A, B[
% {interval, '(', A::term(), B::term(), ')'} -> open interval (A, B), aka ]A, B[
% all -> half open interval [?MINUS_INFINITY, ?PLUS_INFINITY)

% Note: the intervals module uses two special symbols (?MINUS_INFINITY
% and ?PLUS_INFINITY) to define the first, i.e. smallest, valid key and the
% first key that is not valid anymore.
% In Scalaris these values are dependent on the routing table
% implementation. Therefore it is not possible e.g. to use intervals
% over integer ranges and strings at the same time!

%% @doc Creates an empty interval.
-spec empty() -> interval().
empty() -> [].

%% @doc Creates an interval covering the whole key space.
-spec all() -> interval().
all() -> normalize_simple(all).

%% @doc Creates an interval covering a single element.
-spec new(key()) -> interval().
new(X) -> normalize_simple({element, X}).

%% @doc Creates a new interval depending on the given brackets, i.e.:
%%      - closed interval [A, B],
%%      - half-open interval (A, B], aka ]A, B]
%%      - half-open interval [A, B), aka [A, B[
%%      - open interval (A, B), aka ]A, B[
%%      The new interval may wrap around, e.g. if A > B.
%%      If '[A,A]' is given, an interval with the element A is created.
%%      The special cases '(A,A)', '[A,A)', '(A,A]' and
%%      '(?PLUS_INFINITY,?MINUS_INFINITY,)' translate to an empty interval.
%%      '[?MINUS_INFINITY,?PLUS_INFINITY)' translates to 'all'.
%% -spec new(LeftBr::left_bracket(), A::key(), B::key(), RightBr::right_bracket()) -> interval();
%%          (LeftBr::left_bracket(), A::key(), B::?PLUS_INFINITY, RightBr::')') -> interval().
-spec new(LeftBr::left_bracket(), A::key(), B::key() | ?PLUS_INFINITY_TYPE, RightBr::right_bracket()) -> interval().
new(LeftBr, Begin, End, RightBr) when End =/= ?PLUS_INFINITY orelse RightBr =:= ')' -><commit_msg>- better type def for intervals:new/4<commit_after>%  @copyright 2007-2011 Zuse Institute Berlin
%             2008 onScale solutions GmbH

%   Licensed under the Apache License, Version 2.0 (the "License");
%   you may not use this file except in compliance with the License.
%   You may obtain a copy of the License at
%
%       http://www.apache.org/licenses/LICENSE-2.0
%
%   Unless required by applicable law or agreed to in writing, software
%   distributed under the License is distributed on an "AS IS" BASIS,
%   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%   See the License for the specific language governing permissions and
%   limitations under the License.

%% @author <NAME> <<EMAIL>>
%% @author <NAME> <<EMAIL>>
%% @author <NAME> <<EMAIL>>
%% @doc Interval data structure and handling functions.
%%
%% All intervals created by methods of this module are normalized, i.e. simple
%% intervals having unambiguous representations and complex intervals being
%% lists of simple intervals sorted by the order given by interval_sort/2.
%% Such a list contains no adjacent intervals except for those wrapping around,
%% i.e. the first and the last element of the list. This representation is
%% thus unambiguous as well.
%% @end
%% @version $Id$
-module(intervals).
-author('<EMAIL>').
-vsn('$Id$').

-include("scalaris.hrl").

-export([empty/0, new/1, new/4, all/0, from_elements/1,
         % testing / comparing intervals
         is_empty/1, is_all/1, is_subset/2, is_continuous/1,
         is_adjacent/2, in/2,
         is_left_of/2, is_right_of/2,
         split/2,
         % operations for intervals
         intersection/2, union/2, minus/2, 
         % getters for certain intervals
         get_bounds/1, get_elements/1,
         %
         % for unit testing only
         is_well_formed/1, normalize/1
        ]).

-ifdef(with_export_type_support).
-export_type([interval/0, key/0, left_bracket/0, right_bracket/0]).
-endif.

-type left_bracket() :: '(' | '['.
-type right_bracket() :: ')' | ']'.
-type key() :: ?RT:key() | ?MINUS_INFINITY_TYPE. % ?MINUS_INFINITY_TYPE unnecessary (should be included in ?RT:key()) but needed for fewer dialyzer warnings
-type simple_interval2() :: {interval, left_bracket(), key(), key(), right_bracket()} | {interval, left_bracket(), key(), ?PLUS_INFINITY_TYPE, ')'}.
-type simple_interval() :: {element, key()} | all | simple_interval2().
-opaque interval() :: [simple_interval()].

% @type interval() = [simple_interval()].
% [] -> empty interval
% [simple_interval(),...] -> union of the simple intervals
% @type simple_interval() = {element, key()} | {interval, left_bracket(), key(), key(), right_bracket()} | all.
% {element, term()} -> one element interval
% {interval, '[', A::term(), B::term(), ']'} -> closed interval [A, B]
% {interval, '(', A::term(), B::term(), ']'} -> half-open interval (A, B], aka ]A, B]
% {interval, '[', A::term(), B::term(), ')'} -> half-open interval [A, B), aka [A, B[
% {interval, '(', A::term(), B::term(), ')'} -> open interval (A, B), aka ]A, B[
% all -> half open interval [?MINUS_INFINITY, ?PLUS_INFINITY)

% Note: the intervals module uses two special symbols (?MINUS_INFINITY
% and ?PLUS_INFINITY) to define the first, i.e. smallest, valid key and the
% first key that is not valid anymore.
% In Scalaris these values are dependent on the routing table
% implementation. Therefore it is not possible e.g. to use intervals
% over integer ranges and strings at the same time!

%% @doc Creates an empty interval.
-spec empty() -> interval().
empty() -> [].

%% @doc Creates an interval covering the whole key space.
-spec all() -> interval().
all() -> normalize_simple(all).

%% @doc Creates an interval covering a single element.
-spec new(key()) -> interval().
new(X) -> normalize_simple({element, X}).

%% @doc Creates a new interval depending on the given brackets, i.e.:
%%      - closed interval [A, B],
%%      - half-open interval (A, B], aka ]A, B]
%%      - half-open interval [A, B), aka [A, B[
%%      - open interval (A, B), aka ]A, B[
%%      The new interval may wrap around, e.g. if A > B.
%%      If '[A,A]' is given, an interval with the element A is created.
%%      The special cases '(A,A)', '[A,A)', '(A,A]' and
%%      '(?PLUS_INFINITY,?MINUS_INFINITY,)' translate to an empty interval.
%%      '[?MINUS_INFINITY,?PLUS_INFINITY)' translates to 'all'.
%% -spec new(LeftBr::left_bracket(), A::key(), B::key(), RightBr::right_bracket()) -> interval();
%%          (LeftBr::left_bracket(), A::key(), B::?PLUS_INFINITY, RightBr::')') -> interval().
-spec new(LeftBr::left_bracket(), A::key(), B::key(), RightBr::right_bracket()) -> interval();
         (LeftBr::left_bracket(), A::key(), B::?PLUS_INFINITY_TYPE, RightBr::')') -> interval().
new(LeftBr, Begin, End, RightBr) when End =/= ?PLUS_INFINITY orelse RightBr =:= ')' ->
{'fraction_non_alphanumeric': 0.16568231271370842, 'fraction_numerical': 0.009221842296135116, 'mean_word_length': 3.792452830188679, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 62, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1500972', 'n_tokens_mistral': 3088, 'n_tokens_neox': 2999, 'n_words': 1045}