Skip to content

Commit

Permalink
Add bitwise NOT
Browse files Browse the repository at this point in the history
Closes #15
#13
  • Loading branch information
Blake-Madden committed Mar 9, 2024
1 parent 7e041d0 commit 06d4f99
Show file tree
Hide file tree
Showing 6 changed files with 452 additions and 83 deletions.
6 changes: 4 additions & 2 deletions TinyExprChanges.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ The following are changes from the original TinyExpr C library:
- `and`: returns true (i.e., non-zero) if all conditions are true (accepts 1-7 arguments).
- `average`: returns the mean for a range of values (accepts 1-7 arguments).
- `bitand`: bitwise AND.
- `bitlrotate64`: bitwise (`uint64_t`) left rotate. (Only available if compiled as C++20.)
- `bitlrotate`: bitwise left rotate. Versions of this are available for 8-, 16-, 32-, and 64-bit integers (if supported by the platform). (Only available if compiled as C++20.)
- `bitlshift`: left shift.
Negative shift amount arguments (similar to *Excel*) are supported.
- `bitnot`: bitwise NOT. Versions of this are available for 8-, 16-, 32-, and 64-bit integers (if supported by the platform).
- `bitor`: bitwise OR.
- `bitrrotate64`: bitwise (`uint64_t`) right rotate. (Only available if compiled as C++20.)
- `bitrrotate`: bitwise right rotate. Versions of this are available for 8-, 16-, 32-, and 64-bit integers (if supported by the platform). (Only available if compiled as C++20.)
- `bitrshift`: right shift.
Negative shift amount arguments (similar to *Excel*) are supported.
- `bitxor`: bitwise XOR.
Expand Down Expand Up @@ -87,6 +88,7 @@ The following are changes from the original TinyExpr C library:
- `<<<` left (`uint64_t`) rotation operator.
- `>>>` right (`uint64_t`) rotation operator.
- `**` exponentiation (alias for `^`).
- `~` bitwise NOT.
- `round` now supports negative number of digit arguments, similar to *Excel*.
For example, `ROUND(-50.55,-2)` will yield `-100`.
- Custom variables and functions are now stored in a `std::set`
Expand Down
2 changes: 2 additions & 0 deletions docs/manual/compile-time-options.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,11 @@ If compiling as C++20 (and `TE_FLOAT` is not defined), then the following functi
- `BITLROTATE16`
- `BITLROTATE32`
- `BITLROTATE64`
- `BITLROTATE`
- `BITRROTATE8`
- `BITRROTATE16`
- `BITRROTATE32`
- `BITRROTATE64`
- `BITRROTATE`
- `<<<` (unsigned 64-bit left rotation)
- `>>>` (unsigned 64-bit right rotation)
22 changes: 17 additions & 5 deletions docs/manual/functions.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,26 @@ Table: Math Functions\index{functions!math}
| BITLROTATE8(Number, RotateAmount) | Returns *Number* left rotated left to the most significant bit by the specified number (*RotateAmount*) of bits.<br>\linebreak *Number* is rotated as an unsigned 8-bit integer.<br>\linebreak (Only available if compiled as C++20.) |
| BITLROTATE16(Number, RotateAmount) | Returns *Number* left rotated left to the most significant bit by the specified number (*RotateAmount*) of bits.<br>\linebreak *Number* is rotated as an unsigned 16-bit integer.<br>\linebreak (Only available if compiled as C++20.) |
| BITLROTATE32(Number, RotateAmount) | Returns *Number* left rotated left to the most significant bit by the specified number (*RotateAmount*) of bits.<br>\linebreak *Number* is rotated as an unsigned 32-bit integer.<br>\linebreak (Only available if compiled as C++20.) |
| BITLROTATE(Number, RotateAmount) | Returns *Number* left rotated left to the most significant bit by the specified number (*RotateAmount*) of bits.<br>\linebreak *Number* is rotated as an unsigned 53-bit (or 64-bit) integer.<br>\linebreak Note, however, that values beyond the range of `double` should not be used as they will wrap around.<br>\linebreak (Only available if compiled as C++20.) |
| BITLSHIFT(Number, ShiftAmount) | Returns *Number* left shifted by the specified number (*ShiftAmount*) of bits.<br>\linebreak *Number* cannot exceed `(2^48)-1` and *ShiftAmount* cannot exceed `53` (or `64`, if supported). |
| BITLROTATE64(Number, RotateAmount) | Returns *Number* left rotated left to the most significant bit by the specified number (*RotateAmount*) of bits.<br>\linebreak *Number* is rotated as an unsigned 64-bit integer.<br>\linebreak (Only available if compiled as C++20.) |
| BITLROTATE(Number, RotateAmount) | Returns *Number* left rotated left to the most significant bit by the specified number (*RotateAmount*) of bits.<br>\linebreak *Number* is rotated as either a 32- or 64-bit integer (depending on what is supported by the compiler).<br>\linebreak (Only available if compiled as C++20.) |
| BITLSHIFT(Number, ShiftAmount) | Returns *Number* left shifted by the specified number (*ShiftAmount*) of bits.<br>\linebreak *Number* cannot exceed `(2^48)-1` and *ShiftAmount* cannot exceed `53` (or `63`, if 64-bit is supported). |
| BITNOT8(Number) | Returns a bitwise 'NOT' of a 8-bit integer. |
| BITNOT16(Number) | Returns a bitwise 'NOT' of a 16-bit integer. |
| BITNOT32(Number) | Returns a bitwise 'NOT' of a 32-bit integer. |
| BITNOT64(Number) | Returns a bitwise 'NOT' of a 64-bit integer (if 64-bit integers are supported). |
| BITNOT(Number) | Returns a bitwise 'NOT' of a 32- or 64-bit integer (depending on whether 64-bit is supported). |
| BITOR(Number1, Number2) | Returns a bitwise 'OR' of two (integral) numbers. (Both numbers must be positive and cannot exceed `(2^48)-1`.) |
| BITRROTATE8(Number, RotateAmount) | Returns *Number* right rotated right to the least significant bit by the specified number (*RotateAmount*) of bits.<br>\linebreak *Number* is rotated as an unsigned 8-bit integer.<br>\linebreak (Only available if compiled as C++20.) |
| BITRROTATE16(Number, RotateAmount) | Returns *Number* right rotated right to the least significant bit by the specified number (*RotateAmount*) of bits.<br>\linebreak *Number* is rotated as an unsigned 16-bit integer.<br>\linebreak (Only available if compiled as C++20.) |
| BITRROTATE32(Number, RotateAmount) | Returns *Number* right rotated right to the least significant bit by the specified number (*RotateAmount*) of bits.<br>\linebreak *Number* is rotated as an unsigned 32-bit integer.<br>\linebreak (Only available if compiled as C++20.) |
| BITRROTATE(Number, RotateAmount) | Returns *Number* right rotated right to the least significant bit by the specified number (*RotateAmount*) of bits.<br>\linebreak *Number* is rotated as an unsigned 53-bit (or 64-bit) integer.<br>\linebreak Note, however, that values beyond the range of `double` should not be used as they will wrap around.<br>\linebreak (Only available if compiled as C++20.) |
| BITRSHIFT(Number, ShiftAmount) | Returns *Number* right shifted by the specified number (*ShiftAmount*) of bits.<br>\linebreak *Number* cannot exceed `(2^48)-1` and *ShiftAmount* cannot exceed `53` (or `64`, if supported). |
| BITRROTATE64(Number, RotateAmount) | Returns *Number* right rotated right to the least significant bit by the specified number (*RotateAmount*) of bits.<br>\linebreak *Number* is rotated as an unsigned 64-bit integer.<br>\linebreak (Only available if compiled as C++20.) |
| BITRROTATE(Number, RotateAmount) | Returns *Number* right rotated right to the least significant bit by the specified number (*RotateAmount*) of bits.<br>\linebreak *Number* is rotated as either a 32- or 64-bit integer (depending on what is supported by the compiler).<br>\linebreak (Only available if compiled as C++20.) |
| BITRSHIFT(Number, ShiftAmount) | Returns *Number* right shifted by the specified number (*ShiftAmount*) of bits.<br>\linebreak *Number* cannot exceed `(2^48)-1` and *ShiftAmount* cannot exceed `53` (or `63`, if 64-bit is supported). |
| BITXOR(Number1, Number2) | Returns a bitwise 'XOR' of two (integral) numbers. (Both numbers must be positive and cannot exceed `(2^48)-1`.) |
| SUPPORTS32BIT() | Returns true if 32-bit integers are supported. This will affect the supported range of values for bitwise operations. |
| SUPPORTS64BIT() | Returns true if 64-bit integers are supported. This will affect the supported range of values for bitwise operations. |

