text:
# User Documentation for the IMath Library

Author: [M. J. Fromberger](https://github.com/creachadair)

## Installation

1. Edit Makefile to select compiler and options.  The default is to use gcc.
   You may want to change CC to `clang` instead of `gcc` (and on macOS that
   what you will get anyway), but you should be able to use the default GCC
   settings for either.

   By default, the Makefile assumes you can use 64-bit integer types, even
   though they were not standard in ISO/IEC 9899:1990. If you cannot, add
   `-DUSE_32BIT_WORDS` to the compiler options.

2. Type `make` or `make test` to build the test driver and run the unit tests.
   None of these should fail.  If they do, see below for how you can report
   bugs.

   To build with debugging enabled (and optimization disabled), run `make
   DEBUG=Y`.  This sets the preprocessor macro `DEBUG` to 1, and several other
   things (see Makefile for details).

To use the library in your code, include "imath.h" wherever you intend to use
the library's routines.  The integer library is just a single source file, so
you can compile it into your project in whatever way makes sense.  If you wish
to use rational arithmetic, you will also need to include "imrat.h".

## Background

The basic types defined by the imath library are `mpz_t`, an arbitrary
precision signed integer, and `mpq_t`, an arbitrary precision signed rational
number.  The type `mp_int` is a pointer to an `mpz_t`, and `mp_rat` is a
pointer to an `mpq_t`.

Most of the functions in the imath library return a value of type `mp_result`.
This is a signed integer type which can be used to convey status information
and also return small values.  Any negative value is considered to be a status
message.  The following constants are defined for processing these:

| Status      | Description                                  |
| ----------- | -------------------------------------------- |
| `MP_OK`     | operation successful, all is well (= 0)      |
| `MP_FALSE`  | boolean false (= `MP_OK`)                    |
| `MP_TRUE`   | boolean true                                 |
| `MP_MEMORY` | out of memory                                |
| `MP_RANGE`  | parameter out of range                       |
| `MP_UNDEF`  | result is undefined (e.g., division by zero) |
| `MP_TRUNC`  | output value was truncated                   |
| `MP_BADARG` | an invalid parameter was passed              |

If you obtain a zero or negative value of an `mp_result`, you can use the
`mp_error_string()` routine to obtain a pointer to a brief human-readable
string describing the error.  These strings are statically allocated, so they
need not be freed by the caller; the same strings are re-used from call to
call.

Unless otherwise noted, it is legal to use the same parameter for both inputs
and output with most of the functions in this library.  For example, you can
add a number to itself and replace the original by writing:

    mp_int_add(a, a, a);  /* a = a + a */

Any cases in which this is not legal will be noted in the function summaries
below (if you discover that this is not so, please report it as a bug; I will
fix either the function or the documentation :)

## The IMath API

Each of the API functions is documented here.  The general format of the
entries is:

> ------------
>

> return_type function_name(parameters ...)
>

>  -  English description.

Unless otherwise noted, any API function that returns `mp_result` may be
expected to return `MP_OK`, `MP_BADARG`, or `MP_MEMORY`.  Other return values
should be documented in the description.  Please let me know if you discover
this is not the case.

The following macros are defined in "imath.h", to define the sizes of the
various data types used in the library:

| Constant        | Description
| --------------- | ----------------------------------------
| `MP_DIGIT_BIT`  | the number of bits in a single `mpz_t` digit.
| `MP_WORD_BIT`   | the number of bits in a `mpz_t` word.
| `MP_SMALL_MIN`  | the minimum value representable by an `mp_small`.
| `MP_SMALL_MAX`  | the maximum value representable by an `mp_small`.
| `MP_USMALL_MAX` | the maximum value representable by an `mp_usmall`.
| `MP_MIN_RADIX`  | the minimum radix accepted for base conversion.
| `MP_MAX_RADIX`  | the maximum radix accepted for base conversion.

### Initialization

An `mp_int` must be initialized before use. By default, an `mp_int` is
initialized with a certain minimum amount of storage for digits, and the
storage is expanded automatically as needed.  To initialize an `mp_int`, use
the following functions:

------------

mp_result mp_int_init(mp_int z);

 -  Initializes `z` with 1-digit precision and sets it to zero.  This function
    cannot fail unless `z == NULL`.

------------

mp_int mp_int_alloc(void);

 -  Allocates a fresh zero-valued `mpz_t` on the heap, returning NULL in case
    of error. The only possible error is out-of-memory.

------------

mp_result mp_int_init_size(mp_int z, mp_size prec);

 -  Initializes `z` with at least `prec` digits of storage, and sets it to
    zero. If `prec` is zero, the default precision is used. In either case the
    size is rounded up to the nearest multiple of the word size.

------------

mp_result mp_int_init_copy(mp_int z, mp_int old);

 -  Initializes `z` to be a copy of an already-initialized value in `old`. The
    new copy does not share storage with the original.

------------

mp_result mp_int_init_value(mp_int z, mp_small value);

 -  Initializes `z` to the specified signed `value` at default precision.

### Cleanup

When you are finished with an `mp_int`, you must free the memory it uses:

------------

void mp_int_clear(mp_int z);

 -  Releases the storage used by `z`.

------------

void mp_int_free(mp_int z);

 -  Releases the storage used by `z` and also `z` itself.
    This should only be used for `z` allocated by `mp_int_alloc()`.

### Setting Values

To set an `mp_int` which has already been initialized to a small integer value,
use:

------------

mp_result mp_int_set_value(mp_int z, mp_small value);

 -  Sets `z` to the value of the specified signed `value`.

------------

mp_result mp_int_set_uvalue(mp_int z, mp_usmall uvalue);

 -  Sets `z` to the value of the specified unsigned `value`.

To copy one initialized `mp_int` to another, use:

------------

mp_result mp_int_copy(mp_int a, mp_int c);

 -  Replaces the value of `c` with a copy of the value of `a`. No new memory is
    allocated unless `a` has more significant digits than `c` has allocated.

### Arithmetic Functions

------------

static inline bool mp_int_is_odd(mp_int z);

 -  Reports whether `z` is odd, having remainder 1 when divided by 2.

------------

static inline bool mp_int_is_even(mp_int z);

 -  Reports whether `z` is even, having remainder 0 when divided by 2.

------------

void mp_int_zero(mp_int z);

 -  Sets `z` to zero. The allocated storage of `z` is not changed.

------------

mp_result mp_int_abs(mp_int a, mp_int c);

 -  Sets `c` to the absolute value of `a`.

------------

mp_result mp_int_neg(mp_int a, mp_int c);

 -  Sets `c` to the additive inverse (negation) of `a`.

------------

mp_result mp_int_add(mp_int a, mp_int b, mp_int c);

 -  Sets `c` to the sum of `a` and `b`.

------------

mp_result mp_int_add_value(mp_int a, mp_small value, mp_int c);

 -  Sets `c` to the sum of `a` and `value`.

------------

mp_result mp_int_sub(mp_int a, mp_int b, mp_int c);

 -  Sets `c` to the difference of `a` less `b`.

------------

mp_result mp_int_sub_value(mp_int a, mp_small value, mp_int c);

 -  Sets `c` to the difference of `a` less `value`.

------------

mp_result mp_int_mul(mp_int a, mp_int b, mp_int c);

 -  Sets `c` to the product of `a` and `b`.

------------

mp_result mp_int_mul_value(mp_int a, mp_small value, mp_int c);

 -  Sets `c` to the product of `a` and `value`.

------------

mp_result mp_int_mul_pow2(mp_int a, mp_small p2, mp_int c);

 -  Sets `c` to the product of `a` and `2^p2`. Requires `p2 >= 0`.

------------

mp_result mp_int_sqr(mp_int a, mp_int c);

 -  Sets `c` to the square of `a`.

------------

mp_result mp_int_root(mp_int a, mp_small b, mp_int c);

 -  Sets `c` to the greatest integer not less than the `b`th root of `a`,
    using Newton's root-finding algorithm.
    It returns `MP_UNDEF` if `a < 0` and `b` is even.

------------

static inline mp_result mp_int_sqrt(mp_int a, mp_int c);

 -  Sets `c` to the greatest integer not less than the square root of `a`.
    This is a special case of `mp_int_root()`.

------------

mp_result mp_int_div(mp_int a, mp_int b, mp_int q, mp_int r);

 -  Sets `q` and `r` to the quotent and remainder of `a / b`. Division by
    powers of 2 is detected and handled efficiently.  The remainder is pinned
    to `0 <= r < b`.

    Either of `q` or `r` may be NULL, but not both, and `q` and `r` may not
    point to the same value.

------------

mp_result mp_int_div_value(mp_int a, mp_small value, mp_int q, mp_small *r);

 -  Sets `q` and `*r` to the quotent and remainder of `a / value`. Division by
    powers of 2 is detected and handled efficiently. The remainder is pinned to
    `0 <= *r < b`. Either of `q` or `r` may be NULL.

------------

mp_result mp_int_div_pow2(mp_int a, mp_small p2, mp_int q, mp_int r);

 -  Sets `q` and `r` to the quotient and remainder of `a / 2^p2`. This is a
    special case for division by powers of two that is more efficient than
    using ordinary division. Note that `mp_int_div()` will automatically handle
    this case, this function is for cases where you have only the exponent.

------------

mp_result mp_int_mod(mp_int a, mp_int m, mp_int c);

 -  Sets `c` to the remainder of `a / m`.
    The remainder is pinned to `0 <= c < m`.

------------

static inline mp_result mp_int_mod_value(mp_int a, mp_small value, mp_small* r);

 -  Sets `*r` to the remainder of `a / value`.
    The remainder is pinned to `0 <= r < value`.

------------

mp_result mp_int_expt(mp_int a, mp_small b, mp_int c);

 -  Sets `c` to the value of `a` raised to the `b` power.
    It returns `MP_RANGE` if `b < 0`.

------------

mp_result mp_int_expt_value(mp_small a, mp_small b, mp_int c);

 -  Sets `c` to the value of `a` raised to the `b` power.
    It returns `MP_RANGE` if `b < 0`.

------------

mp_result mp_int_expt_full(mp_int a, mp_int b, mp_int c);

 -  Sets `c` to the value of `a` raised to the `b` power.
    It returns `MP_RANGE`) if `b < 0`.

### Comparison Functions

Unless otherwise specified, comparison between values `x` and `y` returns a
**comparator**, an integer value < 0 if `x` is less than `y`, 0 if `x` is equal
to `y`, and > 0 if `x` is greater than `y`.

------------

int mp_int_compare(mp_int a, mp_int b);

 -  Returns the comparator of `a` and `b`.

------------

int mp_int_compare_unsigned(mp_int a, mp_int b);

 -  Returns the comparator of the magnitudes of `a` and `b`, disregarding their
    signs. Neither `a` nor `b` is modified by the comparison.

------------

int mp_int_compare_zero(mp_int z);

 -  Returns the comparator of `z` and zero.

------------

int mp_int_compare_value(mp_int z, mp_small v);

 -  Returns the comparator of `z` and the signed value `v`.

------------

int mp_int_compare_uvalue(mp_int z, mp_usmall uv);

 -  Returns the comparator of `z` and the unsigned value `uv`.

------------

bool mp_int_divisible_value(mp_int a, mp_small v);

 -  Reports whether `a` is divisible by `v`.

------------

