Thanks to visit codestin.com
Credit goes to docs.rs

arrayfire/core/
macros.rs

1/// Macro to print the current stats of ArrayFire's memory manager.
2///
3/// `mem_info!` print 4 values:
4///
5///  Name                    | Description
6/// -------------------------|-------------------------
7///  Allocated Bytes         | Total number of bytes allocated by the memory manager
8///  Allocated Buffers       | Total number of buffers allocated
9///  Locked (In Use) Bytes   | Number of bytes that are in use by active arrays
10///  Locked (In Use) Buffers | Number of buffers that are in use by active arrays
11///
12///  The `Allocated Bytes` is always a multiple of the memory step size. The
13///  default step size is 1024 bytes. This means when a buffer is to be
14///  allocated, the size is always rounded up to a multiple of the step size.
15///  You can use [get_mem_step_size](./fn.get_mem_step_size.html) to check the
16///  current step size and [set_mem_step_size](./fn.set_mem_step_size.html) to
17///  set a custom resolution size.
18///
19///  The `Allocated Buffers` is the number of buffers that use up the allocated
20///  bytes. This includes buffers currently in scope, as well as buffers marked
21///  as free, ie, from arrays gone out of scope. The free buffers are available
22///  for use by new arrays that might be created.
23///
24///  The `Locked Bytes` is the number of bytes in use that cannot be
25///  reallocated at the moment. The difference of Allocated Bytes and Locked
26///  Bytes is the total bytes available for reallocation.
27///
28///  The `Locked Buffers` is the number of buffer in use that cannot be
29///  reallocated at the moment. The difference of Allocated Buffers and Locked
30///  Buffers is the number of buffers available for reallocation.
31///
32/// # Parameters
33///
34/// - `msg` is the message that is printed to screen before printing stats
35///
36/// # Examples
37///
38/// ```rust
39/// use arrayfire::{Dim4, device_mem_info, print, randu, mem_info};
40///
41/// let dims = Dim4::new(&[5, 5, 1, 1]);
42/// let a = randu::<f32>(dims);
43/// print(&a);
44/// mem_info!("Hello!");
45/// ```
46///
47/// Sample Output:
48///
49/// ```text
50/// AF Memory: Here
51/// Allocated [ Bytes | Buffers ] = [ 4096 | 4 ]
52/// In Use    [ Bytes | Buffers ] = [ 2048 | 2 ]
53/// ```
54#[macro_export]
55macro_rules! mem_info {
56    [$msg: expr] => {
57        {
58            let (abytes, abuffs, lbytes, lbuffs) = $crate::device_mem_info();
59            println!("AF Memory: {:?}", $msg);
60            println!("Allocated [Bytes | Buffers] = [ {} | {} ]", abytes, abuffs);
61            println!("In Use    [Bytes | Buffers] = [ {} | {} ]", lbytes, lbuffs);
62        }
63    };
64}
65
66/// Join multiple Arrays along a given dimension
67///
68/// All the Arrays provided to this macro should be of type `&Array`
69///
70/// # Examples
71///
72/// ```rust
73/// use arrayfire::{Dim4, join_many, print, randu};
74///
75/// let a = &randu::<f32>(Dim4::new(&[5, 3, 1, 1]));
76/// let b = &randu::<f32>(Dim4::new(&[5, 3, 1, 1]));
77/// let c = &randu::<f32>(Dim4::new(&[5, 3, 1, 1]));
78/// let d = join_many![2; a, b, c];
79/// print(&d);
80/// ```
81///
82/// # Panics
83///
84/// This macro just calls [join_many](./fn.join_many.html) function after collecting all
85/// the input arrays into a vector.
86// Using macro to implement join many wrapper
87#[macro_export]
88macro_rules! join_many {
89    [$dim: expr; $($x:expr),+] => {
90        {
91            let mut temp_vec = Vec::new();
92            $(
93                temp_vec.push($x);
94             )*
95            $crate::join_many($dim, temp_vec)
96        }
97    };
98}
99
100/// Print given message before printing out the Array to standard output
101///
102/// # Examples
103///
104/// ```rust
105/// use arrayfire::{Dim4, print_gen, randu, af_print};
106/// let dims = Dim4::new(&[3, 1, 1, 1]);
107/// let a = randu::<f32>(dims);
108/// af_print!("Create a 5-by-3 matrix of random floats on the GPU", a);
109/// ```
110///
111#[macro_export]
112macro_rules! af_print {
113    [$msg: expr, $x: expr] => {
114        {
115            $crate::print_gen(String::from($msg), &$x, Some(4));
116        }
117    };
118}
119
120/// Create a dim4 object from provided dimensions
121///
122/// The user can pass 1 or more sizes and the left over values will default to 1.
123#[macro_export]
124macro_rules! dim4 {
125    ($dim0:expr) => {
126        $crate::Dim4::new(&[$dim0, 1, 1, 1])
127    };
128    ($dim0:expr, $dim1:expr) => {
129        $crate::Dim4::new(&[$dim0, $dim1, 1, 1])
130    };
131    ($dim0:expr, $dim1:expr, $dim2:expr) => {
132        $crate::Dim4::new(&[$dim0, $dim1, $dim2, 1])
133    };
134    ($dim0:expr, $dim1:expr, $dim2:expr, $dim3:expr) => {
135        $crate::Dim4::new(&[$dim0, $dim1, $dim2, $dim3])
136    };
137}
138
139/// Create a sequence object
140///
141/// If type is not provided, then the Seq will default to i32 type
142#[macro_export]
143macro_rules! seq {
144    () => {
145        $crate::Seq::<i32>::default()
146    };
147    ($sty:ty; $start:literal : $end:literal : $step:literal) => {
148        $crate::Seq::<$sty>::new($start, $end, $step)
149    };
150    ($start:literal : $end:literal : $step:literal) => {
151        $crate::Seq::<i32>::new($start, $end, $step)
152    };
153    ($sty:ty; $start:expr , $end:expr , $step:expr) => {
154        $crate::Seq::<$sty>::new($start, $end, $step)
155    };
156    ($start:expr , $end:expr , $step:expr) => {
157        $crate::Seq::<i32>::new($start, $end, $step)
158    };
159}
160
161/// Indexing into an existing Array
162///
163/// This macro call with return an Array that has a view of another Array. The Array returned due to
164/// the indexing operation will follow copy-on-write semantics. The Array identifier taken by this
165/// macro is passed to the relevant internal functions as a borrowed reference. Thus, this identifier
166/// will be still available for futher use after the macro call.
167///
168/// The following types of inputs are matched by this macro.
169///
170/// - A simple Array identifier.
171/// - An Array with slicing info for indexing.
172/// - An Array with slicing info and other arrays used for indexing.
173///
174/// Examples on how to use this macro are provided in the [tutorials book][1]
175///
176/// [1]: http://arrayfire.org/arrayfire-rust/book/indexing.html
177#[macro_export]
178macro_rules! view {
179    (@af_max_dims) => {
180        4
181    };
182    ( $array_ident:ident ) => {
183        $array_ident.clone()
184    };
185    ( $array_ident:ident [ $($start:literal : $end:literal : $step:literal),+ ] ) => {
186        {
187            #[allow(non_snake_case)]
188            let AF_MAX_DIMS: usize = view!(@af_max_dims);
189            let mut seq_vec = Vec::<$crate::Seq<i32>>::with_capacity(AF_MAX_DIMS);
190            $(
191                seq_vec.push($crate::seq!($start:$end:$step));
192             )*
193            $crate::index(&$array_ident, &seq_vec)
194        }
195    };
196    (@set_indexer $idim:expr, $idxr:ident, $lterm:expr) => {
197        {
198            $idxr.set_index(&$lterm, $idim, None);
199        }
200    };
201    (@set_indexer $idim:expr, $idxr:ident, $hterm:expr, $($tterm:expr),*) => {
202        {
203            $idxr.set_index(&$hterm, $idim, None);
204            view!(@set_indexer $idim + 1, $idxr, $($tterm),*);
205        }
206    };
207    ($array_ident:ident [ $($_e:expr),+ ]) => {
208        {
209            let mut idxrs = $crate::Indexer::default();
210            view!(@set_indexer 0, idxrs, $($_e),*);
211            $crate::index_gen(&$array_ident, idxrs)
212        }
213    };
214}
215
216/// Macro to evaluate individual Arrays or assignment operations
217///
218/// - Evaluate on one or more Array identifiers: essentially calls [Array::eval][4] on each of those
219///   Array objects individually.
220///
221///   ```rust
222///   use arrayfire::{dim4, eval, randu};
223///   let dims = dim4!(5, 5);
224///   let a = randu::<f32>(dims);
225///   let b = a.clone();
226///   let c = a.clone();
227///   let d = a.clone();
228///   let x = a - b;
229///   let y = c * d;
230///   eval!(&x, &y);
231///   ```
232///
233/// - Evaluate assignment operations: This is essentially syntactic sugar for modifying portions of
234///   Array with another Array using a combination of [Sequences][1] and/or [Array][2] objects.
235///   Full examples for this use case are provided in the [tutorials book][3]
236///
237/// [1]: http://arrayfire.org/arrayfire-rust/arrayfire/struct.Seq.html
238/// [2]: http://arrayfire.org/arrayfire-rust/arrayfire/struct.Array.html
239/// [3]: http://arrayfire.org/arrayfire-rust/book/indexing.html
240/// [4]: http://arrayfire.org/arrayfire-rust/arrayfire/struct.Array.html#method.eval
241#[macro_export]
242macro_rules! eval {
243    ( $l:ident [ $($lb:literal : $le:literal : $ls:literal),+ ] =
244      $r:ident [ $($rb:literal : $re:literal : $rs:literal),+ ]) => {
245        {
246            #[allow(non_snake_case)]
247            let AF_MAX_DIMS: usize = view!(@af_max_dims);
248            let mut seq_vec = Vec::<$crate::Seq<i32>>::with_capacity(AF_MAX_DIMS);
249            $(
250                seq_vec.push($crate::seq!($lb:$le:$ls));
251             )*
252            let mut idxrs = $crate::Indexer::default();
253            for i in 0..seq_vec.len() {
254                idxrs.set_index(&seq_vec[i], i as u32, None);
255            }
256            let eq_rterm = $crate::view!($r[ $($rb:$re:$rs),+ ]);
257            $crate::assign_gen(&mut $l, &idxrs, &eq_rterm);
258        }
259    };
260    ( $l:ident [ $($lb:literal : $le:literal : $ls:literal),+ ] = $r:expr ) => {
261        {
262            #[allow(non_snake_case)]
263            let AF_MAX_DIMS: usize = view!(@af_max_dims);
264            let mut seq_vec = Vec::<$crate::Seq<i32>>::with_capacity(AF_MAX_DIMS);
265            $(
266                seq_vec.push($crate::seq!($lb:$le:$ls));
267             )*
268            let mut idxrs = $crate::Indexer::default();
269            for i in 0..seq_vec.len() {
270                idxrs.set_index(&seq_vec[i], i as u32, None);
271            }
272            $crate::assign_gen(&mut $l, &idxrs, &$r);
273        }
274    };
275    ($lhs:ident [ $($lhs_e:expr),+ ] = $rhs:ident [ $($rhs_e:expr),+ ]) => {
276        {
277            let eq_rterm = $crate::view!($rhs[ $($rhs_e),+ ]);
278            let mut idxrs = $crate::Indexer::default();
279            view!(@set_indexer 0, idxrs, $($lhs_e),*);
280            $crate::assign_gen(&mut $lhs, &idxrs, &eq_rterm);
281        }
282    };
283    ($lhs:ident [ $($lhs_e:expr),+ ] = $rhs:expr) => {
284        {
285            let mut idxrs = $crate::Indexer::default();
286            view!(@set_indexer 0, idxrs, $($lhs_e),*);
287            $crate::assign_gen(&mut $lhs, &idxrs, &$rhs);
288        }
289    };
290    [$($x:expr),+] => {
291        {
292            let mut temp_vec = Vec::new();
293            $(
294                temp_vec.push($x);
295             )*
296            $crate::eval_multiple(temp_vec)
297        }
298    };
299}
300
301/// Create an array of given shape filled with a single value a.k.a constant array
302///
303/// # Examples
304///
305/// ```rust
306/// # use arrayfire::{constant};
307/// let _zeros_1d = constant!(0.0f32; 10);
308/// let _ones_3d = constant!(1u32; 3, 3, 3);
309///
310/// let dim = 10;
311/// let mix_shape = constant!(42.0f32; dim, 10);
312/// ```
313#[macro_export]
314macro_rules! constant {
315    ($value:expr; $($dim:expr),+) => {
316        $crate::constant($value, $crate::dim4!($($dim),*))
317    };
318}
319
320/// Create an array of given shape sampled from uniform distribution
321///
322/// If no type argument is specified, the data type defaults to 32 bit floats.
323///
324/// # Examples
325///
326/// ```rust
327/// # use arrayfire::{randu};
328/// let mat10x10 = randu!(10, 10);
329/// ```
330#[macro_export]
331macro_rules! randu {
332    ($($dim:expr),+) => { $crate::randu::<f32>($crate::dim4!($($dim),*)) };
333    ($type:ty; $($dim:expr),+) => { $crate::randu::<$type>($crate::dim4!($($dim),*)) };
334}
335
336/// Create an array of given shape sampled from normal distribution
337///
338/// If no type argument is specified, the data type defaults to 32 bit floats.
339///
340/// # Examples
341///
342/// ```rust
343/// # use arrayfire::{randn};
344/// let mat10x10 = randn!(10, 10);
345/// ```
346#[macro_export]
347macro_rules! randn {
348    ($($dim:expr),+) => { $crate::randn::<f32>($crate::dim4!($($dim),*)) };
349    ($type:ty; $($dim:expr),+) => { $crate::randn::<$type>($crate::dim4!($($dim),*)) };
350}
351
352#[cfg(test)]
353mod tests {
354    use super::super::array::Array;
355    use super::super::data::constant;
356    use super::super::device::set_device;
357    use super::super::index::index;
358    use super::super::random::randu;
359
360    #[test]
361    fn dim4_construction() {
362        let dim1d = dim4!(2);
363        let dim2d = dim4!(2, 3);
364        let dim3d = dim4!(2, 3, 4);
365        let dim4d = dim4!(2, 3, 4, 2);
366        let _dimn = dim4!(dim1d[0], dim2d[1], dim3d[2], dim4d[3]);
367    }
368
369    #[test]
370    fn seq_construction() {
371        let default_seq = seq!();
372        let _range_1_to_10_step_1 = seq!(0:9:1);
373        let _range_1_to_10_step_1_2 = seq!(f32; 0.0:9.0:1.5);
374        let _range_from_exprs = seq!(default_seq.begin(), default_seq.end(), default_seq.step());
375        let _range_from_exprs2 = seq!(f32; default_seq.begin() as f32,
376                 default_seq.end() as f32, default_seq.step() as f32);
377    }
378
379    #[test]
380    fn seq_view() {
381        set_device(0);
382        let mut dim4d = dim4!(5, 3, 2, 1);
383        dim4d[2] = 1;
384
385        let a = randu::<f32>(dim4d);
386        let seqs = &[seq!(1:3:1), seq!()];
387        let _sub = index(&a, seqs);
388    }
389
390    #[test]
391    fn seq_view2() {
392        set_device(0);
393        // ANCHOR: seq_view2
394        let a = randu::<f32>(dim4!(5, 5));
395        let _sub = view!(a[1:3:1, 1:1:0]); // 1:1:0 means all elements along axis
396
397        // ANCHOR_END: seq_view2
398    }
399
400    #[test]
401    fn view_macro() {
402        set_device(0);
403        let dims = dim4!(5, 5, 2, 1);
404        let a = randu::<f32>(dims);
405        let b = a.clone();
406        let c = a.clone();
407        let d = a.clone();
408        let e = a.clone();
409
410        let _v = view!(a);
411
412        let _m = view!(c[1:3:1, 1:3:2]);
413
414        let x = seq!(1:3:1);
415        let y = seq!(1:3:2);
416        let _u = view!(b[x, y]);
417
418        let values: [u32; 3] = [1, 2, 3];
419        let indices = Array::new(&values, dim4!(3, 1, 1, 1));
420        let indices2 = Array::new(&values, dim4!(3, 1, 1, 1));
421
422        let _w = view!(d[indices, indices2]);
423
424        let _z = view!(e[indices, y]);
425    }
426
427    #[test]
428    fn eval_assign_seq_indexed_array() {
429        set_device(0);
430        let dims = dim4!(5, 5);
431        let mut a = randu::<f32>(dims);
432        //print(&a);
433        //[5 5 1 1]
434        //    0.6010     0.5497     0.1583     0.3636     0.6755
435        //    0.0278     0.2864     0.3712     0.4165     0.6105
436        //    0.9806     0.3410     0.3543     0.5814     0.5232
437        //    0.2126     0.7509     0.6450     0.8962     0.5567
438        //    0.0655     0.4105     0.9675     0.3712     0.7896
439
440        let b = randu::<f32>(dims);
441        //print(&b);
442        //[5 5 1 1]
443        //    0.8966     0.5143     0.0123     0.7917     0.2522
444        //    0.0536     0.3670     0.3988     0.1654     0.9644
445        //    0.5775     0.3336     0.9787     0.8657     0.4711
446        //    0.2908     0.0363     0.2308     0.3766     0.3637
447        //    0.9941     0.5349     0.6244     0.7331     0.9643
448
449        let d0 = seq!(1:2:1);
450        let d1 = seq!(1:2:1);
451        let s0 = seq!(1:2:1);
452        let s1 = seq!(1:2:1);
453        eval!(a[d0, d1] = b[s0, s1]);
454        //print(&a);
455        //[5 5 1 1]
456        //    0.6010     0.5497     0.1583     0.3636     0.6755
457        //    0.0278     0.3670     0.3988     0.4165     0.6105
458        //    0.9806     0.3336     0.9787     0.5814     0.5232
459        //    0.2126     0.7509     0.6450     0.8962     0.5567
460        //    0.0655     0.4105     0.9675     0.3712     0.7896
461    }
462
463    #[test]
464    fn eval_assign_array_to_seqd_array() {
465        set_device(0);
466        // ANCHOR: macro_seq_assign
467        let mut a = randu::<f32>(dim4!(5, 5));
468        let b = randu::<f32>(dim4!(2, 2));
469        eval!(a[1:2:1, 1:2:1] = b);
470        // ANCHOR_END: macro_seq_assign
471    }
472
473    #[test]
474    fn macro_seq_array_assign() {
475        set_device(0);
476        // ANCHOR: macro_seq_array_assign
477        let values: [f32; 3] = [1.0, 2.0, 3.0];
478        let indices = Array::new(&values, dim4!(3));
479        let seq4gen = seq!(0:2:1);
480        let mut a = randu::<f32>(dim4!(5, 3));
481
482        let b = constant(2.0 as f32, dim4!(3, 3));
483
484        eval!(a[indices, seq4gen] = b);
485        // ANCHOR_END: macro_seq_array_assign
486    }
487
488    #[test]
489    fn constant_macro() {
490        set_device(0);
491        let _zeros_1d = constant!(0.0f32; 10);
492        let _zeros_2d = constant!(0.0f64; 5, 5);
493        let _ones_3d = constant!(1u32; 3, 3, 3);
494        let _twos_4d = constant!(2u16; 2, 2, 2, 2);
495
496        let dim = 10;
497        let _mix_shape = constant!(42.0f32; dim, 10);
498    }
499
500    #[test]
501    fn rand_macro() {
502        set_device(0);
503        let _ru5x5 = randu!(5, 5);
504        let _rn5x5 = randn!(5, 5);
505        let _ruu32_5x5 = randu!(u32; 5, 5);
506        let _ruu8_5x5 = randu!(u8; 5, 5);
507    }
508}