FreePascal для учёных и инженеров |
06.05.2019 Вадим Исаев |
Краткий обзор математических возможностей FreePascal, как с помощью стандартных средств FCL, так и с помощью внешних библиотек.
На сегодняшний день моделирование тех или иных процессов уверенно переселилось из области натурных экспериментов в область компьютерных вычислений. И действительно, вместо того, чтобы испортить кучу дорогостоящей техники и материалов (если у нас ничего не получится) лучше заранее знать об этом. И в этом нам помогает многочисленный и разветвлённый математический аппарат с помощью которого пусть и не просчитаешь всё на свете, но можно хотя бы спрогнозировать, что получится из тех или иных умственных выкрутасов.
Не знаю как вы, но я к вопросам программирования отношусь чисто потребительски, т.е. предпочитаю пользоваться готовыми решениями, а не выдумывать что-то самому. Ну правда, зачем расписывать функцию вычисления синуса, мучительно вспоминая, каким образом она высчитывается, если есть уже готовая в модуле "Math"... В принципе, любой язык программирования предоставляет достаточные средства для элементарных математических вычислений. Проблемы начинаются, когда мы хотим решить задачу среднего и высокого уровня. Как пример, для среднего уровня можно привести решение систем линейных/нелинейных уравнений (СЛАУ\СНАУ) или обыкновенных дифференциальных уравнений (ОДУ), на которых строится уже высокий уровень - решение конкретной физической или математической проблемы. Из примеров задач высокого уровня - моделирование старта ракеты, которое строится на решении системы ОДУ или решение задач оптимизации, которое строится на СЛАУ\СНАУ.
Может показаться, что FreePascal безнадёжно уступает таким мастодонтам численных математических методов, как MATLAB или его бесплатным аналогам SCILAB и GNU OCTAVE. Однако при ближайшем рассмотрении это оказывается совсем не так. Хотя по насыщенности математическими функциями FreePascal и уступает MATLAB'у, но это касается лишь функций высшего уровня. На среднем же уровне у FreePascal есть практически всё необходимое. Даже в стандартном составе FCL есть как отдельные среднеуровневые математические функции, так и небольшая математическая библиотека. И если этого не хватит, то в сети можно найти несколько отличных математических библиотек, которые написаны с использованием паскалевского кода.
Здесь комплексное число представлено вполне в традиционной форме:
complex_single = record re: Real; im: Real; end;
Тип Real в зависимости от платформы будет выдаваться:
Определены основные арифметические операции: :=, +, -, *, /, **. Операция := присваивает только реальную часть числа. Если нужно присваивание обеих частей числа, то нужно воспользоваться функцией init(). Есть операция сравнения. Эти операции можно проводить как с двумя комплексными числами, так и с одним комплексным и одним числом типа Real.
Определён основной набор элементарных математических функций:
Ещё один модуль для работы с комплексными числами есть в библиотеке NumLib, однако там организация чисел принципиально другая - они представлены в виде объектов TP 5.5 (Object).
Этот модуль является интерфейсом над сишной библиотекой GMP [2]. В Wiki Freepascal есть небольшая статейка по этому модулю, но она настолько краткая, что вряд ли даст понятие как с этим модулем работать. Это, скорее, просто новость, что "у нас теперь есть и это".
Если коротко, то стандартные типы данных имеют ограничение как на величину обрабатываемых чисел, так и (а это уже намного хуже) на длину мантиссы. Последнее влияет на точность вычислений. Библиотека GMP в принципе позволяет эту проблему решить за счёт самостоятельного определения программистом необходимой ему длины мантиссы. Теоретически её длина ограничивается только имеющейся в компьютере оперативной памятью, т.к. память под число выделяется динамически.
Библиотека работает с тремя типами данных:
Все типы являются составными, типа record. В них отдельными полями лежит служебная информация о числе и динамическое хранилище под само число. Перед использованием таких чисел их надо инициализировать, чтобы для хранилища был выделен какой-нибудь объём памяти. Что интересно, для целых чисел (и, естественно, обыкновенных дробей) память при нехватке перевыделяется. Для типа десятичной дроби такого уже не делается. Сколько выделено, столько и остаётся. Но если памяти не хватает, то её можно перевыделить вручную.
Математика для этого модуля определена скудновато, только самое необходимое - арифметические операции, некоторые дополнительные функции, генерация псевдослучайных чисел. Т.е. до стандартного паскалевского модуля MATH этот модуль сильно не дотягивает.
Все арифметические операции для этих типов чисел представлены в виде функций. При этом программирование становится довольно нудным, однако в Паскале, в отличие от Си, можно запросто определить арифметические операции для любых нестандартных типов данных. И таким образом написание программ с длинными числами значительно упростится.
Программа будет выглядеть примерно так:
program test_gmp; Uses gmp; Var a, b, c: mpf_t; Begin // Определяем размер хранилища для числа по умолчанию mpf_set_default_prec(128); // Инициализация переменных // (выделение памяти для хралища) mpf_init(a); mpf_init(b); mpf_init(c); // Присвоение числа из строки mpf_set_str(a, '1111111111.1111111111', 10); mpf_set_str(b, '2222222222.2222222222', 10); // Сложение mpf_add(c, a, b); // Вывод результата на экран mp_printf('Сумма чисел: %26.10Ff'#10, @c); //Вычитание mpf_sub(c, b, a); // Вывод результата на экран mp_printf('Разность чисел: %26.10Ff'#10, @c); // очистка переменных // (забираем у них память) mpf_clear(a); mpf_clear(b); mpf_clear(c); End.
Пояснения к коду:
Количество_битов = ceil(количество_разрядов_мантиссы / log10(2))
%nn.mmFf
Здесь:
Более подробно о работе с длинными числами с помощью этой библиотеки можно почитать на нашем сайте [4].
БПФ обычно все связывают с цифровым звуком. Однако сам маэстро Фурье изобрёл эту штуку для расчётов теплопроводности, так что есть мнение, что БПФ можно использовать где угодно. Естественно во времена Фурье ничего "быстрого" не существовало. Видимо тогда в уме и на бумажке эту функцию считали намного быстрее, чем сегодня на компьютере.
Модуль fftw_s является заголовочным файлом для библиотеки FFTW [5]. Правда в нём представлена не вся библиотека, а только самая минимальная часть:
Типы данных комплексные. Поля комплексного типа представлены типом Single. В принципе, нет никаких проблем поменять Single на Double. Для этого придётся в модуле fftw_s нужно поменять имя библиотеки с fftw3f на fftw3l и переопределить там же тип для ячейки массива.
В модуле ячейка объявлена таким образом:
complex_single = record re, im: Single; end;
Вычисление БПФ полностью представлена в прилагаемом в комплекте к модулю example.pas. Единственное что там плохо - нет ни одного комментария. Приведу его текст здесь со своими комментариями. Но сначала рисунок для большей понятности. На рис. 1 представлено преобразование аналогового сигнала в цифровую форму.
На рисунке вы можете заметить, что уровень квантования проскакивает мимо реальной амплитуды сигнала. Это всего-лишь трёхбитовый пример, а в реальных устройствах количество бит не менее 8-ми. В высококачественных может быть и 16 и 24 бита. Т.е. уровень сигнала будет равен или максимально приближен к аналоговому оригиналу.
Всё время (T) периода сигнала происходит измерение его амплитуды. На рисунке эти измерения представлены вертикальными линиями перпендикулярными оси t. Для БПФ нас будет интересовать количество и, естественно, уровень сигнала этих измерений. Код примера:
program example; Uses fftw_s; Const s=128; // Количество измерений сигнала Var i,o: Pcomplex_single; // Cигнал и его изображение после БПФ // (одномерные массивы) p: fftw_plan_single; // План вычисления БПФ a: Cardinal; Begin // Выделение памяти для массивов значений fftw_getmem(i, s*SizeOf(complex_single)); fftw_getmem(o, s*SizeOf(complex_single)); // Вычисление плана БПФ // Параметры: // s - количество измерений; // i - сигнал; // o - его изображение; // fftw_forward - прямое преобразование; // [fftw_estimate] - набор флагов. p:=fftw_plan_dft_1d(s, i, o, fftw_forward, [fftw_estimate]); // Значения амплитуды сигнала For a:=0 To s-1 Do Begin i[a].re:=(Single(a)-64); i[a].im:=0; End; WriteLn('Сигнал:'); For a:=0 To s-1 Do WriteLn('(',i[a].re:8:4,',',i[a].im:8:4,')'); // Выполнение БПФ fftw_execute(p); WriteLn('Изображение сигнала после БПФ:'); For a:=0 To s-1 Do WriteLn('(',o[a].re:8:4,',',o[a].im:8:4,')'); // Удаление плана fftw_destroy_plan(p); // освобождение памяти fftw_freemem(i); fftw_freemem(o); End.
Если Вы не хотите пользоваться сишной библиотекой, то для БПФ можно использовать код из статьи на нашем сайте [8].
Это большой, хотя и неполный набор математических функций среднего уровня. Первоначально код функций писался на языке Алгол-60 в начале 60-ых годов прошлого века в нидерландском техническом университете города Эйндховена. Впоследствии код был переведён на Паскаль, т.к. эти языки очень похожи. Для функций есть неплохая документация [9], правда она неполная. К сожалению примеров довольно мало.
Список модулей и функции, которые они выполняют:
Не хватает одной существенной области - нет функций оптимизации.
Функции используют собственные типы данных:
Несколько запутывает ситуацию то, что в заголовках всех функций эти типы используются не по прямому, так сказать, назначению, а почему-то как указатель на массив, что не сильно соответствует паскалевскому стилю работы с массивами. Точнее, здесь это первый элемент массива. Видимо в начале 60-ых для Апгола это было самое правильное решение.
Таким образом, в большинстве случаев встречая функцию типа:
Умножение(a, b: ArbFloat; n: ArbInt): ArbFloat;;
Речь идёт об умножении матрицы на матрицу или матрицы на вектор, или вектора на вектор, количество ячеек которых равно n. Здесь a и b - это первый элемент массива или вектора и сильно напоминает ссылку. Впрочем, определить матрица задана или вектор можно по количеству параметров, которые задают размер и помещаются после ссылки на матрицу или вектор. Если параметр один - это будет вектор, если два - это матрица. Таким образом в вышеприведённой функции речь идёт о векторах. В реализации функции будет что-то типа такого:
Умножение(a, b: ArbFloat; n: ArbInt): ArbFloat; Const highestelement=20000; Type TVector = array[1..highestelement] of ArbFloat; Var v1, v2: ^TVector; i: ArbInt; Begin v1:=@a; v2:=@b; Умножение:=0; For i:=1 To n Do Умножение := Умножение+v1^[i]*v2^[i] End;
Здесь необходимо небольшое пояснение. Внутри функций библиотеки, массивы представлены именно так - с явно заданным количеством ячеек. Это может показаться странным, но не стоит забывать, что функции писались довольно давно, когда динамических массивов в Паскале ещё не было. И, как минимум, с 2000 года код не изменялся. Поэтому если будете работать с этой библиотекой, помните про размер массивов.
Таким образом, программа, которая использует подобную функцию будет выглядеть примерно так:
program TestNumLib; Uses numlib; Const n = 3; Var a: array[1..n] of ArbFloat; b: array[1..n] of ArbFloat; AlgProd: ArbFloat; Begin a[1] := 1.0; a[2] := 2.0; a[3] := 3.0; b[1] := 4.0; b[2] := 5.0; b[3] := 6.0; AlgProd := Умножение(a[1], b[1], n); WriteLn('Алгебраическое умножение векторов a и b:'); WriteLn(AlgProd); End.
В NumLib функция умножения векторов называется omvinp().
Исторически, это первая математическая библиотека среднего уровня, которая появилась в 1986 году для Turbo Pascal 3 (архив [21]). Использовать её можно, но с некоторой осторожностью, обязательно посмотрев исходники и, если нужно, подредактировать их. По крайней мере из исходников обязательно нужно удалить зависимости от модулей Dos и Crt. Они там точно не нужны.
По функционалу эта библиотека немного превосходит NumLib и, что особенно приятно, использует традиционные для Паскаля (и для математики) массивы, которые начинаются с 1. Динамических массивов так же нет и их размер обычно ограничивается какой-либо константой. Это нужно иметь в виду. Для чисел с плавающей точкой используется тип Float, который объявлен как Double. Это позволяет надеяться на более точные результаты. Есть хорошая документация в виде книжки. Лицензия на эту библиотеку для сегодняшнего времени неясна, но в силу своей устарелости вряд ли правообладателю придёт в голову судиться за незаконное использование.
Функционал по главам книги:
К последней главе следует подходить с особой осторожностью, поскольку ни в Windows, ни в Unix досовские рисовалки вряд ли будут работать. Ещё пуще внимания следует уделить каталогам ASM\OBJ, поскольку там содержаться подпрограммы работы со стеком. В каталоге ASM - исходный код этих программ. В их заголовках написано, где они используются. Я бы советовал пересмотреть коды упоминаемых в заголовках программ и исключить ассемблерный код. Если же вы непременно захотите его использовать, то лучше всего будет эти asm'ки переписать под 32- и 64-битный ассемблер. Впрочем, я не большой специалист по ассемблеру, возможно исходный код и так будет работать. Однако имейте в виду.
Таким образом использование этой библиотеки исключительно на ваше усмотрение. В любом случае, прежде чем брать оттуда ту или иную функцию в рабочий проект, следует её тщательно проверить на тестовых данных. Не забывайте, что судя по дате выпуска эта библиотека разрабатывалась для TurboPascal 3.0, а с тех пор много воды утекло.
Эта библиотека [10] родилась довольно давно, как набор математических функций для языка Фортран. Когда язык Pascal и, в частности, Object Pascal, набрал популярность, была сделана версия библиотеки и для него с помощью программного конвертора FORPAS [11]. Несколько печалит то, что фортрановские алгоримы были преобразованы "в лоб", поэтому в программы перекочевали и жившие тогда в фортраньем коде GOTO.
Использование кода из библиотеки для некоммерческих целей свободное.
Функционал:
В этой библиотеки самое привлекательное - описание всех функций на русском языке. Каждая функция на отдельной страничке. Описание подробное, но без излишнего уклона в математику. Для каждой функции есть пример и тестовые данные с правильным ответом. Это на тот случай, если вы соберётесь функцию переделывать. А переделывать придётся, если вы студент и захотите предъявить её преподавателю как реализацию своего замысла. Потому что придётся избавляться от GOTO, иначе никто не поверит, что это ваше.
Ещё одно достоинство - в отличие от предыдущей версии эта библиотека была рассчитана на работу вместе с Delphi, следовательно код не является старым и его работоспособность очень близка к 100%. К "старым библиотекам" я её отнёс исключительно потому, что паскалевский код транслировался со старого Фортрана. К сожалению "осовремениванием" библиотеки никто не занимается, поэтому исходники лучше всего использовать творчески, т.е. делать на их основе свои функции.
В том же 1986 году, что и "Turbo Pascal Numerical Methods Toolbox", группой преподавателей Кембриджского университета была выпущена отличная книга по численным методам "Numerical Recipes: The Art of Scientific Computing" [12] с иллюстрацией этих методов кодом на языке Fortran, естественно старом. Поскольку языки Fortran и Pascal довольно похожи, особенно в плане использования массивов, примерно к 1990 году был выпущен репринт этой книги с иллюстрациями кодом на языке Pascal. Название "Numerical Recipes in Pascal: The Art of Scientific Computing". К сожалению, для текущего (третьего) издания, исходный код доступен только за плату ($70), однако в сети доступен код первого издания (архив [22]) в котором написано, что
** Do I really get this whole library for FREE? ** Yes, providing that you follow these simple rules: (1) You must read and accept the disclaimer of warranty at the end of this document. (2) You must not expect any user support from Numerical Recipes Software, Cambridge University Press, or the authors of the Numerical Recipes books. (3) You must not copy or redistribute any of the programs or procedures for commercial purposes. You CAN make copies of the programs for your friends and colleagues, providing that you include this file (especially its copyright notice and disclaimer of warranty) with any copy that you make.
Таким образом для некоммерческого применения этот код свободно можно использовать а так же копировать в любое нужное вам место. К сожалению самой книжки в открытом доступе я не нашёл.
Поскольку паскалевский код переведён со старого Фортрана, в коде присутствует довольно много GOTO. Работе программ это нисколько не мешает, однако если вы студент и понесёте этот код своему преподавателю, пытаясь выдать за творение собственного гениального разума, то разоблачат вас практически сразу же. Поэтому стоит потратить некоторое время на изменение кода, чтобы убрать оттуда те самые пресловутые GOTO. Это будет крайне полезно для вас, как для программиста.
В библиотеке содержится около 200 функций, с примерами к каждой функции. Примеры имеют расширение .DEM. Каждая функция представлена в отдельном файле, поэтому её можно либо скопипастить в свой код, либо подключить с помощью директивы {$I ФайлСФункцией.PAS }. В каждом файле-функции, в заголовке содержится её краткое описание. Комментарии в коде отсутствуют, поэтому желательно скачать из сети книжку, чтобы в трудных и непонятных случаях ориентироваться по ней.
Динамические массивы отсутствуют, поэтому код потребует адаптации к вашей программе в плане размеров массивов. Типы данных представлены типом Real, поэтому в 64-ёхбитной системе их можно не менять, а вот в 32-ух желательно или поменять на Double, либо переобъявить тип Real как Double. Это благотворно повлияет на точность результата.
Функционал:
Как и в случае с "Turbo Pascal Numerical Methods Toolbox" к коду следует подходить осторожно. Код не привязывался к конкретному компилятору языка, а скорее всего рассчитывался на существовавший тогда стандарт. Об этом говорит присутствующие во всех демонстрашках параметры главной программы (input, outpu). Это можно спокойно стереть или не обращать внимания. Поскольку документация к коду отсутствует, только-только начинающим программистам использовать его будет трудновато.
Ещё одна книга, аналогичная по тематике предыдущей, которую написал профессор Калифорнийского университета Джон Мэтьюз "Numerical methods for Mathematics, Science and Engineering". Код примеров [23] более современный, т.к. базируется на втором издании книги, которая вышла в 1992 году. По крайней мере, GOTO в коде совсем чуть-чуть, хотя код, так же как и в предыдущем случае, переделывался из FORTRAN. Исходный код библиотеки так же является свободным:
This free software is complements of the author. It is permissible to copy this software for educational purposes, provided that it is used with the textbook. The software may not be sold for profit and may only be sold in such a way that the cost of reproduction are recovered.
В интернете эту книгу (а так же и код) оценивают как более продвинутую, поскольку автор не был поставлен в условия экономии места на странице, в отличие от предыдущих авторов. Код организован по другому - все функции встроены в файлы примеров, поэтому код примеров имеет законченный вид. Этот момент очень удобен для студентов. Заголовки файлов содержат описание, что именно рассчитывается. К сожалению комментариев в коде исчезающе малое количество. В большинстве случаев программы интерактивны, т.е. требуют после запуска выбора какого-то пункта для исполнения и ввода необходимых параметров. Динамические массивы не применяются.
Функционал:
Эта библиотека прекрасно подходит для обучения численным методам. Переделки будут минимальны. Во многих случаях достаточно будет просто русифицировать все строки, которые выводит программа на экран. Для научного применения код нужно тщательно просматривать и переделывать под себя, под свою задачу. Книгу в свободном доступе я не нашёл, поэтому совсем начинающим программистам так же будет трудновато её использовать, как и предыдущую библиотеку.
Это несколько менее фундаментальная книга по численным методам, чем две предыдущих, о чём свидетельствует её название. Тем не менее так же является весьма интересной в плане решения уравнений линейной алгебры и методов оптимизации. Описание там весьма подробное и понятное.
В отличие от предыдущей книги, коды примеров изначально создавались именно для языка Pascal и компилятора TurboPascal. В первой главе написано, что код рассчитан на тогдашние персональные компьютеры, которые имели весьма ограниченные ресурсы. Архив с кодом [24].
Названия файлов в архиве строятся по такому принципу:
Функционал:
Прекрасно подходит для изучения численных методов линейной алгебры и методов оптимизации. Рекомендуется в том числе и начинающим. Однако к коду необходимо подходить осторожно из-за его привязки к очень древнему TurboPascal. Необходима тщательная проверка тестовыми данными.
На самом деле это одна и та же библиотека, написанная когда-то заведующим фармакологической лабораторией медицинского факультета университета Лимож (Франция), доктором Жаном Дебо. К сожалению, примерно с 2012 года эту библиотеку больше никто не разрабатывает, однако то что есть работает вполне прилично, в том числе и в FreePascal. Кстати, возможность работы в FreePascal специально упомянуто автором в документации. которая идёт в комплекте. В интернете довольно легко найти примеры, которые используют эту библиотеку.
Первая версия разрабатывалась для Turbo Pascal (отсюда и одно из названий - tpmath). В дальнейшем библиотека переделывалась и дорабатывалась под Delphi (dmath). Последнее название (lmath [13]) - это просто распределение отдельных модулей по каталогам в зависимости от того, какую именно проблему решает тот или иной модуль. Как раз последнюю исследовать более удобно, чтобы не отвлекаться на неинтересные, в данный момент, направления.
Математика в библиотеке строится на типа Float, который, в свою очередь, определяется заданием макроса для компилятора:
Как и в многих других библиотеках, здесь имеются почти все популярные константы для того, чтобы сократить время вычислений. Тип Complex имеет традиционное строение - в виде Record. Дополнительно в типах заданы различные виды векторов и матриц на основе безразмерного массива.
В архиве LMath [25] каталоги с модулями имеют такие назначения:
Подходит для обучения, т.к. есть исходники и документация к функциям. Библиотека давно не обновляется и, похоже, автором заброшена. Для учёного применения использовать осторожно, т.к. есть некоторые функции, которые при определённых условиях вылетают. Исследование кода некоторых из них показало, что это не ошибки как таковые, а скорее лишний функционал, который автору может быть и был нужен, но при некоторых входных условиях он может давать вылет программы.
Несмотря на своё название - Alglib - это не сборник алгоритмов. Начинался проект [14] как сборник программ, которые решают ту или иную конкретную математическую проблему. Начинали это дело русские программисты, но постепенно проект вышел на международный уровень. На сегодняшний день это большая откомпилированная библиотека разнообразнейших функций, для которой имеются интерфейсные модули для нескольких языков программирования, в том числе и для Delphi. Это запросто позволяет подключать библиотеку к программам на FreePascal. В архиве [15] содержится библиотеки для Windows и Linux, 32-ух и 64-ёх разрядные реализации. Для Linux только 64-ёх разрядная. Существуют две версии:
Свободная версия отличается от коммерческой несколько меньшим уровнем оптимизации и отсутствием возможности работать в многопоточном или многопроцессном режиме. Функционал по алгоритмам у обеих версий один и тот же. В коммерческой версии присутствует техподдержка.
Функционал:
В архиве есть краткий справочник по функциям применительно к их работе в Delphi. Самая функционально насыщеная и быстроработающая в FreePascal библиотека. Не подходит для обучения, т.к. нет исходников. Правда в сети можно найти старые исходники, но они сильно давнишние. Больше подходит для учёного применения, т.к. работает быстро. Библиотека регулярно обновляется.
Это не название библиотеки, а человек, который разработал и собрал несколько очень интересных математических комплектов [17]. Этот проект довольно давнишний и в некоторых модулях написано, что они могут работать даже в BP\TP 7. В Delphi - само собой разумеется, так что и в FreePascal будут работать, поскольку в них не предполагается использование каких-либо ОС-зависимых компонентов.
Самое интересное - математические сборки:
Второе, не менее интересное направление - CRC\Hash\Crypto. По CRC, в отличие от FCL'евского модуля, можно вычислять CRC16\24\32\64. CRC128 нет, но возможно оно и не очень востребовано. По крайней мере Википедия пишет, что вместо него используют криптографические хэш-функции. Большое количество хэш-функций и разных алгоритмов шифрования. Российских стандартов к сожалению нет.
В архивах приложены текстовые файлы со списком имеющихся функций и кратким пояснением, что эта функция делает. В исходных кодах так же заголовок каждой функции прокомментирован описанием. Подходит как для обучения, так и для учёного применения. Функционал скорее можно назвать низкоуровневым, чем среднеуровневым. Однако по сравнению со стандартным модулем "Math" низкоуровневых функций прямо-таки завались. Это просто сказка, а не библиотека. На все случаи жизни.
Библиотека регулярно обновляется.
Откровенно говоря, именно в таком ключе вопрос ставить не стоит. Выбор всегда обусловлен поставленной задачей. Поскольку все библиотеки (кроме одной) представлены в виде исходников, я бы покопался в них всех и понадёргал бы функций которые мне понравились и которые, самое важное, мне понятны. В табл. 1 кратко представлены общие впечатления от библиотек по двум, так сказать, номинациям:
В таблице сравниваются только те библиотеки, которые имеют более-менее разнообразный функционал, т.е. универсальные библиотеки, а не те, которые направлены на решение одной или пары-тройки задач.
Таблица 1. Краткое сравнение библиотек
Библиотека | Для учебных целей | Для прочего |
---|---|---|
Numlib | Не рекомендую из-за нетрадиционного использования массивов в заголовках функций. Это может вызвать непонятки не только у студента, но и у преподавателя, который проверяет код. Есть демонстрашки, но без комментариев и подписей, какая демо что демонстрирует. | На ваше усмотрение. Если вас не смущает ограничение на кол-во ячеек в массивах, используемых внутри функций, то проблем с их применением не будет. Документация неполная. |
Turbo Pascal Numerical Methods Toolbox | На ваше усмотрение. Если собираетесь использовать, предварительно коды необходимо внимательно изучить, наверняка там есть что поправить. Есть книга. | На ваше усмотрение. |
Numerical Recipes | Рекомендую. Но с обязательным предварительным изучением кода с целью удаления оттуда GOTO. Книга есть, но бесплатно найти её трудно. | Можно использовать. Только предварительно нужно переделать код для возможности использования безразмерных массивов, как это практикуется в современном Pascal. |
Numerical methods | Рекомендую. Переделка кода требуется редко, но изучить его обязательно. В нём много строк на иностранном языке, желательно их сделать на русском. Книга есть, но бесплатно найти её трудно. | Можно использовать. Только предварительно нужно переделать код для возможности использования безразмерных массивов, как это практикуется в современном Pascal. |
Compact numerical methods | Пожалуй наиболее интересная библиотека, т.к. код демонстрашек в ней подробно прокомментирован. Прилагаемая книжка достойна пристального внимания. | Если вам достаточно линейной алгебры и оптимизации, то хороший выбор. Код, как и в предыдущих библиотеках, лучше всего переделать под использование безразмерных массивов, где это необходимо. |
lmath | Рекомендую. Есть и документация и исходники. Писал преподаватель для студентов. Документация хорошая, не перегруженная математикой, понятная. Есть демонстрашки. Все с подписями кто что делает. В кодах встречаются комментарии, но маловато. | Вполне можно использовать. Поиск нужной функции лёгок, т.к. есть хорошая, разбитая по разделам, документация в которой кратко и понятно описаны способы решения задачи, входные и выходные параметры. Исходник можно посмотреть и, если нужно, подправить. |
Alglib | Не рекомендую из-за отсутствия исходников. На старых версиях сайта (которые при известном старании пока ещё можно найти в интернете) исходники были. Документация простая и понятная. Демонстрашек нет. | Вполне можно использовать, если только вас не смутит отсутствие
информации о том, как именно решается та или иная задача.
В документации, разбитой на разделы, есть описание заголовков функций для Delphi. В них:
|
Wolfgang Ehrhardt | Можно использовать. В модулях есть подписи, для чего они служат. У каждой функции есть коммент, для чего функция предназначена. Кроме того, у всех архивов есть текстовые файлы со списком функций и кратким пояснением, для чего функция нужна. Демонстрашек нет, но есть тестовые файлы, которые могут послужить демонстрашками. | Можно использовать. Единственный недостаток - нет описаний для параметров функций. Документация очень краткая и уступает предыдущим библиотекам. |
Теперь поговорим о недостатках. А как же без них?
Самый наиглавнейший недостаток - не очень высокая, мягко говоря, скорость обработки больших массивов данных. Правда тут есть один нюанс. Для многомерных массивов скорость сильно зависит от порядка обработки размерностей. Это легко проверяется. Тем не менее, Pascal никогда не позиционировлся как компилятор для быстрых программ. Небольшая табличка с результатами тестов трёх разных библиотек (см. табл. 2) показывает скорость работы при решении СЛАУ (у нас всё как у взрослых - ТОП500 суперкомпьютеров тоже меряются "у кого больше" исключительно на СЛАУ). Сразу предупреждаю, сравнивать паскалевские программы с фортрановскими не стоит в принципе, т.к. Фортран до сих пор по скорости остаётся впереди планеты всей. Современный Си если ему и уступает, но не так уж и много, поэтому его из соревнований тоже исключаем. Интереснее всего будет померятся со специализированными математическими программами, типа MATLAB. Правда и здесь мы всё-равно будем мерятся либо с сишными, либо с фортрановскими двоичными библиотеками. Так что приготовьтесь к тому, результат будет немного печален.
MATLAB'а у меня нет и тратить деньги на его покупку что-то неохото. Поэтому меряться будем с аналогом MATLAB'а - GNU Octave и с набирающим популярность математическим пакетом Julia. Размерность матрицы для СЛАУ не сильно большая, 2000 х 2000, чтобы не уснуть в ожидании ответа.
Таблица 2. Скорость вычисления СЛАУ с помощью разных библиотек
Библиотека | Откомпилировано без оптимизации | Откомпилировано с ключом -O2 |
---|---|---|
NumLib, сек. | 20,54 | 15,27 |
Numerical methods, сек. | 23,30 | 18,07 |
alglib, сек. | 3,40 | 3,30 |
LMath, сек. | 79,15 | 39,28 |
GNU Octave, сек. | 3,12 | - |
Julia, сек. | 0,59 | - |
Вот так и выясняется, что в прошлом веке умели писать более быстрые программы, чем в веке нынешнем.
Большого смысла проверять все библиотеки на скорость нет. Я думаю этот пример показателен. Как видно, даже ключ оптимизации при компиляции не сильно помогает приблизится по скорости к математическим пакетам.
Хорошая скорость alglib понятна. В ней паскалевский код всего лишь интерфейс для уже готовой скомпилированной библиотеки. В многопоточном варианте, наверняка скорость будет ещё лучше.
Итак, если вам нужна скорость работы с большим оьъёмом данных, то альтернативы библиотеке alglib нет. Во всех остальных случаях, если объёмы данных небольшие, то принципиальной разницы в использовании той или иной библиотеки не будет.
Второй недостаток касается старых библиотек. В старом Паскале отсутствовала возможность применения динамических (безразмерных) массивов. Естественно их можно было делать как в Си, т.е. на основе указателей. Но в этом случае лучше перейти на язык Си, чтобы не путаться.
При попытке создать достаточно большой статический массив, когда используются старые библиотеки, мы с большой долей вероятности столкнёмся с ошибкой переполнения стека. При переделке функции\программы на динамический массив следует иметь в виду:
В качестве примера переделки статического массива в динамический можно использовать тест из архива [26] для библиотеки "Numerical methods".
Если вам нужно решить какую-нибудь махонькую задачку типа СЛАУ, вовсе не обязательно подключать какой-либо громоздкий сторонний модуль или вставлять сторонний громоздкий кусок кода (а для СЛАУ он будет громоздким, не сомневайтесь). Можно, воспользовавшись идеей Alglib, взять какую-нибудь внешнюю двоичную математическую библиотеку, подготовить заголовок функции и, оп-ля, не парясь получть махонький код. Увы, с математикой есть большая опасность по незнанию её истории нарваться на изрядный казус.
Дело в том, что как раз в математике до сих бешеной популярностью пользуются фортрановские библиотеки, например BLAS или LAPACK. В интернете можно встретить парочку статеек о том, что Фортран хранит многомерные массивы по другому, не так как в Паскале или Си. Это так и есть: сначала подряд идут ячейки первой колонки, потом второй и так далее. См. рис. 2.
Однако если вы подумаете, что простым транспонированием, к примеру, матрицы можно легко решить проблему, как об этом пишут авторы статей, то вы ошиблись. После транспонирования правильный результат всё равно получить не удастся, хотя функция по внешним признакам отработает правильно, без ошибок. Ошибка выскочит уже при завершении программы, в том месте, где идёт работа оператора "End.".
Покапушки в исходном коде LAPACK выявило, что это проблема не только Паскаля, но и Си. В сишных заголовках к LAPACK я и выяснил метод исправления этой проблемы. В фортраньи функции\подпрограммы нужно передавать одномерный массив, составив его из многомерного, т.е. начало второй колонки добавляется к хвосту первой и так далее. Должно получиться как на рис.3.
Вторая особенность фортрановских функций\подпрограмм - параметры в них передаются исключительно в виде ссылки. Это делает Фортран самым быстрым вычислителем, по сравнению с другими языками-компиляторами. Вряд ли это стоит считать проблемой.
Таким образом, перед использованием функций из фортраньих библиотек и если есть необходимость использовать более чем одномерные массивы (как пример - матрицы) нужно выполнить такие шаги:
В архиве с примерами [26] есть файл "test_externlib.pas", который эти шаги демонстрирует.
Теперь ещё один очень важный момент. Многие могут подумать "ну, вот, сколько возни из-за одного простого действия. А стоит ли оно того?". Безусловно стоит. Смотрите в табл. 3.
Таблица 3. Скорость вычисления СЛАУ с помощью фортрановской библиотеки LAPACK
Библиотека | Откомпилировано без оптимизации |
---|---|
LAPACK+BLAS, сек. | 3,07 |
OpenBLAS, сек. | 0,86 |
Как видно, скорость вычисления выше, чем у Alglib, которая использует сишную библиотеку. В варианте LAPACK+BLAS скорость сравнима с GNU Octave, а в варианте с OpenBLAS (это LAPACK+BLAS в одном флаконе) сравнима даже с Julia. Таким образом, в случае нужды в скорости вычислений, такой вариант должен стоять на самом первом месте.
Приведённый здесь список математических библиотек ни в коем случае не является исчерпывающим. В интернете для Pascal можно найти очень много. В своё время для Turbo Pascal было написано довольно много кода, в том числе как специализированных функций для одной задачи, так и многофункциональных библиотек. То что они для TP пускай вас не смущает. Обычно они рабочие, но предварительно просмотреть их нужно и, возможно, кое-что подправить, т.к. люди их писали под свои задачи, а вовсе не под ваши. В качестве примера можно привести математические подпрограммы из [18].
Ещё более интересна может быть книга [19], поскольку все примеры там очень подробно и понятно объяснены на русском языке. Математики самый минимум, без нудной теории. Описание даётся только в рамках практического применения программного кода. Скан книги без проблем можно найти в интернете. Я её настоятельно рекомендую, т.к. она очень хорошо помогает понять алгоритм расчёта той или иной функции. Единственный печальный момент, никто до сих пор не потрудился коды программ выложить в интернет, чтобы не набирать их вручную.
Другая чрезвычайно интересная книга с точки зрения программирования математики [20]. Кодов программ в ней нет, зато есть текстовое описание и рисунки основных алгоритмов.
Архивы библиотек:
Тесты: