Multidimensional Slice?

I am coding a sun position calculator in go, and the calculations use Periodic Terms which are set out in tables (see below).
I initially wanted to set them up as constants, but go does not support arrays or slices as constants.
It seems to me that a multidimensional slice may be the way to go.
The pattern I have seen to do this is as follows:
values := [][]int{}
// These are the first two rows.
row1 := []int{1, 2, 3}
row2 := []int{4, 5, 6}
// Append each row to the two-dimensional slice.
values = append(values, row1)
values = append(values, row2)

Is there 1) a better way to do this instead of using a slice and if so what is it?
2) If I have to use a multidimensional slice is there another way to build it without having to use the append() statement ( there are over 100 rows to append)

    {175347046.0,0,0},
    {3341656.0,4.6692568,6283.07585},
    {34894.0,4.6261,12566.1517},
    {3497.0,2.7441,5753.3849},
    {3418.0,2.8289,3.5231},
    {3136.0,3.6277,77713.7715},
    {2676.0,4.4181,7860.4194},
    {2343.0,6.1352,3930.2097},
    {1324.0,0.7425,11506.7698},
    {1273.0,2.0371,529.691},
    {1199.0,1.1096,1577.3435},
    {990,5.233,5884.927},
    {902,2.045,26.298},
    {857,3.508,398.149},
    {780,1.179,5223.694},
    {753,2.533,5507.553},
    {505,4.583,18849.228},
    {492,4.205,775.523},
    {357,2.92,0.067},
    {317,5.849,11790.629},
    {284,1.899,796.298},
    {271,0.315,10977.079},
    {243,0.345,5486.778},
    {206,4.806,2544.314},
    {205,1.869,5573.143},
    {202,2.458,6069.777},
    {156,0.833,213.299},
    {132,3.411,2942.463},
    {126,1.083,20.775},
    {115,0.645,0.98},
    {103,0.636,4694.003},
    {102,0.976,15720.839},

hi,

note that what you are proposing isn’t really a multidimensional slice, but rather “ragged slices” :slight_smile:
(ie: the memory locality of the elements isn’t that good.)

that said, you could do something like this:

values := [][]int{
   {1,2,3},
   {4,5,6},
   ...
   {42,42,42},
}

another approach that is more memory-locality friendly:

const (
  nrows = 100
  ncols = 3
)

type NdArray [nrows*ncols]int
func (arr*NdArray) Get(x, y int) int {
  return (*arr)[ncols*x + y]
}

values := NdArray{
   1,2,3,
   4,5,6,
   ...
   42,42,42,
}

see:
https://play.golang.org/p/hK98cbii8z

hth,
-s

3 Likes

Thanks for the assistance. I implemented your approach and it works just fine.
As a matter of interest, when you declare NdArray like so:
type NdArray [nrows*ncols]int
how do you discern whether you are declaring an array or a slice?

It’s an array. A slice is always []something as the size is not part of its type.

1 Like

If you are not opposed to using external libraries - package tensor fills your requirement quite well.

Here’s how to do it:

a := tensor.New(tensor.Of(tensor.Int), tensor.WithShape(1,3))

for _, row := range rows {
    // convert each []int into a *tensor.Dense
    // note - this doesn't cause extra allocations.
    r := tensor.New(tensor.WithBacking(row), tensor.WithShape(1,3))
    a, _ = a.Vstack(r)
}

Alternatively, if you want to constraint your data to only float64, you can also use Gonum’s mat64. It has a Stack method, which works similarly.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.