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}