"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; //shared Boolean[8] bits; "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; }