#pragma once #include "pch.h" #include <Objbase....
Creato il: 31 agosto 2025
Risposto usando GPT-5 Thinking da Chat01
Creato il: 31 agosto 2025
Risposto usando GPT-5 Thinking da Chat01
#pragma once
#include "pch.h"
#include <Objbase.h>
static inline float xor_rand_grsh(uint32_t& __restrict state) noexcept
{
uint32_t s = state;
s ^= s << 13u;
s ^= s >> 17u;
s ^= s << 5u;
state = s;
return fmaf(s, 0x1.0p-31f, -1.0f);
}
static inline float xor_rand(uint32_t& __restrict state)
{
uint32_t s = state;
s ^= s << 13u;
s ^= s >> 17u;
s ^= s << 5u;
state = s;
return s * 0x1.0p-32f;
}
static float HillFunc(const float x, uint32_t seed) noexcept
{
int32_t i = 0;
__declspec(align(64u)) float angles[14u];
const float start_angle = 6.28318530717958647692f * x;
#pragma loop(ivdep)
while (i < 14) {
angles[i] = start_angle * (i + 1);
++i;
}
text__declspec(align(64u)) float sin_vals[14u]; __declspec(align(64u)) float cos_vals[14u]; fabe13_sincos_scalar_simple(angles, sin_vals, cos_vals, 14u); float res = fmaf(xor_rand(seed), 2.0f, -1.1f); --i; while (i >= 0) { res += fmaf(fmaf(xor_rand(seed), 2.0f, -1.1f), sin_vals[i], fmaf(xor_rand(seed), 2.0f, -1.1f) * cos_vals[i]); --i; } return res;
}
static inline float ShekelFunc(float x, uint32_t& __restrict seed)
{
uint32_t i = 0u;
float res = 0.0f;
textwhile (i < 10u) { const float r = xor_rand(seed); const float x_part = fmaf(-r, 10.0f, x); res -= 1.0f / fmaf(fmaf(xor_rand(seed), 20.0f, 5.0f), x_part * x_part, fmaf(xor_rand(seed), 0.2f, 1.0f)); ++i; } return res;
}
static float GrishaginFunc(const float x1, const float x2, uint32_t seed) noexcept
{
int32_t i = 0;
__declspec(align(64u)) float angles_i[8u];
__declspec(align(64u)) float angles_j[8u];
#pragma loop(ivdep)
while (i < 8) {
const float pi_mult = 3.14159265358979323846f * (i + 1);
angles_i[i] = pi_mult * x1;
angles_j[i] = pi_mult * x2;
++i;
}
text__declspec(align(64u)) float sin_i[8u], cos_i[8u]; __declspec(align(64u)) float sin_j[8u], cos_j[8u]; fabe13_sincos_scalar_simple(angles_i, sin_i, cos_i, 8u); fabe13_sincos_scalar_simple(angles_j, sin_j, cos_j, 8u); --i; float part1 = 0.0f; float part2 = 0.0f; while (i >= 0) { uint32_t j = 0u; while (j < 8u) { const float sin_term = sin_i[i] * sin_i[i]; const float cos_term = cos_j[j] * cos_j[j]; part1 = fmaf(xor_rand_grsh(seed), sin_term, fmaf(xor_rand_grsh(seed), cos_term, part1)); part2 = fmaf(-xor_rand_grsh(seed), cos_term, fmaf(xor_rand_grsh(seed), sin_term, part2)); ++j; } --i; } return -sqrtf(fmaf(part1, part1, part2 * part2));
}
static inline float RastriginFunc(const float x1, const float x2) noexcept
{
const float term1 = fmaf(x1, x1, x2 * x2);
return (term1 - fmaf(
fabe13_cos(6.28318530717958647692f * x1) +
fabe13_cos(6.28318530717958647692f * x2),
10.0f,
-14.6f)) *
fmaf(-term1, 0.25f, 18.42f);
}
static inline float Shag(const float _m, const float x1, const float x2, const float y1,
const float y2, const uint32_t _N, const float _r) noexcept
{
const float diff = y2 - y1;
return _N == 1u
? fmaf(-(1.0f / _m), diff, x1 + x2) * 0.5f
: diff > 0.0f
? fmaf(-(1.0f / (_m * _m)), (diff) * (diff)_r, x1 + x2) * 0.5f
: fmaf(1.0f / (_m * _m), (diff) * (diff)_r, x1 + x2) * 0.5f;
}
__declspec(align(32u)) struct Interval final
{
public:
std::pair<float, float> start;
std::pair<float, float> end;
float M;
float R;
text__declspec(noalias) __forceinline Interval(const std::pair<float, float> _start, const std::pair<float, float> _end, const uint32_t _N) : start(_start) , end(_end) , M(_N == 1u ? fabsf(_end.second - _start.second) * (1.0f / (_end.first - _start.first)) : _N == 2u ? fabsf(_end.second - _start.second) * (1.0f / sqrtf(_end.first - _start.first)) : fabsf(_end.second - _start.second) * (1.0f / powf(_end.first - _start.first, 1.0f / float(_N)))) , R(0.0f) { } __declspec(noalias) __forceinline void ChangeCharacteristic(const float _m, const uint32_t _N) noexcept { const float delta_x = end.first - start.first; const float delta_y = end.second - start.second; switch (_N) { case 1u: R = fmaf( -(end.second + start.second), 2.0f, fmaf(_m, delta_x, (delta_y * delta_y) * (1.0f / (_m * delta_x)))); break; case 2u: { const float sqrt_dx = sqrtf(delta_x); R = fmaf( -(end.second + start.second), 2.0f, fmaf(_m, sqrt_dx, (delta_y * delta_y) * (1.0f / (_m * sqrt_dx)))); } break; default: { const float pow_dx = powf(delta_x, 1.0f / _N); R = fmaf( -(end.second + start.second), 2.0f, fmaf(_m, pow_dx, (delta_y * delta_y) * (1.0f / (_m * pow_dx)))); } } }
};
//static inline bool Compare(const Interval& __restrict a, const Interval& __restrict b) noexcept
//{
//return a.R < b.R;
//}
struct IntervalComparator final {
inline bool operator()(const Interval a, const Interval b) {
if (a.R < b.R) return true;
if (a.R == b.R && a.start.first > b.start.first) return true;
return false;
//return a.R < b.R;
}
};
typedef std::priority_queue<Interval, std::deque<Interval>, IntervalComparator>
Priority_queue;
const __declspec(noalias) __forceinline PeanoCurve_2D* PeanoCurve_2D::HitTest_2D(float x) const noexcept
{
uint32_t i = 0u;
const uint32_t _razvertka = this->razvertka;
uint32_t num;
const float this_a = this->a;
x -= this_a;
const float b_minus_a = this->b - this_a;
const float inv_b_minus_a = 1.0f / b_minus_a;
const PeanoCurve_2D* Curr = this;
textwhile (i != _razvertka) { const uint32_t shift = 1u << ++i + i; num = shift * x * inv_b_minus_a; x = fmaf(-ldexp(1.0f, -(i << 1)) * num, b_minus_a, x); const List currType = Curr->Type; switch (num) { case 0u: Curr = (currType == Top || currType == Right) ? Curr->DownLeft.get() : Curr->TopRight.get(); break; case 1u: Curr = (currType == Top || currType == Left) ? Curr->TopLeft.get() : Curr->DownRight.get(); break; case 2u: Curr = (currType == Top || currType == Right) ? Curr->TopRight.get() : Curr->DownLeft.get(); break; case 3u: Curr = (currType == Top || currType == Left) ? Curr->DownRight.get() : Curr->TopLeft.get(); } } return Curr;
}
const __declspec(noalias) __forceinline float PeanoCurve_2D::FindX_2D(float target_x1, float target_x2) const noexcept
{
uint32_t _razvertka = this->razvertka;
uint32_t _razvertka1 = _razvertka;
float x1, x2, x = this->a;
const float b_minus_a = this->b - x;
const PeanoCurve_2D* Curr = this;
textwhile (_razvertka != 0u) { const uint32_t exponent = _razvertka1 - _razvertka-- << 1u; x1 = Curr->x1; x2 = Curr->x2; const List currType = Curr->Type; if (target_x1 > x1 && target_x2 > x2) { Curr = Curr->TopRight.get(); if (currType == Top || currType == Right) { x = fmaf(ldexp(1.0f, -exponent) * 0.5f, b_minus_a, x); } } else if (target_x1 < x1 && target_x2 > x2) { Curr = Curr->TopLeft.get(); if (currType == Top || currType == Left) { x = fmaf(ldexp(1.0f, -exponent) * 0.25f, b_minus_a, x); } else { x = fmaf(ldexp(1.0f, -exponent) * 0.75f, b_minus_a, x); } } else if (target_x1 < x1 && target_x2 < x2) { Curr = Curr->DownLeft.get(); if (currType == Down || currType == Left) { x = fmaf(ldexp(1.0f, -exponent) * 0.5f, b_minus_a, x); } } else { Curr = Curr->DownRight.get(); if (currType == Top || currType == Left) { x = fmaf(ldexp(1.0f, -exponent) * 0.75f, b_minus_a, x); } else { x = fmaf(ldexp(1.0f, -exponent) * 0.25f, b_minus_a, x); } } } return x;
}
extern const boost::mpi::communicator world;
extern std::unique_ptr<PeanoCurve_2D> Curve;
extern std::unique_ptr<PeanoCurve_2D> Curve_Inverted;
struct CrossMsg final {
float s_x1, s_x2;
float e_x1, e_x2;
float Rtop;
template <typename Archive>
__declspec(noalias) __forceinline void serialize(Archive& __restrict ar, const unsigned int) noexcept { ar& s_x1& s_x2& e_x1& e_x2& Rtop; }
};
static std::vector<float> Base_LNA_1_2_Mer_AGP(const uint32_t N,
const uint32_t global_iterations, const float a, const float b, const float c, const float d, const float r,
const bool mode, const float epsilon, uint32_t seed)
{
textif (N == 1u) { const float initial_length = b - a; float dmax = initial_length; std::vector<float> Extr; Extr.reserve((global_iterations << 1u) + 2u); //std::vector<std::unique_ptr<Interval>> R; //R.reserve(global_iterations + 1u); Priority_queue R; float best_f = ShekelFunc(a, seed); const float end_val = ShekelFunc(b, seed); uint32_t schetchick = 0u; std::pair<float, float> x_Rmax = std::make_pair(a, b); std::pair<float, float> y_Rmax = std::make_pair(best_f, end_val); Interval interval(std::pair(a, best_f), std::pair(b, end_val), N); R.push(interval); //R.emplace_back(std::make_pair(a, best_f), std::make_pair(b, end_val), 1u); //float Mmax = R.front().M; //float m = r * Mmax; std::vector<float> myVector = { 1.1f, 2.2f, 3.3f, 4.4f, 5.5f }; // 2. Делаем что-то с вектором (например, увеличиваем каждый элемент на 10%) for (float& num : myVector) { // Используем ссылку, чтобы изменять оригинальные значения num *= 1.1f; } // 3. Добавляем новый элемент в конец вектора myVector.push_back(6.6f); // 4. Возвращаем модифицированный вектор return myVector; }
}
// C-обёртка: без std::vector в сигнатуре!
extern "C" __declspec(dllexport) int __cdecl Base_LNA_1_2_Mer_AGP_C(
uint32_t N, uint32_t global_iterations, float a, float b, float c, float d, float r,
bool mode, float epsilon, uint32_t seed,
float** out_data, uint32_t* out_len)
{
try {
auto v = Base_LNA_1_2_Mer_AGP(N, global_iterations, a, b, c, d, r, mode, epsilon, seed);
*out_len = (uint32_t)v.size();
out_data = (float)CoTaskMemAlloc(sizeof(float) * (*out_len));
if (!*out_data) return 2; // OOM
memcpy(*out_data, v.data(), sizeof(float) * (*out_len));
return 0; // ok
}
catch (const std::bad_alloc& e) {
if (out_data) *out_data = nullptr;
if (out_len) *out_len = 0;
return 3;
}
catch (const std::exception& e) {
if (out_data) *out_data = nullptr;
if (out_len) *out_len = 0;
return 1;
}
}
extern "C" __declspec(dllexport) void __cdecl Base_LNA_1_2_Mer_AGP_Free(float* p) {
CoTaskMemFree(p);
} - у меня есть проблема с моей DLL библиотекой, проблема не в самих экспортируемых функциях - проблема в основной функции конструирующей вектор - проблема в том, что я могу сконструировать интервал но не могу положить его в вектор или дэк или приоритетную очередь - я перепробовал все эти структуры хранения и всегда получал исключения, если сделать через emplace_back то тоже получу исключение - причём заметь когда я делаю всё это с обычным вектором примитивного типа то вставка проходит нормально но когда я делаю вставку в вектор/дэк/очередь интервалов то получаю исключение, всё остальное было проверено исключений не вызывает - больше не нашёл ошибок, эта функция ещё в разработке, эта библиотека чисто нативная - однако вызывается она в управляемом коде, более того - мной было протестировано раньше в чисто нативном приложении что вставка интервалов работает нормально, но когда я вызываю эту функцию в MyForm.h clr NetFramework 4.8.1 так System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
textchart2->Series[0]->Points->Clear(); chart2->Series[1]->Points->Clear(); chart2->Series[2]->Points->Clear(); chart2->Series[3]->Points->Clear(); static LARGE_INTEGER start, end; QueryPerformanceCounter(&start); uint32_t seed = GetTickCount(); typedef int(__cdecl* agp_c)( uint32_t, uint32_t, float, float, float, float, float, bool, float, uint32_t, float**, uint32_t*); typedef void(__cdecl* agp_free)(float*); HINSTANCE h = LoadLibrary(L"TEST_FUNC.dll"); if (!h) { DWORD errorCode = GetLastError(); System::String^ errorMessage = "Ошибка загрузки DLL! Код: " + errorCode.ToString(); System::Windows::Forms::MessageBox::Show(errorMessage); return; } auto f = (agp_c)GetProcAddress(h, "Base_LNA_1_2_Mer_AGP_C"); auto ffree = (agp_free)GetProcAddress(h, "Base_LNA_1_2_Mer_AGP_Free"); if (!f || !ffree) { /* обработать ошибку */ } float* buf = nullptr; uint32_t len = 0; int rc = f(1, 10000, 0.0f, 1.0f, -2.2f, 1.8f, 2.5f, false, 0.0001f, seed, &buf, &len); if (rc == 0) { std::vector<float> Extr_2D(buf, buf + len); ffree(buf); textBox2->Text = Convert::ToString(Extr_2D.back()); // ... используете Extr_2D } FreeLibrary(h); то получаю исключение - внешний компанент вызывал исключение SEH глубоко проанализируй в чём тут дело, дело ли в управляемом коде, я не могу отказаться от управляемого кода так как мне нужен вывод на графики, предложи возможные пути решения проблемы
Коротко: у тебя на стыке native/managed выстрелила ошибка выравнивания (alignment) + неудачная сигнатура компаратора. Всё отлично работает в чисто нативном приложении, а под WinForms (/clr) ловишь SEH при вставке Interval
в vector/deque/priority_queue
, потому что:
Interval
помечен __declspec(align(32))
⇒ тип over-aligned (требует 32-байтового выравнивания).IntervalComparator
принимает параметры по значению, т.е. компилятор кладёт копии Interval
на стек.Добавочно усугубляют ситуацию твои локальные массивы с __declspec(align(64))
в других функциях — под /clr(x86) это особенно опасно: стек там часто всего 4/8-байтово выровнен.
const&
Это главная правка: не копируй over-aligned объекты на стек.
cppstruct IntervalComparator final { bool operator()(const Interval& a, const Interval& b) const noexcept { if (a.R < b.R) return true; if (a.R == b.R && a.start.first > b.start.first) return true; return false; } };
(Сейчас у тебя operator()(Interval a, Interval b)
, что и провоцирует копирование/размещение на стеке.)
Interval
(или хотя бы снизь)Если 32 байта тебе не жизненно необходимы — удали __declspec(align(32))
или замени на alignas(16)
.
Чем меньше требуемое выравнивание, тем меньше шансов словить падение на стеке/в контейнерах.
cpp// было: __declspec(align(32u)) struct Interval // стало, если всё же нужно: alignas(16) struct Interval struct Interval final { ... };
Примечание: если ультра-выравнивание реально нужно (SIMD и т.п.), никогда не передавай такие типы по значению, и избегай их размещения на стеке. Держи их по указателю/ссылке.
На x64 по ABI стек выровнен на 16 байт, и жизнь сильно проще.
В проекте WinForms (.NET Framework 4.8.1):
max_align_t
).std::function
, и т.п.std::unique_ptr<Interval>
(или лёгкие ключи/индексы), а сравнивай по ссылке на целевой объект.__declspec(align(64))
В функциях вроде HillFunc
, GrishaginFunc
у тебя есть стековые массивы с 64-байтовым выравниванием. Под /clr(x86) это почти гарантированная мина. Варианты:
alignas(16)
._aligned_malloc(64, size)
/_aligned_free
(или завести свой AlignedAllocator
и использовать std::vector<T, AlignedAllocator<T, 64>>
).Сейчас ты ловишь только std::exception
/bad_alloc
. Доступ по неверному адресу — это SEH, он сюда не попадает. Если хочется «мягко» отловить и вернуть код:
catch(...)
внутри экспортируемой C-обёртки вокруг вызова нативной функции, или__try { ... } __except(EXCEPTION_EXECUTE_HANDLER) { ... }
.Это не лечит причину, но даст аккуратный rc != 0
без выноса процесса.
Priority_queue
ты используешь std::priority_queue<Interval, std::deque<Interval>, IntervalComparator>
. С переходом на const&
в компараторе — ок.std::vector<Interval>
+ std::push_heap/pop_heap
(там меньше «магии») — чисто для диагностики.HitTest_2D
есть const uint32_t shift = 1u << ++i + i;
— приоритет операторов: это 1u << (++i + i)
. Убедись, что именно так задумывалось.FindX_2D
много ветвлений с ldexp(1.0f, -exponent) * K
— всё ок, но проверь, что exponent
не уезжает за 24 (точность float).cppstruct IntervalComparator final { bool operator()(const Interval& a, const Interval& b) const noexcept { if (a.R < b.R) return true; if (a.R == b.R && a.start.first > b.start.first) return true; return false; } };
Сборка x64, отключить “Prefer 32-bit”.
Снизить выравнивание Interval
до alignas(16)
или убрать вовсе. (И не передавать по значению нигде.)
(Опционально) В C-обёртке добавить catch(...)
или __try/__except
, чтобы вместо выноса процесса возвращался код ошибки.
Interval
по указателю:
cppusing PInterval = std::unique_ptr<Interval, AlignedDeleter>; // _aligned_free using PQ = std::priority_queue<PInterval, std::vector<PInterval>, PtrComparator>;
cpptemplate<class T, std::size_t Align> struct AlignedAllocator { /* реализуй allocate/deallocate через _aligned_malloc/_aligned_free */ }; std::vector<Interval, AlignedAllocator<Interval, 32>> v;
const Interval&
(или сравнение по *ptr
).align(32)
у параметров по значению → конфликт ожиданий и реальности → SEH.Если применишь первые три пункта (компаратор по ссылке, x64, уменьшить выравнивание/не класть на стек) — проблема должна исчезнуть. Если нет — пингани, накину набор assert’ов/trace и подскажу, где ещё «торчит» копирование по значению или злоупотребление выравниванием.