How to reorder the elements of an array in-place? [duplicate] - arrays

This question already has answers here:
How to swap the elements of an array, slice, or Vec?
(1 answer)
How to get mutable references to two array elements at the same time?
(8 answers)
Temporarily move out of borrowed content
(3 answers)
Closed 2 years ago.
I would like to write a function fn f<A>(xs: &mut [A; 9]) that reorders an array in-place from:
[a, b, c,
d, e, f,
g, h, i]
to:
[g, d, a,
h, e, b,
i, f, c]
I can't reassign the array due to moving elements out of array:
fn f1<A>(xs: &mut [A; 9]) {
*xs = [xs[6], xs[3], xs[0], xs[7], xs[4], xs[1], xs[8], xs[5], xs[2]];
}
error[E0508]: cannot move out of type `[A; 9]`, a non-copy array
--> src/lib.rs:2:12
|
2 | *xs = [xs[6], xs[3], xs[0], xs[7], xs[4], xs[1], xs[8], xs[5], xs[2]];
| ^^^^^
| |
| cannot move out of here
| move occurs because `xs[_]` has type `A`, which does not implement the `Copy` trait
I cannot do multiple mutable borrows:
fn f2<A>(xs: &mut [A; 9]) {
std::mem::swap(&mut xs[0], &mut xs[6]);
}
error[E0499]: cannot borrow `xs[_]` as mutable more than once at a time
--> src/lib.rs:2:32
|
2 | std::mem::swap(&mut xs[0], &mut xs[6]);
| -------------- ---------- ^^^^^^^^^^ second mutable borrow occurs here
| | |
| | first mutable borrow occurs here
| first borrow later used by call
There is no built-in function that does this transformation for me.
How to implement this?

Related

How to copy or reference a slice of bytes? [duplicate]

This question already has answers here:
How to get a slice as an array in Rust?
(7 answers)
How to convert a slice into an array reference?
(3 answers)
Closed 2 years ago.
How can I copy, or reference a slice of bytes from a larger array?
I only need to read them, but I want the size to be specified to catch errors at compile-time.
let foo = rand::thread_rng().gen::<[u8; 32]>();
let bar: [u8; 16] = foo[0..16];
let baz: &[u8; 16] = &foo[16..32];
The errors are:
error[E0308]: mismatched types
--> src/main.rs:64:22
|
64 | let bar: [u8; 16] = foo[0..16];
| -------- ^^^^^^^^^^ expected array `[u8; 16]`, found slice `[u8]`
| |
| expected due to this
error[E0308]: mismatched types
--> src/main.rs:65:23
|
65 | let baz: &[u8; 16] = &foo[16..32];
| --------- ^^^^^^^^^^^^ expected array `[u8; 16]`, found slice `[u8]`
| |
| expected due to this
|
= note: expected reference `&[u8; 16]`
found reference `&[u8]`
I can see that foo[0..16] is exactly 16 bytes, not a slice of unknown length [u8]. How do I help the compiler see this?
Your problem isn't that you can't reference a slice of bytes; it's that a slice is not an array.
Probably you want the arrayref crate or the TryInto trait. There's also some discussion on doing this automatically in this Github issue.

Bigquery - How to zip two arrays into one?

If I have two arrays in BigQuery that I know are of equal size. How can i zip them into one array of structs or an array of two element arrays or similar?
The following query gives me all possible combinations of x and y which is not what I want.
WITH test AS (
SELECT
['a', 'b', 'c'] as xs,
[1, 2, 3] as ys
)
SELECT struct(x, y) as pairs
FROM test, unnest(xs) as x, unnest(ys) as y
I would like to get something like this:
+--------+--------+
| pair.x | pair.y |
+--------+--------+
| a | 1 |
| b | 2 |
| c | 3 |
+--------+--------+
Use WITH OFFSET and the bracket operator:
WITH test AS (
SELECT
['a', 'b', 'c'] as xs,
[1, 2, 3] as ys
)
SELECT struct(x, ys[OFFSET(off)] as y) as pairs
FROM test, unnest(xs) as x WITH OFFSET off;

