Добавил:
СПбГУТ * ИКСС * Программная инженерия Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
АОПИ. Сортировка и интерполяция.pdf
Скачиваний:
19
Добавлен:
05.02.2022
Размер:
3.39 Mб
Скачать

ИСХОДНЫЕ ФАЙЛЫ MAIN

main.cpp

///------------------

///Главный файл: main.cpp

///------------------

///Подключение стандартных библиотек

#include "FuncLib.h" /// Основные функции для работы с программой #include <iostream> /// Для работы с консольным вводом-выводом #include <cstdint> /// Для работы с типами фиксированного размера #include <deque> /// Для работы с двусторонними очередями

using std::cin; /// Используем поток ввода using std::cout; /// Используем поток вывода

/// Переменная, описывающая текущее состояние системы uint8_t uMode = 0;

/// nAmountOfPoints — количество точек (X, Y) uint32_t nAmountOfPoints = 0;

/// Двусторонние очереди: координаты X и Y std::deque<long double> TContainerX; std::deque<long double> TContainerY;

void MainMenu() { while (true) {

system("cls"); /// Очистка экрана

nAmountOfPoints = TContainerX.size(); /// Узнаем количество точек

/// Если нет ни одной точки, то режим в 0 if (nAmountOfPoints < 1) uMode = 0;

/// Если точек >= 1 и режим установлен в 0, то режим в 1 if (nAmountOfPoints >= 1 && uMode == 0) uMode = 1;

/// Вывод меню

cout << "####### MENU #######\n"

<< "# Current record count: " << nAmountOfPoints << '\n' << "# Choose option:\n"

<< "0. Safe exit\n"

<< "1. Add data from file\n"

<< "2. Add data from console\n";

/// Если режим установлен в 1 или в 2, то вывод доп. функций if (uMode >= 1) {

cout << "-------\n" << "3. Save existing data to file\n"

<<"4. Show existing data\n"

<<"5. Delete some data\n"

<<"6. Clear all data\n"

<<"7. Sort data and remove duplicates\n";

}

/// Если режим установлен в 2, то вывод доп. функций if (uMode >= 2) {

cout << "-------\n" << "8. Interpolate by point\n" << "9. Interpolate by segment\n";

}

cout << "-------\n!. Memory status\n-------\n";

/// Пользователь вводит цифру - номер функции

/// Выполняются только функции, соответствующие текущему этапу (режиму) switch (cin.get()) {

case '0' : return;

case '1' : FuncLib::AddDataFromFile(TContainerX, TContainerY); break;

case '2' : FuncLib::AddDataFromConsole(TContainerX, TContainerY);

break;

17

case '3' : if (uMode >= 1) FuncLib::SaveDataToFile(TContainerX,

TContainerY); break;

case '4' : if (uMode >= 1) FuncLib::ShowData(TContainerX, TContainerY, false); break;

case '5' : if (uMode >= 1) FuncLib::DeleteData(TContainerX, TContainerY); break;

case '6' : if (uMode >= 1) FuncLib::ClearData(TContainerX,

TContainerY); break;

case '7' : if (uMode >= 1) { FuncLib::optHoareSortAndRemoveDuplicates(TContainerX,

TContainerY);

uMode = 2; /// Состояние: данные готовы для интерполяции

}

break;

case '8' : if (uMode >= 2)

FuncLib::optLagrangeInterpolation(TContainerX, TContainerY, false); break; case '9' : if (uMode >= 2)

FuncLib::optLagrangeInterpolation(TContainerX, TContainerY, true); break; case '!' : FuncLib::DrawMemoryStatus(); break;

}

cout << "# PRESS ENTER #"; cin.get(); /// Ввод для продолжения

FuncLib::CinRecovery(); /// Восстановление потока ввода cin

}

}

int main() {

/// Информационное сообщение для пользователя

cout << "############################################\n"; cout << "Interpolation of data by the Lagrange method\n"; cout << "with preliminary sorting by the Hoare method\n"; cout << "############################################\n";

cout << std::fixed; /// Программа работает с фиксированным выводом чисел cin.get(); /// Ожидание ввода для продолжения

MainMenu(); /// Вызов функции отображения меню TContainerX.clear(); /// Очистка контейнера с координатами X TContainerY.clear(); /// Очистка контейнера с координатами Y

/// Сообщение об успешном завершении программы

cout << "--------------------\n" << "The program completed successfully!..\n"; return 0;

}

18

FuncLib.h

///------------------

///Библиотека основных функций (H)

///------------------

#include "InterLib.h" /// Для работы с сортировкой и интерполяцией #include <cstdint> /// Для работы с целочисленными фиксированными типами #include <deque> /// Для работы с двусторонними очередями

#ifndef _MFUNC_LIB_ #define _MFUNC_LIB_

/// Пространство имен FuncLib namespace FuncLib {

/// Целый индексный тип фиксированного размера (для индексации) using IntegerType = uint32_t;

/// Вещественный тип

using NumericalType = long double;

/// Контейнер типа двусторонняя очередь

using ContainerType = std::deque<NumericalType>;

/// Восстановление потока CIN после некорректного ввода void CinRecovery();

/// Добавление данных из файла

bool AddDataFromFile(ContainerType &, ContainerType &);

/// Добавление данных из консоли

void AddDataFromConsole(ContainerType &, ContainerType &);

/// Сохранение данных в файл

bool SaveDataToFile(ContainerType &, ContainerType & );

/// Очистка данных

void ClearData(ContainerType &, ContainerType & );

/// Функция отображения имеющихся точек

void ShowData(ContainerType &, ContainerType &, bool);

/// Функция отображения имеющихся точек

void DeleteData(ContainerType &, ContainerType &);

/// Сортировка Хоара

void optHoareSortAndRemoveDuplicates(ContainerType &, ContainerType &);

/// Интерполяция Лагранжа

void optLagrangeInterpolation(ContainerType &, ContainerType &, bool);

/// Отрисовка статуса памяти void DrawMemoryStatus();

}

#endif

19

FuncLib.cpp

///------------------

///Библиотека основных функций (CPP)

///------------------

#include "InterLib.h" /// Для работы с сортировкой и интерполяцией

#define MAX_POINTS 10000000L /// Максимум 10.000.000 точек

#include <cstdint> /// Для работы с целочисленными фиксированными типами #include <iostream> /// Для работы с консольным вводом-выводом

#include <fstream> /// Для работы с файловым вводом-выводом #include <deque> /// Для работы с двусторонними очередями

#include <iomanip> /// Для работы с фиксированным и экспоненциальным выводом чисел #include <limits> /// Для сравнения чисел с предельными значениями их типов #include <windows.h> /// Для работы с механизмами ядра

#include <ctime> /// Для работы с временем #include <cstring> /// Для работы со строками

/// Пространство имен FuncLib namespace FuncLib {

using std::cin; /// Используем поток ввода using std::cout; /// Используем поток вывода

/// Целый индексный тип фиксированного размера (для индексации) using IntegerType = uint32_t;

/// Вещественный тип

using NumericalType = long double;

/// Контейнер типа двусторонняя очередь

