| "An 8-bit byte. A `Byte` value represents a congruence class |
| of [[integers|Integer]] modulo 256, and may be interpreted |
| as: |
| |
| - an [[unsigned]] integer value in the range `0..255`, or |
| - a [[signed]] integer value in the range `-128..127`. |
| |
| `Byte` is not considered a full numeric type, supporting |
| only: |
| |
| - [[bitwise|Binary]] operations, and |
| - addition and subtraction modulo 256. |
| |
| `Byte`s with modular addition form a [[mathematical |
| group|Invertible]]. Thus, every byte `b` has an additive |
| inverse `-b` where: |
| |
| (-b).signed == -b.signed |
| (-b).unsigned == b.unsigned==0 then 0 else 256 - b.unsigned |
| |
| `Byte` is a [[recursive enumerable type|Enumerable]]. For |
| example, the range: |
| |
| 254.byte .. 1.byte |
| |
| contains the values `254.byte, 255.byte, 0.byte, 1.byte`. |
| |
| `Byte` does not have a [[total order|Comparable]] because |
| any such order would: |
| |
| - be inconsistent with the definition of [[successor]] and |
| [[predecessor]] under modular addition, and |
| - would depend on interpretation of the `Byte` value as |
| signed or unsigned. |
| |
| Thus, to compare the magnitude of two bytes, it is |
| necessary to first convert them to either their `signed` or |
| `unsigned` integer values. |
| |
| `Byte`s are useful mainly because they can be efficiently |
| stored in an [[Array]]." |
| tagged("Basic types") |
| since("1.1.0") |
| shared native final class Byte(congruent) |
| extends Object() |
| satisfies Binary<Byte> & |
| Invertible<Byte> & |
| Enumerable<Byte> { |
| |
| "An integer member of the congruence class of the |
| resulting `Byte`. |
| |
| For any integer `x>=0`: |
| |
| x.byte.unsigned == x % 256 |
| x.byte.signed == x % 256 |
| |
| And for an integer `x<0`: |
| |
| x.byte.unsigned == 256 + x % 256 |
| x.byte.signed == x % 256 |
| |
| And for any integers `x` and `y` which are congruent |
| modulo 256: |
| |
| x.byte == y.byte" |
| Integer congruent; |
| |
| "This byte interpreted as an unsigned integer in the |
| range `0..255` (that is, `0..#FF`)." |
| shared native Integer unsigned |
| = (congruent % #100).and(#FF); |
| |
| "This byte interpreted as a signed integer in the range |
| `-128..127` (that is, `-#80..#7F`)." |
| shared native Integer signed |
| => unsigned > #7F |
| then unsigned - #100 |
| else unsigned; |
| |
| |
| |
| "Whether this byte is even." |
| shared native Boolean even => and(1.byte).zero; |
| |
| "Whether this byte is zero." |
| shared native Boolean zero => unsigned == 0; |
| |
| "Whether this byte is one." |
| shared native Boolean unit => unsigned == 1; |
| |
| "The additive inverse of this byte. For any integer `x`: |
| |
| (-x.byte).signed = -x.byte.signed" |
| shared actual native Byte negated => (-signed).byte; |
| |
| "The modulo 256 sum of this byte and the given byte." |
| shared actual native Byte plus(Byte other) |
| => (this.unsigned + other.unsigned).byte; |
| |
| function indexInRange(Integer index) |
| => 0 <= index < 8; |
| |
| function mask(Integer index) |
| => 1.byte.leftLogicalShift(index); |
| |
| shared actual native Boolean get(Integer index) |
| => indexInRange(index) |
| then !and(mask(index)).zero |
| else false; |
| |
| shared actual native Byte flip(Integer index) |
| => indexInRange(index) |
| then xor(mask(index)) |
| else this; |
| |
| shared actual native Byte set(Integer index, Boolean bit) |
| => indexInRange(index) |
| then (bit then or(mask(index)) |
| else and(mask(index).not)) |
| else this; |
| |
| shared actual native Byte clear(Integer index) |
| => indexInRange(index) |
| then and(mask(index).not) |
| else this; |
| |
| shared actual native Byte not => unsigned.not.byte; |
| |
| shared actual native Byte and(Byte other) |
| => unsigned.and(other.unsigned).byte; |
| |
| shared actual native Byte or(Byte other) |
| => unsigned.or(other.unsigned).byte; |
| |
| shared actual native Byte xor(Byte other) |
| => unsigned.xor(other.unsigned).byte; |
| |
| "If [[shift]] is in the range `0..$111`, shift the bits |
| to the left by `shift` positions, using zero extension |
| to fill in the least significant bits. Otherwise shift |
| the addressable bits to the left by `shift.and($111)` |
| positions, using zero extension." |
| aliased ("leftShift") |
| shared actual native Byte leftLogicalShift(Integer shift) |
| => unsigned.leftLogicalShift(shift.and($111)).byte; |
| |
| "If [[shift]] is in the range `0..$111`, shift the bits |
| to the right by `shift` positions, using zero extension |
| to fill in the most significant bits. Otherwise shift |
| the addressable bits to the right by `shift.and($111)` |
| positions, using zero extension." |
| aliased ("rightShift") |
| shared actual native Byte rightLogicalShift(Integer shift) |
| => unsigned.rightLogicalShift(shift.and($111)).byte; |
| |
| "If [[shift]] is in the range `0..$111`, shift the bits |
| to the right by `shift` positions, using sign extension |
| to fill in the most significant bits. Otherwise shift |
| the addressable bits to the right by `shift.and($111)` |
| positions, using sign extension." |
| shared actual native Byte rightArithmeticShift(Integer shift) |
| => signed.rightArithmeticShift(shift.and($111)).byte; |
| |
| shared actual native Byte predecessor => (unsigned-1).byte; |
| shared actual native Byte successor => (unsigned+1).byte; |
| |
| shared actual native Byte neighbour(Integer offset) |
| => (unsigned + offset).byte; |
| |
| shared actual native Integer offset(Byte other) |
| => minus(other).unsigned; |
| |
| shared actual native Integer offsetSign(Byte other) |
| => this==other then 0 else 1; |
| |
| shared actual native Boolean equals(Object that) |
| => if (is Byte that) |
| then this.unsigned == that.unsigned |
| else false; |
| |
| shared actual native Integer hash => signed; |
| |
| "The [[unsigned]] interpretation of this byte as a |
| string." |
| shared actual native String string => unsigned.string; |
| |
| } |
| |