---
title: "Math functions"
description: "The kScript (legacy) math namespace becomes AssemblyScript's Math: absolute value, rounding, powers and roots, logarithms, and the full trig and hyperbolic…"
order: 48
section: "functions"
---

<!-- source: docs/indicators/functions/math-functions.md; generated by packages/cli/scripts/gen-indicator-docs.ts, do not edit -->

# Math functions

The kScript (legacy) `math` namespace becomes AssemblyScript's `Math`:
absolute value, rounding, powers and roots, logarithms, and the full trig
and hyperbolic families, on `f64`. Call them on any number in `state()`
or `finalize()` and they evaluate per bar, exactly like their JavaScript
counterparts, with one difference worth knowing: the compiler is typed,
so an integer and a float never mix silently.

Every method lives under the `Math.` prefix (capital M). There is no
global `abs()` or `round()` for floats; it is always `Math.abs(...)`,
`Math.round(...)`. Use them to normalize a signal, scale a value into a
range, or build a custom indicator from primitives.

```typescript
const spread = close - average;
// How far is price from its average, regardless of direction?
distance = Math.abs(spread);
```

## What is available

| Group | Methods |
| --- | --- |
| Basic | `abs`, `sign` |
| Rounding | `round`, `floor`, `ceil`, `trunc` |
| Powers and roots | `pow`, `sqrt`, `cbrt`, `hypot` |
| Exp and log | `exp`, `expm1`, `log`, `log1p`, `log2`, `log10` |
| Comparison | `max`, `min` |
| Trig (radians) | `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `atan2` |
| Hyperbolic | `sinh`, `cosh`, `tanh`, `asinh`, `acosh`, `atanh` |

Constants: `Math.PI`, `Math.E`, `Math.SQRT2`, `Math.SQRT1_2`, `Math.LN2`,
`Math.LN10`, `Math.LOG2E`, `Math.LOG10E`.

Each behaves like its JavaScript counterpart. `Math.max` and `Math.min`
take two `f64` arguments and return the larger or smaller; nest them for
three. `Math.round` rounds to the nearest integer and returns an `f64`.
Trig functions work in radians, so divide a bar count or an angle
accordingly (`Math.sin(f64(barIndex) / 10.0)`).

**Types.** `Math.*` takes and returns `f64`. An `i32` (a bar count, a
loop index, a ring cursor) must be cast in (`f64(count)`) and a result
used as an index must be cast out (`i32(Math.floor(x))`); the compiler
refuses the implicit conversion with `AS200`. For integer work
AssemblyScript has typed builtins that need no cast: `abs<i32>(n)`,
`max<i32>(a, b)`, `min<i32>(a, b)`, and integer division truncates on
its own (`7 / 2` is `3` for two `i32` values, `3.5` for two `f64`).

**There is no `Math.avg`.** To average two values, write the arithmetic
(`(a + b) / 2.0`); for a rolling average over a window, use `Sma`
([Moving averages](moving-averages.md)). Calling a method that does not
exist is a compile error, not a runtime one: `Math.unknownFn(x)` stops
the build with `TS2339: Property 'unknownFn' does not exist on type
'~lib/math/NativeMath'`, with the line and column.

## Every method in one module

This module runs the full namespace at once. It builds a few helper values
first (a `centered` series of price minus its average, a `bounded` value
safe for `asin` and `acos`, and a `positive` value safe for `log` and
`sqrt`), then writes each `Math.*` result to its own output.

```typescript
import { input, line, lower, ohlcv, output, param } from "./sdk/declare";
import { in_close, in_high, in_low } from "./gen/inputs";
import {
  emitRow,
  out_abs,
  out_acos,
  out_acosh,
  out_asin,
  out_asinh,
  out_atan,
  out_atan2,
  out_atanh,
  out_cbrt,
  out_ceil,
  out_cos,
  out_cosh,
  out_exp,
  out_expm1,
  out_floor,
  out_hypot,
  out_log,
  out_log10,
  out_log1p,
  out_log2,
  out_max,
  out_min,
  out_pow,
  out_round,
  out_sign,
  out_sin,
  out_sinh,
  out_sqrt,
  out_tan,
  out_tanh,
  out_trunc,
} from "./gen/outputs";
import { p_period } from "./gen/params";
import { Sma } from "./sdk/ta";