using ContainerType = std::deque<NumericalType>;

/// 5 минут на ожидание объектов

const int TIME_FOR_OBJECTS = 5 * 60 * 1000;

/// 5 минут на ожидание сортировки const int TIME_FOR_SORT = 5 * 60 * 1000;

///5 минут на ожидание функции удаления дубликатов const int TIME_FOR_RD = 5 * 60 * 1000;

///Анонимное пространство имен (доступ только внутри FuncLib) namespace {

HANDLE hPipe; /// Дескриптор канала

PROCESS_INFORMATION piProcess; /// Информация о процессе

HANDLE hThread; /// Дескриптор потока HANDLE hMutex; /// Дескриптор мьютекса HANDLE hSemaphore; /// Дескриптор семафора HANDLE hEvent; /// Дескриптор события

HANDLE hWaitableTimer; /// Дескриптор ожидающего таймера

}

/// Восстановление потока ввода при некорректном вводе void CinRecovery();

/// Добавление данных из файла

bool AddDataFromFile(ContainerType &, ContainerType &);

/// Добавление данных из консоли

void AddDataFromConsole(ContainerType &, ContainerType &);

/// Сохранение данных в файл

bool SaveDataToFile(ContainerType &, ContainerType &);

/// Очистка данных

void ClearData(ContainerType &, ContainerType &);

/// Функция отображения имеющихся точек

void ShowData(ContainerType &, ContainerType &, bool);

/// Функция отображения имеющихся точек

void DeleteData(ContainerType &, ContainerType &);

/// Сортировка Хоара

20

void optHoareSortAndRemoveDuplicates(ContainerType &, ContainerType &);

/// Интерполяция Лагранжа

void optLagrangeInterpolation(ContainerType &, ContainerType &, bool);

/// Функция интерполяции Лагранжа в отдельном потоке void LagrangeInterpolationThread(void *);

/// Функция отображения информации о статусе памяти void DrawMemoryStatus();

/// Функция проверки координаты на вхождение в допустимый диапазон bool CheckCoordinate(NumericalType, char *, IntegerType);

/// Функция удаления дубликатов void RemoveDuplicates(void *);

/// Функция ввода координаты X для интерполяции по точке bool EnterXForPoint(NumericalType &);

/// Функция ввода настроек для интерполяции отрезка

void EnterOptForSegment(NumericalType &, NumericalType &, IntegerType &,

IntegerType &, IntegerType);

void DrawGraphPoints(LPVOID * param);

/// Функция запуска сервера канала (программа рисования графиков) bool StartPipe();

/// Функция связи с сервером и отправки строковой информации ему bool SendPipe(char *);

/// Функция остановки связи с сервером и его закрытие void StopPipe();

///Структура - аргумент функции удаления дубликатов

///Создается экземпляр этой структуры

///и передается в функцию RemoveDuplicates() typedef struct ThStructRemoveDuplicates {

ContainerType * TContainerX; /// Указатель на контейнер (X)

ContainerType * TContainerY; /// Указатель на контейнер (Y)

}ThStructRemoveDuplicates;

///Структура - аргумент функции интерполяции

///Создается экземпляр этой структуры

///и передается в функцию LagrangeInterpolationThread() typedef struct ThStructInterpolation {

ContainerType * TContainerX; /// Указатель на контейнер X ContainerType * TContainerY; /// Указатель на контейнер Y NumericalType StartX; /// Стартовая координата X NumericalType FinalX; /// Конечная координата X

IntegerType SplitNumber; /// Число точек для разбиения отрезка

IntegerType nPoints; /// Степень интерполяции

std::ostream * osOutputResult; /// Поток вывода: файловый / консольный bool bDraw; /// Определяет рисование графика (true - рисовать)

} ThStructInterpolation;

}

bool FuncLib::StartPipe() {

STARTUPINFO cif; /// Структура для настройки CreateProcess

ZeroMemory(&cif, sizeof(STARTUPINFO)); /// Обнуление для установки стандартных значений

/// Запуск процесса dpipe.exe

if (!CreateProcess("dpipe.exe", NULL, NULL, NULL, TRUE, 0, NULL, NULL, &cif, &piProcess)) {

cout << "!> An error occurred while trying to create a process dpipe.exe.\n"; return false;

}

///Процесс dpipe.exe переходит в ожидание клиента не сразу,

///поэтому нужно задать небольшое время задержки

21

Sleep(300); return true;

}

bool FuncLib::SendPipe(char *msg) {

DWORD dwWritten; /// Количество действительно записанных байт

if (piProcess.dwProcessId == 0) { /// Если процесс не открыт cout << "!> The process is not running.\n";

return false;

}

/// Если время ожидания превысило 5 секунд (т. е. канал не отвечает)

if (!WaitNamedPipeA("\\\\.\\pipe\\GraphPipe", 5000)) { return false;

}

/// Подключаемся к серверу и отправляем ему строковую информацию hPipe = CreateFile("\\\\.\\pipe\\GraphPipe", GENERIC_WRITE, 0, NULL,

OPEN_EXISTING, 0, NULL);

if (hPipe != INVALID_HANDLE_VALUE) {

/// Если канал активен, то отправляем ему сообщение msg

if (!WriteFile(hPipe, msg, strlen(msg), &dwWritten, NULL)) {

cout << "!> Error sending information to the pipe.\n"; return false;

}

CloseHandle(hPipe); /// Закрываем дескриптор клиента канала hPipe = NULL; /// Чтобы сервер не тратил на нас лишнее время

}

else { /// Если ошибка открытия канала на запись

cout << "!> Error opening pipe.\n"; return false;

}

return true;

}

void FuncLib::StopPipe() {

/// Закрываем процесс сервера (dpipe.exe) с кодом ошибки 0 (нет ошибки) if (!TerminateProcess(piProcess.hProcess, 0)) {

cout << "!> An error occurred while the process is complete.\n";

}

piProcess.hProcess = piProcess.hThread = NULL;

}

/// Функция полного восстановления потока ввода void FuncLib::CinRecovery() {

cin.clear(); /// Сброс флага ошибки

while (cin.get() != '\n') { /// Сброс буфера continue;

}

}

/// Функция проверки координаты на вхождение в допустимый диапазон bool FuncLib::CheckCoordinate(

NumericalType Coordinate, /// Координаты X или Y (массив) char * CoordinateString, /// Наименование координаты (строка)

IntegerType CountOfPairs) /// Номер пары элементов

{

if (Coordinate < 0) Coordinate = -Coordinate; /// Знак числа не учитываем if ((Coordinate > 0) && (Coordinate <= 1.01l *

std::numeric_limits<NumericalType>::min())) {

/// Если число слишком мало (экспонента), то оно не записывается

/// Оповещаем пользователя

cout << '[' << CountOfPairs << " pair] -> " << CoordinateString << " coordinate is too small (exponent). Not recorded.\n";

22

return false;

} else if (Coordinate >= std::numeric_limits<NumericalType>::max() - 1.0l) {

/// Если число слишком велико (экспонента), то оно не записывается

/// Оповещаем пользователя

cout << '[' << CountOfPairs << " pair] -> " << CoordinateString

<< " coordinate is too big (exponent). Not recorded.\n"; return false;

}

