# typhoid - non-standard numeric datatypes

`typhoid`

provides implementations of some non-standard datatypes using `{vctrs}`

## What’s in the box

`numberwang(x)`

for creating numeric values which present themselves as words.`uint16(x)`

for creating 16-bit unsigned integers, where each value is stored as a pair of raw bytes.`fixedpt(x, decimals = 3)`

for creating 32-bit fixed point numeric values.

Each of the types supports `as_<type>()`

and `is_<type>()`

, as well as standard
arithmetic operations (`+`

, `*`

etc) and mathematical functions e.g. `abs()`

## Limitations

These types were created in order to explore the
`{vctrs}`

package, and its capabilities
for easily creating new types, with minimal effort, along with broad support
for standard R features.

These are all pretty naive implementations with ill-defined overflow, and incomplete implementations.

They *could* be the core of properly useful, robust datatypes - but for now
they merely stand as small tutorials on how new types can be defined with
the `{vctrs}`

package.

## Installation

You can install from GitHub with:

```
# install.package('remotes')
remotes::install_github('coolbutuseless/numberwang')
remotes::install_github('coolbutuseless/typhoid')
```

The **numberwang** type is backed by the `{numberwang}`

package which provides
functions for converting from numbers to words, and vice versa.

```
num <- numberwang(42.123)
num
```

```
<typ_numberwang[1]>
[1] "forty-two point one two three"
```

`num + 5`

```
<typ_numberwang[1]>
[1] "forty-seven point one two three"
```

`numberwang(1:3) * 10`

```
<typ_numberwang[3]>
[1] "ten" "twenty" "thirty"
```

`numberwang(1:3) * as_numberwang("twenty seven")`

```
<typ_numberwang[3]>
[1] "twenty-seven" "fifty-four" "eighty-one"
```

`uint16`

values are represented internally as a pair of bytes.

Since a `uint16`

takes up only 16bits, it can only hold integers in the range 0-65535.

This offers space savings compared with R’s standard integer (four bytes), as long as your numbers fit in the given range.

Arithmetic operations are performed modulo 65536.

```
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# uint16 doesn't really behave differently from a small integer
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
uint16(42)
```

```
#> <typ_uint16[1]>
#> [1] 42
```

`uint16(c(100, 150)) * 2`

```
#> <typ_uint16[2]>
#> [1] 200 300
```

```
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# uint16 uses only half the memory of a regular integer, but has
# a much reduced range as well
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ints <- sample(65535)
lobstr::obj_size(ints)
```

`#> 262,192 B`

`lobstr::obj_size(uint16(ints))`

`#> 131,904 B`

Fixed point numbers are implemented as integer values and a divisor which is a
power of 10. For instance `12.34`

is represented as the integer `1234`

with a
divisor of 100.

Fixed point numbers show as many decimal places as
set during initialisation with the `fixedpt(x, decimals = 3)`

call.

When numeric operations are performed on a `fixedpt`

, the result is also a
fixed point, with the number of decimals set to the be the maximum of decimal
places of the two arguments.

Numbers are only representable as a `fixedpt`

if the unscaled number fits into
a normal R integer.

```
n1 <- fixedpt(1:5, decimals = 3)
n1
```

```
#> <typ_fixedpt[5]>
#> [1] 1.000 2.000 3.000 4.000 5.000
```

```
n2 <- fixedpt(101:105, decimals = 5)
n2
```

```
#> <typ_fixedpt[5]>
#> [1] 101.00000 102.00000 103.00000 104.00000 105.00000
```

`n1 * n2`

```
#> <typ_fixedpt[5]>
#> [1] 101.00000 204.00000 309.00000 416.00000 525.00000
```

## Acknowledgements

- R Core for developing and maintaining the language.
- CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining the repository