int mp_int_is_pow2(mp_int z);

 -  Returns `k >= 0` such that `z` is `2^k`, if such a `k` exists. If no such
    `k` exists, the function returns -1.

### Modular Operations

------------

mp_result mp_int_exptmod(mp_int a, mp_int b, mp_int m, mp_int c);

 -  Sets `c` to the value of `a` raised to the `b` power, reduced modulo `m`.
    It returns `MP_RANGE` if `b < 0` or `MP_UNDEF` if `m == 0`.

------------

mp_result mp_int_exptmod_evalue(mp_int a, mp_small value, mp_int m, mp_int c);

 -  Sets `c` to the value of `a` raised to the `value` power, modulo `m`.
    It returns `MP_RANGE` if `value < 0` or `MP_UNDEF` if `m == 0`.

------------

mp_result mp_int_exptmod_bvalue(mp_small value, mp_int b, mp_int m, mp_int c);

 -  Sets `c` to the value of `value` raised to the `b` power, modulo `m`.
    It returns `MP_RANGE` if `b < 0` or `MP_UNDEF` if `m == 0`.

------------

mp_result mp_int_exptmod_known(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c);

 -  Sets `c` to the value of `a` raised to the `b` power, reduced modulo `m`,
    given a precomputed reduction constant `mu` defined for Barrett's modular
    reduction algorithm.

    It returns `MP_RANGE` if `b < 0` or `MP_UNDEF` if `m == 0`.

------------

mp_result mp_int_redux_const(mp_int m, mp_int c);

 -  Sets `c` to the reduction constant for Barrett reduction by modulus `m`.
    Requires that `c` and `m` point to distinct locations.

------------

mp_result mp_int_invmod(mp_int a, mp_int m, mp_int c);

 -  Sets `c` to the multiplicative inverse of `a` modulo `m`, if it exists.
    The least non-negative representative of the congruence class is computed.

    It returns `MP_UNDEF` if the inverse does not exist, or `MP_RANGE` if `a ==
    0` or `m <= 0`.

------------

mp_result mp_int_gcd(mp_int a, mp_int b, mp_int c);

 -  Sets `c` to the greatest common divisor of `a` and `b`.

    It returns `MP_UNDEF` if the GCD is undefined, such as for example if `a`
    and `b` are both zero.

------------

mp_result mp_int_egcd(mp_int a, mp_int b, mp_int c, mp_int x, mp_int y);

 -  Sets `c` to the greatest common divisor of `a` and `b`, and sets `x` and
    `y` to values satisfying Bezout's identity `gcd(a, b) = ax + by`.

    It returns `MP_UNDEF` if the GCD is undefined, such as for example if `a`
    and `b` are both zero.

------------

mp_result mp_int_lcm(mp_int a, mp_int b, mp_int c);

 -  Sets `c` to the least common multiple of `a` and `b`.

    It returns `MP_UNDEF` if the LCM is undefined, such as for example if `a`
    and `b` are both zero.

### Conversion of Values

------------

mp_result mp_int_to_int(mp_int z, mp_small *out);

 -  Returns `MP_OK` if `z` is representable as `mp_small`, else `MP_RANGE`.
    If `out` is not NULL, `*out` is set to the value of `z` when `MP_OK`.

------------

mp_result mp_int_to_uint(mp_int z, mp_usmall *out);

 -  Returns `MP_OK` if `z` is representable as `mp_usmall`, or `MP_RANGE`.
    If `out` is not NULL, `*out` is set to the value of `z` when `MP_OK`.

------------

mp_result mp_int_to_string(mp_int z, mp_size radix, char *str, int limit);

 -  Converts `z` to a zero-terminated string of characters in the specified
    `radix`, writing at most `limit` characters to `str` including the
    terminating NUL value. A leading `-` is used to indicate a negative value.

    Returns `MP_TRUNC` if `limit` was to small to write all of `z`.
    Requires `MP_MIN_RADIX <= radix <= MP_MAX_RADIX`.

------------

mp_result mp_int_string_len(mp_int z, mp_size radix);

 -  Reports the minimum number of characters required to represent `z` as a
    zero-terminated string in the given `radix`.
    Requires `MP_MIN_RADIX <= radix <= MP_MAX_RADIX`.

------------

mp_result mp_int_read_string(mp_int z, mp_size radix, const char *str);

 -  Reads a string of ASCII digits in the specified `radix` from the zero
    terminated `str` provided into `z`. For values of `radix > 10`, the letters
    `A`..`Z` or `a`..`z` are accepted. Letters are interpreted without respect
    to case.

    Leading whitespace is ignored, and a leading `+` or `-` is interpreted as a
    sign flag. Processing stops when a NUL or any other character out of range
    for a digit in the given radix is encountered.

    If the whole string was consumed, `MP_OK` is returned; otherwise
    `MP_TRUNC`. is returned.

    Requires `MP_MIN_RADIX <= radix <= MP_MAX_RADIX`.

------------

mp_result mp_int_read_cstring(mp_int z, mp_size radix, const char *str, char **end);

 -  Reads a string of ASCII digits in the specified `radix` from the zero
    terminated `str` provided into `z`. For values of `radix > 10`, the letters
    `A`..`Z` or `a`..`z` are accepted. Letters are interpreted without respect
    to case.

    Leading whitespace is ignored, and a leading `+` or `-` is interpreted as a
    sign flag. Processing stops when a NUL or any other character out of range
    for a digit in the given radix is encountered.

    If the whole string was consumed, `MP_OK` is returned; otherwise
    `MP_TRUNC`. is returned. If `end` is not NULL, `*end` is set to point to
    the first unconsumed byte of the input string (the NUL byte if the whole
    string was consumed). This emulates the behavior of the standard C
    `strtol()` function.

    Requires `MP_MIN_RADIX <= radix <= MP_MAX_RADIX`.

------------

mp_result mp_int_count_bits(mp_int z);

 -  Returns the number of significant bits in `z`.

------------

mp_result mp_int_to_binary(mp_int z, unsigned char *buf, int limit);

 -  Converts `z` to 2's complement binary, writing at most `limit` bytes into
    the given `buf`.  Returns `MP_TRUNC` if the buffer limit was too small to
    contain the whole value.  If this occurs, the contents of buf will be
    effectively garbage, as the function uses the buffer as scratch space.

    The binary representation of `z` is in base-256 with digits ordered from
    most significant to least significant (network byte ordering).  The
    high-order bit of the first byte is set for negative values, clear for
    non-negative values.

    As a result, non-negative values will be padded with a leading zero byte if
    the high-order byte of the base-256 magnitude is set.  This extra byte is
    accounted for by the `mp_int_binary_len()` function.

------------

mp_result mp_int_read_binary(mp_int z, unsigned char *buf, int len);

 -  Reads a 2's complement binary value from `buf` into `z`, where `len` is the
    length of the buffer.  The contents of `buf` may be overwritten during
    processing, although they will be restored when the function returns.

------------

mp_result mp_int_binary_len(mp_int z);

 -  Returns the number of bytes to represent `z` in 2's complement binary.

------------

mp_result mp_int_to_unsigned(mp_int z, unsigned char *buf, int limit);

 -  Converts the magnitude of `z` to unsigned binary, writing at most `limit`
    bytes into the given `buf`.  The sign of `z` is ignored, but `z` is not
    modified.  Returns `MP_TRUNC` if the buffer limit was too small to contain
    the whole value.  If this occurs, the contents of `buf` will be effectively
    garbage, as the function uses the buffer as scratch space during
    conversion.

    The binary representation of `z` is in base-256 with digits ordered from
    most significant to least significant (network byte ordering).

------------

mp_result mp_int_read_unsigned(mp_int z, unsigned char *buf, int len);

 -  Reads an unsigned binary value from `buf` into `z`, where `len` is the
    length of the buffer. The contents of `buf` are not modified during
    processing.

------------

mp_result mp_int_unsigned_len(mp_int z);

 -  Returns the number of bytes required to represent `z` as an unsigned binary
    value in base 256.

### Other Functions

Ordinarily, integer multiplication and squaring are done using the simple
quadratic "schoolbook" algorithm.  However, for sufficiently large values,
there is a more efficient algorithm usually attributed to Karatsuba and Ofman
that is usually faster.  See Knuth Vol. 2 for more details about how this
algorithm works.

The breakpoint between the "normal" and the recursive algorithm is controlled
by a static digit threshold defined in `imath.c`. Values with fewer significant
digits use the standard algorithm.  This value can be modified by calling
`mp_int_multiply_threshold(n)`.  The `imtimer` program and the
`findthreshold.py` script (Python) can help you find a suitable value for for
your particular platform.

------------

const char *mp_error_string(mp_result res);

 -  Returns a pointer to a brief, human-readable, zero-terminated string
    describing `res`. The returned string is statically allocated and must not
    be freed by the caller.

## Rational Arithmetic

------------

mp_result mp_rat_init(mp_rat r);

 -  Initializes `r` with 1-digit precision and sets it to zero. This function
    cannot fail unless `r` is NULL.

------------

mp_rat mp_rat_alloc(void);

 -  Allocates a fresh zero-valued `mpq_t` on the heap, returning NULL in case
    of error. The only possible error is out-of-memory.

------------

mp_result mp_rat_reduce(mp_rat r);

 -  Reduces `r` in-place to lowest terms and canonical form.

    Zero is represented as 0/1, one as 1/1, and signs are adjusted so that the
    sign of the value is carried by the numerator.

------------

mp_result mp_rat_init_size(mp_rat r, mp_size n_prec, mp_size d_prec);

 -  Initializes `r` with at least `n_prec` digits of storage for the numerator
    and `d_prec` digits of storage for the denominator, and value zero.

    If either precision is zero, the default precision is used, rounded up to
    the nearest word size.

------------

mp_result mp_rat_init_copy(mp_rat r, mp_rat old);

 -  Initializes `r` to be a copy of an already-initialized value in `old`. The
    new copy does not share storage with the original.

------------

mp_result mp_rat_set_value(mp_rat r, mp_small numer, mp_small denom);

 -  Sets the value of `r` to the ratio of signed `numer` to signed `denom`.  It
    returns `MP_UNDEF` if `denom` is zero.

------------

mp_result mp_rat_set_uvalue(mp_rat r, mp_usmall numer, mp_usmall denom);

 -  Sets the value of `r` to the ratio of unsigned `numer` to unsigned
    `denom`. It returns `MP_UNDEF` if `denom` is zero.

------------

void mp_rat_clear(mp_rat r);

 -  Releases the storage used by `r`.

------------

void mp_rat_free(mp_rat r);

 -  Releases the storage used by `r` and also `r` itself.
    This should only be used for `r` allocated by `mp_rat_alloc()`.

------------

mp_result mp_rat_numer(mp_rat r, mp_int z);

 -  Sets `z` to a copy of the numerator of `r`.

------------

mp_int mp_rat_numer_ref(mp_rat r);

 -  Returns a pointer to the numerator of `r`.

------------

mp_result mp_rat_denom(mp_rat r, mp_int z);

 -  Sets `z` to a copy of the denominator of `r`.

------------

mp_int mp_rat_denom_ref(mp_rat r);

 -  Returns a pointer to the denominator of `r`.

------------

mp_sign mp_rat_sign(mp_rat r);

 -  Reports the sign of `r`.

------------

