diff options
Diffstat (limited to 'Objects')
50 files changed, 8698 insertions, 6046 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c index 2d4f2e1..2f887aa 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -693,48 +693,37 @@ PyBuffer_Release(Py_buffer *view) PyObject * PyObject_Format(PyObject *obj, PyObject *format_spec) { - static PyObject * str__format__ = NULL; PyObject *meth; PyObject *empty = NULL; PyObject *result = NULL; - - /* Initialize cached value */ - if (str__format__ == NULL) { - /* Initialize static variable needed by _PyType_Lookup */ - str__format__ = PyUnicode_FromString("__format__"); - if (str__format__ == NULL) - goto done; - } + static PyObject *format_cache = NULL; /* If no format_spec is provided, use an empty string */ if (format_spec == NULL) { - empty = PyUnicode_FromUnicode(NULL, 0); - format_spec = empty; + empty = PyUnicode_FromUnicode(NULL, 0); + format_spec = empty; } - /* Make sure the type is initialized. float gets initialized late */ - if (Py_TYPE(obj)->tp_dict == NULL) - if (PyType_Ready(Py_TYPE(obj)) < 0) - goto done; - /* Find the (unbound!) __format__ method (a borrowed reference) */ - meth = _PyType_Lookup(Py_TYPE(obj), str__format__); + meth = _PyObject_LookupSpecial(obj, "__format__", &format_cache); if (meth == NULL) { - PyErr_Format(PyExc_TypeError, - "Type %.100s doesn't define __format__", - Py_TYPE(obj)->tp_name); + if (!PyErr_Occurred()) + PyErr_Format(PyExc_TypeError, + "Type %.100s doesn't define __format__", + Py_TYPE(obj)->tp_name); goto done; } - /* And call it, binding it to the value */ - result = PyObject_CallFunctionObjArgs(meth, obj, format_spec, NULL); + /* And call it. */ + result = PyObject_CallFunctionObjArgs(meth, format_spec, NULL); + Py_DECREF(meth); if (result && !PyUnicode_Check(result)) { - PyErr_SetString(PyExc_TypeError, - "__format__ method did not return string"); - Py_DECREF(result); - result = NULL; - goto done; + PyErr_SetString(PyExc_TypeError, + "__format__ method did not return string"); + Py_DECREF(result); + result = NULL; + goto done; } done: @@ -1453,7 +1442,7 @@ PyNumber_ToBase(PyObject *n, int base) int PySequence_Check(PyObject *s) { - if (PyObject_IsInstance(s, (PyObject *)&PyDict_Type)) + if (PyDict_Check(s)) return 0; return s != NULL && s->ob_type->tp_as_sequence && s->ob_type->tp_as_sequence->sq_item != NULL; @@ -2322,15 +2311,7 @@ objargs_mktuple(va_list va) va_list countva; PyObject *result, *tmp; -#ifdef VA_LIST_IS_ARRAY - memcpy(countva, va, sizeof(va_list)); -#else -#ifdef __va_copy - __va_copy(countva, va); -#else - countva = va; -#endif -#endif + Py_VA_COPY(countva, va); while (((PyObject *)va_arg(countva, PyObject *)) != NULL) ++n; @@ -2519,7 +2500,10 @@ recursive_isinstance(PyObject *inst, PyObject *cls) if (retval == 0) { PyObject *c = PyObject_GetAttr(inst, __class__); if (c == NULL) { - PyErr_Clear(); + if (PyErr_ExceptionMatches(PyExc_AttributeError)) + PyErr_Clear(); + else + retval = -1; } else { if (c != (PyObject *)(inst->ob_type) && @@ -2537,8 +2521,10 @@ recursive_isinstance(PyObject *inst, PyObject *cls) return -1; icls = PyObject_GetAttr(inst, __class__); if (icls == NULL) { - PyErr_Clear(); - retval = 0; + if (PyErr_ExceptionMatches(PyExc_AttributeError)) + PyErr_Clear(); + else + retval = -1; } else { retval = abstract_issubclass(icls, cls); @@ -2721,3 +2707,66 @@ PyIter_Next(PyObject *iter) PyErr_Clear(); return result; } + + +/* + * Flatten a sequence of bytes() objects into a C array of + * NULL terminated string pointers with a NULL char* terminating the array. + * (ie: an argv or env list) + * + * Memory allocated for the returned list is allocated using malloc() and MUST + * be freed by the caller using a free() loop or _Py_FreeCharPArray(). + */ +char *const * +_PySequence_BytesToCharpArray(PyObject* self) +{ + char **array; + Py_ssize_t i, argc; + PyObject *item = NULL; + + argc = PySequence_Size(self); + if (argc == -1) + return NULL; + + array = malloc((argc + 1) * sizeof(char *)); + if (array == NULL) { + PyErr_NoMemory(); + return NULL; + } + for (i = 0; i < argc; ++i) { + char *data; + item = PySequence_GetItem(self, i); + data = PyBytes_AsString(item); + if (data == NULL) { + /* NULL terminate before freeing. */ + array[i] = NULL; + goto fail; + } + array[i] = strdup(data); + if (!array[i]) { + PyErr_NoMemory(); + goto fail; + } + Py_DECREF(item); + } + array[argc] = NULL; + + return array; + +fail: + Py_XDECREF(item); + _Py_FreeCharPArray(array); + return NULL; +} + + +/* Free's a NULL terminated char** array of C strings. */ +void +_Py_FreeCharPArray(char *const array[]) +{ + Py_ssize_t i; + for (i = 0; array[i] != NULL; ++i) { + free(array[i]); + } + free((void*)array); +} diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 27affb5..7a74104 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -5,24 +5,16 @@ #include "structmember.h" #include "bytes_methods.h" -static PyByteArrayObject *nullbytes = NULL; char _PyByteArray_empty_string[] = ""; void PyByteArray_Fini(void) { - Py_CLEAR(nullbytes); } int PyByteArray_Init(void) { - nullbytes = PyObject_New(PyByteArrayObject, &PyByteArray_Type); - if (nullbytes == NULL) - return 0; - nullbytes->ob_bytes = NULL; - Py_SIZE(nullbytes) = nullbytes->ob_alloc = 0; - nullbytes->ob_exports = 0; return 1; } @@ -41,6 +33,7 @@ _getbytevalue(PyObject* arg, int *value) PyObject *index = PyNumber_Index(arg); if (index == NULL) { PyErr_Format(PyExc_TypeError, "an integer is required"); + *value = -1; return 0; } face_value = PyLong_AsLong(index); @@ -50,6 +43,7 @@ _getbytevalue(PyObject* arg, int *value) if (face_value < 0 || face_value >= 256) { /* this includes the OverflowError in case the long is too large */ PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); + *value = -1; return 0; } @@ -316,9 +310,9 @@ bytearray_repeat(PyByteArrayObject *self, Py_ssize_t count) if (count < 0) count = 0; mysize = Py_SIZE(self); - size = mysize * count; - if (count != 0 && size / count != mysize) + if (count > 0 && mysize > PY_SSIZE_T_MAX / count) return PyErr_NoMemory(); + size = mysize * count; result = (PyByteArrayObject *)PyByteArray_FromStringAndSize(NULL, size); if (result != NULL && size != 0) { if (mysize == 1) @@ -341,9 +335,9 @@ bytearray_irepeat(PyByteArrayObject *self, Py_ssize_t count) if (count < 0) count = 0; mysize = Py_SIZE(self); - size = mysize * count; - if (count != 0 && size / count != mysize) + if (count > 0 && mysize > PY_SSIZE_T_MAX / count) return PyErr_NoMemory(); + size = mysize * count; if (size < self->ob_alloc) { Py_SIZE(self) = size; self->ob_bytes[Py_SIZE(self)] = '\0'; /* Trailing null byte */ @@ -395,7 +389,7 @@ bytearray_subscript(PyByteArrayObject *self, PyObject *index) } else if (PySlice_Check(index)) { Py_ssize_t start, stop, step, slicelength, cur, i; - if (PySlice_GetIndicesEx((PySliceObject *)index, + if (PySlice_GetIndicesEx(index, PyByteArray_GET_SIZE(self), &start, &stop, &step, &slicelength) < 0) { return NULL; @@ -579,7 +573,7 @@ bytearray_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *valu } } else if (PySlice_Check(index)) { - if (PySlice_GetIndicesEx((PySliceObject *)index, + if (PySlice_GetIndicesEx(index, PyByteArray_GET_SIZE(self), &start, &stop, &step, &slicelen) < 0) { return -1; @@ -655,6 +649,11 @@ bytearray_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *valu if (!_canresize(self)) return -1; + + if (slicelen == 0) + /* Nothing to do here. */ + return 0; + if (step < 0) { stop = start + 1; start = stop + step * (slicelen - 1) - 1; @@ -671,7 +670,7 @@ bytearray_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *valu self->ob_bytes + cur + 1, lim); } /* Move the tail of the bytes, in one chunk */ - cur = start + slicelen*step; + cur = start + (size_t)slicelen*step; if (cur < (size_t)PyByteArray_GET_SIZE(self)) { memmove(self->ob_bytes + cur - slicelen, self->ob_bytes + cur, @@ -685,7 +684,8 @@ bytearray_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *valu } else { /* Assign slice */ - Py_ssize_t cur, i; + Py_ssize_t i; + size_t cur; if (needed != slicelen) { PyErr_Format(PyExc_ValueError, @@ -1038,19 +1038,19 @@ bytearray_dealloc(PyByteArrayObject *self) /* Methods */ #define STRINGLIB_CHAR char -#define STRINGLIB_CMP memcmp #define STRINGLIB_LEN PyByteArray_GET_SIZE #define STRINGLIB_STR PyByteArray_AS_STRING #define STRINGLIB_NEW PyByteArray_FromStringAndSize -#define STRINGLIB_EMPTY nullbytes +#define STRINGLIB_ISSPACE Py_ISSPACE +#define STRINGLIB_ISLINEBREAK(x) ((x == '\n') || (x == '\r')) #define STRINGLIB_CHECK_EXACT PyByteArray_CheckExact #define STRINGLIB_MUTABLE 1 -#define FROM_BYTEARRAY 1 #include "stringlib/fastsearch.h" #include "stringlib/count.h" #include "stringlib/find.h" #include "stringlib/partition.h" +#include "stringlib/split.h" #include "stringlib/ctype.h" #include "stringlib/transmogrify.h" @@ -1058,21 +1058,20 @@ bytearray_dealloc(PyByteArrayObject *self) /* The following Py_LOCAL_INLINE and Py_LOCAL functions were copied from the old char* style string object. */ -Py_LOCAL_INLINE(void) -_adjust_indices(Py_ssize_t *start, Py_ssize_t *end, Py_ssize_t len) -{ - if (*end > len) - *end = len; - else if (*end < 0) - *end += len; - if (*end < 0) - *end = 0; - if (*start < 0) - *start += len; - if (*start < 0) - *start = 0; -} - +/* helper macro to fixup start/end slice values */ +#define ADJUST_INDICES(start, end, len) \ + if (end > len) \ + end = len; \ + else if (end < 0) { \ + end += len; \ + if (end < 0) \ + end = 0; \ + } \ + if (start < 0) { \ + start += len; \ + if (start < 0) \ + start = 0; \ + } Py_LOCAL_INLINE(Py_ssize_t) bytearray_find_internal(PyByteArrayObject *self, PyObject *args, int dir) @@ -1139,10 +1138,10 @@ bytearray_count(PyByteArrayObject *self, PyObject *args) if (_getbuffer(sub_obj, &vsub) < 0) return NULL; - _adjust_indices(&start, &end, PyByteArray_GET_SIZE(self)); + ADJUST_INDICES(start, end, PyByteArray_GET_SIZE(self)); count_obj = PyLong_FromSsize_t( - stringlib_count(str + start, end - start, vsub.buf, vsub.len) + stringlib_count(str + start, end - start, vsub.buf, vsub.len, PY_SSIZE_T_MAX) ); PyBuffer_Release(&vsub); return count_obj; @@ -1250,7 +1249,7 @@ _bytearray_tailmatch(PyByteArrayObject *self, PyObject *substr, Py_ssize_t start if (_getbuffer(substr, &vsubstr) < 0) return -1; - _adjust_indices(&start, &end, len); + ADJUST_INDICES(start, end, len); if (direction < 0) { /* startswith */ @@ -1468,20 +1467,11 @@ bytearray_maketrans(PyObject *null, PyObject *args) } -#define FORWARD 1 -#define REVERSE -1 - /* find and count characters and substrings */ #define findchar(target, target_len, c) \ ((char *)memchr((const void *)(target), c, target_len)) -/* Don't call if length < 2 */ -#define Py_STRING_MATCH(target, offset, pattern, length) \ - (target[offset] == pattern[0] && \ - target[offset+length-1] == pattern[length-1] && \ - !memcmp(target+offset+1, pattern+1, length-2) ) - /* Bytes ops must return a string, create a copy */ Py_LOCAL(PyByteArrayObject *) @@ -1509,93 +1499,6 @@ countchar(const char *target, Py_ssize_t target_len, char c, Py_ssize_t maxcount return count; } -Py_LOCAL(Py_ssize_t) -findstring(const char *target, Py_ssize_t target_len, - const char *pattern, Py_ssize_t pattern_len, - Py_ssize_t start, - Py_ssize_t end, - int direction) -{ - if (start < 0) { - start += target_len; - if (start < 0) - start = 0; - } - if (end > target_len) { - end = target_len; - } else if (end < 0) { - end += target_len; - if (end < 0) - end = 0; - } - - /* zero-length substrings always match at the first attempt */ - if (pattern_len == 0) - return (direction > 0) ? start : end; - - end -= pattern_len; - - if (direction < 0) { - for (; end >= start; end--) - if (Py_STRING_MATCH(target, end, pattern, pattern_len)) - return end; - } else { - for (; start <= end; start++) - if (Py_STRING_MATCH(target, start, pattern, pattern_len)) - return start; - } - return -1; -} - -Py_LOCAL_INLINE(Py_ssize_t) -countstring(const char *target, Py_ssize_t target_len, - const char *pattern, Py_ssize_t pattern_len, - Py_ssize_t start, - Py_ssize_t end, - int direction, Py_ssize_t maxcount) -{ - Py_ssize_t count=0; - - if (start < 0) { - start += target_len; - if (start < 0) - start = 0; - } - if (end > target_len) { - end = target_len; - } else if (end < 0) { - end += target_len; - if (end < 0) - end = 0; - } - - /* zero-length substrings match everywhere */ - if (pattern_len == 0 || maxcount == 0) { - if (target_len+1 < maxcount) - return target_len+1; - return maxcount; - } - - end -= pattern_len; - if (direction < 0) { - for (; (end >= start); end--) - if (Py_STRING_MATCH(target, end, pattern, pattern_len)) { - count++; - if (--maxcount <= 0) break; - end -= pattern_len-1; - } - } else { - for (; (start <= end); start++) - if (Py_STRING_MATCH(target, start, pattern, pattern_len)) { - count++; - if (--maxcount <= 0) - break; - start += pattern_len-1; - } - } - return count; -} - /* Algorithms for different cases of string replacement */ @@ -1607,30 +1510,28 @@ replace_interleave(PyByteArrayObject *self, { char *self_s, *result_s; Py_ssize_t self_len, result_len; - Py_ssize_t count, i, product; + Py_ssize_t count, i; PyByteArrayObject *result; self_len = PyByteArray_GET_SIZE(self); - /* 1 at the end plus 1 after every character */ - count = self_len+1; - if (maxcount < count) + /* 1 at the end plus 1 after every character; + count = min(maxcount, self_len + 1) */ + if (maxcount <= self_len) count = maxcount; + else + /* Can't overflow: self_len + 1 <= maxcount <= PY_SSIZE_T_MAX. */ + count = self_len + 1; /* Check for overflow */ /* result_len = count * to_len + self_len; */ - product = count * to_len; - if (product / to_len != count) { - PyErr_SetString(PyExc_OverflowError, - "replace string is too long"); - return NULL; - } - result_len = product + self_len; - if (result_len < 0) { + assert(count > 0); + if (to_len > (PY_SSIZE_T_MAX - self_len) / count) { PyErr_SetString(PyExc_OverflowError, "replace string is too long"); return NULL; } + result_len = count * to_len + self_len; if (! (result = (PyByteArrayObject *) PyByteArray_FromStringAndSize(NULL, result_len)) ) @@ -1717,10 +1618,9 @@ replace_delete_substring(PyByteArrayObject *self, self_len = PyByteArray_GET_SIZE(self); self_s = PyByteArray_AS_STRING(self); - count = countstring(self_s, self_len, - from_s, from_len, - 0, self_len, 1, - maxcount); + count = stringlib_count(self_s, self_len, + from_s, from_len, + maxcount); if (count == 0) { /* no matches */ @@ -1739,9 +1639,9 @@ replace_delete_substring(PyByteArrayObject *self, start = self_s; end = self_s + self_len; while (count-- > 0) { - offset = findstring(start, end-start, - from_s, from_len, - 0, end-start, FORWARD); + offset = stringlib_find(start, end-start, + from_s, from_len, + 0); if (offset == -1) break; next = start + offset; @@ -1817,9 +1717,9 @@ replace_substring_in_place(PyByteArrayObject *self, self_s = PyByteArray_AS_STRING(self); self_len = PyByteArray_GET_SIZE(self); - offset = findstring(self_s, self_len, - from_s, from_len, - 0, self_len, FORWARD); + offset = stringlib_find(self_s, self_len, + from_s, from_len, + 0); if (offset == -1) { /* No matches; return the original bytes */ return return_self(self); @@ -1839,9 +1739,9 @@ replace_substring_in_place(PyByteArrayObject *self, end = result_s + self_len; while ( --maxcount > 0) { - offset = findstring(start, end-start, - from_s, from_len, - 0, end-start, FORWARD); + offset = stringlib_find(start, end-start, + from_s, from_len, + 0); if (offset==-1) break; Py_MEMCPY(start+offset, to_s, from_len); @@ -1861,7 +1761,7 @@ replace_single_character(PyByteArrayObject *self, char *self_s, *result_s; char *start, *next, *end; Py_ssize_t self_len, result_len; - Py_ssize_t count, product; + Py_ssize_t count; PyByteArrayObject *result; self_s = PyByteArray_AS_STRING(self); @@ -1875,16 +1775,12 @@ replace_single_character(PyByteArrayObject *self, /* use the difference between current and new, hence the "-1" */ /* result_len = self_len + count * (to_len-1) */ - product = count * (to_len-1); - if (product / (to_len-1) != count) { + assert(count > 0); + if (to_len - 1 > (PY_SSIZE_T_MAX - self_len) / count) { PyErr_SetString(PyExc_OverflowError, "replace bytes is too long"); return NULL; } - result_len = self_len + product; - if (result_len < 0) { - PyErr_SetString(PyExc_OverflowError, "replace bytes is too long"); - return NULL; - } + result_len = self_len + count * (to_len - 1); if ( (result = (PyByteArrayObject *) PyByteArray_FromStringAndSize(NULL, result_len)) == NULL) @@ -1928,15 +1824,16 @@ replace_substring(PyByteArrayObject *self, char *self_s, *result_s; char *start, *next, *end; Py_ssize_t self_len, result_len; - Py_ssize_t count, offset, product; + Py_ssize_t count, offset; PyByteArrayObject *result; self_s = PyByteArray_AS_STRING(self); self_len = PyByteArray_GET_SIZE(self); - count = countstring(self_s, self_len, - from_s, from_len, - 0, self_len, FORWARD, maxcount); + count = stringlib_count(self_s, self_len, + from_s, from_len, + maxcount); + if (count == 0) { /* no matches, return unchanged */ return return_self(self); @@ -1944,16 +1841,12 @@ replace_substring(PyByteArrayObject *self, /* Check for overflow */ /* result_len = self_len + count * (to_len-from_len) */ - product = count * (to_len-from_len); - if (product / (to_len-from_len) != count) { - PyErr_SetString(PyExc_OverflowError, "replace bytes is too long"); - return NULL; - } - result_len = self_len + product; - if (result_len < 0) { + assert(count > 0); + if (to_len - from_len > (PY_SSIZE_T_MAX - self_len) / count) { PyErr_SetString(PyExc_OverflowError, "replace bytes is too long"); return NULL; } + result_len = self_len + count * (to_len - from_len); if ( (result = (PyByteArrayObject *) PyByteArray_FromStringAndSize(NULL, result_len)) == NULL) @@ -1963,9 +1856,9 @@ replace_substring(PyByteArrayObject *self, start = self_s; end = self_s + self_len; while (count-- > 0) { - offset = findstring(start, end-start, - from_s, from_len, - 0, end-start, FORWARD); + offset = stringlib_find(start, end-start, + from_s, from_len, + 0); if (offset == -1) break; next = start+offset; @@ -2094,123 +1987,6 @@ bytearray_replace(PyByteArrayObject *self, PyObject *args) return res; } - -/* Overallocate the initial list to reduce the number of reallocs for small - split sizes. Eg, "A A A A A A A A A A".split() (10 elements) has three - resizes, to sizes 4, 8, then 16. Most observed string splits are for human - text (roughly 11 words per line) and field delimited data (usually 1-10 - fields). For large strings the split algorithms are bandwidth limited - so increasing the preallocation likely will not improve things.*/ - -#define MAX_PREALLOC 12 - -/* 5 splits gives 6 elements */ -#define PREALLOC_SIZE(maxsplit) \ - (maxsplit >= MAX_PREALLOC ? MAX_PREALLOC : maxsplit+1) - -#define SPLIT_APPEND(data, left, right) \ - str = PyByteArray_FromStringAndSize((data) + (left), \ - (right) - (left)); \ - if (str == NULL) \ - goto onError; \ - if (PyList_Append(list, str)) { \ - Py_DECREF(str); \ - goto onError; \ - } \ - else \ - Py_DECREF(str); - -#define SPLIT_ADD(data, left, right) { \ - str = PyByteArray_FromStringAndSize((data) + (left), \ - (right) - (left)); \ - if (str == NULL) \ - goto onError; \ - if (count < MAX_PREALLOC) { \ - PyList_SET_ITEM(list, count, str); \ - } else { \ - if (PyList_Append(list, str)) { \ - Py_DECREF(str); \ - goto onError; \ - } \ - else \ - Py_DECREF(str); \ - } \ - count++; } - -/* Always force the list to the expected size. */ -#define FIX_PREALLOC_SIZE(list) Py_SIZE(list) = count - - -Py_LOCAL_INLINE(PyObject *) -split_char(const char *s, Py_ssize_t len, char ch, Py_ssize_t maxcount) -{ - register Py_ssize_t i, j, count = 0; - PyObject *str; - PyObject *list = PyList_New(PREALLOC_SIZE(maxcount)); - - if (list == NULL) - return NULL; - - i = j = 0; - while ((j < len) && (maxcount-- > 0)) { - for(; j < len; j++) { - /* I found that using memchr makes no difference */ - if (s[j] == ch) { - SPLIT_ADD(s, i, j); - i = j = j + 1; - break; - } - } - } - if (i <= len) { - SPLIT_ADD(s, i, len); - } - FIX_PREALLOC_SIZE(list); - return list; - - onError: - Py_DECREF(list); - return NULL; -} - - -Py_LOCAL_INLINE(PyObject *) -split_whitespace(const char *s, Py_ssize_t len, Py_ssize_t maxcount) -{ - register Py_ssize_t i, j, count = 0; - PyObject *str; - PyObject *list = PyList_New(PREALLOC_SIZE(maxcount)); - - if (list == NULL) - return NULL; - - for (i = j = 0; i < len; ) { - /* find a token */ - while (i < len && Py_ISSPACE(s[i])) - i++; - j = i; - while (i < len && !Py_ISSPACE(s[i])) - i++; - if (j < i) { - if (maxcount-- <= 0) - break; - SPLIT_ADD(s, j, i); - while (i < len && Py_ISSPACE(s[i])) - i++; - j = i; - } - } - if (j < len) { - SPLIT_ADD(s, j, len); - } - FIX_PREALLOC_SIZE(list); - return list; - - onError: - Py_DECREF(list); - return NULL; -} - PyDoc_STRVAR(split__doc__, "B.split([sep[, maxsplit]]) -> list of bytearrays\n\ \n\ @@ -2222,14 +1998,11 @@ If maxsplit is given, at most maxsplit splits are done."); static PyObject * bytearray_split(PyByteArrayObject *self, PyObject *args) { - Py_ssize_t len = PyByteArray_GET_SIZE(self), n, i, j; - Py_ssize_t maxsplit = -1, count = 0; + Py_ssize_t len = PyByteArray_GET_SIZE(self), n; + Py_ssize_t maxsplit = -1; const char *s = PyByteArray_AS_STRING(self), *sub; - PyObject *list, *str, *subobj = Py_None; + PyObject *list, *subobj = Py_None; Py_buffer vsub; -#ifdef USE_FAST - Py_ssize_t pos; -#endif if (!PyArg_ParseTuple(args, "|On:split", &subobj, &maxsplit)) return NULL; @@ -2237,86 +2010,18 @@ bytearray_split(PyByteArrayObject *self, PyObject *args) maxsplit = PY_SSIZE_T_MAX; if (subobj == Py_None) - return split_whitespace(s, len, maxsplit); + return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit); if (_getbuffer(subobj, &vsub) < 0) return NULL; sub = vsub.buf; n = vsub.len; - if (n == 0) { - PyErr_SetString(PyExc_ValueError, "empty separator"); - PyBuffer_Release(&vsub); - return NULL; - } - if (n == 1) { - list = split_char(s, len, sub[0], maxsplit); - PyBuffer_Release(&vsub); - return list; - } - - list = PyList_New(PREALLOC_SIZE(maxsplit)); - if (list == NULL) { - PyBuffer_Release(&vsub); - return NULL; - } - -#ifdef USE_FAST - i = j = 0; - while (maxsplit-- > 0) { - pos = fastsearch(s+i, len-i, sub, n, FAST_SEARCH); - if (pos < 0) - break; - j = i+pos; - SPLIT_ADD(s, i, j); - i = j + n; - } -#else - i = j = 0; - while ((j+n <= len) && (maxsplit-- > 0)) { - for (; j+n <= len; j++) { - if (Py_STRING_MATCH(s, j, sub, n)) { - SPLIT_ADD(s, i, j); - i = j = j + n; - break; - } - } - } -#endif - SPLIT_ADD(s, i, len); - FIX_PREALLOC_SIZE(list); + list = stringlib_split( + (PyObject*) self, s, len, sub, n, maxsplit + ); PyBuffer_Release(&vsub); return list; - - onError: - Py_DECREF(list); - PyBuffer_Release(&vsub); - return NULL; -} - -/* stringlib's partition shares nullbytes in some cases. - undo this, we don't want the nullbytes to be shared. */ -static PyObject * -make_nullbytes_unique(PyObject *result) -{ - if (result != NULL) { - int i; - assert(PyTuple_Check(result)); - assert(PyTuple_GET_SIZE(result) == 3); - for (i = 0; i < 3; i++) { - if (PyTuple_GET_ITEM(result, i) == (PyObject *)nullbytes) { - PyObject *new = PyByteArray_FromStringAndSize(NULL, 0); - if (new == NULL) { - Py_DECREF(result); - result = NULL; - break; - } - Py_DECREF(nullbytes); - PyTuple_SET_ITEM(result, i, new); - } - } - } - return result; } PyDoc_STRVAR(partition__doc__, @@ -2343,7 +2048,7 @@ bytearray_partition(PyByteArrayObject *self, PyObject *sep_obj) ); Py_DECREF(bytesep); - return make_nullbytes_unique(result); + return result; } PyDoc_STRVAR(rpartition__doc__, @@ -2371,81 +2076,7 @@ bytearray_rpartition(PyByteArrayObject *self, PyObject *sep_obj) ); Py_DECREF(bytesep); - return make_nullbytes_unique(result); -} - -Py_LOCAL_INLINE(PyObject *) -rsplit_char(const char *s, Py_ssize_t len, char ch, Py_ssize_t maxcount) -{ - register Py_ssize_t i, j, count=0; - PyObject *str; - PyObject *list = PyList_New(PREALLOC_SIZE(maxcount)); - - if (list == NULL) - return NULL; - - i = j = len - 1; - while ((i >= 0) && (maxcount-- > 0)) { - for (; i >= 0; i--) { - if (s[i] == ch) { - SPLIT_ADD(s, i + 1, j + 1); - j = i = i - 1; - break; - } - } - } - if (j >= -1) { - SPLIT_ADD(s, 0, j + 1); - } - FIX_PREALLOC_SIZE(list); - if (PyList_Reverse(list) < 0) - goto onError; - - return list; - - onError: - Py_DECREF(list); - return NULL; -} - -Py_LOCAL_INLINE(PyObject *) -rsplit_whitespace(const char *s, Py_ssize_t len, Py_ssize_t maxcount) -{ - register Py_ssize_t i, j, count = 0; - PyObject *str; - PyObject *list = PyList_New(PREALLOC_SIZE(maxcount)); - - if (list == NULL) - return NULL; - - for (i = j = len - 1; i >= 0; ) { - /* find a token */ - while (i >= 0 && Py_ISSPACE(s[i])) - i--; - j = i; - while (i >= 0 && !Py_ISSPACE(s[i])) - i--; - if (j > i) { - if (maxcount-- <= 0) - break; - SPLIT_ADD(s, i + 1, j + 1); - while (i >= 0 && Py_ISSPACE(s[i])) - i--; - j = i; - } - } - if (j >= 0) { - SPLIT_ADD(s, 0, j + 1); - } - FIX_PREALLOC_SIZE(list); - if (PyList_Reverse(list) < 0) - goto onError; - - return list; - - onError: - Py_DECREF(list); - return NULL; + return result; } PyDoc_STRVAR(rsplit__doc__, @@ -2460,10 +2091,10 @@ If maxsplit is given, at most maxsplit splits are done."); static PyObject * bytearray_rsplit(PyByteArrayObject *self, PyObject *args) { - Py_ssize_t len = PyByteArray_GET_SIZE(self), n, i, j; - Py_ssize_t maxsplit = -1, count = 0; + Py_ssize_t len = PyByteArray_GET_SIZE(self), n; + Py_ssize_t maxsplit = -1; const char *s = PyByteArray_AS_STRING(self), *sub; - PyObject *list, *str, *subobj = Py_None; + PyObject *list, *subobj = Py_None; Py_buffer vsub; if (!PyArg_ParseTuple(args, "|On:rsplit", &subobj, &maxsplit)) @@ -2472,54 +2103,18 @@ bytearray_rsplit(PyByteArrayObject *self, PyObject *args) maxsplit = PY_SSIZE_T_MAX; if (subobj == Py_None) - return rsplit_whitespace(s, len, maxsplit); + return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit); if (_getbuffer(subobj, &vsub) < 0) return NULL; sub = vsub.buf; n = vsub.len; - if (n == 0) { - PyErr_SetString(PyExc_ValueError, "empty separator"); - PyBuffer_Release(&vsub); - return NULL; - } - else if (n == 1) { - list = rsplit_char(s, len, sub[0], maxsplit); - PyBuffer_Release(&vsub); - return list; - } - - list = PyList_New(PREALLOC_SIZE(maxsplit)); - if (list == NULL) { - PyBuffer_Release(&vsub); - return NULL; - } - - j = len; - i = j - n; - - while ( (i >= 0) && (maxsplit-- > 0) ) { - for (; i>=0; i--) { - if (Py_STRING_MATCH(s, i, sub, n)) { - SPLIT_ADD(s, i + n, j); - j = i; - i -= n; - break; - } - } - } - SPLIT_ADD(s, 0, j); - FIX_PREALLOC_SIZE(list); - if (PyList_Reverse(list) < 0) - goto onError; + list = stringlib_rsplit( + (PyObject*) self, s, len, sub, n, maxsplit + ); PyBuffer_Release(&vsub); return list; - -onError: - Py_DECREF(list); - PyBuffer_Release(&vsub); - return NULL; } PyDoc_STRVAR(reverse__doc__, @@ -2695,8 +2290,8 @@ bytearray_pop(PyByteArrayObject *self, PyObject *args) return NULL; if (n == 0) { - PyErr_SetString(PyExc_OverflowError, - "cannot pop an empty bytearray"); + PyErr_SetString(PyExc_IndexError, + "pop from empty bytearray"); return NULL; } if (where < 0) @@ -2875,22 +2470,23 @@ bytearray_rstrip(PyByteArrayObject *self, PyObject *args) } PyDoc_STRVAR(decode_doc, -"B.decode([encoding[, errors]]) -> str\n\ +"B.decode(encoding='utf-8', errors='strict') -> str\n\ \n\ -Decode B using the codec registered for encoding. encoding defaults\n\ -to the default encoding. errors may be given to set a different error\n\ +Decode B using the codec registered for encoding. Default encoding\n\ +is 'utf-8'. errors may be given to set a different error\n\ handling scheme. Default is 'strict' meaning that encoding errors raise\n\ a UnicodeDecodeError. Other possible values are 'ignore' and 'replace'\n\ as well as any other name registered with codecs.register_error that is\n\ able to handle UnicodeDecodeErrors."); static PyObject * -bytearray_decode(PyObject *self, PyObject *args) +bytearray_decode(PyObject *self, PyObject *args, PyObject *kwargs) { const char *encoding = NULL; const char *errors = NULL; + static char *kwlist[] = {"encoding", "errors", 0}; - if (!PyArg_ParseTuple(args, "|ss:decode", &encoding, &errors)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss:decode", kwlist, &encoding, &errors)) return NULL; if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); @@ -2984,6 +2580,27 @@ bytearray_join(PyByteArrayObject *self, PyObject *it) return NULL; } +PyDoc_STRVAR(splitlines__doc__, +"B.splitlines([keepends]) -> list of lines\n\ +\n\ +Return a list of the lines in B, breaking at line boundaries.\n\ +Line breaks are not included in the resulting list unless keepends\n\ +is given and true."); + +static PyObject* +bytearray_splitlines(PyObject *self, PyObject *args) +{ + int keepends = 0; + + if (!PyArg_ParseTuple(args, "|i:splitlines", &keepends)) + return NULL; + + return stringlib_splitlines( + (PyObject*) self, PyByteArray_AS_STRING(self), + PyByteArray_GET_SIZE(self), keepends + ); +} + PyDoc_STRVAR(fromhex_doc, "bytearray.fromhex(string) -> bytearray (static method)\n\ \n\ @@ -3120,7 +2737,7 @@ bytearray_methods[] = { _Py_capitalize__doc__}, {"center", (PyCFunction)stringlib_center, METH_VARARGS, center__doc__}, {"count", (PyCFunction)bytearray_count, METH_VARARGS, count__doc__}, - {"decode", (PyCFunction)bytearray_decode, METH_VARARGS, decode_doc}, + {"decode", (PyCFunction)bytearray_decode, METH_VARARGS | METH_KEYWORDS, decode_doc}, {"endswith", (PyCFunction)bytearray_endswith, METH_VARARGS, endswith__doc__}, {"expandtabs", (PyCFunction)stringlib_expandtabs, METH_VARARGS, expandtabs__doc__}, @@ -3162,7 +2779,7 @@ bytearray_methods[] = { {"rsplit", (PyCFunction)bytearray_rsplit, METH_VARARGS, rsplit__doc__}, {"rstrip", (PyCFunction)bytearray_rstrip, METH_VARARGS, rstrip__doc__}, {"split", (PyCFunction)bytearray_split, METH_VARARGS, split__doc__}, - {"splitlines", (PyCFunction)stringlib_splitlines, METH_VARARGS, + {"splitlines", (PyCFunction)bytearray_splitlines, METH_VARARGS, splitlines__doc__}, {"startswith", (PyCFunction)bytearray_startswith, METH_VARARGS , startswith__doc__}, diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index f2ee131..38458ef 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -56,7 +56,7 @@ static PyBytesObject *nullstring; If `str' is NULL then PyBytes_FromStringAndSize() will allocate `size+1' bytes (setting the last byte to the null terminating character) and you can fill in the data yourself. If `str' is non-NULL then the resulting - PyString object must be treated as immutable and you must not fill in nor + PyBytes object must be treated as immutable and you must not fill in nor alter the data yourself, since the strings may be shared. The PyObject member `op->ob_size', which denotes the number of "extra @@ -173,20 +173,12 @@ PyBytes_FromFormatV(const char *format, va_list vargs) char *s; PyObject* string; -#ifdef VA_LIST_IS_ARRAY - Py_MEMCPY(count, vargs, sizeof(va_list)); -#else -#ifdef __va_copy - __va_copy(count, vargs); -#else - count = vargs; -#endif -#endif + Py_VA_COPY(count, vargs); /* step 1: figure out how large a buffer we need */ for (f = format; *f; f++) { if (*f == '%') { const char* p = f; - while (*++f && *f != '%' && !ISALPHA(*f)) + while (*++f && *f != '%' && !Py_ISALPHA(*f)) ; /* skip the 'l' or 'z' in {%ld, %zd, %lu, %zu} since @@ -255,15 +247,15 @@ PyBytes_FromFormatV(const char *format, va_list vargs) /* parse the width.precision part (we're only interested in the precision value, if any) */ n = 0; - while (ISDIGIT(*f)) + while (Py_ISDIGIT(*f)) n = (n*10) + *f++ - '0'; if (*f == '.') { f++; n = 0; - while (ISDIGIT(*f)) + while (Py_ISDIGIT(*f)) n = (n*10) + *f++ - '0'; } - while (*f && *f != '%' && !ISALPHA(*f)) + while (*f && *f != '%' && !Py_ISALPHA(*f)) f++; /* handle the long flag, but only for %ld and %lu. others can be added when necessary. */ @@ -454,22 +446,22 @@ PyObject *PyBytes_DecodeEscape(const char *s, *p++ = c; break; case 'x': - if (s+1 < end && ISXDIGIT(s[0]) && ISXDIGIT(s[1])) { + if (s+1 < end && Py_ISXDIGIT(s[0]) && Py_ISXDIGIT(s[1])) { unsigned int x = 0; c = Py_CHARMASK(*s); s++; - if (ISDIGIT(c)) + if (Py_ISDIGIT(c)) x = c - '0'; - else if (ISLOWER(c)) + else if (Py_ISLOWER(c)) x = 10 + c - 'a'; else x = 10 + c - 'A'; x = x << 4; c = Py_CHARMASK(*s); s++; - if (ISDIGIT(c)) + if (Py_ISDIGIT(c)) x += c - '0'; - else if (ISLOWER(c)) + else if (Py_ISLOWER(c)) x += 10 + c - 'a'; else x += 10 + c - 'A'; @@ -563,29 +555,15 @@ PyBytes_AsStringAndSize(register PyObject *obj, /* Methods */ #include "stringlib/stringdefs.h" -#define STRINGLIB_CHAR char - -#define STRINGLIB_CMP memcmp -#define STRINGLIB_LEN PyBytes_GET_SIZE -#define STRINGLIB_NEW PyBytes_FromStringAndSize -#define STRINGLIB_STR PyBytes_AS_STRING -/* #define STRINGLIB_WANT_CONTAINS_OBJ 1 */ - -#define STRINGLIB_EMPTY nullstring -#define STRINGLIB_CHECK_EXACT PyBytes_CheckExact -#define STRINGLIB_MUTABLE 0 #include "stringlib/fastsearch.h" - #include "stringlib/count.h" #include "stringlib/find.h" #include "stringlib/partition.h" +#include "stringlib/split.h" #include "stringlib/ctype.h" -#include "stringlib/transmogrify.h" -#define _Py_InsertThousandsGrouping _PyBytes_InsertThousandsGrouping -#define _Py_InsertThousandsGroupingLocale _PyBytes_InsertThousandsGroupingLocale -#include "stringlib/localeutil.h" +#include "stringlib/transmogrify.h" PyObject * PyBytes_Repr(PyObject *obj, int smartquotes) @@ -593,13 +571,14 @@ PyBytes_Repr(PyObject *obj, int smartquotes) static const char *hexdigits = "0123456789abcdef"; register PyBytesObject* op = (PyBytesObject*) obj; Py_ssize_t length = Py_SIZE(op); - size_t newsize = 3 + 4 * length; + size_t newsize; PyObject *v; - if (newsize > PY_SSIZE_T_MAX || (newsize-3) / 4 != length) { + if (length > (PY_SSIZE_T_MAX - 3) / 4) { PyErr_SetString(PyExc_OverflowError, "bytes object is too large to make repr"); return NULL; } + newsize = 3 + 4 * length; v = PyUnicode_FromUnicode(NULL, newsize); if (v == NULL) { return NULL; @@ -746,12 +725,12 @@ bytes_repeat(register PyBytesObject *a, register Py_ssize_t n) /* watch out for overflows: the size can overflow int, * and the # of bytes needed can overflow size_t */ - size = Py_SIZE(a) * n; - if (n && size / n != Py_SIZE(a)) { + if (n > 0 && Py_SIZE(a) > PY_SSIZE_T_MAX / n) { PyErr_SetString(PyExc_OverflowError, "repeated bytes are too long"); return NULL; } + size = Py_SIZE(a) * n; if (size == Py_SIZE(a) && PyBytes_CheckExact(a)) { Py_INCREF(a); return (PyObject *)a; @@ -889,12 +868,12 @@ bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op) return result; } -static long +static Py_hash_t bytes_hash(PyBytesObject *a) { register Py_ssize_t len; register unsigned char *p; - register long x; + register Py_hash_t x; if (a->ob_shash != -1) return a->ob_shash; @@ -932,7 +911,7 @@ bytes_subscript(PyBytesObject* self, PyObject* item) char* result_buf; PyObject* result; - if (PySlice_GetIndicesEx((PySliceObject*)item, + if (PySlice_GetIndicesEx(item, PyBytes_GET_SIZE(self), &start, &stop, &step, &slicelength) < 0) { return NULL; @@ -1014,133 +993,6 @@ static const char *stripformat[] = {"|O:lstrip", "|O:rstrip", "|O:strip"}; #define STRIPNAME(i) (stripformat[i]+3) - -/* Don't call if length < 2 */ -#define Py_STRING_MATCH(target, offset, pattern, length) \ - (target[offset] == pattern[0] && \ - target[offset+length-1] == pattern[length-1] && \ - !memcmp(target+offset+1, pattern+1, length-2) ) - - -/* Overallocate the initial list to reduce the number of reallocs for small - split sizes. Eg, "A A A A A A A A A A".split() (10 elements) has three - resizes, to sizes 4, 8, then 16. Most observed string splits are for human - text (roughly 11 words per line) and field delimited data (usually 1-10 - fields). For large strings the split algorithms are bandwidth limited - so increasing the preallocation likely will not improve things.*/ - -#define MAX_PREALLOC 12 - -/* 5 splits gives 6 elements */ -#define PREALLOC_SIZE(maxsplit) \ - (maxsplit >= MAX_PREALLOC ? MAX_PREALLOC : maxsplit+1) - -#define SPLIT_ADD(data, left, right) { \ - str = PyBytes_FromStringAndSize((data) + (left), \ - (right) - (left)); \ - if (str == NULL) \ - goto onError; \ - if (count < MAX_PREALLOC) { \ - PyList_SET_ITEM(list, count, str); \ - } else { \ - if (PyList_Append(list, str)) { \ - Py_DECREF(str); \ - goto onError; \ - } \ - else \ - Py_DECREF(str); \ - } \ - count++; } - -/* Always force the list to the expected size. */ -#define FIX_PREALLOC_SIZE(list) Py_SIZE(list) = count - -#define SKIP_SPACE(s, i, len) { while (i<len && ISSPACE(s[i])) i++; } -#define SKIP_NONSPACE(s, i, len) { while (i<len && !ISSPACE(s[i])) i++; } -#define RSKIP_SPACE(s, i) { while (i>=0 && ISSPACE(s[i])) i--; } -#define RSKIP_NONSPACE(s, i) { while (i>=0 && !ISSPACE(s[i])) i--; } - -Py_LOCAL_INLINE(PyObject *) -split_whitespace(PyBytesObject *self, Py_ssize_t len, Py_ssize_t maxsplit) -{ - const char *s = PyBytes_AS_STRING(self); - Py_ssize_t i, j, count=0; - PyObject *str; - PyObject *list = PyList_New(PREALLOC_SIZE(maxsplit)); - - if (list == NULL) - return NULL; - - i = j = 0; - - while (maxsplit-- > 0) { - SKIP_SPACE(s, i, len); - if (i==len) break; - j = i; i++; - SKIP_NONSPACE(s, i, len); - if (j == 0 && i == len && PyBytes_CheckExact(self)) { - /* No whitespace in self, so just use it as list[0] */ - Py_INCREF(self); - PyList_SET_ITEM(list, 0, (PyObject *)self); - count++; - break; - } - SPLIT_ADD(s, j, i); - } - - if (i < len) { - /* Only occurs when maxsplit was reached */ - /* Skip any remaining whitespace and copy to end of string */ - SKIP_SPACE(s, i, len); - if (i != len) - SPLIT_ADD(s, i, len); - } - FIX_PREALLOC_SIZE(list); - return list; - onError: - Py_DECREF(list); - return NULL; -} - -Py_LOCAL_INLINE(PyObject *) -split_char(PyBytesObject *self, Py_ssize_t len, char ch, Py_ssize_t maxcount) -{ - const char *s = PyBytes_AS_STRING(self); - register Py_ssize_t i, j, count=0; - PyObject *str; - PyObject *list = PyList_New(PREALLOC_SIZE(maxcount)); - - if (list == NULL) - return NULL; - - i = j = 0; - while ((j < len) && (maxcount-- > 0)) { - for(; j<len; j++) { - /* I found that using memchr makes no difference */ - if (s[j] == ch) { - SPLIT_ADD(s, i, j); - i = j = j + 1; - break; - } - } - } - if (i == 0 && count == 0 && PyBytes_CheckExact(self)) { - /* ch not in self, so just use self as list[0] */ - Py_INCREF(self); - PyList_SET_ITEM(list, 0, (PyObject *)self); - count++; - } - else if (i <= len) { - SPLIT_ADD(s, i, len); - } - FIX_PREALLOC_SIZE(list); - return list; - - onError: - Py_DECREF(list); - return NULL; -} - PyDoc_STRVAR(split__doc__, "B.split([sep[, maxsplit]]) -> list of bytes\n\ \n\ @@ -1152,74 +1004,26 @@ If maxsplit is given, at most maxsplit splits are done."); static PyObject * bytes_split(PyBytesObject *self, PyObject *args) { - Py_ssize_t len = PyBytes_GET_SIZE(self), n, i, j; - Py_ssize_t maxsplit = -1, count=0; + Py_ssize_t len = PyBytes_GET_SIZE(self), n; + Py_ssize_t maxsplit = -1; const char *s = PyBytes_AS_STRING(self), *sub; Py_buffer vsub; - PyObject *list, *str, *subobj = Py_None; -#ifdef USE_FAST - Py_ssize_t pos; -#endif + PyObject *list, *subobj = Py_None; if (!PyArg_ParseTuple(args, "|On:split", &subobj, &maxsplit)) return NULL; if (maxsplit < 0) maxsplit = PY_SSIZE_T_MAX; if (subobj == Py_None) - return split_whitespace(self, len, maxsplit); + return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit); if (_getbuffer(subobj, &vsub) < 0) return NULL; sub = vsub.buf; n = vsub.len; - if (n == 0) { - PyErr_SetString(PyExc_ValueError, "empty separator"); - PyBuffer_Release(&vsub); - return NULL; - } - else if (n == 1) { - list = split_char(self, len, sub[0], maxsplit); - PyBuffer_Release(&vsub); - return list; - } - - list = PyList_New(PREALLOC_SIZE(maxsplit)); - if (list == NULL) { - PyBuffer_Release(&vsub); - return NULL; - } - -#ifdef USE_FAST - i = j = 0; - while (maxsplit-- > 0) { - pos = fastsearch(s+i, len-i, sub, n, FAST_SEARCH); - if (pos < 0) - break; - j = i+pos; - SPLIT_ADD(s, i, j); - i = j + n; - } -#else - i = j = 0; - while ((j+n <= len) && (maxsplit-- > 0)) { - for (; j+n <= len; j++) { - if (Py_STRING_MATCH(s, j, sub, n)) { - SPLIT_ADD(s, i, j); - i = j = j + n; - break; - } - } - } -#endif - SPLIT_ADD(s, i, len); - FIX_PREALLOC_SIZE(list); + list = stringlib_split((PyObject*) self, s, len, sub, n, maxsplit); PyBuffer_Release(&vsub); return list; - - onError: - Py_DECREF(list); - PyBuffer_Release(&vsub); - return NULL; } PyDoc_STRVAR(partition__doc__, @@ -1277,90 +1081,6 @@ bytes_rpartition(PyBytesObject *self, PyObject *sep_obj) ); } -Py_LOCAL_INLINE(PyObject *) -rsplit_whitespace(PyBytesObject *self, Py_ssize_t len, Py_ssize_t maxsplit) -{ - const char *s = PyBytes_AS_STRING(self); - Py_ssize_t i, j, count=0; - PyObject *str; - PyObject *list = PyList_New(PREALLOC_SIZE(maxsplit)); - - if (list == NULL) - return NULL; - - i = j = len-1; - - while (maxsplit-- > 0) { - RSKIP_SPACE(s, i); - if (i<0) break; - j = i; i--; - RSKIP_NONSPACE(s, i); - if (j == len-1 && i < 0 && PyBytes_CheckExact(self)) { - /* No whitespace in self, so just use it as list[0] */ - Py_INCREF(self); - PyList_SET_ITEM(list, 0, (PyObject *)self); - count++; - break; - } - SPLIT_ADD(s, i + 1, j + 1); - } - if (i >= 0) { - /* Only occurs when maxsplit was reached. Skip any remaining - whitespace and copy to beginning of string. */ - RSKIP_SPACE(s, i); - if (i >= 0) - SPLIT_ADD(s, 0, i + 1); - - } - FIX_PREALLOC_SIZE(list); - if (PyList_Reverse(list) < 0) - goto onError; - return list; - onError: - Py_DECREF(list); - return NULL; -} - -Py_LOCAL_INLINE(PyObject *) -rsplit_char(PyBytesObject *self, Py_ssize_t len, char ch, Py_ssize_t maxcount) -{ - const char *s = PyBytes_AS_STRING(self); - register Py_ssize_t i, j, count=0; - PyObject *str; - PyObject *list = PyList_New(PREALLOC_SIZE(maxcount)); - - if (list == NULL) - return NULL; - - i = j = len - 1; - while ((i >= 0) && (maxcount-- > 0)) { - for (; i >= 0; i--) { - if (s[i] == ch) { - SPLIT_ADD(s, i + 1, j + 1); - j = i = i - 1; - break; - } - } - } - if (i < 0 && count == 0 && PyBytes_CheckExact(self)) { - /* ch not in self, so just use self as list[0] */ - Py_INCREF(self); - PyList_SET_ITEM(list, 0, (PyObject *)self); - count++; - } - else if (j >= -1) { - SPLIT_ADD(s, 0, j + 1); - } - FIX_PREALLOC_SIZE(list); - if (PyList_Reverse(list) < 0) - goto onError; - return list; - - onError: - Py_DECREF(list); - return NULL; -} - PyDoc_STRVAR(rsplit__doc__, "B.rsplit([sep[, maxsplit]]) -> list of bytes\n\ \n\ @@ -1374,71 +1094,28 @@ If maxsplit is given, at most maxsplit splits are done."); static PyObject * bytes_rsplit(PyBytesObject *self, PyObject *args) { - Py_ssize_t len = PyBytes_GET_SIZE(self), n, i, j; - Py_ssize_t maxsplit = -1, count=0; - const char *s, *sub; + Py_ssize_t len = PyBytes_GET_SIZE(self), n; + Py_ssize_t maxsplit = -1; + const char *s = PyBytes_AS_STRING(self), *sub; Py_buffer vsub; - PyObject *list, *str, *subobj = Py_None; + PyObject *list, *subobj = Py_None; if (!PyArg_ParseTuple(args, "|On:rsplit", &subobj, &maxsplit)) return NULL; if (maxsplit < 0) maxsplit = PY_SSIZE_T_MAX; if (subobj == Py_None) - return rsplit_whitespace(self, len, maxsplit); + return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit); if (_getbuffer(subobj, &vsub) < 0) return NULL; sub = vsub.buf; n = vsub.len; - if (n == 0) { - PyErr_SetString(PyExc_ValueError, "empty separator"); - PyBuffer_Release(&vsub); - return NULL; - } - else if (n == 1) { - list = rsplit_char(self, len, sub[0], maxsplit); - PyBuffer_Release(&vsub); - return list; - } - - list = PyList_New(PREALLOC_SIZE(maxsplit)); - if (list == NULL) { - PyBuffer_Release(&vsub); - return NULL; - } - - j = len; - i = j - n; - - s = PyBytes_AS_STRING(self); - while ( (i >= 0) && (maxsplit-- > 0) ) { - for (; i>=0; i--) { - if (Py_STRING_MATCH(s, i, sub, n)) { - SPLIT_ADD(s, i + n, j); - j = i; - i -= n; - break; - } - } - } - SPLIT_ADD(s, 0, j); - FIX_PREALLOC_SIZE(list); - if (PyList_Reverse(list) < 0) - goto onError; + list = stringlib_rsplit((PyObject*) self, s, len, sub, n, maxsplit); PyBuffer_Release(&vsub); return list; - -onError: - Py_DECREF(list); - PyBuffer_Release(&vsub); - return NULL; } -#undef SPLIT_ADD -#undef MAX_PREALLOC -#undef PREALLOC_SIZE - PyDoc_STRVAR(join__doc__, "B.join(iterable_of_bytes) -> bytes\n\ @@ -1545,20 +1222,20 @@ _PyBytes_Join(PyObject *sep, PyObject *x) return bytes_join(sep, x); } -Py_LOCAL_INLINE(void) -bytes_adjust_indices(Py_ssize_t *start, Py_ssize_t *end, Py_ssize_t len) -{ - if (*end > len) - *end = len; - else if (*end < 0) - *end += len; - if (*end < 0) - *end = 0; - if (*start < 0) - *start += len; - if (*start < 0) - *start = 0; -} +/* helper macro to fixup start/end slice values */ +#define ADJUST_INDICES(start, end, len) \ + if (end > len) \ + end = len; \ + else if (end < 0) { \ + end += len; \ + if (end < 0) \ + end = 0; \ + } \ + if (start < 0) { \ + start += len; \ + if (start < 0) \ + start = 0; \ + } Py_LOCAL_INLINE(Py_ssize_t) bytes_find_internal(PyBytesObject *self, PyObject *args, int dir) @@ -1595,7 +1272,7 @@ bytes_find_internal(PyBytesObject *self, PyObject *args, int dir) PyDoc_STRVAR(find__doc__, "B.find(sub[, start[, end]]) -> int\n\ \n\ -Return the lowest index in S where substring sub is found,\n\ +Return the lowest index in B where substring sub is found,\n\ such that sub is contained within s[start:end]. Optional\n\ arguments start and end are interpreted as in slice notation.\n\ \n\ @@ -1719,7 +1396,7 @@ do_strip(PyBytesObject *self, int striptype) i = 0; if (striptype != RIGHTSTRIP) { - while (i < len && ISSPACE(s[i])) { + while (i < len && Py_ISSPACE(s[i])) { i++; } } @@ -1728,7 +1405,7 @@ do_strip(PyBytesObject *self, int striptype) if (striptype != LEFTSTRIP) { do { j--; - } while (j >= i && ISSPACE(s[j])); + } while (j >= i && Py_ISSPACE(s[j])); j++; } @@ -1805,7 +1482,7 @@ PyDoc_STRVAR(count__doc__, "B.count(sub[, start[, end]]) -> int\n\ \n\ Return the number of non-overlapping occurrences of substring sub in\n\ -string S[start:end]. Optional arguments start and end are interpreted\n\ +string B[start:end]. Optional arguments start and end are interpreted\n\ as in slice notation."); static PyObject * @@ -1826,10 +1503,10 @@ bytes_count(PyBytesObject *self, PyObject *args) else if (PyObject_AsCharBuffer(sub_obj, &sub, &sub_len)) return NULL; - bytes_adjust_indices(&start, &end, PyBytes_GET_SIZE(self)); + ADJUST_INDICES(start, end, PyBytes_GET_SIZE(self)); return PyLong_FromSsize_t( - stringlib_count(str + start, end - start, sub, sub_len) + stringlib_count(str + start, end - start, sub, sub_len, PY_SSIZE_T_MAX) ); } @@ -1946,9 +1623,6 @@ bytes_maketrans(PyObject *null, PyObject *args) return _Py_bytes_maketrans(args); } -#define FORWARD 1 -#define REVERSE -1 - /* find and count characters and substrings */ #define findchar(target, target_len, c) \ @@ -1984,94 +1658,6 @@ countchar(const char *target, Py_ssize_t target_len, char c, Py_ssize_t maxcount return count; } -Py_LOCAL(Py_ssize_t) -findstring(const char *target, Py_ssize_t target_len, - const char *pattern, Py_ssize_t pattern_len, - Py_ssize_t start, - Py_ssize_t end, - int direction) -{ - if (start < 0) { - start += target_len; - if (start < 0) - start = 0; - } - if (end > target_len) { - end = target_len; - } else if (end < 0) { - end += target_len; - if (end < 0) - end = 0; - } - - /* zero-length substrings always match at the first attempt */ - if (pattern_len == 0) - return (direction > 0) ? start : end; - - end -= pattern_len; - - if (direction < 0) { - for (; end >= start; end--) - if (Py_STRING_MATCH(target, end, pattern, pattern_len)) - return end; - } else { - for (; start <= end; start++) - if (Py_STRING_MATCH(target, start,pattern,pattern_len)) - return start; - } - return -1; -} - -Py_LOCAL_INLINE(Py_ssize_t) -countstring(const char *target, Py_ssize_t target_len, - const char *pattern, Py_ssize_t pattern_len, - Py_ssize_t start, - Py_ssize_t end, - int direction, Py_ssize_t maxcount) -{ - Py_ssize_t count=0; - - if (start < 0) { - start += target_len; - if (start < 0) - start = 0; - } - if (end > target_len) { - end = target_len; - } else if (end < 0) { - end += target_len; - if (end < 0) - end = 0; - } - - /* zero-length substrings match everywhere */ - if (pattern_len == 0 || maxcount == 0) { - if (target_len+1 < maxcount) - return target_len+1; - return maxcount; - } - - end -= pattern_len; - if (direction < 0) { - for (; (end >= start); end--) - if (Py_STRING_MATCH(target, end,pattern,pattern_len)) { - count++; - if (--maxcount <= 0) break; - end -= pattern_len-1; - } - } else { - for (; (start <= end); start++) - if (Py_STRING_MATCH(target, start, - pattern, pattern_len)) { - count++; - if (--maxcount <= 0) - break; - start += pattern_len-1; - } - } - return count; -} - /* Algorithms for different cases of string replacement */ @@ -2083,30 +1669,28 @@ replace_interleave(PyBytesObject *self, { char *self_s, *result_s; Py_ssize_t self_len, result_len; - Py_ssize_t count, i, product; + Py_ssize_t count, i; PyBytesObject *result; self_len = PyBytes_GET_SIZE(self); - /* 1 at the end plus 1 after every character */ - count = self_len+1; - if (maxcount < count) + /* 1 at the end plus 1 after every character; + count = min(maxcount, self_len + 1) */ + if (maxcount <= self_len) count = maxcount; + else + /* Can't overflow: self_len + 1 <= maxcount <= PY_SSIZE_T_MAX. */ + count = self_len + 1; /* Check for overflow */ /* result_len = count * to_len + self_len; */ - product = count * to_len; - if (product / to_len != count) { - PyErr_SetString(PyExc_OverflowError, - "replacement bytes are too long"); - return NULL; - } - result_len = product + self_len; - if (result_len < 0) { + assert(count > 0); + if (to_len > (PY_SSIZE_T_MAX - self_len) / count) { PyErr_SetString(PyExc_OverflowError, "replacement bytes are too long"); return NULL; } + result_len = count * to_len + self_len; if (! (result = (PyBytesObject *) PyBytes_FromStringAndSize(NULL, result_len)) ) @@ -2192,10 +1776,9 @@ replace_delete_substring(PyBytesObject *self, self_len = PyBytes_GET_SIZE(self); self_s = PyBytes_AS_STRING(self); - count = countstring(self_s, self_len, - from_s, from_len, - 0, self_len, 1, - maxcount); + count = stringlib_count(self_s, self_len, + from_s, from_len, + maxcount); if (count == 0) { /* no matches */ @@ -2214,9 +1797,9 @@ replace_delete_substring(PyBytesObject *self, start = self_s; end = self_s + self_len; while (count-- > 0) { - offset = findstring(start, end-start, - from_s, from_len, - 0, end-start, FORWARD); + offset = stringlib_find(start, end-start, + from_s, from_len, + 0); if (offset == -1) break; next = start + offset; @@ -2292,9 +1875,9 @@ replace_substring_in_place(PyBytesObject *self, self_s = PyBytes_AS_STRING(self); self_len = PyBytes_GET_SIZE(self); - offset = findstring(self_s, self_len, - from_s, from_len, - 0, self_len, FORWARD); + offset = stringlib_find(self_s, self_len, + from_s, from_len, + 0); if (offset == -1) { /* No matches; return the original string */ return return_self(self); @@ -2314,9 +1897,9 @@ replace_substring_in_place(PyBytesObject *self, end = result_s + self_len; while ( --maxcount > 0) { - offset = findstring(start, end-start, - from_s, from_len, - 0, end-start, FORWARD); + offset = stringlib_find(start, end-start, + from_s, from_len, + 0); if (offset==-1) break; Py_MEMCPY(start+offset, to_s, from_len); @@ -2336,7 +1919,7 @@ replace_single_character(PyBytesObject *self, char *self_s, *result_s; char *start, *next, *end; Py_ssize_t self_len, result_len; - Py_ssize_t count, product; + Py_ssize_t count; PyBytesObject *result; self_s = PyBytes_AS_STRING(self); @@ -2350,18 +1933,13 @@ replace_single_character(PyBytesObject *self, /* use the difference between current and new, hence the "-1" */ /* result_len = self_len + count * (to_len-1) */ - product = count * (to_len-1); - if (product / (to_len-1) != count) { + assert(count > 0); + if (to_len - 1 > (PY_SSIZE_T_MAX - self_len) / count) { PyErr_SetString(PyExc_OverflowError, "replacement bytes are too long"); return NULL; } - result_len = self_len + product; - if (result_len < 0) { - PyErr_SetString(PyExc_OverflowError, - "replacment bytes are too long"); - return NULL; - } + result_len = self_len + count * (to_len - 1); if ( (result = (PyBytesObject *) PyBytes_FromStringAndSize(NULL, result_len)) == NULL) @@ -2404,15 +1982,16 @@ replace_substring(PyBytesObject *self, char *self_s, *result_s; char *start, *next, *end; Py_ssize_t self_len, result_len; - Py_ssize_t count, offset, product; + Py_ssize_t count, offset; PyBytesObject *result; self_s = PyBytes_AS_STRING(self); self_len = PyBytes_GET_SIZE(self); - count = countstring(self_s, self_len, - from_s, from_len, - 0, self_len, FORWARD, maxcount); + count = stringlib_count(self_s, self_len, + from_s, from_len, + maxcount); + if (count == 0) { /* no matches, return unchanged */ return return_self(self); @@ -2420,18 +1999,13 @@ replace_substring(PyBytesObject *self, /* Check for overflow */ /* result_len = self_len + count * (to_len-from_len) */ - product = count * (to_len-from_len); - if (product / (to_len-from_len) != count) { - PyErr_SetString(PyExc_OverflowError, - "replacement bytes are too long"); - return NULL; - } - result_len = self_len + product; - if (result_len < 0) { + assert(count > 0); + if (to_len - from_len > (PY_SSIZE_T_MAX - self_len) / count) { PyErr_SetString(PyExc_OverflowError, "replacement bytes are too long"); return NULL; } + result_len = self_len + count * (to_len-from_len); if ( (result = (PyBytesObject *) PyBytes_FromStringAndSize(NULL, result_len)) == NULL) @@ -2441,9 +2015,9 @@ replace_substring(PyBytesObject *self, start = self_s; end = self_s + self_len; while (count-- > 0) { - offset = findstring(start, end-start, - from_s, from_len, - 0, end-start, FORWARD); + offset = stringlib_find(start, end-start, + from_s, from_len, + 0); if (offset == -1) break; next = start+offset; @@ -2601,7 +2175,7 @@ _bytes_tailmatch(PyBytesObject *self, PyObject *substr, Py_ssize_t start, return -1; str = PyBytes_AS_STRING(self); - bytes_adjust_indices(&start, &end, len); + ADJUST_INDICES(start, end, len); if (direction < 0) { /* startswith */ @@ -2710,22 +2284,23 @@ bytes_endswith(PyBytesObject *self, PyObject *args) PyDoc_STRVAR(decode__doc__, -"B.decode([encoding[, errors]]) -> str\n\ +"B.decode(encoding='utf-8', errors='strict') -> str\n\ \n\ -Decode S using the codec registered for encoding. encoding defaults\n\ -to the default encoding. errors may be given to set a different error\n\ +Decode B using the codec registered for encoding. Default encoding\n\ +is 'utf-8'. errors may be given to set a different error\n\ handling scheme. Default is 'strict' meaning that encoding errors raise\n\ a UnicodeDecodeError. Other possible values are 'ignore' and 'replace'\n\ as well as any other name registerd with codecs.register_error that is\n\ able to handle UnicodeDecodeErrors."); static PyObject * -bytes_decode(PyObject *self, PyObject *args) +bytes_decode(PyObject *self, PyObject *args, PyObject *kwargs) { const char *encoding = NULL; const char *errors = NULL; + static char *kwlist[] = {"encoding", "errors", 0}; - if (!PyArg_ParseTuple(args, "|ss:decode", &encoding, &errors)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss:decode", kwlist, &encoding, &errors)) return NULL; if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); @@ -2733,6 +2308,28 @@ bytes_decode(PyObject *self, PyObject *args) } +PyDoc_STRVAR(splitlines__doc__, +"B.splitlines([keepends]) -> list of lines\n\ +\n\ +Return a list of the lines in B, breaking at line boundaries.\n\ +Line breaks are not included in the resulting list unless keepends\n\ +is given and true."); + +static PyObject* +bytes_splitlines(PyObject *self, PyObject *args) +{ + int keepends = 0; + + if (!PyArg_ParseTuple(args, "|i:splitlines", &keepends)) + return NULL; + + return stringlib_splitlines( + (PyObject*) self, PyBytes_AS_STRING(self), + PyBytes_GET_SIZE(self), keepends + ); +} + + PyDoc_STRVAR(fromhex_doc, "bytes.fromhex(string) -> bytes\n\ \n\ @@ -2745,11 +2342,11 @@ hex_digit_to_int(Py_UNICODE c) { if (c >= 128) return -1; - if (ISDIGIT(c)) + if (Py_ISDIGIT(c)) return c - '0'; else { - if (ISUPPER(c)) - c = TOLOWER(c); + if (Py_ISUPPER(c)) + c = Py_TOLOWER(c); if (c >= 'a' && c <= 'f') return c - 'a' + 10; } @@ -2815,7 +2412,7 @@ bytes_sizeof(PyBytesObject *v) static PyObject * bytes_getnewargs(PyBytesObject *v) { - return Py_BuildValue("(s#)", v->ob_sval, Py_SIZE(v)); + return Py_BuildValue("(y#)", v->ob_sval, Py_SIZE(v)); } @@ -2826,7 +2423,7 @@ bytes_methods[] = { _Py_capitalize__doc__}, {"center", (PyCFunction)stringlib_center, METH_VARARGS, center__doc__}, {"count", (PyCFunction)bytes_count, METH_VARARGS, count__doc__}, - {"decode", (PyCFunction)bytes_decode, METH_VARARGS, decode__doc__}, + {"decode", (PyCFunction)bytes_decode, METH_VARARGS | METH_KEYWORDS, decode__doc__}, {"endswith", (PyCFunction)bytes_endswith, METH_VARARGS, endswith__doc__}, {"expandtabs", (PyCFunction)stringlib_expandtabs, METH_VARARGS, @@ -2865,7 +2462,7 @@ bytes_methods[] = { {"rsplit", (PyCFunction)bytes_rsplit, METH_VARARGS, rsplit__doc__}, {"rstrip", (PyCFunction)bytes_rstrip, METH_VARARGS, rstrip__doc__}, {"split", (PyCFunction)bytes_split, METH_VARARGS, split__doc__}, - {"splitlines", (PyCFunction)stringlib_splitlines, METH_VARARGS, + {"splitlines", (PyCFunction)bytes_splitlines, METH_VARARGS, splitlines__doc__}, {"startswith", (PyCFunction)bytes_startswith, METH_VARARGS, startswith__doc__}, @@ -2892,6 +2489,7 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds) const char *encoding = NULL; const char *errors = NULL; PyObject *new = NULL; + Py_ssize_t size; static char *kwlist[] = {"source", "encoding", "errors", 0}; if (type != &PyBytes_Type) @@ -2922,28 +2520,7 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds) assert(PyBytes_Check(new)); return new; } - - /* If it's not unicode, there can't be encoding or errors */ - if (encoding != NULL || errors != NULL) { - PyErr_SetString(PyExc_TypeError, - "encoding or errors without a string argument"); - return NULL; - } - return PyObject_Bytes(x); -} - -PyObject * -PyBytes_FromObject(PyObject *x) -{ - PyObject *new, *it; - Py_ssize_t i, size; - - if (x == NULL) { - PyErr_BadInternalCall(); - return NULL; - } - - /* Is it an int? */ + /* Is it an integer? */ size = PyNumber_AsSsize_t(x, PyExc_OverflowError); if (size == -1 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) @@ -2965,6 +2542,25 @@ PyBytes_FromObject(PyObject *x) return new; } + /* If it's not unicode, there can't be encoding or errors */ + if (encoding != NULL || errors != NULL) { + PyErr_SetString(PyExc_TypeError, + "encoding or errors without a string argument"); + return NULL; + } + return PyObject_Bytes(x); +} + +PyObject * +PyBytes_FromObject(PyObject *x) +{ + PyObject *new, *it; + Py_ssize_t i, size; + + if (x == NULL) { + PyErr_BadInternalCall(); + return NULL; + } /* Use the modern buffer interface */ if (PyObject_CheckBuffer(x)) { Py_buffer view; @@ -2984,18 +2580,68 @@ PyBytes_FromObject(PyObject *x) PyBuffer_Release(&view); return NULL; } + if (PyUnicode_Check(x)) { + PyErr_SetString(PyExc_TypeError, + "cannot convert unicode object to bytes"); + return NULL; + } + + if (PyList_CheckExact(x)) { + new = PyBytes_FromStringAndSize(NULL, Py_SIZE(x)); + if (new == NULL) + return NULL; + for (i = 0; i < Py_SIZE(x); i++) { + Py_ssize_t value = PyNumber_AsSsize_t( + PyList_GET_ITEM(x, i), PyExc_ValueError); + if (value == -1 && PyErr_Occurred()) { + Py_DECREF(new); + return NULL; + } + if (value < 0 || value >= 256) { + PyErr_SetString(PyExc_ValueError, + "bytes must be in range(0, 256)"); + Py_DECREF(new); + return NULL; + } + ((PyBytesObject *)new)->ob_sval[i] = (char) value; + } + return new; + } + if (PyTuple_CheckExact(x)) { + new = PyBytes_FromStringAndSize(NULL, Py_SIZE(x)); + if (new == NULL) + return NULL; + for (i = 0; i < Py_SIZE(x); i++) { + Py_ssize_t value = PyNumber_AsSsize_t( + PyTuple_GET_ITEM(x, i), PyExc_ValueError); + if (value == -1 && PyErr_Occurred()) { + Py_DECREF(new); + return NULL; + } + if (value < 0 || value >= 256) { + PyErr_SetString(PyExc_ValueError, + "bytes must be in range(0, 256)"); + Py_DECREF(new); + return NULL; + } + ((PyBytesObject *)new)->ob_sval[i] = (char) value; + } + return new; + } /* For iterator version, create a string object and resize as needed */ - /* XXX(gb): is 64 a good value? also, optimize if length is known */ - /* XXX(guido): perhaps use Pysequence_Fast() -- I can't imagine the - input being a truly long iterator. */ - size = 64; + size = _PyObject_LengthHint(x, 64); + if (size == -1 && PyErr_Occurred()) + return NULL; + /* Allocate an extra byte to prevent PyBytes_FromStringAndSize() from + returning a shared empty bytes string. This required because we + want to call _PyBytes_Resize() the returned object, which we can + only do on bytes objects with refcount == 1. */ + size += 1; new = PyBytes_FromStringAndSize(NULL, size); if (new == NULL) return NULL; - /* XXX Optimize this if the arguments is a list, tuple */ - /* Get the iterator */ it = PyObject_GetIter(x); if (it == NULL) @@ -3029,7 +2675,7 @@ PyBytes_FromObject(PyObject *x) /* Append the byte */ if (i >= size) { - size *= 2; + size = 2 * size + 1; if (_PyBytes_Resize(&new, size) < 0) goto error; } @@ -3200,7 +2846,7 @@ _PyBytes_Resize(PyObject **pv, Py_ssize_t newsize) /* _PyBytes_FormatLong emulates the format codes d, u, o, x and X, and * the F_ALT flag, for Python's long (unbounded) ints. It's not used for * Python's regular ints. - * Return value: a new PyString*, or NULL if error. + * Return value: a new PyBytes*, or NULL if error. * . *pbuf is set to point into it, * *plen set to the # of chars following that. * Caller must decref it when done using pbuf. diff --git a/Objects/capsule.c b/Objects/capsule.c index e25af6c..acd3de6 100644 --- a/Objects/capsule.c +++ b/Objects/capsule.c @@ -298,27 +298,27 @@ Python import mechanism to link to one another.\n\ PyTypeObject PyCapsule_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - "PyCapsule", /*tp_name*/ - sizeof(PyCapsule), /*tp_basicsize*/ - 0, /*tp_itemsize*/ + "PyCapsule", /*tp_name*/ + sizeof(PyCapsule), /*tp_basicsize*/ + 0, /*tp_itemsize*/ /* methods */ capsule_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_reserved*/ capsule_repr, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - 0, /*tp_flags*/ - PyCapsule_Type__doc__ /*tp_doc*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + 0, /*tp_flags*/ + PyCapsule_Type__doc__ /*tp_doc*/ }; diff --git a/Objects/classobject.c b/Objects/classobject.c index afd4ec3..6df930f 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -263,10 +263,10 @@ method_repr(PyMethodObject *a) return result; } -static long +static Py_hash_t method_hash(PyMethodObject *a) { - long x, y; + Py_hash_t x, y; if (a->im_self == NULL) x = PyObject_Hash(Py_None); else diff --git a/Objects/cobject.c b/Objects/cobject.c deleted file mode 100644 index a692150..0000000 --- a/Objects/cobject.c +++ /dev/null @@ -1,169 +0,0 @@ - -/* Wrap void* pointers to be passed between C modules */ - -#include "Python.h" - - -/* Declarations for objects of type PyCObject */ - -typedef void (*destructor1)(void *); -typedef void (*destructor2)(void *, void*); - - -static int deprecation_exception(void) -{ - return PyErr_WarnEx(PyExc_PendingDeprecationWarning, - "The CObject API is deprecated as of Python 3.1. " - "Please convert to using the Capsule API.", 1); -} - -PyObject * -PyCObject_FromVoidPtr(void *cobj, void (*destr)(void *)) -{ - PyCObject *self; - - if (deprecation_exception()) { - return NULL; - } - - self = PyObject_NEW(PyCObject, &PyCObject_Type); - if (self == NULL) - return NULL; - self->cobject=cobj; - self->destructor=destr; - self->desc=NULL; - - return (PyObject *)self; -} - -PyObject * -PyCObject_FromVoidPtrAndDesc(void *cobj, void *desc, - void (*destr)(void *, void *)) -{ - PyCObject *self; - - if (deprecation_exception()) { - return NULL; - } - - if (!desc) { - PyErr_SetString(PyExc_TypeError, - "PyCObject_FromVoidPtrAndDesc called with null" - " description"); - return NULL; - } - self = PyObject_NEW(PyCObject, &PyCObject_Type); - if (self == NULL) - return NULL; - self->cobject = cobj; - self->destructor = (destructor1)destr; - self->desc = desc; - - return (PyObject *)self; -} - -void * -PyCObject_AsVoidPtr(PyObject *self) -{ - if (self) { - if (self->ob_type == &PyCObject_Type) - return ((PyCObject *)self)->cobject; - PyErr_SetString(PyExc_TypeError, - "PyCObject_AsVoidPtr with non-C-object"); - } - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_TypeError, - "PyCObject_AsVoidPtr called with null pointer"); - return NULL; -} - -void * -PyCObject_GetDesc(PyObject *self) -{ - if (self) { - if (self->ob_type == &PyCObject_Type) - return ((PyCObject *)self)->desc; - PyErr_SetString(PyExc_TypeError, - "PyCObject_GetDesc with non-C-object"); - } - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_TypeError, - "PyCObject_GetDesc called with null pointer"); - return NULL; -} - -void * -PyCObject_Import(char *module_name, char *name) -{ - PyObject *m, *c; - void *r = NULL; - - if ((m = PyImport_ImportModule(module_name))) { - if ((c = PyObject_GetAttrString(m,name))) { - r = PyCObject_AsVoidPtr(c); - Py_DECREF(c); - } - Py_DECREF(m); - } - return r; -} - -int -PyCObject_SetVoidPtr(PyObject *self, void *cobj) -{ - PyCObject* cself = (PyCObject*)self; - if (cself == NULL || !PyCObject_Check(cself) || - cself->destructor != NULL) { - PyErr_SetString(PyExc_TypeError, - "Invalid call to PyCObject_SetVoidPtr"); - return 0; - } - cself->cobject = cobj; - return 1; -} - -static void -PyCObject_dealloc(PyCObject *self) -{ - if (self->destructor) { - if(self->desc) - ((destructor2)(self->destructor))(self->cobject, self->desc); - else - (self->destructor)(self->cobject); - } - PyObject_DEL(self); -} - - -PyDoc_STRVAR(PyCObject_Type__doc__, -"C objects to be exported from one extension module to another\n\ -\n\ -C objects are used for communication between extension modules. They\n\ -provide a way for an extension module to export a C interface to other\n\ -extension modules, so that extension modules can use the Python import\n\ -mechanism to link to one another."); - -PyTypeObject PyCObject_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "PyCObject", /*tp_name*/ - sizeof(PyCObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)PyCObject_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - 0, /*tp_flags*/ - PyCObject_Type__doc__ /*tp_doc*/ -}; diff --git a/Objects/codeobject.c b/Objects/codeobject.c index e3eccf7..bb938ea 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -54,7 +54,7 @@ PyCode_New(int argcount, int kwonlyargcount, Py_ssize_t i; /* Check argument types */ - if (argcount < 0 || nlocals < 0 || + if (argcount < 0 || kwonlyargcount < 0 || nlocals < 0 || code == NULL || consts == NULL || !PyTuple_Check(consts) || names == NULL || !PyTuple_Check(names) || @@ -108,10 +108,58 @@ PyCode_New(int argcount, int kwonlyargcount, Py_INCREF(lnotab); co->co_lnotab = lnotab; co->co_zombieframe = NULL; + co->co_weakreflist = NULL; } return co; } +PyCodeObject * +PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno) +{ + static PyObject *emptystring = NULL; + static PyObject *nulltuple = NULL; + PyObject *filename_ob = NULL; + PyObject *funcname_ob = NULL; + PyCodeObject *result = NULL; + if (emptystring == NULL) { + emptystring = PyBytes_FromString(""); + if (emptystring == NULL) + goto failed; + } + if (nulltuple == NULL) { + nulltuple = PyTuple_New(0); + if (nulltuple == NULL) + goto failed; + } + funcname_ob = PyUnicode_FromString(funcname); + if (funcname_ob == NULL) + goto failed; + filename_ob = PyUnicode_DecodeFSDefault(filename); + if (filename_ob == NULL) + goto failed; + + result = PyCode_New(0, /* argcount */ + 0, /* kwonlyargcount */ + 0, /* nlocals */ + 0, /* stacksize */ + 0, /* flags */ + emptystring, /* code */ + nulltuple, /* consts */ + nulltuple, /* names */ + nulltuple, /* varnames */ + nulltuple, /* freevars */ + nulltuple, /* cellvars */ + filename_ob, /* filename */ + funcname_ob, /* name */ + firstlineno, /* firstlineno */ + emptystring /* lnotab */ + ); + +failed: + Py_XDECREF(funcname_ob); + Py_XDECREF(filename_ob); + return result; +} #define OFF(x) offsetof(PyCodeObject, x) @@ -284,22 +332,28 @@ code_dealloc(PyCodeObject *co) Py_XDECREF(co->co_lnotab); if (co->co_zombieframe != NULL) PyObject_GC_Del(co->co_zombieframe); + if (co->co_weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject*)co); PyObject_DEL(co); } static PyObject * code_repr(PyCodeObject *co) { - int lineno = -1; - char *filename = "???"; - + int lineno; if (co->co_firstlineno != 0) lineno = co->co_firstlineno; - if (co->co_filename && PyUnicode_Check(co->co_filename)) - filename = _PyUnicode_AsString(co->co_filename); - return PyUnicode_FromFormat( - "<code object %.100U at %p, file \"%.300s\", line %d>", - co->co_name, co, filename, lineno); + else + lineno = -1; + if (co->co_filename && PyUnicode_Check(co->co_filename)) { + return PyUnicode_FromFormat( + "<code object %U at %p, file \"%U\", line %d>", + co->co_name, co, co->co_filename, lineno); + } else { + return PyUnicode_FromFormat( + "<code object %U at %p, file ???, line %d>", + co->co_name, co, lineno); + } } static PyObject * @@ -363,10 +417,10 @@ code_richcompare(PyObject *self, PyObject *other, int op) return res; } -static long +static Py_hash_t code_hash(PyCodeObject *co) { - long h, h0, h1, h2, h3, h4, h5, h6; + Py_hash_t h, h0, h1, h2, h3, h4, h5, h6; h0 = PyObject_Hash(co->co_name); if (h0 == -1) return -1; h1 = PyObject_Hash(co->co_code); @@ -415,7 +469,7 @@ PyTypeObject PyCode_Type = { 0, /* tp_traverse */ 0, /* tp_clear */ code_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ + offsetof(PyCodeObject, co_weakreflist), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ @@ -431,54 +485,14 @@ PyTypeObject PyCode_Type = { code_new, /* tp_new */ }; -/* All about c_lnotab. - -c_lnotab is an array of unsigned bytes disguised as a Python string. In -O -mode, SET_LINENO opcodes aren't generated, and bytecode offsets are mapped -to source code line #s (when needed for tracebacks) via c_lnotab instead. -The array is conceptually a list of - (bytecode offset increment, line number increment) -pairs. The details are important and delicate, best illustrated by example: - - byte code offset source code line number - 0 1 - 6 2 - 50 7 - 350 307 - 361 308 - -The first trick is that these numbers aren't stored, only the increments -from one row to the next (this doesn't really work, but it's a start): - - 0, 1, 6, 1, 44, 5, 300, 300, 11, 1 - -The second trick is that an unsigned byte can't hold negative values, or -values larger than 255, so (a) there's a deep assumption that byte code -offsets and their corresponding line #s both increase monotonically, and (b) -if at least one column jumps by more than 255 from one row to the next, more -than one pair is written to the table. In case #b, there's no way to know -from looking at the table later how many were written. That's the delicate -part. A user of c_lnotab desiring to find the source line number -corresponding to a bytecode address A should do something like this - - lineno = addr = 0 - for addr_incr, line_incr in c_lnotab: - addr += addr_incr - if addr > A: - return lineno - lineno += line_incr - -In order for this to work, when the addr field increments by more than 255, -the line # increment in each pair generated must be 0 until the remaining addr -increment is < 256. So, in the example above, com_set_lineno should not (as -was actually done until 2.2) expand 300, 300 to 255, 255, 45, 45, but to -255, 0, 45, 255, 0, 45. +/* Use co_lnotab to compute the line number from a bytecode index, addrq. See + lnotab_notes.txt for the details of the lnotab representation. */ int PyCode_Addr2Line(PyCodeObject *co, int addrq) { - int size = PyBytes_Size(co->co_lnotab) / 2; + Py_ssize_t size = PyBytes_Size(co->co_lnotab) / 2; unsigned char *p = (unsigned char*)PyBytes_AsString(co->co_lnotab); int line = co->co_firstlineno; int addr = 0; @@ -491,87 +505,13 @@ PyCode_Addr2Line(PyCodeObject *co, int addrq) return line; } -/* - Check whether the current instruction is at the start of a line. - - */ - - /* The theory of SET_LINENO-less tracing. - - In a nutshell, we use the co_lnotab field of the code object - to tell when execution has moved onto a different line. - - As mentioned above, the basic idea is so set things up so - that - - *instr_lb <= frame->f_lasti < *instr_ub - - is true so long as execution does not change lines. - - This is all fairly simple. Digging the information out of - co_lnotab takes some work, but is conceptually clear. - - Somewhat harder to explain is why we don't *always* call the - line trace function when the above test fails. - - Consider this code: - - 1: def f(a): - 2: if a: - 3: print 1 - 4: else: - 5: print 2 - - which compiles to this: - - 2 0 LOAD_FAST 0 (a) - 3 JUMP_IF_FALSE 9 (to 15) - 6 POP_TOP - - 3 7 LOAD_CONST 1 (1) - 10 PRINT_ITEM - 11 PRINT_NEWLINE - 12 JUMP_FORWARD 6 (to 21) - >> 15 POP_TOP - - 5 16 LOAD_CONST 2 (2) - 19 PRINT_ITEM - 20 PRINT_NEWLINE - >> 21 LOAD_CONST 0 (None) - 24 RETURN_VALUE - - If 'a' is false, execution will jump to instruction at offset - 15 and the co_lnotab will claim that execution has moved to - line 3. This is at best misleading. In this case we could - associate the POP_TOP with line 4, but that doesn't make - sense in all cases (I think). - - What we do is only call the line trace function if the co_lnotab - indicates we have jumped to the *start* of a line, i.e. if the - current instruction offset matches the offset given for the - start of a line by the co_lnotab. - - This also takes care of the situation where 'a' is true. - Execution will jump from instruction offset 12 to offset 21. - Then the co_lnotab would imply that execution has moved to line - 5, which is again misleading. - - Why do we set f_lineno when tracing? Well, consider the code - above when 'a' is true. If stepping through this with 'n' in - pdb, you would stop at line 1 with a "call" type event, then - line events on lines 2 and 3, then a "return" type event -- but - you would be shown line 5 during this event. This is a change - from the behaviour in 2.2 and before, and I've found it - confusing in practice. By setting and using f_lineno when - tracing, one can report a line number different from that - suggested by f_lasti on this one occasion where it's desirable. - */ - - +/* Update *bounds to describe the first and one-past-the-last instructions in + the same line as lasti. Return the number of that line. */ int -PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds) +_PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds) { - int size, addr, line; + Py_ssize_t size; + int addr, line; unsigned char* p; p = (unsigned char*)PyBytes_AS_STRING(co->co_lnotab); @@ -586,11 +526,9 @@ PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds) instr_lb -- if we stored the matching value of p somwhere we could skip the first while loop. */ - /* see comments in compile.c for the description of + /* See lnotab_notes.txt for the description of co_lnotab. A point to remember: increments to p - should come in pairs -- although we don't care about - the line increments here, treating them as byte - increments gets confusing, to say the least. */ + come in (addr, line) pairs. */ bounds->ap_lower = 0; while (size > 0) { @@ -603,13 +541,6 @@ PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds) --size; } - /* If lasti and addr don't match exactly, we don't want to - change the lineno slot on the frame or execute a trace - function. Return -1 instead. - */ - if (addr != lasti) - line = -1; - if (size > 0) { while (--size >= 0) { addr += *p++; diff --git a/Objects/complexobject.c b/Objects/complexobject.c index 4948a21..e247ba9 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -8,8 +8,6 @@ #include "Python.h" #include "structmember.h" -#ifndef WITHOUT_COMPLEX - /* elementary operations on complex numbers */ static Py_complex c_1 = {1., 0.}; @@ -264,12 +262,25 @@ PyComplex_ImagAsDouble(PyObject *op) } } +static PyObject * +try_complex_special_method(PyObject *op) { + PyObject *f; + static PyObject *complexstr; + + f = _PyObject_LookupSpecial(op, "__complex__", &complexstr); + if (f) { + PyObject *res = PyObject_CallFunctionObjArgs(f, NULL); + Py_DECREF(f); + return res; + } + return NULL; +} + Py_complex PyComplex_AsCComplex(PyObject *op) { Py_complex cv; PyObject *newop = NULL; - static PyObject *complex_str = NULL; assert(op); /* If op is already of type PyComplex_Type, return its value */ @@ -282,21 +293,7 @@ PyComplex_AsCComplex(PyObject *op) cv.real = -1.; cv.imag = 0.; - if (complex_str == NULL) { - if (!(complex_str = PyUnicode_FromString("__complex__"))) - return cv; - } - - { - PyObject *complexfunc; - complexfunc = _PyType_Lookup(op->ob_type, complex_str); - /* complexfunc is a borrowed reference */ - if (complexfunc) { - newop = PyObject_CallFunctionObjArgs(complexfunc, op, NULL); - if (!newop) - return cv; - } - } + newop = try_complex_special_method(op); if (newop) { if (!PyComplex_Check(newop)) { @@ -309,6 +306,9 @@ PyComplex_AsCComplex(PyObject *op) Py_DECREF(newop); return cv; } + else if (PyErr_Occurred()) { + return cv; + } /* If neither of the above works, interpret op as a float giving the real part of the result, and fill in the imaginary part as 0. */ else { @@ -324,10 +324,11 @@ complex_dealloc(PyObject *op) op->ob_type->tp_free(op); } - static PyObject * -complex_format(PyComplexObject *v, int precision, char format_code) +complex_repr(PyComplexObject *v) { + int precision = 0; + char format_code = 'r'; PyObject *result = NULL; Py_ssize_t len; @@ -344,6 +345,8 @@ complex_format(PyComplexObject *v, int precision, char format_code) char *tail = ""; if (v->cval.real == 0. && copysign(1.0, v->cval.real)==1.0) { + /* Real part is +0: just output the imaginary part and do not + include parens. */ re = ""; im = PyOS_double_to_string(v->cval.imag, format_code, precision, 0, NULL); @@ -352,7 +355,8 @@ complex_format(PyComplexObject *v, int precision, char format_code) goto done; } } else { - /* Format imaginary part with sign, real part without */ + /* Format imaginary part with sign, real part without. Include + parens in the result. */ pre = PyOS_double_to_string(v->cval.real, format_code, precision, 0, NULL); if (!pre) { @@ -371,7 +375,7 @@ complex_format(PyComplexObject *v, int precision, char format_code) tail = ")"; } /* Alloc the final buffer. Add one for the "j" in the format string, - and one for the trailing zero. */ + and one for the trailing zero byte. */ len = strlen(lead) + strlen(re) + strlen(im) + strlen(tail) + 2; buf = PyMem_Malloc(len); if (!buf) { @@ -388,27 +392,15 @@ complex_format(PyComplexObject *v, int precision, char format_code) return result; } -static PyObject * -complex_repr(PyComplexObject *v) -{ - return complex_format(v, 0, 'r'); -} - -static PyObject * -complex_str(PyComplexObject *v) -{ - return complex_format(v, PyFloat_STR_PRECISION, 'g'); -} - -static long +static Py_hash_t complex_hash(PyComplexObject *v) { - long hashreal, hashimag, combined; - hashreal = _Py_HashDouble(v->cval.real); - if (hashreal == -1) + Py_uhash_t hashreal, hashimag, combined; + hashreal = (Py_uhash_t)_Py_HashDouble(v->cval.real); + if (hashreal == (Py_uhash_t)-1) return -1; - hashimag = _Py_HashDouble(v->cval.imag); - if (hashimag == -1) + hashimag = (Py_uhash_t)_Py_HashDouble(v->cval.imag); + if (hashimag == (Py_uhash_t)-1) return -1; /* Note: if the imaginary part is 0, hashimag is 0 now, * so the following returns hashreal unchanged. This is @@ -416,10 +408,10 @@ complex_hash(PyComplexObject *v) * compare equal must have the same hash value, so that * hash(x + 0*j) must equal hash(x). */ - combined = hashreal + 1000003 * hashimag; - if (combined == -1) - combined = -2; - return combined; + combined = hashreal + _PyHASH_IMAG * hashimag; + if (combined == (Py_uhash_t)-1) + combined = (Py_uhash_t)-2; + return (Py_hash_t)combined; } /* This macro may return! */ @@ -504,7 +496,7 @@ complex_div(PyObject *v, PyObject *w) quot = c_quot(a, b); PyFPE_END_PROTECT(quot) if (errno == EDOM) { - PyErr_SetString(PyExc_ZeroDivisionError, "complex division"); + PyErr_SetString(PyExc_ZeroDivisionError, "complex division by zero"); return NULL; } return PyComplex_FromCComplex(quot); @@ -620,24 +612,58 @@ static PyObject * complex_richcompare(PyObject *v, PyObject *w, int op) { PyObject *res; - Py_complex i, j; - TO_COMPLEX(v, i); - TO_COMPLEX(w, j); + Py_complex i; + int equal; if (op != Py_EQ && op != Py_NE) { - /* XXX Should eventually return NotImplemented */ - PyErr_SetString(PyExc_TypeError, - "no ordering relation is defined for complex numbers"); - return NULL; + goto Unimplemented; } - if ((i.real == j.real && i.imag == j.imag) == (op == Py_EQ)) - res = Py_True; + assert(PyComplex_Check(v)); + TO_COMPLEX(v, i); + + if (PyLong_Check(w)) { + /* Check for 0.0 imaginary part first to avoid the rich + * comparison when possible. + */ + if (i.imag == 0.0) { + PyObject *j, *sub_res; + j = PyFloat_FromDouble(i.real); + if (j == NULL) + return NULL; + + sub_res = PyObject_RichCompare(j, w, op); + Py_DECREF(j); + return sub_res; + } + else { + equal = 0; + } + } + else if (PyFloat_Check(w)) { + equal = (i.real == PyFloat_AsDouble(w) && i.imag == 0.0); + } + else if (PyComplex_Check(w)) { + Py_complex j; + + TO_COMPLEX(w, j); + equal = (i.real == j.real && i.imag == j.imag); + } + else { + goto Unimplemented; + } + + if (equal == (op == Py_EQ)) + res = Py_True; else - res = Py_False; + res = Py_False; Py_INCREF(res); return res; + +Unimplemented: + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; } static PyObject * @@ -738,26 +764,30 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v) char *end; double x=0.0, y=0.0, z; int got_bracket=0; - char s_buffer[256]; + PyObject *s_buffer = NULL; Py_ssize_t len; if (PyUnicode_Check(v)) { - if (PyUnicode_GET_SIZE(v) >= (Py_ssize_t)sizeof(s_buffer)) { - PyErr_SetString(PyExc_ValueError, - "complex() literal too large to convert"); + Py_ssize_t i, buflen = PyUnicode_GET_SIZE(v); + Py_UNICODE *bufptr; + s_buffer = PyUnicode_TransformDecimalToASCII( + PyUnicode_AS_UNICODE(v), buflen); + if (s_buffer == NULL) return NULL; + /* Replace non-ASCII whitespace with ' ' */ + bufptr = PyUnicode_AS_UNICODE(s_buffer); + for (i = 0; i < buflen; i++) { + Py_UNICODE ch = bufptr[i]; + if (ch > 127 && Py_UNICODE_ISSPACE(ch)) + bufptr[i] = ' '; } - if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v), - PyUnicode_GET_SIZE(v), - s_buffer, - NULL)) - return NULL; - s = s_buffer; - len = strlen(s); + s = _PyUnicode_AsStringAndSize(s_buffer, &len); + if (s == NULL) + goto error; } else if (PyObject_AsCharBuffer(v, &s, &len)) { PyErr_SetString(PyExc_TypeError, - "complex() arg is not a string"); + "complex() argument must be a string or a number"); return NULL; } @@ -800,7 +830,7 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v) if (PyErr_ExceptionMatches(PyExc_ValueError)) PyErr_Clear(); else - return NULL; + goto error; } if (end != s) { /* all 4 forms starting with <float> land here */ @@ -813,7 +843,7 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v) if (PyErr_ExceptionMatches(PyExc_ValueError)) PyErr_Clear(); else - return NULL; + goto error; } if (end != s) /* <float><signed-float>j */ @@ -868,24 +898,26 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v) if (s-start != len) goto parse_error; + Py_XDECREF(s_buffer); return complex_subtype_from_doubles(type, x, y); parse_error: PyErr_SetString(PyExc_ValueError, "complex() arg is a malformed string"); + error: + Py_XDECREF(s_buffer); return NULL; } static PyObject * complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyObject *r, *i, *tmp, *f; + PyObject *r, *i, *tmp; PyNumberMethods *nbr, *nbi = NULL; Py_complex cr, ci; int own_r = 0; int cr_is_complex = 0; int ci_is_complex = 0; - static PyObject *complexstr; static char *kwlist[] = {"real", "imag", 0}; r = Py_False; @@ -920,26 +952,15 @@ complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } - /* XXX Hack to support classes with __complex__ method */ - if (complexstr == NULL) { - complexstr = PyUnicode_InternFromString("__complex__"); - if (complexstr == NULL) - return NULL; - } - f = PyObject_GetAttr(r, complexstr); - if (f == NULL) - PyErr_Clear(); - else { - PyObject *args = PyTuple_New(0); - if (args == NULL) - return NULL; - r = PyEval_CallObject(f, args); - Py_DECREF(args); - Py_DECREF(f); - if (r == NULL) - return NULL; + tmp = try_complex_special_method(r); + if (tmp) { + r = tmp; own_r = 1; } + else if (PyErr_Occurred()) { + return NULL; + } + nbr = r->ob_type->tp_as_number; if (i != NULL) nbi = i->ob_type->tp_as_number; @@ -1079,7 +1100,7 @@ PyTypeObject PyComplex_Type = { 0, /* tp_as_mapping */ (hashfunc)complex_hash, /* tp_hash */ 0, /* tp_call */ - (reprfunc)complex_str, /* tp_str */ + (reprfunc)complex_repr, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ @@ -1104,5 +1125,3 @@ PyTypeObject PyComplex_Type = { complex_new, /* tp_new */ PyObject_Del, /* tp_free */ }; - -#endif diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 9eda4bd..93daefd 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -92,7 +92,7 @@ classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type) "descriptor '%V' for type '%s' " "needs either an object or a type", descr_name((PyDescrObject *)descr), "?", - descr->d_type->tp_name); + PyDescr_TYPE(descr)->tp_name); return NULL; } } @@ -101,16 +101,16 @@ classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type) "descriptor '%V' for type '%s' " "needs a type, not a '%s' as arg 2", descr_name((PyDescrObject *)descr), "?", - descr->d_type->tp_name, + PyDescr_TYPE(descr)->tp_name, type->ob_type->tp_name); return NULL; } - if (!PyType_IsSubtype((PyTypeObject *)type, descr->d_type)) { + if (!PyType_IsSubtype((PyTypeObject *)type, PyDescr_TYPE(descr))) { PyErr_Format(PyExc_TypeError, "descriptor '%V' for type '%s' " "doesn't apply to type '%s'", descr_name((PyDescrObject *)descr), "?", - descr->d_type->tp_name, + PyDescr_TYPE(descr)->tp_name, ((PyTypeObject *)type)->tp_name); return NULL; } @@ -149,7 +149,7 @@ getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type) PyErr_Format(PyExc_AttributeError, "attribute '%V' of '%.100s' objects is not readable", descr_name((PyDescrObject *)descr), "?", - descr->d_type->tp_name); + PyDescr_TYPE(descr)->tp_name); return NULL; } @@ -204,7 +204,7 @@ getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value) PyErr_Format(PyExc_AttributeError, "attribute '%V' of '%.100s' objects is not writable", descr_name((PyDescrObject *)descr), "?", - descr->d_type->tp_name); + PyDescr_TYPE(descr)->tp_name); return -1; } @@ -222,18 +222,18 @@ methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds) "descriptor '%V' of '%.100s' " "object needs an argument", descr_name((PyDescrObject *)descr), "?", - descr->d_type->tp_name); + PyDescr_TYPE(descr)->tp_name); return NULL; } self = PyTuple_GET_ITEM(args, 0); if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self), - (PyObject *)(descr->d_type))) { + (PyObject *)PyDescr_TYPE(descr))) { PyErr_Format(PyExc_TypeError, "descriptor '%V' " "requires a '%.100s' object " "but received a '%.100s'", descr_name((PyDescrObject *)descr), "?", - descr->d_type->tp_name, + PyDescr_TYPE(descr)->tp_name, self->ob_type->tp_name); return NULL; } @@ -258,7 +258,7 @@ classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args, { PyObject *func, *result; - func = PyCFunction_New(descr->d_method, (PyObject *)descr->d_type); + func = PyCFunction_New(descr->d_method, (PyObject *)PyDescr_TYPE(descr)); if (func == NULL) return NULL; @@ -281,18 +281,18 @@ wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds) "descriptor '%V' of '%.100s' " "object needs an argument", descr_name((PyDescrObject *)descr), "?", - descr->d_type->tp_name); + PyDescr_TYPE(descr)->tp_name); return NULL; } self = PyTuple_GET_ITEM(args, 0); if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self), - (PyObject *)(descr->d_type))) { + (PyObject *)PyDescr_TYPE(descr))) { PyErr_Format(PyExc_TypeError, "descriptor '%V' " "requires a '%.100s' object " "but received a '%.100s'", descr_name((PyDescrObject *)descr), "?", - descr->d_type->tp_name, + PyDescr_TYPE(descr)->tp_name, self->ob_type->tp_name); return NULL; } @@ -712,19 +712,19 @@ proxy_get(proxyobject *pp, PyObject *args) static PyObject * proxy_keys(proxyobject *pp) { - return PyMapping_Keys(pp->dict); + return PyObject_CallMethod(pp->dict, "keys", NULL); } static PyObject * proxy_values(proxyobject *pp) { - return PyMapping_Values(pp->dict); + return PyObject_CallMethod(pp->dict, "values", NULL); } static PyObject * proxy_items(proxyobject *pp) { - return PyMapping_Items(pp->dict); + return PyObject_CallMethod(pp->dict, "items", NULL); } static PyObject * @@ -924,10 +924,10 @@ wrapper_richcompare(PyObject *a, PyObject *b, int op) return v; } -static long +static Py_hash_t wrapper_hash(wrapperobject *wp) { - int x, y; + Py_hash_t x, y; x = _Py_HashPointer(wp->descr); if (x == -1) return -1; @@ -957,7 +957,7 @@ static PyMemberDef wrapper_members[] = { static PyObject * wrapper_objclass(wrapperobject *wp) { - PyObject *c = (PyObject *)wp->descr->d_type; + PyObject *c = (PyObject *)PyDescr_TYPE(wp->descr); Py_INCREF(c); return c; @@ -1068,7 +1068,7 @@ PyWrapper_New(PyObject *d, PyObject *self) assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type)); descr = (PyWrapperDescrObject *)d; assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self), - (PyObject *)(descr->d_type))); + (PyObject *)PyDescr_TYPE(descr))); wp = PyObject_GC_New(wrapperobject, &wrappertype); if (wp != NULL) { @@ -1124,7 +1124,7 @@ typedef struct { } propertyobject; static PyObject * property_copy(PyObject *, PyObject *, PyObject *, - PyObject *, PyObject *); + PyObject *); static PyMemberDef property_members[] = { {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY}, @@ -1141,7 +1141,7 @@ PyDoc_STRVAR(getter_doc, static PyObject * property_getter(PyObject *self, PyObject *getter) { - return property_copy(self, getter, NULL, NULL, NULL); + return property_copy(self, getter, NULL, NULL); } @@ -1151,7 +1151,7 @@ PyDoc_STRVAR(setter_doc, static PyObject * property_setter(PyObject *self, PyObject *setter) { - return property_copy(self, NULL, setter, NULL, NULL); + return property_copy(self, NULL, setter, NULL); } @@ -1161,7 +1161,7 @@ PyDoc_STRVAR(deleter_doc, static PyObject * property_deleter(PyObject *self, PyObject *deleter) { - return property_copy(self, NULL, NULL, deleter, NULL); + return property_copy(self, NULL, NULL, deleter); } @@ -1199,7 +1199,7 @@ property_descr_get(PyObject *self, PyObject *obj, PyObject *type) PyErr_SetString(PyExc_AttributeError, "unreadable attribute"); return NULL; } - return PyObject_CallFunction(gs->prop_get, "(O)", obj); + return PyObject_CallFunctionObjArgs(gs->prop_get, obj, NULL); } static int @@ -1220,9 +1220,9 @@ property_descr_set(PyObject *self, PyObject *obj, PyObject *value) return -1; } if (value == NULL) - res = PyObject_CallFunction(func, "(O)", obj); + res = PyObject_CallFunctionObjArgs(func, obj, NULL); else - res = PyObject_CallFunction(func, "(OO)", obj, value); + res = PyObject_CallFunctionObjArgs(func, obj, value, NULL); if (res == NULL) return -1; Py_DECREF(res); @@ -1230,11 +1230,10 @@ property_descr_set(PyObject *self, PyObject *obj, PyObject *value) } static PyObject * -property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del, - PyObject *doc) +property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del) { propertyobject *pold = (propertyobject *)old; - PyObject *new, *type; + PyObject *new, *type, *doc; type = PyObject_Type(old); if (type == NULL) @@ -1252,15 +1251,12 @@ property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del, Py_XDECREF(del); del = pold->prop_del ? pold->prop_del : Py_None; } - if (doc == NULL || doc == Py_None) { - Py_XDECREF(doc); - if (pold->getter_doc && get != Py_None) { - /* make _init use __doc__ from getter */ - doc = Py_None; - } - else { - doc = pold->prop_doc ? pold->prop_doc : Py_None; - } + if (pold->getter_doc && get != Py_None) { + /* make _init use __doc__ from getter */ + doc = Py_None; + } + else { + doc = pold->prop_doc ? pold->prop_doc : Py_None; } new = PyObject_CallFunction(type, "OOOO", get, set, del, doc); diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 8492c61..3fa5cc4 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -124,15 +124,6 @@ masked); and the PyDictObject struct required a member to hold the table's polynomial. In Tim's experiments the current scheme ran faster, produced equally good collision statistics, needed less code & used less memory. -Theoretical Python 2.5 headache: hash codes are only C "long", but -sizeof(Py_ssize_t) > sizeof(long) may be possible. In that case, and if a -dict is genuinely huge, then only the slots directly reachable via indexing -by a C long can be the first slot in a probe sequence. The probe sequence -will still eventually reach every slot in the table, but the collision rate -on initial probes may be much higher than this scheme was designed for. -Getting a hash code as fat as Py_ssize_t is the only real cure. But in -practice, this probably won't make a lick of difference for many years (at -which point everyone will have terabytes of RAM on 64-bit boxes). */ /* Object used as dummy key to fill deleted entries */ @@ -148,7 +139,7 @@ _PyDict_Dummy(void) /* forward declarations */ static PyDictEntry * -lookdict_unicode(PyDictObject *mp, PyObject *key, long hash); +lookdict_unicode(PyDictObject *mp, PyObject *key, Py_hash_t hash); #ifdef SHOW_CONVERSION_COUNTS static long created = 0L; @@ -318,7 +309,7 @@ the caller can (if it wishes) add the <key, value> pair to the returned PyDictEntry*. */ static PyDictEntry * -lookdict(PyDictObject *mp, PyObject *key, register long hash) +lookdict(PyDictObject *mp, PyObject *key, register Py_hash_t hash) { register size_t i; register size_t perturb; @@ -407,7 +398,7 @@ lookdict(PyDictObject *mp, PyObject *key, register long hash) * This is valuable because dicts with only unicode keys are very common. */ static PyDictEntry * -lookdict_unicode(PyDictObject *mp, PyObject *key, register long hash) +lookdict_unicode(PyDictObject *mp, PyObject *key, register Py_hash_t hash) { register size_t i; register size_t perturb; @@ -458,6 +449,21 @@ lookdict_unicode(PyDictObject *mp, PyObject *key, register long hash) return 0; } +int +_PyDict_HasOnlyStringKeys(PyObject *dict) +{ + Py_ssize_t pos = 0; + PyObject *key, *value; + assert(PyDict_Check(dict)); + /* Shortcut */ + if (((PyDictObject *)dict)->ma_lookup == lookdict_unicode) + return 1; + while (PyDict_Next(dict, &pos, &key, &value)) + if (!PyUnicode_Check(key)) + return 0; + return 1; +} + #ifdef SHOW_TRACK_COUNT #define INCREASE_TRACK_COUNT \ (count_tracked++, count_untracked--); @@ -512,11 +518,11 @@ Eats a reference to key and one to value. Returns -1 if an error occurred, or 0 on success. */ static int -insertdict(register PyDictObject *mp, PyObject *key, long hash, PyObject *value) +insertdict(register PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) { PyObject *old_value; register PyDictEntry *ep; - typedef PyDictEntry *(*lookupfunc)(PyDictObject *, PyObject *, long); + typedef PyDictEntry *(*lookupfunc)(PyDictObject *, PyObject *, Py_hash_t); assert(mp->ma_lookup != NULL); ep = mp->ma_lookup(mp, key, hash); @@ -540,7 +546,7 @@ insertdict(register PyDictObject *mp, PyObject *key, long hash, PyObject *value) Py_DECREF(dummy); } ep->me_key = key; - ep->me_hash = (Py_ssize_t)hash; + ep->me_hash = hash; ep->me_value = value; mp->ma_used++; } @@ -556,7 +562,7 @@ Note that no refcounts are changed by this routine; if needed, the caller is responsible for incref'ing `key` and `value`. */ static void -insertdict_clean(register PyDictObject *mp, PyObject *key, long hash, +insertdict_clean(register PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) { register size_t i; @@ -575,7 +581,7 @@ insertdict_clean(register PyDictObject *mp, PyObject *key, long hash, assert(ep->me_value == NULL); mp->ma_fill++; ep->me_key = key; - ep->me_hash = (Py_ssize_t)hash; + ep->me_hash = hash; ep->me_value = value; mp->ma_used++; } @@ -652,8 +658,7 @@ dictresize(PyDictObject *mp, Py_ssize_t minused) for (ep = oldtable; i > 0; ep++) { if (ep->me_value != NULL) { /* active entry */ --i; - insertdict_clean(mp, ep->me_key, (long)ep->me_hash, - ep->me_value); + insertdict_clean(mp, ep->me_key, ep->me_hash, ep->me_value); } else if (ep->me_key != NULL) { /* dummy entry */ --i; @@ -698,7 +703,7 @@ _PyDict_NewPresized(Py_ssize_t minused) PyObject * PyDict_GetItem(PyObject *op, PyObject *key) { - long hash; + Py_hash_t hash; PyDictObject *mp = (PyDictObject *)op; PyDictEntry *ep; PyThreadState *tstate; @@ -719,7 +724,8 @@ PyDict_GetItem(PyObject *op, PyObject *key) Let's just hope that no exception occurs then... This must be _PyThreadState_Current and not PyThreadState_GET() because in debug mode, the latter complains if tstate is NULL. */ - tstate = _PyThreadState_Current; + tstate = (PyThreadState*)_Py_atomic_load_relaxed( + &_PyThreadState_Current); if (tstate != NULL && tstate->curexc_type != NULL) { /* preserve the existing exception */ PyObject *err_type, *err_value, *err_tb; @@ -747,7 +753,7 @@ PyDict_GetItem(PyObject *op, PyObject *key) PyObject * PyDict_GetItemWithError(PyObject *op, PyObject *key) { - long hash; + Py_hash_t hash; PyDictObject*mp = (PyDictObject *)op; PyDictEntry *ep; @@ -780,7 +786,7 @@ int PyDict_SetItem(register PyObject *op, PyObject *key, PyObject *value) { register PyDictObject *mp; - register long hash; + register Py_hash_t hash; register Py_ssize_t n_used; if (!PyDict_Check(op)) { @@ -826,7 +832,7 @@ int PyDict_DelItem(PyObject *op, PyObject *key) { register PyDictObject *mp; - register long hash; + register Py_hash_t hash; register PyDictEntry *ep; PyObject *old_value, *old_key; @@ -972,7 +978,7 @@ PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue) /* Internal version of PyDict_Next that returns a hash value in addition to the key and value.*/ int -_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue, long *phash) +_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue, Py_hash_t *phash) { register Py_ssize_t i; register Py_ssize_t mask; @@ -990,7 +996,7 @@ _PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue, *ppos = i+1; if (i > mask) return 0; - *phash = (long)(ep[i].me_hash); + *phash = ep[i].me_hash; if (pkey) *pkey = ep[i].me_key; if (pvalue) @@ -1112,7 +1118,7 @@ static PyObject * dict_subscript(PyDictObject *mp, register PyObject *key) { PyObject *v; - long hash; + Py_hash_t hash; PyDictEntry *ep; assert(mp->ma_table != NULL); if (!PyUnicode_CheckExact(key) || @@ -1306,7 +1312,7 @@ dict_fromkeys(PyObject *cls, PyObject *args) PyObject *oldvalue; Py_ssize_t pos = 0; PyObject *key; - long hash; + Py_hash_t hash; if (dictresize(mp, Py_SIZE(seq))) return NULL; @@ -1324,7 +1330,7 @@ dict_fromkeys(PyObject *cls, PyObject *args) PyDictObject *mp = (PyDictObject *)d; Py_ssize_t pos = 0; PyObject *key; - long hash; + Py_hash_t hash; if (dictresize(mp, PySet_GET_SIZE(seq))) return NULL; @@ -1386,8 +1392,12 @@ dict_update_common(PyObject *self, PyObject *args, PyObject *kwds, char *methnam else result = PyDict_MergeFromSeq2(self, arg, 1); } - if (result == 0 && kwds != NULL) - result = PyDict_Merge(self, kwds, 1); + if (result == 0 && kwds != NULL) { + if (PyArg_ValidateKeywordArguments(kwds)) + result = PyDict_Merge(self, kwds, 1); + else + result = -1; + } return result; } @@ -1529,7 +1539,7 @@ PyDict_Merge(PyObject *a, PyObject *b, int override) Py_INCREF(entry->me_key); Py_INCREF(entry->me_value); if (insertdict(mp, entry->me_key, - (long)entry->me_hash, + entry->me_hash, entry->me_value) != 0) return -1; } @@ -1712,7 +1722,7 @@ dict_richcompare(PyObject *v, PyObject *w, int op) static PyObject * dict_contains(register PyDictObject *mp, PyObject *key) { - long hash; + Py_hash_t hash; PyDictEntry *ep; if (!PyUnicode_CheckExact(key) || @@ -1733,7 +1743,7 @@ dict_get(register PyDictObject *mp, PyObject *args) PyObject *key; PyObject *failobj = Py_None; PyObject *val = NULL; - long hash; + Py_hash_t hash; PyDictEntry *ep; if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &failobj)) @@ -1762,7 +1772,7 @@ dict_setdefault(register PyDictObject *mp, PyObject *args) PyObject *key; PyObject *failobj = Py_None; PyObject *val = NULL; - long hash; + Py_hash_t hash; PyDictEntry *ep; if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &failobj)) @@ -1798,7 +1808,7 @@ dict_clear(register PyDictObject *mp) static PyObject * dict_pop(PyDictObject *mp, PyObject *args) { - long hash; + Py_hash_t hash; PyDictEntry *ep; PyObject *old_value, *old_key; PyObject *key, *deflt = NULL; @@ -1843,7 +1853,7 @@ dict_pop(PyDictObject *mp, PyObject *args) static PyObject * dict_popitem(PyDictObject *mp) { - Py_ssize_t i = 0; + Py_hash_t i = 0; PyDictEntry *ep; PyObject *res; @@ -2018,7 +2028,7 @@ static PyMethodDef mapp_methods[] = { int PyDict_Contains(PyObject *op, PyObject *key) { - long hash; + Py_hash_t hash; PyDictObject *mp = (PyDictObject *)op; PyDictEntry *ep; @@ -2034,7 +2044,7 @@ PyDict_Contains(PyObject *op, PyObject *key) /* Internal version of PyDict_Contains used when the hash value is already known */ int -_PyDict_Contains(PyObject *op, PyObject *key, long hash) +_PyDict_Contains(PyObject *op, PyObject *key, Py_hash_t hash) { PyDictObject *mp = (PyDictObject *)op; PyDictEntry *ep; @@ -2123,7 +2133,7 @@ PyTypeObject PyDict_Type = { 0, /* tp_as_number */ &dict_as_sequence, /* tp_as_sequence */ &dict_as_mapping, /* tp_as_mapping */ - (hashfunc)PyObject_HashNotImplemented, /* tp_hash */ + PyObject_HashNotImplemented, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ @@ -2786,7 +2796,63 @@ static PyNumberMethods dictviews_as_number = { (binaryfunc)dictviews_or, /*nb_or*/ }; +static PyObject* +dictviews_isdisjoint(PyObject *self, PyObject *other) +{ + PyObject *it; + PyObject *item = NULL; + + if (self == other) { + if (dictview_len((dictviewobject *)self) == 0) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; + } + + /* Iterate over the shorter object (only if other is a set, + * because PySequence_Contains may be expensive otherwise): */ + if (PyAnySet_Check(other) || PyDictViewSet_Check(other)) { + Py_ssize_t len_self = dictview_len((dictviewobject *)self); + Py_ssize_t len_other = PyObject_Size(other); + if (len_other == -1) + return NULL; + + if ((len_other > len_self)) { + PyObject *tmp = other; + other = self; + self = tmp; + } + } + + it = PyObject_GetIter(other); + if (it == NULL) + return NULL; + + while ((item = PyIter_Next(it)) != NULL) { + int contains = PySequence_Contains(self, item); + Py_DECREF(item); + if (contains == -1) { + Py_DECREF(it); + return NULL; + } + + if (contains) { + Py_DECREF(it); + Py_RETURN_FALSE; + } + } + Py_DECREF(it); + if (PyErr_Occurred()) + return NULL; /* PyIter_Next raised an exception. */ + Py_RETURN_TRUE; +} + +PyDoc_STRVAR(isdisjoint_doc, +"Return True if the view and the given iterable have a null intersection."); + static PyMethodDef dictkeys_methods[] = { + {"isdisjoint", (PyCFunction)dictviews_isdisjoint, METH_O, + isdisjoint_doc}, {NULL, NULL} /* sentinel */ }; @@ -2871,6 +2937,8 @@ static PySequenceMethods dictitems_as_sequence = { }; static PyMethodDef dictitems_methods[] = { + {"isdisjoint", (PyCFunction)dictviews_isdisjoint, METH_O, + isdisjoint_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/enumobject.c b/Objects/enumobject.c index b579f96..00a3346 100644 --- a/Objects/enumobject.c +++ b/Objects/enumobject.c @@ -159,12 +159,13 @@ enum_next(enumobject *en) } PyDoc_STRVAR(enum_doc, -"enumerate(iterable) -> iterator for index, value of iterable\n" +"enumerate(iterable[, start]) -> iterator for index, value of iterable\n" "\n" "Return an enumerate object. iterable must be another object that supports\n" "iteration. The enumerate object yields pairs containing a count (from\n" -"zero) and a value yielded by the iterable argument. enumerate is useful\n" -"for obtaining an indexed list: (0, seq[0]), (1, seq[1]), (2, seq[2]), ..."); +"start, which defaults to zero) and a value yielded by the iterable argument.\n" +"enumerate is useful for obtaining an indexed list:\n" +" (0, seq[0]), (1, seq[1]), (2, seq[2]), ..."); PyTypeObject PyEnum_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 1531867..0106ba3 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -959,20 +959,27 @@ SyntaxError_traverse(PySyntaxErrorObject *self, visitproc visit, void *arg) /* This is called "my_basename" instead of just "basename" to avoid name conflicts with glibc; basename is already prototyped if _GNU_SOURCE is defined, and Python does define that. */ -static char * -my_basename(char *name) -{ - char *cp = name; - char *result = name; - - if (name == NULL) - return "???"; - while (*cp != '\0') { - if (*cp == SEP) - result = cp + 1; - ++cp; +static PyObject* +my_basename(PyObject *name) +{ + Py_UNICODE *unicode; + Py_ssize_t i, size, offset; + + unicode = PyUnicode_AS_UNICODE(name); + size = PyUnicode_GET_SIZE(name); + offset = 0; + for(i=0; i < size; i++) { + if (unicode[i] == SEP) + offset = i + 1; + } + if (offset != 0) { + return PyUnicode_FromUnicode( + PyUnicode_AS_UNICODE(name) + offset, + size - offset); + } else { + Py_INCREF(name); + return name; } - return result; } @@ -980,7 +987,8 @@ static PyObject * SyntaxError_str(PySyntaxErrorObject *self) { int have_lineno = 0; - char *filename = 0; + PyObject *filename; + PyObject *result; /* Below, we always ignore overflow errors, just printing -1. Still, we cannot allow an OverflowError to be raised, so we need to call PyLong_AsLongAndOverflow. */ @@ -990,7 +998,11 @@ SyntaxError_str(PySyntaxErrorObject *self) lineno here */ if (self->filename && PyUnicode_Check(self->filename)) { - filename = _PyUnicode_AsString(self->filename); + filename = my_basename(self->filename); + if (filename == NULL) + return NULL; + } else { + filename = NULL; } have_lineno = (self->lineno != NULL) && PyLong_CheckExact(self->lineno); @@ -998,18 +1010,20 @@ SyntaxError_str(PySyntaxErrorObject *self) return PyObject_Str(self->msg ? self->msg : Py_None); if (filename && have_lineno) - return PyUnicode_FromFormat("%S (%s, line %ld)", + result = PyUnicode_FromFormat("%S (%U, line %ld)", self->msg ? self->msg : Py_None, - my_basename(filename), + filename, PyLong_AsLongAndOverflow(self->lineno, &overflow)); else if (filename) - return PyUnicode_FromFormat("%S (%s)", + result = PyUnicode_FromFormat("%S (%U)", self->msg ? self->msg : Py_None, - my_basename(filename)); + filename); else /* only have_lineno */ - return PyUnicode_FromFormat("%S (line %ld)", + result = PyUnicode_FromFormat("%S (line %ld)", self->msg ? self->msg : Py_None, PyLong_AsLongAndOverflow(self->lineno, &overflow)); + Py_XDECREF(filename); + return result; } static PyMemberDef SyntaxError_members[] = { @@ -1496,7 +1510,7 @@ PyUnicodeEncodeError_Create( const char *encoding, const Py_UNICODE *object, Py_ssize_t length, Py_ssize_t start, Py_ssize_t end, const char *reason) { - return PyObject_CallFunction(PyExc_UnicodeEncodeError, "Uu#nnU", + return PyObject_CallFunction(PyExc_UnicodeEncodeError, "su#nns", encoding, object, length, start, end, reason); } @@ -1608,7 +1622,7 @@ PyUnicodeDecodeError_Create( const char *encoding, const char *object, Py_ssize_t length, Py_ssize_t start, Py_ssize_t end, const char *reason) { - return PyObject_CallFunction(PyExc_UnicodeDecodeError, "Uy#nnU", + return PyObject_CallFunction(PyExc_UnicodeDecodeError, "sy#nns", encoding, object, length, start, end, reason); } @@ -1922,6 +1936,7 @@ SimpleExtendsException(PyExc_Warning, UnicodeWarning, "Base class for warnings about Unicode related problems, mostly\n" "related to conversion problems."); + /* * BytesWarning extends Warning */ @@ -1930,6 +1945,13 @@ SimpleExtendsException(PyExc_Warning, BytesWarning, "related to conversion from str or comparing to str."); +/* + * ResourceWarning extends Warning + */ +SimpleExtendsException(PyExc_Warning, ResourceWarning, + "Base class for warnings about resource usage."); + + /* Pre-computed RuntimeError instance for when recursion depth is reached. Meant to be used when normalizing the exception for exceeding the recursion @@ -2004,6 +2026,7 @@ _PyExc_Init(void) PRE_INIT(ImportWarning) PRE_INIT(UnicodeWarning) PRE_INIT(BytesWarning) + PRE_INIT(ResourceWarning) bltinmod = PyImport_ImportModule("builtins"); if (bltinmod == NULL) @@ -2066,6 +2089,7 @@ _PyExc_Init(void) POST_INIT(ImportWarning) POST_INIT(UnicodeWarning) POST_INIT(BytesWarning) + POST_INIT(ResourceWarning) preallocate_memerrors(); diff --git a/Objects/fileobject.c b/Objects/fileobject.c index b36aa02..d20f196 100644 --- a/Objects/fileobject.c +++ b/Objects/fileobject.c @@ -29,7 +29,7 @@ PyObject * PyFile_FromFd(int fd, char *name, char *mode, int buffering, char *encoding, char *errors, char *newline, int closefd) { - PyObject *io, *stream, *nameobj = NULL; + PyObject *io, *stream; io = PyImport_ImportModule("io"); if (io == NULL) @@ -40,16 +40,8 @@ PyFile_FromFd(int fd, char *name, char *mode, int buffering, char *encoding, Py_DECREF(io); if (stream == NULL) return NULL; - if (name != NULL) { - nameobj = PyUnicode_FromString(name); - if (nameobj == NULL) - PyErr_Clear(); - else { - if (PyObject_SetAttrString(stream, "name", nameobj) < 0) - PyErr_Clear(); - Py_DECREF(nameobj); - } - } + /* ignore name attribute because the name attribute of _BufferedIOMixin + and TextIOWrapper is read only */ return stream; } @@ -352,7 +344,7 @@ stdprinter_new(PyTypeObject *type, PyObject *args, PyObject *kews) } static int -fileio_init(PyObject *self, PyObject *args, PyObject *kwds) +stdprinter_init(PyObject *self, PyObject *args, PyObject *kwds) { PyErr_SetString(PyExc_TypeError, "cannot create 'stderrprinter' instances"); @@ -398,7 +390,13 @@ stdprinter_write(PyStdPrinter_Object *self, PyObject *args) Py_BEGIN_ALLOW_THREADS errno = 0; +#if defined(MS_WIN64) || defined(MS_WINDOWS) + if (n > INT_MAX) + n = INT_MAX; + n = write(self->fd, c, (int)n); +#else n = write(self->fd, c, n); +#endif Py_END_ALLOW_THREADS if (n < 0) { @@ -517,7 +515,7 @@ PyTypeObject PyStdPrinter_Type = { 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - fileio_init, /* tp_init */ + stdprinter_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ stdprinter_new, /* tp_new */ PyObject_Del, /* tp_free */ diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 8161ed5..09c0e961 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -5,7 +5,6 @@ for any kind of float exception without losing portability. */ #include "Python.h" -#include "structseq.h" #include <ctype.h> #include <float.h> @@ -21,7 +20,22 @@ extern int finite(double); #endif -/* Special free list -- see comments for same code in intobject.c. */ +/* Special free list + + Since some Python programs can spend much of their time allocating + and deallocating floats, these operations should be very fast. + Therefore we use a dedicated allocation scheme with a much lower + overhead (in space and time) than straight malloc(): a simple + dedicated free list, filled when necessary with memory from malloc(). + + block_list is a singly-linked list of all PyFloatBlocks ever allocated, + linked via their next members. PyFloatBlocks are never returned to the + system before shutdown (PyFloat_Fini). + + free_list is a singly-linked list of available PyFloatObjects, linked + via abuse of their ob_type members. +*/ + #define BLOCK_SIZE 1000 /* 1K less typical malloc overhead */ #define BHEAD_SIZE 8 /* Enough for a 64-bit pointer */ #define N_FLOATOBJECTS ((BLOCK_SIZE - BHEAD_SIZE) / sizeof(PyFloatObject)) @@ -69,7 +83,7 @@ PyFloat_GetMin(void) static PyTypeObject FloatInfoType; PyDoc_STRVAR(floatinfo__doc__, -"sys.floatinfo\n\ +"sys.float_info\n\ \n\ A structseq holding information about the float type. It contains low level\n\ information about the precision and internal representation. Please study\n\ @@ -96,7 +110,7 @@ static PyStructSequence_Field floatinfo_fields[] = { }; static PyStructSequence_Desc floatinfo_desc = { - "sys.floatinfo", /* name */ + "sys.float_info", /* name */ floatinfo__doc__, /* doc */ floatinfo_fields, /* fields */ 11 @@ -160,52 +174,58 @@ PyFloat_FromString(PyObject *v) { const char *s, *last, *end; double x; - char buffer[256]; /* for errors */ - char *s_buffer = NULL; + PyObject *s_buffer = NULL; Py_ssize_t len; PyObject *result = NULL; if (PyUnicode_Check(v)) { - s_buffer = (char *)PyMem_MALLOC(PyUnicode_GET_SIZE(v)+1); + Py_ssize_t i, buflen = PyUnicode_GET_SIZE(v); + Py_UNICODE *bufptr; + s_buffer = PyUnicode_TransformDecimalToASCII( + PyUnicode_AS_UNICODE(v), buflen); if (s_buffer == NULL) - return PyErr_NoMemory(); - if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v), - PyUnicode_GET_SIZE(v), - s_buffer, - NULL)) - goto error; - s = s_buffer; - len = strlen(s); + return NULL; + /* Replace non-ASCII whitespace with ' ' */ + bufptr = PyUnicode_AS_UNICODE(s_buffer); + for (i = 0; i < buflen; i++) { + Py_UNICODE ch = bufptr[i]; + if (ch > 127 && Py_UNICODE_ISSPACE(ch)) + bufptr[i] = ' '; + } + s = _PyUnicode_AsStringAndSize(s_buffer, &len); + if (s == NULL) { + Py_DECREF(s_buffer); + return NULL; + } + last = s + len; } else if (PyObject_AsCharBuffer(v, &s, &len)) { PyErr_SetString(PyExc_TypeError, - "float() argument must be a string or a number"); + "float() argument must be a string or a number"); return NULL; } last = s + len; - - while (Py_ISSPACE(*s)) + /* strip space */ + while (s < last && Py_ISSPACE(*s)) s++; + while (s < last - 1 && Py_ISSPACE(last[-1])) + last--; /* We don't care about overflow or underflow. If the platform * supports them, infinities and signed zeroes (on underflow) are * fine. */ x = PyOS_string_to_double(s, (char **)&end, NULL); - if (x == -1.0 && PyErr_Occurred()) - goto error; - while (Py_ISSPACE(*end)) - end++; - if (end == last) - result = PyFloat_FromDouble(x); - else { - PyOS_snprintf(buffer, sizeof(buffer), - "invalid literal for float(): %.200s", s); - PyErr_SetString(PyExc_ValueError, buffer); + if (end != last) { + PyErr_Format(PyExc_ValueError, + "could not convert string to float: " + "%R", v); result = NULL; } + else if (x == -1.0 && PyErr_Occurred()) + result = NULL; + else + result = PyFloat_FromDouble(x); - error: - if (s_buffer) - PyMem_FREE(s_buffer); + Py_XDECREF(s_buffer); return result; } @@ -290,32 +310,20 @@ convert_to_double(PyObject **v, double *dbl) } static PyObject * -float_str_or_repr(PyFloatObject *v, int precision, char format_code) +float_repr(PyFloatObject *v) { PyObject *result; char *buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v), - format_code, precision, + 'r', 0, Py_DTSF_ADD_DOT_0, NULL); if (!buf) - return PyErr_NoMemory(); + return PyErr_NoMemory(); result = PyUnicode_FromString(buf); PyMem_Free(buf); return result; } -static PyObject * -float_repr(PyFloatObject *v) -{ - return float_str_or_repr(v, 0, 'r'); -} - -static PyObject * -float_str(PyFloatObject *v) -{ - return float_str_or_repr(v, PyFloat_STR_PRECISION, 'g'); -} - /* Comparison is pretty much a nightmare. When comparing float to float, * we do it as straightforwardly (and long-windedly) as conceivable, so * that, e.g., Python x == y delivers the same result as the platform @@ -519,7 +527,7 @@ float_richcompare(PyObject *v, PyObject *w, int op) return Py_NotImplemented; } -static long +static Py_hash_t float_hash(PyFloatObject *v) { return _Py_HashDouble(v->ob_fval); @@ -567,13 +575,11 @@ float_div(PyObject *v, PyObject *w) double a,b; CONVERT_TO_DOUBLE(v, a); CONVERT_TO_DOUBLE(w, b); -#ifdef Py_NAN if (b == 0.0) { PyErr_SetString(PyExc_ZeroDivisionError, - "float division"); + "float division by zero"); return NULL; } -#endif PyFPE_START_PROTECT("divide", return 0) a = a / b; PyFPE_END_PROTECT(a) @@ -587,13 +593,11 @@ float_rem(PyObject *v, PyObject *w) double mod; CONVERT_TO_DOUBLE(v, vx); CONVERT_TO_DOUBLE(w, wx); -#ifdef Py_NAN if (wx == 0.0) { PyErr_SetString(PyExc_ZeroDivisionError, "float modulo"); return NULL; } -#endif PyFPE_START_PROTECT("modulo", return 0) mod = fmod(vx, wx); if (mod) { @@ -605,11 +609,8 @@ float_rem(PyObject *v, PyObject *w) else { /* the remainder is zero, and in the presence of signed zeroes fmod returns different results across platforms; ensure - it has the same sign as the denominator; we'd like to do - "mod = wx * 0.0", but that may get optimized away */ - mod *= mod; /* hide "mod = +0" from optimizer */ - if (wx < 0.0) - mod = -mod; + it has the same sign as the denominator. */ + mod = copysign(0.0, wx); } PyFPE_END_PROTECT(mod) return PyFloat_FromDouble(mod); @@ -645,11 +646,8 @@ float_divmod(PyObject *v, PyObject *w) else { /* the remainder is zero, and in the presence of signed zeroes fmod returns different results across platforms; ensure - it has the same sign as the denominator; we'd like to do - "mod = wx * 0.0", but that may get optimized away */ - mod *= mod; /* hide "mod = +0" from optimizer */ - if (wx < 0.0) - mod = -mod; + it has the same sign as the denominator. */ + mod = copysign(0.0, wx); } /* snap quotient to nearest integral value */ if (div) { @@ -659,8 +657,7 @@ float_divmod(PyObject *v, PyObject *w) } else { /* div is zero - get the same sign as the true quotient */ - div *= div; /* hide "div = +0" from optimizers */ - floordiv = div * vx / wx; /* zero w/ sign of vx/wx */ + floordiv = copysign(0.0, vx / wx); /* zero w/ sign of vx/wx */ } PyFPE_END_PROTECT(floordiv) return Py_BuildValue("(dd)", floordiv, mod); @@ -681,10 +678,15 @@ float_floor_div(PyObject *v, PyObject *w) return r; } +/* determine whether x is an odd integer or not; assumes that + x is not an infinity or nan. */ +#define DOUBLE_IS_ODD_INTEGER(x) (fmod(fabs(x), 2.0) == 1.0) + static PyObject * float_pow(PyObject *v, PyObject *w, PyObject *z) { double iv, iw, ix; + int negate_result = 0; if ((PyObject *)z != Py_None) { PyErr_SetString(PyExc_TypeError, "pow() 3rd argument not " @@ -699,17 +701,53 @@ float_pow(PyObject *v, PyObject *w, PyObject *z) if (iw == 0) { /* v**0 is 1, even 0**0 */ return PyFloat_FromDouble(1.0); } - if (iv == 0.0) { /* 0**w is error if w<0, else 1 */ + if (Py_IS_NAN(iv)) { /* nan**w = nan, unless w == 0 */ + return PyFloat_FromDouble(iv); + } + if (Py_IS_NAN(iw)) { /* v**nan = nan, unless v == 1; 1**nan = 1 */ + return PyFloat_FromDouble(iv == 1.0 ? 1.0 : iw); + } + if (Py_IS_INFINITY(iw)) { + /* v**inf is: 0.0 if abs(v) < 1; 1.0 if abs(v) == 1; inf if + * abs(v) > 1 (including case where v infinite) + * + * v**-inf is: inf if abs(v) < 1; 1.0 if abs(v) == 1; 0.0 if + * abs(v) > 1 (including case where v infinite) + */ + iv = fabs(iv); + if (iv == 1.0) + return PyFloat_FromDouble(1.0); + else if ((iw > 0.0) == (iv > 1.0)) + return PyFloat_FromDouble(fabs(iw)); /* return inf */ + else + return PyFloat_FromDouble(0.0); + } + if (Py_IS_INFINITY(iv)) { + /* (+-inf)**w is: inf for w positive, 0 for w negative; in + * both cases, we need to add the appropriate sign if w is + * an odd integer. + */ + int iw_is_odd = DOUBLE_IS_ODD_INTEGER(iw); + if (iw > 0.0) + return PyFloat_FromDouble(iw_is_odd ? iv : fabs(iv)); + else + return PyFloat_FromDouble(iw_is_odd ? + copysign(0.0, iv) : 0.0); + } + if (iv == 0.0) { /* 0**w is: 0 for w positive, 1 for w zero + (already dealt with above), and an error + if w is negative. */ + int iw_is_odd = DOUBLE_IS_ODD_INTEGER(iw); if (iw < 0.0) { PyErr_SetString(PyExc_ZeroDivisionError, - "0.0 cannot be raised to a negative power"); + "0.0 cannot be raised to a " + "negative power"); return NULL; } - return PyFloat_FromDouble(0.0); - } - if (iv == 1.0) { /* 1**w is 1, even 1**inf and 1**nan */ - return PyFloat_FromDouble(1.0); + /* use correct sign if iw is odd */ + return PyFloat_FromDouble(iw_is_odd ? iv : 0.0); } + if (iv < 0.0) { /* Whether this is an error is a mess, and bumps into libm * bugs so we have to figure it out ourselves. @@ -720,33 +758,41 @@ float_pow(PyObject *v, PyObject *w, PyObject *z) */ return PyComplex_Type.tp_as_number->nb_power(v, w, z); } - /* iw is an exact integer, albeit perhaps a very large one. + /* iw is an exact integer, albeit perhaps a very large + * one. Replace iv by its absolute value and remember + * to negate the pow result if iw is odd. + */ + iv = -iv; + negate_result = DOUBLE_IS_ODD_INTEGER(iw); + } + + if (iv == 1.0) { /* 1**w is 1, even 1**inf and 1**nan */ + /* (-1) ** large_integer also ends up here. Here's an + * extract from the comments for the previous + * implementation explaining why this special case is + * necessary: + * * -1 raised to an exact integer should never be exceptional. * Alas, some libms (chiefly glibc as of early 2003) return * NaN and set EDOM on pow(-1, large_int) if the int doesn't * happen to be representable in a *C* integer. That's a - * bug; we let that slide in math.pow() (which currently - * reflects all platform accidents), but not for Python's **. - */ - if (iv == -1.0 && Py_IS_FINITE(iw)) { - /* Return 1 if iw is even, -1 if iw is odd; there's - * no guarantee that any C integral type is big - * enough to hold iw, so we have to check this - * indirectly. - */ - ix = floor(iw * 0.5) * 2.0; - return PyFloat_FromDouble(ix == iw ? 1.0 : -1.0); - } - /* Else iv != -1.0, and overflow or underflow are possible. - * Unless we're to write pow() ourselves, we have to trust - * the platform to do this correctly. + * bug. */ + return PyFloat_FromDouble(negate_result ? -1.0 : 1.0); } + + /* Now iv and iw are finite, iw is nonzero, and iv is + * positive and not equal to 1.0. We finally allow + * the platform pow to step in and do the rest. + */ errno = 0; PyFPE_START_PROTECT("pow", return NULL) ix = pow(iv, iw); PyFPE_END_PROTECT(ix) Py_ADJUST_ERANGE1(ix); + if (negate_result) + ix = -ix; + if (errno != 0) { /* We don't expect any errno value other than ERANGE, but * the range of libm bugs appears unbounded. @@ -758,6 +804,8 @@ float_pow(PyObject *v, PyObject *w, PyObject *z) return PyFloat_FromDouble(ix); } +#undef DOUBLE_IS_ODD_INTEGER + static PyObject * float_neg(PyFloatObject *v) { @@ -1113,7 +1161,7 @@ float_hex(PyObject *v) CONVERT_TO_DOUBLE(v, x); if (Py_IS_NAN(x) || Py_IS_INFINITY(x)) - return float_str((PyFloatObject *)v); + return float_repr((PyFloatObject *)v); if (x == 0.0) { if (copysign(1.0, x) == -1.0) @@ -1366,7 +1414,7 @@ float_fromhex(PyObject *cls, PyObject *arg) round_up = 1; break; } - if (round_up == 1) { + if (round_up) { x += 2*half_eps; if (top_exp == DBL_MAX_EXP && x == ldexp((double)(2*half_eps), DBL_MANT_DIG)) @@ -1443,13 +1491,11 @@ float_as_integer_ratio(PyObject *v, PyObject *unused) "Cannot pass infinity to float.as_integer_ratio."); return NULL; } -#ifdef Py_NAN if (Py_IS_NAN(self)) { PyErr_SetString(PyExc_ValueError, "Cannot pass NaN to float.as_integer_ratio."); return NULL; } -#endif PyFPE_START_PROTECT("as_integer_ratio", goto error); float_part = frexp(self, &exponent); /* self == float_part * 2**exponent exactly */ @@ -1817,7 +1863,7 @@ PyTypeObject PyFloat_Type = { 0, /* tp_as_mapping */ (hashfunc)float_hash, /* tp_hash */ 0, /* tp_call */ - (reprfunc)float_str, /* tp_str */ + (reprfunc)float_repr, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 2cf2cdf..10fb8b3 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -31,17 +31,19 @@ frame_getlocals(PyFrameObject *f, void *closure) return f->f_locals; } -static PyObject * -frame_getlineno(PyFrameObject *f, void *closure) +int +PyFrame_GetLineNumber(PyFrameObject *f) { - int lineno; - if (f->f_trace) - lineno = f->f_lineno; + return f->f_lineno; else - lineno = PyCode_Addr2Line(f->f_code, f->f_lasti); + return PyCode_Addr2Line(f->f_code, f->f_lasti); +} - return PyLong_FromLong(lineno); +static PyObject * +frame_getlineno(PyFrameObject *f, void *closure) +{ + return PyLong_FromLong(PyFrame_GetLineNumber(f)); } /* Setter for f_lineno - you can set f_lineno from within a trace function in @@ -345,16 +347,14 @@ frame_gettrace(PyFrameObject *f, void *closure) static int frame_settrace(PyFrameObject *f, PyObject* v, void *closure) { - /* We rely on f_lineno being accurate when f_trace is set. */ + PyObject* old_value; - PyObject* old_value = f->f_trace; + /* We rely on f_lineno being accurate when f_trace is set. */ + f->f_lineno = PyFrame_GetLineNumber(f); + old_value = f->f_trace; Py_XINCREF(v); f->f_trace = v; - - if (v != NULL) - f->f_lineno = PyCode_Addr2Line(f->f_code, f->f_lasti); - Py_XDECREF(old_value); return 0; @@ -391,7 +391,7 @@ static PyGetSetDef frame_getsetlist[] = { the local variables in f_localsplus are NULL. 2. We also maintain a separate free list of stack frames (just like - integers are allocated in a special way -- see intobject.c). When + floats are allocated in a special way -- see floatobject.c). When a stack frame is on the free list, only the following members have a meaning: ob_type == &Frametype diff --git a/Objects/funcobject.c b/Objects/funcobject.c index c2ad964..45f9f57 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -3,7 +3,6 @@ #include "Python.h" #include "code.h" -#include "eval.h" #include "structmember.h" PyObject * @@ -628,7 +627,7 @@ function_call(PyObject *func, PyObject *arg, PyObject *kw) } result = PyEval_EvalCodeEx( - (PyCodeObject *)PyFunction_GET_CODE(func), + PyFunction_GET_CODE(func), PyFunction_GET_GLOBALS(func), (PyObject *)NULL, &PyTuple_GET_ITEM(arg, 0), PyTuple_GET_SIZE(arg), k, nk, d, nd, diff --git a/Objects/genobject.c b/Objects/genobject.c index 34ee7dc..3fa1b4e 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -2,8 +2,6 @@ #include "Python.h" #include "frameobject.h" -#include "genobject.h" -#include "ceval.h" #include "structmember.h" #include "opcode.h" diff --git a/Objects/iterobject.c b/Objects/iterobject.c index b534b4a..91a93f5 100644 --- a/Objects/iterobject.c +++ b/Objects/iterobject.c @@ -177,9 +177,7 @@ calliter_iternext(calliterobject *it) Py_DECREF(args); if (result != NULL) { int ok; - ok = PyObject_RichCompareBool(result, - it->it_sentinel, - Py_EQ); + ok = PyObject_RichCompareBool(it->it_sentinel, result, Py_EQ); if (ok == 0) return result; /* Common case, fast path */ Py_DECREF(result); diff --git a/Objects/listobject.c b/Objects/listobject.c index b3bb21d..73624f0 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -940,6 +940,71 @@ reverse_slice(PyObject **lo, PyObject **hi) * pieces to this algorithm; read listsort.txt for overviews and details. */ +/* A sortslice contains a pointer to an array of keys and a pointer to + * an array of corresponding values. In other words, keys[i] + * corresponds with values[i]. If values == NULL, then the keys are + * also the values. + * + * Several convenience routines are provided here, so that keys and + * values are always moved in sync. + */ + +typedef struct { + PyObject **keys; + PyObject **values; +} sortslice; + +Py_LOCAL_INLINE(void) +sortslice_copy(sortslice *s1, Py_ssize_t i, sortslice *s2, Py_ssize_t j) +{ + s1->keys[i] = s2->keys[j]; + if (s1->values != NULL) + s1->values[i] = s2->values[j]; +} + +Py_LOCAL_INLINE(void) +sortslice_copy_incr(sortslice *dst, sortslice *src) +{ + *dst->keys++ = *src->keys++; + if (dst->values != NULL) + *dst->values++ = *src->values++; +} + +Py_LOCAL_INLINE(void) +sortslice_copy_decr(sortslice *dst, sortslice *src) +{ + *dst->keys-- = *src->keys--; + if (dst->values != NULL) + *dst->values-- = *src->values--; +} + + +Py_LOCAL_INLINE(void) +sortslice_memcpy(sortslice *s1, Py_ssize_t i, sortslice *s2, Py_ssize_t j, + Py_ssize_t n) +{ + memcpy(&s1->keys[i], &s2->keys[j], sizeof(PyObject *) * n); + if (s1->values != NULL) + memcpy(&s1->values[i], &s2->values[j], sizeof(PyObject *) * n); +} + +Py_LOCAL_INLINE(void) +sortslice_memmove(sortslice *s1, Py_ssize_t i, sortslice *s2, Py_ssize_t j, + Py_ssize_t n) +{ + memmove(&s1->keys[i], &s2->keys[j], sizeof(PyObject *) * n); + if (s1->values != NULL) + memmove(&s1->values[i], &s2->values[j], sizeof(PyObject *) * n); +} + +Py_LOCAL_INLINE(void) +sortslice_advance(sortslice *slice, Py_ssize_t n) +{ + slice->keys += n; + if (slice->values != NULL) + slice->values += n; +} + /* Comparison function: PyObject_RichCompareBool with Py_LT. * Returns -1 on error, 1 if x < y, 0 if x >= y. */ @@ -965,19 +1030,19 @@ reverse_slice(PyObject **lo, PyObject **hi) the input (nothing is lost or duplicated). */ static int -binarysort(PyObject **lo, PyObject **hi, PyObject **start) +binarysort(sortslice lo, PyObject **hi, PyObject **start) { register Py_ssize_t k; register PyObject **l, **p, **r; register PyObject *pivot; - assert(lo <= start && start <= hi); + assert(lo.keys <= start && start <= hi); /* assert [lo, start) is sorted */ - if (lo == start) + if (lo.keys == start) ++start; for (; start < hi; ++start) { /* set l to where *start belongs */ - l = lo; + l = lo.keys; r = start; pivot = *r; /* Invariants: @@ -1004,6 +1069,15 @@ binarysort(PyObject **lo, PyObject **hi, PyObject **start) for (p = start; p > l; --p) *p = *(p-1); *l = pivot; + if (lo.values != NULL) { + Py_ssize_t offset = lo.values - lo.keys; + p = start + offset; + pivot = *p; + l += offset; + for (p = start + offset; p > l; --p) + *p = *(p-1); + *l = pivot; + } } return 0; @@ -1272,7 +1346,7 @@ fail: * a convenient way to pass state around among the helper functions. */ struct s_slice { - PyObject **base; + sortslice base; Py_ssize_t len; }; @@ -1286,7 +1360,7 @@ typedef struct s_MergeState { /* 'a' is temp storage to help with merges. It contains room for * alloced entries. */ - PyObject **a; /* may point to temparray below */ + sortslice a; /* may point to temparray below */ Py_ssize_t alloced; /* A stack of n pending runs yet to be merged. Run #i starts at @@ -1307,11 +1381,29 @@ typedef struct s_MergeState { /* Conceptually a MergeState's constructor. */ static void -merge_init(MergeState *ms) +merge_init(MergeState *ms, Py_ssize_t list_size, int has_keyfunc) { assert(ms != NULL); - ms->a = ms->temparray; - ms->alloced = MERGESTATE_TEMP_SIZE; + if (has_keyfunc) { + /* The temporary space for merging will need at most half the list + * size rounded up. Use the minimum possible space so we can use the + * rest of temparray for other things. In particular, if there is + * enough extra space, listsort() will use it to store the keys. + */ + ms->alloced = (list_size + 1) / 2; + + /* ms->alloced describes how many keys will be stored at + ms->temparray, but we also need to store the values. Hence, + ms->alloced is capped at half of MERGESTATE_TEMP_SIZE. */ + if (MERGESTATE_TEMP_SIZE / 2 < ms->alloced) + ms->alloced = MERGESTATE_TEMP_SIZE / 2; + ms->a.values = &ms->temparray[ms->alloced]; + } + else { + ms->alloced = MERGESTATE_TEMP_SIZE; + ms->a.values = NULL; + } + ms->a.keys = ms->temparray; ms->n = 0; ms->min_gallop = MIN_GALLOP; } @@ -1324,10 +1416,8 @@ static void merge_freemem(MergeState *ms) { assert(ms != NULL); - if (ms->a != ms->temparray) - PyMem_Free(ms->a); - ms->a = ms->temparray; - ms->alloced = MERGESTATE_TEMP_SIZE; + if (ms->a.keys != ms->temparray) + PyMem_Free(ms->a.keys); } /* Ensure enough temp memory for 'need' array slots is available. @@ -1336,52 +1426,60 @@ merge_freemem(MergeState *ms) static int merge_getmem(MergeState *ms, Py_ssize_t need) { + int multiplier; + assert(ms != NULL); if (need <= ms->alloced) return 0; + + multiplier = ms->a.values != NULL ? 2 : 1; + /* Don't realloc! That can cost cycles to copy the old data, but * we don't care what's in the block. */ merge_freemem(ms); - if ((size_t)need > PY_SSIZE_T_MAX / sizeof(PyObject*)) { + if ((size_t)need > PY_SSIZE_T_MAX / sizeof(PyObject*) / multiplier) { PyErr_NoMemory(); return -1; } - ms->a = (PyObject **)PyMem_Malloc(need * sizeof(PyObject*)); - if (ms->a) { + ms->a.keys = (PyObject**)PyMem_Malloc(multiplier * need + * sizeof(PyObject *)); + if (ms->a.keys != NULL) { ms->alloced = need; + if (ms->a.values != NULL) + ms->a.values = &ms->a.keys[need]; return 0; } PyErr_NoMemory(); - merge_freemem(ms); /* reset to sane state */ return -1; } #define MERGE_GETMEM(MS, NEED) ((NEED) <= (MS)->alloced ? 0 : \ merge_getmem(MS, NEED)) -/* Merge the na elements starting at pa with the nb elements starting at pb - * in a stable way, in-place. na and nb must be > 0, and pa + na == pb. - * Must also have that *pb < *pa, that pa[na-1] belongs at the end of the - * merge, and should have na <= nb. See listsort.txt for more info. - * Return 0 if successful, -1 if error. +/* Merge the na elements starting at ssa with the nb elements starting at + * ssb.keys = ssa.keys + na in a stable way, in-place. na and nb must be > 0. + * Must also have that ssa.keys[na-1] belongs at the end of the merge, and + * should have na <= nb. See listsort.txt for more info. Return 0 if + * successful, -1 if error. */ static Py_ssize_t -merge_lo(MergeState *ms, PyObject **pa, Py_ssize_t na, - PyObject **pb, Py_ssize_t nb) +merge_lo(MergeState *ms, sortslice ssa, Py_ssize_t na, + sortslice ssb, Py_ssize_t nb) { Py_ssize_t k; - PyObject **dest; + sortslice dest; int result = -1; /* guilty until proved innocent */ Py_ssize_t min_gallop; - assert(ms && pa && pb && na > 0 && nb > 0 && pa + na == pb); + assert(ms && ssa.keys && ssb.keys && na > 0 && nb > 0); + assert(ssa.keys + na == ssb.keys); if (MERGE_GETMEM(ms, na) < 0) return -1; - memcpy(ms->a, pa, na * sizeof(PyObject*)); - dest = pa; - pa = ms->a; + sortslice_memcpy(&ms->a, 0, &ssa, 0, na); + dest = ssa; + ssa = ms->a; - *dest++ = *pb++; + sortslice_copy_incr(&dest, &ssb); --nb; if (nb == 0) goto Succeed; @@ -1398,11 +1496,11 @@ merge_lo(MergeState *ms, PyObject **pa, Py_ssize_t na, */ for (;;) { assert(na > 1 && nb > 0); - k = ISLT(*pb, *pa); + k = ISLT(ssb.keys[0], ssa.keys[0]); if (k) { if (k < 0) goto Fail; - *dest++ = *pb++; + sortslice_copy_incr(&dest, &ssb); ++bcount; acount = 0; --nb; @@ -1412,7 +1510,7 @@ merge_lo(MergeState *ms, PyObject **pa, Py_ssize_t na, break; } else { - *dest++ = *pa++; + sortslice_copy_incr(&dest, &ssa); ++acount; bcount = 0; --na; @@ -1433,14 +1531,14 @@ merge_lo(MergeState *ms, PyObject **pa, Py_ssize_t na, assert(na > 1 && nb > 0); min_gallop -= min_gallop > 1; ms->min_gallop = min_gallop; - k = gallop_right(*pb, pa, na, 0); + k = gallop_right(ssb.keys[0], ssa.keys, na, 0); acount = k; if (k) { if (k < 0) goto Fail; - memcpy(dest, pa, k * sizeof(PyObject *)); - dest += k; - pa += k; + sortslice_memcpy(&dest, 0, &ssa, 0, k); + sortslice_advance(&dest, k); + sortslice_advance(&ssa, k); na -= k; if (na == 1) goto CopyB; @@ -1451,24 +1549,24 @@ merge_lo(MergeState *ms, PyObject **pa, Py_ssize_t na, if (na == 0) goto Succeed; } - *dest++ = *pb++; + sortslice_copy_incr(&dest, &ssb); --nb; if (nb == 0) goto Succeed; - k = gallop_left(*pa, pb, nb, 0); + k = gallop_left(ssa.keys[0], ssb.keys, nb, 0); bcount = k; if (k) { if (k < 0) goto Fail; - memmove(dest, pb, k * sizeof(PyObject *)); - dest += k; - pb += k; + sortslice_memmove(&dest, 0, &ssb, 0, k); + sortslice_advance(&dest, k); + sortslice_advance(&ssb, k); nb -= k; if (nb == 0) goto Succeed; } - *dest++ = *pa++; + sortslice_copy_incr(&dest, &ssa); --na; if (na == 1) goto CopyB; @@ -1480,43 +1578,46 @@ Succeed: result = 0; Fail: if (na) - memcpy(dest, pa, na * sizeof(PyObject*)); + sortslice_memcpy(&dest, 0, &ssa, 0, na); return result; CopyB: assert(na == 1 && nb > 0); - /* The last element of pa belongs at the end of the merge. */ - memmove(dest, pb, nb * sizeof(PyObject *)); - dest[nb] = *pa; + /* The last element of ssa belongs at the end of the merge. */ + sortslice_memmove(&dest, 0, &ssb, 0, nb); + sortslice_copy(&dest, nb, &ssa, 0); return 0; } -/* Merge the na elements starting at pa with the nb elements starting at pb - * in a stable way, in-place. na and nb must be > 0, and pa + na == pb. - * Must also have that *pb < *pa, that pa[na-1] belongs at the end of the - * merge, and should have na >= nb. See listsort.txt for more info. - * Return 0 if successful, -1 if error. +/* Merge the na elements starting at pa with the nb elements starting at + * ssb.keys = ssa.keys + na in a stable way, in-place. na and nb must be > 0. + * Must also have that ssa.keys[na-1] belongs at the end of the merge, and + * should have na >= nb. See listsort.txt for more info. Return 0 if + * successful, -1 if error. */ static Py_ssize_t -merge_hi(MergeState *ms, PyObject **pa, Py_ssize_t na, PyObject **pb, Py_ssize_t nb) +merge_hi(MergeState *ms, sortslice ssa, Py_ssize_t na, + sortslice ssb, Py_ssize_t nb) { Py_ssize_t k; - PyObject **dest; + sortslice dest, basea, baseb; int result = -1; /* guilty until proved innocent */ - PyObject **basea; - PyObject **baseb; Py_ssize_t min_gallop; - assert(ms && pa && pb && na > 0 && nb > 0 && pa + na == pb); + assert(ms && ssa.keys && ssb.keys && na > 0 && nb > 0); + assert(ssa.keys + na == ssb.keys); if (MERGE_GETMEM(ms, nb) < 0) return -1; - dest = pb + nb - 1; - memcpy(ms->a, pb, nb * sizeof(PyObject*)); - basea = pa; + dest = ssb; + sortslice_advance(&dest, nb-1); + sortslice_memcpy(&ms->a, 0, &ssb, 0, nb); + basea = ssa; baseb = ms->a; - pb = ms->a + nb - 1; - pa += na - 1; + ssb.keys = ms->a.keys + nb - 1; + if (ssb.values != NULL) + ssb.values = ms->a.values + nb - 1; + sortslice_advance(&ssa, na - 1); - *dest-- = *pa--; + sortslice_copy_decr(&dest, &ssa); --na; if (na == 0) goto Succeed; @@ -1533,11 +1634,11 @@ merge_hi(MergeState *ms, PyObject **pa, Py_ssize_t na, PyObject **pb, Py_ssize_t */ for (;;) { assert(na > 0 && nb > 1); - k = ISLT(*pb, *pa); + k = ISLT(ssb.keys[0], ssa.keys[0]); if (k) { if (k < 0) goto Fail; - *dest-- = *pa--; + sortslice_copy_decr(&dest, &ssa); ++acount; bcount = 0; --na; @@ -1547,7 +1648,7 @@ merge_hi(MergeState *ms, PyObject **pa, Py_ssize_t na, PyObject **pb, Py_ssize_t break; } else { - *dest-- = *pb--; + sortslice_copy_decr(&dest, &ssb); ++bcount; acount = 0; --nb; @@ -1568,33 +1669,33 @@ merge_hi(MergeState *ms, PyObject **pa, Py_ssize_t na, PyObject **pb, Py_ssize_t assert(na > 0 && nb > 1); min_gallop -= min_gallop > 1; ms->min_gallop = min_gallop; - k = gallop_right(*pb, basea, na, na-1); + k = gallop_right(ssb.keys[0], basea.keys, na, na-1); if (k < 0) goto Fail; k = na - k; acount = k; if (k) { - dest -= k; - pa -= k; - memmove(dest+1, pa+1, k * sizeof(PyObject *)); + sortslice_advance(&dest, -k); + sortslice_advance(&ssa, -k); + sortslice_memmove(&dest, 1, &ssa, 1, k); na -= k; if (na == 0) goto Succeed; } - *dest-- = *pb--; + sortslice_copy_decr(&dest, &ssb); --nb; if (nb == 1) goto CopyA; - k = gallop_left(*pa, baseb, nb, nb-1); + k = gallop_left(ssa.keys[0], baseb.keys, nb, nb-1); if (k < 0) goto Fail; k = nb - k; bcount = k; if (k) { - dest -= k; - pb -= k; - memcpy(dest+1, pb+1, k * sizeof(PyObject *)); + sortslice_advance(&dest, -k); + sortslice_advance(&ssb, -k); + sortslice_memcpy(&dest, 1, &ssb, 1, k); nb -= k; if (nb == 1) goto CopyA; @@ -1605,7 +1706,7 @@ merge_hi(MergeState *ms, PyObject **pa, Py_ssize_t na, PyObject **pb, Py_ssize_t if (nb == 0) goto Succeed; } - *dest-- = *pa--; + sortslice_copy_decr(&dest, &ssa); --na; if (na == 0) goto Succeed; @@ -1617,15 +1718,15 @@ Succeed: result = 0; Fail: if (nb) - memcpy(dest-(nb-1), baseb, nb * sizeof(PyObject*)); + sortslice_memcpy(&dest, -(nb-1), &baseb, 0, nb); return result; CopyA: assert(nb == 1 && na > 0); - /* The first element of pb belongs at the front of the merge. */ - dest -= na; - pa -= na; - memmove(dest+1, pa+1, na * sizeof(PyObject *)); - *dest = *pb; + /* The first element of ssb belongs at the front of the merge. */ + sortslice_memmove(&dest, 1-na, &ssa, 1-na, na); + sortslice_advance(&dest, -na); + sortslice_advance(&ssa, -na); + sortslice_copy(&dest, 0, &ssb, 0); return 0; } @@ -1635,7 +1736,7 @@ CopyA: static Py_ssize_t merge_at(MergeState *ms, Py_ssize_t i) { - PyObject **pa, **pb; + sortslice ssa, ssb; Py_ssize_t na, nb; Py_ssize_t k; @@ -1644,12 +1745,12 @@ merge_at(MergeState *ms, Py_ssize_t i) assert(i >= 0); assert(i == ms->n - 2 || i == ms->n - 3); - pa = ms->pending[i].base; + ssa = ms->pending[i].base; na = ms->pending[i].len; - pb = ms->pending[i+1].base; + ssb = ms->pending[i+1].base; nb = ms->pending[i+1].len; assert(na > 0 && nb > 0); - assert(pa + na == pb); + assert(ssa.keys + na == ssb.keys); /* Record the length of the combined runs; if i is the 3rd-last * run now, also slide over the last run (which isn't involved @@ -1663,10 +1764,10 @@ merge_at(MergeState *ms, Py_ssize_t i) /* Where does b start in a? Elements in a before that can be * ignored (already in place). */ - k = gallop_right(*pb, pa, na, 0); + k = gallop_right(*ssb.keys, ssa.keys, na, 0); if (k < 0) return -1; - pa += k; + sortslice_advance(&ssa, k); na -= k; if (na == 0) return 0; @@ -1674,7 +1775,7 @@ merge_at(MergeState *ms, Py_ssize_t i) /* Where does a end in b? Elements in b after that can be * ignored (already in place). */ - nb = gallop_left(pa[na-1], pb, nb, nb-1); + nb = gallop_left(ssa.keys[na-1], ssb.keys, nb, nb-1); if (nb <= 0) return nb; @@ -1682,9 +1783,9 @@ merge_at(MergeState *ms, Py_ssize_t i) * min(na, nb) elements. */ if (na <= nb) - return merge_lo(ms, pa, na, pb, nb); + return merge_lo(ms, ssa, na, ssb, nb); else - return merge_hi(ms, pa, na, pb, nb); + return merge_hi(ms, ssa, na, ssb, nb); } /* Examine the stack of runs waiting to be merged, merging adjacent runs @@ -1765,103 +1866,12 @@ merge_compute_minrun(Py_ssize_t n) return n + r; } -/* Special wrapper to support stable sorting using the decorate-sort-undecorate - pattern. Holds a key which is used for comparisons and the original record - which is returned during the undecorate phase. By exposing only the key - during comparisons, the underlying sort stability characteristics are left - unchanged. Also, the comparison function will only see the key instead of - a full record. */ - -typedef struct { - PyObject_HEAD - PyObject *key; - PyObject *value; -} sortwrapperobject; - -PyDoc_STRVAR(sortwrapper_doc, "Object wrapper with a custom sort key."); -static PyObject * -sortwrapper_richcompare(sortwrapperobject *, sortwrapperobject *, int); static void -sortwrapper_dealloc(sortwrapperobject *); - -PyTypeObject PySortWrapper_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "sortwrapper", /* tp_name */ - sizeof(sortwrapperobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)sortwrapper_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - sortwrapper_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - (richcmpfunc)sortwrapper_richcompare, /* tp_richcompare */ -}; - - -static PyObject * -sortwrapper_richcompare(sortwrapperobject *a, sortwrapperobject *b, int op) -{ - if (!PyObject_TypeCheck(b, &PySortWrapper_Type)) { - PyErr_SetString(PyExc_TypeError, - "expected a sortwrapperobject"); - return NULL; - } - return PyObject_RichCompare(a->key, b->key, op); -} - -static void -sortwrapper_dealloc(sortwrapperobject *so) +reverse_sortslice(sortslice *s, Py_ssize_t n) { - Py_XDECREF(so->key); - Py_XDECREF(so->value); - PyObject_Del(so); -} - -/* Returns a new reference to a sortwrapper. - Consumes the references to the two underlying objects. */ - -static PyObject * -build_sortwrapper(PyObject *key, PyObject *value) -{ - sortwrapperobject *so; - - so = PyObject_New(sortwrapperobject, &PySortWrapper_Type); - if (so == NULL) - return NULL; - so->key = key; - so->value = value; - return (PyObject *)so; -} - -/* Returns a new reference to the value underlying the wrapper. */ -static PyObject * -sortwrapper_getvalue(PyObject *so) -{ - PyObject *value; - - if (!PyObject_TypeCheck(so, &PySortWrapper_Type)) { - PyErr_SetString(PyExc_TypeError, - "expected a sortwrapperobject"); - return NULL; - } - value = ((sortwrapperobject *)so)->value; - Py_INCREF(value); - return value; + reverse_slice(s->keys, &s->keys[n]); + if (s->values != NULL) + reverse_slice(s->values, &s->values[n]); } /* An adaptive, stable, natural mergesort. See listsort.txt. @@ -1873,9 +1883,9 @@ static PyObject * listsort(PyListObject *self, PyObject *args, PyObject *kwds) { MergeState ms; - PyObject **lo, **hi; Py_ssize_t nremaining; Py_ssize_t minrun; + sortslice lo; Py_ssize_t saved_ob_size, saved_allocated; PyObject **saved_ob_item; PyObject **final_ob_item; @@ -1883,8 +1893,8 @@ listsort(PyListObject *self, PyObject *args, PyObject *kwds) int reverse = 0; PyObject *keyfunc = NULL; Py_ssize_t i; - PyObject *key, *value, *kvpair; static char *kwlist[] = {"key", "reverse", 0}; + PyObject **keys; assert(self != NULL); assert (PyList_Check(self)); @@ -1913,59 +1923,70 @@ listsort(PyListObject *self, PyObject *args, PyObject *kwds) self->ob_item = NULL; self->allocated = -1; /* any operation will reset it to >= 0 */ - if (keyfunc != NULL) { - for (i=0 ; i < saved_ob_size ; i++) { - value = saved_ob_item[i]; - key = PyObject_CallFunctionObjArgs(keyfunc, value, - NULL); - if (key == NULL) { - for (i=i-1 ; i>=0 ; i--) { - kvpair = saved_ob_item[i]; - value = sortwrapper_getvalue(kvpair); - saved_ob_item[i] = value; - Py_DECREF(kvpair); - } - goto dsu_fail; + if (keyfunc == NULL) { + keys = NULL; + lo.keys = saved_ob_item; + lo.values = NULL; + } + else { + if (saved_ob_size < MERGESTATE_TEMP_SIZE/2) + /* Leverage stack space we allocated but won't otherwise use */ + keys = &ms.temparray[saved_ob_size+1]; + else { + keys = PyMem_MALLOC(sizeof(PyObject *) * saved_ob_size); + if (keys == NULL) + return NULL; + } + + for (i = 0; i < saved_ob_size ; i++) { + keys[i] = PyObject_CallFunctionObjArgs(keyfunc, saved_ob_item[i], + NULL); + if (keys[i] == NULL) { + for (i=i-1 ; i>=0 ; i--) + Py_DECREF(keys[i]); + if (keys != &ms.temparray[saved_ob_size+1]) + PyMem_FREE(keys); + goto keyfunc_fail; } - kvpair = build_sortwrapper(key, value); - if (kvpair == NULL) - goto dsu_fail; - saved_ob_item[i] = kvpair; } - } - /* Reverse sort stability achieved by initially reversing the list, - applying a stable forward sort, then reversing the final result. */ - if (reverse && saved_ob_size > 1) - reverse_slice(saved_ob_item, saved_ob_item + saved_ob_size); + lo.keys = keys; + lo.values = saved_ob_item; + } - merge_init(&ms); + merge_init(&ms, saved_ob_size, keys != NULL); nremaining = saved_ob_size; if (nremaining < 2) goto succeed; + /* Reverse sort stability achieved by initially reversing the list, + applying a stable forward sort, then reversing the final result. */ + if (reverse) { + if (keys != NULL) + reverse_slice(&keys[0], &keys[saved_ob_size]); + reverse_slice(&saved_ob_item[0], &saved_ob_item[saved_ob_size]); + } + /* March over the array once, left to right, finding natural runs, * and extending short natural runs to minrun elements. */ - lo = saved_ob_item; - hi = lo + nremaining; minrun = merge_compute_minrun(nremaining); do { int descending; Py_ssize_t n; /* Identify next run. */ - n = count_run(lo, hi, &descending); + n = count_run(lo.keys, lo.keys + nremaining, &descending); if (n < 0) goto fail; if (descending) - reverse_slice(lo, lo + n); + reverse_sortslice(&lo, n); /* If short, extend to min(minrun, nremaining). */ if (n < minrun) { const Py_ssize_t force = nremaining <= minrun ? nremaining : minrun; - if (binarysort(lo, lo + force, lo + n) < 0) + if (binarysort(lo, lo.keys + force, lo.keys + n) < 0) goto fail; n = force; } @@ -1977,27 +1998,27 @@ listsort(PyListObject *self, PyObject *args, PyObject *kwds) if (merge_collapse(&ms) < 0) goto fail; /* Advance to find next run. */ - lo += n; + sortslice_advance(&lo, n); nremaining -= n; } while (nremaining); - assert(lo == hi); if (merge_force_collapse(&ms) < 0) goto fail; assert(ms.n == 1); - assert(ms.pending[0].base == saved_ob_item); + assert(keys == NULL + ? ms.pending[0].base.keys == saved_ob_item + : ms.pending[0].base.keys == &keys[0]); assert(ms.pending[0].len == saved_ob_size); + lo = ms.pending[0].base; succeed: result = Py_None; fail: - if (keyfunc != NULL) { - for (i=0 ; i < saved_ob_size ; i++) { - kvpair = saved_ob_item[i]; - value = sortwrapper_getvalue(kvpair); - saved_ob_item[i] = value; - Py_DECREF(kvpair); - } + if (keys != NULL) { + for (i = 0; i < saved_ob_size; i++) + Py_DECREF(keys[i]); + if (keys != &ms.temparray[saved_ob_size+1]) + PyMem_FREE(keys); } if (self->allocated != -1 && result != NULL) { @@ -2013,7 +2034,7 @@ fail: merge_freemem(&ms); -dsu_fail: +keyfunc_fail: final_ob_item = self->ob_item; i = Py_SIZE(self); Py_SIZE(self) = saved_ob_size; @@ -2098,7 +2119,8 @@ static PyObject * listindex(PyListObject *self, PyObject *args) { Py_ssize_t i, start=0, stop=Py_SIZE(self); - PyObject *v; + PyObject *v, *format_tuple, *err_string; + static PyObject *err_format = NULL; if (!PyArg_ParseTuple(args, "O|O&O&:index", &v, _PyEval_SliceIndex, &start, @@ -2121,7 +2143,20 @@ listindex(PyListObject *self, PyObject *args) else if (cmp < 0) return NULL; } - PyErr_SetString(PyExc_ValueError, "list.index(x): x not in list"); + if (err_format == NULL) { + err_format = PyUnicode_FromString("%r is not in list"); + if (err_format == NULL) + return NULL; + } + format_tuple = PyTuple_Pack(1, v); + if (format_tuple == NULL) + return NULL; + err_string = PyUnicode_Format(err_format, format_tuple); + Py_DECREF(format_tuple); + if (err_string == NULL) + return NULL; + PyErr_SetObject(PyExc_ValueError, err_string); + Py_DECREF(err_string); return NULL; } @@ -2364,7 +2399,7 @@ list_subscript(PyListObject* self, PyObject* item) PyObject* it; PyObject **src, **dest; - if (PySlice_GetIndicesEx((PySliceObject*)item, Py_SIZE(self), + if (PySlice_GetIndicesEx(item, Py_SIZE(self), &start, &stop, &step, &slicelength) < 0) { return NULL; } @@ -2413,7 +2448,7 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value) else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((PySliceObject*)item, Py_SIZE(self), + if (PySlice_GetIndicesEx(item, Py_SIZE(self), &start, &stop, &step, &slicelength) < 0) { return -1; } @@ -2582,7 +2617,7 @@ PyTypeObject PyList_Type = { 0, /* tp_as_number */ &list_as_sequence, /* tp_as_sequence */ &list_as_mapping, /* tp_as_mapping */ - (hashfunc)PyObject_HashNotImplemented, /* tp_hash */ + PyObject_HashNotImplemented, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ @@ -2848,4 +2883,3 @@ listreviter_len(listreviterobject *it) len = 0; return PyLong_FromSsize_t(len); } - diff --git a/Objects/lnotab_notes.txt b/Objects/lnotab_notes.txt new file mode 100644 index 0000000..d247edd --- /dev/null +++ b/Objects/lnotab_notes.txt @@ -0,0 +1,124 @@ +All about co_lnotab, the line number table. + +Code objects store a field named co_lnotab. This is an array of unsigned bytes +disguised as a Python string. It is used to map bytecode offsets to source code +line #s for tracebacks and to identify line number boundaries for line tracing. + +The array is conceptually a compressed list of + (bytecode offset increment, line number increment) +pairs. The details are important and delicate, best illustrated by example: + + byte code offset source code line number + 0 1 + 6 2 + 50 7 + 350 307 + 361 308 + +Instead of storing these numbers literally, we compress the list by storing only +the increments from one row to the next. Conceptually, the stored list might +look like: + + 0, 1, 6, 1, 44, 5, 300, 300, 11, 1 + +The above doesn't really work, but it's a start. Note that an unsigned byte +can't hold negative values, or values larger than 255, and the above example +contains two such values. So we make two tweaks: + + (a) there's a deep assumption that byte code offsets and their corresponding + line #s both increase monotonically, and + (b) if at least one column jumps by more than 255 from one row to the next, + more than one pair is written to the table. In case #b, there's no way to know + from looking at the table later how many were written. That's the delicate + part. A user of co_lnotab desiring to find the source line number + corresponding to a bytecode address A should do something like this + + lineno = addr = 0 + for addr_incr, line_incr in co_lnotab: + addr += addr_incr + if addr > A: + return lineno + lineno += line_incr + +(In C, this is implemented by PyCode_Addr2Line().) In order for this to work, +when the addr field increments by more than 255, the line # increment in each +pair generated must be 0 until the remaining addr increment is < 256. So, in +the example above, assemble_lnotab in compile.c should not (as was actually done +until 2.2) expand 300, 300 to + 255, 255, 45, 45, +but to + 255, 0, 45, 255, 0, 45. + +The above is sufficient to reconstruct line numbers for tracebacks, but not for +line tracing. Tracing is handled by PyCode_CheckLineNumber() in codeobject.c +and maybe_call_line_trace() in ceval.c. + +*** Tracing *** + +To a first approximation, we want to call the tracing function when the line +number of the current instruction changes. Re-computing the current line for +every instruction is a little slow, though, so each time we compute the line +number we save the bytecode indices where it's valid: + + *instr_lb <= frame->f_lasti < *instr_ub + +is true so long as execution does not change lines. That is, *instr_lb holds +the first bytecode index of the current line, and *instr_ub holds the first +bytecode index of the next line. As long as the above expression is true, +maybe_call_line_trace() does not need to call PyCode_CheckLineNumber(). Note +that the same line may appear multiple times in the lnotab, either because the +bytecode jumped more than 255 indices between line number changes or because +the compiler inserted the same line twice. Even in that case, *instr_ub holds +the first index of the next line. + +However, we don't *always* want to call the line trace function when the above +test fails. + +Consider this code: + +1: def f(a): +2: while a: +3: print 1, +4: break +5: else: +6: print 2, + +which compiles to this: + + 2 0 SETUP_LOOP 19 (to 22) + >> 3 LOAD_FAST 0 (a) + 6 POP_JUMP_IF_FALSE 17 + + 3 9 LOAD_CONST 1 (1) + 12 PRINT_ITEM + + 4 13 BREAK_LOOP + 14 JUMP_ABSOLUTE 3 + >> 17 POP_BLOCK + + 6 18 LOAD_CONST 2 (2) + 21 PRINT_ITEM + >> 22 LOAD_CONST 0 (None) + 25 RETURN_VALUE + +If 'a' is false, execution will jump to the POP_BLOCK instruction at offset 17 +and the co_lnotab will claim that execution has moved to line 4, which is wrong. +In this case, we could instead associate the POP_BLOCK with line 5, but that +would break jumps around loops without else clauses. + +We fix this by only calling the line trace function for a forward jump if the +co_lnotab indicates we have jumped to the *start* of a line, i.e. if the current +instruction offset matches the offset given for the start of a line by the +co_lnotab. For backward jumps, however, we always call the line trace function, +which lets a debugger stop on every evaluation of a loop guard (which usually +won't be the first opcode in a line). + +Why do we set f_lineno when tracing, and only just before calling the trace +function? Well, consider the code above when 'a' is true. If stepping through +this with 'n' in pdb, you would stop at line 1 with a "call" type event, then +line events on lines 2, 3, and 4, then a "return" type event -- but because the +code for the return actually falls in the range of the "line 6" opcodes, you +would be shown line 6 during this event. This is a change from the behaviour in +2.2 and before, and I've found it confusing in practice. By setting and using +f_lineno when tracing, one can report a line number different from that +suggested by f_lasti on this one occasion where it's desirable. diff --git a/Objects/longobject.c b/Objects/longobject.c index 6f998ce..552f8f0 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -4,7 +4,6 @@ #include "Python.h" #include "longintrepr.h" -#include "structseq.h" #include <float.h> #include <ctype.h> @@ -95,14 +94,10 @@ maybe_small_long(PyLongObject *v) #define MAX(x, y) ((x) < (y) ? (y) : (x)) #define MIN(x, y) ((x) > (y) ? (y) : (x)) -#define SIGCHECK(PyTryBlock) \ - if (--_Py_Ticker < 0) { \ - _Py_Ticker = _Py_CheckInterval; \ - if (PyErr_CheckSignals()) PyTryBlock \ - } - -/* forward declaration */ -static int bits_in_digit(digit d); +#define SIGCHECK(PyTryBlock) \ + do { \ + if (PyErr_CheckSignals()) PyTryBlock \ + } while(0) /* Normalize (remove leading zeros from) a long int object. Doesn't attempt to free the storage--in most cases, due to the nature @@ -284,12 +279,12 @@ PyLong_FromDouble(double dval) neg = 0; if (Py_IS_INFINITY(dval)) { PyErr_SetString(PyExc_OverflowError, - "cannot convert float infinity to integer"); + "cannot convert float infinity to integer"); return NULL; } if (Py_IS_NAN(dval)) { PyErr_SetString(PyExc_ValueError, - "cannot convert float NaN to integer"); + "cannot convert float NaN to integer"); return NULL; } if (dval < 0.0) { @@ -349,9 +344,10 @@ PyLong_AsLongAndOverflow(PyObject *vv, int *overflow) if (!PyLong_Check(vv)) { PyNumberMethods *nb; - if ((nb = vv->ob_type->tp_as_number) == NULL || - nb->nb_int == NULL) { - PyErr_SetString(PyExc_TypeError, "an integer is required"); + nb = vv->ob_type->tp_as_number; + if (nb == NULL || nb->nb_int == NULL) { + PyErr_SetString(PyExc_TypeError, + "an integer is required"); return -1; } vv = (*nb->nb_int) (vv); @@ -389,14 +385,14 @@ PyLong_AsLongAndOverflow(PyObject *vv, int *overflow) } while (--i >= 0) { prev = x; - x = (x << PyLong_SHIFT) + v->ob_digit[i]; + x = (x << PyLong_SHIFT) | v->ob_digit[i]; if ((x >> PyLong_SHIFT) != prev) { - *overflow = Py_SIZE(v) > 0 ? 1 : -1; + *overflow = sign; goto exit; } } - /* Haven't lost any bits, but casting to long requires extra care - * (see comment above). + /* Haven't lost any bits, but casting to long requires extra + * care (see comment above). */ if (x <= (unsigned long)LONG_MAX) { res = (long)x * sign; @@ -405,11 +401,11 @@ PyLong_AsLongAndOverflow(PyObject *vv, int *overflow) res = LONG_MIN; } else { - *overflow = Py_SIZE(v) > 0 ? 1 : -1; + *overflow = sign; /* res is already set to -1 */ } } - exit: + exit: if (do_decref) { Py_DECREF(vv); } @@ -464,7 +460,7 @@ PyLong_AsSsize_t(PyObject *vv) { } while (--i >= 0) { prev = x; - x = (x << PyLong_SHIFT) + v->ob_digit[i]; + x = (x << PyLong_SHIFT) | v->ob_digit[i]; if ((x >> PyLong_SHIFT) != prev) goto overflow; } @@ -479,7 +475,7 @@ PyLong_AsSsize_t(PyObject *vv) { } /* else overflow */ - overflow: + overflow: PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C ssize_t"); return -1; @@ -509,7 +505,7 @@ PyLong_AsUnsignedLong(PyObject *vv) x = 0; if (i < 0) { PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to unsigned int"); + "can't convert negative value to unsigned int"); return (unsigned long) -1; } switch (i) { @@ -518,10 +514,11 @@ PyLong_AsUnsignedLong(PyObject *vv) } while (--i >= 0) { prev = x; - x = (x << PyLong_SHIFT) + v->ob_digit[i]; + x = (x << PyLong_SHIFT) | v->ob_digit[i]; if ((x >> PyLong_SHIFT) != prev) { PyErr_SetString(PyExc_OverflowError, - "python int too large to convert to C unsigned long"); + "python int too large to convert " + "to C unsigned long"); return (unsigned long) -1; } } @@ -561,7 +558,7 @@ PyLong_AsSize_t(PyObject *vv) } while (--i >= 0) { prev = x; - x = (x << PyLong_SHIFT) + v->ob_digit[i]; + x = (x << PyLong_SHIFT) | v->ob_digit[i]; if ((x >> PyLong_SHIFT) != prev) { PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C size_t"); @@ -599,7 +596,7 @@ _PyLong_AsUnsignedLongMask(PyObject *vv) i = -i; } while (--i >= 0) { - x = (x << PyLong_SHIFT) + v->ob_digit[i]; + x = (x << PyLong_SHIFT) | v->ob_digit[i]; } return x * sign; } @@ -676,7 +673,7 @@ _PyLong_NumBits(PyObject *vv) } return result; -Overflow: + Overflow: PyErr_SetString(PyExc_OverflowError, "int has too many bits " "to express in a platform size_t"); return (size_t)-1; @@ -686,7 +683,7 @@ PyObject * _PyLong_FromByteArray(const unsigned char* bytes, size_t n, int little_endian, int is_signed) { - const unsigned char* pstartbyte;/* LSB of bytes */ + const unsigned char* pstartbyte; /* LSB of bytes */ int incr; /* direction to move pstartbyte */ const unsigned char* pendbyte; /* MSB of bytes */ size_t numsignificantbytes; /* number of bytes that matter */ @@ -774,8 +771,7 @@ _PyLong_FromByteArray(const unsigned char* bytes, size_t n, if (accumbits >= PyLong_SHIFT) { /* There's enough to fill a Python digit. */ assert(idigit < ndigits); - v->ob_digit[idigit] = (digit)(accum & - PyLong_MASK); + v->ob_digit[idigit] = (digit)(accum & PyLong_MASK); ++idigit; accum >>= PyLong_SHIFT; accumbits -= PyLong_SHIFT; @@ -800,9 +796,9 @@ _PyLong_AsByteArray(PyLongObject* v, int little_endian, int is_signed) { Py_ssize_t i; /* index into v->ob_digit */ - Py_ssize_t ndigits; /* |v->ob_size| */ + Py_ssize_t ndigits; /* |v->ob_size| */ twodigits accum; /* sliding register */ - unsigned int accumbits; /* # bits in accum */ + unsigned int accumbits; /* # bits in accum */ int do_twos_comp; /* store 2's-comp? is_signed and v < 0 */ digit carry; /* for computing 2's-comp */ size_t j; /* # bytes filled */ @@ -815,7 +811,7 @@ _PyLong_AsByteArray(PyLongObject* v, ndigits = -(Py_SIZE(v)); if (!is_signed) { PyErr_SetString(PyExc_OverflowError, - "can't convert negative int to unsigned"); + "can't convert negative int to unsigned"); return -1; } do_twos_comp = 1; @@ -861,8 +857,7 @@ _PyLong_AsByteArray(PyLongObject* v, /* Count # of sign bits -- they needn't be stored, * although for signed conversion we need later to * make sure at least one sign bit gets stored. */ - digit s = do_twos_comp ? thisdigit ^ PyLong_MASK : - thisdigit; + digit s = do_twos_comp ? thisdigit ^ PyLong_MASK : thisdigit; while (s != 0) { s >>= 1; accumbits++; @@ -922,230 +917,12 @@ _PyLong_AsByteArray(PyLongObject* v, return 0; -Overflow: + Overflow: PyErr_SetString(PyExc_OverflowError, "int too big to convert"); return -1; } -double -_PyLong_AsScaledDouble(PyObject *vv, int *exponent) -{ -/* NBITS_WANTED should be > the number of bits in a double's precision, - but small enough so that 2**NBITS_WANTED is within the normal double - range. nbitsneeded is set to 1 less than that because the most-significant - Python digit contains at least 1 significant bit, but we don't want to - bother counting them (catering to the worst case cheaply). - - 57 is one more than VAX-D double precision; I (Tim) don't know of a double - format with more precision than that; it's 1 larger so that we add in at - least one round bit to stand in for the ignored least-significant bits. -*/ -#define NBITS_WANTED 57 - PyLongObject *v; - double x; - const double multiplier = (double)(1L << PyLong_SHIFT); - Py_ssize_t i; - int sign; - int nbitsneeded; - - if (vv == NULL || !PyLong_Check(vv)) { - PyErr_BadInternalCall(); - return -1; - } - v = (PyLongObject *)vv; - i = Py_SIZE(v); - sign = 1; - if (i < 0) { - sign = -1; - i = -(i); - } - else if (i == 0) { - *exponent = 0; - return 0.0; - } - --i; - x = (double)v->ob_digit[i]; - nbitsneeded = NBITS_WANTED - 1; - /* Invariant: i Python digits remain unaccounted for. */ - while (i > 0 && nbitsneeded > 0) { - --i; - x = x * multiplier + (double)v->ob_digit[i]; - nbitsneeded -= PyLong_SHIFT; - } - /* There are i digits we didn't shift in. Pretending they're all - zeroes, the true value is x * 2**(i*PyLong_SHIFT). */ - *exponent = i; - assert(x > 0.0); - return x * sign; -#undef NBITS_WANTED -} - -/* Get a C double from a long int object. Rounds to the nearest double, - using the round-half-to-even rule in the case of a tie. */ - -double -PyLong_AsDouble(PyObject *vv) -{ - PyLongObject *v = (PyLongObject *)vv; - Py_ssize_t rnd_digit, rnd_bit, m, n; - digit lsb, *d; - int round_up = 0; - double x; - - if (vv == NULL || !PyLong_Check(vv)) { - PyErr_BadInternalCall(); - return -1.0; - } - - /* Notes on the method: for simplicity, assume v is positive and >= - 2**DBL_MANT_DIG. (For negative v we just ignore the sign until the - end; for small v no rounding is necessary.) Write n for the number - of bits in v, so that 2**(n-1) <= v < 2**n, and n > DBL_MANT_DIG. - - Some terminology: the *rounding bit* of v is the 1st bit of v that - will be rounded away (bit n - DBL_MANT_DIG - 1); the *parity bit* - is the bit immediately above. The round-half-to-even rule says - that we round up if the rounding bit is set, unless v is exactly - halfway between two floats and the parity bit is zero. - - Write d[0] ... d[m] for the digits of v, least to most significant. - Let rnd_bit be the index of the rounding bit, and rnd_digit the - index of the PyLong digit containing the rounding bit. Then the - bits of the digit d[rnd_digit] look something like: - - rounding bit - | - v - msb -> sssssrttttttttt <- lsb - ^ - | - parity bit - - where 's' represents a 'significant bit' that will be included in - the mantissa of the result, 'r' is the rounding bit, and 't' - represents a 'trailing bit' following the rounding bit. Note that - if the rounding bit is at the top of d[rnd_digit] then the parity - bit will be the lsb of d[rnd_digit+1]. If we set - - lsb = 1 << (rnd_bit % PyLong_SHIFT) - - then d[rnd_digit] & (PyLong_BASE - 2*lsb) selects just the - significant bits of d[rnd_digit], d[rnd_digit] & (lsb-1) gets the - trailing bits, and d[rnd_digit] & lsb gives the rounding bit. - - We initialize the double x to the integer given by digits - d[rnd_digit:m-1], but with the rounding bit and trailing bits of - d[rnd_digit] masked out. So the value of x comes from the top - DBL_MANT_DIG bits of v, multiplied by 2*lsb. Note that in the loop - that produces x, all floating-point operations are exact (assuming - that FLT_RADIX==2). Now if we're rounding down, the value we want - to return is simply - - x * 2**(PyLong_SHIFT * rnd_digit). - - and if we're rounding up, it's - - (x + 2*lsb) * 2**(PyLong_SHIFT * rnd_digit). - - Under the round-half-to-even rule, we round up if, and only - if, the rounding bit is set *and* at least one of the - following three conditions is satisfied: - - (1) the parity bit is set, or - (2) at least one of the trailing bits of d[rnd_digit] is set, or - (3) at least one of the digits d[i], 0 <= i < rnd_digit - is nonzero. - - Finally, we have to worry about overflow. If v >= 2**DBL_MAX_EXP, - or equivalently n > DBL_MAX_EXP, then overflow occurs. If v < - 2**DBL_MAX_EXP then we're usually safe, but there's a corner case - to consider: if v is very close to 2**DBL_MAX_EXP then it's - possible that v is rounded up to exactly 2**DBL_MAX_EXP, and then - again overflow occurs. - */ - - if (Py_SIZE(v) == 0) - return 0.0; - m = ABS(Py_SIZE(v)) - 1; - d = v->ob_digit; - assert(d[m]); /* v should be normalized */ - - /* fast path for case where 0 < abs(v) < 2**DBL_MANT_DIG */ - if (m < DBL_MANT_DIG / PyLong_SHIFT || - (m == DBL_MANT_DIG / PyLong_SHIFT && - d[m] < (digit)1 << DBL_MANT_DIG%PyLong_SHIFT)) { - x = d[m]; - while (--m >= 0) - x = x*PyLong_BASE + d[m]; - return Py_SIZE(v) < 0 ? -x : x; - } - - /* if m is huge then overflow immediately; otherwise, compute the - number of bits n in v. The condition below implies n (= #bits) >= - m * PyLong_SHIFT + 1 > DBL_MAX_EXP, hence v >= 2**DBL_MAX_EXP. */ - if (m > (DBL_MAX_EXP-1)/PyLong_SHIFT) - goto overflow; - n = m * PyLong_SHIFT + bits_in_digit(d[m]); - if (n > DBL_MAX_EXP) - goto overflow; - - /* find location of rounding bit */ - assert(n > DBL_MANT_DIG); /* dealt with |v| < 2**DBL_MANT_DIG above */ - rnd_bit = n - DBL_MANT_DIG - 1; - rnd_digit = rnd_bit/PyLong_SHIFT; - lsb = (digit)1 << (rnd_bit%PyLong_SHIFT); - - /* Get top DBL_MANT_DIG bits of v. Assumes PyLong_SHIFT < - DBL_MANT_DIG, so we'll need bits from at least 2 digits of v. */ - x = d[m]; - assert(m > rnd_digit); - while (--m > rnd_digit) - x = x*PyLong_BASE + d[m]; - x = x*PyLong_BASE + (d[m] & (PyLong_BASE-2*lsb)); - - /* decide whether to round up, using round-half-to-even */ - assert(m == rnd_digit); - if (d[m] & lsb) { /* if (rounding bit is set) */ - digit parity_bit; - if (lsb == PyLong_BASE/2) - parity_bit = d[m+1] & 1; - else - parity_bit = d[m] & 2*lsb; - if (parity_bit) - round_up = 1; - else if (d[m] & (lsb-1)) - round_up = 1; - else { - while (--m >= 0) { - if (d[m]) { - round_up = 1; - break; - } - } - } - } - - /* and round up if necessary */ - if (round_up) { - x += 2*lsb; - if (n == DBL_MAX_EXP && - x == ldexp((double)(2*lsb), DBL_MANT_DIG)) { - /* overflow corner case */ - goto overflow; - } - } - - /* shift, adjust for sign, and return */ - x = ldexp(x, rnd_digit*PyLong_SHIFT); - return Py_SIZE(v) < 0 ? -x : x; - - overflow: - PyErr_SetString(PyExc_OverflowError, - "Python int too large to convert to C double"); - return -1.0; -} - /* Create a new long (or int) object from a C pointer */ PyObject * @@ -1209,6 +986,7 @@ PyLong_AsVoidPtr(PyObject *vv) */ #define IS_LITTLE_ENDIAN (int)*(unsigned char*)&one +#define PY_ABS_LLONG_MIN (0-(unsigned PY_LONG_LONG)PY_LLONG_MIN) /* Create a new long int object from a C PY_LONG_LONG int. */ @@ -1394,9 +1172,8 @@ PyLong_AsLongLong(PyObject *vv) case 0: return 0; case 1: return v->ob_digit[0]; } - res = _PyLong_AsByteArray( - (PyLongObject *)vv, (unsigned char *)&bytes, - SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 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) @@ -1427,9 +1204,8 @@ PyLong_AsUnsignedLongLong(PyObject *vv) case 1: return v->ob_digit[0]; } - res = _PyLong_AsByteArray( - (PyLongObject *)vv, (unsigned char *)&bytes, - SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 0); + res = _PyLong_AsByteArray((PyLongObject *)vv, (unsigned char *)&bytes, + SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 0); /* Plan 9 can't handle PY_LONG_LONG in ? : expressions */ if (res < 0) @@ -1466,7 +1242,7 @@ _PyLong_AsUnsignedLongLongMask(PyObject *vv) i = -i; } while (--i >= 0) { - x = (x << PyLong_SHIFT) + v->ob_digit[i]; + x = (x << PyLong_SHIFT) | v->ob_digit[i]; } return x * sign; } @@ -1507,13 +1283,110 @@ PyLong_AsUnsignedLongLongMask(register PyObject *op) } #undef IS_LITTLE_ENDIAN -#endif /* HAVE_LONG_LONG */ +/* Get a C long long int from a Python long or Python int object. + On overflow, returns -1 and sets *overflow to 1 or -1 depending + on the sign of the result. Otherwise *overflow is 0. + + For other errors (e.g., type error), returns -1 and sets an error + condition. +*/ + +PY_LONG_LONG +PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow) +{ + /* This version by Tim Peters */ + register PyLongObject *v; + unsigned PY_LONG_LONG x, prev; + PY_LONG_LONG res; + Py_ssize_t i; + int sign; + int do_decref = 0; /* if nb_int was called */ + + *overflow = 0; + if (vv == NULL) { + PyErr_BadInternalCall(); + return -1; + } + + if (!PyLong_Check(vv)) { + PyNumberMethods *nb; + nb = vv->ob_type->tp_as_number; + if (nb == NULL || nb->nb_int == NULL) { + PyErr_SetString(PyExc_TypeError, + "an integer is required"); + return -1; + } + vv = (*nb->nb_int) (vv); + if (vv == NULL) + return -1; + do_decref = 1; + if (!PyLong_Check(vv)) { + Py_DECREF(vv); + PyErr_SetString(PyExc_TypeError, + "nb_int should return int object"); + return -1; + } + } -#define CHECK_BINOP(v,w) \ - if (!PyLong_Check(v) || !PyLong_Check(w)) { \ - Py_INCREF(Py_NotImplemented); \ - return Py_NotImplemented; \ + res = -1; + v = (PyLongObject *)vv; + i = Py_SIZE(v); + + switch (i) { + case -1: + res = -(sdigit)v->ob_digit[0]; + break; + case 0: + res = 0; + break; + case 1: + res = v->ob_digit[0]; + break; + default: + sign = 1; + x = 0; + if (i < 0) { + sign = -1; + i = -(i); + } + while (--i >= 0) { + prev = x; + x = (x << PyLong_SHIFT) + v->ob_digit[i]; + if ((x >> PyLong_SHIFT) != prev) { + *overflow = sign; + goto exit; + } + } + /* Haven't lost any bits, but casting to long requires extra + * care (see comment above). + */ + if (x <= (unsigned PY_LONG_LONG)PY_LLONG_MAX) { + res = (PY_LONG_LONG)x * sign; + } + else if (sign < 0 && x == PY_ABS_LLONG_MIN) { + res = PY_LLONG_MIN; + } + else { + *overflow = sign; + /* res is already set to -1 */ + } } + exit: + if (do_decref) { + Py_DECREF(vv); + } + return res; +} + +#endif /* HAVE_LONG_LONG */ + +#define CHECK_BINOP(v,w) \ + do { \ + if (!PyLong_Check(v) || !PyLong_Check(w)) { \ + Py_INCREF(Py_NotImplemented); \ + return Py_NotImplemented; \ + } \ + } while(0) /* bits_in_digit(d) returns the unique integer k such that 2**(k-1) <= d < 2**k if d is nonzero, else 0. */ @@ -1640,7 +1513,7 @@ inplace_divrem1(digit *pout, digit *pin, Py_ssize_t size, digit n) pout += size; while (--size >= 0) { digit hi; - rem = (rem << PyLong_SHIFT) + *--pin; + rem = (rem << PyLong_SHIFT) | *--pin; *--pout = hi = (digit)(rem / n); rem -= (twodigits)hi * n; } @@ -1665,8 +1538,122 @@ divrem1(PyLongObject *a, digit n, digit *prem) return long_normalize(z); } -/* Convert a long int object to a string, using a given conversion base. - Return a string object. +/* Convert a long integer to a base 10 string. Returns a new non-shared + string. (Return value is non-shared so that callers can modify the + returned value if necessary.) */ + +static PyObject * +long_to_decimal_string(PyObject *aa) +{ + PyLongObject *scratch, *a; + PyObject *str; + Py_ssize_t size, strlen, size_a, i, j; + digit *pout, *pin, rem, tenpow; + Py_UNICODE *p; + int negative; + + a = (PyLongObject *)aa; + if (a == NULL || !PyLong_Check(a)) { + PyErr_BadInternalCall(); + return NULL; + } + size_a = ABS(Py_SIZE(a)); + negative = Py_SIZE(a) < 0; + + /* quick and dirty upper bound for the number of digits + required to express a in base _PyLong_DECIMAL_BASE: + + #digits = 1 + floor(log2(a) / log2(_PyLong_DECIMAL_BASE)) + + But log2(a) < size_a * PyLong_SHIFT, and + log2(_PyLong_DECIMAL_BASE) = log2(10) * _PyLong_DECIMAL_SHIFT + > 3 * _PyLong_DECIMAL_SHIFT + */ + if (size_a > PY_SSIZE_T_MAX / PyLong_SHIFT) { + PyErr_SetString(PyExc_OverflowError, + "long is too large to format"); + return NULL; + } + /* the expression size_a * PyLong_SHIFT is now safe from overflow */ + size = 1 + size_a * PyLong_SHIFT / (3 * _PyLong_DECIMAL_SHIFT); + scratch = _PyLong_New(size); + if (scratch == NULL) + return NULL; + + /* convert array of base _PyLong_BASE digits in pin to an array of + base _PyLong_DECIMAL_BASE digits in pout, following Knuth (TAOCP, + Volume 2 (3rd edn), section 4.4, Method 1b). */ + pin = a->ob_digit; + pout = scratch->ob_digit; + size = 0; + for (i = size_a; --i >= 0; ) { + digit hi = pin[i]; + for (j = 0; j < size; j++) { + twodigits z = (twodigits)pout[j] << PyLong_SHIFT | hi; + hi = (digit)(z / _PyLong_DECIMAL_BASE); + pout[j] = (digit)(z - (twodigits)hi * + _PyLong_DECIMAL_BASE); + } + while (hi) { + pout[size++] = hi % _PyLong_DECIMAL_BASE; + hi /= _PyLong_DECIMAL_BASE; + } + /* check for keyboard interrupt */ + SIGCHECK({ + Py_DECREF(scratch); + return NULL; + }); + } + /* pout should have at least one digit, so that the case when a = 0 + works correctly */ + if (size == 0) + pout[size++] = 0; + + /* calculate exact length of output string, and allocate */ + strlen = negative + 1 + (size - 1) * _PyLong_DECIMAL_SHIFT; + tenpow = 10; + rem = pout[size-1]; + while (rem >= tenpow) { + tenpow *= 10; + strlen++; + } + str = PyUnicode_FromUnicode(NULL, strlen); + if (str == NULL) { + Py_DECREF(scratch); + return NULL; + } + + /* fill the string right-to-left */ + p = PyUnicode_AS_UNICODE(str) + strlen; + *p = '\0'; + /* pout[0] through pout[size-2] contribute exactly + _PyLong_DECIMAL_SHIFT digits each */ + for (i=0; i < size - 1; i++) { + rem = pout[i]; + for (j = 0; j < _PyLong_DECIMAL_SHIFT; j++) { + *--p = '0' + rem % 10; + rem /= 10; + } + } + /* pout[size-1]: always produce at least one decimal digit */ + rem = pout[i]; + do { + *--p = '0' + rem % 10; + rem /= 10; + } while (rem != 0); + + /* and sign */ + if (negative) + *--p = '-'; + + /* check we've counted correctly */ + assert(p == PyUnicode_AS_UNICODE(str)); + Py_DECREF(scratch); + return (PyObject *)str; +} + +/* Convert a long int object to a string, using a given conversion base, + which should be one of 2, 8, 10 or 16. Return a string object. If base is 2, 8 or 16, add the proper prefix '0b', '0o' or '0x'. */ PyObject * @@ -1676,32 +1663,44 @@ _PyLong_Format(PyObject *aa, int base) PyObject *str; Py_ssize_t i, sz; Py_ssize_t size_a; - Py_UNICODE *p; + Py_UNICODE *p, sign = '\0'; int bits; - char sign = '\0'; + + assert(base == 2 || base == 8 || base == 10 || base == 16); + if (base == 10) + return long_to_decimal_string((PyObject *)a); if (a == NULL || !PyLong_Check(a)) { PyErr_BadInternalCall(); return NULL; } - assert(base >= 2 && base <= 36); size_a = ABS(Py_SIZE(a)); /* Compute a rough upper bound for the length of the string */ - i = base; - bits = 0; - while (i > 1) { - ++bits; - i >>= 1; - } - i = 5; - /* ensure we don't get signed overflow in sz calculation */ - if (size_a > (PY_SSIZE_T_MAX - i) / PyLong_SHIFT) { + switch (base) { + case 16: + bits = 4; + break; + case 8: + bits = 3; + break; + case 2: + bits = 1; + break; + default: + assert(0); /* shouldn't ever get here */ + bits = 0; /* to silence gcc warning */ + } + /* compute length of output string: allow 2 characters for prefix and + 1 for possible '-' sign. */ + if (size_a > (PY_SSIZE_T_MAX - 3) / PyLong_SHIFT) { PyErr_SetString(PyExc_OverflowError, "int is too large to format"); return NULL; } - sz = i + 1 + (size_a * PyLong_SHIFT - 1) / bits; + /* now size_a * PyLong_SHIFT + 3 <= PY_SSIZE_T_MAX, so the RHS below + is safe from overflow */ + sz = 3 + (size_a * PyLong_SHIFT + (bits - 1)) / bits; assert(sz >= 0); str = PyUnicode_FromUnicode(NULL, sz); if (str == NULL) @@ -1714,106 +1713,33 @@ _PyLong_Format(PyObject *aa, int base) if (Py_SIZE(a) == 0) { *--p = '0'; } - else if ((base & (base - 1)) == 0) { + else { /* JRH: special case for power-of-2 bases */ twodigits accum = 0; int accumbits = 0; /* # of bits in accum */ - int basebits = 1; /* # of bits in base-1 */ - i = base; - while ((i >>= 1) > 1) - ++basebits; - for (i = 0; i < size_a; ++i) { accum |= (twodigits)a->ob_digit[i] << accumbits; accumbits += PyLong_SHIFT; - assert(accumbits >= basebits); + assert(accumbits >= bits); do { - char cdigit = (char)(accum & (base - 1)); + Py_UNICODE cdigit; + cdigit = (Py_UNICODE)(accum & (base - 1)); cdigit += (cdigit < 10) ? '0' : 'a'-10; assert(p > PyUnicode_AS_UNICODE(str)); *--p = cdigit; - accumbits -= basebits; - accum >>= basebits; - } while (i < size_a-1 ? accumbits >= basebits : - accum > 0); - } - } - else { - /* Not 0, and base not a power of 2. Divide repeatedly by - base, but for speed use the highest power of base that - fits in a digit. */ - Py_ssize_t size = size_a; - digit *pin = a->ob_digit; - PyLongObject *scratch; - /* powbasw <- largest power of base that fits in a digit. */ - digit powbase = base; /* powbase == base ** power */ - int power = 1; - for (;;) { - twodigits newpow = powbase * (twodigits)base; - if (newpow >> PyLong_SHIFT) - /* doesn't fit in a digit */ - break; - powbase = (digit)newpow; - ++power; - } - - /* Get a scratch area for repeated division. */ - scratch = _PyLong_New(size); - if (scratch == NULL) { - Py_DECREF(str); - return NULL; + accumbits -= bits; + accum >>= bits; + } while (i < size_a-1 ? accumbits >= bits : accum > 0); } - - /* Repeatedly divide by powbase. */ - do { - int ntostore = power; - digit rem = inplace_divrem1(scratch->ob_digit, - pin, size, powbase); - pin = scratch->ob_digit; /* no need to use a again */ - if (pin[size - 1] == 0) - --size; - SIGCHECK({ - Py_DECREF(scratch); - Py_DECREF(str); - return NULL; - }) - - /* Break rem into digits. */ - assert(ntostore > 0); - do { - digit nextrem = (digit)(rem / base); - char c = (char)(rem - nextrem * base); - assert(p > PyUnicode_AS_UNICODE(str)); - c += (c < 10) ? '0' : 'a'-10; - *--p = c; - rem = nextrem; - --ntostore; - /* Termination is a bit delicate: must not - store leading zeroes, so must get out if - remaining quotient and rem are both 0. */ - } while (ntostore && (size || rem)); - } while (size != 0); - Py_DECREF(scratch); } - if (base == 16) { + if (base == 16) *--p = 'x'; - *--p = '0'; - } - else if (base == 8) { + else if (base == 8) *--p = 'o'; - *--p = '0'; - } - else if (base == 2) { + else /* (base == 2) */ *--p = 'b'; - *--p = '0'; - } - else if (base != 10) { - *--p = '#'; - *--p = '0' + base%10; - if (base > 10) - *--p = '0' + base/10; - } + *--p = '0'; if (sign) *--p = sign; if (p != PyUnicode_AS_UNICODE(str)) { @@ -2072,8 +1998,8 @@ digit beyond the first. twodigits convmax = base; int i = 1; - log_base_BASE[base] = log((double)base) / - log((double)PyLong_BASE); + log_base_BASE[base] = (log((double)base) / + log((double)PyLong_BASE)); for (;;) { twodigits next = convmax * base; if (next > PyLong_BASE) @@ -2117,7 +2043,7 @@ digit beyond the first. c = (digit)_PyLong_DigitValue[Py_CHARMASK(*str++)]; for (i = 1; i < convwidth && str != scan; ++i, ++str) { c = (twodigits)(c * base + - (int)_PyLong_DigitValue[Py_CHARMASK(*str)]); + (int)_PyLong_DigitValue[Py_CHARMASK(*str)]); assert(c < PyLong_BASE); } @@ -2190,7 +2116,7 @@ digit beyond the first. long_normalize(z); return (PyObject *) maybe_small_long(z); - onError: + onError: Py_XDECREF(z); slen = strlen(orig_str) < 200 ? strlen(orig_str) : 200; strobj = PyUnicode_FromStringAndSize(orig_str, slen); @@ -2207,17 +2133,34 @@ PyObject * PyLong_FromUnicode(Py_UNICODE *u, Py_ssize_t length, int base) { PyObject *result; - char *buffer = (char *)PyMem_MALLOC(length+1); + PyObject *asciidig; + char *buffer, *end; + Py_ssize_t i, buflen; + Py_UNICODE *ptr; - if (buffer == NULL) + asciidig = PyUnicode_TransformDecimalToASCII(u, length); + if (asciidig == NULL) return NULL; - - if (PyUnicode_EncodeDecimal(u, length, buffer, NULL)) { - PyMem_FREE(buffer); + /* Replace non-ASCII whitespace with ' ' */ + ptr = PyUnicode_AS_UNICODE(asciidig); + for (i = 0; i < length; i++) { + Py_UNICODE ch = ptr[i]; + if (ch > 127 && Py_UNICODE_ISSPACE(ch)) + ptr[i] = ' '; + } + buffer = _PyUnicode_AsStringAndSize(asciidig, &buflen); + if (buffer == NULL) { + Py_DECREF(asciidig); return NULL; } - result = PyLong_FromString(buffer, NULL, base); - PyMem_FREE(buffer); + result = PyLong_FromString(buffer, &end, base); + if (result != NULL && end != buffer + buflen) { + PyErr_SetString(PyExc_ValueError, + "null byte in argument for int()"); + Py_DECREF(result); + result = NULL; + } + Py_DECREF(asciidig); return result; } @@ -2346,12 +2289,12 @@ x_divrem(PyLongObject *v1, PyLongObject *w1, PyLongObject **prem) single-digit quotient q, remainder in vk[0:size_w]. */ SIGCHECK({ - Py_DECREF(a); - Py_DECREF(w); - Py_DECREF(v); - *prem = NULL; - return NULL; - }) + Py_DECREF(a); + Py_DECREF(w); + Py_DECREF(v); + *prem = NULL; + return NULL; + }); /* estimate quotient digit q; may overestimate by 1 (rare) */ vtop = vk[size_w]; @@ -2377,7 +2320,7 @@ x_divrem(PyLongObject *v1, PyLongObject *w1, PyLongObject **prem) (stwodigits)q * (stwodigits)w0[i]; vk[i] = (digit)z & PyLong_MASK; zhi = (sdigit)Py_ARITHMETIC_RIGHT_SHIFT(stwodigits, - z, PyLong_SHIFT); + z, PyLong_SHIFT); } /* add w back if q was too large (this branch taken rarely) */ @@ -2406,6 +2349,153 @@ x_divrem(PyLongObject *v1, PyLongObject *w1, PyLongObject **prem) return long_normalize(a); } +/* For a nonzero PyLong a, express a in the form x * 2**e, with 0.5 <= + abs(x) < 1.0 and e >= 0; return x and put e in *e. Here x is + rounded to DBL_MANT_DIG significant bits using round-half-to-even. + If a == 0, return 0.0 and set *e = 0. If the resulting exponent + e is larger than PY_SSIZE_T_MAX, raise OverflowError and return + -1.0. */ + +/* attempt to define 2.0**DBL_MANT_DIG as a compile-time constant */ +#if DBL_MANT_DIG == 53 +#define EXP2_DBL_MANT_DIG 9007199254740992.0 +#else +#define EXP2_DBL_MANT_DIG (ldexp(1.0, DBL_MANT_DIG)) +#endif + +double +_PyLong_Frexp(PyLongObject *a, Py_ssize_t *e) +{ + Py_ssize_t a_size, a_bits, shift_digits, shift_bits, x_size; + /* See below for why x_digits is always large enough. */ + digit rem, x_digits[2 + (DBL_MANT_DIG + 1) / PyLong_SHIFT]; + double dx; + /* Correction term for round-half-to-even rounding. For a digit x, + "x + half_even_correction[x & 7]" gives x rounded to the nearest + multiple of 4, rounding ties to a multiple of 8. */ + static const int half_even_correction[8] = {0, -1, -2, 1, 0, -1, 2, 1}; + + a_size = ABS(Py_SIZE(a)); + if (a_size == 0) { + /* Special case for 0: significand 0.0, exponent 0. */ + *e = 0; + return 0.0; + } + a_bits = bits_in_digit(a->ob_digit[a_size-1]); + /* The following is an overflow-free version of the check + "if ((a_size - 1) * PyLong_SHIFT + a_bits > PY_SSIZE_T_MAX) ..." */ + if (a_size >= (PY_SSIZE_T_MAX - 1) / PyLong_SHIFT + 1 && + (a_size > (PY_SSIZE_T_MAX - 1) / PyLong_SHIFT + 1 || + a_bits > (PY_SSIZE_T_MAX - 1) % PyLong_SHIFT + 1)) + goto overflow; + a_bits = (a_size - 1) * PyLong_SHIFT + a_bits; + + /* Shift the first DBL_MANT_DIG + 2 bits of a into x_digits[0:x_size] + (shifting left if a_bits <= DBL_MANT_DIG + 2). + + Number of digits needed for result: write // for floor division. + Then if shifting left, we end up using + + 1 + a_size + (DBL_MANT_DIG + 2 - a_bits) // PyLong_SHIFT + + digits. If shifting right, we use + + a_size - (a_bits - DBL_MANT_DIG - 2) // PyLong_SHIFT + + digits. Using a_size = 1 + (a_bits - 1) // PyLong_SHIFT along with + the inequalities + + m // PyLong_SHIFT + n // PyLong_SHIFT <= (m + n) // PyLong_SHIFT + m // PyLong_SHIFT - n // PyLong_SHIFT <= + 1 + (m - n - 1) // PyLong_SHIFT, + + valid for any integers m and n, we find that x_size satisfies + + x_size <= 2 + (DBL_MANT_DIG + 1) // PyLong_SHIFT + + in both cases. + */ + if (a_bits <= DBL_MANT_DIG + 2) { + shift_digits = (DBL_MANT_DIG + 2 - a_bits) / PyLong_SHIFT; + shift_bits = (DBL_MANT_DIG + 2 - a_bits) % PyLong_SHIFT; + x_size = 0; + while (x_size < shift_digits) + x_digits[x_size++] = 0; + rem = v_lshift(x_digits + x_size, a->ob_digit, a_size, + (int)shift_bits); + x_size += a_size; + x_digits[x_size++] = rem; + } + else { + shift_digits = (a_bits - DBL_MANT_DIG - 2) / PyLong_SHIFT; + shift_bits = (a_bits - DBL_MANT_DIG - 2) % PyLong_SHIFT; + rem = v_rshift(x_digits, a->ob_digit + shift_digits, + a_size - shift_digits, (int)shift_bits); + x_size = a_size - shift_digits; + /* For correct rounding below, we need the least significant + bit of x to be 'sticky' for this shift: if any of the bits + shifted out was nonzero, we set the least significant bit + of x. */ + if (rem) + x_digits[0] |= 1; + else + while (shift_digits > 0) + if (a->ob_digit[--shift_digits]) { + x_digits[0] |= 1; + break; + } + } + assert(1 <= x_size && + x_size <= (Py_ssize_t)(sizeof(x_digits)/sizeof(digit))); + + /* Round, and convert to double. */ + x_digits[0] += half_even_correction[x_digits[0] & 7]; + dx = x_digits[--x_size]; + while (x_size > 0) + dx = dx * PyLong_BASE + x_digits[--x_size]; + + /* Rescale; make correction if result is 1.0. */ + dx /= 4.0 * EXP2_DBL_MANT_DIG; + if (dx == 1.0) { + if (a_bits == PY_SSIZE_T_MAX) + goto overflow; + dx = 0.5; + a_bits += 1; + } + + *e = a_bits; + return Py_SIZE(a) < 0 ? -dx : dx; + + overflow: + /* exponent > PY_SSIZE_T_MAX */ + PyErr_SetString(PyExc_OverflowError, + "huge integer: number of bits overflows a Py_ssize_t"); + *e = 0; + return -1.0; +} + +/* Get a C double from a long int object. Rounds to the nearest double, + using the round-half-to-even rule in the case of a tie. */ + +double +PyLong_AsDouble(PyObject *v) +{ + Py_ssize_t exponent; + double x; + + if (v == NULL || !PyLong_Check(v)) { + PyErr_BadInternalCall(); + return -1.0; + } + x = _PyLong_Frexp((PyLongObject *)v, &exponent); + if ((x == -1.0 && PyErr_Occurred()) || exponent > DBL_MAX_EXP) { + PyErr_SetString(PyExc_OverflowError, + "long int too large to convert to float"); + return -1.0; + } + return ldexp(x, (int)exponent); +} + /* Methods */ static void @@ -2414,22 +2504,13 @@ long_dealloc(PyObject *v) Py_TYPE(v)->tp_free(v); } -static PyObject * -long_repr(PyObject *v) -{ - return _PyLong_Format(v, 10); -} - static int long_compare(PyLongObject *a, PyLongObject *b) { Py_ssize_t sign; if (Py_SIZE(a) != Py_SIZE(b)) { - if (ABS(Py_SIZE(a)) == 0 && ABS(Py_SIZE(b)) == 0) - sign = 0; - else - sign = Py_SIZE(a) - Py_SIZE(b); + sign = Py_SIZE(a) - Py_SIZE(b); } else { Py_ssize_t i = ABS(Py_SIZE(a)); @@ -2487,16 +2568,13 @@ long_richcompare(PyObject *self, PyObject *other, int op) return v; } -static long +static Py_hash_t long_hash(PyLongObject *v) { - unsigned long x; + Py_uhash_t x; Py_ssize_t i; int sign; - /* This is designed so that Python ints and longs with the - same value hash to the same value, otherwise comparisons - of mapping keys will turn out weird */ i = Py_SIZE(v); switch(i) { case -1: return v->ob_digit[0]==1 ? -2 : -(sdigit)v->ob_digit[0]; @@ -2509,23 +2587,42 @@ long_hash(PyLongObject *v) sign = -1; i = -(i); } - /* The following loop produces a C unsigned long x such that x is - congruent to the absolute value of v modulo ULONG_MAX. The - resulting x is nonzero if and only if v is. */ while (--i >= 0) { - /* Force a native long #-bits (32 or 64) circular shift */ - x = (x >> (8*SIZEOF_LONG-PyLong_SHIFT)) | (x << PyLong_SHIFT); + /* Here x is a quantity in the range [0, _PyHASH_MODULUS); we + want to compute x * 2**PyLong_SHIFT + v->ob_digit[i] modulo + _PyHASH_MODULUS. + + The computation of x * 2**PyLong_SHIFT % _PyHASH_MODULUS + amounts to a rotation of the bits of x. To see this, write + + x * 2**PyLong_SHIFT = y * 2**_PyHASH_BITS + z + + where y = x >> (_PyHASH_BITS - PyLong_SHIFT) gives the top + PyLong_SHIFT bits of x (those that are shifted out of the + original _PyHASH_BITS bits, and z = (x << PyLong_SHIFT) & + _PyHASH_MODULUS gives the bottom _PyHASH_BITS - PyLong_SHIFT + bits of x, shifted up. Then since 2**_PyHASH_BITS is + congruent to 1 modulo _PyHASH_MODULUS, y*2**_PyHASH_BITS is + congruent to y modulo _PyHASH_MODULUS. So + + x * 2**PyLong_SHIFT = y + z (mod _PyHASH_MODULUS). + + The right-hand side is just the result of rotating the + _PyHASH_BITS bits of x left by PyLong_SHIFT places; since + not all _PyHASH_BITS bits of x are 1s, the same is true + after rotation, so 0 <= y+z < _PyHASH_MODULUS and y + z is + the reduction of x*2**PyLong_SHIFT modulo + _PyHASH_MODULUS. */ + x = ((x << PyLong_SHIFT) & _PyHASH_MODULUS) | + (x >> (_PyHASH_BITS - PyLong_SHIFT)); x += v->ob_digit[i]; - /* If the addition above overflowed we compensate by - incrementing. This preserves the value modulo - ULONG_MAX. */ - if (x < v->ob_digit[i]) - x++; + if (x >= _PyHASH_MODULUS) + x -= _PyHASH_MODULUS; } x = x * sign; - if (x == (unsigned long)-1) - x = (unsigned long)-2; - return (long)x; + if (x == (Py_uhash_t)-1) + x = (Py_uhash_t)-2; + return (Py_hash_t)x; } @@ -2543,8 +2640,8 @@ x_add(PyLongObject *a, PyLongObject *b) if (size_a < size_b) { { PyLongObject *temp = a; a = b; b = temp; } { Py_ssize_t size_temp = size_a; - size_a = size_b; - size_b = size_temp; } + size_a = size_b; + size_b = size_temp; } } z = _PyLong_New(size_a+1); if (z == NULL) @@ -2579,8 +2676,8 @@ x_sub(PyLongObject *a, PyLongObject *b) sign = -1; { PyLongObject *temp = a; a = b; b = temp; } { Py_ssize_t size_temp = size_a; - size_a = size_b; - size_b = size_temp; } + size_a = size_b; + size_b = size_temp; } } else if (size_a == size_b) { /* Find highest digit where a and b differ: */ @@ -2708,9 +2805,9 @@ x_mul(PyLongObject *a, PyLongObject *b) digit *paend = a->ob_digit + size_a; SIGCHECK({ - Py_DECREF(z); - return NULL; - }) + Py_DECREF(z); + return NULL; + }); carry = *pz + f * f; *pz++ = (digit)(carry & PyLong_MASK); @@ -2746,9 +2843,9 @@ x_mul(PyLongObject *a, PyLongObject *b) digit *pbend = b->ob_digit + size_b; SIGCHECK({ - Py_DECREF(z); - return NULL; - }) + Py_DECREF(z); + return NULL; + }); while (pb < pbend) { carry += *pz + *pb++ * f; @@ -2772,7 +2869,10 @@ x_mul(PyLongObject *a, PyLongObject *b) Returns 0 on success, -1 on failure. */ static int -kmul_split(PyLongObject *n, Py_ssize_t size, PyLongObject **high, PyLongObject **low) +kmul_split(PyLongObject *n, + Py_ssize_t size, + PyLongObject **high, + PyLongObject **low) { PyLongObject *hi, *lo; Py_ssize_t size_lo, size_hi; @@ -2961,7 +3061,7 @@ k_mul(PyLongObject *a, PyLongObject *b) return long_normalize(ret); - fail: + fail: Py_XDECREF(ret); Py_XDECREF(ah); Py_XDECREF(al); @@ -3071,7 +3171,7 @@ k_lopsided_mul(PyLongObject *a, PyLongObject *b) Py_DECREF(bslice); return long_normalize(ret); - fail: + fail: Py_DECREF(ret); Py_XDECREF(bslice); return NULL; @@ -3183,47 +3283,267 @@ long_div(PyObject *a, PyObject *b) return (PyObject *)div; } +/* PyLong/PyLong -> float, with correctly rounded result. */ + +#define MANT_DIG_DIGITS (DBL_MANT_DIG / PyLong_SHIFT) +#define MANT_DIG_BITS (DBL_MANT_DIG % PyLong_SHIFT) + static PyObject * -long_true_divide(PyObject *a, PyObject *b) +long_true_divide(PyObject *v, PyObject *w) { - double ad, bd; - int failed, aexp = -1, bexp = -1; + PyLongObject *a, *b, *x; + Py_ssize_t a_size, b_size, shift, extra_bits, diff, x_size, x_bits; + digit mask, low; + int inexact, negate, a_is_small, b_is_small; + double dx, result; - CHECK_BINOP(a, b); - ad = _PyLong_AsScaledDouble((PyObject *)a, &aexp); - bd = _PyLong_AsScaledDouble((PyObject *)b, &bexp); - failed = (ad == -1.0 || bd == -1.0) && PyErr_Occurred(); - if (failed) - return NULL; - /* 'aexp' and 'bexp' were initialized to -1 to silence gcc-4.0.x, - but should really be set correctly after successful calls to - _PyLong_AsScaledDouble() */ - assert(aexp >= 0 && bexp >= 0); + CHECK_BINOP(v, w); + a = (PyLongObject *)v; + b = (PyLongObject *)w; + + /* + Method in a nutshell: + + 0. reduce to case a, b > 0; filter out obvious underflow/overflow + 1. choose a suitable integer 'shift' + 2. use integer arithmetic to compute x = floor(2**-shift*a/b) + 3. adjust x for correct rounding + 4. convert x to a double dx with the same value + 5. return ldexp(dx, shift). + + In more detail: + + 0. For any a, a/0 raises ZeroDivisionError; for nonzero b, 0/b + returns either 0.0 or -0.0, depending on the sign of b. For a and + b both nonzero, ignore signs of a and b, and add the sign back in + at the end. Now write a_bits and b_bits for the bit lengths of a + and b respectively (that is, a_bits = 1 + floor(log_2(a)); likewise + for b). Then + + 2**(a_bits - b_bits - 1) < a/b < 2**(a_bits - b_bits + 1). + + So if a_bits - b_bits > DBL_MAX_EXP then a/b > 2**DBL_MAX_EXP and + so overflows. Similarly, if a_bits - b_bits < DBL_MIN_EXP - + DBL_MANT_DIG - 1 then a/b underflows to 0. With these cases out of + the way, we can assume that + + DBL_MIN_EXP - DBL_MANT_DIG - 1 <= a_bits - b_bits <= DBL_MAX_EXP. + + 1. The integer 'shift' is chosen so that x has the right number of + bits for a double, plus two or three extra bits that will be used + in the rounding decisions. Writing a_bits and b_bits for the + number of significant bits in a and b respectively, a + straightforward formula for shift is: + + shift = a_bits - b_bits - DBL_MANT_DIG - 2 + + This is fine in the usual case, but if a/b is smaller than the + smallest normal float then it can lead to double rounding on an + IEEE 754 platform, giving incorrectly rounded results. So we + adjust the formula slightly. The actual formula used is: + + shift = MAX(a_bits - b_bits, DBL_MIN_EXP) - DBL_MANT_DIG - 2 + + 2. The quantity x is computed by first shifting a (left -shift bits + if shift <= 0, right shift bits if shift > 0) and then dividing by + b. For both the shift and the division, we keep track of whether + the result is inexact, in a flag 'inexact'; this information is + needed at the rounding stage. + + With the choice of shift above, together with our assumption that + a_bits - b_bits >= DBL_MIN_EXP - DBL_MANT_DIG - 1, it follows + that x >= 1. + + 3. Now x * 2**shift <= a/b < (x+1) * 2**shift. We want to replace + this with an exactly representable float of the form + + round(x/2**extra_bits) * 2**(extra_bits+shift). + + For float representability, we need x/2**extra_bits < + 2**DBL_MANT_DIG and extra_bits + shift >= DBL_MIN_EXP - + DBL_MANT_DIG. This translates to the condition: + + extra_bits >= MAX(x_bits, DBL_MIN_EXP - shift) - DBL_MANT_DIG + + To round, we just modify the bottom digit of x in-place; this can + end up giving a digit with value > PyLONG_MASK, but that's not a + problem since digits can hold values up to 2*PyLONG_MASK+1. + + With the original choices for shift above, extra_bits will always + be 2 or 3. Then rounding under the round-half-to-even rule, we + round up iff the most significant of the extra bits is 1, and + either: (a) the computation of x in step 2 had an inexact result, + or (b) at least one other of the extra bits is 1, or (c) the least + significant bit of x (above those to be rounded) is 1. + + 4. Conversion to a double is straightforward; all floating-point + operations involved in the conversion are exact, so there's no + danger of rounding errors. + + 5. Use ldexp(x, shift) to compute x*2**shift, the final result. + The result will always be exactly representable as a double, except + in the case that it overflows. To avoid dependence on the exact + behaviour of ldexp on overflow, we check for overflow before + applying ldexp. The result of ldexp is adjusted for sign before + returning. + */ - if (bd == 0.0) { + /* Reduce to case where a and b are both positive. */ + a_size = ABS(Py_SIZE(a)); + b_size = ABS(Py_SIZE(b)); + negate = (Py_SIZE(a) < 0) ^ (Py_SIZE(b) < 0); + if (b_size == 0) { PyErr_SetString(PyExc_ZeroDivisionError, - "int division or modulo by zero"); - return NULL; + "division by zero"); + goto error; } - - /* True value is very close to ad/bd * 2**(PyLong_SHIFT*(aexp-bexp)) */ - ad /= bd; /* overflow/underflow impossible here */ - aexp -= bexp; - if (aexp > INT_MAX / PyLong_SHIFT) + if (a_size == 0) + goto underflow_or_zero; + + /* Fast path for a and b small (exactly representable in a double). + Relies on floating-point division being correctly rounded; results + may be subject to double rounding on x86 machines that operate with + the x87 FPU set to 64-bit precision. */ + a_is_small = a_size <= MANT_DIG_DIGITS || + (a_size == MANT_DIG_DIGITS+1 && + a->ob_digit[MANT_DIG_DIGITS] >> MANT_DIG_BITS == 0); + b_is_small = b_size <= MANT_DIG_DIGITS || + (b_size == MANT_DIG_DIGITS+1 && + b->ob_digit[MANT_DIG_DIGITS] >> MANT_DIG_BITS == 0); + if (a_is_small && b_is_small) { + double da, db; + da = a->ob_digit[--a_size]; + while (a_size > 0) + da = da * PyLong_BASE + a->ob_digit[--a_size]; + db = b->ob_digit[--b_size]; + while (b_size > 0) + db = db * PyLong_BASE + b->ob_digit[--b_size]; + result = da / db; + goto success; + } + + /* Catch obvious cases of underflow and overflow */ + diff = a_size - b_size; + if (diff > PY_SSIZE_T_MAX/PyLong_SHIFT - 1) + /* Extreme overflow */ goto overflow; - else if (aexp < -(INT_MAX / PyLong_SHIFT)) - return PyFloat_FromDouble(0.0); /* underflow to 0 */ - errno = 0; - ad = ldexp(ad, aexp * PyLong_SHIFT); - if (Py_OVERFLOWED(ad)) /* ignore underflow to 0.0 */ + else if (diff < 1 - PY_SSIZE_T_MAX/PyLong_SHIFT) + /* Extreme underflow */ + goto underflow_or_zero; + /* Next line is now safe from overflowing a Py_ssize_t */ + diff = diff * PyLong_SHIFT + bits_in_digit(a->ob_digit[a_size - 1]) - + bits_in_digit(b->ob_digit[b_size - 1]); + /* Now diff = a_bits - b_bits. */ + if (diff > DBL_MAX_EXP) goto overflow; - return PyFloat_FromDouble(ad); + else if (diff < DBL_MIN_EXP - DBL_MANT_DIG - 1) + goto underflow_or_zero; + + /* Choose value for shift; see comments for step 1 above. */ + shift = MAX(diff, DBL_MIN_EXP) - DBL_MANT_DIG - 2; + + inexact = 0; + + /* x = abs(a * 2**-shift) */ + if (shift <= 0) { + Py_ssize_t i, shift_digits = -shift / PyLong_SHIFT; + digit rem; + /* x = a << -shift */ + if (a_size >= PY_SSIZE_T_MAX - 1 - shift_digits) { + /* In practice, it's probably impossible to end up + here. Both a and b would have to be enormous, + using close to SIZE_T_MAX bytes of memory each. */ + PyErr_SetString(PyExc_OverflowError, + "intermediate overflow during division"); + goto error; + } + x = _PyLong_New(a_size + shift_digits + 1); + if (x == NULL) + goto error; + for (i = 0; i < shift_digits; i++) + x->ob_digit[i] = 0; + rem = v_lshift(x->ob_digit + shift_digits, a->ob_digit, + a_size, -shift % PyLong_SHIFT); + x->ob_digit[a_size + shift_digits] = rem; + } + else { + Py_ssize_t shift_digits = shift / PyLong_SHIFT; + digit rem; + /* x = a >> shift */ + assert(a_size >= shift_digits); + x = _PyLong_New(a_size - shift_digits); + if (x == NULL) + goto error; + rem = v_rshift(x->ob_digit, a->ob_digit + shift_digits, + a_size - shift_digits, shift % PyLong_SHIFT); + /* set inexact if any of the bits shifted out is nonzero */ + if (rem) + inexact = 1; + while (!inexact && shift_digits > 0) + if (a->ob_digit[--shift_digits]) + inexact = 1; + } + long_normalize(x); + x_size = Py_SIZE(x); + + /* x //= b. If the remainder is nonzero, set inexact. We own the only + reference to x, so it's safe to modify it in-place. */ + if (b_size == 1) { + digit rem = inplace_divrem1(x->ob_digit, x->ob_digit, x_size, + b->ob_digit[0]); + long_normalize(x); + if (rem) + inexact = 1; + } + else { + PyLongObject *div, *rem; + div = x_divrem(x, b, &rem); + Py_DECREF(x); + x = div; + if (x == NULL) + goto error; + if (Py_SIZE(rem)) + inexact = 1; + Py_DECREF(rem); + } + x_size = ABS(Py_SIZE(x)); + assert(x_size > 0); /* result of division is never zero */ + x_bits = (x_size-1)*PyLong_SHIFT+bits_in_digit(x->ob_digit[x_size-1]); + + /* The number of extra bits that have to be rounded away. */ + extra_bits = MAX(x_bits, DBL_MIN_EXP - shift) - DBL_MANT_DIG; + assert(extra_bits == 2 || extra_bits == 3); + + /* Round by directly modifying the low digit of x. */ + mask = (digit)1 << (extra_bits - 1); + low = x->ob_digit[0] | inexact; + if (low & mask && low & (3*mask-1)) + low += mask; + x->ob_digit[0] = low & ~(mask-1U); + + /* Convert x to a double dx; the conversion is exact. */ + dx = x->ob_digit[--x_size]; + while (x_size > 0) + dx = dx * PyLong_BASE + x->ob_digit[--x_size]; + Py_DECREF(x); + + /* Check whether ldexp result will overflow a double. */ + if (shift + x_bits >= DBL_MAX_EXP && + (shift + x_bits > DBL_MAX_EXP || dx == ldexp(1.0, (int)x_bits))) + goto overflow; + result = ldexp(dx, (int)shift); + + success: + return PyFloat_FromDouble(negate ? -result : result); -overflow: + underflow_or_zero: + return PyFloat_FromDouble(negate ? -0.0 : 0.0); + + overflow: PyErr_SetString(PyExc_OverflowError, - "int/int too large for a float"); + "integer division result too large for a float"); + error: return NULL; - } static PyObject * @@ -3298,7 +3618,7 @@ long_pow(PyObject *v, PyObject *w, PyObject *x) if (Py_SIZE(b) < 0) { /* if exponent is negative */ if (c) { PyErr_SetString(PyExc_TypeError, "pow() 2nd argument " - "cannot be negative when 3rd argument specified"); + "cannot be negative when 3rd argument specified"); goto Error; } else { @@ -3364,26 +3684,28 @@ long_pow(PyObject *v, PyObject *w, PyObject *x) * is NULL. */ #define REDUCE(X) \ - if (c != NULL) { \ - if (l_divmod(X, c, NULL, &temp) < 0) \ - goto Error; \ - Py_XDECREF(X); \ - X = temp; \ - temp = NULL; \ - } + do { \ + if (c != NULL) { \ + if (l_divmod(X, c, NULL, &temp) < 0) \ + goto Error; \ + Py_XDECREF(X); \ + X = temp; \ + temp = NULL; \ + } \ + } while(0) /* Multiply two values, then reduce the result: result = X*Y % c. If c is NULL, skip the mod. */ -#define MULT(X, Y, result) \ -{ \ - temp = (PyLongObject *)long_mul(X, Y); \ - if (temp == NULL) \ - goto Error; \ - Py_XDECREF(result); \ - result = temp; \ - temp = NULL; \ - REDUCE(result) \ -} +#define MULT(X, Y, result) \ + do { \ + temp = (PyLongObject *)long_mul(X, Y); \ + if (temp == NULL) \ + goto Error; \ + Py_XDECREF(result); \ + result = temp; \ + temp = NULL; \ + REDUCE(result); \ + } while(0) if (Py_SIZE(b) <= FIVEARY_CUTOFF) { /* Left-to-right binary exponentiation (HAC Algorithm 14.79) */ @@ -3392,9 +3714,9 @@ long_pow(PyObject *v, PyObject *w, PyObject *x) digit bi = b->ob_digit[i]; for (j = (digit)1 << (PyLong_SHIFT-1); j != 0; j >>= 1) { - MULT(z, z, z) + MULT(z, z, z); if (bi & j) - MULT(z, a, z) + MULT(z, a, z); } } } @@ -3403,7 +3725,7 @@ long_pow(PyObject *v, PyObject *w, PyObject *x) Py_INCREF(z); /* still holds 1L */ table[0] = z; for (i = 1; i < 32; ++i) - MULT(table[i-1], a, table[i]) + MULT(table[i-1], a, table[i]); for (i = Py_SIZE(b) - 1; i >= 0; --i) { const digit bi = b->ob_digit[i]; @@ -3411,9 +3733,9 @@ long_pow(PyObject *v, PyObject *w, PyObject *x) for (j = PyLong_SHIFT - 5; j >= 0; j -= 5) { const int index = (bi >> j) & 0x1f; for (k = 0; k < 5; ++k) - MULT(z, z, z) + MULT(z, z, z); if (index) - MULT(z, table[index], z) + MULT(z, table[index], z); } } } @@ -3428,13 +3750,13 @@ long_pow(PyObject *v, PyObject *w, PyObject *x) } goto Done; - Error: + Error: if (z != NULL) { Py_DECREF(z); z = NULL; } /* fall through */ - Done: + Done: if (Py_SIZE(b) > FIVEARY_CUTOFF) { for (i = 0; i < 32; ++i) Py_XDECREF(table[i]); @@ -3489,15 +3811,14 @@ long_abs(PyLongObject *v) static int long_bool(PyLongObject *v) { - return ABS(Py_SIZE(v)) != 0; + return Py_SIZE(v) != 0; } static PyObject * long_rshift(PyLongObject *a, PyLongObject *b) { PyLongObject *z = NULL; - long shiftby; - Py_ssize_t newsize, wordshift, loshift, hishift, i, j; + Py_ssize_t shiftby, newsize, wordshift, loshift, hishift, i, j; digit lomask, himask; CHECK_BINOP(a, b); @@ -3516,8 +3837,7 @@ long_rshift(PyLongObject *a, PyLongObject *b) Py_DECREF(a2); } else { - - shiftby = PyLong_AsLong((PyObject *)b); + shiftby = PyLong_AsSsize_t((PyObject *)b); if (shiftby == -1L && PyErr_Occurred()) goto rshift_error; if (shiftby < 0) { @@ -3541,12 +3861,11 @@ long_rshift(PyLongObject *a, PyLongObject *b) for (i = 0, j = wordshift; i < newsize; i++, j++) { z->ob_digit[i] = (a->ob_digit[j] >> loshift) & lomask; if (i+1 < newsize) - z->ob_digit[i] |= - (a->ob_digit[j+1] << hishift) & himask; + z->ob_digit[i] |= (a->ob_digit[j+1] << hishift) & himask; } z = long_normalize(z); } -rshift_error: + rshift_error: return (PyObject *) maybe_small_long(z); } @@ -3558,27 +3877,21 @@ long_lshift(PyObject *v, PyObject *w) PyLongObject *a = (PyLongObject*)v; PyLongObject *b = (PyLongObject*)w; PyLongObject *z = NULL; - long shiftby; - Py_ssize_t oldsize, newsize, wordshift, remshift, i, j; + Py_ssize_t shiftby, oldsize, newsize, wordshift, remshift, i, j; twodigits accum; CHECK_BINOP(a, b); - shiftby = PyLong_AsLong((PyObject *)b); + shiftby = PyLong_AsSsize_t((PyObject *)b); if (shiftby == -1L && PyErr_Occurred()) goto lshift_error; if (shiftby < 0) { PyErr_SetString(PyExc_ValueError, "negative shift count"); goto lshift_error; } - if ((long)(int)shiftby != shiftby) { - PyErr_SetString(PyExc_ValueError, - "outrageous left shift count"); - goto lshift_error; - } /* wordshift, remshift = divmod(shiftby, PyLong_SHIFT) */ - wordshift = (int)shiftby / PyLong_SHIFT; - remshift = (int)shiftby - wordshift * PyLong_SHIFT; + wordshift = shiftby / PyLong_SHIFT; + remshift = shiftby - wordshift * PyLong_SHIFT; oldsize = ABS(Py_SIZE(a)); newsize = oldsize + wordshift; @@ -3602,116 +3915,150 @@ long_lshift(PyObject *v, PyObject *w) else assert(!accum); z = long_normalize(z); -lshift_error: + lshift_error: return (PyObject *) maybe_small_long(z); } +/* Compute two's complement of digit vector a[0:m], writing result to + z[0:m]. The digit vector a need not be normalized, but should not + be entirely zero. a and z may point to the same digit vector. */ + +static void +v_complement(digit *z, digit *a, Py_ssize_t m) +{ + Py_ssize_t i; + digit carry = 1; + for (i = 0; i < m; ++i) { + carry += a[i] ^ PyLong_MASK; + z[i] = carry & PyLong_MASK; + carry >>= PyLong_SHIFT; + } + assert(carry == 0); +} /* Bitwise and/xor/or operations */ static PyObject * long_bitwise(PyLongObject *a, int op, /* '&', '|', '^' */ - PyLongObject *b) + PyLongObject *b) { - digit maska, maskb; /* 0 or PyLong_MASK */ - int negz; + int nega, negb, negz; Py_ssize_t size_a, size_b, size_z, i; PyLongObject *z; - digit diga, digb; - PyObject *v; - if (Py_SIZE(a) < 0) { - a = (PyLongObject *) long_invert(a); - if (a == NULL) + /* Bitwise operations for negative numbers operate as though + on a two's complement representation. So convert arguments + from sign-magnitude to two's complement, and convert the + result back to sign-magnitude at the end. */ + + /* If a is negative, replace it by its two's complement. */ + size_a = ABS(Py_SIZE(a)); + nega = Py_SIZE(a) < 0; + if (nega) { + z = _PyLong_New(size_a); + if (z == NULL) return NULL; - maska = PyLong_MASK; + v_complement(z->ob_digit, a->ob_digit, size_a); + a = z; } - else { + else + /* Keep reference count consistent. */ Py_INCREF(a); - maska = 0; - } - if (Py_SIZE(b) < 0) { - b = (PyLongObject *) long_invert(b); - if (b == NULL) { + + /* Same for b. */ + size_b = ABS(Py_SIZE(b)); + negb = Py_SIZE(b) < 0; + if (negb) { + z = _PyLong_New(size_b); + if (z == NULL) { Py_DECREF(a); return NULL; } - maskb = PyLong_MASK; + v_complement(z->ob_digit, b->ob_digit, size_b); + b = z; } - else { + else Py_INCREF(b); - maskb = 0; + + /* Swap a and b if necessary to ensure size_a >= size_b. */ + if (size_a < size_b) { + z = a; a = b; b = z; + size_z = size_a; size_a = size_b; size_b = size_z; + negz = nega; nega = negb; negb = negz; } - negz = 0; + /* JRH: The original logic here was to allocate the result value (z) + as the longer of the two operands. However, there are some cases + where the result is guaranteed to be shorter than that: AND of two + positives, OR of two negatives: use the shorter number. AND with + mixed signs: use the positive number. OR with mixed signs: use the + negative number. + */ switch (op) { case '^': - if (maska != maskb) { - maska ^= PyLong_MASK; - negz = -1; - } + negz = nega ^ negb; + size_z = size_a; break; case '&': - if (maska && maskb) { - op = '|'; - maska ^= PyLong_MASK; - maskb ^= PyLong_MASK; - negz = -1; - } + negz = nega & negb; + size_z = negb ? size_a : size_b; break; case '|': - if (maska || maskb) { - op = '&'; - maska ^= PyLong_MASK; - maskb ^= PyLong_MASK; - negz = -1; - } + negz = nega | negb; + size_z = negb ? size_b : size_a; break; + default: + PyErr_BadArgument(); + return NULL; } - /* JRH: The original logic here was to allocate the result value (z) - as the longer of the two operands. However, there are some cases - where the result is guaranteed to be shorter than that: AND of two - positives, OR of two negatives: use the shorter number. AND with - mixed signs: use the positive number. OR with mixed signs: use the - negative number. After the transformations above, op will be '&' - iff one of these cases applies, and mask will be non-0 for operands - whose length should be ignored. - */ - - size_a = Py_SIZE(a); - size_b = Py_SIZE(b); - size_z = op == '&' - ? (maska - ? size_b - : (maskb ? size_a : MIN(size_a, size_b))) - : MAX(size_a, size_b); - z = _PyLong_New(size_z); + /* We allow an extra digit if z is negative, to make sure that + the final two's complement of z doesn't overflow. */ + z = _PyLong_New(size_z + negz); if (z == NULL) { Py_DECREF(a); Py_DECREF(b); return NULL; } - for (i = 0; i < size_z; ++i) { - diga = (i < size_a ? a->ob_digit[i] : 0) ^ maska; - digb = (i < size_b ? b->ob_digit[i] : 0) ^ maskb; - switch (op) { - case '&': z->ob_digit[i] = diga & digb; break; - case '|': z->ob_digit[i] = diga | digb; break; - case '^': z->ob_digit[i] = diga ^ digb; break; - } + /* Compute digits for overlap of a and b. */ + switch(op) { + case '&': + for (i = 0; i < size_b; ++i) + z->ob_digit[i] = a->ob_digit[i] & b->ob_digit[i]; + break; + case '|': + for (i = 0; i < size_b; ++i) + z->ob_digit[i] = a->ob_digit[i] | b->ob_digit[i]; + break; + case '^': + for (i = 0; i < size_b; ++i) + z->ob_digit[i] = a->ob_digit[i] ^ b->ob_digit[i]; + break; + default: + PyErr_BadArgument(); + return NULL; + } + + /* Copy any remaining digits of a, inverting if necessary. */ + if (op == '^' && negb) + for (; i < size_z; ++i) + z->ob_digit[i] = a->ob_digit[i] ^ PyLong_MASK; + else if (i < size_z) + memcpy(&z->ob_digit[i], &a->ob_digit[i], + (size_z-i)*sizeof(digit)); + + /* Complement result if negative. */ + if (negz) { + Py_SIZE(z) = -(Py_SIZE(z)); + z->ob_digit[size_z] = PyLong_MASK; + v_complement(z->ob_digit, z->ob_digit, size_z+1); } Py_DECREF(a); Py_DECREF(b); - z = long_normalize(z); - if (negz == 0) - return (PyObject *) maybe_small_long(z); - v = long_invert(z); - Py_DECREF(z); - return v; + return (PyObject *)maybe_small_long(long_normalize(z)); } static PyObject * @@ -3767,23 +4114,34 @@ long_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds); static PyObject * long_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyObject *x = NULL; - int base = -909; /* unlikely! */ + PyObject *obase = NULL, *x = NULL; + long base; + int overflow; static char *kwlist[] = {"x", "base", 0}; if (type != &PyLong_Type) return long_subtype_new(type, args, kwds); /* Wimp out */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:int", kwlist, - &x, &base)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:int", kwlist, + &x, &obase)) return NULL; if (x == NULL) return PyLong_FromLong(0L); - if (base == -909) + if (obase == NULL) return PyNumber_Long(x); - else if (PyUnicode_Check(x)) + + base = PyLong_AsLongAndOverflow(obase, &overflow); + if (base == -1 && PyErr_Occurred()) + return NULL; + if (overflow || (base != 0 && base < 2) || base > 36) { + PyErr_SetString(PyExc_ValueError, + "int() arg 2 must be >= 2 and <= 36"); + return NULL; + } + + if (PyUnicode_Check(x)) return PyLong_FromUnicode(PyUnicode_AS_UNICODE(x), PyUnicode_GET_SIZE(x), - base); + (int)base); else if (PyByteArray_Check(x) || PyBytes_Check(x)) { /* Since PyLong_FromString doesn't have a length parameter, * check here for possible NULs in the string. */ @@ -3797,15 +4155,15 @@ long_new(PyTypeObject *type, PyObject *args, PyObject *kwds) /* We only see this if there's a null byte in x, x is a bytes or buffer, *and* a base is given. */ PyErr_Format(PyExc_ValueError, - "invalid literal for int() with base %d: %R", - base, x); + "invalid literal for int() with base %d: %R", + (int)base, x); return NULL; } - return PyLong_FromString(string, NULL, base); + return PyLong_FromString(string, NULL, (int)base); } else { PyErr_SetString(PyExc_TypeError, - "int() can't convert non-string with explicit base"); + "int() can't convert non-string with explicit base"); return NULL; } } @@ -3870,140 +4228,169 @@ long__format__(PyObject *self, PyObject *args) PyUnicode_GET_SIZE(format_spec)); } -static PyObject * -long_round(PyObject *self, PyObject *args) +/* Return a pair (q, r) such that a = b * q + r, and + abs(r) <= abs(b)/2, with equality possible only if q is even. + In other words, q == a / b, rounded to the nearest integer using + round-half-to-even. */ + +PyObject * +_PyLong_DivmodNear(PyObject *a, PyObject *b) { - PyObject *o_ndigits=NULL, *temp; - PyLongObject *pow=NULL, *q=NULL, *r=NULL, *ndigits=NULL, *one; - int errcode; - digit q_mod_4; - - /* Notes on the algorithm: to round to the nearest 10**n (n positive), - the straightforward method is: - - (1) divide by 10**n - (2) round to nearest integer (round to even in case of tie) - (3) multiply result by 10**n. - - But the rounding step involves examining the fractional part of the - quotient to see whether it's greater than 0.5 or not. Since we - want to do the whole calculation in integer arithmetic, it's - simpler to do: - - (1) divide by (10**n)/2 - (2) round to nearest multiple of 2 (multiple of 4 in case of tie) - (3) multiply result by (10**n)/2. - - Then all we need to know about the fractional part of the quotient - arising in step (2) is whether it's zero or not. - - Doing both a multiplication and division is wasteful, and is easily - avoided if we just figure out how much to adjust the original input - by to do the rounding. - - Here's the whole algorithm expressed in Python. - - def round(self, ndigits = None): - """round(int, int) -> int""" - if ndigits is None or ndigits >= 0: - return self - pow = 10**-ndigits >> 1 - q, r = divmod(self, pow) - self -= r - if (q & 1 != 0): - if (q & 2 == r == 0): - self -= pow - else: - self += pow - return self + PyLongObject *quo = NULL, *rem = NULL; + PyObject *one = NULL, *twice_rem, *result, *temp; + int cmp, quo_is_odd, quo_is_neg; + + /* Equivalent Python code: + + def divmod_near(a, b): + q, r = divmod(a, b) + # round up if either r / b > 0.5, or r / b == 0.5 and q is odd. + # The expression r / b > 0.5 is equivalent to 2 * r > b if b is + # positive, 2 * r < b if b negative. + greater_than_half = 2*r > b if b > 0 else 2*r < b + exactly_half = 2*r == b + if greater_than_half or exactly_half and q % 2 == 1: + q += 1 + r -= b + return q, r */ + if (!PyLong_Check(a) || !PyLong_Check(b)) { + PyErr_SetString(PyExc_TypeError, + "non-integer arguments in division"); + return NULL; + } + + /* Do a and b have different signs? If so, quotient is negative. */ + quo_is_neg = (Py_SIZE(a) < 0) != (Py_SIZE(b) < 0); + + one = PyLong_FromLong(1L); + if (one == NULL) + return NULL; + + if (long_divrem((PyLongObject*)a, (PyLongObject*)b, &quo, &rem) < 0) + goto error; + + /* compare twice the remainder with the divisor, to see + if we need to adjust the quotient and remainder */ + twice_rem = long_lshift((PyObject *)rem, one); + if (twice_rem == NULL) + goto error; + if (quo_is_neg) { + temp = long_neg((PyLongObject*)twice_rem); + Py_DECREF(twice_rem); + twice_rem = temp; + if (twice_rem == NULL) + goto error; + } + cmp = long_compare((PyLongObject *)twice_rem, (PyLongObject *)b); + Py_DECREF(twice_rem); + + quo_is_odd = Py_SIZE(quo) != 0 && ((quo->ob_digit[0] & 1) != 0); + if ((Py_SIZE(b) < 0 ? cmp < 0 : cmp > 0) || (cmp == 0 && quo_is_odd)) { + /* fix up quotient */ + if (quo_is_neg) + temp = long_sub(quo, (PyLongObject *)one); + else + temp = long_add(quo, (PyLongObject *)one); + Py_DECREF(quo); + quo = (PyLongObject *)temp; + if (quo == NULL) + goto error; + /* and remainder */ + if (quo_is_neg) + temp = long_add(rem, (PyLongObject *)b); + else + temp = long_sub(rem, (PyLongObject *)b); + Py_DECREF(rem); + rem = (PyLongObject *)temp; + if (rem == NULL) + goto error; + } + + result = PyTuple_New(2); + if (result == NULL) + goto error; + + /* PyTuple_SET_ITEM steals references */ + PyTuple_SET_ITEM(result, 0, (PyObject *)quo); + PyTuple_SET_ITEM(result, 1, (PyObject *)rem); + Py_DECREF(one); + return result; + + error: + Py_XDECREF(quo); + Py_XDECREF(rem); + Py_XDECREF(one); + return NULL; +} + +static PyObject * +long_round(PyObject *self, PyObject *args) +{ + PyObject *o_ndigits=NULL, *temp, *result, *ndigits; + + /* To round an integer m to the nearest 10**n (n positive), we make use of + * the divmod_near operation, defined by: + * + * divmod_near(a, b) = (q, r) + * + * where q is the nearest integer to the quotient a / b (the + * nearest even integer in the case of a tie) and r == a - q * b. + * Hence q * b = a - r is the nearest multiple of b to a, + * preferring even multiples in the case of a tie. + * + * So the nearest multiple of 10**n to m is: + * + * m - divmod_near(m, 10**n)[1]. + */ if (!PyArg_ParseTuple(args, "|O", &o_ndigits)) return NULL; if (o_ndigits == NULL) return long_long(self); - ndigits = (PyLongObject *)PyNumber_Index(o_ndigits); + ndigits = PyNumber_Index(o_ndigits); if (ndigits == NULL) return NULL; + /* if ndigits >= 0 then no rounding is necessary; return self unchanged */ if (Py_SIZE(ndigits) >= 0) { Py_DECREF(ndigits); return long_long(self); } - Py_INCREF(self); /* to keep refcounting simple */ - /* we now own references to self, ndigits */ - - /* pow = 10 ** -ndigits >> 1 */ - pow = (PyLongObject *)PyLong_FromLong(10L); - if (pow == NULL) - goto error; - temp = long_neg(ndigits); + /* result = self - divmod_near(self, 10 ** -ndigits)[1] */ + temp = long_neg((PyLongObject*)ndigits); Py_DECREF(ndigits); - ndigits = (PyLongObject *)temp; + ndigits = temp; if (ndigits == NULL) - goto error; - temp = long_pow((PyObject *)pow, (PyObject *)ndigits, Py_None); - Py_DECREF(pow); - pow = (PyLongObject *)temp; - if (pow == NULL) - goto error; - assert(PyLong_Check(pow)); /* check long_pow returned a long */ - one = (PyLongObject *)PyLong_FromLong(1L); - if (one == NULL) - goto error; - temp = long_rshift(pow, one); - Py_DECREF(one); - Py_DECREF(pow); - pow = (PyLongObject *)temp; - if (pow == NULL) - goto error; + return NULL; - /* q, r = divmod(self, pow) */ - errcode = l_divmod((PyLongObject *)self, pow, &q, &r); - if (errcode == -1) - goto error; + result = PyLong_FromLong(10L); + if (result == NULL) { + Py_DECREF(ndigits); + return NULL; + } - /* self -= r */ - temp = long_sub((PyLongObject *)self, r); - Py_DECREF(self); - self = temp; - if (self == NULL) - goto error; + temp = long_pow(result, ndigits, Py_None); + Py_DECREF(ndigits); + Py_DECREF(result); + result = temp; + if (result == NULL) + return NULL; - /* get value of quotient modulo 4 */ - if (Py_SIZE(q) == 0) - q_mod_4 = 0; - else if (Py_SIZE(q) > 0) - q_mod_4 = q->ob_digit[0] & 3; - else - q_mod_4 = (PyLong_BASE-q->ob_digit[0]) & 3; + temp = _PyLong_DivmodNear(self, result); + Py_DECREF(result); + result = temp; + if (result == NULL) + return NULL; - if ((q_mod_4 & 1) == 1) { - /* q is odd; round self up or down by adding or subtracting pow */ - if (q_mod_4 == 1 && Py_SIZE(r) == 0) - temp = (PyObject *)long_sub((PyLongObject *)self, pow); - else - temp = (PyObject *)long_add((PyLongObject *)self, pow); - Py_DECREF(self); - self = temp; - if (self == NULL) - goto error; - } - Py_DECREF(q); - Py_DECREF(r); - Py_DECREF(pow); - Py_DECREF(ndigits); - return self; + temp = long_sub((PyLongObject *)self, + (PyLongObject *)PyTuple_GET_ITEM(result, 1)); + Py_DECREF(result); + result = temp; - error: - Py_XDECREF(q); - Py_XDECREF(r); - Py_XDECREF(pow); - Py_XDECREF(self); - Py_XDECREF(ndigits); - return NULL; + return result; } static PyObject * @@ -4065,7 +4452,7 @@ long_bit_length(PyLongObject *v) return (PyObject *)result; -error: + error: Py_DECREF(result); return NULL; } @@ -4087,6 +4474,187 @@ long_is_finite(PyObject *v) } #endif + +static PyObject * +long_to_bytes(PyLongObject *v, PyObject *args, PyObject *kwds) +{ + PyObject *byteorder_str; + PyObject *is_signed_obj = NULL; + Py_ssize_t length; + int little_endian; + int is_signed; + PyObject *bytes; + static char *kwlist[] = {"length", "byteorder", "signed", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nU|O:to_bytes", kwlist, + &length, &byteorder_str, + &is_signed_obj)) + return NULL; + + if (args != NULL && Py_SIZE(args) > 2) { + PyErr_SetString(PyExc_TypeError, + "'signed' is a keyword-only argument"); + return NULL; + } + + if (!PyUnicode_CompareWithASCIIString(byteorder_str, "little")) + little_endian = 1; + else if (!PyUnicode_CompareWithASCIIString(byteorder_str, "big")) + little_endian = 0; + else { + PyErr_SetString(PyExc_ValueError, + "byteorder must be either 'little' or 'big'"); + return NULL; + } + + if (is_signed_obj != NULL) { + int cmp = PyObject_IsTrue(is_signed_obj); + if (cmp < 0) + return NULL; + is_signed = cmp ? 1 : 0; + } + else { + /* If the signed argument was omitted, use False as the + default. */ + is_signed = 0; + } + + if (length < 0) { + PyErr_SetString(PyExc_ValueError, + "length argument must be non-negative"); + return NULL; + } + + bytes = PyBytes_FromStringAndSize(NULL, length); + if (bytes == NULL) + return NULL; + + if (_PyLong_AsByteArray(v, (unsigned char *)PyBytes_AS_STRING(bytes), + length, little_endian, is_signed) < 0) { + Py_DECREF(bytes); + return NULL; + } + + return bytes; +} + +PyDoc_STRVAR(long_to_bytes_doc, +"int.to_bytes(length, byteorder, *, signed=False) -> bytes\n\ +\n\ +Return an array of bytes representing an integer.\n\ +\n\ +The integer is represented using length bytes. An OverflowError is\n\ +raised if the integer is not representable with the given number of\n\ +bytes.\n\ +\n\ +The byteorder argument determines the byte order used to represent the\n\ +integer. If byteorder is 'big', the most significant byte is at the\n\ +beginning of the byte array. If byteorder is 'little', the most\n\ +significant byte is at the end of the byte array. To request the native\n\ +byte order of the host system, use `sys.byteorder' as the byte order value.\n\ +\n\ +The signed keyword-only argument determines whether two's complement is\n\ +used to represent the integer. If signed is False and a negative integer\n\ +is given, an OverflowError is raised."); + +static PyObject * +long_from_bytes(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *byteorder_str; + PyObject *is_signed_obj = NULL; + int little_endian; + int is_signed; + PyObject *obj; + PyObject *bytes; + PyObject *long_obj; + static char *kwlist[] = {"bytes", "byteorder", "signed", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OU|O:from_bytes", kwlist, + &obj, &byteorder_str, + &is_signed_obj)) + return NULL; + + if (args != NULL && Py_SIZE(args) > 2) { + PyErr_SetString(PyExc_TypeError, + "'signed' is a keyword-only argument"); + return NULL; + } + + if (!PyUnicode_CompareWithASCIIString(byteorder_str, "little")) + little_endian = 1; + else if (!PyUnicode_CompareWithASCIIString(byteorder_str, "big")) + little_endian = 0; + else { + PyErr_SetString(PyExc_ValueError, + "byteorder must be either 'little' or 'big'"); + return NULL; + } + + if (is_signed_obj != NULL) { + int cmp = PyObject_IsTrue(is_signed_obj); + if (cmp < 0) + return NULL; + is_signed = cmp ? 1 : 0; + } + else { + /* If the signed argument was omitted, use False as the + default. */ + is_signed = 0; + } + + bytes = PyObject_Bytes(obj); + if (bytes == NULL) + return NULL; + + long_obj = _PyLong_FromByteArray( + (unsigned char *)PyBytes_AS_STRING(bytes), Py_SIZE(bytes), + little_endian, is_signed); + Py_DECREF(bytes); + + /* If from_bytes() was used on subclass, allocate new subclass + * instance, initialize it with decoded long value and return it. + */ + if (type != &PyLong_Type && PyType_IsSubtype(type, &PyLong_Type)) { + PyLongObject *newobj; + int i; + Py_ssize_t n = ABS(Py_SIZE(long_obj)); + + newobj = (PyLongObject *)type->tp_alloc(type, n); + if (newobj == NULL) { + Py_DECREF(long_obj); + return NULL; + } + assert(PyLong_Check(newobj)); + Py_SIZE(newobj) = Py_SIZE(long_obj); + for (i = 0; i < n; i++) { + newobj->ob_digit[i] = + ((PyLongObject *)long_obj)->ob_digit[i]; + } + Py_DECREF(long_obj); + return (PyObject *)newobj; + } + + return long_obj; +} + +PyDoc_STRVAR(long_from_bytes_doc, +"int.from_bytes(bytes, byteorder, *, signed=False) -> int\n\ +\n\ +Return the integer represented by the given array of bytes.\n\ +\n\ +The bytes argument must either support the buffer protocol or be an\n\ +iterable object producing bytes. Bytes and bytearray are examples of\n\ +built-in objects that support the buffer protocol.\n\ +\n\ +The byteorder argument determines the byte order used to represent the\n\ +integer. If byteorder is 'big', the most significant byte is at the\n\ +beginning of the byte array. If byteorder is 'little', the most\n\ +significant byte is at the end of the byte array. To request the native\n\ +byte order of the host system, use `sys.byteorder' as the byte order value.\n\ +\n\ +The signed keyword-only argument indicates whether two's complement is\n\ +used to represent the integer."); + static PyMethodDef long_methods[] = { {"conjugate", (PyCFunction)long_long, METH_NOARGS, "Returns self, the complex conjugate of any int."}, @@ -4096,6 +4664,10 @@ static PyMethodDef long_methods[] = { {"is_finite", (PyCFunction)long_is_finite, METH_NOARGS, "Returns always True."}, #endif + {"to_bytes", (PyCFunction)long_to_bytes, + METH_VARARGS|METH_KEYWORDS, long_to_bytes_doc}, + {"from_bytes", (PyCFunction)long_from_bytes, + METH_VARARGS|METH_KEYWORDS|METH_CLASS, long_from_bytes_doc}, {"__trunc__", (PyCFunction)long_long, METH_NOARGS, "Truncating an Integral returns itself."}, {"__floor__", (PyCFunction)long_long, METH_NOARGS, @@ -4142,40 +4714,40 @@ string, use the optional base. It is an error to supply a base when\n\ converting a non-string."); static PyNumberMethods long_as_number = { - (binaryfunc) long_add, /*nb_add*/ - (binaryfunc) long_sub, /*nb_subtract*/ - (binaryfunc) long_mul, /*nb_multiply*/ - long_mod, /*nb_remainder*/ - long_divmod, /*nb_divmod*/ - long_pow, /*nb_power*/ - (unaryfunc) long_neg, /*nb_negative*/ - (unaryfunc) long_long, /*tp_positive*/ - (unaryfunc) long_abs, /*tp_absolute*/ - (inquiry) long_bool, /*tp_bool*/ - (unaryfunc) long_invert, /*nb_invert*/ - long_lshift, /*nb_lshift*/ - (binaryfunc) long_rshift, /*nb_rshift*/ - long_and, /*nb_and*/ - long_xor, /*nb_xor*/ - long_or, /*nb_or*/ - long_long, /*nb_int*/ - 0, /*nb_reserved*/ - long_float, /*nb_float*/ - 0, /* nb_inplace_add */ - 0, /* nb_inplace_subtract */ - 0, /* nb_inplace_multiply */ - 0, /* nb_inplace_remainder */ - 0, /* nb_inplace_power */ - 0, /* nb_inplace_lshift */ - 0, /* nb_inplace_rshift */ - 0, /* nb_inplace_and */ - 0, /* nb_inplace_xor */ - 0, /* nb_inplace_or */ - long_div, /* nb_floor_divide */ - long_true_divide, /* nb_true_divide */ - 0, /* nb_inplace_floor_divide */ - 0, /* nb_inplace_true_divide */ - long_long, /* nb_index */ + (binaryfunc)long_add, /*nb_add*/ + (binaryfunc)long_sub, /*nb_subtract*/ + (binaryfunc)long_mul, /*nb_multiply*/ + long_mod, /*nb_remainder*/ + long_divmod, /*nb_divmod*/ + long_pow, /*nb_power*/ + (unaryfunc)long_neg, /*nb_negative*/ + (unaryfunc)long_long, /*tp_positive*/ + (unaryfunc)long_abs, /*tp_absolute*/ + (inquiry)long_bool, /*tp_bool*/ + (unaryfunc)long_invert, /*nb_invert*/ + long_lshift, /*nb_lshift*/ + (binaryfunc)long_rshift, /*nb_rshift*/ + long_and, /*nb_and*/ + long_xor, /*nb_xor*/ + long_or, /*nb_or*/ + long_long, /*nb_int*/ + 0, /*nb_reserved*/ + long_float, /*nb_float*/ + 0, /* nb_inplace_add */ + 0, /* nb_inplace_subtract */ + 0, /* nb_inplace_multiply */ + 0, /* nb_inplace_remainder */ + 0, /* nb_inplace_power */ + 0, /* nb_inplace_lshift */ + 0, /* nb_inplace_rshift */ + 0, /* nb_inplace_and */ + 0, /* nb_inplace_xor */ + 0, /* nb_inplace_or */ + long_div, /* nb_floor_divide */ + long_true_divide, /* nb_true_divide */ + 0, /* nb_inplace_floor_divide */ + 0, /* nb_inplace_true_divide */ + long_long, /* nb_index */ }; PyTypeObject PyLong_Type = { @@ -4188,13 +4760,13 @@ PyTypeObject PyLong_Type = { 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ - long_repr, /* tp_repr */ + long_to_decimal_string, /* tp_repr */ &long_as_number, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)long_hash, /* tp_hash */ 0, /* tp_call */ - long_repr, /* tp_str */ + long_to_decimal_string, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ @@ -4231,8 +4803,7 @@ internal representation of integers. The attributes are read only."); static PyStructSequence_Field int_info_fields[] = { {"bits_per_digit", "size of a digit in bits"}, - {"sizeof_digit", "size in bytes of the C type used to " - "represent a digit"}, + {"sizeof_digit", "size in bytes of the C type used to represent a digit"}, {NULL, NULL} }; diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c index 9b77ea7..2e32b2a 100644 --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -3,6 +3,23 @@ #include "Python.h" +#define IS_RELEASED(memobj) \ + (((PyMemoryViewObject *) memobj)->view.buf == NULL) + +#define CHECK_RELEASED(memobj) \ + if (IS_RELEASED(memobj)) { \ + PyErr_SetString(PyExc_ValueError, \ + "operation forbidden on released memoryview object"); \ + return NULL; \ + } + +#define CHECK_RELEASED_INT(memobj) \ + if (IS_RELEASED(memobj)) { \ + PyErr_SetString(PyExc_ValueError, \ + "operation forbidden on released memoryview object"); \ + return -1; \ + } + static Py_ssize_t get_shape0(Py_buffer *buf) { @@ -34,6 +51,7 @@ static int memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags) { int res = 0; + CHECK_RELEASED_INT(self); if (self->view.obj != NULL) res = PyObject_GetBuffer(self->view.obj, view, flags); if (view) @@ -57,11 +75,15 @@ PyMemoryView_FromBuffer(Py_buffer *info) { PyMemoryViewObject *mview; + if (info->buf == NULL) { + PyErr_SetString(PyExc_ValueError, + "cannot make memory view from a buffer with a NULL data pointer"); + return NULL; + } mview = (PyMemoryViewObject *) PyObject_GC_New(PyMemoryViewObject, &PyMemoryView_Type); if (mview == NULL) return NULL; - mview->base = NULL; dup_buffer(&mview->view, info); /* NOTE: mview->view.obj should already have been incref'ed as part of PyBuffer_FillInfo(). */ @@ -91,8 +113,6 @@ PyMemoryView_FromObject(PyObject *base) return NULL; } - mview->base = base; - Py_INCREF(base); return (PyObject *)mview; } @@ -270,8 +290,6 @@ PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort) if (PyBuffer_IsContiguous(view, fort)) { /* no copy needed */ - Py_INCREF(obj); - mem->base = obj; _PyObject_GC_TRACK(mem); return (PyObject *)mem; } @@ -303,21 +321,7 @@ PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort) Py_DECREF(mem); return NULL; } - } - if (buffertype == PyBUF_SHADOW) { - /* return a shadowed memory-view object */ - view->buf = dest; - mem->base = PyTuple_Pack(2, obj, bytes); - Py_DECREF(bytes); - if (mem->base == NULL) { - Py_DECREF(mem); - return NULL; - } - } - else { PyBuffer_Release(view); /* XXX ? */ - /* steal the reference */ - mem->base = bytes; } _PyObject_GC_TRACK(mem); return (PyObject *)mem; @@ -327,12 +331,14 @@ PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort) static PyObject * memory_format_get(PyMemoryViewObject *self) { + CHECK_RELEASED(self); return PyUnicode_FromString(self->view.format); } static PyObject * memory_itemsize_get(PyMemoryViewObject *self) { + CHECK_RELEASED(self); return PyLong_FromSsize_t(self->view.itemsize); } @@ -348,8 +354,9 @@ _IntTupleFromSsizet(int len, Py_ssize_t *vals) return Py_None; } intTuple = PyTuple_New(len); - if (!intTuple) return NULL; - for(i=0; i<len; i++) { + if (!intTuple) + return NULL; + for (i=0; i<len; i++) { o = PyLong_FromSsize_t(vals[i]); if (!o) { Py_DECREF(intTuple); @@ -363,30 +370,35 @@ _IntTupleFromSsizet(int len, Py_ssize_t *vals) static PyObject * memory_shape_get(PyMemoryViewObject *self) { + CHECK_RELEASED(self); return _IntTupleFromSsizet(self->view.ndim, self->view.shape); } static PyObject * memory_strides_get(PyMemoryViewObject *self) { + CHECK_RELEASED(self); return _IntTupleFromSsizet(self->view.ndim, self->view.strides); } static PyObject * memory_suboffsets_get(PyMemoryViewObject *self) { + CHECK_RELEASED(self); return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets); } static PyObject * memory_readonly_get(PyMemoryViewObject *self) { + CHECK_RELEASED(self); return PyBool_FromLong(self->view.readonly); } static PyObject * memory_ndim_get(PyMemoryViewObject *self) { + CHECK_RELEASED(self); return PyLong_FromLong(self->view.ndim); } @@ -405,6 +417,7 @@ static PyGetSetDef memory_getsetlist[] ={ static PyObject * memory_tobytes(PyMemoryViewObject *mem, PyObject *noargs) { + CHECK_RELEASED(mem); return PyObject_CallFunctionObjArgs( (PyObject *) &PyBytes_Type, mem, NULL); } @@ -420,6 +433,7 @@ memory_tolist(PyMemoryViewObject *mem, PyObject *noargs) PyObject *res, *item; char *buf; + CHECK_RELEASED(mem); if (strcmp(view->format, "B") || view->itemsize != 1) { PyErr_SetString(PyExc_NotImplementedError, "tolist() only supports byte views"); @@ -446,9 +460,37 @@ memory_tolist(PyMemoryViewObject *mem, PyObject *noargs) return res; } +static void +do_release(PyMemoryViewObject *self) +{ + if (self->view.obj != NULL) { + PyBuffer_Release(&(self->view)); + } + self->view.obj = NULL; + self->view.buf = NULL; +} + +static PyObject * +memory_enter(PyObject *self, PyObject *args) +{ + CHECK_RELEASED(self); + Py_INCREF(self); + return self; +} + +static PyObject * +memory_exit(PyObject *self, PyObject *args) +{ + do_release((PyMemoryViewObject *) self); + Py_RETURN_NONE; +} + static PyMethodDef memory_methods[] = { + {"release", memory_exit, METH_NOARGS}, {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, NULL}, {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, NULL}, + {"__enter__", memory_enter, METH_NOARGS}, + {"__exit__", memory_exit, METH_VARARGS}, {NULL, NULL} /* sentinel */ }; @@ -457,43 +499,24 @@ static void memory_dealloc(PyMemoryViewObject *self) { _PyObject_GC_UNTRACK(self); - if (self->view.obj != NULL) { - if (self->base && PyTuple_Check(self->base)) { - /* Special case when first element is generic object - with buffer interface and the second element is a - contiguous "shadow" that must be copied back into - the data areay of the first tuple element before - releasing the buffer on the first element. - */ - - PyObject_CopyData(PyTuple_GET_ITEM(self->base,0), - PyTuple_GET_ITEM(self->base,1)); - - /* The view member should have readonly == -1 in - this instance indicating that the memory can - be "locked" and was locked and will be unlocked - again after this call. - */ - PyBuffer_Release(&(self->view)); - } - else { - PyBuffer_Release(&(self->view)); - } - Py_CLEAR(self->base); - } + do_release(self); PyObject_GC_Del(self); } static PyObject * memory_repr(PyMemoryViewObject *self) { - return PyUnicode_FromFormat("<memory at %p>", self); + if (IS_RELEASED(self)) + return PyUnicode_FromFormat("<released memory at %p>", self); + else + return PyUnicode_FromFormat("<memory at %p>", self); } /* Sequence methods */ static Py_ssize_t memory_length(PyMemoryViewObject *self) { + CHECK_RELEASED_INT(self); return get_shape0(&self->view); } @@ -505,6 +528,7 @@ memory_item(PyMemoryViewObject *self, Py_ssize_t result) { Py_buffer *view = &(self->view); + CHECK_RELEASED(self); if (view->ndim == 0) { PyErr_SetString(PyExc_IndexError, "invalid indexing of 0-dim memory"); @@ -554,6 +578,7 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key) Py_buffer *view; view = &(self->view); + CHECK_RELEASED(self); if (view->ndim == 0) { if (key == Py_Ellipsis || (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) { @@ -576,7 +601,7 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key) else if (PySlice_Check(key)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((PySliceObject*)key, get_shape0(view), + if (PySlice_GetIndicesEx(key, get_shape0(view), &start, &stop, &step, &slicelength) < 0) { return NULL; } @@ -623,6 +648,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value) Py_buffer *view = &(self->view); char *srcbuf, *destbuf; + CHECK_RELEASED_INT(self); if (view->readonly) { PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory"); @@ -654,7 +680,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value) else if (PySlice_Check(key)) { Py_ssize_t stop, step; - if (PySlice_GetIndicesEx((PySliceObject*)key, get_shape0(view), + if (PySlice_GetIndicesEx(key, get_shape0(view), &start, &stop, &step, &len) < 0) { return -1; } @@ -715,6 +741,11 @@ memory_richcompare(PyObject *v, PyObject *w, int op) ww.obj = NULL; if (op != Py_EQ && op != Py_NE) goto _notimpl; + if ((PyMemoryView_Check(v) && IS_RELEASED(v)) || + (PyMemoryView_Check(w) && IS_RELEASED(w))) { + equal = (v == w); + goto _end; + } if (PyObject_GetBuffer(v, &vv, PyBUF_CONTIG_RO) == -1) { PyErr_Clear(); goto _notimpl; @@ -750,8 +781,6 @@ _notimpl: static int memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg) { - if (self->base != NULL) - Py_VISIT(self->base); if (self->view.obj != NULL) Py_VISIT(self->view.obj); return 0; @@ -760,7 +789,6 @@ memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg) static int memory_clear(PyMemoryViewObject *self) { - Py_CLEAR(self->base); PyBuffer_Release(&self->view); return 0; } @@ -774,10 +802,10 @@ static PyMappingMethods memory_as_mapping = { }; static PySequenceMethods memory_as_sequence = { - 0, /* sq_length */ - 0, /* sq_concat */ - 0, /* sq_repeat */ - (ssizeargfunc)memory_item, /* sq_item */ + 0, /* sq_length */ + 0, /* sq_concat */ + 0, /* sq_repeat */ + (ssizeargfunc)memory_item, /* sq_item */ }; /* Buffer methods */ diff --git a/Objects/methodobject.c b/Objects/methodobject.c index 356d161..f1a9f4b 100644 --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -224,10 +224,10 @@ meth_richcompare(PyObject *self, PyObject *other, int op) return res; } -static long +static Py_hash_t meth_hash(PyCFunctionObject *a) { - long x,y; + Py_hash_t x, y; if (a->m_self == NULL) x = 0; else { diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index d96d7bd..f31b5da 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -56,10 +56,6 @@ PyModule_New(const char *name) return NULL; } -static char api_version_warning[] = -"Python C API version mismatch for module %.100s:\ - This Python has API version %d, module %.100s has version %d."; - PyObject * PyModule_Create2(struct PyModuleDef* module, int module_api_version) { @@ -79,13 +75,14 @@ PyModule_Create2(struct PyModuleDef* module, int module_api_version) module->m_base.m_index = max_module_number; } name = module->m_name; - if (module_api_version != PYTHON_API_VERSION) { - char message[512]; - PyOS_snprintf(message, sizeof(message), - api_version_warning, name, - PYTHON_API_VERSION, name, - module_api_version); - if (PyErr_WarnEx(PyExc_RuntimeWarning, message, 1)) + if (module_api_version != PYTHON_API_VERSION && module_api_version != PYTHON_ABI_VERSION) { + int err; + err = PyErr_WarnFormat(PyExc_RuntimeWarning, 1, + "Python C API version mismatch for module %.100s: " + "This Python has API version %d, module %.100s has version %d.", + name, + PYTHON_API_VERSION, name, module_api_version); + if (err) return NULL; } /* Make sure name is fully qualified. @@ -192,8 +189,8 @@ PyModule_GetName(PyObject *m) return _PyUnicode_AsString(nameobj); } -const char * -PyModule_GetFilename(PyObject *m) +PyObject* +PyModule_GetFilenameObject(PyObject *m) { PyObject *d; PyObject *fileobj; @@ -209,7 +206,21 @@ PyModule_GetFilename(PyObject *m) PyErr_SetString(PyExc_SystemError, "module filename missing"); return NULL; } - return _PyUnicode_AsString(fileobj); + Py_INCREF(fileobj); + return fileobj; +} + +const char * +PyModule_GetFilename(PyObject *m) +{ + PyObject *fileobj; + char *utf8; + fileobj = PyModule_GetFilenameObject(m); + if (fileobj == NULL) + return NULL; + utf8 = _PyUnicode_AsString(fileobj); + Py_DECREF(fileobj); + return utf8; } PyModuleDef* @@ -254,10 +265,15 @@ _PyModule_Clear(PyObject *m) pos = 0; while (PyDict_Next(d, &pos, &key, &value)) { if (value != Py_None && PyUnicode_Check(key)) { - const char *s = _PyUnicode_AsString(key); - if (s[0] == '_' && s[1] != '_') { - if (Py_VerboseFlag > 1) - PySys_WriteStderr("# clear[1] %s\n", s); + Py_UNICODE *u = PyUnicode_AS_UNICODE(key); + if (u[0] == '_' && u[1] != '_') { + if (Py_VerboseFlag > 1) { + const char *s = _PyUnicode_AsString(key); + if (s != NULL) + PySys_WriteStderr("# clear[1] %s\n", s); + else + PyErr_Clear(); + } PyDict_SetItem(d, key, Py_None); } } @@ -267,10 +283,17 @@ _PyModule_Clear(PyObject *m) pos = 0; while (PyDict_Next(d, &pos, &key, &value)) { if (value != Py_None && PyUnicode_Check(key)) { - const char *s = _PyUnicode_AsString(key); - if (s[0] != '_' || strcmp(s, "__builtins__") != 0) { - if (Py_VerboseFlag > 1) - PySys_WriteStderr("# clear[2] %s\n", s); + Py_UNICODE *u = PyUnicode_AS_UNICODE(key); + if (u[0] != '_' + || PyUnicode_CompareWithASCIIString(key, "__builtins__") != 0) + { + if (Py_VerboseFlag > 1) { + const char *s = _PyUnicode_AsString(key); + if (s != NULL) + PySys_WriteStderr("# clear[2] %s\n", s); + else + PyErr_Clear(); + } PyDict_SetItem(d, key, Py_None); } } @@ -325,19 +348,21 @@ static PyObject * module_repr(PyModuleObject *m) { const char *name; - const char *filename; + PyObject *filename, *repr; name = PyModule_GetName((PyObject *)m); if (name == NULL) { PyErr_Clear(); name = "?"; } - filename = PyModule_GetFilename((PyObject *)m); + filename = PyModule_GetFilenameObject((PyObject *)m); if (filename == NULL) { PyErr_Clear(); return PyUnicode_FromFormat("<module '%s' (built-in)>", name); } - return PyUnicode_FromFormat("<module '%s' from '%s'>", name, filename); + repr = PyUnicode_FromFormat("<module '%s' from '%U'>", name, filename); + Py_DECREF(filename); + return repr; } static int diff --git a/Objects/object.c b/Objects/object.c index ac57cd7..a91c46a 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -2,7 +2,6 @@ /* Generic object operations; and implementation of None (NoObject) */ #include "Python.h" -#include "sliceobject.h" /* For PyEllipsis_Type */ #include "frameobject.h" #ifdef __cplusplus @@ -536,10 +535,12 @@ do_richcompare(PyObject *v, PyObject *w, int op) { richcmpfunc f; PyObject *res; + int checked_reverse_op = 0; if (v->ob_type != w->ob_type && PyType_IsSubtype(w->ob_type, v->ob_type) && (f = w->ob_type->tp_richcompare) != NULL) { + checked_reverse_op = 1; res = (*f)(w, v, _Py_SwappedOp[op]); if (res != Py_NotImplemented) return res; @@ -551,7 +552,7 @@ do_richcompare(PyObject *v, PyObject *w, int op) return res; Py_DECREF(res); } - if ((f = w->ob_type->tp_richcompare) != NULL) { + if (!checked_reverse_op && (f = w->ob_type->tp_richcompare) != NULL) { res = (*f)(w, v, _Py_SwappedOp[op]); if (res != Py_NotImplemented) return res; @@ -634,77 +635,118 @@ PyObject_RichCompareBool(PyObject *v, PyObject *w, int op) All the utility functions (_Py_Hash*()) return "-1" to signify an error. */ -long +/* For numeric types, the hash of a number x is based on the reduction + of x modulo the prime P = 2**_PyHASH_BITS - 1. It's designed so that + hash(x) == hash(y) whenever x and y are numerically equal, even if + x and y have different types. + + A quick summary of the hashing strategy: + + (1) First define the 'reduction of x modulo P' for any rational + number x; this is a standard extension of the usual notion of + reduction modulo P for integers. If x == p/q (written in lowest + terms), the reduction is interpreted as the reduction of p times + the inverse of the reduction of q, all modulo P; if q is exactly + divisible by P then define the reduction to be infinity. So we've + got a well-defined map + + reduce : { rational numbers } -> { 0, 1, 2, ..., P-1, infinity }. + + (2) Now for a rational number x, define hash(x) by: + + reduce(x) if x >= 0 + -reduce(-x) if x < 0 + + If the result of the reduction is infinity (this is impossible for + integers, floats and Decimals) then use the predefined hash value + _PyHASH_INF for x >= 0, or -_PyHASH_INF for x < 0, instead. + _PyHASH_INF, -_PyHASH_INF and _PyHASH_NAN are also used for the + hashes of float and Decimal infinities and nans. + + A selling point for the above strategy is that it makes it possible + to compute hashes of decimal and binary floating-point numbers + efficiently, even if the exponent of the binary or decimal number + is large. The key point is that + + reduce(x * y) == reduce(x) * reduce(y) (modulo _PyHASH_MODULUS) + + provided that {reduce(x), reduce(y)} != {0, infinity}. The reduction of a + binary or decimal float is never infinity, since the denominator is a power + of 2 (for binary) or a divisor of a power of 10 (for decimal). So we have, + for nonnegative x, + + reduce(x * 2**e) == reduce(x) * reduce(2**e) % _PyHASH_MODULUS + + reduce(x * 10**e) == reduce(x) * reduce(10**e) % _PyHASH_MODULUS + + and reduce(10**e) can be computed efficiently by the usual modular + exponentiation algorithm. For reduce(2**e) it's even better: since + P is of the form 2**n-1, reduce(2**e) is 2**(e mod n), and multiplication + by 2**(e mod n) modulo 2**n-1 just amounts to a rotation of bits. + + */ + +Py_hash_t _Py_HashDouble(double v) { - double intpart, fractpart; - int expo; - long hipart; - long x; /* the final hash value */ - /* This is designed so that Python numbers of different types - * that compare equal hash to the same value; otherwise comparisons - * of mapping keys will turn out weird. - */ + int e, sign; + double m; + Py_uhash_t x, y; - fractpart = modf(v, &intpart); - if (fractpart == 0.0) { - /* This must return the same hash as an equal int or long. */ - if (intpart > LONG_MAX/2 || -intpart > LONG_MAX/2) { - /* Convert to long and use its hash. */ - PyObject *plong; /* converted to Python long */ - if (Py_IS_INFINITY(intpart)) - /* can't convert to long int -- arbitrary */ - v = v < 0 ? -271828.0 : 314159.0; - plong = PyLong_FromDouble(v); - if (plong == NULL) - return -1; - x = PyObject_Hash(plong); - Py_DECREF(plong); - return x; - } - /* Fits in a C long == a Python int, so is its own hash. */ - x = (long)intpart; - if (x == -1) - x = -2; - return x; - } - /* The fractional part is non-zero, so we don't have to worry about - * making this match the hash of some other type. - * Use frexp to get at the bits in the double. - * Since the VAX D double format has 56 mantissa bits, which is the - * most of any double format in use, each of these parts may have as - * many as (but no more than) 56 significant bits. - * So, assuming sizeof(long) >= 4, each part can be broken into two - * longs; frexp and multiplication are used to do that. - * Also, since the Cray double format has 15 exponent bits, which is - * the most of any double format in use, shifting the exponent field - * left by 15 won't overflow a long (again assuming sizeof(long) >= 4). - */ - v = frexp(v, &expo); - v *= 2147483648.0; /* 2**31 */ - hipart = (long)v; /* take the top 32 bits */ - v = (v - (double)hipart) * 2147483648.0; /* get the next 32 bits */ - x = hipart + (long)v + (expo << 15); - if (x == -1) - x = -2; - return x; + if (!Py_IS_FINITE(v)) { + if (Py_IS_INFINITY(v)) + return v > 0 ? _PyHASH_INF : -_PyHASH_INF; + else + return _PyHASH_NAN; + } + + m = frexp(v, &e); + + sign = 1; + if (m < 0) { + sign = -1; + m = -m; + } + + /* process 28 bits at a time; this should work well both for binary + and hexadecimal floating point. */ + x = 0; + while (m) { + x = ((x << 28) & _PyHASH_MODULUS) | x >> (_PyHASH_BITS - 28); + m *= 268435456.0; /* 2**28 */ + e -= 28; + y = (Py_uhash_t)m; /* pull out integer part */ + m -= y; + x += y; + if (x >= _PyHASH_MODULUS) + x -= _PyHASH_MODULUS; + } + + /* adjust for the exponent; first reduce it modulo _PyHASH_BITS */ + e = e >= 0 ? e % _PyHASH_BITS : _PyHASH_BITS-1-((-1-e) % _PyHASH_BITS); + x = ((x << e) & _PyHASH_MODULUS) | x >> (_PyHASH_BITS - e); + + x = x * sign; + if (x == (Py_uhash_t)-1) + x = (Py_uhash_t)-2; + return (Py_hash_t)x; } -long +Py_hash_t _Py_HashPointer(void *p) { - long x; + Py_hash_t x; size_t y = (size_t)p; /* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid excessive hash collisions for dicts and sets */ y = (y >> 4) | (y << (8 * SIZEOF_VOID_P - 4)); - x = (long)y; + x = (Py_hash_t)y; if (x == -1) x = -2; return x; } -long +Py_hash_t PyObject_HashNotImplemented(PyObject *v) { PyErr_Format(PyExc_TypeError, "unhashable type: '%.200s'", @@ -712,7 +754,7 @@ PyObject_HashNotImplemented(PyObject *v) return -1; } -long +Py_hash_t PyObject_Hash(PyObject *v) { PyTypeObject *tp = Py_TYPE(v); @@ -934,31 +976,7 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict) goto done; } -#if 0 /* XXX this is not quite _PyType_Lookup anymore */ - /* Inline _PyType_Lookup */ - { - Py_ssize_t i, n; - PyObject *mro, *base, *dict; - - /* Look in tp_dict of types in MRO */ - mro = tp->tp_mro; - assert(mro != NULL); - assert(PyTuple_Check(mro)); - n = PyTuple_GET_SIZE(mro); - for (i = 0; i < n; i++) { - base = PyTuple_GET_ITEM(mro, i); - assert(PyType_Check(base)); - dict = ((PyTypeObject *)base)->tp_dict; - assert(dict && PyDict_Check(dict)); - descr = PyDict_GetItem(dict, name); - if (descr != NULL) - break; - } - } -#else descr = _PyType_Lookup(tp, name); -#endif - Py_XINCREF(descr); f = NULL; @@ -1553,10 +1571,9 @@ _Py_ReadyTypes(void) if (PyType_Ready(&PyStaticMethod_Type) < 0) Py_FatalError("Can't initialize static method type"); -#ifndef WITHOUT_COMPLEX if (PyType_Ready(&PyComplex_Type) < 0) Py_FatalError("Can't initialize complex type"); -#endif + if (PyType_Ready(&PyFloat_Type) < 0) Py_FatalError("Can't initialize float type"); @@ -1739,10 +1756,6 @@ _Py_GetObjects(PyObject *self, PyObject *args) #endif -/* Hack to force loading of cobject.o */ -PyTypeObject *_Py_cobject_hack = &PyCObject_Type; - - /* Hack to force loading of pycapsule.o */ PyTypeObject *_PyCapsule_hack = &PyCapsule_Type; @@ -1887,6 +1900,19 @@ _PyTrash_destroy_chain(void) } } +#ifndef Py_TRACE_REFS +/* For Py_LIMITED_API, we need an out-of-line version of _Py_Dealloc. + Define this here, so we can undefine the macro. */ +#undef _Py_Dealloc +PyAPI_FUNC(void) _Py_Dealloc(PyObject *); +void +_Py_Dealloc(PyObject *op) +{ + _Py_INC_TPFREES(op) _Py_COUNT_ALLOCS_COMMA + (*Py_TYPE(op)->tp_dealloc)(op); +} +#endif + #ifdef __cplusplus } #endif diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index af12f41..3916262 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -2,6 +2,21 @@ #ifdef WITH_PYMALLOC +#ifdef WITH_VALGRIND +#include <valgrind/valgrind.h> + +/* If we're using GCC, use __builtin_expect() to reduce overhead of + the valgrind checks */ +#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) +# define UNLIKELY(value) __builtin_expect((value), 0) +#else +# define UNLIKELY(value) (value) +#endif + +/* -1 indicates that we haven't checked that we're running on valgrind yet. */ +static int running_on_valgrind = -1; +#endif + /* An object allocator for Python. Here is an introduction to the layers of the Python memory architecture, @@ -736,6 +751,13 @@ PyObject_Malloc(size_t nbytes) poolp next; uint size; +#ifdef WITH_VALGRIND + if (UNLIKELY(running_on_valgrind == -1)) + running_on_valgrind = RUNNING_ON_VALGRIND; + if (UNLIKELY(running_on_valgrind)) + goto redirect; +#endif + /* * Limit ourselves to PY_SSIZE_T_MAX bytes to prevent security holes. * Most python internals blindly use a signed Py_ssize_t to track @@ -938,6 +960,11 @@ PyObject_Free(void *p) if (p == NULL) /* free(NULL) has no effect */ return; +#ifdef WITH_VALGRIND + if (UNLIKELY(running_on_valgrind > 0)) + goto redirect; +#endif + pool = POOL_ADDR(p); if (Py_ADDRESS_IN_RANGE(p, pool)) { /* We allocated this address. */ @@ -1132,6 +1159,9 @@ PyObject_Free(void *p) return; } +#ifdef WITH_VALGRIND +redirect: +#endif /* We didn't allocate this address. */ free(p); } @@ -1164,6 +1194,12 @@ PyObject_Realloc(void *p, size_t nbytes) if (nbytes > PY_SSIZE_T_MAX) return NULL; +#ifdef WITH_VALGRIND + /* Treat running_on_valgrind == -1 the same as 0 */ + if (UNLIKELY(running_on_valgrind > 0)) + goto redirect; +#endif + pool = POOL_ADDR(p); if (Py_ADDRESS_IN_RANGE(p, pool)) { /* We're in charge of this block */ @@ -1191,6 +1227,9 @@ PyObject_Realloc(void *p, size_t nbytes) } return bp; } +#ifdef WITH_VALGRIND + redirect: +#endif /* We're not managing this block. If nbytes <= * SMALL_REQUEST_THRESHOLD, it's tempting to try to take over this * block. However, if we do, we need to copy the valid data from @@ -1255,6 +1294,10 @@ PyObject_Free(void *p) #define DEADBYTE 0xDB /* dead (newly freed) memory */ #define FORBIDDENBYTE 0xFB /* untouchable bytes at each end of a block */ +/* We tag each block with an API ID in order to tag API violations */ +#define _PYMALLOC_MEM_ID 'm' /* the PyMem_Malloc() API */ +#define _PYMALLOC_OBJ_ID 'o' /* The PyObject_Malloc() API */ + static size_t serialno = 0; /* incremented on each debug {m,re}alloc */ /* serialno is always incremented via calling this routine. The point is @@ -1345,9 +1388,50 @@ p[2*S+n+S: 2*S+n+2*S] instant at which this block was passed out. */ +/* debug replacements for the PyMem_* memory API */ +void * +_PyMem_DebugMalloc(size_t nbytes) +{ + return _PyObject_DebugMallocApi(_PYMALLOC_MEM_ID, nbytes); +} +void * +_PyMem_DebugRealloc(void *p, size_t nbytes) +{ + return _PyObject_DebugReallocApi(_PYMALLOC_MEM_ID, p, nbytes); +} +void +_PyMem_DebugFree(void *p) +{ + _PyObject_DebugFreeApi(_PYMALLOC_MEM_ID, p); +} + +/* debug replacements for the PyObject_* memory API */ void * _PyObject_DebugMalloc(size_t nbytes) { + return _PyObject_DebugMallocApi(_PYMALLOC_OBJ_ID, nbytes); +} +void * +_PyObject_DebugRealloc(void *p, size_t nbytes) +{ + return _PyObject_DebugReallocApi(_PYMALLOC_OBJ_ID, p, nbytes); +} +void +_PyObject_DebugFree(void *p) +{ + _PyObject_DebugFreeApi(_PYMALLOC_OBJ_ID, p); +} +void +_PyObject_DebugCheckAddress(const void *p) +{ + _PyObject_DebugCheckAddressApi(_PYMALLOC_OBJ_ID, p); +} + + +/* generic debug memory api, with an "id" to identify the API in use */ +void * +_PyObject_DebugMallocApi(char id, size_t nbytes) +{ uchar *p; /* base address of malloc'ed block */ uchar *tail; /* p + 2*SST + nbytes == pointer to tail pad bytes */ size_t total; /* nbytes + 4*SST */ @@ -1362,12 +1446,15 @@ _PyObject_DebugMalloc(size_t nbytes) if (p == NULL) return NULL; + /* at p, write size (SST bytes), id (1 byte), pad (SST-1 bytes) */ write_size_t(p, nbytes); - memset(p + SST, FORBIDDENBYTE, SST); + p[SST] = (uchar)id; + memset(p + SST + 1 , FORBIDDENBYTE, SST-1); if (nbytes > 0) memset(p + 2*SST, CLEANBYTE, nbytes); + /* at tail, write pad (SST bytes) and serialno (SST bytes) */ tail = p + 2*SST + nbytes; memset(tail, FORBIDDENBYTE, SST); write_size_t(tail + SST, serialno); @@ -1376,27 +1463,28 @@ _PyObject_DebugMalloc(size_t nbytes) } /* The debug free first checks the 2*SST bytes on each end for sanity (in - particular, that the FORBIDDENBYTEs are still intact). + particular, that the FORBIDDENBYTEs with the api ID are still intact). Then fills the original bytes with DEADBYTE. Then calls the underlying free. */ void -_PyObject_DebugFree(void *p) +_PyObject_DebugFreeApi(char api, void *p) { uchar *q = (uchar *)p - 2*SST; /* address returned from malloc */ size_t nbytes; if (p == NULL) return; - _PyObject_DebugCheckAddress(p); + _PyObject_DebugCheckAddressApi(api, p); nbytes = read_size_t(q); + nbytes += 4*SST; if (nbytes > 0) memset(q, DEADBYTE, nbytes); PyObject_Free(q); } void * -_PyObject_DebugRealloc(void *p, size_t nbytes) +_PyObject_DebugReallocApi(char api, void *p, size_t nbytes) { uchar *q = (uchar *)p; uchar *tail; @@ -1405,9 +1493,9 @@ _PyObject_DebugRealloc(void *p, size_t nbytes) int i; if (p == NULL) - return _PyObject_DebugMalloc(nbytes); + return _PyObject_DebugMallocApi(api, nbytes); - _PyObject_DebugCheckAddress(p); + _PyObject_DebugCheckAddressApi(api, p); bumpserialno(); original_nbytes = read_size_t(q - 2*SST); total = nbytes + 4*SST; @@ -1417,16 +1505,20 @@ _PyObject_DebugRealloc(void *p, size_t nbytes) if (nbytes < original_nbytes) { /* shrinking: mark old extra memory dead */ - memset(q + nbytes, DEADBYTE, original_nbytes - nbytes); + memset(q + nbytes, DEADBYTE, original_nbytes - nbytes + 2*SST); } - /* Resize and add decorations. */ + /* Resize and add decorations. We may get a new pointer here, in which + * case we didn't get the chance to mark the old memory with DEADBYTE, + * but we live with that. + */ q = (uchar *)PyObject_Realloc(q - 2*SST, total); if (q == NULL) return NULL; write_size_t(q, nbytes); - for (i = 0; i < SST; ++i) + assert(q[SST] == (uchar)api); + for (i = 1; i < SST; ++i) assert(q[SST + i] == FORBIDDENBYTE); q += 2*SST; tail = q + nbytes; @@ -1445,26 +1537,38 @@ _PyObject_DebugRealloc(void *p, size_t nbytes) /* Check the forbidden bytes on both ends of the memory allocated for p. * If anything is wrong, print info to stderr via _PyObject_DebugDumpAddress, * and call Py_FatalError to kill the program. + * The API id, is also checked. */ void -_PyObject_DebugCheckAddress(const void *p) +_PyObject_DebugCheckAddressApi(char api, const void *p) { const uchar *q = (const uchar *)p; + char msgbuf[64]; char *msg; size_t nbytes; const uchar *tail; int i; + char id; if (p == NULL) { msg = "didn't expect a NULL pointer"; goto error; } + /* Check the API id */ + id = (char)q[-SST]; + if (id != api) { + msg = msgbuf; + snprintf(msg, sizeof(msgbuf), "bad ID: Allocated using API '%c', verified using API '%c'", id, api); + msgbuf[sizeof(msgbuf)-1] = 0; + goto error; + } + /* Check the stuff at the start of p first: if there's underwrite * corruption, the number-of-bytes field may be nuts, and checking * the tail could lead to a segfault then. */ - for (i = SST; i >= 1; --i) { + for (i = SST-1; i >= 1; --i) { if (*(q-i) != FORBIDDENBYTE) { msg = "bad leading pad byte"; goto error; @@ -1496,19 +1600,24 @@ _PyObject_DebugDumpAddress(const void *p) size_t nbytes, serial; int i; int ok; + char id; - fprintf(stderr, "Debug memory block at address p=%p:\n", p); - if (p == NULL) + fprintf(stderr, "Debug memory block at address p=%p:", p); + if (p == NULL) { + fprintf(stderr, "\n"); return; + } + id = (char)q[-SST]; + fprintf(stderr, " API '%c'\n", id); nbytes = read_size_t(q - 2*SST); fprintf(stderr, " %" PY_FORMAT_SIZE_T "u bytes originally " "requested\n", nbytes); /* In case this is nuts, check the leading pad bytes first. */ - fprintf(stderr, " The %d pad bytes at p-%d are ", SST, SST); + fprintf(stderr, " The %d pad bytes at p-%d are ", SST-1, SST-1); ok = 1; - for (i = 1; i <= SST; ++i) { + for (i = 1; i <= SST-1; ++i) { if (*(q-i) != FORBIDDENBYTE) { ok = 0; break; @@ -1519,7 +1628,7 @@ _PyObject_DebugDumpAddress(const void *p) else { fprintf(stderr, "not all FORBIDDENBYTE (0x%02x):\n", FORBIDDENBYTE); - for (i = SST; i >= 1; --i) { + for (i = SST-1; i >= 1; --i) { const uchar byte = *(q-i); fprintf(stderr, " at p-%d: 0x%02x", i, byte); if (byte != FORBIDDENBYTE) diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index 33a4d9d..58d373c 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -14,6 +14,7 @@ typedef struct { PyObject *start; PyObject *stop; PyObject *step; + PyObject *length; } rangeobject; /* Helper function for validating step. Always returns a new reference or @@ -43,6 +44,31 @@ validate_step(PyObject *step) return step; } +static PyObject * +compute_range_length(PyObject *start, PyObject *stop, PyObject *step); + +static rangeobject * +make_range_object(PyTypeObject *type, PyObject *start, + PyObject *stop, PyObject *step) +{ + rangeobject *obj = NULL; + PyObject *length; + length = compute_range_length(start, stop, step); + if (length == NULL) { + return NULL; + } + obj = PyObject_New(rangeobject, type); + if (obj == NULL) { + Py_DECREF(length); + return NULL; + } + obj->start = start; + obj->stop = stop; + obj->step = step; + obj->length = length; + return obj; +} + /* XXX(nnorwitz): should we error check if the user passes any empty ranges? range(-10) range(0, -5) @@ -51,7 +77,7 @@ validate_step(PyObject *step) static PyObject * range_new(PyTypeObject *type, PyObject *args, PyObject *kw) { - rangeobject *obj = NULL; + rangeobject *obj; PyObject *start = NULL, *stop = NULL, *step = NULL; if (!_PyArg_NoKeywords("range()", kw)) @@ -97,15 +123,11 @@ range_new(PyTypeObject *type, PyObject *args, PyObject *kw) } } - obj = PyObject_New(rangeobject, &PyRange_Type); - if (obj == NULL) - goto Fail; - obj->start = start; - obj->stop = stop; - obj->step = step; - return (PyObject *) obj; + obj = make_range_object(type, start, stop, step); + if (obj != NULL) + return (PyObject *) obj; -Fail: + /* Failed to create object, release attributes */ Py_XDECREF(start); Py_XDECREF(stop); Py_XDECREF(step); @@ -115,7 +137,7 @@ Fail: PyDoc_STRVAR(range_doc, "range([start,] stop[, step]) -> range object\n\ \n\ -Returns an iterator that generates the numbers in the range on demand."); +Returns a virtual sequence of numbers from start to stop by step."); static void range_dealloc(rangeobject *r) @@ -123,6 +145,7 @@ range_dealloc(rangeobject *r) Py_DECREF(r->start); Py_DECREF(r->stop); Py_DECREF(r->step); + Py_DECREF(r->length); PyObject_Del(r); } @@ -131,7 +154,7 @@ range_dealloc(rangeobject *r) * PyLong_Check(). Return NULL when there is an error. */ static PyObject* -range_length_obj(rangeobject *r) +compute_range_length(PyObject *start, PyObject *stop, PyObject *step) { /* ------------------------------------------------------------- Algorithm is equal to that of get_len_of_range(), but it operates @@ -139,7 +162,6 @@ range_length_obj(rangeobject *r) ---------------------------------------------------------------*/ int cmp_result; PyObject *lo, *hi; - PyObject *step = NULL; PyObject *diff = NULL; PyObject *one = NULL; PyObject *tmp1 = NULL, *tmp2 = NULL, *result; @@ -148,20 +170,19 @@ range_length_obj(rangeobject *r) PyObject *zero = PyLong_FromLong(0); if (zero == NULL) return NULL; - cmp_result = PyObject_RichCompareBool(r->step, zero, Py_GT); + cmp_result = PyObject_RichCompareBool(step, zero, Py_GT); Py_DECREF(zero); if (cmp_result == -1) return NULL; if (cmp_result == 1) { - lo = r->start; - hi = r->stop; - step = r->step; + lo = start; + hi = stop; Py_INCREF(step); } else { - lo = r->stop; - hi = r->start; - step = PyNumber_Negative(r->step); + lo = stop; + hi = start; + step = PyNumber_Negative(step); if (!step) return NULL; } @@ -206,45 +227,451 @@ range_length_obj(rangeobject *r) static Py_ssize_t range_length(rangeobject *r) { - PyObject *len = range_length_obj(r); - Py_ssize_t result = -1; - if (len) { - result = PyLong_AsSsize_t(len); - Py_DECREF(len); - } - return result; + return PyLong_AsSsize_t(r->length); } -/* range(...)[x] is necessary for: seq[:] = range(...) */ +static PyObject * +compute_item(rangeobject *r, PyObject *i) +{ + PyObject *incr, *result; + /* PyLong equivalent to: + * return r->start + (i * r->step) + */ + incr = PyNumber_Multiply(i, r->step); + if (!incr) + return NULL; + result = PyNumber_Add(r->start, incr); + Py_DECREF(incr); + return result; +} static PyObject * -range_item(rangeobject *r, Py_ssize_t i) +compute_range_item(rangeobject *r, PyObject *arg) { - Py_ssize_t len = range_length(r); - PyObject *rem, *incr, *result; - - /* XXX(nnorwitz): should negative indices be supported? */ - /* XXX(nnorwitz): should support range[x] where x > PY_SSIZE_T_MAX? */ - if (i < 0 || i >= len) { - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_IndexError, - "range object index out of range"); + int cmp_result; + PyObject *i, *result; + + PyObject *zero = PyLong_FromLong(0); + if (zero == NULL) return NULL; + + /* PyLong equivalent to: + * if (arg < 0) { + * i = r->length + arg + * } else { + * i = arg + * } + */ + cmp_result = PyObject_RichCompareBool(arg, zero, Py_LT); + if (cmp_result == -1) { + Py_DECREF(zero); + return NULL; + } + if (cmp_result == 1) { + i = PyNumber_Add(r->length, arg); + if (!i) { + Py_DECREF(zero); + return NULL; + } + } else { + i = arg; + Py_INCREF(i); } - /* XXX(nnorwitz): optimize for short ints. */ - rem = PyLong_FromSsize_t(i); - if (!rem) + /* PyLong equivalent to: + * if (i < 0 || i >= r->length) { + * <report index out of bounds> + * } + */ + cmp_result = PyObject_RichCompareBool(i, zero, Py_LT); + Py_DECREF(zero); + if (cmp_result == 0) { + cmp_result = PyObject_RichCompareBool(i, r->length, Py_GE); + } + if (cmp_result == -1) { + Py_DECREF(i); + return NULL; + } + if (cmp_result == 1) { + Py_DECREF(i); + PyErr_SetString(PyExc_IndexError, + "range object index out of range"); return NULL; - incr = PyNumber_Multiply(rem, r->step); - Py_DECREF(rem); - if (!incr) + } + + result = compute_item(r, i); + Py_DECREF(i); + return result; +} + +static PyObject * +range_item(rangeobject *r, Py_ssize_t i) +{ + PyObject *res, *arg = PyLong_FromLong(i); + if (!arg) { return NULL; - result = PyNumber_Add(r->start, incr); - Py_DECREF(incr); + } + res = compute_range_item(r, arg); + Py_DECREF(arg); + return res; +} + +/* Additional helpers, since the standard slice helpers + * all clip to PY_SSIZE_T_MAX + */ + +/* Replace _PyEval_SliceIndex */ +static PyObject * +compute_slice_element(PyObject *obj) +{ + PyObject *result = NULL; + if (obj != NULL) { + if (PyIndex_Check(obj)) { + result = PyNumber_Index(obj); + } + } + if (result == NULL) { + PyErr_SetString(PyExc_TypeError, + "slice indices must be integers or " + "None or have an __index__ method"); + } return result; } +/* Replace PySlice_GetIndicesEx + * Result indicates whether or not the slice is empty + * (-1 = error, 0 = empty slice, 1 = slice contains elements) + */ +static int +compute_slice_indices(rangeobject *r, PySliceObject *slice, + PyObject **start, PyObject **stop, PyObject **step) +{ + int cmp_result, has_elements; + Py_ssize_t clamped_step = 0; + PyObject *zero = NULL, *one = NULL, *neg_one = NULL, *candidate = NULL; + PyObject *tmp_start = NULL, *tmp_stop = NULL, *tmp_step = NULL; + zero = PyLong_FromLong(0); + if (zero == NULL) goto Fail; + one = PyLong_FromLong(1); + if (one == NULL) goto Fail; + neg_one = PyLong_FromLong(-1); + if (neg_one == NULL) goto Fail; + + /* Calculate step value */ + if (slice->step == Py_None) { + clamped_step = 1; + tmp_step = one; + Py_INCREF(tmp_step); + } else { + if (!_PyEval_SliceIndex(slice->step, &clamped_step)) goto Fail; + if (clamped_step == 0) { + PyErr_SetString(PyExc_ValueError, + "slice step cannot be zero"); + goto Fail; + } + tmp_step = compute_slice_element(slice->step); + if (tmp_step == NULL) goto Fail; + } + + /* Calculate start value */ + if (slice->start == Py_None) { + if (clamped_step < 0) { + tmp_start = PyNumber_Subtract(r->length, one); + if (tmp_start == NULL) goto Fail; + } else { + tmp_start = zero; + Py_INCREF(tmp_start); + } + } else { + candidate = compute_slice_element(slice->start); + if (candidate == NULL) goto Fail; + cmp_result = PyObject_RichCompareBool(candidate, zero, Py_LT); + if (cmp_result == -1) goto Fail; + if (cmp_result) { + /* candidate < 0 */ + tmp_start = PyNumber_Add(r->length, candidate); + if (tmp_start == NULL) goto Fail; + Py_CLEAR(candidate); + } else { + /* candidate >= 0 */ + tmp_start = candidate; + candidate = NULL; + } + cmp_result = PyObject_RichCompareBool(tmp_start, zero, Py_LT); + if (cmp_result == -1) goto Fail; + if (cmp_result) { + /* tmp_start < 0 */ + Py_CLEAR(tmp_start); + if (clamped_step < 0) { + tmp_start = neg_one; + } else { + tmp_start = zero; + } + Py_INCREF(tmp_start); + } else { + /* tmp_start >= 0 */ + cmp_result = PyObject_RichCompareBool(tmp_start, r->length, Py_GE); + if (cmp_result == -1) goto Fail; + if (cmp_result) { + /* tmp_start >= r->length */ + Py_CLEAR(tmp_start); + if (clamped_step < 0) { + tmp_start = PyNumber_Subtract(r->length, one); + if (tmp_start == NULL) goto Fail; + } else { + tmp_start = r->length; + Py_INCREF(tmp_start); + } + } + } + } + + /* Calculate stop value */ + if (slice->stop == Py_None) { + if (clamped_step < 0) { + tmp_stop = neg_one; + } else { + tmp_stop = r->length; + } + Py_INCREF(tmp_stop); + } else { + candidate = compute_slice_element(slice->stop); + if (candidate == NULL) goto Fail; + cmp_result = PyObject_RichCompareBool(candidate, zero, Py_LT); + if (cmp_result == -1) goto Fail; + if (cmp_result) { + /* candidate < 0 */ + tmp_stop = PyNumber_Add(r->length, candidate); + if (tmp_stop == NULL) goto Fail; + Py_CLEAR(candidate); + } else { + /* candidate >= 0 */ + tmp_stop = candidate; + candidate = NULL; + } + cmp_result = PyObject_RichCompareBool(tmp_stop, zero, Py_LT); + if (cmp_result == -1) goto Fail; + if (cmp_result) { + /* tmp_stop < 0 */ + Py_CLEAR(tmp_stop); + if (clamped_step < 0) { + tmp_stop = neg_one; + } else { + tmp_stop = zero; + } + Py_INCREF(tmp_stop); + } else { + /* tmp_stop >= 0 */ + cmp_result = PyObject_RichCompareBool(tmp_stop, r->length, Py_GE); + if (cmp_result == -1) goto Fail; + if (cmp_result) { + /* tmp_stop >= r->length */ + Py_CLEAR(tmp_stop); + if (clamped_step < 0) { + tmp_stop = PyNumber_Subtract(r->length, one); + if (tmp_stop == NULL) goto Fail; + } else { + tmp_stop = r->length; + Py_INCREF(tmp_stop); + } + } + } + } + + /* Check if the slice is empty or not */ + if (clamped_step < 0) { + has_elements = PyObject_RichCompareBool(tmp_start, tmp_stop, Py_GT); + } else { + has_elements = PyObject_RichCompareBool(tmp_start, tmp_stop, Py_LT); + } + if (has_elements == -1) goto Fail; + + *start = tmp_start; + *stop = tmp_stop; + *step = tmp_step; + Py_DECREF(neg_one); + Py_DECREF(one); + Py_DECREF(zero); + return has_elements; + + Fail: + Py_XDECREF(tmp_start); + Py_XDECREF(tmp_stop); + Py_XDECREF(tmp_step); + Py_XDECREF(candidate); + Py_XDECREF(neg_one); + Py_XDECREF(one); + Py_XDECREF(zero); + return -1; +} + +static PyObject * +compute_slice(rangeobject *r, PyObject *_slice) +{ + PySliceObject *slice = (PySliceObject *) _slice; + rangeobject *result; + PyObject *start = NULL, *stop = NULL, *step = NULL; + PyObject *substart = NULL, *substop = NULL, *substep = NULL; + int has_elements; + + has_elements = compute_slice_indices(r, slice, &start, &stop, &step); + if (has_elements == -1) return NULL; + + substep = PyNumber_Multiply(r->step, step); + if (substep == NULL) goto fail; + Py_CLEAR(step); + + substart = compute_item(r, start); + if (substart == NULL) goto fail; + Py_CLEAR(start); + + if (has_elements) { + substop = compute_item(r, stop); + if (substop == NULL) goto fail; + } else { + substop = substart; + Py_INCREF(substop); + } + Py_CLEAR(stop); + + result = make_range_object(Py_TYPE(r), substart, substop, substep); + if (result != NULL) { + return (PyObject *) result; + } +fail: + Py_XDECREF(start); + Py_XDECREF(stop); + Py_XDECREF(step); + Py_XDECREF(substart); + Py_XDECREF(substop); + Py_XDECREF(substep); + return NULL; +} + +/* Assumes (PyLong_CheckExact(ob) || PyBool_Check(ob)) */ +static int +range_contains_long(rangeobject *r, PyObject *ob) +{ + int cmp1, cmp2, cmp3; + PyObject *tmp1 = NULL; + PyObject *tmp2 = NULL; + PyObject *zero = NULL; + int result = -1; + + zero = PyLong_FromLong(0); + if (zero == NULL) /* MemoryError in int(0) */ + goto end; + + /* Check if the value can possibly be in the range. */ + + cmp1 = PyObject_RichCompareBool(r->step, zero, Py_GT); + if (cmp1 == -1) + goto end; + if (cmp1 == 1) { /* positive steps: start <= ob < stop */ + cmp2 = PyObject_RichCompareBool(r->start, ob, Py_LE); + cmp3 = PyObject_RichCompareBool(ob, r->stop, Py_LT); + } + else { /* negative steps: stop < ob <= start */ + cmp2 = PyObject_RichCompareBool(ob, r->start, Py_LE); + cmp3 = PyObject_RichCompareBool(r->stop, ob, Py_LT); + } + + if (cmp2 == -1 || cmp3 == -1) /* TypeError */ + goto end; + if (cmp2 == 0 || cmp3 == 0) { /* ob outside of range */ + result = 0; + goto end; + } + + /* Check that the stride does not invalidate ob's membership. */ + tmp1 = PyNumber_Subtract(ob, r->start); + if (tmp1 == NULL) + goto end; + tmp2 = PyNumber_Remainder(tmp1, r->step); + if (tmp2 == NULL) + goto end; + /* result = (int(ob) - start % step) == 0 */ + result = PyObject_RichCompareBool(tmp2, zero, Py_EQ); + end: + Py_XDECREF(tmp1); + Py_XDECREF(tmp2); + Py_XDECREF(zero); + return result; +} + +static int +range_contains(rangeobject *r, PyObject *ob) +{ + if (PyLong_CheckExact(ob) || PyBool_Check(ob)) + return range_contains_long(r, ob); + + return (int)_PySequence_IterSearch((PyObject*)r, ob, + PY_ITERSEARCH_CONTAINS); +} + +static PyObject * +range_count(rangeobject *r, PyObject *ob) +{ + if (PyLong_CheckExact(ob) || PyBool_Check(ob)) { + int result = range_contains_long(r, ob); + if (result == -1) + return NULL; + else if (result) + return PyLong_FromLong(1); + else + return PyLong_FromLong(0); + } else { + Py_ssize_t count; + count = _PySequence_IterSearch((PyObject*)r, ob, PY_ITERSEARCH_COUNT); + if (count == -1) + return NULL; + return PyLong_FromSsize_t(count); + } +} + +static PyObject * +range_index(rangeobject *r, PyObject *ob) +{ + int contains; + + if (!PyLong_CheckExact(ob) && !PyBool_Check(ob)) { + Py_ssize_t index; + index = _PySequence_IterSearch((PyObject*)r, ob, PY_ITERSEARCH_INDEX); + if (index == -1) + return NULL; + return PyLong_FromSsize_t(index); + } + + contains = range_contains_long(r, ob); + if (contains == -1) + return NULL; + + if (contains) { + PyObject *idx, *tmp = PyNumber_Subtract(ob, r->start); + if (tmp == NULL) + return NULL; + /* idx = (ob - r.start) // r.step */ + idx = PyNumber_FloorDivide(tmp, r->step); + Py_DECREF(tmp); + return idx; + } + + /* object is not in the range */ + PyErr_Format(PyExc_ValueError, "%R is not in range", ob); + return NULL; +} + +static PySequenceMethods range_as_sequence = { + (lenfunc)range_length, /* sq_length */ + 0, /* sq_concat */ + 0, /* sq_repeat */ + (ssizeargfunc)range_item, /* sq_item */ + 0, /* sq_slice */ + 0, /* sq_ass_item */ + 0, /* sq_ass_slice */ + (objobjproc)range_contains, /* sq_contains */ +}; + static PyObject * range_repr(rangeobject *r) { @@ -269,16 +696,36 @@ range_repr(rangeobject *r) static PyObject * range_reduce(rangeobject *r, PyObject *args) { - return Py_BuildValue("(O(OOO))", Py_TYPE(r), + return Py_BuildValue("(O(OOO))", Py_TYPE(r), r->start, r->stop, r->step); } -static PySequenceMethods range_as_sequence = { - (lenfunc)range_length, /* sq_length */ - 0, /* sq_concat */ - 0, /* sq_repeat */ - (ssizeargfunc)range_item, /* sq_item */ - 0, /* sq_slice */ +static PyObject * +range_subscript(rangeobject* self, PyObject* item) +{ + if (PyIndex_Check(item)) { + PyObject *i, *result; + i = PyNumber_Index(item); + if (!i) + return NULL; + result = compute_range_item(self, i); + Py_DECREF(i); + return result; + } + if (PySlice_Check(item)) { + return compute_slice(self, item); + } + PyErr_Format(PyExc_TypeError, + "range indices must be integers or slices, not %.200s", + item->ob_type->tp_name); + return NULL; +} + + +static PyMappingMethods range_as_mapping = { + (lenfunc)range_length, /* mp_length */ + (binaryfunc)range_subscript, /* mp_subscript */ + (objobjargproc)0, /* mp_ass_subscript */ }; static PyObject * range_iter(PyObject *seq); @@ -287,10 +734,18 @@ static PyObject * range_reverse(PyObject *seq); PyDoc_STRVAR(reverse_doc, "Returns a reverse iterator."); +PyDoc_STRVAR(count_doc, +"rangeobject.count(value) -> integer -- return number of occurrences of value"); + +PyDoc_STRVAR(index_doc, +"rangeobject.index(value, [start, [stop]]) -> integer -- return index of value.\n" +"Raises ValueError if the value is not present."); + static PyMethodDef range_methods[] = { - {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS, - reverse_doc}, - {"__reduce__", (PyCFunction)range_reduce, METH_VARARGS}, + {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS, reverse_doc}, + {"__reduce__", (PyCFunction)range_reduce, METH_VARARGS}, + {"count", (PyCFunction)range_count, METH_O, count_doc}, + {"index", (PyCFunction)range_index, METH_O, index_doc}, {NULL, NULL} /* sentinel */ }; @@ -307,7 +762,7 @@ PyTypeObject PyRange_Type = { (reprfunc)range_repr, /* tp_repr */ 0, /* tp_as_number */ &range_as_sequence, /* tp_as_sequence */ - 0, /* tp_as_mapping */ + &range_as_mapping, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ @@ -367,22 +822,6 @@ rangeiter_len(rangeiterobject *r) return PyLong_FromLong(r->len - r->index); } -typedef struct { - PyObject_HEAD - PyObject *index; - PyObject *start; - PyObject *step; - PyObject *len; -} longrangeiterobject; - -static PyObject * -longrangeiter_len(longrangeiterobject *r, PyObject *no_args) -{ - return PyNumber_Subtract(r->len, r->index); -} - -static PyObject *rangeiter_new(PyTypeObject *, PyObject *args, PyObject *kw); - PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); @@ -392,6 +831,8 @@ static PyMethodDef rangeiter_methods[] = { {NULL, NULL} /* sentinel */ }; +static PyObject *rangeiter_new(PyTypeObject *, PyObject *args, PyObject *kw); + PyTypeObject PyRangeIter_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "range_iterator", /* tp_name */ @@ -466,7 +907,7 @@ get_len_of_range(long lo, long hi, long step) is not representable as a C long, OverflowError is raised. */ static PyObject * -int_range_iter(long start, long stop, long step) +fast_range_iter(long start, long stop, long step) { rangeiterobject *it = PyObject_New(rangeiterobject, &PyRangeIter_Type); unsigned long ulen; @@ -498,7 +939,21 @@ rangeiter_new(PyTypeObject *type, PyObject *args, PyObject *kw) &start, &stop, &step)) return NULL; - return int_range_iter(start, stop, step); + return fast_range_iter(start, stop, step); +} + +typedef struct { + PyObject_HEAD + PyObject *index; + PyObject *start; + PyObject *step; + PyObject *len; +} longrangeiterobject; + +static PyObject * +longrangeiter_len(longrangeiterobject *r, PyObject *no_args) +{ + return PyNumber_Subtract(r->len, r->index); } static PyMethodDef longrangeiter_methods[] = { @@ -612,7 +1067,7 @@ range_iter(PyObject *seq) PyErr_Clear(); goto long_range; } - int_it = int_range_iter(lstart, lstop, lstep); + int_it = fast_range_iter(lstart, lstop, lstep); if (int_it == NULL && PyErr_ExceptionMatches(PyExc_OverflowError)) { PyErr_Clear(); goto long_range; @@ -627,14 +1082,11 @@ range_iter(PyObject *seq) /* Do all initialization here, so we can DECREF on failure. */ it->start = r->start; it->step = r->step; + it->len = r->length; Py_INCREF(it->start); Py_INCREF(it->step); + Py_INCREF(it->len); - it->len = it->index = NULL; - - it->len = range_length_obj(r); - if (!it->len) - goto create_failure; it->index = PyLong_FromLong(0); if (!it->index) goto create_failure; @@ -651,7 +1103,7 @@ range_reverse(PyObject *seq) { rangeobject *range = (rangeobject*) seq; longrangeiterobject *it; - PyObject *one, *sum, *diff, *len = NULL, *product; + PyObject *one, *sum, *diff, *product; long lstart, lstop, lstep, new_start, new_stop; unsigned long ulen; @@ -714,7 +1166,7 @@ range_reverse(PyObject *seq) new_stop = lstart - lstep; new_start = (long)(new_stop + ulen * lstep); - return int_range_iter(new_start, new_stop, -lstep); + return fast_range_iter(new_start, new_stop, -lstep); long_range: it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); @@ -722,18 +1174,14 @@ long_range: return NULL; /* start + (len - 1) * step */ - len = range_length_obj(range); - if (!len) - goto create_failure; - - /* Steal reference to len. */ - it->len = len; + it->len = range->length; + Py_INCREF(it->len); one = PyLong_FromLong(1); if (!one) goto create_failure; - diff = PyNumber_Subtract(len, one); + diff = PyNumber_Subtract(it->len, one); Py_DECREF(one); if (!diff) goto create_failure; diff --git a/Objects/setobject.c b/Objects/setobject.c index 7aa1a7f..48edad8 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -75,7 +75,7 @@ NULL if the rich comparison returns an error. */ static setentry * -set_lookkey(PySetObject *so, PyObject *key, register long hash) +set_lookkey(PySetObject *so, PyObject *key, register Py_hash_t hash) { register Py_ssize_t i; register size_t perturb; @@ -157,7 +157,7 @@ set_lookkey(PySetObject *so, PyObject *key, register long hash) * see if the comparison altered the table. */ static setentry * -set_lookkey_unicode(PySetObject *so, PyObject *key, register long hash) +set_lookkey_unicode(PySetObject *so, PyObject *key, register Py_hash_t hash) { register Py_ssize_t i; register size_t perturb; @@ -211,10 +211,10 @@ Used by the public insert routine. Eats a reference to key. */ static int -set_insert_key(register PySetObject *so, PyObject *key, long hash) +set_insert_key(register PySetObject *so, PyObject *key, Py_hash_t hash) { register setentry *entry; - typedef setentry *(*lookupfunc)(PySetObject *, PyObject *, long); + typedef setentry *(*lookupfunc)(PySetObject *, PyObject *, Py_hash_t); assert(so->lookup != NULL); entry = so->lookup(so, key, hash); @@ -248,7 +248,7 @@ Note that no refcounts are changed by this routine; if needed, the caller is responsible for incref'ing `key`. */ static void -set_insert_clean(register PySetObject *so, PyObject *key, long hash) +set_insert_clean(register PySetObject *so, PyObject *key, Py_hash_t hash) { register size_t i; register size_t perturb; @@ -349,7 +349,7 @@ set_table_resize(PySetObject *so, Py_ssize_t minused) } else { /* ACTIVE */ --i; - set_insert_clean(so, entry->key, (long) entry->hash); + set_insert_clean(so, entry->key, entry->hash); } } @@ -365,7 +365,7 @@ set_add_entry(register PySetObject *so, setentry *entry) { register Py_ssize_t n_used; PyObject *key = entry->key; - long hash = entry->hash; + Py_hash_t hash = entry->hash; assert(so->fill <= so->mask); /* at least one empty slot */ n_used = so->used; @@ -382,7 +382,7 @@ set_add_entry(register PySetObject *so, setentry *entry) static int set_add_key(register PySetObject *so, PyObject *key) { - register long hash; + register Py_hash_t hash; register Py_ssize_t n_used; if (!PyUnicode_CheckExact(key) || @@ -411,7 +411,7 @@ set_discard_entry(PySetObject *so, setentry *oldentry) { register setentry *entry; PyObject *old_key; - entry = (so->lookup)(so, oldentry->key, (long) oldentry->hash); + entry = (so->lookup)(so, oldentry->key, oldentry->hash); if (entry == NULL) return -1; if (entry->key == NULL || entry->key == dummy) @@ -427,7 +427,7 @@ set_discard_entry(PySetObject *so, setentry *oldentry) static int set_discard_key(PySetObject *so, PyObject *key) { - register long hash; + register Py_hash_t hash; register setentry *entry; PyObject *old_key; @@ -640,7 +640,7 @@ set_merge(PySetObject *so, PyObject *otherset) { PySetObject *other; PyObject *key; - long hash; + Py_hash_t hash; register Py_ssize_t i; register setentry *entry; @@ -678,7 +678,7 @@ set_merge(PySetObject *so, PyObject *otherset) static int set_contains_key(PySetObject *so, PyObject *key) { - long hash; + Py_hash_t hash; setentry *entry; if (!PyUnicode_CheckExact(key) || @@ -700,7 +700,7 @@ set_contains_entry(PySetObject *so, setentry *entry) PyObject *key; setentry *lu_entry; - lu_entry = (so->lookup)(so, entry->key, (long) entry->hash); + lu_entry = (so->lookup)(so, entry->key, entry->hash); if (lu_entry == NULL) return -1; key = lu_entry->key; @@ -764,25 +764,25 @@ set_traverse(PySetObject *so, visitproc visit, void *arg) return 0; } -static long +static Py_hash_t frozenset_hash(PyObject *self) { PySetObject *so = (PySetObject *)self; - long h, hash = 1927868237L; + Py_hash_t h, hash = 1927868237L; setentry *entry; Py_ssize_t pos = 0; if (so->hash != -1) return so->hash; - hash *= (long) PySet_GET_SIZE(self) + 1; + hash *= PySet_GET_SIZE(self) + 1; while (set_next(so, &pos, &entry)) { /* Work to increase the bit dispersion for closely spaced hash values. The is important because some use cases have many combinations of a small number of elements with nearby hashes so that many distinct combinations collapse to only a handful of distinct hash values. */ - h = (long) entry->hash; + h = entry->hash; hash ^= (h ^ (h << 16) ^ 89869747L) * 3644798167u; } hash = hash * 69069L + 907133923L; @@ -929,7 +929,7 @@ set_update_internal(PySetObject *so, PyObject *other) if (PyDict_CheckExact(other)) { PyObject *value; Py_ssize_t pos = 0; - long hash; + Py_hash_t hash; Py_ssize_t dictsize = PyDict_Size(other); /* Do one big resize at the start, rather than @@ -1117,9 +1117,9 @@ set_swap_bodies(PySetObject *a, PySetObject *b) { Py_ssize_t t; setentry *u; - setentry *(*f)(PySetObject *so, PyObject *key, long hash); + setentry *(*f)(PySetObject *so, PyObject *key, Py_ssize_t hash); setentry tab[PySet_MINSIZE]; - long h; + Py_hash_t h; t = a->fill; a->fill = b->fill; b->fill = t; t = a->used; a->used = b->used; b->used = t; @@ -1288,7 +1288,7 @@ set_intersection(PySetObject *so, PyObject *other) while ((key = PyIter_Next(it)) != NULL) { int rv; setentry entry; - long hash = PyObject_Hash(key); + Py_hash_t hash = PyObject_Hash(key); if (hash == -1) { Py_DECREF(it); @@ -1347,9 +1347,9 @@ set_intersection_multi(PySetObject *so, PyObject *args) } PyDoc_STRVAR(intersection_doc, -"Return the intersection of two or more sets as a new set.\n\ +"Return the intersection of two sets as a new set.\n\ \n\ -(i.e. elements that are common to all of the sets.)"); +(i.e. all elements that are in both sets.)"); static PyObject * set_intersection_update(PySetObject *so, PyObject *other) @@ -1445,7 +1445,7 @@ set_isdisjoint(PySetObject *so, PyObject *other) while ((key = PyIter_Next(it)) != NULL) { int rv; setentry entry; - long hash = PyObject_Hash(key);; + Py_hash_t hash = PyObject_Hash(key); if (hash == -1) { Py_DECREF(key); @@ -1528,6 +1528,20 @@ PyDoc_STRVAR(difference_update_doc, "Remove all elements of another set from this set."); static PyObject * +set_copy_and_difference(PySetObject *so, PyObject *other) +{ + PyObject *result; + + result = set_copy(so); + if (result == NULL) + return NULL; + if (set_difference_update_internal((PySetObject *) result, other) != -1) + return result; + Py_DECREF(result); + return NULL; +} + +static PyObject * set_difference(PySetObject *so, PyObject *other) { PyObject *result; @@ -1535,13 +1549,13 @@ set_difference(PySetObject *so, PyObject *other) Py_ssize_t pos = 0; if (!PyAnySet_Check(other) && !PyDict_CheckExact(other)) { - result = set_copy(so); - if (result == NULL) - return NULL; - if (set_difference_update_internal((PySetObject *)result, other) != -1) - return result; - Py_DECREF(result); - return NULL; + return set_copy_and_difference(so, other); + } + + /* If len(so) much more than len(other), it's more efficient to simply copy + * so and then iterate other looking for common elements. */ + if ((PySet_GET_SIZE(so) >> 2) > PyObject_Size(other)) { + return set_copy_and_difference(so, other); } result = make_new_set_basetype(Py_TYPE(so), NULL); @@ -1553,7 +1567,7 @@ set_difference(PySetObject *so, PyObject *other) setentry entrycopy; entrycopy.hash = entry->hash; entrycopy.key = entry->key; - if (!_PyDict_Contains(other, entry->key, (long) entry->hash)) { + if (!_PyDict_Contains(other, entry->key, entry->hash)) { if (set_add_entry((PySetObject *)result, &entrycopy) == -1) { Py_DECREF(result); return NULL; @@ -1563,6 +1577,7 @@ set_difference(PySetObject *so, PyObject *other) return result; } + /* Iterate over so, checking for common elements in other. */ while (set_next(so, &pos, &entry)) { int rv = set_contains_entry((PySetObject *)other, entry); if (rv == -1) { @@ -1644,7 +1659,7 @@ set_symmetric_difference_update(PySetObject *so, PyObject *other) if (PyDict_CheckExact(other)) { PyObject *value; int rv; - long hash; + Py_hash_t hash; while (_PyDict_Next(other, &pos, &key, &value, &hash)) { setentry an_entry; @@ -2117,7 +2132,7 @@ PyTypeObject PySet_Type = { &set_as_number, /* tp_as_number */ &set_as_sequence, /* tp_as_sequence */ 0, /* tp_as_mapping */ - (hashfunc)PyObject_HashNotImplemented, /* tp_hash */ + PyObject_HashNotImplemented, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ @@ -2129,8 +2144,8 @@ PyTypeObject PySet_Type = { (traverseproc)set_traverse, /* tp_traverse */ (inquiry)set_clear_internal, /* tp_clear */ (richcmpfunc)set_richcompare, /* tp_richcompare */ - offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */ - (getiterfunc)set_iter, /* tp_iter */ + offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */ + (getiterfunc)set_iter, /* tp_iter */ 0, /* tp_iternext */ set_methods, /* tp_methods */ 0, /* tp_members */ @@ -2311,7 +2326,7 @@ PySet_Add(PyObject *anyset, PyObject *key) } int -_PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, long *hash) +_PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash) { setentry *entry; @@ -2322,7 +2337,7 @@ _PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, long *hash) if (set_next((PySetObject *)set, pos, &entry) == 0) return 0; *key = entry->key; - *hash = (long) entry->hash; + *hash = entry->hash; return 1; } @@ -2366,12 +2381,26 @@ test_c_api(PySetObject *so) Py_ssize_t i; PyObject *elem=NULL, *dup=NULL, *t, *f, *dup2, *x; PyObject *ob = (PyObject *)so; - long hash; + Py_hash_t hash; + PyObject *str; - /* Verify preconditions and exercise type/size checks */ + /* Verify preconditions */ assert(PyAnySet_Check(ob)); assert(PyAnySet_CheckExact(ob)); assert(!PyFrozenSet_CheckExact(ob)); + + /* so.clear(); so |= set("abc"); */ + str = PyUnicode_FromString("abc"); + if (str == NULL) + return NULL; + set_clear_internal(so); + if (set_update_internal(so, str) == -1) { + Py_DECREF(str); + return NULL; + } + Py_DECREF(str); + + /* Exercise type/size checks */ assert(PySet_Size(ob) == 3); assert(PySet_GET_SIZE(ob) == 3); diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c index ee89006..51c53a8 100644 --- a/Objects/sliceobject.c +++ b/Objects/sliceobject.c @@ -99,9 +99,10 @@ _PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop) } int -PySlice_GetIndices(PySliceObject *r, Py_ssize_t length, +PySlice_GetIndices(PyObject *_r, Py_ssize_t length, Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step) { + PySliceObject *r = (PySliceObject*)_r; /* XXX support long ints */ if (r->step == Py_None) { *step = 1; @@ -130,9 +131,11 @@ PySlice_GetIndices(PySliceObject *r, Py_ssize_t length, } int -PySlice_GetIndicesEx(PySliceObject *r, Py_ssize_t length, - Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, Py_ssize_t *slicelength) +PySlice_GetIndicesEx(PyObject *_r, Py_ssize_t length, + Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, + Py_ssize_t *slicelength) { + PySliceObject *r = (PySliceObject*)_r; /* this is harder to get right than you might think */ Py_ssize_t defstart, defstop; @@ -147,6 +150,13 @@ PySlice_GetIndicesEx(PySliceObject *r, Py_ssize_t length, "slice step cannot be zero"); return -1; } + /* Here *step might be -PY_SSIZE_T_MAX-1; in this case we replace it + * with -PY_SSIZE_T_MAX. This doesn't affect the semantics, and it + * guards against later undefined behaviour resulting from code that + * does "step = -step" as part of a slice reversal. + */ + if (*step < -PY_SSIZE_T_MAX) + *step = -PY_SSIZE_T_MAX; } defstart = *step < 0 ? length-1 : 0; @@ -248,7 +258,7 @@ slice_indices(PySliceObject* self, PyObject* len) return NULL; } - if (PySlice_GetIndicesEx(self, ilen, &start, &stop, + if (PySlice_GetIndicesEx((PyObject*)self, ilen, &start, &stop, &step, &slicelength) < 0) { return NULL; } @@ -336,13 +346,6 @@ slice_richcompare(PyObject *v, PyObject *w, int op) return res; } -static long -slice_hash(PySliceObject *v) -{ - PyErr_SetString(PyExc_TypeError, "unhashable type"); - return -1L; -} - PyTypeObject PySlice_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "slice", /* Name of this type */ @@ -357,7 +360,7 @@ PyTypeObject PySlice_Type = { 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ - (hashfunc)slice_hash, /* tp_hash */ + PyObject_HashNotImplemented, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ diff --git a/Objects/stringlib/README.txt b/Objects/stringlib/README.txt index 60d919e..ab506d6 100644 --- a/Objects/stringlib/README.txt +++ b/Objects/stringlib/README.txt @@ -16,10 +16,6 @@ STRINGLIB_EMPTY a PyObject representing the empty string, only to be used if STRINGLIB_MUTABLE is 0 -int STRINGLIB_CMP(STRINGLIB_CHAR*, STRINGLIB_CHAR*, Py_ssize_t) - - compares two strings. returns 0 if they match, and non-zero if not. - Py_ssize_t STRINGLIB_LEN(PyObject*) returns the length of the given string object (which must be of the diff --git a/Objects/stringlib/count.h b/Objects/stringlib/count.h index eba37e9..de34f96 100644 --- a/Objects/stringlib/count.h +++ b/Objects/stringlib/count.h @@ -9,28 +9,22 @@ Py_LOCAL_INLINE(Py_ssize_t) stringlib_count(const STRINGLIB_CHAR* str, Py_ssize_t str_len, - const STRINGLIB_CHAR* sub, Py_ssize_t sub_len) + const STRINGLIB_CHAR* sub, Py_ssize_t sub_len, + Py_ssize_t maxcount) { Py_ssize_t count; if (str_len < 0) return 0; /* start > len(str) */ if (sub_len == 0) - return str_len + 1; + return (str_len < maxcount) ? str_len + 1 : maxcount; - count = fastsearch(str, str_len, sub, sub_len, FAST_COUNT); + count = fastsearch(str, str_len, sub, sub_len, maxcount, FAST_COUNT); if (count < 0) - count = 0; /* no match */ + return 0; /* no match */ return count; } #endif - -/* -Local variables: -c-basic-offset: 4 -indent-tabs-mode: nil -End: -*/ diff --git a/Objects/stringlib/ctype.h b/Objects/stringlib/ctype.h index 8951276..739cf3d 100644 --- a/Objects/stringlib/ctype.h +++ b/Objects/stringlib/ctype.h @@ -107,4 +107,3 @@ stringlib_swapcase(PyObject *self) STRINGLIB_LEN(self)); return newobj; } - diff --git a/Objects/stringlib/fastsearch.h b/Objects/stringlib/fastsearch.h index 23bccfb..e231c58 100644 --- a/Objects/stringlib/fastsearch.h +++ b/Objects/stringlib/fastsearch.h @@ -5,7 +5,7 @@ /* fast search/count implementation, based on a mix between boyer- moore and horspool, with a few more bells and whistles on the top. - for some more background, see: http://effbot.org/stringlib.htm */ + for some more background, see: http://effbot.org/zone/stringlib.htm */ /* note: fastsearch may access s[n], which isn't a problem when using Python's ordinary string types, but may cause problems if you're @@ -16,19 +16,35 @@ #define FAST_COUNT 0 #define FAST_SEARCH 1 +#define FAST_RSEARCH 2 + +#if LONG_BIT >= 128 +#define STRINGLIB_BLOOM_WIDTH 128 +#elif LONG_BIT >= 64 +#define STRINGLIB_BLOOM_WIDTH 64 +#elif LONG_BIT >= 32 +#define STRINGLIB_BLOOM_WIDTH 32 +#else +#error "LONG_BIT is smaller than 32" +#endif + +#define STRINGLIB_BLOOM_ADD(mask, ch) \ + ((mask |= (1UL << ((ch) & (STRINGLIB_BLOOM_WIDTH -1))))) +#define STRINGLIB_BLOOM(mask, ch) \ + ((mask & (1UL << ((ch) & (STRINGLIB_BLOOM_WIDTH -1))))) Py_LOCAL_INLINE(Py_ssize_t) fastsearch(const STRINGLIB_CHAR* s, Py_ssize_t n, const STRINGLIB_CHAR* p, Py_ssize_t m, - int mode) + Py_ssize_t maxcount, int mode) { - long mask; + unsigned long mask; Py_ssize_t skip, count = 0; Py_ssize_t i, j, mlast, w; w = n - m; - if (w < 0) + if (w < 0 || (mode == FAST_COUNT && maxcount == 0)) return -1; /* look for special cases */ @@ -38,54 +54,101 @@ fastsearch(const STRINGLIB_CHAR* s, Py_ssize_t n, /* use special case for 1-character strings */ if (mode == FAST_COUNT) { for (i = 0; i < n; i++) - if (s[i] == p[0]) + if (s[i] == p[0]) { count++; + if (count == maxcount) + return maxcount; + } return count; - } else { + } else if (mode == FAST_SEARCH) { for (i = 0; i < n; i++) if (s[i] == p[0]) return i; + } else { /* FAST_RSEARCH */ + for (i = n - 1; i > -1; i--) + if (s[i] == p[0]) + return i; } return -1; } mlast = m - 1; - - /* create compressed boyer-moore delta 1 table */ skip = mlast - 1; - /* process pattern[:-1] */ - for (mask = i = 0; i < mlast; i++) { - mask |= (1 << (p[i] & 0x1F)); - if (p[i] == p[mlast]) - skip = mlast - i - 1; - } - /* process pattern[-1] outside the loop */ - mask |= (1 << (p[mlast] & 0x1F)); - - for (i = 0; i <= w; i++) { - /* note: using mlast in the skip path slows things down on x86 */ - if (s[i+m-1] == p[m-1]) { - /* candidate match */ - for (j = 0; j < mlast; j++) - if (s[i+j] != p[j]) - break; - if (j == mlast) { - /* got a match! */ - if (mode != FAST_COUNT) + mask = 0; + + if (mode != FAST_RSEARCH) { + + /* create compressed boyer-moore delta 1 table */ + + /* process pattern[:-1] */ + for (i = 0; i < mlast; i++) { + STRINGLIB_BLOOM_ADD(mask, p[i]); + if (p[i] == p[mlast]) + skip = mlast - i - 1; + } + /* process pattern[-1] outside the loop */ + STRINGLIB_BLOOM_ADD(mask, p[mlast]); + + for (i = 0; i <= w; i++) { + /* note: using mlast in the skip path slows things down on x86 */ + if (s[i+m-1] == p[m-1]) { + /* candidate match */ + for (j = 0; j < mlast; j++) + if (s[i+j] != p[j]) + break; + if (j == mlast) { + /* got a match! */ + if (mode != FAST_COUNT) + return i; + count++; + if (count == maxcount) + return maxcount; + i = i + mlast; + continue; + } + /* miss: check if next character is part of pattern */ + if (!STRINGLIB_BLOOM(mask, s[i+m])) + i = i + m; + else + i = i + skip; + } else { + /* skip: check if next character is part of pattern */ + if (!STRINGLIB_BLOOM(mask, s[i+m])) + i = i + m; + } + } + } else { /* FAST_RSEARCH */ + + /* create compressed boyer-moore delta 1 table */ + + /* process pattern[0] outside the loop */ + STRINGLIB_BLOOM_ADD(mask, p[0]); + /* process pattern[:0:-1] */ + for (i = mlast; i > 0; i--) { + STRINGLIB_BLOOM_ADD(mask, p[i]); + if (p[i] == p[0]) + skip = i - 1; + } + + for (i = w; i >= 0; i--) { + if (s[i] == p[0]) { + /* candidate match */ + for (j = mlast; j > 0; j--) + if (s[i+j] != p[j]) + break; + if (j == 0) + /* got a match! */ return i; - count++; - i = i + mlast; - continue; + /* miss: check if previous character is part of pattern */ + if (i > 0 && !STRINGLIB_BLOOM(mask, s[i-1])) + i = i - m; + else + i = i - skip; + } else { + /* skip: check if previous character is part of pattern */ + if (i > 0 && !STRINGLIB_BLOOM(mask, s[i-1])) + i = i - m; } - /* miss: check if next character is part of pattern */ - if (!(mask & (1 << (s[i+m] & 0x1F)))) - i = i + m; - else - i = i + skip; - } else { - /* skip: check if next character is part of pattern */ - if (!(mask & (1 << (s[i+m] & 0x1F)))) - i = i + m; } } @@ -95,10 +158,3 @@ fastsearch(const STRINGLIB_CHAR* s, Py_ssize_t n, } #endif - -/* -Local variables: -c-basic-offset: 4 -indent-tabs-mode: nil -End: -*/ diff --git a/Objects/stringlib/find.h b/Objects/stringlib/find.h index 4407d71..ce615dc 100644 --- a/Objects/stringlib/find.h +++ b/Objects/stringlib/find.h @@ -19,7 +19,7 @@ stringlib_find(const STRINGLIB_CHAR* str, Py_ssize_t str_len, if (sub_len == 0) return offset; - pos = fastsearch(str, str_len, sub, sub_len, FAST_SEARCH); + pos = fastsearch(str, str_len, sub, sub_len, -1, FAST_SEARCH); if (pos >= 0) pos += offset; @@ -32,42 +32,43 @@ stringlib_rfind(const STRINGLIB_CHAR* str, Py_ssize_t str_len, const STRINGLIB_CHAR* sub, Py_ssize_t sub_len, Py_ssize_t offset) { - /* XXX - create reversefastsearch helper! */ - if (sub_len == 0) { - if (str_len < 0) - return -1; - return str_len + offset; - } else { - Py_ssize_t j, pos = -1; - for (j = str_len - sub_len; j >= 0; --j) - if (STRINGLIB_CMP(str+j, sub, sub_len) == 0) { - pos = j + offset; - break; - } - return pos; - } + Py_ssize_t pos; + + if (str_len < 0) + return -1; + if (sub_len == 0) + return str_len + offset; + + pos = fastsearch(str, str_len, sub, sub_len, -1, FAST_RSEARCH); + + if (pos >= 0) + pos += offset; + + return pos; } +/* helper macro to fixup start/end slice values */ +#define ADJUST_INDICES(start, end, len) \ + if (end > len) \ + end = len; \ + else if (end < 0) { \ + end += len; \ + if (end < 0) \ + end = 0; \ + } \ + if (start < 0) { \ + start += len; \ + if (start < 0) \ + start = 0; \ + } + Py_LOCAL_INLINE(Py_ssize_t) stringlib_find_slice(const STRINGLIB_CHAR* str, Py_ssize_t str_len, const STRINGLIB_CHAR* sub, Py_ssize_t sub_len, Py_ssize_t start, Py_ssize_t end) { - if (start < 0) - start += str_len; - if (start < 0) - start = 0; - if (end > str_len) - end = str_len; - if (end < 0) - end += str_len; - if (end < 0) - end = 0; - - return stringlib_find( - str + start, end - start, - sub, sub_len, start - ); + ADJUST_INDICES(start, end, str_len); + return stringlib_find(str + start, end - start, sub, sub_len, start); } Py_LOCAL_INLINE(Py_ssize_t) @@ -75,17 +76,7 @@ stringlib_rfind_slice(const STRINGLIB_CHAR* str, Py_ssize_t str_len, const STRINGLIB_CHAR* sub, Py_ssize_t sub_len, Py_ssize_t start, Py_ssize_t end) { - if (start < 0) - start += str_len; - if (start < 0) - start = 0; - if (end > str_len) - end = str_len; - if (end < 0) - end += str_len; - if (end < 0) - end = 0; - + ADJUST_INDICES(start, end, str_len); return stringlib_rfind(str + start, end - start, sub, sub_len, start); } @@ -100,7 +91,7 @@ stringlib_contains_obj(PyObject* str, PyObject* sub) ) != -1; } -#endif /* STRINGLIB_STR */ +#endif /* STRINGLIB_WANT_CONTAINS_OBJ */ /* This function is a helper for the "find" family (find, rfind, index, @@ -149,7 +140,7 @@ stringlib_parse_args_finds(const char * function_name, PyObject *args, #undef FORMAT_BUFFER_SIZE -#ifdef FROM_UNICODE +#if STRINGLIB_IS_UNICODE /* Wraps stringlib_parse_args_finds() and additionally ensures that the @@ -179,13 +170,6 @@ stringlib_parse_args_finds_unicode(const char * function_name, PyObject *args, return 0; } -#endif /* FROM_UNICODE */ +#endif /* STRINGLIB_IS_UNICODE */ #endif /* STRINGLIB_FIND_H */ - -/* -Local variables: -c-basic-offset: 4 -indent-tabs-mode: nil -End: -*/ diff --git a/Objects/stringlib/formatter.h b/Objects/stringlib/formatter.h index 4770863..4fdc62d 100644 --- a/Objects/stringlib/formatter.h +++ b/Objects/stringlib/formatter.h @@ -32,7 +32,7 @@ unknown_presentation_type(STRINGLIB_CHAR presentation_type, PyErr_Format(PyExc_ValueError, "Unknown format code '%c' " "for object of type '%.200s'", - presentation_type, + (char)presentation_type, type_name); #if STRINGLIB_IS_UNICODE else @@ -44,6 +44,24 @@ unknown_presentation_type(STRINGLIB_CHAR presentation_type, #endif } +static void +invalid_comma_type(STRINGLIB_CHAR presentation_type) +{ +#if STRINGLIB_IS_UNICODE + /* See comment in unknown_presentation_type */ + if (presentation_type > 32 && presentation_type < 128) +#endif + PyErr_Format(PyExc_ValueError, + "Cannot specify ',' with '%c'.", + (char)presentation_type); +#if STRINGLIB_IS_UNICODE + else + PyErr_Format(PyExc_ValueError, + "Cannot specify ',' with '\\x%x'.", + (unsigned int)presentation_type); +#endif +} + /* get_integer consumes 0 or more decimal digit characters from an input string, updates *result with the corresponding positive @@ -277,8 +295,7 @@ parse_internal_render_format_spec(STRINGLIB_CHAR *format_spec, /* These are allowed. See PEP 378.*/ break; default: - PyErr_Format(PyExc_ValueError, - "Cannot specify ',' with '%c'.", format->type); + invalid_comma_type(format->type); return 0; } } @@ -632,8 +649,8 @@ get_locale_info(int type, LocaleInfo *locale_info) case LT_DEFAULT_LOCALE: locale_info->decimal_point = "."; locale_info->thousands_sep = ","; - locale_info->grouping = "\3"; /* Group every 3 characters, - trailing 0 means repeat + locale_info->grouping = "\3"; /* Group every 3 characters. The + (implicit) trailing 0 means repeat infinitely. */ break; case LT_NO_LOCALE: @@ -759,14 +776,6 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format, goto done; } - /* Error to specify a comma. */ - if (format->thousands_separators) { - PyErr_SetString(PyExc_ValueError, - "Thousands separators not allowed with integer" - " format specifier 'c'"); - goto done; - } - /* taken from unicodeobject.c formatchar() */ /* Integer input truncated to a character */ /* XXX: won't work for int */ @@ -932,20 +941,16 @@ format_float_internal(PyObject *value, from a hard-code pseudo-locale */ LocaleInfo locale; - /* Alternate is not allowed on floats. */ - if (format->alternate) { - PyErr_SetString(PyExc_ValueError, - "Alternate form (#) not allowed in float format " - "specifier"); - goto done; - } + if (format->alternate) + flags |= Py_DTSF_ALT; if (type == '\0') { - /* Omitted type specifier. This is like 'g' but with at least one - digit after the decimal point, and different default precision.*/ - type = 'g'; - default_precision = PyFloat_STR_PRECISION; + /* Omitted type specifier. Behaves in the same way as repr(x) + and str(x) if no precision is given, else like 'g', but with + at least one digit after the decimal point. */ flags |= Py_DTSF_ADD_DOT_0; + type = 'r'; + default_precision = 0; } if (type == 'n') @@ -953,13 +958,6 @@ format_float_internal(PyObject *value, format the result. We take care of that later. */ type = 'g'; -#if PY_VERSION_HEX < 0x0301000 - /* 'F' is the same as 'f', per the PEP */ - /* This is no longer the case in 3.x */ - if (type == 'F') - type = 'f'; -#endif - val = PyFloat_AsDouble(value); if (val == -1.0 && PyErr_Occurred()) goto done; @@ -972,12 +970,8 @@ format_float_internal(PyObject *value, if (precision < 0) precision = default_precision; - -#if PY_VERSION_HEX < 0x03010000 - /* 3.1 no longer converts large 'f' to 'g'. */ - if ((type == 'f' || type == 'F') && fabs(val) >= 1e50) + else if (type == 'r') type = 'g'; -#endif /* Cast "type", because if we're in unicode we need to pass a 8-bit char. This is safe, because we've restricted what "type" @@ -1105,15 +1099,7 @@ format_complex_internal(PyObject *value, from a hard-code pseudo-locale */ LocaleInfo locale; - /* Alternate is not allowed on complex. */ - if (format->alternate) { - PyErr_SetString(PyExc_ValueError, - "Alternate form (#) not allowed in complex format " - "specifier"); - goto done; - } - - /* Neither is zero pading. */ + /* Zero padding is not allowed. */ if (format->fill_char == '0') { PyErr_SetString(PyExc_ValueError, "Zero padding is not allowed in complex format " @@ -1136,10 +1122,13 @@ format_complex_internal(PyObject *value, if (im == -1.0 && PyErr_Occurred()) goto done; + if (format->alternate) + flags |= Py_DTSF_ALT; + if (type == '\0') { /* Omitted type specifier. Should be like str(self). */ - type = 'g'; - default_precision = PyFloat_STR_PRECISION; + type = 'r'; + default_precision = 0; if (re == 0.0 && copysign(1.0, re) == 1.0) skip_re = 1; else @@ -1151,15 +1140,10 @@ format_complex_internal(PyObject *value, format the result. We take care of that later. */ type = 'g'; -#if PY_VERSION_HEX < 0x03010000 - /* This is no longer the case in 3.x */ - /* 'F' is the same as 'f', per the PEP */ - if (type == 'F') - type = 'f'; -#endif - if (precision < 0) precision = default_precision; + else if (type == 'r') + type = 'g'; /* Cast "type", because if we're in unicode we need to pass a 8-bit char. This is safe, because we've restricted what "type" diff --git a/Objects/stringlib/partition.h b/Objects/stringlib/partition.h index 20c7507..0170bdd 100644 --- a/Objects/stringlib/partition.h +++ b/Objects/stringlib/partition.h @@ -8,10 +8,10 @@ #endif Py_LOCAL_INLINE(PyObject*) -stringlib_partition( - PyObject* str_obj, const STRINGLIB_CHAR* str, Py_ssize_t str_len, - PyObject* sep_obj, const STRINGLIB_CHAR* sep, Py_ssize_t sep_len - ) +stringlib_partition(PyObject* str_obj, + const STRINGLIB_CHAR* str, Py_ssize_t str_len, + PyObject* sep_obj, + const STRINGLIB_CHAR* sep, Py_ssize_t sep_len) { PyObject* out; Py_ssize_t pos; @@ -25,15 +25,21 @@ stringlib_partition( if (!out) return NULL; - pos = fastsearch(str, str_len, sep, sep_len, FAST_SEARCH); + pos = fastsearch(str, str_len, sep, sep_len, -1, FAST_SEARCH); if (pos < 0) { +#if STRINGLIB_MUTABLE + PyTuple_SET_ITEM(out, 0, STRINGLIB_NEW(str, str_len)); + PyTuple_SET_ITEM(out, 1, STRINGLIB_NEW(NULL, 0)); + PyTuple_SET_ITEM(out, 2, STRINGLIB_NEW(NULL, 0)); +#else Py_INCREF(str_obj); PyTuple_SET_ITEM(out, 0, (PyObject*) str_obj); Py_INCREF(STRINGLIB_EMPTY); PyTuple_SET_ITEM(out, 1, (PyObject*) STRINGLIB_EMPTY); Py_INCREF(STRINGLIB_EMPTY); PyTuple_SET_ITEM(out, 2, (PyObject*) STRINGLIB_EMPTY); +#endif return out; } @@ -52,13 +58,13 @@ stringlib_partition( } Py_LOCAL_INLINE(PyObject*) -stringlib_rpartition( - PyObject* str_obj, const STRINGLIB_CHAR* str, Py_ssize_t str_len, - PyObject* sep_obj, const STRINGLIB_CHAR* sep, Py_ssize_t sep_len - ) +stringlib_rpartition(PyObject* str_obj, + const STRINGLIB_CHAR* str, Py_ssize_t str_len, + PyObject* sep_obj, + const STRINGLIB_CHAR* sep, Py_ssize_t sep_len) { PyObject* out; - Py_ssize_t pos, j; + Py_ssize_t pos; if (sep_len == 0) { PyErr_SetString(PyExc_ValueError, "empty separator"); @@ -69,21 +75,21 @@ stringlib_rpartition( if (!out) return NULL; - /* XXX - create reversefastsearch helper! */ - pos = -1; - for (j = str_len - sep_len; j >= 0; --j) - if (STRINGLIB_CMP(str+j, sep, sep_len) == 0) { - pos = j; - break; - } + pos = fastsearch(str, str_len, sep, sep_len, -1, FAST_RSEARCH); if (pos < 0) { +#if STRINGLIB_MUTABLE + PyTuple_SET_ITEM(out, 0, STRINGLIB_NEW(NULL, 0)); + PyTuple_SET_ITEM(out, 1, STRINGLIB_NEW(NULL, 0)); + PyTuple_SET_ITEM(out, 2, STRINGLIB_NEW(str, str_len)); +#else Py_INCREF(STRINGLIB_EMPTY); PyTuple_SET_ITEM(out, 0, (PyObject*) STRINGLIB_EMPTY); Py_INCREF(STRINGLIB_EMPTY); PyTuple_SET_ITEM(out, 1, (PyObject*) STRINGLIB_EMPTY); Py_INCREF(str_obj); PyTuple_SET_ITEM(out, 2, (PyObject*) str_obj); +#endif return out; } @@ -102,10 +108,3 @@ stringlib_rpartition( } #endif - -/* -Local variables: -c-basic-offset: 4 -indent-tabs-mode: nil -End: -*/ diff --git a/Objects/stringlib/split.h b/Objects/stringlib/split.h new file mode 100644 index 0000000..60e7767 --- /dev/null +++ b/Objects/stringlib/split.h @@ -0,0 +1,394 @@ +/* stringlib: split implementation */ + +#ifndef STRINGLIB_SPLIT_H +#define STRINGLIB_SPLIT_H + +#ifndef STRINGLIB_FASTSEARCH_H +#error must include "stringlib/fastsearch.h" before including this module +#endif + +/* Overallocate the initial list to reduce the number of reallocs for small + split sizes. Eg, "A A A A A A A A A A".split() (10 elements) has three + resizes, to sizes 4, 8, then 16. Most observed string splits are for human + text (roughly 11 words per line) and field delimited data (usually 1-10 + fields). For large strings the split algorithms are bandwidth limited + so increasing the preallocation likely will not improve things.*/ + +#define MAX_PREALLOC 12 + +/* 5 splits gives 6 elements */ +#define PREALLOC_SIZE(maxsplit) \ + (maxsplit >= MAX_PREALLOC ? MAX_PREALLOC : maxsplit+1) + +#define SPLIT_APPEND(data, left, right) \ + sub = STRINGLIB_NEW((data) + (left), \ + (right) - (left)); \ + if (sub == NULL) \ + goto onError; \ + if (PyList_Append(list, sub)) { \ + Py_DECREF(sub); \ + goto onError; \ + } \ + else \ + Py_DECREF(sub); + +#define SPLIT_ADD(data, left, right) { \ + sub = STRINGLIB_NEW((data) + (left), \ + (right) - (left)); \ + if (sub == NULL) \ + goto onError; \ + if (count < MAX_PREALLOC) { \ + PyList_SET_ITEM(list, count, sub); \ + } else { \ + if (PyList_Append(list, sub)) { \ + Py_DECREF(sub); \ + goto onError; \ + } \ + else \ + Py_DECREF(sub); \ + } \ + count++; } + + +/* Always force the list to the expected size. */ +#define FIX_PREALLOC_SIZE(list) Py_SIZE(list) = count + +Py_LOCAL_INLINE(PyObject *) +stringlib_split_whitespace(PyObject* str_obj, + const STRINGLIB_CHAR* str, Py_ssize_t str_len, + Py_ssize_t maxcount) +{ + Py_ssize_t i, j, count=0; + PyObject *list = PyList_New(PREALLOC_SIZE(maxcount)); + PyObject *sub; + + if (list == NULL) + return NULL; + + i = j = 0; + while (maxcount-- > 0) { + while (i < str_len && STRINGLIB_ISSPACE(str[i])) + i++; + if (i == str_len) break; + j = i; i++; + while (i < str_len && !STRINGLIB_ISSPACE(str[i])) + i++; +#ifndef STRINGLIB_MUTABLE + if (j == 0 && i == str_len && STRINGLIB_CHECK_EXACT(str_obj)) { + /* No whitespace in str_obj, so just use it as list[0] */ + Py_INCREF(str_obj); + PyList_SET_ITEM(list, 0, (PyObject *)str_obj); + count++; + break; + } +#endif + SPLIT_ADD(str, j, i); + } + + if (i < str_len) { + /* Only occurs when maxcount was reached */ + /* Skip any remaining whitespace and copy to end of string */ + while (i < str_len && STRINGLIB_ISSPACE(str[i])) + i++; + if (i != str_len) + SPLIT_ADD(str, i, str_len); + } + FIX_PREALLOC_SIZE(list); + return list; + + onError: + Py_DECREF(list); + return NULL; +} + +Py_LOCAL_INLINE(PyObject *) +stringlib_split_char(PyObject* str_obj, + const STRINGLIB_CHAR* str, Py_ssize_t str_len, + const STRINGLIB_CHAR ch, + Py_ssize_t maxcount) +{ + Py_ssize_t i, j, count=0; + PyObject *list = PyList_New(PREALLOC_SIZE(maxcount)); + PyObject *sub; + + if (list == NULL) + return NULL; + + i = j = 0; + while ((j < str_len) && (maxcount-- > 0)) { + for(; j < str_len; j++) { + /* I found that using memchr makes no difference */ + if (str[j] == ch) { + SPLIT_ADD(str, i, j); + i = j = j + 1; + break; + } + } + } +#ifndef STRINGLIB_MUTABLE + if (count == 0 && STRINGLIB_CHECK_EXACT(str_obj)) { + /* ch not in str_obj, so just use str_obj as list[0] */ + Py_INCREF(str_obj); + PyList_SET_ITEM(list, 0, (PyObject *)str_obj); + count++; + } else +#endif + if (i <= str_len) { + SPLIT_ADD(str, i, str_len); + } + FIX_PREALLOC_SIZE(list); + return list; + + onError: + Py_DECREF(list); + return NULL; +} + +Py_LOCAL_INLINE(PyObject *) +stringlib_split(PyObject* str_obj, + const STRINGLIB_CHAR* str, Py_ssize_t str_len, + const STRINGLIB_CHAR* sep, Py_ssize_t sep_len, + Py_ssize_t maxcount) +{ + Py_ssize_t i, j, pos, count=0; + PyObject *list, *sub; + + if (sep_len == 0) { + PyErr_SetString(PyExc_ValueError, "empty separator"); + return NULL; + } + else if (sep_len == 1) + return stringlib_split_char(str_obj, str, str_len, sep[0], maxcount); + + list = PyList_New(PREALLOC_SIZE(maxcount)); + if (list == NULL) + return NULL; + + i = j = 0; + while (maxcount-- > 0) { + pos = fastsearch(str+i, str_len-i, sep, sep_len, -1, FAST_SEARCH); + if (pos < 0) + break; + j = i + pos; + SPLIT_ADD(str, i, j); + i = j + sep_len; + } +#ifndef STRINGLIB_MUTABLE + if (count == 0 && STRINGLIB_CHECK_EXACT(str_obj)) { + /* No match in str_obj, so just use it as list[0] */ + Py_INCREF(str_obj); + PyList_SET_ITEM(list, 0, (PyObject *)str_obj); + count++; + } else +#endif + { + SPLIT_ADD(str, i, str_len); + } + FIX_PREALLOC_SIZE(list); + return list; + + onError: + Py_DECREF(list); + return NULL; +} + +Py_LOCAL_INLINE(PyObject *) +stringlib_rsplit_whitespace(PyObject* str_obj, + const STRINGLIB_CHAR* str, Py_ssize_t str_len, + Py_ssize_t maxcount) +{ + Py_ssize_t i, j, count=0; + PyObject *list = PyList_New(PREALLOC_SIZE(maxcount)); + PyObject *sub; + + if (list == NULL) + return NULL; + + i = j = str_len - 1; + while (maxcount-- > 0) { + while (i >= 0 && STRINGLIB_ISSPACE(str[i])) + i--; + if (i < 0) break; + j = i; i--; + while (i >= 0 && !STRINGLIB_ISSPACE(str[i])) + i--; +#ifndef STRINGLIB_MUTABLE + if (j == str_len - 1 && i < 0 && STRINGLIB_CHECK_EXACT(str_obj)) { + /* No whitespace in str_obj, so just use it as list[0] */ + Py_INCREF(str_obj); + PyList_SET_ITEM(list, 0, (PyObject *)str_obj); + count++; + break; + } +#endif + SPLIT_ADD(str, i + 1, j + 1); + } + + if (i >= 0) { + /* Only occurs when maxcount was reached */ + /* Skip any remaining whitespace and copy to beginning of string */ + while (i >= 0 && STRINGLIB_ISSPACE(str[i])) + i--; + if (i >= 0) + SPLIT_ADD(str, 0, i + 1); + } + FIX_PREALLOC_SIZE(list); + if (PyList_Reverse(list) < 0) + goto onError; + return list; + + onError: + Py_DECREF(list); + return NULL; +} + +Py_LOCAL_INLINE(PyObject *) +stringlib_rsplit_char(PyObject* str_obj, + const STRINGLIB_CHAR* str, Py_ssize_t str_len, + const STRINGLIB_CHAR ch, + Py_ssize_t maxcount) +{ + Py_ssize_t i, j, count=0; + PyObject *list = PyList_New(PREALLOC_SIZE(maxcount)); + PyObject *sub; + + if (list == NULL) + return NULL; + + i = j = str_len - 1; + while ((i >= 0) && (maxcount-- > 0)) { + for(; i >= 0; i--) { + if (str[i] == ch) { + SPLIT_ADD(str, i + 1, j + 1); + j = i = i - 1; + break; + } + } + } +#ifndef STRINGLIB_MUTABLE + if (count == 0 && STRINGLIB_CHECK_EXACT(str_obj)) { + /* ch not in str_obj, so just use str_obj as list[0] */ + Py_INCREF(str_obj); + PyList_SET_ITEM(list, 0, (PyObject *)str_obj); + count++; + } else +#endif + if (j >= -1) { + SPLIT_ADD(str, 0, j + 1); + } + FIX_PREALLOC_SIZE(list); + if (PyList_Reverse(list) < 0) + goto onError; + return list; + + onError: + Py_DECREF(list); + return NULL; +} + +Py_LOCAL_INLINE(PyObject *) +stringlib_rsplit(PyObject* str_obj, + const STRINGLIB_CHAR* str, Py_ssize_t str_len, + const STRINGLIB_CHAR* sep, Py_ssize_t sep_len, + Py_ssize_t maxcount) +{ + Py_ssize_t j, pos, count=0; + PyObject *list, *sub; + + if (sep_len == 0) { + PyErr_SetString(PyExc_ValueError, "empty separator"); + return NULL; + } + else if (sep_len == 1) + return stringlib_rsplit_char(str_obj, str, str_len, sep[0], maxcount); + + list = PyList_New(PREALLOC_SIZE(maxcount)); + if (list == NULL) + return NULL; + + j = str_len; + while (maxcount-- > 0) { + pos = fastsearch(str, j, sep, sep_len, -1, FAST_RSEARCH); + if (pos < 0) + break; + SPLIT_ADD(str, pos + sep_len, j); + j = pos; + } +#ifndef STRINGLIB_MUTABLE + if (count == 0 && STRINGLIB_CHECK_EXACT(str_obj)) { + /* No match in str_obj, so just use it as list[0] */ + Py_INCREF(str_obj); + PyList_SET_ITEM(list, 0, (PyObject *)str_obj); + count++; + } else +#endif + { + SPLIT_ADD(str, 0, j); + } + FIX_PREALLOC_SIZE(list); + if (PyList_Reverse(list) < 0) + goto onError; + return list; + + onError: + Py_DECREF(list); + return NULL; +} + +Py_LOCAL_INLINE(PyObject *) +stringlib_splitlines(PyObject* str_obj, + const STRINGLIB_CHAR* str, Py_ssize_t str_len, + int keepends) +{ + /* This does not use the preallocated list because splitlines is + usually run with hundreds of newlines. The overhead of + switching between PyList_SET_ITEM and append causes about a + 2-3% slowdown for that common case. A smarter implementation + could move the if check out, so the SET_ITEMs are done first + and the appends only done when the prealloc buffer is full. + That's too much work for little gain.*/ + + register Py_ssize_t i; + register Py_ssize_t j; + PyObject *list = PyList_New(0); + PyObject *sub; + + if (list == NULL) + return NULL; + + for (i = j = 0; i < str_len; ) { + Py_ssize_t eol; + + /* Find a line and append it */ + while (i < str_len && !STRINGLIB_ISLINEBREAK(str[i])) + i++; + + /* Skip the line break reading CRLF as one line break */ + eol = i; + if (i < str_len) { + if (str[i] == '\r' && i + 1 < str_len && str[i+1] == '\n') + i += 2; + else + i++; + if (keepends) + eol = i; + } +#ifndef STRINGLIB_MUTABLE + if (j == 0 && eol == str_len && STRINGLIB_CHECK_EXACT(str_obj)) { + /* No linebreak in str_obj, so just use it as list[0] */ + if (PyList_Append(list, str_obj)) + goto onError; + break; + } +#endif + SPLIT_APPEND(str, j, eol); + j = i; + } + return list; + + onError: + Py_DECREF(list); + return NULL; +} + +#endif diff --git a/Objects/stringlib/string_format.h b/Objects/stringlib/string_format.h index b2095fd..6f10727 100644 --- a/Objects/stringlib/string_format.h +++ b/Objects/stringlib/string_format.h @@ -499,13 +499,16 @@ get_field_object(SubString *input, PyObject *args, PyObject *kwargs, PyObject *key = SubString_new_object(&first); if (key == NULL) goto error; - if ((kwargs == NULL) || (obj = PyDict_GetItem(kwargs, key)) == NULL) { + + /* Use PyObject_GetItem instead of PyDict_GetItem because this + code is no longer just used with kwargs. It might be passed + a non-dict when called through format_map. */ + if ((kwargs == NULL) || (obj = PyObject_GetItem(kwargs, key)) == NULL) { PyErr_SetObject(PyExc_KeyError, key); Py_DECREF(key); goto error; } Py_DECREF(key); - Py_INCREF(obj); } else { /* look up in args */ @@ -1039,6 +1042,11 @@ do_string_format(PyObject *self, PyObject *args, PyObject *kwargs) return build_string(&input, args, kwargs, recursion_depth, &auto_number); } +static PyObject * +do_string_format_map(PyObject *self, PyObject *obj) +{ + return do_string_format(self, NULL, obj); +} /************************************************************************/ @@ -1180,10 +1188,15 @@ static PyTypeObject PyFormatterIter_Type = { describing the parsed elements. It's a wrapper around stringlib/string_format.h's MarkupIterator */ static PyObject * -formatter_parser(STRINGLIB_OBJECT *self) +formatter_parser(PyObject *ignored, STRINGLIB_OBJECT *self) { formatteriterobject *it; + if (!PyUnicode_Check(self)) { + PyErr_Format(PyExc_TypeError, "expected str, got %s", Py_TYPE(self)->tp_name); + return NULL; + } + it = PyObject_New(formatteriterobject, &PyFormatterIter_Type); if (it == NULL) return NULL; @@ -1315,7 +1328,7 @@ static PyTypeObject PyFieldNameIter_Type = { field_name_split. The iterator it returns is a FieldNameIterator */ static PyObject * -formatter_field_name_split(STRINGLIB_OBJECT *self) +formatter_field_name_split(PyObject *ignored, STRINGLIB_OBJECT *self) { SubString first; Py_ssize_t first_idx; @@ -1324,6 +1337,11 @@ formatter_field_name_split(STRINGLIB_OBJECT *self) PyObject *first_obj = NULL; PyObject *result = NULL; + if (!PyUnicode_Check(self)) { + PyErr_Format(PyExc_TypeError, "expected str, got %s", Py_TYPE(self)->tp_name); + return NULL; + } + it = PyObject_New(fieldnameiterobject, &PyFieldNameIter_Type); if (it == NULL) return NULL; diff --git a/Objects/stringlib/stringdefs.h b/Objects/stringlib/stringdefs.h index a5672c7..1c49426 100644 --- a/Objects/stringlib/stringdefs.h +++ b/Objects/stringlib/stringdefs.h @@ -11,6 +11,8 @@ #define STRINGLIB_TYPE_NAME "string" #define STRINGLIB_PARSE_CODE "S" #define STRINGLIB_EMPTY nullstring +#define STRINGLIB_ISSPACE Py_ISSPACE +#define STRINGLIB_ISLINEBREAK(x) ((x == '\n') || (x == '\r')) #define STRINGLIB_ISDECIMAL(x) ((x >= '0') && (x <= '9')) #define STRINGLIB_TODECIMAL(x) (STRINGLIB_ISDECIMAL(x) ? (x - '0') : -1) #define STRINGLIB_TOUPPER Py_TOUPPER @@ -21,7 +23,7 @@ #define STRINGLIB_NEW PyBytes_FromStringAndSize #define STRINGLIB_RESIZE _PyBytes_Resize #define STRINGLIB_CHECK PyBytes_Check -#define STRINGLIB_CMP memcmp +#define STRINGLIB_CHECK_EXACT PyBytes_CheckExact #define STRINGLIB_TOSTR PyObject_Str #define STRINGLIB_GROUPING _PyBytes_InsertThousandsGrouping #define STRINGLIB_GROUPING_LOCALE _PyBytes_InsertThousandsGroupingLocale diff --git a/Objects/stringlib/transmogrify.h b/Objects/stringlib/transmogrify.h index 4390e22..1e132e5 100644 --- a/Objects/stringlib/transmogrify.h +++ b/Objects/stringlib/transmogrify.h @@ -1,13 +1,6 @@ /* NOTE: this API is -ONLY- for use with single byte character strings. */ /* Do not use it with Unicode. */ -#include "bytes_methods.h" - -#ifndef STRINGLIB_MUTABLE -#warning "STRINGLIB_MUTABLE not defined before #include, assuming 0" -#define STRINGLIB_MUTABLE 0 -#endif - /* the more complicated methods. parts of these should be pulled out into the shared code in bytes_methods.c to cut down on duplicate code bloat. */ @@ -25,10 +18,10 @@ stringlib_expandtabs(PyObject *self, PyObject *args) size_t i, j; PyObject *u; int tabsize = 8; - + if (!PyArg_ParseTuple(args, "|i:expandtabs", &tabsize)) return NULL; - + /* First pass: determine size of output string */ i = j = 0; e = STRINGLIB_STR(self) + STRINGLIB_LEN(self); @@ -55,20 +48,20 @@ stringlib_expandtabs(PyObject *self, PyObject *args) } } } - + if ((i + j) > PY_SSIZE_T_MAX) { PyErr_SetString(PyExc_OverflowError, "result is too long"); return NULL; } - + /* Second pass: create output string and fill it */ u = STRINGLIB_NEW(NULL, i + j); if (!u) return NULL; - + j = 0; q = STRINGLIB_STR(u); - + for (p = STRINGLIB_STR(self); p < e; p++) if (*p == '\t') { if (tabsize > 0) { @@ -84,7 +77,7 @@ stringlib_expandtabs(PyObject *self, PyObject *args) if (*p == '\n' || *p == '\r') j = 0; } - + return u; } @@ -110,16 +103,16 @@ pad(PyObject *self, Py_ssize_t left, Py_ssize_t right, char fill) } u = STRINGLIB_NEW(NULL, - left + STRINGLIB_LEN(self) + right); + left + STRINGLIB_LEN(self) + right); if (u) { if (left) memset(STRINGLIB_STR(u), fill, left); Py_MEMCPY(STRINGLIB_STR(u) + left, - STRINGLIB_STR(self), - STRINGLIB_LEN(self)); + STRINGLIB_STR(self), + STRINGLIB_LEN(self)); if (right) memset(STRINGLIB_STR(u) + left + STRINGLIB_LEN(self), - fill, right); + fill, right); } return u; @@ -269,87 +262,3 @@ stringlib_zfill(PyObject *self, PyObject *args) return (PyObject*) s; } - - -#define _STRINGLIB_SPLIT_APPEND(data, left, right) \ - str = STRINGLIB_NEW((data) + (left), \ - (right) - (left)); \ - if (str == NULL) \ - goto onError; \ - if (PyList_Append(list, str)) { \ - Py_DECREF(str); \ - goto onError; \ - } \ - else \ - Py_DECREF(str); - -PyDoc_STRVAR(splitlines__doc__, -"B.splitlines([keepends]) -> list of lines\n\ -\n\ -Return a list of the lines in B, breaking at line boundaries.\n\ -Line breaks are not included in the resulting list unless keepends\n\ -is given and true."); - -static PyObject* -stringlib_splitlines(PyObject *self, PyObject *args) -{ - register Py_ssize_t i; - register Py_ssize_t j; - Py_ssize_t len; - int keepends = 0; - PyObject *list; - PyObject *str; - char *data; - - if (!PyArg_ParseTuple(args, "|i:splitlines", &keepends)) - return NULL; - - data = STRINGLIB_STR(self); - len = STRINGLIB_LEN(self); - - /* This does not use the preallocated list because splitlines is - usually run with hundreds of newlines. The overhead of - switching between PyList_SET_ITEM and append causes about a - 2-3% slowdown for that common case. A smarter implementation - could move the if check out, so the SET_ITEMs are done first - and the appends only done when the prealloc buffer is full. - That's too much work for little gain.*/ - - list = PyList_New(0); - if (!list) - goto onError; - - for (i = j = 0; i < len; ) { - Py_ssize_t eol; - - /* Find a line and append it */ - while (i < len && data[i] != '\n' && data[i] != '\r') - i++; - - /* Skip the line break reading CRLF as one line break */ - eol = i; - if (i < len) { - if (data[i] == '\r' && i + 1 < len && - data[i+1] == '\n') - i += 2; - else - i++; - if (keepends) - eol = i; - } - _STRINGLIB_SPLIT_APPEND(data, j, eol); - j = i; - } - if (j < len) { - _STRINGLIB_SPLIT_APPEND(data, j, len); - } - - return list; - - onError: - Py_XDECREF(list); - return NULL; -} - -#undef _STRINGLIB_SPLIT_APPEND - diff --git a/Objects/stringlib/unicodedefs.h b/Objects/stringlib/unicodedefs.h index 366acfe..09dae6d 100644 --- a/Objects/stringlib/unicodedefs.h +++ b/Objects/stringlib/unicodedefs.h @@ -11,6 +11,8 @@ #define STRINGLIB_TYPE_NAME "unicode" #define STRINGLIB_PARSE_CODE "U" #define STRINGLIB_EMPTY unicode_empty +#define STRINGLIB_ISSPACE Py_UNICODE_ISSPACE +#define STRINGLIB_ISLINEBREAK BLOOM_LINEBREAK #define STRINGLIB_ISDECIMAL Py_UNICODE_ISDECIMAL #define STRINGLIB_TODECIMAL Py_UNICODE_TODECIMAL #define STRINGLIB_TOUPPER Py_UNICODE_TOUPPER @@ -21,6 +23,7 @@ #define STRINGLIB_NEW PyUnicode_FromUnicode #define STRINGLIB_RESIZE PyUnicode_Resize #define STRINGLIB_CHECK PyUnicode_Check +#define STRINGLIB_CHECK_EXACT PyUnicode_CheckExact #define STRINGLIB_GROUPING _PyUnicode_InsertThousandsGrouping #define STRINGLIB_GROUPING_LOCALE _PyUnicode_InsertThousandsGroupingLocale @@ -34,23 +37,4 @@ #define STRINGLIB_WANT_CONTAINS_OBJ 1 -/* STRINGLIB_CMP was defined as: - -Py_LOCAL_INLINE(int) -STRINGLIB_CMP(const Py_UNICODE* str, const Py_UNICODE* other, Py_ssize_t len) -{ - if (str[0] != other[0]) - return 1; - return memcmp((void*) str, (void*) other, len * sizeof(Py_UNICODE)); -} - -but unfortunately that gives a error if the function isn't used in a file that -includes this file. So, reluctantly convert it to a macro instead. */ - -#define STRINGLIB_CMP(str, other, len) \ - (((str)[0] != (other)[0]) ? \ - 1 : \ - memcmp((void*) (str), (void*) (other), (len) * sizeof(Py_UNICODE))) - - #endif /* !STRINGLIB_UNICODEDEFS_H */ diff --git a/Objects/structseq.c b/Objects/structseq.c index 7031225..ef17f49 100644 --- a/Objects/structseq.c +++ b/Objects/structseq.c @@ -3,7 +3,6 @@ #include "Python.h" #include "structmember.h" -#include "structseq.h" static char visible_length_key[] = "n_sequence_fields"; static char real_length_key[] = "n_fields"; @@ -30,113 +29,42 @@ PyObject * PyStructSequence_New(PyTypeObject *type) { PyStructSequence *obj; + Py_ssize_t size = REAL_SIZE_TP(type), i; - obj = PyObject_New(PyStructSequence, type); + obj = PyObject_GC_NewVar(PyStructSequence, type, size); if (obj == NULL) return NULL; + /* Hack the size of the variable object, so invisible fields don't appear + to Python code. */ Py_SIZE(obj) = VISIBLE_SIZE_TP(type); + for (i = 0; i < size; i++) + obj->ob_item[i] = NULL; - return (PyObject*) obj; + return (PyObject*)obj; } -static void -structseq_dealloc(PyStructSequence *obj) -{ - Py_ssize_t i, size; - - size = REAL_SIZE(obj); - for (i = 0; i < size; ++i) { - Py_XDECREF(obj->ob_item[i]); - } - PyObject_Del(obj); -} - -static Py_ssize_t -structseq_length(PyStructSequence *obj) +void +PyStructSequence_SetItem(PyObject* op, Py_ssize_t i, PyObject* v) { - return VISIBLE_SIZE(obj); + PyStructSequence_SET_ITEM(op, i, v); } -static PyObject* -structseq_item(PyStructSequence *obj, Py_ssize_t i) +PyObject* +PyStructSequence_GetItem(PyObject* op, Py_ssize_t i) { - if (i < 0 || i >= VISIBLE_SIZE(obj)) { - PyErr_SetString(PyExc_IndexError, "tuple index out of range"); - return NULL; - } - Py_INCREF(obj->ob_item[i]); - return obj->ob_item[i]; + return PyStructSequence_GET_ITEM(op, i); } -static PyObject* -structseq_slice(PyStructSequence *obj, Py_ssize_t low, Py_ssize_t high) -{ - PyTupleObject *np; - Py_ssize_t i; - - if (low < 0) - low = 0; - if (high > VISIBLE_SIZE(obj)) - high = VISIBLE_SIZE(obj); - if (high < low) - high = low; - np = (PyTupleObject *)PyTuple_New(high-low); - if (np == NULL) - return NULL; - for(i = low; i < high; ++i) { - PyObject *v = obj->ob_item[i]; - Py_INCREF(v); - PyTuple_SET_ITEM(np, i-low, v); - } - return (PyObject *) np; -} - -static PyObject * -structseq_subscript(PyStructSequence *self, PyObject *item) +static void +structseq_dealloc(PyStructSequence *obj) { - if (PyIndex_Check(item)) { - Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) - return NULL; - - if (i < 0) - i += VISIBLE_SIZE(self); - - if (i < 0 || i >= VISIBLE_SIZE(self)) { - PyErr_SetString(PyExc_IndexError, - "tuple index out of range"); - return NULL; - } - Py_INCREF(self->ob_item[i]); - return self->ob_item[i]; - } - else if (PySlice_Check(item)) { - Py_ssize_t start, stop, step, slicelen, cur, i; - PyObject *result; - - if (PySlice_GetIndicesEx((PySliceObject *)item, - VISIBLE_SIZE(self), &start, &stop, - &step, &slicelen) < 0) { - return NULL; - } - if (slicelen <= 0) - return PyTuple_New(0); - result = PyTuple_New(slicelen); - if (result == NULL) - return NULL; - for (cur = start, i = 0; i < slicelen; - cur += step, i++) { - PyObject *v = self->ob_item[cur]; - Py_INCREF(v); - PyTuple_SET_ITEM(result, i, v); - } - return result; - } - else { - PyErr_SetString(PyExc_TypeError, - "structseq index must be integer"); - return NULL; + Py_ssize_t i, size; + + size = REAL_SIZE(obj); + for (i = 0; i < size; ++i) { + Py_XDECREF(obj->ob_item[i]); } + PyObject_GC_Del(obj); } static PyObject * @@ -223,11 +151,6 @@ structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return (PyObject*) res; } -static PyObject * -make_tuple(PyStructSequence *obj) -{ - return structseq_slice(obj, 0, VISIBLE_SIZE(obj)); -} static PyObject * structseq_repr(PyStructSequence *obj) @@ -236,7 +159,6 @@ structseq_repr(PyStructSequence *obj) #define REPR_BUFFER_SIZE 512 #define TYPE_MAXSIZE 100 - PyObject *tup; PyTypeObject *typ = Py_TYPE(obj); int i, removelast = 0; Py_ssize_t len; @@ -246,10 +168,6 @@ structseq_repr(PyStructSequence *obj) /* pointer to end of writeable buffer; safes space for "...)\0" */ endofbuf= &buf[REPR_BUFFER_SIZE-5]; - if ((tup = make_tuple(obj)) == NULL) { - return NULL; - } - /* "typename(", limited to TYPE_MAXSIZE */ len = strlen(typ->tp_name) > TYPE_MAXSIZE ? TYPE_MAXSIZE : strlen(typ->tp_name); @@ -262,19 +180,17 @@ structseq_repr(PyStructSequence *obj) char *cname, *crepr; cname = typ->tp_members[i].name; - - val = PyTuple_GetItem(tup, i); - if (cname == NULL || val == NULL) { + if (cname == NULL) { + PyErr_Format(PyExc_SystemError, "In structseq_repr(), member %d name is NULL" + " for type %.500s", i, typ->tp_name); return NULL; } + val = PyStructSequence_GET_ITEM(obj, i); repr = PyObject_Repr(val); - if (repr == NULL) { - Py_DECREF(tup); + if (repr == NULL) return NULL; - } crepr = _PyUnicode_AsString(repr); if (crepr == NULL) { - Py_DECREF(tup); Py_DECREF(repr); return NULL; } @@ -300,7 +216,6 @@ structseq_repr(PyStructSequence *obj) break; } } - Py_DECREF(tup); if (removelast) { /* overwrite last ", " */ pbuf-=2; @@ -312,62 +227,6 @@ structseq_repr(PyStructSequence *obj) } static PyObject * -structseq_concat(PyStructSequence *obj, PyObject *b) -{ - PyObject *tup, *result; - tup = make_tuple(obj); - result = PySequence_Concat(tup, b); - Py_DECREF(tup); - return result; -} - -static PyObject * -structseq_repeat(PyStructSequence *obj, Py_ssize_t n) -{ - PyObject *tup, *result; - tup = make_tuple(obj); - result = PySequence_Repeat(tup, n); - Py_DECREF(tup); - return result; -} - -static int -structseq_contains(PyStructSequence *obj, PyObject *o) -{ - PyObject *tup; - int result; - tup = make_tuple(obj); - if (!tup) - return -1; - result = PySequence_Contains(tup, o); - Py_DECREF(tup); - return result; -} - -static long -structseq_hash(PyObject *obj) -{ - PyObject *tup; - long result; - tup = make_tuple((PyStructSequence*) obj); - if (!tup) - return -1; - result = PyObject_Hash(tup); - Py_DECREF(tup); - return result; -} - -static PyObject * -structseq_richcompare(PyObject *obj, PyObject *o2, int op) -{ - PyObject *tup, *result; - tup = make_tuple((PyStructSequence*) obj); - result = PyObject_RichCompare(tup, o2, op); - Py_DECREF(tup); - return result; -} - -static PyObject * structseq_reduce(PyStructSequence* self) { PyObject* tup; @@ -409,33 +268,16 @@ structseq_reduce(PyStructSequence* self) return result; } -static PySequenceMethods structseq_as_sequence = { - (lenfunc)structseq_length, - (binaryfunc)structseq_concat, /* sq_concat */ - (ssizeargfunc)structseq_repeat, /* sq_repeat */ - (ssizeargfunc)structseq_item, /* sq_item */ - 0, /* sq_slice */ - 0, /* sq_ass_item */ - 0, /* sq_ass_slice */ - (objobjproc)structseq_contains, /* sq_contains */ -}; - -static PyMappingMethods structseq_as_mapping = { - (lenfunc)structseq_length, - (binaryfunc)structseq_subscript, -}; - static PyMethodDef structseq_methods[] = { - {"__reduce__", (PyCFunction)structseq_reduce, - METH_NOARGS, NULL}, + {"__reduce__", (PyCFunction)structseq_reduce, METH_NOARGS, NULL}, {NULL, NULL} }; static PyTypeObject _struct_sequence_template = { PyVarObject_HEAD_INIT(&PyType_Type, 0) NULL, /* tp_name */ - 0, /* tp_basicsize */ - 0, /* tp_itemsize */ + sizeof(PyStructSequence) - sizeof(PyObject *), /* tp_basicsize */ + sizeof(PyObject *), /* tp_itemsize */ (destructor)structseq_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ @@ -443,19 +285,19 @@ static PyTypeObject _struct_sequence_template = { 0, /* tp_reserved */ (reprfunc)structseq_repr, /* tp_repr */ 0, /* tp_as_number */ - &structseq_as_sequence, /* tp_as_sequence */ - &structseq_as_mapping, /* tp_as_mapping */ - structseq_hash, /* tp_hash */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ - structseq_richcompare, /* tp_richcompare */ + 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ @@ -494,11 +336,9 @@ PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc) n_members = i; memcpy(type, &_struct_sequence_template, sizeof(PyTypeObject)); + type->tp_base = &PyTuple_Type; type->tp_name = desc->name; type->tp_doc = desc->doc; - type->tp_basicsize = sizeof(PyStructSequence)+ - sizeof(PyObject*)*(n_members-1); - type->tp_itemsize = 0; members = PyMem_NEW(PyMemberDef, n_members-n_unnamed_members+1); if (members == NULL) @@ -537,3 +377,11 @@ PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc) SET_DICT_FROM_INT(real_length_key, n_members); SET_DICT_FROM_INT(unnamed_fields_key, n_unnamed_members); } + +PyTypeObject* +PyStructSequence_NewType(PyStructSequence_Desc *desc) +{ + PyTypeObject *result = (PyTypeObject*)PyType_GenericAlloc(&PyType_Type, 0); + PyStructSequence_InitType(result, desc); + return result; +} diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index aa3be82..72b79c9 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -312,13 +312,13 @@ Done: 1330111, 1412633, 1165069, 1247599, 1495177, 1577699 */ -static long +static Py_hash_t tuplehash(PyTupleObject *v) { - register long x, y; + register Py_hash_t x, y; register Py_ssize_t len = Py_SIZE(v); register PyObject **p; - long mult = 1000003L; + Py_hash_t mult = 1000003L; x = 0x345678L; p = v->ob_item; while (--len >= 0) { @@ -327,7 +327,7 @@ tuplehash(PyTupleObject *v) return -1; x = (x ^ y) * mult; /* the cast might truncate len; that doesn't change hash stability */ - mult += (long)(82520L + len + len); + mult += (Py_hash_t)(82520L + len + len); } x += 97531L; if (x == -1) @@ -689,7 +689,7 @@ tuplesubscript(PyTupleObject* self, PyObject* item) PyObject* it; PyObject **src, **dest; - if (PySlice_GetIndicesEx((PySliceObject*)item, + if (PySlice_GetIndicesEx(item, PyTuple_GET_SIZE(self), &start, &stop, &step, &slicelength) < 0) { return NULL; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 310a56c..8eaf51f 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1359,8 +1359,14 @@ consistent method resolution\norder (MRO) for bases"); i = 0; while (PyDict_Next(set, &i, &k, &v) && (size_t)off < sizeof(buf)) { PyObject *name = class_name(k); - off += PyOS_snprintf(buf + off, sizeof(buf) - off, " %s", - name ? _PyUnicode_AsString(name) : "?"); + char *name_str; + if (name != NULL) { + name_str = _PyUnicode_AsString(name); + if (name_str == NULL) + name_str = "?"; + } else + name_str = "?"; + off += PyOS_snprintf(buf + off, sizeof(buf) - off, " %s", name_str); Py_XDECREF(name); if (--n && (size_t)(off+1) < sizeof(buf)) { buf[off++] = ','; @@ -1898,6 +1904,12 @@ type_init(PyObject *cls, PyObject *args, PyObject *kwds) return res; } +long +PyType_GetFlags(PyTypeObject *type) +{ + return type->tp_flags; +} + static PyObject * type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) { @@ -2232,6 +2244,10 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) for (i = 0; i < nslots; i++, mp++) { mp->name = _PyUnicode_AsString( PyTuple_GET_ITEM(slots, i)); + if (mp->name == NULL) { + Py_DECREF(type); + return NULL; + } mp->type = T_OBJECT_EX; mp->offset = slotoffset; @@ -2303,6 +2319,57 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) return (PyObject *)type; } +static short slotoffsets[] = { + -1, /* invalid slot */ +#include "typeslots.inc" +}; + +PyObject* PyType_FromSpec(PyType_Spec *spec) +{ + PyHeapTypeObject *res = (PyHeapTypeObject*)PyType_GenericAlloc(&PyType_Type, 0); + char *res_start = (char*)res; + PyType_Slot *slot; + + if (res == NULL) + return NULL; + res->ht_name = PyUnicode_FromString(spec->name); + if (!res->ht_name) + goto fail; + res->ht_type.tp_name = _PyUnicode_AsString(res->ht_name); + if (!res->ht_type.tp_name) + goto fail; + + res->ht_type.tp_basicsize = spec->basicsize; + res->ht_type.tp_itemsize = spec->itemsize; + res->ht_type.tp_flags = spec->flags | Py_TPFLAGS_HEAPTYPE; + + for (slot = spec->slots; slot->slot; slot++) { + if (slot->slot >= sizeof(slotoffsets)/sizeof(slotoffsets[0])) { + PyErr_SetString(PyExc_RuntimeError, "invalid slot offset"); + goto fail; + } + *(void**)(res_start + slotoffsets[slot->slot]) = slot->pfunc; + + /* need to make a copy of the docstring slot, which usually + points to a static string literal */ + if (slot->slot == Py_tp_doc) { + ssize_t len = strlen(slot->pfunc)+1; + char *tp_doc = PyObject_MALLOC(len); + if (tp_doc == NULL) + goto fail; + memcpy(tp_doc, slot->pfunc, len); + res->ht_type.tp_doc = tp_doc; + } + } + + return (PyObject*)res; + + fail: + Py_DECREF(res); + return NULL; +} + + /* Internal API to look for a name through the MRO. This returns a borrowed reference, and doesn't set an exception! */ PyObject * @@ -3309,23 +3376,32 @@ object_format(PyObject *self, PyObject *args) PyObject *format_spec; PyObject *self_as_str = NULL; PyObject *result = NULL; - PyObject *format_meth = NULL; if (!PyArg_ParseTuple(args, "U:__format__", &format_spec)) return NULL; self_as_str = PyObject_Str(self); if (self_as_str != NULL) { - /* find the format function */ - format_meth = PyObject_GetAttrString(self_as_str, "__format__"); - if (format_meth != NULL) { - /* and call it */ - result = PyObject_CallFunctionObjArgs(format_meth, format_spec, NULL); - } - } - + /* Issue 7994: If we're converting to a string, we + should reject format specifications */ + if (PyUnicode_GET_SIZE(format_spec) > 0) { + if (PyErr_WarnEx(PyExc_PendingDeprecationWarning, + "object.__format__ with a non-empty format " + "string is deprecated", 1) < 0) { + goto done; + } + /* Eventually this will become an error: + PyErr_Format(PyExc_TypeError, + "non-empty format string passed to object.__format__"); + goto done; + */ + } + + result = PyObject_Format(self_as_str, format_spec); + } + +done: Py_XDECREF(self_as_str); - Py_XDECREF(format_meth); return result; } @@ -3483,11 +3559,8 @@ add_getset(PyTypeObject *type, PyGetSetDef *gsp) static void inherit_special(PyTypeObject *type, PyTypeObject *base) { - Py_ssize_t oldsize, newsize; /* Copying basicsize is connected to the GC flags */ - oldsize = base->tp_basicsize; - newsize = type->tp_basicsize ? type->tp_basicsize : oldsize; if (!(type->tp_flags & Py_TPFLAGS_HAVE_GC) && (base->tp_flags & Py_TPFLAGS_HAVE_GC) && (!type->tp_traverse && !type->tp_clear)) { @@ -3514,7 +3587,8 @@ inherit_special(PyTypeObject *type, PyTypeObject *base) type->tp_new = base->tp_new; } } - type->tp_basicsize = newsize; + if (type->tp_basicsize == 0) + type->tp_basicsize = base->tp_basicsize; /* Copy other non-function slots */ @@ -3901,13 +3975,10 @@ PyType_Ready(PyTypeObject *type) tp_reserved) but not tp_richcompare. */ if (type->tp_reserved && !type->tp_richcompare) { int error; - char msg[240]; - PyOS_snprintf(msg, sizeof(msg), - "Type %.100s defines tp_reserved (formerly " - "tp_compare) but not tp_richcompare. " - "Comparisons may not behave as intended.", - type->tp_name); - error = PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1); + error = PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "Type %.100s defines tp_reserved (formerly tp_compare) " + "but not tp_richcompare. Comparisons may not behave as intended.", + type->tp_name); if (error == -1) goto error; } @@ -4306,14 +4377,14 @@ static PyObject * wrap_hashfunc(PyObject *self, PyObject *args, void *wrapped) { hashfunc func = (hashfunc)wrapped; - long res; + Py_hash_t res; if (!check_num_args(args, 0)) return NULL; res = (*func)(self); if (res == -1 && PyErr_Occurred()) return NULL; - return PyLong_FromLong(res); + return PyLong_FromSsize_t(res); } static PyObject * @@ -4910,12 +4981,12 @@ slot_tp_str(PyObject *self) } } -static long +static Py_hash_t slot_tp_hash(PyObject *self) { PyObject *func, *res; static PyObject *hash_str; - long h; + Py_ssize_t h; func = lookup_method(self, "__hash__", &hash_str); @@ -4932,14 +5003,30 @@ slot_tp_hash(PyObject *self) Py_DECREF(func); if (res == NULL) return -1; - if (PyLong_Check(res)) + + if (!PyLong_Check(res)) { + PyErr_SetString(PyExc_TypeError, + "__hash__ method should return an integer"); + return -1; + } + /* Transform the PyLong `res` to a Py_hash_t `h`. For an existing + hashable Python object x, hash(x) will always lie within the range of + Py_hash_t. Therefore our transformation must preserve values that + already lie within this range, to ensure that if x.__hash__() returns + hash(y) then hash(x) == hash(y). */ + h = PyLong_AsSsize_t(res); + if (h == -1 && PyErr_Occurred()) { + /* res was not within the range of a Py_hash_t, so we're free to + use any sufficiently bit-mixing transformation; + long.__hash__ will do nicely. */ + PyErr_Clear(); h = PyLong_Type.tp_hash(res); - else - h = PyLong_AsLong(res); + } + /* -1 is reserved for errors. */ + if (h == -1) + h = -2; Py_DECREF(res); - if (h == -1 && !PyErr_Occurred()) - h = -2; - return h; + return h; } static PyObject * @@ -5078,7 +5165,7 @@ static char *name_op[] = { }; static PyObject * -half_richcompare(PyObject *self, PyObject *other, int op) +slot_tp_richcompare(PyObject *self, PyObject *other, int op) { PyObject *func, *args, *res; static PyObject *op_str[6]; @@ -5101,28 +5188,6 @@ half_richcompare(PyObject *self, PyObject *other, int op) } static PyObject * -slot_tp_richcompare(PyObject *self, PyObject *other, int op) -{ - PyObject *res; - - if (Py_TYPE(self)->tp_richcompare == slot_tp_richcompare) { - res = half_richcompare(self, other, op); - if (res != Py_NotImplemented) - return res; - Py_DECREF(res); - } - if (Py_TYPE(other)->tp_richcompare == slot_tp_richcompare) { - res = half_richcompare(other, self, _Py_SwappedOp[op]); - if (res != Py_NotImplemented) { - return res; - } - Py_DECREF(res); - } - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; -} - -static PyObject * slot_tp_iter(PyObject *self) { PyObject *func, *res; @@ -5658,7 +5723,7 @@ update_one_slot(PyTypeObject *type, slotdef *p) generic = p->function; d = (PyWrapperDescrObject *)descr; if (d->d_base->wrapper == p->wrapper && - PyType_IsSubtype(type, d->d_type)) + PyType_IsSubtype(type, PyDescr_TYPE(d))) { if (specific == NULL || specific == d->d_wrapped) @@ -6162,7 +6227,7 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds) and first local variable on the stack. */ PyFrameObject *f = PyThreadState_GET()->frame; PyCodeObject *co = f->f_code; - int i, n; + Py_ssize_t i, n; if (co == NULL) { PyErr_SetString(PyExc_SystemError, "super(): no code object"); diff --git a/Objects/typeslots.inc b/Objects/typeslots.inc new file mode 100644 index 0000000..5186dcf --- /dev/null +++ b/Objects/typeslots.inc @@ -0,0 +1,75 @@ +/* Generated by typeslots.py $Revision$ */ +0, +0, +offsetof(PyHeapTypeObject, as_mapping.mp_ass_subscript), +offsetof(PyHeapTypeObject, as_mapping.mp_length), +offsetof(PyHeapTypeObject, as_mapping.mp_subscript), +offsetof(PyHeapTypeObject, as_number.nb_absolute), +offsetof(PyHeapTypeObject, as_number.nb_add), +offsetof(PyHeapTypeObject, as_number.nb_and), +offsetof(PyHeapTypeObject, as_number.nb_bool), +offsetof(PyHeapTypeObject, as_number.nb_divmod), +offsetof(PyHeapTypeObject, as_number.nb_float), +offsetof(PyHeapTypeObject, as_number.nb_floor_divide), +offsetof(PyHeapTypeObject, as_number.nb_index), +offsetof(PyHeapTypeObject, as_number.nb_inplace_add), +offsetof(PyHeapTypeObject, as_number.nb_inplace_and), +offsetof(PyHeapTypeObject, as_number.nb_inplace_floor_divide), +offsetof(PyHeapTypeObject, as_number.nb_inplace_lshift), +offsetof(PyHeapTypeObject, as_number.nb_inplace_multiply), +offsetof(PyHeapTypeObject, as_number.nb_inplace_or), +offsetof(PyHeapTypeObject, as_number.nb_inplace_power), +offsetof(PyHeapTypeObject, as_number.nb_inplace_remainder), +offsetof(PyHeapTypeObject, as_number.nb_inplace_rshift), +offsetof(PyHeapTypeObject, as_number.nb_inplace_subtract), +offsetof(PyHeapTypeObject, as_number.nb_inplace_true_divide), +offsetof(PyHeapTypeObject, as_number.nb_inplace_xor), +offsetof(PyHeapTypeObject, as_number.nb_int), +offsetof(PyHeapTypeObject, as_number.nb_invert), +offsetof(PyHeapTypeObject, as_number.nb_lshift), +offsetof(PyHeapTypeObject, as_number.nb_multiply), +offsetof(PyHeapTypeObject, as_number.nb_negative), +offsetof(PyHeapTypeObject, as_number.nb_or), +offsetof(PyHeapTypeObject, as_number.nb_positive), +offsetof(PyHeapTypeObject, as_number.nb_power), +offsetof(PyHeapTypeObject, as_number.nb_remainder), +offsetof(PyHeapTypeObject, as_number.nb_rshift), +offsetof(PyHeapTypeObject, as_number.nb_subtract), +offsetof(PyHeapTypeObject, as_number.nb_true_divide), +offsetof(PyHeapTypeObject, as_number.nb_xor), +offsetof(PyHeapTypeObject, as_sequence.sq_ass_item), +offsetof(PyHeapTypeObject, as_sequence.sq_concat), +offsetof(PyHeapTypeObject, as_sequence.sq_contains), +offsetof(PyHeapTypeObject, as_sequence.sq_inplace_concat), +offsetof(PyHeapTypeObject, as_sequence.sq_inplace_repeat), +offsetof(PyHeapTypeObject, as_sequence.sq_item), +offsetof(PyHeapTypeObject, as_sequence.sq_length), +offsetof(PyHeapTypeObject, as_sequence.sq_repeat), +offsetof(PyHeapTypeObject, ht_type.tp_alloc), +offsetof(PyHeapTypeObject, ht_type.tp_base), +offsetof(PyHeapTypeObject, ht_type.tp_bases), +offsetof(PyHeapTypeObject, ht_type.tp_call), +offsetof(PyHeapTypeObject, ht_type.tp_clear), +offsetof(PyHeapTypeObject, ht_type.tp_dealloc), +offsetof(PyHeapTypeObject, ht_type.tp_del), +offsetof(PyHeapTypeObject, ht_type.tp_descr_get), +offsetof(PyHeapTypeObject, ht_type.tp_descr_set), +offsetof(PyHeapTypeObject, ht_type.tp_doc), +offsetof(PyHeapTypeObject, ht_type.tp_getattr), +offsetof(PyHeapTypeObject, ht_type.tp_getattro), +offsetof(PyHeapTypeObject, ht_type.tp_hash), +offsetof(PyHeapTypeObject, ht_type.tp_init), +offsetof(PyHeapTypeObject, ht_type.tp_is_gc), +offsetof(PyHeapTypeObject, ht_type.tp_iter), +offsetof(PyHeapTypeObject, ht_type.tp_iternext), +offsetof(PyHeapTypeObject, ht_type.tp_methods), +offsetof(PyHeapTypeObject, ht_type.tp_new), +offsetof(PyHeapTypeObject, ht_type.tp_repr), +offsetof(PyHeapTypeObject, ht_type.tp_richcompare), +offsetof(PyHeapTypeObject, ht_type.tp_setattr), +offsetof(PyHeapTypeObject, ht_type.tp_setattro), +offsetof(PyHeapTypeObject, ht_type.tp_str), +offsetof(PyHeapTypeObject, ht_type.tp_traverse), +offsetof(PyHeapTypeObject, ht_type.tp_members), +offsetof(PyHeapTypeObject, ht_type.tp_getset), +offsetof(PyHeapTypeObject, ht_type.tp_free), diff --git a/Objects/typeslots.py b/Objects/typeslots.py new file mode 100644 index 0000000..2e00c80 --- /dev/null +++ b/Objects/typeslots.py @@ -0,0 +1,30 @@ +#!/usr/bin/python +# Usage: typeslots.py < Include/typeslots.h > typeslots.inc + +import sys, re + +print("/* Generated by typeslots.py $Revision$ */") +res = {} +for line in sys.stdin: + m = re.match("#define Py_([a-z_]+) ([0-9]+)", line) + if not m: + continue + member = m.group(1) + if member.startswith("tp_"): + member = "ht_type."+member + elif member.startswith("nb_"): + member = "as_number."+member + elif member.startswith("mp_"): + member = "as_mapping."+member + elif member.startswith("sq_"): + member = "as_sequence."+member + elif member.startswith("bf_"): + member = "as_buffer."+member + res[int(m.group(2))] = member + +M = max(res.keys())+1 +for i in range(1,M): + if i in res: + print("offsetof(PyHeapTypeObject, %s)," % res[i]) + else: + print("0,") diff --git a/Objects/unicodectype.c b/Objects/unicodectype.c index 1597bbd..9f6ac89 100644 --- a/Objects/unicodectype.c +++ b/Objects/unicodectype.c @@ -9,7 +9,6 @@ */ #include "Python.h" -#include "unicodeobject.h" #define ALPHA_MASK 0x01 #define DECIMAL_MASK 0x02 @@ -23,11 +22,12 @@ #define XID_CONTINUE_MASK 0x200 #define PRINTABLE_MASK 0x400 #define NODELTA_MASK 0x800 +#define NUMERIC_MASK 0x1000 typedef struct { - const Py_UNICODE upper; - const Py_UNICODE lower; - const Py_UNICODE title; + const Py_UCS4 upper; + const Py_UCS4 lower; + const Py_UCS4 title; const unsigned char decimal; const unsigned char digit; const unsigned short flags; @@ -36,15 +36,13 @@ typedef struct { #include "unicodetype_db.h" static const _PyUnicode_TypeRecord * -gettyperecord(Py_UNICODE code) +gettyperecord(Py_UCS4 code) { int index; -#ifdef Py_UNICODE_WIDE if (code >= 0x110000) index = 0; else -#endif { index = index1[(code>>SHIFT)]; index = index2[(index<<SHIFT)+(code&((1<<SHIFT)-1))]; @@ -53,30 +51,10 @@ gettyperecord(Py_UNICODE code) return &_PyUnicode_TypeRecords[index]; } -/* Returns 1 for Unicode characters having the category 'Zl', 'Zp' or - type 'B', 0 otherwise. */ - -int _PyUnicode_IsLinebreak(register const Py_UNICODE ch) -{ - switch (ch) { - case 0x000A: /* LINE FEED */ - case 0x000D: /* CARRIAGE RETURN */ - case 0x001C: /* FILE SEPARATOR */ - case 0x001D: /* GROUP SEPARATOR */ - case 0x001E: /* RECORD SEPARATOR */ - case 0x0085: /* NEXT LINE */ - case 0x2028: /* LINE SEPARATOR */ - case 0x2029: /* PARAGRAPH SEPARATOR */ - return 1; - default: - return 0; - } -} - /* Returns the titlecase Unicode characters corresponding to ch or just ch if no titlecase mapping is known. */ -Py_UNICODE _PyUnicode_ToTitlecase(register Py_UNICODE ch) +Py_UCS4 _PyUnicode_ToTitlecase(register Py_UCS4 ch) { const _PyUnicode_TypeRecord *ctype = gettyperecord(ch); int delta = ctype->title; @@ -93,7 +71,7 @@ Py_UNICODE _PyUnicode_ToTitlecase(register Py_UNICODE ch) /* Returns 1 for Unicode characters having the category 'Lt', 0 otherwise. */ -int _PyUnicode_IsTitlecase(Py_UNICODE ch) +int _PyUnicode_IsTitlecase(Py_UCS4 ch) { const _PyUnicode_TypeRecord *ctype = gettyperecord(ch); @@ -103,7 +81,7 @@ int _PyUnicode_IsTitlecase(Py_UNICODE ch) /* Returns 1 for Unicode characters having the XID_Start property, 0 otherwise. */ -int _PyUnicode_IsXidStart(Py_UNICODE ch) +int _PyUnicode_IsXidStart(Py_UCS4 ch) { const _PyUnicode_TypeRecord *ctype = gettyperecord(ch); @@ -113,7 +91,7 @@ int _PyUnicode_IsXidStart(Py_UNICODE ch) /* Returns 1 for Unicode characters having the XID_Continue property, 0 otherwise. */ -int _PyUnicode_IsXidContinue(Py_UNICODE ch) +int _PyUnicode_IsXidContinue(Py_UCS4 ch) { const _PyUnicode_TypeRecord *ctype = gettyperecord(ch); @@ -123,14 +101,14 @@ int _PyUnicode_IsXidContinue(Py_UNICODE ch) /* Returns the integer decimal (0-9) for Unicode characters having this property, -1 otherwise. */ -int _PyUnicode_ToDecimalDigit(Py_UNICODE ch) +int _PyUnicode_ToDecimalDigit(Py_UCS4 ch) { const _PyUnicode_TypeRecord *ctype = gettyperecord(ch); return (ctype->flags & DECIMAL_MASK) ? ctype->decimal : -1; } -int _PyUnicode_IsDecimalDigit(Py_UNICODE ch) +int _PyUnicode_IsDecimalDigit(Py_UCS4 ch) { if (_PyUnicode_ToDecimalDigit(ch) < 0) return 0; @@ -140,14 +118,14 @@ int _PyUnicode_IsDecimalDigit(Py_UNICODE ch) /* Returns the integer digit (0-9) for Unicode characters having this property, -1 otherwise. */ -int _PyUnicode_ToDigit(Py_UNICODE ch) +int _PyUnicode_ToDigit(Py_UCS4 ch) { const _PyUnicode_TypeRecord *ctype = gettyperecord(ch); return (ctype->flags & DIGIT_MASK) ? ctype->digit : -1; } -int _PyUnicode_IsDigit(Py_UNICODE ch) +int _PyUnicode_IsDigit(Py_UCS4 ch) { if (_PyUnicode_ToDigit(ch) < 0) return 0; @@ -157,522 +135,11 @@ int _PyUnicode_IsDigit(Py_UNICODE ch) /* Returns the numeric value as double for Unicode characters having this property, -1.0 otherwise. */ -/* TODO: replace with unicodetype_db.h table */ - -double _PyUnicode_ToNumeric(Py_UNICODE ch) +int _PyUnicode_IsNumeric(Py_UCS4 ch) { - switch (ch) { - case 0x0F33: - return (double) -1 / 2; - case 0x17F0: - case 0x3007: -#ifdef Py_UNICODE_WIDE - case 0x1018A: -#endif - return (double) 0; - case 0x09F4: - case 0x17F1: - case 0x215F: - case 0x2160: - case 0x2170: - case 0x3021: - case 0x3192: - case 0x3220: - case 0x3280: -#ifdef Py_UNICODE_WIDE - case 0x10107: - case 0x10142: - case 0x10158: - case 0x10159: - case 0x1015A: - case 0x10320: - case 0x103D1: -#endif - return (double) 1; - case 0x00BD: - case 0x0F2A: - case 0x2CFD: -#ifdef Py_UNICODE_WIDE - case 0x10141: - case 0x10175: - case 0x10176: -#endif - return (double) 1 / 2; - case 0x2153: - return (double) 1 / 3; - case 0x00BC: -#ifdef Py_UNICODE_WIDE - case 0x10140: -#endif - return (double) 1 / 4; - case 0x2155: - return (double) 1 / 5; - case 0x2159: - return (double) 1 / 6; - case 0x215B: - return (double) 1 / 8; - case 0x0BF0: - case 0x1372: - case 0x2169: - case 0x2179: - case 0x2469: - case 0x247D: - case 0x2491: - case 0x24FE: - case 0x277F: - case 0x2789: - case 0x2793: - case 0x3038: - case 0x3229: - case 0x3289: -#ifdef Py_UNICODE_WIDE - case 0x10110: - case 0x10149: - case 0x10150: - case 0x10157: - case 0x10160: - case 0x10161: - case 0x10162: - case 0x10163: - case 0x10164: - case 0x10322: - case 0x103D3: - case 0x10A44: -#endif - return (double) 10; - case 0x0BF1: - case 0x137B: - case 0x216D: - case 0x217D: -#ifdef Py_UNICODE_WIDE - case 0x10119: - case 0x1014B: - case 0x10152: - case 0x1016A: - case 0x103D5: - case 0x10A46: -#endif - return (double) 100; - case 0x0BF2: - case 0x216F: - case 0x217F: - case 0x2180: -#ifdef Py_UNICODE_WIDE - case 0x10122: - case 0x1014D: - case 0x10154: - case 0x10171: - case 0x10A47: -#endif - return (double) 1000; - case 0x137C: - case 0x2182: -#ifdef Py_UNICODE_WIDE - case 0x1012B: - case 0x10155: -#endif - return (double) 10000; - case 0x216A: - case 0x217A: - case 0x246A: - case 0x247E: - case 0x2492: - case 0x24EB: - return (double) 11; - case 0x0F2F: - return (double) 11 / 2; - case 0x216B: - case 0x217B: - case 0x246B: - case 0x247F: - case 0x2493: - case 0x24EC: - return (double) 12; - case 0x246C: - case 0x2480: - case 0x2494: - case 0x24ED: - return (double) 13; - case 0x0F30: - return (double) 13 / 2; - case 0x246D: - case 0x2481: - case 0x2495: - case 0x24EE: - return (double) 14; - case 0x246E: - case 0x2482: - case 0x2496: - case 0x24EF: - return (double) 15; - case 0x0F31: - return (double) 15 / 2; - case 0x09F9: - case 0x246F: - case 0x2483: - case 0x2497: - case 0x24F0: - return (double) 16; - case 0x16EE: - case 0x2470: - case 0x2484: - case 0x2498: - case 0x24F1: - return (double) 17; - case 0x0F32: - return (double) 17 / 2; - case 0x16EF: - case 0x2471: - case 0x2485: - case 0x2499: - case 0x24F2: - return (double) 18; - case 0x16F0: - case 0x2472: - case 0x2486: - case 0x249A: - case 0x24F3: - return (double) 19; - case 0x09F5: - case 0x17F2: - case 0x2161: - case 0x2171: - case 0x3022: - case 0x3193: - case 0x3221: - case 0x3281: -#ifdef Py_UNICODE_WIDE - case 0x10108: - case 0x1015B: - case 0x1015C: - case 0x1015D: - case 0x1015E: - case 0x103D2: -#endif - return (double) 2; - case 0x2154: -#ifdef Py_UNICODE_WIDE - case 0x10177: -#endif - return (double) 2 / 3; - case 0x2156: - return (double) 2 / 5; - case 0x1373: - case 0x2473: - case 0x2487: - case 0x249B: - case 0x24F4: - case 0x3039: -#ifdef Py_UNICODE_WIDE - case 0x10111: - case 0x103D4: - case 0x10A45: -#endif - return (double) 20; -#ifdef Py_UNICODE_WIDE - case 0x1011A: - return (double) 200; - case 0x10123: - return (double) 2000; - case 0x1012C: - return (double) 20000; -#endif - case 0x3251: - return (double) 21; - case 0x3252: - return (double) 22; - case 0x3253: - return (double) 23; - case 0x3254: - return (double) 24; - case 0x3255: - return (double) 25; - case 0x3256: - return (double) 26; - case 0x3257: - return (double) 27; - case 0x3258: - return (double) 28; - case 0x3259: - return (double) 29; - case 0x09F6: - case 0x17F3: - case 0x2162: - case 0x2172: - case 0x3023: - case 0x3194: - case 0x3222: - case 0x3282: -#ifdef Py_UNICODE_WIDE - case 0x10109: -#endif - return (double) 3; - case 0x0F2B: - return (double) 3 / 2; - case 0x00BE: -#ifdef Py_UNICODE_WIDE - case 0x10178: -#endif - return (double) 3 / 4; - case 0x2157: - return (double) 3 / 5; - case 0x215C: - return (double) 3 / 8; - case 0x1374: - case 0x303A: - case 0x325A: -#ifdef Py_UNICODE_WIDE - case 0x10112: - case 0x10165: -#endif - return (double) 30; -#ifdef Py_UNICODE_WIDE - case 0x1011B: - case 0x1016B: - return (double) 300; - case 0x10124: - return (double) 3000; - case 0x1012D: - return (double) 30000; -#endif - case 0x325B: - return (double) 31; - case 0x325C: - return (double) 32; - case 0x325D: - return (double) 33; - case 0x325E: - return (double) 34; - case 0x325F: - return (double) 35; - case 0x32B1: - return (double) 36; - case 0x32B2: - return (double) 37; - case 0x32B3: - return (double) 38; - case 0x32B4: - return (double) 39; - case 0x09F7: - case 0x17F4: - case 0x2163: - case 0x2173: - case 0x3024: - case 0x3195: - case 0x3223: - case 0x3283: -#ifdef Py_UNICODE_WIDE - case 0x1010A: -#endif - return (double) 4; - case 0x2158: - return (double) 4 / 5; - case 0x1375: - case 0x32B5: -#ifdef Py_UNICODE_WIDE - case 0x10113: -#endif - return (double) 40; -#ifdef Py_UNICODE_WIDE - case 0x1011C: - return (double) 400; - case 0x10125: - return (double) 4000; - case 0x1012E: - return (double) 40000; -#endif - case 0x32B6: - return (double) 41; - case 0x32B7: - return (double) 42; - case 0x32B8: - return (double) 43; - case 0x32B9: - return (double) 44; - case 0x32BA: - return (double) 45; - case 0x32BB: - return (double) 46; - case 0x32BC: - return (double) 47; - case 0x32BD: - return (double) 48; - case 0x32BE: - return (double) 49; - case 0x17F5: - case 0x2164: - case 0x2174: - case 0x3025: - case 0x3224: - case 0x3284: -#ifdef Py_UNICODE_WIDE - case 0x1010B: - case 0x10143: - case 0x10148: - case 0x1014F: - case 0x1015F: - case 0x10173: - case 0x10321: -#endif - return (double) 5; - case 0x0F2C: - return (double) 5 / 2; - case 0x215A: - return (double) 5 / 6; - case 0x215D: - return (double) 5 / 8; - case 0x1376: - case 0x216C: - case 0x217C: - case 0x32BF: -#ifdef Py_UNICODE_WIDE - case 0x10114: - case 0x10144: - case 0x1014A: - case 0x10151: - case 0x10166: - case 0x10167: - case 0x10168: - case 0x10169: - case 0x10174: - case 0x10323: -#endif - return (double) 50; - case 0x216E: - case 0x217E: -#ifdef Py_UNICODE_WIDE - case 0x1011D: - case 0x10145: - case 0x1014C: - case 0x10153: - case 0x1016C: - case 0x1016D: - case 0x1016E: - case 0x1016F: - case 0x10170: -#endif - return (double) 500; - case 0x2181: -#ifdef Py_UNICODE_WIDE - case 0x10126: - case 0x10146: - case 0x1014E: - case 0x10172: -#endif - return (double) 5000; -#ifdef Py_UNICODE_WIDE - case 0x1012F: - case 0x10147: - case 0x10156: - return (double) 50000; -#endif - case 0x17F6: - case 0x2165: - case 0x2175: - case 0x3026: - case 0x3225: - case 0x3285: -#ifdef Py_UNICODE_WIDE - case 0x1010C: -#endif - return (double) 6; - case 0x1377: -#ifdef Py_UNICODE_WIDE - case 0x10115: -#endif - return (double) 60; -#ifdef Py_UNICODE_WIDE - case 0x1011E: - return (double) 600; - case 0x10127: - return (double) 6000; - case 0x10130: - return (double) 60000; -#endif - case 0x17F7: - case 0x2166: - case 0x2176: - case 0x3027: - case 0x3226: - case 0x3286: -#ifdef Py_UNICODE_WIDE - case 0x1010D: -#endif - return (double) 7; - case 0x0F2D: - return (double) 7 / 2; - case 0x215E: - return (double) 7 / 8; - case 0x1378: -#ifdef Py_UNICODE_WIDE - case 0x10116: -#endif - return (double) 70; -#ifdef Py_UNICODE_WIDE - case 0x1011F: - return (double) 700; - case 0x10128: - return (double) 7000; - case 0x10131: - return (double) 70000; -#endif - case 0x17F8: - case 0x2167: - case 0x2177: - case 0x3028: - case 0x3227: - case 0x3287: -#ifdef Py_UNICODE_WIDE - case 0x1010E: -#endif - return (double) 8; - case 0x1379: -#ifdef Py_UNICODE_WIDE - case 0x10117: -#endif - return (double) 80; -#ifdef Py_UNICODE_WIDE - case 0x10120: - return (double) 800; - case 0x10129: - return (double) 8000; - case 0x10132: - return (double) 80000; -#endif - case 0x17F9: - case 0x2168: - case 0x2178: - case 0x3029: - case 0x3228: - case 0x3288: -#ifdef Py_UNICODE_WIDE - case 0x1010F: -#endif - return (double) 9; - case 0x0F2E: - return (double) 9 / 2; - case 0x137A: -#ifdef Py_UNICODE_WIDE - case 0x10118: -#endif - return (double) 90; -#ifdef Py_UNICODE_WIDE - case 0x10121: - case 0x1034A: - return (double) 900; - case 0x1012A: - return (double) 9000; - case 0x10133: - return (double) 90000; -#endif - default: - return (double) _PyUnicode_ToDigit(ch); - } -} + const _PyUnicode_TypeRecord *ctype = gettyperecord(ch); -int _PyUnicode_IsNumeric(Py_UNICODE ch) -{ - return _PyUnicode_ToNumeric(ch) != -1.0; + return (ctype->flags & NUMERIC_MASK) != 0; } /* Returns 1 for Unicode characters to be hex-escaped when repr()ed, @@ -688,61 +155,17 @@ int _PyUnicode_IsNumeric(Py_UNICODE ch) * Zp Separator, Paragraph ('\u2029', PARAGRAPH SEPARATOR) * Zs (Separator, Space) other than ASCII space('\x20'). */ -int _PyUnicode_IsPrintable(Py_UNICODE ch) +int _PyUnicode_IsPrintable(Py_UCS4 ch) { const _PyUnicode_TypeRecord *ctype = gettyperecord(ch); return (ctype->flags & PRINTABLE_MASK) != 0; } -#ifndef WANT_WCTYPE_FUNCTIONS - -/* Returns 1 for Unicode characters having the bidirectional type - 'WS', 'B' or 'S' or the category 'Zs', 0 otherwise. */ - -int _PyUnicode_IsWhitespace(register const Py_UNICODE ch) -{ - switch (ch) { - case 0x0009: /* HORIZONTAL TABULATION */ - case 0x000A: /* LINE FEED */ - case 0x000B: /* VERTICAL TABULATION */ - case 0x000C: /* FORM FEED */ - case 0x000D: /* CARRIAGE RETURN */ - case 0x001C: /* FILE SEPARATOR */ - case 0x001D: /* GROUP SEPARATOR */ - case 0x001E: /* RECORD SEPARATOR */ - case 0x001F: /* UNIT SEPARATOR */ - case 0x0020: /* SPACE */ - case 0x0085: /* NEXT LINE */ - case 0x00A0: /* NO-BREAK SPACE */ - case 0x1680: /* OGHAM SPACE MARK */ - case 0x2000: /* EN QUAD */ - case 0x2001: /* EM QUAD */ - case 0x2002: /* EN SPACE */ - case 0x2003: /* EM SPACE */ - case 0x2004: /* THREE-PER-EM SPACE */ - case 0x2005: /* FOUR-PER-EM SPACE */ - case 0x2006: /* SIX-PER-EM SPACE */ - case 0x2007: /* FIGURE SPACE */ - case 0x2008: /* PUNCTUATION SPACE */ - case 0x2009: /* THIN SPACE */ - case 0x200A: /* HAIR SPACE */ - case 0x200B: /* ZERO WIDTH SPACE */ - case 0x2028: /* LINE SEPARATOR */ - case 0x2029: /* PARAGRAPH SEPARATOR */ - case 0x202F: /* NARROW NO-BREAK SPACE */ - case 0x205F: /* MEDIUM MATHEMATICAL SPACE */ - case 0x3000: /* IDEOGRAPHIC SPACE */ - return 1; - default: - return 0; - } -} - /* Returns 1 for Unicode characters having the category 'Ll', 0 otherwise. */ -int _PyUnicode_IsLowercase(Py_UNICODE ch) +int _PyUnicode_IsLowercase(Py_UCS4 ch) { const _PyUnicode_TypeRecord *ctype = gettyperecord(ch); @@ -752,7 +175,7 @@ int _PyUnicode_IsLowercase(Py_UNICODE ch) /* Returns 1 for Unicode characters having the category 'Lu', 0 otherwise. */ -int _PyUnicode_IsUppercase(Py_UNICODE ch) +int _PyUnicode_IsUppercase(Py_UCS4 ch) { const _PyUnicode_TypeRecord *ctype = gettyperecord(ch); @@ -762,7 +185,7 @@ int _PyUnicode_IsUppercase(Py_UNICODE ch) /* Returns the uppercase Unicode characters corresponding to ch or just ch if no uppercase mapping is known. */ -Py_UNICODE _PyUnicode_ToUppercase(Py_UNICODE ch) +Py_UCS4 _PyUnicode_ToUppercase(Py_UCS4 ch) { const _PyUnicode_TypeRecord *ctype = gettyperecord(ch); int delta = ctype->upper; @@ -776,7 +199,7 @@ Py_UNICODE _PyUnicode_ToUppercase(Py_UNICODE ch) /* Returns the lowercase Unicode characters corresponding to ch or just ch if no lowercase mapping is known. */ -Py_UNICODE _PyUnicode_ToLowercase(Py_UNICODE ch) +Py_UCS4 _PyUnicode_ToLowercase(Py_UCS4 ch) { const _PyUnicode_TypeRecord *ctype = gettyperecord(ch); int delta = ctype->lower; @@ -790,46 +213,10 @@ Py_UNICODE _PyUnicode_ToLowercase(Py_UNICODE ch) /* Returns 1 for Unicode characters having the category 'Ll', 'Lu', 'Lt', 'Lo' or 'Lm', 0 otherwise. */ -int _PyUnicode_IsAlpha(Py_UNICODE ch) +int _PyUnicode_IsAlpha(Py_UCS4 ch) { const _PyUnicode_TypeRecord *ctype = gettyperecord(ch); return (ctype->flags & ALPHA_MASK) != 0; } -#else - -/* Export the interfaces using the wchar_t type for portability - reasons: */ - -int _PyUnicode_IsWhitespace(Py_UNICODE ch) -{ - return iswspace(ch); -} - -int _PyUnicode_IsLowercase(Py_UNICODE ch) -{ - return iswlower(ch); -} - -int _PyUnicode_IsUppercase(Py_UNICODE ch) -{ - return iswupper(ch); -} - -Py_UNICODE _PyUnicode_ToLowercase(Py_UNICODE ch) -{ - return towlower(ch); -} - -Py_UNICODE _PyUnicode_ToUppercase(Py_UNICODE ch) -{ - return towupper(ch); -} - -int _PyUnicode_IsAlpha(Py_UNICODE ch) -{ - return iswalpha(ch); -} - -#endif diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 2cdbc0e..7a70a5e 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -41,9 +41,6 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #define PY_SSIZE_T_CLEAN #include "Python.h" -#include "bytes_methods.h" - -#include "unicodeobject.h" #include "ucnhash.h" #ifdef MS_WINDOWS @@ -114,21 +111,12 @@ static PyUnicodeObject *unicode_empty; shared as well. */ static PyUnicodeObject *unicode_latin1[256]; -/* Default encoding to use and assume when NULL is passed as encoding - parameter; it is fixed to "utf-8". Always use the - PyUnicode_GetDefaultEncoding() API to access this global. - - Don't forget to alter Py_FileSystemDefaultEncoding if you change the - hard coded default! -*/ -static const char unicode_default_encoding[] = "utf-8"; - /* Fast detection of the most frequent whitespace characters */ const unsigned char _Py_ascii_whitespace[] = { 0, 0, 0, 0, 0, 0, 0, 0, -/* case 0x0009: * HORIZONTAL TABULATION */ +/* case 0x0009: * CHARACTER TABULATION */ /* case 0x000A: * LINE FEED */ -/* case 0x000B: * VERTICAL TABULATION */ +/* case 0x000B: * LINE TABULATION */ /* case 0x000C: * FORM FEED */ /* case 0x000D: * CARRIAGE RETURN */ 0, 1, 1, 1, 1, 1, 0, 0, @@ -169,8 +157,10 @@ static void raise_encode_exception(PyObject **exceptionObject, static unsigned char ascii_linebreak[] = { 0, 0, 0, 0, 0, 0, 0, 0, /* 0x000A, * LINE FEED */ +/* 0x000B, * LINE TABULATION */ +/* 0x000C, * FORM FEED */ /* 0x000D, * CARRIAGE RETURN */ - 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x001C, * FILE SEPARATOR */ /* 0x001D, * GROUP SEPARATOR */ @@ -212,11 +202,22 @@ PyUnicode_GetMax(void) /* the linebreak mask is set up by Unicode_Init below */ +#if LONG_BIT >= 128 +#define BLOOM_WIDTH 128 +#elif LONG_BIT >= 64 +#define BLOOM_WIDTH 64 +#elif LONG_BIT >= 32 +#define BLOOM_WIDTH 32 +#else +#error "LONG_BIT is smaller than 32" +#endif + #define BLOOM_MASK unsigned long static BLOOM_MASK bloom_linebreak; -#define BLOOM(mask, ch) ((mask & (1 << ((ch) & 0x1F)))) +#define BLOOM_ADD(mask, ch) ((mask |= (1UL << ((ch) & (BLOOM_WIDTH - 1))))) +#define BLOOM(mask, ch) ((mask & (1UL << ((ch) & (BLOOM_WIDTH - 1))))) #define BLOOM_LINEBREAK(ch) \ ((ch) < 128U ? ascii_linebreak[(ch)] : \ @@ -226,12 +227,12 @@ Py_LOCAL_INLINE(BLOOM_MASK) make_bloom_mask(Py_UNICODE* ptr, Py_ssize_t len) { /* calculate simple bloom-style bitmask for a given unicode string */ - long mask; + BLOOM_MASK mask; Py_ssize_t i; mask = 0; for (i = 0; i < len; i++) - mask |= (1 << (ptr[i] & 0x1F)); + BLOOM_ADD(mask, ptr[i]); return mask; } @@ -651,7 +652,7 @@ PyObject *PyUnicode_FromWideChar(register const wchar_t *w, return NULL; /* Copy the wchar_t data into the new object */ -#ifdef HAVE_USABLE_WCHAR_T +#if Py_UNICODE_SIZE == SIZEOF_WCHAR_T memcpy(unicode->str, w, size * sizeof(wchar_t)); #else { @@ -671,7 +672,8 @@ PyObject *PyUnicode_FromWideChar(register const wchar_t *w, #undef CONVERT_WCHAR_TO_SURROGATES static void -makefmt(char *fmt, int longflag, int size_tflag, int zeropad, int width, int precision, char c) +makefmt(char *fmt, int longflag, int longlongflag, int size_tflag, + int zeropad, int width, int precision, char c) { *fmt++ = '%'; if (width) { @@ -683,6 +685,19 @@ makefmt(char *fmt, int longflag, int size_tflag, int zeropad, int width, int pre fmt += sprintf(fmt, ".%d", precision); if (longflag) *fmt++ = 'l'; + else if (longlongflag) { + /* longlongflag should only ever be nonzero on machines with + HAVE_LONG_LONG defined */ +#ifdef HAVE_LONG_LONG + char *f = PY_FORMAT_LONG_LONG; + while (*f) + *fmt++ = *f++; +#else + /* we shouldn't ever get here */ + assert(0); + *fmt++ = 'l'; +#endif + } else if (size_tflag) { char *f = PY_FORMAT_SIZE_T; while (*f) @@ -694,6 +709,16 @@ makefmt(char *fmt, int longflag, int size_tflag, int zeropad, int width, int pre #define appendstring(string) {for (copy = string;*copy;) *s++ = *copy++;} +/* size of fixed-size buffer for formatting single arguments */ +#define ITEM_BUFFER_LEN 21 +/* maximum number of characters required for output of %ld. 21 characters + allows for 64-bit integers (in decimal) and an optional sign. */ +#define MAX_LONG_CHARS 21 +/* maximum number of characters required for output of %lld. + We need at most ceil(log10(256)*SIZEOF_LONG_LONG) digits, + plus 1 for the sign. 53/22 is an upper bound for log10(256). */ +#define MAX_LONG_LONG_CHARS (2 + (SIZEOF_LONG_LONG*53-1) / 22) + PyObject * PyUnicode_FromFormatV(const char *format, va_list vargs) { @@ -709,24 +734,16 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) Py_UNICODE *s; PyObject *string; /* used by sprintf */ - char buffer[21]; + char buffer[ITEM_BUFFER_LEN+1]; /* use abuffer instead of buffer, if we need more space * (which can happen if there's a format specifier with width). */ char *abuffer = NULL; char *realbuffer; Py_ssize_t abuffersize = 0; - char fmt[60]; /* should be enough for %0width.precisionld */ + char fmt[61]; /* should be enough for %0width.precisionlld */ const char *copy; -#ifdef VA_LIST_IS_ARRAY - Py_MEMCPY(count, vargs, sizeof(va_list)); -#else -#ifdef __va_copy - __va_copy(count, vargs); -#else - count = vargs; -#endif -#endif + Py_VA_COPY(count, vargs); /* step 1: count the number of %S/%R/%A/%s format specifications * (we call PyObject_Str()/PyObject_Repr()/PyObject_ASCII()/ * PyUnicode_DecodeUTF8() for these objects once during step 3 and put the @@ -735,15 +752,22 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) if (*f == '%') { if (*(f+1)=='%') continue; - if (*(f+1)=='S' || *(f+1)=='R' || *(f+1)=='A') + if (*(f+1)=='S' || *(f+1)=='R' || *(f+1)=='A' || *(f+1) == 'V') ++callcount; - while (ISDIGIT((unsigned)*f)) + while (Py_ISDIGIT((unsigned)*f)) width = (width*10) + *f++ - '0'; - while (*++f && *f != '%' && !ISALPHA((unsigned)*f)) + while (*++f && *f != '%' && !Py_ISALPHA((unsigned)*f)) ; if (*f == 's') ++callcount; } + else if (128 <= (unsigned char)*f) { + PyErr_Format(PyExc_ValueError, + "PyUnicode_FromFormatV() expects an ASCII-encoded format " + "string, got a non-ASCII byte: 0x%02x", + (unsigned char)*f); + return NULL; + } } /* step 2: allocate memory for the results of * PyObject_Str()/PyObject_Repr()/PyUnicode_DecodeUTF8() calls */ @@ -758,37 +782,70 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) /* step 3: figure out how large a buffer we need */ for (f = format; *f; f++) { if (*f == '%') { +#ifdef HAVE_LONG_LONG + int longlongflag = 0; +#endif const char* p = f; width = 0; - while (ISDIGIT((unsigned)*f)) + while (Py_ISDIGIT((unsigned)*f)) width = (width*10) + *f++ - '0'; - while (*++f && *f != '%' && !ISALPHA((unsigned)*f)) + while (*++f && *f != '%' && !Py_ISALPHA((unsigned)*f)) ; /* skip the 'l' or 'z' in {%ld, %zd, %lu, %zu} since * they don't affect the amount of space we reserve. */ - if ((*f == 'l' || *f == 'z') && - (f[1] == 'd' || f[1] == 'u')) + if (*f == 'l') { + if (f[1] == 'd' || f[1] == 'u') { + ++f; + } +#ifdef HAVE_LONG_LONG + else if (f[1] == 'l' && + (f[2] == 'd' || f[2] == 'u')) { + longlongflag = 1; + f += 2; + } +#endif + } + else if (*f == 'z' && (f[1] == 'd' || f[1] == 'u')) { ++f; + } switch (*f) { case 'c': + { +#ifndef Py_UNICODE_WIDE + int ordinal = va_arg(count, int); + if (ordinal > 0xffff) + n += 2; + else + n++; +#else (void)va_arg(count, int); - /* fall through... */ + n++; +#endif + break; + } case '%': n++; break; case 'd': case 'u': case 'i': case 'x': (void) va_arg(count, int); - /* 20 bytes is enough to hold a 64-bit - integer. Decimal takes the most space. - This isn't enough for octal. - If a width is specified we need more - (which we allocate later). */ - if (width < 20) - width = 20; +#ifdef HAVE_LONG_LONG + if (longlongflag) { + if (width < MAX_LONG_LONG_CHARS) + width = MAX_LONG_LONG_CHARS; + } + else +#endif + /* MAX_LONG_CHARS is enough to hold a 64-bit integer, + including sign. Decimal takes the most space. This + isn't enough for octal. If a width is specified we + need more (which we allocate later). */ + if (width < MAX_LONG_CHARS) + width = MAX_LONG_CHARS; n += width; + /* XXX should allow for large precision here too. */ if (abuffersize < width) abuffersize = width; break; @@ -815,12 +872,20 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) { PyObject *obj = va_arg(count, PyObject *); const char *str = va_arg(count, const char *); + PyObject *str_obj; assert(obj || str); assert(!obj || PyUnicode_Check(obj)); - if (obj) + if (obj) { n += PyUnicode_GET_SIZE(obj); - else - n += strlen(str); + *callresult++ = NULL; + } + else { + str_obj = PyUnicode_DecodeUTF8(str, strlen(str), "replace"); + if (!str_obj) + goto fail; + n += PyUnicode_GET_SIZE(str_obj); + *callresult++ = str_obj; + } break; } case 'S': @@ -885,8 +950,9 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) n++; } expand: - if (abuffersize > 20) { - abuffer = PyObject_Malloc(abuffersize); + if (abuffersize > ITEM_BUFFER_LEN) { + /* add 1 for sprintf's trailing null byte */ + abuffer = PyObject_Malloc(abuffersize + 1); if (!abuffer) { PyErr_NoMemory(); goto fail; @@ -910,23 +976,32 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) if (*f == '%') { const char* p = f++; int longflag = 0; + int longlongflag = 0; int size_tflag = 0; zeropad = (*f == '0'); /* parse the width.precision part */ width = 0; - while (ISDIGIT((unsigned)*f)) + while (Py_ISDIGIT((unsigned)*f)) width = (width*10) + *f++ - '0'; precision = 0; if (*f == '.') { f++; - while (ISDIGIT((unsigned)*f)) + while (Py_ISDIGIT((unsigned)*f)) precision = (precision*10) + *f++ - '0'; } - /* handle the long flag, but only for %ld and %lu. - others can be added when necessary. */ - if (*f == 'l' && (f[1] == 'd' || f[1] == 'u')) { - longflag = 1; - ++f; + /* Handle %ld, %lu, %lld and %llu. */ + if (*f == 'l') { + if (f[1] == 'd' || f[1] == 'u') { + longflag = 1; + ++f; + } +#ifdef HAVE_LONG_LONG + else if (f[1] == 'l' && + (f[2] == 'd' || f[2] == 'u')) { + longlongflag = 1; + f += 2; + } +#endif } /* handle the size_t flag. */ if (*f == 'z' && (f[1] == 'd' || f[1] == 'u')) { @@ -936,12 +1011,27 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) switch (*f) { case 'c': - *s++ = va_arg(vargs, int); + { + int ordinal = va_arg(vargs, int); +#ifndef Py_UNICODE_WIDE + if (ordinal > 0xffff) { + ordinal -= 0x10000; + *s++ = 0xD800 | (ordinal >> 10); + *s++ = 0xDC00 | (ordinal & 0x3FF); + } else +#endif + *s++ = ordinal; break; + } case 'd': - makefmt(fmt, longflag, size_tflag, zeropad, width, precision, 'd'); + makefmt(fmt, longflag, longlongflag, size_tflag, zeropad, + width, precision, 'd'); if (longflag) sprintf(realbuffer, fmt, va_arg(vargs, long)); +#ifdef HAVE_LONG_LONG + else if (longlongflag) + sprintf(realbuffer, fmt, va_arg(vargs, PY_LONG_LONG)); +#endif else if (size_tflag) sprintf(realbuffer, fmt, va_arg(vargs, Py_ssize_t)); else @@ -949,9 +1039,15 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) appendstring(realbuffer); break; case 'u': - makefmt(fmt, longflag, size_tflag, zeropad, width, precision, 'u'); + makefmt(fmt, longflag, longlongflag, size_tflag, zeropad, + width, precision, 'u'); if (longflag) sprintf(realbuffer, fmt, va_arg(vargs, unsigned long)); +#ifdef HAVE_LONG_LONG + else if (longlongflag) + sprintf(realbuffer, fmt, va_arg(vargs, + unsigned PY_LONG_LONG)); +#endif else if (size_tflag) sprintf(realbuffer, fmt, va_arg(vargs, size_t)); else @@ -959,12 +1055,12 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) appendstring(realbuffer); break; case 'i': - makefmt(fmt, 0, 0, zeropad, width, precision, 'i'); + makefmt(fmt, 0, 0, 0, zeropad, width, precision, 'i'); sprintf(realbuffer, fmt, va_arg(vargs, int)); appendstring(realbuffer); break; case 'x': - makefmt(fmt, 0, 0, zeropad, width, precision, 'x'); + makefmt(fmt, 0, 0, 0, zeropad, width, precision, 'x'); sprintf(realbuffer, fmt, va_arg(vargs, int)); appendstring(realbuffer); break; @@ -992,18 +1088,23 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) case 'V': { PyObject *obj = va_arg(vargs, PyObject *); - const char *str = va_arg(vargs, const char *); + va_arg(vargs, const char *); if (obj) { Py_ssize_t size = PyUnicode_GET_SIZE(obj); Py_UNICODE_COPY(s, PyUnicode_AS_UNICODE(obj), size); s += size; } else { - appendstring(str); + Py_UNICODE_COPY(s, PyUnicode_AS_UNICODE(*callresult), + PyUnicode_GET_SIZE(*callresult)); + s += PyUnicode_GET_SIZE(*callresult); + Py_DECREF(*callresult); } + ++callresult; break; } case 'S': case 'R': + case 'A': { Py_UNICODE *ucopy; Py_ssize_t usize; @@ -1039,7 +1140,8 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) appendstring(p); goto end; } - } else + } + else *s++ = *f; } @@ -1054,7 +1156,7 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) if (callresults) { PyObject **callresult2 = callresults; while (callresult2 < callresult) { - Py_DECREF(*callresult2); + Py_XDECREF(*callresult2); ++callresult2; } PyObject_Free(callresults); @@ -1082,35 +1184,154 @@ PyUnicode_FromFormat(const char *format, ...) return ret; } -Py_ssize_t PyUnicode_AsWideChar(PyUnicodeObject *unicode, - wchar_t *w, - Py_ssize_t size) +/* Helper function for PyUnicode_AsWideChar() and PyUnicode_AsWideCharString(): + convert a Unicode object to a wide character string. + + - If w is NULL: return the number of wide characters (including the nul + character) required to convert the unicode object. Ignore size argument. + + - Otherwise: return the number of wide characters (excluding the nul + character) written into w. Write at most size wide characters (including + the nul character). */ +static Py_ssize_t +unicode_aswidechar(PyUnicodeObject *unicode, + wchar_t *w, + Py_ssize_t size) +{ +#if Py_UNICODE_SIZE == SIZEOF_WCHAR_T + Py_ssize_t res; + if (w != NULL) { + res = PyUnicode_GET_SIZE(unicode); + if (size > res) + size = res + 1; + else + res = size; + memcpy(w, unicode->str, size * sizeof(wchar_t)); + return res; + } + else + return PyUnicode_GET_SIZE(unicode) + 1; +#elif Py_UNICODE_SIZE == 2 && SIZEOF_WCHAR_T == 4 + register const Py_UNICODE *u; + const Py_UNICODE *uend; + const wchar_t *worig, *wend; + Py_ssize_t nchar; + + u = PyUnicode_AS_UNICODE(unicode); + uend = u + PyUnicode_GET_SIZE(unicode); + if (w != NULL) { + worig = w; + wend = w + size; + while (u != uend && w != wend) { + if (0xD800 <= u[0] && u[0] <= 0xDBFF + && 0xDC00 <= u[1] && u[1] <= 0xDFFF) + { + *w = (((u[0] & 0x3FF) << 10) | (u[1] & 0x3FF)) + 0x10000; + u += 2; + } + else { + *w = *u; + u++; + } + w++; + } + if (w != wend) + *w = L'\0'; + return w - worig; + } + else { + nchar = 1; /* nul character at the end */ + while (u != uend) { + if (0xD800 <= u[0] && u[0] <= 0xDBFF + && 0xDC00 <= u[1] && u[1] <= 0xDFFF) + u += 2; + else + u++; + nchar++; + } + } + return nchar; +#elif Py_UNICODE_SIZE == 4 && SIZEOF_WCHAR_T == 2 + register Py_UNICODE *u, *uend, ordinal; + register Py_ssize_t i; + wchar_t *worig, *wend; + Py_ssize_t nchar; + + u = PyUnicode_AS_UNICODE(unicode); + uend = u + PyUnicode_GET_SIZE(u); + if (w != NULL) { + worig = w; + wend = w + size; + while (u != uend && w != wend) { + ordinal = *u; + if (ordinal > 0xffff) { + ordinal -= 0x10000; + *w++ = 0xD800 | (ordinal >> 10); + *w++ = 0xDC00 | (ordinal & 0x3FF); + } + else + *w++ = ordinal; + u++; + } + if (w != wend) + *w = 0; + return w - worig; + } + else { + nchar = 1; /* nul character */ + while (u != uend) { + if (*u > 0xffff) + nchar += 2; + else + nchar++; + u++; + } + return nchar; + } +#else +# error "unsupported wchar_t and Py_UNICODE sizes, see issue #8670" +#endif +} + +Py_ssize_t +PyUnicode_AsWideChar(PyObject *unicode, + wchar_t *w, + Py_ssize_t size) { if (unicode == NULL) { PyErr_BadInternalCall(); return -1; } + return unicode_aswidechar((PyUnicodeObject*)unicode, w, size); +} - /* If possible, try to copy the 0-termination as well */ - if (size > PyUnicode_GET_SIZE(unicode)) - size = PyUnicode_GET_SIZE(unicode) + 1; +wchar_t* +PyUnicode_AsWideCharString(PyObject *unicode, + Py_ssize_t *size) +{ + wchar_t* buffer; + Py_ssize_t buflen; -#ifdef HAVE_USABLE_WCHAR_T - memcpy(w, unicode->str, size * sizeof(wchar_t)); -#else - { - register Py_UNICODE *u; - register Py_ssize_t i; - u = PyUnicode_AS_UNICODE(unicode); - for (i = size; i > 0; i--) - *w++ = *u++; + if (unicode == NULL) { + PyErr_BadInternalCall(); + return NULL; } -#endif - if (size > PyUnicode_GET_SIZE(unicode)) - return PyUnicode_GET_SIZE(unicode); - else - return size; + buflen = unicode_aswidechar((PyUnicodeObject *)unicode, NULL, 0); + if (PY_SSIZE_T_MAX / sizeof(wchar_t) < buflen) { + PyErr_NoMemory(); + return NULL; + } + + buffer = PyMem_MALLOC(buflen * sizeof(wchar_t)); + if (buffer == NULL) { + PyErr_NoMemory(); + return NULL; + } + buflen = unicode_aswidechar((PyUnicodeObject *)unicode, buffer, buflen); + if (size != NULL) + *size = buflen; + return buffer; } #endif @@ -1210,27 +1431,26 @@ PyObject *PyUnicode_FromEncodedObject(register PyObject *obj, return v; } -PyObject *PyUnicode_Decode(const char *s, - Py_ssize_t size, - const char *encoding, - const char *errors) +/* Convert encoding to lower case and replace '_' with '-' in order to + catch e.g. UTF_8. Return 0 on error (encoding is longer than lower_len-1), + 1 on success. */ +static int +normalize_encoding(const char *encoding, + char *lower, + size_t lower_len) { - PyObject *buffer = NULL, *unicode; - Py_buffer info; - char lower[20]; /* Enough for any encoding name we recognize */ - char *l; const char *e; + char *l; + char *l_end; - if (encoding == NULL) - encoding = PyUnicode_GetDefaultEncoding(); - - /* Convert encoding to lower case and replace '_' with '-' in order to - catch e.g. UTF_8 */ e = encoding; l = lower; - while (*e && l < &lower[(sizeof lower) - 2]) { - if (ISUPPER(*e)) { - *l++ = TOLOWER(*e++); + l_end = &lower[lower_len - 1]; + while (*e) { + if (l == l_end) + return 0; + if (Py_ISUPPER(*e)) { + *l++ = Py_TOLOWER(*e++); } else if (*e == '_') { *l++ = '-'; @@ -1241,23 +1461,39 @@ PyObject *PyUnicode_Decode(const char *s, } } *l = '\0'; + return 1; +} + +PyObject *PyUnicode_Decode(const char *s, + Py_ssize_t size, + const char *encoding, + const char *errors) +{ + PyObject *buffer = NULL, *unicode; + Py_buffer info; + char lower[11]; /* Enough for any encoding shortcut */ + + if (encoding == NULL) + encoding = PyUnicode_GetDefaultEncoding(); /* Shortcuts for common default encodings */ - if (strcmp(lower, "utf-8") == 0) - return PyUnicode_DecodeUTF8(s, size, errors); - else if ((strcmp(lower, "latin-1") == 0) || - (strcmp(lower, "iso-8859-1") == 0)) - return PyUnicode_DecodeLatin1(s, size, errors); + if (normalize_encoding(encoding, lower, sizeof(lower))) { + if (strcmp(lower, "utf-8") == 0) + return PyUnicode_DecodeUTF8(s, size, errors); + else if ((strcmp(lower, "latin-1") == 0) || + (strcmp(lower, "iso-8859-1") == 0)) + return PyUnicode_DecodeLatin1(s, size, errors); #if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T) - else if (strcmp(lower, "mbcs") == 0) - return PyUnicode_DecodeMBCS(s, size, errors); + else if (strcmp(lower, "mbcs") == 0) + return PyUnicode_DecodeMBCS(s, size, errors); #endif - else if (strcmp(lower, "ascii") == 0) - return PyUnicode_DecodeASCII(s, size, errors); - else if (strcmp(lower, "utf-16") == 0) - return PyUnicode_DecodeUTF16(s, size, errors, 0); - else if (strcmp(lower, "utf-32") == 0) - return PyUnicode_DecodeUTF32(s, size, errors, 0); + else if (strcmp(lower, "ascii") == 0) + return PyUnicode_DecodeASCII(s, size, errors); + else if (strcmp(lower, "utf-16") == 0) + return PyUnicode_DecodeUTF16(s, size, errors, 0); + else if (strcmp(lower, "utf-32") == 0) + return PyUnicode_DecodeUTF32(s, size, errors, 0); + } /* Decode via the codec registry */ buffer = NULL; @@ -1378,11 +1614,77 @@ PyObject *PyUnicode_AsEncodedObject(PyObject *unicode, return NULL; } +PyObject * +PyUnicode_EncodeFSDefault(PyObject *unicode) +{ +#if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T) + return PyUnicode_EncodeMBCS(PyUnicode_AS_UNICODE(unicode), + PyUnicode_GET_SIZE(unicode), + NULL); +#elif defined(__APPLE__) + return PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(unicode), + PyUnicode_GET_SIZE(unicode), + "surrogateescape"); +#else + PyInterpreterState *interp = PyThreadState_GET()->interp; + /* Bootstrap check: if the filesystem codec is implemented in Python, we + cannot use it to encode and decode filenames before it is loaded. Load + the Python codec requires to encode at least its own filename. Use the C + version of the locale codec until the codec registry is initialized and + the Python codec is loaded. + + Py_FileSystemDefaultEncoding is shared between all interpreters, we + cannot only rely on it: check also interp->fscodec_initialized for + subinterpreters. */ + if (Py_FileSystemDefaultEncoding && interp->fscodec_initialized) { + return PyUnicode_AsEncodedString(unicode, + Py_FileSystemDefaultEncoding, + "surrogateescape"); + } + else { + /* locale encoding with surrogateescape */ + wchar_t *wchar; + char *bytes; + PyObject *bytes_obj; + size_t error_pos; + + wchar = PyUnicode_AsWideCharString(unicode, NULL); + if (wchar == NULL) + return NULL; + bytes = _Py_wchar2char(wchar, &error_pos); + if (bytes == NULL) { + if (error_pos != (size_t)-1) { + char *errmsg = strerror(errno); + PyObject *exc = NULL; + if (errmsg == NULL) + errmsg = "Py_wchar2char() failed"; + raise_encode_exception(&exc, + "filesystemencoding", + PyUnicode_AS_UNICODE(unicode), PyUnicode_GET_SIZE(unicode), + error_pos, error_pos+1, + errmsg); + Py_XDECREF(exc); + } + else + PyErr_NoMemory(); + PyMem_Free(wchar); + return NULL; + } + PyMem_Free(wchar); + + bytes_obj = PyBytes_FromString(bytes); + PyMem_Free(bytes); + return bytes_obj; + } +#endif +} + PyObject *PyUnicode_AsEncodedString(PyObject *unicode, const char *encoding, const char *errors) { PyObject *v; + char lower[11]; /* Enough for any encoding shortcut */ if (!PyUnicode_Check(unicode)) { PyErr_BadArgument(); @@ -1393,31 +1695,42 @@ PyObject *PyUnicode_AsEncodedString(PyObject *unicode, encoding = PyUnicode_GetDefaultEncoding(); /* Shortcuts for common default encodings */ - if (errors == NULL) { - if (strcmp(encoding, "utf-8") == 0) - return PyUnicode_AsUTF8String(unicode); - else if (strcmp(encoding, "latin-1") == 0) - return PyUnicode_AsLatin1String(unicode); + if (normalize_encoding(encoding, lower, sizeof(lower))) { + if (strcmp(lower, "utf-8") == 0) + return PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(unicode), + PyUnicode_GET_SIZE(unicode), + errors); + else if ((strcmp(lower, "latin-1") == 0) || + (strcmp(lower, "iso-8859-1") == 0)) + return PyUnicode_EncodeLatin1(PyUnicode_AS_UNICODE(unicode), + PyUnicode_GET_SIZE(unicode), + errors); #if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T) - else if (strcmp(encoding, "mbcs") == 0) - return PyUnicode_AsMBCSString(unicode); + else if (strcmp(lower, "mbcs") == 0) + return PyUnicode_EncodeMBCS(PyUnicode_AS_UNICODE(unicode), + PyUnicode_GET_SIZE(unicode), + errors); #endif - else if (strcmp(encoding, "ascii") == 0) - return PyUnicode_AsASCIIString(unicode); - /* During bootstrap, we may need to find the encodings - package, to load the file system encoding, and require the - file system encoding in order to load the encodings - package. - - Break out of this dependency by assuming that the path to - the encodings module is ASCII-only. XXX could try wcstombs - instead, if the file system encoding is the locale's - encoding. */ - else if (Py_FileSystemDefaultEncoding && - strcmp(encoding, Py_FileSystemDefaultEncoding) == 0 && - !PyThreadState_GET()->interp->codecs_initialized) - return PyUnicode_AsASCIIString(unicode); - } + else if (strcmp(lower, "ascii") == 0) + return PyUnicode_EncodeASCII(PyUnicode_AS_UNICODE(unicode), + PyUnicode_GET_SIZE(unicode), + errors); + } + /* During bootstrap, we may need to find the encodings + package, to load the file system encoding, and require the + file system encoding in order to load the encodings + package. + + Break out of this dependency by assuming that the path to + the encodings module is ASCII-only. XXX could try wcstombs + instead, if the file system encoding is the locale's + encoding. */ + if (Py_FileSystemDefaultEncoding && + strcmp(encoding, Py_FileSystemDefaultEncoding) == 0 && + !PyThreadState_GET()->interp->codecs_initialized) + return PyUnicode_EncodeASCII(PyUnicode_AS_UNICODE(unicode), + PyUnicode_GET_SIZE(unicode), + errors); /* Encode via the codec registry */ v = PyCodec_Encode(unicode, encoding, errors); @@ -1430,12 +1743,13 @@ PyObject *PyUnicode_AsEncodedString(PyObject *unicode, /* If the codec returns a buffer, raise a warning and convert to bytes */ if (PyByteArray_Check(v)) { - char msg[100]; + int error; PyObject *b; - PyOS_snprintf(msg, sizeof(msg), - "encoder %s returned buffer instead of bytes", - encoding); - if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) { + + error = PyErr_WarnFormat(PyExc_RuntimeWarning, 1, + "encoder %s returned bytearray instead of bytes", + encoding); + if (error) { Py_DECREF(v); return NULL; } @@ -1509,32 +1823,48 @@ PyUnicode_DecodeFSDefault(const char *s) { PyObject* PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size) { - /* During the early bootstrapping process, Py_FileSystemDefaultEncoding - can be undefined. If it is case, decode using UTF-8. The following assumes - that Py_FileSystemDefaultEncoding is set to a built-in encoding during the - bootstrapping process where the codecs aren't ready yet. - */ - if (Py_FileSystemDefaultEncoding) { #if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T) - if (strcmp(Py_FileSystemDefaultEncoding, "mbcs") == 0) { - return PyUnicode_DecodeMBCS(s, size, "replace"); - } + return PyUnicode_DecodeMBCS(s, size, NULL); #elif defined(__APPLE__) - if (strcmp(Py_FileSystemDefaultEncoding, "utf-8") == 0) { - return PyUnicode_DecodeUTF8(s, size, "replace"); - } -#endif + return PyUnicode_DecodeUTF8(s, size, "surrogateescape"); +#else + PyInterpreterState *interp = PyThreadState_GET()->interp; + /* Bootstrap check: if the filesystem codec is implemented in Python, we + cannot use it to encode and decode filenames before it is loaded. Load + the Python codec requires to encode at least its own filename. Use the C + version of the locale codec until the codec registry is initialized and + the Python codec is loaded. + + Py_FileSystemDefaultEncoding is shared between all interpreters, we + cannot only rely on it: check also interp->fscodec_initialized for + subinterpreters. */ + if (Py_FileSystemDefaultEncoding && interp->fscodec_initialized) { return PyUnicode_Decode(s, size, Py_FileSystemDefaultEncoding, - "replace"); + "surrogateescape"); } else { - return PyUnicode_DecodeUTF8(s, size, "replace"); + /* locale encoding with surrogateescape */ + wchar_t *wchar; + PyObject *unicode; + size_t len; + + if (s[size] != '\0' || size != strlen(s)) { + PyErr_SetString(PyExc_TypeError, "embedded NUL character"); + return NULL; + } + + wchar = _Py_char2wchar(s, &len); + if (wchar == NULL) + return PyErr_NoMemory(); + + unicode = PyUnicode_FromWideChar(wchar, len); + PyMem_Free(wchar); + return unicode; } +#endif } -/* Convert the argument to a bytes object, according to the file - system encoding */ int PyUnicode_FSConverter(PyObject* arg, void* addr) @@ -1546,7 +1876,7 @@ PyUnicode_FSConverter(PyObject* arg, void* addr) Py_DECREF(*(PyObject**)addr); return 1; } - if (PyBytes_Check(arg) || PyByteArray_Check(arg)) { + if (PyBytes_Check(arg)) { output = arg; Py_INCREF(output); } @@ -1554,9 +1884,7 @@ PyUnicode_FSConverter(PyObject* arg, void* addr) arg = PyUnicode_FromObject(arg); if (!arg) return 0; - output = PyUnicode_AsEncodedObject(arg, - Py_FileSystemDefaultEncoding, - "surrogateescape"); + output = PyUnicode_EncodeFSDefault(arg); Py_DECREF(arg); if (!output) return 0; @@ -1566,15 +1894,50 @@ PyUnicode_FSConverter(PyObject* arg, void* addr) return 0; } } - if (PyBytes_Check(output)) { - size = PyBytes_GET_SIZE(output); - data = PyBytes_AS_STRING(output); + size = PyBytes_GET_SIZE(output); + data = PyBytes_AS_STRING(output); + if (size != strlen(data)) { + PyErr_SetString(PyExc_TypeError, "embedded NUL character"); + Py_DECREF(output); + return 0; + } + *(PyObject**)addr = output; + return Py_CLEANUP_SUPPORTED; +} + + +int +PyUnicode_FSDecoder(PyObject* arg, void* addr) +{ + PyObject *output = NULL; + Py_ssize_t size; + void *data; + if (arg == NULL) { + Py_DECREF(*(PyObject**)addr); + return 1; + } + if (PyUnicode_Check(arg)) { + output = arg; + Py_INCREF(output); } else { - size = PyByteArray_GET_SIZE(output); - data = PyByteArray_AS_STRING(output); + arg = PyBytes_FromObject(arg); + if (!arg) + return 0; + output = PyUnicode_DecodeFSDefaultAndSize(PyBytes_AS_STRING(arg), + PyBytes_GET_SIZE(arg)); + Py_DECREF(arg); + if (!output) + return 0; + if (!PyUnicode_Check(output)) { + Py_DECREF(output); + PyErr_SetString(PyExc_TypeError, "decoder failed to return unicode"); + return 0; + } } - if (size != strlen(data)) { + size = PyUnicode_GET_SIZE(output); + data = PyUnicode_AS_UNICODE(output); + if (size != Py_UNICODE_strlen(data)) { PyErr_SetString(PyExc_TypeError, "embedded NUL character"); Py_DECREF(output); return 0; @@ -1632,18 +1995,34 @@ Py_ssize_t PyUnicode_GetSize(PyObject *unicode) const char *PyUnicode_GetDefaultEncoding(void) { - return unicode_default_encoding; + return "utf-8"; } -int PyUnicode_SetDefaultEncoding(const char *encoding) +/* create or adjust a UnicodeDecodeError */ +static void +make_decode_exception(PyObject **exceptionObject, + const char *encoding, + const char *input, Py_ssize_t length, + Py_ssize_t startpos, Py_ssize_t endpos, + const char *reason) { - if (strcmp(encoding, unicode_default_encoding) != 0) { - PyErr_Format(PyExc_ValueError, - "Can only set default encoding to %s", - unicode_default_encoding); - return -1; + if (*exceptionObject == NULL) { + *exceptionObject = PyUnicodeDecodeError_Create( + encoding, input, length, startpos, endpos, reason); } - return 0; + else { + if (PyUnicodeDecodeError_SetStart(*exceptionObject, startpos)) + goto onError; + if (PyUnicodeDecodeError_SetEnd(*exceptionObject, endpos)) + goto onError; + if (PyUnicodeDecodeError_SetReason(*exceptionObject, reason)) + goto onError; + } + return; + +onError: + Py_DECREF(*exceptionObject); + *exceptionObject = NULL; } /* error handling callback helper: @@ -1679,20 +2058,13 @@ int unicode_decode_call_errorhandler(const char *errors, PyObject **errorHandler goto onError; } - if (*exceptionObject == NULL) { - *exceptionObject = PyUnicodeDecodeError_Create( - encoding, *input, *inend-*input, *startinpos, *endinpos, reason); - if (*exceptionObject == NULL) - goto onError; - } - else { - if (PyUnicodeDecodeError_SetStart(*exceptionObject, *startinpos)) - goto onError; - if (PyUnicodeDecodeError_SetEnd(*exceptionObject, *endinpos)) - goto onError; - if (PyUnicodeDecodeError_SetReason(*exceptionObject, reason)) - goto onError; - } + make_decode_exception(exceptionObject, + encoding, + *input, *inend - *input, + *startinpos, *endinpos, + reason); + if (*exceptionObject == NULL) + goto onError; restuple = PyObject_CallFunctionObjArgs(*errorHandler, *exceptionObject, NULL); if (restuple == NULL) @@ -2408,6 +2780,120 @@ PyObject *PyUnicode_DecodeUTF8Stateful(const char *s, #undef ASCII_CHAR_MASK +#ifdef __APPLE__ + +/* Simplified UTF-8 decoder using surrogateescape error handler, + used to decode the command line arguments on Mac OS X. */ + +wchar_t* +_Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size) +{ + int n; + const char *e; + wchar_t *unicode, *p; + + /* Note: size will always be longer than the resulting Unicode + character count */ + if (PY_SSIZE_T_MAX / sizeof(wchar_t) < (size + 1)) { + PyErr_NoMemory(); + return NULL; + } + unicode = PyMem_Malloc((size + 1) * sizeof(wchar_t)); + if (!unicode) + return NULL; + + /* Unpack UTF-8 encoded data */ + p = unicode; + e = s + size; + while (s < e) { + Py_UCS4 ch = (unsigned char)*s; + + if (ch < 0x80) { + *p++ = (wchar_t)ch; + s++; + continue; + } + + n = utf8_code_length[ch]; + if (s + n > e) { + goto surrogateescape; + } + + switch (n) { + case 0: + case 1: + goto surrogateescape; + + case 2: + if ((s[1] & 0xc0) != 0x80) + goto surrogateescape; + ch = ((s[0] & 0x1f) << 6) + (s[1] & 0x3f); + assert ((ch > 0x007F) && (ch <= 0x07FF)); + *p++ = (wchar_t)ch; + break; + + case 3: + /* Decoding UTF-8 sequences in range \xed\xa0\x80-\xed\xbf\xbf + will result in surrogates in range d800-dfff. Surrogates are + not valid UTF-8 so they are rejected. + See http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf + (table 3-7) and http://www.rfc-editor.org/rfc/rfc3629.txt */ + if ((s[1] & 0xc0) != 0x80 || + (s[2] & 0xc0) != 0x80 || + ((unsigned char)s[0] == 0xE0 && + (unsigned char)s[1] < 0xA0) || + ((unsigned char)s[0] == 0xED && + (unsigned char)s[1] > 0x9F)) { + + goto surrogateescape; + } + ch = ((s[0] & 0x0f) << 12) + ((s[1] & 0x3f) << 6) + (s[2] & 0x3f); + assert ((ch > 0x07FF) && (ch <= 0xFFFF)); + *p++ = (Py_UNICODE)ch; + break; + + case 4: + if ((s[1] & 0xc0) != 0x80 || + (s[2] & 0xc0) != 0x80 || + (s[3] & 0xc0) != 0x80 || + ((unsigned char)s[0] == 0xF0 && + (unsigned char)s[1] < 0x90) || + ((unsigned char)s[0] == 0xF4 && + (unsigned char)s[1] > 0x8F)) { + goto surrogateescape; + } + ch = ((s[0] & 0x7) << 18) + ((s[1] & 0x3f) << 12) + + ((s[2] & 0x3f) << 6) + (s[3] & 0x3f); + assert ((ch > 0xFFFF) && (ch <= 0x10ffff)); + +#if SIZEOF_WCHAR_T == 4 + *p++ = (wchar_t)ch; +#else + /* compute and append the two surrogates: */ + + /* translate from 10000..10FFFF to 0..FFFF */ + ch -= 0x10000; + + /* high surrogate = top 10 bits added to D800 */ + *p++ = (wchar_t)(0xD800 + (ch >> 10)); + + /* low surrogate = bottom 10 bits added to DC00 */ + *p++ = (wchar_t)(0xDC00 + (ch & 0x03FF)); +#endif + break; + } + s += n; + continue; + + surrogateescape: + *p++ = 0xDC00 + ch; + s++; + } + *p = L'\0'; + return unicode; +} + +#endif /* __APPLE__ */ /* Allocation strategy: if the string is short, convert into a stack buffer and allocate exactly as much space needed at the end. Else allocate the @@ -3366,7 +3852,7 @@ PyObject *PyUnicode_DecodeUnicodeEscape(const char *s, } for (i = 0; i < digits; ++i) { c = (unsigned char) s[i]; - if (!ISXDIGIT(c)) { + if (!Py_ISXDIGIT(c)) { endinpos = (s+i+1)-starts; if (unicode_decode_call_errorhandler( errors, &errorHandler, @@ -3732,7 +4218,7 @@ PyObject *PyUnicode_DecodeRawUnicodeEscape(const char *s, outpos = p-PyUnicode_AS_UNICODE(v); for (x = 0, i = 0; i < count; ++i, ++s) { c = (unsigned char)*s; - if (!ISXDIGIT(c)) { + if (!Py_ISXDIGIT(c)) { endinpos = s-starts; if (unicode_decode_call_errorhandler( errors, &errorHandler, @@ -4431,32 +4917,46 @@ static int is_dbcs_lead_byte(const char *s, int offset) static int decode_mbcs(PyUnicodeObject **v, const char *s, /* MBCS string */ int size, /* sizeof MBCS string */ - int final) + int final, + const char *errors) { Py_UNICODE *p; - Py_ssize_t n = 0; - int usize = 0; + Py_ssize_t n; + DWORD usize; + DWORD flags; assert(size >= 0); + /* check and handle 'errors' arg */ + if (errors==NULL || strcmp(errors, "strict")==0) + flags = MB_ERR_INVALID_CHARS; + else if (strcmp(errors, "ignore")==0) + flags = 0; + else { + PyErr_Format(PyExc_ValueError, + "mbcs encoding does not support errors='%s'", + errors); + return -1; + } + /* Skip trailing lead-byte unless 'final' is set */ if (!final && size >= 1 && is_dbcs_lead_byte(s, size - 1)) --size; /* First get the size of the result */ if (size > 0) { - usize = MultiByteToWideChar(CP_ACP, 0, s, size, NULL, 0); - if (usize == 0) { - PyErr_SetFromWindowsErrWithFilename(0, NULL); - return -1; - } - } + usize = MultiByteToWideChar(CP_ACP, flags, s, size, NULL, 0); + if (usize==0) + goto mbcs_decode_error; + } else + usize = 0; if (*v == NULL) { /* Create unicode object */ *v = _PyUnicode_New(usize); if (*v == NULL) return -1; + n = 0; } else { /* Extend unicode object */ @@ -4466,15 +4966,35 @@ static int decode_mbcs(PyUnicodeObject **v, } /* Do the conversion */ - if (size > 0) { + if (usize > 0) { p = PyUnicode_AS_UNICODE(*v) + n; - if (0 == MultiByteToWideChar(CP_ACP, 0, s, size, p, usize)) { - PyErr_SetFromWindowsErrWithFilename(0, NULL); - return -1; + if (0 == MultiByteToWideChar(CP_ACP, flags, s, size, p, usize)) { + goto mbcs_decode_error; } } - return size; + +mbcs_decode_error: + /* If the last error was ERROR_NO_UNICODE_TRANSLATION, then + we raise a UnicodeDecodeError - else it is a 'generic' + windows error + */ + if (GetLastError()==ERROR_NO_UNICODE_TRANSLATION) { + /* Ideally, we should get reason from FormatMessage - this + is the Windows 2000 English version of the message + */ + PyObject *exc = NULL; + const char *reason = "No mapping for the Unicode character exists " + "in the target multi-byte code page."; + make_decode_exception(&exc, "mbcs", s, size, 0, 0, reason); + if (exc != NULL) { + PyCodec_StrictErrors(exc); + Py_DECREF(exc); + } + } else { + PyErr_SetFromWindowsErrWithFilename(0, NULL); + } + return -1; } PyObject *PyUnicode_DecodeMBCSStateful(const char *s, @@ -4491,10 +5011,10 @@ PyObject *PyUnicode_DecodeMBCSStateful(const char *s, #ifdef NEED_RETRY retry: if (size > INT_MAX) - done = decode_mbcs(&v, s, INT_MAX, 0); + done = decode_mbcs(&v, s, INT_MAX, 0, errors); else #endif - done = decode_mbcs(&v, s, (int)size, !consumed); + done = decode_mbcs(&v, s, (int)size, !consumed, errors); if (done < 0) { Py_XDECREF(v); @@ -4528,20 +5048,45 @@ PyObject *PyUnicode_DecodeMBCS(const char *s, */ static int encode_mbcs(PyObject **repr, const Py_UNICODE *p, /* unicode */ - int size) /* size of unicode */ + int size, /* size of unicode */ + const char* errors) { - int mbcssize = 0; - Py_ssize_t n = 0; + BOOL usedDefaultChar = FALSE; + BOOL *pusedDefaultChar; + int mbcssize; + Py_ssize_t n; + PyObject *exc = NULL; + DWORD flags; assert(size >= 0); + /* check and handle 'errors' arg */ + if (errors==NULL || strcmp(errors, "strict")==0) { + flags = WC_NO_BEST_FIT_CHARS; + pusedDefaultChar = &usedDefaultChar; + } else if (strcmp(errors, "replace")==0) { + flags = 0; + pusedDefaultChar = NULL; + } else { + PyErr_Format(PyExc_ValueError, + "mbcs encoding does not support errors='%s'", + errors); + return -1; + } + /* First get the size of the result */ if (size > 0) { - mbcssize = WideCharToMultiByte(CP_ACP, 0, p, size, NULL, 0, NULL, NULL); + mbcssize = WideCharToMultiByte(CP_ACP, flags, p, size, NULL, 0, + NULL, pusedDefaultChar); if (mbcssize == 0) { PyErr_SetFromWindowsErrWithFilename(0, NULL); return -1; } + /* If we used a default char, then we failed! */ + if (pusedDefaultChar && *pusedDefaultChar) + goto mbcs_encode_error; + } else { + mbcssize = 0; } if (*repr == NULL) { @@ -4549,6 +5094,7 @@ static int encode_mbcs(PyObject **repr, *repr = PyBytes_FromStringAndSize(NULL, mbcssize); if (*repr == NULL) return -1; + n = 0; } else { /* Extend string object */ @@ -4560,13 +5106,20 @@ static int encode_mbcs(PyObject **repr, /* Do the conversion */ if (size > 0) { char *s = PyBytes_AS_STRING(*repr) + n; - if (0 == WideCharToMultiByte(CP_ACP, 0, p, size, s, mbcssize, NULL, NULL)) { + if (0 == WideCharToMultiByte(CP_ACP, flags, p, size, s, mbcssize, + NULL, pusedDefaultChar)) { PyErr_SetFromWindowsErrWithFilename(0, NULL); return -1; } + if (pusedDefaultChar && *pusedDefaultChar) + goto mbcs_encode_error; } - return 0; + +mbcs_encode_error: + raise_encode_exception(&exc, "mbcs", p, size, 0, 0, "invalid character"); + Py_XDECREF(exc); + return -1; } PyObject *PyUnicode_EncodeMBCS(const Py_UNICODE *p, @@ -4579,10 +5132,10 @@ PyObject *PyUnicode_EncodeMBCS(const Py_UNICODE *p, #ifdef NEED_RETRY retry: if (size > INT_MAX) - ret = encode_mbcs(&repr, p, INT_MAX); + ret = encode_mbcs(&repr, p, INT_MAX, errors); else #endif - ret = encode_mbcs(&repr, p, (int)size); + ret = encode_mbcs(&repr, p, (int)size, errors); if (ret < 0) { Py_XDECREF(repr); @@ -5699,6 +6252,30 @@ PyObject *PyUnicode_Translate(PyObject *str, return NULL; } +PyObject * +PyUnicode_TransformDecimalToASCII(Py_UNICODE *s, + Py_ssize_t length) +{ + PyObject *result; + Py_UNICODE *p; /* write pointer into result */ + Py_ssize_t i; + /* Copy to a new string */ + result = (PyObject *)_PyUnicode_New(length); + Py_UNICODE_COPY(PyUnicode_AS_UNICODE(result), s, length); + if (result == NULL) + return result; + p = PyUnicode_AS_UNICODE(result); + /* Iterate over code points */ + for (i = 0; i < length; i++) { + Py_UNICODE ch =s[i]; + if (ch > 127) { + int decimal = Py_UNICODE_TODECIMAL(ch); + if (decimal >= 0) + p[i] = '0' + decimal; + } + } + return result; +} /* --- Decimal Encoder ---------------------------------------------------- */ int PyUnicode_EncodeDecimal(Py_UNICODE *s, @@ -5840,28 +6417,30 @@ int PyUnicode_EncodeDecimal(Py_UNICODE *s, #include "stringlib/unicodedefs.h" #include "stringlib/fastsearch.h" + #include "stringlib/count.h" -/* Include _ParseTupleFinds from find.h */ -#define FROM_UNICODE #include "stringlib/find.h" #include "stringlib/partition.h" +#include "stringlib/split.h" #define _Py_InsertThousandsGrouping _PyUnicode_InsertThousandsGrouping #define _Py_InsertThousandsGroupingLocale _PyUnicode_InsertThousandsGroupingLocale #include "stringlib/localeutil.h" /* helper macro to fixup start/end slice values */ -#define FIX_START_END(obj) \ - if (start < 0) \ - start += (obj)->length; \ - if (start < 0) \ - start = 0; \ - if (end > (obj)->length) \ - end = (obj)->length; \ - if (end < 0) \ - end += (obj)->length; \ - if (end < 0) \ - end = 0; +#define ADJUST_INDICES(start, end, len) \ + if (end > len) \ + end = len; \ + else if (end < 0) { \ + end += len; \ + if (end < 0) \ + end = 0; \ + } \ + if (start < 0) { \ + start += len; \ + if (start < 0) \ + start = 0; \ + } Py_ssize_t PyUnicode_Count(PyObject *str, PyObject *substr, @@ -5881,10 +6460,10 @@ Py_ssize_t PyUnicode_Count(PyObject *str, return -1; } - FIX_START_END(str_obj); - + ADJUST_INDICES(start, end, str_obj->length); result = stringlib_count( - str_obj->str + start, end - start, sub_obj->str, sub_obj->length + str_obj->str + start, end - start, sub_obj->str, sub_obj->length, + PY_SSIZE_T_MAX ); Py_DECREF(sub_obj); @@ -5939,8 +6518,7 @@ int tailmatch(PyUnicodeObject *self, if (substring->length == 0) return 1; - FIX_START_END(self); - + ADJUST_INDICES(start, end, self->length); end -= substring->length; if (end < start) return 0; @@ -6281,305 +6859,40 @@ PyUnicodeObject *pad(PyUnicodeObject *self, return u; } -#define SPLIT_APPEND(data, left, right) \ - str = PyUnicode_FromUnicode((data) + (left), (right) - (left)); \ - if (!str) \ - goto onError; \ - if (PyList_Append(list, str)) { \ - Py_DECREF(str); \ - goto onError; \ - } \ - else \ - Py_DECREF(str); - -static -PyObject *split_whitespace(PyUnicodeObject *self, - PyObject *list, - Py_ssize_t maxcount) +PyObject *PyUnicode_Splitlines(PyObject *string, int keepends) { - register Py_ssize_t i; - register Py_ssize_t j; - Py_ssize_t len = self->length; - PyObject *str; - register const Py_UNICODE *buf = self->str; - - for (i = j = 0; i < len; ) { - /* find a token */ - while (i < len && Py_UNICODE_ISSPACE(buf[i])) - i++; - j = i; - while (i < len && !Py_UNICODE_ISSPACE(buf[i])) - i++; - if (j < i) { - if (maxcount-- <= 0) - break; - SPLIT_APPEND(buf, j, i); - while (i < len && Py_UNICODE_ISSPACE(buf[i])) - i++; - j = i; - } - } - if (j < len) { - SPLIT_APPEND(buf, j, len); - } - return list; - - onError: - Py_DECREF(list); - return NULL; -} - -PyObject *PyUnicode_Splitlines(PyObject *string, - int keepends) -{ - register Py_ssize_t i; - register Py_ssize_t j; - Py_ssize_t len; PyObject *list; - PyObject *str; - Py_UNICODE *data; string = PyUnicode_FromObject(string); if (string == NULL) return NULL; - data = PyUnicode_AS_UNICODE(string); - len = PyUnicode_GET_SIZE(string); - - list = PyList_New(0); - if (!list) - goto onError; - for (i = j = 0; i < len; ) { - Py_ssize_t eol; + list = stringlib_splitlines( + (PyObject*) string, PyUnicode_AS_UNICODE(string), + PyUnicode_GET_SIZE(string), keepends); - /* Find a line and append it */ - while (i < len && !BLOOM_LINEBREAK(data[i])) - i++; - - /* Skip the line break reading CRLF as one line break */ - eol = i; - if (i < len) { - if (data[i] == '\r' && i + 1 < len && - data[i+1] == '\n') - i += 2; - else - i++; - if (keepends) - eol = i; - } - SPLIT_APPEND(data, j, eol); - j = i; - } - if (j < len) { - SPLIT_APPEND(data, j, len); - } - - Py_DECREF(string); - return list; - - onError: - Py_XDECREF(list); Py_DECREF(string); - return NULL; -} - -static -PyObject *split_char(PyUnicodeObject *self, - PyObject *list, - Py_UNICODE ch, - Py_ssize_t maxcount) -{ - register Py_ssize_t i; - register Py_ssize_t j; - Py_ssize_t len = self->length; - PyObject *str; - register const Py_UNICODE *buf = self->str; - - for (i = j = 0; i < len; ) { - if (buf[i] == ch) { - if (maxcount-- <= 0) - break; - SPLIT_APPEND(buf, j, i); - i = j = i + 1; - } else - i++; - } - if (j <= len) { - SPLIT_APPEND(buf, j, len); - } - return list; - - onError: - Py_DECREF(list); - return NULL; -} - -static -PyObject *split_substring(PyUnicodeObject *self, - PyObject *list, - PyUnicodeObject *substring, - Py_ssize_t maxcount) -{ - register Py_ssize_t i; - register Py_ssize_t j; - Py_ssize_t len = self->length; - Py_ssize_t sublen = substring->length; - PyObject *str; - - for (i = j = 0; i <= len - sublen; ) { - if (Py_UNICODE_MATCH(self, i, substring)) { - if (maxcount-- <= 0) - break; - SPLIT_APPEND(self->str, j, i); - i = j = i + sublen; - } else - i++; - } - if (j <= len) { - SPLIT_APPEND(self->str, j, len); - } - return list; - - onError: - Py_DECREF(list); - return NULL; -} - -static -PyObject *rsplit_whitespace(PyUnicodeObject *self, - PyObject *list, - Py_ssize_t maxcount) -{ - register Py_ssize_t i; - register Py_ssize_t j; - Py_ssize_t len = self->length; - PyObject *str; - register const Py_UNICODE *buf = self->str; - - for (i = j = len - 1; i >= 0; ) { - /* find a token */ - while (i >= 0 && Py_UNICODE_ISSPACE(buf[i])) - i--; - j = i; - while (i >= 0 && !Py_UNICODE_ISSPACE(buf[i])) - i--; - if (j > i) { - if (maxcount-- <= 0) - break; - SPLIT_APPEND(buf, i + 1, j + 1); - while (i >= 0 && Py_UNICODE_ISSPACE(buf[i])) - i--; - j = i; - } - } - if (j >= 0) { - SPLIT_APPEND(buf, 0, j + 1); - } - if (PyList_Reverse(list) < 0) - goto onError; - return list; - - onError: - Py_DECREF(list); - return NULL; -} - -static -PyObject *rsplit_char(PyUnicodeObject *self, - PyObject *list, - Py_UNICODE ch, - Py_ssize_t maxcount) -{ - register Py_ssize_t i; - register Py_ssize_t j; - Py_ssize_t len = self->length; - PyObject *str; - register const Py_UNICODE *buf = self->str; - - for (i = j = len - 1; i >= 0; ) { - if (buf[i] == ch) { - if (maxcount-- <= 0) - break; - SPLIT_APPEND(buf, i + 1, j + 1); - j = i = i - 1; - } else - i--; - } - if (j >= -1) { - SPLIT_APPEND(buf, 0, j + 1); - } - if (PyList_Reverse(list) < 0) - goto onError; return list; - - onError: - Py_DECREF(list); - return NULL; } static -PyObject *rsplit_substring(PyUnicodeObject *self, - PyObject *list, - PyUnicodeObject *substring, - Py_ssize_t maxcount) -{ - register Py_ssize_t i; - register Py_ssize_t j; - Py_ssize_t len = self->length; - Py_ssize_t sublen = substring->length; - PyObject *str; - - for (i = len - sublen, j = len; i >= 0; ) { - if (Py_UNICODE_MATCH(self, i, substring)) { - if (maxcount-- <= 0) - break; - SPLIT_APPEND(self->str, i + sublen, j); - j = i; - i -= sublen; - } else - i--; - } - if (j >= 0) { - SPLIT_APPEND(self->str, 0, j); - } - if (PyList_Reverse(list) < 0) - goto onError; - return list; - - onError: - Py_DECREF(list); - return NULL; -} - -#undef SPLIT_APPEND - -static PyObject *split(PyUnicodeObject *self, PyUnicodeObject *substring, Py_ssize_t maxcount) { - PyObject *list; - if (maxcount < 0) maxcount = PY_SSIZE_T_MAX; - list = PyList_New(0); - if (!list) - return NULL; - if (substring == NULL) - return split_whitespace(self,list,maxcount); - - else if (substring->length == 1) - return split_char(self,list,substring->str[0],maxcount); + return stringlib_split_whitespace( + (PyObject*) self, self->str, self->length, maxcount + ); - else if (substring->length == 0) { - Py_DECREF(list); - PyErr_SetString(PyExc_ValueError, "empty separator"); - return NULL; - } - else - return split_substring(self,list,substring,maxcount); + return stringlib_split( + (PyObject*) self, self->str, self->length, + substring->str, substring->length, + maxcount + ); } static @@ -6587,28 +6900,19 @@ PyObject *rsplit(PyUnicodeObject *self, PyUnicodeObject *substring, Py_ssize_t maxcount) { - PyObject *list; - if (maxcount < 0) maxcount = PY_SSIZE_T_MAX; - list = PyList_New(0); - if (!list) - return NULL; - if (substring == NULL) - return rsplit_whitespace(self,list,maxcount); - - else if (substring->length == 1) - return rsplit_char(self,list,substring->str[0],maxcount); + return stringlib_rsplit_whitespace( + (PyObject*) self, self->str, self->length, maxcount + ); - else if (substring->length == 0) { - Py_DECREF(list); - PyErr_SetString(PyExc_ValueError, "empty separator"); - return NULL; - } - else - return rsplit_substring(self,list,substring,maxcount); + return stringlib_rsplit( + (PyObject*) self, self->str, self->length, + substring->str, substring->length, + maxcount + ); } static @@ -6621,10 +6925,14 @@ PyObject *replace(PyUnicodeObject *self, if (maxcount < 0) maxcount = PY_SSIZE_T_MAX; + else if (maxcount == 0 || self->length == 0) + goto nothing; if (str1->length == str2->length) { - /* same length */ Py_ssize_t i; + /* same length */ + if (str1->length == 0) + goto nothing; if (str1->length == 1) { /* replace characters */ Py_UNICODE u1, u2; @@ -6643,8 +6951,8 @@ PyObject *replace(PyUnicodeObject *self, u->str[i] = u2; } } else { - i = fastsearch( - self->str, self->length, str1->str, str1->length, FAST_SEARCH + i = stringlib_find( + self->str, self->length, str1->str, str1->length, 0 ); if (i < 0) goto nothing; @@ -6652,14 +6960,20 @@ PyObject *replace(PyUnicodeObject *self, if (!u) return NULL; Py_UNICODE_COPY(u->str, self->str, self->length); - while (i <= self->length - str1->length) - if (Py_UNICODE_MATCH(self, i, str1)) { - if (--maxcount < 0) - break; - Py_UNICODE_COPY(u->str+i, str2->str, str2->length); - i += str1->length; - } else - i++; + + /* change everything in-place, starting with this one */ + Py_UNICODE_COPY(u->str+i, str2->str, str2->length); + i += str1->length; + + while ( --maxcount > 0) { + i = stringlib_find(self->str+i, self->length-i, + str1->str, str1->length, + i); + if (i == -1) + break; + Py_UNICODE_COPY(u->str+i, str2->str, str2->length); + i += str1->length; + } } } else { @@ -6668,9 +6982,8 @@ PyObject *replace(PyUnicodeObject *self, Py_UNICODE *p; /* replace strings */ - n = stringlib_count(self->str, self->length, str1->str, str1->length); - if (n > maxcount) - n = maxcount; + n = stringlib_count(self->str, self->length, str1->str, str1->length, + maxcount); if (n == 0) goto nothing; /* new_size = self->length + n * (str2->length - str1->length)); */ @@ -6700,15 +7013,12 @@ PyObject *replace(PyUnicodeObject *self, if (str1->length > 0) { while (n-- > 0) { /* look for next match */ - j = i; - while (j <= e) { - if (Py_UNICODE_MATCH(self, j, str1)) - break; - j++; - } - if (j > i) { - if (j > e) - break; + j = stringlib_find(self->str+i, self->length-i, + str1->str, str1->length, + i); + if (j == -1) + break; + else if (j > i) { /* copy unchanged part [i:j] */ Py_UNICODE_COPY(p, self->str+i, j-i); p += j - i; @@ -6970,10 +7280,7 @@ PyUnicode_CompareWithASCIIString(PyObject* uni, const char* str) return ((int)id[i] < (int)str[i]) ? -1 : 1; /* This check keeps Python strings that end in '\0' from comparing equal to C strings identical up to that point. */ - if (PyUnicode_GET_SIZE(uni) != i) - /* We'll say the Python string is longer. */ - return 1; - if (id[i]) + if (PyUnicode_GET_SIZE(uni) != i || id[i]) return 1; /* uni is longer */ if (str[i]) return -1; /* str is longer */ @@ -7154,11 +7461,11 @@ unicode_count(PyUnicodeObject *self, PyObject *args) &start, &end)) return NULL; - FIX_START_END(self); - + ADJUST_INDICES(start, end, self->length); result = PyLong_FromSsize_t( stringlib_count(self->str + start, end - start, - substring->str, substring->length) + substring->str, substring->length, + PY_SSIZE_T_MAX) ); Py_DECREF(substring); @@ -7167,39 +7474,26 @@ unicode_count(PyUnicodeObject *self, PyObject *args) } PyDoc_STRVAR(encode__doc__, - "S.encode([encoding[, errors]]) -> bytes\n\ + "S.encode(encoding='utf-8', errors='strict') -> bytes\n\ \n\ -Encode S using the codec registered for encoding. encoding defaults\n\ -to the default encoding. errors may be given to set a different error\n\ +Encode S using the codec registered for encoding. Default encoding\n\ +is 'utf-8'. errors may be given to set a different error\n\ handling scheme. Default is 'strict' meaning that encoding errors raise\n\ a UnicodeEncodeError. Other possible values are 'ignore', 'replace' and\n\ 'xmlcharrefreplace' as well as any other name registered with\n\ codecs.register_error that can handle UnicodeEncodeErrors."); static PyObject * -unicode_encode(PyUnicodeObject *self, PyObject *args) +unicode_encode(PyUnicodeObject *self, PyObject *args, PyObject *kwargs) { + static char *kwlist[] = {"encoding", "errors", 0}; char *encoding = NULL; char *errors = NULL; - PyObject *v; - if (!PyArg_ParseTuple(args, "|ss:encode", &encoding, &errors)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss:encode", + kwlist, &encoding, &errors)) return NULL; - v = PyUnicode_AsEncodedString((PyObject *)self, encoding, errors); - if (v == NULL) - goto onError; - if (!PyBytes_Check(v)) { - PyErr_Format(PyExc_TypeError, - "encoder did not return a bytes object " - "(type=%.400s)", - Py_TYPE(v)->tp_name); - Py_DECREF(v); - return NULL; - } - return v; - - onError: - return NULL; + return PyUnicode_AsEncodedString((PyObject *)self, encoding, errors); } PyDoc_STRVAR(expandtabs__doc__, @@ -7334,12 +7628,12 @@ unicode_getitem(PyUnicodeObject *self, Py_ssize_t index) /* Believe it or not, this produces the same value for ASCII strings as string_hash(). */ -static long +static Py_hash_t unicode_hash(PyUnicodeObject *self) { Py_ssize_t len; Py_UNICODE *p; - long x; + Py_hash_t x; if (self->hash != -1) return self->hash; @@ -8704,6 +8998,13 @@ unicode_freelistsize(PyUnicodeObject *self) { return PyLong_FromLong(numfree); } + +static PyObject * +unicode__decimal2ascii(PyObject *self) +{ + return PyUnicode_TransformDecimalToASCII(PyUnicode_AS_UNICODE(self), + PyUnicode_GET_SIZE(self)); +} #endif PyDoc_STRVAR(startswith__doc__, @@ -8810,6 +9111,12 @@ PyDoc_STRVAR(format__doc__, Return a formatted version of S, using substitutions from args and kwargs.\n\ The substitutions are identified by braces ('{' and '}')."); +PyDoc_STRVAR(format_map__doc__, + "S.format_map(mapping) -> str\n\ +\n\ +Return a formatted version of S, using substitutions from mapping.\n\ +The substitutions are identified by braces ('{' and '}')."); + static PyObject * unicode__format__(PyObject* self, PyObject* args) { @@ -8844,13 +9151,12 @@ unicode_getnewargs(PyUnicodeObject *v) return Py_BuildValue("(u#)", v->str, v->length); } - static PyMethodDef unicode_methods[] = { /* Order is according to common usage: often used methods should appear first, since lookup is done sequentially. */ - {"encode", (PyCFunction) unicode_encode, METH_VARARGS, encode__doc__}, + {"encode", (PyCFunction) unicode_encode, METH_VARARGS | METH_KEYWORDS, encode__doc__}, {"replace", (PyCFunction) unicode_replace, METH_VARARGS, replace__doc__}, {"split", (PyCFunction) unicode_split, METH_VARARGS, split__doc__}, {"rsplit", (PyCFunction) unicode_rsplit, METH_VARARGS, rsplit__doc__}, @@ -8891,9 +9197,8 @@ static PyMethodDef unicode_methods[] = { {"isprintable", (PyCFunction) unicode_isprintable, METH_NOARGS, isprintable__doc__}, {"zfill", (PyCFunction) unicode_zfill, METH_VARARGS, zfill__doc__}, {"format", (PyCFunction) do_string_format, METH_VARARGS | METH_KEYWORDS, format__doc__}, + {"format_map", (PyCFunction) do_string_format_map, METH_O, format_map__doc__}, {"__format__", (PyCFunction) unicode__format__, METH_VARARGS, p_format__doc__}, - {"_formatter_field_name_split", (PyCFunction) formatter_field_name_split, METH_NOARGS}, - {"_formatter_parser", (PyCFunction) formatter_parser, METH_NOARGS}, {"maketrans", (PyCFunction) unicode_maketrans, METH_VARARGS | METH_STATIC, maketrans__doc__}, {"__sizeof__", (PyCFunction) unicode__sizeof__, METH_NOARGS, sizeof__doc__}, @@ -8902,8 +9207,9 @@ static PyMethodDef unicode_methods[] = { #endif #if 0 - /* This one is just used for debugging the implementation. */ + /* These methods are just used for debugging the implementation. */ {"freelistsize", (PyCFunction) unicode_freelistsize, METH_NOARGS}, + {"_decimal2ascii", (PyCFunction) unicode__decimal2ascii, METH_NOARGS}, #endif {"__getnewargs__", (PyCFunction)unicode_getnewargs, METH_NOARGS}, @@ -8954,7 +9260,7 @@ unicode_subscript(PyUnicodeObject* self, PyObject* item) Py_UNICODE* result_buf; PyObject* result; - if (PySlice_GetIndicesEx((PySliceObject*)item, PyUnicode_GET_SIZE(self), + if (PySlice_GetIndicesEx(item, PyUnicode_GET_SIZE(self), &start, &stop, &step, &slicelength) < 0) { return NULL; } @@ -10008,6 +10314,15 @@ Py_UNICODE_strncpy(Py_UNICODE *s1, const Py_UNICODE *s2, size_t n) return s1; } +Py_UNICODE* +Py_UNICODE_strcat(Py_UNICODE *s1, const Py_UNICODE *s2) +{ + Py_UNICODE *u1 = s1; + u1 += Py_UNICODE_strlen(u1); + Py_UNICODE_strcpy(u1, s2); + return s1; +} + int Py_UNICODE_strcmp(const Py_UNICODE *s1, const Py_UNICODE *s2) { @@ -10022,6 +10337,23 @@ Py_UNICODE_strcmp(const Py_UNICODE *s1, const Py_UNICODE *s2) return 0; } +int +Py_UNICODE_strncmp(const Py_UNICODE *s1, const Py_UNICODE *s2, size_t n) +{ + register Py_UNICODE u1, u2; + for (; n != 0; n--) { + u1 = *s1; + u2 = *s2; + if (u1 != u2) + return (u1 < u2) ? -1 : +1; + if (u1 == '\0') + return 0; + s1++; + s2++; + } + return 0; +} + Py_UNICODE* Py_UNICODE_strchr(const Py_UNICODE *s, Py_UNICODE c) { @@ -10032,15 +10364,72 @@ Py_UNICODE_strchr(const Py_UNICODE *s, Py_UNICODE c) return NULL; } +Py_UNICODE* +Py_UNICODE_strrchr(const Py_UNICODE *s, Py_UNICODE c) +{ + const Py_UNICODE *p; + p = s + Py_UNICODE_strlen(s); + while (p != s) { + p--; + if (*p == c) + return (Py_UNICODE*)p; + } + return NULL; +} -#ifdef __cplusplus +Py_UNICODE* +PyUnicode_AsUnicodeCopy(PyObject *object) +{ + PyUnicodeObject *unicode = (PyUnicodeObject *)object; + Py_UNICODE *copy; + Py_ssize_t size; + + /* Ensure we won't overflow the size. */ + if (PyUnicode_GET_SIZE(unicode) > ((PY_SSIZE_T_MAX / sizeof(Py_UNICODE)) - 1)) { + PyErr_NoMemory(); + return NULL; + } + size = PyUnicode_GET_SIZE(unicode) + 1; /* copy the nul character */ + size *= sizeof(Py_UNICODE); + copy = PyMem_Malloc(size); + if (copy == NULL) { + PyErr_NoMemory(); + return NULL; + } + memcpy(copy, PyUnicode_AS_UNICODE(unicode), size); + return copy; } -#endif +/* A _string module, to export formatter_parser and formatter_field_name_split + to the string.Formatter class implemented in Python. */ -/* - Local variables: - c-basic-offset: 4 - indent-tabs-mode: nil - End: -*/ +static PyMethodDef _string_methods[] = { + {"formatter_field_name_split", (PyCFunction) formatter_field_name_split, + METH_O, PyDoc_STR("split the argument as a field name")}, + {"formatter_parser", (PyCFunction) formatter_parser, + METH_O, PyDoc_STR("parse the argument as a format string")}, + {NULL, NULL} +}; + +static struct PyModuleDef _string_module = { + PyModuleDef_HEAD_INIT, + "_string", + PyDoc_STR("string helper module"), + 0, + _string_methods, + NULL, + NULL, + NULL, + NULL +}; + +PyMODINIT_FUNC +PyInit__string(void) +{ + return PyModule_Create(&_string_module); +} + + +#ifdef __cplusplus +} +#endif diff --git a/Objects/unicodetype_db.h b/Objects/unicodetype_db.h index f46f1fb..88a7912 100644 --- a/Objects/unicodetype_db.h +++ b/Objects/unicodetype_db.h @@ -1,4 +1,4 @@ -/* this file was generated by Tools/unicode/makeunicodedata.py 2.6 */ +/* this file was generated by Tools/unicode/makeunicodedata.py 3.2 */ /* a list of unique character type descriptors */ const _PyUnicode_TypeRecord _PyUnicode_TypeRecords[] = { @@ -8,24 +8,25 @@ const _PyUnicode_TypeRecord _PyUnicode_TypeRecords[] = { {0, 0, 0, 0, 0, 48}, {0, 0, 0, 0, 0, 1056}, {0, 0, 0, 0, 0, 1024}, - {0, 0, 0, 0, 0, 1542}, - {0, 0, 0, 1, 1, 1542}, - {0, 0, 0, 2, 2, 1542}, - {0, 0, 0, 3, 3, 1542}, - {0, 0, 0, 4, 4, 1542}, - {0, 0, 0, 5, 5, 1542}, - {0, 0, 0, 6, 6, 1542}, - {0, 0, 0, 7, 7, 1542}, - {0, 0, 0, 8, 8, 1542}, - {0, 0, 0, 9, 9, 1542}, + {0, 0, 0, 0, 0, 5638}, + {0, 0, 0, 1, 1, 5638}, + {0, 0, 0, 2, 2, 5638}, + {0, 0, 0, 3, 3, 5638}, + {0, 0, 0, 4, 4, 5638}, + {0, 0, 0, 5, 5, 5638}, + {0, 0, 0, 6, 6, 5638}, + {0, 0, 0, 7, 7, 5638}, + {0, 0, 0, 8, 8, 5638}, + {0, 0, 0, 9, 9, 5638}, {0, 32, 0, 0, 0, 1921}, {0, 0, 0, 0, 0, 1536}, {65504, 0, 65504, 0, 0, 1801}, {0, 0, 0, 0, 0, 1801}, - {0, 0, 0, 0, 2, 1028}, - {0, 0, 0, 0, 3, 1028}, + {0, 0, 0, 0, 2, 5124}, + {0, 0, 0, 0, 3, 5124}, {743, 0, 743, 0, 0, 1801}, - {0, 0, 0, 0, 1, 1028}, + {0, 0, 0, 0, 1, 5124}, + {0, 0, 0, 0, 0, 5120}, {121, 0, 121, 0, 0, 1801}, {0, 1, 0, 0, 0, 1921}, {65535, 0, 65535, 0, 0, 1801}, @@ -63,17 +64,20 @@ const _PyUnicode_TypeRecord _PyUnicode_TypeRecords[] = { {0, 10795, 0, 0, 0, 1921}, {0, 65373, 0, 0, 0, 1921}, {0, 10792, 0, 0, 0, 1921}, + {10815, 0, 10815, 0, 0, 1801}, {0, 65341, 0, 0, 0, 1921}, {0, 69, 0, 0, 0, 1921}, {0, 71, 0, 0, 0, 1921}, {10783, 0, 10783, 0, 0, 1801}, {10780, 0, 10780, 0, 0, 1801}, + {10782, 0, 10782, 0, 0, 1801}, {65326, 0, 65326, 0, 0, 1801}, {65330, 0, 65330, 0, 0, 1801}, {65331, 0, 65331, 0, 0, 1801}, {65334, 0, 65334, 0, 0, 1801}, {65333, 0, 65333, 0, 0, 1801}, {65329, 0, 65329, 0, 0, 1801}, + {42893, 613, 42893, 0, 0, 3849}, {65327, 0, 65327, 0, 0, 1801}, {65325, 0, 65325, 0, 0, 1801}, {10743, 0, 10743, 0, 0, 1801}, @@ -117,16 +121,16 @@ const _PyUnicode_TypeRecord _PyUnicode_TypeRecords[] = { {65488, 0, 65488, 0, 0, 1801}, {0, 0, 0, 0, 0, 1537}, {0, 7264, 0, 0, 0, 1921}, - {0, 0, 0, 0, 1, 1540}, - {0, 0, 0, 0, 2, 1540}, - {0, 0, 0, 0, 3, 1540}, - {0, 0, 0, 0, 4, 1540}, - {0, 0, 0, 0, 5, 1540}, - {0, 0, 0, 0, 6, 1540}, - {0, 0, 0, 0, 7, 1540}, - {0, 0, 0, 0, 8, 1540}, - {0, 0, 0, 0, 9, 1540}, - {0, 0, 0, 0, 0, 1792}, + {0, 0, 0, 0, 1, 5636}, + {0, 0, 0, 0, 2, 5636}, + {0, 0, 0, 0, 3, 5636}, + {0, 0, 0, 0, 4, 5636}, + {0, 0, 0, 0, 5, 5636}, + {0, 0, 0, 0, 6, 5636}, + {0, 0, 0, 0, 7, 5636}, + {0, 0, 0, 0, 8, 5636}, + {0, 0, 0, 0, 9, 5636}, + {0, 0, 0, 0, 0, 5888}, {42877, 7545, 42877, 0, 0, 3849}, {3814, 0, 3814, 0, 0, 1801}, {65477, 0, 65477, 0, 0, 1801}, @@ -149,20 +153,21 @@ const _PyUnicode_TypeRecord _PyUnicode_TypeRecords[] = { {0, 65424, 0, 0, 0, 1921}, {0, 65408, 0, 0, 0, 1921}, {0, 65410, 0, 0, 0, 1921}, - {0, 0, 0, 0, 0, 1028}, - {0, 0, 0, 0, 4, 1028}, - {0, 0, 0, 0, 5, 1028}, - {0, 0, 0, 0, 6, 1028}, - {0, 0, 0, 0, 7, 1028}, - {0, 0, 0, 0, 8, 1028}, - {0, 0, 0, 0, 9, 1028}, + {0, 0, 0, 0, 0, 5124}, + {0, 0, 0, 0, 4, 5124}, + {0, 0, 0, 0, 5, 5124}, + {0, 0, 0, 0, 6, 5124}, + {0, 0, 0, 0, 7, 5124}, + {0, 0, 0, 0, 8, 5124}, + {0, 0, 0, 0, 9, 5124}, + {0, 0, 0, 0, 0, 1792}, {0, 58019, 0, 0, 0, 1921}, {0, 57153, 0, 0, 0, 1921}, {0, 57274, 0, 0, 0, 1921}, {0, 28, 0, 0, 0, 1921}, {65508, 0, 65508, 0, 0, 1801}, - {0, 16, 0, 0, 0, 1792}, - {65520, 0, 65520, 0, 0, 1792}, + {0, 16, 0, 0, 0, 5888}, + {65520, 0, 65520, 0, 0, 5888}, {0, 26, 0, 0, 0, 1024}, {65510, 0, 65510, 0, 0, 1024}, {0, 54793, 0, 0, 0, 1921}, @@ -173,214 +178,525 @@ const _PyUnicode_TypeRecord _PyUnicode_TypeRecords[] = { {0, 54756, 0, 0, 0, 1921}, {0, 54787, 0, 0, 0, 1921}, {0, 54753, 0, 0, 0, 1921}, + {0, 54754, 0, 0, 0, 1921}, + {0, 54721, 0, 0, 0, 1921}, {58272, 0, 58272, 0, 0, 1801}, + {0, 0, 0, 0, 0, 5889}, {42877, 7545, 42877, 0, 0, 3969}, + {42893, 613, 42893, 0, 0, 3969}, {0, 40, 0, 0, 0, 1921}, {65496, 0, 65496, 0, 0, 1801}, }; /* type indexes */ -#define SHIFT 8 +#define SHIFT 7 static unsigned char index1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 34, 37, - 38, 34, 34, 34, 39, 40, 41, 42, 43, 44, 45, 46, 34, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 47, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 48, 21, 21, 21, 21, 49, - 21, 50, 51, 52, 53, 54, 8, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 55, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 21, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 8, 8, 8, 68, 69, 70, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 21, 21, 21, 71, 72, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 73, 74, - 75, 76, 77, 78, 79, 80, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 81, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 82, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 21, 21, 83, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 84, 85, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 86, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 86, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 34, 35, 36, 37, + 38, 39, 34, 34, 34, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 65, 66, 67, 64, + 64, 64, 64, 68, 69, 64, 64, 64, 64, 64, 64, 70, 17, 71, 72, 73, 74, 75, + 76, 64, 77, 78, 79, 80, 81, 82, 83, 64, 64, 84, 85, 34, 34, 34, 34, 34, + 34, 86, 34, 34, 34, 34, 34, 87, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 88, 89, 90, 91, 34, 34, 34, 92, 34, 34, + 34, 93, 94, 34, 34, 34, 34, 34, 95, 34, 34, 34, 96, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 97, 98, 99, 34, 34, 34, 34, 34, 34, 100, 101, 34, 34, + 34, 34, 34, 34, 34, 34, 102, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 103, 34, 34, 34, 34, 34, 34, 34, 34, 104, 34, 34, 34, 34, + 100, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 103, 34, 34, 34, 34, 34, 34, 105, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 106, 107, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 108, 109, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 110, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 111, 34, 34, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 126, 127, 128, + 129, 130, 131, 132, 34, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 17, 143, 144, 145, 146, 147, 17, 17, 17, 17, 17, 17, 148, 17, 149, 17, + 150, 17, 151, 17, 152, 17, 17, 17, 153, 17, 17, 17, 154, 155, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 34, 34, 34, 34, 34, 34, 156, 17, 157, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 34, 34, 34, 34, 34, 34, 34, 34, 158, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 34, 34, 34, 34, 159, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 160, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 64, 161, 162, 163, 164, 17, 165, 17, 166, 167, 168, 169, 170, 171, + 172, 173, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 174, 175, 176, + 177, 178, 17, 179, 180, 181, 182, 183, 184, 185, 186, 65, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 187, 188, 189, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 86, 190, 34, 191, + 192, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 193, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 194, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 195, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 196, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 197, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 198, 34, 199, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 34, 193, 34, 34, 199, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 200, 17, 201, 202, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 203, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 203, }; static unsigned char index2[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 2, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, 5, 5, 5, 5, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, @@ -388,455 +704,424 @@ static unsigned char index2[] = { 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 19, 5, 5, - 1, 5, 5, 5, 5, 20, 21, 5, 22, 5, 17, 5, 23, 19, 5, 5, 5, 5, 5, 16, 16, + 1, 5, 5, 5, 5, 20, 21, 5, 22, 5, 17, 5, 23, 19, 5, 24, 24, 24, 5, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 5, 16, 16, 16, 16, 16, 16, 16, 19, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 5, - 18, 18, 18, 18, 18, 18, 18, 24, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 27, 28, 25, 26, 25, 26, 25, 26, 19, 25, 26, 25, 26, 25, 26, 25, - 26, 25, 26, 25, 26, 25, 26, 25, 26, 19, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 29, 25, 26, 25, 26, 25, 26, 30, 31, 32, 25, 26, 25, 26, 33, 25, - 26, 34, 34, 25, 26, 19, 35, 36, 37, 25, 26, 34, 38, 39, 40, 41, 25, 26, - 42, 19, 40, 43, 44, 45, 25, 26, 25, 26, 25, 26, 46, 25, 26, 46, 19, 19, - 25, 26, 46, 25, 26, 47, 47, 25, 26, 25, 26, 48, 25, 26, 19, 49, 25, 26, - 19, 50, 49, 49, 49, 49, 51, 52, 53, 51, 52, 53, 51, 52, 53, 25, 26, 25, - 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 54, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 19, 51, 52, 53, - 25, 26, 55, 56, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 57, 19, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 19, 19, 19, 19, 19, 19, 58, 25, - 26, 59, 60, 19, 19, 25, 26, 61, 62, 63, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 64, 65, 19, 66, 67, 19, 68, 68, 19, 69, 19, 70, 19, 19, 19, 19, - 68, 19, 19, 71, 19, 19, 19, 19, 72, 73, 19, 74, 19, 19, 19, 73, 19, 75, - 76, 19, 19, 77, 19, 19, 19, 19, 19, 19, 19, 78, 19, 19, 79, 19, 19, 79, - 19, 19, 19, 19, 79, 80, 81, 81, 82, 19, 19, 19, 19, 19, 83, 19, 49, 19, + 18, 18, 18, 18, 18, 18, 18, 25, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, + 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, + 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, + 26, 27, 28, 29, 26, 27, 26, 27, 26, 27, 19, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 19, 26, 27, 26, 27, 26, 27, 26, 27, + 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, + 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, + 26, 27, 30, 26, 27, 26, 27, 26, 27, 31, 32, 33, 26, 27, 26, 27, 34, 26, + 27, 35, 35, 26, 27, 19, 36, 37, 38, 26, 27, 35, 39, 40, 41, 42, 26, 27, + 43, 19, 41, 44, 45, 46, 26, 27, 26, 27, 26, 27, 47, 26, 27, 47, 19, 19, + 26, 27, 47, 26, 27, 48, 48, 26, 27, 26, 27, 49, 26, 27, 19, 50, 26, 27, + 19, 51, 50, 50, 50, 50, 52, 53, 54, 52, 53, 54, 52, 53, 54, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 55, 26, 27, 26, 27, + 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 19, 52, 53, 54, + 26, 27, 56, 57, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, + 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, + 26, 27, 26, 27, 26, 27, 26, 27, 58, 19, 26, 27, 26, 27, 26, 27, 26, 27, + 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 19, 19, 19, 19, 19, 19, 59, 26, + 27, 60, 61, 62, 62, 26, 27, 63, 64, 65, 26, 27, 26, 27, 26, 27, 26, 27, + 26, 27, 66, 67, 68, 69, 70, 19, 71, 71, 19, 72, 19, 73, 19, 19, 19, 19, + 71, 19, 19, 74, 19, 75, 19, 19, 76, 77, 19, 78, 19, 19, 19, 77, 19, 79, + 80, 19, 19, 81, 19, 19, 19, 19, 19, 19, 19, 82, 19, 19, 83, 19, 19, 83, + 19, 19, 19, 19, 83, 84, 85, 85, 86, 19, 19, 19, 19, 19, 87, 19, 50, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 5, 5, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 49, 49, 49, - 49, 49, 5, 5, 5, 5, 5, 5, 5, 49, 5, 49, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 19, 19, 19, 19, 19, 19, 19, 19, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 5, 5, 5, 5, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 50, 50, 50, + 50, 50, 5, 5, 5, 5, 5, 5, 5, 50, 5, 50, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 84, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 88, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 25, 26, 25, 26, 49, 5, 25, 26, 0, 0, 85, - 44, 44, 44, 5, 0, 0, 0, 0, 0, 5, 5, 86, 17, 87, 87, 87, 0, 88, 0, 89, 89, + 17, 17, 17, 17, 17, 17, 17, 17, 26, 27, 26, 27, 50, 5, 26, 27, 0, 0, 89, + 45, 45, 45, 5, 0, 0, 0, 0, 0, 5, 5, 90, 17, 91, 91, 91, 0, 92, 0, 93, 93, 19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 90, 91, 91, 91, 19, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 92, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 93, 94, 94, 95, 96, 97, 98, 98, 98, 99, 100, 101, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 102, 103, 104, 19, 105, 106, 5, 25, 26, 107, 25, - 26, 19, 57, 57, 57, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 94, 95, 95, 95, 19, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 96, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 97, 98, 98, 99, 100, 101, 102, 102, 102, 103, + 104, 105, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, + 26, 27, 26, 27, 26, 27, 26, 27, 106, 107, 108, 19, 109, 110, 5, 26, 27, + 111, 26, 27, 19, 58, 58, 58, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 103, - 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, - 103, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, - 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 5, - 17, 17, 17, 17, 17, 5, 5, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 109, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, - 26, 25, 26, 110, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 111, 111, 111, 111, 111, 111, 111, - 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, - 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, - 111, 111, 0, 0, 49, 5, 5, 5, 5, 5, 5, 0, 112, 112, 112, 112, 112, 112, - 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, - 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, - 112, 112, 112, 112, 19, 0, 5, 5, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 5, 17, 5, 17, 17, 5, 17, 17, 5, 17, 0, 0, 0, 0, 0, 0, 0, - 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 49, 49, 49, 5, 5, + 16, 16, 16, 16, 16, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, + 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, + 5, 17, 17, 17, 17, 17, 5, 5, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 113, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, + 26, 27, 26, 27, 114, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 115, 115, 115, 115, 115, 115, + 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, + 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, + 115, 115, 115, 0, 0, 50, 5, 5, 5, 5, 5, 5, 0, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 19, 0, 5, 5, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 5, 17, 5, 17, 17, 5, 17, 17, 5, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 50, 50, 50, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 5, 0, 0, 5, 5, 0, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, - 5, 5, 5, 49, 49, 17, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 49, 17, 17, - 17, 17, 17, 17, 17, 1, 5, 17, 17, 17, 17, 17, 17, 49, 49, 17, 17, 5, 17, - 17, 17, 17, 49, 49, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 49, 49, 49, 5, 5, - 49, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 1, 49, 17, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 49, 49, 5, 5, 5, 5, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 17, 49, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 49, 17, 17, 17, 17, 0, 0, 0, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 5, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 5, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 0, - 17, 17, 17, 0, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 49, 49, 0, 0, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 0, 0, 0, 49, 49, 49, - 49, 0, 0, 17, 49, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17, 17, 0, 0, 17, 17, - 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 49, 49, 0, 49, 49, 49, - 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 49, 49, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 17, 17, 17, 0, 49, 49, 49, 49, 49, 49, 0, - 0, 0, 0, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 0, - 49, 49, 0, 49, 49, 0, 49, 49, 0, 0, 17, 0, 17, 17, 17, 17, 17, 0, 0, 0, - 0, 17, 17, 0, 0, 17, 17, 17, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 49, 49, - 49, 49, 0, 49, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 17, 17, 49, 49, 49, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 0, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 0, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, - 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 0, 49, 49, 49, 49, 49, 0, 0, 17, - 49, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 0, 17, 17, 17, 0, 0, - 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 17, 17, 0, 0, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 17, 17, 17, 0, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 49, 49, - 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 0, 49, 49, - 49, 49, 49, 0, 0, 17, 49, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17, 17, 0, 0, - 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 49, 49, 0, 49, - 49, 49, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 49, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 49, 0, 49, 49, 49, 49, 49, 49, - 0, 0, 0, 49, 49, 49, 0, 49, 49, 49, 49, 0, 0, 0, 49, 49, 0, 49, 0, 49, - 49, 0, 0, 0, 49, 49, 0, 0, 0, 49, 49, 49, 0, 0, 0, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 17, 17, 17, 17, 17, 0, 0, 0, 17, - 17, 17, 0, 17, 17, 17, 17, 0, 0, 49, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 17, 17, 17, 0, 49, 49, 49, 49, - 49, 49, 49, 49, 0, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 0, 0, 0, 49, 17, 17, 17, + 5, 5, 5, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 5, 0, 0, 5, 5, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 5, 5, 5, 5, 50, 50, 17, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 5, 50, 17, + 17, 17, 17, 17, 17, 17, 1, 5, 17, 17, 17, 17, 17, 17, 50, 50, 17, 17, 5, + 17, 17, 17, 17, 50, 50, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 50, 50, 50, + 5, 5, 50, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 1, 50, 17, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 50, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 50, 50, 5, 5, 5, 5, 50, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 17, 17, + 17, 17, 50, 17, 17, 17, 17, 17, 17, 17, 17, 17, 50, 17, 17, 17, 50, 17, + 17, 17, 17, 17, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 17, 17, 17, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 17, 17, 17, 50, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 50, 17, 17, 17, + 17, 17, 17, 17, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 17, 17, 5, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 50, 50, 50, 50, 50, 50, 50, 0, 50, + 50, 50, 50, 50, 50, 50, 0, 17, 17, 17, 0, 50, 50, 50, 50, 50, 50, 50, 50, + 0, 0, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 0, 50, + 0, 0, 0, 50, 50, 50, 50, 0, 0, 17, 50, 17, 17, 17, 17, 17, 17, 17, 0, 0, + 17, 17, 0, 0, 17, 17, 17, 50, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 50, + 50, 0, 50, 50, 50, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 50, + 50, 5, 5, 24, 24, 24, 24, 24, 24, 5, 5, 0, 0, 0, 0, 0, 17, 17, 17, 0, 50, + 50, 50, 50, 50, 50, 0, 0, 0, 0, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, + 50, 50, 50, 50, 50, 0, 50, 50, 0, 50, 50, 0, 50, 50, 0, 0, 17, 0, 17, 17, + 17, 17, 17, 0, 0, 0, 0, 17, 17, 0, 0, 17, 17, 17, 0, 0, 0, 17, 0, 0, 0, + 0, 0, 0, 0, 50, 50, 50, 50, 0, 50, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 17, 17, 50, 50, 50, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 17, 17, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 0, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 0, 50, 50, 50, + 50, 50, 0, 0, 17, 50, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 0, + 17, 17, 17, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, + 50, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 0, 50, 50, 50, 50, 50, 50, + 50, 50, 0, 0, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, + 50, 0, 50, 50, 0, 50, 50, 50, 50, 50, 0, 0, 17, 50, 17, 17, 17, 17, 17, + 17, 17, 0, 0, 17, 17, 0, 0, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, + 0, 0, 0, 0, 50, 50, 0, 50, 50, 50, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 5, 50, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 50, 0, 50, 50, 50, 50, 50, 50, 0, 0, 0, 50, 50, 50, 0, 50, 50, 50, + 50, 0, 0, 0, 50, 50, 0, 50, 0, 50, 50, 0, 0, 0, 50, 50, 0, 0, 0, 50, 50, + 50, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 0, 0, 0, 17, 17, 17, 0, 17, 17, 17, 17, 0, 0, 50, 0, + 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 24, 24, 24, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, + 0, 0, 17, 17, 17, 0, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 0, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, + 50, 50, 50, 0, 0, 0, 50, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 0, + 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 50, 50, 0, 0, 0, 0, 0, 0, + 50, 50, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, + 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 5, 0, 0, 17, 17, 0, 50, 50, 50, 50, + 50, 50, 50, 50, 0, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 0, 0, 17, 50, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 0, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, - 17, 17, 0, 49, 49, 0, 0, 0, 0, 0, 0, 49, 49, 17, 17, 0, 0, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, - 0, 0, 17, 17, 0, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 0, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, - 49, 49, 0, 0, 17, 49, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 0, 17, - 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 49, 0, 49, - 49, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 5, 5, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 49, 49, 49, 49, 49, 49, - 49, 49, 0, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 49, 17, 17, 17, 17, 17, - 17, 17, 0, 17, 17, 17, 0, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, - 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 5, 5, 5, 5, 5, 5, 0, 0, 0, 5, 49, 49, 49, 49, 49, 49, 0, 0, 17, - 17, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 0, 49, 0, 0, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 17, 0, 0, 0, 0, - 17, 17, 17, 17, 17, 17, 0, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 5, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, - 49, 113, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 5, 49, 49, 49, 49, 49, - 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 0, 49, 0, 0, - 49, 49, 0, 49, 0, 0, 49, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 0, 49, 49, 49, - 49, 49, 49, 49, 0, 49, 49, 49, 0, 49, 0, 49, 0, 0, 49, 49, 0, 49, 49, 49, - 49, 17, 49, 113, 17, 17, 17, 17, 17, 17, 0, 17, 17, 49, 0, 0, 49, 49, 49, - 49, 49, 0, 49, 0, 17, 17, 17, 17, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 0, 0, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 5, 5, 5, 5, - 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 17, 5, 17, 5, 17, 5, 5, 5, 5, 17, 17, 49, 49, 49, 49, 49, 49, 49, 49, - 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 5, 17, 17, 49, 49, 49, 49, 0, 0, 0, 0, 17, 17, - 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 0, 5, 5, 5, 5, 5, 5, 5, 5, 17, 5, 5, 5, 5, 5, - 5, 0, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 49, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 5, 5, 5, 5, 5, 5, 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, - 49, 49, 49, 49, 17, 17, 17, 49, 17, 17, 17, 49, 49, 17, 17, 17, 17, 17, - 17, 17, 49, 49, 49, 17, 17, 17, 17, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 49, 17, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 5, 5, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 5, 49, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 0, 0, 49, 49, 49, - 49, 49, 49, 49, 0, 49, 0, 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, - 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 0, 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 0, - 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 49, 49, 49, 49, 49, 49, 49, 49, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 0, 0, - 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 5, 5, 5, 124, 124, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, - 49, 49, 49, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, 5, 5, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 0, 17, - 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 1, 1, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 5, 5, 5, 49, 5, 5, 5, 5, 49, 17, 0, 0, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, - 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 17, 2, 0, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, - 0, 0, 5, 0, 0, 0, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 49, 49, 49, 49, - 49, 49, 49, 17, 17, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, - 17, 17, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 17, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 0, 0, 0, 17, 17, 17, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 49, 49, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 0, 0, 0, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 0, 0, 0, 49, 49, 49, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 17, 17, 0, 0, 0, 0, 0, 0, 0, 50, 0, 50, 50, 17, 17, 0, 0, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 0, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 17, 0, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 0, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 0, 0, 50, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 0, 17, + 17, 17, 17, 50, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 50, + 50, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 24, 24, 24, 24, + 24, 0, 0, 0, 5, 50, 50, 50, 50, 50, 50, 0, 0, 17, 17, 0, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 0, 0, 50, + 50, 50, 50, 50, 50, 50, 0, 0, 0, 17, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, + 0, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 17, 50, 117, 17, 17, 17, + 17, 17, 17, 17, 0, 0, 0, 0, 5, 50, 50, 50, 50, 50, 50, 50, 17, 17, 17, + 17, 17, 17, 17, 17, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 0, 50, 0, 0, 50, 50, 0, 50, 0, 0, + 50, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 0, + 50, 50, 50, 0, 50, 0, 50, 0, 0, 50, 50, 0, 50, 50, 50, 50, 17, 50, 117, + 17, 17, 17, 17, 17, 17, 0, 17, 17, 50, 0, 0, 50, 50, 50, 50, 50, 0, 50, + 0, 17, 17, 17, 17, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, + 0, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 5, 5, 5, 5, 5, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 5, 17, + 5, 17, 5, 17, 5, 5, 5, 5, 17, 17, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, + 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 5, 17, 17, 50, 50, 50, 50, 50, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 0, 5, 5, 5, 5, 5, 5, 5, 5, 17, 5, 5, 5, 5, 5, 5, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 50, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 5, 5, 5, 5, 5, 5, 50, 50, 50, 50, 50, 50, 17, 17, 17, 17, 50, 50, + 50, 50, 17, 17, 17, 50, 17, 17, 17, 50, 50, 17, 17, 17, 17, 17, 17, 17, + 50, 50, 50, 17, 17, 17, 17, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 50, 17, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 17, 17, 17, 17, 5, 5, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 5, 50, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 0, 0, 50, 50, + 50, 50, 50, 50, 50, 0, 50, 0, 50, 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 0, 50, 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 0, 50, 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, 0, 50, + 0, 50, 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 17, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 119, 120, 121, 122, 123, 124, 125, 126, 127, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 5, 5, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 2, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 5, 5, 0, 0, 0, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 5, 5, 5, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, + 50, 50, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 17, 17, 17, 5, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 0, 17, 17, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 1, 1, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 5, 5, 5, 50, 5, 5, 5, 5, 50, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, + 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 17, 2, 0, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 17, 50, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 0, 0, 0, 0, 5, 0, 0, 0, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 50, + 50, 50, 50, 50, 50, 50, 17, 17, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 119, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 17, 17, 17, 17, 17, 0, 0, 5, 5, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, + 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 50, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 17, 17, 17, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 0, 0, 0, 50, 50, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, + 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 5, 5, 5, 5, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 50, 50, 50, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 5, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 50, 50, 50, 50, 17, 50, 50, 50, 50, 17, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 49, 125, - 19, 19, 19, 126, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 17, 17, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 19, 19, 19, 19, 19, 127, 19, 19, 128, 19, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 129, 129, 129, 129, 129, 129, 129, 129, 130, 130, - 130, 130, 130, 130, 130, 130, 129, 129, 129, 129, 129, 129, 0, 0, 130, - 130, 130, 130, 130, 130, 0, 0, 129, 129, 129, 129, 129, 129, 129, 129, - 130, 130, 130, 130, 130, 130, 130, 130, 129, 129, 129, 129, 129, 129, - 129, 129, 130, 130, 130, 130, 130, 130, 130, 130, 129, 129, 129, 129, - 129, 129, 0, 0, 130, 130, 130, 130, 130, 130, 0, 0, 19, 129, 19, 129, 19, - 129, 19, 129, 0, 130, 0, 130, 0, 130, 0, 130, 129, 129, 129, 129, 129, - 129, 129, 129, 130, 130, 130, 130, 130, 130, 130, 130, 131, 131, 132, - 132, 132, 132, 133, 133, 134, 134, 135, 135, 136, 136, 0, 0, 129, 129, - 129, 129, 129, 129, 129, 129, 137, 137, 137, 137, 137, 137, 137, 137, - 129, 129, 129, 129, 129, 129, 129, 129, 137, 137, 137, 137, 137, 137, - 137, 137, 129, 129, 129, 129, 129, 129, 129, 129, 137, 137, 137, 137, - 137, 137, 137, 137, 129, 129, 19, 138, 19, 0, 19, 19, 130, 130, 139, 139, - 140, 5, 141, 5, 5, 5, 19, 138, 19, 0, 19, 19, 142, 142, 142, 142, 140, 5, - 5, 5, 129, 129, 19, 19, 0, 0, 19, 19, 130, 130, 143, 143, 0, 5, 5, 5, - 129, 129, 19, 19, 19, 104, 19, 19, 130, 130, 144, 144, 107, 5, 5, 5, 0, - 0, 19, 138, 19, 0, 19, 19, 145, 145, 146, 146, 140, 5, 5, 0, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 3, 1, 1, 1, 1, 1, 2, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 1, 1, 1, 1, - 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 147, 19, 0, 0, 148, 149, 150, 151, - 152, 153, 5, 5, 5, 5, 5, 19, 147, 23, 20, 21, 148, 149, 150, 151, 152, - 153, 5, 5, 5, 5, 5, 0, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 5, 5, 17, 5, - 5, 5, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 98, 5, 5, 5, 5, 98, 5, 5, 19, 98, 98, - 98, 19, 19, 98, 98, 98, 19, 5, 98, 5, 5, 124, 98, 98, 98, 98, 98, 5, 5, - 5, 5, 5, 5, 98, 5, 154, 5, 98, 5, 155, 156, 98, 98, 124, 19, 98, 98, 157, - 98, 19, 49, 49, 49, 49, 19, 5, 5, 19, 19, 98, 98, 5, 5, 5, 5, 5, 98, 19, - 19, 19, 19, 5, 5, 5, 5, 158, 5, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, - 159, 159, 159, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, - 160, 160, 160, 160, 160, 124, 124, 124, 25, 26, 124, 124, 124, 124, 0, 0, - 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 50, 129, + 19, 19, 19, 130, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, + 17, 17, 17, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 19, 19, 19, 19, 19, 131, 19, 19, 132, + 19, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 133, 133, 133, 133, 133, 133, 133, 133, 134, + 134, 134, 134, 134, 134, 134, 134, 133, 133, 133, 133, 133, 133, 0, 0, + 134, 134, 134, 134, 134, 134, 0, 0, 133, 133, 133, 133, 133, 133, 133, + 133, 134, 134, 134, 134, 134, 134, 134, 134, 133, 133, 133, 133, 133, + 133, 133, 133, 134, 134, 134, 134, 134, 134, 134, 134, 133, 133, 133, + 133, 133, 133, 0, 0, 134, 134, 134, 134, 134, 134, 0, 0, 19, 133, 19, + 133, 19, 133, 19, 133, 0, 134, 0, 134, 0, 134, 0, 134, 133, 133, 133, + 133, 133, 133, 133, 133, 134, 134, 134, 134, 134, 134, 134, 134, 135, + 135, 136, 136, 136, 136, 137, 137, 138, 138, 139, 139, 140, 140, 0, 0, + 133, 133, 133, 133, 133, 133, 133, 133, 141, 141, 141, 141, 141, 141, + 141, 141, 133, 133, 133, 133, 133, 133, 133, 133, 141, 141, 141, 141, + 141, 141, 141, 141, 133, 133, 133, 133, 133, 133, 133, 133, 141, 141, + 141, 141, 141, 141, 141, 141, 133, 133, 19, 142, 19, 0, 19, 19, 134, 134, + 143, 143, 144, 5, 145, 5, 5, 5, 19, 142, 19, 0, 19, 19, 146, 146, 146, + 146, 144, 5, 5, 5, 133, 133, 19, 19, 0, 0, 19, 19, 134, 134, 147, 147, 0, + 5, 5, 5, 133, 133, 19, 19, 19, 108, 19, 19, 134, 134, 148, 148, 111, 5, + 5, 5, 0, 0, 19, 142, 19, 0, 19, 19, 149, 149, 150, 150, 144, 5, 5, 0, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 3, 1, 1, 1, 1, 1, 2, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 151, 50, 0, 0, 152, 153, + 154, 155, 156, 157, 5, 5, 5, 5, 5, 50, 151, 23, 20, 21, 152, 153, 154, + 155, 156, 157, 5, 5, 5, 5, 5, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 5, 5, 5, 5, 17, 5, 5, 5, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 102, 5, 5, 5, 5, 102, + 5, 5, 19, 102, 102, 102, 19, 19, 102, 102, 102, 19, 5, 102, 5, 5, 158, + 102, 102, 102, 102, 102, 5, 5, 5, 5, 5, 5, 102, 5, 159, 5, 102, 5, 160, + 161, 102, 102, 158, 19, 102, 102, 162, 102, 19, 50, 50, 50, 50, 19, 5, 5, + 19, 19, 102, 102, 5, 5, 5, 5, 5, 102, 19, 19, 19, 19, 5, 5, 5, 5, 163, 5, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 128, 128, 128, 26, 27, 128, 128, 128, 128, 24, 0, 0, 0, 0, 0, + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, @@ -850,86 +1135,70 @@ static unsigned char index2[] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 23, 20, 21, 148, 149, 150, 151, 152, 153, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 23, 20, 21, 148, 149, 150, 151, 152, 153, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 23, 20, 21, 148, 149, 150, 151, 152, 153, 5, 5, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 20, 21, 152, 153, 154, 155, 156, 157, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 23, 20, 21, 152, 153, 154, 155, + 156, 157, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 23, 20, 21, 152, + 153, 154, 155, 156, 157, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 161, 161, 161, 161, 161, 161, 161, 161, - 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, - 161, 161, 161, 161, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, - 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, - 162, 162, 147, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 23, 20, 21, 148, 149, 150, - 151, 152, 153, 5, 147, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 151, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 23, 20, 21, 152, 153, 154, 155, 156, 157, 24, + 151, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 23, + 20, 21, 152, 153, 154, 155, 156, 157, 24, 23, 20, 21, 152, 153, 154, 155, + 156, 157, 24, 23, 20, 21, 152, 153, 154, 155, 156, 157, 24, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 5, + 5, 5, 5, 0, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 0, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 0, 5, 0, 5, 5, 5, 5, 0, 0, 0, 5, 0, 5, 5, 5, 5, 5, 5, 5, 0, 0, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 23, 20, - 21, 148, 149, 150, 151, 152, 153, 5, 23, 20, 21, 148, 149, 150, 151, 152, - 153, 5, 23, 20, 21, 148, 149, 150, 151, 152, 153, 5, 5, 0, 0, 0, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 0, 5, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 111, - 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, - 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, - 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, - 111, 111, 111, 0, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, - 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, - 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, - 112, 112, 112, 112, 112, 112, 112, 112, 0, 25, 26, 163, 164, 165, 166, - 167, 25, 26, 25, 26, 25, 26, 168, 169, 170, 0, 19, 25, 26, 19, 25, 26, - 19, 19, 19, 19, 19, 19, 49, 0, 0, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 19, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, - 5, 5, 5, 5, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, - 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, - 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, - 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, - 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, - 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, - 49, 49, 49, 49, 49, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 115, 115, 115, 115, + 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, + 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, + 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 0, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 0, 26, 27, 168, 169, 170, 171, 172, 26, 27, 26, + 27, 26, 27, 173, 174, 175, 176, 19, 26, 27, 19, 26, 27, 19, 19, 19, 19, + 19, 19, 50, 177, 177, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 19, 5, 5, 5, + 5, 5, 5, 26, 27, 26, 27, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 24, + 5, 5, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, + 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, + 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, + 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, + 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, + 0, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, + 50, 50, 50, 50, 50, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 85, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 89, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, @@ -941,524 +1210,818 @@ static unsigned char index2[] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, + 0, 0, 2, 5, 5, 5, 5, 50, 50, 128, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 17, 17, 17, 17, 17, 17, 5, 50, 50, 50, 50, 50, 5, 5, 128, 128, + 128, 50, 50, 5, 5, 5, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 0, 0, 17, 17, 5, 5, 50, 50, 50, 5, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 5, 50, 50, 50, 50, 0, 0, 0, + 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 5, 5, 24, 24, 24, 24, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, + 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 0, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 179, 50, 50, 179, + 50, 50, 50, 179, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, + 179, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 179, 179, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 179, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, + 50, 179, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 179, + 179, 179, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 179, 179, 179, 179, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, + 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 179, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 179, 179, 50, 179, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, + 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 2, 5, 5, 5, 5, 49, 49, 124, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 17, 17, 17, 17, 17, 17, 5, 49, 49, 49, - 49, 49, 5, 5, 124, 124, 124, 49, 49, 5, 5, 5, 0, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 17, 17, 5, 5, 49, 49, 49, 5, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, - 49, 49, 49, 49, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 5, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, - 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 0, 0, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 49, 17, 5, 5, 5, 5, 0, 0, - 0, 0, 0, 0, 0, 0, 17, 17, 5, 49, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, - 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 25, 26, 25, 26, 25, 26, 25, - 26, 25, 26, 25, 26, 25, 26, 19, 19, 25, 26, 25, 26, 25, 26, 25, 26, 25, - 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, - 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, - 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 49, - 19, 19, 19, 19, 19, 19, 19, 19, 25, 26, 25, 26, 172, 25, 26, 25, 26, 25, - 26, 25, 26, 25, 26, 49, 5, 5, 25, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 49, 49, 49, 49, 49, 49, 49, 17, 49, 49, 49, 17, 49, 49, 49, 49, 17, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 17, - 17, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 17, 49, 49, 49, 49, 49, 49, - 49, 49, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 5, 5, 5, - 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 5, 5, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 5, 5, 5, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 50, 17, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 5, 50, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, + 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 17, 17, 5, 5, 5, 5, 5, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 50, 50, 50, 50, 50, 50, 50, 50, 50, 5, 5, 26, 27, 26, 27, + 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 19, 19, 26, 27, 26, 27, 26, 27, + 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, + 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, + 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, 26, 27, + 26, 27, 50, 19, 19, 19, 19, 19, 19, 19, 19, 26, 27, 26, 27, 180, 26, 27, + 26, 27, 26, 27, 26, 27, 26, 27, 50, 5, 5, 26, 27, 181, 19, 0, 26, 27, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 27, 26, 27, 26, 27, 26, 27, + 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 50, 50, 50, 50, 50, 50, 50, 17, 50, 50, + 50, 17, 50, 50, 50, 50, 17, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 17, 17, 17, 17, 17, 5, 5, + 5, 5, 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 5, 5, 5, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 50, 50, 50, 50, 50, 50, 5, 5, 5, 50, 0, 0, 0, + 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 17, 17, 17, 17, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 50, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 17, 50, 50, 50, 50, 50, + 50, 50, 50, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 5, 5, + 5, 5, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 5, 5, 5, 50, 17, 0, 0, 0, 0, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 17, 50, 17, 17, 17, 50, 50, 17, 17, 50, 50, + 50, 50, 50, 17, 17, 50, 17, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 50, 50, 50, 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, 0, 0, 50, 50, + 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 0, + 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 17, 17, 17, 17, 17, 17, 17, 17, 5, 17, 17, 0, 0, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, - 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, - 19, 0, 0, 0, 0, 0, 49, 17, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 0, - 49, 0, 49, 49, 0, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 85, 85, 85, 85, 85, 85, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 85, 85, 5, 5, 0, 0, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 17, 17, 17, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 0, 0, 0, 0, 85, 49, 85, 49, 85, 0, - 85, 49, 85, 49, 85, 49, 85, 49, 85, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 1, 0, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, 5, 5, - 5, 5, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 5, 5, 5, 5, 17, 5, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 113, 113, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 49, 49, 49, 49, 49, - 49, 0, 0, 49, 49, 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, 0, 0, 49, - 49, 49, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 1, 1, 5, 5, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 0, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, - 0, 0, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 5, 5, 5, 5, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 124, 49, 49, 49, 49, 49, 49, 49, 49, 124, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 5, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, - 49, 49, 49, 49, 49, 49, 49, 49, 5, 124, 124, 124, 124, 124, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 173, 173, 173, 173, 173, - 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, - 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, - 173, 173, 173, 173, 173, 173, 174, 174, 174, 174, 174, 174, 174, 174, - 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, - 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, - 174, 174, 174, 174, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, - 49, 0, 0, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 0, 0, 0, 49, - 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 5, 5, 5, 5, 0, 0, 0, 0, 0, 5, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, + 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 179, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, + 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 0, 0, 0, 0, + 0, 50, 17, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 5, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 0, 50, 0, 50, 50, + 0, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 89, 89, 89, 89, 89, 89, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 89, 89, 5, 5, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 17, + 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 17, 17, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, + 17, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 5, 5, 5, 5, 0, 0, 0, 0, 89, 50, 89, 50, 89, 0, 89, 50, 89, 50, 89, 50, + 89, 50, 89, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 0, 0, 1, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, 5, 5, 5, 5, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 5, 5, 5, 5, 17, 5, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 117, 117, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 0, 0, 0, 50, 50, 50, 50, 50, 50, 0, 0, 50, 50, 50, + 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, 0, 0, 50, 50, 50, 0, 0, 0, 5, + 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 5, 5, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 0, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, + 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 24, 24, 24, 24, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 24, 0, 0, 0, 0, 0, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 0, 0, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 24, 24, 24, 24, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 128, 50, 50, 50, 50, 50, 50, 50, 50, 128, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 5, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, + 0, 50, 50, 50, 50, 50, 50, 50, 50, 5, 128, 128, 128, 128, 128, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 182, 182, 182, 182, + 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, + 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, + 182, 182, 182, 182, 182, 182, 182, 183, 183, 183, 183, 183, 183, 183, + 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, + 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, + 183, 183, 183, 183, 183, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, + 50, 50, 0, 0, 50, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 0, 0, 0, + 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 0, 5, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 24, 24, 24, 24, 24, 24, 0, 0, 0, 5, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 17, 17, 17, 0, 17, 17, 0, 0, 0, 0, 0, - 17, 17, 17, 17, 49, 49, 49, 49, 0, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 0, 0, 0, 0, 17, 17, 17, 0, 0, 0, 0, 17, 23, 20, 21, 148, 5, - 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 50, 17, 17, 17, 0, 17, 17, 0, 0, 0, 0, 0, 17, 17, + 17, 17, 50, 50, 50, 50, 0, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 0, 0, 0, 0, 17, 17, 17, 0, 0, 0, 0, 17, 23, 20, 21, 152, 24, 24, 24, + 24, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, + 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 24, 24, 5, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 5, + 5, 5, 5, 5, 5, 5, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, + 23, 20, 21, 152, 153, 154, 155, 156, 157, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 17, 17, 17, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 5, 5, 5, 5, + 5, 0, 0, 0, 0, 23, 20, 21, 152, 153, 154, 155, 156, 157, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 1, 5, + 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 158, 158, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 158, 158, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, + 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 17, 17, 17, + 5, 5, 5, 17, 17, 17, 17, 17, 17, 1, 1, 1, 1, 1, 1, 1, 1, 17, 17, 17, 17, + 17, 17, 17, 17, 5, 5, 17, 17, 17, 17, 17, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, + 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 17, 17, 17, 5, 5, 5, 17, 17, 17, 17, - 17, 17, 1, 1, 1, 1, 1, 1, 1, 1, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 17, - 17, 17, 17, 17, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 17, 17, 5, 5, 5, 5, 5, + 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, - 17, 17, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 17, 17, 17, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, - 19, 19, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 19, 19, 19, 19, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 98, 0, 98, 98, 0, 0, 98, 0, 0, 98, 98, 0, 0, 98, 98, 98, - 98, 0, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, 0, 19, 0, 19, 19, - 19, 19, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 98, 98, 0, - 98, 98, 98, 98, 0, 0, 98, 98, 98, 98, 98, 98, 98, 98, 0, 98, 98, 98, 98, - 98, 98, 98, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 98, 98, 0, 98, 98, 98, - 98, 0, 98, 98, 98, 98, 98, 0, 98, 0, 0, 0, 98, 98, 98, 98, 98, 98, 98, 0, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, + 19, 19, 19, 19, 19, 102, 0, 102, 102, 0, 0, 102, 0, 0, 102, 102, 0, 0, + 102, 102, 102, 102, 0, 102, 102, 102, 102, 102, 102, 102, 102, 19, 19, + 19, 19, 0, 19, 0, 19, 19, 19, 19, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 102, 102, 0, 102, 102, 102, 102, + 0, 0, 102, 102, 102, 102, 102, 102, 102, 102, 0, 102, 102, 102, 102, 102, + 102, 102, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 102, 102, 0, 102, 102, 102, + 102, 0, 102, 102, 102, 102, 102, 0, 102, 0, 0, 0, 102, 102, 102, 102, + 102, 102, 102, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, + 19, 19, 19, 19, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, 19, 19, + 19, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, 0, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 5, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 5, 19, 19, 19, 19, 19, 19, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 5, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 5, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 5, 19, 19, 19, - 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 5, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 5, 19, 19, 19, 19, 19, 19, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 5, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 5, 19, 19, 19, 19, + 19, 19, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 5, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 5, 19, 19, 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 5, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 5, 19, 19, 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 5, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 5, 19, 19, 19, 19, 19, 19, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 5, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 5, 19, 19, 19, 19, 19, - 19, 98, 19, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, 5, 5, 5, 5, + 19, 19, 19, 19, 19, 5, 19, 19, 19, 19, 19, 19, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 5, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 5, 19, 19, + 19, 19, 19, 19, 102, 19, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 151, 23, 20, 21, 152, 153, + 154, 155, 156, 157, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, + 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, + 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 0, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, + 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 0, 5, 0, 5, 0, 5, 0, 5, + 5, 5, 0, 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 0, 5, 0, 0, 5, 5, 5, 5, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 179, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 179, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, + 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 179, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 179, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, + 1, 1, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, @@ -1471,18 +2034,1376 @@ static unsigned char index2[] = { 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, }; +/* Returns the numeric value as double for Unicode characters + * having this property, -1.0 otherwise. + */ +double _PyUnicode_ToNumeric(Py_UCS4 ch) +{ + switch (ch) { + case 0x0F33: + return (double) -1.0/2.0; + case 0x0030: + case 0x0660: + case 0x06F0: + case 0x07C0: + case 0x0966: + case 0x09E6: + case 0x0A66: + case 0x0AE6: + case 0x0B66: + case 0x0BE6: + case 0x0C66: + case 0x0C78: + case 0x0CE6: + case 0x0D66: + case 0x0E50: + case 0x0ED0: + case 0x0F20: + case 0x1040: + case 0x1090: + case 0x17E0: + case 0x17F0: + case 0x1810: + case 0x1946: + case 0x19D0: + case 0x1A80: + case 0x1A90: + case 0x1B50: + case 0x1BB0: + case 0x1C40: + case 0x1C50: + case 0x2070: + case 0x2080: + case 0x2189: + case 0x24EA: + case 0x24FF: + case 0x3007: + case 0x96F6: + case 0xA620: + case 0xA6EF: + case 0xA8D0: + case 0xA900: + case 0xA9D0: + case 0xAA50: + case 0xABF0: + case 0xF9B2: + case 0xFF10: + case 0x1018A: + case 0x104A0: + case 0x11066: + case 0x1D7CE: + case 0x1D7D8: + case 0x1D7E2: + case 0x1D7EC: + case 0x1D7F6: + case 0x1F100: + case 0x1F101: + return (double) 0.0; + case 0x0031: + case 0x00B9: + case 0x0661: + case 0x06F1: + case 0x07C1: + case 0x0967: + case 0x09E7: + case 0x0A67: + case 0x0AE7: + case 0x0B67: + case 0x0BE7: + case 0x0C67: + case 0x0C79: + case 0x0C7C: + case 0x0CE7: + case 0x0D67: + case 0x0E51: + case 0x0ED1: + case 0x0F21: + case 0x1041: + case 0x1091: + case 0x1369: + case 0x17E1: + case 0x17F1: + case 0x1811: + case 0x1947: + case 0x19D1: + case 0x19DA: + case 0x1A81: + case 0x1A91: + case 0x1B51: + case 0x1BB1: + case 0x1C41: + case 0x1C51: + case 0x2081: + case 0x215F: + case 0x2160: + case 0x2170: + case 0x2460: + case 0x2474: + case 0x2488: + case 0x24F5: + case 0x2776: + case 0x2780: + case 0x278A: + case 0x3021: + case 0x3192: + case 0x3220: + case 0x3280: + case 0x4E00: + case 0x58F1: + case 0x58F9: + case 0x5E7A: + case 0x5F0C: + case 0xA621: + case 0xA6E6: + case 0xA8D1: + case 0xA901: + case 0xA9D1: + case 0xAA51: + case 0xABF1: + case 0xFF11: + case 0x10107: + case 0x10142: + case 0x10158: + case 0x10159: + case 0x1015A: + case 0x10320: + case 0x103D1: + case 0x104A1: + case 0x10858: + case 0x10916: + case 0x10A40: + case 0x10A7D: + case 0x10B58: + case 0x10B78: + case 0x10E60: + case 0x11052: + case 0x11067: + case 0x12415: + case 0x1241E: + case 0x1242C: + case 0x12434: + case 0x1244F: + case 0x12458: + case 0x1D360: + case 0x1D7CF: + case 0x1D7D9: + case 0x1D7E3: + case 0x1D7ED: + case 0x1D7F7: + case 0x1F102: + case 0x2092A: + return (double) 1.0; + case 0x2152: + return (double) 1.0/10.0; + case 0x09F4: + case 0x0B75: + case 0xA833: + return (double) 1.0/16.0; + case 0x00BD: + case 0x0B73: + case 0x0D74: + case 0x0F2A: + case 0x2CFD: + case 0xA831: + case 0x10141: + case 0x10175: + case 0x10176: + case 0x10E7B: + return (double) 1.0/2.0; + case 0x2153: + case 0x10E7D: + case 0x1245A: + case 0x1245D: + return (double) 1.0/3.0; + case 0x00BC: + case 0x09F7: + case 0x0B72: + case 0x0D73: + case 0xA830: + case 0x10140: + case 0x10E7C: + case 0x12460: + case 0x12462: + return (double) 1.0/4.0; + case 0x2155: + return (double) 1.0/5.0; + case 0x2159: + case 0x12461: + return (double) 1.0/6.0; + case 0x2150: + return (double) 1.0/7.0; + case 0x09F5: + case 0x0B76: + case 0x215B: + case 0xA834: + case 0x1245F: + return (double) 1.0/8.0; + case 0x2151: + return (double) 1.0/9.0; + case 0x0BF0: + case 0x0D70: + case 0x1372: + case 0x2169: + case 0x2179: + case 0x2469: + case 0x247D: + case 0x2491: + case 0x24FE: + case 0x277F: + case 0x2789: + case 0x2793: + case 0x3038: + case 0x3229: + case 0x3289: + case 0x4EC0: + case 0x5341: + case 0x62FE: + case 0xF973: + case 0xF9FD: + case 0x10110: + case 0x10149: + case 0x10150: + case 0x10157: + case 0x10160: + case 0x10161: + case 0x10162: + case 0x10163: + case 0x10164: + case 0x10322: + case 0x103D3: + case 0x1085B: + case 0x10917: + case 0x10A44: + case 0x10B5C: + case 0x10B7C: + case 0x10E69: + case 0x1105B: + case 0x1D369: + return (double) 10.0; + case 0x0BF1: + case 0x0D71: + case 0x137B: + case 0x216D: + case 0x217D: + case 0x4F70: + case 0x767E: + case 0x964C: + case 0x10119: + case 0x1014B: + case 0x10152: + case 0x1016A: + case 0x103D5: + case 0x1085D: + case 0x10919: + case 0x10A46: + case 0x10B5E: + case 0x10B7E: + case 0x10E72: + case 0x11064: + return (double) 100.0; + case 0x0BF2: + case 0x0D72: + case 0x216F: + case 0x217F: + case 0x2180: + case 0x4EDF: + case 0x5343: + case 0x9621: + case 0x10122: + case 0x1014D: + case 0x10154: + case 0x10171: + case 0x1085E: + case 0x10A47: + case 0x10B5F: + case 0x10B7F: + case 0x11065: + return (double) 1000.0; + case 0x137C: + case 0x2182: + case 0x4E07: + case 0x842C: + case 0x1012B: + case 0x10155: + case 0x1085F: + return (double) 10000.0; + case 0x2188: + return (double) 100000.0; + case 0x4EBF: + case 0x5104: + return (double) 100000000.0; + case 0x5146: + return (double) 1000000000000.0; + case 0x216A: + case 0x217A: + case 0x246A: + case 0x247E: + case 0x2492: + case 0x24EB: + return (double) 11.0; + case 0x0F2F: + return (double) 11.0/2.0; + case 0x216B: + case 0x217B: + case 0x246B: + case 0x247F: + case 0x2493: + case 0x24EC: + return (double) 12.0; + case 0x246C: + case 0x2480: + case 0x2494: + case 0x24ED: + return (double) 13.0; + case 0x0F30: + return (double) 13.0/2.0; + case 0x246D: + case 0x2481: + case 0x2495: + case 0x24EE: + return (double) 14.0; + case 0x246E: + case 0x2482: + case 0x2496: + case 0x24EF: + return (double) 15.0; + case 0x0F31: + return (double) 15.0/2.0; + case 0x09F9: + case 0x246F: + case 0x2483: + case 0x2497: + case 0x24F0: + return (double) 16.0; + case 0x16EE: + case 0x2470: + case 0x2484: + case 0x2498: + case 0x24F1: + return (double) 17.0; + case 0x0F32: + return (double) 17.0/2.0; + case 0x16EF: + case 0x2471: + case 0x2485: + case 0x2499: + case 0x24F2: + return (double) 18.0; + case 0x16F0: + case 0x2472: + case 0x2486: + case 0x249A: + case 0x24F3: + return (double) 19.0; + case 0x0032: + case 0x00B2: + case 0x0662: + case 0x06F2: + case 0x07C2: + case 0x0968: + case 0x09E8: + case 0x0A68: + case 0x0AE8: + case 0x0B68: + case 0x0BE8: + case 0x0C68: + case 0x0C7A: + case 0x0C7D: + case 0x0CE8: + case 0x0D68: + case 0x0E52: + case 0x0ED2: + case 0x0F22: + case 0x1042: + case 0x1092: + case 0x136A: + case 0x17E2: + case 0x17F2: + case 0x1812: + case 0x1948: + case 0x19D2: + case 0x1A82: + case 0x1A92: + case 0x1B52: + case 0x1BB2: + case 0x1C42: + case 0x1C52: + case 0x2082: + case 0x2161: + case 0x2171: + case 0x2461: + case 0x2475: + case 0x2489: + case 0x24F6: + case 0x2777: + case 0x2781: + case 0x278B: + case 0x3022: + case 0x3193: + case 0x3221: + case 0x3281: + case 0x3483: + case 0x4E8C: + case 0x5169: + case 0x5F0D: + case 0x5F10: + case 0x8CAE: + case 0x8CB3: + case 0x8D30: + case 0xA622: + case 0xA6E7: + case 0xA8D2: + case 0xA902: + case 0xA9D2: + case 0xAA52: + case 0xABF2: + case 0xF978: + case 0xFF12: + case 0x10108: + case 0x1015B: + case 0x1015C: + case 0x1015D: + case 0x1015E: + case 0x103D2: + case 0x104A2: + case 0x10859: + case 0x1091A: + case 0x10A41: + case 0x10B59: + case 0x10B79: + case 0x10E61: + case 0x11053: + case 0x11068: + case 0x12400: + case 0x12416: + case 0x1241F: + case 0x12423: + case 0x1242D: + case 0x12435: + case 0x1244A: + case 0x12450: + case 0x12459: + case 0x1D361: + case 0x1D7D0: + case 0x1D7DA: + case 0x1D7E4: + case 0x1D7EE: + case 0x1D7F8: + case 0x1F103: + case 0x22390: + return (double) 2.0; + case 0x2154: + case 0x10177: + case 0x10E7E: + case 0x1245B: + case 0x1245E: + return (double) 2.0/3.0; + case 0x2156: + return (double) 2.0/5.0; + case 0x1373: + case 0x2473: + case 0x2487: + case 0x249B: + case 0x24F4: + case 0x3039: + case 0x5344: + case 0x5EFF: + case 0x10111: + case 0x103D4: + case 0x1085C: + case 0x10918: + case 0x10A45: + case 0x10B5D: + case 0x10B7D: + case 0x10E6A: + case 0x1105C: + case 0x1D36A: + return (double) 20.0; + case 0x1011A: + case 0x10E73: + return (double) 200.0; + case 0x10123: + return (double) 2000.0; + case 0x1012C: + return (double) 20000.0; + case 0x3251: + return (double) 21.0; + case 0x3252: + return (double) 22.0; + case 0x3253: + return (double) 23.0; + case 0x3254: + return (double) 24.0; + case 0x3255: + return (double) 25.0; + case 0x3256: + return (double) 26.0; + case 0x3257: + return (double) 27.0; + case 0x3258: + return (double) 28.0; + case 0x3259: + return (double) 29.0; + case 0x0033: + case 0x00B3: + case 0x0663: + case 0x06F3: + case 0x07C3: + case 0x0969: + case 0x09E9: + case 0x0A69: + case 0x0AE9: + case 0x0B69: + case 0x0BE9: + case 0x0C69: + case 0x0C7B: + case 0x0C7E: + case 0x0CE9: + case 0x0D69: + case 0x0E53: + case 0x0ED3: + case 0x0F23: + case 0x1043: + case 0x1093: + case 0x136B: + case 0x17E3: + case 0x17F3: + case 0x1813: + case 0x1949: + case 0x19D3: + case 0x1A83: + case 0x1A93: + case 0x1B53: + case 0x1BB3: + case 0x1C43: + case 0x1C53: + case 0x2083: + case 0x2162: + case 0x2172: + case 0x2462: + case 0x2476: + case 0x248A: + case 0x24F7: + case 0x2778: + case 0x2782: + case 0x278C: + case 0x3023: + case 0x3194: + case 0x3222: + case 0x3282: + case 0x4E09: + case 0x4EE8: + case 0x53C1: + case 0x53C2: + case 0x53C3: + case 0x53C4: + case 0x5F0E: + case 0xA623: + case 0xA6E8: + case 0xA8D3: + case 0xA903: + case 0xA9D3: + case 0xAA53: + case 0xABF3: + case 0xF96B: + case 0xFF13: + case 0x10109: + case 0x104A3: + case 0x1085A: + case 0x1091B: + case 0x10A42: + case 0x10B5A: + case 0x10B7A: + case 0x10E62: + case 0x11054: + case 0x11069: + case 0x12401: + case 0x12408: + case 0x12417: + case 0x12420: + case 0x12424: + case 0x12425: + case 0x1242E: + case 0x1242F: + case 0x12436: + case 0x12437: + case 0x1243A: + case 0x1243B: + case 0x1244B: + case 0x12451: + case 0x1D362: + case 0x1D7D1: + case 0x1D7DB: + case 0x1D7E5: + case 0x1D7EF: + case 0x1D7F9: + case 0x1F104: + case 0x20AFD: + case 0x20B19: + case 0x22998: + case 0x23B1B: + return (double) 3.0; + case 0x09F6: + case 0x0B77: + case 0xA835: + return (double) 3.0/16.0; + case 0x0F2B: + return (double) 3.0/2.0; + case 0x00BE: + case 0x09F8: + case 0x0B74: + case 0x0D75: + case 0xA832: + case 0x10178: + return (double) 3.0/4.0; + case 0x2157: + return (double) 3.0/5.0; + case 0x215C: + return (double) 3.0/8.0; + case 0x1374: + case 0x303A: + case 0x325A: + case 0x5345: + case 0x10112: + case 0x10165: + case 0x10E6B: + case 0x1105D: + case 0x1D36B: + case 0x20983: + return (double) 30.0; + case 0x1011B: + case 0x1016B: + case 0x10E74: + return (double) 300.0; + case 0x10124: + return (double) 3000.0; + case 0x1012D: + return (double) 30000.0; + case 0x325B: + return (double) 31.0; + case 0x325C: + return (double) 32.0; + case 0x325D: + return (double) 33.0; + case 0x325E: + return (double) 34.0; + case 0x325F: + return (double) 35.0; + case 0x32B1: + return (double) 36.0; + case 0x32B2: + return (double) 37.0; + case 0x32B3: + return (double) 38.0; + case 0x32B4: + return (double) 39.0; + case 0x0034: + case 0x0664: + case 0x06F4: + case 0x07C4: + case 0x096A: + case 0x09EA: + case 0x0A6A: + case 0x0AEA: + case 0x0B6A: + case 0x0BEA: + case 0x0C6A: + case 0x0CEA: + case 0x0D6A: + case 0x0E54: + case 0x0ED4: + case 0x0F24: + case 0x1044: + case 0x1094: + case 0x136C: + case 0x17E4: + case 0x17F4: + case 0x1814: + case 0x194A: + case 0x19D4: + case 0x1A84: + case 0x1A94: + case 0x1B54: + case 0x1BB4: + case 0x1C44: + case 0x1C54: + case 0x2074: + case 0x2084: + case 0x2163: + case 0x2173: + case 0x2463: + case 0x2477: + case 0x248B: + case 0x24F8: + case 0x2779: + case 0x2783: + case 0x278D: + case 0x3024: + case 0x3195: + case 0x3223: + case 0x3283: + case 0x4E96: + case 0x56DB: + case 0x8086: + case 0xA624: + case 0xA6E9: + case 0xA8D4: + case 0xA904: + case 0xA9D4: + case 0xAA54: + case 0xABF4: + case 0xFF14: + case 0x1010A: + case 0x104A4: + case 0x10A43: + case 0x10B5B: + case 0x10B7B: + case 0x10E63: + case 0x11055: + case 0x1106A: + case 0x12402: + case 0x12409: + case 0x1240F: + case 0x12418: + case 0x12421: + case 0x12426: + case 0x12430: + case 0x12438: + case 0x1243C: + case 0x1243D: + case 0x1243E: + case 0x1243F: + case 0x1244C: + case 0x12452: + case 0x12453: + case 0x1D363: + case 0x1D7D2: + case 0x1D7DC: + case 0x1D7E6: + case 0x1D7F0: + case 0x1D7FA: + case 0x1F105: + case 0x20064: + case 0x200E2: + case 0x2626D: + return (double) 4.0; + case 0x2158: + return (double) 4.0/5.0; + case 0x1375: + case 0x32B5: + case 0x534C: + case 0x10113: + case 0x10E6C: + case 0x1105E: + case 0x1D36C: + case 0x2098C: + case 0x2099C: + return (double) 40.0; + case 0x1011C: + case 0x10E75: + return (double) 400.0; + case 0x10125: + return (double) 4000.0; + case 0x1012E: + return (double) 40000.0; + case 0x32B6: + return (double) 41.0; + case 0x32B7: + return (double) 42.0; + case 0x32B8: + return (double) 43.0; + case 0x32B9: + return (double) 44.0; + case 0x32BA: + return (double) 45.0; + case 0x32BB: + return (double) 46.0; + case 0x32BC: + return (double) 47.0; + case 0x32BD: + return (double) 48.0; + case 0x32BE: + return (double) 49.0; + case 0x0035: + case 0x0665: + case 0x06F5: + case 0x07C5: + case 0x096B: + case 0x09EB: + case 0x0A6B: + case 0x0AEB: + case 0x0B6B: + case 0x0BEB: + case 0x0C6B: + case 0x0CEB: + case 0x0D6B: + case 0x0E55: + case 0x0ED5: + case 0x0F25: + case 0x1045: + case 0x1095: + case 0x136D: + case 0x17E5: + case 0x17F5: + case 0x1815: + case 0x194B: + case 0x19D5: + case 0x1A85: + case 0x1A95: + case 0x1B55: + case 0x1BB5: + case 0x1C45: + case 0x1C55: + case 0x2075: + case 0x2085: + case 0x2164: + case 0x2174: + case 0x2464: + case 0x2478: + case 0x248C: + case 0x24F9: + case 0x277A: + case 0x2784: + case 0x278E: + case 0x3025: + case 0x3224: + case 0x3284: + case 0x3405: + case 0x382A: + case 0x4E94: + case 0x4F0D: + case 0xA625: + case 0xA6EA: + case 0xA8D5: + case 0xA905: + case 0xA9D5: + case 0xAA55: + case 0xABF5: + case 0xFF15: + case 0x1010B: + case 0x10143: + case 0x10148: + case 0x1014F: + case 0x1015F: + case 0x10173: + case 0x10321: + case 0x104A5: + case 0x10E64: + case 0x11056: + case 0x1106B: + case 0x12403: + case 0x1240A: + case 0x12410: + case 0x12419: + case 0x12422: + case 0x12427: + case 0x12431: + case 0x12439: + case 0x1244D: + case 0x12454: + case 0x12455: + case 0x1D364: + case 0x1D7D3: + case 0x1D7DD: + case 0x1D7E7: + case 0x1D7F1: + case 0x1D7FB: + case 0x1F106: + case 0x20121: + return (double) 5.0; + case 0x0F2C: + return (double) 5.0/2.0; + case 0x215A: + case 0x1245C: + return (double) 5.0/6.0; + case 0x215D: + return (double) 5.0/8.0; + case 0x1376: + case 0x216C: + case 0x217C: + case 0x2186: + case 0x32BF: + case 0x10114: + case 0x10144: + case 0x1014A: + case 0x10151: + case 0x10166: + case 0x10167: + case 0x10168: + case 0x10169: + case 0x10174: + case 0x10323: + case 0x10A7E: + case 0x10E6D: + case 0x1105F: + case 0x1D36D: + return (double) 50.0; + case 0x216E: + case 0x217E: + case 0x1011D: + case 0x10145: + case 0x1014C: + case 0x10153: + case 0x1016C: + case 0x1016D: + case 0x1016E: + case 0x1016F: + case 0x10170: + case 0x10E76: + return (double) 500.0; + case 0x2181: + case 0x10126: + case 0x10146: + case 0x1014E: + case 0x10172: + return (double) 5000.0; + case 0x2187: + case 0x1012F: + case 0x10147: + case 0x10156: + return (double) 50000.0; + case 0x0036: + case 0x0666: + case 0x06F6: + case 0x07C6: + case 0x096C: + case 0x09EC: + case 0x0A6C: + case 0x0AEC: + case 0x0B6C: + case 0x0BEC: + case 0x0C6C: + case 0x0CEC: + case 0x0D6C: + case 0x0E56: + case 0x0ED6: + case 0x0F26: + case 0x1046: + case 0x1096: + case 0x136E: + case 0x17E6: + case 0x17F6: + case 0x1816: + case 0x194C: + case 0x19D6: + case 0x1A86: + case 0x1A96: + case 0x1B56: + case 0x1BB6: + case 0x1C46: + case 0x1C56: + case 0x2076: + case 0x2086: + case 0x2165: + case 0x2175: + case 0x2185: + case 0x2465: + case 0x2479: + case 0x248D: + case 0x24FA: + case 0x277B: + case 0x2785: + case 0x278F: + case 0x3026: + case 0x3225: + case 0x3285: + case 0x516D: + case 0x9646: + case 0x9678: + case 0xA626: + case 0xA6EB: + case 0xA8D6: + case 0xA906: + case 0xA9D6: + case 0xAA56: + case 0xABF6: + case 0xF9D1: + case 0xF9D3: + case 0xFF16: + case 0x1010C: + case 0x104A6: + case 0x10E65: + case 0x11057: + case 0x1106C: + case 0x12404: + case 0x1240B: + case 0x12411: + case 0x1241A: + case 0x12428: + case 0x12440: + case 0x1244E: + case 0x1D365: + case 0x1D7D4: + case 0x1D7DE: + case 0x1D7E8: + case 0x1D7F2: + case 0x1D7FC: + case 0x1F107: + case 0x20AEA: + return (double) 6.0; + case 0x1377: + case 0x10115: + case 0x10E6E: + case 0x11060: + case 0x1D36E: + return (double) 60.0; + case 0x1011E: + case 0x10E77: + return (double) 600.0; + case 0x10127: + return (double) 6000.0; + case 0x10130: + return (double) 60000.0; + case 0x0037: + case 0x0667: + case 0x06F7: + case 0x07C7: + case 0x096D: + case 0x09ED: + case 0x0A6D: + case 0x0AED: + case 0x0B6D: + case 0x0BED: + case 0x0C6D: + case 0x0CED: + case 0x0D6D: + case 0x0E57: + case 0x0ED7: + case 0x0F27: + case 0x1047: + case 0x1097: + case 0x136F: + case 0x17E7: + case 0x17F7: + case 0x1817: + case 0x194D: + case 0x19D7: + case 0x1A87: + case 0x1A97: + case 0x1B57: + case 0x1BB7: + case 0x1C47: + case 0x1C57: + case 0x2077: + case 0x2087: + case 0x2166: + case 0x2176: + case 0x2466: + case 0x247A: + case 0x248E: + case 0x24FB: + case 0x277C: + case 0x2786: + case 0x2790: + case 0x3027: + case 0x3226: + case 0x3286: + case 0x3B4D: + case 0x4E03: + case 0x67D2: + case 0x6F06: + case 0xA627: + case 0xA6EC: + case 0xA8D7: + case 0xA907: + case 0xA9D7: + case 0xAA57: + case 0xABF7: + case 0xFF17: + case 0x1010D: + case 0x104A7: + case 0x10E66: + case 0x11058: + case 0x1106D: + case 0x12405: + case 0x1240C: + case 0x12412: + case 0x1241B: + case 0x12429: + case 0x12441: + case 0x12442: + case 0x12443: + case 0x1D366: + case 0x1D7D5: + case 0x1D7DF: + case 0x1D7E9: + case 0x1D7F3: + case 0x1D7FD: + case 0x1F108: + case 0x20001: + return (double) 7.0; + case 0x0F2D: + return (double) 7.0/2.0; + case 0x215E: + return (double) 7.0/8.0; + case 0x1378: + case 0x10116: + case 0x10E6F: + case 0x11061: + case 0x1D36F: + return (double) 70.0; + case 0x1011F: + case 0x10E78: + return (double) 700.0; + case 0x10128: + return (double) 7000.0; + case 0x10131: + return (double) 70000.0; + case 0x0038: + case 0x0668: + case 0x06F8: + case 0x07C8: + case 0x096E: + case 0x09EE: + case 0x0A6E: + case 0x0AEE: + case 0x0B6E: + case 0x0BEE: + case 0x0C6E: + case 0x0CEE: + case 0x0D6E: + case 0x0E58: + case 0x0ED8: + case 0x0F28: + case 0x1048: + case 0x1098: + case 0x1370: + case 0x17E8: + case 0x17F8: + case 0x1818: + case 0x194E: + case 0x19D8: + case 0x1A88: + case 0x1A98: + case 0x1B58: + case 0x1BB8: + case 0x1C48: + case 0x1C58: + case 0x2078: + case 0x2088: + case 0x2167: + case 0x2177: + case 0x2467: + case 0x247B: + case 0x248F: + case 0x24FC: + case 0x277D: + case 0x2787: + case 0x2791: + case 0x3028: + case 0x3227: + case 0x3287: + case 0x516B: + case 0x634C: + case 0xA628: + case 0xA6ED: + case 0xA8D8: + case 0xA908: + case 0xA9D8: + case 0xAA58: + case 0xABF8: + case 0xFF18: + case 0x1010E: + case 0x104A8: + case 0x10E67: + case 0x11059: + case 0x1106E: + case 0x12406: + case 0x1240D: + case 0x12413: + case 0x1241C: + case 0x1242A: + case 0x12444: + case 0x12445: + case 0x1D367: + case 0x1D7D6: + case 0x1D7E0: + case 0x1D7EA: + case 0x1D7F4: + case 0x1D7FE: + case 0x1F109: + return (double) 8.0; + case 0x1379: + case 0x10117: + case 0x10E70: + case 0x11062: + case 0x1D370: + return (double) 80.0; + case 0x10120: + case 0x10E79: + return (double) 800.0; + case 0x10129: + return (double) 8000.0; + case 0x10132: + return (double) 80000.0; + case 0x0039: + case 0x0669: + case 0x06F9: + case 0x07C9: + case 0x096F: + case 0x09EF: + case 0x0A6F: + case 0x0AEF: + case 0x0B6F: + case 0x0BEF: + case 0x0C6F: + case 0x0CEF: + case 0x0D6F: + case 0x0E59: + case 0x0ED9: + case 0x0F29: + case 0x1049: + case 0x1099: + case 0x1371: + case 0x17E9: + case 0x17F9: + case 0x1819: + case 0x194F: + case 0x19D9: + case 0x1A89: + case 0x1A99: + case 0x1B59: + case 0x1BB9: + case 0x1C49: + case 0x1C59: + case 0x2079: + case 0x2089: + case 0x2168: + case 0x2178: + case 0x2468: + case 0x247C: + case 0x2490: + case 0x24FD: + case 0x277E: + case 0x2788: + case 0x2792: + case 0x3029: + case 0x3228: + case 0x3288: + case 0x4E5D: + case 0x5EFE: + case 0x7396: + case 0xA629: + case 0xA6EE: + case 0xA8D9: + case 0xA909: + case 0xA9D9: + case 0xAA59: + case 0xABF9: + case 0xFF19: + case 0x1010F: + case 0x104A9: + case 0x10E68: + case 0x1105A: + case 0x1106F: + case 0x12407: + case 0x1240E: + case 0x12414: + case 0x1241D: + case 0x1242B: + case 0x12446: + case 0x12447: + case 0x12448: + case 0x12449: + case 0x1D368: + case 0x1D7D7: + case 0x1D7E1: + case 0x1D7EB: + case 0x1D7F5: + case 0x1D7FF: + case 0x1F10A: + case 0x2F890: + return (double) 9.0; + case 0x0F2E: + return (double) 9.0/2.0; + case 0x137A: + case 0x10118: + case 0x10341: + case 0x10E71: + case 0x11063: + case 0x1D371: + return (double) 90.0; + case 0x10121: + case 0x1034A: + case 0x10E7A: + return (double) 900.0; + case 0x1012A: + return (double) 9000.0; + case 0x10133: + return (double) 90000.0; + } + return -1.0; +} + +/* Returns 1 for Unicode characters having the bidirectional + * type 'WS', 'B' or 'S' or the category 'Zs', 0 otherwise. + */ +int _PyUnicode_IsWhitespace(register const Py_UCS4 ch) +{ + switch (ch) { + case 0x0009: + case 0x000A: + case 0x000B: + case 0x000C: + case 0x000D: + case 0x001C: + case 0x001D: + case 0x001E: + case 0x001F: + case 0x0020: + case 0x0085: + case 0x00A0: + case 0x1680: + case 0x180E: + case 0x2000: + case 0x2001: + case 0x2002: + case 0x2003: + case 0x2004: + case 0x2005: + case 0x2006: + case 0x2007: + case 0x2008: + case 0x2009: + case 0x200A: + case 0x2028: + case 0x2029: + case 0x202F: + case 0x205F: + case 0x3000: + return 1; + } + return 0; +} + +/* Returns 1 for Unicode characters having the line break + * property 'BK', 'CR', 'LF' or 'NL' or having bidirectional + * type 'B', 0 otherwise. + */ +int _PyUnicode_IsLinebreak(register const Py_UCS4 ch) +{ + switch (ch) { + case 0x000A: + case 0x000B: + case 0x000C: + case 0x000D: + case 0x001C: + case 0x001D: + case 0x001E: + case 0x0085: + case 0x2028: + case 0x2029: + return 1; + } + return 0; +} + diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c index f43b68d..13323cf 100644 --- a/Objects/weakrefobject.c +++ b/Objects/weakrefobject.c @@ -139,7 +139,7 @@ weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw) } -static long +static Py_hash_t weakref_hash(PyWeakReference *self) { if (self->hash != -1) @@ -583,7 +583,7 @@ proxy_iternext(PyWeakReference *proxy) } -WRAP_METHOD(proxy_bytes, "__bytes__"); +WRAP_METHOD(proxy_bytes, "__bytes__") static PyMethodDef proxy_methods[] = { |