Rearrange the file tree.
[u/mdw/catacomb] / math / t / mpx-gen
diff --git a/math/t/mpx-gen b/math/t/mpx-gen
new file mode 100755 (executable)
index 0000000..891e4d6
--- /dev/null
@@ -0,0 +1,118 @@
+#! /usr/bin/awk -f
+#
+# Generate test vectors for MPX testing
+
+# --- Generate an `l'-byte hex number ---
+
+function r(l,  i, s, x)
+{
+  if (!l) l = len;
+  s = "";
+  for (i = 0; i < l; i++) {
+    x = int(rand() * 256);
+    s = s sprintf("%02X", x);
+  }
+  return (s);
+}
+
+# --- Main code ---
+
+BEGIN {
+
+  # --- Initialization ---
+
+  i = 1;
+  if (i in ARGV) len = ARGV[i++]; else len = 32;
+  if (i in ARGV) op = ARGV[i++]; else op = "+";
+  if (i in ARGV) rep = ARGV[i++]; else rep = 1;
+
+  # --- Output filters ---
+  #
+  # This is complicated.  `bc' emits numbers split over multiple lines with
+  # backslashes.  It also doesn't pad to an even number of digits, which the
+  # test rig is expecting, or use lower-case, which looks nicer.
+  #
+  # The first bit matches a line ending with a backslash.  If it finds one,
+  # it appends the next line, removes the backslash/newline pair, and loops
+  # around to the top.
+  #
+  # The next substitution translates the whole kaboodle into lower-case.
+  #
+  # The next one looks for an off number of hex digits and prepends a zero if
+  # it finds one.
+  #
+  # The one after that just indents by two spaces. The final one sticks a
+  # semicolon on the end.
+
+  bc = "bc | sed '\
+:top\n\
+/\\\\$/ {\n\
+  N\n\
+  s/\\\\\\\n\
+//;\n\
+  b top;\n\
+}\n\
+y/ABCDEF/abcdef/\n\
+s/^[0-9a-f]\\([0-9a-f][0-9a-f]\\)*$/0&/\n\
+s/^/  /\n\
+$ s/$/;/'";
+  out = "sed 'y/ABCDEF/abcdef/; s/^/  /'"
+
+  # --- Main code ---
+
+  srand();
+
+  while (rep--) {
+    x = r();
+
+    print "obase = 16" | bc;
+    print "ibase = 16" | bc;
+
+    # --- Shifting operations ---
+
+    if (op == "<<" || op == ">>") {
+      y = int(rand() * len * 4) + int(rand() * len * 4);
+      rop = (op == "<<" ? "*" : "/");
+      z = sprintf("%X", y);
+      print x, y | out;
+      print x, rop, "(2 ^ " z ")" | bc;
+    }
+
+    # --- Division ---
+
+    else if (op == "/") {
+      ylen = int(rand() * len) + 1;
+      y = r(ylen);
+      print x | out;
+      print y | out;
+      print x, "/", y | bc;
+      print x, "%", y | bc;
+    }
+
+    # --- Squaring ---
+
+    else if (op == "2") {
+      print x | out;
+      print x, "*", x | bc;
+    }
+
+    # --- Other operations ---
+
+    else {
+      y = r();
+      if (op == "-" && x < y) {
+       t = x; x = y; y = t;
+      }
+      print x | out;
+      print y | out;
+      print x, op, y | bc;
+    }
+
+    close(out);
+    close(bc);
+    if (rep)
+      print;
+  }
+
+  exit 0;
+}