1use crate::{arrays::QirArray, strings::convert};
7use std::{ffi::CString, rc::Rc};
8
9#[repr(C)]
10pub struct Range {
11 pub start: i64,
12 pub step: i64,
13 pub end: i64,
14}
15
16#[no_mangle]
17pub extern "C" fn quantum__rt__range_to_string(input: Range) -> *const CString {
18 let mut range_str = input.start.to_string() + "..";
19 if input.step != 1 {
20 range_str += &(input.step.to_string() + "..");
21 }
22 range_str += &input.end.to_string();
23
24 convert(&range_str)
25}
26
27#[no_mangle]
28pub unsafe extern "C" fn quantum__rt__array_slice_1d(
29 arr: *const QirArray,
30 range: Range,
31) -> *const QirArray {
32 let array = &*arr;
33 let item_size: i64 = array
34 .elem_size
35 .try_into()
36 .expect("Array element size too large for `usize` type on this platform.");
37 let mut slice = QirArray {
38 elem_size: array.elem_size,
39 data: Vec::new(),
40 };
41 let iter: Box<dyn Iterator<Item = i64>> = if range.step > 0 {
42 Box::new(range.start * item_size..=range.end * item_size)
43 } else {
44 Box::new((range.end * item_size..=range.start * item_size).rev())
45 };
46
47 let step: i64 = range.step.abs();
48 for i in iter.step_by((step * item_size).try_into().expect(
49 "Range step multiplied by item size is too large for `usize` type on this platform",
50 )) {
51 let index = i
52 .try_into()
53 .expect("Item index too large for `usize` type on this platform.");
54 let mut copy = vec![0; array.elem_size];
55 copy.copy_from_slice(&array.data[index..index + array.elem_size]);
56 slice.data.append(&mut copy);
57 }
58
59 Rc::into_raw(Rc::new(slice))
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65 use crate::{
66 arrays::{
67 __quantum__rt__array_concatenate, __quantum__rt__array_copy,
68 __quantum__rt__array_create_1d, __quantum__rt__array_get_element_ptr_1d,
69 __quantum__rt__array_get_size_1d, __quantum__rt__array_update_reference_count,
70 },
71 strings::{__quantum__rt__string_get_data, __quantum__rt__string_update_reference_count},
72 };
73 use std::ffi::CStr;
74
75 #[test]
76 fn test_range_to_string() {
77 let input4 = Range {
78 start: 0,
79 step: 1,
80 end: 9,
81 };
82 let str4 = quantum__rt__range_to_string(input4);
83 unsafe {
84 assert_eq!(
85 CStr::from_ptr(__quantum__rt__string_get_data(str4))
86 .to_str()
87 .unwrap(),
88 "0..9"
89 );
90 }
91 let input5 = Range {
92 start: 0,
93 step: 2,
94 end: 12,
95 };
96 let str5 = quantum__rt__range_to_string(input5);
97 unsafe {
98 assert_eq!(
99 CStr::from_ptr(__quantum__rt__string_get_data(str5))
100 .to_str()
101 .unwrap(),
102 "0..2..12"
103 );
104 }
105 unsafe {
106 __quantum__rt__string_update_reference_count(str4, -1);
107 __quantum__rt__string_update_reference_count(str5, -1);
108 }
109 }
110
111 #[test]
112 fn test_array_slicing() {
113 let arr = __quantum__rt__array_create_1d(1, 3);
114 unsafe {
115 assert_eq!(__quantum__rt__array_get_size_1d(arr), 3);
116 let first = __quantum__rt__array_get_element_ptr_1d(arr, 0);
117 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr, 0), 0);
118 *first = 42;
119 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr, 0), 42);
120 let second = __quantum__rt__array_get_element_ptr_1d(arr, 1);
121 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr, 1), 0);
122 *second = 31;
123 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr, 1), 31);
124 let arr2 = __quantum__rt__array_copy(arr, true);
125 assert_eq!(__quantum__rt__array_get_size_1d(arr2), 3);
126 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr2, 0), 42);
127 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr2, 1), 31);
128 let arr3 = __quantum__rt__array_concatenate(arr, arr2);
129 assert_eq!(__quantum__rt__array_get_size_1d(arr3), 6);
130 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr3, 0), 42);
131 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr3, 1), 31);
132 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr3, 2), 0);
133 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr3, 3), 42);
134 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr3, 4), 31);
135 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr3, 5), 0);
136 let arr4 = quantum__rt__array_slice_1d(
139 arr3,
140 Range {
141 start: 0,
142 step: 2,
143 end: 5,
144 },
145 );
146 assert_eq!(__quantum__rt__array_get_size_1d(arr4), 3);
147 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr4, 0), 42);
148 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr4, 1), 0);
149 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr4, 2), 31);
150 let arr5 = quantum__rt__array_slice_1d(
153 arr3,
154 Range {
155 start: 4,
156 step: -2,
157 end: 0,
158 },
159 );
160 assert_eq!(__quantum__rt__array_get_size_1d(arr5), 3);
161 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr5, 0), 31);
162 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr5, 1), 0);
163 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr5, 2), 42);
164 let arr6 = quantum__rt__array_slice_1d(
167 arr5,
168 Range {
169 start: 0,
170 step: 1,
171 end: -1,
172 },
173 );
174 assert_eq!(__quantum__rt__array_get_size_1d(arr6), 0);
176 __quantum__rt__array_update_reference_count(arr, -1);
177 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr2, 1), 31);
178 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr3, 0), 42);
179 __quantum__rt__array_update_reference_count(arr2, -1);
180 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr3, 0), 42);
181 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr3, 1), 31);
182 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr3, 2), 0);
183 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr3, 3), 42);
184 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr3, 4), 31);
185 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr3, 5), 0);
186 __quantum__rt__array_update_reference_count(arr3, -1);
187 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr4, 0), 42);
188 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr4, 1), 0);
189 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr4, 2), 31);
190 __quantum__rt__array_update_reference_count(arr4, -1);
191 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr5, 0), 31);
192 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr5, 1), 0);
193 assert_eq!(*__quantum__rt__array_get_element_ptr_1d(arr5, 2), 42);
194 __quantum__rt__array_update_reference_count(arr5, -1);
195 __quantum__rt__array_update_reference_count(arr6, -1);
196 }
197 }
198}