various questions

bearophile bearophileHUGS at lycos.com
Wed Jul 28 13:51:31 PDT 2010


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


More information about the Digitalmars-d-learn mailing list