mp_result mp_rat_copy(mp_rat a, mp_rat c);

 -  Sets `c` to a copy of the value of `a`. No new memory is allocated unless a
    term of `a` has more significant digits than the corresponding term of `c`
    has allocated.

------------

void mp_rat_zero(mp_rat r);

 -  Sets `r` to zero. The allocated storage of `r` is not changed.

------------

mp_result mp_rat_abs(mp_rat a, mp_rat c);

 -  Sets `c` to the absolute value of `a`.

------------

mp_result mp_rat_neg(mp_rat a, mp_rat c);

 -  Sets `c` to the absolute value of `a`.

------------

mp_result mp_rat_recip(mp_rat a, mp_rat c);

 -  Sets `c` to the reciprocal of `a` if the reciprocal is defined.
    It returns `MP_UNDEF` if `a` is zero.

------------

mp_result mp_rat_add(mp_rat a, mp_rat b, mp_rat c);

 -  Sets `c` to the sum of `a` and `b`.

------------

mp_result mp_rat_sub(mp_rat a, mp_rat b, mp_rat c);

 -  Sets `c` to the difference of `a` less `b`.

------------

mp_result mp_rat_mul(mp_rat a, mp_rat b, mp_rat c);

 -  Sets `c` to the product of `a` and `b`.

------------

mp_result mp_rat_div(mp_rat a, mp_rat b, mp_rat c);

 -  Sets `c` to the ratio `a / b` if that ratio is defined.
    It returns `MP_UNDEF` if `b` is zero.

------------

mp_result mp_rat_add_int(mp_rat a, mp_int b, mp_rat c);

 -  Sets `c` to the sum of `a` and integer `b`.

------------

mp_result mp_rat_sub_int(mp_rat a, mp_int b, mp_rat c);

 -  Sets `c` to the difference of `a` less integer `b`.

------------

mp_result mp_rat_mul_int(mp_rat a, mp_int b, mp_rat c);

 -  Sets `c` to the product of `a` and integer `b`.

------------

mp_result mp_rat_div_int(mp_rat a, mp_int b, mp_rat c);

 -  Sets `c` to the ratio `a / b` if that ratio is defined.
    It returns `MP_UNDEF` if `b` is zero.

------------

mp_result mp_rat_expt(mp_rat a, mp_small b, mp_rat c);

 -  Sets `c` to the value of `a` raised to the `b` power.
    It returns `MP_RANGE` if `b < 0`.

------------

int mp_rat_compare(mp_rat a, mp_rat b);

 -  Returns the comparator of `a` and `b`.

------------

int mp_rat_compare_unsigned(mp_rat a, mp_rat b);

 -  Returns the comparator of the magnitudes of `a` and `b`, disregarding their
    signs. Neither `a` nor `b` is modified by the comparison.

------------

int mp_rat_compare_zero(mp_rat r);

 -  Returns the comparator of `r` and zero.

------------

int mp_rat_compare_value(mp_rat r, mp_small n, mp_small d);

 -  Returns the comparator of `r` and the signed ratio `n / d`.
    It returns `MP_UNDEF` if `d` is zero.

------------

bool mp_rat_is_integer(mp_rat r);

 -  Reports whether `r` is an integer, having canonical denominator 1.

------------

mp_result mp_rat_to_ints(mp_rat r, mp_small *num, mp_small *den);

 -  Reports whether the numerator and denominator of `r` can be represented as
    small signed integers, and if so stores the corresponding values to `num`
    and `den`. It returns `MP_RANGE` if either cannot be so represented.

------------

mp_result mp_rat_to_string(mp_rat r, mp_size radix, char *str, int limit);

 -  Converts `r` to a zero-terminated string of the format `"n/d"` with `n` and
    `d` in the specified radix and writing no more than `limit` bytes to the
    given output buffer `str`. The output of the numerator includes a sign flag
    if `r` is negative.  Requires `MP_MIN_RADIX <= radix <= MP_MAX_RADIX`.

------------

mp_result mp_rat_to_decimal(mp_rat r, mp_size radix, mp_size prec, mp_round_mode round, char *str, int limit);

 -  Converts the value of `r` to a string in decimal-point notation with the
    specified radix, writing no more than `limit` bytes of data to the given
    output buffer.  It generates `prec` digits of precision, and requires
    `MP_MIN_RADIX <= radix <= MP_MAX_RADIX`.

    Ratios usually must be rounded when they are being converted for output as
    a decimal value.  There are four rounding modes currently supported:

    ```
      MP_ROUND_DOWN
        Truncates the value toward zero.
        Example:  12.009 to 2dp becomes 12.00
    ```

    ```
      MP_ROUND_UP
        Rounds the value away from zero:
        Example:  12.001 to 2dp becomes 12.01, but
                  12.000 to 2dp remains 12.00
    ```

    ```
      MP_ROUND_HALF_DOWN
         Rounds the value to nearest digit, half goes toward zero.
         Example:  12.005 to 2dp becomes 12.00, but
                   12.006 to 2dp becomes 12.01
    ```

    ```
      MP_ROUND_HALF_UP
         Rounds the value to nearest digit, half rounds upward.
         Example:  12.005 to 2dp becomes 12.01, but
                   12.004 to 2dp becomes 12.00
    ```

------------

mp_result mp_rat_string_len(mp_rat r, mp_size radix);

 -  Reports the minimum number of characters required to represent `r` as a
    zero-terminated string in the given `radix`.
    Requires `MP_MIN_RADIX <= radix <= MP_MAX_RADIX`.

------------

mp_result mp_rat_decimal_len(mp_rat r, mp_size radix, mp_size prec);

 -  Reports the length in bytes of the buffer needed to convert `r` using the
    `mp_rat_to_decimal()` function with the specified `radix` and `prec`. The
    buffer size estimate may slightly exceed the actual required capacity.

------------

mp_result mp_rat_read_string(mp_rat r, mp_size radix, const char *str);

 -  Sets `r` to the value represented by a zero-terminated string `str` in the
    format `"n/d"` including a sign flag. It returns `MP_UNDEF` if the encoded
    denominator has value zero.

------------

mp_result mp_rat_read_cstring(mp_rat r, mp_size radix, const char *str, char **end);

 -  Sets `r` to the value represented by a zero-terminated string `str` in the
    format `"n/d"` including a sign flag. It returns `MP_UNDEF` if the encoded
    denominator has value zero. If `end` is not NULL then `*end` is set to
    point to the first unconsumed character in the string, after parsing.

------------

mp_result mp_rat_read_ustring(mp_rat r, mp_size radix, const char *str, char **end);

 -  Sets `r` to the value represented by a zero-terminated string `str` having
    one of the following formats, each with an optional leading sign flag:

    ```
       n         : integer format, e.g. "123"
       n/d       : ratio format, e.g., "-12/5"
       z.ffff    : decimal format, e.g., "1.627"
    ```

    It returns `MP_UNDEF` if the effective denominator is zero. If `end` is not
    NULL then `*end` is set to point to the first unconsumed character in the
    string, after parsing.

------------

mp_result mp_rat_read_decimal(mp_rat r, mp_size radix, const char *str);

 -  Sets `r` to the value represented by a zero-terminated string `str` in the
    format `"z.ffff"` including a sign flag. It returns `MP_UNDEF` if the
    effective denominator is zero.

------------

mp_result mp_rat_read_cdecimal(mp_rat r, mp_size radix, const char *str, char **end);

 -  Sets `r` to the value represented by a zero-terminated string `str` in the
    format `"z.ffff"` including a sign flag. It returns `MP_UNDEF` if the
    effective denominator is zero.
    If `end` is not NULL then `*end` is set to point to
    the first unconsumed character in the string, after parsing.

## Representation Details

> NOTE: You do not need to read this section to use IMath.  This is provided
> for the benefit of developers wishing to extend or modify the internals of
> the library.

IMath uses a signed magnitude representation for arbitrary precision integers.
The magnitude is represented as an array of radix-R digits in increasing order
of significance; the value of R is chosen to be half the size of the largest
available unsigned integer type, so typically 16 or 32 bits.  Digits are
represented as mp_digit, which must be an unsigned integral type.

Digit arrays are allocated using `malloc(3)` and `realloc(3)`.  Because this
can be an expensive operation, the library takes pains to avoid allocation as
much as possible.  For this reason, the `mpz_t` structure distinguishes between
how many digits are allocated and how many digits are actually consumed by the
representation.  The fields of an `mpz_t` are:

    mp_digit    single;  /* single-digit value (see note) */
    mp_digit   *digits;  /* array of digits               */
    mp_size     alloc;   /* how many digits are allocated */
    mp_size     used;    /* how many digits are in use    */
    mp_sign     sign;    /* the sign of the value         */

The elements of `digits` at indices less than `used` are the significant
figures of the value; the elements at indices greater than or equal to `used`
are undefined (and may contain garbage).  At all times, `used` must be at least
1 and at most `alloc`.

To avoid interaction with the memory allocator, single-digit values are stored
directly in the `mpz_t` structure, in the `single` field.  The semantics of
access are the same as the more general case.

The number of digits allocated for an `mpz_t` is referred to in the library
documentation as its "precision".  Operations that affect an `mpz_t` cause
precision to increase as needed.  In any case, all allocations are measured in
digits, and rounded up to the nearest `mp_word` boundary.  There is a default
minimum precision stored as a static constant default_precision (`imath.c`).
This value can be set using `mp_int_default_precision(n)`.

Note that the allocated size of an `mpz_t` can only grow; the library never
reallocates in order to decrease the size.  A simple way to do so explicitly is
to use `mp_int_init_copy()`, as in:

```
mpz_t big, new;

/* ... */
mp_int_init_copy(&new, &big);
mp_int_swap(&new, &big);
mp_int_clear(&new);
```

The value of `sign` is 0 for positive values and zero, 1 for negative values.
Constants `MP_ZPOS` and `MP_NEG` are defined for these; no other sign values
are used.

If you are adding to this library, you should be careful to preserve the
convention that inputs and outputs can overlap, as described above.  So, for
example, `mp_int_add(a, a, a)` is legal.  Often, this means you must maintain
one or more temporary mpz_t structures for intermediate values.  The private
macros `DECLARE_TEMP(N)`, `CLEANUP_TEMP()`, and `TEMP(K)` can be used to
maintain a conventional structure like this:

```c
{
  /* Declare how many temp values you need.
	 Use TEMP(i) to access the ith value (0-indexed). */
  DECLARE_TEMP(8);
  ...

  /* Perform actions that must return MP_OK or fail. */
  REQUIRE(mp_int_copy(x, TEMP(1)));
  ...
  REQUIRE(mp_int_expt(TEMP(1), TEMP(2), TEMP(3)));
  ...

  /* You can also use REQUIRE directly for more complex cases. */
  if (some_difficult_question(TEMP(3)) != answer(x)) {
	REQUIRE(MP_RANGE);  /* falls through to cleanup (below) */
  }

  /* Ensure temporary values are cleaned up at exit.

     If control reaches here via a REQUIRE failure, the code below
	 the cleanup will not be executed.
   */
  CLEANUP_TEMP();
  return MP_OK;
}
```

Under the covers, these macros are just maintaining an array of `mpz_t` values,
and a jump label to handle cleanup. You may only have one `DECLARE_TEMP` and
its corresponding `CLEANUP_TEMP` per function body.

