Zamieszczam to jako odpowiedź, ponieważ komentarze są nieco zbyt ograniczone, aby je wypowiedzieć.
Odpowiedź ta stara się wyjaśnić różnice w układzie pamięci tablic i rekordów w FORTRAN i Delphi i zmienia answer przez Todd Grigsby i answer przez Remy Lebeau (I upvoted oba).
FORTRAN i kilka innych centrycznych języków obliczeniowych przechowuje zagnieżdżone tablice w column major order. Delphi i wiele innych języków używa row major order.
Z perspektywy pamięci, zapis nie jest niczym innym niż tablicę pól:
- ma nazwy, a nie indeks
- może mieć różne rodzaje
Dla obliczenia intensywnego operacje, może mieć sens przechowywanie głównej kolejności kolumn zagnieżdżonych, kiedy twoje algorytmy faworyzują kolumny. To samo dotyczy zamówienia głównego rzędu. Więc w pętlach musisz match the order of your indexes with the order of your storage.
Biorąc pod uwagę ten rekord i tablica definicja w FORTRAN:
TYPE WallInfo
CHARACTER(len=40) :: Name
REAL :: Azimuth
REAL :: Tilt
REAL :: Area
REAL :: Height
END TYPE WallInfo
TYPE(WallInfo), ALLOCATABLE, DIMENSION(:) :: Wall
i funkcjonalnym odpowiednikiem definicja w Delphi:
type
WallInfo = record
Name: array[0..39] of Char;
Azimuth: Real;
Tilt: Real;
Area: Real;
Height: Real;
end;
var
Wall: array of WallInfo;
i tablicę 3 elementów WallInfo, to jak układ pamięci wyglądałoby (wszystkie były ciągłymi obszarami pamięci, dzielę je na linie, aby były czytelne):
w FORTRAN:
Name[0,0]...Name[0,39], Name[1,0]...Name[1,39], Name[2,0]...Name[2,39],
Azimuth[0], Azimuth[1], Azimuth[2],
Tilt[0], Tilt[1], Tilt[2],
Area[0], Area[1], Area[2],
Height[0], Height[1], Height[2],
w Delphi:
Name[0,0]...Name[0,39], Azimuth[0], Tilt[0], Area[0], Height[0],
Name[1,0]...Name[1,39], Azimuth[1], Tilt[1], Area[1], Height[1],
Name[2,0]...Name[2,39], Azimuth[2], Tilt[2], Area[2], Height[2],
Więc to wezwanie FORTRAN:
CALL HeatFlow (Wall% Powierzchnia, Ściana% Azymut)
po prostu przekazać wskazówki do obszaru [ 0] i położenia Azymutów [0] oraz długość tych obszarów pamięci dla funkcji.
W Delphi, że nie jest możliwe, więc trzeba
- skonstruować nowy obszar i Azymut arays
- skopiować je z informacją w tablicy WallInfo przykład rekord o nazwie Mur
- wyślij je do funkcji
- jeśli są to parametry var: skopiuj zmiany z dwóch tablic z powrotem do muru
Todd Grigsby i Remy Lebeau wykazały pierwsze trzy kroki w ich odpowiedzi, używając prostego kodu Delphi lub rejestru RTTI Delphi.
Krok 4 działa w podobny sposób.
Oba rozwiązania wykorzystują generyczne, które zostały wprowadzone w Delphi 2009. Until Delphi 2010, RTTI on records was very minimal), więc otrzymałeś odpowiednią wersję Delphi dla obu odpowiedzi.
Uwaga (ponownie): tłumacząc swoje algorytmy z FORTRAN na Delphi, upewnij się, że oglądasz pętle i inne indeksowanie w tablicach z powodu głównej zmiany kolumny/wiersza.
Czy próbowałeś z tablicą lub rekordem w swojej tablicy przypadków WallInfo? Delphi obsługuje tablice dinamiczne. Przed wprowadzeniem nowej wartości najpierw ustaw rozmiar tablicy z wartością SetLength. –
Tak fajna, jak odpowiedź Remy'ego na odpowiedź RTTI, byłbym skłonny przetłumaczyć powyższy typ rekordu na osobne tablice liniowe: "Nazwa: Tablica ciągu; Azymut: Tablica podwójna; ... ", a potem nie musiałbym zbierać danych za pomocą tego cudownego hakerskiego interfejsu RTTI, ponieważ zostałby już zebrany. –