Translate this page:
Please select your language to translate the article


You can just close the window to don't translate
Library
Your profile

Back to contents

Cybernetics and programming
Reference:

The use of fortran linear algebra libraries in the delphi environment

Malashkevich Irina Ardalionovna

Associate Professor, Department of Information Systems, Volga State University of Technology

424038, Russia, respublika Marii El, g. Ioshkar-Ola, ul. Leninskii prospect, 3

malashkevichia@volgatech.net
Other publications by this author
 

 
Malashkevich Vasilii Borisovich

PhD in Technical Science



424000, Respublika Marii El, g. Ioshkar-Ola, pl. Lenina, dom 3.

MalashkevichVB@volgatech.net
Other publications by this author
 

 

DOI:

10.7256/2306-4196.2013.1.8314

Received:

18-01-2013


Published:

1-02-2013


Abstract: 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

Рис.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/