Is it possible to create a reference to block in Eigen3

I want to Create a global matrix
G=+---+---+
| A | B |
+---+---+
| C | D |
+---+---+
Is that possible to create a reference to each blocks? So that I can consider each block as a matrix individually?
Yes, there is the Ref class for that:
MatrixXd G(100,100); // global matrix
// reference to sub-blocks:
Ref<MatrixXd> A = G.topLeftCorner(50,50);
Ref<MatrixXd> B = G.topRightCorner(50,50);
Ref<MatrixXd> C = G.bottomLeftCorner(50,50);
Ref<MatrixXd> D = G.bottomRightCorner(50,50);
// Accessing/modifiying the submatrices:
A.setOnes();
B.setRandom();
C.setIdentity();
D = A+B+C;
If G is const, you can make Ref<const MatrixXd> to the sub-matrices (these are read-only, of course).

C - MPI: Parallel Processing of Column Arrays

I have a matrix (c) of 10x10 (M = 10) elements in which I divide the matrix by rows to be executed by 5 different processes (slaves = 5) with each process corresponding to 2 rows of that matrix.
offset = 0;
rows = (M / slaves);
MPI_Send(&c[offset][0], rows*M, MPI_DOUBLE, id_slave,0,MPI_COMM_WORLD);
offset= offset+rows;
Now I want to divide the matrix but by columns. I did the test as follows by changing array indices but not working:
MPI_Send(&c[0][offset], rows*M, MPI_DOUBLE, id_slave,0,MPI_COMM_WORLD);
Do you know how to do it? Thank you.
You are using the wrong datatype. As noted by Jonathan Dursi, you need to create a strided datatype that tells MPI how to access the memory in such a way that it matches the data layout of a column or a set of consecutive columns.
In your case, instead of
MPI_Send(&c[0][offset], rows*M, MPI_DOUBLE, id_slave, 0, MPI_COMM_WORLD);
you have to do:
MPI_Datatype dt_columns;
MPI_Type_vector(M, rows, M, MPI_DOUBLE, &dt_columns);
MPI_Type_commit(&dt_columns);
MPI_Send(&c[0][offset], 1, dt_columns, id_slave, 0, MPI_COMM_WORLD);
MPI_Type_vector(M, rows, M, MPI_DOUBLE, &dt_columns) creates a new MPI datatype that consists of M blocks of rows elements of MPI_DOUBLE each with the heads of the consecutive blocks M elements apart (stride M). Something like this:
|<------------ stride = M ------------->|
|<---- rows --->| |
+---+---+---+---+---+---+---+---+---+---+--
| x | x | x | x | | | | | | | ^
+---+---+---+---+---+---+---+---+---+---+ |
| x | x | x | x | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+
. . . . . . . . . . . M blocks
+---+---+---+---+---+---+---+---+---+---+
| x | x | x | x | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+ |
| x | x | x | x | | | | | | | v
+---+---+---+---+---+---+---+---+---+---+--
>> ------ C stores such arrays row-wise ------ >>
If you set rows equal to 1, then you create a type that corresponds to a single column. This type cannot be used to send multiple columns though, e.g., two columns, as MPI will look for the second one there, where the first one ends, which is at the bottom of the matrix. You have to tell MPI to pretend that a column is just one element wide, i.e. resize the datatype. This can be done using MPI_Type_create_resized:
MPI_Datatype dt_temp, dt_column;
MPI_Type_vector(M, 1, M, MPI_DOUBLE, &dt_temp);
MPI_Type_create_resized(dt_temp, 0, sizeof(double), &dt_column);
MPI_Type_commit(&dt_column);
You can use this type to send as many columns as you like:
// Send one column
MPI_Send(&c[0][offset], 1, dt_column, id_slave, 0, MPI_COMM_WORLD);
// Send five columns
MPI_Send(&c[0][offset], 5, dt_column, id_slave, 0, MPI_COMM_WORLD);
You can also use dt_column in MPI_Scatter[v] and/or MPI_Gather[v] to scatter and/or gather entire columns.
The problem with your code is the following:
your c array is continuous in memory, and in C it stored row-major order, and the dividing it by row like you do will just add constant offset from the beginning.
and the way you are going to divide it by columns just gives you wrong offset.
You can imagine it for 3x3 matrix and 3 slave processes:
a[3][3] = {{a00 a01 a02},
{a10 a11 a12},
{a20 a21 a22}}
which is actually in memory looks like:
A = {a00,a01,a02,a10,a11,a12,a20,a21,a22}
For example we want to send data to CPU with id = 1. In this case a[1][0] will point you to the forth element of A and the a[0][1] will point you to the second element of A. And the in both cases you just send the rows*M elements from the specific point in A.
In first case it will be:
a10,a11,a12
And in second case:
a01,a02,a10
One of the way to solve things you want is to transpose your matrix and the send it.
And also it is much natural to use MPI_Scatter than MPI_Send for this problem,
something like it explained here: scatter

