2014-05-03 18:27:38 -04:00
|
|
|
/*
|
2017-06-30 03:22:17 -04:00
|
|
|
* This file is part of the MicroPython project, http://micropython.org/
|
2014-05-03 18:27:38 -04:00
|
|
|
*
|
|
|
|
* The MIT License (MIT)
|
|
|
|
*
|
|
|
|
* Copyright (c) 2013, 2014 Damien P. George
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
* THE SOFTWARE.
|
|
|
|
*/
|
all: Unify header guard usage.
The code conventions suggest using header guards, but do not define how
those should look like and instead point to existing files. However, not
all existing files follow the same scheme, sometimes omitting header guards
altogether, sometimes using non-standard names, making it easy to
accidentally pick a "wrong" example.
This commit ensures that all header files of the MicroPython project (that
were not simply copied from somewhere else) follow the same pattern, that
was already present in the majority of files, especially in the py folder.
The rules are as follows.
Naming convention:
* start with the words MICROPY_INCLUDED
* contain the full path to the file
* replace special characters with _
In addition, there are no empty lines before #ifndef, between #ifndef and
one empty line before #endif. #endif is followed by a comment containing
the name of the guard macro.
py/grammar.h cannot use header guards by design, since it has to be
included multiple times in a single C file. Several other files also do not
need header guards as they are only used internally and guaranteed to be
included only once:
* MICROPY_MPHALPORT_H
* mpconfigboard.h
* mpconfigport.h
* mpthreadport.h
* pin_defs_*.h
* qstrdefs*.h
2017-06-29 17:14:58 -04:00
|
|
|
#ifndef MICROPY_INCLUDED_PY_MPZ_H
|
|
|
|
#define MICROPY_INCLUDED_PY_MPZ_H
|
2015-01-01 15:27:54 -05:00
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
#include "py/mpconfig.h"
|
|
|
|
#include "py/misc.h"
|
2014-05-03 18:27:38 -04:00
|
|
|
|
2014-09-06 12:15:34 -04:00
|
|
|
// This mpz module implements arbitrary precision integers.
|
|
|
|
//
|
|
|
|
// The storage for each digit is defined by mpz_dig_t. The actual number of
|
|
|
|
// bits in mpz_dig_t that are used is defined by MPZ_DIG_SIZE. The machine must
|
|
|
|
// also provide a type that is twice as wide as mpz_dig_t, in both signed and
|
|
|
|
// unsigned versions.
|
|
|
|
//
|
|
|
|
// MPZ_DIG_SIZE can be between 4 and 8*sizeof(mpz_dig_t), but it makes most
|
2015-03-28 17:45:57 -04:00
|
|
|
// sense to have it as large as possible. If MPZ_DIG_SIZE is not already
|
|
|
|
// defined then it is auto-detected below, depending on the machine. The types
|
|
|
|
// are then set based on the value of MPZ_DIG_SIZE (although they can be freely
|
|
|
|
// changed so long as the constraints mentioned above are met).
|
2014-09-06 12:15:34 -04:00
|
|
|
|
2015-03-28 17:45:57 -04:00
|
|
|
#ifndef MPZ_DIG_SIZE
|
|
|
|
#if defined(__x86_64__) || defined(_WIN64)
|
2021-03-15 09:57:36 -04:00
|
|
|
// 64-bit machine, using 32-bit storage for digits
|
2015-03-28 17:45:57 -04:00
|
|
|
#define MPZ_DIG_SIZE (32)
|
|
|
|
#else
|
2021-03-15 09:57:36 -04:00
|
|
|
// default: 32-bit machine, using 16-bit storage for digits
|
2015-03-28 17:45:57 -04:00
|
|
|
#define MPZ_DIG_SIZE (16)
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if MPZ_DIG_SIZE > 16
|
2017-12-27 22:02:36 -05:00
|
|
|
#define MPZ_DBL_DIG_SIZE (64)
|
2014-09-06 12:15:34 -04:00
|
|
|
typedef uint32_t mpz_dig_t;
|
|
|
|
typedef uint64_t mpz_dbl_dig_t;
|
|
|
|
typedef int64_t mpz_dbl_dig_signed_t;
|
2015-03-28 17:45:57 -04:00
|
|
|
#elif MPZ_DIG_SIZE > 8
|
2017-12-27 22:02:36 -05:00
|
|
|
#define MPZ_DBL_DIG_SIZE (32)
|
2014-02-22 14:25:23 -05:00
|
|
|
typedef uint16_t mpz_dig_t;
|
|
|
|
typedef uint32_t mpz_dbl_dig_t;
|
|
|
|
typedef int32_t mpz_dbl_dig_signed_t;
|
2015-03-28 17:45:57 -04:00
|
|
|
#elif MPZ_DIG_SIZE > 4
|
2017-12-27 22:02:36 -05:00
|
|
|
#define MPZ_DBL_DIG_SIZE (16)
|
2015-03-28 17:45:57 -04:00
|
|
|
typedef uint8_t mpz_dig_t;
|
|
|
|
typedef uint16_t mpz_dbl_dig_t;
|
|
|
|
typedef int16_t mpz_dbl_dig_signed_t;
|
|
|
|
#else
|
2017-12-27 22:02:36 -05:00
|
|
|
#define MPZ_DBL_DIG_SIZE (8)
|
2015-03-28 17:45:57 -04:00
|
|
|
typedef uint8_t mpz_dig_t;
|
|
|
|
typedef uint8_t mpz_dbl_dig_t;
|
|
|
|
typedef int8_t mpz_dbl_dig_signed_t;
|
2014-09-06 12:15:34 -04:00
|
|
|
#endif
|
|
|
|
|
2014-10-30 09:39:22 -04:00
|
|
|
#ifdef _WIN64
|
2015-11-20 09:59:06 -05:00
|
|
|
#ifdef __MINGW32__
|
|
|
|
#define MPZ_LONG_1 1LL
|
|
|
|
#else
|
|
|
|
#define MPZ_LONG_1 1i64
|
|
|
|
#endif
|
2014-10-30 09:39:22 -04:00
|
|
|
#else
|
|
|
|
#define MPZ_LONG_1 1L
|
|
|
|
#endif
|
|
|
|
|
2015-09-15 11:15:57 -04:00
|
|
|
// these define the maximum storage needed to hold an int or long long
|
|
|
|
#define MPZ_NUM_DIG_FOR_INT ((sizeof(mp_int_t) * 8 + MPZ_DIG_SIZE - 1) / MPZ_DIG_SIZE)
|
|
|
|
#define MPZ_NUM_DIG_FOR_LL ((sizeof(long long) * 8 + MPZ_DIG_SIZE - 1) / MPZ_DIG_SIZE)
|
2014-02-22 14:25:23 -05:00
|
|
|
|
|
|
|
typedef struct _mpz_t {
|
2021-11-29 08:31:46 -05:00
|
|
|
// Zero has neg=0, len=0. Negative zero is not allowed.
|
2017-02-15 23:50:28 -05:00
|
|
|
size_t neg : 1;
|
|
|
|
size_t fixed_dig : 1;
|
2020-03-09 19:09:49 -04:00
|
|
|
size_t alloc : (8 * sizeof(size_t) - 2);
|
2017-02-15 23:50:28 -05:00
|
|
|
size_t len;
|
2014-02-22 14:25:23 -05:00
|
|
|
mpz_dig_t *dig;
|
|
|
|
} mpz_t;
|
|
|
|
|
2014-03-01 14:50:50 -05:00
|
|
|
// convenience macro to declare an mpz with a digit array from the stack, initialised by an integer
|
2021-03-15 09:57:36 -04:00
|
|
|
#define MPZ_CONST_INT(z, val) mpz_t z; mpz_dig_t z##_digits[MPZ_NUM_DIG_FOR_INT]; mpz_init_fixed_from_int(&z, z_digits, MPZ_NUM_DIG_FOR_INT, val);
|
2014-02-22 14:25:23 -05:00
|
|
|
|
|
|
|
void mpz_init_zero(mpz_t *z);
|
2014-07-03 08:25:24 -04:00
|
|
|
void mpz_init_from_int(mpz_t *z, mp_int_t val);
|
2017-02-15 23:50:28 -05:00
|
|
|
void mpz_init_fixed_from_int(mpz_t *z, mpz_dig_t *dig, size_t dig_alloc, mp_int_t val);
|
2014-02-22 14:25:23 -05:00
|
|
|
void mpz_deinit(mpz_t *z);
|
|
|
|
|
|
|
|
void mpz_set(mpz_t *dest, const mpz_t *src);
|
2014-07-03 08:25:24 -04:00
|
|
|
void mpz_set_from_int(mpz_t *z, mp_int_t src);
|
2014-09-10 17:10:33 -04:00
|
|
|
void mpz_set_from_ll(mpz_t *z, long long i, bool is_signed);
|
2015-01-02 07:39:22 -05:00
|
|
|
#if MICROPY_PY_BUILTINS_FLOAT
|
|
|
|
void mpz_set_from_float(mpz_t *z, mp_float_t src);
|
|
|
|
#endif
|
2017-02-15 23:59:51 -05:00
|
|
|
size_t mpz_set_from_str(mpz_t *z, const char *str, size_t len, bool neg, unsigned int base);
|
2017-02-15 23:50:28 -05:00
|
|
|
void mpz_set_from_bytes(mpz_t *z, bool big_endian, size_t len, const byte *buf);
|
2014-02-22 14:25:23 -05:00
|
|
|
|
2021-03-15 09:57:36 -04:00
|
|
|
static inline bool mpz_is_zero(const mpz_t *z) {
|
|
|
|
return z->len == 0;
|
|
|
|
}
|
|
|
|
static inline bool mpz_is_neg(const mpz_t *z) {
|
2021-11-29 08:31:46 -05:00
|
|
|
return z->neg != 0;
|
2021-03-15 09:57:36 -04:00
|
|
|
}
|
2014-10-03 13:44:14 -04:00
|
|
|
int mpz_cmp(const mpz_t *lhs, const mpz_t *rhs);
|
2014-02-22 14:25:23 -05:00
|
|
|
|
|
|
|
void mpz_abs_inpl(mpz_t *dest, const mpz_t *z);
|
|
|
|
void mpz_neg_inpl(mpz_t *dest, const mpz_t *z);
|
2014-03-01 14:50:50 -05:00
|
|
|
void mpz_not_inpl(mpz_t *dest, const mpz_t *z);
|
2015-10-01 13:01:37 -04:00
|
|
|
void mpz_shl_inpl(mpz_t *dest, const mpz_t *lhs, mp_uint_t rhs);
|
|
|
|
void mpz_shr_inpl(mpz_t *dest, const mpz_t *lhs, mp_uint_t rhs);
|
2014-02-22 14:25:23 -05:00
|
|
|
void mpz_add_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
|
|
|
|
void mpz_sub_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
|
|
|
|
void mpz_mul_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
|
|
|
|
void mpz_pow_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
|
2017-02-01 18:41:22 -05:00
|
|
|
void mpz_pow3_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs, const mpz_t *mod);
|
2014-03-22 19:52:36 -04:00
|
|
|
void mpz_and_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
|
|
|
|
void mpz_or_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
|
|
|
|
void mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
|
2014-02-22 14:25:23 -05:00
|
|
|
void mpz_divmod_inpl(mpz_t *dest_quo, mpz_t *dest_rem, const mpz_t *lhs, const mpz_t *rhs);
|
|
|
|
|
2021-03-15 09:57:36 -04:00
|
|
|
static inline size_t mpz_max_num_bits(const mpz_t *z) {
|
|
|
|
return z->len * MPZ_DIG_SIZE;
|
|
|
|
}
|
2023-10-19 16:42:36 -04:00
|
|
|
// CIRCUITPY-CHANGE
|
2020-04-28 10:13:49 -04:00
|
|
|
static inline size_t mpz_num_bits(const mpz_t *z) {
|
2021-06-01 22:57:55 -04:00
|
|
|
if (mpz_is_zero(z)) {
|
2021-06-01 23:10:41 -04:00
|
|
|
return 0;
|
2021-06-01 22:57:55 -04:00
|
|
|
}
|
2021-03-15 09:57:36 -04:00
|
|
|
size_t last_bits = (8 * (sizeof(long) - sizeof(mpz_dig_t))) - __builtin_clzl(z->dig[z->len - 1]);
|
|
|
|
return z->len * MPZ_DIG_SIZE + last_bits;
|
|
|
|
}
|
2014-07-24 09:21:37 -04:00
|
|
|
mp_int_t mpz_hash(const mpz_t *z);
|
2014-07-03 08:25:24 -04:00
|
|
|
bool mpz_as_int_checked(const mpz_t *z, mp_int_t *value);
|
2014-07-31 09:41:43 -04:00
|
|
|
bool mpz_as_uint_checked(const mpz_t *z, mp_uint_t *value);
|
2017-02-15 23:50:28 -05:00
|
|
|
void mpz_as_bytes(const mpz_t *z, bool big_endian, size_t len, byte *buf);
|
2014-06-01 08:32:54 -04:00
|
|
|
#if MICROPY_PY_BUILTINS_FLOAT
|
2014-03-08 10:04:54 -05:00
|
|
|
mp_float_t mpz_as_float(const mpz_t *z);
|
|
|
|
#endif
|
2017-02-15 23:59:51 -05:00
|
|
|
size_t mpz_as_str_inpl(const mpz_t *z, unsigned int base, const char *prefix, char base_char, char comma, char *str);
|
2015-01-01 15:27:54 -05:00
|
|
|
|
all: Unify header guard usage.
The code conventions suggest using header guards, but do not define how
those should look like and instead point to existing files. However, not
all existing files follow the same scheme, sometimes omitting header guards
altogether, sometimes using non-standard names, making it easy to
accidentally pick a "wrong" example.
This commit ensures that all header files of the MicroPython project (that
were not simply copied from somewhere else) follow the same pattern, that
was already present in the majority of files, especially in the py folder.
The rules are as follows.
Naming convention:
* start with the words MICROPY_INCLUDED
* contain the full path to the file
* replace special characters with _
In addition, there are no empty lines before #ifndef, between #ifndef and
one empty line before #endif. #endif is followed by a comment containing
the name of the guard macro.
py/grammar.h cannot use header guards by design, since it has to be
included multiple times in a single C file. Several other files also do not
need header guards as they are only used internally and guaranteed to be
included only once:
* MICROPY_MPHALPORT_H
* mpconfigboard.h
* mpconfigport.h
* mpthreadport.h
* pin_defs_*.h
* qstrdefs*.h
2017-06-29 17:14:58 -04:00
|
|
|
#endif // MICROPY_INCLUDED_PY_MPZ_H
|