all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
blob 288d56919e825d90c5e09dc94c8e58cb025a30a7 7980 bytes (raw)
name: gnu/packages/patches/qd-fix-accuracy-in-angle-computation.patch 	 # note: path name is non-authoritative(*)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
 
From e5ccba8fc889c38f49a247ff3060e8462388f6f9 Mon Sep 17 00:00:00 2001
From: Sharlatan Hellseher <sharlatanus@gmail.com>
Date: Thu, 2 Nov 2023 02:49:54 +0000
Subject: [PATCH] Fix accuracy in angle computation (#224)

Author: Mihai Cara <mcara@users.noreply.github.com>
Source: https://github.com/spacetelescope/spherical_geometry/pull/224

* Fix accuracy in angle computation

* Enhance comparisons and expose QD 2*pi
---
 include/qd/c_dd.h    |  2 ++
 include/qd/c_qd.h    |  4 ++-
 include/qd/qd_real.h | 11 ++++----
 src/c_dd.cpp         |  8 ++++++
 src/c_qd.cpp         | 15 +++++++++--
 src/qd_real.cpp      | 63 +++++++++++++++++++++++++++-----------------
 6 files changed, 71 insertions(+), 32 deletions(-)

diff --git a/include/qd/c_dd.h b/include/qd/c_dd.h
index 203a8fa..7ffcb01 100644
--- a/include/qd/c_dd.h
+++ b/include/qd/c_dd.h
@@ -90,6 +90,8 @@ void c_dd_comp(const double *a, const double *b, int *result);
 void c_dd_comp_dd_d(const double *a, double b, int *result);
 void c_dd_comp_d_dd(double a, const double *b, int *result);
 void c_dd_pi(double *a);
+void c_dd_2pi(double *a);
+double c_dd_epsilon(void);
 
 #ifdef __cplusplus
 }
diff --git a/include/qd/c_qd.h b/include/qd/c_qd.h
index 9062d1d..b118f26 100644
--- a/include/qd/c_qd.h
+++ b/include/qd/c_qd.h
@@ -65,7 +65,7 @@ void c_qd_copy(const double *a, double *b);
 void c_qd_copy_dd(const double *a, double *b);
 void c_qd_copy_d(double a, double *b);
 
-void c_qd_sqrt(const double *a, double *b);
+int c_qd_sqrt(const double *a, double *b);
 void c_qd_sqr(const double *a, double *b);
 
 void c_qd_abs(const double *a, double *b);
@@ -111,6 +111,8 @@ void c_qd_comp(const double *a, const double *b, int *result);
 void c_qd_comp_qd_d(const double *a, double b, int *result);
 void c_qd_comp_d_qd(double a, const double *b, int *result);
 void c_qd_pi(double *a);
+void c_qd_2pi(double *a);
+double c_qd_epsilon(void);
 
 #ifdef __cplusplus
 }
