basic_types/
basic_types.rs

1//! This example demonstrates how LibraryLink native data types can be used in Rust
2//! functions called via LibraryLink.
3
4use wolfram_library_link::{self as wll, NumericArray, UninitNumericArray};
5
6wll::generate_loader!(load_basic_types_functions);
7
8//======================================
9// Primitive data types
10//======================================
11
12//---------
13// square()
14//---------
15
16/// Define a function to square a number.
17///
18/// The exported LibraryLink function may be loaded and used by evaluating:
19///
20/// ```wolfram
21/// square = LibraryFunctionLoad["libbasic_types", "square", {Integer}, Integer];
22/// square[2]
23/// ```
24//
25// Export the `square` function via LibraryLink. This will generate a "wrapper" function
26// that correctly implements the lightweight LibraryLink <=> Rust conversion.
27#[wll::export]
28fn square(x: i64) -> i64 {
29    x * x
30}
31
32//-----------------
33// reverse_string()
34//-----------------
35
36#[wll::export]
37fn reverse_string(string: String) -> String {
38    string.chars().rev().collect()
39}
40
41//------------------
42// add2() and add3()
43//------------------
44
45#[wll::export]
46fn add2(x: i64, y: i64) -> i64 {
47    x + y
48}
49
50#[wll::export]
51fn add3(x: i64, y: i64, z: i64) -> i64 {
52    x + y + z
53}
54
55//======================================
56// NumericArray's
57//======================================
58
59//------------
60// total_i64()
61//------------
62
63// Load and use by evaluating:
64//
65// ```wolfram
66// total = LibraryFunctionLoad[
67//     "libbasic_types",
68//     "total_i64",
69//     {LibraryDataType[NumericArray, "Integer64"]},
70//     Integer
71// ];
72//
73// total[NumericArray[Range[100], "Integer64"]]
74// ```
75#[wll::export]
76fn total_i64(list: &NumericArray<i64>) -> i64 {
77    list.as_slice().into_iter().sum()
78}
79
80//---------------
81// positive_i64()
82//---------------
83
84/// Get the sign of every element in `list` as a numeric array of 0's and 1's.
85///
86/// The returned array will have the same dimensions as `list`.
87#[wll::export]
88fn positive_i64(list: &NumericArray<i64>) -> NumericArray<u8> {
89    let mut bools: UninitNumericArray<u8> =
90        UninitNumericArray::from_dimensions(list.dimensions());
91
92    for pair in list.as_slice().into_iter().zip(bools.as_slice_mut()) {
93        let (elem, entry): (&i64, &mut std::mem::MaybeUninit<u8>) = pair;
94
95        entry.write(u8::from(elem.is_positive()));
96    }
97
98    unsafe { bools.assume_init() }
99}
100
101//======================================
102// get_random_number()
103//======================================
104
105// Load and use by evaluating:
106//
107// ```wolfram
108// randomNumber = LibraryFunctionLoad[
109//     "libbasic_types",
110//     "xkcd_get_random_number",
111//     {},
112//     Integer
113// ];
114// randomNumber[]
115// ```
116#[wll::export(name = "xkcd_get_random_number")]
117fn get_random_number() -> i64 {
118    // chosen by fair dice roll.
119    // guaranteed to be random.
120    // xkcd.com/221
121    4
122}
123
124//======================================
125// raw_square()
126//======================================
127
128#[wll::export]
129fn raw_square(args: &[wll::sys::MArgument], ret: wll::sys::MArgument) {
130    if args.len() != 1 {
131        panic!("unexpected number of arguments");
132    }
133
134    let x: i64 = unsafe { *args[0].integer };
135
136    unsafe {
137        *ret.integer = x * x;
138    }
139}