#include <bits/stdc++.h>   using namespace std;   const int MOD = 1000000007;   void yes() {     cout <<  Yes           <<   n ;   }   void no() {     cout <<  No           <<   n ;   }   struct Sync_stdio {     Sync_stdio() {       cin.tie(NULL);       ios_base::sync_with_stdio(false);     }   } _sync_stdio;   struct FAIL {     FAIL() {       cout <<  CHANGE!!!             <<   n ;     }   };   class BipartiteMatching {    public:     struct Edge {       int first_part_vertex;       int second_part_vertex;     };     struct Vertex {       int vertex_id;       int part;     };     BipartiteMatching(int size_first_, int size_second_)         : size_first(size_first_), size_second(size_second_), graph(size_first) {}     void add_edge(int first_part_vertex, int second_part_vertex) {       graph[first_part_vertex].push_back(second_part_vertex);     }     vector<Edge> find_matching() {       if (!calculated_matching) {         calculate_matching();       }       vector<Edge> answer;       for (int i = 0; i < size_second; ++i) {         if (mt[i] != -1) {           answer.push_back({mt[i], i});         }       }       return answer;     }     vector<Vertex> find_minimum_vertex_cover() {       if (!calculated_matching) {         calculate_matching();       }       cerr <<  Doesn t work             <<   n ;       return {};     }       private:     bool try_kuhn(int vertex) {       if (used[vertex]) {         return false;       }       used[vertex] = true;       for (int to : graph[vertex]) {         if (mt[to] == -1 || try_kuhn(mt[to])) {           mt[to] = vertex;           return true;         }       }       return false;     }     void calculate_matching() {       mt.assign(size_second, -1);       for (int i = 0; i < size_first; ++i) {         used.assign(size_first, false);         try_kuhn(i);       }       calculated_matching = true;     }     int size_first, size_second;     int calculated_matching = false;     vector<vector<int>> graph;     vector<int> mt;     vector<char> used;   };   bool can(int n, int m) {     BipartiteMatching matching(n * m, n * m);     for (int i1 = (0); i1 < (n); ++i1) {       for (int j1 = (0); j1 < (m); ++j1) {         for (int i2 = (0); i2 < (n); ++i2) {           for (int j2 = (0); j2 < (m); ++j2) {             if ((i1 + j1) % 2 && abs(i1 - i2) + abs(j1 - j2) == 3) {               matching.add_edge(i1 * m + j1, i2 * m + j2);             }           }         }       }     }     return matching.find_matching().size() == n * m / 2;   }   void build_table(int n, int m) {     vector<vector<int>> ans(n, vector<int>(m));     for (int i = (0); i < (n); ++i) {       for (int j = (0); j < (m); ++j) {         ans[i][j] = can(i + 1, j + 1);       }     }     for (int i = (0); i < (n); ++i) {       for (int j = (0); j < (m); ++j) {         cout << ans[i][j];       }       cout <<   n ;     }   }   int main() {     long long n, m;     cin >> n >> m;     if (n > m) {       swap(n, m);     }     if (n >= 3) {       cout << n * m / 2 * 2;       return 0;     }     if (n == 2) {       if (m == 7) {         cout << 12;       } else if (m >= 4) {         cout << n * m / 2 * 2;       } else if (m == 3) {         cout << 4;       } else {         cout << 0;       }       return 0;     }     cout << m / 6 * 6 + max((m % 6 - 3) * 2, 0LL);   }