Mercurial > public > cpp-enigma
comparison enigma/machine.h @ 13:b9d124a15926
To improve cache performance, the enigma machine rotors are now stored
together with the reflector in a vector.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Mon, 02 Jul 2012 19:14:36 -0500 |
parents | 424111a36ed7 |
children | 919b7a0d1802 |
comparison
equal
deleted
inserted
replaced
12:424111a36ed7 | 13:b9d124a15926 |
---|---|
45 const std::string& plugboard_settings = ""); | 45 const std::string& plugboard_settings = ""); |
46 | 46 |
47 // set the rotor display (starting position) - 3 rotor version | 47 // set the rotor display (starting position) - 3 rotor version |
48 void set_display(char left, char mid, char right) | 48 void set_display(char left, char mid, char right) |
49 { | 49 { |
50 assert(rotors.size() == 3); | 50 assert(rotors.size() == 4); |
51 | 51 |
52 rotors[0]->set_display(left); | 52 rotors[1].set_display(left); |
53 rotors[1]->set_display(mid); | 53 rotors[2].set_display(mid); |
54 rotors[2]->set_display(right); | 54 rotors[3].set_display(right); |
55 } | 55 } |
56 | 56 |
57 // set the rotor display (starting position) - 4 rotor version | 57 // set the rotor display (starting position) - 4 rotor version |
58 void set_display(char c0, char c1, char c2, char c3) | 58 void set_display(char c0, char c1, char c2, char c3) |
59 { | 59 { |
60 assert(rotors.size() == 4); | 60 assert(rotors.size() == 5); |
61 | 61 |
62 rotors[0]->set_display(c0); | 62 rotors[1].set_display(c0); |
63 rotors[1]->set_display(c1); | 63 rotors[2].set_display(c1); |
64 rotors[2]->set_display(c2); | 64 rotors[3].set_display(c2); |
65 rotors[3]->set_display(c3); | 65 rotors[4].set_display(c3); |
66 } | 66 } |
67 | 67 |
68 // Set the rotor display (starting position) using a string; the | 68 // Set the rotor display (starting position) using a string; the |
69 // string length must match the number of rotors in use or a | 69 // string length must match the number of rotors in use or a |
70 // enigma_machine_error exception will be thrown: | 70 // enigma_machine_error exception will be thrown: |
71 void set_display(const std::string& val) | 71 void set_display(const std::string& val) |
72 { | 72 { |
73 if (val.size() == 3 && rotors.size() == 3) | 73 if (val.size() == 3 && rotors.size() == 4) |
74 { | 74 { |
75 set_display(val[0], val[1], val[2]); | 75 set_display(val[0], val[1], val[2]); |
76 } | 76 } |
77 else if (val.size() == 4 && rotors.size() == 4) | 77 else if (val.size() == 4 && rotors.size() == 5) |
78 { | 78 { |
79 set_display(val[0], val[1], val[2], val[3]); | 79 set_display(val[0], val[1], val[2], val[3]); |
80 } | 80 } |
81 else | 81 else |
82 { | 82 { |
86 | 86 |
87 // return the rotor display (starting position) as a string | 87 // return the rotor display (starting position) as a string |
88 std::string get_display() const | 88 std::string get_display() const |
89 { | 89 { |
90 std::string result; | 90 std::string result; |
91 for (const auto& r : rotors) | 91 for (std::size_t i = 1; i < rotors.size(); ++i) |
92 { | 92 { |
93 result += r->get_display(); | 93 result += rotors[i].get_display(); |
94 } | 94 } |
95 return result; | 95 return result; |
96 } | 96 } |
97 | 97 |
98 // simulate front panel key press; returns the lamp character that is lit | 98 // simulate front panel key press; returns the lamp character that is lit |
141 // | 141 // |
142 std::string army_str() const { return str(true); } | 142 std::string army_str() const { return str(true); } |
143 std::string navy_str() const { return str(false); } | 143 std::string navy_str() const { return str(false); } |
144 | 144 |
145 private: | 145 private: |
146 rotor_vector rotors; | 146 // Note that to improve cache performance, the rotors and reflectors are stored |
147 std::shared_ptr<rotor> reflector; | 147 // in a contiguous vector. |
148 std::vector<rotor> rotors; // rotor & reflector array | |
148 plugboard pb; | 149 plugboard pb; |
149 rotor* r_rotor; // rightmost rotor | 150 rotor* r_rotor; // rightmost rotor |
150 rotor* m_rotor; // 2nd to right rotor | 151 rotor* m_rotor; // 2nd to right rotor |
151 rotor* l_rotor; // 3rd to right rotor | 152 rotor* l_rotor; // 3rd to right rotor |
152 | 153 |
186 // perform an encrypt or decrypt operation | 187 // perform an encrypt or decrypt operation |
187 // signal_num - the wire (0-25) that the simulated current occurs on | 188 // signal_num - the wire (0-25) that the simulated current occurs on |
188 // Returns a lamp number to light (an integer 0-25). | 189 // Returns a lamp number to light (an integer 0-25). |
189 int electric_signal(int signal_num) | 190 int electric_signal(int signal_num) |
190 { | 191 { |
191 int pos = pb.signal(signal_num); | 192 int n = pb.signal(signal_num); |
192 | 193 |
193 for (auto r = rotors.rbegin(); r != rotors.rend(); ++r) | 194 if (rotors.size() == 4) // 3 rotors + reflector |
194 { | 195 { |
195 pos = (*r)->signal_in(pos); | 196 n = rotors[3].signal_in(n); |
196 } | 197 n = rotors[2].signal_in(n); |
197 | 198 n = rotors[1].signal_in(n); |
198 pos = reflector->signal_in(pos); | 199 n = rotors[0].signal_in(n); // reflector |
199 | 200 n = rotors[1].signal_out(n); |
200 for (const auto& r : rotors) | 201 n = rotors[2].signal_out(n); |
201 { | 202 n = rotors[3].signal_out(n); |
202 pos = r->signal_out(pos); | 203 } |
203 } | 204 else // Kriegsmarine 4 rotor + reflector |
204 | 205 { |
205 return pb.signal(pos); | 206 n = rotors[4].signal_in(n); |
207 n = rotors[3].signal_in(n); | |
208 n = rotors[2].signal_in(n); | |
209 n = rotors[1].signal_in(n); | |
210 n = rotors[0].signal_in(n); // reflector | |
211 n = rotors[1].signal_out(n); | |
212 n = rotors[2].signal_out(n); | |
213 n = rotors[3].signal_out(n); | |
214 n = rotors[4].signal_out(n); | |
215 } | |
216 return pb.signal(n); | |
206 } | 217 } |
207 | 218 |
208 std::string str(bool army) const; | 219 std::string str(bool army) const; |
209 }; | 220 }; |
210 } | 221 } |