Skip to content

Commit

Permalink
Add std::map (#18)
Browse files Browse the repository at this point in the history
* Update macros and regenerate for latest SWIG

* Add map and documentation
  • Loading branch information
sethrj authored Dec 21, 2019
1 parent d8e6a25 commit ee1d8b0
Show file tree
Hide file tree
Showing 16 changed files with 2,162 additions and 68 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ endif()
flibcpp_add_module(flc_algorithm)
target_link_libraries(flc_algorithm flc_random flc)

flibcpp_add_module(flc_map)
target_link_libraries(flc_map flc flc_string)

flibcpp_add_module(flc_random)
target_link_libraries(flc_random flc)

Expand Down
60 changes: 59 additions & 1 deletion doc/modules/map.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,65 @@
Map
***

Maps, sorted dictionaries mapping keys to values, are not yet implemented.
Maps are sorted dictionaries mapping keys to values. Currently they have
limited functionality and few instantiations: maps of ints to ints and of
strings to strings.

Basic functionality
===================

All map types support the following basic operations.

Construction and destruction
----------------------------

Like other wrapped C++ classes in Flibcpp, maps are
constructed using an interface function. The default constructor is an empty
map. Maps are destroyed using the ``release`` type-bound subroutine.

Modification
------------

The contents of the map can be changed with the following methods:

``insert``:
Add a new key-value pair to the map. If the key already exists, the value in
the map will remain unchanged. An optional ``logical`` parameter can be
passed that will be set to ``.true.`` if insertion was successful and
``.false.`` if the key already existed.

``set``:
Assign the given value to the key, regardless of whether the value already
existed.

``get``:
Return the value for the specified key, creating it with a default value
(zero for numeric types, empty for string types) if it does not exist.

``clear``:
Remove all items from the map.

The ``size`` method returns the number of elements, and ``count`` will return
the number of elements with the given key.

Here's an example of creating, modifying, and destroying a map::

use flc_map, only : Map => MapIntInt
type(Map) :: m
logical :: inserted = .false.
integer(C_INT) :: value
m = Map()
call m%insert(123, 456)
call m%insert(123, 567, inserted) ! inserted = false, value unchanged
call m%set(123, 567) ! value is changed
value = m%get(911) ! implicitly created value of zero
call m%erase(911)
call m%release()

Iteration
---------

Iterating over a map to determine its contents is not yet supported.

.. ############################################################################
.. end of doc/modules/map.rst
Expand Down
14 changes: 10 additions & 4 deletions doc/modules/set.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,17 @@ an element to and removing an element from the set. A ``clear`` subroutine
removes all elements from the set.

The ``size`` method returns the number of elements, and ``count`` will return
the number of elements of a given value
the number of elements of a given value.

Here's an example of creating, modifying, and destroying a set::

use flc_set, only : Set => SetInt4
use flc_set, only : Set => SetInt
type(Set) :: s
logical :: inserted
s = Set()
call s%insert(2)
call s%insert(3) ! Set has 2 elements
call s%insert(3) ! Duplicate element, ignored
call s%insert(3, inserted) ! Set has 2 elements, inserted => true
call s%insert(3, inserted) ! Duplicate element, ignored; inserted => false
call s%erase(2) ! Remove 2 from the set
call s%erase(1) ! Nonexistent set element, ignored
write(0,*) "Number of 3s in the set:" s%count(3)
Expand Down Expand Up @@ -76,6 +77,11 @@ newly allocated ``Set`` instances and do not modify the original sets.
``includes``: :math:`A \supseteq B`
Return whether all elements of the other set are in the original set.

Iteration
---------

Iterating over a set to determine its contents is not yet supported.

Numeric sets
===============

Expand Down
30 changes: 30 additions & 0 deletions include/flc_map.i
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*!
* \file flc_map.i
*
* Copyright (c) 2019 Oak Ridge National Laboratory, UT-Battelle, LLC.
* Distributed under an MIT open source license: see LICENSE for details.
*/

%module "flc_map"
%include "import_flc.i"
%flc_add_header

%include <std_map.i>

/* -------------------------------------------------------------------------
* Numeric maps
* ------------------------------------------------------------------------- */

%template(MapIntInt) std::map<int, int>;

/* -------------------------------------------------------------------------
* String maps
* ------------------------------------------------------------------------- */

%fortran_autofree_rvalue(std::map<std::string, int>);
%fortran_autofree_rvalue(std::map<std::string, std::string>);

%include <std_string.i>
%import "flc_string.i"
%template(MapStringInt) std::map<std::string, int>;
%template(MapStringString) std::map<std::string, std::string>;
21 changes: 10 additions & 11 deletions include/flc_set.i
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
} // end %extend
%enddef

