Testing array ptr for offset 0...
Era Scarecrow via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Thu May 26 14:13:14 PDT 2016
On Thursday, 26 May 2016 at 11:47:13 UTC, ag0aep6g wrote:
> I don't follow. Why can't you use a built-in array? What can
> you do with the stand-in that you can't do with the array
> itself?
I can do the job with the built-in arrays, however the need for
another temporary array to keep track of lengths so I can slice
them after the fact is what i want to avoid. I'm also slicing
static arrays. I'm trying to see if this code would be more
efficient or not (if it is, it's not by much, which I'm sure has
to do with the cache more than anything else).
To do what I want currently it's something like...
enum Size = 1024, Other = 128;
Data[Size][Other] staticarray; //stack allocation
Data[][] sliced = staticarray[];
scan(sliced, condition);
void scan(ref Data[][] data, Condition cond) {
int lengths[Size];
foreach(i; ...) {
if (cond)
data[i][lengths[i]++] = ...
}
//cleanup/shrink
foreach(i, l; lengths)
data[i] = data[i][0 .. l];
}
By adding a struct overload for opOpAssign I can shrink it all
down to this, and avoid lengths entirely... As such internally
the length starts at 0, and checks are in place to ensure the
bounds are never exceeded.
void scan(ref Data[][] data, Condition cond) {
foreach(i; ...) {
if (cond)
data[i] ~= ...
}
}
> Seems a bit back and forth, but as far as I can see it works as
> you want. Why do you think the answer it gives is wrong? What
> answer does it give you?
The answer is wrong _because_ the code blows up. I inverted the
check to check if length is at offset 0 since (the length can
only be 1 and a better test), however it _still_ gives the wrong
answer. Curiously CTFE is fine with this casting as long as the
pointer stays in that one spot.
template isArrayLengthOffsetZero() {
bool check() {
size_t[] arr = new size_t[1];
return *(cast(size_t*) &arr) == 1;
}
enum isArrayLengthOffsetZero = check(); //wrong answer
// enum isArrayLengthOffsetZero = !check(); //right answer but
logically wrong
}
//test struct
struct S(T) {
static if (isArrayLengthOffsetZero!()) {
size_t length;
T* ptr;
} else {
T* ptr;
size_t length;
}
this(T* p) { ptr = p; }
//opOpAssign
}
unittest {
import std.stdio;
//union to get our overlapping data types
union X { string str; S!(immutable char) s_str;}
X x;
x.s_str = S!(immutable char)("t".ptr); //only ptr assigned
//writeln(x.str); //blows up
writeln(x.str.length); //not 0...
assert(x.str.length == 0); //fails
}
Most likely the internal array structure CTFE uses for the array
is inverted, and if that's the case the proper answer to how to
get the simple offset of ptr (or length) is a mess.
Forcing the inverted answer works, but this is a lot of overhead
to try and make an algorithm faster. Speedups are minimal at
best, so I'm about ready to drop this line of thought.
More information about the Digitalmars-d-learn
mailing list