Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
uPython-mirror
Commits
6e0b6d02
Commit
6e0b6d02
authored
Jan 02, 2015
by
David Steinberg
Committed by
Damien George
Jan 02, 2015
Browse files
py: Fix float to int conversion for large exponents.
parent
ffc96a90
Changes
4
Hide whitespace changes
Inline
Side-by-side
py/mpz.c
View file @
6e0b6d02
...
...
@@ -590,6 +590,14 @@ mpz_t *mpz_from_ll(long long val, bool is_signed) {
return
z
;
}
#if MICROPY_PY_BUILTINS_FLOAT
mpz_t
*
mpz_from_float
(
mp_float_t
val
)
{
mpz_t
*
z
=
mpz_zero
();
mpz_set_from_float
(
z
,
val
);
return
z
;
}
#endif
mpz_t
*
mpz_from_str
(
const
char
*
str
,
mp_uint_t
len
,
bool
neg
,
mp_uint_t
base
)
{
mpz_t
*
z
=
mpz_zero
();
mpz_set_from_str
(
z
,
str
,
len
,
neg
,
base
);
...
...
@@ -682,6 +690,80 @@ void mpz_set_from_ll(mpz_t *z, long long val, bool is_signed) {
}
}
#if MICROPY_PY_BUILTINS_FLOAT
void
mpz_set_from_float
(
mpz_t
*
z
,
mp_float_t
src
)
{
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
#define EXP_SZ 11
#define FRC_SZ 52
typedef
uint64_t
mp_float_int_t
;
#else
#define EXP_SZ 8
#define FRC_SZ 23
typedef
uint32_t
mp_float_int_t
;
#endif
union
{
mp_float_t
f
;
struct
{
mp_float_int_t
frc
:
FRC_SZ
,
exp
:
EXP_SZ
,
sgn
:
1
;
}
p
;
}
u
=
{
src
};
z
->
neg
=
u
.
p
.
sgn
;
if
(
u
.
p
.
exp
==
0
)
{
// value == 0 || value < 1
mpz_init_zero
(
z
);
}
else
if
(
u
.
p
.
exp
==
((
1
<<
EXP_SZ
)
-
1
))
{
// inf or NaN
#if 0
// TODO: this probably isn't the right place to throw an exception
if(u.p.frc == 0)
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OverflowError, "cannot convert float infinity to integer"));
else
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "cannot convert float NaN to integer"));
#else
mpz_init_zero
(
z
);
#endif
}
else
{
const
int
adj_exp
=
(
int
)
u
.
p
.
exp
-
((
1
<<
(
EXP_SZ
-
1
))
-
1
);
if
(
adj_exp
<
0
)
{
// value < 1 , truncates to 0
mpz_init_zero
(
z
);
}
else
if
(
adj_exp
==
0
)
{
// 1 <= value < 2 , so truncates to 1
mpz_init_from_int
(
z
,
1
);
}
else
{
// 2 <= value
const
int
dig_cnt
=
(
adj_exp
+
1
+
(
DIG_SIZE
-
1
))
/
DIG_SIZE
;
const
unsigned
int
rem
=
adj_exp
%
DIG_SIZE
;
int
dig_ind
,
shft
;
mp_float_int_t
frc
=
u
.
p
.
frc
|
((
mp_float_int_t
)
1
<<
FRC_SZ
);
if
(
adj_exp
<
FRC_SZ
)
{
shft
=
0
;
dig_ind
=
0
;
frc
>>=
FRC_SZ
-
adj_exp
;
}
else
{
shft
=
(
rem
-
FRC_SZ
)
%
DIG_SIZE
;
dig_ind
=
(
adj_exp
-
FRC_SZ
)
/
DIG_SIZE
;
}
mpz_need_dig
(
z
,
dig_cnt
);
z
->
len
=
dig_cnt
;
if
(
dig_ind
!=
0
)
{
memset
(
z
->
dig
,
0
,
dig_ind
*
sizeof
(
mpz_dig_t
));
}
if
(
shft
!=
0
)
{
z
->
dig
[
dig_ind
++
]
=
(
frc
<<
shft
)
&
DIG_MASK
;
frc
>>=
DIG_SIZE
-
shft
;
}
while
(
dig_ind
!=
dig_cnt
)
{
z
->
dig
[
dig_ind
++
]
=
frc
&
DIG_MASK
;
frc
>>=
DIG_SIZE
;
}
}
}
}
#undef EXP_SZ
#undef FRC_SZ
#endif
// returns number of bytes from str that were processed
mp_uint_t
mpz_set_from_str
(
mpz_t
*
z
,
const
char
*
str
,
mp_uint_t
len
,
bool
neg
,
mp_uint_t
base
)
{
assert
(
base
<
36
);
...
...
py/mpz.h
View file @
6e0b6d02
...
...
@@ -85,6 +85,9 @@ void mpz_deinit(mpz_t *z);
mpz_t
*
mpz_zero
(
void
);
mpz_t
*
mpz_from_int
(
mp_int_t
i
);
mpz_t
*
mpz_from_ll
(
long
long
i
,
bool
is_signed
);
#if MICROPY_PY_BUILTINS_FLOAT
mpz_t
*
mpz_from_float
(
mp_float_t
i
);
#endif
mpz_t
*
mpz_from_str
(
const
char
*
str
,
mp_uint_t
len
,
bool
neg
,
mp_uint_t
base
);
void
mpz_free
(
mpz_t
*
z
);
...
...
@@ -93,6 +96,9 @@ mpz_t *mpz_clone(const mpz_t *src);
void
mpz_set
(
mpz_t
*
dest
,
const
mpz_t
*
src
);
void
mpz_set_from_int
(
mpz_t
*
z
,
mp_int_t
src
);
void
mpz_set_from_ll
(
mpz_t
*
z
,
long
long
i
,
bool
is_signed
);
#if MICROPY_PY_BUILTINS_FLOAT
void
mpz_set_from_float
(
mpz_t
*
z
,
mp_float_t
src
);
#endif
mp_uint_t
mpz_set_from_str
(
mpz_t
*
z
,
const
char
*
str
,
mp_uint_t
len
,
bool
neg
,
mp_uint_t
base
);
bool
mpz_is_zero
(
const
mpz_t
*
z
);
...
...
py/objint_mpz.c
View file @
6e0b6d02
...
...
@@ -298,9 +298,9 @@ mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
#if MICROPY_PY_BUILTINS_FLOAT
mp_obj_t
mp_obj_new_int_from_float
(
mp_float_t
val
)
{
// TODO: This doesn't handle numbers with large exponent
long
long
i
=
MICROPY_FLOAT_C_FUN
(
trunc
)(
val
);
return
mp_obj_new_int_from_ll
(
i
)
;
mp_obj_int_t
*
o
=
mp_obj_int_new_mpz
();
mpz_set_from_float
(
&
o
->
mpz
,
val
);
return
o
;
}
#endif
...
...
tests/float/float2int.py
View file @
6e0b6d02
# This case occurs with time.time() values
print
(
int
(
1418774543.
))
# TODO: General case with large exponent
#print(int(2.**100))
print
(
int
(
2.
**
100
))
print
(
"%d"
%
1418774543.
)
# TODO: General case with large exponent
#print("%d" % 2.**100)
print
(
"%d"
%
2.
**
100
)
testpass
=
True
for
i
in
range
(
0
,
1024
):
bitcnt
=
len
(
bin
(
int
(
2.
**
i
)))
-
3
;
if
i
!=
bitcnt
:
print
(
'fail: 2**%u was %u bits long'
%
(
i
,
bitcnt
));
testpass
=
False
print
(
"power of 2 test: %s"
%
(
testpass
and
'passed'
or
'failed'
))
testpass
=
True
for
i
in
range
(
0
,
23
):
digcnt
=
len
(
str
(
int
(
10.
**
i
)))
-
1
;
if
i
!=
digcnt
:
print
(
'fail: 10**%u was %u digits long'
%
(
i
,
digcnt
));
testpass
=
False
print
(
"power of 10 test: %s"
%
(
testpass
and
'passed'
or
'failed'
))
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment