Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
Pyston
Commits
801dec8c
Commit
801dec8c
authored
May 07, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #504 from kmod/pr492
delete capi/float.cpp
parents
0defcec2
8aa08824
Changes
16
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
770 additions
and
530 deletions
+770
-530
from_cpython/Include/pyconfig.h
from_cpython/Include/pyconfig.h
+2
-0
from_cpython/Modules/_collectionsmodule.c
from_cpython/Modules/_collectionsmodule.c
+3
-1
src/CMakeLists.txt
src/CMakeLists.txt
+0
-1
src/capi/abstract.cpp
src/capi/abstract.cpp
+38
-2
src/capi/float.cpp
src/capi/float.cpp
+0
-496
src/runtime/builtin_modules/builtins.cpp
src/runtime/builtin_modules/builtins.cpp
+41
-8
src/runtime/float.cpp
src/runtime/float.cpp
+563
-0
src/runtime/int.cpp
src/runtime/int.cpp
+8
-3
src/runtime/iterobject.cpp
src/runtime/iterobject.cpp
+3
-2
src/runtime/list.cpp
src/runtime/list.cpp
+9
-10
src/runtime/long.cpp
src/runtime/long.cpp
+48
-2
src/runtime/str.cpp
src/runtime/str.cpp
+10
-1
src/runtime/types.cpp
src/runtime/types.cpp
+33
-1
test/tests/builtins.py
test/tests/builtins.py
+2
-2
test/tests/intmethods.py
test/tests/intmethods.py
+3
-0
test/tests/list.py
test/tests/list.py
+7
-1
No files found.
from_cpython/Include/pyconfig.h
View file @
801dec8c
...
@@ -27,6 +27,8 @@
...
@@ -27,6 +27,8 @@
#define SIZEOF_INT 4
#define SIZEOF_INT 4
#define SIZEOF_LONG 8
#define SIZEOF_LONG 8
#define SIZEOF_LONG_LONG 8
#define SIZEOF_LONG_LONG 8
#define SIZEOF_DOUBLE 8
#define SIZEOF_FLOAT 4
#define SIZEOF_OFF_T 8
#define SIZEOF_OFF_T 8
#define SIZEOF_PTHREAD_T 8
#define SIZEOF_PTHREAD_T 8
#define HAVE_COPYSIGN 1
#define HAVE_COPYSIGN 1
...
...
from_cpython/Modules/_collectionsmodule.c
View file @
801dec8c
...
@@ -55,7 +55,9 @@ typedef struct BLOCK {
...
@@ -55,7 +55,9 @@ typedef struct BLOCK {
struct
BLOCK
*
leftlink
;
struct
BLOCK
*
leftlink
;
}
block
;
}
block
;
#define MAXFREEBLOCKS 10
// Pyston change: disable free block cache
// #define MAXFREEBLOCKS 10
#define MAXFREEBLOCKS 0
static
Py_ssize_t
numfreeblocks
=
0
;
static
Py_ssize_t
numfreeblocks
=
0
;
static
block
*
freeblocks
[
MAXFREEBLOCKS
];
static
block
*
freeblocks
[
MAXFREEBLOCKS
];
...
...
src/CMakeLists.txt
View file @
801dec8c
...
@@ -30,7 +30,6 @@ add_library(PYSTON_OBJECTS OBJECT ${OPTIONAL_SRCS}
...
@@ -30,7 +30,6 @@ add_library(PYSTON_OBJECTS OBJECT ${OPTIONAL_SRCS}
capi/codecs.cpp
capi/codecs.cpp
capi/descrobject.cpp
capi/descrobject.cpp
capi/errors.cpp
capi/errors.cpp
capi/float.cpp
capi/modsupport.cpp
capi/modsupport.cpp
capi/object.cpp
capi/object.cpp
capi/typeobject.cpp
capi/typeobject.cpp
...
...
src/capi/abstract.cpp
View file @
801dec8c
...
@@ -557,8 +557,29 @@ extern "C" int PyObject_CheckReadBuffer(PyObject* obj) noexcept {
...
@@ -557,8 +557,29 @@ extern "C" int PyObject_CheckReadBuffer(PyObject* obj) noexcept {
}
}
extern
"C"
int
PyObject_AsReadBuffer
(
PyObject
*
obj
,
const
void
**
buffer
,
Py_ssize_t
*
buffer_len
)
noexcept
{
extern
"C"
int
PyObject_AsReadBuffer
(
PyObject
*
obj
,
const
void
**
buffer
,
Py_ssize_t
*
buffer_len
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
PyBufferProcs
*
pb
;
void
*
pp
;
Py_ssize_t
len
;
if
(
obj
==
NULL
||
buffer
==
NULL
||
buffer_len
==
NULL
)
{
null_error
();
return
-
1
;
}
pb
=
obj
->
cls
->
tp_as_buffer
;
if
(
pb
==
NULL
||
pb
->
bf_getreadbuffer
==
NULL
||
pb
->
bf_getsegcount
==
NULL
)
{
PyErr_SetString
(
PyExc_TypeError
,
"expected a readable buffer object"
);
return
-
1
;
}
if
((
*
pb
->
bf_getsegcount
)(
obj
,
NULL
)
!=
1
)
{
PyErr_SetString
(
PyExc_TypeError
,
"expected a single-segment buffer object"
);
return
-
1
;
}
len
=
(
*
pb
->
bf_getreadbuffer
)(
obj
,
0
,
&
pp
);
if
(
len
<
0
)
return
-
1
;
return
-
1
;
*
buffer
=
pp
;
*
buffer_len
=
len
;
return
0
;
}
}
static
PyObject
*
call_function_tail
(
PyObject
*
callable
,
PyObject
*
args
)
{
static
PyObject
*
call_function_tail
(
PyObject
*
callable
,
PyObject
*
args
)
{
...
@@ -1818,6 +1839,21 @@ extern "C" PyObject* PyNumber_Long(PyObject* o) noexcept {
...
@@ -1818,6 +1839,21 @@ extern "C" PyObject* PyNumber_Long(PyObject* o) noexcept {
}
}
extern
"C"
PyObject
*
PyNumber_Float
(
PyObject
*
o
)
noexcept
{
extern
"C"
PyObject
*
PyNumber_Float
(
PyObject
*
o
)
noexcept
{
if
(
o
==
NULL
)
return
null_error
();
if
(
o
->
cls
==
float_cls
)
return
o
;
if
(
PyInt_Check
(
o
))
return
boxFloat
(((
BoxedInt
*
)
o
)
->
n
);
else
if
(
PyLong_Check
(
o
))
{
double
result
=
PyLong_AsDouble
(
o
);
if
(
result
==
-
1.0
&&
PyErr_Occurred
())
return
NULL
;
return
boxFloat
(
result
);
}
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
nullptr
;
return
nullptr
;
}
}
...
...
src/capi/float.cpp
deleted
100644 → 0
View file @
0defcec2
// Copyright (c) 2014-2015 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file is mostly copied from CPython
#include "Python.h"
#include "core/types.h"
#include "runtime/types.h"
namespace
pyston
{
extern
"C"
{
typedef
enum
{
unknown_format
,
ieee_big_endian_format
,
ieee_little_endian_format
}
float_format_type
;
static
float_format_type
double_format
,
float_format
;
static
float_format_type
detected_double_format
,
detected_float_format
;
static
PyObject
*
float_getformat
(
PyTypeObject
*
v
,
PyObject
*
arg
)
noexcept
{
float_format_type
r
;
BoxedString
*
str
=
static_cast
<
BoxedString
*>
(
arg
);
if
(
!
PyString_Check
(
arg
))
{
PyErr_Format
(
PyExc_TypeError
,
"__getformat__() argument must be string, not %.500s"
,
Py_TYPE
(
arg
)
->
tp_name
);
return
NULL
;
}
if
(
str
->
s
==
"double"
)
{
r
=
double_format
;
}
else
if
(
str
->
s
==
"float"
)
{
r
=
float_format
;
}
else
{
PyErr_SetString
(
PyExc_ValueError
,
"__getformat__() argument 1 must be "
"'double' or 'float'"
);
return
NULL
;
}
switch
(
r
)
{
case
unknown_format
:
return
static_cast
<
PyObject
*>
(
boxStrConstant
(
"unknown"
));
case
ieee_little_endian_format
:
return
static_cast
<
PyObject
*>
(
boxStrConstant
(
"IEEE, little-endian"
));
case
ieee_big_endian_format
:
return
static_cast
<
PyObject
*>
(
boxStrConstant
(
"IEEE, big-endian"
));
default:
Py_FatalError
(
"insane float_format or double_format"
);
return
NULL
;
}
}
PyDoc_STRVAR
(
float_getformat_doc
,
"float.__getformat__(typestr) -> string
\n
"
"
\n
"
"You probably don't want to use this function. It exists mainly to be
\n
"
"used in Python's test suite.
\n
"
"
\n
"
"typestr must be 'double' or 'float'. This function returns whichever of
\n
"
"'unknown', 'IEEE, big-endian' or 'IEEE, little-endian' best describes the
\n
"
"format of floating point numbers used by the C type named by typestr."
);
static
PyObject
*
float_setformat
(
PyTypeObject
*
v
,
PyObject
*
args
)
noexcept
{
char
*
typestr
;
char
*
format
;
float_format_type
f
;
float_format_type
detected
;
float_format_type
*
p
;
if
(
!
PyArg_ParseTuple
(
args
,
"ss:__setformat__"
,
&
typestr
,
&
format
))
return
NULL
;
if
(
strcmp
(
typestr
,
"double"
)
==
0
)
{
p
=
&
double_format
;
detected
=
detected_double_format
;
}
else
if
(
strcmp
(
typestr
,
"float"
)
==
0
)
{
p
=
&
float_format
;
detected
=
detected_float_format
;
}
else
{
PyErr_SetString
(
PyExc_ValueError
,
"__setformat__() argument 1 must "
"be 'double' or 'float'"
);
return
NULL
;
}
if
(
strcmp
(
format
,
"unknown"
)
==
0
)
{
f
=
unknown_format
;
}
else
if
(
strcmp
(
format
,
"IEEE, little-endian"
)
==
0
)
{
f
=
ieee_little_endian_format
;
}
else
if
(
strcmp
(
format
,
"IEEE, big-endian"
)
==
0
)
{
f
=
ieee_big_endian_format
;
}
else
{
PyErr_SetString
(
PyExc_ValueError
,
"__setformat__() argument 2 must be "
"'unknown', 'IEEE, little-endian' or "
"'IEEE, big-endian'"
);
return
NULL
;
}
if
(
f
!=
unknown_format
&&
f
!=
detected
)
{
PyErr_Format
(
PyExc_ValueError
,
"can only set %s format to 'unknown' or the "
"detected platform value"
,
typestr
);
return
NULL
;
}
*
p
=
f
;
Py_RETURN_NONE
;
}
/*----------------------------------------------------------------------------
* _PyFloat_{Pack,Unpack}{4,8}. See floatobject.h.
*/
extern
"C"
int
_PyFloat_Pack4
(
double
x
,
unsigned
char
*
p
,
int
le
)
noexcept
{
if
(
float_format
==
unknown_format
)
{
unsigned
char
sign
;
int
e
;
double
f
;
unsigned
int
fbits
;
int
incr
=
1
;
if
(
le
)
{
p
+=
3
;
incr
=
-
1
;
}
if
(
x
<
0
)
{
sign
=
1
;
x
=
-
x
;
}
else
sign
=
0
;
f
=
frexp
(
x
,
&
e
);
/* Normalize f to be in the range [1.0, 2.0) */
if
(
0.5
<=
f
&&
f
<
1.0
)
{
f
*=
2.0
;
e
--
;
}
else
if
(
f
==
0.0
)
e
=
0
;
else
{
PyErr_SetString
(
PyExc_SystemError
,
"frexp() result out of range"
);
return
-
1
;
}
if
(
e
>=
128
)
goto
Overflow
;
else
if
(
e
<
-
126
)
{
/* Gradual underflow */
f
=
ldexp
(
f
,
126
+
e
);
e
=
0
;
}
else
if
(
!
(
e
==
0
&&
f
==
0.0
))
{
e
+=
127
;
f
-=
1.0
;
/* Get rid of leading 1 */
}
f
*=
8388608.0
;
/* 2**23 */
fbits
=
(
unsigned
int
)(
f
+
0.5
);
/* Round */
assert
(
fbits
<=
8388608
);
if
(
fbits
>>
23
)
{
/* The carry propagated out of a string of 23 1 bits. */
fbits
=
0
;
++
e
;
if
(
e
>=
255
)
goto
Overflow
;
}
/* First byte */
*
p
=
(
sign
<<
7
)
|
(
e
>>
1
);
p
+=
incr
;
/* Second byte */
*
p
=
(
char
)(((
e
&
1
)
<<
7
)
|
(
fbits
>>
16
));
p
+=
incr
;
/* Third byte */
*
p
=
(
fbits
>>
8
)
&
0xFF
;
p
+=
incr
;
/* Fourth byte */
*
p
=
fbits
&
0xFF
;
/* Done */
return
0
;
}
else
{
float
y
=
(
float
)
x
;
const
char
*
s
=
(
char
*
)
&
y
;
int
i
,
incr
=
1
;
if
(
Py_IS_INFINITY
(
y
)
&&
!
Py_IS_INFINITY
(
x
))
goto
Overflow
;
if
((
float_format
==
ieee_little_endian_format
&&
!
le
)
||
(
float_format
==
ieee_big_endian_format
&&
le
))
{
p
+=
3
;
incr
=
-
1
;
}
for
(
i
=
0
;
i
<
4
;
i
++
)
{
*
p
=
*
s
++
;
p
+=
incr
;
}
return
0
;
}
Overflow:
PyErr_SetString
(
PyExc_OverflowError
,
"float too large to pack with f format"
);
return
-
1
;
}
extern
"C"
int
_PyFloat_Pack8
(
double
x
,
unsigned
char
*
p
,
int
le
)
noexcept
{
if
(
double_format
==
unknown_format
)
{
unsigned
char
sign
;
int
e
;
double
f
;
unsigned
int
fhi
,
flo
;
int
incr
=
1
;
if
(
le
)
{
p
+=
7
;
incr
=
-
1
;
}
if
(
x
<
0
)
{
sign
=
1
;
x
=
-
x
;
}
else
sign
=
0
;
f
=
frexp
(
x
,
&
e
);
/* Normalize f to be in the range [1.0, 2.0) */
if
(
0.5
<=
f
&&
f
<
1.0
)
{
f
*=
2.0
;
e
--
;
}
else
if
(
f
==
0.0
)
e
=
0
;
else
{
PyErr_SetString
(
PyExc_SystemError
,
"frexp() result out of range"
);
return
-
1
;
}
if
(
e
>=
1024
)
goto
Overflow
;
else
if
(
e
<
-
1022
)
{
/* Gradual underflow */
f
=
ldexp
(
f
,
1022
+
e
);
e
=
0
;
}
else
if
(
!
(
e
==
0
&&
f
==
0.0
))
{
e
+=
1023
;
f
-=
1.0
;
/* Get rid of leading 1 */
}
/* fhi receives the high 28 bits; flo the low 24 bits (== 52 bits) */
f
*=
268435456.0
;
/* 2**28 */
fhi
=
(
unsigned
int
)
f
;
/* Truncate */
assert
(
fhi
<
268435456
);
f
-=
(
double
)
fhi
;
f
*=
16777216.0
;
/* 2**24 */
flo
=
(
unsigned
int
)(
f
+
0.5
);
/* Round */
assert
(
flo
<=
16777216
);
if
(
flo
>>
24
)
{
/* The carry propagated out of a string of 24 1 bits. */
flo
=
0
;
++
fhi
;
if
(
fhi
>>
28
)
{
/* And it also progagated out of the next 28 bits. */
fhi
=
0
;
++
e
;
if
(
e
>=
2047
)
goto
Overflow
;
}
}
/* First byte */
*
p
=
(
sign
<<
7
)
|
(
e
>>
4
);
p
+=
incr
;
/* Second byte */
*
p
=
(
unsigned
char
)(((
e
&
0xF
)
<<
4
)
|
(
fhi
>>
24
));
p
+=
incr
;
/* Third byte */
*
p
=
(
fhi
>>
16
)
&
0xFF
;
p
+=
incr
;
/* Fourth byte */
*
p
=
(
fhi
>>
8
)
&
0xFF
;
p
+=
incr
;
/* Fifth byte */
*
p
=
fhi
&
0xFF
;
p
+=
incr
;
/* Sixth byte */
*
p
=
(
flo
>>
16
)
&
0xFF
;
p
+=
incr
;
/* Seventh byte */
*
p
=
(
flo
>>
8
)
&
0xFF
;
p
+=
incr
;
/* Eighth byte */
*
p
=
flo
&
0xFF
;
/* p += incr; Unneeded (for now) */
/* Done */
return
0
;
Overflow:
PyErr_SetString
(
PyExc_OverflowError
,
"float too large to pack with d format"
);
return
-
1
;
}
else
{
const
char
*
s
=
(
char
*
)
&
x
;
int
i
,
incr
=
1
;
if
((
double_format
==
ieee_little_endian_format
&&
!
le
)
||
(
double_format
==
ieee_big_endian_format
&&
le
))
{
p
+=
7
;
incr
=
-
1
;
}
for
(
i
=
0
;
i
<
8
;
i
++
)
{
*
p
=
*
s
++
;
p
+=
incr
;
}
return
0
;
}
}
double
_PyFloat_Unpack4
(
const
unsigned
char
*
p
,
int
le
)
noexcept
{
if
(
float_format
==
unknown_format
)
{
unsigned
char
sign
;
int
e
;
unsigned
int
f
;
double
x
;
int
incr
=
1
;
if
(
le
)
{
p
+=
3
;
incr
=
-
1
;
}
/* First byte */
sign
=
(
*
p
>>
7
)
&
1
;
e
=
(
*
p
&
0x7F
)
<<
1
;
p
+=
incr
;
/* Second byte */
e
|=
(
*
p
>>
7
)
&
1
;
f
=
(
*
p
&
0x7F
)
<<
16
;
p
+=
incr
;
if
(
e
==
255
)
{
PyErr_SetString
(
PyExc_ValueError
,
"can't unpack IEEE 754 special value "
"on non-IEEE platform"
);
return
-
1
;
}
/* Third byte */
f
|=
*
p
<<
8
;
p
+=
incr
;
/* Fourth byte */
f
|=
*
p
;
x
=
(
double
)
f
/
8388608.0
;
/* XXX This sadly ignores Inf/NaN issues */
if
(
e
==
0
)
e
=
-
126
;
else
{
x
+=
1.0
;
e
-=
127
;
}
x
=
ldexp
(
x
,
e
);
if
(
sign
)
x
=
-
x
;
return
x
;
}
else
{
float
x
;
if
((
float_format
==
ieee_little_endian_format
&&
!
le
)
||
(
float_format
==
ieee_big_endian_format
&&
le
))
{
char
buf
[
4
];
char
*
d
=
&
buf
[
3
];
int
i
;
for
(
i
=
0
;
i
<
4
;
i
++
)
{
*
d
--
=
*
p
++
;
}
memcpy
(
&
x
,
buf
,
4
);
}
else
{
memcpy
(
&
x
,
p
,
4
);
}
return
x
;
}
}
double
_PyFloat_Unpack8
(
const
unsigned
char
*
p
,
int
le
)
noexcept
{
if
(
double_format
==
unknown_format
)
{
unsigned
char
sign
;
int
e
;
unsigned
int
fhi
,
flo
;
double
x
;
int
incr
=
1
;
if
(
le
)
{
p
+=
7
;
incr
=
-
1
;
}
/* First byte */
sign
=
(
*
p
>>
7
)
&
1
;
e
=
(
*
p
&
0x7F
)
<<
4
;
p
+=
incr
;
/* Second byte */
e
|=
(
*
p
>>
4
)
&
0xF
;
fhi
=
(
*
p
&
0xF
)
<<
24
;
p
+=
incr
;
if
(
e
==
2047
)
{
PyErr_SetString
(
PyExc_ValueError
,
"can't unpack IEEE 754 special value "
"on non-IEEE platform"
);
return
-
1.0
;
}
/* Third byte */
fhi
|=
*
p
<<
16
;
p
+=
incr
;
/* Fourth byte */
fhi
|=
*
p
<<
8
;
p
+=
incr
;
/* Fifth byte */
fhi
|=
*
p
;
p
+=
incr
;
/* Sixth byte */
flo
=
*
p
<<
16
;
p
+=
incr
;
/* Seventh byte */
flo
|=
*
p
<<
8
;
p
+=
incr
;
/* Eighth byte */
flo
|=
*
p
;
x
=
(
double
)
fhi
+
(
double
)
flo
/
16777216.0
;
/* 2**24 */
x
/=
268435456.0
;
/* 2**28 */
if
(
e
==
0
)
e
=
-
1022
;
else
{
x
+=
1.0
;
e
-=
1023
;
}
x
=
ldexp
(
x
,
e
);
if
(
sign
)
x
=
-
x
;
return
x
;
}
else
{
double
x
;
if
((
double_format
==
ieee_little_endian_format
&&
!
le
)
||
(
double_format
==
ieee_big_endian_format
&&
le
))
{
char
buf
[
8
];
char
*
d
=
&
buf
[
7
];
int
i
;
for
(
i
=
0
;
i
<
8
;
i
++
)
{
*
d
--
=
*
p
++
;
}
memcpy
(
&
x
,
buf
,
8
);
}
else
{
memcpy
(
&
x
,
p
,
8
);
}
return
x
;
}
}
}
}
src/runtime/builtin_modules/builtins.cpp
View file @
801dec8c
...
@@ -13,6 +13,7 @@
...
@@ -13,6 +13,7 @@
// limitations under the License.
// limitations under the License.
#include <algorithm>
#include <algorithm>
#include <cfloat>
#include <cstddef>
#include <cstddef>
#include <err.h>
#include <err.h>
...
@@ -375,6 +376,14 @@ Box* issubclass_func(Box* child, Box* parent) {
...
@@ -375,6 +376,14 @@ Box* issubclass_func(Box* child, Box* parent) {
return
boxBool
(
rtn
);
return
boxBool
(
rtn
);
}
}
Box
*
intern_func
(
Box
*
str
)
{
if
(
!
PyString_CheckExact
(
str
))
// have to use exact check!
raiseExcHelper
(
TypeError
,
"can't intern subclass of string"
);
PyString_InternInPlace
(
&
str
);
checkAndThrowCAPIException
();
return
str
;
}
Box
*
bltinImport
(
Box
*
name
,
Box
*
globals
,
Box
*
locals
,
Box
**
args
)
{
Box
*
bltinImport
(
Box
*
name
,
Box
*
globals
,
Box
*
locals
,
Box
**
args
)
{
Box
*
fromlist
=
args
[
0
];
Box
*
fromlist
=
args
[
0
];
Box
*
level
=
args
[
1
];
Box
*
level
=
args
[
1
];
...
@@ -590,7 +599,6 @@ public:
...
@@ -590,7 +599,6 @@ public:
static
Box
*
__reduce__
(
Box
*
self
)
{
static
Box
*
__reduce__
(
Box
*
self
)
{
RELEASE_ASSERT
(
isSubclass
(
self
->
cls
,
BaseException
),
""
);
RELEASE_ASSERT
(
isSubclass
(
self
->
cls
,
BaseException
),
""
);
BoxedException
*
exc
=
static_cast
<
BoxedException
*>
(
self
);
BoxedException
*
exc
=
static_cast
<
BoxedException
*>
(
self
);
return
BoxedTuple
::
create
({
self
->
cls
,
EmptyTuple
,
self
->
getAttrWrapper
()
});
return
BoxedTuple
::
create
({
self
->
cls
,
EmptyTuple
,
self
->
getAttrWrapper
()
});
}
}
};
};
...
@@ -967,16 +975,38 @@ Box* builtinRound(Box* _number, Box* _ndigits) {
...
@@ -967,16 +975,38 @@ Box* builtinRound(Box* _number, Box* _ndigits) {
raiseExcHelper
(
TypeError
,
"a float is required"
);
raiseExcHelper
(
TypeError
,
"a float is required"
);
BoxedFloat
*
number
=
(
BoxedFloat
*
)
_number
;
BoxedFloat
*
number
=
(
BoxedFloat
*
)
_number
;
double
x
=
number
->
d
;
if
(
isSubclass
(
_ndigits
->
cls
,
int_cls
))
{
/* interpret 2nd argument as a Py_ssize_t; clip on overflow */
BoxedInt
*
ndigits
=
(
BoxedInt
*
)
_ndigits
;
Py_ssize_t
ndigits
=
PyNumber_AsSsize_t
(
_ndigits
,
NULL
);
if
(
ndigits
==
-
1
&&
PyErr_Occurred
())
if
(
ndigits
->
n
==
0
)
throwCAPIException
();
return
boxFloat
(
round
(
number
->
d
));
}
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
/* nans, infinities and zeros round to themselves */
if
(
!
std
::
isfinite
(
x
)
||
x
==
0.0
)
return
boxFloat
(
x
);
/* Deal with extreme values for ndigits. For ndigits > NDIGITS_MAX, x
always rounds to itself. For ndigits < NDIGITS_MIN, x always
rounds to +-0.0. Here 0.30103 is an upper bound for log10(2). */
#define NDIGITS_MAX ((int)((DBL_MANT_DIG - DBL_MIN_EXP) * 0.30103))
#define NDIGITS_MIN (-(int)((DBL_MAX_EXP + 1) * 0.30103))
if
(
ndigits
>
NDIGITS_MAX
)
/* return x */
return
boxFloat
(
x
);
else
if
(
ndigits
<
NDIGITS_MIN
)
/* return 0.0, but with sign of x */
return
boxFloat
(
0.0
*
x
);
else
{
/* finite x, and ndigits is not unreasonably large */
/* _Py_double_round is defined in floatobject.c */
Box
*
rtn
=
_Py_double_round
(
x
,
(
int
)
ndigits
);
if
(
!
rtn
)
throwCAPIException
();
throwCAPIException
();
return
rtn
;
}
#undef NDIGITS_MAX
#undef NDIGITS_MIN
}
}
Box
*
builtinCmp
(
Box
*
a
,
Box
*
b
)
{
Box
*
builtinCmp
(
Box
*
a
,
Box
*
b
)
{
...
@@ -1103,6 +1133,9 @@ void setupBuiltins() {
...
@@ -1103,6 +1133,9 @@ void setupBuiltins() {
=
new
BoxedBuiltinFunctionOrMethod
(
boxRTFunction
((
void
*
)
issubclass_func
,
BOXED_BOOL
,
2
),
"issubclass"
);
=
new
BoxedBuiltinFunctionOrMethod
(
boxRTFunction
((
void
*
)
issubclass_func
,
BOXED_BOOL
,
2
),
"issubclass"
);
builtins_module
->
giveAttr
(
"issubclass"
,
issubclass_obj
);
builtins_module
->
giveAttr
(
"issubclass"
,
issubclass_obj
);
Box
*
intern_obj
=
new
BoxedBuiltinFunctionOrMethod
(
boxRTFunction
((
void
*
)
intern_func
,
UNKNOWN
,
1
),
"intern"
);
builtins_module
->
giveAttr
(
"intern"
,
intern_obj
);
CLFunction
*
import_func
=
boxRTFunction
((
void
*
)
bltinImport
,
UNKNOWN
,
5
,
4
,
false
,
false
,
CLFunction
*
import_func
=
boxRTFunction
((
void
*
)
bltinImport
,
UNKNOWN
,
5
,
4
,
false
,
false
,
ParamNames
({
"name"
,
"globals"
,
"locals"
,
"fromlist"
,
"level"
},
""
,
""
));
ParamNames
({
"name"
,
"globals"
,
"locals"
,
"fromlist"
,
"level"
},
""
,
""
));
builtins_module
->
giveAttr
(
"__import__"
,
new
BoxedBuiltinFunctionOrMethod
(
import_func
,
"__import__"
,
builtins_module
->
giveAttr
(
"__import__"
,
new
BoxedBuiltinFunctionOrMethod
(
import_func
,
"__import__"
,
...
...
src/runtime/float.cpp
View file @
801dec8c
...
@@ -12,6 +12,7 @@
...
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// See the License for the specific language governing permissions and
// limitations under the License.
// limitations under the License.
#include <cfloat>
#include <cmath>
#include <cmath>
#include <cstring>
#include <cstring>
...
@@ -833,6 +834,568 @@ const char* floatGetFormatDoc = "float.__getformat__(typestr) -> string\n"
...
@@ -833,6 +834,568 @@ const char* floatGetFormatDoc = "float.__getformat__(typestr) -> string\n"
"'unknown', 'IEEE, big-endian' or 'IEEE, little-endian' best describes the
\n
"
"'unknown', 'IEEE, big-endian' or 'IEEE, little-endian' best describes the
\n
"
"format of floating point numbers used by the C type named by typestr."
;
"format of floating point numbers used by the C type named by typestr."
;
static
PyObject
*
float_setformat
(
PyTypeObject
*
v
,
PyObject
*
args
)
noexcept
{
char
*
typestr
;
char
*
format
;
float_format_type
f
;
float_format_type
detected
;
float_format_type
*
p
;
if
(
!
PyArg_ParseTuple
(
args
,
"ss:__setformat__"
,
&
typestr
,
&
format
))
return
NULL
;
if
(
strcmp
(
typestr
,
"double"
)
==
0
)
{
p
=
&
double_format
;
detected
=
detected_double_format
;
}
else
if
(
strcmp
(
typestr
,
"float"
)
==
0
)
{
p
=
&
float_format
;
detected
=
detected_float_format
;
}
else
{
PyErr_SetString
(
PyExc_ValueError
,
"__setformat__() argument 1 must "
"be 'double' or 'float'"
);
return
NULL
;
}
if
(
strcmp
(
format
,
"unknown"
)
==
0
)
{
f
=
unknown_format
;
}
else
if
(
strcmp
(
format
,
"IEEE, little-endian"
)
==
0
)
{
f
=
ieee_little_endian_format
;
}
else
if
(
strcmp
(
format
,
"IEEE, big-endian"
)
==
0
)
{
f
=
ieee_big_endian_format
;
}
else
{
PyErr_SetString
(
PyExc_ValueError
,
"__setformat__() argument 2 must be "
"'unknown', 'IEEE, little-endian' or "
"'IEEE, big-endian'"
);
return
NULL
;
}
if
(
f
!=
unknown_format
&&
f
!=
detected
)
{
PyErr_Format
(
PyExc_ValueError
,
"can only set %s format to 'unknown' or the "
"detected platform value"
,
typestr
);
return
NULL
;
}
*
p
=
f
;
Py_RETURN_NONE
;
}
/*----------------------------------------------------------------------------
* _PyFloat_{Pack,Unpack}{4,8}. See floatobject.h.
*/
extern
"C"
int
_PyFloat_Pack4
(
double
x
,
unsigned
char
*
p
,
int
le
)
noexcept
{
if
(
float_format
==
unknown_format
)
{
unsigned
char
sign
;
int
e
;
double
f
;
unsigned
int
fbits
;
int
incr
=
1
;
if
(
le
)
{
p
+=
3
;
incr
=
-
1
;
}
if
(
x
<
0
)
{
sign
=
1
;
x
=
-
x
;
}
else
sign
=
0
;
f
=
frexp
(
x
,
&
e
);
/* Normalize f to be in the range [1.0, 2.0) */
if
(
0.5
<=
f
&&
f
<
1.0
)
{
f
*=
2.0
;
e
--
;
}
else
if
(
f
==
0.0
)
e
=
0
;
else
{
PyErr_SetString
(
PyExc_SystemError
,
"frexp() result out of range"
);
return
-
1
;
}
if
(
e
>=
128
)
goto
Overflow
;
else
if
(
e
<
-
126
)
{
/* Gradual underflow */
f
=
ldexp
(
f
,
126
+
e
);
e
=
0
;
}
else
if
(
!
(
e
==
0
&&
f
==
0.0
))
{
e
+=
127
;
f
-=
1.0
;
/* Get rid of leading 1 */
}
f
*=
8388608.0
;
/* 2**23 */
fbits
=
(
unsigned
int
)(
f
+
0.5
);
/* Round */
assert
(
fbits
<=
8388608
);
if
(
fbits
>>
23
)
{
/* The carry propagated out of a string of 23 1 bits. */
fbits
=
0
;
++
e
;
if
(
e
>=
255
)
goto
Overflow
;
}
/* First byte */
*
p
=
(
sign
<<
7
)
|
(
e
>>
1
);
p
+=
incr
;
/* Second byte */
*
p
=
(
char
)(((
e
&
1
)
<<
7
)
|
(
fbits
>>
16
));
p
+=
incr
;
/* Third byte */
*
p
=
(
fbits
>>
8
)
&
0xFF
;
p
+=
incr
;
/* Fourth byte */
*
p
=
fbits
&
0xFF
;
/* Done */
return
0
;
}
else
{
float
y
=
(
float
)
x
;
const
char
*
s
=
(
char
*
)
&
y
;
int
i
,
incr
=
1
;
if
(
Py_IS_INFINITY
(
y
)
&&
!
Py_IS_INFINITY
(
x
))
goto
Overflow
;
if
((
float_format
==
ieee_little_endian_format
&&
!
le
)
||
(
float_format
==
ieee_big_endian_format
&&
le
))
{
p
+=
3
;
incr
=
-
1
;
}
for
(
i
=
0
;
i
<
4
;
i
++
)
{
*
p
=
*
s
++
;
p
+=
incr
;
}
return
0
;
}
Overflow:
PyErr_SetString
(
PyExc_OverflowError
,
"float too large to pack with f format"
);
return
-
1
;
}
extern
"C"
int
_PyFloat_Pack8
(
double
x
,
unsigned
char
*
p
,
int
le
)
noexcept
{
if
(
double_format
==
unknown_format
)
{
unsigned
char
sign
;
int
e
;
double
f
;
unsigned
int
fhi
,
flo
;
int
incr
=
1
;
if
(
le
)
{
p
+=
7
;
incr
=
-
1
;
}
if
(
x
<
0
)
{
sign
=
1
;
x
=
-
x
;
}
else
sign
=
0
;
f
=
frexp
(
x
,
&
e
);
/* Normalize f to be in the range [1.0, 2.0) */
if
(
0.5
<=
f
&&
f
<
1.0
)
{
f
*=
2.0
;
e
--
;
}
else
if
(
f
==
0.0
)
e
=
0
;
else
{
PyErr_SetString
(
PyExc_SystemError
,
"frexp() result out of range"
);
return
-
1
;
}
if
(
e
>=
1024
)
goto
Overflow
;
else
if
(
e
<
-
1022
)
{
/* Gradual underflow */
f
=
ldexp
(
f
,
1022
+
e
);
e
=
0
;
}
else
if
(
!
(
e
==
0
&&
f
==
0.0
))
{
e
+=
1023
;
f
-=
1.0
;
/* Get rid of leading 1 */
}
/* fhi receives the high 28 bits; flo the low 24 bits (== 52 bits) */
f
*=
268435456.0
;
/* 2**28 */
fhi
=
(
unsigned
int
)
f
;
/* Truncate */
assert
(
fhi
<
268435456
);
f
-=
(
double
)
fhi
;
f
*=
16777216.0
;
/* 2**24 */
flo
=
(
unsigned
int
)(
f
+
0.5
);
/* Round */
assert
(
flo
<=
16777216
);
if
(
flo
>>
24
)
{
/* The carry propagated out of a string of 24 1 bits. */
flo
=
0
;
++
fhi
;
if
(
fhi
>>
28
)
{
/* And it also progagated out of the next 28 bits. */
fhi
=
0
;
++
e
;
if
(
e
>=
2047
)
goto
Overflow
;
}
}
/* First byte */
*
p
=
(
sign
<<
7
)
|
(
e
>>
4
);
p
+=
incr
;
/* Second byte */
*
p
=
(
unsigned
char
)(((
e
&
0xF
)
<<
4
)
|
(
fhi
>>
24
));
p
+=
incr
;
/* Third byte */
*
p
=
(
fhi
>>
16
)
&
0xFF
;
p
+=
incr
;
/* Fourth byte */
*
p
=
(
fhi
>>
8
)
&
0xFF
;
p
+=
incr
;
/* Fifth byte */
*
p
=
fhi
&
0xFF
;
p
+=
incr
;
/* Sixth byte */
*
p
=
(
flo
>>
16
)
&
0xFF
;
p
+=
incr
;
/* Seventh byte */
*
p
=
(
flo
>>
8
)
&
0xFF
;
p
+=
incr
;
/* Eighth byte */
*
p
=
flo
&
0xFF
;
/* p += incr; Unneeded (for now) */
/* Done */
return
0
;
Overflow:
PyErr_SetString
(
PyExc_OverflowError
,
"float too large to pack with d format"
);
return
-
1
;
}
else
{
const
char
*
s
=
(
char
*
)
&
x
;
int
i
,
incr
=
1
;
if
((
double_format
==
ieee_little_endian_format
&&
!
le
)
||
(
double_format
==
ieee_big_endian_format
&&
le
))
{
p
+=
7
;
incr
=
-
1
;
}
for
(
i
=
0
;
i
<
8
;
i
++
)
{
*
p
=
*
s
++
;
p
+=
incr
;
}
return
0
;
}
}
extern
"C"
double
_PyFloat_Unpack4
(
const
unsigned
char
*
p
,
int
le
)
noexcept
{
if
(
float_format
==
unknown_format
)
{
unsigned
char
sign
;
int
e
;
unsigned
int
f
;
double
x
;
int
incr
=
1
;
if
(
le
)
{
p
+=
3
;
incr
=
-
1
;
}
/* First byte */
sign
=
(
*
p
>>
7
)
&
1
;
e
=
(
*
p
&
0x7F
)
<<
1
;
p
+=
incr
;
/* Second byte */
e
|=
(
*
p
>>
7
)
&
1
;
f
=
(
*
p
&
0x7F
)
<<
16
;
p
+=
incr
;
if
(
e
==
255
)
{
PyErr_SetString
(
PyExc_ValueError
,
"can't unpack IEEE 754 special value "
"on non-IEEE platform"
);
return
-
1
;
}
/* Third byte */
f
|=
*
p
<<
8
;
p
+=
incr
;
/* Fourth byte */
f
|=
*
p
;
x
=
(
double
)
f
/
8388608.0
;
/* XXX This sadly ignores Inf/NaN issues */
if
(
e
==
0
)
e
=
-
126
;
else
{
x
+=
1.0
;
e
-=
127
;
}
x
=
ldexp
(
x
,
e
);
if
(
sign
)
x
=
-
x
;
return
x
;
}
else
{
float
x
;
if
((
float_format
==
ieee_little_endian_format
&&
!
le
)
||
(
float_format
==
ieee_big_endian_format
&&
le
))
{
char
buf
[
4
];
char
*
d
=
&
buf
[
3
];
int
i
;
for
(
i
=
0
;
i
<
4
;
i
++
)
{
*
d
--
=
*
p
++
;
}
memcpy
(
&
x
,
buf
,
4
);
}
else
{
memcpy
(
&
x
,
p
,
4
);
}
return
x
;
}
}
extern
"C"
double
_PyFloat_Unpack8
(
const
unsigned
char
*
p
,
int
le
)
noexcept
{
if
(
double_format
==
unknown_format
)
{
unsigned
char
sign
;
int
e
;
unsigned
int
fhi
,
flo
;
double
x
;
int
incr
=
1
;
if
(
le
)
{
p
+=
7
;
incr
=
-
1
;
}
/* First byte */
sign
=
(
*
p
>>
7
)
&
1
;
e
=
(
*
p
&
0x7F
)
<<
4
;
p
+=
incr
;
/* Second byte */
e
|=
(
*
p
>>
4
)
&
0xF
;
fhi
=
(
*
p
&
0xF
)
<<
24
;
p
+=
incr
;
if
(
e
==
2047
)
{
PyErr_SetString
(
PyExc_ValueError
,
"can't unpack IEEE 754 special value "
"on non-IEEE platform"
);
return
-
1.0
;
}
/* Third byte */
fhi
|=
*
p
<<
16
;
p
+=
incr
;
/* Fourth byte */
fhi
|=
*
p
<<
8
;
p
+=
incr
;
/* Fifth byte */
fhi
|=
*
p
;
p
+=
incr
;
/* Sixth byte */
flo
=
*
p
<<
16
;
p
+=
incr
;
/* Seventh byte */
flo
|=
*
p
<<
8
;
p
+=
incr
;
/* Eighth byte */
flo
|=
*
p
;
x
=
(
double
)
fhi
+
(
double
)
flo
/
16777216.0
;
/* 2**24 */
x
/=
268435456.0
;
/* 2**28 */
if
(
e
==
0
)
e
=
-
1022
;
else
{
x
+=
1.0
;
e
-=
1023
;
}
x
=
ldexp
(
x
,
e
);
if
(
sign
)
x
=
-
x
;
return
x
;
}
else
{
double
x
;
if
((
double_format
==
ieee_little_endian_format
&&
!
le
)
||
(
double_format
==
ieee_big_endian_format
&&
le
))
{
char
buf
[
8
];
char
*
d
=
&
buf
[
7
];
int
i
;
for
(
i
=
0
;
i
<
8
;
i
++
)
{
*
d
--
=
*
p
++
;
}
memcpy
(
&
x
,
buf
,
8
);
}
else
{
memcpy
(
&
x
,
p
,
8
);
}
return
x
;
}
}
#if DBL_MANT_DIG == 53
#define FIVE_POW_LIMIT 22
#else
#error "C doubles do not appear to be IEEE 754 binary64 format"
#endif
extern
"C"
PyObject
*
_Py_double_round
(
double
x
,
int
ndigits
)
noexcept
{
double
rounded
,
m
;
Py_ssize_t
buflen
,
mybuflen
=
100
;
char
*
buf
,
*
buf_end
,
shortbuf
[
100
],
*
mybuf
=
shortbuf
;
int
decpt
,
sign
,
val
,
halfway_case
;
PyObject
*
result
=
NULL
;
_Py_SET_53BIT_PRECISION_HEADER
;
/* Easy path for the common case ndigits == 0. */
if
(
ndigits
==
0
)
{
rounded
=
round
(
x
);
if
(
fabs
(
rounded
-
x
)
==
0.5
)
/* halfway between two integers; use round-away-from-zero */
rounded
=
x
+
(
x
>
0.0
?
0.5
:
-
0.5
);
return
PyFloat_FromDouble
(
rounded
);
}
/* The basic idea is very simple: convert and round the double to a
decimal string using _Py_dg_dtoa, then convert that decimal string
back to a double with _Py_dg_strtod. There's one minor difficulty:
Python 2.x expects round to do round-half-away-from-zero, while
_Py_dg_dtoa does round-half-to-even. So we need some way to detect
and correct the halfway cases.
Detection: a halfway value has the form k * 0.5 * 10**-ndigits for
some odd integer k. Or in other words, a rational number x is
exactly halfway between two multiples of 10**-ndigits if its
2-valuation is exactly -ndigits-1 and its 5-valuation is at least
-ndigits. For ndigits >= 0 the latter condition is automatically
satisfied for a binary float x, since any such float has
nonnegative 5-valuation. For 0 > ndigits >= -22, x needs to be an
integral multiple of 5**-ndigits; we can check this using fmod.
For -22 > ndigits, there are no halfway cases: 5**23 takes 54 bits
to represent exactly, so any odd multiple of 0.5 * 10**n for n >=
23 takes at least 54 bits of precision to represent exactly.
Correction: a simple strategy for dealing with halfway cases is to
(for the halfway cases only) call _Py_dg_dtoa with an argument of
ndigits+1 instead of ndigits (thus doing an exact conversion to
decimal), round the resulting string manually, and then convert
back using _Py_dg_strtod.
*/
/* nans, infinities and zeros should have already been dealt
with by the caller (in this case, builtin_round) */
assert
(
std
::
isfinite
(
x
)
&&
x
!=
0.0
);
/* find 2-valuation val of x */
m
=
frexp
(
x
,
&
val
);
while
(
m
!=
floor
(
m
))
{
m
*=
2.0
;
val
--
;
}
/* determine whether this is a halfway case */
if
(
val
==
-
ndigits
-
1
)
{
if
(
ndigits
>=
0
)
halfway_case
=
1
;
else
if
(
ndigits
>=
-
FIVE_POW_LIMIT
)
{
double
five_pow
=
1.0
;
int
i
;
for
(
i
=
0
;
i
<
-
ndigits
;
i
++
)
five_pow
*=
5.0
;
halfway_case
=
fmod
(
x
,
five_pow
)
==
0.0
;
}
else
halfway_case
=
0
;
}
else
halfway_case
=
0
;
/* round to a decimal string; use an extra place for halfway case */
_Py_SET_53BIT_PRECISION_START
;
buf
=
_Py_dg_dtoa
(
x
,
3
,
ndigits
+
halfway_case
,
&
decpt
,
&
sign
,
&
buf_end
);
_Py_SET_53BIT_PRECISION_END
;
if
(
buf
==
NULL
)
{
PyErr_NoMemory
();
return
NULL
;
}
buflen
=
buf_end
-
buf
;
/* in halfway case, do the round-half-away-from-zero manually */
if
(
halfway_case
)
{
int
i
,
carry
;
/* sanity check: _Py_dg_dtoa should not have stripped
any zeros from the result: there should be exactly
ndigits+1 places following the decimal point, and
the last digit in the buffer should be a '5'.*/
assert
(
buflen
-
decpt
==
ndigits
+
1
);
assert
(
buf
[
buflen
-
1
]
==
'5'
);
/* increment and shift right at the same time. */
decpt
+=
1
;
carry
=
1
;
for
(
i
=
buflen
-
1
;
i
--
>
0
;)
{
carry
+=
buf
[
i
]
-
'0'
;
buf
[
i
+
1
]
=
carry
%
10
+
'0'
;
carry
/=
10
;
}
buf
[
0
]
=
carry
+
'0'
;
}
/* Get new buffer if shortbuf is too small. Space needed <= buf_end -
buf + 8: (1 extra for '0', 1 for sign, 5 for exp, 1 for '\0'). */
if
(
buflen
+
8
>
mybuflen
)
{
mybuflen
=
buflen
+
8
;
mybuf
=
(
char
*
)
PyMem_Malloc
(
mybuflen
);
if
(
mybuf
==
NULL
)
{
PyErr_NoMemory
();
goto
exit
;
}
}
/* copy buf to mybuf, adding exponent, sign and leading 0 */
PyOS_snprintf
(
mybuf
,
mybuflen
,
"%s0%se%d"
,
(
sign
?
"-"
:
""
),
buf
,
decpt
-
(
int
)
buflen
);
/* and convert the resulting string back to a double */
errno
=
0
;
_Py_SET_53BIT_PRECISION_START
;
rounded
=
_Py_dg_strtod
(
mybuf
,
NULL
);
_Py_SET_53BIT_PRECISION_END
;
if
(
errno
==
ERANGE
&&
fabs
(
rounded
)
>=
1.
)
PyErr_SetString
(
PyExc_OverflowError
,
"rounded value too large to represent"
);
else
result
=
PyFloat_FromDouble
(
rounded
);
/* done computing value; now clean up */
if
(
mybuf
!=
shortbuf
)
PyMem_Free
(
mybuf
);
exit:
_Py_dg_freedtoa
(
buf
);
return
result
;
}
void
setupFloat
()
{
void
setupFloat
()
{
_addFunc
(
"__add__"
,
BOXED_FLOAT
,
(
void
*
)
floatAddFloat
,
(
void
*
)
floatAddInt
,
(
void
*
)
floatAdd
);
_addFunc
(
"__add__"
,
BOXED_FLOAT
,
(
void
*
)
floatAddFloat
,
(
void
*
)
floatAddInt
,
(
void
*
)
floatAdd
);
float_cls
->
giveAttr
(
"__radd__"
,
float_cls
->
getattr
(
"__add__"
));
float_cls
->
giveAttr
(
"__radd__"
,
float_cls
->
getattr
(
"__add__"
));
...
...
src/runtime/int.cpp
View file @
801dec8c
...
@@ -200,7 +200,7 @@ extern "C" PyObject* PyInt_FromString(const char* s, char** pend, int base) noex
...
@@ -200,7 +200,7 @@ extern "C" PyObject* PyInt_FromString(const char* s, char** pend, int base) noex
if
(
x
<
0
)
if
(
x
<
0
)
return
PyLong_FromString
(
s
,
pend
,
base
);
return
PyLong_FromString
(
s
,
pend
,
base
);
}
else
}
else
x
=
strto
u
l
(
s
,
&
end
,
base
);
x
=
strtol
(
s
,
&
end
,
base
);
if
(
end
==
s
||
!
isalnum
(
Py_CHARMASK
(
end
[
-
1
])))
if
(
end
==
s
||
!
isalnum
(
Py_CHARMASK
(
end
[
-
1
])))
goto
bad
;
goto
bad
;
while
(
*
end
&&
isspace
(
Py_CHARMASK
(
*
end
)))
while
(
*
end
&&
isspace
(
Py_CHARMASK
(
*
end
)))
...
@@ -672,8 +672,13 @@ extern "C" Box* intLShiftInt(BoxedInt* lhs, BoxedInt* rhs) {
...
@@ -672,8 +672,13 @@ extern "C" Box* intLShiftInt(BoxedInt* lhs, BoxedInt* rhs) {
if
(
rhs
->
n
<
0
)
if
(
rhs
->
n
<
0
)
raiseExcHelper
(
ValueError
,
"negative shift count"
);
raiseExcHelper
(
ValueError
,
"negative shift count"
);
// TODO overflow?
bool
undefined
=
rhs
->
n
>=
sizeof
(
rhs
->
n
)
*
8
;
if
(
!
undefined
)
{
int64_t
res
=
lhs
->
n
<<
rhs
->
n
;
if
((
res
>>
rhs
->
n
)
==
lhs
->
n
)
return
boxInt
(
lhs
->
n
<<
rhs
->
n
);
return
boxInt
(
lhs
->
n
<<
rhs
->
n
);
}
return
longLshift
(
boxLong
(
lhs
->
n
),
rhs
);
}
}
extern
"C"
Box
*
intLShift
(
BoxedInt
*
lhs
,
Box
*
rhs
)
{
extern
"C"
Box
*
intLShift
(
BoxedInt
*
lhs
,
Box
*
rhs
)
{
...
...
src/runtime/iterobject.cpp
View file @
801dec8c
...
@@ -109,7 +109,7 @@ Box* seqiterNext(Box* s) {
...
@@ -109,7 +109,7 @@ Box* seqiterNext(Box* s) {
}
}
static
void
seqiterGCVisit
(
GCVisitor
*
v
,
Box
*
b
)
{
static
void
seqiterGCVisit
(
GCVisitor
*
v
,
Box
*
b
)
{
assert
(
b
->
cls
==
seqiter_cls
);
assert
(
b
->
cls
==
seqiter_cls
||
b
->
cls
==
seqreviter_cls
);
boxGCHandler
(
v
,
b
);
boxGCHandler
(
v
,
b
);
BoxedSeqIter
*
si
=
static_cast
<
BoxedSeqIter
*>
(
b
);
BoxedSeqIter
*
si
=
static_cast
<
BoxedSeqIter
*>
(
b
);
...
@@ -182,7 +182,8 @@ void setupIter() {
...
@@ -182,7 +182,8 @@ void setupIter() {
seqiter_cls
->
freeze
();
seqiter_cls
->
freeze
();
seqiter_cls
->
tpp_hasnext
=
seqiterHasnextUnboxed
;
seqiter_cls
->
tpp_hasnext
=
seqiterHasnextUnboxed
;
seqreviter_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedSeqIter
),
false
,
"reversed"
);
seqreviter_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
seqiterGCVisit
,
0
,
0
,
sizeof
(
BoxedSeqIter
),
false
,
"reversed"
);
seqreviter_cls
->
giveAttr
(
"next"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
seqiterNext
,
UNKNOWN
,
1
)));
seqreviter_cls
->
giveAttr
(
"next"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
seqiterNext
,
UNKNOWN
,
1
)));
seqreviter_cls
->
giveAttr
(
"__hasnext__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
seqreviterHasnext
,
BOXED_BOOL
,
1
)));
seqreviter_cls
->
giveAttr
(
"__hasnext__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
seqreviterHasnext
,
BOXED_BOOL
,
1
)));
...
...
src/runtime/list.cpp
View file @
801dec8c
...
@@ -25,6 +25,7 @@
...
@@ -25,6 +25,7 @@
#include "core/stats.h"
#include "core/stats.h"
#include "core/types.h"
#include "core/types.h"
#include "gc/collector.h"
#include "gc/collector.h"
#include "gc/roots.h"
#include "runtime/objmodel.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
#include "runtime/types.h"
#include "runtime/util.h"
#include "runtime/util.h"
...
@@ -423,23 +424,21 @@ extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) {
...
@@ -423,23 +424,21 @@ extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) {
size_t
v_size
;
size_t
v_size
;
Box
**
v_elts
;
Box
**
v_elts
;
RootedBox
v_as_seq
((
Box
*
)
nullptr
);
if
(
!
v
)
{
if
(
!
v
)
{
v_size
=
0
;
v_size
=
0
;
v_elts
=
NULL
;
v_elts
=
NULL
;
}
else
if
(
v
->
cls
==
list_cls
||
isSubclass
(
v
->
cls
,
list_cls
))
{
}
else
{
BoxedList
*
lv
=
static_cast
<
BoxedList
*>
(
v
);
v_as_seq
=
RootedBox
(
PySequence_Fast
(
v
,
"can only assign an iterable"
));
v_size
=
lv
->
size
;
if
(
v_as_seq
==
NULL
)
throwCAPIException
();
v_size
=
PySequence_Fast_GET_SIZE
(
v_as_seq
);
// If lv->size is 0, lv->elts->elts is garbage
// If lv->size is 0, lv->elts->elts is garbage
if
(
v_size
)
if
(
v_size
)
v_elts
=
lv
->
elts
->
elts
;
v_elts
=
PySequence_Fast_ITEMS
(
v_as_seq
)
;
else
else
v_elts
=
NULL
;
v_elts
=
NULL
;
}
else
if
(
v
->
cls
==
tuple_cls
||
isSubclass
(
v
->
cls
,
tuple_cls
))
{
BoxedTuple
*
tv
=
static_cast
<
BoxedTuple
*>
(
v
);
v_size
=
tv
->
size
();
v_elts
=
&
tv
->
elts
[
0
];
}
else
{
RELEASE_ASSERT
(
0
,
"unsupported type for list slice assignment: '%s'"
,
getTypeName
(
v
));
}
}
// If self->size is 0, self->elts->elts is garbage
// If self->size is 0, self->elts->elts is garbage
...
...
src/runtime/long.cpp
View file @
801dec8c
...
@@ -116,7 +116,48 @@ extern "C" unsigned PY_LONG_LONG PyLong_AsUnsignedLongLongMask(PyObject* vv) noe
...
@@ -116,7 +116,48 @@ extern "C" unsigned PY_LONG_LONG PyLong_AsUnsignedLongLongMask(PyObject* vv) noe
}
}
extern
"C"
PY_LONG_LONG
PyLong_AsLongLong
(
PyObject
*
vv
)
noexcept
{
extern
"C"
PY_LONG_LONG
PyLong_AsLongLong
(
PyObject
*
vv
)
noexcept
{
Py_FatalError
(
"unimplemented"
);
PY_LONG_LONG
bytes
;
int
one
=
1
;
int
res
;
if
(
vv
==
NULL
)
{
PyErr_BadInternalCall
();
return
-
1
;
}
if
(
!
PyLong_Check
(
vv
))
{
PyNumberMethods
*
nb
;
PyObject
*
io
;
if
(
PyInt_Check
(
vv
))
return
(
PY_LONG_LONG
)
PyInt_AsLong
(
vv
);
if
((
nb
=
vv
->
cls
->
tp_as_number
)
==
NULL
||
nb
->
nb_int
==
NULL
)
{
PyErr_SetString
(
PyExc_TypeError
,
"an integer is required"
);
return
-
1
;
}
io
=
(
*
nb
->
nb_int
)(
vv
);
if
(
io
==
NULL
)
return
-
1
;
if
(
PyInt_Check
(
io
))
{
bytes
=
PyInt_AsLong
(
io
);
Py_DECREF
(
io
);
return
bytes
;
}
if
(
PyLong_Check
(
io
))
{
bytes
=
PyLong_AsLongLong
(
io
);
Py_DECREF
(
io
);
return
bytes
;
}
Py_DECREF
(
io
);
PyErr_SetString
(
PyExc_TypeError
,
"integer conversion failed"
);
return
-
1
;
}
res
=
_PyLong_AsByteArray
((
PyLongObject
*
)
vv
,
(
unsigned
char
*
)
&
bytes
,
SIZEOF_LONG_LONG
,
IS_LITTLE_ENDIAN
,
1
);
/* Plan 9 can't handle PY_LONG_LONG in ? : expressions */
if
(
res
<
0
)
return
(
PY_LONG_LONG
)
-
1
;
else
return
bytes
;
}
}
extern
"C"
PY_LONG_LONG
PyLong_AsLongLongAndOverflow
(
PyObject
*
obj
,
int
*
overflow
)
noexcept
{
extern
"C"
PY_LONG_LONG
PyLong_AsLongLongAndOverflow
(
PyObject
*
obj
,
int
*
overflow
)
noexcept
{
...
@@ -442,7 +483,12 @@ extern "C" void* PyLong_AsVoidPtr(PyObject* vv) noexcept {
...
@@ -442,7 +483,12 @@ extern "C" void* PyLong_AsVoidPtr(PyObject* vv) noexcept {
extern
"C"
int
_PyLong_AsByteArray
(
PyLongObject
*
v
,
unsigned
char
*
bytes
,
size_t
n
,
int
little_endian
,
extern
"C"
int
_PyLong_AsByteArray
(
PyLongObject
*
v
,
unsigned
char
*
bytes
,
size_t
n
,
int
little_endian
,
int
is_signed
)
noexcept
{
int
is_signed
)
noexcept
{
Py_FatalError
(
"unimplemented"
);
RELEASE_ASSERT
(
little_endian
==
1
,
"not implemented"
);
RELEASE_ASSERT
(
n
==
8
,
"did not yet check if the behaviour is correct for sizes other than 8"
);
size_t
count
=
0
;
mpz_export
(
bytes
,
&
count
,
-
1
,
n
,
0
,
0
,
((
BoxedLong
*
)
v
)
->
n
);
RELEASE_ASSERT
(
count
<=
n
,
"overflow handling is not yet implemented"
);
return
0
;
}
}
extern
"C"
PyObject
*
_PyLong_FromByteArray
(
const
unsigned
char
*
bytes
,
size_t
n
,
int
little_endian
,
extern
"C"
PyObject
*
_PyLong_FromByteArray
(
const
unsigned
char
*
bytes
,
size_t
n
,
int
little_endian
,
...
...
src/runtime/str.cpp
View file @
801dec8c
...
@@ -2305,8 +2305,17 @@ extern "C" PyObject* PyString_FromStringAndSize(const char* s, ssize_t n) noexce
...
@@ -2305,8 +2305,17 @@ extern "C" PyObject* PyString_FromStringAndSize(const char* s, ssize_t n) noexce
return
boxStrConstantSize
(
s
,
n
);
return
boxStrConstantSize
(
s
,
n
);
}
}
static
/*const*/
char
*
string_getbuffer
(
register
PyObject
*
op
)
noexcept
{
char
*
s
;
Py_ssize_t
len
;
if
(
PyString_AsStringAndSize
(
op
,
&
s
,
&
len
))
return
NULL
;
return
s
;
}
extern
"C"
char
*
PyString_AsString
(
PyObject
*
o
)
noexcept
{
extern
"C"
char
*
PyString_AsString
(
PyObject
*
o
)
noexcept
{
RELEASE_ASSERT
(
isSubclass
(
o
->
cls
,
str_cls
),
""
);
if
(
!
PyString_Check
(
o
))
return
string_getbuffer
(
o
);
BoxedString
*
s
=
static_cast
<
BoxedString
*>
(
o
);
BoxedString
*
s
=
static_cast
<
BoxedString
*>
(
o
);
return
getWriteableStringContents
(
s
);
return
getWriteableStringContents
(
s
);
...
...
src/runtime/types.cpp
View file @
801dec8c
...
@@ -978,7 +978,39 @@ Box* sliceRepr(BoxedSlice* self) {
...
@@ -978,7 +978,39 @@ Box* sliceRepr(BoxedSlice* self) {
extern
"C"
int
PySlice_GetIndices
(
PySliceObject
*
r
,
Py_ssize_t
length
,
Py_ssize_t
*
start
,
Py_ssize_t
*
stop
,
extern
"C"
int
PySlice_GetIndices
(
PySliceObject
*
r
,
Py_ssize_t
length
,
Py_ssize_t
*
start
,
Py_ssize_t
*
stop
,
Py_ssize_t
*
step
)
noexcept
{
Py_ssize_t
*
step
)
noexcept
{
Py_FatalError
(
"unimplemented"
);
/* XXX support long ints */
if
(
r
->
step
==
Py_None
)
{
*
step
=
1
;
}
else
{
if
(
!
PyInt_Check
(
r
->
step
)
&&
!
PyLong_Check
(
r
->
step
))
return
-
1
;
*
step
=
PyInt_AsSsize_t
(
r
->
step
);
}
if
(
r
->
start
==
Py_None
)
{
*
start
=
*
step
<
0
?
length
-
1
:
0
;
}
else
{
if
(
!
PyInt_Check
(
r
->
start
)
&&
!
PyLong_Check
(
r
->
step
))
return
-
1
;
*
start
=
PyInt_AsSsize_t
(
r
->
start
);
if
(
*
start
<
0
)
*
start
+=
length
;
}
if
(
r
->
stop
==
Py_None
)
{
*
stop
=
*
step
<
0
?
-
1
:
length
;
}
else
{
if
(
!
PyInt_Check
(
r
->
stop
)
&&
!
PyLong_Check
(
r
->
step
))
return
-
1
;
*
stop
=
PyInt_AsSsize_t
(
r
->
stop
);
if
(
*
stop
<
0
)
*
stop
+=
length
;
}
if
(
*
stop
>
length
)
return
-
1
;
if
(
*
start
>=
length
)
return
-
1
;
if
(
*
step
==
0
)
return
-
1
;
return
0
;
}
}
extern
"C"
int
PySlice_GetIndicesEx
(
PySliceObject
*
_r
,
Py_ssize_t
length
,
Py_ssize_t
*
start
,
Py_ssize_t
*
stop
,
extern
"C"
int
PySlice_GetIndicesEx
(
PySliceObject
*
_r
,
Py_ssize_t
length
,
Py_ssize_t
*
start
,
Py_ssize_t
*
stop
,
...
...
test/tests/builtins.py
View file @
801dec8c
...
@@ -105,8 +105,8 @@ print callable(lambda: 1)
...
@@ -105,8 +105,8 @@ print callable(lambda: 1)
print
range
(
5L
,
7L
)
print
range
(
5L
,
7L
)
print
round
(
-
1.1
),
round
(
-
1.9
)
for
n
in
[
0
,
1
,
2
,
3
,
4
,
5
]:
print
round
(
0.5
),
round
(
-
0.5
)
print
round
(
-
1.1
,
n
),
round
(
-
1.9
,
n
),
round
(
0.5
,
n
),
round
(
-
0.5
,
n
),
round
(
-
0.123456789
,
n
)
print
list
(
iter
(
xrange
(
100
).
__iter__
().
next
,
20
))
print
list
(
iter
(
xrange
(
100
).
__iter__
().
next
,
20
))
...
...
test/tests/intmethods.py
View file @
801dec8c
...
@@ -66,6 +66,9 @@ class L(object):
...
@@ -66,6 +66,9 @@ class L(object):
print
type
(
int
(
L
()))
print
type
(
int
(
L
()))
print
int
(
u'123'
)
print
int
(
u'123'
)
print
int
(
"9223372036854775808"
,
0
)
print
1
<<
63
,
1
<<
64
,
-
1
<<
63
,
-
1
<<
64
,
2
<<
63
print
type
(
1
<<
63
),
type
(
1
<<
64
),
type
(
-
1
<<
63
),
type
(
-
1
<<
64
),
type
(
2
<<
63
)
for
b
in
range
(
26
):
for
b
in
range
(
26
):
try
:
try
:
...
...
test/tests/list.py
View file @
801dec8c
...
@@ -124,7 +124,13 @@ for i in xrange(3):
...
@@ -124,7 +124,13 @@ for i in xrange(3):
l
[
j
:
k
]
=
[
"added"
]
l
[
j
:
k
]
=
[
"added"
]
print
i
,
j
,
k
,
l
print
i
,
j
,
k
,
l
def
G
():
yield
"a"
yield
"b"
yield
"c"
l
=
[
0
,
1
,
2
,
3
,
4
,
5
]
l
[
1
:]
=
G
()
print
l
l
=
[
1
,
3
,
5
,
7
,
2
,
4
]
l
=
[
1
,
3
,
5
,
7
,
2
,
4
]
print
l
.
sort
(
key
=
lambda
x
:
x
%
3
)
print
l
.
sort
(
key
=
lambda
x
:
x
%
3
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a 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