diff --git a/include/qd/qd_real.h b/include/qd/qd_real.h
index 32079d0..9435678 100644
--- a/include/qd/qd_real.h
+++ b/include/qd/qd_real.h
@@ -120,16 +120,16 @@ struct QD_API qd_real {
   static qd_real rand(void);
 
   void to_digits(char *s, int &expn, int precision = _ndigits) const;
-  void write(char *s, int len, int precision = _ndigits, 
+  void write(char *s, int len, int precision = _ndigits,
       bool showpos = false, bool uppercase = false) const;
-  std::string to_string(int precision = _ndigits, int width = 0, 
-      std::ios_base::fmtflags fmt = static_cast<std::ios_base::fmtflags>(0), 
+  std::string to_string(int precision = _ndigits, int width = 0,
+      std::ios_base::fmtflags fmt = static_cast<std::ios_base::fmtflags>(0),
       bool showpos = false, bool uppercase = false, char fill = ' ') const;
   static int read(const char *s, qd_real &a);
 
   /* Debugging methods */
   void dump(const std::string &name = "", std::ostream &os = std::cerr) const;
-  void dump_bits(const std::string &name = "", 
+  void dump_bits(const std::string &name = "",
                  std::ostream &os = std::cerr) const;
 
   static qd_real debug_rand();
@@ -150,7 +150,7 @@ namespace std {
 }
 
 QD_API qd_real polyeval(const qd_real *c, int n, const qd_real &x);
-QD_API qd_real polyroot(const qd_real *c, int n, 
+QD_API qd_real polyroot(const qd_real *c, int n,
     const qd_real &x0, int max_iter = 64, double thresh = 0.0);
 
 QD_API qd_real qdrand(void);
@@ -190,6 +190,7 @@ QD_API qd_real operator/(double a, const qd_real &b);
 
 QD_API qd_real sqr(const qd_real &a);
 QD_API qd_real sqrt(const qd_real &a);
+QD_API qd_real fsqrt(const qd_real &a, int &flag);
 QD_API qd_real pow(const qd_real &a, int n);
 QD_API qd_real pow(const qd_real &a, const qd_real &b);
 QD_API qd_real npwr(const qd_real &a, int n);
diff --git a/src/c_dd.cpp b/src/c_dd.cpp
index 1cb2989..1df03e2 100644
--- a/src/c_dd.cpp
+++ b/src/c_dd.cpp
@@ -311,4 +311,12 @@ void c_dd_pi(double *a) {
   TO_DOUBLE_PTR(dd_real::_pi, a);
 }
 
+void c_dd_2pi(double *a) {
+  TO_DOUBLE_PTR(dd_real::_2pi, a);
+}
+
+double c_dd_epsilon(void) {
+    return (double) std::numeric_limits<dd_real>::epsilon();
+}
+
 }
diff --git a/src/c_qd.cpp b/src/c_qd.cpp
index 010cf85..95cffb3 100644
--- a/src/c_qd.cpp
+++ b/src/c_qd.cpp
@@ -237,11 +237,14 @@ void c_qd_copy_d(double a, double *b) {
 }
 
 
-void c_qd_sqrt(const double *a, double *b) {
+int c_qd_sqrt(const double *a, double *b) {
+  int flag;
   qd_real bb;
-  bb = sqrt(qd_real(a));
+  bb = fsqrt(qd_real(a), flag);
   TO_DOUBLE_PTR(bb, b);
+  return flag;
 }
+
 void c_qd_sqr(const double *a, double *b) {
   qd_real bb;
   bb = sqr(qd_real(a));
@@ -447,4 +450,12 @@ void c_qd_pi(double *a) {
   TO_DOUBLE_PTR(qd_real::_pi, a);
 }
 
+void c_qd_2pi(double *a) {
+  TO_DOUBLE_PTR(qd_real::_2pi, a);
+}
+
+double c_qd_epsilon(void) {
+    return (double) std::numeric_limits<qd_real>::epsilon();
+}
+
 }
diff --git a/src/qd_real.cpp b/src/qd_real.cpp
index 70988ff..2da15c2 100644
--- a/src/qd_real.cpp
+++ b/src/qd_real.cpp
@@ -191,7 +191,7 @@ istream &operator>>(istream &s, qd_real &qd) {
 ostream &operator<<(ostream &os, const qd_real &qd) {
   bool showpos = (os.flags() & ios_base::showpos) != 0;
   bool uppercase = (os.flags() & ios_base::uppercase) != 0;
-  return os << qd.to_string(os.precision(), os.width(), os.flags(), 
+  return os << qd.to_string(os.precision(), os.width(), os.flags(),
       showpos, uppercase, os.fill());
 }
 
@@ -346,9 +346,9 @@ void qd_real::to_digits(char *s, int &expn, int precision) const {
   }
 
   /* If first digit is 10, shift everything. */
-  if (s[0] > '9') { 
-    e++; 
-    for (i = precision; i >= 2; i--) s[i] = s[i-1]; 
+  if (s[0] > '9') {
+    e++;
+    for (i = precision; i >= 2; i--) s[i] = s[i-1];
     s[0] = '1';
     s[1] = '0';
   }
@@ -519,7 +519,6 @@ string qd_real::to_string(int precision, int width, ios_base::fmtflags fmt,
     	if( fabs( from_string / this->x[0] ) > 3.0 ){
 
     		int point_position;
-    		char temp;
 
     		// loop on the string, find the point, move it up one
     		// don't act on the first character
@@ -736,37 +735,53 @@ qd_real qd_real::accurate_div(const qd_real &a, const qd_real &b) {
   return qd_real(q0, q1, q2, q3);
 }
 
-QD_API qd_real sqrt(const qd_real &a) {
-  /* Strategy:  
-
-     Perform the following Newton iteration:
+QD_API qd_real fsqrt(const qd_real &a, int &flag) {
+  /* Uses Heron's method, see:
+     https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
 
-       x' = x + (1 - a * x^2) * x / 2;
-       
-     which converges to 1/sqrt(a), starting with the
-     double precision approximation to 1/sqrt(a).
-     Since Newton's iteration more or less doubles the
-     number of correct digits, we only need to perform it 
-     twice.
+     1. x0 = approximate sqrt(a);
+     2. x_{n+1} = (1/2) * (x_n + a / x_n);
+     3. repeat 2 until corrections are small
   */
 
+  int i;
+  double e, eps;
+
+  qd_real r, diff;
+  qd_real half = "0.5000000000000000000000000000000000"
+                 "000000000000000000000000000000000000";
+
   if (a.is_zero())
-    return 0.0;
+    return (qd_real) 0.0;
 
   if (a.is_negative()) {
     qd_real::error("(qd_real::sqrt): Negative argument.");
     return qd_real::_nan;
   }
 
-  qd_real r = (1.0 / std::sqrt(a[0]));
-  qd_real h = mul_pwr2(a, 0.5);
+  eps = std::numeric_limits<qd_real>::epsilon();
 
-  r += ((0.5 - h * sqr(r)) * r);
-  r += ((0.5 - h * sqr(r)) * r);
-  r += ((0.5 - h * sqr(r)) * r);
+  qd_real x = std::sqrt(a[0]);
+  qd_real y;
 
-  r *= a;
-  return r;
+  for (i=0; i < 10; i++) {
+      y = half * (x + a / x);
+      diff = x - y;
+      x = y;
+      e = fabs(((diff[3] + diff[2]) + diff[1]) + diff[0]);
+      if (e < fabs(x.x[0]) * eps) {
+          flag = 0; // convergence achieved
+          return x;
+      }
+  }
+
+  flag = 1; // failed to converge
+  return x;
+}
+
+QD_API qd_real sqrt(const qd_real &a) {
+  int flag;
+  return fsqrt(a, flag);
 }
 
 
-- 
2.41.0


debug log:

solving 288d56919e ...
found 288d56919e in https://yhetil.org/guix/8467e1ff586aa25e5659801006dcb7a0784dc576.1698938938.git.sharlatanus@gmail.com/

applying [1/1] https://yhetil.org/guix/8467e1ff586aa25e5659801006dcb7a0784dc576.1698938938.git.sharlatanus@gmail.com/
diff --git a/gnu/packages/patches/qd-fix-accuracy-in-angle-computation.patch b/gnu/packages/patches/qd-fix-accuracy-in-angle-computation.patch
new file mode 100644
index 0000000000..288d56919e

1:37: trailing whitespace.
 
1:47: trailing whitespace.
 
1:51: trailing whitespace.
 
1:59: trailing whitespace.
 
1:68: trailing whitespace.
 
Checking patch gnu/packages/patches/qd-fix-accuracy-in-angle-computation.patch...
Applied patch gnu/packages/patches/qd-fix-accuracy-in-angle-computation.patch cleanly.
warning: squelched 40 whitespace errors
warning: 45 lines add whitespace errors.

index at:
100644 288d56919e825d90c5e09dc94c8e58cb025a30a7	gnu/packages/patches/qd-fix-accuracy-in-angle-computation.patch

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/guix.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.