"Small" integer values are represented by the types `mp_small` and `mp_usmall`,
which are mapped to appropriately-sized types on the host system.  The default
for `mp_small` is "long" and the default for `mp_usmall` is "unsigned long".
You may change these, provided you insure that `mp_small` is signed and
`mp_usmall` is unsigned.  You will also need to adjust the size macros:

    MP_SMALL_MIN, MP_SMALL_MAX
    MP_USMALL_MIN, MP_USMALL_MAX

... which are defined in `<imath.h>`, if you change these.

Rational numbers are represented using a pair of arbitrary precision integers,
with the convention that the sign of the numerator is the sign of the rational
value, and that the result of any rational operation is always represented in
lowest terms.  The canonical representation for rational zero is 0/1.  See
"imrat.h".

## Testing and Reporting of Bugs

Test vectors are included in the `tests/` subdirectory of the imath
distribution.  When you run `make test`, it builds the `imtest` program and
runs all available test vectors.  If any tests fail, you will get a line like
this:

    x    y    FAILED      v

Here, _x_ is the line number of the test which failed, _y_ is index of the test
within the file, and _v_ is the value(s) actually computed.  The name of the
file is printed at the beginning of each test, so you can find out what test
vector failed by executing the following (with x, y, and v replaced by the
above values, and where "foo.t" is the name of the test file that was being
processed at the time):

    % tail +x tests/foo.t | head -1

