Dynamic arrays vs Variable-length arrays - arrays

What is the differences between Dynamic Arrays and Variable-length Arrays?
There are two separate sheets in Wikipedia about this:
1) Regarding Dynamic arrays:
https://en.wikipedia.org/wiki/Dynamic_array
2) Regarding Variable-length Arrays:
https://en.wikipedia.org/wiki/Variable-length_array
But it is not very clear the differences.
Could you give an example in some programming language the Dynamic Array which is not Variable-length one and vice versa.

There are four kind of arrays:
1) Dynamic Arrays
2) Variable-length Arrays
3) Fixed-length Array
4) Static array
Let's consider the four arrays in more details.
1) Dynamic array
In this case there is an API in array which alter length variable.
It can be a method that directly modifies the length
setSize(int newLength)
or a methods that modify it indirrectly:
add(Object newElement)
remove(Object toBeRemoved)
Both of these methods modify the length after adding/removing an element.
Example in Java that emulates Dynamic array:
java.util.ArrayList
2) Variable-length array
Variable-length array is a special case of Dynamic array.
In this case length is read-only and there is no API in array which modifies this variable.
But this variable can be changed by the system the other ways.
Example in Java that emulates Variable-length array - regular java arrays like int[].
Lets consider the example:
int[] a = new int[5]; System.out.println(a.length);
a = new int[10]; System.out.println(a.length);
In this case length variable is changed but we cannot modify it directly like
a.length = 20;
3) Fixed-length array
Fixed-length array is a special case of Variable-length array.
In this case once assigned a value to the length, we cannot modify it anymore.
But it is important to note that length variable is still determined at runtime
Example in Java that emulates this behaviour: final array variables like final int[].
Lets consider the example:
final int[] a;
if (someVar > 0) { a = new int[100]; } else { a = new int[200]; }
In this case a.length is either 100 or 200 and still determined at runtime.
4) Static array
Static array is a special case of Fixed-length array.
In this case length not only can be changed but also can be determined at runtime.
Example of such array in Java can be the following construction:
{1, 2, 3, 100, 200, 500}
This constuction can be assigned to a variable only while its initialization
int[] a = {1, 2, 3};
But if we try reassignment like
a = {1, 2};
we get compilation error.
Example in Java that emulates such an array:
final int[] a = {1, 2, 3};

Variable-length arrays have variable sizes that are set once during runtime.
Dynamic arrays are also variable length arrays, but they can also re-size (re-dimension) after they are created. This allows the array to grow to accommodate additional elements above its original capacity. If using an array, you would have to manually resize the array or overwrite existing data.
For example in C#, arrays (like int[]) are variable-length arrays. Lists (like List<int> or ArrayList) are a dynamically re-sizing arrays. A list hides some of the re-sizing in its .Add() method so the developer doesn't have to worry about it on their own.

Related

Does D distinguish between return/argument types of dynamic vs. static arrays?

Suppose I define a function, mutate, which replaces a random index's contents of an int array, a, with some function applied
int[] mutate(int[] a) {
int randomIndex = cast(int) uniform(a[randomIndex]);
a[randomIndex] = a[randomIndex] + 1;
return a;
}
Does this function specify input and return values of dynamic int array, static int array, or both? That is, is this function limited to accepting and returning either subtype of array? Is there a way to distinguish between dynamic and static arrays as arguments to a function?
Do either of the following throw an error?
void main() {
int[] dyn;
dyn = [1, 2, 3];
writeln(mutate(dyn));
int[3] stat = [1,2,3];
writeln(mutate(stat));
}
int[] mutate(int[] a)
That takes a slice and returns a slice. A slice is not necessarily a dynamic array, it might be a static array, though then you need to pass it as stat[] instead of just stat.
A slice is like a ptr and length combo in C: a pointer to data (which may reside anywhere, a dynamic array, a malloc array, a static array, some block of memory, whatever) and a count of the length.
When you return one like that, you do need to be kinda careful not to store it. The slice doesn't know where it is stored and you might easily lose track of who owns it and end up using a bad pointer! So be sure the scope is safe when doing something like this.
Read this for more info:
http://dlang.org/d-array-article.html

Swift 3 UnsafeMutablePointer initialization for C type float**

