Skip to content

Commit

Permalink
Merge branch 'master' into AMSC
Browse files Browse the repository at this point in the history
  • Loading branch information
lformaggia committed Aug 20, 2024
2 parents 6e06471 + 24626d6 commit 70e7cad
Show file tree
Hide file tree
Showing 10 changed files with 301 additions and 5 deletions.
2 changes: 1 addition & 1 deletion Examples/src/LinearAlgebra/spectra
72 changes: 72 additions & 0 deletions Examples/src/STL/Span/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
############################################################
#
# An example of Makefile for the course on
# Advanced Programming for Scientific Computing
# It should be modified for adapting it to the various examples
#
############################################################
#
# The environmental variable PACS_ROOT should be set to the
# root directory where the examples reside. In practice, the directory
# where this file is found. The resolution of PACS_ROOT is made in the
# Makefile.h file, where other important variables are also set.
# The only user defined variable that must be set in this file is
# the one indicating where Makefile.h resides

MAKEFILEH_DIR=../../..
#
include $(MAKEFILEH_DIR)/Makefile.inc
#
# You may have an include file also in the current directory
#
-include Makefile.inc

#
# The general setting is as follows:
# mains are identified bt main_XX.cpp
# all other files are XX.cpp
#

# get all files *.cpp
SRCS=$(wildcard *.cpp)
# get the corresponding object file
OBJS = $(SRCS:.cpp=.o)
# get all headers in the working directory
HEADERS=$(wildcard *.hpp)
#
exe_sources=$(filter main%.cpp,$(SRCS))
EXEC=$(exe_sources:.cpp=)

#========================== ORA LA DEFINIZIONE DEGLI OBIETTIVI
.phony= all clean distclean doc

.DEFAULT_GOAL = all

all: $(DEPEND) $(EXEC)

clean:
$(RM) -f $(EXEC) $(OBJS)

distclean:
$(MAKE) clean
$(RM) -f ./doc $(DEPEND)
$(RM) *.out *.bak *~

doc:
doxygen $(DOXYFILE)

$(EXEC): $(OBJS)

$(OBJS): $(SRCS)

$(DEPEND): $(SRCS)
-\rm $(DEPEND)
for f in $(SRCS); do \
$(CXX) $(STDFLAGS) $(CPPFLAGS) -MM $$f >> $(DEPEND); \
done

-include $(DEPEND)




93 changes: 93 additions & 0 deletions Examples/src/STL/Span/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# The std::span utility #
`std::span` is a utility introduced in C++20 that provides a view over a contiguous sequence of elements. It is a lightweight, non-owning reference to an array or a portion of an array, which can be used to pass arrays or parts of arrays to functions without copying the data.

Its main purpose is to provide a safe and efficient way to work with arrays and array-like containers, such as `std::array`, `std::vector`, and built-in arrays, without the need to copy or manage memory.

## Key Features ##
- Non-owning: `std::span` does not own the elements it references, meaning it does not manage the memory of the underlying data.
- Contiguous: The elements referenced by `std::span` are guaranteed to be contiguous in memory.
- Bounds-safe: Provides bounds-checked access to elements when using the at method.
- Flexible: Can be constructed from arrays, `std::array`, `std::vector`, and other contiguous containers.

## Usage ##
Here are some common use cases and examples of how to use `std::span`:

Creating a std::span
You can create a std::span from various types of containers:
```cpp
#include <span>
#include <vector>
#include <array>
#include <iostream>

int main() {
// From a C-style array
int arr[] = {1, 2, 3, 4, 5};
std::span<int> span1(arr);

// From a std::array
std::array<int, 5> stdArr = {1, 2, 3, 4, 5};
std::span<int> span2(stdArr);

// From a std::vector
std::vector<int> vec = {1, 2, 3, 4, 5};
std::span<int> span3(vec);

// Output elements
for (int i : span1) {
std::cout << i << " ";
}
std::cout << std::endl;

return 0;
}
```
Slicing a std::span
You can create sub-spans (slices) from an existing std::span:
```cpp
#include <span>
#include <iostream>

int main() {
int arr[] = {1, 2, 3, 4, 5};
std::span<int> span(arr);

// Create a sub-span from index 1 to 3
std::span<int> subSpan = span.subspan(1, 3);

// Output elements of the sub-span
for (int i : subSpan) {
std::cout << i << " ";
}
std::cout << std::endl;

return 0;
}
```


Bounds-checked Access
You can access elements with bounds checking using the at method:
```cpp
#include <span>
#include <iostream>

int main() {
int arr[] = {1, 2, 3, 4, 5};
std::span<int> span(arr);

try {
std::cout << span.at(2) << std::endl; // Outputs: 3
std::cout << span.at(5) << std::endl; // Throws std::out_of_range
} catch (const std::out_of_range& e) {
std::cerr << "Out of range error: " << e.what() << std::endl;
}

return 0;
}
```

