#pragma once #include "pch.h" #include <Objbase....
बनाया गया: 30 अगस्त 2025
का उपयोग करके उत्तर दिया गया GPT-5 Thinking द्वारा Chat01
बनाया गया: 30 अगस्त 2025
का उपयोग करके उत्तर दिया गया GPT-5 Thinking द्वारा Chat01
#pragma once
#include "pch.h"
#include <Objbase.h>
extern "C" __declspec(dllexport) float __cdecl 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);
}
extern "C" __declspec(dllexport) float __cdecl 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;
}
extern "C" __declspec(dllexport) float __cdecl ShekelFunc(float x, uint32_t 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));
}
extern "C" __declspec(dllexport) float __cdecl 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);
}
extern "C" __declspec(dllexport) float __cdecl 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>& __restrict _start, const std::pair<float, float>& __restrict _end, const uint32_t _N) noexcept : 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)))) { } __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)))); } } }
};
extern "C" __declspec(dllexport) bool __cdecl Compare(const Interval& __restrict a, const Interval& __restrict b) noexcept
{
return a.R < b.R;
}
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; }
};
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<Interval> R; R.reserve(global_iterations + 1u); 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); R.emplace_back(std::make_pair(a, best_f), std::make_pair(b, end_val), N); 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 библиотека, если я упрощаю основную экспортируюмую функцию возвращающую вектор до std::vector<float> myVector = { 1.1f, 2.2f, 3.3f, 4.4f, 5.5f };
text// 2. Делаем что-то с вектором (например, увеличиваем каждый элемент на 10%) for (float& num : myVector) { // Используем ссылку, чтобы изменять оригинальные значения num *= 1.1f; } // 3. Добавляем новый элемент в конец вектора myVector.push_back(6.6f); // 4. Возвращаем модифицированный вектор return myVector; - то всё работает нормально, но в таком виде в каком она сейчас она вызывает исключения в управляемом коде в котором я её вызываю в myforms приложении, я пометил некоторые остальные функции как экспортируемые так как казалось это уберёт ошибку но не помогло - остальные функции в dll можно пометить статическими и будет тот же эффект, dll и основной проект имеют схожие настройки кроме clr флагов, но все настройки касаемо вычислений с плавающей запятой идентичные, проблема точно не в денормалах, вот код в управляемой форме: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { chart2->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 } само исключение выбрасывается не в управляемом коде а в самой dll в вызове функции шекеля здесь const float r = xor_rand(seed); const float x_part = fmaf(-r, 10.0f, x); - иногда исключение выбрасывается в первой, иногда во второй строчке, при том, что изолированно я проверил что fmaf вычисления у меня работают, здесь также библиотека <cmath> - подключена, функция для рандома также правильна, подскажи в каком направлении копать, какая самая вероятная причина падения, может быть функция шекеля должна принимать ссылку? так как в рандоме используется ссылка, касаемо самой логики функции они правильны - потому что я проверял их изолированно не из dll а в консольном приложении проверял эти функции
Кратко: по симптомам это почти наверняка не “математика”, а ABI/прототип (несовпадение сигнатур / соглашения о вызове / ref vs value) → порча стека/регистров, из-за чего падение иногда в const float r = xor_rand(seed);
, иногда в fmaf(...)
. Когда вы упрощаете функцию и не вызываете ShekelFunc()/xor_rand()
, всё ок — как только идёт вызов RNG через ссылку, срабатывает.
Вот куда копать и что изменить (в порядке вероятности/пользы):
extern "C"
+ &
у внутренних функций (или сделайте API pointer-based)Экспортировать функции с C-линковкой и C++-ссылками — плохая идея. В разных TU легко получить рассинхрон прототипов (особенно при PCH). Достаточно в одном месте объявить xor_rand(uint32_t)
(по значению), а где-то определить xor_rand(uint32_t&)
— компилятор примет, линковщик тоже, а в рантайме вызов передаст значение вместо адреса → state
в xor_rand
станет “левым” указателем → падение ровно на строке uint32_t s = state;
.
Надёжные варианты:
Вариант А (рекомендую): сделать RNG внутренним и pointer-based
cpp// .cpp (без dllexport/extern "C") static inline float xor_rand_u32(uint32_t* state) noexcept { uint32_t s = *state; s ^= s << 13u; s ^= s >> 17u; s ^= s << 5u; *state = s; return s * 0x1.0p-32f; } static inline float xor_rand_grsh_u32(uint32_t* state) noexcept { uint32_t s = *state; s ^= s << 13u; s ^= s >> 17u; s ^= s << 5u; *state = s; return fmaf((float)s, 0x1.0p-31f, -1.0f); }
и везде вызывать как:
cppconst float r = xor_rand_u32(&seed);
Вариант B: если принципиально оставить ссылку — не экспортируйте эти функции, держите их static inline
в том же TU, где вызываете; и убедитесь, что есть один общий заголовок с единственной корректной декларацией, который подключается повсюду. После правки — удалите .pch
и пересоберите “с нуля”.
float xor_rand(uint32_t state)
(без &
) или без extern "C"
, или с другим __stdcall/__vectorcall
.fmaf
/xor_rand
.cppextern "C" float __cdecl xor_rand(uint32_t& state) noexcept; static_assert(std::is_same_v<decltype(&xor_rand), float(__cdecl*)(uint32_t&)>, "xor_rand prototype mismatch");
Сейчас ShekelFunc(float x, uint32_t seed)
принимает сид по значению (это ок), но тогда RNG меняет только локальную копию. Функционально это нормально, но чтобы исключить любые сюрпризы с адресацией, можно тоже перейти на pointer/reference:
cpp// либо static float ShekelFunc(float x, uint32_t& seed) noexcept // либо static float ShekelFunc(float x, uint32_t* seed) noexcept
и вызывать консистентно с п.1.
В смешанной среде иногда кто-то снимает маски SSE/x87. Это не ваша корневая причина (по формуле деления на 0 быть не должно), но на всякий случай заглушите ловушки в начале экспортируемой C-обёртки:
cpp#include <float.h> #include <immintrin.h> extern "C" __declspec(dllexport) int __cdecl Base_LNA_1_2_Mer_AGP_C(...){ // Маскируем x87 _controlfp_s(nullptr, _MCW_EM, _MCW_EM); // Маскируем SSE исключения + включаем FTZ/DAZ (по желанию) unsigned mx = _mm_getcsr(); _mm_setcsr(mx | 0x1F80 /*маски*/ | 0x8040 /*FTZ|DAZ*/); __try { auto v = Base_LNA_1_2_Mer_AGP(...); ... return 0; } __except(EXCEPTION_EXECUTE_HANDLER) { if (out_data) *out_data = nullptr; if (out_len) *out_len = 0; return 4; // аппаратное исключение } }
HitTest_2D
: выражение 1u << ++i + i
читается как 1u << (++i + i)
. Если там ожидалась другая логика — расставьте скобки явно. Это не влияет на N==1 ветку, но потенциально минное поле.LoadLibrary
бы упал) и что обе сборки на /MD (CRT в DLL вы обходите через CoTaskMemAlloc
, это правильно).ShekelFunc
заменить вызовы на xor_rand_u32(&seed)
.dllexport/extern "C"
у внутренних функций; экспорт оставить только у C-обёрток.Если после этого всё ещё падает — почти наверняка где-то осталась неправильная декларация одной из функций. В таком случае откройте листинг вызова xor_rand
(ассемблер): вы должны видеть передачу адреса переменной seed
(на x64 — через регистр с последующим обращением по памяти), а не самого значения. Если передаётся значение — найден источник.