librarylibs/Radix/src/Radix.xtl

Radix: an eight-digit calculator in any radix (hexadecimal, octal, decimal): the specification HEX1000's ROM program must meet Import it with an alias of your choice: "rx:" u_se< "Radix". Put libs/Radix/src on XETAL_PATH ("just path"); the reference is libs/Radix/docs. Names with l: are exported; the others are private to this file.

A number is eight digits in radix r (16, 8 or 10), as a calculator chip keeps it: a whole number from 0 to r^8 - 1. Arithmetic wraps like an odometer, modulo r^8: in hexadecimal FFFFFFFF + 1 is 0 and 5 - 7 is FFFFFFFE (the r's complement a digit-serial subtract leaves). The radix is the first argument of every function, bound once by applying the function to it: u:k_ey := rx:k_ey 16.

source

Numbers as digits

ˡWidth : Int

value · line 19

Width: the digits a number has (the display's).

      ʳˣ⁼u̲se< "Radix"
      ʳˣWidth
8
ˡWidth ← 8

ˡm̲odulus : Int -> Int

function · line 25

m_odulus r: r^8, one more than the largest number.

      ʳˣ⁼u̲se< "Radix"
      ʳˣm̲odulus 16
4294967296
ˡm̲odulus ← { r → r ^ ˡWidth }

ˡd̲igits : Int -> Int -> Int

function · line 32

r d_igits n: the eight digits of n, most significant first (the display's order); n is wrapped first.

      ʳˣ⁼u̲se< "Radix"
      16 ʳˣd̲igits 255
0 0 0 0 0 0 15 15
ˡd̲igits ← { r n → (ˡWidth r̲eshape r) e̲ncode n m̲od ˡm̲odulus r }
Used in: ˡs̲creen

ˡv̲alue : Num a => a -> a -> a

function · line 38

r v_alue ds: the number eight digits (or any digits) stand for.

      ʳˣ⁼u̲se< "Radix"
      16 ʳˣv̲alue 1 0 0
256
ˡv̲alue ← { r ds → r d̲ecode ds }

ˡw̲rap : Int -> Int -> Int

function · line 44

r w_rap n: n modulo r^8 (an odometer).

      ʳˣ⁼u̲se< "Radix"
      16 ʳˣw̲rap -1
4294967295
ˡw̲rap ← { r n → n m̲od ˡm̲odulus r }
Used in: ˡa̲lu, ʰt̲imes

The keys

Keys : Char

value (private) · line 51

Key codes: the digits 0 to 15 are themselves, then + - * = and X (clear: C is a hexadecimal digit); Keys is the text whose place, less 1, is the code.

Keys ← ⎕D c̲at (6 t̲ake ⎕A) c̲at "+-*=X"

ˡKeyPlus : Int

value · line 57

KeyPlus: the code of +.

      ʳˣ⁼u̲se< "Radix"
      ʳˣKeyPlus
16
ˡKeyPlus ← 16
Used in: ˡk̲ey

ˡKeyMinus : Int

value · line 63

KeyMinus: the code of -.

      ʳˣ⁼u̲se< "Radix"
      ʳˣKeyMinus
17
ˡKeyMinus ← 17

ˡKeyTimes : Int

value · line 69

KeyTimes: the code of *.

      ʳˣ⁼u̲se< "Radix"
      ʳˣKeyTimes
18
ˡKeyTimes ← 18

ˡKeyEquals : Int

value · line 75

KeyEquals: the code of =.

      ʳˣ⁼u̲se< "Radix"
      ʳˣKeyEquals
19
ˡKeyEquals ← 19
Used in: ˡk̲ey

ˡKeyClear : Int

value · line 81

KeyClear: the code of X, clear.

      ʳˣ⁼u̲se< "Radix"
      ʳˣKeyClear
20
ˡKeyClear ← 20
Used in: ˡk̲ey

ˡk̲eys : Char -> Int

function · line 88

k_eys text: the key codes of a text such as "12+34=" (spaces are skipped; any other character gives 21, which k_ey ignores).

      ʳˣ⁼u̲se< "Radix"
      ʳˣk̲eys "12+34="
1 2 16 3 4 19
ˡk̲eys ← { t → (Keys i̲ndexOf (t ≠ f̲irst " ") r̲eplicate t) − 1 }

The calculator: a step per key

ˡReset : Int

value · line 98

The state, five numbers: the accumulator, the entry, the pending operation (0 none, 1 +, 2 -, 3 *), the phase (0 after an operator, 1 entering digits, 2 after =) and the number displayed.

      ʳˣ⁼u̲se< "Radix"
      ʳˣReset
0 0 0 0 0
ˡReset ← 0 0 0 0 0
Used in: ˡk̲ey, ˡr̲un

ʰa̲cc : a -> a

function (private) · line 100
ʰa̲cc ← { s → 1 s̲elect s }

ʰe̲ntry : a -> a

function (private) · line 101
ʰe̲ntry ← { s → 2 s̲elect s }

ʰo̲p : a -> a

function (private) · line 102
ʰo̲p ← { s → 3 s̲elect s }

ʰp̲hase : a -> a

function (private) · line 103
ʰp̲hase ← { s → 4 s̲elect s }

ˡa̲lu : Int -> Int -> Int

function · line 111

r a_lu ops: the operation ops[1] (1 +, 2 -, 3 *) of ops[2] and ops[3], wrapped (the operands as one vector: a function has two sides).

      ʳˣ⁼u̲se< "Radix"
      16 ʳˣa̲lu 2 5 7
4294967294
ˡa̲lu ← { r ops →
  op ← f̲irst ops
  a ← 2 s̲elect ops
  b ← 3 s̲elect ops
  r ˡw̲rap '+ r̲/ (op = 1 2 3) × (a + b) c̲at (a − b) c̲at r ʰt̲imes a c̲at b
}
Used in: ʰs̲ettle

ʰt̲imes : Int -> Int -> Int

function (private) · line 121

r t_imes a b: a * b wrapped, without overflow: b split at r^4, so no partial product reaches r^12 (FFFFFFFF * FFFFFFFF itself is past a 64-bit Int).

ʰt̲imes ← { r ab →
  a ← f̲irst ab
  b ← f̲irst 1 d̲rop ab
  half ← r ^ 4
  r ˡw̲rap (half × r ˡw̲rap a × b d̲iv half) + a × b m̲od half
}
Used in: ˡa̲lu

ʰs̲ettle : Int -> Int -> Int

function (private) · line 131

The pending operation settled: the accumulator after it takes the entry (the entry itself when nothing is pending; the accumulator unchanged when no digit was entered since).

ʰs̲ettle ← { r s →
  1 ≠ ʰp̲hase s ? ʰa̲cc s
  0 = ʰo̲p s ? ʰe̲ntry s
  r ˡa̲lu (ʰo̲p s) c̲at (ʰa̲cc s) c̲at ʰe̲ntry s
}
Used in: ˡk̲ey

ˡk̲ey : Int -> Int -> Int -> Int

function · line 144

r k_ey s k: the state after the key k (a step: the machine's ROM program must leave the same display). A digit not below the radix, or one that would make a ninth digit, is ignored.

      ʳˣ⁼u̲se< "Radix"
      ᵘk̲ey ← ʳˣk̲ey 16
      ʳˣReset ᵘk̲ey 10
0 10 0 1 10
ˡk̲ey ← { r s k →
  k ≥ 21 ? s
  k = ˡKeyClear ? ˡReset
  k = ˡKeyEquals ? (r ʰs̲ettle s) c̲at 0 0 2 c̲at r ʰs̲ettle s
  k ≥ ˡKeyPlus ? (r ʰs̲ettle s) c̲at 0 c̲at (k − 15) c̲at 0 c̲at r ʰs̲ettle s
  k ≥ r ? s
  fresh ← 2 = ʰp̲hase s
  old ← (n̲ot fresh) × (1 = ʰp̲hase s) × ʰe̲ntry s
  old ≥ r ^ ˡWidth − 1 ? s
  entry ← k + r × old
  ((n̲ot fresh) × ʰa̲cc s) c̲at entry c̲at ((n̲ot fresh) × ʰo̲p s) c̲at 1 c̲at entry
}
Used in: ˡr̲un

ˡd̲isplay : a -> a

function · line 161

d_isplay s: the number displayed.

      ʳˣ⁼u̲se< "Radix"
      ʳˣd̲isplay 70 0 0 2 70
70
ˡd̲isplay ← { s → 5 s̲elect s }
Used in: ˡs̲creen

ˡs̲creen : Int -> Int -> Char

function · line 168

r s_creen s: the display as eight characters: the digits, leading zeros blank (zero itself shows one 0).

      ʳˣ⁼u̲se< "Radix"
      16 ʳˣs̲creen 0 0 0 0 305419896
12345678
ˡs̲creen ← { r s →
  ds ← r ˡd̲igits ˡd̲isplay s
  blank ← ('∧ s̲\ 0 = 7 t̲ake ds) c̲at 0
  (1 + (1 − blank) × 1 + ds) s̲elect " " c̲at 16 t̲ake Keys
}
Used in: ˡc̲alc

ˡc̲alc : Int -> Char -> Char

function · line 179

r c_alc text: the screen after the keys of a text, from Reset: 16 rx:c_alc "12+34=" is " 46".

      ʳˣ⁼u̲se< "Radix"
      16 ʳˣc̲alc "5-7="
FFFFFFFE
ˡc̲alc ← { r t →
  s ← r ˡr̲un ˡk̲eys t
  r ˡs̲creen s
}

ˡr̲un : Int -> Int -> Int

function · line 189

r r_un keys: the state after every key, from Reset (the harness: a loop over the keys, as Clocked's).

      ʳˣ⁼u̲se< "Radix"
      16 ʳˣr̲un ʳˣk̲eys "12+34="
70 0 0 2 70
ˡr̲un ← { r keys →
  (n, s) ← (t̲ally keys) '{ (i, s) → (i + 1, (r ˡk̲ey s)_ i s̲elect keys) } p̲ower (1, ˡReset)
  s
}
Used in: ˡc̲alc