[vlc-commits] variables: try to retain exact value converting float to fraction
Rémi Denis-Courmont
git at videolan.org
Sun Oct 26 17:49:52 CET 2014
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sun Oct 26 18:45:37 2014 +0200| [2d788ac2386845acfc21f50c7b82e0a36ea198ea] | committer: Rémi Denis-Courmont
variables: try to retain exact value converting float to fraction
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=2d788ac2386845acfc21f50c7b82e0a36ea198ea
---
src/misc/variables.c | 33 ++++++++++++++++++++-------------
1 file changed, 20 insertions(+), 13 deletions(-)
diff --git a/src/misc/variables.c b/src/misc/variables.c
index 4ad38b7..3005074 100644
--- a/src/misc/variables.c
+++ b/src/misc/variables.c
@@ -32,6 +32,7 @@
# include <search.h>
#endif
#include <assert.h>
+#include <float.h>
#include <math.h>
#include <limits.h>
#ifdef __GLIBC__
@@ -1307,19 +1308,25 @@ int (var_InheritURational)(vlc_object_t *object,
unsigned d = strtol(*next ? &next[1] : "0", NULL, 0);
if (*next == '.') {
- /* Interpret as a float number */
- double r = us_atof(tmp);
- double c = ceil(r);
- if (c >= UINT_MAX)
- goto error;
- unsigned m = c;
- if (m > 0) {
- d = UINT_MAX / m;
- n = r * d;
- } else {
- n = 0;
- d = 0;
- }
+ /* Interpret as a (finite positive) float number */
+ const int ubits = CHAR_BIT * sizeof (unsigned);
+ int exp;
+ double f = frexp(us_atof(tmp), &exp);
+
+ if (!isgreaterequal(f, 0.))
+ goto error; /* negative or not a number */
+
+ if (exp <= 1 - ubits) {
+ n = 0; /* too small */
+ d = 1;
+ } else if (exp <= 0) {
+ n = floor(scalbn(f, ubits - 1 + exp));
+ d = 1u << (ubits - 1);
+ } else if (exp <= ubits) {
+ n = floor(scalbn(f, ubits));
+ d = 1u << (ubits - exp);
+ } else
+ goto error; /* too big */
} else if ( *next == '\0' ) {
/* plain integer given */
*num = n;
More information about the vlc-commits
mailing list