diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDHistoWorkspace.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDHistoWorkspace.h
index ef9e1fb3ef3d11c1480515a422fab94808025f00..0aff81ab35ef56bc0c0da1dcace3436fc731284a 100644
--- a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDHistoWorkspace.h
+++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDHistoWorkspace.h
@@ -75,6 +75,12 @@ namespace MDEvents
     MDHistoWorkspace & operator/=(const MDHistoWorkspace & b);
     MDHistoWorkspace & operator/=(const Mantid::DataObjects::WorkspaceSingleValue & b);
 
+    MDHistoWorkspace & operator&=(const MDHistoWorkspace & b);
+    MDHistoWorkspace & operator|=(const MDHistoWorkspace & b);
+    MDHistoWorkspace & operator^=(const MDHistoWorkspace & b);
+
+    void operatorNot();
+
 
 
     // --------------------------------------------------------------------------------------------
diff --git a/Code/Mantid/Framework/MDEvents/src/MDHistoWorkspace.cpp b/Code/Mantid/Framework/MDEvents/src/MDHistoWorkspace.cpp
index 8a4badd49f43d10a15e76b14f35318795007553a..b558573ad0edabb3b8ef9ba9a68aa32a33c497c0 100644
--- a/Code/Mantid/Framework/MDEvents/src/MDHistoWorkspace.cpp
+++ b/Code/Mantid/Framework/MDEvents/src/MDHistoWorkspace.cpp
@@ -324,14 +324,22 @@ namespace MDEvents
     return out;
   }
 
+  //----------------------------------------------------------------------------------------------
+  /** Check if the two workspace's sizes match (for comparison or element-by-element operation
+   *
+   * @param other :: the workspace to compare to
+   * @param operation :: descriptive string (for the error message)
+   * @throw an error if they don't match
+   */
   void MDHistoWorkspace::checkWorkspaceSize(const MDHistoWorkspace & other, std::string operation)
   {
     if (other.getNumDims() != this->getNumDims())
-      throw std::invalid_argument("Cannot perform the " + operation + " operation on this workspace. The number of dimensions does not match.");
+      throw std::invalid_argument("Cannot perform the " + operation + " operation on this MDHistoWorkspace. The number of dimensions does not match.");
     if (other.m_length != this->m_length)
-      throw std::invalid_argument("Cannot perform the " + operation + " operation on this workspace. The length of the signals vector does not match.");
+      throw std::invalid_argument("Cannot perform the " + operation + " operation on this MDHistoWorkspace. The length of the signals vector does not match.");
   }
 