param("period", 5, { min: 2, max: 200 });
input("close", ohlcv.close);
input("high", ohlcv.high);
input("low", ohlcv.low);
output("abs", line, lower, { description: "Math.abs of the centered close" });
output("round", line, lower, { description: "Math.round" });
output("max", line, lower, { description: "Math.max of high and close" });
output("min", line, lower, { description: "Math.min of low and close" });
output("pow", line, lower, { description: "Math.pow of the small value, squared" });
output("sqrt", line, lower, { description: "Math.sqrt of the positive value" });
output("log", line, lower, { description: "Math.log of the positive value" });
output("floor", line, lower, { description: "Math.floor" });
output("ceil", line, lower, { description: "Math.ceil" });
output("sign", line, lower, { description: "Math.sign: -1, 0, or 1" });
output("sin", line, lower, { description: "Math.sin of the bar index over 8" });
output("cos", line, lower, { description: "Math.cos of the bar index over 8" });
output("tan", line, lower, { description: "Math.tan of the bar index over 40" });
output("asin", line, lower, { description: "Math.asin of the bounded value" });
output("acos", line, lower, { description: "Math.acos of the bounded value" });
output("atan", line, lower, { description: "Math.atan of the centered close" });
output("atan2", line, lower, { description: "Math.atan2 of centered over positive" });
output("sinh", line, lower, { description: "Math.sinh of the small value" });
output("cosh", line, lower, { description: "Math.cosh of the small value" });
output("tanh", line, lower, { description: "Math.tanh of the small value" });
output("asinh", line, lower, { description: "Math.asinh of the small value" });
output("acosh", line, lower, { description: "Math.acosh of the positive value" });
output("atanh", line, lower, { description: "Math.atanh of half the bounded value" });
output("exp", line, lower, { description: "Math.exp of the small value" });
output("expm1", line, lower, { description: "Math.expm1 of the small value" });
output("log1p", line, lower, { description: "Math.log1p of the small value's magnitude" });
output("log2", line, lower, { description: "Math.log2 of the positive value" });
output("log10", line, lower, { description: "Math.log10 of the positive value" });
output("cbrt", line, lower, { description: "Math.cbrt of the centered close" });
output("hypot", line, lower, { description: "Math.hypot of centered and small" });
output("trunc", line, lower, { description: "Math.trunc of the centered close" });

let sma = new Sma(5);
let barIndex: i32 = 0;
let centered: f64 = NaN;
let bounded: f64 = NaN;
let positive: f64 = NaN;
let small: f64 = NaN;
let high: f64 = NaN;
let low: f64 = NaN;
let close: f64 = NaN;

export function init(): void {
  sma = new Sma(i32(p_period()));
}

export function state(): i32 {
  close = in_close();
  high = in_high();
  low = in_low();
  const average = sma.update(close);
  centered = close - average;
  // The bar index is an i32 counter; the trig helpers want an f64 in radians.
  bounded = Math.sin(f64(barIndex) / 10.0);
  positive = Math.abs(centered) + 1.0;
  small = centered / 10.0;
  barIndex += 1;
  return isNaN(average) ? 0 : 1;
}

export function finalize(): void {
  const angle = f64(barIndex) / 8.0;
  out_abs(Math.abs(centered));
  out_round(Math.round(centered));
  out_max(Math.max(high, close));
  out_min(Math.min(low, close));
  out_pow(Math.pow(small, 2.0));
  out_sqrt(Math.sqrt(positive));
  out_log(Math.log(positive));
  out_floor(Math.floor(centered));
  out_ceil(Math.ceil(centered));
  out_sign(Math.sign(centered));
  out_sin(Math.sin(angle));
  out_cos(Math.cos(angle));
  out_tan(Math.tan(f64(barIndex) / 40.0));
  out_asin(Math.asin(bounded));
  out_acos(Math.acos(bounded));
  out_atan(Math.atan(centered));
  out_atan2(Math.atan2(centered, positive));
  out_sinh(Math.sinh(small));
  out_cosh(Math.cosh(small));
  out_tanh(Math.tanh(small));
  out_asinh(Math.asinh(small));
  out_acosh(Math.acosh(positive));
  out_atanh(Math.atanh(bounded / 2.0));
  out_exp(Math.exp(small));
  out_expm1(Math.expm1(small));
  out_log1p(Math.log1p(Math.abs(small)));
  out_log2(Math.log2(positive));
  out_log10(Math.log10(positive));
  out_cbrt(Math.cbrt(centered));
  out_hypot(Math.hypot(centered, small));
  out_trunc(Math.trunc(centered));
  emitRow();
}

export function reset(): void {
  sma.reset();
  barIndex = 0;
  centered = NaN;
  bounded = NaN;
  positive = NaN;
  small = NaN;
  high = NaN;
  low = NaN;
  close = NaN;
}
```

## Domain notes

A few methods are only defined for part of the number line, exactly as in
standard math:

- `Math.sqrt` and `Math.log` expect non-negative input. Guard with
  `Math.abs(x) + 1.0` or a `Math.max` floor if your series can go negative
  or hit zero.
- `Math.asin` and `Math.acos` only accept values in `[-1, 1]`. Feed them
  something already bounded (the module uses `Math.sin(...)`).
- `Math.acosh` expects input `>= 1`.

Out-of-domain input produces `NaN` rather than trapping, so an output may
simply show gaps where the input left the valid range, and `NaN` written
to an output draws nothing and never trips an alert. A division by zero
on `f64` yields an infinity, not a trap; `isFinite(x)` catches both before
the value reaches an output. Integer division by zero DOES trap and
aborts the evaluation, so guard an `i32` divisor.
