Jump to page: 1 2
Thread overview
Setting a hard limit on slice size, is this possible?
Aug 06, 2021
james.p.leblanc
Aug 06, 2021
Paul Backus
Aug 06, 2021
james.p.leblanc
Aug 06, 2021
Tejas
Aug 06, 2021
Tejas
Aug 06, 2021
Tejas
Aug 06, 2021
james.p.leblanc
Aug 06, 2021
H. S. Teoh
Aug 06, 2021
Tejas
Aug 06, 2021
Paul Backus
Aug 07, 2021
Tejas
Aug 07, 2021
Paul Backus
Aug 07, 2021
james.p.leblanc
Aug 07, 2021
Tejas
Aug 07, 2021
Paul Backus
Aug 07, 2021
Tejas
Aug 07, 2021
Paul Backus
Aug 08, 2021
Tejas
Aug 08, 2021
james.p.leblanc
Aug 07, 2021
Tejas
August 06, 2021

I am aware of the "capacity" concept with slices.

But, I would like to know if it is possible to set a
hard limit on a slice size.

I prefer it to error and crash instead of a doing an
extension or reallocation.

I understand my question screams of "convoluted
thinking". But, I need to align my slice according to
certain criteria.

(Alternatively, I could use an array ... if I could
align that according to criteria known at compile
time. Is this possible?).

I have a working solution (ugly trick, maybe is a
better description) to align my slice as desired.

But, the solution would be more robust if I could
guarantee that the slice is never moved in memory.

Any thoughts, hints, etc are welcome!

James

August 06, 2021

On Friday, 6 August 2021 at 10:50:19 UTC, james.p.leblanc wrote:

>

I am aware of the "capacity" concept with slices.

But, I would like to know if it is possible to set a
hard limit on a slice size.

I prefer it to error and crash instead of a doing an
extension or reallocation.

I don't think there's any way to make built-in slices behave like this, but you can pretty easily define your own wrapper type:

struct MySlice(T, size_t maxLength)
{
    private T[] payload;

    invariant(payload.length <= maxLength);

    this(T[] slice) { payload = slice; }

    T opIndex(size_t i) { return payload[i]; }

    // etc.
}
August 06, 2021

On Friday, 6 August 2021 at 11:58:59 UTC, Paul Backus wrote:

>

struct MySlice(T, size_t maxLength)
{
private T[] payload;
invariant(payload.length <= maxLength);
this(T[] slice) { payload = slice; }
T opIndex(size_t i) { return payload[i]; }
// etc.
}


Paul,

Thanks very much for your reply.  I understand only
a fraction of the suggested solution.  I will need to
digest this a bit, and do some more background reading
on templates.

My initial, naive attempts to use this in a simple main()
were unsuccessful.  I'll keep plugging at it ...

Best Regards,
James
August 06, 2021

On Friday, 6 August 2021 at 16:32:59 UTC, james.p.leblanc wrote:

>

On Friday, 6 August 2021 at 11:58:59 UTC, Paul Backus wrote:

>

struct MySlice(T, size_t maxLength)
{
private T[] payload;
invariant(payload.length <= maxLength);
this(T[] slice) { payload = slice; }
T opIndex(size_t i) { return payload[i]; }
// etc.
}


Paul,

Thanks very much for your reply.  I understand only
a fraction of the suggested solution.  I will need to
digest this a bit, and do some more background reading
on templates.

My initial, naive attempts to use this in a simple main()
were unsuccessful.  I'll keep plugging at it ...

Best Regards,
James

If you want something even simpler, maybe this could help:

void setCapacity(int/*or whatever type you want*/ a[], ulong capacity){
    assert(capacity < 100/*whatever you want to set*/);
    a.length = capacity;
}

void main(){
     int[] arr;
     setCapacity(arr, 50);//works :D
     //setCapacity(arr, 1000);// fails :(
}

Of course, this won't work if you want to resize the capacity natively, ie, by using .length directly; then you will have to use Paul's solution.

If you still have difficulties, please ping.

Also, if you're completely new, please try the book "programming in D", it is a marvellous resource.
link:
http://ddili.org/ders/d.en/

