Array Index Confusion In C Code - c#

I'm porting some C Code to C#. I'm stuck at a piece where I don't quite understand the Author's intention of writing code in unfamiliar fashion.
The Code is:
typedef struct{
Int32 window[2][8];
Int32 windowF[2][8];
short Index;
}BLOCK_SWITCHING_CONTROL;
maxWindow = SrchMaxWithIndex( &blockSwitchingControl->window[0][8-1],
&blockSwitchingControl->Index, 8);
*****************************************************************************
*
* function name: SrchMaxWithIndex
* description: search for the biggest value in an array
* returns: the max value
*
**********************************************************************************/
static Int32 SrchMaxWithIndex(const Int32 in[], Int16 *index, Int16 n)
{
Int32 max;
Int32 i, idx;
/* Search maximum value in array and return index and value */
max = 0;
idx = 0;
for (i = 0; i < n; i++) {
if (in[i+1] > max) {
max = in[i+1];
idx = i;
}
}
*index = idx;
return(max);
}
As you can see, when SrchMaxWithIndex is being called, not an array but a single Int32 is being passed as its first parameter which is of course wrong. But because I know for sure the C code has nothing wrong with it, I'm convinced that I'm missing something here.
What am I missing? What was the Author's intention to pass a single Int32 instead of an array?
So far I've ported the above to C# in the following manner:
static class BLOCK_SWITCHING_CONTROL{
Int32[][] window = new int[2]{new int[8], new int[8]};
Int32[][] windowF = new int[2]{new int[8], new int[8]};
short Index;
};
maxWindow = SrchMaxWithIndex( blockSwitchingControl.window[0]/*[8-1]*/,
out blockSwitchingControl.Index);
*****************************************************************************
*
* function name: SrchMaxWithIndex
* description: search for the biggest value in an array
* returns: the max value
*
**********************************************************************************/
static Int32 SrchMaxWithIndex(Int32 _in[], out Int16 index)
{
Int32 max;
Int32 i, idx;
/* Search maximum value in array and return index and value */
max = 0;
idx = 0;
for (i = 0; i < _in.Length; i++) {
if (in[i+1] > max) {
max = in[i+1];
idx = i;
}
}
index = idx;
return(max);
}
But it is just to remove the errors in C#.

The C code is not passing a single integer. It's passing the address of an integer, using the & prefix operator.
There does seem to be some kind of typo though, since the C code references a windowN member in the struct which does not seem to exist.
Assuming it means windowF, this code:
maxWindow = SrchMaxWithIndex(&blockSwitchingControl->windowF[0][8-1],
&blockSwitchingControl->Index, 8);
Tells the called function to treat the given address as an array of 8 integers. I think this will overflow into windowF[1][]. It's very scary code, but if it were as wrong as you state, it wouldn't compile. You can't in general pass an integer to a function expecting a pointer, in C.

OK, first, I have to assume you have a mistake in the code:
blockSwitchingControl->windowN
Does not exist in the BLOCK_SWITCHING_CONTROL structure. So I'll answer this assuming you ment something like windowF
Now to your question, the author did pass an array... sort of.
Presumably blockSwitchingControl is an structure of type BLOCK_SWITCHING_CONTROL. What we're doing here:
&blockSwitchingControl->windowF[0][8-1]
is passing the address of windowF's [0][7]'th element. A multi-dimensional array is linear (continuous) memory so Int32 windowF[2][8] is properly sized for 16 Int32s to be stored in a "row" in memory. Something like:
windowF[2][8] => [0][1][2][3][4][5][6][7][8][9][A][B][C][D][E][F][10]
Thus, if I were to pass the address of windowF's [0][7] element, I'm really passing part of the array:
windowF[0][7] [0][1][2][3][4][5][6][7][8][9][A][B][C][D][E][F][10] //full array
-----------------------------^
So now inside the SrchMaxWithIndex() I have _in[] = an array of Int32's which is equivalent to part of windowF's array. So you can see they're passing an "array's worth of values", even if it's not how you'd expect.

The address of an element of an array is being passed (note the & in &blockSwitchingControl->windowN[0][8-1]).
So in[i+1] will be equivalent to blockSwitchingControl->windowN[0][8], which is, presumably, a valid item in the array.

Related

C# Intersecting two rangers not behaving as expected

