Ruslan1 38 June 25 Posted June 25 · Report post Здравствуйте! Использую ИИ для поиска проблем в исходном коде. Иногда находит реально потенциально опасные или некорректные вещи в вроде бы работающих исходниках (неоптимальные решения, зависимости, критические гонки), копает глубоко. Но сейчас пользуюсь этим так: скармливаю исходник (один файл) через окно чата, и докидываю руками дефайны-хедеры-функции из других файлов, если не хватает для анализа. Использую в основном Джемини. Его уровня понимания и анализа абсолютно хватает. И (обычно) советы адекватные, и предлагаемые им куски кода для замены. Но это всё работает с одним файлом. Можно ему и несколько загрузить, но это очень неудобно. Знаю, что есть (куча!) систем ИИ, которые разработаны именно под мои хотелки (анализ исходников), и можно закидывать для обработки проект целиком (десятки файлов). Но сложно понять, что из них хорошо а что неудобно (или очень избыточно). Хотелось бы халявы, пусть и с ограничениями (как Джемини). Но малая денежка в месяц тоже покатит. Применение для Си-файлов, не супер-сложные проекты (десятки файлов, ну, может, до 1 мегабайт текста своего кода в проекте). Использую Вижуал Студио (VSC) и Кейл. Хорошо если прямо к ним что-то подключить можно (думаю, к VSC, он всё же посовременней). В интернете много всего, всё пробовать здоровья не хватит. Кто что лично использует? Что-то несложное для "начинающего ИИ-шника", пожалуйста? Заранее спасибо! Quote Share this post Link to post Share on other sites More sharing options...
dimka76 99 June 25 Posted June 25 · Report post On 6/25/2026 at 3:38 PM, Ruslan1 said: Использую Вижуал Студио (VSC) и Кейл. Хорошо если прямо к ним что-то подключить можно (думаю, к VSC, он всё же посовременней). В интернете много всего, всё пробовать здоровья не хватит. Кто что лично использует? Что-то несложное для "начинающего ИИ-шника", пожалуйста? Заранее спасибо! В VS Code есть Copilot. Он может получать доступ целиком ко всему проекту. Сам не пользовался, знаю понаслышке. Quote Share this post Link to post Share on other sites More sharing options...
amaora 42 June 25 Posted June 25 · Report post Пробовал opencode и codex. Их можно подключать к разным llm, которые поддерживают работу с инструментами. В одном из них были бесплатные модели для тестов. Оба можно подключить к локальной llm (например ollama) если есть большая видеокарта. Успешно использовать эти инструменты у меня получалось больше для анализа кода, но не для генерации. Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 352 June 26 Posted June 26 · Report post А можно увидеть результат такого анализа? Дипсик, чатЖПТ, гемини такю фигню наанализровали, что иногда смешно - как будто бухого друга пытаюсь переубедить. Quote Share this post Link to post Share on other sites More sharing options...
Ruslan1 38 June 26 Posted June 26 · Report post 26 минут назад, Arlleex сказал: А можно увидеть результат такого анализа? Дипсик, чатЖПТ, гемини такю фигню наанализровали, что иногда смешно - как будто бухого друга пытаюсь переубедить. Не согласен. с GPT у меня тоже всё было нормально. Да, иногда делает неправильные выводы и становится смешно. Но! только из-за того что не видит картину целиком. Кстати, читает не только код, но и комментарии. И находит противоречия (например, если код поменялся а комментарий ему не соответствует, или если не раскрывает неявные хитрости, использованные в коде). И это супер-полезно в любом случае. Моё мнение- вычищать всё что найдено (конечно, думать надо). То есть сделать максимально хорошо, плохо оно получится само. Есть глюки, полный файл я бы ему переписывать не доверил точно (что-то теряет случайным образом, что-то молча меняет на бред). Но отдельные функции и под контролем программиста- справляется почти всегда на "отлично". Примеры: У меня согласно ТЗ два набора корректировок. Но он не знает, поэтому считает код ошибкой. Позже я ему скормил ТЗ, он пересчитал и согласился Цитата Критическая ошибка: Неверная плоскость поворота (Логический баг) Давайте внимательно посмотрим, как вы применяете угол установки в функции adxl355_3_axes_apply_correction_and_angle: C x_old = dest[ACC_IDX_x]; // Это dest[1] (бывшая ось b) y_old = dest[ACC_IDX_y]; // Это dest[2] (бывшая ось c) x_new = (x_old * cosIA) - (y_old * sinIA); y_new = (x_old * sinIA) + (y_old * cosIA); dest[ACC_IDX_x] = x_new; dest[ACC_IDX_y] = y_new; В чем проблема? Согласно вашим новым комментариям: ACC_IDX_x — это направление NS (Север-Юг), горизонтальная ось. ACC_IDX_y — это направление W (Запад), вторая горизонтальная ось. ACC_IDX_z — это направление UP (Вертикаль), вертикальная ось Z. Ваша тригонометрическая формула поворачивает вектор вокруг вертикальной оси Z (в горизонтальной плоскости XY между Севером и Западом). Однако, судя по названию переменной INSTALL_ANGLE (Угол установки) и по тому, что при расчете calc_factory_coeffs вы упоминаете «offset 1g up», этот угол обычно означает наклон прибора относительно горизонта (крен/тангаж из-за неровной фиксации корпуса на объекте), а не азимут (поворот по компасу). Если INSTALL_ANGLE — это наклон корпуса относительно горизонта: Вы должны корректировать проекцию ускорения свободного падения ($g$), которая «пролазит» в горизонтальные оси из-за наклона. Для этого поворот нужно делать между горизонтальной осью (X или Y) и вертикальной осью (Z). Поворачивая X и Y между собой, вы никак не компенсируете наклон прибора относительно горизонтали. Если INSTALL_ANGLE — это строго азимутальный поворот корпуса (вокруг вертикали): Тогда математика верна, но она не компенсирует ошибку поверхностного монтажа (0G offset) по вертикали, о которой шла речь в расчете коэффициентов. ⚠️ Резюме: Если датчик наклонен «вперед-назад» или «влево-вправо», в формуле обязательно должна участвовать ось ACC_IDX_z (dest[0]). Поворот осей x и y между собой компенсацию наклона горизонта не выполняет. Тут незнание мной инструмента: Цитата Использование неоптимальных функций геометрии В коде используются cosf() и sinf() отдельно: C *cosIA = cosf(installRadian); *sinIA = sinf(installRadian); В ESP-IDF (и в целом в GCC для архитектур Xtensa/RISC-V) для одновременного расчета синуса и косинуса эффективнее использовать функцию sincosf(installRadian, sinIA, cosIA);. Это работает почти в два раза быстрее, так как тригонометрический ряд считается один раз. Тут реальная ошибка и несколько замечаний из-за того что он не видит всю картину: Цитата 1. Критические ошибки и потенциальные сбои (Crash / Memory Corruption) Опасное использование send() для серверов (Mode 1 и Mode 2) В функции streaming_sending_to_clients_and_servers отправка для клиентов и серверов написана по-разному. Посмотрите на этот фрагмент: C // Для клиентов: send(tcpClient[i].sock, Stream1Buf, sizeof(Stream1Buf), 0); // Для серверов: send(out_srv[i].sock, Stream1Buf, STREAM1_BUFFER_LENGTH, 0); В чем проблема: Stream1Buf состоит из элементов типа int16_t. sizeof(Stream1Buf) возвращает размер в байтах ($600 \times 2 = 1200$). Однако константа STREAM1_BUFFER_LENGTH равна 600. Следствие: При отправке серверу вы передаете в send значение 600 вместо 1200. Сервер получает только половину пакета (заголовок и часть сэмплов), а вторая половина теряется. Для Stream2Buf отправляется 100 байт вместо 200. Несинхронизированный доступ к глобальным буферам (Состояние гонки / Race Condition) Массивы Stream1Buf, Stream2Buf и структура Stream16 объявлены как static глобальные переменные. В чем проблема: Функция streaming_prepare_package формирует данные в Stream1Buf. Сразу после этого вызывается streaming_sending_to_clients_and_servers. Сетевой стек FreeRTOS/lwIP выполняет отправку через send() не мгновенно — данные уходят в буфер сокета. Если задача streaming_task проснется по новому прерыванию быстрее, чем lwIP успеет отправить данные медленному клиенту, функция streaming_prepare_package перезапишет этот глобальный буфер прямо во время отправки. Следствие: Клиенты будут получать «кашу» из частично старых и частично новых данных (data corruption). Блокирующий send в UI/системном таске По умолчанию сокеты в lwIP блокирующие. Если один из серверов или клиентов «зависнет» (TCP-окно станет равным 0 или пропадет связь без закрытия сокета), вызов send() заблокирует выполнение задачи streaming_task на таймаут отправки (который по умолчанию может быть очень большим). Следствие: Таск streaming_task перестанет забирать данные из Streaming_Queue. Очередь переполнится, и вся система стриминга встанет. 2. Логические ошибки и неявное поведение Некорректный инкремент packetNo в Stream16 В функции stream16_prepare_package вы делаете так: C Stream16.fixed.PacketNo = packetNo; // ... (заполнение структуры) packetNo++; // для следующего пакета В чем проблема: В C/C++ многобайтовые поля структур (как uint16_t PacketNo) сохраняются в нативном для процессора формате. ESP32 — это архитектура Little-Endian. В то же время в streaming_prepare_package (Mode 1) вы не переводите packetNo в Big-Endian, хотя Modbus обычно требует Big-Endian. Если принимающая сторона ждет определенный порядок байт, где-то точно будет ошибка. Потеря точности при расчете времени (ms01) C Stream16.header.ms01 = (uint16_t)(SeismicBuf[idx_first].tv.tv_usec / 100); Переменная tv_usec имеет тип suseconds_t (обычно int32_t). Деление на 100 работает корректно, но если tv_usec по какой-то причине (сбой RTC/SNTP) станет отрицательным или превысит 1 секунду, явное приведение к uint16_t приведет к искажению данных времени. Лучше добавить валидацию диапазона. Магические числа при расчете CRC в Mode 1/2 C pnt_u8 = (uint8_t *)&Stream1Buf[93]; pnt_u8[0] = crc16 >> 8; pnt_u8[1] = crc16; В комментариях написано: «CRC_HI into byte 186, and CRC_Lo into byte 187». Индекс Stream1Buf[93] — это 186-й и 187-й байты от начала массива. Смещение рассчитано верно, но запись crc16 >> 8 в pnt_u8[0] записывает старший байт в меньший адрес памяти (Big Endian). Убедитесь, что ваша функция my_usMBCRC16 ожидает именно такой порядок байт на выходе, так как ESP32 работает в Little Endian. 3. Проблемы с производительностью и архитектурой ESP32 Слишком высокий приоритет задачи C #define Streaming_TASK_PRIORITY (configMAX_PRIORITIES - 1) Вы создаете задачу стриминга с приоритетом Streaming_TASK_PRIORITY - 1 (то есть фактически на самом высшем доступном уровне приложения). В чем проблема: Сетевая обработка (особенно циклы for по всем клиентам с блокирующими вызовами send) может занимать относительно много процессорного времени. Следствие: Задача стриминга может «заголодать» (starve) внутренний системный таск lwIP (IP-таск обычно работает на приоритете ESP_TASK_TCPIP_PRIO, который равен 18 по умолчанию). Если таск приложения имеет приоритет выше, чем таск сетевого стека, это может приводить к непредсказуемым задержкам самого lwIP и утечкам буферов сокетов (mbufs/pbufs). Рекомендуется опустить приоритет задачи стриминга ниже приоритета TCP/IP стека. Маленький размер стека (Stack Overflow) C xTaskCreate(streaming_task, "streaming", 2048, ...) Размер стека 2048 слов (то есть 8 КБ на ESP32) выглядит достаточным для текущего кода, так как большие буферы выделены как static. Однако внутри streaming_prepare_package вызывается функция localtime_r, которая активно использует стек. Если в будущем внутри send() или функций логирования ESP_LOGE увеличится глубина вызовов, это может легко вызвать Stack Overflow. Для сетевых задач на ESP32 безопасным минимумом считается 4096. Рекомендации по исправлению Цитата Шаг 4. Защита от зависания сокетов и блокировки всей системы Теперь переходим к скрытой архитектурной угрозе, которая может намертво заблокировать отправку данных при реальной эксплуатации, когда начнутся проблемы с сетью (WiFi мигнет, кабель выдернут, сервер зависнет). В чем проблема сейчас? По умолчанию сокеты в lwIP создаются в блокирующем режиме. Если один из серверов (out_srv) или клиентов резко отключится от сети без закрытия TCP-сессии, его буфер отправки переполнится. Когда streaming_task вызовет: C send(out_srv[i].sock, Stream1Buf, sizeof(Stream1Buf), 0); этот вызов заблокирует (остановит) выполнение всего таска streaming_task на время системного таймаута (который может длиться минуты). В это время данные для всех остальных исправных серверов и клиентов отправляться не будут, очередь Streaming_Queue переполнится, и стриминг полностью встанет. Как исправить? Нужно сделать так, чтобы функция send() возвращала управление немедленно, если буфер сокета полон, либо завершалась по короткому таймауту (например, 20-50 мс). Есть два пути решения. Выберите, какой вам ближе: Цитата Важное сопутствующее исправление очереди Даже при отправке раз в 500 мс, в вашей системе есть критическое узкое горлышко — размер очереди Streaming_Queue. C Streaming_Queue = xQueueCreate(2, sizeof(StreamingQueue_t)) Поскольку таск streaming_task просыпается по этой очереди на каждый сэмпл (или каждую секунду, если данных нет), это означает, что Seismic_Task пишет в эту очередь очень часто (например, каждые 5 или 10 мс). Если таск стриминга застрянет на отправке «плохому» сокету на 50 мс, очередь из 2 элементов переполнится всего за 10–20 мс! Seismic_Task либо заблокируется, либо начнет терять данные прямо на входе. Обязательно увеличьте размер очереди в streaming_init(): C // Было: xQueueCreate(2, ... // Стало: резервируем очередь на 50 элементов (этого хватит на 250-500 мс задержки сетевого таска) if (NULL == (Streaming_Queue = xQueueCreate(50, sizeof(StreamingQueue_t)))) return false; Это исправление абсолютно бесплатно с точки зрения оперативной памяти (каждый элемент очереди — это просто индекс uint16_t, 50 элементов займут всего 100 байт RAM), но оно на порядки поднимет стабильность системы при сетевых сбоях. ну и так далее. Кое-что- явно мои ошибки после переделки старых файлов для нового прибора (еще не вылезли на тестировании, но обязательно добавили бы мне головной боли при отладке выявленных проблем). Кое-что из-за того, что он не имеет доступа к другим функциям (например как я обрабатываю таймауты)- приходилось дополнительно докидывать функции из других файлов. Quote Share this post Link to post Share on other sites More sharing options...
yes 25 June 26 Posted June 26 · Report post 18 hours ago, Ruslan1 said: Использую в основном Джемини. Его уровня понимания и анализа абсолютно хватает. И (обычно) советы адекватные, и предлагаемые им куски кода для замены. Но это всё работает с одним файлом. Можно ему и несколько загрузить, но это очень неудобно. советую попробовать Claude - по-моему лучше. также (удивительно для меня) deepseek гораздо лучше находит какие-то правильные решения по конфигурации периферии, практические решения каких-то железячных вопросов - может потому, что он не брезгует лазить по китайским форумам и т.п. а вероятность того, что такую проблему решал уже кто-то из ярда китайцев выше 🙂 Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 352 June 26 Posted June 26 · Report post Писец. Приехали. "Ищет по форумам... правильные решения...". Стоит три раза написать "Ты уверен?", как любой из Искуственных Идиотов переобувается в воздухе ровно на 180 градусов, и теперь правильное стало не правильным, а неправильное стало "код 10/10, можно в продакшн". Quote Share this post Link to post Share on other sites More sharing options...
jcxz 370 June 26 Posted June 26 · Report post 1 час назад, Ruslan1 сказал: Примеры: Честно говоря - не увидел ничего полезного. 34 минуты назад, Arlleex сказал: "Ищет по форумам... правильные решения...". Если - по нашему форуму в том числе, то ему точно не следует доверять! Если я на некоем форуме, задам вопрос, а потом, получив в ответ на него явную чушь, тем не менее - присвою ему статус "Solved". То боюсь что завтра эта чушь станет аксиомой для кучи народа, полагающегося на ИИ. Для каких-то main-stream тематик такой трюк конечно не сработает (так как база решений в инете велика), но для редких и специфичных вопросов, думаю - запросто сработает. 34 минуты назад, Arlleex сказал: Стоит три раза написать "Ты уверен?", как любой из Искуственных Идиотов 1) Можно тренировать свой мозг и умения, самостоятельно анализируя код. 2) Можно тренировать чужую ИИ-модель (параллельно теряя компетенцию). Каждый сам для себя решает - каким путём идти. PS: Как раз сегодня утром слышал новость в тему: https://3dnews.ru/1144130/ford-vernul-uvolennih-ingenerov-dlya-ispravleniya-oshibok-kotorie-nadelal-ii Quote Share this post Link to post Share on other sites More sharing options...
Ruslan1 38 June 26 Posted June 26 · Report post Мне кажется, тут многие путают "попросил ИИ написать код" и "попросил ИИ проанализировать мой код". Анализ кода ИИ - это просто ещё одно ревью (правило четырёх глаз), а не истина в последней инстанции. 19 минут назад, jcxz сказал: Честно говоря - не увидел ничего полезного. Ну, значит Вы переросли этот уровень и ИИ Вам не поможет (не нужен). Я ещё не дорос, так что он мне помогает. 19 минут назад, jcxz сказал: 1) Можно тренировать свой мозг и умения, самостоятельно анализируя код. 2) Можно тренировать чужую ИИ-модель (параллельно теряя компетенцию). Есть третий вариант: 3) можно попросить ИИ проанализировать то, что программист уже проанализировал. Параллельно прокачивая свою компетенцию. Это замечательно, если ИИ видит в моём коде не то, что я хотел написать (считает ошибкой). Это значит, что я либо неправильно написал, либо недостаточно (или некорректно) прокомментировал написанное. Quote Share this post Link to post Share on other sites More sharing options...
haker_fox 164 June 26 Posted June 26 · Report post Иногда прошу Google AI сгенерировать yaml-файлы стеки для Docker или небольшие фрагменты на Java Script (для nore-red). Затем, вставляю ему же его творчество и прошу найти ошибки. Парадокс в том, что он находит критические ошибки в своём творении. Теперь я пишу запрос таким образом: "Сгенерируй мне такой-то скрипт без критических ошибок". Это даёт более-менее адекватный результат. В принципе, иной раз это помогает увидеть что-то новое, посмотреть на проблему с иного ракурса т.к. ИИ -- поисковик. Только более гибкий, подстраивающийся под запрос. Quote Share this post Link to post Share on other sites More sharing options...
jcxz 370 June 26 Posted June 26 · Report post 23 минуты назад, Ruslan1 сказал: Мне кажется, тут и "попросил ИИ проанализировать мой код". Анализ кода ИИ - это просто ещё одно ревью (правило четырёх глаз), а не истина в последней инстанции. Я говорил именно о ревью с помощью ИИ. Тоже пробовал что-то подобное. В результате получаю кучу рекомендаций типа: "Вот здесь мне кажется, что наверное что-то не так". После рассмотрения этих рекомендаций, вижу что всё - мимо. Потому как по вызову скажем: Func(buf, sizeof(buf)); невозможно определить - требуется ли Func() размер 2-го аргумента в байтах или в количестве элементов. Также невозможно определить - блокирующее ли внутри Func() использование buf или не блокирующее. Для этого часто нужно проанализировать чуть ли не весь код программы. Чего ИИ не сможет сделать. А значит: практически вся эта куча рекомендаций - впустую тратит моё время. Которое я с большей порльзой потрачу на самостоятельную отладку и ревью. Если что и тренируется, то больше тренируются пальцы. В наборе сообщений при общении с ИИ. Имхо - все эти анализаторы заточены на начинающих. На их типичные ошибки. Точно так же как тех.поддержка производителей: чуть более сложный и специфический вопрос (чем тупое нечитание документации) и в ответ на твой вопрос = полная тишина. Либо шаблонные советы совсем мимо темы вопроса. Этот вывод - из личного опыта. 23 минуты назад, Ruslan1 сказал: Это замечательно, если ИИ видит в моём коде не то, что я хотел написать (считает ошибкой). Это значит, что я либо неправильно написал, либо недостаточно (или некорректно) прокомментировал написанное. Не знаю, может просто вы пишете больше комментов в коде, чем я. И ИИ ориентируется ещё и по вашим комментам. И потому советы даёт точнее. Я пишу мало комментов в коде. Есть такой грех, признаю. PS: 23 минуты назад, Ruslan1 сказал: многие путают "попросил ИИ написать код" Точно не путаю. Ибо с "написать код" у ИИ всё ещё гораздо хуже. Буквально на днях всё пришлось переписывать почти с 0 после такой ИИ-генерации. Хотел сэкономить время. Думал - задача распространённая, к тому-же - на распространённой платформе (винда, а не редкий МК), должен ИИ справиться. В результате - даже после общения и уточняющих запросов, ИИ не смог создать код даже просто компилирующийся без ошибок и варнингов. Не говоря уж о том, что ещё и не работоспособный. Польза была разве только что в том, что он навёл на работающую либу. Но рабочий код на ней тем не менее написать он не смог. Речь о ЧатГПТ. 23 минуты назад, haker_fox сказал: "Сгенерируй мне такой-то скрипт без критических ошибок". Задание звучит как "Сгенерируй код с некритическими ошибками". Quote Share this post Link to post Share on other sites More sharing options...
uriy 9 June 26 Posted June 26 · Report post Использую claude с платной подпиской. Загнал туда мануал на китайском языке на процессор ARM926 порядка 1000 страниц, даташиты на NAND флеш и SDRAM это еще порядка 100 страниц. Разбираю и модифицирую чужой проект. То как он объясняет код меня устраивает на 100%. Переписываюсь с ним на английском. Прошу найти что-то из китайского мануала и объяснить. Исходники закидываю файлами только те что сейчас ведем. В плане разработки временами советует полную чушь. Но чтобы разобраться вещь незаменимая. Например до этого я не работал с NAND, гораздо удобней его спросить то что не ясно чем что-то искать на других сайтах. 1 Quote Share this post Link to post Share on other sites More sharing options...
kpv 20 June 26 Posted June 26 · Report post Александр Лесь, «Шпаргалка», 1990 прошлое, настоящее и будущее ИИ (шпаргальщиков) в сети много где лежит, например здесь Quote Share this post Link to post Share on other sites More sharing options...
amaora 42 June 26 Posted June 26 · Report post 12 hours ago, Arlleex said: А можно увидеть результат такого анализа? Quote >>> Look into the code and analyse lse_qrupdate function implementation. Give me a detailed explanation of what this function does. ## Assistant (Plan · DeepSeek V4 Flash Free · 21.2s) _Thinking:_ The user wants a detailed explanation of what the `lse_qrupdate` function does. Let me synthesize the information from the task result into a clear, detailed explanation. ## `lse_qrupdate` — Detailed Analysis **Location:** `lse.c:22–228` (internal `static` function) ### Purpose `lse_qrupdate` is the **core computational kernel** of the LSE (Least Squares Estimation) library. It performs a **QR factorization update**: given an existing upper-triangular matrix `R` (stored as a cascade matrix `rm`), it incorporates a new row vector `xz` into `R` by applying **Givens rotations** to zero out the new row's elements column-by-column, producing the updated `R`. Mathematically, it computes the updated QR factorization of `[R; x^T]` without recomputing from scratch — an O(n²) operation vs O(n³) for a full QR. ### Two Algorithmic Paths Controlled by `LSE_FAST_GIVENS` (defined as `1` in `lse.h`): 1. **Standard Givens rotations** (`LSE_FAST_GIVENS == 0`): Uses `sqrt` + divide to compute the rotation coefficients. Simpler but more expensive. 2. **Fast Givens rotations** (`LSE_FAST_GIVENS != 0`, the default): Uses a **diagonal scaling matrix** `D` per cascade to avoid square roots entirely. Each `lse_upper_t` has a `d[]` array of scale factors. The algorithm maintains `R^T D R` implicitly, updating both `R` and `D` with cheaper operations. This is the more numerically efficient path. ### Parameters | Param | Role | |---|---| | `ls` | LSE solver state (threshold, cascade count, etc.) | | `rm` | Cascade matrix to update (has `len`, `rows`, `keep`, `lazy`, `m[]`, and optionally `d[]`) | | `xz` | Incoming row vector (read/write — used as workspace, destroyed) | | `d0` | (Fast Givens only) Scale factor for the incoming row | | `nz` | Number of leading zeros in the vector — allows skipping columns | ### Algorithm Walkthrough ``` Step 1: Determine active column count n = min(rm->rows, rm->keep) Step 2: If leading zeros (nz > 0), advance the matrix pointer past nz columns Step 3: For each column i from nz to n-1: - Load x0 = -xz, xi = m (diagonal) - If x0 == 0, skip (already zeroed for this column) - Compute Givens rotation (standard or fast) to zero xz - Apply rotation to remaining elements i..len-1 in both m[i..] and xz[i..] - Update diagonal scale d and d0 (fast Givens path) - Check that scale factors stay within LSE_DMAX bounds; rescale if they exceed it (prevents overflow) Step 4: If n < rm->rows (we still have rows left in this cascade): - If rm->lazy flag is set: recursively call lse_qrupdate on the next cascade (rm + 1), passing the retained row as the new vector - Copy remaining elements from xz into the current row of rm - Store d[n] = d0 (fast Givens) Step 5: Increment rm->keep Step 6: If keep >= threshold and there are >= 2 cascades: - If not the top cascade: mark as "lazy" (keep=0, lazy=1) — the row is retained but will be merged lazily - If it IS the top cascade: update the threshold value ``` ### Key Design Decisions 1. **Cascade architecture**: Rather than resizing a single matrix, LSE uses multiple cascade matrices (`rm[0..n_cascades-1]`) with geometrically growing capacities. When a cascade fills up (`keep >= threshold`), it's either: - Marked **lazy** — its last row stays in place and will be merged into the parent cascade later (during `lse_qrmerge` / `lse_qrfinal`). - Or kept, with the threshold increased (at the top cascade). This gives O(1) amortized insertion cost. 2. **Leading-zero skipping**: The `nz` parameter allows the function to skip already-zero columns, which is critical when processing ridge regression rows or when merging partially-sparse cascades. 3. **Fast Givens rescaling**: The `LSE_DMAX` check prevents the scale factors `d` from growing unbounded, which would cause loss of precision or overflow. When exceeded, the corresponding row(s) are uniformly rescaled. 4. **Branch prediction hints**: `likely/unlikely` macros give the compiler hints about which branches are taken most often (e.g., leading zeros are rare, threshold overflow is rare). ### Relationship to Other Functions ``` lse_insert (public API) └─ lse_qrupdate (insert row into top cascade) lse_ridge (public API) └─ lse_qrupdate (insert regularization rows) lse_merge (public API) └─ lse_qrupdate (insert rows from another solver) lse_qrmerge (internal) └─ lse_qrupdate × N (merge lazy cascades row by row) lse_qrfinal (internal) └─ lse_qrmerge (merge all cascades into one) lse_qrstep (internal, used by lse_esv) └─ lse_qrupdate (transpose lower→upper for SVD estimation) ``` ### Memory Layout of `lse_upper_t` The matrix `m[]` stores an upper-triangular matrix in **packed column-major** (or similar dense-triangular) format. The pointer arithmetic in the function: - `m += nz * rm->len - nz * (nz - 1) / 2` — advances past `nz` columns - `m += -i` — backs up to the start of the current column - `m += rm->len` — advances to the next column This is consistent with a packed upper-triangular storage where each column has decreasing length. Quote Share this post Link to post Share on other sites More sharing options...
tonyk_av 79 June 27 Posted June 27 · Report post 21 hours ago, jcxz said: Ибо с "написать код" у ИИ всё ещё гораздо хуже. Не согласен. Тут всё очень сильно зависит от темы и правильности постановки вопроса. Попробовал ИИ для вывода нужных мне формул- он справился. Да, не сразу, да, после указания ему на его ошибки, но справился. Если бы я не знал, как должен выглядеть результат, то тупой вопрос "выведи мне формулу..." дал бы такой же тупой результат. Но я знал, поэтому в итоге получил исходники на С и графики для разных условий использования алгоритма, подтверждающие правильность полученного результата. Математикой по этой теме в последние годы мало занимался, поэтому с ИИ я решил задачу быстрее, чем выводя эти уравнения в Maple. По моим наблюдениям, ИИ хорошо справляется с задачами, имеющими более-менее строгую математическую постановку и требующими учёта большого числа факторов. Ну и необходимо правильно задавать вопросы и правильно указывать ему на его ошибки. Quote Share this post Link to post Share on other sites More sharing options...