Kstars

cachingdms.cpp
1/*
2 SPDX-FileCopyrightText: 2016 Akarsh Simha <akarsh.simha@kdemail.net>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7/* Project Includes */
8#include "cachingdms.h"
9
10/* KDE Includes */
11
12/* Qt Includes */
13#include <QString>
14
15/* STL Includes */
16#include <cmath>
17
18#ifdef COUNT_DMS_SINCOS_CALLS
19unsigned long CachingDms::cachingdms_constructor_calls = 0;
20long CachingDms::cachingdms_delta = 0; // difference of ( trig function calls ) - ( trig computations )
21unsigned long CachingDms::cachingdms_bad_uses = 0;
22#endif
23
24CachingDms::CachingDms(const double &x) : dms(x)
25{
26 dms::SinCos(m_sin, m_cos);
27#ifdef COUNT_DMS_SINCOS_CALLS
28 ++cachingdms_constructor_calls;
29 cachingdms_delta -= 2;
30 m_cacheUsed = false;
31#endif
32}
33
34#ifdef COUNT_DMS_SINCOS_CALLS
35CachingDms::~CachingDms()
36{
37 if (!m_cacheUsed)
38 ++cachingdms_bad_uses;
39}
40#endif
41
42CachingDms::CachingDms(const QString &s, bool isDeg) : dms(s, isDeg)
43{
44 dms::SinCos(m_sin, m_cos);
45#ifdef COUNT_DMS_SINCOS_CALLS
46 ++cachingdms_constructor_calls;
47 cachingdms_delta -= 2;
48 m_cacheUsed = false;
49#endif
50}
51
52CachingDms::CachingDms(const int &d, const int &m, const int &s, const int &ms) : dms(d, m, s, ms)
53{
54 dms::SinCos(m_sin, m_cos);
55#ifdef COUNT_DMS_SINCOS_CALLS
56 ++cachingdms_constructor_calls;
57 cachingdms_delta -= 2;
58 m_cacheUsed = false;
59#endif
60}
61
62void CachingDms::setUsing_atan2(const double &y, const double &x)
63{
64 /*
65 * NOTE: A bit of independent profiling shows that on my machine
66 * (Intel Core i5, x86_64, glibc 2.24-2) the square-root based
67 * computation below has some advantage, running ~ 70% faster on
68 * average for some range of values.
69 *
70 */
71 dms::setRadians(atan2(y, x));
72 double r = sqrt(y * y + x * x);
73 m_cos = x / r;
74 m_sin = y / r;
75
76#ifdef COUNT_DMS_SINCOS_CALLS
77 if (!m_cacheUsed)
78 ++cachingdms_bad_uses;
79 m_cacheUsed = false;
80#endif
81 // One may be tempted to do the following:
82 // dms::setRadians( atan2( y, x ) );
83 // m_cos = dms::cos();
84 // m_sin = (y/x) * m_cos;
85 // However, this has a problem when x = 0. The result for m_sin
86 // must be 1, but instead the above code will result in NaN.
87 // So we will need a conditional:
88 // m_sin = (x == 0) ? 1. : (y/x) * m_cos;
89 // The conditional makes the performance worse than just setting
90 // the angle and using sincos()
91}
92
93void CachingDms::setUsing_asin(const double &sine)
94{
95 dms::setRadians(asin(sine));
96 m_sin = sine;
97 // Note: The below is valid because in the range of asin, which is
98 // [-pi/2, pi/2], cosine is always non-negative
99 m_cos = std::sqrt(1 - sine * sine);
100#ifdef COUNT_DMS_SINCOS_CALLS
101 if (!m_cacheUsed)
102 ++cachingdms_bad_uses;
103 m_cacheUsed = false;
104#endif
105}
106
107void CachingDms::setUsing_acos(const double &cosine)
108{
109 dms::setRadians(acos(cosine));
110 m_cos = cosine;
111 // Note: The below is valid because in the range of acos, which is
112 // [0, pi], sine is always non-negative
113 m_sin = std::sqrt(1 - cosine * cosine);
114#ifdef COUNT_DMS_SINCOS_CALLS
115 if (!m_cacheUsed)
116 ++cachingdms_bad_uses;
117 m_cacheUsed = false;
118#endif
119}
120
122{
123 CachingDms result;
124 result.setFromString(s, deg);
125 return result;
126}
127
129{
130 return CachingDms(-D, -m_sin, m_cos);
131}
132
134{
135 D = angle.Degrees();
136 dms::SinCos(m_sin, m_cos);
137#ifdef COUNT_DMS_SINCOS_CALLS
138 ++cachingdms_constructor_calls;
139 cachingdms_delta -= 2;
140 m_cacheUsed = false;
141#endif
142}
143
144#ifdef COUNT_DMS_SINCOS_CALLS
146{
147 m_sin = o.sin();
148 m_cos = o.cos();
149 D = o.D;
150 m_cacheUsed = false;
151}
152CachingDms &CachingDms::operator=(const CachingDms &o)
153{
154 if (!m_cacheUsed)
155 ++cachingdms_bad_uses;
156 m_sin = o.sin();
157 m_cos = o.cos();
158 D = o.D;
159 m_cacheUsed = false;
160 return (*this);
161}
162#endif
163
164// Makes trig identities more readable:
165#define sinA a.sin()
166#define cosA a.cos()
167#define sinB b.sin()
168#define cosB b.cos()
169
170// We use trigonometric addition / subtraction formulae to speed up
171// computation. This way, we have no trigonometric function calls at
172// all, but only floating point multiplications and
173// addition/subtraction instead.
174// The only caveat is that error can accumulate if used repeatedly!
175
176CachingDms operator+(const CachingDms &a, const CachingDms &b)
177{
178 return CachingDms(a.Degrees() + b.Degrees(), sinA * cosB + cosA * sinB, cosA * cosB - sinA * sinB);
179}
180
181CachingDms operator-(const CachingDms &a, const CachingDms &b)
182{
183 return CachingDms(a.Degrees() - b.Degrees(), sinA * cosB - cosA * sinB, cosA * cosB + sinA * sinB);
184}
185
186CachingDms operator+(const dms &a, const CachingDms &b)
187{
188 return CachingDms(a + dms(b));
189}
190
191CachingDms operator-(const dms &a, const CachingDms &b)
192{
193 return CachingDms(a - dms(b));
194}
195
196CachingDms operator+(const CachingDms &a, const dms &b)
197{
198 return CachingDms(dms(a) + b);
199}
200
201CachingDms operator-(const CachingDms &a, const dms &b)
202{
203 return CachingDms(dms(a) - b);
204}
205
206#undef sinA
207#undef cosA
208#undef sinB
209#undef cosB
a dms subclass that caches its sine and cosine values every time the angle is changed.
Definition cachingdms.h:19
CachingDms operator-()
operator -
double cos() const
Get the cosine of this angle.
Definition cachingdms.h:204
void setUsing_atan2(const double &y, const double &x)
Sets the angle using atan2()
static CachingDms fromString(const QString &s, bool deg)
Construct an angle from the given string.
bool setFromString(const QString &s, bool isDeg=true) override
Sets the angle from string.
Definition cachingdms.h:120
CachingDms()
Default Constructor.
Definition cachingdms.h:24
double sin() const
Get the sine of this angle.
Definition cachingdms.h:190
void setUsing_asin(const double &sine)
Sets the angle using asin()
void setUsing_acos(const double &cosine)
Sets the angle using acos()
An angle, stored as degrees, but expressible in many ways.
Definition dms.h:38
void SinCos(double &s, double &c) const
Compute Sine and Cosine of the angle simultaneously.
Definition dms.h:447
virtual void setRadians(const double &Rad)
Set angle according to the argument, in radians.
Definition dms.h:333
const double & Degrees() const
Definition dms.h:141
QCA_EXPORT const SecureArray operator+(const SecureArray &a, const SecureArray &b)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:19:01 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.