I am trying to use two lists to determine if the list intersects each other.
As far as I am aware range one should not intersect with range two, so it should spit out an empty list. However as you can see in the list I am getting numbers that are never even included in the two ranges provided.
Am I doing something wrong or is this a weird bug? I have fed this to the OpenAI chatbot too and it agrees with me that this should not be happening. (Cool bot btw).
Thanks for any help!!!
The code:
public void Challenge2()
{
List<(Int32 min1, Int32 max1, Int32 min2, Int32 max2)> _numbers = new(){(64, 67, 43, 63)};
Int32 count = 0;
foreach ((Int32 min1, Int32 max1, Int32 min2, Int32 max2) in _numbers)
{
//if (min1 <= max2 && max2 > min2 || min2 <= max1 && max1 > min1)
var s = Enumerable.Intersect(Enumerable.Range(min1, max1), Enumerable.Range(min2, max2));
if (Enumerable.Intersect(Enumerable.Range(min1, max1), Enumerable.Range(min2, max2)).Any())
{
count++;
}
}
}
I think the basic problem here is your understanding of the arguments to Enumerable.Range. If you look at the documentation for Enumerable.Range(Int32, Int32), you'll see that the first int argument is the start number, and the second int argument is the count. Therefore, you should be creating your ranges like:
var intersection = Enumerable.Intersect(
Enumerable.Range(min1, max1 - min1 + 1),
Enumerable.Range(min2, max2 - min2 + 1));
Also, there's no need to calculate it twice (you do it a second time in the if condition). It's not clear to me what your count variable is supposed to represent, but probabaly one of the following should apply:
if (intersection.Any())
{
count++;
}
// Or just:
int count = intersection.Count();

for loop from intPtr, how?

How do I write a for loop to iterate over an array of floats, given the intPtr for the start of the array?
It's C# in Unity, so I know the bytes of a float are 4. But am having only crashes when trying to increment from the intPtr by the simple use of the number 4 as a value to increment by.
This is what's not working:
float myFloatVar = 42.42f
for ( int i = varIntPtr ; i < varIntPtr + 12 ; i+=4 ) {
presumedToBeAnArrayLocation[i] = myFloatVar * i;
}
given the intPtr for the start of the array?
If you have a pointer to the start of an array, then unless that array is externally pinned: your code is already irretrievably broken - an unmanaged pointer doesn't get updated with GC movement, so you now have undefined behaviour.
If we assume that it is pinned, or is unmanaged memory (and therefore not subject to GC movement), then something like:
float* typed = ptr.ToPointer();
for (int i = 0; i < count; i++)
{
float v = typed[i];
}
However, it is usually preferable to use spans when possible:
var typed = new Span<float>(ptr.ToPointer(), count);
foreach (var v in typed) {
}

Cartesian product subset returning set of mostly 0

I'm trying to calculate
If we calculated every possible combination of numbers from 0 to (c-1)
with a length of x
what set would occur at point i
For example:
c = 4
x = 4
i = 3
Would yield:
[0000]
[0001]
[0002]
[0003] <- i
[0010]
....
[3333]
This is very nearly the same problem as in the related question Logic to select a specific set from Cartesian set. However, because x and i are large enough to require the use of BigInteger objects, the code has to be changed to return a List, and take an int, instead of a string array:
int PossibleNumbers;
public List<int> Get(BigInteger Address)
{
List<int> values = new List<int>();
BigInteger sizes = new BigInteger(1);
for (int j = 0; j < PixelArrayLength; j++)
{
BigInteger index = BigInteger.Divide(Address, sizes);
index = (index % PossibleNumbers);
values.Add((int)index);
sizes *= PossibleNumbers;
}
return values;
}
This seems to behave as I'd expect, however, when I start using values like this:
c = 66000
x = 950000
i = (66000^950000)/2
So here, I'm looking for the ith value in the cartesian set of 0 to (c-1) of length 950000, or put another way, the halfway point.
At this point, I just get a list of zeroes returned. How can I solve this problem?
Notes: It's quite a specific problem, and I apologise for the wall-of-text, I do hope it's not too much, I was just hoping to properly explain what I meant. Thanks to you all!
Edit: Here are some more examples: http://pastebin.com/zmSDQEGC
Here is a generic base converter... it takes a decimal for the base10 value to convert into your newBase and returns an array of int's. If you need a BigInteger this method works perfectly well with just changing the base10Value to BigInteger.
EDIT: Converted method to BigInteger since that's what you need.
EDIT 2: Thanks phoog for pointing out BigInteger is base2 so changing the method signature.
public static int[] ConvertToBase(BigInteger value, int newBase, int length)
{
var result = new Stack<int>();
while (value > 0)
{
result.Push((int)(value % newBase));
if (value < newBase)
value = 0;
else
value = value / newBase;
}
for (var i = result.Count; i < length; i++)
result.Push(0);
return result.ToArray();
}
usage...
int[] a = ConvertToBase(13, 4, 4) = [0,0,3,1]
int[] b = ConvertToBase(0, 4, 4) = [0,0,3,1]
int[] c = ConvertToBase(1234, 12, 4) = [0,8,6,10]
However the probelm you specifically state is a bit large to test it on. :)
Just calculating 66000 ^ 950000 / 2 is a good bit of work as Phoog mentioned. Unless of course you meant ^ to be the XOR operator. In which case it's quite fast.
EDIT: From the comments... The largest base10 number that can be represented given a particular newBase and length is...
var largestBase10 = BigInteger.Pow(newBase, length)-1;
The first expression of the problem boils down to "write 3 as a 4-digit base-4 number". So, if the problem is "write i as an x-digit base-c number", or, in this case, "write (66000^950000)/2 as a 950000-digit base 66000 number", then does that make it easier?
If you're specifically looking for the halfway point of the cartesian product, it's not so hard. If you assume that c is even, then the most significant digit is c / 2, and the rest of the digits are zero. If your return value is all zeros, then you may have an off-by-one error, or the like, since actually only one digit is incorrect.

