Оптимизированные арифметические методы в R

В пакете openssl реализуется класс bignum с соответствующими методами арифметики и сравнения для выполнения вычислений по произвольным размерам.

В криптографии существует общий частный случай для модульной экспоненты x^p %% m, который используется, например, RSA. Для больших p вычисление x^p невозможно, но x^p %% m можно эффективно вычислить, что OpenSSL реализует в BN_mod_exp().

Предоставляет ли R какой-либо механизм для реализации методов ^.bignum и %%.bignum, так что при оценке x^y %% z мы можем назвать этот частный случай, а не вычислять x^p?

Ответы

Ответ 1

Поздно вечеринке, но да, это абсолютно возможно, и ее умеренно распространенный метод программирования на некоторых языках, например С++, где технику называют шаблоны выражений.

R, будучи слабо типизированным, не может полностью использовать шаблон в одинаковой степени. Но "светлая" версия по-прежнему возможна.

В двух словах вы определяете свой оператор ^.bignum, чтобы вместо этого или сразу же вычислить результат, он возвращает прокси-объект, который означает операцию "Возрождение". Этот прокси-объект имеет специально переопределенный метод %%, который вызывает реализацию ExpMod (например, BM_mod_exp). Он также определяет метод, который принуждает его к bignum путем оценки фактической операции x ^ y.

В коде это выглядит следующим образом:

# Vectorisation left as an exercise for the reader.

`^.bignum` = function (x, y)
    structure(c(x, y), class = 'bignum_mod_exp_proxy')

eval_exp = function (x)
    call_actual_exp(x[1], x[2])

as.bignum = function (x)
    if (inherits(x, 'bignum_mod_exp_proxy'))
        eval_exp(x)
    else
        # … implement other coercions to bignum, e.g. from `numeric`.

`%%.bignum_mod_exp_proxy` = function (x, y)
    call_BN_mod_exp(x[1], x[2], y)

# Pretend that a `bignum_mod_exp_proxy` in all other contexts. E.g.:

print.bignum_mod_exp_proxy = function (x, ...)
    print(eval_exp(x))

# … etc., for the rest of the `bignum` operations.

На самом деле вы можете даже переопределить =.bignum_mod_exp_proxy, <-.bignum_mod_exp_proxy и assign.bignum_mod_exp_proxy (преобразование assign в общий S3), так что назначения z = x ^ y оцениваются с помощью bignum. Тем не менее, это, вероятно, слишком велико, и для каждого задания будут накладные расходы.