return true; /// Если число входит в допустимый диапазон, то возврат TRUE

}

///Функция удаления дубликатов

///Принимает указатель на ThStructRemoveDuplicates void FuncLib::RemoveDuplicates(void * aStructRD) {

ThStructRemoveDuplicates *ptrStructRD = (ThStructRemoveDuplicates *) aStructRD; IntegerType i, nAmountOfPoints = ptrStructRD->TContainerX->size(); NumericalType PrevElem;

/// Цикл, выполняющий основную работу for (i = 1; i < nAmountOfPoints; ++i) {

/// Если найдены две одинаковые X координаты, то…

if (ptrStructRD->TContainerX[0][i-1] == ptrStructRD->TContainerX[0][i]) {

/// Если их соответствующие Y координаты не равны друг другу, то…

if (ptrStructRD->TContainerY[0][i-1] != ptrStructRD->TContainerY[0][i]) {

/// Удаление второй точки

PrevElem = ptrStructRD->TContainerX[0][i - 1];

/// И всех последующих

while (i < nAmountOfPoints && PrevElem == ptrStructRD- >TContainerX[0][i]) {

/// erase удаляет элемент контейнера (X) ptrStructRD->TContainerX->erase(ptrStructRD->TContainerX->begin()

+ i);

/// erase удаляет элемент контейнера (Y) ptrStructRD->TContainerY->erase(ptrStructRD->TContainerY->begin()

+ i);

--nAmountOfPoints; /// Число данных уменьшается

}

}

///Удаление первой точки

///(помимо верхнего условия, этот этап выполняется, если Y координаты равны друг другу)

ptrStructRD->TContainerX->erase(ptrStructRD->TContainerX->begin() + i -

1);

ptrStructRD->TContainerY->erase(ptrStructRD->TContainerY->begin() + i -

1);

--i; /// Счетчик уменьшается --nAmountOfPoints; /// Число данных уменьшается

}

}

}

void FuncLib::ShowData(

ContainerType & TContainerX, /// Контейнер с X координатами ContainerType & TContainerY, /// Контейнер с Y координатами

bool bLeftCounter) /// Определяет, нужен ли столбец с нумерацией слева

{

IntegerType iCounter, nSize = TContainerX.size();

cout << std::scientific; /// Отображение данных в экспоненциальной записи

if (bLeftCounter == false) { /// Если нумерация не нужна cout << "X\t\t\tY\n";

for (iCounter = 0; iCounter < nSize; ++iCounter) cout << TContainerX[iCounter] << "\t\t"

<< TContainerY[iCounter] << '\n';

23

}

else { /// Если нумерация нужна cout << "N\t\tX\t\t\tY\n";

for (iCounter = 0; iCounter < nSize; ++iCounter)

cout << (iCounter + 1) << ".\t\t" << TContainerX[iCounter] << "\t\t" << TContainerY[iCounter] << '\n';

}

cout << std::fixed; /// Возврат к выводу чисел по умолчанию

}

bool FuncLib::AddDataFromFile(

ContainerType & TContainerX, /// Координаты X ContainerType & TContainerY) /// Координаты Y

{

/// Текущий размер массива

IntegerType ContainerSize = TContainerX.size();

/// Имя файла (макс. 256 символов) char FileNameStr[256];

/// Восстановление потока ввода, если до вызова функции была ошибка ввода

CinRecovery();

cout << "#> Enter the file name (maximum 255 characters): "; cin.getline(FileNameStr, 256); /// Ввод имени файла

/// Файловая переменная. Открываем файл для чтения в бинарном режиме std::fstream FileInput (FileNameStr, std::fstream::in | std::fstream::binary); if (!FileInput.is_open()) { /// Если ошибка при открытии файла

cout << "!> File open error. Try again later.\n"; return false; /// Возвращаем False

}

/// Временные переменные

NumericalType TempX, TempY;

IntegerType CountOfPairs = 0; /// Счетчик количества пар чисел

/// Повторять до тех пор, пока не достигнут конец файла

/// или число точек не станет равным MAX_POINTS

while (!FileInput.eof() && ContainerSize < MAX_POINTS) { FileInput >> TempX >> TempY; /// Чтение координат XY из файла ++CountOfPairs; /// Увеличение счетчика

if (FileInput.fail()) { /// Если ошибка чтения

cout << "!> File read error. Pair number: " << CountOfPairs << ".\n";

FileInput.clear(); /// Сброс флага ошибки char ch;

do {

ch = FileInput.get(); /// Считываем ошибочные символы

}

while (ch != '\n' && !FileInput.eof()); /// Пока не достигнут конец

строки или файла

continue; /// Последующая запись некорректных данных не происходит

}

if (CheckCoordinate(TempX, (char *) "X", CountOfPairs)

&& CheckCoordinate(TempY, (char *) "Y", CountOfPairs)) { TContainerX.push_back(TempX); /// Добавляем в конец TContainerY.push_back(TempY); /// Добавляем в конец

++ContainerSize; /// Увеличиваем число точек

}

}

FileInput.close(); /// Закрываем файл

/// Если размер контейнера превышен if (ContainerSize >= MAX_POINTS) {

cout << "!> Number of points exceeded.\n";

}

cout << "!> Operation completed.\n"; return true;

}

24

void FuncLib::AddDataFromConsole(

ContainerType & TContainerX, /// Координаты X ContainerType & TContainerY) /// Координаты Y

{

///Временные переменные

NumericalType TempX, TempY;

///Текущий размер массива

IntegerType ContainerSize = TContainerX.size();

/// Восстановление потока ввода, если до вызова функции была ошибка ввода

CinRecovery();

/// Пока число точек не станет равным MAX_POINTS

while (ContainerSize < MAX_POINTS) {

cout << "#> Enter a point (X, Y) to add or any characters to stop: "; cin >> TempX >> TempY; /// Ввод данных во временные переменные

if (!cin.good()) { /// Если ввод неверный

/// Оповещаем пользователя о конце ввода

cout << "!> Adding data completed. Perhaps it was an input error (try

again later).\n";

break; /// Выходим из цикла

}

/// Иначе проверяем координаты на вхождение в допустимый диапазон if (CheckCoordinate(TempX, (char *) "X", 1)

&& CheckCoordinate(TempY, (char *) "Y", 1)) { TContainerX.push_back(TempX); /// Добавляем в конец TContainerY.push_back(TempY); /// Добавляем в конец

++ContainerSize; /// Увеличиваем число точек

}

}

if (ContainerSize == MAX_POINTS) { /// Если число точек равно MAX_POINTS cout << "!> Number of points exceeded.\n";

}

cout << "!> Operation completed.\n"; CinRecovery();

}

/// True - если успешно, иначе False bool FuncLib::SaveDataToFile(

ContainerType & TContainerX, /// Координаты X ContainerType & TContainerY) /// Координаты Y

