scalabook

Форк
0
/
spire.md 
249 строк · 14.7 Кб

Spire

Spire — это числовая библиотека для Scala, которая должна быть универсальной, быстрой и точной.

Используя такие функции, как специализация, макросы, классы типов и неявные выражения, Spire прилагает все усилия, чтобы бросить вызов общепринятым представлениям о компромиссах между производительностью и точностью. Основная цель — позволить разработчикам писать эффективный числовой код без необходимости "встраивать" определенные числовые представления. В большинстве случаев универсальные реализации, использующие специализированные классы типов Spire, работают идентично соответствующим прямым реализациям.

Пример использования библиотеки Spire:

import spire.*
import spire.implicits.*
import spire.math.*
Complex(3.0,5.0).sin
// val res0: spire.math.Complex[Double] = (10.472508533940392 + -73.46062169567367i)

Числовые типы

Помимо поддержки всех встроенных числовых типов Scala, Spire представляет несколько новых, все из которых можно найти в spire.math

:

  • Natural
    - беззнаковое, неизменяемое целое число произвольной точности
  • Rational
    - дроби целых чисел с идеальной точностью
  • Algebraic
    - лениво вычисляемые алгебраические числа произвольной точности
  • Real
    - реализация вычислимых действительных чисел
  • Complex[A]
    - комплексные числа, точки на комплексной плоскости
  • Jet[A]
    - N-мерные двойные числа для автоматического дифференцирования
  • Quaternion[A]
    - расширение комплексных чисел в четырехмерное пространство
  • от UByte
    до ULong
    - классы значений, поддерживающие беззнаковые операции
  • SafeLong
    - быстрый целочисленный тип с защитой от переполнения
  • Number
    - запечатанный тип с поддержкой традиционной числовой опоры
  • Interval[A]
    - арифметика на открытых, закрытых и несвязанных интервалах
  • Polynomial[A]
    - одномерные (с одной переменной) полиномиальные выражения
  • Trilean
    - класс значений, поддерживающий трехзначную логику
  • FixedPoint
    - дроби с Long
    числителем и неявным знаменателем (в доп.)

Классы типов

Spire предоставляет классы типов для поддержки широкого спектра унарных и двоичных операций с числами. Классы типов являются специализированными, не выполняют упаковку и используют неявные выражения для обеспечения удобного инфиксного синтаксиса.

Классы типов общего назначения можно найти в пакете spire.math

:

  • Numeric[A]
    - все типы чисел, прилагает все усилия для поддержки операторов
  • Fractional[A]
    - типы дробных чисел, где /
    - честное деление
  • Integral[A]
    - типы целых чисел, где /
    - деление по уровням

Некоторые классы типов общего назначения построены на основе набора более фундаментальных классов типов, определенных в spire.algebra

. Многие из них соответствуют понятиям абстрактной алгебры:

  • Eq[A]
    - типы, которые можно сравнивать на равенство
  • Order[A]
    - типы, которые можно сравнивать и упорядочивать
  • PartialOrder[A]
    - типы, которые можно сравнивать на равенство и для которых упорядочены определенные пары
  • Semigroup[A]
    - типы с ассоциативным бинарным оператором |+|
  • Monoid[A]
    - полугруппы, имеющие единичный элемент
  • Group[A]
    - моноиды, имеющие обратный оператор
  • (Left/Right/)Action[P, G]
    - действия влево/вправо для полугрупп/моноидов/групп
  • Semiring[A]
    - типы, образующие полугруппы под +
    и *
  • Rng[A]
    - типы, которые образуют группу +
    и полугруппу под *
  • Rig[A]
    - типы, образующие моноиды под +
    и *
  • Ring[A]
    - типы, образующие группу под +
    и моноид под *
  • EuclideanRing[A]
    - кольца с частными и остатками (евклидово деление)
  • Field[A]
    - евклидовы кольца с мультипликативными инверсиями (взаимными)
  • Signed[A]
    - типы, имеющие знак (отрицательный, ноль, положительный)
  • NRoot[A]
    - типы, поддерживающие k-корни, журналы и дробные степени
  • Module[V,R]
    - типы, образующие левый R-модуль
  • VectorSpace[V,F]
    - типы, образующие векторное пространство
  • NormedVectorSpace[V,F]
    - типы с соответствующей нормой
  • InnerProductSpace[V,F]
    - типы с внутренним произведением
  • MetricSpace[V,R]
    - типы со связанной метрикой
  • Trig[A]
    - типы, поддерживающие тригонометрические функции
  • Bool[A]
    - типы, образующие булеву алгебру
  • Heyting[A]
    - типы, образующие алгебру Гейтинга

Варианты Semigroup

/Monoid
/Group
/Action
с частичными операциями определены в подпакете spire.algebra.partial
.

Помимо самих классов типов, spire.implicits