Within Swift 3, I need to send data to a C object accepting float ** input.
In Swift 2, I used to declare a UnsafeMutablePointer< UnsafeMutablePointer<Float32>>, construct a swift Array (only for init!), and pass this to the pointer, and it worked:
var bufferOut: UnsafeMutablePointer< UnsafeMutablePointer<Float32>>?
arrayOut = Array(repeating: Array(repeating: 0, count: Int(size1), count: Int(size2))
bufferOut = UnsafeMutablePointer< UnsafeMutablePointer<Float32>>(arrayOut)
This is all broken now in Swift 3!
What is the most Swifty way to pass a C-Style float** and initialize it?
What would be the best way to assign values in a UnsafeMutablePointer< UnsafeMutablePointer<T>>?
Documentations say that for T ** one should use AutoreleasingUnsafeMutablePointer<T> but I actually never managed to construct one!
Note that I don't actually care for the Array in the above example! If I could just initialize the Pointer directly using known capacities, I would.
Note: The Expected use cases Section of UnsafeRawPointer describes useful situations such C array and C Buffers, however translating such methods for the above construct is not evident!
Here is what I ended up doing and is working. It follows recommendations from new UnsafeMuTablePointer Reference showing example programs on simple schemes. In summary, it is required to allocate and assign each slot starting from top-level!
So in order to construct an UnsafeMutablePointer< UnsafeMutablePointer<T>> of size (size1, size2) (like a matrix), you can go ahead as follows using an intermediate vector here called vectorBuf:
var vectorBuf : UnsafeMutablePointer<T>?
vectorBuf = UnsafeMutablePointer<T>.allocate(capacity: size2)
for index in 0...(size2) { // had Int(channelCount)*
vectorBuf!.advanced(by: index).pointee = 0.0
}
/// This is where allocation and initialization happens:
bufferOut = UnsafeMutablePointer< UnsafeMutablePointer<T>?>.allocate(capacity: Int(size1))
for index in 0...Int(size1) {
bufferOut!.advanced(by: index).pointee = UnsafeMutablePointer<T>.allocate(capacity: (size2) )
bufferOut!.advanced(by: index).pointee?.assign(from: vectorBuf!, count: size2)
}
Hope this can be useful to others trying to use swift with signal processing calls in C/C++!

Declaring an array in a loop

Is it possible to declare an array inside a loop. For some reasons I can not declare it before the loop since its length changes. I am wondering if I can re-declare/delete an array within the loop. I am using C++/CLI language.
Native c++ arrays, must have their size determined at compile-time if they are allocated on the stack, and so if you want to use native arrays, you'll have to allocate them with the new operator.
Unrecommended solution:
int rows = 1000;
int arr[] = new int[rows]; //new array with 1000 integers
int rows = 5;
delete arr; //don't forget to delete the previous allocation before re-sizing
int arr[] = new int[rows]; //new array with 5 integers
This however forces you to constantly be aware of allocations and de-allocations. That's why the standard and Microsoft gave you std::vector and cli::array.
The Managed way:
If you want your array to be on the managed heap, use cli::array:
cli::array<int> ^arr= gcnew cli::array<int>(1000); //new array with 1000 integers
Array::Resize(arr, 5); //resize arr to 5 integers
The unmanaged way:
If you want your array to be on the unmanaged heap (native C++), use std::vector:
std::vector<int> arr(1000); //new array with 1000 integers
arr.resize(5); //resize array to 5 integers
You could use Array::Resize method in each iteration (as eladidan says); or you could use a List<> class, add items in each iteration and finally call List<>::ToArray() to get the array you are looking for. Probably the first way would be more efficient but the second one is more convenient.

What's the difference between arrays of arrays and multidimensional arrays?

I had a language-agnostic discussion with someone in the C++ chat and he said that arrays of arrays and multidimensional arrays are two things.
But from what I learned, a multidimensional array is nothing more than an array of other arrays that all have the same size. In particular he is saying
Well, they kind of are in C, where you simulate multiple dimensions with nested arrays
but that’s only because C doesn’t actually support multiple dimension arrays
Can someone please explain what the canonical computer-science definition of "multiple dimension arrays" is and why C (or the abstract definition "array of arrays") does not fit that definition?
Take .NET arrays which illustrate this nicely:
C# has a distinction between jagged arrays which are defined in a nested fashion:
int[][] jagged = new int[3][];
Each nested array can have a different length:
jagged[0] = new int[3];
jagged[1] = new int[4];
(And note that one of the nested arrays isn’t initialised at all, i.e. null.)
By contrast, a multidimensional array is defined as follows:
int[,] multidim = new int[3, 4];
Here, it doesn’t make sense to talk of nested arrays, and indeed trying to access multidim[0] would be a compile-time error – you need to access it providing all dimensions, i.e. multidim[0, 1].
Their types are different too, as the declarations above reveal.
Furthermore, their handling is totally different. For instance, you can iterate over the above jagged array with an object of type int[]:
foreach (int[] x in jagged) …
but iterating over a multidimensional array is done with items of type int:
foreach (int x in multidim) …
Conceptually, a jagged array is an array of arrays (… of arrays of arrays … ad infinitum) of T while a multidimensional array is an array of T with a set access pattern (i.e. the index is a tuple).
I would expect multidimensional arrays to offer operations such as "Give me the number of dimensions" or "Give me a certain column" or "Give me a certain sub-view". C arrays don't offer these operations.
From Wikipedia:
Multi-dimensional arrays
The number of indices needed to specify an element is called the dimension, dimensionality, or rank of the array type. (This nomenclature conflicts with the concept of dimension in linear algebra,[5] where it is the number of elements. Thus, an array of numbers with 5 rows and 4 columns, hence 20 elements, is said to have dimension 2 in computing contexts, but represents a matrix with dimension 4-by-5 or 20 in mathematics. Also, the computer science meaning of "rank" is similar to its meaning in tensor algebra but not to the linear algebra concept of rank of a matrix.)
Many languages support only one-dimensional arrays. In those languages, a multi-dimensional array is typically represented by an Iliffe vector, a one-dimensional array of references to arrays of one dimension less. A two-dimensional array, in particular, would be implemented as a vector of pointers to its rows. Thus an element in row i and column j of an array A would be accessed by double indexing (A[i][j] in typical notation). This way of emulating multi-dimensional arrays allows the creation of ragged or jagged arrays, where each row may have a different size — or, in general, where the valid range of each index depends on the values of all preceding indices.
This representation for multi-dimensional arrays is quite prevalent in C and C++ software. However, C and C++ will use a linear indexing formula for multi-dimensional arrays that are declared as such, e.g. by int A[10][20] or int A[m][n], instead of the traditional int **A.[6]:p.81
For an example of a language supporting multidimensional arrays, see here.
C does not have multidimensional arrays but C have arrays of arrays.
In the Standard, the wording multidimensional array is used but C multidimensional arrays are in reality arrays of arrays. From Kernighan & Ritchie:
"In C, a two-dimensional array is really a one-dimensional array, each of whose elements is an array."
Some languages support multidimensional arrays as first class types. The "Expert C Programming" book shows the example of Ada which supports both arrays of arrays and multidimensional arrays.
I get his point. He actually differ them from implementation point of view, but both are actually valid to be said multidimensional arrays.
The "array of array" kind uses linear indexing as it's actually implemented as one dimensional array, despite at language level it's referenced via multiple index. Ex, in C:
int a[5][5];
would actually have the same structure as:
int a[25];
The compiler would translate an access such as:
a[i][j]
to:
a[i * jDimensionWidth + j]
where jDimensionWidth = 5 in above example. And it's even possible to access it like:
int* b = (int*) a;
printf("%d\n",b[12] == a[2][2]); // should output 1
The "multidimensional array" kind is implemented through Iliffe vector as he said, where the indexing can't be linearized because the address is not linear as well since the vector is typically implemented as heap object. This kind of multidimensional array doesn't fit the equation (for 2-dimensional array):
addr(a[i + 1]) = addr(a[i]) + (a[i].width * sizeof(a[i][j].datatype))
which is fulfilled by the "array of array" kind.

How should I initialize this multi-dimensional array?

I have a giant 3-dimensional array that represents my world. It's too big to initialize statically:
alias Cell[128][128][128] World; // <-- The compiler points to this line
Error: index 128 overflow for static array
I tried using World* world but it still errors out with the overflow above. So what I have right now is this ugly mess:
alias Cell[][][] World;
// ...
private World world;
// ...
world.length = WORLD_XDIM;
for (uint x = 0; x < world.length; ++x)
{
world[x].length = WORLD_YDIM;
for (uint y = 0; y < world[x].length; ++y)
{
world[x][y].length = WORLD_ZDIM;
}
}
That works, but it makes me cry a little on the inside. Is there a way to cast the result of calloc to a 3-dimensional array? I've done it with slicing regular arrays, but the 3-D thing is confounding me.
If you want to declare a jagged array (i.e. where each sub-array may have varying length), then you need to use a loop like you're doing, but that's unnecessary for uniform arrays. This is how you initialize a multi-dimensional array which isn't jagged:
auto arr = new Cell[][][](128, 128, 128);
When you put the numbers between the brackets, you're make it a dynamic array of static arrays. So,
auto arr = new Cell[128][128][128];
declares a dynamic array of a static arrays of length 128 of static arrays of length 128. I guess that it would be useful if you actually needed to do that (which I never have), but it definitely trips up newbies on a regular basis.
Personally, to avoid such issues completely, I just never put the numbers in between the brackets, even when declaring a single dimension array:
auto arr = new Cell[](128);
I find the fact that putting the number between the brackets on the first dimension is treated as a dynamic array while putting numbers in any further levels is treated as a static array to be a poor design choice, and I don't know why that's the way that it is, but that's the way that it is. I can understand wanting to be able to create dynamic arrays of static arrays, but it would have been far more consistent to either disallow new Cell[128] or to make it return a Cell[128]* rather than a Cell[] of length 128, but unfortunately, that's not how it works.

Resources