diff --git a/alib2algo/src/automaton/FSMTotal.cpp b/alib2algo/src/automaton/FSMTotal.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a0d8fb324745fa1eca035e2cae207f0f86f11949
--- /dev/null
+++ b/alib2algo/src/automaton/FSMTotal.cpp
@@ -0,0 +1,118 @@
+/*
+ * FSMTotal.cpp
+ *
+ *  Created on: 20. 9. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#include "FSMTotal.h"
+
+#include <exception/AlibException.h>
+
+#include <automaton/FSM/NFA.h>
+#include <automaton/FSM/DFA.h>
+
+namespace automaton {
+
+automaton::Automaton FSMTotal::total(const Automaton& automaton) {
+	automaton::Automaton* out = NULL;
+	automaton.getData().Accept((void*) &out, FSMTotal::FSM_TOTAL);
+	automaton::Automaton res = std::move(*out);
+	delete out;
+	return res;
+}
+
+automaton::NFA FSMTotal::total(const automaton::NFA& automaton) {
+	if(! automaton.isDeterministic()) {
+		throw exception::AlibException("Automaton must be deterministic to make its transition function total");
+	}
+
+	automaton::NFA res(automaton);
+	automaton::State nullState = automaton::createUniqueState(automaton::State("q0"), automaton.getStates());
+	res.addState(nullState);
+
+	for(const auto& q : res.getStates()) {
+		for(const auto& a : res.getInputAlphabet()) {
+			if(res.getTransitions().find(std::make_pair(q, a)) == res.getTransitions().end()) {
+				res.addTransition(q, a, nullState);
+			}
+		}
+	}
+
+	return res;
+}
+
+automaton::DFA FSMTotal::total(const automaton::DFA& automaton) {
+	automaton::DFA res(automaton);
+	automaton::State nullState = automaton::createUniqueState(automaton::State("q0"), automaton.getStates());
+	res.addState(nullState);
+
+	for(const auto& q : res.getStates()) {
+		for(const auto& a : res.getInputAlphabet()) {
+			if(res.getTransitions().find(std::make_pair(q, a)) == res.getTransitions().end()) {
+				res.addTransition(q, a, nullState);
+			}
+		}
+	}
+
+	return res;
+}
+
+void FSMTotal::Visit(void*, const UnknownAutomaton&) const {
+	throw exception::AlibException("Unsupported automaton type UnknownAutomaton");
+}
+
+void FSMTotal::Visit(void*, const EpsilonNFA&) const {
+	throw exception::AlibException("Unsupported automaton type EpsilonNFA");
+}
+
+void FSMTotal::Visit(void* data, const NFA& automaton) const {
+	automaton::Automaton*& out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->total(automaton));
+}
+
+void FSMTotal::Visit(void* data, const DFA& automaton) const {
+	automaton::Automaton*& out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->total(automaton));
+}
+
+void FSMTotal::Visit(void*, const ExtendedNFA&) const {
+	throw exception::AlibException("Unsupported automaton type ExtendedNFA");
+}
+
+void FSMTotal::Visit(void*, const CompactNFA&) const {
+	throw exception::AlibException("Unsupported automaton type CompactNFA");
+}
+
+void FSMTotal::Visit(void*, const DPDA&) const {
+	throw exception::AlibException("Unsupported automaton type UnknownAutomaton");
+}
+
+void FSMTotal::Visit(void*, const SinglePopDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type SinglePopDPDA");
+}
+
+void FSMTotal::Visit(void*, const InputDrivenNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type InputDrivenNPDA");
+}
+
+void FSMTotal::Visit(void*, const VisiblyPushdownNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA");
+}
+
+void FSMTotal::Visit(void*, const NPDA&) const {
+	throw exception::AlibException("Unsupported automaton type NPDA");
+}
+
+void FSMTotal::Visit(void*, const SinglePopNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type SinglePopNPDA");
+}
+
+void FSMTotal::Visit(void*, const OneTapeDTM&) const {
+	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
+}
+
+const FSMTotal FSMTotal::FSM_TOTAL;
+
+}
+
diff --git a/alib2algo/src/automaton/FSMTotal.h b/alib2algo/src/automaton/FSMTotal.h
new file mode 100644
index 0000000000000000000000000000000000000000..420abb04b34383bffd02c2b903c9249f9b9b9ca1
--- /dev/null
+++ b/alib2algo/src/automaton/FSMTotal.h
@@ -0,0 +1,54 @@
+/*
+ * FSMTotal.h
+ *
+ *  Created on: 20. 9. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#ifndef FSM_TOTAL_H_
+#define FSM_TOTAL_H_
+
+#include <algorithm>
+#include <deque>
+#include <set>
+
+#include "automaton/Automaton.h"
+#include <automaton/common/State.h>
+
+namespace automaton {
+
+/**
+ * Makes finite automaton's transition function total.
+ * Source: Melichar: Algorithm 2.22
+ */
+class FSMTotal : public VisitableAutomatonBase::const_visitor_type {
+public:
+	/**
+	 * Computes epsilon closure of a state in epsilon nonfree automaton
+	 */
+	static automaton::Automaton total(const automaton::Automaton& automaton);
+
+	static automaton::NFA total(const automaton::NFA& automaton);
+	static automaton::DFA total(const automaton::DFA& automaton);
+
+private:
+	void Visit(void*, const UnknownAutomaton& automaton) const;
+	void Visit(void*, const EpsilonNFA& automaton) const;
+	void Visit(void*, const NFA& automaton) const;
+	void Visit(void*, const DFA& automaton) const;
+	void Visit(void*, const ExtendedNFA& automaton) const;
+	void Visit(void*, const CompactNFA& automaton) const;
+	void Visit(void*, const DPDA& automaton) const;
+	void Visit(void*, const SinglePopDPDA& automaton) const;
+	void Visit(void*, const InputDrivenNPDA& automaton) const;
+	void Visit(void*, const VisiblyPushdownNPDA& automaton) const;
+	void Visit(void*, const NPDA& automaton) const;
+	void Visit(void*, const SinglePopNPDA& automaton) const;
+	void Visit(void*, const OneTapeDTM& automaton) const;
+
+	static const FSMTotal FSM_TOTAL;
+};
+
+}
+
+#endif /* FSM_TOTAL_H_ */
diff --git a/alib2algo/test-src/automaton/FSMTotalTest.cpp b/alib2algo/test-src/automaton/FSMTotalTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..af6566234751d340aee87535e4845f5ba5a67aa8
--- /dev/null
+++ b/alib2algo/test-src/automaton/FSMTotalTest.cpp
@@ -0,0 +1,48 @@
+#include "FSMTotalTest.h"
+
+#include <automaton/FSM/DFA.h>
+#include <alphabet/LabeledSymbol.h>
+#include <label/Label.h>
+#include <label/CharacterLabel.h>
+
+#include "automaton/FSMTotal.h"
+#include "normalize/dfa/NormalizeDFA.h"
+#include "trim/automaton/TrimFSM.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION( TotalTest );
+
+void TotalTest::setUp() {
+}
+
+void TotalTest::tearDown() {
+}
+
+void TotalTest::testTotal() {
+	automaton::State q0("q0");
+	automaton::State q1("q1");
+	automaton::State q2("q2");
+
+	alphabet::Symbol a(alphabet::LabeledSymbol(label::Label(label::CharacterLabel('a'))));
+	alphabet::Symbol b(alphabet::LabeledSymbol(label::Label(label::CharacterLabel('b'))));
+	alphabet::Symbol c(alphabet::LabeledSymbol(label::Label(label::CharacterLabel('c'))));
+
+	automaton::DFA automaton(q0);
+	automaton.setStates({q0, q1, q2});
+	automaton.setFinalStates({q0, q1, q2});
+	automaton.setInputSymbols({a, b, c});
+
+	automaton.addTransition(q0, a, q0);
+	automaton.addTransition(q0, b, q1);
+	automaton.addTransition(q0, c, q2);
+	automaton.addTransition(q1, b, q1);
+	automaton.addTransition(q1, c, q2);
+	automaton.addTransition(q2, c, q2);
+
+	automaton::DFA totalAutomaton = automaton::FSMTotal::total(automaton);
+	CPPUNIT_ASSERT(totalAutomaton.isTotal());
+
+	automaton::DFA trimmedAutomaton = trim::TrimFSM::trim(automaton);
+	automaton::DFA trimmedTotalAutomaton = trim::TrimFSM::trim(totalAutomaton);
+
+	CPPUNIT_ASSERT(normalize::NormalizeDFA::normalize(trimmedAutomaton) == normalize::NormalizeDFA::normalize(trimmedTotalAutomaton));
+}
diff --git a/alib2algo/test-src/automaton/FSMTotalTest.h b/alib2algo/test-src/automaton/FSMTotalTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..1a7b09f16db80b52d4d7dc9c932ce2fb470a9df6
--- /dev/null
+++ b/alib2algo/test-src/automaton/FSMTotalTest.h
@@ -0,0 +1,19 @@
+#ifndef FSM_TOTAL_TEST_H_
+#define FSM_TOTAL_TEST_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class TotalTest : public CppUnit::TestFixture
+{
+  CPPUNIT_TEST_SUITE( TotalTest );
+  CPPUNIT_TEST( testTotal );
+  CPPUNIT_TEST_SUITE_END();
+
+public:
+  void setUp();
+  void tearDown();
+
+  void testTotal();
+};
+
+#endif /* FSM_TOTAL_TEST_H_ */