{

/// Имя файла (макс. 256 символов) char FileNameStr[256];

/// Восстановление потока ввода, если до вызова функции была ошибка ввода

CinRecovery();

cout << "#> Enter the file name (maximum 255 characters): "; cin.getline(FileNameStr, 256); /// Ввод имени файла

/// Файловая переменная. Открываем файл для записи в бинарном режиме std::fstream FileOutput (FileNameStr, std::fstream::out | std::fstream::binary); if (!FileOutput.is_open()) { /// Если ошибка открытия

cout << "!> File open error. Try again later.\n"; return false; /// Возвращаем False

}

/// endIdx - последний индекс контейнера X IntegerType i, endIdx = TContainerX.size() - 1;

/// Далее запись в файл

for (i = 0; i < endIdx; ++i) { FileOutput << TContainerX[i] << ' ';

FileOutput << TContainerY[i] << '\r' << '\n';

}

FileOutput << TContainerX[i] << ' ';

FileOutput << TContainerY[i]; /// В конце \n не записываем

25

FileOutput.close(); /// Закрываем файл

cout << "!> Data is written to file \'" << FileNameStr << "\'.\n"; return true; /// Возвращаем True

}

void FuncLib::ClearData(

ContainerType & TContainerX, /// Контейнер X ContainerType & TContainerY) /// Контейнер Y

{

TContainerX.clear();

TContainerY.clear();

cout << "!> Data cleared.\n";

}

void FuncLib::DeleteData(

ContainerType & TContainerX, /// Контейнер X ContainerType & TContainerY) /// Контейнер Y

{

/// iLineNumber - номер строки для удаления, nSize - размер контейнера

IntegerType iLineNumber, nSize = TContainerX.size(); while (nSize > 0) {/// Если размер контейнера больше 0 CinRecovery(); /// Восстанавливаем поток ввода

/// Отображение данных контейнеров по нумерованному порядку (столбец N)

ShowData(TContainerX, TContainerY, true);

cout << "#> Enter line number (1-" << nSize << ") to delete (or 0 - to stop):

";

cin >> iLineNumber; /// Просим пользователя ввести номер строки

/// Если ошибка ввода или выход за границы, то повтор ввода

/// iLineNumber - беззнаковое число, поэтому проверки на < 0 нет while (!cin.good() || iLineNumber > nSize) {

CinRecovery();

cout << "!> Incorrect. Try again (1-" << nSize << ", or 0 - to stop): "; cin >> iLineNumber;

}

if (iLineNumber == 0) { /// Если введено число 0, то выход из функции.

cout << "!> Deletion aborted.\n"; return;

}

/// Иначе удаление элемента по индексу (= номер - 1) TContainerX.erase(TContainerX.begin() + iLineNumber - 1); TContainerY.erase(TContainerY.begin() + iLineNumber - 1);

--nSize;

cout << "!> Deleted!\n";

}

/// Если контейнер пуст, то удалять нечего cout << "!> No data.\n";

return; /// Выходим

}

void FuncLib::optHoareSortAndRemoveDuplicates( ContainerType & TContainerX, /// Координаты X ContainerType & TContainerY) /// Координаты Y

{

CinRecovery(); /// Восстанавливаем поток ввода в случае ошибки

///Если введено число 2, то операции будут выполняться во вторичном потоке cout << "#> In the main stream (not 2) or in the secondary stream (2): "; char ch = cin.get();

unsigned int start_time, end_time;

///Создание и настройка структуры для работы с функцией

InterLib::ThStructSort StructSort;

StructSort.TContainerX = &TContainerX; /// Ссылка на контейнер X StructSort.TContainerY = &TContainerY; /// Ссылка на контейнер Y

26

StructSort.aFirstElem = 0; /// Начальный индекс элемента

StructSort.aLastElem = TContainerX.size() - 1; /// Конечный индекс элемента start_time = clock();

if (ch != '2') /// Если введено не число 2, то в основном потоке

InterLib::HoareSort(&StructSort); else { /// Иначе во вторичном

HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) InterLib::HoareSort, (void*) &StructSort, 0, NULL); /// Вызов функции

cout << "Please wait!\n";

WaitForSingleObject(hThread, TIME_FOR_SORT); /// Ждем TIME_FOR_SORT секунд CloseHandle(hThread); /// Закрываем дескриптор

}

end_time = clock();

cout << "!> Sorted. Time: "

<< (end_time - start_time) / 1000 << " s. (" << (end_time - start_time) << "

ms.)\n";

cout << "!> Now delete duplicates...\n";

/// Теперь начинаем удалять дубликаты

ThStructRemoveDuplicates StructRD; /// Тоже структура, но для другой функции StructRD.TContainerX = &TContainerX; /// Ссылка на контейнер X StructRD.TContainerY = &TContainerY; /// Ссылка на контейнер Y

start_time = clock();

if (ch != '2') /// Если ранее было введено не число 2, то в основном потоке

RemoveDuplicates(&StructRD); else { /// Иначе во вторичном

HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) RemoveDuplicates, (void*) &StructRD, 0, NULL); /// Вызов функции

WaitForSingleObject(hThread, TIME_FOR_RD); /// Ждем TIME_FOR_RD секунд CloseHandle(hThread); /// Закрываем дескриптор

}

end_time = clock();

cout << "!> Duplicate X coordinates removed. Time: "

<< (end_time - start_time) / 1000 << " s. (" << (end_time - start_time) << "

ms.)\n";

}

/// True - если ввод верный, иначе False

bool FuncLib::EnterXForPoint(NumericalType & TempX) { cout << "#> Enter the X coordinate: ";

cin >> TempX; /// Вводим координату X

if (cin.good()) return true; /// Если ввод верный, то возвращаем True CinRecovery(); /// В противном случае восстанавливаем поток ввода

/// Оповещаем пользователя о конце ввода

cout << "!> Entry data completed. Perhaps it was an input error (try again

later).\n"; return false;

}

void FuncLib::EnterOptForSegment(

NumericalType & StartX, /// Ввод стартовой координаты (X) NumericalType & FinalX, /// Ввод конечной координаты (X)

IntegerType & SplitNumber,/// Ввод количества точек для разбиения отрезка

IntegerType & nPoints,/// Степень интерполяции

IntegerType nMaxPoints) /// Максимально возможная степень интерполяции

{

cout << "#> Enter the maximum degree of the polynomial (1-" << nMaxPoints << "):

";

cin >> nPoints; /// Вводим число узлов интерполяции

while (!cin.good() || nPoints < 1 || nPoints > nMaxPoints) { /// Пока ввод неверныйcout << "#> Incorrect. Try again (1-" << nMaxPoints << "): ";

CinRecovery(); /// Восстанавливаем поток ввода

27

cin >> nPoints; /// Вводим снова

}

cout << "#> Enter the starting X coordinate: ";

cin >> StartX; /// Вводим стартовую координату while (!cin.good()) { /// Пока ввод неверный cout << "#> Incorrect. Try again: ";

CinRecovery(); /// Восстанавливаем поток ввода cin >> StartX; /// Вводим снова

}

cout << "#> Enter the final X coordinate: ";

cin >> FinalX; /// Вводим конечную координату