%define %flc_extend_set_pod(CTYPE)
%define %flc_std_set_extend_pod(CTYPE)
%extend {
%apply (const SWIGTYPE *DATA, ::size_t SIZE)
{ (const CTYPE* DATA, size_type SIZE) };

Expand All @@ -58,16 +59,15 @@
void insert(const CTYPE* DATA, size_type SIZE) {
$self->insert(DATA, DATA + SIZE);
}
}
%enddef

/* ------------------------------------------------------------------------- */
/*! \def %specialize_std_set_pod
*
* Inject member functions and typemaps for POD classes.
*
* These provide an efficient constructor from a Fortan array view. It also
* offers a "view" functionality for getting an array pointer to the
* set-owned data.
* These provide an efficient constructor from a Fortan array view.
*
* This definition is considered part of the \em public API so that downstream
* apps that generate FLC-based bindings can instantiate their own POD sets.
Expand All @@ -79,11 +79,8 @@

namespace std {
template<> class set<T> {

SWIG_STD_SET_COMMON(set, T, std::less<T>, std::allocator<T>)
%extend {
%flc_extend_set_pod(T)
}
%swig_std_set(T, std::less<T>, std::allocator<T>)
%flc_std_set_extend_pod(T)
};
}
%enddef
Expand Down Expand Up @@ -131,8 +128,10 @@ static bool flc_set_includes(const Set_t& left, const Set_t& right)

// Allow direct insertion of a wrapped std::string
%extend std::set<std::string> {
void insert_ref(std::string& str) {
$self->insert(str);
%apply SWIGTYPE& { const std::string& STR_CLASS };

void insert_ref(const std::string& STR_CLASS) {
$self->insert(STR_CLASS);
}
}

Expand Down
36 changes: 18 additions & 18 deletions include/flc_vector.i
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
* Macro definitions
* ------------------------------------------------------------------------- */

%define %flc_extend_vector_pod(CTYPE)
%define %flc_std_vector_extend_pod(CTYPE)
%extend {
%apply (const SWIGTYPE *DATA, ::size_t SIZE)
{ (const CTYPE* DATA, size_type SIZE) };

Expand All @@ -40,48 +41,47 @@
vector<CTYPE>& view() {
return *$self;
}
}
%enddef

/* ------------------------------------------------------------------------- */
/*! \def %specialize_std_vector_pod
/*! \def %flc_template_std_vector_pod
*
* Inject member functions and typemaps for POD classes.
* Inject member functions and typemaps for POD classes, and instantiate.
*
* These provide an efficient constructor from a Fortan array view. It also
* offers a "view" functionality for getting an array pointer to the
* The added methods provide an efficient constructor from a Fortan array view.
* It also offers a "view" functionality for getting an array pointer to the
* vector-owned data.
*
* This definition is considered part of the \em public API so that downstream
* apps that generate FLC-based bindings can instantiate their own POD vectors.
*/
%define %specialize_std_vector_pod(T)
%define %flc_template_std_vector_pod(NAME, T)

// Automatically free temporary vectors as appropriate
%fortran_autofree_rvalue(std::vector<T>);

namespace std {
template<> class vector<T> {

SWIG_STD_VECTOR_COMMON(T, const T&)
SWIG_STD_VECTOR_REF(T)
%extend {
%flc_extend_vector_pod(T)
}
%swig_std_vector(T, const T&)
%swig_std_vector_extend_ref(T)
%flc_std_vector_extend_pod(T)
};
}

// Instantiate the template
%template(NAME) std::vector<T>;

%enddef

/* -------------------------------------------------------------------------
* Numeric vectors
* ------------------------------------------------------------------------- */

%specialize_std_vector_pod(int32_t)
%specialize_std_vector_pod(int64_t)
%specialize_std_vector_pod(double)

%template(VectorInt4) std::vector<int32_t>;
%template(VectorInt8) std::vector<int64_t>;
%template(VectorReal8) std::vector<double>;
%flc_template_std_vector_pod(VectorInt4, int32_t)
%flc_template_std_vector_pod(VectorInt8, int64_t)
%flc_template_std_vector_pod(VectorReal8, double)

/* -------------------------------------------------------------------------
* String vectors
Expand Down
4 changes: 2 additions & 2 deletions src/flc_algorithm.f90
Original file line number Diff line number Diff line change
Expand Up @@ -778,8 +778,8 @@ subroutine swigf_sort__SWIG_7(data, cmp)

subroutine SWIGTM_fout_bool(imout, fout)
use, intrinsic :: ISO_C_BINDING
integer(kind=C_INT), intent(IN) :: imout
logical, intent(OUT) :: fout
integer(kind=C_INT), intent(in) :: imout
logical, intent(out) :: fout
! TODO: fout = (imout /= 0) ???
if (imout /= 0) then
fout = .true.
Expand Down
Loading

0 comments on commit ee1d8b0

Please sign in to comment.