Find product of integers at interval of X and update value at position 'i' in an array for N queries

I have given an array of integers of length up to 10^5 & I want to do following operation on array.
1-> Update value of array at any position i . (1 <= i <= n)
2-> Get products of number at indexes 0, X, 2X, 3X, 4X.... (J * X <= n)
Number of operation will be up to 10^5.
Is there any log n approach to answer query and update values.
(Original thought is to use Segment Tree but I think that it is not needed...)
Let N = 10^5, A:= original array of size N
We use 0-based notation when we saying indexing below
Make a new array B of integers which of length up to M = NlgN :
First integer is equal to A[0];
Next N integers is of index 1,2,3...N of A; I call it group 1
Next N/2 integers is of index 2,4,6....; I call it group 2
Next N/3 integers 3,6,9.... I call it group 3
Here is an example of visualized B:
B = [A[0] | A[1], A[2], A[3], A[4] | A[2], A[4] | A[3] | A[4]]
I think the original thoughts can be used without even using Segment Tree..
(It is overkill when you think for operation 2, we always will query specific range on B instead of any range, i.e. we do not need that much flexibility and complexity to maintain the data structure)
You can create the new array B described above, also create another array C of length M, C[i] := products of Group i
For operation 1 simply use O(# factors of i) to see which Group(s) you need to update, and update the values in both B and C (i.e. C[x]/old B[y] *new B[y])
For operation 2 just output corresponding C[i]
Not sure if I was wrong but this should be even faster and should pass the judge, if the original idea is correct but got TLE
As OP has added a new condition: for operation 2, we need to multiply A[0] as well, so we can special handle it. Here is my thought:
Just declare a new variable z = A[0], for operation 1, if it is updating index 0, update this variable; for operation 2, query using the same method above, and multiply by z afterwards.
I have updated my answer so now I simply use the first element of B to represent A[0]
Example
A = {1,4,6,2,8,7}
B = {1 | 4,6,2,8,7 | 6,8 | 2 | 8 | 7 } // O(N lg N)
C = {1 | 2688 | 48 | 2 | 8 | 7 } // O (Nlg N)
factorization for all possible index X (X is the index, so <= N) // O(N*sqrt(N))
opeartion 1:
update A[4] to 5: factors = 1,2,4 // Number of factors of index, ~ O(sqrt(N))
which means update Group 1,2,4 i.e. the corresponding elements in B & C
to locate the corresponding elements in B & C maybe a bit tricky,
but that should not increase the complexity
B = {1 | 4,6,2,5,7 | 6,5 | 2 | 5 | 7 } // O(sqrt(N))
C = {1 | 2688 | 48/8*5 | 2 | 8/8*5 | 7 } // O(sqrt(N))
update A[0] to 2:
B = {2 | 4,6,2,5,7 | 6,5 | 2 | 5 | 7 } // O(1)
C = {2 | 2688/8*5 | 48/8*5 | 2 | 8/8*5 | 7 } // O(1)
// Now A is actually {2,4,6,2,5,7}
operation 2:
X = 3
C[3] * C[0] = 2*2 = 4 // O(1)
X = 2
C[2] * C[0] = 30*2 = 60 // O(1)

Resources