ИСХОДНЫЕ ФАЙЛЫ 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