• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 	Multi-precision real number class. C++ interface fo MPFR library.
3 	Project homepage: http://www.holoborodko.com/pavel/
4 	Contact e-mail:   pavel@holoborodko.com
5 
6 	Copyright (c) 2008-2011 Pavel Holoborodko
7 
8 	Core Developers:
9 	Pavel Holoborodko, Dmitriy Gubanov, Konstantin Holoborodko.
10 
11 	Contributors:
12 	Brian Gladman, Helmut Jarausch, Fokko Beekhof, Ulrich Mutze,
13 	Heinz van Saanen, Pere Constans, Peter van Hoof, Gael Guennebaud,
14 	Tsai Chia Cheng, Alexei Zubanov.
15 
16 	****************************************************************************
17 	This library is free software; you can redistribute it and/or
18 	modify it under the terms of the GNU Lesser General Public
19 	License as published by the Free Software Foundation; either
20 	version 2.1 of the License, or (at your option) any later version.
21 
22 	This library is distributed in the hope that it will be useful,
23 	but WITHOUT ANY WARRANTY; without even the implied warranty of
24 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25 	Lesser General Public License for more details.
26 
27 	You should have received a copy of the GNU Lesser General Public
28 	License along with this library; if not, write to the Free Software
29 	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
30 
31 	****************************************************************************
32 	****************************************************************************
33 	Redistribution and use in source and binary forms, with or without
34 	modification, are permitted provided that the following conditions
35 	are met:
36 
37 	1. Redistributions of source code must retain the above copyright
38 	notice, this list of conditions and the following disclaimer.
39 
40 	2. Redistributions in binary form must reproduce the above copyright
41 	notice, this list of conditions and the following disclaimer in the
42 	documentation and/or other materials provided with the distribution.
43 
44 	3. The name of the author may be used to endorse or promote products
45 	derived from this software without specific prior written permission.
46 
47 	THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
48 	ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 	ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
51 	FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 	DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 	OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 	HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 	LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 	OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 	SUCH DAMAGE.
58 */
59 #include <cstring>
60 #include "mpreal.h"
61 
62 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
63 #include "dlmalloc.h"
64 #endif
65 
66 using std::ws;
67 using std::cerr;
68 using std::endl;
69 using std::string;
70 using std::ostream;
71 using std::istream;
72 
73 namespace mpfr{
74 
75 mp_rnd_t   mpreal::default_rnd  = MPFR_RNDN;	//(mpfr_get_default_rounding_mode)();
76 mp_prec_t  mpreal::default_prec = 64;			//(mpfr_get_default_prec)();
77 int		   mpreal::default_base = 10;
78 int        mpreal::double_bits = -1;
79 
80 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
81 bool       mpreal::is_custom_malloc = false;
82 #endif
83 
84 // Default constructor: creates mp number and initializes it to 0.
mpreal()85 mpreal::mpreal()
86 {
87 
88 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
89 	set_custom_malloc();
90 #endif
91 
92 	mpfr_init2(mp,default_prec);
93 	mpfr_set_ui(mp,0,default_rnd);
94 
95 	MPREAL_MSVC_DEBUGVIEW_CODE;
96 }
97 
mpreal(const mpreal & u)98 mpreal::mpreal(const mpreal& u)
99 {
100 
101 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
102 	set_custom_malloc();
103 #endif
104 
105 	mpfr_init2(mp,mpfr_get_prec(u.mp));
106 	mpfr_set(mp,u.mp,default_rnd);
107 
108 	MPREAL_MSVC_DEBUGVIEW_CODE;
109 }
110 
mpreal(const mpfr_t u)111 mpreal::mpreal(const mpfr_t u)
112 {
113 
114 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
115 	set_custom_malloc();
116 #endif
117 
118 	mpfr_init2(mp,mpfr_get_prec(u));
119 	mpfr_set(mp,u,default_rnd);
120 
121 	MPREAL_MSVC_DEBUGVIEW_CODE;
122 }
123 
mpreal(const mpf_t u)124 mpreal::mpreal(const mpf_t u)
125 {
126 
127 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
128 	set_custom_malloc();
129 #endif
130 
131 	mpfr_init2(mp,(mp_prec_t) mpf_get_prec(u)); // (gmp: mp_bitcnt_t) unsigned long -> long (mpfr: mp_prec_t)
132 	mpfr_set_f(mp,u,default_rnd);
133 
134 	MPREAL_MSVC_DEBUGVIEW_CODE;
135 }
136 
mpreal(const mpz_t u,mp_prec_t prec,mp_rnd_t mode)137 mpreal::mpreal(const mpz_t u, mp_prec_t prec, mp_rnd_t mode)
138 {
139 
140 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
141 	set_custom_malloc();
142 #endif
143 
144 	mpfr_init2(mp,prec);
145 	mpfr_set_z(mp,u,mode);
146 
147 	MPREAL_MSVC_DEBUGVIEW_CODE;
148 }
149 
mpreal(const mpq_t u,mp_prec_t prec,mp_rnd_t mode)150 mpreal::mpreal(const mpq_t u, mp_prec_t prec, mp_rnd_t mode)
151 {
152 
153 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
154 	set_custom_malloc();
155 #endif
156 
157 	mpfr_init2(mp,prec);
158 	mpfr_set_q(mp,u,mode);
159 
160 	MPREAL_MSVC_DEBUGVIEW_CODE;
161 }
162 
mpreal(const double u,mp_prec_t prec,mp_rnd_t mode)163 mpreal::mpreal(const double u, mp_prec_t prec, mp_rnd_t mode)
164 {
165 
166 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
167 	set_custom_malloc();
168 #endif
169 
170     if(double_bits == -1 || fits_in_bits(u, double_bits))
171     {
172     	mpfr_init2(mp,prec);
173 	    mpfr_set_d(mp,u,mode);
174 
175 		MPREAL_MSVC_DEBUGVIEW_CODE;
176     }
177     else
178         throw conversion_overflow();
179 }
180 
mpreal(const long double u,mp_prec_t prec,mp_rnd_t mode)181 mpreal::mpreal(const long double u, mp_prec_t prec, mp_rnd_t mode)
182 {
183 
184 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
185 	set_custom_malloc();
186 #endif
187 
188     mpfr_init2(mp,prec);
189 	mpfr_set_ld(mp,u,mode);
190 
191 	MPREAL_MSVC_DEBUGVIEW_CODE;
192 }
193 
mpreal(const unsigned long int u,mp_prec_t prec,mp_rnd_t mode)194 mpreal::mpreal(const unsigned long int u, mp_prec_t prec, mp_rnd_t mode)
195 {
196 
197 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
198 	set_custom_malloc();
199 #endif
200 
201 	mpfr_init2(mp,prec);
202 	mpfr_set_ui(mp,u,mode);
203 
204 	MPREAL_MSVC_DEBUGVIEW_CODE;
205 }
206 
mpreal(const unsigned int u,mp_prec_t prec,mp_rnd_t mode)207 mpreal::mpreal(const unsigned int u, mp_prec_t prec, mp_rnd_t mode)
208 {
209 
210 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
211 	set_custom_malloc();
212 #endif
213 
214 	mpfr_init2(mp,prec);
215 	mpfr_set_ui(mp,u,mode);
216 
217 	MPREAL_MSVC_DEBUGVIEW_CODE;
218 }
219 
mpreal(const long int u,mp_prec_t prec,mp_rnd_t mode)220 mpreal::mpreal(const long int u, mp_prec_t prec, mp_rnd_t mode)
221 {
222 
223 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
224 	set_custom_malloc();
225 #endif
226 
227 	mpfr_init2(mp,prec);
228 	mpfr_set_si(mp,u,mode);
229 
230 	MPREAL_MSVC_DEBUGVIEW_CODE;
231 }
232 
mpreal(const int u,mp_prec_t prec,mp_rnd_t mode)233 mpreal::mpreal(const int u, mp_prec_t prec, mp_rnd_t mode)
234 {
235 
236 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
237 	set_custom_malloc();
238 #endif
239 
240 	mpfr_init2(mp,prec);
241 	mpfr_set_si(mp,u,mode);
242 
243 	MPREAL_MSVC_DEBUGVIEW_CODE;
244 }
245 
246 #if defined (MPREAL_HAVE_INT64_SUPPORT)
mpreal(const uint64_t u,mp_prec_t prec,mp_rnd_t mode)247 mpreal::mpreal(const uint64_t u, mp_prec_t prec, mp_rnd_t mode)
248 {
249 
250 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
251 	set_custom_malloc();
252 #endif
253 
254 	mpfr_init2(mp,prec);
255 	mpfr_set_uj(mp, u, mode);
256 
257 	MPREAL_MSVC_DEBUGVIEW_CODE;
258 }
259 
mpreal(const int64_t u,mp_prec_t prec,mp_rnd_t mode)260 mpreal::mpreal(const int64_t u, mp_prec_t prec, mp_rnd_t mode)
261 {
262 
263 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
264 	set_custom_malloc();
265 #endif
266 
267 	mpfr_init2(mp,prec);
268 	mpfr_set_sj(mp, u, mode);
269 
270 	MPREAL_MSVC_DEBUGVIEW_CODE;
271 }
272 #endif
273 
mpreal(const char * s,mp_prec_t prec,int base,mp_rnd_t mode)274 mpreal::mpreal(const char* s, mp_prec_t prec, int base, mp_rnd_t mode)
275 {
276 
277 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
278 	set_custom_malloc();
279 #endif
280 
281 	mpfr_init2(mp,prec);
282 	mpfr_set_str(mp, s, base, mode);
283 
284 	MPREAL_MSVC_DEBUGVIEW_CODE;
285 }
286 
mpreal(const std::string & s,mp_prec_t prec,int base,mp_rnd_t mode)287 mpreal::mpreal(const std::string& s, mp_prec_t prec, int base, mp_rnd_t mode)
288 {
289 
290 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
291 	set_custom_malloc();
292 #endif
293 
294 	mpfr_init2(mp,prec);
295 	mpfr_set_str(mp, s.c_str(), base, mode);
296 
297 	MPREAL_MSVC_DEBUGVIEW_CODE;
298 }
299 
~mpreal()300 mpreal::~mpreal()
301 {
302 	mpfr_clear(mp);
303 }
304 
305 // Operators - Assignment
operator =(const char * s)306 mpreal& mpreal::operator=(const char* s)
307 {
308 	mpfr_t t;
309 
310 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
311 	set_custom_malloc();
312 #endif
313 
314 	if(0==mpfr_init_set_str(t,s,default_base,default_rnd))
315 	{
316 		// We will rewrite mp anyway, so flash it and resize
317 		mpfr_set_prec(mp,mpfr_get_prec(t));
318 		mpfr_set(mp,t,mpreal::default_rnd);
319 		mpfr_clear(t);
320 
321 		MPREAL_MSVC_DEBUGVIEW_CODE;
322 
323 	}else{
324 		mpfr_clear(t);
325 	}
326 
327 	return *this;
328 }
329 
fma(const mpreal & v1,const mpreal & v2,const mpreal & v3,mp_rnd_t rnd_mode)330 const mpreal fma (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode)
331 {
332 	mpreal a;
333 	mp_prec_t p1, p2, p3;
334 
335 	p1 = v1.get_prec();
336 	p2 = v2.get_prec();
337 	p3 = v3.get_prec();
338 
339 	a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1));
340 
341 	mpfr_fma(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode);
342 	return a;
343 }
344 
fms(const mpreal & v1,const mpreal & v2,const mpreal & v3,mp_rnd_t rnd_mode)345 const mpreal fms (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode)
346 {
347 	mpreal a;
348 	mp_prec_t p1, p2, p3;
349 
350 	p1 = v1.get_prec();
351 	p2 = v2.get_prec();
352 	p3 = v3.get_prec();
353 
354 	a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1));
355 
356 	mpfr_fms(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode);
357 	return a;
358 }
359 
agm(const mpreal & v1,const mpreal & v2,mp_rnd_t rnd_mode)360 const mpreal agm (const mpreal& v1, const mpreal& v2, mp_rnd_t rnd_mode)
361 {
362 	mpreal a;
363 	mp_prec_t p1, p2;
364 
365 	p1 = v1.get_prec();
366 	p2 = v2.get_prec();
367 
368 	a.set_prec(p1>p2?p1:p2);
369 
370 	mpfr_agm(a.mp, v1.mp, v2.mp, rnd_mode);
371 
372 	return a;
373 }
374 
sum(const mpreal tab[],unsigned long int n,mp_rnd_t rnd_mode)375 const mpreal sum (const mpreal tab[], unsigned long int n, mp_rnd_t rnd_mode)
376 {
377 	mpreal x;
378 	mpfr_ptr* t;
379 	unsigned long int i;
380 
381 	t = new mpfr_ptr[n];
382 	for (i=0;i<n;i++) t[i] = (mpfr_ptr)tab[i].mp;
383 	mpfr_sum(x.mp,t,n,rnd_mode);
384 	delete[] t;
385 	return x;
386 }
387 
remquo(long * q,const mpreal & x,const mpreal & y,mp_rnd_t rnd_mode)388 const mpreal remquo (long* q, const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
389 {
390 	mpreal a;
391 	mp_prec_t yp, xp;
392 
393 	yp = y.get_prec();
394 	xp = x.get_prec();
395 
396 	a.set_prec(yp>xp?yp:xp);
397 
398 	mpfr_remquo(a.mp,q, x.mp, y.mp, rnd_mode);
399 
400 	return a;
401 }
402 
403 template <class T>
toString(T t,std::ios_base & (* f)(std::ios_base &))404 std::string toString(T t, std::ios_base & (*f)(std::ios_base&))
405 {
406 	std::ostringstream oss;
407 	oss << f << t;
408 	return oss.str();
409 }
410 
411 #if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
412 
toString(const std::string & format) const413 std::string mpreal::toString(const std::string& format) const
414 {
415 	char *s = NULL;
416 	string out;
417 
418 	if( !format.empty() )
419 	{
420 		if(!(mpfr_asprintf(&s,format.c_str(),mp) < 0))
421 		{
422 			out = std::string(s);
423 
424 			mpfr_free_str(s);
425 		}
426 	}
427 
428 	return out;
429 }
430 
431 #endif
432 
toString(int n,int b,mp_rnd_t mode) const433 std::string mpreal::toString(int n, int b, mp_rnd_t mode) const
434 {
435   (void)b;
436   (void)mode;
437 #if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0))
438 
439 	// Use MPFR native function for output
440 	char format[128];
441 	int digits;
442 
443 	digits = n > 0 ? n : bits2digits(mpfr_get_prec(mp));
444 
445 	sprintf(format,"%%.%dRNg",digits);		// Default format
446 
447 	return toString(std::string(format));
448 
449 #else
450 
451 	char *s, *ns = NULL;
452 	size_t slen, nslen;
453 	mp_exp_t exp;
454 	string out;
455 
456 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
457 	set_custom_malloc();
458 #endif
459 
460 	if(mpfr_inf_p(mp))
461 	{
462 		if(mpfr_sgn(mp)>0) return "+Inf";
463 		else			   return "-Inf";
464 	}
465 
466 	if(mpfr_zero_p(mp)) return "0";
467 	if(mpfr_nan_p(mp))  return "NaN";
468 
469 	s  = mpfr_get_str(NULL,&exp,b,0,mp,mode);
470 	ns = mpfr_get_str(NULL,&exp,b,n,mp,mode);
471 
472 	if(s!=NULL && ns!=NULL)
473 	{
474 		slen  = strlen(s);
475 		nslen = strlen(ns);
476 		if(nslen<=slen)
477 		{
478 			mpfr_free_str(s);
479 			s = ns;
480 			slen = nslen;
481 		}
482 		else {
483 			mpfr_free_str(ns);
484 		}
485 
486 		// Make human eye-friendly formatting if possible
487 		if (exp>0 && static_cast<size_t>(exp)<slen)
488 		{
489 			if(s[0]=='-')
490 			{
491 				// Remove zeros starting from right end
492 				char* ptr = s+slen-1;
493 				while (*ptr=='0' && ptr>s+exp) ptr--;
494 
495 				if(ptr==s+exp) out = string(s,exp+1);
496 				else		   out = string(s,exp+1)+'.'+string(s+exp+1,ptr-(s+exp+1)+1);
497 
498 				//out = string(s,exp+1)+'.'+string(s+exp+1);
499 			}
500 			else
501 			{
502 				// Remove zeros starting from right end
503 				char* ptr = s+slen-1;
504 				while (*ptr=='0' && ptr>s+exp-1) ptr--;
505 
506 				if(ptr==s+exp-1) out = string(s,exp);
507 				else		     out = string(s,exp)+'.'+string(s+exp,ptr-(s+exp)+1);
508 
509 				//out = string(s,exp)+'.'+string(s+exp);
510 			}
511 
512 		}else{ // exp<0 || exp>slen
513 			if(s[0]=='-')
514 			{
515 				// Remove zeros starting from right end
516 				char* ptr = s+slen-1;
517 				while (*ptr=='0' && ptr>s+1) ptr--;
518 
519 				if(ptr==s+1) out = string(s,2);
520 				else		 out = string(s,2)+'.'+string(s+2,ptr-(s+2)+1);
521 
522 				//out = string(s,2)+'.'+string(s+2);
523 			}
524 			else
525 			{
526 				// Remove zeros starting from right end
527 				char* ptr = s+slen-1;
528 				while (*ptr=='0' && ptr>s) ptr--;
529 
530 				if(ptr==s) out = string(s,1);
531 				else	   out = string(s,1)+'.'+string(s+1,ptr-(s+1)+1);
532 
533 				//out = string(s,1)+'.'+string(s+1);
534 			}
535 
536 			// Make final string
537 			if(--exp)
538 			{
539 				if(exp>0) out += "e+"+mpfr::toString<mp_exp_t>(exp,std::dec);
540 				else 	  out += "e"+mpfr::toString<mp_exp_t>(exp,std::dec);
541 			}
542 		}
543 
544 		mpfr_free_str(s);
545 		return out;
546 	}else{
547 		return "conversion error!";
548 	}
549 #endif
550 }
551 
552 
553 //////////////////////////////////////////////////////////////////////////
554 // I/O
operator <<(ostream & os,const mpreal & v)555 ostream& operator<<(ostream& os, const mpreal& v)
556 {
557 	return os<<v.toString(static_cast<int>(os.precision()));
558 }
559 
operator >>(istream & is,mpreal & v)560 istream& operator>>(istream &is, mpreal& v)
561 {
562 	string tmp;
563 	is >> tmp;
564 	mpfr_set_str(v.mp, tmp.c_str(),mpreal::default_base,mpreal::default_rnd);
565 	return is;
566 }
567 
568 
569 #if defined (MPREAL_HAVE_CUSTOM_MPFR_MALLOC)
570 	// Optimized dynamic memory allocation/(re-)deallocation.
mpreal_allocate(size_t alloc_size)571 	void * mpreal::mpreal_allocate(size_t alloc_size)
572 	{
573 		return(dlmalloc(alloc_size));
574 	}
575 
mpreal_reallocate(void * ptr,size_t old_size,size_t new_size)576 	void * mpreal::mpreal_reallocate(void *ptr, size_t old_size, size_t new_size)
577 	{
578 		return(dlrealloc(ptr,new_size));
579 	}
580 
mpreal_free(void * ptr,size_t size)581 	void mpreal::mpreal_free(void *ptr, size_t size)
582 	{
583 		dlfree(ptr);
584 	}
585 
set_custom_malloc(void)586 	inline void mpreal::set_custom_malloc(void)
587 	{
588 		if(!is_custom_malloc)
589 		{
590 			mp_set_memory_functions(mpreal_allocate,mpreal_reallocate,mpreal_free);
591 			is_custom_malloc = true;
592 		}
593 	}
594 #endif
595 
596 }
597 
598