Skip to content

Column-major vs. row-major broadcasting #57

@DavisVaughan

Description

@DavisVaughan

Hi xtensor team, really impressed with your product. I'm working on some examples using R, but I'm having a bit of trouble with the broadcasting piece. I think there might be a bug in the xtensor-r headers somewhere.

My guess is that the issue lies in the difference between how R and xtensor/python denote dimensions (if im not mistaken).

In R) (2, 3, 4) == (2 row, 3 col, 4 deep)
In python/xtensor) (2, 3, 4) == (2 deep, 3 rows, 4 cols)

With that said, take a look at my example below of a simple broadcast. It seems like the dimensions get mixed up somewhere along the way.

Cpp file:

https://gist.githubusercontent.com/DavisVaughan/1bebb3219fb08c48f91fa5ad3411643a/raw/fc75cc083672d7c26db62c47c1dea05a1eb5a0d0/xtensor-cpp.cpp

# download and source the file
url_link <- 'https://gist.githubusercontent.com/DavisVaughan/1bebb3219fb08c48f91fa5ad3411643a/raw/fc75cc083672d7c26db62c47c1dea05a1eb5a0d0/xtensor-cpp.cpp'
tf <- tempfile(fileext = ".cpp")
download.file(url_link, tf)
Rcpp::sourceCpp(tf)

mat <- matrix(c(1,2,3,4), ncol = 2)
mat
#>      [,1] [,2]
#> [1,]    1    3
#> [2,]    2    4

# I expect to be able to go from:
# [2,2] -> [2,2,1] == [2 rows, 2 cols] -> [2 rows, 2 cols, 1 deep]

mtrx_broadcast_cpp(mat, c(2, 2, 1))
#> , , 1
#> 
#>      [,1] [,2]
#> [1,]    1    2
#> [2,]    1    2
#> 
#> , , 2
#> 
#>      [,1] [,2]
#> [1,]    3    4
#> [2,]    3    4

# Okay...maybe I was supposed to do it the python way?
# [1, 2, 2] == [1 deep, 2 row, 2 col]
mtrx_broadcast_cpp(mat, c(1, 2, 2))
#> , , 1
#> 
#>      [,1] [,2]
#> [1,]    1    2
#> 
#> , , 2
#> 
#>      [,1] [,2]
#> [1,]    3    4

# Frustrating!

# this works with numpy, and I think it works with xtensor,
# the diffference is just the R vs xtensor way of defining dimensions
library(reticulate)

np <- import("numpy", convert = FALSE)

two_by_two <- np$ones(c(2L,2L))
two_by_two
#> [[1. 1.]
#>  [1. 1.]]

np$broadcast_to(two_by_two, c(1L,2L,2L))
#> [[[1. 1.]
#>   [1. 1.]]]

# more informative would be to do..
np$broadcast_to(two_by_two, c(3L,2L,2L))
#> [[[1. 1.]
#>   [1. 1.]]
#> 
#>  [[1. 1.]
#>   [1. 1.]]
#> 
#>  [[1. 1.]
#>   [1. 1.]]]

# I want ^ this behavior, but if possible, with R semantics where I would
# specify c(2,2,3) as the dimension to broadcast to, but it doesnt even
# work right now so lets focus on that

Created on 2018-11-06 by the reprex
package
(v0.2.0).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions