CRITICAL_SECTION cs;//критическая секция
//concurrency::concurrent_vector <LONGLONG> arrIndex;
void RUNarrIndex(LONGLONG treadIndex, LONGLONG startFor, LONGLONG endFor, LONGLONG sMin, LONGLONG sMax, concurrency::concurrent_vector<LONGLONG>& arr, concurrency::concurrent_vector <LONGLONG>& arrIndex, concurrency::concurrent_vector<LONGLONG>& arrK)
{
LONGLONG k= 0;
//for (;;) {
for (LONGLONG i = startFor; i <= endFor; i++) {
if ((arr[i - 1] > 0 && arr[i - 1]) <= sMax) {
for (LONGLONG j = (sMax - arr[i - 1]); j >= 1; j--) {
if (arrIndex[j] > 0) {
k = j + arr[i - 1];
if (arrIndex[k] == 0) {
//EnterCriticalSection(&cs);//критическая секция
arrIndex[k] = i;
//LeaveCriticalSection(&cs);//критическая секция
if (k >= sMin) {
arrK[treadIndex] = k;
return; }
}
}
}
k = arr[i - 1];
if (arrIndex[k] == 0) {
//EnterCriticalSection(&cs);//критическая секция
arrIndex[k] = i;
//LeaveCriticalSection(&cs);//критическая секция
if (k >= sMin) {
arrK[treadIndex] = k; return; }
}
}
}
//}
arrK[treadIndex] = k;
}
extern "C" __declspec(dllexport) void XLLbuttonFindSummands()
{
unsigned int startTime = clock(); // начальное время
//{CComVariant result, p0(L"Выбирите диапазон"), p1(L"BedvitXLL");
//if (AutoWrap(DISPATCH_METHOD, &result, pExcelDisp, L"InputBox", 2, p1, p0) != S_OK) { MessageBox(hwndExcel, L"InputBox: ", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
////MessageBox(hwndExcel, std::wstring(result.pdate).c_str(), L"BedvitXLL", MB_OK | MB_ICONINFORMATION);
//}
LONGLONG xlLastCell=1; //определение последней ячейки 1го столбца
{CComVariant result, p0(1048576), p1(1), p2(-4162);//xlUp
if (AutoWrap(DISPATCH_PROPERTYGET, &result, pExcelDisp, L"Cells", 2, p1, p0) != S_OK) { MessageBox(hwndExcel, L"pxlCells: ", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
if (AutoWrap(DISPATCH_PROPERTYGET, &result, result.pdispVal, L"End", 1, p2) != S_OK) { MessageBox(hwndExcel, L"pxlEnd: ", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
if (AutoWrap(DISPATCH_PROPERTYGET, &result, result.pdispVal, L"Row", 0) != S_OK) { MessageBox(hwndExcel, L"xlLastCell: ", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
xlLastCell = result.llVal; }
CComVariant safeArrayInOut; //получим данные с листа: массив, макс и мин
LONGLONG sMinCell, sMaxCell;
{CComVariant result, p0(std::wstring(L"A1:A" + std::to_wstring(xlLastCell)).c_str()), p1(L"B1"), p2(L"B2");
if (AutoWrap(DISPATCH_PROPERTYGET, &result, pExcelDisp, L"Range", 1, p0) != S_OK) { MessageBox(hwndExcel, L"Range: ", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
if (AutoWrap(DISPATCH_PROPERTYGET, &safeArrayInOut, result.pdispVal, L"Value", 0) != S_OK) { MessageBox(hwndExcel, L"ValueGET: ", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
if (AutoWrap(DISPATCH_PROPERTYGET, &result, pExcelDisp, L"Range", 1, p1) != S_OK) { MessageBox(hwndExcel, L"Range: ", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
if (AutoWrap(DISPATCH_PROPERTYGET, &result, result.pdispVal, L"Value", 0) != S_OK) { MessageBox(hwndExcel, L"ValueGET: ", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
sMinCell = result.date;
if (AutoWrap(DISPATCH_PROPERTYGET, &result, pExcelDisp, L"Range", 1, p2) != S_OK) { MessageBox(hwndExcel, L"Range: ", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
if (AutoWrap(DISPATCH_PROPERTYGET, &result, result.pdispVal, L"Value", 0) != S_OK) { MessageBox(hwndExcel, L"ValueGET: ", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
sMaxCell = result.date; }
CComPtr <IDispatch> pxlRangeOut; {
CComVariant result; CComVariant p(std::wstring(L"C1:C" + std::to_wstring(xlLastCell)).c_str());
if (AutoWrap(DISPATCH_PROPERTYGET, &result, pExcelDisp, L"Range", 1, p) != S_OK) { MessageBox(hwndExcel, L"Range: ", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
pxlRangeOut = result.pdispVal; }
if (AutoWrap(DISPATCH_METHOD, NULL, pxlRangeOut, L"ClearContents", 0) != S_OK) { MessageBox(hwndExcel, L"ClearContents: ", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
/////////////РАБОТА С SafeArray/////////////
if (!(safeArrayInOut.vt & VT_ARRAY)) { MessageBox(hwndExcel, L"Выделите диапазон!", L"BedvitXLL", MB_OK | MB_ICONEXCLAMATION); return; } //если VARIANT НЕ содержит SAFEARRAY //8204 vt != (VT_ARRAY | VT_VARIANT)
if (safeArrayInOut.parray->cDims != 2) { MessageBox(hwndExcel, L"Массив не равный двум размерностям", L"BedvitXLL", MB_OK | MB_ICONERROR); return; } //если VARIANT содержит SAFEARRAY не равный двум размерностям
size_t lLbound_0 = safeArrayInOut.parray->rgsabound[0].lLbound; //нижняя граница 1х массив
size_t cElements_0 = safeArrayInOut.parray->rgsabound[0].cElements; //количество элементов 1х массив/2х массив - столбцов
size_t lLbound_1 = safeArrayInOut.parray->rgsabound[1].lLbound; //нижняя граница 2х массив
size_t cElements_1 = safeArrayInOut.parray->rgsabound[1].cElements; //количество элементов 2х массив - строк
size_t elemSize = SafeArrayGetElemsize(safeArrayInOut.parray); //размер элемента массива в байтах
VARIANT HUGEP* cArray; //в си-массив
HRESULT hr = SafeArrayAccessData(safeArrayInOut.parray, (void HUGEP**)&cArray); //открываем массив для редактирования
if (FAILED(hr)) { MessageBox(hwndExcel, L"FAILED(SafeArrayAccessData)", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
LONGLONG a, b, c, i, n, k=0, j, sMin, sMax;
LONGLONG mGCD = cArray[0].date;
n = cElements_1;
concurrency::concurrent_vector <LONGLONG> arr(n);
//arr.resize(n);
for (long i = 0; i < n; i++) {
a = cArray[i].date;
arr[i] = a;
b = mGCD;
while (b > 0) {
c = b;
b = a % b;
a = c;
}
mGCD = a;
}
for (i = 0; i < n; i++) {arr[i] = arr[i] / mGCD;}
sMin = sMinCell / mGCD;
sMax = sMaxCell / mGCD;
//std::vector<LONGLONG> arrIndex(sMax+1);
concurrency::concurrent_vector <LONGLONG> arrIndex(sMax + 1);
//arrIndex.resize(sMax + 1);
if (sMin > sMax) {sMin = sMax;}
concurrency::concurrent_vector <LONGLONG> arrK;
//void RUNarrIndex(int startFor, int EndFor, LONGLONG sMin, LONGLONG sMax, std::vector<LONGLONG> &arrIndex, std::vector<LONGLONG> &arr)
if (n >= 24) {
LONGLONG treadCount = 2;
LONGLONG de = n / treadCount;
LONGLONG mod = n % treadCount;
std::vector<std::thread> thr(2);
arrK.resize(treadCount);
for (int i = 0; i < treadCount; i++) {
LONGLONG startFor = i * de + 1;
LONGLONG endFor= (i+1) * de;
if (i == treadCount-1) {endFor = endFor + mod;}
thr[i] = std::thread(RUNarrIndex, i, startFor, endFor, sMin, sMax, std::ref(arr), std::ref(arrIndex), std::ref(arrK));
}
for (int i = 0; i < treadCount; i++) { thr[i].join(); }
}
else
{
//for (;;) {
for (i = 1; i <= n; i++) {
if ((arr[i - 1] > 0 && arr[i - 1]) <= sMax) {
for (j =(sMax - arr[i - 1]); j >= 1; j--) {
if (arrIndex[j] > 0) {
k = j + arr[i - 1];
if (arrIndex[k] == 0) {
arrIndex[k] = i;
if (k >= sMin) { goto endFor_; }
}
}
}
k = arr[i - 1];
if (arrIndex[k] == 0) {
arrIndex[k] = i;
if (k >= sMin) { goto endFor_; }
}
}
}
//}
}
endFor_:
for (i = 0; i < arrK.size(); i++) { k = max(k, arrK[i]); }
if (k < sMin) {
for (k = sMin-1; k >= 1; k--) {
if (arrIndex[k] > 0) { continue; }
}
}
i = 0;
if ((k*mGCD < sMinCell) || (k * mGCD > sMaxCell)) {
if (MessageBox(hwndExcel, L"Точное решение не найдено. Вывести максимально приближенное?", L"BedvitXLL", MB_YESNO | MB_ICONINFORMATION) == IDNO)
{
hr = SafeArrayUnaccessData(safeArrayInOut.parray); //закрываем массив
if (FAILED(hr)) { MessageBox(hwndExcel, L"FAILED(SafeArrayUnaccessData)", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
return;
}
}
std::vector<LONGLONG> arrSubsetIndex;
while (k > 0) {
arrSubsetIndex.push_back(arrIndex[k]);
k = k - arr[arrIndex[k] - 1];
}
for (i = 0; i < n; i++) {VariantClear(&cArray[i]);} //очищаем SafeArray
for (i = 0; i < arrSubsetIndex.size(); i++) {
cArray[arrSubsetIndex[i]-1].llVal = arr[arrSubsetIndex[i] - 1]*mGCD;
cArray[arrSubsetIndex[i]-1].vt = VT_I8;
}
hr = SafeArrayUnaccessData(safeArrayInOut.parray); //закрываем массив
if (FAILED(hr)) { MessageBox(hwndExcel, L"FAILED(SafeArrayUnaccessData)", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
/////////////РАБОТА С SafeArray/////////////
//CComPtr <IDispatch> pxlRangeOut; {
// CComVariant result; CComVariant p(std::wstring(L"C1:C" + std::to_wstring(xlLastCell)).c_str());
// if (AutoWrap(DISPATCH_PROPERTYGET, &result, pExcelDisp, L"Range", 1, p) != S_OK) { MessageBox(hwndExcel, L"Range: ", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
// pxlRangeOut = result.pdispVal; }
//if (AutoWrap(DISPATCH_METHOD, NULL, pxlRangeOut, L"ClearContents", 0) != S_OK) { MessageBox(hwndExcel, L"ClearContents: ", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
//CComPtr <IDispatch> pxlResize; {
// CComVariant result; CComVariant p0(curCount); CComVariant p1(1); //строки//столбцы
// if (AutoWrap(DISPATCH_PROPERTYGET, &result, pxlRangeOut, L"Resize", 2, p1, p0) != S_OK) { MessageBox(hwndExcel, L"pxlResize: ", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
// pxlResize = result.pdispVal; }
if (AutoWrap(DISPATCH_PROPERTYPUT, NULL, pxlRangeOut, L"Value", 1, safeArrayInOut) != S_OK) { MessageBox(hwndExcel, L"ValuePUT: ", L"BedvitXLL", MB_OK | MB_ICONERROR); return; }
MessageBox(hwndExcel, std::wstring(L"millisecond: " + std::to_wstring(clock() - startTime)).c_str(), L"BedvitXLL", MB_OK | MB_ICONINFORMATION);
} |