+
   //----------------------------------------------------------------------------------------------
   /** Perform the += operation, element-by-element, for two MDHistoWorkspace's
    *
@@ -366,6 +374,220 @@ namespace MDEvents
     return *this;
   }
 
+  //----------------------------------------------------------------------------------------------
+  /** Perform the -= operation, element-by-element, for two MDHistoWorkspace's
+   *
+   * @param b :: workspace on the RHS of the operation
+   * @return *this after operation */
+  MDHistoWorkspace & MDHistoWorkspace::operator-=(const MDHistoWorkspace & b)
+  {
+    checkWorkspaceSize(b, "-=");
+    for (size_t i=0; i<m_length; ++i)
+    {
+      m_signals[i] -= b.m_signals[i];
+      m_errorsSquared[i] += b.m_errorsSquared[i];
+    }
+    return *this;
+  }
+
+  //----------------------------------------------------------------------------------------------
+  /** Perform the -= operation with a scalar as the RHS argument
+   *
+   * @param b :: WorkspaceSingleValue (signal and error) as the RHS argument
+   * @return *this after operation */
+  MDHistoWorkspace & MDHistoWorkspace::operator-=(const Mantid::DataObjects::WorkspaceSingleValue & b)
+  {
+    signal_t signal = b.dataY(0)[0];
+    signal_t errorSquared = b.dataE(0)[0];
+    errorSquared *= errorSquared;
+    for (size_t i=0; i<m_length; ++i)
+    {
+      m_signals[i] -= signal;
+      m_errorsSquared[i] += errorSquared;
+    }
+    return *this;
+  }
+
+  //----------------------------------------------------------------------------------------------
+  /** Perform the *= operation, element-by-element, for two MDHistoWorkspace's
+   *
+   * Error propagation of \f$ f = a * b \f$  is given by:
+   * \f$ df^2 = f^2 * (da^2 / a^2 + db^2 / b^2) \f$
+   *
+   * @param b_ws :: workspace on the RHS of the operation
+   * @return *this after operation */
+  MDHistoWorkspace & MDHistoWorkspace::operator*=(const MDHistoWorkspace & b_ws)
+  {
+    checkWorkspaceSize(b_ws, "*=");
+    for (size_t i=0; i<m_length; ++i)
+    {
+      signal_t a = m_signals[i];
+      signal_t da2 = m_errorsSquared[i];
+
+      signal_t b = b_ws.m_signals[i];
+      signal_t db2 = b_ws.m_errorsSquared[i];
+
+      signal_t f = a * b;
+      signal_t df2 = (f * f) * ( da2 / (a*a) + db2 / (b*b) );
+
+      m_signals[i] = f;
+      m_errorsSquared[i] = df2;
+    }
+    return *this;
+  }
+
+  //----------------------------------------------------------------------------------------------
+  /** Perform the *= operation with a scalar as the RHS argument
+   *
+   * Error propagation of \f$ f = a * b \f$  is given by:
+   * \f$ df^2 = f^2 * (da^2 / a^2 + db^2 / b^2) \f$
+   *
+   * @param b_ws :: WorkspaceSingleValue (signal and error) as the RHS argument
+   * @return *this after operation */
+  MDHistoWorkspace & MDHistoWorkspace::operator*=(const Mantid::DataObjects::WorkspaceSingleValue & b_ws)
+  {
+    signal_t b = b_ws.dataY(0)[0];
+    signal_t db2 = b_ws.dataE(0)[0] * b_ws.dataE(0)[0];
+    signal_t db2_relative = db2 / (b*b);
+    for (size_t i=0; i<m_length; ++i)
+    {
+      signal_t a = m_signals[i];
+      signal_t da2 = m_errorsSquared[i];
+
+      signal_t f = a * b;
+      signal_t df2 = (f * f) * ( da2 / (a*a) + db2_relative );
+
+      m_signals[i] = f;
+      m_errorsSquared[i] = df2;
+    }
+    return *this;
+  }
+
+  //----------------------------------------------------------------------------------------------
+  /** Perform the /= operation, element-by-element, for two MDHistoWorkspace's
+   *
+   * Error propagation of \f$ f = a / b \f$  is given by:
+   * \f$ df^2 = f^2 * (da^2 / a^2 + db^2 / b^2) \f$
+   *
+   * @param b_ws :: workspace on the RHS of the operation
+   * @return *this after operation */
+  MDHistoWorkspace & MDHistoWorkspace::operator/=(const MDHistoWorkspace & b_ws)
+  {
+    checkWorkspaceSize(b_ws, "/=");
+    for (size_t i=0; i<m_length; ++i)
+    {
+      signal_t a = m_signals[i];
+      signal_t da2 = m_errorsSquared[i];
+
+      signal_t b = b_ws.m_signals[i];
+      signal_t db2 = b_ws.m_errorsSquared[i];
+
+      signal_t f = a / b;
+      signal_t df2 = (f * f) * ( da2 / (a*a) + db2 / (b*b) );
+
+      m_signals[i] = f;
+      m_errorsSquared[i] = df2;
+    }
+    return *this;
+  }
+
+  //----------------------------------------------------------------------------------------------
+  /** Perform the /= operation with a scalar as the RHS argument
+   *
+   * Error propagation of \f$ f = a / b \f$  is given by:
+   * \f$ df^2 = f^2 * (da^2 / a^2 + db^2 / b^2) \f$
+   *
+   * @param b_ws :: WorkspaceSingleValue (signal and error) as the RHS argument
+   * @return *this after operation */
+  MDHistoWorkspace & MDHistoWorkspace::operator/=(const Mantid::DataObjects::WorkspaceSingleValue & b_ws)
+  {
+    signal_t b = b_ws.dataY(0)[0];
+    signal_t db2 = b_ws.dataE(0)[0] * b_ws.dataE(0)[0];
+    signal_t db2_relative = db2 / (b*b);
+    for (size_t i=0; i<m_length; ++i)
+    {
+      signal_t a = m_signals[i];
+      signal_t da2 = m_errorsSquared[i];
+
+      signal_t f = a / b;
+      signal_t df2 = (f * f) * ( da2 / (a*a) + db2_relative );
+
+      m_signals[i] = f;
+      m_errorsSquared[i] = df2;
+    }
+    return *this;
+  }
+
+
+  //----------------------------------------------------------------------------------------------
+  /** A boolean &= (and) operation, element-by-element, for two MDHistoWorkspace's.
+   *
+   * 0.0 is "false", all other values are "true". All errors are set to 0.
+   *
+   * @param b :: workspace on the RHS of the operation
+   * @return *this after operation */
+  MDHistoWorkspace & MDHistoWorkspace::operator&=(const MDHistoWorkspace & b)
+  {
+    checkWorkspaceSize(b, "&= (and)");
+    for (size_t i=0; i<m_length; ++i)
+    {
+      m_signals[i] = m_signals[i] && b.m_signals[i];
+      m_errorsSquared[i] = 0;
+    }
+    return *this;
+  }
+
+  //----------------------------------------------------------------------------------------------
+  /** A boolean |= (or) operation, element-by-element, for two MDHistoWorkspace's.
+   *
+   * 0.0 is "false", all other values are "true". All errors are set to 0.
+   *
+   * @param b :: workspace on the RHS of the operation
+   * @return *this after operation */
+  MDHistoWorkspace & MDHistoWorkspace::operator|=(const MDHistoWorkspace & b)
+  {
+    checkWorkspaceSize(b, "|= (or)");
+    for (size_t i=0; i<m_length; ++i)
+    {
+      m_signals[i] = m_signals[i] || b.m_signals[i];
+      m_errorsSquared[i] = 0;
+    }
+    return *this;
+  }
+
+  //----------------------------------------------------------------------------------------------
+  /** A boolean ^= (xor) operation, element-by-element, for two MDHistoWorkspace's.
+   *
+   * 0.0 is "false", all other values are "true". All errors are set to 0.
+   *
+   * @param b :: workspace on the RHS of the operation
+   * @return *this after operation */
+  MDHistoWorkspace & MDHistoWorkspace::operator^=(const MDHistoWorkspace & b)
+  {
+    checkWorkspaceSize(b, "^= (xor)");
+    for (size_t i=0; i<m_length; ++i)
+    {
+      m_signals[i] = bool(m_signals[i]) ^ bool(b.m_signals[i]);
+      m_errorsSquared[i] = 0;
+    }
+    return *this;
+  }
+
+  //----------------------------------------------------------------------------------------------
+  /** A boolean not operation, performed in-place.
+   * All errors are set to 0.
+   *
+   * 0.0 is "false", all other values are "true". All errors are set to 0.
+   */
+  void MDHistoWorkspace::operatorNot()
+  {
+    for (size_t i=0; i<m_length; ++i)
+    {
+      m_signals[i] = !bool(m_signals[i]);
+      m_errorsSquared[i] = 0;
+    }
+  }
+
 
 } // namespace Mantid
 } // namespace MDEvents
diff --git a/Code/Mantid/Framework/MDEvents/test/MDHistoWorkspaceTest.h b/Code/Mantid/Framework/MDEvents/test/MDHistoWorkspaceTest.h
index ffbba22b13423c16c3114a61bb63bd88cb7413f2..c258d400ad4c79c5109afd12b59713170477d51d 100644
--- a/Code/Mantid/Framework/MDEvents/test/MDHistoWorkspaceTest.h
+++ b/Code/Mantid/Framework/MDEvents/test/MDHistoWorkspaceTest.h
@@ -14,6 +14,7 @@
 #include <iomanip>
 #include <iostream>
 #include "MantidAPI/IMDWorkspace.h"
+#include "MantidDataObjects/WorkspaceSingleValue.h"
 
 using namespace Mantid::MDEvents;
 using namespace Mantid::Geometry;
@@ -32,16 +33,25 @@ public:
   MDHistoWorkspace_sptr two;
   MDHistoWorkspace_sptr three;
 
-  MDHistoWorkspace_sptr ma
-
+  /** Create some fake workspace, 5x5, with 2.0 and 3.0 each */
   MDHistoWorkspaceTest()
   {
-    MDEventsTestHelper::makeFakeMDHistoWorkspace(
-    two.
+    two = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 2.0);
+    three = MDEventsTestHelper::makeFakeMDHistoWorkspace(3.0, 2, 5, 10.0, 3.0);
   }
 
+  /** Check that a workspace has the right signal/error*/
+  void checkWorkspace(MDHistoWorkspace_sptr ws, double expectedSignal, double expectedErrorSquared)
+  {
+    for (size_t i=0; i < ws->getNPoints(); i++)
+    {
+      TS_ASSERT_DELTA( ws->getSignalAt(i), expectedSignal, 1e-5 );
+      TS_ASSERT_DELTA( ws->getErrorAt(i), expectedErrorSquared, 1e-5 );
+    }
+  }
 
 
+  //--------------------------------------------------------------------------------------
   void test_constructor()
   {
     MDHistoDimension_sptr dimX(new MDHistoDimension("X", "x", "m", -10, 10, 5));
@@ -364,7 +374,7 @@ public:
   void test_getSignalAtCoord()
   {
     // 2D workspace with signal[i] = i (linear index)
-    MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 1.0, 2, 10);
+    MDHistoWorkspace_sptr ws = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.0, 2, 10);
     for (size_t i=0; i<100; i++)
       ws->setSignalAt(i, double(i));
     IMDWorkspace_sptr iws(ws);
@@ -379,6 +389,133 @@ public:
     TS_ASSERT( boost::math::isnan(iws->getSignalAtCoord(VMD(3.5, 10.02)) ) );
   }
 
+  //--------------------------------------------------------------------------------------
+  void test_plus_ws()
+  {
+    MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 2.5 /*errorSquared*/);
+    MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace(3.0, 2, 5, 10.0, 3.5 /*errorSquared*/);
+    *a += *b;
+    checkWorkspace(a, 5.0, 6.0);
+  }
+
+  void test_plus_scalar()
+  {
+    MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 2.5 /*errorSquared*/);
+    WorkspaceSingleValue b(3.0, sqrt(3.5) );
+    *a += b;
+    checkWorkspace(a, 5.0, 6.0);
+  }
+
+  //--------------------------------------------------------------------------------------
+  void test_minus_ws()
+  {
+    MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(3.0, 2, 5, 10.0, 2.5 /*errorSquared*/);
+    MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 3.5 /*errorSquared*/);
+    *a -= *b;
+    checkWorkspace(a, 1.0, 6.0);
+  }
+
+  void test_minus_scalar()
+  {
+    MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(3.0, 2, 5, 10.0, 2.5 /*errorSquared*/);
+    WorkspaceSingleValue b(2.0, sqrt(3.5) );
+    *a -= b;
+    checkWorkspace(a, 1.0, 6.0);
+  }
+
+  //--------------------------------------------------------------------------------------
+  void test_times_ws()
+  {
+    MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 2.0 /*errorSquared*/);
+    MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace(3.0, 2, 5, 10.0, 3.0 /*errorSquared*/);
+    *a *= *b;
+    checkWorkspace(a, 6.0, 36. * (.5 + 1./3.));
+  }
+
+  //--------------------------------------------------------------------------------------
+  void test_times_scalar()
+  {
+    MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 2.0 /*errorSquared*/);
+    WorkspaceSingleValue b(3.0, sqrt(3.0) );
+    *a *= b;
+    checkWorkspace(a, 6.0, 36. * (.5 + 1./3.));
+    // Scalar without error
+    MDHistoWorkspace_sptr d = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 2.0 /*errorSquared*/);
+    WorkspaceSingleValue e(3.0, 0);
+    *d *= e;
+    checkWorkspace(d, 6.0, 9 * 2.0);
+  }
+
+  //--------------------------------------------------------------------------------------
+  void test_divide_ws()
+  {
+    MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(3.0, 2, 5, 10.0, 3.0 /*errorSquared*/);
+    MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.0, 2, 5, 10.0, 2.0 /*errorSquared*/);
+    *a /= *b;
+    checkWorkspace(a, 1.5, 1.5 * 1.5 * (.5 + 1./3.));
+  }
+
+  //--------------------------------------------------------------------------------------
+  void test_divide_scalar()
+  {
+    MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(3.0, 2, 5, 10.0, 3.0 /*errorSquared*/);
+    WorkspaceSingleValue b(2.0, sqrt(2.0) );
+    *a /= b;
+    checkWorkspace(a, 1.5, 1.5 * 1.5 * (.5 + 1./3.));
+  }
+
+  //--------------------------------------------------------------------------------------
+  void test_boolean_and()
+  {
+    MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.0);
+    MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.34, 2, 5, 10.0, 2.0);
+    MDHistoWorkspace_sptr c = MDEventsTestHelper::makeFakeMDHistoWorkspace(0.00, 2, 5, 10.0, 2.0);
+    *a &= *b;
+    checkWorkspace(a, 1.0, 0.0);
+    *b &= *c;
+    checkWorkspace(b, 0.0, 0.0);
+  }
+
+  //--------------------------------------------------------------------------------------
+  void test_boolean_or()
+  {
+    MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.0);
+    MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.34, 2, 5, 10.0, 2.0);
+    MDHistoWorkspace_sptr c = MDEventsTestHelper::makeFakeMDHistoWorkspace(0.00, 2, 5, 10.0, 2.0);
+    *a |= *b;
+    checkWorkspace(a, 1.0, 0.0);
+    *b |= *c;
+    checkWorkspace(b, 1.0, 0.0);
+    *c |= *c;
+    checkWorkspace(c, 0.0, 0.0);
+  }
+
+  //--------------------------------------------------------------------------------------
+  void test_boolean_xor()
+  {
+    MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.0);
+    MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace(2.34, 2, 5, 10.0, 2.0);
+    MDHistoWorkspace_sptr c = MDEventsTestHelper::makeFakeMDHistoWorkspace(0.00, 2, 5, 10.0, 2.0);
+    *a ^= *b;
+    checkWorkspace(a, 0.0, 0.0);
+    *b ^= *c;
+    checkWorkspace(b, 1.0, 0.0);
+    *c ^= *c;
+    checkWorkspace(c, 0.0, 0.0);
+  }
+
+  //--------------------------------------------------------------------------------------
+  void test_boolean_operatorNot()
+  {
+    MDHistoWorkspace_sptr a = MDEventsTestHelper::makeFakeMDHistoWorkspace(1.23, 2, 5, 10.0, 3.0);
+    MDHistoWorkspace_sptr b = MDEventsTestHelper::makeFakeMDHistoWorkspace(0.00, 2, 5, 10.0, 2.0);
+    a->operatorNot();
+    checkWorkspace(a, 0.0, 0.0);
+    b->operatorNot();
+    checkWorkspace(b, 1.0, 0.0);
+  }
+
+
 };
 
 
