瀏覽代碼

Add ctkUtils::closestPowerOfTen

Julien Finet 14 年之前
父節點
當前提交
0961c9b02e
共有 4 個文件被更改,包括 180 次插入0 次删除
  1. 2 0
      Libs/Core/Testing/Cpp/CMakeLists.txt
  2. 125 0
      Libs/Core/Testing/Cpp/ctkUtilsTest5.cpp
  3. 35 0
      Libs/Core/ctkUtils.cpp
  4. 18 0
      Libs/Core/ctkUtils.h

+ 2 - 0
Libs/Core/Testing/Cpp/CMakeLists.txt

@@ -36,6 +36,7 @@ SET(KITTests_SRCS
   ctkUtilsTest2.cpp
   ctkUtilsTest3.cpp
   ctkUtilsTest4.cpp
+  ctkUtilsTest5.cpp
   ctkDependencyGraphTest1.cpp
   ctkDependencyGraphTest2.cpp
   ctkPimplTest1.cpp
@@ -130,6 +131,7 @@ SIMPLE_TEST( ctkUtilsTest1 )
 SIMPLE_TEST( ctkUtilsTest2 )
 SIMPLE_TEST( ctkUtilsTest3 )
 SIMPLE_TEST( ctkUtilsTest4 )
+SIMPLE_TEST( ctkUtilsTest5 )
 SIMPLE_TEST( ctkWorkflowTest1 )
 SIMPLE_TEST( ctkWorkflowTest2 )
 SIMPLE_TEST( ctkWorkflowTest3 )

+ 125 - 0
Libs/Core/Testing/Cpp/ctkUtilsTest5.cpp

@@ -0,0 +1,125 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// Qt includes
+#include <QDebug>
+#include <QStringList>
+
+// CTK includes
+#include "ctkUtils.h"
+
+// STD includes
+#include <stdlib.h>
+#include <iostream>
+#include <limits>
+#include <string>
+#include <vector>
+
+//-----------------------------------------------------------------------------
+int ctkUtilsTest5(int , char *  [] )
+{
+  std::cout.precision(16);
+
+  if (ctk::closestPowerOfTen(1.) != 1.)
+    {
+    std::cerr << "closest power of 10 failed for number:"
+              << 1. << ". Found " << ctk::closestPowerOfTen(1.)
+              << " instead of 1." << std::endl;
+    return EXIT_FAILURE;
+    }
+  if (ctk::closestPowerOfTen(2.) != 1.)
+    {
+    std::cerr << "closest power of 10 failed for number:"
+              << 2. << ". Found " << ctk::closestPowerOfTen(2.)
+              << " instead of 1." << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  if (ctk::closestPowerOfTen(10.) != 10.)
+    {
+    std::cerr << "closest power of 10 failed for number:"
+              << 10. << ". Found " << ctk::closestPowerOfTen(10.)
+              << " instead of 10." << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  if (ctk::closestPowerOfTen(45.) != 10.)
+    {
+    std::cerr << "closest power of 10 failed for number:"
+              << 45. << ". Found " << ctk::closestPowerOfTen(45.)
+              << " instead of 10." << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  if (ctk::closestPowerOfTen(98) != 100.)
+    {
+    std::cerr << "closest power of 10 failed for number:"
+              << 98. << ". Found " << ctk::closestPowerOfTen(98.)
+              << " instead of 100." << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  if (ctk::closestPowerOfTen(50.) != 10.)
+    {
+    std::cerr << "closest power of 10 failed for number:"
+              << 50. << ". Found " << ctk::closestPowerOfTen(50.)
+              << " instead of 10." << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  if (ctk::closestPowerOfTen(-1234.) != -1000)
+    {
+    std::cerr << "closest power of 10 failed for number:"
+              << -1234 << ". Found " << ctk::closestPowerOfTen(-1234)
+              << " instead of -1000" << std::endl;
+    return EXIT_FAILURE;
+    }
+  double closest  = ctk::closestPowerOfTen(0.01);
+  if ( closest < 0.01 - std::numeric_limits<double>::epsilon() ||
+       closest > 0.01 + std::numeric_limits<double>::epsilon())
+    {
+    std::cerr << "closest power of 10 failed for number:"
+              << 0.01 << ". Found " << closest
+              << " instead of 0.01" << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  closest = ctk::closestPowerOfTen(0.00000000015);
+  if ( closest < 0.0000000001 - std::numeric_limits<double>::epsilon() ||
+       closest > 0.0000000001 + std::numeric_limits<double>::epsilon())
+    {
+    std::cerr << "closest power of 10 failed for number:"
+              << 0.00000000015 << ". Found " << closest
+              << " instead of 0.0000000001" << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  closest = ctk::closestPowerOfTen(0.1);
+  if (closest < 0.1 - std::numeric_limits<double>::epsilon() ||
+       closest > 0.1 + std::numeric_limits<double>::epsilon())
+    {
+    std::cerr << "closest power of 10 failed for number:"
+              << 0.1 << ". Found " << closest
+              << " instead of 0.1" << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  return EXIT_SUCCESS;
+}

+ 35 - 0
Libs/Core/ctkUtils.cpp

@@ -210,6 +210,7 @@ int ctk::significantDecimals(double value)
   return -1;
 }
 
+//-----------------------------------------------------------------------------
 int ctk::orderOfMagnitude(double value)
 {
   value = qAbs(value);
@@ -239,3 +240,37 @@ int ctk::orderOfMagnitude(double value)
   // we went 1 order too far, so decrement it
   return magnitudeOrder - magnitudeStep;
 }
+
+//-----------------------------------------------------------------------------
+double ctk::closestPowerOfTen(double value)
+{
+  double sign = value >= 0. ? 1 : -1;
+  value = qAbs(value);
+  if (value == 0.)
+    {
+    return 0.;
+    }
+
+  double magnitude = 1.;
+  double nextMagnitude = magnitude;
+
+  if (value >= 1.)
+    {
+    do
+      {
+      magnitude = nextMagnitude;
+      nextMagnitude *= 10.;
+      }
+    while ( (value - magnitude)  > (nextMagnitude - value) );
+    }
+  else
+    {
+    do
+      {
+      magnitude = nextMagnitude;
+      nextMagnitude /= 10.;
+      }
+    while ( (value - magnitude)  < (nextMagnitude - value) );
+    }
+  return magnitude * sign;
+}

+ 18 - 0
Libs/Core/ctkUtils.h

@@ -78,13 +78,31 @@ QRegExp CTK_CORE_EXPORT nameFiltersToRegExp(const QStringList& nameFilters);
 /// \ingroup Core
 /// Return a "smart" number of decimals needed to display (in a gui) a floating
 /// number.
+/// e.g. significantDecimals(120.01) returns 2
 int CTK_CORE_EXPORT significantDecimals(double value);
 
 ///
 /// \ingroup Core
 /// Return the order of magnitude of a number.
+/// e.g.: orderOfMagnitude(1) returns 0
+///       orderOfMagnitude(10) returns 1
+///       orderOfMagnitude(99) returns 1
+///       orderOfMagnitude(101) returns 2
+///       orderOfMagnitude(0.1) returns -1
+///       orderOfMagnitude(0.15) returns -1
+///       orderOfMagnitude(0.) returns NaN
 int CTK_CORE_EXPORT orderOfMagnitude(double value);
 
+///
+/// \ingroup Core
+/// Return the order of magnitude of a number.
+/// e.g.: closestPowerOfTen(11) returns 10
+///       closestPowerOfTen(-40) returns -10
+///       closestPowerOfTen(99) returns 100
+///       closestPowerOfTen(0.012) returns 0.010
+///       orderOfMagnitude(0.)  returns 0
+double CTK_CORE_EXPORT closestPowerOfTen(double value);
+
 }
 
 #endif