## Conclusion ##
`std::span` is a versatile and efficient utility for working with contiguous sequences of elements in C++. It provides a safe and convenient way to pass arrays and array-like containers to functions without copying data, making it a valuable addition to the C++ standard library.
## What do I learn Here? ##
A nice utility that can be helpsul when is necessary to mix C-style arrays and C++ contiguos containers.
40 changes: 40 additions & 0 deletions Examples/src/STL/Span/main_span.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include <iostream>
#include <span>
#include <vector>

void
printSpan(std::span<int> span)
{
for(int element : span)
{
std::cout << element << " ";
}
std::cout << std::endl;
}

int
main()
{
// a C=style array
int numbers[] = {1, 2, 3, 4, 5};

// Create a span from the array
std::span<int> span(numbers);

// Print the elements of the span
printSpan(span);

// Modify the elements of the span
for(int &element : span)
{
element *= 2;
}

// Print the modified elements of the span
printSpan(span);

std::cout << "The original array is also modified\n";
// and I can print it using printSpan!
printSpan(numbers);
return 0;
}
3 changes: 2 additions & 1 deletion Examples/src/Utilities/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ We hve also traits and concepts to test sparse and dense matrices separately.
* `is_specialization.hpp`. Type traits and concepts to test if a class is the specialization of a class template.

* `JoinVectors.hpp` Just an example on how to imitate the `join` phyton command. You can use it to iterate jointly on a set of vectors.

* `overloaded` A facility, called `overloaded` that implements the overloaded design pattern that may be used to visit a `std::variant`.

* `parallel_for` An example of metaprogramming to implement a parallel for loop. I show also some example of use of concepts.

Expand All @@ -88,7 +90,6 @@ utilities of the Standard Library, but with a simpler interface.

* `tuple_utilities` Contains some utilities for tuples: `tuple_common_type_t<Tuple>` that returns the common tpe of all types contained in a tuple, and `for_each<Tuple F>` and `for_each2<Tuple, F>` that apply (possibly in parallel) the function object `F` to all elements of the tuple. The first one returns a tuple with the result, the second one does not and is thus applicable also if `F` is a void function. `all_of<Tuple,F>` and `any_of<Tuple,F>`, that apply predicate `F` to all elements of a tuple. The first returns true if the predicate is true for all elements, the second if it is true for at least one element.

* `overloaded` A facility, called `overloaded` that implements the overloaded design pattern that may be used to visit a `std::variant`.



Expand Down
38 changes: 38 additions & 0 deletions Examples/src/Utilities/parallel_for.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#ifndef HH_PARALLEL_FOR_HPP_HH
#define HH_PARALLEL_FOR_HPP_HH
#include <algorithm>
#include <concepts>
#include <execution>
#include <ranges>
namespace apsc
{
/**
* @brief Executes a parallel loop over a range of indices using the specified
* execution policy.
*
* This function executes a parallel loop over a range of indices specified by
* `first` and `last`, using the specified execution policy `p`. The loop body
* is defined by the callable object `f`, which takes an index as its argument.
*
* @tparam Policy The type of the execution policy.
* @tparam Index The type of the loop indices.
* @tparam F The type of the callable object representing the loop body.
*
* @param p The execution policy to use for parallel execution.
* @param first The first index of the loop range (inclusive).
* @param last The last index of the loop range (exclusive).
* @param f The callable object representing the loop body.
*/
template <typename Policy, std::integral Index, typename F>
requires requires(Policy p, Index i, F f) {
f(i);
requires std::is_execution_policy_v<std::remove_cvref_t<Policy>>;
}
auto
parallel_for(Policy &&p, Index first, Index last, F f) -> void
{
auto r = std::ranges::views::iota(first, last);
std::for_each(p, r.begin(), r.end(), std::move(f));
}
} // namespace apsc
#endif
52 changes: 52 additions & 0 deletions Examples/src/Utilities/test_parallel_for.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include "parallel_for.hpp"
#include <iostream>

// Test case 1: Parallel loop with lambda function
void
test_case_1()
{
std::cout << "Test case 1:\n";
std::vector sum = {1, -1, 3, 4, 7, 9, 11};
auto add_to_sum = [&sum](int i) { sum[i] += 2; };
apsc::parallel_for(std::execution::par, std::size_t{0}, sum.size(),
add_to_sum);
std::cout << "computed values " << std::endl;
for(int i : sum)
{
std::cout << i << " ";
}
std::cout << std::endl;
}

// Test case 2: Parallel loop with function object
struct MultiplyByTwo
{
std::vector<int> v;
void
operator()(int i)
{
v.push_back(i * 2);
}
};

void
test_case_2()
{
std::cout << "Test case 2:\n";
MultiplyByTwo m;
apsc::parallel_for(std::execution::par, 0, 5, std::ref(m));
for(int i : m.v)
{
std::cout << i << " ";
}
std::cout << std::endl;
// Expected output: 0 2 4 6 8
}

int
main()
{
test_case_1();
test_case_2();
return 0;
}
2 changes: 1 addition & 1 deletion Extras/json
Submodule json updated 251 files
2 changes: 1 addition & 1 deletion Extras/muparser
2 changes: 1 addition & 1 deletion Extras/pybind11
Submodule pybind11 updated 170 files

0 comments on commit 70e7cad

Please sign in to comment.