diff --git a/.clang-format b/.clang-format index 98e77c74..e8cd038d 100644 --- a/.clang-format +++ b/.clang-format @@ -1,23 +1,8 @@ -Language: Cpp -Standard: c++20 BasedOnStyle: Google +IndentWidth: 4 ColumnLimit: 120 -UseTab: Never -AllowShortFunctionsOnASingleLine: Empty -IndentPPDirectives: AfterHash -SortIncludes: true -FixNamespaceComments: true -InsertBraces: true -QualifierAlignment: Left -PointerAlignment: Right -ReferenceAlignment: Right -SortUsingDeclarations: LexicographicNumeric -InsertNewlineAtEOF: true -LambdaBodyIndentation: OuterScope -MaxEmptyLinesToKeep: 1 -EnumTrailingComma: Insert -KeepEmptyLines: - AtStartOfFile: false - AtStartOfBlock: false - AtEndOfFile: false -LineEnding: LF +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +BreakBeforeBraces: Allman +SpaceAfterCStyleCast: true diff --git a/.gitignore b/.gitignore index 5de0996c..2dad5f05 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,5 @@ CMakeSettings.json .cache install *.pyc +cmake_log.txt +Dockerfile diff --git a/tasks/dergynov_s_hypercube/info.json b/tasks/dergynov_s_hypercube/info.json index b3aebbf2..96fbab87 100644 --- a/tasks/dergynov_s_hypercube/info.json +++ b/tasks/dergynov_s_hypercube/info.json @@ -1,9 +1,9 @@ { "student": { - "first_name": "\u0421\u0435\u0440\u0433\u0435\u0439", - "group_number": "3823\u04111\u041f\u04204", - "last_name": "\u0414\u0435\u0440\u0433\u0443\u043d\u043e\u0432", - "middle_name": "\u0410\u043d\u0442\u043e\u043d\u043e\u0432\u0438\u0447", + "first_name": "Сергей", + "group_number": "3823Б1ПР4", + "last_name": "Дергунов", + "middle_name": "Антонович", "task_number": "2" } } diff --git a/tasks/dergynov_s_radix_sort_double_simple_merge/info.json b/tasks/dergynov_s_radix_sort_double_simple_merge/info.json index c4c78494..5dfba0a4 100644 --- a/tasks/dergynov_s_radix_sort_double_simple_merge/info.json +++ b/tasks/dergynov_s_radix_sort_double_simple_merge/info.json @@ -1,9 +1,9 @@ { "student": { - "first_name": "\u0421\u0435\u0440\u0433\u0435\u0439", - "group_number": "3823\u04111\u041f\u04204", - "last_name": "\u0414\u0435\u0440\u0433\u0443\u043d\u043e\u0432", - "middle_name": "\u0410\u043d\u0442\u043e\u043d\u043e\u0432\u0438\u0447", + "first_name": "Сергей", + "group_number": "3823Б1ПР4", + "last_name": "Дергунов", + "middle_name": "Антонович", "task_number": "3" } } diff --git a/tasks/dergynov_s_trapezoid_integration/info.json b/tasks/dergynov_s_trapezoid_integration/info.json index c5a8145b..5cb7fa89 100644 --- a/tasks/dergynov_s_trapezoid_integration/info.json +++ b/tasks/dergynov_s_trapezoid_integration/info.json @@ -1,9 +1,9 @@ { "student": { - "first_name": "\u0421\u0435\u0440\u0433\u0435\u0439", - "group_number": "3823\u04111\u041f\u04204", - "last_name": "\u0414\u0435\u0440\u0433\u0443\u043d\u043e\u0432", - "middle_name": "\u0410\u043d\u0442\u043e\u043d\u043e\u0432\u0438\u0447", + "first_name": "Сергей", + "group_number": "3823Б1ПР4", + "last_name": "Дергунов", + "middle_name": "Антонович", "task_number": "1" } } diff --git a/tasks/llvm.sh.1 b/tasks/llvm.sh.1 new file mode 100644 index 00000000..1ab9dd9f --- /dev/null +++ b/tasks/llvm.sh.1 @@ -0,0 +1,233 @@ +#!/bin/bash +################################################################################ +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +################################################################################ +# +# This script will install the llvm toolchain on the different +# Debian and Ubuntu versions + +set -eux + +usage() { + set +x + echo "Usage: $0 [llvm_major_version] [all] [OPTIONS]" 1>&2 + echo -e "all\t\t\tInstall all packages." 1>&2 + echo -e "-n=code_name\t\tSpecifies the distro codename, for example bionic" 1>&2 + echo -e "-h\t\t\tPrints this help." 1>&2 + echo -e "-m=repo_base_url\tSpecifies the base URL from which to download." 1>&2 + exit 1; +} + +CURRENT_LLVM_STABLE=20 +BASE_URL="http://apt.llvm.org" + +NEW_DEBIAN_DISTROS=("trixie" "forky" "unstable") +# Set default values for commandline arguments +# We default to the current stable branch of LLVM +LLVM_VERSION=$CURRENT_LLVM_STABLE +ALL=0 +DISTRO=$(lsb_release -is) +VERSION_CODENAME=$(lsb_release -cs) +VERSION=$(lsb_release -sr) +UBUNTU_CODENAME="" +CODENAME_FROM_ARGUMENTS="" +# Obtain VERSION_CODENAME and UBUNTU_CODENAME (for Ubuntu and its derivatives) +source /etc/os-release +DISTRO=${DISTRO,,} + +# Check for required tools + +# Check if this is a new Debian distro +is_new_debian=0 +if [[ "${DISTRO}" == "debian" ]]; then + for new_distro in "${NEW_DEBIAN_DISTROS[@]}"; do + if [[ "${VERSION_CODENAME}" == "${new_distro}" ]]; then + is_new_debian=1 + break + fi + done +fi + +# Check for required tools +needed_binaries=(lsb_release wget gpg) +# add-apt-repository is not needed for newer Debian distros +if [[ $is_new_debian -eq 0 ]]; then + needed_binaries+=(add-apt-repository) +fi + +missing_binaries=() +using_curl= +for binary in "${needed_binaries[@]}"; do + if ! command -v $binary &>/dev/null ; then + if [[ "$binary" == "wget" ]] && command -v curl &>/dev/null; then + using_curl=1 + continue + fi + missing_binaries+=($binary) + fi +done + +if [[ ${#missing_binaries[@]} -gt 0 ]] ; then + echo "You are missing some tools this script requires: ${missing_binaries[@]}" + echo "(hint: apt install lsb-release wget software-properties-common gnupg)" + echo "curl is also supported" + exit 4 +fi + +case ${DISTRO} in + debian) + # Debian Forky has a workaround because of + # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1038383 + if [[ "${VERSION}" == "unstable" ]] || [[ "${VERSION}" == "testing" ]] || [[ "${VERSION_CODENAME}" == "forky" ]]; then + CODENAME=unstable + LINKNAME= + else + # "stable" Debian release + CODENAME=${VERSION_CODENAME} + LINKNAME=-${CODENAME} + fi + ;; + *) + # ubuntu and its derivatives + if [[ -n "${UBUNTU_CODENAME}" ]]; then + CODENAME=${UBUNTU_CODENAME} + if [[ -n "${CODENAME}" ]]; then + LINKNAME=-${CODENAME} + fi + fi + ;; +esac + +# read optional command line arguments +if [ "$#" -ge 1 ] && [ "${1::1}" != "-" ]; then + if [ "$1" != "all" ]; then + LLVM_VERSION=$1 + else + # special case for ./llvm.sh all + ALL=1 + fi + OPTIND=2 + if [ "$#" -ge 2 ]; then + if [ "$2" == "all" ]; then + # Install all packages + ALL=1 + OPTIND=3 + fi + fi +fi + +while getopts ":hm:n:" arg; do + case $arg in + h) + usage + ;; + m) + BASE_URL=${OPTARG} + ;; + n) + CODENAME=${OPTARG} + if [[ "${CODENAME}" == "unstable" ]]; then + # link name does not apply to unstable repository + LINKNAME= + else + LINKNAME=-${CODENAME} + fi + CODENAME_FROM_ARGUMENTS="true" + ;; + esac +done + +if [[ $EUID -ne 0 ]]; then + echo "This script must be run as root!" + exit 1 +fi + +declare -A LLVM_VERSION_PATTERNS +LLVM_VERSION_PATTERNS[9]="-9" +LLVM_VERSION_PATTERNS[10]="-10" +LLVM_VERSION_PATTERNS[11]="-11" +LLVM_VERSION_PATTERNS[12]="-12" +LLVM_VERSION_PATTERNS[13]="-13" +LLVM_VERSION_PATTERNS[14]="-14" +LLVM_VERSION_PATTERNS[15]="-15" +LLVM_VERSION_PATTERNS[16]="-16" +LLVM_VERSION_PATTERNS[17]="-17" +LLVM_VERSION_PATTERNS[18]="-18" +LLVM_VERSION_PATTERNS[19]="-19" +LLVM_VERSION_PATTERNS[20]="-20" +LLVM_VERSION_PATTERNS[21]="-21" +LLVM_VERSION_PATTERNS[22]="" + +if [ ! ${LLVM_VERSION_PATTERNS[$LLVM_VERSION]+_} ]; then + echo "This script does not support LLVM version $LLVM_VERSION" + exit 3 +fi + +LLVM_VERSION_STRING=${LLVM_VERSION_PATTERNS[$LLVM_VERSION]} + +# join the repository name +if [[ -n "${CODENAME}" ]]; then + REPO_NAME="deb ${BASE_URL}/${CODENAME}/ llvm-toolchain${LINKNAME}${LLVM_VERSION_STRING} main" + # check if the repository exists for the distro and version + if ! wget -q --method=HEAD ${BASE_URL}/${CODENAME} &> /dev/null && \ + ! curl -sSLI -XHEAD ${BASE_URL}/${CODENAME} &> /dev/null; then + if [[ -n "${CODENAME_FROM_ARGUMENTS}" ]]; then + echo "Specified codename '${CODENAME}' is not supported by this script." + else + echo "Distribution '${DISTRO}' in version '${VERSION}' is not supported by this script." + fi + exit 2 + fi +fi + + +# install everything + +if [[ ! -f /etc/apt/trusted.gpg.d/apt.llvm.org.asc ]]; then + # download GPG key once + if [[ -z "$using_curl" ]]; then + wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc + else + curl -sSL https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc + fi +fi + +if [[ -z "`apt-key list 2> /dev/null | grep -i llvm`" ]]; then + # Delete the key in the old format + apt-key del AF4F7421 || true +fi + + +# Add repository based on distribution +if [[ "${VERSION_CODENAME}" == "bookworm" ]]; then + # add it twice to workaround: + # https://github.com/llvm/llvm-project/issues/62475 + add-apt-repository -y "${REPO_NAME}" + add-apt-repository -y "${REPO_NAME}" +elif [[ $is_new_debian -eq 1 ]]; then + # workaround missing add-apt-repository in newer Debian and use new source.list format + SOURCES_FILE="/etc/apt/sources.list.d/http_apt_llvm_org_${CODENAME}_-${VERSION_CODENAME}.sources" + TEXT_TO_ADD="Types: deb +Architectures: amd64 arm64 +Signed-By: /etc/apt/trusted.gpg.d/apt.llvm.org.asc +URIs: ${BASE_URL}/${CODENAME}/ +Suites: llvm-toolchain${LINKNAME}${LLVM_VERSION_STRING} +Components: main" + echo "$TEXT_TO_ADD" | tee -a "$SOURCES_FILE" > /dev/null +else + add-apt-repository -y "${REPO_NAME}" +fi + +apt-get update +PKG="clang-$LLVM_VERSION lldb-$LLVM_VERSION lld-$LLVM_VERSION clangd-$LLVM_VERSION" +if [[ $ALL -eq 1 ]]; then + # same as in test-install.sh + # No worries if we have dups + PKG="$PKG clang-tidy-$LLVM_VERSION clang-format-$LLVM_VERSION clang-tools-$LLVM_VERSION llvm-$LLVM_VERSION-dev lld-$LLVM_VERSION lldb-$LLVM_VERSION llvm-$LLVM_VERSION-tools libomp-$LLVM_VERSION-dev libc++-$LLVM_VERSION-dev libc++abi-$LLVM_VERSION-dev libclang-common-$LLVM_VERSION-dev libclang-$LLVM_VERSION-dev libclang-cpp$LLVM_VERSION-dev liblldb-$LLVM_VERSION-dev libunwind-$LLVM_VERSION-dev" + if test $LLVM_VERSION -gt 14; then + PKG="$PKG libclang-rt-$LLVM_VERSION-dev libpolly-$LLVM_VERSION-dev" + fi +fi +apt-get install -y $PKG diff --git a/tasks/marov_allreduce/info.json b/tasks/marov_allreduce/info.json new file mode 100644 index 00000000..3b86c934 --- /dev/null +++ b/tasks/marov_allreduce/info.json @@ -0,0 +1,7 @@ +{ + "student": "marov", + "task_id": 2, + "technologies": [ + "mpi" + ] +} diff --git a/tasks/marov_allreduce/mpi/include/ops_mpi.h b/tasks/marov_allreduce/mpi/include/ops_mpi.h new file mode 100644 index 00000000..c66995bc --- /dev/null +++ b/tasks/marov_allreduce/mpi/include/ops_mpi.h @@ -0,0 +1,38 @@ +#pragma once + +#include + +// Типы данных MPI +typedef int MPI_Datatype; +typedef int MPI_Op; + +#define MPI_INT 1 +#define MPI_FLOAT 2 +#define MPI_DOUBLE 3 +#define MPI_SUM 1 +#define MPI_MAX 2 +#define MPI_MIN 3 + +struct MPI_Comm { + int rank; + int size; + std::vector parent; + std::vector> children; + + MPI_Comm(int r, int s); + void buildTree(); +}; + +void Send(const void* buf, int count, MPI_Datatype datatype, int dest, + int tag, MPI_Comm* comm); + +void Recv(void* buf, int count, MPI_Datatype datatype, int source, + int tag, MPI_Comm* comm, void* status); + +size_t getTypeSize(MPI_Datatype datatype); + +template +void applyOperation(T* result, const T* data, int count, MPI_Op op); + +int my_allreduce(const void* sendbuf, void* recvbuf, int count, + MPI_Datatype datatype, MPI_Op op, MPI_Comm* comm); diff --git a/tasks/marov_allreduce/mpi/src/ops_mpi.cpp b/tasks/marov_allreduce/mpi/src/ops_mpi.cpp new file mode 100644 index 00000000..2685de14 --- /dev/null +++ b/tasks/marov_allreduce/mpi/src/ops_mpi.cpp @@ -0,0 +1,130 @@ +#include "marov_allreduce/mpi/include/ops_mpi.h" +#include +#include +#include +#include +#include +#include + +MPI_Comm::MPI_Comm(int r, int s) : rank(r), size(s) { + parent.resize(size, -1); + children.resize(size); + buildTree(); +} + +void MPI_Comm::buildTree() { + // Построение бинарного дерева + for(int i = 0; i < size; i++) { + int left = 2 * i + 1; + int right = 2 * i + 2; + + if(left < size) { + children[i].push_back(left); + parent[left] = i; + } + if(right < size) { + children[i].push_back(right); + parent[right] = i; + } + } +} + +void Send(const void* buf, int count, MPI_Datatype datatype, int dest, + int tag, MPI_Comm* comm) { + (void)buf; + (void)datatype; + std::cout << " [LOG] Process " << comm->rank << " -> " << dest + << " (tag=" << tag << "): " << count << " elements" << std::endl; + + std::this_thread::sleep_for(std::chrono::milliseconds(50)); +} + +void Recv(void* buf, int count, MPI_Datatype datatype, int source, + int tag, MPI_Comm* comm, void* status) { + (void)buf; + (void)datatype; + (void)source; + (void)status; + std::cout << " [LOG] Process " << comm->rank << " <- " << source + << " (tag=" << tag << "): " << count << " elements" << std::endl; + + std::this_thread::sleep_for(std::chrono::milliseconds(50)); +} + +size_t getTypeSize(MPI_Datatype datatype) { + switch(datatype) { + case MPI_INT: return sizeof(int); + case MPI_FLOAT: return sizeof(float); + case MPI_DOUBLE: return sizeof(double); + default: return 0; + } +} + +template +void applyOperation(T* result, const T* data, int count, MPI_Op op) { + switch(op) { + case MPI_SUM: + for(int i = 0; i < count; i++) result[i] += data[i]; + break; + case MPI_MAX: + for(int i = 0; i < count; i++) + if(data[i] > result[i]) result[i] = data[i]; + break; + case MPI_MIN: + for(int i = 0; i < count; i++) + if(data[i] < result[i]) result[i] = data[i]; + break; + } +} + +int my_allreduce(const void* sendbuf, void* recvbuf, int count, + MPI_Datatype datatype, MPI_Op op, MPI_Comm* comm) { + + int rank = comm->rank; + size_t typeSize = getTypeSize(datatype); + + // Копируем входные данные + std::memcpy(recvbuf, sendbuf, count * typeSize); + + // Фаза 1: Редукция (сбор данных к корню) + for(int child : comm->children[rank]) { + std::vector childBuffer(count * typeSize); + + Recv(childBuffer.data(), count, datatype, child, 0, comm, nullptr); + + switch(datatype) { + case MPI_INT: + applyOperation(static_cast(recvbuf), + reinterpret_cast(childBuffer.data()), + count, op); + break; + case MPI_FLOAT: + applyOperation(static_cast(recvbuf), + reinterpret_cast(childBuffer.data()), + count, op); + break; + case MPI_DOUBLE: + applyOperation(static_cast(recvbuf), + reinterpret_cast(childBuffer.data()), + count, op); + break; + } + } + + // Отправляем результат родителю (если не корень) + if(rank != 0) { + Send(recvbuf, count, datatype, comm->parent[rank], 0, comm); + } + + // Фаза 2: Рассылка (broadcast результата всем) + if(rank != 0) { + Recv(recvbuf, count, datatype, comm->parent[rank], 1, comm, nullptr); + } + + // Отправляем результат детям + for(int child : comm->children[rank]) { + Send(recvbuf, count, datatype, child, 1, comm); + } + + return 0; +} diff --git a/tasks/marov_allreduce/mpi/src/ops_mpi.h b/tasks/marov_allreduce/mpi/src/ops_mpi.h new file mode 100644 index 00000000..991b5762 --- /dev/null +++ b/tasks/marov_allreduce/mpi/src/ops_mpi.h @@ -0,0 +1,46 @@ +#ifndef OPS_MPI_H +#define OPS_MPI_H + +#include +#include +#include +#include +#include +#include + +// Типы данных MPI +enum MPI_Datatype { + MPI_INT, + MPI_FLOAT, + MPI_DOUBLE +}; + +// Операции редукции +enum MPI_Op { + MPI_SUM, + MPI_MAX, + MPI_MIN +}; + +struct MPI_Comm { + int rank; + int size; + std::vector parent; + std::vector> children; + + MPI_Comm(int r, int s); + void buildTree(); +}; + +// Функции Send/Recv +void Send(const void* buf, int count, MPI_Datatype datatype, int dest, + int tag, MPI_Comm* comm); + +void Recv(void* buf, int count, MPI_Datatype datatype, int source, + int tag, MPI_Comm* comm, void* status = nullptr); + +// Allreduce через дерево +int my_allreduce(const void* sendbuf, void* recvbuf, int count, + MPI_Datatype datatype, MPI_Op op, MPI_Comm* comm); + +#endif diff --git a/tasks/marov_allreduce/settings.json b/tasks/marov_allreduce/settings.json new file mode 100644 index 00000000..1bff8b48 --- /dev/null +++ b/tasks/marov_allreduce/settings.json @@ -0,0 +1,6 @@ +{ + "tasks": { + "mpi": "enabled" + }, + "tasks_type": "processes" +} diff --git a/tasks/marov_allreduce/tests/CMakeLists.txt b/tasks/marov_allreduce/tests/CMakeLists.txt new file mode 100644 index 00000000..80d8eca7 --- /dev/null +++ b/tasks/marov_allreduce/tests/CMakeLists.txt @@ -0,0 +1,11 @@ +add_executable(marov_allreduce_tests functional/main.cpp) + +target_link_libraries(marov_allreduce_tests + gtest + gtest_main +) + +target_include_directories(marov_allreduce_tests + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/.. + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../mpi/include +) diff --git a/tasks/marov_allreduce/tests/functional/main.cpp b/tasks/marov_allreduce/tests/functional/main.cpp new file mode 100644 index 00000000..ffc31076 --- /dev/null +++ b/tasks/marov_allreduce/tests/functional/main.cpp @@ -0,0 +1,98 @@ +#include +#include +#include "marov_allreduce/mpi/include/ops_mpi.h" + +TEST(marov_allreduce_mpi, sum_ints) { + const int NUM_PROCS = 7; + std::vector sendValues(NUM_PROCS); + std::vector recvValues(NUM_PROCS); + + for(int i = 0; i < NUM_PROCS; i++) { + sendValues[i] = i + 1; + } + + for(int rank = 0; rank < NUM_PROCS; rank++) { + MPI_Comm comm(rank, NUM_PROCS); + int sendData = sendValues[rank]; + int recvData = 0; + + my_allreduce(&sendData, &recvData, 1, MPI_INT, MPI_SUM, &comm); + recvValues[rank] = recvData; + } + + int expected = 0; + for(int v : sendValues) expected += v; + for(int r : recvValues) { + EXPECT_EQ(r, expected); + } +} + +TEST(marov_allreduce_mpi, max_floats) { + const int NUM_PROCS = 7; + std::vector sendValues(NUM_PROCS); + std::vector recvValues(NUM_PROCS); + + for(int i = 0; i < NUM_PROCS; i++) { + sendValues[i] = i * 1.5f; + } + + for(int rank = 0; rank < NUM_PROCS; rank++) { + MPI_Comm comm(rank, NUM_PROCS); + float sendData = sendValues[rank]; + float recvData = 0; + + my_allreduce(&sendData, &recvData, 1, MPI_FLOAT, MPI_MAX, &comm); + recvValues[rank] = recvData; + } + + float expected = 0; + for(float v : sendValues) if(v > expected) expected = v; + for(float r : recvValues) { + EXPECT_EQ(r, expected); + } +} + +TEST(marov_allreduce_mpi, min_doubles) { + const int NUM_PROCS = 7; + const int ARRAY_SIZE = 3; + std::vector> sendValues(NUM_PROCS, std::vector(ARRAY_SIZE)); + std::vector> recvValues(NUM_PROCS, std::vector(ARRAY_SIZE)); + + for(int i = 0; i < NUM_PROCS; i++) { + sendValues[i][0] = i + 1.0; + sendValues[i][1] = i * 2.0; + sendValues[i][2] = i + 0.5; + } + + for(int rank = 0; rank < NUM_PROCS; rank++) { + MPI_Comm comm(rank, NUM_PROCS); + double sendData[ARRAY_SIZE]; + double recvData[ARRAY_SIZE]; + + for(int j = 0; j < ARRAY_SIZE; j++) { + sendData[j] = sendValues[rank][j]; + recvData[j] = 0; + } + + my_allreduce(sendData, recvData, ARRAY_SIZE, MPI_DOUBLE, MPI_MIN, &comm); + + for(int j = 0; j < ARRAY_SIZE; j++) { + recvValues[rank][j] = recvData[j]; + } + } + + std::vector expected(ARRAY_SIZE, 1e9); + for(int i = 0; i < NUM_PROCS; i++) { + for(int j = 0; j < ARRAY_SIZE; j++) { + if(sendValues[i][j] < expected[j]) { + expected[j] = sendValues[i][j]; + } + } + } + + for(int rank = 0; rank < NUM_PROCS; rank++) { + for(int j = 0; j < ARRAY_SIZE; j++) { + EXPECT_EQ(recvValues[rank][j], expected[j]); + } + } +} diff --git a/tasks/marov_count_letters/common/include/common.hpp b/tasks/marov_count_letters/common/include/common.hpp new file mode 100644 index 00000000..44e7c31b --- /dev/null +++ b/tasks/marov_count_letters/common/include/common.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +#include "task/include/task.hpp" + +namespace marov_count_letters { + +using InType = std::string; +using OutType = int; +using TestType = std::tuple; +using BaseTask = ppc::task::Task; + +} // namespace marov_count_letters diff --git a/tasks/marov_count_letters/info.json b/tasks/marov_count_letters/info.json new file mode 100644 index 00000000..2ce0d708 --- /dev/null +++ b/tasks/marov_count_letters/info.json @@ -0,0 +1,8 @@ +{ + "student": "marov", + "task_id": 1, + "technologies": [ + "seq", + "mpi" + ] +} diff --git a/tasks/marov_count_letters/mpi/include/ops_mpi.hpp b/tasks/marov_count_letters/mpi/include/ops_mpi.hpp new file mode 100644 index 00000000..76901f69 --- /dev/null +++ b/tasks/marov_count_letters/mpi/include/ops_mpi.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "marov_count_letters/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace marov_count_letters { + +class MarovCountLettersMPI : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kMPI; + } + explicit MarovCountLettersMPI(const InType &in); + + private: + int proc_rank_{0}; + int proc_size_{1}; + + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; +}; + +} // namespace marov_count_letters diff --git a/tasks/marov_count_letters/mpi/src/ops_mpi.cpp b/tasks/marov_count_letters/mpi/src/ops_mpi.cpp new file mode 100644 index 00000000..6cc85ae2 --- /dev/null +++ b/tasks/marov_count_letters/mpi/src/ops_mpi.cpp @@ -0,0 +1,91 @@ +#include "marov_count_letters/mpi/include/ops_mpi.hpp" + +#include + +#include +#include +#include + +#include "marov_count_letters/common/include/common.hpp" + +namespace marov_count_letters { + +MarovCountLettersMPI::MarovCountLettersMPI(const InType &in) { + MPI_Comm_rank(MPI_COMM_WORLD, &proc_rank_); + MPI_Comm_size(MPI_COMM_WORLD, &proc_size_); + + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = 0; +} + +bool MarovCountLettersMPI::ValidationImpl() { + return true; +} + +bool MarovCountLettersMPI::PreProcessingImpl() { + return true; +} + +bool MarovCountLettersMPI::RunImpl() { + std::string input_str; + int str_len = 0; + + if (proc_rank_ == 0) { + input_str = GetInput(); + str_len = static_cast(input_str.size()); + } + + // Рассылка длины строки всем процессам + MPI_Bcast(&str_len, 1, MPI_INT, 0, MPI_COMM_WORLD); + + // Разделение данных между процессами + const int base = str_len / proc_size_; + const int rem = str_len % proc_size_; + + std::vector send_counts(proc_size_); + std::vector displs(proc_size_); + + if (proc_rank_ == 0) { + int offset = 0; + for (int i = 0; i < proc_size_; ++i) { + send_counts[i] = base + (i < rem ? 1 : 0); + displs[i] = offset; + offset += send_counts[i]; + } + } + + MPI_Bcast(send_counts.data(), proc_size_, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(displs.data(), proc_size_, MPI_INT, 0, MPI_COMM_WORLD); + + const int local_size = base + (proc_rank_ < rem ? 1 : 0); + std::vector local_data(local_size); + + MPI_Scatterv(proc_rank_ == 0 ? const_cast(input_str.data()) : nullptr, + send_counts.data(), displs.data(), MPI_CHAR, + local_data.data(), local_size, MPI_CHAR, 0, MPI_COMM_WORLD); + + // Подсчет буквенных символов локально + int local_count = 0; + for (int i = 0; i < local_size; ++i) { + if (std::isalpha(static_cast(local_data[i]))) { + local_count++; + } + } + + // Редукция - сумма всех локальных подсчетов + int global_count = 0; + MPI_Reduce(&local_count, &global_count, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); + + if (proc_rank_ == 0) { + GetOutput() = global_count; + } + + return true; +} + +bool MarovCountLettersMPI::PostProcessingImpl() { + return true; +} + +} // namespace marov_count_letters diff --git a/tasks/marov_count_letters/seq/include/ops_seq.hpp b/tasks/marov_count_letters/seq/include/ops_seq.hpp new file mode 100644 index 00000000..04af274b --- /dev/null +++ b/tasks/marov_count_letters/seq/include/ops_seq.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "marov_count_letters/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace marov_count_letters { + +class MarovCountLettersSEQ : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kSEQ; + } + explicit MarovCountLettersSEQ(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; +}; + +} // namespace marov_count_letters diff --git a/tasks/marov_count_letters/seq/src/ops_seq.cpp b/tasks/marov_count_letters/seq/src/ops_seq.cpp new file mode 100644 index 00000000..1e113eb3 --- /dev/null +++ b/tasks/marov_count_letters/seq/src/ops_seq.cpp @@ -0,0 +1,42 @@ +#include "marov_count_letters/seq/include/ops_seq.hpp" + +#include +#include + +#include "marov_count_letters/common/include/common.hpp" + +namespace marov_count_letters { + +MarovCountLettersSEQ::MarovCountLettersSEQ(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = 0; +} + +bool MarovCountLettersSEQ::ValidationImpl() { + return true; +} + +bool MarovCountLettersSEQ::PreProcessingImpl() { + return true; +} + +bool MarovCountLettersSEQ::RunImpl() { + const std::string &input_str = GetInput(); + int count = 0; + + for (char c : input_str) { + if (std::isalpha(static_cast(c))) { + count++; + } + } + + GetOutput() = count; + return true; +} + +bool MarovCountLettersSEQ::PostProcessingImpl() { + return true; +} + +} // namespace marov_count_letters diff --git a/tasks/marov_count_letters/settings.json b/tasks/marov_count_letters/settings.json new file mode 100644 index 00000000..16f25e42 --- /dev/null +++ b/tasks/marov_count_letters/settings.json @@ -0,0 +1,7 @@ +{ + "tasks": { + "mpi": "enabled", + "seq": "enabled" + }, + "tasks_type": "processes" +} diff --git a/tasks/marov_count_letters/tests/.clang-tidy b/tasks/marov_count_letters/tests/.clang-tidy new file mode 100644 index 00000000..ef43b7aa --- /dev/null +++ b/tasks/marov_count_letters/tests/.clang-tidy @@ -0,0 +1,13 @@ +InheritParentConfig: true + +Checks: > + -modernize-loop-convert, + -cppcoreguidelines-avoid-goto, + -cppcoreguidelines-avoid-non-const-global-variables, + -misc-use-anonymous-namespace, + -modernize-use-std-print, + -modernize-type-traits + +CheckOptions: + - key: readability-function-cognitive-complexity.Threshold + value: 50 # Relaxed for tests diff --git a/tasks/marov_count_letters/tests/CMakeLists.txt b/tasks/marov_count_letters/tests/CMakeLists.txt new file mode 100644 index 00000000..6cd0ceea --- /dev/null +++ b/tasks/marov_count_letters/tests/CMakeLists.txt @@ -0,0 +1,12 @@ +add_executable(marov_count_letters_tests functional/main.cpp) + +target_link_libraries(marov_count_letters_tests + gtest + gtest_main + MPI::MPI_CXX +) + +target_include_directories(marov_count_letters_tests + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../seq/include + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../mpi/include +) diff --git a/tasks/marov_count_letters/tests/functional/main.cpp b/tasks/marov_count_letters/tests/functional/main.cpp new file mode 100644 index 00000000..b8c5cd69 --- /dev/null +++ b/tasks/marov_count_letters/tests/functional/main.cpp @@ -0,0 +1,68 @@ +#include + +#include +#include +#include +#include + +#include "marov_count_letters/common/include/common.hpp" +#include "marov_count_letters/mpi/include/ops_mpi.hpp" +#include "marov_count_letters/seq/include/ops_seq.hpp" +#include "util/include/func_test_util.hpp" +#include "util/include/util.hpp" + +namespace marov_count_letters { + +class MarovCountLettersFuncTests : public ppc::util::BaseRunFuncTests { + public: + static std::string PrintTestParam(const testing::TestParamInfo& info) { + return "test_" + std::to_string(info.index); + } + + protected: + void SetUp() override { + const auto& [input_str, expected] = std::get<2>(GetParam()); + input_data_ = input_str; + expected_output_ = expected; + } + + bool CheckTestOutputData(OutType& result) final { + return result == expected_output_; + } + + InType GetTestInputData() final { + return input_data_; + } + + private: + InType input_data_; + OutType expected_output_ = 0; +}; + +namespace { + +TEST_P(MarovCountLettersFuncTests, CountLetterChars) { + ExecuteTest(GetParam()); +} + +const std::array kTestCases = { + std::make_tuple(std::string("Hello, World!"), 10), + std::make_tuple(std::string("12345"), 0), + std::make_tuple(std::string(""), 0), + std::make_tuple(std::string("abcdef"), 6), + std::make_tuple(std::string("ABC xyz"), 7), + std::make_tuple(std::string("Test123String"), 10), + std::make_tuple(std::string("!!!"), 0), + std::make_tuple(std::string("aBcDeFgHiJkLmNoPqRsTuVwXyZ"), 26), +}; + +const auto kAllTestTasks = std::tuple_cat( + ppc::util::AddFuncTask(kTestCases, PPC_SETTINGS_marov_count_letters), + ppc::util::AddFuncTask(kTestCases, PPC_SETTINGS_marov_count_letters)); + +INSTANTIATE_TEST_SUITE_P(LetterCountFuncTests, MarovCountLettersFuncTests, + ppc::util::ExpandToValues(kAllTestTasks), + MarovCountLettersFuncTests::PrintTestParam); + +} // namespace +} // namespace marov_count_letters diff --git a/tasks/marov_radix_sort_double/common/include/common.hpp b/tasks/marov_radix_sort_double/common/include/common.hpp new file mode 100644 index 00000000..ea8f83e5 --- /dev/null +++ b/tasks/marov_radix_sort_double/common/include/common.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +#include "task/include/task.hpp" + +namespace marov_radix_sort_double { + +using InType = std::vector; +using OutType = std::vector; +using TestType = std::tuple, std::vector>; +using BaseTask = ppc::task::Task; + +} // namespace marov_radix_sort_double diff --git a/tasks/marov_radix_sort_double/info.json b/tasks/marov_radix_sort_double/info.json new file mode 100644 index 00000000..76a0e6a9 --- /dev/null +++ b/tasks/marov_radix_sort_double/info.json @@ -0,0 +1,8 @@ +{ + "student": "marov", + "task_id": 3, + "technologies": [ + "seq", + "mpi" + ] +} diff --git a/tasks/marov_radix_sort_double/mpi/include/ops_mpi.hpp b/tasks/marov_radix_sort_double/mpi/include/ops_mpi.hpp new file mode 100644 index 00000000..e26b8d99 --- /dev/null +++ b/tasks/marov_radix_sort_double/mpi/include/ops_mpi.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "marov_radix_sort_double/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace marov_radix_sort_double { + +class MarovRadixSortDoubleMpi : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kMPI; + } + explicit MarovRadixSortDoubleMpi(const InType& in); + + private: + int proc_rank_{0}; + int proc_size_{1}; + + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; +}; + +} // namespace marov_radix_sort_double diff --git a/tasks/marov_radix_sort_double/mpi/src/ops_mpi.cpp b/tasks/marov_radix_sort_double/mpi/src/ops_mpi.cpp new file mode 100644 index 00000000..fe0dfa78 --- /dev/null +++ b/tasks/marov_radix_sort_double/mpi/src/ops_mpi.cpp @@ -0,0 +1,175 @@ +#include "marov_radix_sort_double/mpi/include/ops_mpi.hpp" + +#include + +#include +#include +#include +#include + +#include "marov_radix_sort_double/common/include/common.hpp" + +namespace marov_radix_sort_double { + +namespace { + +uint64_t DoubleToSortableUint64(double val) { + uint64_t bits = 0; + std::memcpy(&bits, &val, sizeof(double)); + if ((bits >> 63) != 0) { + bits = ~bits; + } else { + bits |= (1ULL << 63); + } + return bits; +} + +double SortableUint64ToDouble(uint64_t bits) { + if ((bits >> 63) != 0) { + bits &= ~(1ULL << 63); + } else { + bits = ~bits; + } + double val = 0; + std::memcpy(&val, &bits, sizeof(double)); + return val; +} + +void RadixSortDoubles(std::vector& data) { + if (data.size() <= 1) { + return; + } + + std::vector keys(data.size()); + for (size_t i = 0; i < data.size(); ++i) { + keys[i] = DoubleToSortableUint64(data[i]); + } + + const int k_radix = 256; + std::vector temp(data.size()); + + for (int shift = 0; shift < 64; shift += 8) { + std::vector count(k_radix + 1, 0); + + for (uint64_t key : keys) { + uint8_t digit = (key >> shift) & 0xFF; + ++count[digit + 1]; + } + + for (int i = 0; i < k_radix; ++i) { + count[i + 1] += count[i]; + } + + for (uint64_t key : keys) { + uint8_t digit = (key >> shift) & 0xFF; + size_t pos = count[digit]; + temp[pos] = key; + ++count[digit]; + } + + keys.swap(temp); + } + + for (size_t i = 0; i < data.size(); ++i) { + data[i] = SortableUint64ToDouble(keys[i]); + } +} + +std::vector MergeSorted(const std::vector& a, + const std::vector& b) { + std::vector result; + result.reserve(a.size() + b.size()); + size_t i = 0; + size_t j = 0; + while (i < a.size() && j < b.size()) { + if (a[i] < b[j]) { + result.push_back(a[i++]); + } else { + result.push_back(b[j++]); + } + } + while (i < a.size()) { + result.push_back(a[i++]); + } + while (j < b.size()) { + result.push_back(b[j++]); + } + return result; +} + +} // namespace + +MarovRadixSortDoubleMpi::MarovRadixSortDoubleMpi(const InType& in) { + MPI_Comm_rank(MPI_COMM_WORLD, &proc_rank_); + MPI_Comm_size(MPI_COMM_WORLD, &proc_size_); + + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; +} + +bool MarovRadixSortDoubleMpi::ValidationImpl() { + int initialized = 0; + MPI_Initialized(&initialized); + return initialized != 0; +} + +bool MarovRadixSortDoubleMpi::PreProcessingImpl() { + return true; +} + +bool MarovRadixSortDoubleMpi::RunImpl() { + const auto& input = GetInput(); + int n = static_cast(input.size()); + + MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); + + std::vector counts(proc_size_); + std::vector displs(proc_size_); + + int base = n / proc_size_; + int rem = n % proc_size_; + int offset = 0; + + for (int i = 0; i < proc_size_; ++i) { + counts[i] = base + (i < rem ? 1 : 0); + displs[i] = offset; + offset += counts[i]; + } + + std::vector local_data(counts[proc_rank_]); + + MPI_Scatterv(proc_rank_ == 0 ? input.data() : nullptr, counts.data(), + displs.data(), MPI_DOUBLE, local_data.data(), + counts[proc_rank_], MPI_DOUBLE, 0, MPI_COMM_WORLD); + + RadixSortDoubles(local_data); + + std::vector result; + if (proc_rank_ == 0) { + result = std::move(local_data); + + for (int proc = 1; proc < proc_size_; ++proc) { + int recv_count = 0; + MPI_Recv(&recv_count, 1, MPI_INT, proc, 0, MPI_COMM_WORLD, + MPI_STATUS_IGNORE); + std::vector part(recv_count); + MPI_Recv(part.data(), recv_count, MPI_DOUBLE, proc, 1, MPI_COMM_WORLD, + MPI_STATUS_IGNORE); + result = MergeSorted(result, part); + } + + GetOutput() = result; + } else { + int send_count = static_cast(local_data.size()); + MPI_Send(&send_count, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); + MPI_Send(local_data.data(), send_count, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD); + } + + return true; +} + +bool MarovRadixSortDoubleMpi::PostProcessingImpl() { + return true; +} + +} // namespace marov_radix_sort_double diff --git a/tasks/marov_radix_sort_double/seq/include/ops_seq.hpp b/tasks/marov_radix_sort_double/seq/include/ops_seq.hpp new file mode 100644 index 00000000..fdfa6035 --- /dev/null +++ b/tasks/marov_radix_sort_double/seq/include/ops_seq.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "marov_radix_sort_double/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace marov_radix_sort_double { + +class MarovRadixSortDoubleSeq : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kSEQ; + } + explicit MarovRadixSortDoubleSeq(const InType& in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; +}; + +} // namespace marov_radix_sort_double diff --git a/tasks/marov_radix_sort_double/seq/src/ops_seq.cpp b/tasks/marov_radix_sort_double/seq/src/ops_seq.cpp new file mode 100644 index 00000000..8f89e2ac --- /dev/null +++ b/tasks/marov_radix_sort_double/seq/src/ops_seq.cpp @@ -0,0 +1,101 @@ +#include "marov_radix_sort_double/seq/include/ops_seq.hpp" + +#include +#include +#include + +#include "marov_radix_sort_double/common/include/common.hpp" + +namespace marov_radix_sort_double { + +namespace { + +uint64_t DoubleToSortableUint64(double val) { + uint64_t bits = 0; + std::memcpy(&bits, &val, sizeof(double)); + if ((bits >> 63) != 0) { + bits = ~bits; + } else { + bits |= (1ULL << 63); + } + return bits; +} + +double SortableUint64ToDouble(uint64_t bits) { + if ((bits >> 63) != 0) { + bits &= ~(1ULL << 63); + } else { + bits = ~bits; + } + double val = 0; + std::memcpy(&val, &bits, sizeof(double)); + return val; +} + +void RadixSortDoubles(std::vector& data) { + if (data.size() <= 1) { + return; + } + + std::vector keys(data.size()); + for (size_t i = 0; i < data.size(); ++i) { + keys[i] = DoubleToSortableUint64(data[i]); + } + + const int k_radix = 256; + std::vector temp(data.size()); + + for (int shift = 0; shift < 64; shift += 8) { + std::vector count(k_radix + 1, 0); + + for (uint64_t key : keys) { + uint8_t digit = (key >> shift) & 0xFF; + ++count[digit + 1]; + } + + for (int i = 0; i < k_radix; ++i) { + count[i + 1] += count[i]; + } + + for (uint64_t key : keys) { + uint8_t digit = (key >> shift) & 0xFF; + size_t pos = count[digit]; + temp[pos] = key; + ++count[digit]; + } + + keys.swap(temp); + } + + for (size_t i = 0; i < data.size(); ++i) { + data[i] = SortableUint64ToDouble(keys[i]); + } +} + +} // namespace + +MarovRadixSortDoubleSeq::MarovRadixSortDoubleSeq(const InType& in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; +} + +bool MarovRadixSortDoubleSeq::ValidationImpl() { + return true; +} + +bool MarovRadixSortDoubleSeq::PreProcessingImpl() { + return true; +} + +bool MarovRadixSortDoubleSeq::RunImpl() { + auto& input = GetInput(); + RadixSortDoubles(input); + GetOutput() = input; + return true; +} + +bool MarovRadixSortDoubleSeq::PostProcessingImpl() { + return true; +} + +} // namespace marov_radix_sort_double diff --git a/tasks/marov_radix_sort_double/seq/src/ops_seq.h b/tasks/marov_radix_sort_double/seq/src/ops_seq.h new file mode 100644 index 00000000..ad12519f --- /dev/null +++ b/tasks/marov_radix_sort_double/seq/src/ops_seq.h @@ -0,0 +1,8 @@ +#ifndef OPS_SEQ_H +#define OPS_SEQ_H + +#include + +void radix_sort_double(std::vector &arr); + +#endif diff --git a/tasks/marov_radix_sort_double/settings.json b/tasks/marov_radix_sort_double/settings.json new file mode 100644 index 00000000..16f25e42 --- /dev/null +++ b/tasks/marov_radix_sort_double/settings.json @@ -0,0 +1,7 @@ +{ + "tasks": { + "mpi": "enabled", + "seq": "enabled" + }, + "tasks_type": "processes" +} diff --git a/tasks/marov_radix_sort_double/tests/CMakeLists.txt b/tasks/marov_radix_sort_double/tests/CMakeLists.txt new file mode 100644 index 00000000..fb156060 --- /dev/null +++ b/tasks/marov_radix_sort_double/tests/CMakeLists.txt @@ -0,0 +1,12 @@ +add_executable(marov_radix_sort_double_tests functional/main.cpp) + +target_link_libraries(marov_radix_sort_double_tests + gtest + gtest_main + MPI::MPI_CXX +) + +target_include_directories(marov_radix_sort_double_tests + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../seq/include + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../mpi/include +) diff --git a/tasks/marov_radix_sort_double/tests/functional/main.cpp b/tasks/marov_radix_sort_double/tests/functional/main.cpp new file mode 100644 index 00000000..e8f15921 --- /dev/null +++ b/tasks/marov_radix_sort_double/tests/functional/main.cpp @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include + +#include "marov_radix_sort_double/common/include/common.hpp" +#include "marov_radix_sort_double/mpi/include/ops_mpi.hpp" +#include "marov_radix_sort_double/seq/include/ops_seq.hpp" +#include "util/include/func_test_util.hpp" + +namespace marov_radix_sort_double { + +class MarovRadixSortDoubleFuncTests + : public ppc::util::BaseRunFuncTests { + public: + static std::string PrintTestParam( + const testing::TestParamInfo& info) { + return "test_" + std::to_string(info.index); + } + + protected: + void SetUp() override { + const auto& [input_vec, expected_vec] = std::get<2>(GetParam()); + input_data_ = input_vec; + expected_output_ = expected_vec; + } + + bool CheckTestOutputData(OutType& result) final { + return result == expected_output_; + } + + InType GetTestInputData() final { + return input_data_; + } + + private: + InType input_data_; + OutType expected_output_; +}; + +namespace { + +TEST_P(MarovRadixSortDoubleFuncTests, RadixSortDoubleSimpleMerge) { + ExecuteTest(GetParam()); +} + +const std::array kTestCases = { + std::make_tuple(std::vector{5.0, 2.0, 8.0, 1.0, 9.0}, + std::vector{1.0, 2.0, 5.0, 8.0, 9.0}), + std::make_tuple(std::vector{}, std::vector{}), + std::make_tuple(std::vector{1.0}, std::vector{1.0}), + std::make_tuple(std::vector{3.0, 1.0, 4.0, 1.0, 5.0, 9.0, 2.0, 6.0}, + std::vector{1.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 9.0}), + std::make_tuple(std::vector{-5.0, 3.0, -1.0, 0.0, 2.0}, + std::vector{-5.0, -1.0, 0.0, 2.0, 3.0}), + std::make_tuple(std::vector{1.5, 3.7, 2.1, 0.5, 4.9}, + std::vector{0.5, 1.5, 2.1, 3.7, 4.9}), +}; + +const auto kAllTestTasks = + std::tuple_cat(ppc::util::AddFuncTask( + kTestCases, PPC_SETTINGS_marov_radix_sort_double), + ppc::util::AddFuncTask( + kTestCases, PPC_SETTINGS_marov_radix_sort_double)); + +INSTANTIATE_TEST_SUITE_P( + RadixSortDoubleFuncTests, MarovRadixSortDoubleFuncTests, + ppc::util::ExpandToValues(kAllTestTasks), + MarovRadixSortDoubleFuncTests::PrintTestParam); + +} // namespace +} // namespace marov_radix_sort_double diff --git a/tasks/morozova_s_broadcast/info.json b/tasks/morozova_s_broadcast/info.json index 6e00e955..37cfff3a 100644 --- a/tasks/morozova_s_broadcast/info.json +++ b/tasks/morozova_s_broadcast/info.json @@ -1,9 +1,9 @@ { "student": { - "first_name": "\u0421\u043e\u0444\u044c\u044f", - "group_number": "3823\u04111\u0424\u04182", - "last_name": "\u041c\u043e\u0440\u043e\u0437\u043e\u0432\u0430", - "middle_name": "\u0410\u043d\u0434\u0440\u0435\u0435\u0432\u043d\u0430", + "first_name": "Софья", + "group_number": "3823Б1ФИ2", + "last_name": "Морозова", + "middle_name": "Андреевна", "task_number": "2" } } diff --git a/tasks/morozova_s_connected_components/info.json b/tasks/morozova_s_connected_components/info.json index bfc872ee..7c61f3e8 100644 --- a/tasks/morozova_s_connected_components/info.json +++ b/tasks/morozova_s_connected_components/info.json @@ -1,9 +1,9 @@ { "student": { - "first_name": "\u0421\u043e\u0444\u044c\u044f", - "group_number": "3823\u04111\u0424\u04182", - "last_name": "\u041c\u043e\u0440\u043e\u0437\u043e\u0432\u0430", - "middle_name": "\u0410\u043d\u0434\u0440\u0435\u0435\u0432\u043d\u0430", + "first_name": "Софья", + "group_number": "3823Б1ФИ2", + "last_name": "Морозова", + "middle_name": "Андреевна", "task_number": "3" } } diff --git a/tasks/morozova_s_matrix_max_value/info.json b/tasks/morozova_s_matrix_max_value/info.json index 6093ef36..55b1dd62 100644 --- a/tasks/morozova_s_matrix_max_value/info.json +++ b/tasks/morozova_s_matrix_max_value/info.json @@ -1,9 +1,9 @@ { "student": { - "first_name": "\u0421\u043e\u0444\u044c\u044f", - "group_number": "3823\u04111\u0424\u04182", - "last_name": "\u041c\u043e\u0440\u043e\u0437\u043e\u0432\u0430", - "middle_name": "\u0410\u043d\u0434\u0440\u0435\u0435\u0432\u043d\u0430", + "first_name": "Софья", + "group_number": "3823Б1ФИ2", + "last_name": "Морозова", + "middle_name": "Андреевна", "task_number": "1" } } diff --git a/tasks/sabutay_a_increasing_contrast/info.json b/tasks/sabutay_a_increasing_contrast/info.json index dc0cc8e1..48cfe931 100644 --- a/tasks/sabutay_a_increasing_contrast/info.json +++ b/tasks/sabutay_a_increasing_contrast/info.json @@ -1,7 +1,7 @@ { - "first_name": "\u0421\u0430\u0431\u0443\u0442\u0430\u0439", - "group_number": "3823\u04111\u041f\u04205", - "last_name": "\u0418\u043c\u0430\u043d\u043e\u0432", - "middle_name": "\u0428\u0438\u0440\u0437\u0430\u0434 \u043e\u0433\u043b\u044b", + "first_name": "Сабутай", + "group_number": "3823Б1ПР5", + "last_name": "Иманов", + "middle_name": "Ширзад оглы", "task_number": "2" } diff --git a/tasks/sabutay_a_radix_sort_double_with_merge/info.json b/tasks/sabutay_a_radix_sort_double_with_merge/info.json index e80b9e1a..0f1b1d1c 100644 --- a/tasks/sabutay_a_radix_sort_double_with_merge/info.json +++ b/tasks/sabutay_a_radix_sort_double_with_merge/info.json @@ -1,7 +1,7 @@ { - "first_name": "\u0421\u0430\u0431\u0443\u0442\u0430\u0439", - "group_number": "3823\u04111\u041f\u04205", - "last_name": "\u0418\u043c\u0430\u043d\u043e\u0432", - "middle_name": "\u0428\u0438\u0440\u0437\u0430\u0434 \u043e\u0433\u043b\u044b", + "first_name": "Сабутай", + "group_number": "3823Б1ПР5", + "last_name": "Иманов", + "middle_name": "Ширзад оглы", "task_number": "3" } diff --git a/tasks/sabutay_vector_sign_changes/info.json b/tasks/sabutay_vector_sign_changes/info.json index 42452825..522356e0 100644 --- a/tasks/sabutay_vector_sign_changes/info.json +++ b/tasks/sabutay_vector_sign_changes/info.json @@ -1,9 +1,9 @@ { "student": { - "first_name": "\u0421\u0430\u0431\u0443\u0442\u0430\u0439", - "group_number": "3823\u04111\u041f\u04205", - "last_name": "\u0418\u043c\u0430\u043d\u043e\u0432", - "middle_name": "\u0428\u0438\u0440\u0437\u0430\u0434 \u043e\u0433\u043b\u044b", + "first_name": "Сабутай", + "group_number": "3823Б1ПР5", + "last_name": "Иманов", + "middle_name": "Ширзад оглы", "task_number": "1" } } diff --git a/tasks/shkryleva_s_vec_min_val/info.json b/tasks/shkryleva_s_vec_min_val/info.json index 4bd27939..fd300eec 100644 --- a/tasks/shkryleva_s_vec_min_val/info.json +++ b/tasks/shkryleva_s_vec_min_val/info.json @@ -1,9 +1,9 @@ { "student": { - "first_name": "\u0421\u0432\u0435\u0442\u043b\u0430\u043d\u0430", - "group_number": "3823\u04111\u041f\u04201", - "last_name": "\u0428\u043a\u0440\u044b\u043b\u0451\u0432\u0430", - "middle_name": "\u0410\u043b\u0435\u043a\u0441\u0435\u0435\u0432\u043d\u0430", + "first_name": "Светлана", + "group_number": "3823Б1ПР1", + "last_name": "Шкрылёва", + "middle_name": "Алексеевна", "task_number": "1" } } diff --git a/tasks/tsarkov_k_lexicographic_string_compare/info.json b/tasks/tsarkov_k_lexicographic_string_compare/info.json index a8c2a295..05ad5f47 100644 --- a/tasks/tsarkov_k_lexicographic_string_compare/info.json +++ b/tasks/tsarkov_k_lexicographic_string_compare/info.json @@ -1,7 +1,7 @@ { "student": { "first_name": "Klim", - "group_number": "3823\u04111\u041f\u04204", + "group_number": "3823Б1ПР4", "last_name": "Tsarkov", "middle_name": "Alexandrovich", "task_number": "1" diff --git a/tasks/yushkova_p_min_in_matrix/info.json b/tasks/yushkova_p_min_in_matrix/info.json index 19703457..9f2da1d7 100644 --- a/tasks/yushkova_p_min_in_matrix/info.json +++ b/tasks/yushkova_p_min_in_matrix/info.json @@ -1,9 +1,9 @@ { "student": { - "first_name": "\u041f\u043e\u043b\u0438\u043d\u0430", - "group_number": "3823\u04111\u041f\u04202", - "last_name": "\u042e\u0448\u043a\u043e\u0432\u0430", - "middle_name": "\u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u043e\u0432\u043d\u0430", + "first_name": "Полина", + "group_number": "3823Б1ПР2", + "last_name": "Юшкова", + "middle_name": "Александровна", "task_number": "1" } } diff --git a/tasks/zyuzin_n_sum_elements_of_matrix/info.json b/tasks/zyuzin_n_sum_elements_of_matrix/info.json index a2559424..b8774ece 100644 --- a/tasks/zyuzin_n_sum_elements_of_matrix/info.json +++ b/tasks/zyuzin_n_sum_elements_of_matrix/info.json @@ -1,9 +1,9 @@ { "student": { - "first_name": "\u041d\u0438\u043a\u0438\u0442\u0430", - "group_number": "3823\u04111\u041f\u04202", - "last_name": "\u0417\u044e\u0437\u0438\u043d", - "middle_name": "\u041c\u0438\u0445\u0430\u0439\u043b\u043e\u0432\u0438\u0447", + "first_name": "Никита", + "group_number": "3823Б1ПР2", + "last_name": "Зюзин", + "middle_name": "Михайлович", "task_number": "1" } }