Jason Spencer:
> 1.  How can I cast a single dimension dynamic array to a multi-dimension
> static array?  I'm trying to do roughly the following:
>    auto data = cast(float[100][100])std.file.read(fname, fsize);

I have tried a natural implementation, but it doesn't work and I don't know why 
it doesn't work or how to fix it:

import std.file, std.stdio;
void main() {
    enum int N = 10;
    auto filename = "data.dat";
    auto data = slurp!(float[N][N])(filename, "%s")[0];
}


So I have written an ugly version:

import std.file, std.stdio, std.contracts;

void main() {
    enum int N = 10;
    alias float DataType;
    auto filename = "data.dat";

    // be careful with endiness
    enum size_t data_size = N * N * DataType.sizeof;
    void[] raw = std.file.read(filename, data_size);
    enforce(raw.length == data_size);
    DataType[N][N] data = void;
    data[0].ptr[0 .. N*N] = (cast(DataType[])raw)[];
}


But that creates dynamic arrays, copies them, etc. Ugly, unsafe and 
inefficient. So better to have unsafe and efficient code, going back to C:

import std.contracts, std.c.stdio;

void main() {
    enum int N = 10;
    alias float DataType;
    auto filename = "data.dat";

    DataType[N][N] data = void;

    auto fin = fopen((filename ~ '\0').ptr, "rb");
    enforce(fin != null);

    // be careful with endiness
    size_t nread = fread(data[0].ptr, DataType.sizeof, N * N, fin);
    enforce(nread == N * N);

    fclose(fin);
}


In D fixed-sized nD arrays are contiguous, so I think that code is correct.
Be careful with floats endinaness.
Other people maybe can give you better solutions. But the point is that a 
minimally useful Phobos2 must be able to read/write a binary basic type (like a 
matrix) from disk with no extra copying and allocations and with a safe and 
nice syntax.


> They're just arguments to some run-time function
> that actually initializes them.

Currently AAs are (mostly) run-time things. Things can change in future as CTFE 
gets better.


> 4.  Lastly, compiling.  In src/main.d, I had "import data.stats;", and in
> src/data/stats.d, I had "module data.stats;".  On the command line in src, I 
> figured
> I'd just have to say "dmd main.d" and I'd be good to go.  Or maybe "dmd -I.
> main.d" or "dmd -Idata main.d".  But I had to specify both files for the
> compiler, as in "dmd main.d data/stats.d" to avoid undefined symbols from
> stat.d at link time.  Is that right?  If so, how does dmd know where to get
> phobos files from?  Is there a slicker way to do this with dmd?

<sarcasm>Walter seems to think that Java and Python are too much handy on this, 
and he thinks it's not the work of the compiler to look for the file it needs 
by itself. Probably because this can become slow if a project has thousands of 
source files. So to make things clean and tidy it's better to never make dmd 
handy, even if your project is 2 files long. So you need to use an external 
tool to solve this problem. I use one named "bud" not being able to use the 
built-in one named rdmd, and Andrei didn't help me to learn how to use it and I 
have not found docs about it. There are other tools good for larger projects 
that of course are much harder to use.</sarcasm>  I have never appreciated all 
this situation. Good luck.


> But I decide
> these based on command-line arguments at run time.  So I need some
> slick way of mapping the run-time element size, row count, and column
> count into a static array type to instantiate my template with.

A basic brutal way to do that is to use a switch, that switches according to 
the runtime value to use the correctly compile-time instantiated template. If 
the switch becomes too much large you can use a string mixin to shrink it to 
few lines.

Bye,
bearophile

Reply via email to