определяет множество неявных функций, которые предоставляют унарные и инфиксные операторы для классов типов. Самый простой способ использовать их — импортировать файлы spire.implicits.*
.

С чего начать?

Spire содержит множество типов, а также другие механизмы, обеспечивающие удобство использования. Самый простой способ использовать Spire — импортировать зависимости:

import spire.algebra.* // предоставляет алгебраические классы типов
import spire.implicits.* // обеспечивает инфиксные операторы, инстансы и конверсию
import spire.math.* // обеспечивает функции, типа и классы типов

Операции, отсортированные по классам типов

Ниже приводится более подробное описание классов типов, предоставляемых Spire, а также операторов, которые они используют. Хотя Spire по возможности избегает введения новых операторов, в некоторых случаях это было неизбежно.

Числа

Эти классы типов высокого уровня будут включать все соответствующие классы алгебраических типов.

  • Integral
    : целочисленные типы (например, Int
    , BigInt
    )
  • Fractional
    : дробные/десятичные типы (например, Double
    , Rational
    )
  • Numeric
    : тип произвольного числа, прилагающий "все усилия" для поддержки операций

Класс типов Numeric

уникален тем, что обеспечивает ту же функциональность, что Fractional
и все числовые типы. Каждый тип будет пытаться "поступить правильно", насколько это возможно, в противном случае выдавать ошибки. Пользователям, которые настороженно относятся к такому поведению, рекомендуется использовать более точные классы типов.

Синтаксис

Используя строковую интерполяцию и макросы, Spire обеспечивает удобный синтаксис для числовых типов. Эти макросы оцениваются во время компиляции, и любые ошибки, с которыми они сталкиваются, возникают во время компиляции.

Например:

object LiteralsDemo:
import spire.syntax.literals.*
// byte-ы и short-ы
val x = b"100" // без аннотации типа!
val y = h"999"
val mask = b"255" // беззнаковая константа сконвертированная в знаковую (-1)
// дроби
val n1 = r"1/3"
val n2 = r"1599/115866" // упроститься при компиляции до 13/942
object SIDemo:
// SI нотация для больших чисел
import spire.syntax.literals.si.* // также доступны `.us` и `.eu`
val w = i"1 944 234 123" // Int
val x = j"89 234 614 123 234 772" // Long
val y = big"123 234 435 456 567 678 234 123 112 234 345" // BigInt
val z = dec"1 234 456 789.123456789098765" // BigDecimal

Spire также предоставляет макрос цикла cfor

, синтаксис которого немного похож на традиционный цикл for
из C или Java. Этот макрос расширяется до хвостовой рекурсивной функции, которая встраивает литеральные аргументы функции.

Макрос может быть вложен сам в себя и выгодно отличается от других конструкций цикла в Scala, таких как for

и while
:

import spire.syntax.cfor.*
// печатает числа от 0 до 9
cfor(0)(_ < 10, _ + 1): i =>
println(i)
// простой алгоритм сортировки
def selectionSort(ns: Array[Int]): Unit =
val limit = ns.length - 1
cfor(0)(_ < limit, _ + 1): i =>
var k = i
val n = ns(i)
cfor(i + 1)(_ <= limit, _ + 1): j =>
if ns(j) < ns(k) then k = j
ns(i) = ns(k)
ns(k) = n

Остальные операции

Разное

Кроме того, Spire предоставляет множество других методов, которые "отсутствуют" в java.Math

scala.math
), например:

  • log(BigDecimal): BigDecimal
  • exp(BigDecimal): BigDecimal
  • pow(BigDecimal): BigDecimal
  • pow(Long): Long
  • gcd(Long, Long): Long
  • и так далее...

Тесты

Помимо модульных тестов, Spire поставляется с относительно детальным набором микротестов JMH. Чтобы запустить тесты из SBT, перейдите к подпроекту benchmark

и затем запустите Jmh / run -l
, чтобы просмотреть список тестов:

$ sbt
> project benchmark
> Jmh / run -l

[info] Benchmarks:
[info] spire.benchmark.AddBenchmarks.addComplexDoubleStateDirect
[info] spire.benchmark.AddBenchmarks.addComplexDoubleStateGeneric
[info] spire.benchmark.AddBenchmarks.addComplexFloatStateDirect
...

Чтобы запустить все доступные тесты:

> Jmh / run

Чтобы запустить определенный метод тестирования:

> Jmh / run spire.benchmark.AddBenchmarks.addComplexDoubleStateDirect

Чтобы запустить все тесты в определенном классе:

> Jmh / run spire.benchmark.AddBenchmarks

Чтобы просмотреть все доступные варианты использования JMH:

> Jmh / run -h

Если вы планируете внести свой вклад в Spire, обязательно запустите соответствующие тесты, чтобы убедиться, что ваши изменения не повлияют на производительность. Тесты обычно включают сравнение с эквивалентными классами Scala или Java, чтобы попытаться измерить как относительную, так и абсолютную производительность.


Ссылки:

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.