August 06, 2021

On Friday, 6 August 2021 at 17:16:28 UTC, Tejas wrote:

>

On Friday, 6 August 2021 at 16:32:59 UTC, james.p.leblanc wrote:

>

On Friday, 6 August 2021 at 11:58:59 UTC, Paul Backus wrote:

>

[...]


Paul,

Thanks very much for your reply.  I understand only
a fraction of the suggested solution.  I will need to
digest this a bit, and do some more background reading
on templates.

My initial, naive attempts to use this in a simple main()
were unsuccessful.  I'll keep plugging at it ...

Best Regards,
James

If you want something even simpler, maybe this could help:

void setCapacity(int[] a)// not int a[]

August 06, 2021

On Friday, 6 August 2021 at 10:50:19 UTC, james.p.leblanc wrote:

>

I am aware of the "capacity" concept with slices.

But, I would like to know if it is possible to set a
hard limit on a slice size.

I prefer it to error and crash instead of a doing an
extension or reallocation.

I understand my question screams of "convoluted
thinking". But, I need to align my slice according to
certain criteria.

(Alternatively, I could use an array ... if I could
align that according to criteria known at compile
time. Is this possible?).

I have a working solution (ugly trick, maybe is a
better description) to align my slice as desired.

But, the solution would be more robust if I could
guarantee that the slice is never moved in memory.

Any thoughts, hints, etc are welcome!

James

Okay we were overthinking the solution.

Just use a static array

int[your_max_length]/*or whatever type*/ var;

You're good to go!

I almost feel stupid now lol

August 06, 2021

mes
On Friday, 6 August 2021 at 17:25:24 UTC, Tejas wrote:

>

Okay we were overthinking the solution.

Just use a static array

int[your_max_length]/*or whatever type*/ var;

You're good to go!

I almost feel stupid now lol

Hello Tejas,

Kind thanks for your replies ... all are appreciated.

However, do NOT feel stupid ... the motivation behind why
I cannot use a standard int[your_max_length] (in other words,
use a static array), is because I need to do a specified
memory alignment (known at compile time) on my slice, or array.

I understand that neither a slice or an array is capable to doing
an arbitrary memory alignment. (But, perhaps I am wrong about this ...)

I believe structs can be aligned, but need to learn more about
the speicific of that.

In the meantime, I have written a way to get an aligned slice from a
static array. Ugly beginner code is below. While I believe this basic
idea should work, I would like to guarantee that my slice does not get
moved in memory (destroying the alignment).

Ugly code here:


import std.stdio;

enum MAXLENGTH = 1024;
enum ALIGN = 128;

void main(){

// static array to allow creation of aligned slice
ubyte[MAXLENGTH+ALIGN] u;

writeln("u.ptr: ", u.ptr);
auto u_i = cast(ulong) u.ptr;

auto u_excess = u_i%ALIGN;
writeln("u_excess: ", u_excess);

ulong mustadd;
if(u_excess !=0){
mustadd = ALIGN-u_excess;
}
writeln("mustadd: ", mustadd);

// create aligned pointer for our needed slice
auto zp = cast(double*) (u.ptr + mustadd);

// create slice
double[] z = zp[0 .. MAXLENGTH];
writeln("z.ptr: ", z.ptr);
writeln("z.length: ", z.length);
auto z_i = cast(ulong) z.ptr;
auto z_excess = z_i%ALIGN;
writeln("z_excess: ", z_excess);
}

August 06, 2021
On Fri, Aug 06, 2021 at 06:02:01PM +0000, james.p.leblanc via Digitalmars-d-learn wrote: [...]
> However, do NOT feel stupid ... the motivation behind why
> I cannot use a standard int[your_max_length] (in other words,
> use a static array), is because I need to do a specified
> memory alignment (known at compile time) on my slice, or array.

I've never actually tried this myself, but have you looked into the `align` keyword in the D spec?  I'm not 100% sure whether it can be applied to static arrays (or arrays in general) but it might be worth a look.


> I understand that neither a slice or an array is capable to doing an arbitrary memory alignment.  (But, perhaps I am wrong about this ...)
> 
> I believe structs can be aligned, but need to learn more about the speicific of that.