while (!cin.good() || StartX > FinalX) { /// Пока ввод неверный cout << "#> Incorrect. Try again: ";

CinRecovery(); /// Восстанавливаем поток ввода cin >> FinalX; /// Вводим снова

}

cout << "#> Enter the number of split points (1-" << MAX_POINTS << "): ";

cin >> SplitNumber; /// Вводим количество точек для разбиения отрезка

while (!cin.good() || SplitNumber < 2 || SplitNumber > MAX_POINTS) { /// Пока

ввод неверный

cout << "#> Incorrect. Try again (1-" << MAX_POINTS << "): "; CinRecovery(); /// Восстанавливаем поток ввода

cin >> SplitNumber; /// Вводим снова

}

}

/// Функция интерполяции Лагранжа

/// Функция принимает указатель на структуру ThStructInterpolation void FuncLib::LagrangeInterpolationThread(void * aStructInterpolation){

///Дескриптор объекта

HANDLE hObj = NULL;

///Если работа с объектами, то hObj содержит дескриптор объекта

hObj = (hMutex != NULL) ? hMutex : hObj;

hObj = (hSemaphore != NULL) ? hSemaphore : hObj; hObj = (hEvent != NULL) ? hEvent : hObj;

hObj = (hWaitableTimer != NULL) ? hWaitableTimer : hObj;

/// Ожидание объекта if (hObj != NULL) {

DWORD dwWaitResult = WaitForSingleObject(hObj, TIME_FOR_OBJECTS); switch (dwWaitResult) {

case WAIT_OBJECT_0: break;

case WAIT_TIMEOUT:

cout << "!> Timeout exceeded.\n"; return;

case WAIT_ABANDONED:

cout << "!> Mutex was not released.\n"; return;

default:

cout << "!> WaitForSingleObject error: " <<

GetLastError() << "\n"; return;

}

}

ThStructInterpolation *ptrStructInterpolation = (ThStructInterpolation *) aStructInterpolation;

/// Получаем значения из структуры в отдельные переменные

NumericalType StartX = ptrStructInterpolation->StartX; NumericalType FinalX = ptrStructInterpolation->FinalX; IntegerType SplitNumber = ptrStructInterpolation->SplitNumber;

/// Степень интерполяции

28

IntegerType nPoints = ptrStructInterpolation->nPoints;

/// Размер одного миниотрезка

NumericalType SizeOfOneSplit = (FinalX - StartX) / (SplitNumber - 1);

/// Вспомогательные переменные

NumericalType TempX, ResultFunc;

IntegerType nSize = ptrStructInterpolation->TContainerX->size(), iPos = 0; IntegerType nxStart, nxStop;

/// Буфер (для работы с каналом) char dest[1024];

unsigned int start_time, end_time;

if (ptrStructInterpolation->bDraw) { /// Если необходимо рисование

/// Максимальное и минимальное Y (их вычисление перед рисованием)

NumericalType MinY, MaxY;

cout << "Preparation, wait...\n"; /// Происходит подготовка start_time = clock();

NumericalType * YArr = new (std::nothrow) NumericalType[SplitNumber + 1]; if (!YArr) { /// Если ошибка выделения памяти

cout << "!> Memory was not allocated.\n"; return;

}

/// Интерполируем граничные точки

MinY = InterLib::LagrangeInterpolation(*ptrStructInterpolation->TContainerX, *ptrStructInterpolation->TContainerY, StartX, 0, nPoints);

YArr[0] = MinY;

MaxY = InterLib::LagrangeInterpolation(*ptrStructInterpolation->TContainerX, *ptrStructInterpolation->TContainerY, FinalX, nSize - nPoints, nSize);

YArr[SplitNumber] = MinY;

/// Если на крайняя левая точка больше по Y, чем крайняя правая,

/// то обмен переменных местами if (MinY > MaxY) {

TempX = MinY; MinY = MaxY; MaxY = TempX;

}

IntegerType i = 1; /// Цикл начинается с 1 (для 0 интерполяция прошла ранее)

TempX = StartX + SizeOfOneSplit; /// Для StartX интерполяция прошла ранее

/// Вычисление мин. и макс. Y на отрезке от StartX до FinalX для

автомасштабирования графика while (i < SplitNumber) {

/// Двигаемся по контейнеру X для определения положения точки TempX

/// или соседних точек TempX

while (iPos < nSize && ptrStructInterpolation->TContainerX[0][iPos] <

TempX) {

++iPos;

}

///Настройка стартового и конечного индекса массива

///Для интерполяции центральной точки

nxStart = iPos - nPoints; nxStop = iPos + nPoints;

nxStart = (nxStart > nSize) ? 0 : nxStart; /// nxStart - беззнаковое

число

nxStop = (nxStop > nSize) ? nSize : nxStop; nxStop += (nxStop == nxStart + 1) ? 1 : 0;

/// Запись результата в массив

YArr[i] = InterLib::LagrangeInterpolation(*ptrStructInterpolation- >TContainerX,

*ptrStructInterpolation->TContainerY, TempX, nxStart, nxStop); MaxY = (YArr[i] > MaxY) ? YArr[i] : MaxY; /// Сравнение максимума MinY = (YArr[i] < MinY) ? YArr[i] : MinY; /// Сравнение минимума TempX += SizeOfOneSplit;

++i;

}

cout << "Preparation has already been successfully completed.\nPlease wait until the main work is completed...\n";

29

/// Старт канала и инициализация if (!StartPipe()) return;

if (!SendPipe((char *)"InitDrawPanel 0 15")) {

StopPipe(); return;

}

///Дальнейшие вызовы SendPipe не нуждаются в проверке true/false sprintf(dest, "InitGraph %Le %Le %Le %Le", StartX, FinalX, MinY, MaxY);

SendPipe(dest);

SendPipe((char *)"ClearDevice");

///Запись точек и отображение их на графике

TempX = StartX;

i = 0;

while (i < SplitNumber) {

*ptrStructInterpolation->osOutputResult << TempX << " " << YArr[i] <<

'\r' << '\n';

sprintf(dest, "DrawPoint %Le %Le", TempX, YArr[i]); SendPipe(dest);

TempX += SizeOfOneSplit; ++i;

}

delete [] YArr; /// Освобождение памяти

YArr = NULL;

ptrStructInterpolation->osOutputResult->flush(); /// Сброс буфера SendPipe((char *)"DrawChartBorder"); /// Отрисовка границ SendPipe((char *)"DrawAxes"); /// Отрисовка осей

SendPipe((char *)"DrawLinesAndValues 6"); /// Отрисовка промежуточных значений (6 шт.)

end_time = clock();

cout << "\n\nDone. Time: "

<< (end_time - start_time) / 1000 << " s. (" << (end_time - start_time) << " ms.)\n";

cin.get(); StopPipe();

}

