Library
|
Your profile |
Cybernetics and programming
Reference:
Malashkevich I.A., Malashkevich V.B.
The use of fortran linear algebra libraries in the delphi environment
// Cybernetics and programming.
2013. № 1.
P. 1-8.
DOI: 10.7256/2306-4196.2013.1.8314 URL: https://en.nbpublish.com/library_read_article.php?id=8314
The use of fortran linear algebra libraries in the delphi environment
DOI: 10.7256/2306-4196.2013.1.8314Received: 18-01-2013Published: 1-02-2013Abstract: The article presents the components and header modules written in Object Pascal, allowing to easy include libraries with such functions and procedures for numerical solution of linear-algebra as BLAS, LAPACK, ARPACK etc. written in FORTRAN. Using these libraries in modern programming languages such as C ++ or Object Pascal is hard due to significant problems associated with the methods of passing parameters to subroutines, as well as to the method of representation of an array in memory. Another serious problem is the numbering of the elements that start from 1 in FORTRAN. In Object Pascal considering this condition may require careful analysis and the modification of the algorithm for solving the problem. This greatly increases the complexity of programming and leads to hidden, difficult to detect algorithmic errors. To provide transparent access the routines of FORTRAN-libraries while programming in Object Pascal in Delphi environment the authors developed two classes of objects for representing one-dimensional arrays TVector and two-dimensional arrays TMatrix. Keywords: fortran, library, linear algebra, delphi, Object Pascal, TVector, TMatrix, programming, algorithm, subroutineБиблиотеки подпрограмм BLAS, LAPACK, ARPACK [1,2], написанные на языке Fortran77, содержит обширный набор подпрограмм для решения наиболее часто встречающихся задач линейной алгебры. Эти библиотека позволяет решать системы линейных уравнений, линейные задачи наименьших квадратов, находить собственные значения и вектора матриц, их сингулярные значения. Также возможно решение сопутствующих задач, таких как факторизация матриц или вычисление числа обусловленности. Подпрограммы LAPACK и ARPACK интенсивно используют пакет BLAS (Basic Linear Algebra Set), обеспечивающий выполнение элементарных операций, таких как сложение и умножение векторов и матриц, вычисление скалярного произведения и т.п. Все подпрограммы указанных пакетов применяют эффективные алгоритмы вычислений, тщательно протестированные и оптимизированные для достижения максимальной производительности. Они имеют версии для вычислений с единичной и двойной точностью и распространяются как в исходных кодах, так и формате dll-файлов. Вместе с тем использование этих библиотек в современных языках программирования, например в C++ или Object Pascal, сталкивается с существенными проблемами, связанными с методами передачи параметров в подпрограммы, а также со способом представления массивов в оперативной памяти. Подпрограммы BLAS, LAPACK, ARPACK воспринимают все векторные параметры подпрограмм как адреса соответствующих объектов. Кроме того все массивы в языке FORTRAN в качестве номера первого элемента используют индекс 1, тогда как динамические массивы C++ и Object Pascal принимают в качестве номера первого элемента массива индекс 0. Передача параметров по адресу (ссылке), принятая в FORTRAN, имеет простой аналог в языке Object Pascal и не является серьезной проблемой. Достаточно объявить вызываемые функции библиотеки LAPACK в стиле, например var dsaupd_: function(var ido: Integer; var bmat: Char; var n: Integer; var which: Char; var nev: Integer; var tol: TData; resid: PData; var ncv: Integer; v: PData; var ldv: integer; iparam: PInteger; ipntr: PInteger; workd, workl: PData; var lworkl: Integer; var info: Integer ) : integer cdecl; Более серьезной проблемой является нумерация элементов с 1, принятая в FORTRAN. В Object Pascal учет этого условия может потребовать тщательного анализа и модификации алгоритма решения задачи. Это существенно увеличивает трудоемкость программирования и ведет к появлению скрытых, трудно обнаруживаемых алгоритмических ошибок. Наибольшие затруднения представляют вызовы подпрограмм FORTRAN-библиотек, связанные с обработкой матриц. Проблемой здесь является метод сохранения матриц по столбцам, принятый в языке FORTRAN, тогда как в Object Pascal массивы хранятся в памяти по строкам (Рис.1). Поэтому прямая передача адреса начального элемента в подпрограмму LAPACK из программы Object Pascal приведет к обработке транспонированной матрицы, либо к ошибке обращения к памяти для неквадратных матриц. Рис.1 Методы размещения массива в оперативной памяти в FORTRAN и Object Pascal. Для преодоления указанных трудностей и обеспечения прозрачного обращения к подпрограммам FORTRAN-библиотек из программ на языке Object Pascal среды Delphi были разработаны два класса объектов для представления одномерных массивов TVector и двумерных массивов - TMatrix. Определения классов имею вид: TMode = (mDELPHI=0, mFORTRAN); //Режим работы массива TVector = class private fMode : TMode; // mDELPHI V[0..Size-1]; mFORTRAN V[1..Size] fSize: Integer; //Кол-во элементов fFirstItem: PDouble; protected function GetPointer(i: integer): PDouble; procedure SetByPointer(i:integer; p : PDouble); function GetValid(i:integer):Boolean; function GetValue(i:integer):Double; procedure SetValue(i:integer; v:Double); procedure SetSize(const N:integer); public constructor SetLen (ASize: integer; AMode : TMode = mDELPHI); destructor Destroy; override; procedure Clear; procedure Assign(Source: TVector); function FirstIndex: Integer; function LastIndex:Integer; procedure SetZero; property Mode : TMode read fMode write fMode; property Size : Integer read fSize write SetSize; property Item[i:integer] : Double read GetValue write SetValue; default; property Ptr[i:integer] : PDouble read GetPointer write SetByPointer; property FirstItem: PDouble read fFirstItem; end; TMatrix = class(TVector) private fRowCount: integer; fColCount: integer; protected function GetPointer(ARow, ACol:integer) : PDouble; procedure SetPtr(ARow, ACol:integer; p : PDouble); function GetValid(ARow, ACol:integer):Boolean; function GetValue(ARow, ACol:integer):Double; procedure SetValue(ARow, ACol:integer; v:Double); procedure SetCell(ARow, ACol:integer; v:Double; IsValid:Boolean); public constructor SetLen(ARows, ACols:integer; AMode:TMode=mDELPHI); procedure Assign(Source: TMatrix); property Item[ARow, ACol: integer]:Double read GetValue write SetValue; default; property Ptr[ARow, ACol: integer]:PDouble read GetPointer write SetPtr; property Rows: integer read fRowCount; property Cols: integer read fColCount; function FirstRow: Integer; function FirstCol: Integer; function LastRow: Integer; function LastCol: Integer; property Valid[ARow, ACol:integer]:Boolean read GetValid; end; Оба класса имеют конструктор SetLen, который обеспечивает выделение памяти для хранения массивов. Физически массив всегда представляется как одномерный, причем для двумерных массивов данные располагаются по столбцам, как это принято в FORTARN. Элементы массивов во внутренней памяти всегда нумеруются с 0-го индекса, однако обращаться к ним следует с учетом режима индексации, заданного свойством Mode. При Mode= mFORTRAN индексом первого элемента является 1. В этом режиме также принято извлечение и запись элементов двумерного массива в стиле FORTRAN – по столбцам. В режиме Mode=mDELPHI обращение к элементам массива выполняется, как это принято в Object Pascal. При этом для учета способа хранения элементов во внутреннем массиве используется соответствующий способ расчета индексов. В качестве примера использования предложенных классов приводится выдержка из программы на языке Object Pascal для решения проблемы собственных значений методом Арнольди [2] с применением пакетов BLAS, LAPACK и ARPACK. //Объявления используемых модулей uses Utils, BLAS, LAPACK, ARPACK, Vector, Matrix; //Объявления массивов var v, d : TMatrix; workl, workd, resid, ax : TVector;
//Создание массивов в стиле FORTRAN workl := TVector.SetLen(maxncv*(maxncv+8),mFORTRAN); workd := TVector.SetLen(3*maxn,mFORTRAN); v := TMatrix.SetLen(ldv,maxncv,mFORTRAN); d := TMatrix.SetLen(maxncv,2,mFORTRAN); … //Вызов подпрограммы из пакета ARPACK dseupd_( rvec, howmny, @select(1), d.Ptr(1,1), v.Ptr(1,1), ldv, sigma, bmat, n, which(1), nev, tol, resid.Ptr(1), ncv, v.Ptr(1,1), ldv, iparam.Ptr(1), ipntr.Ptr(1), workd.Ptr(1), workl.Ptr(1), lworkl, ierr ); //Приведение массива к стилю Delphi d.Mode := mDELPHI; for j:=0 to nconv-1 do for j:=0 to 1 do … d[j, i] … … Разработанные классы объектов решают все перечисленные проблемы и обеспечивают прозрачный доступ к подпрограммам математических библиотек BLAS, LAPACK и ARPACK из программ на языке Object Pascal. References
1. www.netlib.org/lapack
2. http://www.caam.rice.edu/software/ARPACK/ |