1 /* ************************************************************************** */
2 /*                                                                            */
3 /*     Copyright (C)    2000-2007 Cédric Auger (cedric@grisbi.org)            */
4 /*          2003-2008 Benjamin Drieu (bdrieu@april.org)	                      */
5 /*                      2009-2018 Pierre Biava (grisbi@pierre.biava.name)     */
6 /*                      2009 Mickaël Remars (grisbi@remars.com)               */
7 /*          https://www.grisbi.org/                                            */
8 /*                                                                            */
9 /*  This program is free software; you can redistribute it and/or modify      */
10 /*  it under the terms of the GNU General Public License as published by      */
11 /*  the Free Software Foundation; either version 2 of the License, or         */
12 /*  (at your option) any later version.                                       */
13 /*                                                                            */
14 /*  This program is distributed in the hope that it will be useful,           */
15 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of            */
16 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
17 /*  GNU General Public License for more details.                              */
18 /*                                                                            */
19 /*  You should have received a copy of the GNU General Public License         */
20 /*  along with this program; if not, write to the Free Software               */
21 /*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
22 /*                                                                            */
23 /* ************************************************************************** */
24 
25 /**
26  * \file gsb_real.c
27  * grisbi use a special structure to describe a real number
28  * all is defined her
29  */
30 
31 
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35 
36 #include "include.h"
37 #include <stdlib.h>
38 #include <string.h>
39 #include <math.h>
40 #include <glib/gstdio.h>
41 #include <assert.h>
42 
43 /*START_INCLUDE*/
44 #include "gsb_real.h"
45 /*END_INCLUDE*/
46 
47 #ifdef G_OS_WIN32
48 #define rint(x) (floor(x + 0.5))
49 #endif /*G_OS_WIN32 */
50 
51 /*START_STATIC*/
52 /*END_STATIC*/
53 
54 /*START_EXTERN*/
55 /*END_EXTERN*/
56 
57 /******************************************************************************/
58 /* Private functions                                                          */
59 /******************************************************************************/
60 /**
61  * remplace le tableau gsb_real_power_10[]
62  *
63  * \param	exposant
64  *
65  * \return
66  **/
gsb_real_get_power_10(gint exponent)67 static glong gsb_real_get_power_10 (gint exponent)
68 {
69 	glong power_10 = 1;
70 
71     while (exponent > 0)
72     {
73 		power_10 *= 10;
74 		exponent--;
75 	}
76 
77 	return power_10;
78 }
79 
80 /**
81  * ajoute le séparateur des milliers passé en paramètre
82  *
83  * \param string to modify WARNING string is free
84  * \param
85  *
86  * \return a new allocated sring
87  **/
gsb_real_add_thousands_sep(gchar * str_number,const gchar * thousands_sep)88 static gchar *gsb_real_add_thousands_sep (gchar *str_number,
89 										  const gchar *thousands_sep)
90 {
91     gchar *mon_thousands_sep;
92     gchar *result = NULL;
93     gchar *ptr;
94     gchar *dest;
95     gchar *tmp_ptr;
96     gchar **tab_str = NULL;
97     gssize nbre_char;
98     gint i = 0;
99     gint j = 0;
100     gint sep = 0;
101     gssize longueur;
102 
103     if (thousands_sep == NULL)
104         return str_number;
105 
106     nbre_char = strlen (str_number);
107     str_number = g_strreverse (str_number);
108     ptr = str_number;
109 
110     if ((longueur = strlen (thousands_sep)) == 1)
111         mon_thousands_sep = g_strndup (thousands_sep, 1);
112     else
113         mon_thousands_sep = g_strndup ("&", 1);
114 
115     dest = g_malloc0 (128 * sizeof (gchar));
116     tmp_ptr = dest;
117 
118     while (i < nbre_char)
119     {
120         dest[i+sep] = ptr[0];
121 
122         ptr++;
123         tmp_ptr++;
124         i++;
125         j++;
126         if (i < nbre_char && j == 3)
127         {
128             tmp_ptr = g_stpcpy (tmp_ptr, mon_thousands_sep);
129             j = 0;
130             sep++;
131         }
132     };
133 
134     result = g_strndup (dest, nbre_char + sep);
135     result = g_strreverse (result);
136 
137     /* on met le bon séparateur si necessaire */
138     if (longueur > 1)
139     {
140         tab_str = g_strsplit (result, "&", 0);
141         g_free (result);
142 
143         result = g_strjoinv (thousands_sep, tab_str);
144         g_strfreev (tab_str);
145     }
146 
147     g_free (mon_thousands_sep);
148     g_free (str_number);
149     g_free (dest);
150 
151     return result;
152 }
153 
154 /**
155  * reduce the exponent to its smallest possible value,
156  * without losing any precision
157  *
158  * \param mantissa a pointer to the 64 bits mantissa to be reduced
159  * \param exponent a pointer to the exponent to be reduced
160  *
161  * \return
162  **/
gsb_real_raw_minimize_exponent(gint64 * mantissa,gint * exponent)163 static void gsb_real_raw_minimize_exponent (gint64 *mantissa,
164 											gint *exponent)
165 {
166     while (*exponent > 0)
167     {
168         lldiv_t d = lldiv (*mantissa, 10);
169         if (d.rem != 0)
170             return;
171         *mantissa = d.quot;
172         --*exponent;
173     }
174 }
175 
176 /**
177  * reduce the exponent to its smallest possible value,
178  * without losing any precision
179  *
180  * \param num a pointer to the number to be reduced
181  *
182  * \return
183  **/
gsb_real_minimize_exponent(GsbReal * num)184 static void gsb_real_minimize_exponent (GsbReal *num)
185 {
186     gint64 mantissa = num->mantissa;
187 
188     gsb_real_raw_minimize_exponent (&mantissa, &num->exponent);
189     num->mantissa = mantissa;
190 }
191 
192 /**
193  *
194  *
195  * \param
196  * \param
197  *
198  * \return
199  **/
gsb_real_double_to_real_add_exponent(gdouble number,gint exp_add)200 static GsbReal gsb_real_double_to_real_add_exponent (gdouble number,
201 													 gint exp_add)
202 {
203     gdouble tmp_double, decimal;
204     gdouble maxlong;
205 	GsbReal real_number = {0, exp_add};
206 
207     maxlong = (gdouble) G_MAXINT64 / 10;
208 /*     printf ("number initial = %f exp_add = %d\n",number, exp_add);  */
209 
210 	if(exp_add >=9)
211 		return null_real;
212 
213 	while ((modf (number, &tmp_double) || real_number.exponent < 0) && real_number.exponent < 9)
214     {
215         number = number * 10;
216         real_number.exponent++;
217 
218         if (fabs (number) > maxlong)
219             number = rint (number);
220     }
221 	decimal = modf (number, &tmp_double);
222 /*     printf ("number = %f decimal = %f tmp_double = %f\n", number, decimal, tmp_double);  */
223 
224 	if (((real_number.exponent == (9 - exp_add))) && (fabs (decimal) >= 0.5))
225     {
226         if (tmp_double < 0)
227 		    real_number.mantissa = ((gint64) tmp_double) - 1;
228         else
229             real_number.mantissa = ((gint64) tmp_double) + 1;
230 
231         gsb_real_minimize_exponent (&real_number);
232     }
233 	else
234         real_number.mantissa = (gint64) (tmp_double);
235 /*     printf ("real_number.mantissa = %lld real_number.exponent = %d\n", real_number.mantissa,real_number.exponent);  */
236 
237     return real_number;
238 }
239 
240 /**
241  * grow the exponent up to target_exponent
242  * (only if possible without losing precision)
243  *
244  * \param num a pointer to the number
245  * \param target_exponent the desired exponent
246  *
247  * \return
248  **/
gsb_real_grow_exponent(GsbReal * num,gint target_exponent)249 static gboolean gsb_real_grow_exponent (GsbReal *num,
250 										gint target_exponent)
251 {
252     gint64 mantissa = num->mantissa;
253     gint exponent = num->exponent;
254     gboolean succes = TRUE;
255 
256     while (exponent < target_exponent)
257     {
258         gint64 new_mantissa;
259 
260         new_mantissa = mantissa * 10;
261         if ((new_mantissa > G_MAXINT64) || (new_mantissa < G_MININT64))
262         {
263             succes = FALSE;
264             break;
265         }
266         mantissa = new_mantissa;
267         ++exponent;
268     }
269     num->mantissa = mantissa;
270     num->exponent = exponent;
271 
272     return succes;
273 }
274 
275 /**
276  * truncate the number. WARNING there loss of accuracy
277  *
278  * \param mantissa a pointer to the 64 bits mantissa to be truncate
279  * \param exponent a pointer to the exponent to be truncate
280  *
281  * \return
282  **/
gsb_real_raw_truncate_number(gint64 * mantissa,gint * exponent)283 static gboolean gsb_real_raw_truncate_number (gint64 *mantissa,
284 											  gint *exponent)
285 {
286     gint64 new_mantissa = *mantissa;
287     gint new_exponent = *exponent;
288 
289     if (new_mantissa > G_MAXINT64)
290     {
291         do
292         {
293             --new_exponent;
294             new_mantissa = new_mantissa / 10;
295         } while (new_mantissa > G_MAXINT64);
296     }
297     else if (new_mantissa < G_MININT64)
298     {
299         do
300         {
301             --new_exponent;
302             new_mantissa = new_mantissa / 10;
303         } while (new_mantissa < G_MININT64);
304     }
305     else
306     {
307         return FALSE;
308     }
309 
310     /* exponent must be greater or equal to 0 */
311     if (new_exponent < 0)
312     {
313         return FALSE;
314     }
315     else
316     {
317         *exponent = new_exponent;
318         *mantissa = new_mantissa;
319         return TRUE;
320     }
321 }
322 
323 /******************************************************************************/
324 /* Public functions                                                           */
325 /******************************************************************************/
326 /**
327  * Return the real in a formatted string with an optional currency
328  * symbol, according to the given locale regarding decimal separator,
329  * thousands separator and positive or negative sign.
330  *
331  * \param number		    Number to format.
332  * \param locale      		the locale obtained with gsb_locale_get_locale (), or built manually
333  * \param currency_symbol 	the currency symbol
334  *
335  * \return		A newly allocated string of the number (this
336  *			function will never return NULL)
337  **/
gsb_real_raw_format_string(GsbReal number,struct lconv * locale,const gchar * currency_symbol)338 gchar *gsb_real_raw_format_string (GsbReal number,
339 								   struct lconv *locale,
340 								   const gchar *currency_symbol)
341 {
342     gchar buffer[G_ASCII_DTOSTR_BUF_SIZE];
343     gchar format[40];
344     gchar *result = NULL, *temp = NULL;
345 	const gchar *cs_start;
346     const gchar *cs_start_space;
347     const gchar *sign;
348     const gchar *mon_decimal_point;
349     const gchar *cs_end_space;
350     const gchar *cs_end;
351     gint nbre_char;
352 	long long denominateur = 1;
353 	lldiv_t units;
354 
355     cs_start = (currency_symbol && locale->p_cs_precedes) ? currency_symbol : "";
356     cs_start_space = (currency_symbol && locale->p_cs_precedes && locale->p_sep_by_space) ? " " : "";
357     sign = (number.mantissa < 0) ? locale->negative_sign : locale->positive_sign;
358     mon_decimal_point = locale->mon_decimal_point && *locale->mon_decimal_point ? locale->mon_decimal_point : "";
359     cs_end_space = (currency_symbol && !locale->p_cs_precedes && locale->p_sep_by_space) ? " " : "";
360     cs_end = (currency_symbol && !locale->p_cs_precedes) ? currency_symbol : "";
361 
362 	/* on retourne 0.00 avec mon_decimal_point */
363 	if (number.mantissa == 0)
364 	{
365 		if (mon_decimal_point && strlen (mon_decimal_point) == 0)
366         	return g_strdup ("0.00");
367 		else
368 			return g_strconcat ("0",mon_decimal_point, "00", NULL);
369 	}
370 
371 	denominateur = gsb_real_get_power_10 (number.exponent);
372 	units = lldiv (llabs (number.mantissa), denominateur);
373 
374     nbre_char = g_sprintf (buffer, "%.0f", (gdouble) units.quot);
375 
376     temp = g_strndup (buffer, nbre_char);
377 
378     if (units.quot >= 1000)
379     {
380         temp = gsb_real_add_thousands_sep (temp, locale->mon_thousands_sep);
381     }
382 
383     g_snprintf (format, sizeof (format), "%s%d%s", "%s%s%s%s%s%0", number.exponent, "lld%s%s");
384 
385     result = g_strdup_printf (format,
386 							  cs_start,
387 							  cs_start_space,
388 							  sign,
389 							  temp,
390 							  mon_decimal_point,
391 							  units.rem,
392 							  cs_end_space,
393 							  cs_end);
394 
395     g_free (temp);
396 
397     return result;
398 }
399 
400 /**
401  * get a real number from an integer
402  *
403  * \param mantissa
404  * \param exponent -1 for no limit
405  *
406  * \return a GsbReal from the integer
407  **/
gsb_real_new(gint64 mantissa,gint exponent)408 GsbReal gsb_real_new (gint64 mantissa,
409 					  gint exponent)
410 {
411     GsbReal number = null_real;
412 
413     number.mantissa = mantissa;
414     number.exponent = exponent;
415 
416     return number;
417 }
418 
419 /**
420  * get a GsbReal number from a string
421  * the string can be formatted :
422  * - spaces and the given utf8-encoded thousands separators are ignored
423  * - handle ",", "." and the given utf8-encoded decimal separator
424  * - another character makes a error_real return
425  *
426  * \param string
427  * \param mon_thousands_sep, can be NULL or empty, but only one utf8 sequence
428  * \param mon_decimal_point, can be NULL or empty, but only one utf8 sequence
429  *
430  * \return the number in the string transformed to GsbReal
431  **/
gsb_real_raw_get_from_string(const gchar * string,const gchar * mon_thousands_sep,const gchar * mon_decimal_point)432 GsbReal gsb_real_raw_get_from_string (const gchar *string,
433 									  const gchar *mon_thousands_sep,
434                                       const gchar *mon_decimal_point)
435 {
436     static gchar *space_chars;
437     static gchar *decimal_chars;
438     static const gchar *positive_chars = "+";
439     static const gchar *negative_chars = "-";
440     static const gchar *decimal_char_dot = ".";
441     static const gchar *decimal_char_comma = ",";
442     static const gchar *empty_char = "" ;
443     const gchar *default_decimal_char_dot = decimal_char_dot;
444     const gchar *default_decimal_char_comma = decimal_char_comma;
445     unsigned nb_digits = 0;
446     gint64 mantissa = 0;
447     gint8 sign = 0;
448     gint8 dot_position = -1;
449     const gchar *p = string;
450     gboolean success = FALSE;
451 	gboolean error = FALSE;
452 
453     if (!string)
454         return error_real;
455 
456     if (mon_thousands_sep)
457     {
458         if (g_strstr_len (mon_thousands_sep, -1, decimal_char_dot))
459             default_decimal_char_dot = empty_char;
460         if (g_strstr_len (mon_thousands_sep, -1, decimal_char_comma))
461             default_decimal_char_comma = empty_char ;
462     }
463 
464     decimal_chars = g_strconcat(default_decimal_char_dot,
465                                 default_decimal_char_comma,
466                                 mon_decimal_point,
467                                 NULL);
468     space_chars = g_strconcat(" ", mon_thousands_sep, NULL);
469 
470     for (; ;)
471     {
472         if (g_ascii_isdigit (*p))
473         {
474             mantissa *= 10;
475             mantissa += (*p - '0');
476             if (mantissa > G_MAXINT64)
477             {
478                 break;
479             }
480             if (sign == 0) sign = 1; /* no sign found yet ==> positive */
481             ++nb_digits;
482             ++p;
483         }
484         else if (*p == 0) /* terminal zero */
485         {
486             success = TRUE;
487             break;
488         }
489         else if (decimal_chars && strchr (decimal_chars, *p))
490         {
491             if (dot_position >= 0) /* already found a decimal separator */
492             {
493                 break;
494             }
495             dot_position = nb_digits;
496             p = g_utf8_find_next_char (p, NULL);
497         }
498         else if (g_utf8_strchr (space_chars, -1,  g_utf8_get_char(p)))
499         {
500             /* just skip spaces and thousands separators */
501             p = g_utf8_find_next_char (p, NULL);
502         }
503         else if (strchr (negative_chars, *p))
504         {
505             if (sign != 0) /* sign already set */
506             {
507                 break;
508             }
509             sign = -1;
510             ++p;
511         }
512         else if (strchr (positive_chars, *p))
513         {
514             if (sign != 0) /* sign already set */
515             {
516                 break;
517             }
518             sign = 1;
519             ++p;
520         }
521         else /* unknown char ==> error */
522         {
523 			/* si une première erreur on passe au caractère suivant sinon on sort à la deuxième */
524 			if (error)
525 				break;
526 			p = g_utf8_find_next_char (p, NULL);
527 			error = TRUE;
528         }
529     }
530     /* Free memory */
531     g_free (decimal_chars);
532     g_free (space_chars);
533     if (success == TRUE)
534     {
535         GsbReal result;
536 
537         result.mantissa = sign * mantissa;
538         result.exponent = (dot_position >= 0) ? nb_digits - dot_position : 0;
539 
540 		return result;
541     }
542     else
543     {
544         return error_real;
545     }
546 }
547 
548 /**
549  * get a GsbReal number from a string, during file load
550  * the string can be formatted :
551  * - spaces and the given utf8-encoded thousands separators are ignored
552  * - handle only "." as a decimal separator
553  * - another character makes a error_real return
554  *
555  * \param string
556  * \param mon_thousands_sep, can be NULL or empty, but only one utf8 sequence
557  * \param mon_decimal_point, can be NULL or empty, but only one utf8 sequence
558  *
559  * \return the number in the string transformed to GsbReal
560  **/
gsb_real_safe_real_from_string(const gchar * string)561 GsbReal gsb_real_safe_real_from_string (const gchar *string)
562 {
563     unsigned nb_digits = 0;
564     gint64 mantissa = 0;
565     gint8 sign = 0;
566     gint8 dot_position = -1;
567     const gchar *p = string;
568 
569     if (!string)
570         return error_real;
571     if (g_strstr_len (string, -1, ERROR_REAL_STRING))
572         return error_real;
573 
574     for (; ;)
575     {
576         if (g_ascii_isdigit (*p))
577         {
578             mantissa *= 10;
579             mantissa += (*p - '0');
580             if (mantissa > G_MAXINT64)
581                 return error_real;
582             if (sign == 0) sign = 1; /* no sign found yet ==> positive */
583             ++nb_digits;
584             ++p;
585             /* printf ("mantissa = %lld nb_digits = %d\n", mantissa, nb_digits); */
586         }
587         else if (*p == 0) /* terminal zero */
588         {
589 			GsbReal result;
590 			result.mantissa = sign * mantissa;
591             if (mantissa == 0)
592                 result.exponent = 0;
593             else
594                 result.exponent = (dot_position >= 0) ? nb_digits - dot_position : 0;
595             /* printf ("result.mantissa = %ld result.exponent = %d\n", result.mantissa, result.exponent); */
596             return result;
597         }
598         else if (strchr (".", *p))
599         {
600             if (dot_position >= 0) /* already found a decimal separator */
601                 return error_real;
602             dot_position = nb_digits;
603             p = g_utf8_find_next_char (p, NULL);
604         }
605         else if (strchr ("-", *p))
606         {
607             if (sign != 0) /* sign already set */
608                 return error_real;
609             sign = -1;
610             ++p;
611         }
612         else /* unknown char ==> error */
613         {
614             return error_real;
615         }
616     }
617 }
618 
619 /**
620  * compare 2 GsbReal and return the result (-1, 0, 1)
621  *
622  * \param number_1
623  * \param number_2
624  *
625  * \return -1 if number_1 < number_2 ; 0 if number_1 = number_2 ; 1 if number_1 > number_2
626  **/
gsb_real_cmp(GsbReal number_1,GsbReal number_2)627 gint gsb_real_cmp (GsbReal number_1,
628 				   GsbReal number_2)
629 {
630     gsb_real_normalize (&number_1,
631 			 &number_2);
632     if (number_1.mantissa < number_2.mantissa)
633 	return -1;
634     if (number_1.mantissa == number_2.mantissa)
635 	return 0;
636 
637     return 1;
638 }
639 
640 /**
641  * normalize the 2 numbers to be able to add/substract/compare them later
642  * for that transform the 2 numbers to have the same exponent
643  * and after that we can work on the mantissa
644  *
645  * \param number_1 a pointer to GsbReal which contains the number_1 to transform
646  * \param number_2 a pointer to GsbReal which contains the number_2 to transform
647  *
648  * \return TRUE if normalization occurred without loss of precision
649  * 		   FALSE if exponents can't be the same without loss of precision
650  **/
gsb_real_normalize(GsbReal * number_1,GsbReal * number_2)651 gboolean gsb_real_normalize (GsbReal *number_1,
652 							 GsbReal *number_2)
653 {
654     gboolean safe_precision = TRUE;
655 
656     gsb_real_minimize_exponent (number_1);
657     gsb_real_minimize_exponent (number_2);
658 
659     if (number_1->exponent < number_2->exponent)
660     {
661         safe_precision = gsb_real_grow_exponent (number_1,
662                                                   number_2->exponent);
663         if (!safe_precision)
664 		{
665 			while (number_2->exponent > number_1->exponent)
666             {
667                 number_2->exponent--;
668                 number_2->mantissa = number_2->mantissa / 10;
669             }
670 		}
671     }
672     else if (number_2->exponent < number_1->exponent)
673     {
674         safe_precision = gsb_real_grow_exponent (number_2,
675                                                   number_1->exponent);
676         if (!safe_precision)
677 		{
678             while (number_1->exponent > number_2->exponent)
679             {
680                 number_1->exponent--;
681                 number_1->mantissa = number_1->mantissa / 10;
682             }
683 		}
684     }
685 
686     return safe_precision;
687 }
688 
689 /**
690  * give the absolute value of the number
691  *
692  * \param number
693  *
694  * \return a GsbReal, the absolute value of the given number
695  **/
gsb_real_abs(GsbReal number)696 GsbReal gsb_real_abs (GsbReal number)
697 {
698     number.mantissa = llabs (number.mantissa);
699     return number;
700 }
701 
702 
703 /**
704  * modify the number to adjust the exponent wanted
705  *
706  * \param number
707  * \param return_exponent the exponent we want to have for the returned number, or -1 if no limit
708  *
709  * \return the transformed number
710  **/
gsb_real_adjust_exponent(GsbReal number,gint return_exponent)711 GsbReal gsb_real_adjust_exponent (GsbReal number,
712 								  gint return_exponent)
713 {
714     gint exponent;
715 
716     if (return_exponent == -1)
717         return number;
718 
719     if (number.exponent == return_exponent)
720         return number;
721 
722 /*    printf ("\nnumber.mantissa = %"G_GINT64_MODIFIER"d number.exponent = %d return_exponent = %d\n",
723                 number.mantissa, number.exponent, return_exponent);
724 */
725     exponent = abs (number.exponent - return_exponent);
726 /*
727     printf ("exponent = %d gsb_real_get_power_10 (exponent) = %ld\n", exponent, gsb_real_get_power_10 (exponent));
728 */
729 	if (number.exponent < return_exponent)
730 	{
731         number.mantissa = number.mantissa * gsb_real_get_power_10 (exponent);
732         number.exponent = return_exponent;
733 	}
734 	else
735 	{
736         lldiv_t tmp_num;
737         gint sign;
738 
739         sign = (number.mantissa < 0) ? -1 : 1;
740 
741         tmp_num = lldiv (llabs (number.mantissa), gsb_real_get_power_10 (exponent));
742 
743         if (tmp_num.rem > (0.5 * gsb_real_get_power_10 (exponent)))
744             number.mantissa = (tmp_num.quot + 1) * sign;
745         else
746             number.mantissa = tmp_num.quot * sign;
747 
748         number.exponent = return_exponent;
749     }
750 /*
751     printf ("number.mantissa = %"G_GINT64_MODIFIER"d number.exponent = %d\n",
752                 number.mantissa, number.exponent);
753 */
754     return number;
755 }
756 
757 /**
758  * add 2 GsbReal
759  * when an overflow occurs, error_real is returned
760  *
761  * \param number_1
762  * \param number_2
763  *
764  * \return a GsbReal = number_1 + number_2, or error_real when an error occurred
765  **/
gsb_real_add(GsbReal number_1,GsbReal number_2)766 GsbReal gsb_real_add (GsbReal number_1,
767                       GsbReal number_2)
768 {
769     gint64 mantissa;
770 
771     if ((number_1.mantissa == error_real.mantissa)
772       || (number_2.mantissa == error_real.mantissa)
773       || !gsb_real_normalize (&number_1, &number_2))
774 		return error_real;
775 
776 	mantissa = (gint64) number_1.mantissa + number_2.mantissa;
777     if ((mantissa > G_MAXINT64) || (mantissa < G_MININT64))
778     {
779         if (!gsb_real_raw_truncate_number (&mantissa, &number_1.exponent))
780             return error_real;
781     }
782     number_1.mantissa = mantissa;
783 
784     return number_1;
785 }
786 
787 /**
788  * substract between 2 GsbReal : number_1 - number_2
789  *
790  * \param number_1
791  * \param number_2
792  *
793  * \return a GsbReal = number_1 - number_2
794  **/
gsb_real_sub(GsbReal number_1,GsbReal number_2)795 GsbReal gsb_real_sub (GsbReal number_1,
796                       GsbReal number_2)
797 {
798     number_2.mantissa = -number_2.mantissa;
799     return gsb_real_add (number_1, number_2);
800 }
801 
802 /**
803  * return the opposite of the number
804  * ie 5 returns -5 in GsbReal number
805  *
806  * \param number
807  *
808  * \return its opposite
809  **/
gsb_real_opposite(GsbReal number)810 GsbReal gsb_real_opposite (GsbReal number)
811 {
812     if (number.mantissa == error_real.mantissa)
813     {
814         return error_real;
815     }
816 
817     number.mantissa = -number.mantissa;
818     return number;
819 }
820 
821 /**
822  * multiply 2 GsbReals. no overflow possible
823  *
824  * \param number_1
825  * \param number_2
826  *
827  * \return the multiplication between the 2
828  **/
gsb_real_mul(GsbReal number_1,GsbReal number_2)829 GsbReal gsb_real_mul (GsbReal number_1,
830                       GsbReal number_2)
831 {
832     gint64 mantissa;
833 
834     if (number_1.mantissa == error_real.mantissa
835          || number_2.mantissa == error_real.mantissa)
836     {
837         return error_real;
838     }
839 
840     mantissa = (gint64) number_1.mantissa * number_2.mantissa;
841     number_1.exponent += number_2.exponent;
842 
843     gsb_real_raw_minimize_exponent (&mantissa, &number_1.exponent);
844 
845     if ((mantissa > G_MAXINT64) || (mantissa < G_MININT64))
846     {
847         if (!gsb_real_raw_truncate_number (&mantissa, &number_1.exponent))
848             return error_real;
849     }
850     number_1.mantissa = mantissa;
851 
852     return number_1;
853 }
854 
855 /**
856  * divide 2 GsbReals
857  *
858  * \param number_1
859  * \param number_2
860  *
861  * \return the div between the 2
862  **/
gsb_real_div(GsbReal number_1,GsbReal number_2)863 GsbReal gsb_real_div (GsbReal number_1,
864                       GsbReal number_2)
865 {
866     GsbReal number;
867 	gint64 reste;
868 
869 	if (number_1.mantissa == error_real.mantissa ||
870 	     number_2.mantissa == error_real.mantissa ||
871 	     !number_2.mantissa)
872 		return error_real;
873 
874 	reste = number_1.mantissa % number_2.mantissa;
875 
876 	if((number_1.mantissa >= number_2.mantissa) && !reste)
877 	{
878 		number.mantissa = number_1.mantissa / number_2.mantissa;
879 		number.exponent = number_1.exponent - number_2.exponent;
880 		while (number.exponent < 0)
881 		{
882 			number.mantissa *= 10;
883 			number.exponent ++ ;
884 		}
885 	}
886 	else
887 	{
888 		number = gsb_real_double_to_real_add_exponent ((gdouble) number_1.mantissa / (gdouble) number_2.mantissa,
889 													   number_1.exponent - number_2.exponent);
890 	}
891     return number;
892 }
893 
894 /**
895  * convert a double to a GsbReal
896  *
897  * \param number a gdouble number
898  *
899  * \return the number in GsbReal format
900  *
901  * \return
902  **/
gsb_real_double_to_real(gdouble number)903 GsbReal gsb_real_double_to_real (gdouble number)
904 {
905 	return gsb_real_double_to_real_add_exponent(number, 0);
906 }
907 
908 /**
909  * retourne une chaine représentative d'un nombre avec le point comme séparateur décimal
910  * et pas de separateur de milliers
911  *
912  * The returned string should be freed with g_free() when no longer needed.
913  *
914  * \return
915  **/
gsb_real_safe_real_to_string(GsbReal number,gint default_exponent)916 gchar *gsb_real_safe_real_to_string (GsbReal number,
917 									 gint default_exponent)
918 {
919     gchar buffer[G_ASCII_DTOSTR_BUF_SIZE];
920     gchar format[40];
921     gchar *result = NULL;
922     gchar *partie_entiere;
923     const gchar *sign;
924     const gchar *mon_decimal_point;
925     gint nbre_char;
926     lldiv_t units;
927 
928     if ((number.exponent < 0)
929     || (number.exponent >= EXPONENT_MAX)
930     || (number.mantissa == error_real.mantissa))
931       return g_strdup (ERROR_REAL_STRING);
932 
933     if (number.mantissa == 0)
934         return g_strdup ("0.00");
935 
936     if (default_exponent != -1)
937         number = gsb_real_adjust_exponent (number, default_exponent);
938 
939     sign = (number.mantissa < 0) ? "-" : "";
940     mon_decimal_point = ".";
941 
942     units = lldiv (llabs (number.mantissa), gsb_real_get_power_10 (number.exponent));
943 
944     nbre_char = g_sprintf (buffer, "%.0f", (gdouble) units.quot);
945 
946     partie_entiere = g_strndup (buffer, nbre_char);
947 
948     g_snprintf (format, sizeof (format), "%s%d%s", "%s%s%s%0", number.exponent, "lld");
949 
950     result = g_strdup_printf (format, sign, partie_entiere, mon_decimal_point, units.rem);
951     g_free (partie_entiere);
952 
953 /*     printf ("number.mantissa = %lld number.exponent = %d résultat = %s\n",
954  *                         number.mantissa, number.exponent, result);
955  */
956     return result;
957 }
958 
959 /**
960  *
961  *
962  * \param
963  *
964  * \return
965  **/
gsb_real_real_to_double(GsbReal number)966 gdouble gsb_real_real_to_double (GsbReal number)
967 {
968     gdouble result;
969 
970     result = number.mantissa;
971 
972     while (number.exponent > 0)
973     {
974         result /= 10;
975         number.exponent--;
976     }
977 
978     return result;
979 }
980 
981 /**
982  *
983  *
984  * \param
985  *
986  * \return
987  **/
988 /* Local Variables: */
989 /* c-basic-offset: 4 */
990 /* End: */
991