# HG changeset patch # User Brian Neal # Date 1341274476 18000 # Node ID b9d124a1592615c0a42d73f8f1c94cefb63c5b91 # Parent 424111a36ed77f37cd8a6be696b354beb2501b23 To improve cache performance, the enigma machine rotors are now stored together with the reflector in a vector. diff -r 424111a36ed7 -r b9d124a15926 enigma/machine.cpp --- a/enigma/machine.cpp Sun Jul 01 12:53:10 2012 -0500 +++ b/enigma/machine.cpp Mon Jul 02 19:14:36 2012 -0500 @@ -18,10 +18,14 @@ const rotor_vector& rv, std::shared_ptr reflector, const plugboard& pb) - : rotors(rv), - reflector(reflector), + : rotors(), pb(pb) { + rotors.push_back(*reflector); + for (const auto& r : rv) + { + rotors.push_back(*r); + } rotor_count_check(); } @@ -30,10 +34,14 @@ enigma_machine::enigma_machine( const rotor_vector& rv, std::shared_ptr reflector) - : rotors(rv), - reflector(reflector), + : rotors(), pb() { + rotors.push_back(*reflector); + for (const auto& r : rv) + { + rotors.push_back(*r); + } rotor_count_check(); } @@ -45,26 +53,28 @@ const std::string& reflector_name, const std::string& plugboard_settings) : rotors(), - reflector(create_reflector(reflector_name.c_str())), pb(plugboard_settings) { + const auto ukw(create_reflector(reflector_name.c_str())); + rotors.push_back(*ukw); for (const auto& name : rotor_types) { - rotors.push_back(create_rotor(name.c_str())); + const auto r(create_rotor(name.c_str())); + rotors.push_back(*r); } rotor_count_check(); // if ring settings are supplied, there has to be one for each rotor if (!ring_settings.empty()) { - if (rotors.size() != ring_settings.size()) + if (rotors.size() - 1 != ring_settings.size()) { throw enigma_machine_error("rotor/ring setting count mismatch"); } - for (std::size_t i = 0; i < rotors.size(); ++i) + for (std::size_t i = 1; i < rotors.size(); ++i) { - rotors[i]->set_ring_setting(ring_settings[i]); + rotors[i].set_ring_setting(ring_settings[i - 1]); } } } @@ -73,22 +83,24 @@ void enigma_machine::rotor_count_check() { - if (rotors.size() != 3 && rotors.size() != 4) + // the first rotor is actually the reflector; so we should have a total + // of 4 or 5 rotors + if (rotors.size() != 4 && rotors.size() != 5) { throw enigma_machine_error("rotor count"); } - if (rotors.size() == 3) + if (rotors.size() == 4) { - r_rotor = rotors[2].get(); - m_rotor = rotors[1].get(); - l_rotor = rotors[0].get(); + r_rotor = &rotors[3]; + m_rotor = &rotors[2]; + l_rotor = &rotors[1]; } else { - r_rotor = rotors[3].get(); - m_rotor = rotors[2].get(); - l_rotor = rotors[1].get(); + r_rotor = &rotors[4]; + m_rotor = &rotors[3]; + l_rotor = &rotors[2]; } } @@ -98,11 +110,11 @@ { std::ostringstream os; - os << reflector->name() << ' '; + os << rotors[0].name() << ' '; - for (const auto& r : rotors) + for (std::size_t i = 1; i < rotors.size(); ++i) { - os << r->name() << '/' << r->get_ring_setting() << ' '; + os << rotors[i].name() << '/' << rotors[i].get_ring_setting() << ' '; } os << get_display() << ' ' << (army ? pb.army_str() : pb.navy_str()); diff -r 424111a36ed7 -r b9d124a15926 enigma/machine.h --- a/enigma/machine.h Sun Jul 01 12:53:10 2012 -0500 +++ b/enigma/machine.h Mon Jul 02 19:14:36 2012 -0500 @@ -47,22 +47,22 @@ // set the rotor display (starting position) - 3 rotor version void set_display(char left, char mid, char right) { - assert(rotors.size() == 3); + assert(rotors.size() == 4); - rotors[0]->set_display(left); - rotors[1]->set_display(mid); - rotors[2]->set_display(right); + rotors[1].set_display(left); + rotors[2].set_display(mid); + rotors[3].set_display(right); } // set the rotor display (starting position) - 4 rotor version void set_display(char c0, char c1, char c2, char c3) { - assert(rotors.size() == 4); + assert(rotors.size() == 5); - rotors[0]->set_display(c0); - rotors[1]->set_display(c1); - rotors[2]->set_display(c2); - rotors[3]->set_display(c3); + rotors[1].set_display(c0); + rotors[2].set_display(c1); + rotors[3].set_display(c2); + rotors[4].set_display(c3); } // Set the rotor display (starting position) using a string; the @@ -70,11 +70,11 @@ // enigma_machine_error exception will be thrown: void set_display(const std::string& val) { - if (val.size() == 3 && rotors.size() == 3) + if (val.size() == 3 && rotors.size() == 4) { set_display(val[0], val[1], val[2]); } - else if (val.size() == 4 && rotors.size() == 4) + else if (val.size() == 4 && rotors.size() == 5) { set_display(val[0], val[1], val[2], val[3]); } @@ -88,9 +88,9 @@ std::string get_display() const { std::string result; - for (const auto& r : rotors) + for (std::size_t i = 1; i < rotors.size(); ++i) { - result += r->get_display(); + result += rotors[i].get_display(); } return result; } @@ -143,8 +143,9 @@ std::string navy_str() const { return str(false); } private: - rotor_vector rotors; - std::shared_ptr reflector; + // Note that to improve cache performance, the rotors and reflectors are stored + // in a contiguous vector. + std::vector rotors; // rotor & reflector array plugboard pb; rotor* r_rotor; // rightmost rotor rotor* m_rotor; // 2nd to right rotor @@ -188,21 +189,31 @@ // Returns a lamp number to light (an integer 0-25). int electric_signal(int signal_num) { - int pos = pb.signal(signal_num); + int n = pb.signal(signal_num); - for (auto r = rotors.rbegin(); r != rotors.rend(); ++r) + if (rotors.size() == 4) // 3 rotors + reflector { - pos = (*r)->signal_in(pos); + n = rotors[3].signal_in(n); + n = rotors[2].signal_in(n); + n = rotors[1].signal_in(n); + n = rotors[0].signal_in(n); // reflector + n = rotors[1].signal_out(n); + n = rotors[2].signal_out(n); + n = rotors[3].signal_out(n); } - - pos = reflector->signal_in(pos); - - for (const auto& r : rotors) + else // Kriegsmarine 4 rotor + reflector { - pos = r->signal_out(pos); + n = rotors[4].signal_in(n); + n = rotors[3].signal_in(n); + n = rotors[2].signal_in(n); + n = rotors[1].signal_in(n); + n = rotors[0].signal_in(n); // reflector + n = rotors[1].signal_out(n); + n = rotors[2].signal_out(n); + n = rotors[3].signal_out(n); + n = rotors[4].signal_out(n); } - - return pb.signal(pos); + return pb.signal(n); } std::string str(bool army) const; diff -r 424111a36ed7 -r b9d124a15926 enigma/tests/test_plugboard.t.h --- a/enigma/tests/test_plugboard.t.h Sun Jul 01 12:53:10 2012 -0500 +++ b/enigma/tests/test_plugboard.t.h Mon Jul 02 19:14:36 2012 -0500 @@ -143,7 +143,7 @@ void test_get_wiring() { plugboard pb; - alpha_int_array w(pb.get_wiring()); + auto w(pb.get_wiring()); for (int i = 0; i < 26; ++i) { @@ -161,7 +161,7 @@ std::swap(w[8], w[20]); std::swap(w[24], w[25]); - alpha_int_array w1(pb.get_wiring()); + auto w1(pb.get_wiring()); for (int i = 0; i < 26; ++i) { TS_ASSERT_EQUALS(w[i], w1[i]); @@ -182,7 +182,7 @@ plugboard pb; pb.set_wiring(w); - alpha_int_array w2 = pb.get_wiring(); + auto w2 = pb.get_wiring(); TS_ASSERT_EQUALS(w, w2); }