1pub struct LatexExportState
20{
21 nr_qbits: usize,
25 nr_cbits: usize,
27
28 add_init: bool,
32 expand_composite: bool,
35
36 matrix: Vec<Vec<Option<String>>>,
41 in_use: Vec<bool>,
45 controlled: bool,
50 reserved_ranges: Vec<(usize, usize)>,
54 loops: Vec<(usize, usize, usize)>,
56 open_loops: Vec<(usize, usize)>
59}
60
61impl LatexExportState
62{
63 pub fn new(nr_qbits: usize, nr_cbits: usize) -> Self
68 {
69 LatexExportState
70 {
71 nr_qbits: nr_qbits,
72 nr_cbits: nr_cbits,
73 add_init: true,
74 expand_composite: true,
75 matrix: vec![],
76 in_use: vec![true; nr_qbits + nr_cbits],
77 controlled: false,
78 reserved_ranges: vec![],
79 loops: vec![],
80 open_loops: vec![]
81 }
82 }
83
84 fn total_nr_bits(&self) -> usize
86 {
87 self.nr_qbits + self.nr_cbits
88 }
89
90 fn add_column(&mut self)
95 {
96 let nr_bits = self.total_nr_bits();
97 self.matrix.push(vec![None; nr_bits]);
98 self.in_use.clear();
99 self.in_use.resize(nr_bits, false);
100 }
101
102 fn get_bit_indices(&self, qbits: &[usize], cbits: Option<&[usize]>)
103 -> crate::error::Result<Vec<usize>>
104 {
105 if let Some(&bit) = qbits.iter().find(|&&b| b >= self.nr_qbits)
106 {
107 return Err(crate::error::Error::InvalidQBit(bit));
108 }
109
110 let mut bits = qbits.to_vec();
111 if let Some(cbs) = cbits
112 {
113 if let Some(&bit) = cbs.iter().find(|&&b| b >= self.nr_cbits)
114 {
115 return Err(crate::error::Error::InvalidCBit(bit));
116 }
117 bits.extend(cbs.iter().map(|&b| self.nr_qbits + b));
118 }
119
120 Ok(bits)
121 }
122
123 pub fn reserve(&mut self, qbits: &[usize], cbits: Option<&[usize]>)
128 -> crate::error::Result<()>
129 {
130 let bits = self.get_bit_indices(qbits, cbits)?;
131 if bits.iter().any(|&b| self.in_use[b])
132 {
133 self.add_column();
134 }
135
136 Ok(())
137 }
138
139 fn reserve_all(&mut self)
144 {
145 if self.in_use.contains(&true)
146 {
147 self.add_column();
148 }
149 }
150
151 pub fn start_range_op(&mut self, qbits: &[usize], cbits: Option<&[usize]>)
157 -> crate::error::Result<()>
158 {
159 let bits = self.get_bit_indices(qbits, cbits)?;
160 if let Some(&first) = bits.iter().min()
161 {
162 let last = *bits.iter().max().unwrap();
163
164 if self.reserved_ranges.is_empty()
165 {
166 if self.in_use[first..=last].contains(&true)
167 {
168 self.add_column();
169 }
170 self.reserved_ranges.push((first, last));
171 }
172 else
173 {
174 let &(outer_first, outer_last) = self.reserved_ranges.last().unwrap();
175 if outer_first <= first && outer_last >= last
176 {
177 self.reserved_ranges.push((first, last));
178 }
179 else
180 {
181 return Err(crate::error::Error::from(crate::error::ExportError::RangeAlreadyOpen));
182 }
183 }
184
185 }
186
187 Ok(())
188 }
189
190 pub fn end_range_op(&mut self)
195 {
196 if let Some((first, last)) = self.reserved_ranges.pop()
197 {
198 for bit in first..=last
199 {
200 self.in_use[bit] = true;
201 }
202 }
203 }
204
205 pub fn set_field(&mut self, bit: usize, contents: String) -> crate::error::Result<()>
210 {
211 if self.reserved_ranges.is_empty()
212 {
213 self.reserve(&[bit], None)?;
214 }
215
216 let col = self.matrix.last_mut().unwrap();
217 col[bit] = Some(contents);
218 self.in_use[bit] = true;
219 Ok(())
220 }
221
222 pub fn set_measurement(&mut self, qbit: usize, cbit: usize, basis: Option<&str>)
228 -> crate::error::Result<()>
229 {
230 let cbit_idx = self.nr_qbits + cbit;
231 self.start_range_op(&[qbit], Some(&[cbit]))?;
232 let meter = if let Some(b) = basis
233 {
234 format!(r"\meterB{{{}}}", b)
235 }
236 else
237 {
238 String::from(r"\meter")
239 };
240 self.set_field(qbit, meter)?;
241 self.set_field(cbit_idx, format!(r"\cw \cwx[{}]", qbit as isize - cbit_idx as isize))?;
242 self.end_range_op();
243
244 Ok(())
245 }
246
247 pub fn set_reset(&mut self, qbit: usize) -> crate::error::Result<()>
251 {
252 self.set_field(qbit, String::from(r"\push{~\ket{0}~} \ar @{|-{}} [0,-1]"))
253 }
254
255 pub fn set_condition(&mut self, control: &[usize], target: u64, qbits: &[usize])
264 -> crate::error::Result<()>
265 {
266 if let Some(&bit) = qbits.iter().find(|&&b| b >= self.nr_qbits)
267 {
268 return Err(crate::error::Error::InvalidQBit(bit));
269 }
270 if let Some(&bit) = control.iter().find(|&&b| b >= self.nr_cbits)
271 {
272 return Err(crate::error::Error::InvalidCBit(bit));
273 }
274
275 if qbits.is_empty()
276 {
277 return Ok(());
278 }
279
280 let mut pbit = *qbits.iter().max().unwrap();
281 let mut bp: Vec<(usize, usize)> = control.iter().enumerate()
282 .map(|(pos, &idx)| (self.nr_qbits + idx, pos))
283 .collect();
284 bp.sort();
285 for (bit, pos) in bp
286 {
287 let ctrl = if (target & (1 << pos)) == 0 { r"\cctrlo" } else { r"\cctrl" };
288 self.set_field(bit, format!("{}{{{}}}", ctrl, pbit as isize - bit as isize))?;
289 pbit = bit;
290 }
291
292 Ok(())
293 }
294
295 pub fn add_block_gate(&mut self, qbits: &[usize], desc: &str) -> crate::error::Result<()>
302 {
303 let ranges = crate::support::get_ranges(qbits);
304 if !ranges.is_empty()
305 {
306 self.start_range_op(qbits, None)?;
307
308 let (first, last) = ranges[0];
309 if last == first
310 {
311 self.set_field(first, format!(r"\gate{{{}}}", desc))?;
312 }
313 else
314 {
315 self.set_field(first,
316 format!(r"\multigate{{{}}}{{{}}}", last-first, desc))?;
317 for bit in first+1..last+1
318 {
319 self.set_field(bit, format!(r"\ghost{{{}}}", desc))?;
320 }
321 }
322
323 let mut prev_last = last;
324 for &(first, last) in ranges[1..].iter()
325 {
326 if last == first
327 {
328 self.set_field(first,
329 format!(r"\gate{{{}}} \qwx[{}]", desc, prev_last as isize - first as isize))?;
330 }
331 else
332 {
333 self.set_field(first,
334 format!(r"\multigate{{{}}}{{{}}} \qwx[{}]",
335 last - first, desc, prev_last as isize - first as isize))?;
336 for bit in first+1..last+1
337 {
338 self.set_field(bit, format!(r"\ghost{{{}}}", desc))?;
339 }
340 }
341
342 prev_last = last;
343 }
344
345 self.end_range_op();
346 }
347
348 Ok(())
349 }
350
351 pub fn start_loop(&mut self, count: usize)
357 {
358 self.reserve_all();
359 self.open_loops.push((self.matrix.len() - 1, count));
360 }
361
362 pub fn end_loop(&mut self) -> crate::error::Result<()>
366 {
367 if let Some((start, count)) = self.open_loops.pop()
368 {
369 let end = self.matrix.len() - 1;
370 self.loops.push((start, end, count));
371 self.reserve_all();
372 Ok(())
373 }
374 else
375 {
376 Err(crate::error::Error::from(crate::error::ExportError::CantCloseLoop))
377 }
378 }
379
380 pub fn add_cds(&mut self, bit: usize, count: usize, label: &str) -> crate::error::Result<()>
386 {
387 self.reserve_all();
388 self.set_field(bit, format!(r"\cds{{{}}}{{{}}}", count, label))?;
389 self.reserve_all();
390 Ok(())
391 }
392
393 pub fn set_barrier(&mut self, qbits: &[usize]) -> crate::error::Result<()>
399 {
400 if let Some(&bit) = qbits.iter().find(|&&b| b >= self.nr_qbits)
401 {
402 return Err(crate::error::Error::InvalidQBit(bit));
403 }
404
405 let ranges = crate::support::get_ranges(qbits);
406
407 self.add_column();
408 for (first, last) in ranges
409 {
410 self.set_field(first, format!(r"\qw \barrier{{{}}}", last - first))?;
411 }
412
413 Ok(())
414 }
415
416 pub fn code(&self) -> String
421 {
422 let mut res = String::from("\\Qcircuit @C=1em @R=.7em {\n");
423
424 if !self.loops.is_empty()
425 {
426 let mut prev_idx = 0;
427 res += r" & ";
428 for (start, end, count) in self.loops.iter()
429 {
430 res += r"& ".repeat(start - prev_idx).as_str();
431 res += format!("\\mbox{{}} \\POS\"{},{}\".\"{},{}\".\"{},{}\".\"{},{}\"!C*+<.7em>\\frm{{^\\}}}},+U*++!D{{{}\\times}}",
432 2, start+2, 2, start+2, 2, end+2,
433 2, end+2, count).as_str();
434 prev_idx = *start;
435 }
436 res += "\\\\\n";
437
438 res += r" ";
439 res += r"& ".repeat(self.matrix.len()).as_str();
440 res += "\\\\\n";
441 }
442
443 let last_col_used = self.in_use.contains(&true);
444 for i in 0..self.total_nr_bits()
445 {
446 if self.add_init
447 {
448 if i < self.nr_qbits
449 {
450 res += r" \lstick{\ket{0}}";
451 }
452 else
453 {
454 res += r" \lstick{0}";
455 }
456 }
457 else
458 {
459 res += r" ";
460 }
461 for row in self.matrix.iter()
462 {
463 res += " & ";
464 if let Some(ref s) = row[i]
465 {
466 res += s.as_str();
467 }
468 else if i < self.nr_qbits
469 {
470 res += r"\qw";
471 }
472 else
473 {
474 res += r"\cw";
475 }
476 }
477
478 if last_col_used
479 {
480 res += r" & ";
481 res += if i < self.nr_qbits { r"\qw" } else { r"\cw" };
482 }
483 res += " \\\\\n";
484 }
485 res += "}\n";
486
487 res
488 }
489
490 pub fn set_controlled(&mut self, controlled: bool) -> bool
498 {
499 let res = self.controlled;
500 self.controlled = controlled;
501 res
502 }
503
504 pub fn is_controlled(&self) -> bool
507 {
508 self.controlled
509 }
510
511 pub fn set_expand_composite(&mut self, expand: bool)
518 {
519 self.expand_composite = expand;
520 }
521
522 pub fn expand_composite(&self) -> bool
528 {
529 self.expand_composite
530 }
531
532 pub fn set_add_init(&mut self, add_init: bool)
537 {
538 self.add_init = add_init;
539 }
540}
541
542pub trait Latex: crate::gates::Gate
544{
545 fn latex(&self, bits: &[usize], state: &mut LatexExportState)
550 -> crate::error::Result<()>
551 {
552 self.check_nr_bits(bits.len())?;
553 state.add_block_gate(bits, self.description())
554 }
555}
556
557#[cfg(test)]
558mod tests
559{
560 use super::{LatexExportState, Latex};
561
562 struct NoLatexGate;
563
564 impl crate::gates::Gate for NoLatexGate
565 {
566 fn cost(&self) -> f64 { 0.0 }
567 fn description(&self) -> &str { "NLG" }
568 fn nr_affected_bits(&self) -> usize { 3 }
569 fn matrix(&self) -> crate::cmatrix::CMatrix { unimplemented!() }
570 }
571 impl Latex for NoLatexGate {}
572
573 #[test]
574 fn test_new()
575 {
576 let nr_qbits = 5;
577 let nr_cbits = 2;
578 let state = LatexExportState::new(nr_qbits, nr_cbits);
579 assert_eq!(state.nr_qbits, nr_qbits);
580 assert_eq!(state.nr_cbits, nr_cbits);
581 assert_eq!(state.add_init, true);
582 assert_eq!(state.expand_composite, true);
583 assert_eq!(state.matrix, Vec::<Vec<Option<String>>>::new());
584 assert_eq!(state.in_use, vec![true; nr_qbits+nr_cbits]);
585 assert_eq!(state.controlled, false);
586 assert_eq!(state.loops, vec![]);
587 assert_eq!(state.open_loops, vec![]);
588 }
589
590 #[test]
591 fn test_total_nr_bits()
592 {
593 let state = LatexExportState::new(5, 2);
594 assert_eq!(state.total_nr_bits(), 7);
595
596 let state = LatexExportState::new(3, 0);
597 assert_eq!(state.total_nr_bits(), 3);
598
599 let state = LatexExportState::new(2, 8);
600 assert_eq!(state.total_nr_bits(), 10);
601 }
602
603 #[test]
604 fn test_add_column()
605 {
606 let mut state = LatexExportState::new(3, 1);
607 state.add_column();
608 assert_eq!(state.matrix, vec![vec![None, None, None, None]]);
609
610 state.matrix[0][1] = Some(String::from("x"));
611 state.add_column();
612 assert_eq!(state.matrix, vec![
613 vec![None, Some(String::from("x")), None, None],
614 vec![None, None, None, None]
615 ]);
616 }
617
618 #[test]
619 fn test_reserve()
620 {
621 let mut state = LatexExportState::new(2, 2);
622 assert_eq!(state.reserve(&[0], None), Ok(()));
623 assert_eq!(state.in_use, vec![false; 4]);
624 assert_eq!(state.matrix, vec![vec![None; 4]]);
625
626 state.in_use[0] = true;
627 assert_eq!(state.reserve(&[1], None), Ok(()));
628 assert_eq!(state.in_use, vec![true, false, false, false]);
629 assert_eq!(state.matrix, vec![vec![None, None, None, None]]);
630
631 assert_eq!(state.reserve(&[0], None), Ok(()));
632 assert_eq!(state.in_use, vec![false; 4]);
633 assert_eq!(state.matrix, vec![vec![None; 4]; 2]);
634
635 state.in_use[3] = true;
636 assert_eq!(state.reserve(&[0, 1], None), Ok(()));
637 assert_eq!(state.in_use, vec![false, false, false, true]);
638 assert_eq!(state.matrix, vec![vec![None; 4]; 2]);
639
640 assert_eq!(state.reserve(&[0, 1], Some(&[0])), Ok(()));
641 assert_eq!(state.in_use, vec![false, false, false, true]);
642 assert_eq!(state.matrix, vec![vec![None; 4]; 2]);
643
644 assert_eq!(state.reserve(&[0, 1], Some(&[1])), Ok(()));
645 assert_eq!(state.in_use, vec![false, false, false, false]);
646 assert_eq!(state.matrix, vec![vec![None; 4]; 3]);
647 }
648
649 #[test]
650 fn test_reserve_all()
651 {
652 let mut state = LatexExportState::new(2, 2);
653 state.reserve_all();
654 assert_eq!(state.in_use, vec![false; 4]);
655 assert_eq!(state.matrix, vec![vec![None; 4]]);
656
657 state.reserve_all();
658 assert_eq!(state.in_use, vec![false; 4]);
659 assert_eq!(state.matrix, vec![vec![None; 4]]);
660
661 state.in_use[0] = true;
662 state.reserve_all();
663 assert_eq!(state.in_use, vec![false; 4]);
664 assert_eq!(state.matrix, vec![vec![None; 4]; 2]);
665 }
666
667 #[test]
668 fn test_range_op()
669 {
670 let mut state = LatexExportState::new(2, 2);
671 assert_eq!(state.start_range_op(&[0], None), Ok(()));
672 assert_eq!(state.in_use, vec![false; 4]);
673 assert_eq!(state.matrix, vec![vec![None; 4]]);
674 state.end_range_op();
675 assert_eq!(state.in_use, vec![true, false, false, false]);
676 assert_eq!(state.matrix, vec![vec![None; 4]]);
677
678 assert_eq!(state.start_range_op(&[0, 1], None), Ok(()));
679 assert_eq!(state.in_use, vec![false; 4]);
680 assert_eq!(state.matrix, vec![vec![None; 4]; 2]);
681 state.end_range_op();
682 assert_eq!(state.in_use, vec![true, true, false, false]);
683 assert_eq!(state.matrix, vec![vec![None; 4]; 2]);
684
685 assert_eq!(state.start_range_op(&[0], None), Ok(()));
686 assert_eq!(state.in_use, vec![false; 4]);
687 assert_eq!(state.matrix, vec![vec![None; 4]; 3]);
688 state.end_range_op();
689 assert_eq!(state.in_use, vec![true, false, false, false]);
690 assert_eq!(state.matrix, vec![vec![None; 4]; 3]);
691
692 assert_eq!(state.start_range_op(&[1], None), Ok(()));
693 assert_eq!(state.in_use, vec![true, false, false, false]);
694 assert_eq!(state.matrix, vec![vec![None; 4]; 3]);
695 state.end_range_op();
696 assert_eq!(state.in_use, vec![true, true, false, false]);
697 assert_eq!(state.matrix, vec![vec![None; 4]; 3]);
698
699 assert_eq!(state.start_range_op(&[0], Some(&[1])), Ok(()));
700 assert_eq!(state.in_use, vec![false; 4]);
701 assert_eq!(state.matrix, vec![vec![None; 4]; 4]);
702 state.end_range_op();
703 assert_eq!(state.in_use, vec![true; 4]);
704 assert_eq!(state.matrix, vec![vec![None; 4]; 4]);
705 }
706
707 #[test]
708 fn test_set_field()
709 {
710 let mut state = LatexExportState::new(2, 0);
711 assert_eq!(state.set_field(0, String::from("hello")), Ok(()));
712 assert_eq!(state.in_use, vec![true, false]);
713 assert_eq!(state.matrix, vec![
714 vec![Some(String::from("hello")), None]
715 ]);
716
717 assert_eq!(state.set_field(1, String::from("world")), Ok(()));
718 assert_eq!(state.in_use, vec![true, true]);
719 assert_eq!(state.matrix, vec![
720 vec![Some(String::from("hello")), Some(String::from("world"))]
721 ]);
722
723 assert_eq!(state.set_field(0, String::from("hi there")), Ok(()));
724 assert_eq!(state.in_use, vec![true, false]);
725 assert_eq!(state.matrix, vec![
726 vec![Some(String::from("hello")), Some(String::from("world"))],
727 vec![Some(String::from("hi there")), None]
728 ]);
729
730 state.add_column();
731 assert_eq!(state.set_field(1, String::from("planet Mars")), Ok(()));
732 assert_eq!(state.in_use, vec![false, true]);
733 assert_eq!(state.matrix, vec![
734 vec![Some(String::from("hello")), Some(String::from("world"))],
735 vec![Some(String::from("hi there")), None],
736 vec![None, Some(String::from("planet Mars"))]
737 ]);
738 }
739
740 #[test]
741 fn test_set_measurement()
742 {
743 let mut state = LatexExportState::new(2, 2);
744 assert_eq!(state.set_measurement(0, 1, None), Ok(()));
745 assert_eq!(state.set_measurement(1, 0, Some("X")), Ok(()));
746 assert_eq!(state.code(),
747r#"\Qcircuit @C=1em @R=.7em {
748 \lstick{\ket{0}} & \meter & \qw & \qw \\
749 \lstick{\ket{0}} & \qw & \meterB{X} & \qw \\
750 \lstick{0} & \cw & \cw \cwx[-1] & \cw \\
751 \lstick{0} & \cw \cwx[-3] & \cw & \cw \\
752}
753"#);
754 }
755
756 #[test]
757 fn test_set_reset()
758 {
759 let mut state = LatexExportState::new(2, 0);
760 assert_eq!(state.set_reset(0), Ok(()));
761 assert_eq!(state.code(),
762r#"\Qcircuit @C=1em @R=.7em {
763 \lstick{\ket{0}} & \push{~\ket{0}~} \ar @{|-{}} [0,-1] & \qw \\
764 \lstick{\ket{0}} & \qw & \qw \\
765}
766"#);
767 }
768
769 #[test]
770 fn test_set_condition()
771 {
772 let mut state = LatexExportState::new(2, 2);
773 assert_eq!(state.start_range_op(&[], None), Ok(()));
774 assert_eq!(state.set_condition(&[0, 1], 2, &[]), Ok(()));
775 state.end_range_op();
776
777 assert_eq!(state.start_range_op(&[0], Some(&[0, 1])), Ok(()));
778 assert_eq!(state.set_field(0, String::from(r"\gate{X}")), Ok(()));
779 assert_eq!(state.set_condition(&[0, 1], 2, &[0]), Ok(()));
780 state.end_range_op();
781
782 assert_eq!(state.start_range_op(&[1], Some(&[0, 1])), Ok(()));
783 assert_eq!(state.set_field(1, String::from(r"\gate{H}")), Ok(()));
784 assert_eq!(state.set_condition(&[0, 1], 1, &[1]), Ok(()));
785 state.end_range_op();
786
787 assert_eq!(state.code(),
788r#"\Qcircuit @C=1em @R=.7em {
789 \lstick{\ket{0}} & \gate{X} & \qw & \qw \\
790 \lstick{\ket{0}} & \qw & \gate{H} & \qw \\
791 \lstick{0} & \cctrlo{-2} & \cctrl{-1} & \cw \\
792 \lstick{0} & \cctrl{-1} & \cctrlo{-1} & \cw \\
793}
794"#);
795 }
796
797 #[test]
798 fn test_add_block_gate()
799 {
800 let mut state = LatexExportState::new(1, 0);
801 assert_eq!(state.add_block_gate(&[0], "G"), Ok(()));
802 assert_eq!(state.code(),
803r#"\Qcircuit @C=1em @R=.7em {
804 \lstick{\ket{0}} & \gate{G} & \qw \\
805}
806"#);
807
808 let mut state = LatexExportState::new(3, 0);
809 assert_eq!(state.add_block_gate(&[1, 0, 2], "G"), Ok(()));
810 assert_eq!(state.code(),
811r#"\Qcircuit @C=1em @R=.7em {
812 \lstick{\ket{0}} & \multigate{2}{G} & \qw \\
813 \lstick{\ket{0}} & \ghost{G} & \qw \\
814 \lstick{\ket{0}} & \ghost{G} & \qw \\
815}
816"#);
817
818 let mut state = LatexExportState::new(5, 0);
819 assert_eq!(state.add_block_gate(&[1, 0, 3], "G"), Ok(()));
820 assert_eq!(state.code(),
821r#"\Qcircuit @C=1em @R=.7em {
822 \lstick{\ket{0}} & \multigate{1}{G} & \qw \\
823 \lstick{\ket{0}} & \ghost{G} & \qw \\
824 \lstick{\ket{0}} & \qw & \qw \\
825 \lstick{\ket{0}} & \gate{G} \qwx[-2] & \qw \\
826 \lstick{\ket{0}} & \qw & \qw \\
827}
828"#);
829 }
830
831 #[test]
832 fn test_loop()
833 {
834 let mut state = LatexExportState::new(2, 0);
835 state.start_loop(23);
836 assert_eq!(state.reserve(&[0, 1], None), Ok(()));
837 assert_eq!(state.set_field(0, String::from(r"\gate{H}")), Ok(()));
838 assert_eq!(state.set_field(1, String::from(r"\gate{X}")), Ok(()));
839 assert_eq!(state.add_cds(0, 1, r"\leftrightarrow"), Ok(()));
840 assert_eq!(state.reserve(&[0, 1], None), Ok(()));
841 assert_eq!(state.set_field(0, String::from(r"\gate{H}")), Ok(()));
842 assert_eq!(state.set_field(1, String::from(r"\gate{X}")), Ok(()));
843 assert_eq!(state.end_loop(), Ok(()));
844
845 assert_eq!(state.code(),
846r#"\Qcircuit @C=1em @R=.7em {
847 & \mbox{} \POS"2,2"."2,2"."2,4"."2,4"!C*+<.7em>\frm{^\}},+U*++!D{23\times}\\
848 & & & & \\
849 \lstick{\ket{0}} & \gate{H} & \cds{1}{\leftrightarrow} & \gate{H} & \qw \\
850 \lstick{\ket{0}} & \gate{X} & \qw & \gate{X} & \qw \\
851}
852"#);
853 }
854
855 #[test]
856 fn test_loop_close_error()
857 {
858 let mut state = LatexExportState::new(2, 0);
859 assert_eq!(state.end_loop(),
860 Err(crate::error::Error::ExportError(crate::error::ExportError::CantCloseLoop))
861 );
862 }
863
864 #[test]
865 fn test_set_barrier()
866 {
867 let mut state = LatexExportState::new(3, 0);
868 assert_eq!(state.set_field(0, String::from(r"\gate{X}")), Ok(()));
869 assert_eq!(state.set_field(1, String::from(r"\gate{X}")), Ok(()));
870 assert_eq!(state.set_field(2, String::from(r"\gate{X}")), Ok(()));
871 assert_eq!(state.set_barrier(&[0]), Ok(()));
872
873 assert_eq!(state.set_field(0, String::from(r"\gate{X}")), Ok(()));
874 assert_eq!(state.set_field(1, String::from(r"\gate{X}")), Ok(()));
875 assert_eq!(state.set_field(2, String::from(r"\gate{X}")), Ok(()));
876 assert_eq!(state.set_barrier(&[0, 2]), Ok(()));
877
878 assert_eq!(state.set_field(0, String::from(r"\gate{X}")), Ok(()));
879 assert_eq!(state.set_field(1, String::from(r"\gate{X}")), Ok(()));
880 assert_eq!(state.set_field(2, String::from(r"\gate{X}")), Ok(()));
881 assert_eq!(state.set_barrier(&[0, 1, 2]), Ok(()));
882
883 assert_eq!(state.code(),
884r#"\Qcircuit @C=1em @R=.7em {
885 \lstick{\ket{0}} & \gate{X} & \qw \barrier{0} & \gate{X} & \qw \barrier{0} & \gate{X} & \qw \barrier{2} & \qw \\
886 \lstick{\ket{0}} & \gate{X} & \qw & \gate{X} & \qw & \gate{X} & \qw & \qw \\
887 \lstick{\ket{0}} & \gate{X} & \qw & \gate{X} & \qw \barrier{0} & \gate{X} & \qw & \qw \\
888}
889"#);
890 }
891
892 #[test]
893 fn test_no_init()
894 {
895 let mut state = LatexExportState::new(1, 1);
896 assert_eq!(state.set_measurement(0, 0, None), Ok(()));
897
898 assert_eq!(state.code(),
899r#"\Qcircuit @C=1em @R=.7em {
900 \lstick{\ket{0}} & \meter & \qw \\
901 \lstick{0} & \cw \cwx[-1] & \cw \\
902}
903"#);
904
905 state.set_add_init(false);
906 assert_eq!(state.code(),
907r#"\Qcircuit @C=1em @R=.7em {
908 & \meter & \qw \\
909 & \cw \cwx[-1] & \cw \\
910}
911"#);
912 }
913
914 #[test]
915 fn test_default_trait_impl()
916 {
917 let gate = NoLatexGate {};
918 let mut state = LatexExportState::new(5, 0);
919 assert_eq!(gate.latex(&[1, 2, 4], &mut state), Ok(()));
920 assert_eq!(gate.latex(&[0, 2, 3], &mut state), Ok(()));
921 assert_eq!(state.code(),
922r#"\Qcircuit @C=1em @R=.7em {
923 \lstick{\ket{0}} & \qw & \gate{NLG} & \qw \\
924 \lstick{\ket{0}} & \multigate{1}{NLG} & \qw & \qw \\
925 \lstick{\ket{0}} & \ghost{NLG} & \multigate{1}{NLG} \qwx[-2] & \qw \\
926 \lstick{\ket{0}} & \qw & \ghost{NLG} & \qw \\
927 \lstick{\ket{0}} & \gate{NLG} \qwx[-2] & \qw & \qw \\
928}
929"#);
930 }
931}