2013-06-17 2 views
3

이것은 다소 이전의 질문 중 하나입니다. found here. 기본적으로 dll/함수를 기본 예제로 테스트하려고하는데 'E2010 - 호환되지 않는 유형 : AInteger/ADouble 및 '및'E1012 - 상수 표현이 배열의 범위를 벗어남 [] 오류가 발생합니다. 나는 (다소) 말하려고하는 것이지만, 내가 무엇을 고쳐야 하는지를 알 수 없다. AIntegerADouble 유형 내 배열 인델파이 배열 초기화

var 
    n: Integer; 
    Ap, Ai: AInteger; 
    Ax, b: ADouble; 

begin 
    // Initializations 
    n := 5; 
    Ap := [0, 2, 5, 9, 10, 12]; <- E2010 
    Ai := [0, 1, 0, 2, 4, 1, 2, 3, 4, 2, 1, 4]; <- E2010 
    Ax := [2, 3, 3, -1, 4, 4, -3, 1, 2, 2, 6, 1]; <- E2010 and E1012 
    b := [8, 45, -3, 3, 19]; <- E1012 

:

ADouble = array[0..High(Integer) div SizeOf(Double) - 1] of Double; 
AInteger = array[0..High(Integer) div SizeOf(Integer) - 1] of Integer; 

과 (루디의 델파이 페이지와 다른 C - 투 - 파스칼 소식통에 따르면)이 방법을 초기화해야한다 그들은 이후 예를 들어 C에서 double Ax[]으로 작성되었습니다. 뭔가 잘못되었거나 내 dll을 테스트하기 위해 바뀔 수있는 간단한 내용이있을 것입니다.하지만 예제/솔루션을 찾을 수 없기 때문에 잘못 검색했을 수 있습니다. 그래서, 질문 형태 :

Q1 "

를 참조 E1012이며, 당신이이 등의 작업을 수행 할 경우 [AInteger 및 ADouble], 높은 에 너무 가까이 오지하지 않도록주의 (정수), 컴파일러가 데이터 구조가 너무 큰 것이라고 불평 할지도 모릅니다. " 어떻게이 코드를 변경해야합니다 :

2 분기 (루디의 페이지에서 인용)?

미리 도움을 청하십시오.

+0

그것은 도움이 될 수 있습니다. 당신이 당신의 배열을 초기화하기 위해 작성한 코드는 델파이/파스칼의 모든 버전에서 일한 적이 있으며, 그것은 잘못된 구문 때문에 루디의 페이지는, 그들이 AFAICT해야 말을하지 않습니다 그것은 사실이 있음을하시기 바랍니다 말한다면 루디 (잘 알고있다 링크를 제공하십시오). 델파이는 상수 배열 (해당 구문이 아닌) 또는 의사 생성자 구문을 사용하는 동적 배열의 초기화 만 허용합니다. 자신이하려는 일을 분명히하지 않았기 때문에 어떻게 바꾸어야 하는지를 말하기는 어렵습니다. –

+0

이것은 드문 드문 한 행렬 솔버처럼 보입니다. 어느 쪽이 관심 밖에서 사용하고 있습니까? 저는 Tim Davis의 CSparse를 좋아해요. C 코드를 .obj로 컴파일 한 다음 똑같은 방식으로 연결하는 방법으로 마무리했습니다. –

+0

Ken - 죄송합니다, 제가 언급 한 링크는 C에서 Pascal 로의 변환을 포함합니다. 루디 (Rudy)의 페이지는 "Array Parameters"하위 섹션의 [여기] (http://rvelthuis.de/articles/articles-convert.html 여기)에 언급되어 있습니다. @David 바로 내가 작업하고있는 솔버입니다. 내가 가기로 결정한 방식이 다른 누군가에 의해 수행되었음을 알고 기꺼이 하하입니다. –

답변

8

이와 같은 구문으로이를 수행 할 수 있습니다.

같은 배열을 정의 :

ADouble = array[0..High(Integer) div SizeOf(Double) - 1] of Double; 

전체 32 비트 RAM의 크기의 정수의 배열을 초기화합니다! 그러한 변수는 절대로 할당 할 수 없으며 (Win64에서만 가능하지만 4GB의 RAM을 사용하여 6 개의 정수를 저장합니다)! :)

배열은 동적 인이어야합니다. 즉 런타임에 크기가 변경되어야합니다. 따라서 다음과 같이 정의해야합니다.

type 
    AInteger = array of integer; 

이러한 배열은 현재 언어 AFAIR 상태로 직접 할당 할 수 없습니다.

그래서 당신은 이러한 기능을 쓸 필요가 :

procedure SetArray(var dest: AInteger; const values: array of integer); 
begin 
    SetLength(dest,Length(values)); 
    move(values[0],dest[0],length(values)*sizeof(integer)); 
end; 

을 그리고 당신은 소스로 일정하게 배열 중 하나를 사용할 수 있습니다

const 
    C: array[0..5] of Integer = (0, 2, 5, 9, 10, 12); 
var 
    Ap: AInteger; 
begin 
    SetArray(Ap,C); 

그대로 사용하거나 오픈 배열 매개 변수을 :

var 
    Ai: AInteger; 
begin 
    SetArray(Ai,[0, 2, 5, 9, 10, 12]); 

물론 두 번째 솔루션은 당신이 기대하는 것.

업데이트 : 새로운 버전에 대한, 당신은 물론 같은 동적 배열 생성자를 사용할 수 있습니다 : 당신은 스파 스 솔버 코드를 C로 작성을하고하려고하는 것처럼

var 
    Ai: AInteger; 
begin 
    Ai := AInteger.Create(0,2,5,9,10,12); 
+6

당신은'직접 아이를 동적 배열을 만들 수 있습니다 = AInteger.Create을 (0,2,5,9,10,12)를,' –

+0

감사합니다! 처음에는 동적 배열을 정의한 것처럼 동적 배열을 사용하고 있었지만 위에 정의한 방법으로 코드를 변경하는 것이 좋습니다. 처음에는 올바른 아이디어를 가지고 있다는 것을 알게되어 기분이 좋습니다. –

0

이 질문은 오픈 어레이과는 관계가 없으므로 질문에서 해당 태그를 제거하십시오.

사용중인 대괄호 구문은 Set 값을 선언합니다. 기본적으로 각 비트가 해당 위치의 값에 해당하는 특별한 유형의 비트 마스크입니다. 즉, [0, 2, 5, 9, 10, 12]은 요소 6 개를 포함하는 Set of Integer이며 비트 0은 값 0을 나타내고 비트 1은 값 2를 나타내고 비트 2는 값 5를 나타냅니다. Set은 시도하고있는 것처럼 배열에 직접 할당 할 수 없습니다.

+2

나는 그렇게 무례하지 않을 것이다. AFAIK'[0, 2, 5, 9, 10, 12]'는 배열을 포함하는 열린 배열 매개 변수이기도하므로 함수를 통해 정수 배열에 영향을 줄 수 있습니다. 내 대답을 보라. –

2

그것은 나에게 보인다 델파이 프로그램에 연결하십시오. 나는 당신이 당신의 외부 수입을 선언 한 방식에 근본적인 문제가 있다고 생각합니다. 직접 물어 본 질문에 답하기보다는 외부 수입을 신고하고 부르는 올바른 방법이라고 생각하는 것을 보여 드리겠습니다.

내가 말하고 싶은 첫 번째 것은 선언 한 대형 정적 배열 유형이 여기에 필요한 것이 아니라는 것입니다. 이러한 배열 유형은 때때로 유용 할 수 있지만 실제로는 다른 배열을 PADouble = ^ADouble으로 변환 할 때만 유용합니다. 귀하의 상황에서 당신은 그 배열이 전혀 필요하지 않으며 나는 당신이 그들을 제거하는 것이 좋습니다.

난 당신이 입력 매개 변수로 n, nz, Ap, Ai, Axb를 받아 출력 매개 변수로 x을 반환 solve라는 함수를 호출한다고 가정하겠습니다. 이 함수는 이되도록 x을 반환합니다.는 10 진수의 Ap, AiAx으로 지정된 n 차원의 희소 행렬입니다. nz 매개 변수는 0이 아닌 요소의 수를 지정합니다. 실제 함수가 세부 사항에서 달라질 것이라는 데는 의심의 여지가 없지만 개념은 동일합니다. 예를 들어, nzAp[n]에서 유추하는 것이 일반적이지만 자세한 내용은 해결할 수 있습니다.

첫 번째 요소에 대한 포인터로 매개 변수를받는 함수를 선언하는 것이 좋습니다. 따라서 함수 선언은 다음과 같습니다.