else {

cout << "The main work has already started, please wait...\n";

/// Вычисляем точки start_time = clock();

TempX = StartX;

while (TempX <= FinalX) {

/// Двигаемся по контейнеру X для определения положения точки TempX

/// или соседних точек TempX

while (iPos < nSize && ptrStructInterpolation->TContainerX[0][iPos] <

TempX) {

++iPos;

}

///Настройка стартового и конечного индекса массива

///Для интерполяции центральной точки

nxStart = iPos - nPoints; nxStop = iPos + nPoints;

nxStart = (nxStart > nSize) ? 0 : nxStart; /// nxStart - беззнаковое

число

nxStop = (nxStop > nSize) ? nSize : nxStop; nxStop += (nxStop == nxStart + 1) ? 1 : 0;

/// Интерполяция точки

ResultFunc = InterLib::LagrangeInterpolation(*ptrStructInterpolation- >TContainerX, *ptrStructInterpolation->TContainerY, TempX, nxStart, nxStop);

*ptrStructInterpolation->osOutputResult << TempX << " " << ResultFunc <<

"\r\n";

TempX += SizeOfOneSplit;

}

30

end_time = clock();

cout << "\n\nDone. Time: "

<<(end_time - start_time) / 1000 << " s. (" << (end_time - start_time)

<<" ms.)\n";

}

if (hMutex != NULL && !ReleaseMutex(hMutex)) {

cout << "ReleaseMutex error: " << GetLastError() << '\n'; return;

}

if (hSemaphore != NULL && !ReleaseSemaphore(hSemaphore, 1, NULL)) {

cout << "ReleaseSemaphore error: " << GetLastError() << '\n'; return;

}

if (hEvent != NULL && !SetEvent(hEvent))

{

cout << "SetEvent error: " << GetLastError() << '\n'; return;

}

if (hWaitableTimer != NULL && !CancelWaitableTimer(hWaitableTimer))

{

cout << "CancelWaitableTimer error: " << GetLastError() << '\n'; return;

}

}

void FuncLib::optLagrangeInterpolation( ContainerType & TContainerX, /// Контейнер X ContainerType & TContainerY, /// Контейнер Y

bool PointOrSegment) /// False - точка, True - отрезок

{

bool ConsoleOrFile; /// False - консоль, True - файл

/// TempX временная переменная для ввода координаты X

NumericalType TempX, ResultFunc; IntegerType nSize = TContainerX.size();

///Файловая переменная std::fstream FileOutput;

///Восстанавливаем поток ввода

CinRecovery();

///Используем временные переменные типа 'символ' для ввода настроек char ch, chPaint;

cout << "#> Result in console (not 2) or file (2): "; cin >> ch; /// Считываем

///Если 2, то результат в файл, иначе в консоль

ConsoleOrFile = (ch == '2') ? true : false;

/// Восстанавливаем поток ввода

CinRecovery();

/// Если файловый вывод if (ConsoleOrFile) {

char FileNameStr[256]; /// Заводим переменную для считывания имени файла cout << "#> Enter the file name (maximum 255 characters): "; cin.getline(FileNameStr, 256); /// Считываем 256 символов

/// Открываем файл на запись

FileOutput.open(FileNameStr, std::fstream::out | std::fstream::binary); if (!FileOutput.is_open()) { /// Если ошибка открытия файла

cout << "!> File open error. Try again later.\n"; return;

}

31

}

/// Если интерполяция точек отрезка if (PointOrSegment) {

cout << "!> Choose kernel mechanism:\n"

<<"#> 1 : Secondary thread\n"

<<"#> 2 : Secondary thread with Mutex\n"

<<"#> 3 : Secondary thread with Semaphore\n"

<<"#> 4 : Secondary thread with Event\n"

<<"#> 5 : Secondary thread with Waitable Timer\n"

<<"#> Any others : Main thread\n#> ";

cin >> ch; /// Вводим символ

CinRecovery(); /// Восстанавливаем поток ввода

cout << "#> Draw a graph? (Y : yes, Any others : no): "; cin >> chPaint;

CinRecovery(); /// Восстанавливаем поток ввода

/// Настройка структуры

FuncLib::ThStructInterpolation StructInterpolation; StructInterpolation.TContainerX = &TContainerX; StructInterpolation.TContainerY = &TContainerY;

StructInterpolation.bDraw = (chPaint == 'y') || (chPaint == 'Y') ? true :

false;

/// Настраиваем интерполяцию для отрезка (ввод пользователя)

EnterOptForSegment(StructInterpolation.StartX, StructInterpolation.FinalX, StructInterpolation.SplitNumber, StructInterpolation.nPoints, nSize);

StructInterpolation.osOutputResult = ConsoleOrFile ? &FileOutput : &cout; if (ch < '1' || ch > '5') { /// Если основной поток

LagrangeInterpolationThread(&StructInterpolation);

}

else { /// Если вторичный поток switch (ch) {

case '2': /// Мьютекс

hMutex = CreateMutex(NULL, FALSE, NULL); if (hMutex == NULL) {

cout << "CreateMutex error: " << GetLastError() << ".\n"; return;

}

break;

case '3': /// Семафор

hSemaphore = CreateSemaphore(NULL, 1, 1, NULL); if (hSemaphore == NULL) {

cout << "CreateSemaphore error: " << GetLastError() << ".\n"; return;

}

break;

case '4': /// Событие

hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); if (hEvent == NULL) {

cout << "CreateEvent error: " << GetLastError() << ".\n"; return;

}

break;

case '5': /// Таймер ожидания long a;

cout << "#> Enter delay time (ms): ";

/// Ввод задержки в мс cin >> a;

while (!cin.good() || a > 100000 || a < 500) {

CinRecovery();

cout << "#> Incorrect. Try again: "; cin >> a;

}

LARGE_INTEGER liDueTime;

32

liDueTime.QuadPart = (-10000LL) * a;

hWaitableTimer = CreateWaitableTimer(NULL, TRUE, NULL); if (hWaitableTimer == NULL) {

cout << "CreateWaitableTimer error: " << GetLastError() <<

".\n";

return;

}

if (!SetWaitableTimer(hWaitableTimer, &liDueTime, 0, NULL, NULL,

0))

{

cout << "SetWaitableTimer error: " << GetLastError() << "\n"; return;

}

}

/// Запуск потока

hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) LagrangeInterpolationThread, (void*)&StructInterpolation, 0, NULL);

if (hThread == NULL) {

cout << "CreateThread error: " << GetLastError() << ".\n"; return;

}

CinRecovery();

cout << "Please wait!\n";

cin.get(); cin.get(); /// Считывание (обязательно два подряд)

TerminateThread(hThread, 0); /// Остановка потока

///Если был запущен процесс dpipe.exe

///а поток не успел вызвать StopPipe, то вызываем здесь if (piProcess.dwProcessId) StopPipe();

CloseHandle(hThread); /// Закрываем дескриптор hThread = NULL;

/// Закрываем дескрипторы switch (ch) {

case '2': CloseHandle(hMutex);

hMutex = NULL; break;

case '3': CloseHandle(hSemaphore);

hSemaphore = NULL; break;

case '4': CloseHandle(hEvent);

hEvent = NULL; break;

case '5': CloseHandle(hWaitableTimer);

