D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 6345 - A different kind of vector operation
Summary: A different kind of vector operation
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P4 enhancement
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-07-18 12:15 UTC by bearophile_hugs
Modified: 2024-12-13 17:55 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description bearophile_hugs 2011-07-18 12:15:46 UTC
Currently (DMD 2.054) this is not allowed, but a vector op like this is sometimes useful to me:

struct Foo {
    int x, y;
    int[100] array;
}
void main() {
    auto foos = new Foo[100];
    foos[].y += 10; // ********
}


For the programmer I think the meaning of such code is easy enough to understand and use.

At the moment I don't see the need to define a operator overload for this too (I mean something like opSliceUnary).


Don notes:

> An interesting use case:
> void main()
> {
>     cdouble[100] foos;
>     foos[].re = 5.0;
> }



Wilfried Kirschenmann suggests:

> void main() {
>   auto foos = new Foo[100];
>   auto ints = new int[100]
>   ints = foos[].y;
> }
> 
> This would simplify the wrinting of numerous application, especially
> in the writing of image/video processing (eg. rgb2yuv conversions)
> This would also simplify the writing of template library transforming
> "array of struct" to "struct of arrays" in a transparent manner for
> the library user.


Andrej Mitrovic notes (I don't understand this):

> float[] buffers = malloc..;
> float*[] CBuffers = buffers[].ptr;
Comment 1 kennytm 2011-07-18 12:44:34 UTC
What if I define


ref int y(Foo[] f) {
    return f[0].x;
}


?
Comment 2 bearophile_hugs 2011-07-27 13:56:06 UTC
Another possible purpose. Given this matrix:

auto M = new double[][](10, 20);

This:

M[][1] = 1.0;

Means:

foreach (row; p)
    row[1] = 1.0;


This replaces some usages of std.range.transversal().
Comment 3 Don 2011-07-28 00:36:12 UTC
All these operations require the use of strided slices, which would be a huge amount of work to implement. Also, there are a plethora of corner cases.
Comment 4 bearophile_hugs 2011-07-28 05:15:59 UTC
(In reply to comment #3)
> All these operations require the use of strided slices, which would be a huge
> amount of work to implement. Also, there are a plethora of corner cases.

I see. Those corner cases are bad. If you think this is too much work for the gain I'll close this enhancement request, to leave similar functionalities to matrix libraries.
Comment 5 Nick Treleaven 2023-07-05 13:52:44 UTC
List comprehensions would cover these and avoid any ambiguity. They are also more expressive and composable than vector ops:

>    auto foos = new Foo[100];
>    foos[].y += 10; // ********
    
[e.y += 10 for e in foos];

Note this doesn't need to allocate an array as the result is not used.

>     cdouble[100] foos;
>     foos[].re = 5.0;

[e.re = 5.0 for e in foos];

>   auto foos = new Foo[100];
>   auto ints = new int[100]
>   ints = foos[].y;

ints = [e.y for e in foos];

> float[] buffers = malloc...;
> float*[] CBuffers = buffers[].ptr;

float*[] cBuffers = [e.ptr for e in buffers];

Also, type inference could be used `auto cBuffers = ` because the RHS is no longer ambiguous with `float*`.
(This would also solve Issue #2548).

> auto M = new double[][](10, 20);
> M[][1] = 1.0;

[e[1] = 1.0 for e in m];

And indexes mean they can cover vector ops too:

> a[] = b[] / c[];

a = [b[i] / e for i, e in c];

A benefit is that `b.length` can be larger than `c.length`. 
Also we can use the index variable e.g. to index b in reverse order.

The key benefit however is that we can use expressions not supported by vector ops such as function calls, comparisons and the conditional operator - see issue #5636.
Comment 6 Nick Treleaven 2023-07-17 10:23:41 UTC
A less drastic change would be this syntax, which also solves the ambiguities:

float*[] CBuffers = buffers[#].ptr;

m[#][1] = 1.0;

c[#] = a[#] < b[#]; // issue #5636

Note: issue #5636 was fixed by simply documenting that comparisons, equality, etc make the operation not a vector op, just an array comparison.
Comment 7 dlangBugzillaToGithub 2024-12-13 17:55:49 UTC
THIS ISSUE HAS BEEN MOVED TO GITHUB

https://github.com/dlang/dmd/issues/18355

DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB