diff --git a/Core/Code/DataManagement/mitkTypeOperations.h b/Core/Code/DataManagement/mitkTypeOperations.h index cba27a37dd..c58579daac 100644 --- a/Core/Code/DataManagement/mitkTypeOperations.h +++ b/Core/Code/DataManagement/mitkTypeOperations.h @@ -1,48 +1,92 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKTYPEOPERATIONS_H_ #define MITKTYPEOPERATIONS_H_ #include +#include "mitkExceptionMacro.h" + /** - * @brief implements sum = s1 + s2 + * @brief implements sum = addend1 + addend2 * Takes FixedArray so you sum all deriving classes like e.g. * sum two points returning a point or * sum a vector and a point, returning a vector. * * @attention Please make sure, that you really want to add the types you specified. * @attention E.g., summing two points does geometrically not make sense, which is why itk does * @attention not provide an operator+ for these types. * - * @param sum - * @param s1 - * @param s2 */ template< typename TCoordRep, unsigned int NPointDimension> void add(itk::FixedArray& sum, - itk::FixedArray& s1, itk::FixedArray& s2) + itk::FixedArray& addend1, itk::FixedArray& addend2) +{ + for (typename itk::FixedArray::SizeType var = 0; var < NPointDimension; ++var) + { + sum[var] = addend1[var] + addend2[var]; + } +} + + +template< typename TCoordRep, unsigned int NPointDimension> +void sub(itk::FixedArray& difference, + itk::FixedArray& minuend, itk::FixedArray& subtrahend) +{ + for (typename itk::FixedArray::SizeType var = 0; var < NPointDimension; ++var) + { + difference[var] = minuend[var] - subtrahend[var]; + } +} + + +template< typename TCoordRep, unsigned int NPointDimension> +void mul(itk::FixedArray& product, + itk::FixedArray& multiplicand, itk::FixedArray& multiplier) +{ + for (typename itk::FixedArray::SizeType var = 0; var < NPointDimension; ++var) + { + product[var] = multiplicand[var] * multiplier[var]; + } +} + + +/** + * + * @throws mitk::Exception in case division by zero is attempted + * + * @param quotient + * @param dividend + * @param divisor + * @param eps defines how near to 0 an exception shall be thrown if trying to divide by such a value. + */ +template< typename TCoordRep, unsigned int NPointDimension> +void div(itk::FixedArray& quotient, + itk::FixedArray& dividend, itk::FixedArray& divisor, + TCoordRep eps = mitk::eps) { for (typename itk::FixedArray::SizeType var = 0; var < NPointDimension; ++var) { - sum[var] = s1[var] + s2[var]; + if (Equal(divisor[var], 0.0, eps)) + mitkThrow() << "Division by zero attempted. 0 found in " << divisor; + quotient[var] = dividend[var] / divisor[var]; // TODO SW: do we want an exception thrown when dividing against zero? } } #endif /* MITKTYPEOPERATIONS_H_ */ diff --git a/Core/Code/Testing/mitkTypeOperationTest.cpp b/Core/Code/Testing/mitkTypeOperationTest.cpp index 71ed395730..f6f2d7e12e 100644 --- a/Core/Code/Testing/mitkTypeOperationTest.cpp +++ b/Core/Code/Testing/mitkTypeOperationTest.cpp @@ -1,69 +1,131 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkTestingMacros.h" #include "mitkPoint.h" #include "mitkTypeOperations.h" #include "mitkTypes.h" // for Equal method. TODO SW: Replace this once the Equal methods have their own header. #include using namespace mitk; static ScalarType bValues[3] = {14.123456, 10.2, 5.123456789}; static ScalarType cValues[3] = { 2.654321, 5.1, 2.543231111}; static Point3D a, b, c; + static void Setup(void) { b = bValues; c = cValues; } + template -static void TestForValues(itk::FixedArray& result, +static void TestForValuesHelper(itk::FixedArray& result, ScalarType v0, ScalarType v1, ScalarType v2, std::string message, ScalarType eps = mitk::eps) { MITK_TEST_CONDITION_REQUIRED( - Equal(result[0], v0) - && Equal(result[1], v1) - && Equal(result[2], v2), message) + Equal(result[0], v0, eps) + && Equal(result[1], v1, eps) + && Equal(result[2], v2, eps), message) } - static void Test_Addition(void) { Setup(); add(a, b, c); - TestForValues(a, 16.777777, 15.3, 7.6666879, "summation a = b + c correctly performed"); + TestForValuesHelper(a, 16.777777, 15.3, 7.6666879, "summation a = b + c correctly performed"); } + +static void Test_Substraction(void) +{ + Setup(); + + sub(a, b, c); + + TestForValuesHelper(a, 11.469135, 5.1, 2.580225678, "difference a = b - c correctly performed"); +} + + +static void Test_Multiplication(void) +{ + Setup(); + + mul(a, b, c); + + TestForValuesHelper(a, 37.4881858534, 52.02, 13.0301347016, "multiplication a = b * c correctly performed", 1E-10); + // google calculator provides us with only 10 digits after comma :) +} + + +static void Test_Division(void) +{ + Setup(); + + div(a, b, c); + + TestForValuesHelper(a, 5.32092991014, 2.0, 2.01454628596, "division a = b / c correctly performed", 1E-11); + // 11 digits after comma provided by google calculator :) +} + + +static void Test_DivisionByZero(void) +{ + Setup(); + c[2] = mitk::eps; + + MITK_TEST_FOR_EXCEPTION(mitk::Exception&, div(a,b,c, 2.0 * c[2])) +} + + +static void Test_DivisionByAlmostZero(void) +{ + Setup(); + c[2] = 2.0 * mitk::eps; + + div(a,b,c); + + MITK_TEST_CONDITION_REQUIRED(true, "division by element almost equal to zero doesn't throw exception") +} + + int mitkTypeOperationTest(int /*argc*/ , char* /*argv*/[]) { // always start with this! MITK_TEST_BEGIN("TypeOperationTest") Test_Addition(); + Test_Substraction(); + + Test_Multiplication(); + + Test_Division(); + Test_DivisionByZero(); + Test_DivisionByAlmostZero(); + MITK_TEST_END() }