Feature suggestion: impl Default for Zip, and add Zip::with_shape() constructor

Offen
#1,227 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Anfängerfreundlichkeit
35/100
Issue-Typ
Feature
Klarheit
Größtenteils klar
Aktivitätsstatus
Veraltet
Tech-Stack
rust
Bereich
data

Rechercherichtung

Start by reviewing the existing Zip::from, Zip::and, and and_broadcast entry points and how they handle shapes and broadcasting. Compare the proposed Default and Zip::with_shape APIs with the motivating example; done means the API direction and resulting behavior are clearly agreed and validated.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

Motivating example: I'm computing 3D positions on a unit sphere from a uniform grid of (longitude, latitude) pairs. This is what it looks like now:

        const SHAPE: (usize, usize) = (HEIGHT, WIDTH);
        let cell_size_lon = TAU / WIDTH as f32;
        let cell_size_lat = PI / HEIGHT as f32;
        let lon = Array1::linspace(cell_size_lon, TAU - cell_size_lon, WIDTH)
            .into_shape((1, WIDTH)).unwrap();
        let lat = Array1::linspace(-FRAC_PI_2 + cell_size_lat, FRAC_PI_2 - cell_size_lat, HEIGHT)
            .into_shape((HEIGHT, 1)).unwrap();
        let pos = Zip::from(lat.mapv(f32::cos).broadcast(SHAPE).unwrap())
            .and(lat.mapv(f32::sin).broadcast(SHAPE).unwrap())
            .and(lon.mapv(f32::cos).broadcast(SHAPE).unwrap())
            .and(lon.mapv(f32::sin).broadcast(SHAPE).unwrap())
            .par_map_collect(|&cos_lat, &sin_lat, &cos_lon, &sin_lon| {
                Vec3::new(cos_lat * sin_lon, sin_lat, cos_lat * cos_lon)
            });

I know about azip! and par_azip! but I don't think the small reduction in character count outweighs the additional "magic" syntax, so I don't use them.

Notice the distinction between Zip::from and Zip::and even though these both serve the same purpose: add another producer to the Zip.

This lopsided distinction could be eliminated if Zip implemented Default (and/or had the customary zero-args new() constructor):

        let pos = Zip::default()
            .and(lat.mapv(f32::cos).broadcast(SHAPE).unwrap())
            .and(lat.mapv(f32::sin).broadcast(SHAPE).unwrap())
            .and(lon.mapv(f32::cos).broadcast(SHAPE).unwrap())
            .and(lon.mapv(f32::sin).broadcast(SHAPE).unwrap())
            .par_map_collect(|&cos_lat, &sin_lat, &cos_lon, &sin_lon| {
                Vec3::new(cos_lat * sin_lon, sin_lat, cos_lat * cos_lon)
            });

Even nicer (for this use case) would be if we could specify the shape once up front in the constructor, so we could use and_broadcast on all producers (not just the 2nd-4th):

        let pos = Zip::with_shape(SHAPE)
            .and_broadcast(lat.mapv(f32::cos))
            .and_broadcast(lat.mapv(f32::sin))
            .and_broadcast(lon.mapv(f32::cos))
            .and_broadcast(lon.mapv(f32::sin))
            .par_map_collect(|&cos_lat, &sin_lat, &cos_lon, &sin_lon| {
                Vec3::new(cos_lat * sin_lon, sin_lat, cos_lat * cos_lon)
            });

I can't tell whether this is at all feasible or desirable, just throwing it out there for your consideration, and so that other users with similar needs can chime in.

Vorherrschende Sprache
Rust
Sterne
4.3k
Forks
391
PR-Merge-Kennzahlen
Keine gemergten PRs in 30 T.

Beitragsleitfaden

Für dieses Repository ist kein Beitragsleitfaden indexiert

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus rust-ndarray/ndarray

Alle Issues in rust-ndarray/ndarray

Ähnliche Issues

Weitere Issues zu Rust

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.