swift
mathutils.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2013 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
4 #include "misc/math/mathutils.h"
5 
6 #include <cmath>
7 #include <cstdlib>
8 #include <limits>
9 
10 #include <QTime>
11 #include <QtGlobal>
12 
13 #include "misc/math/constants.h"
14 #include "misc/verify.h"
15 
16 namespace swift::misc::math
17 {
18  double CMathUtils::round(double value, int digits)
19  {
20  // gosh, is there no Qt method for this??? It's year 2013
21  double fractpart, intpart;
22  fractpart = modf(value, &intpart);
23  if (epsilonZeroLimits(fractpart)) { return value; } // do not mess any "integers" to the worse
24  const double m = pow(10.0, digits);
25  const qint64 ri = qRound64(value * m); // do not loose any range here
26  const double rv = static_cast<double>(ri) / m;
27  return rv;
28  }
29 
30  double CMathUtils::roundEpsilon(double value, double epsilon)
31  {
32  if (epsilonZeroLimits(epsilon)) { return value; } // avoid division by 0
33  double fractpart, intpart;
34  fractpart = modf(value, &intpart);
35  if (epsilonZeroLimits(fractpart)) { return value; } // do not mess any "integers" to the worse
36  const double roundValue = value / epsilon;
37  const qint64 ri = qRound64(roundValue);
38  const double rv = static_cast<double>(ri) * epsilon; // do not loose any range here
39  return rv;
40  }
41 
42  bool CMathUtils::epsilonEqual(float v1, float v2, float epsilon) { return qAbs(v1 - v2) <= epsilon; }
43 
44  bool CMathUtils::epsilonEqual(double v1, double v2, double epsilon) { return qAbs(v1 - v2) <= epsilon; }
45 
46  double CMathUtils::deg2rad(double degree) { return degree * c_pi / 180.0; }
47 
48  double CMathUtils::rad2deg(double radians) { return radians * 180.0 / c_pi; }
49 
50  double CMathUtils::normalizeDegrees180(double degrees)
51  {
52  const double result = CMathUtils::normalizeDegrees360(degrees + 180.0) - 180.0;
53  return (result <= -180.0) ? 180.0 : result; // -180->180
54  }
55 
56  double CMathUtils::normalizeDegrees360(double degrees)
57  {
58  const double result = std::fmod(degrees, 360.0);
59  return (result >= 0.0) ? result : result + 360.0;
60  }
61 
62  QRandomGenerator &CMathUtils::randomGenerator()
63  {
64  thread_local QRandomGenerator rng(QRandomGenerator::global()->generate());
65  return rng;
66  }
67 
68  int CMathUtils::randomInteger(int low, int high)
69  {
70  Q_ASSERT_X(high < INT_MAX, Q_FUNC_INFO, "Cannot add 1");
71  return randomGenerator().bounded(low, high + 1);
72  }
73 
74  double CMathUtils::randomDouble(double max)
75  {
76  constexpr int MAX(std::min(RAND_MAX - 1, INT_MAX - 1));
77  const double r = randomInteger(0, MAX);
78  return (r / MAX) * max;
79  }
80 
81  bool CMathUtils::randomBool() { return randomInteger(0, 1); }
82 
83  int CMathUtils::roundToMultipleOf(int value, int divisor)
84  {
85  Q_ASSERT(divisor != 0);
86  Q_ASSERT(divisor >= -std::numeric_limits<int>::max());
87  divisor = std::abs(divisor);
88  Q_ASSERT(std::abs(value) < std::numeric_limits<int>::max() - divisor / 2);
89 
90  int multiplier = value / divisor;
91  int remainder = std::abs(value % divisor);
92  int shortfall = divisor - remainder;
93 
94  if (shortfall < remainder) { multiplier += value < 0 ? -1 : 1; }
95 
96  return multiplier * divisor;
97  }
98 
99  QString CMathUtils::fractionalPartAsString(double value, int width)
100  {
101  double intpart;
102  const double fractpart = modf(value, &intpart);
103  const int prec = width >= 0 ? width + 1 : 10;
104  const QString f = QString::number(fractpart, 'f', prec); // avoid scientific notation
105  const QString fInt = f.length() < 3 ? QString("0") : f.mid(2);
106  if (width < 0) { return fInt; }
107  if (fInt.length() >= width) { return fInt.left(width); }
108  return fInt.leftJustified(width, '0');
109  }
110 
111  double CMathUtils::sum(const QList<double> &values)
112  {
113  double sum = 0;
114  for (double v : values) { sum += v; }
115  return sum;
116  }
117 
118  QList<double> CMathUtils::squaredDifferences(const QList<double> &values)
119  {
120  const double meanValue = mean(values);
121  return squaredDifferences(values, meanValue);
122  }
123 
124  QList<double> CMathUtils::squaredDifferences(const QList<double> &values, double meanValue)
125  {
126  QList<double> squaresDifferences;
127  for (double v : values)
128  {
129  const double vd = v - meanValue;
130  squaresDifferences.push_back(vd * vd);
131  }
132  return squaresDifferences;
133  }
134 
135  double CMathUtils::mean(const QList<double> &values)
136  {
137  SWIFT_VERIFY_X(!values.isEmpty(), Q_FUNC_INFO, "Need values");
138  return sum(values) / values.size();
139  }
140 
141  double CMathUtils::variance(const QList<double> &values)
142  {
143  const double variance = mean(squaredDifferences(values));
144  return variance;
145  }
146 
147  double CMathUtils::standardDeviation(const QList<double> &values)
148  {
149  const double sd = sqrt(variance(values));
150  return sd;
151  }
152 
153  QPair<double, double> CMathUtils::standardDeviationAndMean(const QList<double> &values)
154  {
155  const double meanValue = mean(values);
156  const double varianceValue = mean(squaredDifferences(values, meanValue));
157  const double sd = sqrt(varianceValue);
158  return QPair<double, double>(sd, meanValue);
159  }
160 } // namespace swift::misc::math
static double rad2deg(double radians)
Radians to degrees.
Definition: mathutils.cpp:48
static double deg2rad(double degree)
Degrees to radians.
Definition: mathutils.cpp:46
static bool epsilonEqual(float v1, float v2, float epsilon=1E-06f)
Epsilon safe equal.
Definition: mathutils.cpp:42
static QRandomGenerator & randomGenerator()
Thread-local random generator.
Definition: mathutils.cpp:62
static bool epsilonZeroLimits(double v)
Epsilon safe zero.
Definition: mathutils.h:48
static int randomInteger(int low, int high)
Random number between low and high.
Definition: mathutils.cpp:68
static bool randomBool()
Random boolean.
Definition: mathutils.cpp:81
static double sum(const QList< double > &values)
Calculate the sum.
Definition: mathutils.cpp:111
static int roundToMultipleOf(int value, int divisor)
Round numToRound to the nearest multiple of divisor.
Definition: mathutils.cpp:83
static double normalizeDegrees180(double degrees)
Normalize: -180< degrees ≤180.
Definition: mathutils.cpp:50
static QPair< double, double > standardDeviationAndMean(const QList< double > &values)
Standard deviation (first) and mean (second)
Definition: mathutils.cpp:153
static double standardDeviation(const QList< double > &values)
Calculate the standard deviation.
Definition: mathutils.cpp:147
static double mean(const QList< double > &values)
Calculate the mean.
Definition: mathutils.cpp:135
static double round(double value, int digits)
Utility round method.
Definition: mathutils.cpp:18
static QString fractionalPartAsString(double value, int width=-1)
Fractional part as integer string, e.g. 3.12 -> 12 / 3.012 -> 012.
Definition: mathutils.cpp:99
static double normalizeDegrees360(double degrees)
Normalize: 0≤ degrees <360.
Definition: mathutils.cpp:56
static double randomDouble(double max=1)
Random double 0-max.
Definition: mathutils.cpp:74
static double roundEpsilon(double value, double epsilon)
Round by given epsilon.
Definition: mathutils.cpp:30
constexpr double c_pi
PI.
Definition: constants.h:12
#define SWIFT_VERIFY_X(COND, WHERE, WHAT)
A weaker kind of assert.
Definition: verify.h:26