I have a very simple code snippet which you can check here:
type
TMatrix = array of array of Byte;
PMatrix = ^TMatrix;
const
testarray:array [0..2,0..2] of Byte=(
(1,2,3), (4,5,6), (7,8,9));
function PickValue(input:PMatrix):Byte;
begin
Result:=input^[1,3];
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Showmessage(inttostr(PickValue(#testarray)));
end;
end.
How can I cast testarray properly to pass it to the PickValue function? Above code crashes in its current form. I'm using delphi 2007.
Thanks in advance!
You cannot cast that static array to be a dynamic array. These types are simply not compatible. The static array is laid out in one contiguous block of memory. The dynamic array has indirection to variable sized arrays at each dimension. In effect think of it as ^^Byte with extra compiler management and meta data. No amount of casting can help you.
You have, at least, the following options:
Copy the contents of the static array to a dynamic array. Then pass that dynamic array to your function.
Switch your static array to be a dynamic array so that no conversion is needed.
Arrange that your function accepts static arrays rather than dynamic arrays, again to avoid requiring a conversion.
Have the function accept a pointer to the first element and the inner dimension. Then perform the indexing manually. The i,j element is at linear offset i*innerDim + j.
Your pointer type PMatrix is probably not needed. Dynamic arrays are already implemented as pointers. This seems to be a level of indirection too far.
Of course, asking for element 3 when the array indices only go up to 2 isn't right, but that is presently the lesser of your concerns. Remember that dynamic arrays are zero based and you have specified zero based for your static array.
I am struggling to be able to recommend which solution is best since I don't understand your real goals and usage based on the simplified example presented here.
Related
In C if I have:
int grades[100][200];
and want to pass the first row, then I write: grades[0], but what if I want to pass first column? writing this won't help grades[][0]
You can't pass columns in C. You pass pointers to the beginning of some continuous data.
Rows in C are written continuously in memory, so you pass the pointer to the first element of some row (you do it implicitly by using its name: matrix[row]; an explicit version would be &matrix[row][0]), and you can use the row by iterating over the continuous memory.
To use columns, you need to pass the whole array (a pointer to the first element in the 2D array, actually), and pass also the length of the rows, and then the function has to jump that length to jump from an element of the same column to the next one. This is one of many possible solutions, you could develop any other solution, for example copying the column in a temporary array as some comment pointed out; but this one is commonly used in cblas functions for example.
If it helps to visualize, a 2-dimensional array is an array of arrays, it's not formulated as a matrix. Thereby, we can pass a sub-array (i.e., a row), but there's no direct way of passing a column.
One way to achieve this is to loop over the outer array, pick the element at the fixed location (mimicking the "column"), and use the values to create a separate array, or pass to function that needs to process the data.
Matrixes do not exist in C (check by reading the C11 standard n1570). Only arrays, and in your example, it is an array of arrays of int. So columns don't exist neither.
A good approach is to view a matrix like some abstract data type (using flexible array members ....) See this answer for details.
Consider also using (and perhaps looking inside its source code) the GNU scientific library GSL, and other libraries like OpenCV, see the list here.
In some cases, arbitrary precision arithmetic (with gmplib) could be needed.
For example: I want to use reflect to get a slice's data as an array to manipulate it.
func inject(data []int) {
sh := (*reflect.SliceHeader)(unsafe.Pointer(&data))
dh := (*[len(data)]int)(unsafe.Pointer(sh.Data))
printf("%v\n", dh)
}
This function will emit a compile error for len(data) is not a constant. How should I fix it?
To add to the #icza's comment, you can easily extract the underlying array by using &data[0]—assuming data is an initialized slice. IOW, there's no need to jump through the hoops here: the address of the first slice's element is actually the address of the first slot in the slice's underlying array—no magic here.
Since taking an address of an element of an array is creating
a reference to that memory—as long as the garbage collector is
concerned—you can safely let the slice itself go out of scope
without the fear of that array's memory becoming inaccessible.
The only thing which you can't really do with the resulting
pointer is passing around the result of dereferencing it.
That's simply because arrays in Go have their length encoded in
their type, so you'll be unable to create a function to accept
such array—because you do not know the array's length in advance.
Now please stop and think.
After extracting the backing array from a slice, you have
a pointer to the array's memory.
To sensibly carry it around, you'll also need to carry around
the array's length… but this is precisely what slices do:
they pack the address of a backing array with the length of the
data in it (and also the capacity).
Hence really I think you should reconsider your problem
as from where I stand I'm inclined to think it's a non-problem
to begin with.
There are cases where wielding pointers to the backing arrays
extracted from slices may help: for instance, when "pooling"
such arrays (say, via sync.Pool) to reduce memory churn
in certain situations, but these are concrete problems.
If you have a concrete problem, please explain it,
not your attempted solution to it—what #Flimzy said.
Update I think I should may be better explain the
you can't really do with the resulting
pointer is passing around the result of dereferencing it.
bit.
A crucial point about arrays in Go (as opposed to slices)
is that arrays—as everything in Go—are passed around
by value, and for arrays that means their data is copied.
That is, if you have
var a, b [8 * 1024 * 1024]byte
...
b = a
the statement b = a would really copy 8 MiB of data.
The same obviously applies to arguments of functions.
Slices sidestep this problem by holding a pointer
to the underlying (backing) array. So a slice value
is a little struct type containing
a pointer and two integers.
Hence copying it is really cheap but "in exchange" it
has reference semantics: both the original value and
its copy point to the same backing array—that is,
reference the same data.
I really advise you to read these two pieces,
in the indicated order:
https://blog.golang.org/go-slices-usage-and-internals
https://blog.golang.org/slices
Let's say I have an associative array keyed by unsigned int; values could be of any fixed-size type. There is some pre-defined maximum no. of instances.
API usage example: MyStruct * valuePtr = get(1234); and put(6789, &myStructInstance); ...basic.
I want to minimise cache misses as I read entries rapidly and at random from this array, so I pre-malloc(sizeof(MyType) * MAX_ENTRIES) to ensure locality of reference inasmuch as possible.
Genericism is important for the values array. I've looked at C pseudo-generics, but prefer void * for simplicity; however, not sure if this is at odds with performance goals. Ultimately, I would like to know what is best for performance.
How should I implement my associative array for performance? Thoughts thus far...
Do I pass the associative array a single void * pointer to the malloced values array and allow it to use that internally (for which we would need to guarantee a matching keys array size)? Can I do this generically, since the type needs(?) to be known in order to index into values array?
Do I have a separate void * valuePtrs[] within the associative array, then have these pointers point to each element in the malloced values array? This would seem to avoid need to know about concrete type?
Do I use C pseudo-generics and thus allow get() to return a specific value type? Surely in this case, the only benefit is not having to explicitly cast, e.g. MyStruct* value = (MyStruct*) get(...)... the array element still has to be dereferenced and so has the same overhead?
And, in general, does the above approach to minimising cahce misses appear to make sense?
In both cases, the performance is basically the same.
In the first one (void* implementation), you will need to look up the value + dereference the pointer. So these are two instructions.
In the other implementation, you will need to multiply the index with the size of the values. So this implementation also asks for two instructions.
However, the first implementation will be easier and more clean to implement. Also, the array is fully transparent; the user will not need to know what kind of structures are in the array.
See solutions categorised below, in terms of pros and cons (thanks to Ruben for assisting my thinking)... I've implemented Option 2 and 5 for my use case, which is somewhat generalised; I recommend Option 4 if you need a very specific, one-off data structure. Option 3 is most flexible while being trivial to code, and is also the slowest. Option 4 is the quickest. Option 5 is a little slow but with flexibility on the array size and ease of general use.
Associative array struct points to array of typed pointers:
pros no failure value required, explicit casts not required, does not need compile-time size of array
cons costly double deref, requires generic library code
Associative array struct holds array of void * pointers:
pros no failure value required, no generic library code
cons costly double deref, explicit casts following get(), needs compile time size of array if VLAs are not used
Associative array struct points to array of void * values:
pros no generic library code, does not need compile-time size of array
cons costly triple deref, explicit casts following get(), requires offset calc which requires sizeof value passed in explicitly
Associative array struct holds array of typed values:
pros cheap single deref, explicit casts not required, keys and entries allocated contiguously
cons requires generic library code, failure value must be supplied, needs compile time size of array if VLAs are not used
Associative array struct points to array of typed values:
pros explicit casts not required, flexible array size
cons costly double deref, requires generic library code, failure value must be supplied, needs compile time size of array if VLAs are not used
I want to make a 2D array "data" with the following dimensions: data(T,N)
T is a constant and N I dont know anything about to begin with. Is it possible to do something like this in fortran
do i = 1, T
check a few flags
if (all flags ok)
c = c+ 1
data(i,c) = some value
end if
end do
Basically I have no idea about the second dimension. Depending on some flags, if those flags are fine, I want to keep adding more elements to the array.
How can I do this?
There are several possible solutions. You could make data an allocatable array and guess the maximum value for N. As long as you don't excess N, you keep adding data items. If a new item would exceed the array size, you create a temporary array, copy data to the temporary array, deallocate data and reallocate with a larger dimension.
Another design choice would be to use a linked list. This is more flexible in that the length is indefinite. You loss "random access" in that the list is chained rather than indexed. You create an user defined type that contains various data, e.g., scalers, arrays, whatever, and also a pointer. When you add a list item, the pointer points to that next item. The is possible in Fortran >=90 since pointers are supported.
I suggest searching the web or reading a book about these data structures.
Assuming what you wrote is more-or-less how your code really goes, then you assuredly do know one thing: N cannot be greater than T. You would not have to change your do-loop, but you will definitely need to initialize data before the loop.
My program is running though 3D array, labelling 'clusters' that it finds and then doing some checks to see if any neighbouring clusters have a label higher than the current cluster. There's a second array that holds the 'proper' cluster label. If it finds that the nth adjoining cluster is labelled correctly, that element is assigned to 0, otherwise is assigns it to the correct label (for instance if the nth site has label 2, and a neighbour is labeled 3, the 3rd element of the labelArray is set to 2). I've got a good reason to do this, honest!
All I want is to be able to assign the nth element of the labelArray on the fly. I've looked at allocatable arrays and declaring things as labelArray(*) but I don't really understand these, despite searching the web, and StackOverflow.
So any help on doing this would be awesome.
Here is a Stack Overflow question with some code examples showing several ways of using Fortran allocatable arrays: How to get priorly-unkown array as the output of a function in Fortran: declaring, allocating, testing for being already being allocated, using the new move_alloc and allocation on assignment. Not shown there is explicit deallocation, since the examples are using move_alloc and automatic deallocation on exit of a procedure.
P.S. If you want to repeatedly add one element you should think about your data structure approach. Adding one element at a time by growing an array is not an efficient approach. To grow an array from N elements to N+1 in Fortran will likely mean creating a new array and copying all of the existing elements. A more appropriate data structure might be a linked list. You can create a linked list in Fortran by creating a user-defined type and using pointers. You chain the members together, pointing from one to the next. The overhead to adding another member is minor. The drawback is that it is easiest to access the members of the list in order. You don't have the easy ability of an array, using indices, to access the members in any order.
Info about linked lists in Fortran that I found on the web: http://www-uxsup.csx.cam.ac.uk/courses/Fortran/paper_12.pdf and http://www.iag.uni-stuttgart.de/IAG/institut/abteilungen/numerik/images/4/4c/Pointer_Introduction.pdf
If you declare an array allocatable, you use deffered shape in the form real,
allocatable :: labelArray(:,:)
, or
real,dimension(:,:),allocatable :: labelArray
with number of double colons meaning rank (number of your indexes) of your array.
If the array is unallocated you use
allocate(labelarray(shapeyouwant))
with the correct number of indexes. For example allocate(labelarray(2:3,-1:5)) for array with indexes 2 to 3 in demension 1 and -1 to 5 in dimension 2.
For change of dimension you have to deallocate the array first using
deallocate(labelArray)
To reallocate an allocated array to a new shape you first need to allocate a new array with the new shape, copy the existing array to the new array and move the reference of the old array to the new array using move_alloc().
call allocate(tmp(size_old+n_enlarge))
tmp(1:size_old) = array(1:size_old)
call move_alloc(tmp, array)
The old array is deallocated automatically when the new array reference is moved by move_alloc().
Fortran 95 deallocates arrays automatically, if they fall out of scope (end of their subroutine for example).
Fortran 2008 has a nice feature of automatic allocation on assignment. If you say array1=array2 and array1 is not allocated, it is automatically allocated to have the correct shape.
It can also be used for re-allocation (see also Fortran array automatically growing when adding a value and How to add new element to dynamical array in Fortran 90)
labelArray = [labelArray, new_element]
Late comment... check Numerical Recipes for Fortran 90. They implemented a nice reallocate function that was Fortran 90 compliant. Your arrays must be pointer attributed in this case, not allocatable attributed.
The function receives the old array and desired size, and returns a pointer to the new resized array.
If at all possible, use Fortran 95 or 2003. If 2003 is impossible, then 95 is a good compromise. It provides better pointer syntax.