12-flags-and-comparisons.fth 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. \ There are words for true and false:
  2. true .
  3. false .
  4. true hex u. decimal
  5. \ int equality
  6. 1 1 = .
  7. \ check if zero
  8. 1 0= .
  9. \ less and greater
  10. 0 1 < .
  11. 0 0 < .
  12. 1 0 > .
  13. \ is assuming unsigned value, then wrong result
  14. -1 1 u< .
  15. \ compare to
  16. -1 1 < .
  17. \ boolean words work bitwise. For example:
  18. 1 2 and .
  19. \ Will be treated like this:
  20. \ 0000 0001 (is 1)
  21. \ and 0000 0010 (is 2)
  22. \ -> 0000 0000 (is 0)
  23. \ or written in binary:
  24. \ %00000001 %00000010 and -> %00000000
  25. \ Here is an example for or:
  26. 1 2 or .
  27. \ 0000 0001 (is 1)
  28. \ or 0000 0010 (is 2)
  29. \ -> 0000 0011 (is 3)
  30. \ boolean words can be used with flags (zero or non-zero)
  31. \ To make a proper flag out of any integer, you can use 0<>:
  32. 3 0<> .
  33. \ 0= checks for all bits being 0. Since false is encoded by 0, this
  34. \ turns any non-zero into a 0 and any 0 into a -1.
  35. 3 0= .
  36. \ Boolean words can replace conditionals:
  37. : foo ( n1 -- n2 )
  38. ( if there is not a 0, then write a 14, otherwise write a 0 )
  39. 0= if 14 else 0 then ;
  40. : bar ( n1 -- n2 )
  41. \ -1 has all bits 1 and will not filter anything out when used with
  42. \ `and` as a bit mask, but if the other argument has a 0 bit
  43. \ anywhere, the result will also have a 0 bit at that position,
  44. \ because both bits must be 1 for the resulting bit to be 1. A 0 on
  45. \ the other hand will have all bits 0, filtering everything out,
  46. \ when used as a bit mask, resulting in a 0 as a total result.
  47. 0= 14 and
  48. \ examples:
  49. \ 0 0= -> -1
  50. \ -1 14 -> -1 14
  51. \ -1 14 and -> 14
  52. \ 123 0= -> 0
  53. \ 0 14 -> 0 14
  54. \ 0 14 and -> 0
  55. ;
  56. \ Exercise: Write min without making use of `if`.
  57. \ Previous version of min:
  58. : min ( n1 n2 -- n )
  59. \ Only let the `if` decide whether or not to swap the
  60. \ arguments.
  61. 2dup > if swap then
  62. drop ;
  63. : min ( n1 n2 -- n )
  64. 2dup <
  65. \ 3 1 3dup -> 3 1 3 1
  66. \ 3 1 3 1 < -> 3 1 0
  67. \ 3 1 0
  68. \ seeking something that uses 0 to keep the 1
  69. \ - - maybe?
  70. \ ans ?
  71. \ 3 1 0 or -> 3 1
  72. \ 3 1 nip -> 1
  73. \ 1 3 -1 or -> 1 -1
  74. ;
  75. : min
  76. 2dup > 1+ pick nip nip ;
  77. : min
  78. 2dup > 1+ roll nip ;
  79. \ : min
  80. \ \ 3 1 -- 1 3
  81. \ \ adds the information, which one is greater
  82. \ 2dup >
  83. \ \ 3 1 -1 -- 1 3 0
  84. \ \ `and` sets the greater value to 0 and keeps the smaller
  85. \ \ value, because of different result of > (-1 or 0)
  86. \ and
  87. \ \ 3 1 -- 1 0
  88. \ \ tuck stores the smaller number, if it is on top of the
  89. \ \ stack, at the bottom of the stack. If the smaller number
  90. \ \ is not at the top of the stack, then it stores a 0 at
  91. \ \ the bottom of the stack.
  92. \ tuck
  93. \ \ After `tuck` we still have either the smaller number on
  94. \ \ top of the stack or a zero, because of `and` with false
  95. \ \ (0). However, we also have a "backup" of the smaller
  96. \ \ number at the bottom of the stack, so that we can work
  97. \ \ with the top element, without losing the minimum number.
  98. \ \ 1 3 1 -- 0 1 0
  99. \ \ 0= will determin, whether we have had the smaller number
  100. \ \ on top, or a 0 and give 0 or -1 as a result. This makes
  101. \ \ the actual distinction between the smaller number and 0,
  102. \ \ as it outputs a -1 for input 0 and a 0 for any other
  103. \ \ input:
  104. \ \ If there is a 0, we get a -1, which is all bits set to
  105. \ \ 1. We only got a 0 on the stack, when the bigger number
  106. \ \ was on top of the stack initially.
  107. \ \ If there is a non-zero value, we get a 0, which is all
  108. \ \ bits set to 0. We only got a 0, if the smaller number
  109. \ \ was initially on top of the stack. (OR ZERO AS A NUMBER!
  110. \ \ MISTAKE!)
  111. \ 0=
  112. \ \ 1 3 0 -- 0 1 -1
  113. \ and
  114. \ \ 1 0 -- 0 1
  115. \ or
  116. \ \ 1 -- 1
  117. \ ;
  118. : min ( a b - x )
  119. \ adds the information, which one is greater
  120. 2dup <
  121. tuck
  122. 0=
  123. and
  124. -rot and or ;
  125. \ Test cases:
  126. 2 0 min .s .
  127. 0 2 min .s .
  128. 0 -1 min .s .
  129. -1 0 min .s .
  130. 3 1 min .s .
  131. 1 3 min .s .