# The HOPS language

Each line of a HOPS script is an independent program and each line/program consists of a semicolon separated list of functional equations and generating functions. We shall now describe operations, functions and transformations that can be used when building such programs.

## Binary operations

Operation Meaning
`f + g` sum of `f` and `g`
`f - g` difference of `f` and `g`
`f ^ g` `f` to the power `g`
`f @ g` `f` composed with `g` (can also be written `f(g)` when `f` is a name)
`f ? g` coefficients of `f` selected by nonnegative integer coefficients of `g`
`f * g` product of `f` and `g`
`f / g` quotient of `f` and `g`
`f .* g` coefficient-wise/Hadamard product of `f` and `g`
`f ./ g` coefficient-wise quotient of `f` and `g`

## Functions

Function Meaning
`diff(f)` derivative of `f`
`int(f)` integral of `f`
`sqrt(f)` `f^(1/2)`
`abs(f)` `f` multiplied by the sign of its leading coefficient
`log(f)` logarithmic function
`exp(f)` exponential function
`sin(f)` sine function
`cos(f)` cosine function
`tan(f)` tangent function
`sec(f)` `1/cos(f)`
`arcsin(f)` arcsine function
`arccos(f)` arccosine function
`arctan(f)` arctangent function
`sinh(f)` hyperbolic sine function
`cosh(f)` hyperbolic cosine function
`tanh(f)` hyperbolic tangent function
`arsinh(f)` area hyperbolic sine function
`arcosh(f)` area hyperbolic cosine function
`artanh(f)` area hyperbolic tangent function
`laplace(f)` `f .* {n!}`
`laplacei(f)` `f ./ {n!}`
`revert(f)` the compositional inverse of `f`
`absolute(f)` coefficient-wise absolute value
`bisect0(f)` if `f={a0,a1,a2,a3,a4,...}` then `bisect0(f)={a0,a2,a4,...}`
`bisect1(f)` if `f={a0,a1,a2,a3,a4,...}` then `bisect1(f)={a1,a3,a5,...}`
`bous(f)` Boustrophedon transform
`bousi(f)` inverse Boustrophedon transform
`cyc(f)` `sum[(phi(k)/k)*log(1/(1-f(x^k)))], k>0`; phi = totient function
`delta(f)` `shift(f)-f`
`euler(f)` Euler transform
`euleri(f)` inverse Euler transform
`hankel(f)` Hankel transform
`indicator(f)` if `f={a_k}` then `indicator(f)={b_i}` where `b_(a_k)=1`; else `b_i=0`
`indicatorc(f)` "complement" of `indicator(f)`: substituting 0 for 1 and 1 for 0
`shift(f)` if `f={a0,a1,a2,a3,a4,...}` then `shift(f)={a1,a2,a3,...}`
`mobius(f)` Möbius transform
`mobiusi(f)` inverse Möbius transform
`mset(f)` if `f={a_k}` then `mset(f)=product[(1-x^k)^(-a_k)], k>0`
`partition(f)` see https://oeis.org/transforms.txt (Includes constant term)
`point(f)` `laplace(x*diff(laplacei(f)))`
`prods(f)` if `f = {a0,a1,a2,...}` then `prods(f)={a0,a0*a1,a0*a1*a2,...}`
`pset(f)` if `f={a_k}` then `pset(f)=product[(1+x^k)^a_k], k>0`
`seq(f)` `1/(1-f)`
`T019(f)` if `f={a[n]}` then `{a[n+2]-2*a[n+1]+a[n]}`
`trisect0(f)` if `f={a0,a1,a2,a3,a4,...}` then `trisect0(f)={a0,a3,a6,...}`
`trisect1(f)` if `f={a0,a1,a2,a3,a4,...}` then `trisect0(f)={a1,a4,a7,...}`
`trisect2(f)` if `f={a0,a1,a2,a3,a4,...}` then `trisect0(f)={a2,a5,a8,...}`
`weight(f)` if `f={a0,a1,a2,...}` then `weight(f)=(1+x^n)^a0*(1+x^n)^a1*...`
`dirichlet(f,g)` Dirichlet convolution

## A grammar for HOPS scripts

A HOPS script is a list of independent programs (`prg`) - one program per line:

``hops = prg { "\n" prg }``

A program is a list of semicolon separated commands (`cmd`):

``prg = cmd { ";" cmd }``

A command is a generating function expression (`expr0`) or an assignment:

``cmd = expr0 | name "=" expr0``

We use the precedence climbing method to define generating function expressions:

``````expr0 = expr0 ("+" | "-") expr0 | expr1

expr1 = expr1 ("*" | "/" | ".*" | "./") expr1 | expr2

expr2 = ("-" | "+") expr2 | expr3 "!" | expr3 "^" expr3 | expr3 "@" expr3 | expr3 "?" expr3 |expr3

expr3 = "x" | anum | tag | name | lit | "{" { terms } "}" | "[" { terms } "]" | name "(" expr0 { "," expr0 }  ")" | name expr3 | "(" expr0 ")"

lit = int

int = digit { digit }

digit = "0" | "1" | ... | "9"

alpha = "A" | "B" | ... | "Z" | "a" | "b" | ... | "z"

alphanum = alpha | digit

name = alphanum { alphanum | "_" }

terms = cexpr0 { "," expr0 } ("..." | cexpr0 | fun)

fun = the same as cexpr0 except lit = linear

linear = int | int "*n"

cexpr0 = cexpr0 ("+" | "-") cexpr0 | cexpr1

cexpr1 = cexpr1 ("*" | "/") cexpr1 | cexpr2

cexpr2 = ("+" | "-") cexpr2 | cexpr3 "!" | cexpr3 "^" cexpr3 | cexpr3

cexpr3 = lit | cexpr0``````