None of the tests should fail (but see [Note 2](#note2)); if any do, it
probably indicates a bug in the library (or at the very least, some assumption
I made which I shouldn't have).  Please [file an
issue](https://github.com/creachadair/imath/issues/new), including the `FAILED`
test line(s), as well as the output of the above `tail` command (so I know what
inputs caused the failure).

If you build with the preprocessor symbol `DEBUG` defined as a positive
integer, the digit allocators (`s_alloc`, `s_realloc`) fill all new buffers
with the value `0xdeadbeefabad1dea`, or as much of it as will fit in a digit,
so that you can more easily catch uninitialized reads in the debugger.

## Notes

1. You can generally use the same variables for both input
   and output.  One exception is that you may not use the same variable for
   both the quotient and the remainder of `mp_int_div()`.

2. Many of the tests for this library were written under
   the assumption that the `mp_small` type is 32 bits or more.  If you compile
   with a smaller type, you may see `MP_RANGE` errors in some of the tests that
   otherwise pass (due to conversion failures).  Also, the pi generator (pi.c)
   will not work correctly if `mp_small` is too short, as its algorithm for arc
   tangent is fairly simple-minded.

## Contacts

The IMath library was written by Michael J. Fromberger.

If you discover any bugs or testing failures, please [open an
issue](https://github.com/creachadair/imath/issues/new).  Please be sure to
include a complete description of what went wrong, and if possible, a test
vector for `imtest` and/or a minimal test program that will demonstrate the bug
on your system.  Please also let me know what hardware, operating system, and
compiler you're using.

## Acknowledgements

The algorithms used in this library came from Vol. 2 of Donald Knuth's "The Art
of Computer Programming" (Seminumerical Algorithms).  Thanks to Nelson Bolyard,
Bryan Olson, Tom St. Denis, Tushar Udeshi, and Eric Silva for excellent
feedback on earlier versions of this code.  Special thanks to Jonathan Shapiro
for some very helpful design advice, as well as feedback and some clever ideas
for improving performance in some common use cases.

## License and Disclaimers

IMath is Copyright 2002-2009 Michael J. Fromberger
You may use it subject to the following Licensing Terms:

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.

  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.

repository: creachadair/imath

gha_language: C

gha_license_id: NOASSERTION

repo_name: creachadair/imath


text:
#Pioneers game design

##Primary Objective

Pioneers is a round based strategy game designed to be highly simplistic but deeply strategic. The main feature is a persistent world in which all players play (although there may be a need for a set of worlds to distribute players of differing skill ranges). The game state continues even when the player is no longer in the game. While a controversial choice, it gives this game a very novel feature not often seen on the Roblox platform.

##Key Mechanics
The goal of this game is to build the largest civilisation of all. This is not easy as the world is persistent meaning your civilisation may be attacked at any point. The larger your civilisation gets the bigger a target you are for other players. Ideally the largest civilisation is constantly changing as players battle.

The world is broken down into hexagonal tiles from which everything is based upon. The world is *not* randomly generated nor does it contain any special elements. The default map is all just a default tile so players have equivalent starting states. All progress is based purely on strategy.

The world progresses in discrete steps. Each step takes a set amount of time to progress, likely 10-20 seconds. This time forces the player to decide their turn however turns aren’t likely to require much input as most of the work is automatically carried out (eg farmers will automatically walk to a storage or home tile). These steps also decide when actions are taken, eg wood gained from forestry, military unit attacking or unit walking to another tile. This is discussed in more detail under the Units section.

A player can create different tiles to form their civilisation. These tiles are Keep, Path, House, Farm, Mine, Forestry, Barracks, Wall, Gate and Storage. These tiles can be placed anywhere but give certain bonuses or have specific restrictions depending on the tiles surrounding. For example a player may only have one keep and this keep determines if their civilisation is destroyed not. When a players keep is destroyed they have lost. All tiles must be adjacent to a path. Farms, mines, orestries and storage all get efficiency bonuses from being adjacent to their own tiles. This is discussed in more detail under the Tiles section.

As all civilisations exist within the same world they progress even when the owner is offline. This means players continues to accumulate resources and progress during time away from the game. This also means their civilisation may be attacked while they are away too. This is discussed further under the intended strategies section.

##Units
There are only two main types of unit, villagers and soldiers.

- Villagers can be assigned to work but are unable to fight.
- Soldiers are unable to work but will fight other units or attack tiles.

This divide is to promote players to construct large numbers of houses and soldier units in order to attack instead of repurposing a lot of villagers. This also promotes the use of soldiers to idly protect the civilisation.

Soldiers do not require rest breaks. Villagers are only able to walk on paths or through gates however soldiers are able to on grass tiles in order to reach other civilisations. Villagers can automatically walk to any path-connected tile but soldiers can only move to an adjacent tile.

##Tiles

!!! success ""
    ###Grass
    This is the default tile and indicates nothing is currently placed. This is the only tiles that can be built on top of.

!!! edit ""
    ###Keep

    This is the foundation of the civilisation. Players can choose where to place their keep however they cannot place it too close to another civilisation. When a player places a keep they are also able to immediately place 6 paths followed by 1 house, 1 farm, 1 forestry and 1 mine. Keeps cannot be constructed normally.

!!! quote ""
    ###Path

    Designated area to allow units to walk. Connects all the parts of a civilisation together however paths cannot be built too far away from any houses to prevent potential abuse.

!!! warning ""
    ###House

    Creates a villager instantly when placed and another after a set number of turns, possibly around 20 turns. This creation of villagers is dependant on there being enough food within the civilisation and the house being within a 10 tile walk of a storage tile.

!!! question ""
    ###Farm/Mine/Forestry

    Generates 1 food/stone/wood respectively every turn a villager is working on one of these tiles. If they are adjacent to another tile of the same type (ie two farms are next to each other) then they generate 1 extra resource for every adjacent tile.

!!! tip ""
    ###Storage

    Holds resources. Collected resources need to be stored in one of these tiles in order for them to be usable. Collected resources are shared across all storage tiles to prevent over complicating gameplay. The keep counts as a storage tile.

!!! bug ""
    ###Barracks

    Converts a villager to a soldier after a given number of turns training. Only one villager may train at this tile at a time.

!!! example ""
    ###Wall/Gate

    A high health tile which prevents soldiers from breaching into the civilisation. They are expensive to make and give nothing back for removing. Gates are the same as a wall except cost more and require a soldier present at all times in exchange for allowing friendly units to pass through.

##Resources
There are only 3 resources which are food, stone and wood. Food is required by villagers every time they take a rest (they grab food from the nearest storage tile and then return home). Stone and wood are used in varying amounts to construct all tiles.

##Intended Strategies
Ideally players will strategically plan out the placement of their tiles in order to optimise the efficiency of their civilisation. A well planned civilisation would be capable of outperforming a significantly larger civilisation. This should take the form of large blocks of farm/mine/forestry tiles with storage and house tiles close by for efficient walking of workers.

Walls are expensive so should be carefully planned before placing. No resources are returned upon their removal. Due to this it is likely players will wall in their civilisation and only expand when they can afford to protect their expansion either with walls or with soldiers. This will create tiered civilisations where larger ones get even harder and harder to fully destroy.

When a storage tile is destroyed a percentage (likely 10-20%) of the held resources are given to the destroying player. This encourages players to go and try hunt storage tiles. Due to this new players will be given a protection period where they cannot be attacked. This period is likely to last a set number of turns until players are generally expected to be able to defend themselves or until they construct a barracks.

##Anti abuse measures
Due to the world being persistent and shared some measures must be taken in order to prevent abuse.

If a civilisation has not been visited by the player for over 1-7 days (depending on size) then it will be automatically destroyed.

Soldiers will automatically start to return to the keep if they have not been given any actions for 10 turns. This prevents soldiers from being left around the map which could stop new civilisations being created. This also means any attack must be planned and executed on the spot instead of soldiers being left to accumulate near a civilisation. Larger groups of soldiers become harder and harder to manage.

Tiles must be connected by paths and paths can only extend a set distance from near houses. This prevents civilisations growing artificially which could prevent new civilisations being made.

A civilisation can only be attacked by one player at a time with a cool down time. This prevents players colluding and ruining the experience for others.

##Example civilisation progression

!!! info "An initial civilisation when the player first starts playing"
    ![P1](assets/exampleprogress/p1.png)
    Purple = Keep
    Grey = Path
    Green = Farm
    Orange = House
    Yellowish = Forestry
    Blue = Mine

!!! success "A typical expansion after the first 10-20 minutes of gameplay"
    ![P2](assets/exampleprogress/p2.png)
     Cyan = Storage

!!! success "Further development expected to be reached at around 30-40 minutes of gameplay"
    ![P3](assets/exampleprogress/p3.png)

    Typical high level structures start to show

!!! success "Civilisation now large enough to require barracks and walls for protection"
    ![P4](assets/exampleprogress/p4.png)
    Black = Wall
    Pink = Gate
    Red = Barracks

!!! warning "A poorly planned expansion beyond the walls"
    ![P5](assets/exampleprogress/p5.png)
    This area uses the tiles in a poorly optimised way which is hard to correct.

!!! success "A more carefully planned expansion"
    ![P6](assets/exampleprogress/p6.png)
    This demonstrates how hard it is to plan safe expansions. This expansion would be incredibly costly to try execute and incredibly difficult without true planning. Walls require paths to make them (as villagers can only walk on paths) however paths require houses near and houses require storage near. This means the expansion has to either be tiny or storage tiles will not be protected by walls for a while.

##Monetisation
As this is more of an experiment money is not the primary focus of this game and monetisation will not be heavily pushed. This game is meant to be competitive so any method of monetisation that would give any kind of competitive advantage will not be implemented.

!!! success ""
    ####Cosmetics

    As always players could pay to have their units or tiles look a different theme. They could even pay a large sum to have their own custom model implemented into the game just for their own civilisation! Free content which players pay to have in the game!

!!! danger ""
    ####Third party alerts/status

    Discussed in future improvements this feature could be monetised. It could be argued that this provides an advantage however it is not a direct advantage and would be fairly priced so the majority of players could afford it.

!!! warning ""
    ####Clans

    Clans would have to pay a subscription which scales to their size/ability.

##Future improvements

!!! success ""
    ####Unit Training

    There could be training giving to improve units abilities, for example you could train a villager to be better at farming or train soldiers to use bows or spears however this is beyond the scope of the original game.

!!! success ""
    ####Tile Upgrades

    Tiles could be upgraded allowing them to be improved or provide different functionality.

!!! success ""
    ####Technology

    New tiles or units could be unlocked via researching technology.

!!! tip ""
    ####Competitive

    Either a closed world where only certain highly rated players can play or private matches where players could fight 1 on 1, many player free for all or team based games. These matches could have different values for round timing, tile/costs etc to make them either faster or slower paced. This could even allow for an elo based matchmaking system!

!!! danger ""
    ####Alerts

    Via the use of 3rd party platforms such as discord, players could be notified when their civilisation is under attack and react quickly. This could potentially greatly improve user retention as they are alerted about the game state and are likely to play to try defend their civilisation.

!!! quote ""
    ####Website

    A website could provide users with a simple overview of the entire map and possibly even the status of their own civilisation. Maybe this could even migrate off Roblox entirely?

!!! info ""
    ####Clans

    Allow players to join a clan. These clans can compete against each-other on stats/leaderboards. If a clan declares they are at war with another then multiple clan members can attack a civilisation of another clan at the same time. This could lead to some incredibly intense battles.

license: MIT

branch_name: refs/heads/master

extension: md

license_type: permissive


text:
---
layout: default
---

# 1994-04-10 - Re:  Zero Knowledge, Hamiltonian Cycles, and Passwords

## Header Data

From: Hal<EMAIL_ADDRESS>To<EMAIL_ADDRESS>Message Hash: 12b604d71409cafdf366b9508a25752894afcf56702c223e5de77d35ae93ddbc

Message ID<EMAIL_ADDRESS>Reply To: _N/A_

UTC Datetime: 1994-04-10 23:31:52 UTC

Raw Date: Sun, 10 Apr 94 16:31:52 PDT

## Raw message

```
{% raw  %}From: Hal<EMAIL_ADDRESS>Date: Sun, 10 Apr 94 16:31:52 PDT
To<EMAIL_ADDRESS>Subject: Re:  Zero Knowledge, Hamiltonian Cycles, and Passwords
Message-ID<EMAIL_ADDRESS>MIME-Version: 1.0
Content-Type: text/plain

From<EMAIL_ADDRESS>(Timothy C. May)
> And yet suppose Alice shows you one. In a textbook, for example. How
> did she "find" it? She likely didn't. Rather, she took 50 nodes, drew
> a path visiting each node once, stored this as her 'Hamiltonian cycle'
> and then proceeded to draw in 50 or 70 or whatever "other links,"
> which are "ringers," as it were (that is, they are never part of the
> Hamiltonian she "constructed").
>
> The resulting complete graph--50 nodes with maybe 100 or 500 or whatever
> links--only she knows a valid Hamiltonian cycle for (there may be
> others, which neither she nor anyone else will ever find).

I think something like this may be the idea behind "obfuscated computing,"
which Mike Duvos was writing about here a little while back.  The idea is
that you do this trick not just with a graph, but with a boolean circuit
composed of and, or, not gates, etc.  Take your algorithm and express it as
such a circuit, then obfuscate it by drawing in extra gates, connections,
etc.  The resulting circuit has your original circuit embedded in it, but
figuring out what the total circuit does can be computationally intractable.
Someone could build or emulate this circuit and get a result, but they would
not be able to figure out exactly what formula they were computing.

I'm not 100% certain that this technique is used, but Tim's posting reminded
me that I had read something about this several years ago, and this is how
I remember it.

Hal

{% endraw %}
```

## Thread

+ Return to [April 1994](/archive/1994/04)

+ Return to "[Hal <hfinney@shell.portal.com>](/authors/hal_hfinney_at_shell_portal_com_)"
+ Return to<EMAIL_ADDRESS>(Timothy C. May)](/authors/tcmay_at_netcom_com_timothy_c_may_)"

+ 1994-04-10 (Sun, 10 Apr 94 16:31:52 PDT) - Re:  Zero Knowledge, Hamiltonian Cycles, and Passwords - _Hal<EMAIL_ADDRESS>  + 1994-04-11 (Sun, 10 Apr 94 18:10:09 PDT) - [Re: Zero Knowledge, Hamiltonian Cycles, and Passwords](/archive/1994/04/56fd4de3a7b04d8291790631f5c43d00c344fb7bfb82bbccca8fab04d3d517ad) -<EMAIL_ADDRESS>(Timothy C. May)_

gha_license_id: MIT


text:
![https://img.shields.io/badge/ungit-docker-blue](https://img.shields.io/badge/docker-ungit-blue)
![https://camo.githubusercontent.com/716bbdd0ef8120e6d1fbd05bd50f8dcaa276d8ee10248ca8dde63d08026d3663/68747470733a2f2f62616467652e667572792e696f2f6a732f756e6769742e737667](https://camo.githubusercontent.com/716bbdd0ef8120e6d1fbd05bd50f8dcaa276d8ee10248ca8dde63d08026d3663/68747470733a2f2f62616467652e667572792e696f2f6a732f756e6769742e737667)

## Usage

### Build the image
1.  clone the repository: `git clone https://github.com/ottx96/ungit-docker.git`
2.  cd into the directory: `cd ungit-docker`
3.  build the image: `docker build -t ungit:latest .`

### Run the container
`docker run -d --rm --name ungit -p [local port]:8448 -v "[git repo]:/git" ungit`

#### Example (run inside git repo)
`docker run -d --rm --name ungit -p 8448:8448 -v "$(pwd):/git" ungit`

## Purpose
I have created this image to help people that aren't familiar with git.
Also, this is meant to be run temporarily from time to time.
The container can be stopped at any time.

## Credits / Source
https://github.com/FredrikNoren/ungit

branch_name: refs/heads/main


text:
Write and export by default the function that accepts arguments of func and
either invokes func returning its result, if at least arity number of arguments
have been provided, or returns a function that accepts the remaining func
arguments, and so on. The arity of func may be specified if func.length is not
sufficient.

```js
const abc = function(a, b, c) {
  return [a, b, c];
};

const curried = _.curry(abc);

curried(1)(2)(3); // [1, 2, 3]
curried(1, 2, 3); // [1, 2, 3]
```

repository: gadzhimari/katas

gha_language: JavaScript

repo_name: gadzhimari/katas


text:
---
layout: post
title: 'The "OO" Antipattern'
date: 2020-05-28 00:01:00 +0000
tags:
  antipatterns
  blog-roundup
  c++-learner-track
  c++-style
  slogans
  war-stories
---

For those who only read above the fold: I _don't_ say that all object-orientation is bad!
OOP, especially classical polymorphic OOP, has a well-deserved place in real code.
I'm going to talk about a very specific antipattern that I see with some frequency:
the use of `class` for things that should be simple free functions.

I originally wrote about this specific piece of code
[on Code Review StackExchange](https://codereview.stackexchange.com/questions/188300/counting-the-number-of-domino-tilings-for-a-rectangular-grid)
(February 2018). I gave an unrecorded lightning talk based on the same material in April 2018.

If this kind of thing appeals to you, I recommend with the highest possible recommendation
that you get yourself a copy of Kernighan and Plauger's [_The Elements of Programming Style_](https://amzn.to/2X5W1H0)
(1974, reissued 1978).

## The original code

Students who've learned C++ in a particular kind of academic setting often approach
it with the "everything is an object" mindset. Suppose they're given a task to compute
some value; then their first step is to create a `ValueComputer` object with a
member function `vc.computeResult()`.

For example: A student is asked to use [dynamic programming](https://en.wikipedia.org/wiki/Dynamic_programming)
to count the number of distinct [domino tilings](https://en.wikipedia.org/wiki/Domino_tiling)
of a $$w\times h$$ rectangle. The student writes:

    int main()
    {
        DominoTilingCounter tc(4, 7);  // in a 4x7 rectangle
        std::cout << tc.count() << '\n';
    }

Having framed the problem, they go on to implement the `DominoTilingCounter` class.
The clever student even adds memoization, so that the `count()` member function won't be
so slow the second time it's called:

    class DominoTilingCounter {
        int height, width;
        bool done = false;
        int tilingCount;
        int computeCount(int h, int w, std::string_view prevRow, int rowIdx) {
            [...recursive solution omitted...]
        }
    public:
        explicit DominoTilingCounter(int h, int w) : height(h), width(w) {
            if (h == 0 || w == 0 || (w*h) % 2 != 0) {
                tilingCount = 0;
                done = true;
            }
        }
        int count() {
            if (!done) {
                tilingCount = computeCount(height, width, "", 0);
                done = true;
            }
            return tilingCount;
        }
    };

(Experienced programmers may be cringing, here. That's the point.)

Unfortunately, this code fails the [const-correctness](/blog/2019/01/03/const-is-a-contract/) test:
the `count()` member function sounds like it should be non-modifying, but in fact
it needs to update member data and thus cannot be const.

    std::cout << DominoTilingCounter(4, 7).count() << '\n';
        // Fails to compile!

(Hacker News points out that this _does_ compile; class prvalues are not const
the way scalar prvalues are. Oops.)
Anyway, we can fix this issue incidentally, just by applying a little more logic.

## The logical leap

Look: when you construct a `DominoTilingCounter` object `tc`,
it is _specifically for the purpose_ of computing `tc.count()`, right?
There's no other purpose that `tc` could serve?

Again: When you construct a `DominoTilingCounter` object, it is specifically
for the purpose of computing `tc.count()`.

So put the computation in the constructor!

    class DominoTilingCounter {
        int height, width;
        int tilingCount;
        int computeCount(int h, int w, std::string_view prevRow, int rowIdx) {
            [...recursive solution omitted...]
        }
    public:
        explicit DominoTilingCounter(int h, int w) : height(h), width(w) {
            if (h == 0 || w == 0 || (w*h) % 2 != 0) {
                tilingCount = 0;
            } else {
                tilingCount = computeCount(height, width, "", 0);
            }
        }
        int count() const {
            return tilingCount;
        }
    };

This refactoring does several things:

- It permits `count()` to be a const member function.

- It eliminates the "empty, uncomputed" state from your program.

- It eliminates the data member `done`, whose whole purpose was to track that empty state.
    (In C++17 we might use a `std::optional` for that purpose; but look, now we don't have to!)

In fact, the private data members `height` and `width` are now unused as well. It turns out
that we were using them only to pass data from the constructor to the computation in
the `count()` method; and now that the computation is taking place in the constructor, we
don't need those data members anymore. Our code shrinks drastically.

## The final leap

In the original code, the student's `computeCount` member function happened to take `w` and `h`
as function parameters, rather than reading them from the `height` and `width` data members.
That was a fortunate accident: `computeCount` doesn't use any of the
data members of the `DominoTilingCounter` object, and so we can mark it `static`.
Our code is now something like this:

    class DominoTilingCounter {
        int tilingCount;
        static int computeCount(int h, int w, std::string_view prevRow, int rowIdx) {
            if (h == 0 || w == 0 || (w*h) % 2 != 0) {
                return 0;
            }
            [...recursive solution omitted...]
        }
    public:
        explicit DominoTilingCounter(int h, int w) {
            tilingCount = computeCount(h, w, "", 0);
        }
        int count() const {
            return tilingCount;
        }
    };

The final leap is to observe that this entire class does nothing but wrap an assignment to an `int`!

> Avoid classes that are tantamount to `int`.

What we _should_ write is a simple free function `countDominoTilings(w, h)`:

    int countDominoTilingsImpl(int h, int w, std::string_view prevRow, int rowIdx) {
        if (h == 0 || w == 0 || (w*h) % 2 != 0) {
            return 0;
        }
        [...recursive solution omitted...]
    }

    int countDominoTilings(int h, int w) {
        return countDominoTilingsImpl(h, w, "", 0);
    }

    int main() {
        int tc = countDominoTilings(4, 7);  // in a 4x7 rectangle
        std::cout << tc << '\n';
    }

No more `class`, no more worrying about const, no more worrying about memoization (it becomes the
caller's problem, for better or worse). Our original `DominoTilingCounter` object wasn't thread-safe,
but now we don't have to worry about that, either. And our code is about a dozen lines shorter.

----

Again, this is not to say that all classes are bad! In fact, the antipattern discussed here is
very close to the [Builder pattern](https://en.wikipedia.org/wiki/Builder_pattern),
and there's nothing wrong with the Builder pattern — when it's needed, that is.
All I'm saying is:

When you have to compute a value, don't write a `ValueComputer` class.
Write a `compute_value` function instead.

----

For other takes on this topic, see:

- ["Execution in the Kingdom of Nouns"](http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html) (Steve Yegge, March 2006)

- ["Stop Writing Classes"](https://www.youtube.com/watch?v=o9pEzgHorH0) (Jack Diederich, PyCon 2012)

repository: Quuxplusone/blog

gha_language: HTML

repo_name: Quuxplusone/blog


text:
# Installation
> `npm install --save @types/esquery`

# Summary
This package contains type definitions for esquery (https://github.com/jrfeenst/esquery).

# Details
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/esquery.

### Additional Details
 * Last updated: Mon, 23 Dec 2019 16:27:39 GMT
 * Dependencies: [@types/estree](https://npmjs.com/package/@types/estree)
 * Global values: `esquery`

# Credits
These definitions were written by cherryblossom000 (https://github.com/cherryblossom000), and Brad Zacher (https://github.com/bradzacher).


text:
# Just Enough Vi for MonoDevelop 6.0

Simplified Vi mode for MonoDevelop/Xamarin Studio. It's not supposed to *completely* emulate Vi/Vim but be just enough for navigating.

[![Join the chat at https://gitter.im/hifi/monodevelop-justenoughvi](https://badges.gitter.im/hifi/monodevelop-justenoughvi.svg)](https://gitter.im/hifi/monodevelop-justenoughvi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

## Current Features

 * Intuitive and predictable normal mode navigation
 * Full line visual select with yank/delete/indent
 * Pass-through insert mode for full IDE potential

## Out of scope

 * `:` ex mode

## Status

There's a lot of bugs in cursor placement (compared to Vi/Vim) when handling some commands. Some are not a big issue but some are annoying enough and should be fixed.

## Building

 * MonoDevelop development assemblies
 * Add-in Maker (available in add-in catalogue)

repository: dambrisco/monodevelop-justenoughvi

repo_name: dambrisco/monodevelop-justenoughvi


text:
#API Review
--------------------------------
Patrick Grady - plg5
Bobby Wang - bcw22

###Part 1
1. The separation between the front and back end in the UML is very clear. The binding has a single function that the front end calls, and the back end returns one data type. This design was chosen to heavily emphasize flexibility, and it enables the back end to be entirely independent of implementation-specific details. Another front end could be plugged in to work with minimal effort. Additionally, the generic way which the back end describes states would easily allow extension if required.

2. The package-protected paradigm permeating the back end and front end prohibits information flow except for very specific API calls

3. The program will use an exception based architecture to handle errors. This permits the easy upward flow of information, and automatically handles the termination of the current command. This will handle parsing errors and logical errors thrown by the back end.
4. The API is well designed since it limits the binding to be small so that there are no unneeded external functions or data. This allows our contract between the front and back to be very rigid and consistent, and ultimately extendable if needed.

### Part 2

#### Demo what you currently have running (it could be anything, but it should definitely be something).

Completed.

#### Come up with at least four use cases for your part (it is absolutely fine if they are useful for both teams).

1. Update the state of visual state of board when a new command is inputted

2. Display an error when an invalid command is inputted

3. Change the language that the slogo commands are entered and parsed in

4. Change the pen color of a turtle

5. Change the background color of the image

#### What feature/design problem are you most excited to work on?

##### Patrick

I'm most excited to work on making Slogo work in multiple languages. There's a lot of extensibility involved with this language feature, and there's so many ways of implementing it. I hope that I'll be able to find a relatively intuitive, clean way of implementing this feature.

##### Bobby
I'm most excited to work on updating the visual state based solely on the command module data. I've never worked on front end before (outside of my game), so this experience will teach me a lot. It also allows for a lot of personal creativity, since I'm almost solely in charge of the visual look of our UI.

##### What feature/design problem are you most worried about working on?

##### Patrick
I'm most worried about displaying the turtle in an intuitive, clean way. With one turtle, the issues shouldn't be too bad. However, with multiple turtles and pen colors, the canvas can quickly get messy. When we incorporate other issues like re-sizing the canvas if the turtle moves off screen, there are a whole host of other extensiblity issues that can crop up.

##### Bobby
I'm worried about displaying the current state of variables and the list of past entered commands. Displaying them in and of themsleves shouldn't be too bad - however, when it comes to re-executing commands by clicking on them, there are many issues of encapsulation that may come up.


text:
---
title: Do you use RSS?
date: 2020-08-28
cover_image: /img/000006.png
cover_image_alt: The screenshots of Fluent Reader
categories: Essay
tags:
  - rss
  - reader
---

I read things by RSS.

## What Is RSS? & How to Use it?

> Really Simple Syndication (RSS) is an XML-based document format for the syndication of web content so that it can be republished on other sites or downloaded periodically and presented to users.

Yes, **Really Simple**. You can just add the RSS feed URL to your RSS client. After that, your client will fetch new articles from the RSS feed URLs.

Actually, RSS is just a file on the Internet. It looks like this:

```xml
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>...</title>
  <subtitle>...</subtitle>
  <link href="..." rel="self"/>
  <link href="..."/>
  <updated>...</updated>
  <id>...</id>
  <author>
    <name>...</name>
  </author>
  <entry>
    <title>...</title>
    <link href="..."/>
    <id>...</id>
    <published>...</published>
    <updated>...</updated>
    <content type="html"><![CDATA[...]]></content>
    <summary type="html">...</summary>
  </entry>
</feed>
```

_To see the source, go to [the RSS feed of my blog](/atom.xml)._

And all you need to do is to know its link and add it to your RSS feeds list.

## How do I Use RSS?

**I use [Fluent Reader](https://hyliu.me/fluent-reader/).**

Fluent Reader is an RSS reader based on [Electron](https://www.electronjs.org/) for desktop. It's frontend is based on [Fluent UI](https://github.com/microsoft/fluentui) which is an UI framework by Microsoft based on [React](https://reactjs.org/).

Fluent Reader's UI design is just wonferful, just like [Windows UWP](https://docs.microsoft.com/en-us/windows/uwp/) apps.

If you want to add an RSS feed, go to settings and enter your RSS feed URL in "Add Source" text field.

Then click "Add" button. You will get your articles then:

## My RSS Feeds

| Title | URL |
| --- | --- |
| Apple Newsroom | https://www.apple.com/newsroom/rss-feed.rss |
| The Verge | https://www.theverge.com/rss/index.xml |
| Polygon | https://www.polygon.com/rss/index.xml |
| Tobias Ahlin | https://tobiasahlin.com/feed.xml |
| Airbnb Design | https://airbnb.design/feed/ |

gha_language: CSS


text:
#### git workflow

The Git workflow consists of editing files in the working directory, adding files to the staging area, and saving changes to a Git repository.

In Git, we save changes with a commit, which we will learn more about in this lesson.

<aside class="notes">
</aside>

branch_name: refs/heads/denny


text:
# @tracker1/docker-cli

[![npm version](https://img.shields.io/github/package-json/v/tracker1/node-docker-cli)](https://www.npmjs.com/package/@tracker1/docker-cli)
[![Dependency Status](https://img.shields.io/librariesio/release/npm/@tracker1/docker-cli)](https://libraries.io/npm/@tracker1/docker-cli)
![Github Issues](https://img.shields.io/github/issues/tracker1/node-docker-cli?style=plastic)
[![MIT License](https://img.shields.io/github/license/tracker1/node-docker-cli)](./LICENSE)

<!-- [![Actions Status](https://github.com/tracker1/node-docker-cli/workflows/Tests/badge.svg)](https://github.com/tracker1/node-docker-cli/actions) -->
<!--[![Code Coverage](https://img.shields.io/coveralls/github/tracker1/node-docker-cli)](https://github.com/tracker1/node-docker-cli) -->

Quick command interface for running docker commands with parsed results.

```js
import dockerCommand from '@tracker1/docker-cli';

const result = await dockerCommand('ps', options);
```

## dockerCommand

The command `dockerCommand(command, options)` has to input parameters.

* `command` (string) - the command to run
* `options` (object, optional) - Additional parameters to run
  * `machineName` (string) - the docker-machine configuration name to use.
  * `cwd` (string) - the working path to use
  * `echo` (bool) - when true, will echo the console output as the command runs

## Related Projects

[docker-cli-js](https://github.com/Quobject/docker-cli-js) - Original inspiration, started with some logic from this project. Reduced interface footprint to single method, separated logic out and using camelCase response naming.

## License

MIT License


text:
### Currently Limited Functionality

Available here: [Deploy Vapor Dammit](https://deployvapordammit.herokuapp.com/)

Only accepts `POST` requests to `/catDB/create` with a `JSON` body that matches:

```
{
   "cat_id": <int value>,
   "cat_name": <string value>,
   "cat_breed": <string value>
}
```

`cat_id` does not autoincrement/generate and is the DB's primary key. You may get an error if attempting to use a low int value.

### TODO:

- Instructions of how this was setup along w/ links to resources used

repository: spacedrabbit/vapor-with-postgres-demo

repo_name: spacedrabbit/vapor-with-postgres-demo


text:
# Publishing to Maven Central

This project publishing is not automated. Everything is executed manually from a developer machine.

## Step 1. Prerequisites

1. You need a OSSRH account with rights to release `com.wix` artifacts. Credentials are excpected to be available under environment variables `SONATYPE_USERNAME` and `SONATYPE_PASSWORD`.
2. Additionally, you need a valid PGP key for your account. This project uses sbt-pgp plugin, usage can be found here: https://github.com/sbt/sbt-pgp/wiki/Using-GPG .

## Step 2. Publishing

Since process is not automated, you must manually change versions before and after publishing artifacts. Please commit the changes.

Publishing itself is done by executing following command:

```sh
sbt +publishSigned
```

## Step 3. Releasing

After publishing artifacts successfully, they will be visible (if you have rights) in https://oss.sonatype.org/#stagingRepositories . Make sure content looks OK, then close and release it. Usually, artifacts become available in a couple of hours. If not, wait at least 24 hours before panicking.

Refer to https://central.sonatype.org/pages/ossrh-guide.html for more detailed information.


text:
bitcoin-splitter
================

A simple ruby script that uses electrum to split funds from wallet to two different addresses.

We bought a miner with a friend and we want to split the rewards in half, preferably automatically.

Installation
------------

This script uses only standard library and calls command line electrum client. It needs to have "addresstosplit" in the wallet.

No race conditions were tested for, as both destination addresses are friendly in my use-case. Please note that it splits balance from ALL ADDRESSES in the wallet, so please do not use the wallet for other purposes. I run it as a separate user in my system with their own wallet.

Electrum has to be 1.9.4 or later, because 1.8.x versions do not understand paytomany command. We want to have both destination addresses in one transaction to make any race conditions or electrum run errors easier to handle.

Usage
-----

Usage: splitter.rb changeaddress destinationaddr1 destinationaddr2 [maximumexpectedfee] [balancethreshold]

Any confirmed coins coming to the wallet will be split to destinationaddr1 and destinationaddr2 (minus the maximumexpectedfee - we
let Electrum calculate the fee, so there will be some small change in most cases).

If there are any unconfirmed coins in the wallet, this script just quits. It is supposed to be run from cron, so we split the
balances after confirmation.

Example: addresstosplit has 1BTC, fee is 0.001 (default), destinationaddr1 and destinationaddr2 both receive 0.4995 BTC and
any change (if the fee is actually smaller) goes to changeaddress.

FAQ
---

Q: Why did you not use [sx](http://sx.dyne.org/)?

A: Because it does not compile on any system I use. Electrum is quite portable.

Author and Donations
--------------------

This small script was written by [Juraj Bednar](http://juraj.bednar.sk/about-me/).

If you find this useful, please donate to 14Svhg5GiZEsCpKihy46w1V6mhPiz53UxV

license: Unlicense


text:
# Rust Tetris

## What is this?
This is a small learning project to get up to speed with Rust. This will probably contain some horrible coding style but i try to keep it clean :).

So the goal of the project is to build a tetris game for the commandline using Rust.

repository: CptPie/Rust-Tetris

gha_language: Rust

repo_name: CptPie/Rust-Tetris


text:
CloudSnap [![Build Status](https://secure.travis-ci.org/renanivo/cloudsnap.png?branch=master)](http://travis-ci.org/renanivo/cloudsnap)
=========

A python 2.7 Google App Engine (GAE) script to create images (AMIs) from all of your Amazon EC2 instances.

Configuration
-------------

### settings.py

Copy settings.example.py to settings.py and fill:

- Your AWS account key (AWS['key'])
- Your AWS account secret (AWS['secret'])
- Your GAE's administrator email (LOGGER['sender'])
- Your email to receive logs (LOGGER['to'])

**Obs**: lacks a configuration wizard.

### app.yaml

Since cloudsnap is already taken (by me) you will need to replace the application name with something else. Remember to [signup for an GAE Account](https://appengine.google.com/) and verify the availability of the application name.

### cron.yaml

The cron.yaml is configured according to my needs. Feel free to change the scheduling and timezone according to yours.

Deploying
----------

Download [GAE python SDK](http://code.google.com/appengine/downloads.html#Google_App_Engine_SDK_for_Python) and follow [application upload instructions](http://code.google.com/appengine/docs/python/gettingstarted/uploading.html).

Development Environment
-----------------------

To set up the project on your development environment, follow these steps:

- Download the APP Engine SDK
- Move the SDK folder to /usr/local/google_appengine (the google_appengine folder may be anywhere. If you place it elsewhere take a look at Makefile and replace the path to run the unit tests)
- Install virtualenv and virtualenvwrapper:

    ```bash
    sudo pip install virtualenv
    sudo pip install virtualenvwrapper
    ```

- Clone the project

    ```bash
    git clone https://github.com/renanivo/cloudsnap.git
    ```

- Create a new virtualenv on the project folder:

    ```bash
    virtualenv --no-site-packages cloudsnap
    ```

- Go to the project folder and execute:

    ```bash
    add2virtualenv cloudsnap
    make setup
    ```

repository: renanivo/cloudsnap

gha_language: Python

repo_name: renanivo/cloudsnap


text:
# Asset_tracking_POV
This prototype is a mockup interface to CMX that can take in the notifications data using CMX REST APIs to locate assets by the mac address on a floor map, The prototype is built using a python Flask server and CISCO UI toolkit and cisco NeXt UI toolkit
the GUI allows the user to orgnise assets into groups and allows the user to reqest the location of an asset or group of assets

## Usage:
Clone the repo :
```
$ git clone https://github.com/Abdellbar/Asset_tracking_POV
```

Install dependencies :
```
$ pip install flask
$ pip install WTForms
```
update the mac address of the devices to be tracked, in the GroupTag_Form,Select_Form classes in server.py and js/nodes.js files

Launch the server by issueing
```
$ python server.py
```

In a web browser open :
http://<IP_ADDRESS>:5000/start

## Integrate to CMX:

Add the url 'http://<IP_ADDRESS>:5000/webhook' into CMX to post the location data directly to the app


text:
# Notes-App

_Notes web page with validation of users using nodejs and mongodb_

### Pre Requirements 📋

_In addition to having installed nodejs and mongodb, you will need to have installed the following modules by npm_

```
npm i express express-session express-handlebars bcryptjs passport passport-local connect-flash method-override mongoose
```

repository: natashaverma/notes-app

repo_name: natashaverma/notes-app


text:
---
title: Control Egress Traffic
overview: Describes how to configure Istio to route traffic from services in the mesh to external services.

order: 40

layout: docs
type: markdown
---
{% include home.html %}

By default, Istio-enabled services are unable to access URLs outside of the cluster because
iptables is used in the pod to transparently redirect all outbound traffic to the sidecar proxy,
which only handles intra-cluster destinations.

This task describes how to configure Istio to expose external services to Istio-enabled clients.
You'll learn how to enable access to external services using egress rules,
or alternatively, to simply bypass the Istio proxy for a specific range of IPs.

## Before you begin

* Setup Istio by following the instructions in the
  [Installation guide]({{home}}/docs/setup/).

* Start the [sleep](https://github.com/istio/istio/tree/master/samples/sleep) sample
  which will be used as a test source for external calls.

  ```bash
  kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml)
  ```

  Note that any pod that you can `exec` and `curl` from would do.

## Using Istio egress rules

Using Istio egress rules, you can access any publicly accessible service
from within your Istio cluster. In this task we will use
[httpbin.org](http://httpbin.org) and [www.google.com](http://www.google.com) as examples.

### Configuring the external services

1. Create an egress rule to allow access to an external HTTP service:

   ```bash
   cat <<EOF | istioctl create -f -
   apiVersion: config.istio.io/v1alpha2
   kind: EgressRule
   metadata:
     name: httpbin-egress-rule
   spec:
     destination:
       service: httpbin.org
     ports:
       - port: 80
         protocol: http
   EOF
   ```

2. Create an egress rule to allow access to an external HTTPS service:

   ```bash
   cat <<EOF | istioctl create -f -
   apiVersion: config.istio.io/v1alpha2
   kind: EgressRule
   metadata:
     name: google-egress-rule
   spec:
     destination:
       service: www.google.com
     ports:
       - port: 443
         protocol: https
   EOF
   ```

### Make requests to the external services

1. Exec into the pod being used as the test source. For example,
   if you are using the sleep service, run the following commands:

   ```bash
   export SOURCE_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
   kubectl exec -it $SOURCE_POD -c sleep bash
   ```

2. Make a request to the external HTTP service:

   ```bash
   curl http://httpbin.org/headers
   ```

3. Make a request to the external HTTPS service.
   External services of type HTTPS must be accessed over HTTP with the port specified in the request:

   ```bash
   curl http://www.google.com:443
   ```

### Setting route rules on an external service

Similar to inter-cluster requests, Istio
[routing rules]({{home}}/docs/concepts/traffic-management/rules-configuration.html)
can also be set for external services that are accessed using egress rules.
To illustrate we will use [istioctl]({{home}}/docs/reference/commands/istioctl.html)
to set a timeout rule on calls to the httpbin.org service.

1. From inside the pod being used as the test source, invoke the `/delay` endpoint of the httpbin.org external service:

   ```bash
   kubectl exec -it $SOURCE_POD -c sleep bash
   time curl -o /dev/null -s -w "%{http_code}\n" http://httpbin.org/delay/5
   ```

   ```bash
   200

   real    0m5.024s
   user    0m0.003s
   sys     0m0.003s
   ```

   The request should return 200 (OK) in approximately 5 seconds.

1. Exit the source pod and use `istioctl` to set a 3s timeout on calls to the httpbin.org external service:

   ```bash
   cat <<EOF | istioctl create -f -
   apiVersion: config.istio.io/v1alpha2
   kind: RouteRule
   metadata:
     name: httpbin-timeout-rule
   spec:
     destination:
       service: httpbin.org
     http_req_timeout:
       simple_timeout:
         timeout: 3s
   EOF
   ```

1. Wait a few seconds, then issue the _curl_ request again:

   ```bash
   kubectl exec -it $SOURCE_POD -c sleep bash
   time curl -o /dev/null -s -w "%{http_code}\n" http://httpbin.org/delay/5
   ```

   ```bash
   504

   real    0m3.149s
   user    0m0.004s
   sys     0m0.004s
   ```

   This time a 504 (Gateway Timeout) appears after 3 seconds.
   Although httpbin.org was waiting 5 seconds, Istio cut off the request at 3 seconds.

## Calling external services directly

The Istio egress rules currently only supports HTTP/HTTPS requests.
If you want to access services with other protocols (e.g., mongodb://host/database),
or if you want to completely bypass Istio for a specific IP range,
you will need to configure the source service's Envoy sidecar to prevent it from
[intercepting]({{home}}/docs/concepts/traffic-management/request-routing.html#communication-between-services)
the external requests. This can be done using the `--includeIPRanges` option of
[istioctl kube-inject]({{home}}/docs/reference/commands/istioctl.html#istioctl-kube-inject)
when starting the service.

The simplest way to use the `--includeIPRanges` option is to pass it the IP range(s)
used for internal cluster services, thereby excluding external IPs from being redirected
to the sidecar proxy.
The values used for internal IP range(s), however, depends on where your cluster is running.
For example, with Minikube the range is <IP_ADDRESS>/24, so you would start the sleep service like this:

```bash
kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml --includeIPRanges=<IP_ADDRESS>/24)
```

On IBM Bluemix, use:

```bash
kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml --includeIPRanges=<IP_ADDRESS>/16,<IP_ADDRESS>/16,<IP_ADDRESS>/24)
```

On Google Container Engine (GKE) the ranges are not fixed, so you will
need to run the `gcloud container clusters describe` command to determine the ranges to use. For example:

```bash
gcloud container clusters describe XXXXXXX --zone=XXXXXX | grep -e clusterIpv4Cidr -e servicesIpv4Cidr
```
```
clusterIpv4Cidr: <IP_ADDRESS>/14
servicesIpv4Cidr: <IP_ADDRESS>/20
```
```bash
kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml --includeIPRanges=<IP_ADDRESS>/14,<IP_ADDRESS>/20)
```

On Azure Container Service(ACS), use:

```bash
kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml --includeIPRanges=<IP_ADDRESS>/16,<IP_ADDRESS>/16)
```

After starting your service this way, the Istio sidecar will only intercept and manage internal requests
within the cluster. Any external request will simply bypass the sidecar and go straight to its intended
destination.

```bash
export SOURCE_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
kubectl exec -it $SOURCE_POD -c sleep curl http://httpbin.org/headers
```

## Understanding what happened

In this task we looked at two ways to call external services from within an Istio cluster:

1. Using an egress rule (recommended)

2. Configuring the Istio sidecar to exclude external IPs from its remapped IP table

The first approach (egress rule) currently only supports HTTP(S) requests, but allows
you to use all of the same Istio service mesh features for calls to services within or outside
of the cluster. We demonstrated this by setting a timeout rule for calls to an external service.

The second approach bypasses the Istio sidecar proxy, giving your services direct access to any
external URL. However, configuring the proxy this way does require
cloud provider specific knowledge and configuration.

## Cleanup

1. Remove the rules.

   ```bash
   istioctl delete egressrule httpbin-egress-rule google-egress-rule
   istioctl delete routerule httpbin-timeout-rule
   ```

1. Shutdown the [sleep](https://github.com/istio/istio/tree/master/samples/sleep) service.

   ```bash
   kubectl delete -f samples/sleep/sleep.yaml
   ```

## Further reading

* Read more about [egress rules]({{home}}/docs/concepts/traffic-management/rules-configuration.html#egress-rules).

* Learn how to setup
  [timeouts]({{home}}/docs/reference/config/traffic-rules/routing-rules.html#httptimeout),
  [retries]({{home}}/docs/reference/config/traffic-rules/routing-rules.html#httpretry),
  and [circuit breakers]({{home}}/docs/reference/config/traffic-rules/destination-policies.html#circuitbreaker) for egress traffic.


text:
---
tags: javascript java perl ruby datetime
layout: post
title: "Next and previous JavaScript months"
---

The date/time libraries shipping with some languages I've used
are just awful -- e.g., Perl, Java, JavaScript.  Fortunately, the
first two have great libraries available
DateTime for Perl and
Joda-Time for
Java.[1] For JavaScript, it's slim pickings. There is
DateJS which
provides some parsing and fluent interface functionality, but
seems to be lacking in other concepts (e.g., durations and
intervals). But AFAICT there's nothing of the comprehensiveness
or extensibility of either of the Java or Perl alternatives.

While DateJS allows you to do math, there's also a nice little
hack you can do for at least one simple use case: given
a date, what are the next and previous months?

In good APIs this is handled with ease:

{% highlight java %}
// Java:
  DateTime now    = new DateTime();
  DateTime future = now.plusMonths(1);
  DateTime past   = now.minusMonths(1);
  System.out.println( "Future: " + future + "\nPast: " + past );

//  ==> Future: 2012-02-09T22:31:55.656-05:00
//  ==> Past: 2011-12-09T22:31:55.656-05:00
{% endhighlight %}

{% highlight perl %}
# Perl:
  my $now    = DateTime->now( time_zone => 'America/New_York' );
  my $future = $now->clone->add( months => 1 );
  my $past   = $now->clone->subtract( months => 1 );
  print "Future: $future\nPast: $past\n";

#  ==> Future: 2012-02-09T22:36:01
#  ==> Past: 2011-12-09T22:36:01
{% endhighlight %}

{% highlight ruby %}
# Ruby:[2]
  now    = DateTime.now
  future = now.advance( :months => 1 )
  past   = now.advance( :months => -1 )
  puts "Future: #{future}\nPast: #{past}"

#  ==> Future: 2012-02-09T22:55:26-05:00
#  ==> Past: 2011-12-09T22:55:26-05:00
{% endhighlight %}

In JavaScript you can't do that. But you can find the
previous/next months pretty easily. The <tt>Date</tt> constructor
takes a series of values for defining the date. If you specify a
day '0' for the day of month, you'll get the last day of the
previous month, and if you specify a day '32' you'll get
somewhere around the first day of the following month:

{% highlight javascript %}
// (using Rhino 1.7R3)
  var now    = new Date();
  var future = new Date( now.getFullYear(), now.getMonth(), 32 );
  var past   = new Date( now.getFullYear(), now.getMonth(), 0 );
  print( "Future: " + future + "\nPast: " + past + "\n" );

// ==> Future: Wed Feb 01 2012 00:00:00 GMT-0500 (EST)
// ==> Past: Sat Dec 31 2011 00:00:00 GMT-0500 (EST)
{% endhighlight %}

It's not the same result, but that's okay because the day is
unnecessary. I've tested it in Rhino and a few browsers (FF,
Chrome, IE 8) and all had the same result. Hope it helps.

----

[1] JDK 8 will vastly improve the default, taking it from terrible to awesome -- see
JSR 310.

[2] The 'advance' function is not in the core Ruby
Date/DateTime library, but it is added by Rails. I had a devil of
a time getting this to run as a standalone script so just ran it
in the rails console. The interplay between the names of Ruby
libraries, the classes, and the documentation is very confusing
to an outsider -- for example, 'ri DateTime' gives you methods
monkeypatched into the class by ActiveSupport.


text:
# Description

Plugin dedicated to Blink cameras.

It allows you to display videos from different cameras.

The following actions are available (depending on the camera model):
- to arm/disarm the motion detection of a system
- to arm/disarm the motion detection of a camera.
- Take a video
- Take photo (updated camera thumbnail)
- View a camera's latest video history (with option to download videos or delete them)

Camera information is also available:
* Date of the last event,
* URL and path of the last video (and its thumbnail),
* Camera thumbnail URL and path (from "Take a photo")
* wifi power,
* Temperature,
* Battery status,
* [Doorbell only] Source of the last evebt ("pir" for IR detection, "button_press" pour the button)

>**In the plugin, Blink Mini cameras and Doorbell do not have the same capabilities as other Blink XT, Outdoor cameras, etc.<br> For example, camera thumbnails are not implemented for Mini**

# Configuration of the plugin

In the plugin configuration screen the following options are available:

* Blink account
  + Area to enter the email, password and pin code associated with your Blink account. (The pin code entry field is only displayed when the connection is not yet validated)

* Security
  + _"Block access to video and image URLs without being authenticated in Jeedom?"_
    - If the box is checked, the URLs of the videos (and images) can only be opened if the user is already connected to Jeedom
    - If the box is not checked, the urls are freely accessible

  + Jeedom address to use for URLs: allows you to choose which Jeedom URL will be used in the "Last video URL" and "Thumbnail URL" info.
    *These URLs correspond to those you have defined in the configuration of your Jeedom system: "Settings / System / Configuration" menu then "Networks" tab: internal access or external access.*

>**It is advisable to choose "External access" only if you have checked "Block access to URLs..."**

* Widget
  + Thumbnail content: allows you to choose what is displayed in the widget
  + Thumbnail size: allows you to define the reduction to be applied (as a percentage of the initial size).

* Historical view
  + This view is accessible from the widget
  + It displays the latest videos available
  + The maximum number of downloaded videos allows you to limit the amount of data to download when opening the historical view
  + The size of the video previews can also be configured.

    *Warning: If you configure a large size and a large number of videos, this can cause slowness in the historical view*

>**Don't forget to click on the "Save" button**

![Configuration du plugin](..\assets\images\cfg_plugin.png "Configuraion du plugin")

# Creation and configuration of equipment

## Adding equipment

Adding equipment is done manually.

To do this, you must click on the "Add" button with the "+" icon.

![Ajout d'un équipment](..\assets\images\cfg_plugin_general.png "Ajout d'un équipment")

You can then enter a name for the equipment.

The equipment configuration window then opens.

## Equipment configuration

### Equipment tab
![Onglet équipement](..\assets\images\cfg_equipment.png "Equipement")

The standard options for Jeedom equipment are at the top of the screen.

If you have correctly configured your Blink account (see configuration of the plugin), 2 other options are available in the lower part of the screen:
- System: Corresponds to the system created in your Blink application.
- Camera: allows you to select the camera to use with this equipment

>**Don't forget to click on the "Save" button**

### Commands tab

Commands are automatically created when the equipment is created.

Icons are associated with actions, you can modify them in the classic way in Jeedom.

The "Display" checkboxes allow you to choose the information or commands that will be visible on the widget.

![Onglet commandes](..\assets\images\cfg_commands.png "Commandes")

Historical view
===
The history view is accessible from the camera widget. (History command)

This view gives you access to the latest videos from the camera.

The number of videos displayed as well as the size of the thumbnails is configurable on the plugin: see [Configuration du plugin](#-Configuration-du-plugin)

Use in scenarios
===
You can trigger a scenario by directly activating the information "Last event"

> See "Event" field in the image below

![Utilisation dans des scénarios](..\assets\images\scenario.png "Utilisation dans des scénarios")

branch_name: refs/heads/beta

gha_language: PHP


text:
##### Wabonki

[![Codacy Badge](https://api.codacy.com/project/badge/Grade/e7d53b2090aa431290a9b6995215684f)](https://app.codacy.com/app/zeab/wabonki?utm_source=github.com&utm_medium=referral&utm_content=zeab/wabonki&utm_campaign=Badge_Grade_Dashboard)
[![Build Status](https://travis-ci.org/zeab/wabonki.svg?branch=master)](https://travis-ci.org/zeab/wabonki)

This is a super lib that contains everything I have needed to build reactive kubernets ready microservices.
Use the scala-template project to save as a new template
Build a new project using that template
Import this project
Copy and splice the bit's needed for all the other example code

# Seeds
----
Here are a collection of Basic Seeds.
Seeds are outline of information used to grow a specific pre-determined actions.

Theory behind Seeds:
--
A seed is just a message.
There are many types of seeds.
Not all seeds need to sprout at once.
Seeds can be stored, re-used and germinated when necessary.
A seed will always grow to become what you expect it to be.
A seed is self contained.

Types of Seeds:
--
Http Seeds
    All the component to execute a single http request

Terminal Seeds
    All the component to execute a single terminal command

repository: zeab/wabonki

gha_language: Scala

repo_name: zeab/wabonki


text:
# Introduction

Unsatisified with the current state of Linux OS I have decided to build my own distro with it's own pacakge manager. I have created this book in order to evaluate how current package formats work, what they do well, and where they can make improvements.

## Terminology

In this post I will use several terms that are not explained in the [glossary](./glossary.md), this section will (hopefully) explain them so that everyone knows what I mean when I use each of them. If this section, or any other section of this post, is confusing please contact me and tell me. I am afraid I am not perfect, or a mind-reader, so I need you to tell me if something is wrong or if I omitted some important information.

### Package Building

**Building a package** will be used to refer to the process of compiling, or otherwise making a package’s source code executable, usually so that some file inside (usually a shell script or file written in object code) can be executed in order to start the program the package is for.

### Package Installation

The act of **installing a software package** involves moving the installed files of a package into a file system. Most of the time, when someone says that they are installing a package, what they are doing is they are installing the package’s file to the live file system (that is, the file system of the PC that is being used).

### Package Preparation

An important step in package development is the **preparation** of the sources being used to build the package.

### Source Compilation

When one is creating a software package, quite frequently one will need to **compile the package’s source code**, which means convert the source code written in some programming language into something that is machine readable and executable. This conversion is performed, using so called “compilers” like the GNU Compiler Collection (GCC) which creates object code from the source code.