function solve(
    n: Integer; 
    nz: Integer; 
    Ap: PInteger; 
    Ai: PInteger; 
    Ax: PDouble; 
    b: PDouble; 
    x: PDouble 
): Integer; cdecl; external; 

그런 다음 스파 스 매트릭스 배열을 채워야합니다. 이러한 동적 배열을 선언 :

var 
    Ap: TArray<Integer>; 
    Ai: TArray<Integer>; 
    Ax: TArray<Double>; 
.... 
SetLength(Ap, n); 
Ap[0] := ...; 
.... 
SetLength(Ai, nz); 
Ap[0] := ...; 
.... 
SetLength(Ax, nz); 
Ax[0] := ...; 
.... 

당신은 런타임에 매트릭스의 내용이 그래서 루프를 사용하여 작성 될 것 n, nz 등의 가치를 알 수있을 것으로 기대. 문제의 코드는 아마도 외부 코드를 테스트하고 테스트하는 테스트 코드 일 것입니다. Arnaud의 대답은 동적 배열을 채우는 방법에 대한 조언을 제공합니다.

또한 bx를 초기화해야합니다

var 
    b: TArray<Double>; 
    x: TArray<Double>; 
.... 
SetLength(b, n); 
b[0] := ...; 
.... 
SetLength(x, n); 
// no need to initialise values of x[i] since it is the output 

지금 당신이 함수를 호출 할 수 있습니다 :

var 
    retval: Integer; 
.... 
retval := solve(n, nz, PInteger(Ap), PInteger(Ai), PDouble(Ax), 
    PDouble(b), PDouble(x)); 

마지막으로 포인트를 일반 배열의 사용을 converning. 현대 델파이를 사용하고 있기 때문에 제네릭 동적 배열을 사용하는 것이 좋습니다. 따라서 array of ... 대신 TArray<...>을 사용해야합니다. 그 이유는 제네릭 형식이 구식 동적 배열과 다른 형식 호환성 규칙을 갖고 있기 때문입니다. 위의 코드에서 예를 들어, bx은 할당 호환됩니다. 그들은 다음과 같이 선언 된 경우 그러나 :

var 
    b: array of Double; 
    x: array of Double; 

는 그들이 할당 호환되지 않을 것입니다. 유형을 선언하여이 문제를 해결할 수 있습니다. TDoubleArray = array of Double. 그러나 generic 배열을 사용하는 경우 즉시 사용할 수있는 TArray<T> 유형의 반환 값보다 TList<T>과 같은 일반 컨테이너 클래스를 사용할 수 있습니다.

나는 이것이 당신이 물어 꽤 질문이 아니라는 것을 알고 있지만, 나는 당신에게 도움이 될 수 있다는 느낌이 듭니다. 당신이 당신의 배열을하려고 노력하고 정확하게 설명하면

+0

+1 TDavis의 스파 스 패키지를 사용하고 있습니다. 팁을 주셔서 감사합니다. 나는 TArray 을 전혀 모르고 있었고, 호환성 문제를 디버깅하는 데 시간을 허비하기 전에 그것에 대해 배웠 기 때문에 기뻤습니다. 이것은 게시 된 정확한 질문에 대답하지 않을 수도 있지만 많은 조언을 제공합니다 (그리고 아마도 전체적으로 많은 시간을 절약 할 것입니다). 정말 감사. –

+0

CSparse에서 어떤 루틴을 호출 할 계획입니까? 나는 LU 해결하고있다. 나는 또한 어떻게 당신이 당신의 매트릭스를 만들 계획을하고 있는지 궁금해. 나는 삼중 항을 모은 다음 이들을 스파 스 열 저장 장치로 변환합니다. 그 전환은 아주 까다 롭습니다. 실제로 Tim의 코드를 Delphi로 포팅하여 실제로 만들었습니다. 상용 제품에 해당되는 경우 Tim에게 라이센스를 지불해야합니다. 그의 코드는 정말 훌륭합니다. –

+0

또한 LU 해결 방법을 사용할 것이며 앞으로는 A 매트릭스가 제공 될 것이며 필요한 Ap, Ai 등의 벡터를 "만들어야"할 것입니다. 행렬 자체는 평균적으로 상당히 클 것입니다 (n = 10^5). 저는 코드를 좋아하지만 다시 수치 분석/통합, 선형 대수 및 프로그래밍을 좋아합니다. –