One thing that might help you is if you had a struct with the appropriate align(...) declaration that wraps around your array elements. Pretty sure that would guarantee the alignment of array elements, which in turn should guarantee alignment of the array as a whole.


T

-- 
It is the quality rather than the quantity that matters. -- Lucius Annaeus Seneca
August 06, 2021

On Friday, 6 August 2021 at 18:02:01 UTC, james.p.leblanc wrote:

>

mes
On Friday, 6 August 2021 at 17:25:24 UTC, Tejas wrote:

>

Okay we were overthinking the solution.

Just use a static array

int[your_max_length]/*or whatever type*/ var;

You're good to go!

I almost feel stupid now lol

Hello Tejas,

Kind thanks for your replies ... all are appreciated.

However, do NOT feel stupid ... the motivation behind why
I cannot use a standard int[your_max_length] (in other words,
use a static array), is because I need to do a specified
memory alignment (known at compile time) on my slice, or array.

I understand that neither a slice or an array is capable to doing
an arbitrary memory alignment. (But, perhaps I am wrong about this ...)

I believe structs can be aligned, but need to learn more about
the speicific of that.

In the meantime, I have written a way to get an aligned slice from a
static array. Ugly beginner code is below. While I believe this basic
idea should work, I would like to guarantee that my slice does not get
moved in memory (destroying the alignment).

Ugly code here:


import std.stdio;

enum MAXLENGTH = 1024;
enum ALIGN = 128;

void main(){

// static array to allow creation of aligned slice
ubyte[MAXLENGTH+ALIGN] u;

writeln("u.ptr: ", u.ptr);
auto u_i = cast(ulong) u.ptr;

auto u_excess = u_i%ALIGN;
writeln("u_excess: ", u_excess);

ulong mustadd;
if(u_excess !=0){
mustadd = ALIGN-u_excess;
}
writeln("mustadd: ", mustadd);

// create aligned pointer for our needed slice
auto zp = cast(double*) (u.ptr + mustadd);

// create slice
double[] z = zp[0 .. MAXLENGTH];
writeln("z.ptr: ", z.ptr);
writeln("z.length: ", z.length);
auto z_i = cast(ulong) z.ptr;
auto z_excess = z_i%ALIGN;
writeln("z_excess: ", z_excess);
}

If you're being that specialized, don't bother with fundamental data types, the hunt for simplicity will lead you to create very complex things.

As HS Teoh said, take a look at align:
https://dlang.org/spec/attribute.html#align

Stealing Paul's answer now:

import std;

enum your_max_length = 1000;
enum your_align = 256;
struct MySlice(T/*, size_t maxLength*/)
{
    private align(your_align)T payload;

    //invariant(payload.length <= maxLength);

    //this(T[] slice) { payload = slice; }

    //T opIndex(size_t i) { return payload[i]; }
}
void main()
{
   MySlice!(int/*, 1000*/)[your_max_length] slice;
    writeln(slice.sizeof);
}
August 06, 2021

On Friday, 6 August 2021 at 19:03:53 UTC, Tejas wrote:

>

Stealing Paul's answer now:

import std;

enum your_max_length = 1000;
enum your_align = 256;
struct MySlice(T/*, size_t maxLength*/)
{
    private align(your_align)T payload;

    //invariant(payload.length <= maxLength);

    //this(T[] slice) { payload = slice; }

    //T opIndex(size_t i) { return payload[i]; }
}
void main()
{
   MySlice!(int/*, 1000*/)[your_max_length] slice;
    writeln(slice.sizeof);
}

You can actually pass the alignment as a parameter too:

struct Aligned(T, size_t alignment)
    if (alignment >= T.alignof)
{
    align(alignment) T payload;
    alias payload this;
}

void main()
{
    Aligned!(int, 16)[4] x;
    assert(x.alignof == 16);
    assert(x.sizeof == 64);

    Aligned!(int[4], 16) y;
    assert(y.alignof == 16);
    assert(y.sizeof == 16);
}
« First   ‹ Prev
1 2