A workaround for a big multidimensional array (Jagged Array) C#?

I'm trying to initialize an array in three dimension to load a voxel world.
The total size of the map should be (2048/1024/2048). I tried to initialize an jagged array of "int" but I throw a memory exception. What is the size limit?
Size of my table: 2048 * 1024 * 2048 = 4'191'893'824
Anyone know there a way around this problem?
// System.OutOfMemoryException here !
int[][][] matrice = CreateJaggedArray<int[][][]>(2048,1024,2048);
// if i try normal Initialization I also throws the exception
int[, ,] matrice = new int[2048,1024,2048];
static T CreateJaggedArray<T>(params int[] lengths)
{
return (T)InitializeJaggedArray(typeof(T).GetElementType(), 0, lengths);
}
static object InitializeJaggedArray(Type type, int index, int[] lengths)
{
Array array = Array.CreateInstance(type, lengths[index]);
Type elementType = type.GetElementType();
if (elementType != null)
{
for (int i = 0; i < lengths[index]; i++)
{
array.SetValue(
InitializeJaggedArray(elementType, index + 1, lengths), i);
}
}
return array;
}
The maximum size of a single object in C# is 2GB. Since you are creating a multi-dimensional array rather than a jagged array (despite the name of your method) it is a single object that needs to contain all of those items, not several. If you actually used a jagged array then you wouldn't have a single item with all of that data (even though the total memory footprint would be a tad larger, not smaller, it's just spread out more).
Thank you so much to all the staff who tried to help me in understanding and solving my problem.
I tried several solution to be able to load a lot of data and stored in a table.
After two days, here are my tests and finally the solution which can store 4'191'893'824 entry into one array
I add my final solution, hoping someone could help
the goal
I recall the goal: Initialize an integer array [2048/1024/2048] for storing 4'191'893'824 data
Test 1: with JaggedArray method (failure)
system out of memory exception thrown
/* ******************** */
/* Jagged Array method */
/* ******************** */
// allocate the first dimension;
bigData = new int[2048][][];
for (int x = 0; x < 2048; x++)
{
// allocate the second dimension;
bigData[x] = new int[1024][];
for (int y = 0; y < 1024; y++)
{
// the last dimension allocation
bigData[x][y] = new int[2048];
}
}
Test 2: with List method (failure)
system out of memory exception thrown (divide the big array into several small array .. Does not work because "List <>" allows a maximum of "2GB" Ram allocution like a simple array unfortunately.)
/* ******************** */
/* List method */
/* ******************** */
List<int[,,]> bigData = new List<int[,,]>(512);
for (int a = 0; a < 512; a++)
{
bigData.Add(new int[256, 128, 256]);
}
Test 3: with MemoryMappedFile (Solution)
I finally finally found the solution!
Use the class "Memory Mapped File" contains the contents of a file in virtual memory.
MemoryMappedFile MSDN
Use with custom class that I found on codeproject here. The initialization is long but it works well!
/* ************************ */
/* MemoryMappedFile method */
/* ************************ */
string path = AppDomain.CurrentDomain.BaseDirectory;
var myList = new GenericMemoryMappedArray<int>(2048L*1024L*2048L, path);
using (myList)
{
myList.AutoGrow = false;
/*
for (int a = 0; a < (2048L * 1024L * 2048L); a++)
{
myList[a] = a;
}
*/
myList[12456] = 8;
myList[1939848234] = 1;
// etc...
}
From the MSDN documentation on Arrays (emphasis added)
By default, the maximum size of an Array is 2 gigabytes (GB). In a
64-bit environment, you can avoid the size restriction by setting the
enabled attribute of the gcAllowVeryLargeObjects configuration element
to true in the run-time environment. However, the array will still be
limited to a total of 4 billion elements, and to a maximum index of
0X7FEFFFFF in any given dimension (0X7FFFFFC7 for byte arrays and
arrays of single-byte structures).
So despite the above answers, even if you set the flag to allow a larger object size, the array is still limited to the 32bit limit of the number of elements.
EDIT: You'll likely have to redesign to eliminate the need for a multidimensional array as you're currently using it (as others have suggested, there are a few ways to do this between using actual jagged arrays, or some other collection of dimensions). Given the scale of the number of elements, it may be best to use a design that dynamically allocates objects/memory as used instead of arrays that have to pre-allocate it. (unless you don't mind using many gigabytes of memory) EDITx2: That is, perhaps you can define data structures that define filled content rather than defining every possible voxel in the world, even the "empty" ones. (I'm assuming the vast majority of voxels are "empty" rather than "filled")
EDIT: Although not trivial, especially if most of the space is considered "empty", then your best bet would be to introduce some sort of spatial tree that will let you efficiently query your world to see what objects are in a particular area. For example: Octrees (as Eric suggested) or RTrees
Creating this object as described, either as a standard array or as a jagged array, is going to destroy the locality of reference that allows your CPU to be performant. I recommend you use a structure like this instead:
class BigArray
{
ArrayCell[,,] arrayCell = new ArrayCell[32,16,32];
public int this[int i, int j, int k]
{
get { return (arrayCell[i/64, j/64, k/64])[i%64, j%64, k%16]; }
}
}
class ArrayCell
{
int[,,] cell = new int[64,64,64];
public int this[int i, int j, int k]
{
get { return cell[i,j,k]; }
}
}

