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