diff --git a/Code/Mantid/Framework/TestHelpers/inc/MantidTestHelpers/MDEventsTestHelper.h b/Code/Mantid/Framework/TestHelpers/inc/MantidTestHelpers/MDEventsTestHelper.h
index b1645e54061fa36251b78edd398a205f162f0277..710ce1068133b8860f6eaa7a8023205b510d7646 100644
--- a/Code/Mantid/Framework/TestHelpers/inc/MantidTestHelpers/MDEventsTestHelper.h
+++ b/Code/Mantid/Framework/TestHelpers/inc/MantidTestHelpers/MDEventsTestHelper.h
@@ -43,7 +43,8 @@ namespace MDEventsTestHelper
   DLL_TESTHELPERS Mantid::MDEvents::MDEventWorkspace3Lean::sptr makeFileBackedMDEW(std::string wsName, bool fileBacked);
 
   /// Make a fake n-dimensional MDHistoWorkspace
-  DLL_TESTHELPERS Mantid::MDEvents::MDHistoWorkspace_sptr makeFakeMDHistoWorkspace(double signal, size_t numDims, size_t numBins = 10, double max = 10.0);
+  DLL_TESTHELPERS Mantid::MDEvents::MDHistoWorkspace_sptr makeFakeMDHistoWorkspace(double signal, size_t numDims, size_t numBins = 10, double max = 10.0,
+      double errorSquared=1.0);
 
 
   //-------------------------------------------------------------------------------------
diff --git a/Code/Mantid/Framework/TestHelpers/src/MDEventsTestHelper.cpp b/Code/Mantid/Framework/TestHelpers/src/MDEventsTestHelper.cpp
index da0dc1d0c46e50cecd8f98a2dde7ce3c4c043add..eaeee5883d1c31c9c17e15cd0b5b0530752fb274 100644
--- a/Code/Mantid/Framework/TestHelpers/src/MDEventsTestHelper.cpp
+++ b/Code/Mantid/Framework/TestHelpers/src/MDEventsTestHelper.cpp
@@ -205,7 +205,7 @@ namespace MDEventsTestHelper
    * @return the MDHisto
    */
   Mantid::MDEvents::MDHistoWorkspace_sptr makeFakeMDHistoWorkspace(double signal, size_t numDims, size_t numBins,
-      double max)
+      double max, double errorSquared)
   {
     Mantid::MDEvents::MDHistoWorkspace * ws = NULL;
     if (numDims ==1)
@@ -236,7 +236,7 @@ namespace MDEventsTestHelper
           );
     }
     Mantid::MDEvents::MDHistoWorkspace_sptr ws_sptr(ws);
-    ws_sptr->setTo(signal, signal);
+    ws_sptr->setTo(signal, errorSquared);
     return ws_sptr;
   }