Ascii Bytes Array To Int32 or Double

I'm re-writing alibrary with a mandate to make it totally allocation free. The goal is to have 0 collections after the app's startup phase is done.
Previously, there were a lot of calls like this:
Int32 foo = Int32.Parse(ASCIIEncoding.ASCII.GetString(bytes, start, length));
Which I believe is allocating a string. I couldn't find a C# library function that would do the same thing automatically. I looked at the BitConverter class, but it looks like that is only if your Int32 is encoded with the actual bytes that represent it. Here, I have an array of bytes representing Ascii characters that represent an Int32.
Here's what I did
public static Int32 AsciiBytesToInt32(byte[] bytes, int start, int length)
{
Int32 Temp = 0;
Int32 Result = 0;
Int32 j = 1;
for (int i = start + length - 1; i >= start; i--)
{
Temp = ((Int32)bytes[i]) - 48;
if (Temp < 0 || Temp > 9)
{
throw new Exception("Bytes In AsciiBytesToInt32 Are Not An Int32");
}
Result += Temp * j;
j *= 10;
}
return Result;
}
Does anyone know of a C# library function that already does this in a more optimal way? Or an improvement to make the above run faster (its going to be called millions of times during the day probably). Thanks!
Millions of times per day shouldn't be a problem - I'd expect that to be able to run hundreds of thousands of times per second. Personally I'd rewrite the above to only declare "temp" within the loop (and get rid of the Pascal-cases local variable names - urgh) but it should be okay.
The code would be more immediately understandable as:
int digit = bytes[i] - '0';
which does the same as your
Temp = ((Int32)bytes[i]) - 48;
line, but in a simpler way (IMO). They should behave exactly the same way.
On a general note, trying to write C# without any allocations is pretty harsh, and fights against the way the language and framework are designed. Do you believe this is actually a reasonable requirement? Admittedly I've heard about it being the way some games are written in managed code... but it does seem a bit odd.
Of course, you're going to allocate an exception if the bytes are inappropriate...
EDIT: Note that your code doesn't allow for negative numbers. Is that okay?

Categories

Resources