summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/manuals/evenmore/evenmore-bitwise.tex
diff options
context:
space:
mode:
Diffstat (limited to 'doc/context/sources/general/manuals/evenmore/evenmore-bitwise.tex')
-rw-r--r--doc/context/sources/general/manuals/evenmore/evenmore-bitwise.tex194
1 files changed, 194 insertions, 0 deletions
diff --git a/doc/context/sources/general/manuals/evenmore/evenmore-bitwise.tex b/doc/context/sources/general/manuals/evenmore/evenmore-bitwise.tex
new file mode 100644
index 000000000..030229413
--- /dev/null
+++ b/doc/context/sources/general/manuals/evenmore/evenmore-bitwise.tex
@@ -0,0 +1,194 @@
+% language=us runpath=texruns:manuals/evenmore
+
+\environment evenmore-style
+
+\startcomponent evenmore-bitwise
+
+\startchapter[title={Bitwise operations}]
+
+Occasionally we use a bit set to pass (or store) options and one way of doing
+that is to add up some constants. However, what you would like to do is to set a
+specific bit. Of course one can write macros for that but performance wise one
+can wonder if there are other ways. One solution is to extend the engine but that
+has its own pitfalls. For instance, I played with additions to \type {\numexpr}
+and although they worked okay and brought now performance degradation, I decided
+to remove that experiment. One problem is that we have no real 32 bit cardinals
+(unsigned integers) in \TEX\ and the engine makes sure that we never exceed the
+minima and maxima. Another problem is that in expressions we then need either
+verbose \type {and}, \type {or}, \type {xor}, \type {not} and other verbose
+operators, if only because the usual symbols can have catcodes that are
+unsuitable.
+
+So in the end I decided to come up with a set of primitive like commands that
+do the job. It is no problem to have a set of dedicated verbose commands and we
+can extend the repertoire if needed. So this is what we have now:
+
+\starttabulate[||i2c||]
+\NC command \NC operator equivalent \NC optional \NC \NR
+\NC \type {\bitwiseset a} \NC \type {a} \NC \NC \NR
+\NC \type {\bitwisenot a} \NC \type {~a} \NC \NC \NR
+\NC \type {\bitwisenil a b} \NC \type {a & (~ b)} \NC \type {with} \NC \NR
+\NC \type {\bitwiseand a b} \NC \type {a & b} \NC \type {with} \NC \NR
+\NC \type {\bitwiseor a b} \NC \type {a | b} \NC \type {with} \NC \NR
+\NC \type {\bitwisexor a b} \NC \type {a ~ b} \NC \type {with} \NC \NR
+\NC \type {\bitwiseshift a b} \NC \type {a >> b} \NC \type {by} \NC \NR
+\NC \type {\bitwiseshift a -b} \NC \type {a << b} \NC \type {by} \NC \NR
+\NC \type {\ifbitwiseand a b} \NC \type {(a & b) ~= 0} \NC \NC \NR
+\stoptabulate
+
+Here a some examples:
+
+\startbuffer
+\scratchcounter = \bitwiseand "01 "02 \uchexnumbers{\scratchcounter} \quad
+\scratchcounter = \bitwiseand "01 with "02 \uchexnumbers{\scratchcounter} \quad
+\scratchcounter = \bitwiseand "03 "02 \uchexnumbers{\scratchcounter} \qquad
+\scratchcounter = \bitwiseor "01 "02 \uchexnumbers{\scratchcounter} \quad
+\scratchcounter = \bitwiseor "01 with "02 \uchexnumbers{\scratchcounter} \quad
+\scratchcounter = \bitwiseor "03 "02 \uchexnumbers{\scratchcounter} \qquad
+\scratchcounter = \bitwisexor "01 "02 \uchexnumbers{\scratchcounter} \quad
+\scratchcounter = \bitwisexor "01 with "02 \uchexnumbers{\scratchcounter} \quad
+\scratchcounter = \bitwisexor "03 "02 \uchexnumbers{\scratchcounter}
+\stopbuffer
+
+\typebuffer
+
+This gives the nine values:
+
+{\tt\getbuffer}
+
+Because they are numeric operations you can chain them, as in:
+
+\starttyping
+\scratchcounter = \bitwisenil \bitwisenil "0F "02 "01 \relax
+\scratchcounter = \bitwisenil \bitwisenil "0F with "02 with "01 \relax
+\stoptyping
+
+We try as good as possible to support all bits in the range from zero upto \type
+{0xFFFFFFFF};
+
+\startbuffer
+\scratchcounter \bitwiseset "FFFFFFFF
+
+\ifbitwiseand \scratchcounter "80000000 YES \else NOP \fi
+\ifbitwiseand \scratchcounter "F0000000 YES \else NOP \fi
+\ifbitwiseand \scratchcounter "10000000 YES \else NOP \fi
+
+\scratchcounter \bitwisenot \scratchcounter
+
+\ifbitwiseand \scratchcounter "80000000 YES \else NOP \fi
+\ifbitwiseand \scratchcounter "F0000000 YES \else NOP \fi
+\ifbitwiseand \scratchcounter "10000000 YES \else NOP \fi
+\stopbuffer
+
+\typebuffer
+
+and we get:
+
+\startpacked \tt \getbuffer \stoppacked
+
+Of course you can just use normal counters and \TEX\ integers but using the bit
+commands have the advantage that they do some checking and can do real \type {or}
+etc operations. Here is some food for thought:
+
+\startbuffer
+\scratchcounter \bitwiseand "01 "02
+\scratchcounter \numexpr "01+"02\relax
+
+\ifcase \bitwiseand \scratchcounterone \plusone \else \fi
+\ifbitwiseand \scratchcounterone \plusone \else \fi
+\ifnum \scratchcounterone=\plusone \else \fi
+\stopbuffer
+
+\typebuffer
+
+and we get:
+
+\startpacked \tt \getbuffer \stoppacked
+
+You can also go real binary, but we only provide a combined setter|/|getter for
+that, but you can mix that one with the other commands:
+
+\startbuffer
+\scratchcounterone = \bitwise 1101
+\scratchcountertwo = \bitwise 11011101110111011101110111011101
+\scratchcounterthree = \bitwiseor \bitwise 0001 \bitwise 1100
+
+{0x\uchexnumber{\scratchcounterone} \bitwise\scratchcounterone }\par
+{0x\uchexnumber{\scratchcountertwo} \bitwise\scratchcountertwo }\par
+{0x\uchexnumber{\scratchcounterthree} \bitwise\scratchcounterthree}\par
+\stopbuffer
+
+\typebuffer
+
+We get bits back:
+
+\startpacked \tt \getbuffer \stoppacked
+
+The above commands are typical for the things we can do with \LUAMETATEX\ and
+\LMTX\ and are unlikely to become available in \MKIV.
+
+There is a special command for (re)setting a bit in a register:
+
+\startbuffer
+ \scratchcounter 0
+\bitwiseflip \scratchcounter 1 [\the\scratchcounter]
+\bitwiseflip \scratchcounter 4 [\the\scratchcounter]
+\bitwiseflip \scratchcounter 8 [\the\scratchcounter]
+\bitwiseflip \scratchcounter -5 [\the\scratchcounter]
+\stopbuffer
+
+\typebuffer
+
+This gives: \inlinebuffer. Of course a global assignment works too:
+
+\startbuffer
+ \global \globalscratchcounter 0
+{\global \bitwiseflip \globalscratchcounter 2 } [\the\globalscratchcounter]
+{\global \bitwiseflip \globalscratchcounter 4 } [\the\globalscratchcounter]
+{\global \bitwiseflip \globalscratchcounter 8 } [\the\globalscratchcounter]
+{\global \bitwiseflip \globalscratchcounter -6 } [\the\globalscratchcounter]
+\stopbuffer
+
+\typebuffer
+
+Here we get: \inlinebuffer. A side effect of it being an number makes that
+this is also valid:
+
+\starttyping
+\scratchcounterone\bitwiseflip \scratchcountertwo -16
+\stoptyping
+
+\stopchapter
+
+\stopcomponent
+
+% (\scratchcounterone \bitwiseset "F \uchexnumber{\scratchcounterone})\par
+% (\scratchcounterone \bitwiseset "FF \uchexnumber{\scratchcounterone})\par
+% (\scratchcounterone \bitwiseset "FFF \uchexnumber{\scratchcounterone})\par
+% (\scratchcounterone \bitwiseset "FFFF \uchexnumber{\scratchcounterone})\par
+% (\scratchcounterone \bitwiseset "FFFFF \uchexnumber{\scratchcounterone})\par
+% (\scratchcounterone \bitwiseset "FFFFFF \uchexnumber{\scratchcounterone})\par
+% (\scratchcounterone \bitwiseset "FFFFFFF \uchexnumber{\scratchcounterone})\par
+% (\scratchcounterone \bitwiseset "FFFFFFFF \uchexnumber{\scratchcounterone})\par
+%
+% (\scratchcounterone \bitwiseset "0000FFFF
+% \scratchcounterone \bitwiseshift \scratchcounterone -16
+% \uchexnumber{\scratchcounterone})\par
+%
+% \scratchcounterone \bitwiseset "FFFFFFFF
+% \scratchcountertwo \bitwiseset "FFFFFFFE
+%
+% \the\scratchcounterone : \uchexnumber{\scratchcounterone}\par
+% \the\scratchcountertwo : \uchexnumber{\scratchcountertwo}\par
+
+% I need to check this on the garden run as it looks like that server is some 50%
+% faster than my (in terms of computers) old laptop.
+
+% \testfeatureonce{10000}{\scratchcounter \bitwiseand "01 "02 } \elapsedtime\par
+% \testfeatureonce{10000}{\scratchcounter \numexpr "01+"02\relax} \elapsedtime\par
+% \testfeatureonce{10000}{\ifcase\bitwiseand \scratchcounterone \plusone \else \fi} \elapsedtime\par
+% \testfeatureonce{10000}{\ifbitwiseand \scratchcounterone \plusone \else \fi} \elapsedtime\par
+% %testfeatureonce{10000}{\ifnum \scratchcounterone=\plusone \else \fi} \elapsedtime\par
+%
+% \testfeatureonce{100000}{\scratchcounter = \bitwise 1101 } \elapsedtime\par
+% \testfeatureonce{100000}{\scratchcounter = \bitwise 11011101110111011101110111011101 } \elapsedtime\par