1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
use crate::Qubit;
use num::complex::Complex;

pub fn x(qubit: &mut Qubit) {
    not(qubit);
}

pub fn y(qubit: &mut Qubit) {
    let mat = [[Complex::new(0.0, 0.0), Complex::new(0.0, -1.0)],
	       [Complex::new(0.0, 1.0), Complex::new(0.0, 0.0)]];
    let mut state: (Complex<f32>, Complex<f32>)= (Complex::new(0.0, 0.0), Complex::new(0.0, 0.0));

    state.0 = mat[0][0] * qubit.state.0 + mat[0][1] * qubit.state.1;
    state.1 = mat[1][0] * qubit.state.0 + mat[1][1] * qubit.state.1;

    qubit.state = normalize_phase(state);
}

pub fn z(qubit: &mut Qubit) {
    phase(qubit, std::f32::consts::PI);
}

pub fn phase(qubit: &mut Qubit, deg: f32) {
    let mat = [[Complex::new(1.0, 0.0), Complex::new(0.0, 0.0)],
	       [Complex::new(0.0, 0.0), Complex::new(deg.cos(), deg.sin())]];
    let mut state: (Complex<f32>, Complex<f32>)= (Complex::new(0.0, 0.0), Complex::new(0.0, 0.0));

    state.0 = mat[0][0] * qubit.state.0 + mat[0][1] * qubit.state.1;
    state.1 = mat[1][0] * qubit.state.0 + mat[1][1] * qubit.state.1;

    qubit.state = normalize_phase(state);
}

pub fn not(qubit: &mut Qubit) {
    let state = qubit.state;
    qubit.state = (state.1.re, Complex::new(state.0, -state.1.im));
}

pub fn h(qubit: &mut Qubit) {
    let root_two = (2.0 as f32).sqrt();
    let mat = [[1.0 / root_two, 1.0 / root_two],
		[1.0 / root_two, -1.0 / root_two]];
    let mut state: (Complex<f32>, Complex<f32>)= (Complex::new(0.0, 0.0), Complex::new(0.0, 0.0));

    state.0 = mat[0][0] * qubit.state.0 + mat[0][1] * qubit.state.1;
    state.1 = mat[1][0] * qubit.state.0 + mat[1][1] * qubit.state.1;

    qubit.state = normalize_phase(state);
}

pub fn sqrt_not(qubit: &mut Qubit) {
    let mat = [[Complex::new(1.0, 1.0) / 2.0, Complex::new(1.0, -1.0) / 2.0],
	       [Complex::new(1.0, -1.0) / 2.0, Complex::new(1.0, 1.0) / 2.0]];
    let mut state: (Complex<f32>, Complex<f32>)= (Complex::new(0.0, 0.0), Complex::new(0.0, 0.0));

    state.0 = mat[0][0] * qubit.state.0 + mat[0][1] * qubit.state.1;
    state.1 = mat[1][0] * qubit.state.0 + mat[1][1] * qubit.state.1;

    qubit.state = normalize_phase(state);
}

fn normalize_phase(state: (Complex<f32>, Complex<f32>)) -> (f32, Complex<f32>) {
    if (state.0 == Complex{re: 0.0, im: 0.0}) {
	return (0.0, Complex::new(1.0, 0.0));
    }

    let size = (state.0.conj() * state.0).re.sqrt();
    let d_phase = (state.0 / size).conj();

    let l = (d_phase * state.0).re;
    let r = d_phase * state.1;
    (l, r)
}

#[cfg(test)]
mod tests {
    use super::*;
    use num::complex::Complex;

    #[test]
    fn test_x() {
	let mut qubit = Qubit::default();
	x(&mut qubit);
	assert_eq!(qubit.state, (0.0, Complex{re: 1.0, im: 0.0}));
    }

    #[test]
    fn test_y() {
	let mut qubit0 = Qubit::default();
	y(&mut qubit0);
	assert_eq!(qubit0.state, (0.0, Complex{re: 1.0, im: 0.0}));

	let mut qubit1 = Qubit::default();
	x(&mut qubit1);
	y(&mut qubit1);
	assert_eq!(qubit1.state, (1.0, Complex{re: 0.0, im: 0.0}));
    }

    #[test]
    fn test_z() {
	let mut qubit0 = Qubit::default();
	z(&mut qubit0);
	assert_eq!(qubit0.state, (1.0, Complex{re: 0.0, im: 0.0}));

	let mut qubit1 = Qubit::default();
	x(&mut qubit1);
	z(&mut qubit1);
	assert_eq!(qubit1.state, (0.0, Complex{re: 1.0, im: 0.0}));
    }

    #[test]
    fn test_not() {
	let mut qubit = Qubit::default();
	not(&mut qubit);
	assert_eq!(qubit.state, (0.0, Complex{re: 1.0, im: 0.0}));
    }

    #[test]
    fn test_h() {
	// Test on a qubit of state [1.0, 0.0]
	let mut qubit0 = Qubit::default();

	h(&mut qubit0);

	let root_two = (2.0 as f32).sqrt();

	let got = qubit0.state;
	let want = (1.0 / root_two, Complex{re: 1.0 / root_two, im: 0.0});

	assert_eq!(got, want);

	// Test on a qubit of state [0.0, 1.0]
	let mut qubit1 = Qubit::default();
	not(&mut qubit1);

	h(&mut qubit1);

	let got = qubit1.state;
	let want = (1.0 / root_two, Complex{re: -1.0 / root_two, im: 0.0});

	assert_eq!(got, want);
    }

    #[test]
    fn test_sqrt_not() {
	let mut qubit = Qubit::default();

	sqrt_not(&mut qubit);

	sqrt_not(&mut qubit);
	let mut other_qubit = Qubit::default();
	not(&mut other_qubit);

	let got = qubit.state;
	let want = other_qubit.state;

	assert_eq!(got, want);
    }

    #[test]
    fn test_normalize_phase() {
	let state = (Complex::new(0.0, -1.0), Complex::new(1.0, 0.0));
	let got = normalize_phase(state);
	let want = (1.0, Complex::new(0.0, 1.0));
	assert_eq!(got, want);
    }
}