diff --git a/dev/TEAL.md b/dev/TEAL.md index e9ae148..33c1288 100644 --- a/dev/TEAL.md +++ b/dev/TEAL.md @@ -358,11 +358,15 @@ return stack matches the name of the input value. | `json_ref r` | key B's value, of type R, from a [valid](jsonspec.md) utf-8 encoded json object A | The following opcodes take byte-array values that are interpreted as -big-endian unsigned integers. For mathematical operators, the +decimals. For mathematical operators, the returned values are the shortest byte-array that can represent the returned value. For example, the zero value is the empty byte-array. For comparison operators, the returned value is a uint64. +Decimals are interpreted as follows: +Given A: uint64, B: []byte, width: uint64, E: uint64 interpret B as a big-endian unsigned integer and multiply that with: +(-1)^A * 10^((-1)^E * width) + Input lengths are limited to a maximum length of 64 bytes, representing a 512 bit unsigned integer. Output lengths are not explicitly restricted, though only `b*` and `b+` can produce a larger @@ -371,18 +375,23 @@ bytes on outputs. | Opcode | Description | | - | -- | -| `b+` | A plus B. A and B are interpreted as big-endian unsigned integers | -| `b-` | A minus B. A and B are interpreted as big-endian unsigned integers. Fail on underflow. | -| `b/` | A divided by B (truncated division). A and B are interpreted as big-endian unsigned integers. Fail if B is zero. | -| `b*` | A times B. A and B are interpreted as big-endian unsigned integers. | -| `b<` | 1 if A is less than B, else 0. A and B are interpreted as big-endian unsigned integers | -| `b>` | 1 if A is greater than B, else 0. A and B are interpreted as big-endian unsigned integers | -| `b<=` | 1 if A is less than or equal to B, else 0. A and B are interpreted as big-endian unsigned integers | -| `b>=` | 1 if A is greater than or equal to B, else 0. A and B are interpreted as big-endian unsigned integers | -| `b==` | 1 if A is equal to B, else 0. A and B are interpreted as big-endian unsigned integers | -| `b!=` | 0 if A is equal to B, else 1. A and B are interpreted as big-endian unsigned integers | +| `b+` | Addition of decimals. | +| `b-` | Subtraction of decimals. Fail on underflow. | +| `b/` | Division of decimals (truncated division). Fail if B is zero. | +| `b*` | Multilpication of decimals. | +| `b<` | Less than, 1 if true, else 0. | +| `b>` | Greater than, 1 if true, else 0. | +| `b<=` | Less than xor equal, 1 if true, else 0. | +| `b>=` | Greater than xor equal, 1 if true, else 0. | +| `b==` | Equal, 1 if true, else 0. | +| `b!=` | Not equal, 1 if true, else 0. | | `b%` | A modulo B. A and B are interpreted as big-endian unsigned integers. Fail if B is zero. | -| `bsqrt` | The largest integer I such that I^2 <= A. A and I are interpreted as big-endian unsigned integers | +| `bsqrt` | The largest integer I such that I^2 <= A. A and I are interpreted as big-endian unsigned integers. | +| `bpow` | Decimal to the power of a decimal. | +| `bexp` | e to the power of a decimal. | +| `bln` | Natural logarithm of a decimal. | +| `blog2` | Logarithm base 2 of a decimal. | +| `blog10` | Logarithm base 10 of a decimal. | These opcodes operate on the bits of byte-array values. The shorter input array is interpreted as though left padded with zeros until it is the diff --git a/dev/TEAL_opcodes.md b/dev/TEAL_opcodes.md index 1ab0fe3..24d0007 100644 --- a/dev/TEAL_opcodes.md +++ b/dev/TEAL_opcodes.md @@ -1219,79 +1219,109 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with - **Cost**: 130 - Availability: v7 -## b+ +## b+ widthB widthD widthY - Opcode: 0xa0 -- Stack: ..., A: []byte, B: []byte → ..., []byte -- A plus B. A and B are interpreted as big-endian unsigned integers +- Stack: ..., A: uint64, B: []byte, C: uint64, D: []byte, E: uint64, F: uint64, G: uint64 → ..., X: uint64, Y: []byte +- Addition of decimals. B and D are interpreted as big-endian unsigned integers. - **Cost**: 10 -- Availability: v4 +- Availability: v9 + +wB = (-1)^E * widthB ; wD = (-1)^F * widthD ; wY = (-1)^G * widthY +[(-1)^A * B * 10^wB] + [(-1)^C * D * 10^wD] = (-1)^X * Y * 10^wY. widthB, widthD and widthY are uint64. widthY decimal output precision is guaranteed. -## b- +## b- widthB widthD widthY - Opcode: 0xa1 -- Stack: ..., A: []byte, B: []byte → ..., []byte -- A minus B. A and B are interpreted as big-endian unsigned integers. Fail on underflow. +- Stack: ..., A: uint64, B: []byte, C: uint64, D: []byte, E: uint64, F: uint64, G: uint64 → ..., X: uint64, Y: []byte +- Subtraction of decimals. B and D are interpreted as big-endian unsigned integers. Fail on underflow. - **Cost**: 10 -- Availability: v4 +- Availability: v9 -## b/ +wB = (-1)^E * widthB ; wD = (-1)^F * widthD ; wY = (-1)^G * widthY +[(-1)^A * B * 10^wB] - [(-1)^C * D * 10^wD] = (-1)^X * Y * 10^wY. widthB, widthD and widthY are uint64. widthY output precision is guaranteed. + +## b/ widthB widthD widthY - Opcode: 0xa2 -- Stack: ..., A: []byte, B: []byte → ..., []byte -- A divided by B (truncated division). A and B are interpreted as big-endian unsigned integers. Fail if B is zero. +- Stack: ..., A: uint64, B: []byte, C: uint64, D: []byte, E: uint64, F: uint64, G: uint64 → ..., X: uint64, Y: []byte +- Division of decimals (truncated division). B and D are interpreted as big-endian unsigned integers. Fail if D is zero. - **Cost**: 20 -- Availability: v4 +- Availability: v9 + +wB = (-1)^E * widthB ; wD = (-1)^F * widthD ; wY = (-1)^G * widthY +[(-1)^A * B * 10^wB] / [(-1)^C * D * 10^wD] = (-1)^X * Y * 10^wY. widthB, widthD and widthY are uint64. widthY output precision is guaranteed. -## b* +## b* widthB widthD widthY - Opcode: 0xa3 -- Stack: ..., A: []byte, B: []byte → ..., []byte -- A times B. A and B are interpreted as big-endian unsigned integers. +- Stack: ..., A: uint64, B: []byte, C: uint64, D: []byte, E: uint64, F: uint64, G: uint64 → ..., X: uint64, Y: []byte +- Multilpication of decimals. B and D are interpreted as big-endian unsigned integers. - **Cost**: 20 -- Availability: v4 +- Availability: v9 -## b< +wB = (-1)^E * widthB ; wD = (-1)^F * widthD ; wY = (-1)^G * widthY +[(-1)^A * B * 10^wB] * [(-1)^C * D * 10^wD] = (-1)^X * Y * 10^wY. widthB, widthD and widthY are uint64. widthY output precision is guaranteed. + +## b< widthB widthD - Opcode: 0xa4 -- Stack: ..., A: []byte, B: []byte → ..., uint64 -- 1 if A is less than B, else 0. A and B are interpreted as big-endian unsigned integers -- Availability: v4 +- Stack: ..., A: uint, B: []byte, C: uint, D: []byte, E: uint64, F: uint64 → ..., uint64 +- Less than, 1 if true, else 0. B and D are interpreted as big-endian unsigned integers. +- Availability: v9 -## b> +wB = (-1)^E * widthB ; wD = (-1)^F * widthD +(-1)^A * B * 10^wB < (-1)^C * D * 10^wD. widthB and widthD are uint. + +## b> widthB widthD - Opcode: 0xa5 -- Stack: ..., A: []byte, B: []byte → ..., uint64 -- 1 if A is greater than B, else 0. A and B are interpreted as big-endian unsigned integers -- Availability: v4 +- Stack: ..., A: uint, B: []byte, C: uint, D: []byte, E: uint64, F: uint64 → ..., uint64 +- Greater than, 1 if true, else 0. B and D are interpreted as big-endian unsigned integers. +- Availability: v9 -## b<= +wB = (-1)^E * widthB ; wD = (-1)^F * widthD +(-1)^A * B * 10^wB > (-1)^C * D * 10^wD. widthB and widthD are uint. + +## b<= widthB widthD - Opcode: 0xa6 -- Stack: ..., A: []byte, B: []byte → ..., uint64 -- 1 if A is less than or equal to B, else 0. A and B are interpreted as big-endian unsigned integers -- Availability: v4 +- Stack: ..., A: uint, B: []byte, C: uint, D: []byte, E: uint64, F: uint64 → ..., uint64 +- Less than xor equal, 1 if true, else 0. B and D are interpreted as big-endian unsigned integers. +- Availability: v9 -## b>= +wB = (-1)^E * widthB ; wD = (-1)^F * widthD +(-1)^A * B * 10^wB <= (-1)^C * D * 10^wD. widthB and widthD are uint. + +## b>= widthB widthD - Opcode: 0xa7 -- Stack: ..., A: []byte, B: []byte → ..., uint64 -- 1 if A is greater than or equal to B, else 0. A and B are interpreted as big-endian unsigned integers -- Availability: v4 +- Stack: ..., A: uint, B: []byte, C: uint, D: []byte, E: uint64, F: uint64 → ..., uint64 +- Greater than xor equal, 1 if true, else 0. B and D are interpreted as big-endian unsigned integers. +- Availability: v9 -## b== +wB = (-1)^E * widthB ; wD = (-1)^F * widthD +(-1)^A * B * 10^wB >= (-1)^C * D * 10^wD. widthB and widthD are uint. + +## b== widthB widthD - Opcode: 0xa8 -- Stack: ..., A: []byte, B: []byte → ..., uint64 -- 1 if A is equal to B, else 0. A and B are interpreted as big-endian unsigned integers -- Availability: v4 +- Stack: ..., A: uint, B: []byte, C: uint, D: []byte, E: uint64, F: uint64 → ..., uint64 +- Equal, 1 if true, else 0. B and D are interpreted as big-endian unsigned integers. +- Availability: v9 -## b!= +wB = (-1)^E * widthB ; wD = (-1)^F * widthD +(-1)^A * B * 10^wB == (-1)^C * D * 10^wD. widthB and widthD are uint. + +## b!= widthB widthD - Opcode: 0xa9 -- Stack: ..., A: []byte, B: []byte → ..., uint64 -- 0 if A is equal to B, else 1. A and B are interpreted as big-endian unsigned integers -- Availability: v4 +- Stack: ..., A: uint, B: []byte, C: uint, D: []byte, E: uint64, F: uint64 → ..., uint64 +- Not equal, 1 if true, else 0. B and D are interpreted as big-endian unsigned integers. +- Availability: v9 + +wB = (-1)^E * widthB ; wD = (-1)^F * widthD +(-1)^A * B * 10^wB != (-1)^C * D * 10^wD. widthB and widthD are uint. ## b% @@ -1340,6 +1370,42 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with - zero filled byte-array of length A - Availability: v4 +## bexp widthB widthY + +- Opcode: 0x?? +- Stack: ..., A: uint, B: []byte, E: uint64, F: uint64 → ..., Y: []byte +- e to the power of a decimal. B is interpreted as big-endian unsigned integers. +- **Cost**: base cost plus cost dependent on widthY +- Availability: v9 + +wB = (-1)^E * widthB ; wY = (-1)^F * widthY +exp[(-1)^A * B * 10^wB] = Y * 10^wY. widthB and widthY are uint64. widthY output precision is guaranteed. +Calculation is based on the Taylor expansion of e^q. + +## bln widthA widthY + +- Opcode: 0x?? +- Stack: ..., A: []byte, E: uint64, F: uint64 → ..., X: uint, Y: []byte +- Natural logarithm of a decimal. A is interpreted as big-endian unsigned integers. +- **Cost**: base cost plus cost dependent on widthY +- Availability: v9 + +wA = (-1)^E * widthA ; wY = (-1)^F * widthY +ln[A * 10^wA] = (-1)^X * Y * 10^wY. widthA and widthY are uint64. widthY output precision is guaranteed. +Calculation is based on the following identity: ln(q) = log2(q) / log2(e) + +## bsin widthB widthY + +- Opcode: 0x?? +- Stack: ..., A: uint, B: []byte, E: uint64, F: uint64 → ..., X: uint, Y: []byte +- Decimal to the power of a decimal. B and Y are interpreted as big-endian unsigned integers. +- **Cost**: base cost plus cost dependent on widthY +- Availability: v9 + +wB = (-1)^E * widthB ; wY = (-1)^F * widthY +sin((-1)^A * B * 10^wB) = (-1)^X * Y * 10^wY. widthB and widthY are uint64. widthY output precision is guaranteed. +Calculation is based on the Taylor expansion of sin(q). + ## log - Opcode: 0xb0