hWaitableTimer = NULL; break;

}

}

} else { /// Если интерполяция точки

IntegerType nPoints;

cout << "#> Enter the maximum degree of the polynomial (1-" << nSize << "):

";

cin >> nPoints; /// Вводим степень интерполяции

while (!cin.good() || nPoints < 1 || nPoints > nSize) { /// Пока ввод

неверный

cout << "#> Incorrect. Try again (1–" << nSize << "): ";

CinRecovery(); /// Восстанавливаем поток ввода cin >> nPoints; /// Вводим снова

}

if (nPoints == nSize) { /// Если степень равна размеру массива,

33

/// То нет смысла производить бинарный поиск

while (EnterXForPoint(TempX)) { /// Пока ввод координаты верный

/// Вычисляем

ResultFunc = InterLib::LagrangeInterpolation(TContainerX, TContainerY, TempX, 0, nSize);

(ConsoleOrFile ? FileOutput : cout) << TempX << " " << ResultFunc <<

'\r' << '\n';

}

}

else { /// Если степень НЕ равна размеру массива

IntegerType nxStart, nxStop, mid;

while (EnterXForPoint(TempX)) { /// Пока ввод координаты верный

/// Бинарный поиск точки в массиве

IntegerType left = 0, right = nSize; while (left <= right) {

mid = (left + right) / 2;

if (TempX < TContainerX[mid])

right = mid - 1;

else if (TempX > TContainerX[mid])

left = mid + 1;

else break; /// Элемент найден

}

///Здесь mid содержит индекс имеющегося элемента

///или тот индекс, куда нужно вставить искомый элемент

///чтобы он имел этот индекс.

///Далее настройка стартового и конечного индекса массива

///Для интерполяции центральной точки

nxStart = mid - nPoints; nxStop = mid + nPoints;

nxStart = (nxStart > nSize) ? 0 : nxStart; nxStop = (nxStop > nSize) ? nSize : nxStop; nxStop += (nxStop - nxStart == 1) ? 1 : 0;

/// Вводим и вычисляем

ResultFunc = InterLib::LagrangeInterpolation(TContainerX, TContainerY, TempX, nxStart, nxStop);

(ConsoleOrFile ? FileOutput : cout) << TempX << " " << ResultFunc <<

'\r' << '\n';

}

}

}

if (FileOutput.is_open()) FileOutput.close(); /// Если файл был открыт, закрываем cout << "\n!> Data has been interpolated!\n";

}

void FuncLib::DrawGraphPoints(LPVOID * param) {

long bytes = * (long *) param; /// Коэффициент для отображения

bytes = (bytes < 1) ? 1 : bytes; char dest[1024]; /// Буфер

/// Структура для получения статуса памяти

MEMORYSTATUSEX mstatus; mstatus.dwLength = sizeof(mstatus); LARGE_INTEGER liDueTime;

liDueTime.QuadPart = -10000000LL; /// 1 секунда

// Создаем анонимный таймер ожидания

hWaitableTimer = CreateWaitableTimer(NULL, TRUE, NULL); if (hWaitableTimer == NULL) { /// Если ошибка

cout << "CreateWaitableTimer error: " << GetLastError() << '\n'; return;

}

/// Рисуем точки на графике

for (int x = 0; x <= 100; x += 5) {

/// Получаем актуальную информацию

34

GlobalMemoryStatusEx(&mstatus);

/// Запуск таймера

if (!SetWaitableTimer(hWaitableTimer, &liDueTime, 0, NULL, NULL, 0)) { break;

}

/// Ожидание таймера

if (WaitForSingleObject(hWaitableTimer, 1500) != WAIT_OBJECT_0) { break;

}

sprintf(dest, "DrawPoint %Le %Le %d %d", static_cast<NumericalType>(x), static_cast<NumericalType>(mstatus.ullAvailPhys) / bytes, 4, 1);

if (!SendPipe(dest)) break; /// Если ошибка, то выход

sprintf(dest, "DrawPoint %Le %Le %d %d", static_cast<NumericalType>(x), static_cast<NumericalType>(mstatus.ullAvailPageFile) / bytes, 4, 2);

if (!SendPipe(dest)) break; /// Если ошибка, то выход

sprintf(dest, "DrawPoint %Le %Le %d %d", static_cast<NumericalType>(x), static_cast<NumericalType>(mstatus.ullAvailVirtual) / bytes / 1024, 4,

4);

if (!SendPipe(dest)) break; /// Если ошибка, то выход

}

CancelWaitableTimer(hWaitableTimer); /// Отключаем таймер ожидания CloseHandle(hWaitableTimer); /// Закрываем дескриптор hWaitableTimer = NULL;

}

void FuncLib::DrawMemoryStatus() {

MEMORYSTATUSEX mem_status; /// Структура для получения статуса памяти mem_status.dwLength = sizeof(mem_status);/// Устанавливаем размер структуры

GlobalMemoryStatusEx(&mem_status); /// Получаем статус памяти char dest[1024]; /// Буфер

long bytes = 1048576; /// Коэффициент для отображения

/// Старт канала и инициализация

if (!StartPipe() || !SendPipe((char *)"InitDrawPanel 0 15")) { return;

}

/// Дальнейшие вызовы SendPipe не нуждаются в проверке true/false

SendPipe((char *)"ClearDevice");

/// Отображение информации в окне

sprintf(dest, "DrawText %d %d %d [Memory status]", 10, 6, 0);

SendPipe(dest);

sprintf(dest, "DrawText %d %d %d Percentage of physical memory that is in use:", 10, 30, 0);

SendPipe(dest);

sprintf(dest, "DrawText %d %d %d %lu", 30, 50, 0, mem_status.dwMemoryLoad);

SendPipe(dest);

sprintf(dest, "DrawText %d %d %d The amount of actual physical memory, in bytes:", 10, 70, 0);

SendPipe(dest);

sprintf(dest, "DrawText %d %d %d %llu", 30, 90, 0, mem_status.ullTotalPhys);

SendPipe(dest);

sprintf(dest, "DrawText %d %d %d The amount of physical memory currently available, in bytes:", 10, 110, 1);

SendPipe(dest);

sprintf(dest, "DrawText %d %d %d %llu", 30, 130, 1, mem_status.ullAvailPhys);

SendPipe(dest);

sprintf(dest, "DrawText %d %d %d The current committed memory limit for the system", 10, 150, 0);

SendPipe(dest);

sprintf(dest, "DrawText %d %d %d or the current process, whichever is smaller, in bytes:", 10, 170, 0);

SendPipe(dest);

sprintf(dest, "DrawText %d %d %d %llu", 30, 190, 0, mem_status.ullTotalPageFile);

35

SendPipe(dest);

sprintf(dest, "DrawText %d %d %d The maximum amount of memory the current process can commit, in bytes:", 10, 210, 2);

SendPipe(dest);

sprintf(dest, "DrawText %d %d %d %llu", 30, 230, 2, mem_status.ullAvailPageFile);

SendPipe(dest);

sprintf(dest, "DrawText %d %d %d The size of the user-mode portion of", 10, 250,

0);

SendPipe(dest);

sprintf(dest, "DrawText %d %d %d the virtual address space of the calling process, in bytes:", 10, 270, 0);

SendPipe(dest);

sprintf(dest, "DrawText %d %d %d %llu", 30, 290, 0, mem_status.ullTotalVirtual / 1024);

SendPipe(dest);

sprintf(dest, "DrawText %d %d %d The amount of unreserved and uncommitted memory currently in the user-mode", 10, 310, 4);

SendPipe(dest);

sprintf(dest, "DrawText %d %d %d portion of the virtual address space of the calling process, in bytes:", 10, 330, 4);

SendPipe(dest);

sprintf(dest, "DrawText %d %d %d %llu", 30, 350, 4, mem_status.ullAvailVirtual / 1024);

SendPipe(dest);

/// Определение максимальной координаты X для автомасштабирования графика

NumericalType mxY = (mem_status.ullTotalPhys > mem_status.ullTotalVirtual) ? mem_status.ullTotalPhys : mem_status.ullTotalVirtual;

mxY = (mxY * 1.001L) / (1024 * bytes);

/// Инициализация графика

sprintf(dest, "InitGraph %Le %Le %Le %Le %Le %Le %Le %Le", 0.0L, 100.0L, 0.0L, mxY, 0.3L, 0.3L, 0.4L, 0.6L);

SendPipe(dest);

sprintf(dest, "DrawLine %d %llu %d %llu %d", 0, mem_status.ullTotalPhys / bytes, 100, mem_status.ullTotalPhys / bytes, 1);

SendPipe(dest);

sprintf(dest, "DrawLine %d %llu %d %llu %d", 0, mem_status.ullTotalPageFile / bytes, 100, mem_status.ullTotalPageFile / bytes, 2);

SendPipe(dest);

sprintf(dest, "DrawLine %d %llu %d %llu %d", 0, mem_status.ullTotalVirtual / bytes / 1024, 100, mem_status.ullTotalVirtual / bytes / 1024, 4);

SendPipe(dest);

SendPipe((char *)"DrawChartBorder"); /// Отрисовка границ SendPipe((char *)"DrawAxes"); /// Отрисовка осей

SendPipe((char *)"DrawLinesAndValues 4"); /// Отрисовка промежуточных значений (4

шт.)sprintf(dest, "DrawText %d %d %d MBytes\n", 300, 375, 0); SendPipe(dest);