Table: Bitwise Functions\index{functions!bitwise}
Table: Engineering Functions\index{functions!engineering}
:::

::: {.notesection data-latex=""}
Expand Down Expand Up @@ -96,3 +103,8 @@ Table: Logic Functions\index{functions!logical}
The first argument to any logic function must be valid (i.e., not NaN). If the first argument evaluates to NaN, then NaN will be returned.
Any subsequent arguments that evaluate to NaN will be ignored.
:::

## Compatibility Note {-}

`BITNOT` will call either `BITNOT32` or `BITNOT64`, depending on whether 64-bit integers are supported.
This differs from *Excel*, which only works with 16-bit integers. To match the behavior of *Excel*, explicitly call `BITNOT16`.
21 changes: 13 additions & 8 deletions docs/manual/operators.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The following operators\index{operators} are supported within math expressions:
| % | Modulus: Divides two values and returns the remainder. |
| + | Addition. |
| \- | Subtraction. |
| ^ | Either exponentiation or bitwise XOR. Exponentiation is the default; define `TE_BITWISE_OPERATORS` to enable bitwise behavior. For exponentiation, the number in front of ^ is the base, the number after it is the power to raise it to. |
| ^ | Either exponentiation (the default) or bitwise XOR. For exponentiation, the number in front of ^ is the base, the number after it is the power to raise it to. |
| ** | Exponentiation. (This is an alias for ^) |
| < | Less than. |
| \> | Greater than. |
Expand All @@ -20,26 +20,31 @@ The following operators\index{operators} are supported within math expressions:
| \=\= | Equals. (This is an alias for \=) |
| <> | Not equal to. |
| \!\= | Not equal to. (This is an alias for <>) |
| & | Either logical or bitwise conjunction (AND). Logical is the default, define `TE_BITWISE_OPERATORS` to enable bitwise behavior. |
| && | Either logical conjunction (AND). |
| \| | Logical or bitwise alternative (OR). Logical is the default, define `TE_BITWISE_OPERATORS` to enable bitwise behavior. |
| \|\| | Logical alternative (OR). |
| & | Either logical (the default) or bitwise conjunction (AND). |
| && | Logical conjunction (AND). |
| \| | Either Logical (the default) or bitwise alternative (OR). |
| \|\ | | Logical alternative (OR). |
| ( ) | Groups sub-expressions, overriding the order of operations. |
| << | Bitwise left shift. |
| >> | Bitwise right shift. |
| ~ | Bitwise NOT. |
| << | Bitwise left shift. |
| >> | Bitwise right shift. |
| <<< | Bitwise left rotate. (Only available if compiled as C++20.) |
| >>> | Bitwise right rotate. (Only available if compiled as C++20.) |

Table: Operators
:::

::: {.tipsection data-latex=""}
Define `TE_BITWISE_OPERATORS` to enable bitwise behavior for `&`, `|`, and `^`.
:::

::: {.minipage data-latex="{\textwidth}"}
For operators, the order of precedence is:

| Operator | Description |
| :-- | :-- |
| ( ) | Instructions in parentheses are executed first. (If `TE_BRACKETS_AS_PARENS` is defined, then `[]` are treated the same way.) |
| \+ and - | Positive or negative sign for a value. |
| \+, -, ~ | Positive or negative sign for a value, and bitwise NOT. |
| ^ | Exponentiation. |
| \*, /, and % | Multiplication, division, and modulus. |
| \+ and - | Addition and subtraction. |
Expand Down
Loading

0 comments on commit 06d4f99

Please sign in to comment.