#Creating fixed size matrix at runtime
1 messages · Page 1 of 1 (latest)
you could allocate slices for each row
and a slice of slices would be the matrix itself
how would i go about doing that
allocator.alloc(f32, row_width);
and then the matrix would be allocator.alloc([]f32, matrix_height);
youd probably wanna make the matrix, then loop through it and allocate each row and fill it
could you show me an example code
var matrix = try allocator.alloc([]f32, matrix_height);
for (matrix) |*m| {
m.* = try allocator.alloc(f32, row_width);
// fill row with 0s
@memset(m, 0);
}
what if i instead fill each cell with a struct?
will it make the struct for each cell
or one struct for all
itll be whatever data type T you want in each cell, i used f32 here just as an example, i dont know what you mean by one struct for all
var matrix = try allocator.alloc([]Cell, matrix_height);
for (matrix) |*m| {
m.* = try allocator.alloc(Cell, row_width);
// fill row with 0s
@memset(m, Cell{.value=0, other_stuff=...});
}
i might instead use ?Cell
i think thatll work? and itll be the same data copied into each cell
no reason to use ?Cell if theyre never going to be null after you init them
if memset doesnt work you can just do for (m) |c| c.* = Cell { … };
for this piece of code im getting error: type '*[]u8' is not an indexable pointer on the memset
ah m.*
yep 👍
i worded it wrong i think
i tested it
for (mat) |m| for (m) |*r| {
try stdout.print("matrix {}\n", .{&r});
};
and every cell points to the same place in memory
i want the opposite
so i assume i need a for loop?
try removing the & in front of the r
youre printing the address of the pointer to the element, instead of the address of the element. which is going to be the same thing every time.
why is &r the same for every eiteration
ohhhh
im curious now tho, how do i get the address of the element?
you already do, r is a pointer to each element
and if you print r it prints the address the pointer is holding
for (mat) |m| for (m) |*r| {
try stdout.print("matrix {}\n", .{r});
};
this prints out the element not the address:(
oh it worked with f32's for me but if it's a struct you need {*}
np 👍
If you do this, I'd do more this instead:
const matrix = try allocator.alloc([]f32, matrix_height);
const elems = try allocator.alloc(f32, matrix_height * row_width);
var i: usize = 0;
for (matrix) |*m| {
m.* = elems[i..][0..row_width];
i += row_width;
}
You could even compute the number of bytes needed ahead of time, and do this instead:
const cell_count = matrix_height * row_width;
const total_bytes_needed = (cell_count * @sizeOf(f32)) + (matrix_height * @sizeOf([]f32));
const backing = try allocator.alignedAlloc(u8, @alignOf([]f32), total_bytes_needed);
const fba_state = std.heap.FixedBufferAllocator.init(backing);
const fba = fba.allocator();
const matrix = try fba.alloc([]f32, matrix_height);
const elems = try fba.alloc(f32, cell_count);
var i: usize = 0;
for (matrix) |*m| {
m.* = elems[i..][0..row_width];
i += row_width;
}
This way, you only need allocator.free(backing);, rather than this for the first example:
allocator.free(elems);
allocator.free(matrix);
oh wow that makes a lot of sense lol
unfortunately its all going to be in a function, so that'd get messy (i think)
the first one tho
i dont really get that one
It's just makes one slice containing all elements, instead of allocating a slice per row.
Makes the allocation pattern simpler, and both easier and quicker to free it.
The second one simply takes this one step further by putting the elements and the column-slice into one allocation, rather than just the elements.
If it matters that much, one can put all that into a function, and then
const Matrix = struct {
backing: []u8,
columns: [][]f32,
elements: []f32,
};
...
return .{
.backing = backing,
.columns = matrix,
.elements = elems,
};