https://github.com/akkartik/mu/blob/main/505colors.mu
  1 fn nearest-color-euclidean r: int, g: int, b: int -> _/eax: int {
  2   var result/edi: int <- copy 0x100/invalid
  3   var max-distance/esi: int <- copy 0x30000/max  # 3 * 0x100*0x100
  4   var r2/ecx: int <- copy 0
  5   var g2/edx: int <- copy 0
  6   var b2/ebx: int <- copy 0
  7   var color/eax: int <- copy 0
  8   {
  9     compare color, 0x100
 10     break-if->=
 11     $nearest-color-euclidean:body: {
 12       r2, g2, b2 <- color-rgb color
 13       {
 14         var curr-distance/eax: int <- euclidean-distance-squared r, g, b, r2, g2, b2
 15         compare curr-distance, max-distance
 16         break-if->= $nearest-color-euclidean:body
 17         max-distance <- copy curr-distance
 18       }
 19       result <- copy color
 20     }
 21     color <- increment
 22     loop
 23   }
 24   return result
 25 }
 26 
 27 fn euclidean-distance-squared r1: int, g1: int, b1: int, r2: int, g2: int, b2: int -> _/eax: int {
 28   var result/edi: int <- copy 0
 29   # red
 30   var tmp/eax: int <- copy r1
 31   tmp <- subtract r2
 32   tmp <- multiply tmp
 33   result <- add tmp
 34   # green
 35   tmp <- copy g1
 36   tmp <- subtract g2
 37   tmp <- multiply tmp
 38   result <- add tmp
 39   # blue
 40   tmp <- copy b1
 41   tmp <- subtract b2
 42   tmp <- multiply tmp
 43   result <- add tmp
 44   return result
 45 }
 46 
 47 # Hue/saturation/luminance for an rgb triple.
 48 # rgb are in [0, 256)
 49 # hsl are also returned in [0, 256)
 50 # from https://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl
 51 fn hsl r: int, g: int, b: int -> _/ecx: int, _/edx: int, _/ebx: int {
 52   var _max/eax: int <- maximum r, g
 53   _max <- maximum _max, b
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
c{0: 0 (((1 string-address)) <- ((new)) abc) -- nil
c{0: 1 (((2 string-address)) <- ((string-copy)) ((1 string-address)) ((2 literal)) ((4 literal))) -- nil
c{1: 0 ✓ (((1 string-address)) <- ((new)) abc)
c{1: 1 ✓ (((2 string-address)) <- ((string-copy)) ((1 string-address)) ((2 literal)) ((4 literal)))
cn0: convert-names in main
cn0: (((1 string-address)) <- ((new)) abc) nil nil
cn0: checking arg abc
cn0: checking oarg ((1 string-address))
maybe-add: ((1 string-address))
cn0: (((2 string-address)) <- ((string-copy)) ((1 string-address)) ((2 literal)) ((4 literal))) nil nil
cn0: checking arg ((1 string-address))
maybe-add: ((1 string-address))
cn0: checking arg ((2 literal))
cn0: checking arg ((4 literal))
cn0: checking oarg ((2 string-address))
maybe-add: ((2 string-address))
cn1: (((1 string-address)) <- ((new)) abc)
cn1: (((2 string-address)) <- ((string-copy)) ((1 string-address)) ((2 literal)) ((4 literal)))
schedule: main
run: main 0: (((1 string-address)) <- ((new)) abc)
run: main 0: 1000 => ((1 string-address))
mem: ((1 string-address)): 1 <= 1000
run: main 1: (((2 string-address)) <- ((string-copy)) ((1 string-address)) ((2 literal)) ((4 literal)))
mem: ((1 string-address)) => 1000
run: string-copy/main 0: (((default-space space-address)) <- ((new)) ((space literal)) ((30 literal)))
run: string-copy/main 0: 1004 => ((default-space space-address))
run: string-copy/main 1: (((1 string-address)) <- ((next-input)))
arg: nil 0 (1000 2 4)
run: string-copy/main 1: 1000 => ((1 string-address))
mem: ((1 string-address)): 1006 <= 1000
run: string-copy/main 2: (((2 integer)) <- ((next-input)))
arg: nil 1 (1000 2 4)
run: string-copy/main 2: 2 => ((2 integer))
mem: ((2 integer)): 1007 <= 2
run: string-copy/main 3: (((3 integer)) <- ((next-input)))
arg: nil 2 (1000 2 4)
run: string-copy/main 3: 4 => ((3 integer))
mem: ((3 integer)): 1008 <= 4
run: string-copy/main 4: (((4 integer)) <- ((length)) ((1 string-address) (deref)))
array-len: ((1 string-address) (deref))
mem: ((1000 integer) (raw)) => 3
run: string-copy/main 4: 3 => ((4 integer))
mem: ((4 integer)): 1009 <= 3
run: string-copy/main 5: (((3 integer)) <- ((min)) ((4 integer)) ((3 integer)))
mem: ((4 integer)) => 3
mem: ((3 integer)) => 4
run: min/string-copy/main 0: (((default-space space-address)) <- ((new)) ((space literal)) ((30 literal)))
run: min/string-copy/main 0: 1035 => ((default-space space-address))
run: min/string-copy/main 1: (((1 integer)) <- ((next-input)))
arg: nil 0 (3 4)
run: min/string-copy/main 1: 3 => ((1 integer))
mem: ((1 integer)): 1037 <= 3
run: min/string-copy/main 2: (((2 integer)) <- ((next-input)))
arg: nil 1 (3 4)
run: min/string-copy/main 2: 4 => ((2 integer))
mem: ((2 integer)): 1038 <= 4
run: min/string-copy/main 3: (((3 boolean)) <- ((less-than)) ((1 integer)) ((2 integer)))
mem: ((1 integer)) => 3
mem: ((2 integer)) => 4
run: min/string-copy/main 3: t => ((3 boolean))
mem: ((3 boolean)): 1039 <= t
run: min/string-copy/main 4: (((jump-if)) ((3 boolean)) ((1 offset)))
mem: ((3 boolean)) => t
run: min/string-copy/main 6: (((reply)) ((1 integer)))
mem: ((1 integer)) => 3
run: string-copy/main 5: 3 => ((3 integer))
mem: ((3 integer)): 1008 <= 3
run: string-copy/main 6: (((4 integer)) <- ((subtract)) ((3 integer)) ((2 integer)))
mem: ((3 integer)) => 3
mem: ((2 integer)) => 2
run: string-copy/main 6: 1 => ((4 integer))
mem: ((4 integer)): 1009 <= 1
run: string-copy/main 7: (((5 string-address)) <- ((new)) ((string literal)) ((4 integer)))
mem: ((4 integer)) => 1
run: string-copy/main 7: 1066 => ((5 string-address))
mem: ((5 string-address)): 1010 <= 1066
run: string-copy/main 8: (((6 integer)) <- ((copy)) ((2 integer)))
mem: ((2 integer)) => 2
run: string-copy/main 8: 2 => ((6 integer))
mem: ((6 integer)): 1011 <= 2
run: string-copy/main 9: (((7 integer)) <- ((copy)) ((0 literal)))
run: string-copy/main 9: 0 => ((7 integer))
mem: ((7 integer)): 1012 <= 0
run: string-copy/main 10: (((8 boolean)) <- ((greater-or-equal)) ((6 integer)) ((3 integer)))
mem: ((6 integer)) => 2
mem: ((3 integer)) => 3
run: string-copy/main 10: nil => ((8 boolean))
mem: ((8 boolean)): 1013 <= nil
run: string-copy/main 11: (((jump-if)) ((8 boolean)) ((6 offset)))
mem: ((8 boolean)) => nil
run: string-copy/main 12: (((9 character)) <- ((index)) ((1 string-address) (deref)) ((6 integer)))
mem: ((6 integer)) => 2
array-len: ((1000 string) (raw))
mem: ((1000 integer) (raw)) => 3
mem: ((1003 byte) (raw)) => c
run: string-copy/main 12: #\c => ((9 character))
mem: ((9 character)): 1014 <= #\c
run: string-copy/main 13: (((10 character-address)) <- ((index-address)) ((5 string-address) (deref)) ((7 integer)))
mem: ((7 integer)) => 0
array-len: ((1066 string) (raw))
mem: ((1066 integer) (raw)) => 1
run: string-copy/main 13: 1067 => ((10 character-address))
mem: ((10 character-address)): 1015 <= 1067
run: string-copy/main 14: (((10 character-address) (deref)) <- ((copy)) ((9 character)))
mem: ((9 character)) => c
run: string-copy/main 14: #\c => ((10 character-address) (deref))
mem: ((10 character-address) (deref)): 1067 <= #\c
run: string-copy/main 15: (((6 integer)) <- ((add)) ((6 integer)) ((1 literal)))
mem: ((6 integer)) => 2
run: string-copy/main 15: 3 => ((6 integer))
mem: ((6 integer)): 1011 <= 3
run: string-copy/main 16: (((7 integer)) <- ((add)) ((7 integer)) ((1 literal)))
mem: ((7 integer)) => 0
run: string-copy/main 16: 1 => ((7 integer))
mem: ((7 integer)): 1012 <= 1
run: string-copy/main 17: (((jump)) ((-8 offset)))
run: string-copy/main 10: (((8 boolean)) <- ((greater-or-equal)) ((6 integer)) ((3 integer)))
mem: ((6 integer)) => 3
mem: ((3 integer)) => 3
run: string-copy/main 10: t => ((8 boolean))
mem: ((8 boolean)): 1013 <= t
run: string-copy/main 11: (((jump-if)) ((8 boolean)) ((6 offset)))
mem: ((8 boolean)) => t
run: string-copy/main 18: (((reply)) ((5 string-address)))
mem: ((5 string-address)) => 1066
run: main 1: 1066 => ((2 string-address))
mem: ((2 string-address)): 2 <= 1066
schedule: done with routine nil
edx: int <- copy 0 158 var l/ebx: int <- copy 0 159 h, s, l <- hsl 0, 0, 0 160 check-ints-equal h, 0, "F - test-hsl-black/hue" 161 check-ints-equal s, 0, "F - test-hsl-black/saturation" 162 check-ints-equal l, 0, "F - test-hsl-black/luminance" 163 } 164 165 fn test-hsl-white { 166 var h/ecx: int <- copy 0 167 var s/edx: int <- copy 0 168 var l/ebx: int <- copy 0 169 h, s, l <- hsl 0xff, 0xff, 0xff 170 check-ints-equal h, 0, "F - test-hsl-white/hue" 171 check-ints-equal s, 0, "F - test-hsl-white/saturation" 172 check-ints-equal l, 0xff, "F - test-hsl-white/luminance" 173 } 174 175 fn test-hsl-grey { 176 var h/ecx: int <- copy 0 177 var s/edx: int <- copy 0 178 var l/ebx: int <- copy 0 179 h, s, l <- hsl 0x30, 0x30, 0x30 180 check-ints-equal h, 0, "F - test-hsl-grey/hue" 181 check-ints-equal s, 0, "F - test-hsl-grey/saturation" 182 check-ints-equal l, 0x30, "F - test-hsl-grey/luminance" 183 } 184 185 # red hues: 0-0x54 186 fn test-hsl-slightly-red { 187 var h/ecx: int <- copy 0 188 var s/edx: int <- copy 0 189 var l/ebx: int <- copy 0 190 h, s, l <- hsl 0xff, 0xfe, 0xfe 191 check-ints-equal h, 0, "F - test-hsl-slightly-red/hue" 192 check-ints-equal s, 0xff, "F - test-hsl-slightly-red/saturation" 193 check-ints-equal l, 0xfe, "F - test-hsl-slightly-red/luminance" # TODO: should round up 194 } 195 196 fn test-hsl-extremely-red { 197 var h/ecx: int <- copy 0 198 var s/edx: int <- copy 0 199 var l/ebx: int <- copy 0 200 h, s, l <- hsl 0xff, 0, 0 201 check-ints-equal h, 0, "F - test-hsl-extremely-red/hue" 202 check-ints-equal s, 0xff, "F - test-hsl-extremely-red/saturation" 203 check-ints-equal l, 0x7f, "F - test-hsl-extremely-red/luminance" # TODO: should round up 204 } 205 206 # green hues: 0x55-0xaa 207 fn test-hsl-slightly-green { 208 var h/ecx: int <- copy 0 209 var s/edx: int <- copy 0 210 var l/ebx: int <- copy 0 211 h, s, l <- hsl 0xfe, 0xff, 0xfe 212 check-ints-equal h, 0x55, "F - test-hsl-slightly-green/hue" 213 check-ints-equal s, 0xff, "F - test-hsl-slightly-green/saturation" 214 check-ints-equal l, 0xfe, "F - test-hsl-slightly-green/luminance" # TODO: should round up 215 } 216 217 fn test-hsl-extremely-green { 218 var h/ecx: int <- copy 0 219 var s/edx: int <- copy 0 220 var l/ebx: int <- copy 0 221 h, s, l <- hsl 0, 0xff, 0 222 check-ints-equal h, 0x55, "F - test-hsl-extremely-green/hue" 223 check-ints-equal s, 0xff, "F - test-hsl-extremely-green/saturation" 224 check-ints-equal l, 0x7f, "F - test-hsl-extremely-green/luminance" # TODO: should round up 225 } 226 227 # blue hues: 0xab-0xff 228 fn test-hsl-slightly-blue { 229 var h/ecx: int <- copy 0 230 var s/edx: int <- copy 0 231 var l/ebx: int <- copy 0 232 h, s, l <- hsl 0xfe, 0xfe, 0xff 233 check-ints-equal h, 0xab, "F - test-hsl-slightly-blue/hue" 234 check-ints-equal s, 0xff, "F - test-hsl-slightly-blue/saturation" 235 check-ints-equal l, 0xfe, "F - test-hsl-slightly-blue/luminance" # TODO: should round up 236 } 237 238 fn test-hsl-extremely-blue { 239 var h/ecx: int <- copy 0 240 var s/edx: int <- copy 0 241 var l/ebx: int <- copy 0 242 h, s, l <- hsl 0, 0, 0xff 243 check-ints-equal h, 0xab, "F - test-hsl-extremely-blue/hue" 244 check-ints-equal s, 0xff, "F - test-hsl-extremely-blue/saturation" 245 check-ints-equal l, 0x7f, "F - test-hsl-extremely-blue/luminance" # TODO: should round up 246 } 247 248 # cyan: 0x7f 249 250 fn test-hsl-cyan { 251 var h/ecx: int <- copy 0 252 var s/edx: int <- copy 0 253 var l/ebx: int <- copy 0 254 h, s, l <- hsl 0, 0xff, 0xff 255 check-ints-equal h, 0x80, "F - test-hsl-cyan/hue" 256 check-ints-equal s, 0xff, "F - test-hsl-cyan/saturation" 257 check-ints-equal l, 0x7f, "F - test-hsl-cyan/luminance" # TODO: should round up 258 } 259 260 fn nearest-color-euclidean-hsl h: int, s: int, l: int -> _/eax: int { 261 var result/edi: int <- copy 0x100/invalid 262 var max-distance/esi: int <- copy 0x30000/max # 3 * 0x100*0x100 263 var a/ecx: int <- copy 0 264 var b/edx: int <- copy 0 265 var c/ebx: int <- copy 0 266 var color/eax: int <- copy 0 267 { 268 compare color, 0x100 269 break-if->= 270 $nearest-color-euclidean-hsl:body: { 271 a, b, c <- color-rgb color 272 a, b, c <- hsl a, b, c 273 { 274 var curr-distance/eax: int <- euclidean-hsl-squared a, b, c, h, s, l 275 compare curr-distance, max-distance 276 break-if->= $nearest-color-euclidean-hsl:body 277 max-distance <- copy curr-distance 278 } 279 result <- copy color 280 } 281 color <- increment 282 loop 283 } 284 return result 285 } 286 287 fn test-nearest-color-euclidean-hsl { 288 # red from lightest to darkest 289 var red/eax: int <- nearest-color-euclidean-hsl 0, 0xff, 0xff 290 check-ints-equal red, 0x58/88, "F - test-nearest-color-euclidean-hsl/full-red1" 291 red <- nearest-color-euclidean-hsl 0, 0xff, 0xc0 292 check-ints-equal red, 0x40/64, "F - test-nearest-color-euclidean-hsl/full-red2" 293 red <- nearest-color-euclidean-hsl 0, 0xff, 0x80 294 check-ints-equal red, 0x28/40, "F - test-nearest-color-euclidean-hsl/full-red3" 295 red <- nearest-color-euclidean-hsl 0, 0xff, 0x40 296 check-ints-equal red, 0x28/40, "F - test-nearest-color-euclidean-hsl/full-red4" 297 red <- nearest-color-euclidean-hsl 0, 0xff, 0 298 check-ints-equal red, 0x28/40, "F - test-nearest-color-euclidean-hsl/full-red5" 299 # try a number really close to red but on the other side of the cylinder 300 red <- nearest-color-euclidean-hsl 0xff, 0xff, 0xff 301 #? draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, red, 7/fg 0/bg 302 check-ints-equal red, 0x57/87, "F - test-nearest-color-euclidean-hsl/other-end-of-red" # still looks red 303 # half-saturation red from lightest to darkest 304 red <- nearest-color-euclidean-hsl 0, 0x80, 0xff 305 check-ints-equal red, 0xf/15, "F - test-nearest-color-euclidean-hsl/half-red1" # ?? grey ?? 306 red <- nearest-color-euclidean-hsl 0, 0x80, 0xc0 307 check-ints-equal red, 4, "F - test-nearest-color-euclidean-hsl/half-red2" 308 red <- nearest-color-euclidean-hsl 0, 0x80, 0x80 309 check-ints-equal red, 4, "F - test-nearest-color-euclidean-hsl/half-red3" 310 red <- nearest-color-euclidean-hsl 0, 0x80, 0x40 311 check-ints-equal red, 4, "F - test-nearest-color-euclidean-hsl/half-red4" 312 red <- nearest-color-euclidean-hsl 0, 0x80, 0 313 check-ints-equal red, 0x70/112, "F - test-nearest-color-euclidean-hsl/half-red5" 314 } 315 316 fn euclidean-hsl-squared h1: int, s1: int, l1: int, h2: int, s2: int, l2: int -> _/eax: int { 317 var result/edi: int <- copy 0 318 # hue 319 var tmp/eax: int <- copy h1 320 tmp <- subtract h2 321 tmp <- multiply tmp 322 # TODO: should we do something to reflect that hue is a cylindrical space? 323 # I can't come up with a failing test. 324 result <- add tmp 325 # saturation 326 tmp <- copy s1 327 tmp <- subtract s2 328 tmp <- multiply tmp 329 result <- add tmp 330 # luminance 331 tmp <- copy l1 332 tmp <- subtract l2 333 tmp <- multiply tmp 334 result <- add tmp 335 return result 336 } 337 338 ### 339 340 fn maximum a: int, b: int -> _/eax: int { 341 var a2/eax: int <- copy a 342 compare a2, b 343 { 344 break-if-< 345 return a 346 } 347 return b 348 } 349 350 fn minimum a: int, b: int -> _/eax: int { 351 var a2/eax: int <- copy a 352 compare a2, b 353 { 354 break-if-> 355 return a 356 } 357 return b 358 }