Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
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
Kirill Smelkov
cpython
Commits
7cc5521d
Commit
7cc5521d
authored
Mar 21, 2012
by
Stefan Krah
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Whitespace.
parent
851a07e5
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
168 additions
and
168 deletions
+168
-168
Modules/_decimal/_decimal.c
Modules/_decimal/_decimal.c
+2
-2
Modules/_decimal/libmpdec/context.c
Modules/_decimal/libmpdec/context.c
+118
-118
Modules/_decimal/libmpdec/io.c
Modules/_decimal/libmpdec/io.c
+24
-24
Modules/_decimal/libmpdec/mpdecimal.c
Modules/_decimal/libmpdec/mpdecimal.c
+1
-1
Modules/_decimal/libmpdec/mpdecimal.h
Modules/_decimal/libmpdec/mpdecimal.h
+7
-7
Modules/_decimal/libmpdec/typearith.h
Modules/_decimal/libmpdec/typearith.h
+16
-16
No files found.
Modules/_decimal/_decimal.c
View file @
7cc5521d
...
...
@@ -1585,14 +1585,14 @@ current_context(void)
#define CURRENT_CONTEXT(ctxobj) \
ctxobj = current_context(); \
if (ctxobj == NULL) { \
return NULL;
\
return NULL;
\
}
/* ctx := pointer to the mpd_context_t struct of the current context */
#define CURRENT_CONTEXT_ADDR(ctx) { \
PyObject *_c_t_x_o_b_j = current_context(); \
if (_c_t_x_o_b_j == NULL) { \
return NULL;
\
return NULL;
\
} \
ctx = CTX(_c_t_x_o_b_j); \
}
...
...
Modules/_decimal/libmpdec/context.c
View file @
7cc5521d
...
...
@@ -35,7 +35,7 @@
void
mpd_dflt_traphandler
(
mpd_context_t
*
ctx
UNUSED
)
{
raise
(
SIGFPE
);
raise
(
SIGFPE
);
}
void
(
*
mpd_traphandler
)(
mpd_context_t
*
)
=
mpd_dflt_traphandler
;
...
...
@@ -48,239 +48,239 @@ void (* mpd_traphandler)(mpd_context_t *) = mpd_dflt_traphandler;
void
mpd_setminalloc
(
mpd_ssize_t
n
)
{
static
int
minalloc_is_set
=
0
;
if
(
minalloc_is_set
)
{
mpd_err_warn
(
"mpd_setminalloc: ignoring request to set "
"MPD_MINALLOC a second time
\n
"
);
return
;
}
if
(
n
<
MPD_MINALLOC_MIN
||
n
>
MPD_MINALLOC_MAX
)
{
mpd_err_fatal
(
"illegal value for MPD_MINALLOC"
);
/* GCOV_NOT_REACHED */
}
MPD_MINALLOC
=
n
;
minalloc_is_set
=
1
;
static
int
minalloc_is_set
=
0
;
if
(
minalloc_is_set
)
{
mpd_err_warn
(
"mpd_setminalloc: ignoring request to set "
"MPD_MINALLOC a second time
\n
"
);
return
;
}
if
(
n
<
MPD_MINALLOC_MIN
||
n
>
MPD_MINALLOC_MAX
)
{
mpd_err_fatal
(
"illegal value for MPD_MINALLOC"
);
/* GCOV_NOT_REACHED */
}
MPD_MINALLOC
=
n
;
minalloc_is_set
=
1
;
}
void
mpd_init
(
mpd_context_t
*
ctx
,
mpd_ssize_t
prec
)
{
mpd_ssize_t
ideal_minalloc
;
mpd_ssize_t
ideal_minalloc
;
mpd_defaultcontext
(
ctx
);
mpd_defaultcontext
(
ctx
);
if
(
!
mpd_qsetprec
(
ctx
,
prec
))
{
mpd_addstatus_raise
(
ctx
,
MPD_Invalid_context
);
return
;
}
if
(
!
mpd_qsetprec
(
ctx
,
prec
))
{
mpd_addstatus_raise
(
ctx
,
MPD_Invalid_context
);
return
;
}
ideal_minalloc
=
2
*
((
prec
+
MPD_RDIGITS
-
1
)
/
MPD_RDIGITS
);
if
(
ideal_minalloc
<
MPD_MINALLOC_MIN
)
ideal_minalloc
=
MPD_MINALLOC_MIN
;
if
(
ideal_minalloc
>
MPD_MINALLOC_MAX
)
ideal_minalloc
=
MPD_MINALLOC_MAX
;
ideal_minalloc
=
2
*
((
prec
+
MPD_RDIGITS
-
1
)
/
MPD_RDIGITS
);
if
(
ideal_minalloc
<
MPD_MINALLOC_MIN
)
ideal_minalloc
=
MPD_MINALLOC_MIN
;
if
(
ideal_minalloc
>
MPD_MINALLOC_MAX
)
ideal_minalloc
=
MPD_MINALLOC_MAX
;
mpd_setminalloc
(
ideal_minalloc
);
mpd_setminalloc
(
ideal_minalloc
);
}
void
mpd_maxcontext
(
mpd_context_t
*
ctx
)
{
ctx
->
prec
=
MPD_MAX_PREC
;
ctx
->
emax
=
MPD_MAX_EMAX
;
ctx
->
emin
=
MPD_MIN_EMIN
;
ctx
->
round
=
MPD_ROUND_HALF_EVEN
;
ctx
->
traps
=
MPD_Traps
;
ctx
->
status
=
0
;
ctx
->
newtrap
=
0
;
ctx
->
clamp
=
0
;
ctx
->
allcr
=
1
;
ctx
->
prec
=
MPD_MAX_PREC
;
ctx
->
emax
=
MPD_MAX_EMAX
;
ctx
->
emin
=
MPD_MIN_EMIN
;
ctx
->
round
=
MPD_ROUND_HALF_EVEN
;
ctx
->
traps
=
MPD_Traps
;
ctx
->
status
=
0
;
ctx
->
newtrap
=
0
;
ctx
->
clamp
=
0
;
ctx
->
allcr
=
1
;
}
void
mpd_defaultcontext
(
mpd_context_t
*
ctx
)
{
ctx
->
prec
=
2
*
MPD_RDIGITS
;
ctx
->
emax
=
MPD_MAX_EMAX
;
ctx
->
emin
=
MPD_MIN_EMIN
;
ctx
->
round
=
MPD_ROUND_HALF_UP
;
ctx
->
traps
=
MPD_Traps
;
ctx
->
status
=
0
;
ctx
->
newtrap
=
0
;
ctx
->
clamp
=
0
;
ctx
->
allcr
=
1
;
ctx
->
prec
=
2
*
MPD_RDIGITS
;
ctx
->
emax
=
MPD_MAX_EMAX
;
ctx
->
emin
=
MPD_MIN_EMIN
;
ctx
->
round
=
MPD_ROUND_HALF_UP
;
ctx
->
traps
=
MPD_Traps
;
ctx
->
status
=
0
;
ctx
->
newtrap
=
0
;
ctx
->
clamp
=
0
;
ctx
->
allcr
=
1
;
}
void
mpd_basiccontext
(
mpd_context_t
*
ctx
)
{
ctx
->
prec
=
9
;
ctx
->
emax
=
MPD_MAX_EMAX
;
ctx
->
emin
=
MPD_MIN_EMIN
;
ctx
->
round
=
MPD_ROUND_HALF_UP
;
ctx
->
traps
=
MPD_Traps
|
MPD_Clamped
;
ctx
->
status
=
0
;
ctx
->
newtrap
=
0
;
ctx
->
clamp
=
0
;
ctx
->
allcr
=
1
;
ctx
->
prec
=
9
;
ctx
->
emax
=
MPD_MAX_EMAX
;
ctx
->
emin
=
MPD_MIN_EMIN
;
ctx
->
round
=
MPD_ROUND_HALF_UP
;
ctx
->
traps
=
MPD_Traps
|
MPD_Clamped
;
ctx
->
status
=
0
;
ctx
->
newtrap
=
0
;
ctx
->
clamp
=
0
;
ctx
->
allcr
=
1
;
}
int
mpd_ieee_context
(
mpd_context_t
*
ctx
,
int
bits
)
{
if
(
bits
<=
0
||
bits
>
MPD_IEEE_CONTEXT_MAX_BITS
||
bits
%
32
)
{
return
-
1
;
}
ctx
->
prec
=
9
*
(
bits
/
32
)
-
2
;
ctx
->
emax
=
3
*
((
mpd_ssize_t
)
1
<<
(
bits
/
16
+
3
));
ctx
->
emin
=
1
-
ctx
->
emax
;
ctx
->
round
=
MPD_ROUND_HALF_EVEN
;
ctx
->
traps
=
0
;
ctx
->
status
=
0
;
ctx
->
newtrap
=
0
;
ctx
->
clamp
=
1
;
ctx
->
allcr
=
1
;
return
0
;
if
(
bits
<=
0
||
bits
>
MPD_IEEE_CONTEXT_MAX_BITS
||
bits
%
32
)
{
return
-
1
;
}
ctx
->
prec
=
9
*
(
bits
/
32
)
-
2
;
ctx
->
emax
=
3
*
((
mpd_ssize_t
)
1
<<
(
bits
/
16
+
3
));
ctx
->
emin
=
1
-
ctx
->
emax
;
ctx
->
round
=
MPD_ROUND_HALF_EVEN
;
ctx
->
traps
=
0
;
ctx
->
status
=
0
;
ctx
->
newtrap
=
0
;
ctx
->
clamp
=
1
;
ctx
->
allcr
=
1
;
return
0
;
}
mpd_ssize_t
mpd_getprec
(
const
mpd_context_t
*
ctx
)
{
return
ctx
->
prec
;
return
ctx
->
prec
;
}
mpd_ssize_t
mpd_getemax
(
const
mpd_context_t
*
ctx
)
{
return
ctx
->
emax
;
return
ctx
->
emax
;
}
mpd_ssize_t
mpd_getemin
(
const
mpd_context_t
*
ctx
)
{
return
ctx
->
emin
;
return
ctx
->
emin
;
}
int
mpd_getround
(
const
mpd_context_t
*
ctx
)
{
return
ctx
->
round
;
return
ctx
->
round
;
}
uint32_t
mpd_gettraps
(
const
mpd_context_t
*
ctx
)
{
return
ctx
->
traps
;
return
ctx
->
traps
;
}
uint32_t
mpd_getstatus
(
const
mpd_context_t
*
ctx
)
{
return
ctx
->
status
;
return
ctx
->
status
;
}
int
mpd_getclamp
(
const
mpd_context_t
*
ctx
)
{
return
ctx
->
clamp
;
return
ctx
->
clamp
;
}
int
mpd_getcr
(
const
mpd_context_t
*
ctx
)
{
return
ctx
->
allcr
;
return
ctx
->
allcr
;
}
int
mpd_qsetprec
(
mpd_context_t
*
ctx
,
mpd_ssize_t
prec
)
{
if
(
prec
<=
0
||
prec
>
MPD_MAX_PREC
)
{
return
0
;
}
ctx
->
prec
=
prec
;
return
1
;
if
(
prec
<=
0
||
prec
>
MPD_MAX_PREC
)
{
return
0
;
}
ctx
->
prec
=
prec
;
return
1
;
}
int
mpd_qsetemax
(
mpd_context_t
*
ctx
,
mpd_ssize_t
emax
)
{
if
(
emax
<
0
||
emax
>
MPD_MAX_EMAX
)
{
return
0
;
}
ctx
->
emax
=
emax
;
return
1
;
if
(
emax
<
0
||
emax
>
MPD_MAX_EMAX
)
{
return
0
;
}
ctx
->
emax
=
emax
;
return
1
;
}
int
mpd_qsetemin
(
mpd_context_t
*
ctx
,
mpd_ssize_t
emin
)
{
if
(
emin
>
0
||
emin
<
MPD_MIN_EMIN
)
{
return
0
;
}
ctx
->
emin
=
emin
;
return
1
;
if
(
emin
>
0
||
emin
<
MPD_MIN_EMIN
)
{
return
0
;
}
ctx
->
emin
=
emin
;
return
1
;
}
int
mpd_qsetround
(
mpd_context_t
*
ctx
,
int
round
)
{
if
(
!
(
0
<=
round
&&
round
<
MPD_ROUND_GUARD
))
{
return
0
;
}
ctx
->
round
=
round
;
return
1
;
if
(
!
(
0
<=
round
&&
round
<
MPD_ROUND_GUARD
))
{
return
0
;
}
ctx
->
round
=
round
;
return
1
;
}
int
mpd_qsettraps
(
mpd_context_t
*
ctx
,
uint32_t
traps
)
{
if
(
traps
>
MPD_Max_status
)
{
return
0
;
}
ctx
->
traps
=
traps
;
return
1
;
if
(
traps
>
MPD_Max_status
)
{
return
0
;
}
ctx
->
traps
=
traps
;
return
1
;
}
int
mpd_qsetstatus
(
mpd_context_t
*
ctx
,
uint32_t
flags
)
{
if
(
flags
>
MPD_Max_status
)
{
return
0
;
}
ctx
->
status
=
flags
;
return
1
;
if
(
flags
>
MPD_Max_status
)
{
return
0
;
}
ctx
->
status
=
flags
;
return
1
;
}
int
mpd_qsetclamp
(
mpd_context_t
*
ctx
,
int
c
)
{
if
(
c
!=
0
&&
c
!=
1
)
{
return
0
;
}
ctx
->
clamp
=
c
;
return
1
;
if
(
c
!=
0
&&
c
!=
1
)
{
return
0
;
}
ctx
->
clamp
=
c
;
return
1
;
}
int
mpd_qsetcr
(
mpd_context_t
*
ctx
,
int
c
)
{
if
(
c
!=
0
&&
c
!=
1
)
{
return
0
;
}
ctx
->
allcr
=
c
;
return
1
;
if
(
c
!=
0
&&
c
!=
1
)
{
return
0
;
}
ctx
->
allcr
=
c
;
return
1
;
}
void
mpd_addstatus_raise
(
mpd_context_t
*
ctx
,
uint32_t
flags
)
{
ctx
->
status
|=
flags
;
if
(
flags
&
ctx
->
traps
)
{
ctx
->
newtrap
=
(
flags
&
ctx
->
traps
);
mpd_traphandler
(
ctx
);
}
ctx
->
status
|=
flags
;
if
(
flags
&
ctx
->
traps
)
{
ctx
->
newtrap
=
(
flags
&
ctx
->
traps
);
mpd_traphandler
(
ctx
);
}
}
Modules/_decimal/libmpdec/io.c
View file @
7cc5521d
...
...
@@ -328,33 +328,33 @@ conversion_error:
static
inline
char
*
word_to_string
(
char
*
s
,
mpd_uint_t
x
,
int
n
,
char
*
dot
)
{
switch
(
n
)
{
switch
(
n
)
{
#ifdef CONFIG_64
case
20
:
EXTRACT_DIGIT
(
s
,
x
,
10000000000000000000ULL
,
dot
);
/* GCOV_NOT_REACHED */
case
19
:
EXTRACT_DIGIT
(
s
,
x
,
1000000000000000000ULL
,
dot
);
case
18
:
EXTRACT_DIGIT
(
s
,
x
,
100000000000000000ULL
,
dot
);
case
17
:
EXTRACT_DIGIT
(
s
,
x
,
10000000000000000ULL
,
dot
);
case
16
:
EXTRACT_DIGIT
(
s
,
x
,
1000000000000000ULL
,
dot
);
case
15
:
EXTRACT_DIGIT
(
s
,
x
,
100000000000000ULL
,
dot
);
case
14
:
EXTRACT_DIGIT
(
s
,
x
,
10000000000000ULL
,
dot
);
case
13
:
EXTRACT_DIGIT
(
s
,
x
,
1000000000000ULL
,
dot
);
case
12
:
EXTRACT_DIGIT
(
s
,
x
,
100000000000ULL
,
dot
);
case
11
:
EXTRACT_DIGIT
(
s
,
x
,
10000000000ULL
,
dot
);
case
20
:
EXTRACT_DIGIT
(
s
,
x
,
10000000000000000000ULL
,
dot
);
/* GCOV_NOT_REACHED */
case
19
:
EXTRACT_DIGIT
(
s
,
x
,
1000000000000000000ULL
,
dot
);
case
18
:
EXTRACT_DIGIT
(
s
,
x
,
100000000000000000ULL
,
dot
);
case
17
:
EXTRACT_DIGIT
(
s
,
x
,
10000000000000000ULL
,
dot
);
case
16
:
EXTRACT_DIGIT
(
s
,
x
,
1000000000000000ULL
,
dot
);
case
15
:
EXTRACT_DIGIT
(
s
,
x
,
100000000000000ULL
,
dot
);
case
14
:
EXTRACT_DIGIT
(
s
,
x
,
10000000000000ULL
,
dot
);
case
13
:
EXTRACT_DIGIT
(
s
,
x
,
1000000000000ULL
,
dot
);
case
12
:
EXTRACT_DIGIT
(
s
,
x
,
100000000000ULL
,
dot
);
case
11
:
EXTRACT_DIGIT
(
s
,
x
,
10000000000ULL
,
dot
);
#endif
case
10
:
EXTRACT_DIGIT
(
s
,
x
,
1000000000UL
,
dot
);
case
9
:
EXTRACT_DIGIT
(
s
,
x
,
100000000UL
,
dot
);
case
8
:
EXTRACT_DIGIT
(
s
,
x
,
10000000UL
,
dot
);
case
7
:
EXTRACT_DIGIT
(
s
,
x
,
1000000UL
,
dot
);
case
6
:
EXTRACT_DIGIT
(
s
,
x
,
100000UL
,
dot
);
case
5
:
EXTRACT_DIGIT
(
s
,
x
,
10000UL
,
dot
);
case
4
:
EXTRACT_DIGIT
(
s
,
x
,
1000UL
,
dot
);
case
3
:
EXTRACT_DIGIT
(
s
,
x
,
100UL
,
dot
);
case
2
:
EXTRACT_DIGIT
(
s
,
x
,
10UL
,
dot
);
default:
if
(
s
==
dot
)
*
s
++
=
'.'
;
*
s
++
=
'0'
+
(
char
)
x
;
}
case
10
:
EXTRACT_DIGIT
(
s
,
x
,
1000000000UL
,
dot
);
case
9
:
EXTRACT_DIGIT
(
s
,
x
,
100000000UL
,
dot
);
case
8
:
EXTRACT_DIGIT
(
s
,
x
,
10000000UL
,
dot
);
case
7
:
EXTRACT_DIGIT
(
s
,
x
,
1000000UL
,
dot
);
case
6
:
EXTRACT_DIGIT
(
s
,
x
,
100000UL
,
dot
);
case
5
:
EXTRACT_DIGIT
(
s
,
x
,
10000UL
,
dot
);
case
4
:
EXTRACT_DIGIT
(
s
,
x
,
1000UL
,
dot
);
case
3
:
EXTRACT_DIGIT
(
s
,
x
,
100UL
,
dot
);
case
2
:
EXTRACT_DIGIT
(
s
,
x
,
10UL
,
dot
);
default:
if
(
s
==
dot
)
*
s
++
=
'.'
;
*
s
++
=
'0'
+
(
char
)
x
;
}
*
s
=
'\0'
;
return
s
;
*
s
=
'\0'
;
return
s
;
}
/* Print exponent x to string s. Undefined for MPD_SSIZE_MIN. */
...
...
Modules/_decimal/libmpdec/mpdecimal.c
View file @
7cc5521d
...
...
@@ -6192,7 +6192,7 @@ mpd_qpowmod(mpd_t *result, const mpd_t *base, const mpd_t *exp,
mpd_qdivint
(
&
texp
,
&
texp
,
&
two
,
&
maxcontext
,
status
);
}
if
(
mpd_isspecial
(
&
texp
)
||
mpd_isspecial
(
&
tbase
)
||
mpd_isspecial
(
&
tmod
)
||
mpd_isspecial
(
result
))
{
mpd_isspecial
(
&
tmod
)
||
mpd_isspecial
(
result
))
{
/* MPD_Malloc_error */
goto
mpd_errors
;
}
...
...
Modules/_decimal/libmpdec/mpdecimal.h
View file @
7cc5521d
...
...
@@ -749,14 +749,14 @@ EXTINLINE void mpd_copy_flags(mpd_t *result, const mpd_t *a);
/******************************************************************************/
#define mpd_err_fatal(...) \
do {fprintf(stderr, "%s:%d: error: ", __FILE__, __LINE__); \
fprintf(stderr, __VA_ARGS__); fputc('\n', stderr);
\
exit(1);
\
} while (0)
do {fprintf(stderr, "%s:%d: error: ", __FILE__, __LINE__); \
fprintf(stderr, __VA_ARGS__); fputc('\n', stderr);
\
exit(1);
\
} while (0)
#define mpd_err_warn(...) \
do {fprintf(stderr, "%s:%d: warning: ", __FILE__, __LINE__); \
fprintf(stderr, __VA_ARGS__); fputc('\n', stderr);
\
} while (0)
do {fprintf(stderr, "%s:%d: warning: ", __FILE__, __LINE__); \
fprintf(stderr, __VA_ARGS__); fputc('\n', stderr);
\
} while (0)
/******************************************************************************/
...
...
Modules/_decimal/libmpdec/typearith.h
View file @
7cc5521d
...
...
@@ -207,10 +207,10 @@ _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
{
mpd_uint_t
h
,
l
;
asm
(
"mulq %3
\n\t
"
:
"=d"
(
h
),
"=a"
(
l
)
:
"%a"
(
a
),
"rm"
(
b
)
:
"cc"
asm
(
"mulq %3
\n\t
"
:
"=d"
(
h
),
"=a"
(
l
)
:
"%a"
(
a
),
"rm"
(
b
)
:
"cc"
);
*
hi
=
h
;
...
...
@@ -223,10 +223,10 @@ _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
{
mpd_uint_t
qq
,
rr
;
asm
(
"divq %4
\n\t
"
:
"=a"
(
qq
),
"=d"
(
rr
)
:
"a"
(
lo
),
"d"
(
hi
),
"rm"
(
d
)
:
"cc"
asm
(
"divq %4
\n\t
"
:
"=a"
(
qq
),
"=d"
(
rr
)
:
"a"
(
lo
),
"d"
(
hi
),
"rm"
(
d
)
:
"cc"
);
*
q
=
qq
;
...
...
@@ -464,10 +464,10 @@ _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
{
mpd_uint_t
h
,
l
;
asm
(
"mull %3
\n\t
"
:
"=d"
(
h
),
"=a"
(
l
)
:
"%a"
(
a
),
"rm"
(
b
)
:
"cc"
asm
(
"mull %3
\n\t
"
:
"=d"
(
h
),
"=a"
(
l
)
:
"%a"
(
a
),
"rm"
(
b
)
:
"cc"
);
*
hi
=
h
;
...
...
@@ -480,10 +480,10 @@ _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
{
mpd_uint_t
qq
,
rr
;
asm
(
"divl %4
\n\t
"
:
"=a"
(
qq
),
"=d"
(
rr
)
:
"a"
(
lo
),
"d"
(
hi
),
"rm"
(
d
)
:
"cc"
asm
(
"divl %4
\n\t
"
:
"=a"
(
qq
),
"=d"
(
rr
)
:
"a"
(
lo
),
"d"
(
hi
),
"rm"
(
d
)
:
"cc"
);
*
q
=
qq
;
...
...
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