Skip to content

Commit 32712ab

Browse files
authored
Merge pull request #9 from swig-fortran/std-set
Add std::set
2 parents 613a815 + af09ba2 commit 32712ab

File tree

8 files changed

+2140
-8
lines changed

8 files changed

+2140
-8
lines changed

CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ target_link_libraries(flc_algorithm flc_random flc)
229229
flibcpp_add_module(flc_random)
230230
target_link_libraries(flc_random flc)
231231

232+
flibcpp_add_module(flc_set)
233+
target_link_libraries(flc_set flc flc_string)
234+
232235
flibcpp_add_module(flc_string)
233236
target_link_libraries(flc_string flc)
234237

doc/modules/set.rst

+102-4
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,113 @@
22
.. File : doc/modules/set.rst
33
.. ############################################################################
44
5-
.. _modules_set:
5+
.. _modules_Set:
66

77
***
88
Set
99
***
1010

11-
Sorted sets with unions, intersections, etc., are not yet implemented as
12-
objects. However, the :ref:`modules_algorithm_set_operations` for arrays can
13-
replicate some basic Set-like functionality.
11+
Sets are sorted containers of unique elements. The ``flc_set`` module
12+
defines sets of ``integer`` and of ``type(String)``.
13+
14+
Basic functionality
15+
===================
16+
17+
All set types support the following basic operations.
18+
19+
Construction and destruction
20+
----------------------------
21+
22+
Like other wrapped C++ classes in Flibcpp, sets are
23+
constructed using an interface function. The default constructor is an empty
24+
set. Sets are destroyed using the ``release`` type-bound subroutine.
25+
26+
Modification
27+
------------
28+
29+
The two primary operations on a set are ``insert`` and ``erase`` for adding
30+
an element to and removing an element from the set. A ``clear`` subroutine
31+
removes all elements from the set.
32+
33+
The ``size`` method returns the number of elements, and ``count`` will return
34+
the number of elements of a given value
35+
36+
Here's an example of creating, modifying, and destroying a set::
37+
38+
use flc_set, only : Set => SetInt4
39+
type(Set) :: s
40+
s = Set()
41+
call s%insert(2)
42+
call s%insert(3) ! Set has 2 elements
43+
call s%insert(3) ! Duplicate element, ignored
44+
call s%erase(2) ! Remove 2 from the set
45+
call s%erase(1) ! Nonexistent set element, ignored
46+
write(0,*) "Number of 3s in the set:" s%count(3)
47+
call s%clear() ! Remove all elements, size is now zero
48+
call s%insert(1)
49+
call s%release() ! Free memory
50+
51+
Set operations
52+
--------------
53+
54+
The Fortran ``Set`` classes have been extended to include several useful set
55+
algorithms. (In C++, these are implemented using the ``<algorithm>`` header and
56+
therefore should resemble the functions in
57+
:ref:`the flc_algorithm module <modules_algorithm_set_operations>`.
58+
59+
All set operations take a single argument, another ``Set`` object, and do not
60+
modify either the original or the argument. All but the ``includes`` return
61+
newly allocated ``Set`` instances and do not modify the original sets.
62+
63+
``difference``: :math:`A \setminus B`
64+
Returns a new set with all elements from the original that are *not* present
65+
in the other set.
66+
67+
``intersection``: :math:`A \cap B`
68+
Return all elements that are in both sets.
69+
70+
``symmetric_difference``: :math:`(A \setminus B) \cup (B \setminus A)`
71+
Return all elements that are in one set or the other but not both.
72+
73+
``union``: :math:`A \cup B`
74+
Return all elements that are in either set.
75+
76+
``includes``: :math:`A \supseteq B`
77+
Return whether all elements of the other set are in the original set.
78+
79+
Numeric sets
80+
===============
81+
82+
Unlike :ref:`vectors<modules_Vector>`, the ``flc_set`` module includes
83+
a single "native integer" numeric instantiations. The value type is
84+
``integer(C_INT)`` and is 64 bits on most modern systems. Since the C++
85+
implementation of numerical sets is not very efficient, the assumption is that
86+
the ``set`` will be used in a non-numerically-intensive capacity where the
87+
default integer is the most appropriate option.
88+
89+
Construct from an array
90+
-----------------------
91+
92+
Numeric sets can be created very efficiently from Fortran data by accepting
93+
an array argument::
94+
95+
use flc_set, only : Set => SetInt
96+
type(Set) :: s
97+
98+
s = Set([1, 1, 2, 10])
99+
write(0,*) "Size should be 3:", s%size()
100+
101+
The ``assign`` bound method acts like a constructor but for an existing set.
102+
103+
String sets
104+
==============
105+
106+
The native "element" type of ``SetString`` is a ``character(len=:)``. Set
107+
operations that accept an input will take any native character string; and
108+
returned values will be allocatable character arrays.
109+
110+
An additional ``insert_ref`` function allows assignment of
111+
:ref:`String types <modules_string_type>`
14112

15113
.. ############################################################################
16114
.. end of doc/modules/set.rst

doc/modules/vector.rst

+3-4
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,14 @@ All vector types support the following basic operations.
2020
Construction and destruction
2121
----------------------------
2222

23-
Vectors are constructed using three interface functions:
23+
Vectors are constructed using four interface functions:
2424

2525
- The function without arguments creates an empty vector;
2626
- A single integer argument assigns that many elements with default values;
2727
and
2828
- An integer argument followed by an element with the vector's element type
2929
will copy that value to all elements of the vector.
30-
31-
(To do: copy construction)
30+
- A vector object will create a copy of that vector.
3231

3332
Here are three examples of initialization::
3433

@@ -153,7 +152,7 @@ However, as with native pointers described above, these references are
153152
``%release()`` bound method.
154153

155154
An additional ``set_ref`` function allows vector elements to be assigned from
156-
vector classes.
155+
``String`` types.
157156

158157
.. ############################################################################
159158
.. end of doc/modules/vector.rst

include/flc_set.i

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*!
2+
* \file flc_set.i
3+
*
4+
* Copyright (c) 2019 Oak Ridge National Laboratory, UT-Battelle, LLC.
5+
* Distributed under an MIT open source license: see LICENSE for details.
6+
*/
7+
8+
%module "flc_set"
9+
%include "import_flc.i"
10+
%flc_add_header
11+
12+
%include <std_set.i>
13+
14+
// Support for set operations
15+
%{
16+
#include <algorithm>
17+
#include <iterator>
18+
%}
19+
20+
/* -------------------------------------------------------------------------
21+
* Macro definitions
22+
* ------------------------------------------------------------------------- */
23+
24+
%define %flc_define_set_algorithm(FUNCNAME)
25+
%insert("header") {
26+
template<class Set_t>
27+
static Set_t flc_##FUNCNAME(const Set_t& left, const Set_t& right)
28+
{
29+
Set_t result;
30+
std::FUNCNAME(left.begin(), left.end(),
31+
right.begin(), right.end(),
32+
std::inserter(result, result.end()));
33+
return result;
34+
}
35+
} // end %insert
36+
%enddef
37+
38+
%define %flc_extend_set_algorithm(FUNCNAME, RETVAL, TYPE)
39+
// The rename with the stringifying macro is necessary because 'union' is a
40+
// keyword.
41+
%rename(#FUNCNAME) std::set<TYPE>::set_##FUNCNAME;
42+
%extend std::set<TYPE> {
43+
RETVAL set_##FUNCNAME(const std::set<TYPE>& other)
44+
{ return flc_set_##FUNCNAME(*$self, other); }
45+
} // end %extend
46+
%enddef
47+
48+
%define %flc_extend_set_pod(CTYPE)
49+
%apply (const SWIGTYPE *DATA, ::size_t SIZE)
50+
{ (const CTYPE* DATA, size_type SIZE) };
51+
52+
// Construct from an array of data
53+
set(const CTYPE* DATA, size_type SIZE) {
54+
return new std::set<CTYPE>(DATA, DATA + SIZE);
55+
}
56+
57+
// Insert an array of data
58+
void insert(const CTYPE* DATA, size_type SIZE) {
59+
$self->insert(DATA, DATA + SIZE);
60+
}
61+
%enddef
62+
63+
/* ------------------------------------------------------------------------- */
64+
/*! \def %specialize_std_set_pod
65+
*
66+
* Inject member functions and typemaps for POD classes.
67+
*
68+
* These provide an efficient constructor from a Fortan array view. It also
69+
* offers a "view" functionality for getting an array pointer to the
70+
* set-owned data.
71+
*
72+
* This definition is considered part of the \em public API so that downstream
73+
* apps that generate FLC-based bindings can instantiate their own POD sets.
74+
*/
75+
%define %specialize_std_set_pod(T)
76+
77+
// Automatically free temporary sets as appropriate
78+
%fortran_autofree_rvalue(std::set<T>);
79+
80+
namespace std {
81+
template<> class set<T> {
82+
83+
SWIG_STD_SET_COMMON(set, T, std::less<T>, std::allocator<T>)
84+
%extend {
85+
%flc_extend_set_pod(T)
86+
}
87+
};
88+
}
89+
%enddef
90+
91+
/* -------------------------------------------------------------------------
92+
* Algorithms
93+
* ------------------------------------------------------------------------- */
94+
95+
%flc_define_set_algorithm(set_difference)
96+
%flc_define_set_algorithm(set_intersection)
97+
%flc_define_set_algorithm(set_symmetric_difference)
98+
%flc_define_set_algorithm(set_union)
99+
100+
%insert("header") %{
101+
template<class Set_t>
102+
static bool flc_set_includes(const Set_t& left, const Set_t& right)
103+
{
104+
return std::includes(left.begin(), left.end(),
105+
right.begin(), right.end());
106+
}
107+
%}
108+
109+
%define %flc_extend_algorithms(TYPE)
110+
%flc_extend_set_algorithm(difference, std::set<TYPE >, TYPE)
111+
%flc_extend_set_algorithm(intersection, std::set<TYPE >, TYPE)
112+
%flc_extend_set_algorithm(symmetric_difference, std::set<TYPE >, TYPE)
113+
%flc_extend_set_algorithm(union, std::set<TYPE >, TYPE)
114+
%flc_extend_set_algorithm(includes, bool, TYPE)
115+
%enddef
116+
117+
/* -------------------------------------------------------------------------
118+
* Numeric sets
119+
* ------------------------------------------------------------------------- */
120+
121+
%flc_extend_algorithms(int)
122+
%specialize_std_set_pod(int)
123+
124+
%template(SetInt) std::set<int>;
125+
126+
/* -------------------------------------------------------------------------
127+
* String sets
128+
* ------------------------------------------------------------------------- */
129+
130+
%fortran_autofree_rvalue(std::set<std::string>);
131+
132+
// Allow direct insertion of a wrapped std::string
133+
%extend std::set<std::string> {
134+
void insert_ref(std::string& str) {
135+
$self->insert(str);
136+
}
137+
}
138+
139+
%include <std_string.i>
140+
%import "flc_string.i"
141+
%flc_extend_algorithms(std::string)
142+
%template(SetString) std::set<std::string>;

0 commit comments

Comments
 (0)