/// Старт потока для рисования точек на графике

CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) DrawGraphPoints, &bytes, 0, NULL); CinRecovery();

cin.get(); cin.get(); TerminateThread(hThread, 0); StopPipe(); CloseHandle(hThread); hThread = NULL;

}

36

InterLib.h

///------------------

///Сортировка и интерполяция (H)

///------------------

#include <deque> /// Для работы с двусторонними очеред¤ми

#include <cstdint> /// Для работы с целочисленными фиксированными типами

#ifndef _INTER_LIB_

#define _INTER_LIB_ namespace InterLib {

/// Целое число фиксированного размера using IntegerType = uint32_t;

/// Любой числовой тип

using NumericalType = long double;

/// Любой контейнерный тип

using ContainerType = std::deque<NumericalType>;

/// Структура для работы с HoareSort typedef struct ThStructSort {

ContainerType * TContainerX; /// Координаты X ContainerType * TContainerY; /// Координаты Y IntegerType aFirstElem; /// Индекс первого элемента IntegerType aLastElem; /// Индекс последнего элемента

}ThStructSort;

///Функция сортировки Хоара в отдельном потоке void HoareSort(void *);

///Функция интерполяции Лагранжа

NumericalType LagrangeInterpolation(

ContainerType & TContainerX, ContainerType & TContainerY, NumericalType ntX, IntegerType nStart, IntegerType nStop

);

}

#endif

37

InterLib.cpp

///------------------

///Сортировка и интерполяция (CPP)

///------------------

#include <deque> /// Для работы с двусторонними очередями #include <stack> /// Для работы со стеком

#include <cstdint> /// Для работы с целочисленными фиксированными типами namespace InterLib {

/// Целое число фиксированного размера using IntegerType = uint32_t;

/// Любой числовой тип

using NumericalType = long double;

/// Любой контейнерный тип

using ContainerType = std::deque<NumericalType>;

void HoareSort(void *);

NumericalType LagrangeInterpolation(ContainerType &, ContainerType &, NumericalType, IntegerType, IntegerType);

///Структура для работы с потоками

///Создается экземпляр этой структуры и передается в функцию HoareSort() typedef struct ThStructSort {

ContainerType * TContainerX; /// Координаты X

ContainerType * TContainerY; /// Координаты Y IntegerType aFirstElem; /// Индекс первого элемента IntegerType aLastElem; /// Индекс последнего элемента

} ThStructSort;

}

/// Сортировка Хоара (быстрый итеративный вариант) void InterLib::HoareSort(void * aStructSort) {

ThStructSort *ptrStructSort = (ThStructSort *) aStructSort; IntegerType Left = ptrStructSort->aFirstElem;

IntegerType Right = ptrStructSort->aLastElem; IntegerType L2, R2;

NumericalType PivotValue; std::stack<NumericalType> Lows; std::stack<NumericalType> Highs; Lows.push(Left); Highs.push(Right);

while (!Lows.empty()) { Left = Lows.top(); Lows.pop();

Right = Highs.top(); Highs.pop();

L2 = Left;

R2 = Right;

PivotValue = ptrStructSort->TContainerX[0][(Left + Right) / 2];

do {while (ptrStructSort->TContainerX[0][L2] < PivotValue) ++L2;

while (ptrStructSort->TContainerX[0][R2] > PivotValue) --R2;

if (L2 <= R2) {

if (ptrStructSort->TContainerX[0][L2]

> ptrStructSort->TContainerX[0][R2])

{

NumericalType Temp = ptrStructSort->TContainerX[0][L2]; ptrStructSort->TContainerX[0][L2]

= ptrStructSort->TContainerX[0][R2];

38

ptrStructSort->TContainerX[0][R2] = Temp;

Temp = ptrStructSort->TContainerY[0][L2]; ptrStructSort->TContainerY[0][L2]

= ptrStructSort->TContainerY[0][R2]; ptrStructSort->TContainerY[0][R2] = Temp;

}

++L2;

if (R2 > 0) --R2;

}

} while (L2 <= R2); if (L2 < Right) {

Lows.push(L2);

Highs.push(Right);

}

if (R2 > Left) { Lows.push(Left); Highs.push(R2);

}

}

}

/// Интерполяция Лагранжа

InterLib::NumericalType InterLib::LagrangeInterpolation( ContainerType & TContainerX, /// Контейнер X ContainerType & TContainerY, /// Контейнер Y NumericalType ntX, /// Координата X

IntegerType nStart, /// Стартовый индекс интерполяции IntegerType nStop) /// Конечный индекс интерполяции

{

IntegerType i, j;

NumericalType ntProduct, ntResult = 0; for (i = nStart; i < nStop; i++) {

ntProduct = 1;

for (j = nStart; j < nStop; j++) { if (j != i) {

ntProduct *= (ntX - TContainerX[j])

/ (TContainerX[i] - TContainerX[j]);

}

}

ntResult += ntProduct * TContainerY[i];

}

return ntResult;

}

39