c.p.brown
12th of July 2026


2020s
TXT
gifded:gtk4::vala:
screenie
Bash together a process by mixing Python, Rebol, text or Shellscript operators... whatever works.

Used for both commercial and personal scripting projects.
This gets a lot of use, pretty happy with it.

Source is here.
Note there is no license to use this software, it exists here for my own use, should I need to obtain it via internet.

Instructions for Linux:
  • extract && cd to gifded
  • install vala and gtksourceview5-devel
  • copy install/.local/share/gtksourceview-5 to /.local/share/
  • compile using clear && valac gifded.vala --pkg gtk4 --pkg gtksourceview-5 -X -lm
  • install any other dependencies it complains about, and try again
  • run ./gifded
  • if it looks like ass, install adw-gtk3-theme and enable via gnome-tweaks
  • if it still looks like ass, SOLS: its a backward compatibility issue (being addressed in the sequel via hardcoded theme)

fulltardie:gtk4::vala::wip:
screenie

Used to keep track of a large number of recurring transactions.
Also great for quickly testing future scenarios.

This was originally a Python script written on the Blackberry to determine if I can afford overseas vfx contracts.

r21:gtk3::red:
screenie

Used to manage my 2021 site. 32-bit, Gtk3.
Last Red program before switching to Vala/Gtk4.



dramaqueen:gtk3::red:
screenie
Site builder with T&C configurator.

Used for commerical projects, since replaced by a faster commandline version written in Vala.
reexsa:gtk3::red:
screenie
Interface for testing Red-Parse.

Red [ needs 'view ] ;; interactively test parse rules ;; by c.p.brown 2021 ;; ;; attempt [] may freeze the script, uncomment if its a problem marg: 10 tabh: 0 ;; height of the statusbar (none atm) nudgeu: func [] [ uu/offset/x: 0 uu/offset/y: min (max 200 uu/offset/y) 600 uu/size/x: tp/size/x vv/offset/y: uu/offset/y + 10 vv/size/y: tp/size/y - ((uu/offset/y + 10) + tabh) maa/offset/y: 0 maa/size/x: uu/size/x mbb/offset/y: uu/offset/y + 10 mcc/offset/y: uu/offset/y + 10 maa/size/y: uu/offset/y mbb/size/y: vv/size/y mcc/size/y: vv/size/y maah/offset/y: 0 mbbh/offset/y: 0 mcch/offset/y: 0 maap/offset/y: maah/size/y + marg mbbp/offset/y: mbbh/size/y + marg mccp/offset/y: mcch/size/y + marg maap/size/y: maa/size/y - (maah/size/y + (2 * marg)) mbbp/size/y: mbb/size/y - (mbbh/size/y + (2 * marg)) mccp/size/y: mcc/size/y - (mcch/size/y + (2 * marg)) uu/draw: compose/deep [ pen off fill-pen 100.100.100 circle (to-pair compose/deep [(to-integer (uu/size/x * 0.5) - 10) 5]) 2 2 circle (to-pair compose/deep [(to-integer (uu/size/x * 0.5)) 5]) 2 2 circle (to-pair compose/deep [(to-integer (uu/size/x * 0.5) + 10) 5]) 2 2 ] ] nudgev: func [] [ vv/offset/y: uu/offset/y + 10 vv/offset/x: min (max 100 vv/offset/x) (tp/size/x - 100) if vv/offset/x < 100 [ return 0 ] maa/offset/x: 0 mbb/offset/x: 0 mcc/offset/x: vv/offset/x + 10 mbb/size/x: vv/offset/x mcc/size/x: (tp/size/x - mcc/offset/x) maah/offset/x: 0 mbbh/offset/x: 0 mcch/offset/x: 0 maah/size/x: maa/size/x mbbh/size/x: mbb/size/x mcch/size/x: mcc/size/x maap/offset/x: marg mbbp/offset/x: marg mccp/offset/x: marg maap/size/x: maah/size/x - (marg + marg + 1) mbbp/size/x: mbbh/size/x - (marg + marg) mccp/size/x: mcch/size/x - (marg + marg + 1) vv/draw: compose/deep [ pen off fill-pen 100.100.100 circle (to-pair compose/deep [5 (to-integer (vv/size/y * 0.5) - 10)]) 2 2 circle (to-pair compose/deep [5 (to-integer (vv/size/y * 0.5))]) 2 2 circle (to-pair compose/deep [5 (to-integer (vv/size/y * 0.5) + 10)]) 2 2 ] ] view/tight/flags/options [ title "reexsa" below hh: panel 800x55 35.35.35 [ parsers: drop-list 200x30 font-name "consolas" font-size 10 font-color 180.180.180 bold data (collect [foreach file read %./ [ if (find (to-string file) ".parse") [keep rejoin ["./" (to-string file)]] ]]) on-change [ pfn: copy parsers/data/(parsers/selected) pn: "" parse pfn [ thru "./" copy pn to ".parse" ] parsername/text: pn pset: load to-file parsers/data/(parsers/selected) maap/text: (reduce pset/1) mbbp/text: (reduce pset/2) maap/font/color: 255.0.0 s: copy mbbp/text attempt [ do maap/text mccp/text: s maap/font/color: 128.255.128 ] ] pad 10x0 parsername: field 200x30 font-name "consolas" font-size 10 font-color 180.180.180 bold pnew: button 80x34 "save" font-name "consolas" font-size 10 font-color 180.180.180 bold [ if (parsername/text <> "") and (parsername/text <> none) [ newparsername: rejoin [ "./" parsername/text ".parse" ] write to-file newparsername ( reduce [ maap/text mbbp/text ]) clear parsers/data parsers/data: (collect [foreach file read %./ [ if (find (to-string file) ".parse") [keep rejoin ["./" (to-string file)]] ]]) parsers/selected: index? find parsers/data newparsername ] ] pad 10x0 psave: button 160x34 "save output" font-name "consolas" font-size 10 font-color 180.180.180 bold [ if (parsername/text <> "") and (parsername/text <> none) [ op: request-dir unless none? op [ write to-file rejoin [ op parsername "_output.txt" ] mccp/text ] ] ] ] tp: panel 800x745 [ below maa: panel 800x300 40.40.40 [ maah: panel 45.45.45 800x55 [ text 200x30 "parse" font-name "consolas" font-size 24 font-color 80.80.80 bold ] maap: area 800x300 40.40.40 font-name "consolas" font-size 12 font-color 128.255.128 bold with [ text: {parse s [ any [ to "^^/* " change "^^/* " "^^/<li>" pre: [ to "^^/" change "^^/" "</li>^^/" | to end change end "</li>" end ] :pre ] ]^/parse s [ any [ to "^^/<li>" not "</li>^^/<li>" change "^^/<li>" "<ul>^^/<li>" ] ]} ] on-change [ face/font/color: 255.0.0 s: copy mbbp/text attempt [ do maap/text mccp/text: s face/font/color: 128.255.128 ] ] ] uu: panel 800x10 30.30.30 loose [] on-drag [ nudgeu ] across mbb: panel 390x400 40.40.40 [ mbbh: panel 390x55 45.45.45 [ text 200x30 "source" font-name "consolas" font-size 24 font-color 80.80.80 bold ] mbbp: area 390x300 40.40.40 font-name "consolas" font-size 12 font-color 128.255.255 bold with [ text: {a list:^/* one^/* two^/* three^/end of * list^/another list^/* AAA^/* BBB^/end of the other list} ;;*/ <- emacs red-mode is screwy atm ] on-change [ face/font/color: 255.0.0 s: copy mbbp/text attempt [ do maap/text mccp/text: s face/font/color: 128.255.128 ] ] ] vv: panel 10x390 30.30.30 loose [] on-drag [ nudgev ] mcc: panel 390x400 40.40.40 [ mcch: panel 390x55 45.45.45 [ text 200x30 "result" font-name "consolas" font-size 24 font-color 80.80.80 bold ] mccp: area 390x345 40.40.40 font-name "consolas" font-size 12 font-color 255.255.128 bold ] ] do [ if exists? %./default.parse [ pset: load %./default.parse maap/text: (reduce pset/1) mbbp/text: (reduce pset/2) parsername/text: "default" parsers/selected: index? find parsers/data "./default.parse" maap/font/color: 255.0.0 s: copy mbbp/text attempt [ do maap/text mccp/text: s maap/font/color: 128.255.128 ] ] psave/offset/x: tp/size/x - (psave/size/x + marg) pnew/offset/x: psave/offset/x - (pnew/size/x + marg) parsername/offset/x: (parsers/offset/x + parsers/size/x + marg) parsername/size/x: pnew/offset/x - (parsers/size/x + (4 * marg)) nudgeu nudgev ] ] [ resize ] [ actors: object [ on-resizing: function [ face event ] [ if face/size/x > 500 [ if face/size/y > (uu/offset/y + 200) [ hh/size/x: face/size/x tp/size: face/size - 0x55 psave/offset/x: face/size/x - (psave/size/x + marg) pnew/offset/x: psave/offset/x - (pnew/size/x + marg) parsername/offset/x: (parsers/offset/x + parsers/size/x + marg) parsername/size/x: pnew/offset/x - (parsers/size/x + (4 * marg)) nudgeu nudgev ] ] ] ] ]
REF
VALA TESTS:vala:

Attempt to solve the riddle of:

CAIRO
CAIROSCRIPT

Render Cairo from text commands at runtime.
Currently busted.

bool validatecairocmd(string c) { // assumes newline has been removed via commands.split("\n") if (c.char_count() < 3) { return false; } string[] cp = c.split("("); if (cp.length < 2) { return false; } if (cp[1].get_char(cp[1].index_of_nth_char(cp[1].char_count() - 1)) != ')') { return false; } cp[1] = cp[1].substring(0,cp[1].char_count() - 1); string[] arg = splitunquoted(cp[1],","); cp[0] = cp[0].strip(); int cmd = 1; string[] cmds = { "int", "double", "bool", "uint", "if", "for", "else", "while", "break", "continue", "fill", "move_to", "paint", "poppler_render_pdf", "rectangle", "set_source_rgba", "stroke" }; for (int i = 0; i < cmds.length; i++) { if (strcmp(cp[0],cmds[i]) == 0) { cmd = i; break; } } if (cmd == -1) { return false; } int[] argcounts = { 1, // int 1, // double 1, // uint 1, // bool 3, // if a cond b 3, // for i= i< i+= for(0,10,1) 0, // else 3, // while a cond b 0, // break 0, // continue 0, // fill 2, // move_to x y 0, // paint 1, // poppler_render_pdf full_path_to_file 4, // rectangle px py sx sy 4, // set_source_rgba r g b a 0 // stroke }; print("\tcommand %d \"%s\" requires %d args, provides %d...\n",cmd,cp[0],argcounts[cmd],arg.length ); if (arg.length == argcounts[cmd]) { print("\tcommand validated.\n"); return true; } return false; } // classes class cx_cmd : Object { private string[] cmd; private Poppler.Document popplerdocument; public cx_cmd (string c) { string[] cp = c.split("("); cp[1] = cp[1].substring(0,cp[1].char_count() - 1); string[] arg = splitunquoted(cp[1],","); cmd.resize(0); cmd += cp[0].strip(); for (int i = 0; i < arg.length; i++) { cmd += arg[i].strip(); } for (int i = 0; i < cmd.length; i++) { print("cmd part %d is %s\n",i,cmd[i]); } if (strcmp(cmd[0],"poppler_render_pdf") == 0) { GLib.File pdffile = GLib.File.new_for_path(cmd[1]); if (pdffile.query_exists()) { popplerdocument = new Poppler.Document.from_file(pdffile.get_uri(),null); } } } public void run(cairoview da, Cairo.Context ctx) { ctx.set_font_options(da.cv_opt); double csx = da.get_allocated_width(); double csy = da.get_allocated_height(); // collect memorized vals da.cv_sizx = da.cv_olsz[0]; da.cv_sizy = da.cv_olsz[1]; da.cv_posx = da.cv_olof[0]; da.cv_posy = da.cv_olof[1]; //Cairo.Matrix smtx = new Cairo.Matrix.identity(); //ctx.transform(smtx); // zoom if (da.iscr) { da.cv_aszy = (da.cv_ogsz[1] + da.cv_zinc[1]); da.cv_aszy = double.max(da.cv_aszy,1.0); da.cv_sizy = (da.cv_aszy / da.cv_ogsz[1]); da.cv_aszx = (da.cv_ogsz[0] + da.cv_zinc[0]); da.cv_aszx = double.max(da.cv_aszx,1.0); da.cv_sizx = (da.cv_aszx / da.cv_ogsz[0]); } if (da.izom) { // set relative xy scale to 1 + mousemove offset da.cv_sizx = 1.0 + (-(da.cv_mdwn[0] - da.cv_moom[0]) * 0.01); da.cv_sizy = 1.0 + ((da.cv_mdwn[1] - da.cv_moom[1]) * 0.01); da.cv_aszx = (da.cv_ogsz[0] * da.cv_sizx); da.cv_aszy = (da.cv_ogsz[1] * da.cv_sizy); } // TODO: redo the math to work without scale // set position when zooming if (da.izom) { da.cv_posx = (((da.cv_olof[0] - da.cv_mdwn[0]) * da.cv_sizx) + da.cv_mdwn[0]); da.cv_posy = (((da.cv_olof[1] - da.cv_mdwn[1]) * da.cv_sizy) + da.cv_mdwn[1]); da.cv_trgx = ((da.cv_olmd[0] - da.cv_mdwn[0]) * da.cv_sizx) + da.cv_mdwn[0]; da.cv_trgy = ((da.cv_olmd[1] - da.cv_mdwn[1]) * da.cv_sizy) + da.cv_mdwn[1]; } if (da.iscr) { da.cv_posx = ((da.cv_olof[0] - da.cv_mdwn[0]) * da.cv_sizx) + da.cv_mdwn[0]; da.cv_posy = ((da.cv_olof[1] - da.cv_mdwn[1]) * da.cv_sizy) + da.cv_mdwn[1]; da.cv_trgx = ((da.cv_olmd[0] - da.cv_mdwn[0]) * da.cv_sizx) + da.cv_mdwn[0]; da.cv_trgy = ((da.cv_olmd[1] - da.cv_mdwn[1]) * da.cv_sizy) + da.cv_mdwn[1]; } if(da.ipan) { da.cv_posx = da.cv_olof[0] + (da.cv_moom[0] - da.cv_mdwn[0]); da.cv_posy = da.cv_olof[1] + (da.cv_moom[1] - da.cv_mdwn[1]); da.cv_trgx = da.cv_olmd[0] + (da.cv_moom[0] - da.cv_mdwn[0]); da.cv_trgy = da.cv_olmd[1] + (da.cv_moom[1] - da.cv_mdwn[1]); } // font //ctx.select_font_face("Monospace",Cairo.FontSlant.NORMAL,Cairo.FontWeight.NORMAL); // margin double mxy = double.min((csx * da.cv_aszx),(csy * da.cv_aszy)); double xmarg = mxy * 0.1; double ymarg = mxy * 0.1; double fsx = ((csx * da.cv_aszx) - (xmarg * 2.0)) - (4 * da.cv_aszx); double fsy = ((csy * da.cv_aszy) - (ymarg * 2.0)) - (4 * da.cv_aszy); double ffsx = (csx - (csx * 0.2)) - 4; double ffsy = (csy - (csy * 0.2)) - 4; //da.cv_posx = double.min(da.cv_posx,0.0); //da.cv_posx = double.max(da.cv_posx,(0 - ((csx * da.cv_aszx) - csx))); //da.cv_posy = double.min(da.cv_posy,0.0); //da.cv_posy = double.max(da.cv_posy,(0 - ((csy * da.cv_aszy) - csy))); // transform matrix Cairo.Matrix mtx = new Cairo.Matrix.identity(); double cx_px = da.cv_posx; //da.cv_olof[0] + ((da.cv_moom[0] - da.cv_mdwn[0]) * 1.0); double cx_py = da.cv_posy; //da.cv_olof[1] + ((da.cv_moom[1] - da.cv_mdwn[1]) * 1.0); mtx.x0 = da.cv_posx * (0.3333 * (1.0 / da.cv_aszx)); mtx.y0 = da.cv_posy * (0.3333 * (1.0 / da.cv_aszy)); mtx.xx = da.cv_aszx; mtx.yy = da.cv_aszy; ctx.transform(mtx); // incoming command if (strcmp(cmd[0],"set_source_rgba") == 0) { ctx.set_source_rgba(double.parse(cmd[1]),double.parse(cmd[2]),double.parse(cmd[3]),double.parse(cmd[4])); return; } if (strcmp(cmd[0],"rectangle") == 0) { ctx.rectangle(double.parse(cmd[1]),double.parse(cmd[2]),double.parse(cmd[3]),double.parse(cmd[4])); return; } if (strcmp(cmd[0],"paint") == 0) { ctx.paint(); return; } if (strcmp(cmd[0],"fill") == 0) { ctx.fill(); return; } if (strcmp(cmd[0],"stroke") == 0) { ctx.stroke(); return; } if (strcmp(cmd[0],"set_line_width") == 0) { ctx.set_line_width(double.parse(cmd[1])); return; } if (strcmp(cmd[0],"set_line_cap") == 0) { if (strcmp(cmd[1],"BUTT") == 0) { ctx.set_line_cap(BUTT); return; } if (strcmp(cmd[1],"ROUND") == 0) { ctx.set_line_cap(ROUND); return; } ctx.set_line_cap(SQUARE); return; } if (strcmp(cmd[0],"poppler_render_pdf") == 0) { Cairo.Script cs = new Cairo.Script("./test_cairoscript.txt"); Poppler.Page pdfpage = popplerdocument.get_page(1); pdfpage.render_for_printing_with_options(ctx,DOCUMENT); } double cx_xinc = (fsx / 8.0); double cx_yinc = (fsy / 8.0); ctx.set_line_width(2); double cx_yfmin = ymarg; double cx_xfmax = (fsx + xmarg); double cx_yfmax = (fsy + ymarg); ctx.set_source_rgba(1.0,0.1,0.05,0.75); for (int i = 0; i <= 8.0; i++) { cx_px = ((cx_xinc * i) + xmarg); cx_py = ymarg; ctx.move_to(cx_px, cx_py); ctx.line_to(cx_px, cx_yfmax); ctx.stroke(); cx_px = xmarg; cx_py = ((cx_yinc * i) + ymarg); ctx.move_to(cx_px, cx_py); ctx.line_to(cx_xfmax, cx_py); ctx.stroke(); } ctx.move_to(da.cv_mdwn[0],da.cv_mdwn[1]); ctx.line_to(da.cv_moom[0],da.cv_moom[1]); ctx.stroke(); // end wheel signal here if (da.iscr) { da.iscr = false; da.cv_ogsz = {da.cv_aszx,da.cv_aszy}; da.cv_olsz = {da.cv_sizx,da.cv_sizy}; da.cv_olof = {da.cv_posx,da.cv_posy}; da.cv_olmd = {da.cv_trgx,da.cv_trgy}; } } } string[] splitunquoted (string s, string d) { StringBuilder sb = new StringBuilder(""); sb.append(s); string ex = "%c".printf('\x1E'); string dx = "%c".printf('\x1F'); char qc = '\"'; // " string qs = "\""; // " string[] q = {}; q += s; int f = 0; bool u = false; int ii = sb.str.index_of_char(qc); if (ii > -1) { if (ii == 0) { f = 2; print("1st quote char is at position %d, 1st unquoted segment is at split-string index %d\n",ii,f); } int oo = sb.str.index_of_char(qc,(ii+1)); if (oo > -1) { string ecs = "\\" + qs; uint ec = sb.replace(ecs,ex,0); print("\tstring with delimited escaped quotes is %s\n",sb.str); q = sb.str.split(qs); if ((q.length & 1) == 0) { u = true; print("\tquote-separated segment count is %d\n",q.length); q[q.length - 2] = q[q.length - 2] + qs +q[q.length - 1]; q.resize(q.length - 1); } if (ec > 0) { for (int i = 0; i < q.length; i++) { if (q[i].last_index_of(ex) > -1) { q[i] = q[i].replace(ex,ecs); print("\tsegment with restored escaped quotes is %s\n",q[i]); } } sb.assign(string.joinv("",q)); } } } if (q.length > 1) { for (int i = f; i < q.length; i += 2) { print("\tunquoted segment %d is %s\n",i,q[i]); q[i] = q[i].replace(d,dx); print("\tunquoted segment %d with delimiters is %s\n",i,q[i]); } f = (f+1) % 2; for (int i = f; i < q.length; i += 2) { print("\tquoted segment %d is %s\n",i,q[i]); q[i] = qs + q[i] + qs; print("\tquoted segment %d with restored quotes is %s\n",i,q[i]); } sb.assign(string.joinv("",q)); q = sb.str.split(dx); } else { sb.replace(d,dx,0); q = sb.str.split(dx); } return q; } class cairoview : Gtk.DrawingArea { private cx_cmd[] cxcmds; public Gtk.GestureClick cv_touchpan; public Gtk.EventControllerScroll cv_wheeler; public Gtk.EventControllerMotion cv_hover; public Cairo.FontOptions cv_opt; public bool izom; // zoom mode public bool ipan; // pan mode public bool iscr; // scroll mode public bool ipik; // pick mode public double[] cv_olsz; // graph pre-draw size xy public double[] cv_ogsz; // graph pre-draw absolute scale public double[] cv_olmd; // graph pre-draw mousedown xy public double[] cv_olof; // graph pre-draw offset xy public double cv_olbh; // graph pre-draw bar height public double[] cv_moom; // graph live mousemove xy public double[] cv_mdwn; // graph live mousedown xy public double[] cv_zinc; // graph live zoom incrament public double cv_aszx; // graph post-draw size x public double cv_aszy; // graph post-draw size y public double cv_posx; // graph post-draw offset x public double cv_posy; // graph post_draw offset y public double cv_sizx; // graph post-draw size x public double cv_sizy; // graph post-draw size y public double cv_trgx; public double cv_trgy; public double cv_weel; // wheel +/- for vscroll public Cairo.RecordingSurface cv_record; public Cairo.Context cv_rctx; void redraw(Gtk.DrawingArea da, Cairo.Context ctx, int w, int h) { for (int i = 0; i < cxcmds.length; i++) { cxcmds[i].run(this,cv_rctx); } ctx.set_source_surface = cv_record; ctx.paint(); //ctx.set_source_rgba(0.8,0.1,0.1,1.0); //ctx.rectangle(10.0,10.0,480.0,480.0); //ctx.stroke(); } public void updatecmd (string[] cmds) { cxcmds.resize(0); for (int i = 0; i < cmds.length; i++) { print("validating cmd \"%s\"...\n",cmds[i]); if (validatecairocmd(cmds[i])) { cxcmds += new cx_cmd(cmds[i]); } else { print("cmd not validated.\n"); } } this.queue_draw(); } public cairoview () { cv_rctx = new Cairo.Surface(cv_record); this.set_draw_func(redraw); cv_touchpan = new Gtk.GestureClick(); cv_wheeler = new Gtk.EventControllerScroll(VERTICAL); cv_hover = new Gtk.EventControllerMotion(); cv_touchpan.set_button(0); this.add_controller(cv_touchpan); this.add_controller(cv_wheeler); this.add_controller(cv_hover); izom = false; // zoom mode ipan = false; // pan mode iscr = false; // scroll mode ipik = false; // pick mode cv_olsz = {1.0,1.0}; // graph pre-draw size xy cv_ogsz = {1.0,1.0}; // graph pre-draw absolute scale cv_olmd = {0.0,0.0}; // graph pre-draw mousedown xy cv_olof = {0.0,0.0}; // graph pre-draw offset xy cv_olbh = 30.0; // graph pre-draw bar height cv_moom = {0.0,0.0}; // graph live mousemove xy cv_mdwn = {0.0,0.0}; // graph live mousedown xy cv_zinc = {0.0,0.0}; // graph live zoom incrament cv_aszx = 1.0; // graph post-draw size x cv_aszy = 1.0; // graph post-draw size y cv_posx = 0.0; // graph post-draw offset x cv_posy = 0.0; // graph post_draw offset y cv_sizx = 0.0; // graph post-draw size x cv_sizy = 0.0; // graph post-draw size y cv_trgx = 0.0; cv_trgy = 0.0; cv_weel = 0.0; // wheel +/- for vscroll cv_opt = new Cairo.FontOptions(); cv_opt.set_hint_metrics(OFF); cv_touchpan.begin.connect ((event,seq) => { double x, y; event.get_point(seq,out x,out y); ipik = (cv_touchpan.get_current_button() == 1); izom = (cv_touchpan.get_current_button() == 3); ipan = (cv_touchpan.get_current_button() == 2); cv_mdwn = {x, y}; if (ipik) { cv_olmd = {cv_mdwn[0], cv_mdwn[1]}; cv_trgx = cv_mdwn[0]; cv_trgy = cv_mdwn[1]; this.queue_draw(); } }); cv_touchpan.update.connect((event, seq) => { double x, y; uint cb = cv_touchpan.get_current_button(); event.get_point(seq,out x,out y); if (ipan || izom ) { print("panning at %.2f %.2f...\n",x,y); cv_moom = {x,y}; } if ((cb == 1) || (cb == 2) || (cb == 3)) { this.queue_draw(); } }); cv_hover.motion.connect ((event, x, y) => { if (!izom && !ipan && !ipik) { cv_mdwn = {x, y}; } }); cv_touchpan.released.connect((n_press,x,y) => { ipan = false; izom = false; ipik = false; iscr = false; cv_ogsz[0] = cv_aszx; cv_ogsz[1] = cv_aszy; cv_olsz = {cv_sizx,cv_sizy}; cv_olof = {cv_posx,cv_posy}; cv_olmd = {cv_trgx,cv_trgy}; cv_moom = {0.0,0.0}; }); cv_wheeler.scroll.connect ((x,y) => { iscr = true; if (y > 0) { cv_weel = -1.0; cv_zinc[0] = (-0.1 * cv_ogsz[0]); cv_zinc[1] = (-0.1 * cv_ogsz[1]); } if (y < 0) { cv_weel = 1.0; cv_zinc[0] = (0.1 * cv_ogsz[0]); cv_zinc[1] = (0.1 * cv_ogsz[1]); } this.queue_draw(); return true; }); } } int main(string[] args) { Gtk.Application myapp = new Gtk.Application("com.mytest.mytest",GLib.ApplicationFlags.DEFAULT_FLAGS); myapp.activate.connect (() => { Gtk.ApplicationWindow mywin = new Gtk.ApplicationWindow(myapp); Gtk.Paned divider = new Gtk.Paned(HORIZONTAL); Gtk.ScrolledWindow editorscroll = new Gtk.ScrolledWindow(); Gtk.TextTagTable editortexttagtable = new Gtk.TextTagTable(); GtkSource.Buffer editorbuffer = new GtkSource.Buffer(editortexttagtable); GtkSource.View editorview = new GtkSource.View.with_buffer(editorbuffer); GtkSource.Gutter editorgutter = editorview.get_gutter(LEFT); Gtk.Box drawbox = new Gtk.Box(VERTICAL,0); Gtk.ScrolledWindow drawscroll = new Gtk.ScrolledWindow(); cairoview cv = new cairoview(); drawbox.hexpand = true; drawbox.vexpand = true; cv.hexpand = true; cv.vexpand = true; editorview.accepts_tab = true; editorview.set_monospace(true); editorview.tab_width = 4; editorview.indent_on_tab = true; editorview.indent_width = 4; editorview.show_line_numbers = true; editorview.highlight_current_line = true; editorview.vexpand = true; editorview.hexpand = true; editorview.top_margin = 0; editorview.left_margin = 0; editorview.right_margin = 0; editorview.bottom_margin = 0; editorview.space_drawer.enable_matrix = true; editorbuffer.set_highlight_syntax(true); divider.wide_handle = true; divider.position = 300; editorbuffer.set_style_scheme(GtkSource.StyleSchemeManager.get_default().get_scheme("frownedupon")); editorbuffer.set_language(GtkSource.LanguageManager.get_default().get_language("vala")); //editorbuffer.set_text("set_source_rgba(0.1,0.2,0.3,1.0)\npaint()\nset_source_rgba(0.4,0.1,0.1,1.0)\nrectangle(50,50,100,25)\nfill()"); editorbuffer.set_text("set_source_rgba(0.9,0.9,0.9,1.0)\npaint()\npoppler_render_pdf(./Statement.pdf)"); editorview.buffer.changed.connect(() => { string[] initcmd = editorview.buffer.text.split("\n"); cv.updatecmd(initcmd); }); // assemble ui editorscroll.set_child(editorview); drawbox.append(cv); drawscroll.set_child(drawbox); divider.start_child = editorscroll; divider.end_child = drawscroll; mywin.set_child(divider); mywin.default_width = 800; mywin.default_height = 500; mywin.present(); string[] tc = editorview.buffer.text.split("\n"); cv.updatecmd(tc); }); return myapp.run(args); }
FONTMATRIX

Smooth scaling of fonts.
Disable hinting to prevent jank when interactively resizing text.
Avoid cumulative scaling by writing directly to fontmatrix.xx and fontmatrix.yy, instead of fontmatrix.scale()

// fontmatrix text // by c.p.brown 2025 // // r-click+drag to scale public class CssColor { public string name; public string hex; public Gdk.RGBA rgba; public double[] hsva; public string cssrgb; public double baseval; public void sethex (string h) { hex = h; double ghue; double gsat; double gval; rgba.parse(h); Gtk.rgb_to_hsv( rgba.red, rgba.green, rgba.blue, out ghue, out gsat, out gval ); hsva = {ghue,gsat,gval,rgba.alpha}; cssrgb = rgba.to_string(); } public void setrgba (float[] r) { hex = "#%02X%02X%02X%02X".printf( ((int) (r[0] * 255.0)), ((int) (r[1] * 255.0)), ((int) (r[2] * 255.0)), ((int) (r[3] * 255.0)) ); rgba.red = r[0]; rgba.green = r[1]; rgba.blue = r[2]; rgba.alpha = r[3]; double ghue; double gsat; double gval; Gtk.rgb_to_hsv( rgba.red, rgba.green, rgba.blue, out ghue, out gsat, out gval ); hsva = {ghue,gsat,gval,rgba.alpha}; cssrgb = rgba.to_string(); } public void sethsv (double[] r) { hsva[0] = r[0]; hsva[1] = r[1]; hsva[2] = r[2]; hsva[3] = r[3]; double gred; double ggreen; double gblue; Gtk.hsv_to_rgb( (float) hsva[0], (float) hsva[1], (float) hsva[2], out gred, out ggreen, out gblue ); rgba.red = (float) gred; rgba.green = (float) ggreen; rgba.blue = (float) gblue; rgba.alpha = (float) hsva[3]; cssrgb = rgba.to_string(); hex = "#%02X%02X%02X%02X".printf( ((int) (gred * 255.0)), ((int) (ggreen * 255.0)), ((int) (gblue * 255.0)), ((int) (hsva[3] * 255.0)) ); } public CssColor (string n, string? h) { name = n; if (h != null) { sethex(h); } } } class fontview : Gtk.Box { private double[] cv_olsz; private double[] cv_ogsz; private double[] cv_olmd; private double[] cv_olof; private double[] cv_olxy; private double cv_olbh; private Gtk.DrawingArea ccimg; public void redraw() { ccimg.queue_draw(); } public fontview () { ccimg = new Gtk.DrawingArea(); ccimg.hexpand = true; ccimg.vexpand = true; Gtk.GestureClick cv_touchpan = new Gtk.GestureClick(); Gtk.EventControllerScroll cv_wheeler = new Gtk.EventControllerScroll(VERTICAL); Gtk.EventControllerMotion cv_hover = new Gtk.EventControllerMotion(); cv_touchpan.set_button(0); ccimg.add_controller(cv_touchpan); ccimg.add_controller(cv_wheeler); ccimg.add_controller(cv_hover); bool izom = false; // zoom mode bool ipan = false; // pan mode bool iscr = false; // scroll mode bool ipik = false; // pick mode cv_olsz = {1.0,1.0}; // graph pre-draw size xy cv_ogsz = {1.0,1.0}; // graph pre-draw absolute scale cv_olmd = {0.0,0.0}; // graph pre-draw mousedown xy cv_olof = {0.0,0.0}; // graph pre-draw offset xy cv_olbh = 30.0; // graph pre-draw bar height double[] cv_moom = {0.0,0.0}; // graph live mousemove xy double[] cv_mdwn = {0.0,0.0}; // graph live mousedown xy double[] cv_zinc = {0.0,0.0}; // graph live zoom incrament double cv_aszx = 1.0; // graph post-draw size x double cv_aszy = 1.0; // graph post-draw size y double cv_posx = 0.0; // graph post-draw offset x double cv_posy = 0.0; // graph post_draw offset y double cv_sizx = 0.0; // graph post-draw size x double cv_sizy = 0.0; // graph post-draw size y double cv_trgx = 0.0; double cv_trgy = 0.0; double cv_weel = 0.0; // wheel +/- for vscroll CssColor cv_bgc = new CssColor("bgdef_col","#08131AFF"); CssColor cv_fgc = new CssColor("fgdef_col","#142E3DFF"); CssColor cv_txc = new CssColor("txdef_col","#50B5F2FF"); Cairo.Matrix cv_fmx = Cairo.Matrix.identity(); Cairo.FontOptions cv_opt = new Cairo.FontOptions(); cv_opt.set_hint_metrics(OFF); cv_touchpan.begin.connect ((event,seq) => { double x, y; event.get_point(seq,out x,out y); ipik = (cv_touchpan.get_current_button() == 1); izom = (cv_touchpan.get_current_button() == 3); ipan = (cv_touchpan.get_current_button() == 2); cv_mdwn = {x, y}; if (ipik) { cv_olmd = {cv_mdwn[0], cv_mdwn[1]}; cv_trgx = cv_mdwn[0]; cv_trgy = cv_mdwn[1]; ccimg.queue_draw(); } }); cv_touchpan.update.connect((event, seq) => { double x, y; uint cb = cv_touchpan.get_current_button(); event.get_point(seq,out x,out y); if (ipan || izom ) { cv_moom = {x,y}; } if ((cb == 1) || (cb == 2) || (cb == 3)) { ccimg.queue_draw(); } }); cv_hover.motion.connect ((event, x, y) => { if (!izom && !ipan && !ipik) { cv_mdwn = {x, y}; } }); cv_touchpan.released.connect((n_press,x,y) => { ipan = false; izom = false; ipik = false; iscr = false; cv_ogsz[0] = cv_aszx; cv_ogsz[1] = cv_aszy; cv_olsz = {cv_sizx,cv_sizy}; cv_olof = {cv_posx,cv_posy}; cv_olmd = {cv_trgx,cv_trgy}; cv_moom = {0.0,0.0}; }); cv_wheeler.scroll.connect ((x,y) => { iscr = true; if (y > 0) { cv_weel = -1.0; cv_zinc[0] = (-0.1 * cv_ogsz[0]); cv_zinc[1] = (-0.1 * cv_ogsz[1]); } if (y < 0) { cv_weel = 1.0; cv_zinc[0] = (0.1 * cv_ogsz[0]); cv_zinc[1] = (0.1 * cv_ogsz[1]); } ccimg.queue_draw(); return true; }); this.append(ccimg); ccimg.set_draw_func((ds,ctx,daw,dah) => { ctx.set_font_options(cv_opt); double csx = ccimg.get_allocated_width(); double csy = ccimg.get_allocated_height(); // collect memorized vals cv_sizx = cv_olsz[0]; cv_sizy = cv_olsz[1]; cv_posx = cv_olof[0]; cv_posy = cv_olof[1]; // zoom if (iscr) { cv_aszy = (cv_ogsz[1] + cv_zinc[1]); cv_aszy = double.max(cv_aszy,1.0); cv_sizy = (cv_aszy / cv_ogsz[1]); cv_aszx = (cv_ogsz[0] + cv_zinc[0]); cv_aszx = double.max(cv_aszx,1.0); cv_sizx = (cv_aszx / cv_ogsz[0]); } if (izom) { // set relative xy scale to 1 + mousemove offset cv_sizx = 1.0 + (-(cv_mdwn[0] - cv_moom[0]) * 0.01); cv_sizy = 1.0 + ((cv_mdwn[1] - cv_moom[1]) * 0.01); cv_aszx = (cv_ogsz[0] * cv_sizx); cv_aszy = (cv_ogsz[1] * cv_sizy); } // set position when zooming if (izom) { cv_posx = (((cv_olof[0] - cv_mdwn[0]) * cv_sizx) + cv_mdwn[0]); cv_posy = (((cv_olof[1] - cv_mdwn[1]) * cv_sizy) + cv_mdwn[1]); cv_trgx = ((cv_olmd[0] - cv_mdwn[0]) * cv_sizx) + cv_mdwn[0]; cv_trgy = ((cv_olmd[1] - cv_mdwn[1]) * cv_sizy) + cv_mdwn[1]; } if (iscr) { cv_posx = ((cv_olof[0] - cv_mdwn[0]) * cv_sizx) + cv_mdwn[0]; cv_posy = ((cv_olof[1] - cv_mdwn[1]) * cv_sizy) + cv_mdwn[1]; cv_trgx = ((cv_olmd[0] - cv_mdwn[0]) * cv_sizx) + cv_mdwn[0]; cv_trgy = ((cv_olmd[1] - cv_mdwn[1]) * cv_sizy) + cv_mdwn[1]; } if(ipan) { cv_posx = cv_olof[0] + (cv_moom[0] - cv_mdwn[0]); cv_posy = cv_olof[1] + (cv_moom[1] - cv_mdwn[1]); cv_trgx = cv_olmd[0] + (cv_moom[0] - cv_mdwn[0]); cv_trgy = cv_olmd[1] + (cv_moom[1] - cv_mdwn[1]); } // font ctx.select_font_face("Monospace",Cairo.FontSlant.NORMAL,Cairo.FontWeight.NORMAL); // selection hit if (ipik) { cv_trgx = cv_mdwn[0]; cv_trgy = cv_mdwn[1]; } // margin double mxy = double.min((csx * cv_aszx),(csy * cv_aszy)); double xmarg = mxy * 0.1; double ymarg = mxy * 0.1; double fsx = ((csx * cv_aszx) - (xmarg * 2.0)) - (4 * cv_aszx); double fsy = ((csy * cv_aszy) - (ymarg * 2.0)) - (4 * cv_aszy); double ffsx = (csx - (csx * 0.2)) - 4; double ffsy = (csy - (csy * 0.2)) - 4; cv_posx = double.min(cv_posx,0.0); cv_posx = double.max(cv_posx,(0 - ((csx * cv_aszx) - csx))); cv_posy = double.min(cv_posy,0.0); cv_posy = double.max(cv_posy,(0 - ((csy * cv_aszy) - csy))); // paint bg ctx.set_source_rgba(cv_bgc.rgba.red,cv_bgc.rgba.green,cv_bgc.rgba.blue,1.0); ctx.paint(); // grid double cx_xinc = (fsx / 8.0); double cx_yinc = (fsy / 8.0); ctx.set_line_width(2); double cx_yfmin = cv_posy + ymarg; double cx_xfmax = cv_posx + (fsx + xmarg); double cx_yfmax = cv_posy + (fsy + ymarg); ctx.set_source_rgba(cv_fgc.rgba.red,cv_fgc.rgba.green,cv_fgc.rgba.blue,1.0); for (int i = 0; i <= 8.0; i++) { double cx_px = cv_posx + ((cx_xinc * i) + xmarg); double cx_py = cv_posy + ymarg; ctx.move_to(cx_px, cx_py); ctx.line_to(cx_px, cx_yfmax); ctx.stroke(); cx_px = cv_posx + xmarg; cx_py = cv_posy + ((cx_yinc * i) + ymarg); ctx.move_to(cx_px, cx_py); ctx.line_to(cx_xfmax, cx_py); ctx.stroke(); } // text 1 double cx_fz = 20.0; double cx_fsy = double.max(10.0,(cx_fz * cv_aszy)); double cx_fsx = double.max(10.0,(cx_fz * cv_aszx));; cv_fmx.xx = cx_fsx; cv_fmx.yy = cx_fsy; ctx.set_font_matrix(cv_fmx); ctx.set_source_rgba(cv_txc.rgba.red,cv_txc.rgba.green,cv_txc.rgba.blue,1.0); double cx_mxx = Math.sqrt((cv_fmx.xx * cv_fmx.xx) + (cv_fmx.xy * cv_fmx.xy)); double cx_mzz = Math.sqrt((cv_fmx.yx * cv_fmx.yx) + (cv_fmx.yy * cv_fmx.yy)); ctx.move_to((cv_posx + (cx_xinc * 2) + xmarg),(cv_posy + (cx_yinc * 4) + ymarg)); ctx.show_text("yy %.4f".printf(cv_fmx.yy)); ctx.move_to((cv_posx + (cx_xinc * 2) + xmarg),(cv_posy + (cx_yinc * 4.5) + ymarg)); ctx.show_text("sx %.4f".printf(cx_mxx)); ctx.move_to((cv_posx + (cx_xinc * 2) + xmarg),(cv_posy + (cx_yinc * 5) + ymarg)); ctx.show_text("sy %.4f".printf(cx_mzz)); // wheel-end goes here, since there is no wheel-end signal if (iscr) { iscr = false; cv_ogsz = {cv_aszx,cv_aszy}; cv_olsz = {cv_sizx,cv_sizy}; cv_olof = {cv_posx,cv_posy}; cv_olmd = {cv_trgx,cv_trgy}; } }); } } int main(string[] args) { Gtk.Application myapp = new Gtk.Application("com.mytest.mytest",GLib.ApplicationFlags.DEFAULT_FLAGS); myapp.activate.connect (() => { Gtk.ApplicationWindow mywin = new Gtk.ApplicationWindow(myapp); Gtk.Box drawbox = new Gtk.Box(VERTICAL,0); fontview fv = new fontview(); drawbox.hexpand = true; drawbox.vexpand = true; drawbox.append(fv); mywin.set_child(drawbox); mywin.default_width = 500; mywin.default_height = 500; mywin.present(); fv.redraw(); }); return myapp.run(args); }
CHAR
GETCHAR

Getting indices of unichar characters:

for (int x = 0; x < s.char_count(); x++) { ch = s.get_char(s.index_of_nth_char(x)); }

// test different methods of getting at characters... // by c.p.brown 2024 void main() { GLib.Intl.setlocale(ALL,""); unichar[] removeme = {'零','一','二','三','四','五','六','七','八','九'}; unichar ch; unichar qo = '«'; unichar qc = '»'; // iterate i @ for(), use cached index string s = "零1234五67«八»9零"; int i = 0; bool quoted = false; int64 tts = GLib.get_real_time(); int oldi = 0; for (int x = 0; s.get_next_char(ref i, out ch); x++) { if ((ch == qo) && (!quoted)) { quoted = true; } if ((ch == qc) && (quoted)) { quoted = false; } if ((!quoted) && (ch in removeme)) { s = s.splice(oldi,i,""); i = oldi; } oldi = i; } int64 tte = GLib.get_real_time(); print(s + "\n"); print("took %.2f microseconds\n\n",((double) (tte - tts))); // iterate i last s = "零1234五67«八»9零"; quoted = false; i = 0; int64 ttbs = GLib.get_real_time(); for (int x = 0; x < s.char_count(); x++) { if ((s.get_char(i) == qo) && (!quoted)) { quoted = true; } if ((s.get_char(i) == qc) && (quoted)) { quoted = false; } if ((!quoted) && (s.get_char(i) in removeme)) { s = s.splice(i,(i + s.get_char(i).to_utf8(null)),""); } s.get_next_char(ref i, out ch); } int64 ttbe = GLib.get_real_time(); print(s + "\n"); print("took %.2f microseconds\n\n",((double) (ttbe - ttbs))); // use index_of_nth_char instead of get_next_char s = "零1234五67«八»9零"; quoted = false; i = 0; int64 ttcs = GLib.get_real_time(); for (int x = 0; x < s.char_count(); x++) { i = s.index_of_nth_char(x); if ((s.get_char(i) == qo) && (!quoted)) { quoted = true; } if ((s.get_char(i) == qc) && (quoted)) { quoted = false; } if ((!quoted) && (s.get_char(i) in removeme)) { s = s.splice(i,(i + s.get_char(i).to_utf8(null)),""); } } int64 ttce = GLib.get_real_time(); print(s + "\n"); print("took %.2f microseconds\n\n",((double) (ttce - ttcs))); // use index_of_nth_char with previous index s = "零1234五67«八»9零"; quoted = false; i = 0; int64 ttds = GLib.get_real_time(); int o = 0; for (int x = 0; x < s.char_count(); x++) { i = s.index_of_nth_char(x+1); if ((s.get_char(o) == qo) && (!quoted)) { quoted = true; } if ((s.get_char(o) == qc) && (quoted)) { quoted = false; } if ((!quoted) && (s.get_char(o) in removeme)) { s = s.splice(o,i,""); } o = i; } int64 ttde = GLib.get_real_time(); print(s + "\n"); print("took %.2f microseconds\n\n",((double) (ttde - ttds))); // use index_of_nth_char with previous index and less get_char()s s = "零1234五67«八»9零"; quoted = false; i = 0; int64 ttes = GLib.get_real_time(); int p = 0; for (int x = 0; x < s.char_count(); x++) { unichar uh = s.get_char(p); i = s.index_of_nth_char(x+1); if ((uh == qo) && (!quoted)) { quoted = true; } else { if ((uh == qc) && (quoted)) { quoted = false; } } if ((!quoted) && (uh in removeme)) { s = s.splice(p,i,""); } p = i; } int64 ttee = GLib.get_real_time(); print(s + "\n"); print("took %.2f microseconds\n\n",((double) (ttee - ttes))); string pre = "unicode«善悪»_"; string suffixed = "_" + pre.substring(0,pre.index_of_nth_char(pre.char_count() - 1)); print("convert unicode prefix \"%s\" to suffix \"%s\"\n\n",pre, suffixed); string whs = " "; unichar whc = whs.get_char(0); print("int code for space is %d\n",((int) whc)); print("32 to char is \'%s\'\n",((char) 32).to_string()); print("32 to unichar is \'%s\'\n\n",((unichar) 32).to_string()); whs = "\t"; whc = whs.get_char(0); print("int code for tab is %d\n",((int) whc)); print("9 to char is \'%s\'\n",((char) 9).to_string()); print("9 to unichar is \'%s\'\n\n",((unichar) 9).to_string()); }
#+RESULTS:
123467«八»9 took 3.00 microseconds 123467«八»9 took 3.00 microseconds 123467«八»9 took 3.00 microseconds 123467«八»9 took 2.00 microseconds 123467«八»9 took 1.00 microseconds convert unicode prefix "unicode«善悪»_" to suffix "_unicode«善悪»" int code for space is 32 32 to char is ' ' 32 to unichar is ' ' int code for tab is 9 9 to char is ' ' 9 to unichar is ' '
tests:

// accessing unichar // by c.p.brown 2014 void main() { GLib.Intl.setlocale(ALL,""); string s = "\t«善悪»\n"; print("%s.length is %d\n",s,s.length); print("%s.char_count() is %d\n",s,s.char_count()); print("\n((string) s[i]):\n"); //for (int i = 0; i < s.char_count(); i++) { // print("s[%d] is \"%s\"\n",i,((string) s[i])); //} print("\t...segfault\n"); print("\ns[i].to_string():\n(invalid unicode chars)\n"); //for (int i = 0; i < s.char_count(); i++) { // print("s[%d] is \"%s\"\n",i,s[i].to_string()); //} print("\nget_char:\n(invalid unicode chars)\n"); //for (int i = 0; i < s.char_count(); i++) { // unichar c = s.get_char(i); // print("s.get_char(%d) is \'%u\' %d \"%s\"\n",i,c,((int) c),c.to_string()); //} print("\nget_char(index_of_nth_char()):\n"); for (int i = 0; i < s.char_count(); i++) { int n = s.index_of_nth_char(i); unichar c = s.get_char(n); print("s.get_char(index_of_nth_char(%d)) is \'%u\' %d \"%s\"\n",i,c,((int) c),c.to_string()); } print("\nget_next_char:\n"); unichar ch; int i = 0; int[] idxes = {0}; for (int x = 1; s.get_next_char(ref i, out ch); x++) { print("%d s.get_next_char(ref %d, out [unichar]) is \'%u\' %d \"%s\"\n",x,idxes[x-1],ch,((int) ch),ch.to_string()); idxes += i; } print("\nget_char(get_next_char()) @previous i:\n"); unichar cc; i = 0; idxes = {0}; for (int x = 1; s.get_next_char(ref i, out cc); x++) { unichar c = s.get_char(idxes[x-1]); print("%d s.get_char(%d) \'%u\' %d \"%s\"\n",x,idxes[x-1],c,((int) c),c.to_string()); idxes += i; } }
#+RESULTS:
«善悪» .length is 12 «善悪» .char_count() is 6 ((string) s[i]): ...segfault s[i].to_string(): (invalid unicode chars) get_char: (invalid unicode chars) get_char(index_of_nth_char()): s.get_char(index_of_nth_char(0)) is '9' 9 " " s.get_char(index_of_nth_char(1)) is '171' 171 "«" s.get_char(index_of_nth_char(2)) is '21892' 21892 "善" s.get_char(index_of_nth_char(3)) is '24746' 24746 "悪" s.get_char(index_of_nth_char(4)) is '187' 187 "»" s.get_char(index_of_nth_char(5)) is '10' 10 " " get_next_char: 1 s.get_next_char(ref 0, out [unichar]) is '9' 9 " " 2 s.get_next_char(ref 1, out [unichar]) is '171' 171 "«" 3 s.get_next_char(ref 3, out [unichar]) is '21892' 21892 "善" 4 s.get_next_char(ref 6, out [unichar]) is '24746' 24746 "悪" 5 s.get_next_char(ref 9, out [unichar]) is '187' 187 "»" 6 s.get_next_char(ref 11, out [unichar]) is '10' 10 " " get_char(get_next_char()) @previous i: 1 s.get_char(0) '9' 9 " " 2 s.get_char(1) '171' 171 "«" 3 s.get_char(3) '21892' 21892 "善" 4 s.get_char(6) '24746' 24746 "悪" 5 s.get_char(9) '187' 187 "»" 6 s.get_char(11) '10' 10 " "
GETCHARPACKET
// break string s into array of c items of up to n chars // by c.p.brown 2024 // set c to 0 to fit c to (s.char_count() / n), plus leftovers // dont set n to 0 string printstringarray (string[] s, int f) { // 0 1 2 3 4 5 6 7 8 string[] ii = {"", "\"", "{", "[", "[", "| ", "", "", ""}; string[] dd = {";", ",", ",", " ", ",", " | ", " ", "\n", ",\n"}; string[] oo = {"", "\"", "}", "]", "]", " |", "", "", ""}; string o = ii[f]; for (int i = 0; i < (s.length - 1); i++) { o = (o + "%s".printf(s[i]) + dd[f]); } o = (o + "%s".printf(s[s.length - 1]) + oo[f]); return o; } string[] charpacket (string s, int c, int n) { // c = number of packets // n = max chars per packet // c and n are exclusive, set c to 0 to use n int sc = s.char_count(); string[] pak = new string[c]; if (c == 0) { double sdv = ((double) sc) / ((double) n); int idv = (sc / n); if ((sdv - idv) > 0.0) { pak = new string[(idv + 1)]; } else { pak = new string[idv]; } } for (int i = 0; i < pak.length; i++) { pak[i] = ""; } int p = 0; int v = 0; sc = sc + 1; for (int x = 1; x < sc; x++) { unichar uh = s.get_char(p); pak[v] += uh.to_string(); p = s.index_of_nth_char(x); if ((x % n) == 0) { v += 1; if (v >= pak.length) { break; } } } return pak; } void main() { GLib.Intl.setlocale(ALL,""); string s = "零123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; string[] p = charpacket(s,10,5); print("10 items, 5 chars:\n%s\n",printstringarray(p,2)); p = charpacket(s,4,3); print("4 items, 3 chars:\n%s\n",printstringarray(p,2)); p = charpacket(s,0,6); print("fit items, 6 chars:\n%s\n",printstringarray(p,2)); }
#+RESULTS:
10 items, 5 chars: {零1234,56789,ABCDE,FGHIJ,KLMNO,PQRST,UVWXY,Z,,} 4 items, 3 chars: {零12,345,678,9AB} fit items, 6 chars: {零12345,6789AB,CDEFGH,IJKLMN,OPQRST,UVWXYZ}
COLOR
all of these need tests...
4BITCOLOR

| bits |   read | binary              | range | packed         | store |          colors |
|------+--------+---------------------+-------+----------------+-------+-----------------|
|    2 |    & 3 | 00                  |     4 | 3333     (4K)  | int16 |              64 |
|    4 |    0xF | 0000                |    16 | 15151515 (16M) | int32 |            4096 |
|    8 |   0xFF | 0000 0000           |   256 | (too large)    |       |        16777216 |
|   12 |  0xFFF | 0000 0000 0000      |  4096 | (too large)    |       |     68719476736 |
|   16 | 0xFFFF | 0000 0000 0000 0000 | 65536 | (too large)    |       | 281474976710656 |
#+TBLFM: $4=(2^$1) :: $7=($4*$4*$4)

// pack 3x 2-bit values (0..3) into uint8 // pack 3x 4-bit values (0..15) into uint16 // pack 3x 8-bit values (0..255) into uint32 // by c.p.brown, 2026 string printallmy8bits (uint8 n) { int b = 7; string o = ""; string[] s = {"0","1"}; for (int i = b; i >= 0; i--) { if ((((i+1) % 8) == 0) && (i < b)) { o = o + " "; } o = o + "%s".printf(s[((n >> i) & 1)]); } return o; } string printallmy16bits (uint16 n) { int b = 15; string o = ""; string[] s = {"0","1"}; for (int i = b; i >= 0; i--) { if ((((i+1) % 8) == 0) && (i < b)) { o = o + " "; } o = o + "%s".printf(s[((n >> i) & 1)]); } return o; } string printallmyu32bits (uint n) { int b = 31; string o = ""; string[] s = {"0","1"}; for (int i = b; i >= 0; i--) { if ((((i+1) % 8) == 0) && (i < b)) { o = o + " "; } o = o + "%s".printf(s[((n >> i) & 1)]); } return o; } void main() { print("2-bit\n"); uint8 ggg = 3; uint8 bbb = 3; uint8 rrr = 0; for (int x = 0; x < 4; x++) { uint8 u = (rrr << 4); u += (ggg << 2); u += bbb; print( "%s = {%s %s %s} = %u %u %u\n", printallmyuint8bits(u), printallmyuint8bits(((u >> 4) & 3)), printallmyuint8bits(((u >> 2) & 3)), printallmyuint8bits((u & 3)), ((u >> 4) & 3), ((u >> 2) & 3), (u & 3) ); rrr += 1; bbb -= 1; } print("4-bit\n"); uint8 gg = 15; uint8 bb = 15; uint8 rr = 0; for (int x = 0; x < 16; x++) { uint16 u = (rr << 8); u += (gg << 4); u += bb; uint8 ur = ((u >> 8) & 0xF); uint8 ug = ((u >> 4) & 0xF); uint8 ub = (uint8) (u & 0xF); print( "%s = {%s %s %s} = %u %u %u\n", printallmyuint16bits(u), printallmyuint8bits(ur), printallmyuint8bits(ug), printallmyuint8bits(ub), ((u >> 8) & 0xF), ((u >> 4) & 0xF), (u & 0xF) ); rr += 1; bb -= 1; } print("8-bit\n"); uint8 g = 255; uint8 b = 255; uint8 r = 0; for (int x = 0; x <= 256; x += 8) { uint u = (r << 16); u += (g << 8); u += b; uint8 ur = (uint8) ((u >> 16) & 0xFF); uint8 ug = (uint8) ((u >> 8) & 0xFF); uint8 ub = (uint8) (u & 0xFF); print( "[%03d] %s = {%s %s %s} = %u %u %u\n",x, printallmyuint32bits(u), printallmyuint8bits(ur), printallmyuint8bits(ug), printallmyuint8bits(ub), ((u >> 16) & 0xFF), ((u >> 8) & 0xFF), (u & 0xFF) ); if (x == 0) { r += 7; b -= 7; } else { r += 8; b -= 8; } } }
#+RESULTS:
2-bit 00001111 = {00000000 00000011 00000011} = 0 3 3 00011110 = {00000001 00000011 00000010} = 1 3 2 00101101 = {00000010 00000011 00000001} = 2 3 1 00111100 = {00000011 00000011 00000000} = 3 3 0 4-bit 00000000 11111111 = {00000000 00001111 00001111} = 0 15 15 00000001 11111110 = {00000001 00001111 00001110} = 1 15 14 00000010 11111101 = {00000010 00001111 00001101} = 2 15 13 00000011 11111100 = {00000011 00001111 00001100} = 3 15 12 00000100 11111011 = {00000100 00001111 00001011} = 4 15 11 00000101 11111010 = {00000101 00001111 00001010} = 5 15 10 00000110 11111001 = {00000110 00001111 00001001} = 6 15 9 00000111 11111000 = {00000111 00001111 00001000} = 7 15 8 00001000 11110111 = {00001000 00001111 00000111} = 8 15 7 00001001 11110110 = {00001001 00001111 00000110} = 9 15 6 00001010 11110101 = {00001010 00001111 00000101} = 10 15 5 00001011 11110100 = {00001011 00001111 00000100} = 11 15 4 00001100 11110011 = {00001100 00001111 00000011} = 12 15 3 00001101 11110010 = {00001101 00001111 00000010} = 13 15 2 00001110 11110001 = {00001110 00001111 00000001} = 14 15 1 00001111 11110000 = {00001111 00001111 00000000} = 15 15 0 8-bit [000] 00000000 00000000 11111111 11111111 = {00000000 11111111 11111111} = 0 255 255 [008] 00000000 00000111 11111111 11111000 = {00000111 11111111 11111000} = 7 255 248 [016] 00000000 00001111 11111111 11110000 = {00001111 11111111 11110000} = 15 255 240 [024] 00000000 00010111 11111111 11101000 = {00010111 11111111 11101000} = 23 255 232 [032] 00000000 00011111 11111111 11100000 = {00011111 11111111 11100000} = 31 255 224 [040] 00000000 00100111 11111111 11011000 = {00100111 11111111 11011000} = 39 255 216 [048] 00000000 00101111 11111111 11010000 = {00101111 11111111 11010000} = 47 255 208 [056] 00000000 00110111 11111111 11001000 = {00110111 11111111 11001000} = 55 255 200 [064] 00000000 00111111 11111111 11000000 = {00111111 11111111 11000000} = 63 255 192 [072] 00000000 01000111 11111111 10111000 = {01000111 11111111 10111000} = 71 255 184 [080] 00000000 01001111 11111111 10110000 = {01001111 11111111 10110000} = 79 255 176 [088] 00000000 01010111 11111111 10101000 = {01010111 11111111 10101000} = 87 255 168 [096] 00000000 01011111 11111111 10100000 = {01011111 11111111 10100000} = 95 255 160 [104] 00000000 01100111 11111111 10011000 = {01100111 11111111 10011000} = 103 255 152 [112] 00000000 01101111 11111111 10010000 = {01101111 11111111 10010000} = 111 255 144 [120] 00000000 01110111 11111111 10001000 = {01110111 11111111 10001000} = 119 255 136 [128] 00000000 01111111 11111111 10000000 = {01111111 11111111 10000000} = 127 255 128 [136] 00000000 10000111 11111111 01111000 = {10000111 11111111 01111000} = 135 255 120 [144] 00000000 10001111 11111111 01110000 = {10001111 11111111 01110000} = 143 255 112 [152] 00000000 10010111 11111111 01101000 = {10010111 11111111 01101000} = 151 255 104 [160] 00000000 10011111 11111111 01100000 = {10011111 11111111 01100000} = 159 255 96 [168] 00000000 10100111 11111111 01011000 = {10100111 11111111 01011000} = 167 255 88 [176] 00000000 10101111 11111111 01010000 = {10101111 11111111 01010000} = 175 255 80 [184] 00000000 10110111 11111111 01001000 = {10110111 11111111 01001000} = 183 255 72 [192] 00000000 10111111 11111111 01000000 = {10111111 11111111 01000000} = 191 255 64 [200] 00000000 11000111 11111111 00111000 = {11000111 11111111 00111000} = 199 255 56 [208] 00000000 11001111 11111111 00110000 = {11001111 11111111 00110000} = 207 255 48 [216] 00000000 11010111 11111111 00101000 = {11010111 11111111 00101000} = 215 255 40 [224] 00000000 11011111 11111111 00100000 = {11011111 11111111 00100000} = 223 255 32 [232] 00000000 11100111 11111111 00011000 = {11100111 11111111 00011000} = 231 255 24 [240] 00000000 11101111 11111111 00010000 = {11101111 11111111 00010000} = 239 255 16 [248] 00000000 11110111 11111111 00001000 = {11110111 11111111 00001000} = 247 255 8 [256] 00000000 11111111 11111111 00000000 = {11111111 11111111 00000000} = 255 255 0
[5_DONE]DRGBATODHSVA
double[] drgbatodhsva (double r, double g, double b, double a) { // pack rgba into a single 32-bit integer as hsva // by c.p.brown 2026 // // based on Alvy Ray Smith's HSV specification (1978) // https://alvyray.com/Papers/CG/hsv2rgb.htm // // depends on dmod() modulo function to handle negative numbers double cr = double.max(0.0,double.min(1.0,r)); double cg = double.max(0.0,double.min(1.0,g)); double cb = double.max(0.0,double.min(1.0,b)); double ca = double.max(0.0,double.min(1.0,a)); double h = 0.0; double s = 0.0; double v = 0.0; double mx = double.max(cr,double.max(cg,cb)); double mi = double.min(cr,double.min(cg,cb)); double d = mx - mi; v = mx; if (v == 0.0) { s = 0.0; } else { s = d / mx; } if (mx == mi) { h = 0.0; } else { if (mx == cr) { h = dmod(((1.0 / 6.0) * ((cg - cb) / d)),1.0); } else { if (mx == cg) { h = ((1.0 / 6.0) * (2.0 + ((cb - cr) / d))); } else { h = ((1.0 / 6.0) * (4.0 + ((cr - cg) / d))); } } } h = double.min(double.max(h,0.0),1.0); s = double.min(double.max(s,0.0),1.0); v = double.min(double.max(v,0.0),1.0); a = ca; return {h,s,v,a}; }
[5_DONE]DHSVATODRGBA
double[] dhsvatodrgba (double h, double s, double v, double a) { // convert double h,s,v,a to double[] rgba // by c.p.brown 2026 // // based on the work of Alvy Ray Smith (1978) // https://alvyray.com/Papers/CG/hsv2rgb.htm // // p 1 prints color information // p 2 prints a list of uints to copy for reverse conversion tests double hh = double.max(0.0,double.min(1.0,h)); double ss = double.max(0.0,double.min(1.0,s)); double vv = double.max(0.0,double.min(1.0,v)); double aa = double.max(0.0,double.min(1.0,a)); double rr = vv; double gg = vv; double bb = vv; if (ss > 0.0) { double hd = h * 6.0; int seg = (int) hd; double frac = hd - seg; if ((seg & 1) == 0) { frac = (1.0 - frac); } double xx = vv * (1.0 - ss); double yy = vv * (1.0 - (ss * frac)); if (seg == 0) { rr = vv; gg = yy; bb = xx; } else { if (seg == 1) { rr = yy; gg = vv; bb = xx; } else { if (seg == 2) { rr = xx; gg = vv; bb = yy; } else { if (seg == 3) { rr = xx; gg = yy; bb = vv; } else { if (seg == 4) { rr = yy; gg = xx; bb = vv; } else { if (seg == 5) { rr = vv; gg = xx; bb = yy; } } } } } } } return {rr,gg,bb,aa}; }
[5_DONE]DRGBATOHEX
string drgbatohex (double r, double g, double b, double a) { uint8 rr = ((uint8) ((double.min(double.max(r,0.0),1.0) * 255.0) + 0.5)); uint8 gg = ((uint8) ((double.min(double.max(g,0.0),1.0) * 255.0) + 0.5)); uint8 bb = ((uint8) ((double.min(double.max(b,0.0),1.0) * 255.0) + 0.5)); uint8 aa = ((uint8) ((double.min(double.max(a,0.0),1.0) * 255.0) + 0.5)); StringBuilder sb = new StringBuilder(""); sb.append("#%02X%02X%02X%02X".printf(rr,gg,bb,aa)); return sb.str; }
[5_DONE]DHSVATOIRGBA
uint8[] dhsvatoirgba (double h, double s, double v, double a) { // convert double h,s,v,a to double[] rgba // by c.p.brown 2026 // // based on the work of Alvy Ray Smith (1978) // https://alvyray.com/Papers/CG/hsv2rgb.htm // // p 1 prints color information // p 2 prints a list of uints to copy for reverse conversion tests double hh = double.max(0.0,double.min(1.0,h)); double ss = double.max(0.0,double.min(1.0,s)); double vv = double.max(0.0,double.min(1.0,v)); double aa = double.max(0.0,double.min(1.0,a)); double rr = vv; double gg = vv; double bb = vv; if (ss > 0.0) { double hd = hh * 6.0; int seg = (int) hd; double frac = hd - seg; if ((seg & 1) == 0) { frac = (1.0 - frac); } double xx = vv * (1.0 - ss); double yy = vv * (1.0 - (ss * frac)); if (seg == 0) { rr = vv; gg = yy; bb = xx; } else { if (seg == 1) { rr = yy; gg = vv; bb = xx; } else { if (seg == 2) { rr = xx; gg = vv; bb = yy; } else { if (seg == 3) { rr = xx; gg = yy; bb = vv; } else { if (seg == 4) { rr = yy; gg = xx; bb = vv; } else { if (seg == 5) { rr = vv; gg = xx; bb = yy; } } } } } } } uint8 ir = ((uint8) ((double.min(double.max(rr,0.0),1.0) * 255.0) + 0.5)); uint8 ig = ((uint8) ((double.min(double.max(gg,0.0),1.0) * 255.0) + 0.5)); uint8 ib = ((uint8) ((double.min(double.max(bb,0.0),1.0) * 255.0) + 0.5)); uint8 ia = ((uint8) ((aa * 255.0) + 0.5)); return {ir,ig,ib,ia}; }
[5_DONE]DRGBATOIRGBA
uint8[] drgbatoirgba (double r, double g, double b, double a) { uint8 ir = ((uint8) ((double.min(double.max(r,0.0),1.0) * 255.0) + 0.5)); uint8 ig = ((uint8) ((double.min(double.max(g,0.0),1.0) * 255.0) + 0.5)); uint8 ib = ((uint8) ((double.min(double.max(b,0.0),1.0) * 255.0) + 0.5)); uint8 ia = ((uint8) ((double.min(double.max(a,0.0),1.0) * 255.0) + 0.5)); return {ir,ig,ib,ia}; }
[5_DONE]iRGBATOHEX
string irgbatohex (uint8 r, uint8 g, uint8 b, uint8 a) { StringBuilder sb = new StringBuilder(""); sb.append("#%02X%02X%02X%02X".printf(r,g,b,a)); return sb.str; }
[5_DONE]HEXTODRGBA
double[] hextodrgba (string hex) { // read colors from hex, // removes leading hash, ensures hex string is 8 characters // by c.p.brown 2026 StringBuilder sb = new StringBuilder(""); sb.append(hex); if (sb.str.get_char(sb.str.index_of_nth_char(0)) == '#') { sb.replace("#","",1); } if (sb.str.char_count() > 8) { sb.str = sb.str.substring(0,8); } while (sb.str.char_count() < 8) { sb.append("0"); } uint v = uint.parse(sb.str,16); double r = ((double) ((v >> 24) & 0xFF)) / 255.0; double g = ((double) ((v >> 16) & 0xFF)) / 255.0; double b = ((double) ((v >> 8) & 0xFF)) / 255.0; double a = ((double) (v & 0xFF)) / 255.0; return {r,g,b,a}; }
[5_DONE]HEXTOIRGBA
uint8[] hextoirgba (string hex) { // read colors from hex, // removes leading hash, ensures hex string is 8 characters // by c.p.brown 2026 StringBuilder sb = new StringBuilder(""); sb.append(hex); if (sb.str.get_char(sb.str.index_of_nth_char(0)) == '#') { sb.replace("#","",1); } if (sb.str.char_count() > 8) { sb.str = sb.str.substring(0,8); } while (sb.str.char_count() < 8) { sb.append("0"); } uint v = uint.parse(sb.str,16); uint8 r = (uint8) ((v >> 24) & 0xFF); uint8 g = (uint8) ((v >> 16) & 0xFF); uint8 b = (uint8) ((v >> 8) & 0xFF); uint8 a = (uint8) (v & 0xFF); return {r,g,b,a}; }
DATETIME
CHECKDATETIME

check valid iso dates
"yyyy-mm-ddThh:mm:ss+hh:mm"
"yyyymmdd hhmmss+hhmm"

where:
  • T is optional, but must be replaced with a space
  • year must be 4 digits
  • other values must be 2 digits
  • - and : are optional and can be removed
  • + is not optional if an offset is specified
  • the offset can be removed
  • the offset can be replaced with Z for UTC

void main() { TimeZone tz = new TimeZone.local(); string[] isos = { "2026-03-01T10:30:00+09:30", "2026-03-01 10:30:00-09:30", "2026-03-01 10:30:00 09:30", "2026 03 01 10 30 00 09 30", "20260301 10:30:00+09:30", "2026-03-01 103000+0930", "2026-03-01T10:30:00+9:30", "2026-3-01T10:30:00+09:30", "20260301T103000+0930", "20260301103000+0930", "20260301T1030000930", "202603011030000930", "20260301 103000+0930", "202631T1030+0930", "260301T1030+0930", "2026-03-01T10:30:00", "20260301 103000", "2026-03-01T10:30:00Z", "2026-03-01T10:30:00UTC", "2026-03-01" }; foreach (string iso in isos) { DateTime mm = new DateTime.from_iso8601(iso,tz); if (mm != null) { print("[X] %s is valid: %d, %d, %d, %d, %d, %d, %s\n",iso,mm.get_year(),mm.get_month(),mm.get_day_of_month(),mm.get_hour(),mm.get_minute(),mm.get_second(),(mm.get_timezone().get_identifier())); } else { print("[ ] %s is not valid\n",iso); } } }
#+RESULTS:
[X] 2026-03-01T10:30:00+09:30 is valid: 2026, 3, 1, 10, 30, 0, +09:30 [X] 2026-03-01 10:30:00-09:30 is valid: 2026, 3, 1, 10, 30, 0, -09:30 [ ] 2026-03-01 10:30:00 09:30 is not valid [ ] 2026 03 01 10 30 00 09 30 is not valid [X] 20260301 10:30:00+09:30 is valid: 2026, 3, 1, 10, 30, 0, +09:30 [X] 2026-03-01 103000+0930 is valid: 2026, 3, 1, 10, 30, 0, +0930 [ ] 2026-03-01T10:30:00+9:30 is not valid [ ] 2026-3-01T10:30:00+09:30 is not valid [X] 20260301T103000+0930 is valid: 2026, 3, 1, 10, 30, 0, +0930 [ ] 20260301103000+0930 is not valid [ ] 20260301T1030000930 is not valid [ ] 202603011030000930 is not valid [X] 20260301 103000+0930 is valid: 2026, 3, 1, 10, 30, 0, +0930 [ ] 202631T1030+0930 is not valid [ ] 260301T1030+0930 is not valid [X] 2026-03-01T10:30:00 is valid: 2026, 3, 1, 10, 30, 0, Australia/Adelaide [X] 20260301 103000 is valid: 2026, 3, 1, 10, 30, 0, Australia/Adelaide [X] 2026-03-01T10:30:00Z is valid: 2026, 3, 1, 10, 30, 0, UTC [ ] 2026-03-01T10:30:00UTC is not valid [ ] 2026-03-01 is not valid
DATEDIF

GLib.Date tests

void main() { Date n = new Date(); n.set_time_t(time_t()); print("now is %d-%d-%d\n",(int) n.get_year(), n.get_month(), (int) n.get_day()); Date t = new Date(); t.set_dmy((DateDay) 15, 7, (DateYear) 2026); print("then is %d-%d-%d\n",(int) t.get_year(), t.get_month(), (int) t.get_day()); print("difference between now and then is %d days\n",n.days_between(t)); Date a = new Date(); a.set_dmy((DateDay) 16, 5, (DateYear) 2026); int dur = 60; Date b = a.copy(); b.add_days((uint) dur); print("\n%d days from %d-%d-%d is %d-%d-%d\n",dur,(int) a.get_year(), a.get_month(), (int) a.get_day(), (int) b.get_year(), b.get_month(), (int) b.get_day()); }
#+RESULTS:
Compilation succeeded - 3 warning(s) now is 2026-5-18 then is 2026-7-15 difference between now and then is 58 days 60 days from 2026-5-16 is 2026-7-15
DAYCOUNT

Count nth days per month.
Takes a month list, from-day per month, nth-day from from-day.
Can span years.
Handles leap-years correctly.
Ignores invalid input.

Options:
  • from-day + nth-day
  • from-day + nth-weekday
  • from-day + nth-workday-on-or-before-day
  • from-day + nth-workday-on-or-after-day
  • from-day + nth-workday-closest-to-day

int lymd (int m, int y) { // get last day of month, replace feb 28 with 29 if leap-year if (m == 2) { if ((y % 100) == 0) { if ((y % 400) == 0) { return 29; } } else { if ((y % 4) == 0) { return 29; } } return 28; } else { int[] lastdays = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; return lastdays[m]; } return -1; } string printintarray (int[] s, int o, int b, int f) { if (s.length == 0) { return "(empty array)"; } string[] ii = {"", "\"", "{", "[", "[", "| ", "", ""}; string[] dd = {";", ",", ",", " ", ",", " | ", " ", "\n"}; string[] oo = {"", "\"", "}", "]", "]", " |", "", ""}; string oa = ii[f]; for (int i = o; i < (s.length - 1); i += b) { oa = (oa + "%d".printf(s[i]) + dd[f]); } oa = (oa + "%d".printf(s[s.length - 1]) + oo[f]); return oa; } string whiggle (int n, int p, int e) { // n = number // p = pad width // e = use "single" instead of 1st, eg: every single day, instead of every 1st day if ((e == 1) && (n == 1)) { return "single"; } int l = n % 10; if (l == 0) { return "%0*dth".printf(p,n); } int ll = n % 100; if ((ll > 10) && (ll < 20)) { return "%0*dth".printf(p,n); } if (l < 4) { string[] w = {"th","st","nd","rd"}; return "%0*d%s".printf(p,n,w[l]); } return "%0*dth".printf(p,n); } int[] countyears (int nthyear, int fromyear, int thisyear, int lastyear) { int[] yearindices = {}; int yy = fromyear; if ((fromyear > 1989) && (nthyear > 0) && (lastyear >= thisyear)) { while (yy <= lastyear) { yearindices += yy; yy += nthyear; } } return yearindices; } int[] countmonths (int[] yearindices, int thisyear, int nthmonth, int frommonth) { int[] monthandyears = {}; int mm = frommonth - 1; // -1 for modulo int y = 0; int x = 0; if ((thisyear > 2020) && (nthmonth > 0) && (yearindices.length > 0)) { while (y < yearindices.length) { if (x > 100) { break; } int cm = ((mm % 12) + 1); monthandyears += cm; monthandyears += yearindices[y]; int nm = (((cm + nthmonth) % 12) + 1); if (nm < cm) { y += 1; } mm += nthmonth; x += 1; } } return monthandyears; } int getdayoffsetofweekday(int d, int f, int w, int i, int m, int y) { GLib.Date j = Date(); int fd = int.max(d,f); j.set_dmy((DateDay) fd, m,(DateYear) y); int jw = (int) j.get_weekday(); int dayoffset = (w - jw); int nth = i; if (dayoffset == 0) { dayoffset = fd; } else { if (dayoffset < 0) { dayoffset = (fd + dayoffset); } else { dayoffset = ((fd + dayoffset) - (nth - 7)); } } return dayoffset; } void forecast (int[] monthindices, int[] dayspermonth, int nthday, int fromday, int weekd, string[] lomo) { int md = int.max(fromday,1); int nth = nthday; int[,] wwkd = {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,-1,-2},{0,0,0,0,0,0,2,1},{0,0,0,0,0,0,-1,1}}; for (int mo = 0; mo < monthindices.length; mo += 2) { int c = 0; if (monthindices[mo] == 2) { dayspermonth[monthindices[mo]] = lymd(monthindices[mo],monthindices[mo+1]); } if ((weekd > 0) && (weekd < 8)) { nth = nthday * 7; md = getdayoffsetofweekday(md, fromday, weekd, nth, monthindices[mo], monthindices[mo+1]); } print("[%02d] month %02d (%02d days) + offset %02d : \n",mo,monthindices[mo],dayspermonth[monthindices[mo]],md); while (md < dayspermonth[monthindices[mo]]) { if (c > 100) { print("while %d < %d broke loose...\n",md,dayspermonth[monthindices[mo]]); break; } if (weekd > 7) { GLib.Date w = new GLib.Date(); w.set_dmy(((DateDay) md),((DateMonth) monthindices[mo]), ((DateYear) monthindices[mo+1])); w.add_days(nth); int nwd = w.get_weekday(); if (nwd > 5) { int nwe = int.max(0,(weekd - 7)); nth = nthday + wwkd[nwe,nwd]; } } if ((md + nth) < dayspermonth[monthindices[mo]]) { md += nthday; print("\t%s of %s, %d\n",whiggle(md,2,0),lomo[monthindices[mo]],monthindices[mo+1]); } else { md = fromday; break; } c += 1; } print("\n"); } } void main() { int[] lastdmy = {19,8,2029}; int[] dayspermonth = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int[] monthindices = {}; int[] yearindices = {}; int[] monthyears = {}; int fromday = 4; int nthday = 7; int frommonth = 8; int nthmonth = 3; int fromyear = 2025; int nthyear = 2; GLib.DateTime nt = new DateTime.now_local(); int thisyear = nt.get_year(); int lastyear = 2029; string[] lomo = {"null","January","February","March","April","May","June","July","August","September","October","December"}; print("\nevery 4th day from the 5th of every 3rd month from august, of every 2nd year from 2025:\n"); int weekd = 0; yearindices = countyears(nthyear,fromyear,thisyear,lastyear); print("collected years: %s\n",printintarray(yearindices,0,1,2)); monthindices = countmonths (yearindices, thisyear, nthmonth, frommonth); print("collected months: %s\n",printintarray(monthindices,0,2,2)); print("collected month-years: %s\n",printintarray(monthindices,1,2,2)); forecast(monthindices, dayspermonth, nthday, fromday, weekd, lomo); print("\nevery workday on or before the 5th of every 3rd month from august, of every 2nd year from 2025:\n"); nthday = 5; fromday = 0; weekd = 8; // 8 is on or before, 9 is on or after, 10 is closest to yearindices = countyears(nthyear,fromyear,thisyear,lastyear); print("collected years: %s\n",printintarray(yearindices,0,1,2)); monthindices = countmonths (yearindices, thisyear, nthmonth, frommonth); print("collected months: %s\n",printintarray(monthindices,0,2,2)); print("collected month-years: %s\n",printintarray(monthindices,1,2,2)); forecast(monthindices, dayspermonth, nthday, fromday, weekd, lomo); }
#+RESULTS:
Compilation succeeded - 4 warning(s) every 4th day from the 5th of every 3rd month from august, of every 2nd year from 2025: collected years: {2025,2027,2029} collected months: {8,11,2,5,8,11,2,5,8,11,2029} collected month-years: {2025,2025,2027,2027,2027,2027,2029,2029,2029,2029} [00] month 08 (31 days) + offset 04 : 11th of August, 2025 18th of August, 2025 25th of August, 2025 [02] month 11 (30 days) + offset 04 : 11th of December, 2025 18th of December, 2025 25th of December, 2025 [04] month 02 (28 days) + offset 04 : 11th of February, 2027 18th of February, 2027 25th of February, 2027 [06] month 05 (31 days) + offset 04 : 11th of May, 2027 18th of May, 2027 25th of May, 2027 [08] month 08 (31 days) + offset 04 : 11th of August, 2027 18th of August, 2027 25th of August, 2027 [10] month 11 (30 days) + offset 04 : 11th of December, 2027 18th of December, 2027 25th of December, 2027 [12] month 02 (28 days) + offset 04 : 11th of February, 2029 18th of February, 2029 25th of February, 2029 [14] month 05 (31 days) + offset 04 : 11th of May, 2029 18th of May, 2029 25th of May, 2029 [16] month 08 (31 days) + offset 04 : 11th of August, 2029 18th of August, 2029 25th of August, 2029 [18] month 11 (30 days) + offset 04 : 11th of December, 2029 18th of December, 2029 25th of December, 2029 every workday on or before the 5th of every 3rd month from august, of every 2nd year from 2025: collected years: {2025,2027,2029} collected months: {8,11,2,5,8,11,2,5,8,11,2029} collected month-years: {2025,2025,2027,2027,2027,2027,2029,2029,2029,2029} [00] month 08 (31 days) + offset 01 : 06th of August, 2025 11th of August, 2025 16th of August, 2025 21st of August, 2025 26th of August, 2025 31st of August, 2025 [02] month 11 (30 days) + offset 31 : [04] month 02 (28 days) + offset 31 : [06] month 05 (31 days) + offset 31 : [08] month 08 (31 days) + offset 31 : [10] month 11 (30 days) + offset 31 : [12] month 02 (28 days) + offset 31 : [14] month 05 (31 days) + offset 31 : [16] month 08 (31 days) + offset 31 : [18] month 11 (30 days) + offset 31 :
FORECAST

Complex recurrence, revisited.

This revision intends to cover the following scenarios not handled previously:
  • Every nth day (or weekday) of a single month.
  • Every nth and nth day in alternation, either per-month or absolute, eg:
    • The 2nd and 3rd day of March (2,3).
    • The 2nd and 3rd day of March, from the 5th (7,8).
    • Every 2nd then 3rd day of March (2,5,7,10,12,15,17,20,22,25,27,30).
    • Every 2nd then 5th day of March, from the 10th (12,17,19,24,26).
    • The 2nd and 3rd Tuesday of March 2025 (11,18).
    • The 2nd and 3rd Tuesday of April 2025, from the 12th (22,29).
    • Every 2nd then 3rd Tuesday of April 2025 (8,29).
    • Every 90 and 91 days from July 1st 2025.
  • Every nth and nth month in alternation, eg:
    • The 2nd and 10th month of every year (2,10).
    • The 2nd and 5th month, from the 2nd month, of every year (4,7).
    • Every 2nd then 3rd month of every year (2,5,7,10,12).
    • Every 2nd then 3rd month, from the 3rd month, of every year (5,8,10).
    • Every 4th month from March 2025.
  • Every nth year.

// build complex recurrance rules using english // by c.p.brown, 2025 // // 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 // {01,10,00,08,00,00, 00,00,00,00,00,11, 00,00,00,2025} // | | | | | | // +---------------+ +---------------+ +-----------+ // every|the of|of every of|of every // nth nth nth // then nth then nth this|year // day|weekd this|month from now|from year // of the month| of the year| // (day count) (month count) // from now|from day from now|from month // // TODO: // - return a Date[] of two dates: recurring-date and offset-date, // to report workday dates without affecting the recurrance // - resolve ambiguity: // "every nth day from the nth day of [month] from [none ] ..." // "every nth day from the nth day of [none ] from [month] ..." int imod (int l, int r) { if (l >= 0) { return (l % r); } if (l >= -r) { return (l + r); } return ((l % r) + r) % r; } double dmod (double l, double r) { if (l >= 0) { return (l % r); } if (l >= -r) { return (l + r); } return ((l % r) + r) % r; } bool compareintarrays (int[] a, int[] b) { if (a.length == b.length) { for (int i = 0; i < a.length; i++) { if (a[i] != b[i]) { return false; } } return true; } return false; } bool isly(int y) { // (year % 100 == 0) checks if the year is at the beginning of a century // (year % 400 == 0) checks if the above, if true, is every 400th year, which is a leap-year // (year % 4 == 0) otherwise, this checks if its every 4th year, which is a leap-year if ((y % 100) == 0 ) { return ((y % 400) == 0); } return ((y % 4) == 0); } int iwkd (DateWeekday wd) { if (wd == MONDAY) { return 1; } if (wd == TUESDAY) { return 2; } if (wd == WEDNESDAY) { return 3; } if (wd == THURSDAY) { return 4; } if (wd == FRIDAY) { return 5; } if (wd == SATURDAY) { return 6; } if (wd == SUNDAY) { return 7; } if (wd == BAD_WEEKDAY) { return 0; } return 0; } string printintarray (int[] s, int f) { if (s.length == 0) { return "(empty array)"; } string[] ii = {"", "\"", "{", "[", "[", "| ", "", ""}; string[] dd = {";", ",", ",", " ", ",", " | ", " ", "\n"}; string[] oo = {"", "\"", "}", "]", "]", " |", "", ""}; string o = ii[f]; for (int i = 0; i < (s.length - 1); i++) { o = (o + "%d".printf(s[i]) + dd[f]); } o = (o + "%d".printf(s[s.length - 1]) + oo[f]); return o; } int lymd (int m, int y) { // get last day of month, replace feb 28 with 29 if leap-year if (m == 2) { if ((y % 100) == 0) { if ((y % 400) == 0) { return 29; } } else { if ((y % 4) == 0) { return 29; } } return 28; } else { int[] lastdays = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; return lastdays[m]; } return -1; } string whiggle (int n, int p, int e) { // n = number // p = pad width // e = use "single" instead of 1st, eg: every single day, instead of every 1st day if ((e == 1) && (n == 1)) { return "single"; } int l = n % 10; if (l == 0) { return "%0*dth".printf(p,n); } int ll = n % 100; if ((ll > 10) && (ll < 20)) { return "%0*dth".printf(p,n); } if (l < 4) { string[] w = {"th","st","nd","rd"}; return "%0*d%s".printf(p,n,w[l]); } return "%0*dth".printf(p,n); } int getdayoffsetofweekday(int ind, int d, int f, int w, int i, int m, int y) { string tabs = ("%*s").printf(ind," ").replace(" ","\t"); int nind = ind + 1; GLib.Date j = Date(); int fd = int.max(d,f); //if (fd == 0) { fd = 1; } print("%sgetdayoffsetofweekday fromday is %d max(previouisday %d,fromday %d)\n",tabs,fd,d,f); j.set_dmy((DateDay) fd, m,(DateYear) y); int jw = (int) j.get_weekday(); int dayoffset = (w - jw); print("%sgetdayoffsetofweekday weekday of %d-%d-%d is %d\n",tabs,y,m,fd,jw); print("%sgetdayoffsetofweekday weekday offset is %d\n",tabs,dayoffset); int nth = i; //print("getdayoffsetofweekday interval is %d\n",nth); //if (fd > d) { fd = f; } if (dayoffset == 0) { dayoffset = fd; } else { //dayoffset += 1; if (dayoffset < 0) { dayoffset = (fd + dayoffset); } else { dayoffset = ((fd + dayoffset) - (nth - 7)); } } print("%sgetdayoffsetofweekday returnts %d\n",tabs,dayoffset); return dayoffset; } Date adddayspermonth (int ind, ref int q, int dd, int mm, int yy, int n, int an, int df, int m, anm, int fd, int int fm, wd, bool wkd, bool om, bool oy) { string tabs = ("%*s").printf(ind," ").replace(" ","\t"); int nind = ind + 1; print("%s[%d] adddayspermonth day is %d, nth is %d, fromday is %d, weekday is %d, month is %d, year is %d\n",tabs,q,dd,n,fd,wd,mm,yy); GLib.Date nd = Date(); nd.set_dmy((DateDay) 1, 1, (DateYear) 1989); int[,] wwkd = {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,-1,-2},{0,0,0,0,0,0,2,1},{0,0,0,0,0,0,-1,1}}; // alternate nth and andnth int nth = n; int mth = m; if (an > 0) { if ((q & 1) != 0) { nth = an; print("%s[%d] adddayspermonth nth is now %d\n",tabs,q,nth); } } if (anm > 0) { if ((q & 1) != 0) { mth = anm; print("%s[%d] adddayspermonth mth is now %d\n",tabs,q,mth); } } if (wkd) { nth = nth * 7; print("%s[%d] adddayspermonth nth is now %d\n",tabs,q,nth); } // initialize date with incoming (previous) date GLib.Date j = new GLib.Date(); j.set_dmy((DateDay) dd, mm, (DateYear) yy); int dayoffset = -1; // set a day-offset if day is less than fromday if (fd > 0) { dayoffset = int.max((fd - 1),0); // determine offset if calculating nth weekday if (wkd) { dayoffset = getdayoffsetofweekday(nind, dd, fd, wd, nth, mm, yy); } if (wd > 7) { // get work-weekday on-or-before (dayoffset + nth) GLib.Date w = new GLib.Date(); w.set_dmy(j.get_day(), j.get_month(), j.get_year()); w.add_days(nth); int nwd = w.get_weekday(); print("%s[%d] adddayspermonth %d-%d-%d weekday is %d \n",tabs,q,((int) w.get_year()),((int) w.get_month()),((int) w.get_day()),nwd); if (nwd > 5) { int nwe = int.max(0,(wd - 7)); nth = nth + wwkd[nwe,nwd]; } } // offset date with date + n days + dayoffset print("%s[%d] adddayspermonth dayoffset is %d, nth is %d, dayoffset + nth is %d\n",tabs,q,dayoffset,nth,(dayoffset + nth)); if ((dayoffset + nth) > lymd(mm,yy)) { // the next day exceeds days per month... // bail if limited to one month if (om) { return nd; } // bail if limited to one year and current month is december if ((mm == 12) && oy) { return nd; } if (mth > 0) { if ((mm + mth) > 12) { if (oy) { return nd; } } } else { mth = 1; } j.add_months(mth); mm = (int) j.get_month(); } j.set_day((DateDay) (dayoffset + nth)); print("%s[%d] adddayspermonth day is now %d\n",tabs,q,((int) j.get_day())); } else { // or offset with date + n day if (om) { if ((dayoffset + nth) > lymd(mm,yy)) { return nd; } } j.add_days(dayoffset + nth); } print("%s[%d] adddayspermonth day is now %d\n",tabs,q,((int) j.get_day())); print("%s[%d] adddayspermonth returning %d-%d-%d\n",tabs,q,((int) j.get_year()),((int) j.get_month()),((int) j.get_day())); return j; } Date adddaysperyear (int ind, int dd, int mm, int yy, int n, bool oy) { string tabs = ("%*s").printf(ind," ").replace(" ","\t"); int nind = ind + 1; GLib.Date j = new GLib.Date(); j.set_dmy((DateDay) dd, mm, (DateYear) yy); j.add_days(n); int nm = (int) j.get_month(); if (nm < mm) { if (!oy) { j.set_month(1); j.set_day((DateDay) 1); j.add_days(n - 1); } else { GLib.Date nd = Date(); nd.set_dmy((DateDay) 1, 1, (DateYear) 1989); return nd; } } return j; } Date getnextdate(int ind, Date s, Date n, Date b, int[] r, ref int q) { string tabs = ("%*s").printf(ind," ").replace(" ","\t"); int nind = ind + 1; int[] predictions = {}; GLib.Date a = Date(); a.set_dmy((DateDay) s.get_day(), s.get_month(), (DateYear) s.get_year()); GLib.Date nd = Date(); nd.set_dmy((DateDay) 1, 1, (DateYear) 1989); int nty = (int) n.get_year(); int ntm = (int) n.get_month(); int ntd = (int) n.get_day(); int dd = (int) a.get_day(); int mm = (int) a.get_month(); int yy = (int) a.get_year(); int ld = (int) b.get_day(); int lm = (int) b.get_month(); int ly = (int) b.get_year(); // 00 whatday..... : the, every // 01 nthday...... : 1st, 2nd, 3rd, etc // 02 andnthday... : "", and 2nd, and 3rd, and 4th, etc. (when used with 'every', it alternates) // 03 weekday..... : day, monday, tuesday, wednesday, thursday, friday, saturday, sunday, weekday on or before the, weekday on or after the, weekday closest to the // 04 dayof ...... : of the month, "" // 05 fromday..... : "", from the 1st day, from the 2nd day, from the 3rd day, ... from the last day // 06 whatmonth... : of, of every // 07 nthmonth.... : "", 1st, 2nd, 3rd, etc. // 08 andnthmonth. : "", and 1st, and 2nd, and 3rd, etc. // 09 themonth.... : "", january, february, march, etc. // 10 monthof .... : "of the year", "" // 11 frommonth... : "", from january, from february, from march, etc. // 12 whatyear.... : of, of every // 13 nthyear..... : "", year, 2nd year, 3rd year, etc. // 14 theyear..... : "", 1990 ... 2026 // 15 fromyear.... : "", 1990 ... 2026 string[] lomo = {"null","January","February","March","April","May","June","July","August","September","October","December"}; string[] lowd = {"null","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"}; int[,] wwkd = {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,-1,-2},{0,0,0,0,0,0,2,1},{0,0,0,0,0,0,-1,1}}; int whatday = r[0]; // "the" or "every" int nthday = r[1]; int andnthday = r[2]; int weekd = r[3]; int ofthemonth = r[4]; // "of the month", "" int fromday = r[5]; // "from the" int whatmonth = r[6]; // "of the" or "of every" int nthmonth = r[7]; int andnthmonth = r[8]; int themonth = r[9]; int monthof = r[10]; // "of the year" int frommonth = r[11]; // "from the" int whatyear = r[12]; // "of the" or "of every" int nthyear = r[13]; int theyear = r[14]; // "from" int fromyear = int.max(1990,r[15]); if (r[13] == 0) { fromyear = nty; } //fromyear = fromyear - 1990; //print("fromyear is %d, at index %d\n",fromyear,(fromyear - 1990)); // offsets are used at the begining of each month/year if we're counting per month/year // otherwise they are used to set an initial start date if we're day counting from a start date int dayoffset = 0; int monthoffset = 0; int yearoffset = 0; int[] dayintervals = {1,0}; int[] monthintervals = {1,0}; int yearinterval = 1; // if true, the following determine if we need to recalculate offsets per year/month bool countpermonth = false; bool countperyear = false; if (whatyear == 1) { countperyear = true; } if ((nthmonth > 0) || (whatmonth == 1)) { countpermonth = true; } // toggles to help determine forecast type bool oneday = false; // a single day of a month, or two via 'andnth' bool onemonth = false; // limit to a specific month, or two via 'andnthmonth' bool oneyear = false; // limit to a specific year bool isweekday = ((weekd > 0) && (weekd < 8)); // find day of weekday // type of forecast to run, from least to most complex bool onedate = false; // find a single one-off date bool daycounting = false; // count every n days, don't reset each month/year bool daycountingpereverymonth = false; // count every n days per every month bool daycountingpernthyear = false; // count every n days per nth year bool daycountingpernthmontheveryyear = false; // count every n days per n months every year bool daycountingpernthmonthpernthyear = false; // count every n days per n months per n year // determine forecast type... if ( (nthday > 0) && // every nth day (n) (ofthemonth == 0) && (fromday > 0) && // from a specific day (d) (whatmonth == 0) && // of a specific month (m) (whatyear == 0) // of a specific year (y) ) { daycounting = true; // simple date.add_days(n) from dmy } if ( (nthday > 0) && // every nth day (n) (ofthemonth == 1) && // of the month (fromday > 0) && // from a specific day (d) (whatmonth == 0) && // of a specific month (m) (whatyear == 0) // of a specific year (y) ) { daycountingpermonth = true; // date.add_days(n) from dmy, per month } // m | 1 | 1 | 2 | 3 | // md | 5 | 3 | 4 | 5 | md[] // a | 01 02 03 04 05 | 06 07 08 | 09 10 11 12 | 13 14 15 16 17 | // d | 01 02 03 04 05 | 01 02 03 | 01 02 03 04 | 01 02 03 04 05 | // i | ^ : | ^ | ^ : | ^ : | i = 2 // i+n | ^ | | ^ | ^ | n = 2 // // d = a % md[m], where if a % md[m] == 0 m += 1 if ( (nthday > 0) && // every nth day (whatmonth > 0) && // of every (month) (whatyear == 0) // of a specific year ) { daycountingpermonth = true; // count nth days of each month(s), regardless of year } if (whatyear == 0) { nthyear = 0; fromyear = 0; oneyear = true; } if ((whatmonth == 0) && oneyear) { onemonth = true; } if ((whatmonth == 0) && (nthmonth == 0)) { frommonth = 0; } if ((whatday == 0) && (nthday == 0)) { fromday = 0; } if ((whatday == 0) && onemonth) { oneday = true; } if ((whatmonth > 0) && (nthmonth == 0)) { nthmonth = 1; } if (oneday && onemonth && oneyear) { if (q > 0) { return nd; } if (theyear < 1990) { a.set_year((DateYear) nty); yy = (int) a.get_year(); } else { a.set_year((DateYear) theyear); yy = (int) a.get_year(); } yy = (int) a.get_year(); if (themonth < 1) { a.set_month(ntm); mm = (int) a.get_month(); } else { a.set_month(themonth); mm = (int) a.get_month(); } if (nthday == 0) { a.set_day((DateDay) int.min(ntd,lymd(mm,yy))); dd = (int) a.get_day(); } else { //print("getnextdate (single date) nth is %d, fromday is %d\n",nthday,fromday); int nth = nthday; dayoffset = int.max((fromday - 1),0); if ((q & 1) != 0) { nth = andnthday; } if (weekd > 0) { nth = nthday * 7; //print("getnextdate (single date) nthday is %d, weekday is %d, fromday is %d, month is %d, year is %d, calculating offset...\n",nthday,weekd,fromday, mm, yy); dayoffset = getdayoffsetofweekday(nind,dd, fromday, weekd, nth, mm, yy); //print("getnextdate (single date) dayoffset is %d, + nth %d * 7 (%d) days is %d\n",dayoffset,nthday,nth,(dayoffset + nth)); } a.set_day((DateDay) (dayoffset + nth)); dd = (int) a.get_day(); if ((dayoffset + nth) > lymd(mm,yy)) { print("%sgetnextdate (single date) returns out-of-range date\n",tabs); return nd; } } // return an invalid date, checked in the calling code and not collected. print("%sgetnextdate (single date) returns %d-%d-%d\n",tabs,yy,mm,dd); return a; } // daycounting... if (daycounting || daycountingpermonth || daycountingperyear) { int nth = nthday; if (andnthday > 0) { if ((q & 1) != 0) { nth = andnthday; } } if (nth == 0) { nth = 1; } if ((weekd > 0) && (weekd < 8)) { nth = nth * 7; } // get initial offset if (q == 0) { if (fromday > lymd(mm,yy)) { return nd; } if (theyear > 0) { a.set_year((DateYear) theyear); } if (themonth > 0) { a.set_month(themonth); } if ((whatmonth == 0) && (fromday > 0) && (nth > 0)) { fromday = 0; } print("%s[%d] getnextdate (daycounter) initial date is %d-%d-%d\n",tabs,q,((int) a.get_year()),((int) a.get_month()),((int) a.get_day())); } // get workweekday if (weekd > 7) { GLib.Date j = new GLib.Date(); j.set_dmy((DateDay) dd, mm, (DateYear) yy); j.add_days(nth); int nwd = j.get_weekday(); print("%s[%d] getnextdate (daycounter) %d-%d-%d weekday is %d \n",tabs,q,((int) j.get_year()),((int) j.get_month()),((int) j.get_day()),nwd); if (nwd > 5) { int nwe = int.max(0,(weekd - 7)); nth = nth + wwkd[nwe,nwd]; } } // add days... if (daycountingperyear) { print("%s[%d] getnextdate (daycounter) daycountingperyear...\n",tabs,q); a = adddaysperyear(nind,dd,mm,yy,nthday,oneyear); } else { if (daycountingpermonth) { print("%s[%d] getnextdate (daycounter) daycountingpermonth...\n",tabs,q); a = adddayspermonth(nind,ref q,dd,mm,yy,nthday,andnthday,dayof,nthmonth,andnthmonth,fromday,frommonth,weekd,isweekday,onemonth,oneyear); } else { a.add_days(nth); } } dd = (int) a.get_day(); mm = (int) a.get_month(); yy = (int) a.get_year(); print("%s[%d] getnextdate (daycounter) returns %d-%d-%d\n",tabs,q,yy,mm,dd); return a; } else { // determine if a specific month is specified if (whatmonth == 0) { if (nthmonth != 0) { if (andnthmonth == 0) { frommonth = 0; onemonth = true; } } else { frommonth = 0; onemonth = true; } } // determine if a specific year is specified if (whatyear == 0) { fromyear = 0; nthyear = 0; oneyear = true; } // get next day using fromday + nthday int nth = nthday; if (q == 0) { dd = 0; } dayoffset = int.max(dd,int.max(0,(fromday - 1))); if (andnthday > 0) { if ((q & 1) != 0) { nth = andnthday; } } print("%s[%d] getnextdate (init) previous day %d, from day %d, weekday %d, nthday %d, month %d, year %d\n",tabs,q,dd,fromday,weekd,nthday,mm,yy); if ((weekd > 0) && (weekd < 8)) { nth = (nth * 7); dayoffset = getdayoffsetofweekday(nind,dd, fromday, weekd, nth, mm, yy); print("%s[%d] getnextdate (init) dayoffset is %d, + nth %d * 7 (%d) days is %d\n",tabs,q,dayoffset,nthday,nth,(dayoffset + nth)); } else { if (weekd > 7) { // get work-weekday on-or-before (dayoffset + nth) GLib.Date j = new GLib.Date(); j.set_dmy((DateDay) (dayoffset + nth), mm, (DateYear) yy); int nwd = j.get_weekday(); print("%s[%d] getnextdate (init) day %d weekday is %d \n",tabs,q,(dayoffset + nth),nwd); if (nwd > 5) { int nwe = int.max(0,(weekd - 7)); nth = nth + wwkd[nwe,nwd]; } } } if (countpermonth) { print("%s[%d] getnextdate (countpermonth) dayoffset %d + nth %d is %d\n",tabs,q,dayoffset,nth,(dayoffset + nth)); if ((nth + dayoffset) > lymd(mm,yy)) { if (countperyear) { if ((mm + nthmonth) > 12) { // per month per year, rolling over to +nth month, +nth year if (nthyear > 0) { a.add_years(nthyear); yy = (int) a.get_year(); a.set_month(frommonth); mm = (int) a.get_month(); a.set_day((DateDay) 1); dd = (int) a.get_day(); dayoffset = fromday; if ((weekd > 0) && (weekd < 8)) { dayoffset = getdayoffsetofweekday(nind,dd, fromday, weekd, nthday, mm, yy); } a.set_day((DateDay) (dayoffset + nth)); dd = (int) a.get_day(); if ((dayoffset + nth) > lymd(mm,yy)) { //print("getnextdate (per month rollover per year rollover) dayoffset %d + nth %d is invalid\n",dayoffset,nth); return nd; } else { //print("getnextdate (per month rollover per year rollover) returns %d-%d-%d\n",yy,mm,dd); return a; } } else { //print("getnextdate (per month rollover per year rollover) reached end of a single year, returning invalid date\n"); return nd; } } } // per month, rolling over to +nth month a.add_months(nthmonth); mm = (int) a.get_month(); a.set_day((DateDay) 1); dd = (int) a.get_day(); print("%s[%d] getnextdate (per month rollover) incremented +%d month is %d-%d-%d\n",tabs,q,nthmonth,yy,mm,dd); dayoffset = fromday; if ((weekd > 0) && (weekd < 8)) { dayoffset = getdayoffsetofweekday(nind,dd, fromday, weekd, nth, mm, yy); print("%s[%d] getnextdate (per month rollover) new monthly offset is %d\n",tabs,q,dayoffset); } else { if (weekd > 7) { // get work-weekday on-or-before (dayoffset + nth) GLib.Date j = new GLib.Date(); j.set_dmy((DateDay) (dayoffset + nth), mm, (DateYear) yy); int nwd = j.get_weekday(); print("%s[%d] getnextdate (per month rollover) day %d weekday is %d \n",tabs,q,(dayoffset + nth),nwd); if (nwd > 5) { int nwe = int.max(0,(weekd - 7)); nth = nth + wwkd[nwe,nwd]; print("%s[%d] getnextdate (per month rollover) day %d weekday %d offset type is %d, offset is %d, nth is now %d\n",tabs,q,(dayoffset + nthday),nwd,nwe,wwkd[nwe,nwd],nth); } } } if ((dayoffset + nth) > lymd(mm,yy)) { print("%s[%d] getnextdate (per month rollover) dayoffset %d + nth %d is invalid\n",tabs,q,dayoffset,nth); return nd; } else { a.set_day((DateDay) (dayoffset + nth)); dd = (int) a.get_day(); print("%s[%d] getnextdate (per month rollover) returns %d-%d-%d\n\n",tabs,q,yy,mm,dd); return a; } } else { // per month a.set_day((DateDay) (dayoffset + nth)); dd = (int) a.get_day(); if ((dayoffset + nth) > lymd(mm,yy)) { print("%sgetnextdate (per month) dayoffset %d + nth %d is invalid\n",tabs,dayoffset,nth); return nd; } else { print("%s[%d] getnextdate (per month) returns %d-%d-%d\n\n",tabs,q,yy,mm,dd); return a; } } } } print("%sgetnextdate (per month no rollover) did not incrament from %d to %d+%d, returning invalid date\n",tabs,dd,dd,dayoffset); return nd; } void printrule (int[] r) { GLib.DateTime nt = new DateTime.now_local(); int ntd = nt.get_day_of_month(); int ntm = nt.get_month(); int nty = nt.get_year(); int whatday = r[0]; // "the" or "every" int nthday = r[1]; int andnthday = r[2]; int weekd = r[3]; int dayof = r[4]; int fromday = r[5]; // "from the" int whatmonth = r[6]; // "of the" or "of every" int nthmonth = r[7]; int andnthmonth = r[8]; int themonth = r[9]; int monthof = r[10]; int frommonth = r[11]; // "from the" int whatyear = r[12]; // "of the" or "of every" int nthyear = r[13]; int theyear = r[14]; // int fromyear = r[15]; //if (r[13] == 0) { fromyear = nty; } string[] whd = {"the","every"}; string[] nth = {}; string[] ath = {}; nth += ""; ath += ""; for (int i = 1; i < 366; i++) { nth += "%s".printf(whiggle(i,0,1)); ath += "then %s".printf(whiggle(i,0,1)); } string[] wkd = {"day","monday","tuesday","wednesday","thursday","friday","saturday","sunday","weekday on or before the","weekday on or after the","weekday closest to the"}; string[] fdy = {"","from the 1st","from the 2nd","from the 3rd","from the 4th","from the 5th","from the 6th","from the 7th","from the 8th","from the 9th","from the 10th","from the 11th","from the 12th","from the 13th","from the 14th","from the 15th","from the 16th","from the 17th","from the 18th","from the 19th","from the 20th","from the 21st","from the 22nd","from the 23rd","from the 24th","from the 25th","from the 26th","from the 27th","from the 28th","from the 29th","from the 30th","from the 31st","from the last"}; string[] doo = {"of the month",""}; string[] whm = {"of","of every"}; string[] mth = {"","1st","2nd","3rd","4th","5th","6th","7th","8th","9th","10th","11th","12th"}; string[] amh = {"","and 1st","and 2nd","and 3rd","and 4th","and 5th","and 6th","and 7th","and 8th","and 9th","and 10th","and 11th","and 12th"}; string[] thm = {"","january","february","march","april","may","june","july","august","september","october","november","december"}; string[] moo = {"of the year",""}; string[] fmo = {"","from january","from february","from march","from april","from may","from june","from july","from august","from september","from october","from november","from december"}; string[] wye = {"of","of every"}; string[] yth = {"","year","2nd year", "3rd year", "4th year", "5th year", "6th year", "7th year", "8th year", "9th year", "decade"}; string[] thy = {}; thy += ""; for (int i = 1990; i < (nty + 2); i++) { thy += "%d".printf(i); } string[] fye = {}; fye += ""; for (int i = 1990; i < (nty + 2); i++) { fye += "%d".printf(i); } int theyearindex = 0; int fromyearindex = 0; if (theyear > 0) { theyearindex = theyear - 1989; } if (fromyear > 0) { fromyearindex = fromyear - 1989; } if ((themonth == 0) && (whatmonth == 0)) { thm[0] = "this month"; } if ((whatmonth == 1) && (whatyear == 0) && (nthyear == 0)) { thm[0] = "month"; } if ((theyear == 0) && (whatyear == 0)) { thy[0] = "this year"; } if ((whatmonth == 1) && (dayof == 0)) { doo[0] = ""; } if ((whatyear == 0) && (monthof == 0)) { moo[0] = ""; } if (weekd < 8) { print( "\"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", whd[whatday], nth[nthday], ath[andnthday], wkd[weekd], doo[dayof], fdy[fromday], whm[whatmonth], mth[nthmonth], amh[andnthmonth], thm[themonth], moo[monthof], fmo[frommonth], wye[whatyear], yth[nthyear], thy[theyearindex], fye[fromyearindex] ); } else { print( "\"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", whd[whatday], wkd[weekd], nth[nthday], ath[andnthday], doo[dayof], fdy[fromday], whm[whatmonth], mth[nthmonth], amh[andnthmonth], thm[themonth], moo[monthof], fmo[frommonth], wye[whatyear], yth[nthyear], thy[theyearindex], fye[fromyearindex] ); } } int[] forecast(int ind, int[] r) { string tabs = ("%*s").printf(ind," ").replace(" ","\t"); int nind = ind + 1; int[] predictions = {}; // now GLib.DateTime nt = new DateTime.now_local(); int ntd = nt.get_day_of_month(); int ntm = nt.get_month(); int nty = nt.get_year(); GLib.Date n = Date(); n.set_dmy((DateDay) ntd, ntm, (DateYear) nty); // start counting from date a GLib.Date a = Date(); a.set_dmy((DateDay) 1, ntm, (DateYear) nty); //int mm = ((ntm - 2) % 12) + 1; //int yy = nty; //if (mm > ntm) { yy = nty - 1; a.set_year((DateYear) yy); } //a.set_month(mm); //a.set_day((DateDay) lymd(mm,yy)); // stop counting to date b GLib.Date b = Date(); b.set_dmy((DateDay) ntd,ntm,(DateYear) nty); b.add_years(1); for (int i = 0; i < 5; i++) { if (a.compare(b) > 0) { break; } //print("\nforecast iteration %d\n",i); a = getnextdate(nind,a,n,b,r,ref i); if (((int) a.get_year()) > 1989) { if (a.compare(n) > 0) { predictions += (int) a.get_year(); predictions += (int) a.get_month(); predictions += (int) a.get_day(); } } else { print("no more dates\n"); break; } } return predictions; } void main () { // 00 whatday..... : the, every // 01 nthday...... : "", 1st, 2nd, 3rd, etc // 02 andnthday... : "", and 2nd, and 3rd, and 4th, etc. (when used with 'every', it alternates) // 03 weekday..... : day, monday, tuesday, wednesday, thursday, friday, saturday, sunday, weekday on or before the, weekday on or after the, weekday closest to the, last // 04 fromday..... : "", from the 1st day, from the 2nd day, from the 3rd day, ... from the last day // 05 whatmonth... : of, of every // 06 nthmonth.... : "", 1st, 2nd, 3rd, etc. // 07 andnthmonth. : "", then 1st, then 2nd, then 3rd, etc. // 08 themonth.... : "", january, february, march, etc. // 09 frommonth... : "", from january, from february, from march, etc. // 10 whatyear.... : of, of every // 11 nthyear..... : "", year, 2nd year, 3rd year, etc. // 12 theyear..... : "", 1990 ... 2026 <- limits are for ux reasons // 13 fromyear.... : "", 1990 ... 2026 print("the 2nd of march 2026\n"); print("---------------------\n"); int[] rule = {0,2,0,0,0,0, 0,0,0,3,0,0, 0,0,2026,0}; printrule(rule); int[] test = {2026,3,2}; int[] forecasted = forecast(0,rule); print("%s\n\n",printintarray(forecasted,2)); // the 2nd tuesday of this month 2026 print("the 2nd tuesday of this month of 2026\n"); print("-------------------------------------\n"); rule = {0,2,0,2,0,0, 0,0,0,0,0,0, 0,0,2026,0}; printrule(rule); forecasted = forecast(0,rule); print("%s\n\n",printintarray(forecasted,2)); print("the 2nd tuesday from the 10th of august of this year\n"); print("----------------------------------------------------\n"); // the 2nd tuesday from the 10th of august this year rule = {0,2,0,2,0,10, 0,0,0,8,0,0, 0,0,0,0}; printrule(rule); forecasted = forecast(0,rule); print("%s\n\n",printintarray(forecasted,2)); print("every 2nd tuesday of the month from the 10th of august of this year\n"); print("-------------------------------------------------------------------\n"); // every 2nd monday of the month from the 10th of of august this year rule = {1,2,0,2,0,10, 0,0,0,8,0,0, 0,0,0,0}; printrule(rule); forecasted = forecast(0,rule); test = {2025,8,19,2025,9,9,2025,9,16,2025,9,23,2025,10,14}; print("test is ... %s\n",printintarray(test,2)); print("forecast is %s : ",printintarray(forecasted,2)); if (compareintarrays(forecasted,test)) { print("correct\n\n"); } else { print("incorrect\n\n"); } print("every 2nd tuesday from the 10th of august of this year\n"); print("------------------------------------------------------\n"); rule = {1,2,0,2,1,10, 0,0,0,8,0,0, 0,0,0,0}; printrule(rule); forecasted = forecast(0,rule); test = {2025,8,19,2025,9,2,2025,9,16,2025,9,30,2025,10,14}; print("test is ... %s\n",printintarray(test,2)); print("forecast is %s : ",printintarray(forecasted,2)); if (compareintarrays(forecasted,test)) { print("correct\n\n"); } else { print("incorrect\n\n"); } rule = {1,2,1,2,0,4, 1,0,0,3,0,0, 0,0,0,0}; printrule(rule); forecasted = forecast(0,rule); print("%s\n\n",printintarray(forecasted,2)); rule = {1,23,0,0,0,0, 1,0,0,5,0,0, 0,0,0,0}; printrule(rule); forecasted = forecast(0,rule); print("%s\n\n",printintarray(forecasted,2)); rule = {1,2,3,0,0,0, 0,0,0,3,0,0, 0,0,2026,0}; printrule(rule); forecasted = forecast(0,rule); print("%s\n\n",printintarray(forecasted,2)); rule = {1,90,91,0,1,0, 0,0,0,7,1,0, 0,0,0,0}; printrule(rule); forecasted = forecast(0,rule); print("%s\n\n",printintarray(forecasted,2)); rule = {1,90,91,8,1,0, 0,0,0,7,0,0, 0,0,0,0}; printrule(rule); forecasted = forecast(0,rule); print("%s\n\n",printintarray(forecasted,2)); rule = {1,26,0,8,0,0, 1,0,0,0,0,0, 0,0,0,0}; printrule(rule); forecasted = forecast(0,rule); print("%s\n\n",printintarray(forecasted,2)); }
#+RESULTS:
Compilation failed: 2 error(s), 6 warning(s)
TIMEPARSER

valid times
"hh:mm:ss AM"
"hh:mm:ss PM"
"hh:mm AM"
"hh:mm PM"
"hh AM"
"hh PM"
"HH:mm:ss"
"HH:mm"
"hh:mm:ss AM+hh:mm"
"hh:mm:ss PM+hh:mm"
"hh:mm AM+hh:mm"
"hh:mm PM+hh:mm"
"hh AM+hh:mm"
"hh PM+hh:mm"
"HH:mm:ss+hh:mm"
"HH:mm+hh:mm"
"hh:mm:ss AM-hh:mm"
"hh:mm:ss PM-hh:mm"
"hh:mm AM-hh:mm"
"hh:mm PM-hh:mm"
"hh AM-hh:mm"
"hh PM-hh:mm"
"HH:mm:ss-hh:mm"
"HH:mm-hh:mm"
"hh:mm:ss AM +hh:mm"
"hh:mm:ss PM +hh:mm"
"hh:mm AM +hh:mm"
"hh:mm PM +hh:mm"
"hh AM +hh:mm"
"hh PM +hh:mm"
"HH:mm:ss +hh:mm"
"HH:mm +hh:mm"
"hh:mm:ss AM -hh:mm"
"hh:mm:ss PM -hh:mm"
"hh:mm AM -hh:mm"
"hh:mm PM -hh:mm"
"hh AM -hh:mm"
"hh PM -hh:mm"
"HH:mm:ss -hh:mm"
"HH:mm -hh:mm"

where:
  • hh is the hour in range 1..12
  • HH is the hour in 0..23
  • +/-hh:mm is the timezone offset

int64 timeparser (string s) { // timeparser // by c.p.brown 2026 StringBuilder aa = new StringBuilder(""); aa.append(s); int acc = aa.str.char_count(); if (acc < 4) { return -1; } // hh : mm : ss AM + hh : mm // 012345678901234567890123456 27 chars for a stretched but valid time if (acc > 27) { //print("input too long\n"); return -1; } uint ptz = aa.replace("+", " + ", 0); uint ntz = aa.replace("-", " - ", 0); bool htz = ((ptz == 1) || (ntz == 1)); uint adv = aa.replace(":", " ", 0); aa.str = compactstring(aa.str,true); // true removes newlines string[] aap = aa.str.split(" "); int caap = aap.length; if (caap < 2) { //print("input is too ambiguous\n"); return -1; } if ((caap > 2) && (adv == 0)) { //print("time format lacks colons\n"); return -1; } int[] sparts = {3600,60,1}; int[] tvhmaxnum = {13,60,60}; int[] maxnum = {24,60,60}; if (caap < 2) { return -1; } if ((caap > 4) && !htz) { //print("time dimensions > 4\n"); return -1; } if ((caap > 7) && htz) { //print("time + tz dimensions > 7\n"); return -1; } int laap = caap - 1; int tzh = 0; int tzm = 0; int neg = -1; if (htz) { for (int y = 0; y < caap; y++) { neg = -1; if (aap[y] == "+") { neg = 0; } else { if (aap[y] == "-") { neg = 1; } } if (neg > -1) { if ((y + 2) == laap) { if (isanumber(aap[y+1]) && (int.parse(aap[y+1]) < tvhmaxnum[0])) { if (isanumber(aap[y+2]) && (int.parse(aap[y+2]) < tvhmaxnum[1])) { tzh = int.parse(aap[y+1]); tzm = int.parse(aap[y+2]); laap = (y - 1); break; } else { //print("tzm out of bounds or not a number\n"); return -1; } } else { //print("tzh out of bounds or not a number\n"); return -1; } } else { //print("tz dimensions > 2\n"); return -1; } laap = (y - 1); } } if (laap < 0) { //print("tz consumed input\n"); return -1; } } bool ipm = (aap[laap].up() == "PM"); bool tvh = ((aap[laap].up() == "AM") || ipm); if (tvh) { laap -= 1; } if (laap < 0) { return -1; } int secs = 0; bool allnums = true; for (int y = 0; y <= laap; y++) { int hp = int.parse(aap[y]); allnums = ( allnums && isanumber(aap[y]) && ( (tvh && (hp < tvhmaxnum[y])) || (!tvh && (hp < maxnum[y])) ) ); } if (allnums) { int tzs = 0; if (htz) { tzs += (sparts[0] * tzh); tzs += (sparts[1] * tzm); if (neg == 1) { tzs = (0 - tzs); } } //print("\ntzs %016d is %s\n",tzs,printallmy32bits(tzs)); for (int y = 0; y <= laap; y++) { int hp = int.parse(aap[y]); if (y == 0) { if (ipm) { hp += 12; } } secs += (hp * sparts[y]); } //print("sec %016d is %s\n",secs,printallmy32bits(secs)); int64 psecs = ((((int64) tzs) << 32) | secs); //print("out %016lld is %s\n",psecs,printallmy64bits(psecs)); return psecs; } return -1; }
TIMEPARSER_TEST
// timeparser test // by c.p.brown 2026 string printallmy64bits (int64 n) { int b = 63; string o = ""; for (int i = b; i >= 0; i--) { o = o + "%lld".printf((n >> i) & 1); if ((i % 4) == 0) { o = (o + " "); } } return o; } string printallmy32bits (int n) { int b = 31; string o = ""; for (int i = b; i >= 0; i--) { o = o + "%d".printf((n >> i) & 1); if ((i % 4) == 0) { o = (o + " "); } } return o; } string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } string printstringarray (string[] s, int f) { // 0 1 2 3 4 5 6 7 8 9 string[] ii = {"", "\"", "{", "{\"", "[", "[", "| ", "", "", ""}; string[] dd = {";", ",", ",", "\",\"", " ", ",", " | ", " ", "\n", ",\n"}; string[] oo = {"", "\"", "}", "\"}", "]", "]", " |", "", "", ""}; string o = ii[f]; for (int i = 0; i < (s.length - 1); i++) { o = (o + "%s".printf(s[i]) + dd[f]); } o = (o + "%s".printf(s[s.length - 1]) + oo[f]); return o; } bool isanumber (string s, bool pc, out string c) { StringBuilder sb = new StringBuilder(""); StringBuilder sbs = new StringBuilder(""); sbs.append(s); sbs.str = sbs.str.strip(); bool hasradix = false; int scc = sbs.str.char_count(); int pfx = 0; int pnc = 0; bool prx = true; bool pre = true; for (int x = 0; x < scc; x++) { int i = sbs.str.index_of_nth_char(x); unichar u = sbs.str.get_char(i); if (pre) { if (u == ' ') { continue; } if (u == ',') { c = ""; return false; } if (u == '-') { pfx = (x + 1); pre = false; sb.append_unichar(u); continue; } if (u == '+') { pfx = (x + 1); pre = false; continue; } if (u == '$') { pfx = (x + 1); pre = false; continue; } if (u == '±') { pfx = (x + 1); pre = false; continue; } } if (x == pfx) { if (u == ' ') { continue; } } if (u == ',') { continue; } if (u == '.') { if (!hasradix) { pre = false; prx = false; sb.append_unichar(u); hasradix = true; continue; } else { c = ""; return false; } } if (u.isdigit() == false) { if (!pre) { if (x == (scc - 2)) { if (u == ' ') { unichar j = sbs.str.get_char(sbs.str.index_of_nth_char(x+1)); if (j == '°') { if (sb.str.char_count() > 0) { c = maxfrac(double.parse(sb.str)); c = stripzeroes(c); return true; } } } } else { if (x == (scc - 1)) { if (u == '°') { if (sb.str.char_count() > 0) { c = maxfrac(double.parse(sb.str.dup())); c = stripzeroes(c); return true; } } if (u == '%') { if (sb.str.char_count() > 0) { if (pc) { double perc = double.parse(sb.str); c = maxfrac((perc / 100.0)); } else { c = maxfrac(double.parse(sb.str.dup())); } c = stripzeroes(c); return true; } } } } } c = ""; return false; } pre = false; sb.append_unichar(u); pnc += 1; if (pnc > 14) { if (sb.str.char_count() > 0) { c = maxfrac(double.parse(sb.str.dup())); c = stripzeroes(c); return true; } } } c = maxfrac(double.parse(sb.str.dup())); c = c = stripzeroes(c); return true; } string compactstring (string s, bool n) { // compact string // by cpbrown 2024 // // n = remove newlines StringBuilder compacted = new StringBuilder(""); if (n) { for (int i = 0; i < s.char_count(); i++) { unichar tc = s.get_char(s.index_of_nth_char(i)); if (!tc.isspace()) { compacted.append_unichar(tc); continue; } else { unichar pc = 'A'; if (i > 0) { pc = s.get_char(s.index_of_nth_char(i-1)); } if (pc.isspace()) { continue; } tc = ' '; compacted.append_unichar(tc); } } } else { for (int i = 0; i < s.char_count(); i++) { unichar tc = s.get_char(s.index_of_nth_char(i)); if (tc == '\n') { compacted.append_unichar(tc); continue; } if (!tc.isspace()) { compacted.append_unichar(tc); continue; } else { unichar pc = 'A'; if (i > 0) { pc = s.get_char(s.index_of_nth_char(i-1)); } if (pc != '\n') { if (pc.isspace()) { continue; } } tc = ' '; compacted.append_unichar(tc); } } } compacted.str = compacted.str.strip(); return compacted.str; } int64 timeparser (string s) { // timeparser // by c.p.brown 2026 StringBuilder aa = new StringBuilder(""); aa.append(s); int acc = aa.str.char_count(); if (acc < 4) { return -1; } // hh : mm : ss AM + hh : mm // 012345678901234567890123456 27 chars for a stretched but valid time if (acc > 27) { //print("input too long\n"); return -1; } uint ptz = aa.replace("+", " + ", 0); uint ntz = aa.replace("-", " - ", 0); bool htz = ((ptz == 1) || (ntz == 1)); uint adv = aa.replace(":", " ", 0); aa.str = compactstring(aa.str,true); // true removes newlines string[] aap = aa.str.split(" "); int caap = aap.length; if (caap < 2) { //print("input is too ambiguous\n"); return -1; } if ((caap > 2) && (adv == 0)) { //print("time format lacks colons\n"); return -1; } int[] sparts = {3600,60,1}; int[] tvhmaxnum = {13,60,60}; int[] maxnum = {24,60,60}; if (caap < 2) { return -1; } if ((caap > 4) && !htz) { //print("time dimensions > 4\n"); return -1; } if ((caap > 7) && htz) { //print("time + tz dimensions > 7\n"); return -1; } int laap = caap - 1; int tzh = 0; int tzm = 0; int neg = -1; if (htz) { for (int y = 0; y < caap; y++) { neg = -1; if (aap[y] == "+") { neg = 0; } else { if (aap[y] == "-") { neg = 1; } } if (neg > -1) { if ((y + 2) == laap) { if (isanumber(aap[y+1]) && (int.parse(aap[y+1]) < tvhmaxnum[0])) { if (isanumber(aap[y+2]) && (int.parse(aap[y+2]) < tvhmaxnum[1])) { tzh = int.parse(aap[y+1]); tzm = int.parse(aap[y+2]); laap = (y - 1); break; } else { //print("tzm out of bounds or not a number\n"); return -1; } } else { //print("tzh out of bounds or not a number\n"); return -1; } } else { //print("tz dimensions > 2\n"); return -1; } laap = (y - 1); } } if (laap < 0) { //print("tz consumed input\n"); return -1; } } bool ipm = (aap[laap].up() == "PM"); bool tvh = ((aap[laap].up() == "AM") || ipm); if (tvh) { laap -= 1; } if (laap < 0) { return -1; } int secs = 0; bool allnums = true; for (int y = 0; y <= laap; y++) { int hp = int.parse(aap[y]); allnums = ( allnums && isanumber(aap[y]) && ( (tvh && (hp < tvhmaxnum[y])) || (!tvh && (hp < maxnum[y])) ) ); } if (allnums) { int tzs = 0; if (htz) { tzs += (sparts[0] * tzh); tzs += (sparts[1] * tzm); if (neg == 1) { tzs = (0 - tzs); } } //print("\ntzs %016d is %s\n",tzs,printallmy32bits(tzs)); for (int y = 0; y <= laap; y++) { int hp = int.parse(aap[y]); if (y == 0) { if (ipm) { hp += 12; } } secs += (hp * sparts[y]); } //print("sec %016d is %s\n",secs,printallmy32bits(secs)); int64 psecs = ((((int64) tzs) << 32) | secs); //print("out %016lld is %s\n",psecs,printallmy64bits(psecs)); return psecs; } return -1; } void main() { int64 tts = GLib.get_monotonic_time(); GLib.Intl.setlocale(ALL,""); string[] isos = { "11:20:15 AM", "11:20:15 PM", "11:20 AM", "11:20 PM", "11 AM", "11 PM", "23:20:15", "23:20", "12:20:15", "12:20", "11:20:15 AM+09:30", "11:20:15 PM+09:30", "11:20 AM+09:30", "11:20 PM+09:30", "11 AM+09:30", "11 PM+09:30", "23:20:15+09:30", "23:20+09:30", "11:20:15 AM-10:00", "11:20:15 PM-09:30", "11:20 AM-09:30", "11:20 PM-09:30", "11 AM-09:30", "11 PM-09:30", "23:20:15-09:30", "23:10-09:30", "11:20:15 AM +09:30", "11:20:15 PM +09:30", "11:20 AM +09:30", "11:20 PM +09:30", "11 AM +09:30", "11 PM +09:30", "23:20:15 +09:30", "23:20 +09:30", "11:20:15 AM -09:30", "11:20:15 PM -09:30", "11:20 AM -09:30", "11:20 PM -09:30", "11 AM -09:30", "11 PM -09:30", "23:20:15 -09:30", "23:20 -09:30", "11:20:00", "11:20:00 PM+09:30", "11:20:00+09:30", "11:20:00 +9:30", "11:20+09:30", "11:20:00 a", "11:20:00 am", "11:20:00 A", "11:20:00 Am", "11:20:00 AM", "11:20:70", "20:20:00 AM", "20:20:00", "30:20:00", "12:59:59", "0:0:0", "24:60:60", "11:80:00", "11:20:00 p", "11:20:00 pm", "11:20:00 Pm", "11:20:00 PM", "20:20", "1:3 AM", "1:3 PM", "1:3:2 AM", "1:3:2 PM", "1:3:2", "1:3:2", "1:3", "1 PM", "1", "11:20 AM", "11:20 PM", "11 :20AM", "11 :20 PM", "11:20AM", "11: 20 PM", "11 : 20 : AM", "11 : 20 PM", "11 :20AM", " 11 :20 :00PM", " 11:20:00 PM ", " 11 :20 :00 PM ", " 11:20 : 00 PM ", " 11 : 20 : 00 PM.", " 0011 : 0020 : 0000 PM + 0009 : 0030 ", " 11 : 20 : 00 PM\n ", "11:20:00:PM", "11:20:00:12:PM", "11::20:00 PM", ":11:20:00 PM", "11:20:00:PM +9:00", "11:20:00+4:30", "23:20+1:30", "11+00:30", "11+1:30 PM", "11:20:00+5:1PM", "11:20:00:PM-5000" }; foreach (string iso in isos) { int64 tpp = timeparser(iso); //print("tpp is %lld\n",tpp); if (tpp != -1) { int tps = (int) (tpp & 0x1FFFF); int tpz = (int) ((tpp >> 32) & 0xFFFFFFFF); //print("tps is %d\n",tps); //print("tpz is %d\n",tpz); TimeZone tz = new TimeZone.local(); if (tpz != 0) { tz = new TimeZone.offset(tpz); } DateTime nn = new DateTime.now(tz); nn = nn.add_hours(0 - nn.get_hour()); nn = nn.add_minutes(0 - nn.get_minute()); nn = nn.add_seconds(0 - nn.get_second()); //print("now hh mm ss is %d %d %d %s\n",nn.get_hour(),nn.get_minute(),nn.get_second(),nn.format_iso8601()); nn = nn.add_seconds(tps); //print("\"%s\" is %d seconds, date is %s\n",iso,tps,nn.format_iso8601()); TimeSpan uof = nn.get_utc_offset(); print("\"%s\"\n",iso); print("=%02d:%02d:%02d %s\n\n",nn.get_hour(),nn.get_minute(), nn.get_second(), nn.get_timezone_abbreviation()); } else { print("\"%s\" is not valid\n\n",iso); } } int64 tte = GLib.get_monotonic_time(); print("\ntimeparser_test took %s\n",printusecs(tte - tts)); }
#+RESULTS:
Compilation succeeded - 5 warning(s) "11:20:15 AM" =11:20:15 ACDT "11:20:15 PM" =23:20:15 ACDT "11:20 AM" =11:20:00 ACDT "11:20 PM" =23:20:00 ACDT "11 AM" =11:00:00 ACDT "11 PM" =23:00:00 ACDT "23:20:15" =23:20:15 ACDT "23:20" =23:20:00 ACDT "12:20:15" =12:20:15 ACDT "12:20" =12:20:00 ACDT "11:20:15 AM+09:30" =11:20:15 +09:30:00 "11:20:15 PM+09:30" =23:20:15 +09:30:00 "11:20 AM+09:30" =11:20:00 +09:30:00 "11:20 PM+09:30" =23:20:00 +09:30:00 "11 AM+09:30" =11:00:00 +09:30:00 "11 PM+09:30" =23:00:00 +09:30:00 "23:20:15+09:30" =23:20:15 +09:30:00 "23:20+09:30" =23:20:00 +09:30:00 "11:20:15 AM-10:00" =11:20:15 -10:00:00 "11:20:15 PM-09:30" =23:20:15 -09:30:00 "11:20 AM-09:30" =11:20:00 -09:30:00 "11:20 PM-09:30" =23:20:00 -09:30:00 "11 AM-09:30" =11:00:00 -09:30:00 "11 PM-09:30" =23:00:00 -09:30:00 "23:20:15-09:30" =23:20:15 -09:30:00 "23:10-09:30" =23:10:00 -09:30:00 "11:20:15 AM +09:30" =11:20:15 +09:30:00 "11:20:15 PM +09:30" =23:20:15 +09:30:00 "11:20 AM +09:30" =11:20:00 +09:30:00 "11:20 PM +09:30" =23:20:00 +09:30:00 "11 AM +09:30" =11:00:00 +09:30:00 "11 PM +09:30" =23:00:00 +09:30:00 "23:20:15 +09:30" =23:20:15 +09:30:00 "23:20 +09:30" =23:20:00 +09:30:00 "11:20:15 AM -09:30" =11:20:15 -09:30:00 "11:20:15 PM -09:30" =23:20:15 -09:30:00 "11:20 AM -09:30" =11:20:00 -09:30:00 "11:20 PM -09:30" =23:20:00 -09:30:00 "11 AM -09:30" =11:00:00 -09:30:00 "11 PM -09:30" =23:00:00 -09:30:00 "23:20:15 -09:30" =23:20:15 -09:30:00 "23:20 -09:30" =23:20:00 -09:30:00 "11:20:00" =11:20:00 ACDT "11:20:00 PM+09:30" =23:20:00 +09:30:00 "11:20:00+09:30" =11:20:00 +09:30:00 "11:20:00 +9:30" =11:20:00 +09:30:00 "11:20+09:30" =11:20:00 +09:30:00 "11:20:00 a" is not valid "11:20:00 am" =11:20:00 ACDT "11:20:00 A" is not valid "11:20:00 Am" =11:20:00 ACDT "11:20:00 AM" =11:20:00 ACDT "11:20:70" is not valid "20:20:00 AM" is not valid "20:20:00" =20:20:00 ACDT "30:20:00" is not valid "12:59:59" =12:59:59 ACDT "0:0:0" =00:00:00 ACDT "24:60:60" is not valid "11:80:00" is not valid "11:20:00 p" is not valid "11:20:00 pm" =23:20:00 ACDT "11:20:00 Pm" =23:20:00 ACDT "11:20:00 PM" =23:20:00 ACDT "20:20" =20:20:00 ACDT "1:3 AM" =01:03:00 ACDT "1:3 PM" =13:03:00 ACDT "1:3:2 AM" =01:03:02 ACDT "1:3:2 PM" =13:03:02 ACDT "1:3:2" =01:03:02 ACDT "1:3:2" =01:03:02 ACDT "1:3" is not valid "1 PM" =13:00:00 ACDT "1" is not valid "11:20 AM" =11:20:00 ACDT "11:20 PM" =23:20:00 ACDT "11 :20AM" is not valid "11 :20 PM" =23:20:00 ACDT "11:20AM" is not valid "11: 20 PM" =23:20:00 ACDT "11 : 20 : AM" =11:20:00 ACDT "11 : 20 PM" =23:20:00 ACDT "11 :20AM" is not valid " 11 :20 :00PM" is not valid " 11:20:00 PM " =23:20:00 ACDT " 11 :20 :00 PM " =23:20:00 ACDT " 11:20 : 00 PM " =23:20:00 ACDT " 11 : 20 : 00 PM." is not valid string too long for a valid time format " 0011 : 0020 : 0000 PM + 0009 : 0030 " is not valid " 11 : 20 : 00 PM " =23:20:00 ACDT "11:20:00:PM" =23:20:00 ACDT "11:20:00:12:PM" is not valid "11::20:00 PM" =23:20:00 ACDT ":11:20:00 PM" =23:20:00 ACDT "11:20:00:PM +9:00" =23:20:00 +09:00:00 "11:20:00+4:30" =11:20:00 +04:30:00 "23:20+1:30" =23:20:00 +01:30:00 "11+00:30" =11:00:00 +00:30:00 "11+1:30 PM" is not valid "11:20:00+5:1PM" is not valid "11:20:00:PM-5000" is not valid timeparser_test took 1.42 ms
FILES
FILESEEK

Read a file as 100-char lines.

void main() { GLib.Intl.setlocale(ALL,""); print(","); char[] charline = new char[100]; GLib.FileStream fstr = GLib.FileStream.open("./cpbrown_notes.org","r"); for (int r = 0; r < 10; r++) { StringBuilder sbline = new StringBuilder(""); if (fstr.gets(charline) != null) { sbline.append((string) charline); sbline.replace("\n","\n,",-1); print(sbline.str); } else { break; } } }
#+RESULTS:
,# -*- mode:org; org-confirm-babel-evaluate: nil; org-todo-keyword-faces: (("[0_TODO]" . "orange") ("[1_IP..]" . "yellow") ("[2_FIX.]" . "red") ("[3_WAIT]" . "blue") ("[4_NOPE]" . "black") ("[5_DONE]" . "green")); -*- ,#+STARTUP: indent overview align ,#+OPTIONS: toc:nil num:nil title:nil \n:t author:nil ::nil H:1 f:nil ,#+TITLE: the work ,#+AUTHOR: c.p.brown ,#+TODO: [0_TODO] [1_IP..] [2_FIX.] [3_WAIT] [4_NOPE] [5_DONE] ,#+SUBTITLE: ,#+NOTHING: 零 goes here ,
FILESTREAM

Load a large file line by line.

string[] readfilelines (string s) { string[] dat = {}; GLib.File f = File.new_for_path(s); if (f.query_exists()) { GLib.FileStream fs; try { fs = GLib.FileStream.open(s,"r"); } catch (Error e) { print("error opening file: %s\n",e.message); return dat; } while (true) { StringBuilder sb = new StringBuilder(""); string l = fs.read_line(); if (l == null) { break; } sb.append(l.dup()); dat += sb.str; } } else { print("error finding file: %s\n",s); } return dat; } void main() { GLib.Intl.setlocale(ALL,""); string[] dat = readfilelines("./cpbrown_notes.org"); for (int i = 1; i < 1000; i += 101) { print("[%03d] %s\n",i,dat[i]); } }
#+RESULTS:
Compilation succeeded - 1 warning(s) [001] #+STARTUP: indent overview align [102] circle (to-pair compose/deep [(to-integer (uu/size/x * 0.5) - 10) 5]) 2 2 [203] pset: load %./default.parse [304] print("(row,col) at index %d is (%d,%d)\n",idx,row,col); [405] } [506] 15 | 0.79 | 0.66 | 19 | ███████████████████ [607] print("(i << 4) | %u is %u\n",v,r); [708] [809] if (cmd == -1) { return false; } [910] double mxy = double.min((csx * da.cv_aszx),(csy * da.cv_aszy));
GETFILEPARTS

string[] getfilefileparts (GLib.File f) { string fileext = ""; string filename = ""; string filepath = ""; string fp = f.get_path(); int ii = fp.last_index_of("."); if (ii != -1) { fileext = fp.substring(ii+1); filename = fp.substring(0,ii); int qq = filename.last_index_of("/"); if (qq != -1) { filepath = filename.substring(0,qq); filename = filename.substring(qq + 1); } } return {f.get_parent().get_path(),filename,fileext}; } string[] getfilestringparts (string f) { string fileext = ""; string filename = ""; string filepath = ""; int ii = f.last_index_of("."); if (ii != -1) { fileext = f.substring(ii+1); filename = f.substring(0,ii); int qq = filename.last_index_of("/"); if (qq != -1) { filepath = filename.substring(0,qq); filename = filename.substring(qq + 1); } } return {filepath,filename,fileext}; } void main() { string sf = "./test/a/file/goes.here"; print("src...: %s\n",sf); GLib.File myfile = GLib.File.new_for_path(sf); string[] fp = getfilefileparts(myfile); print("file..: { %s }\n",string.joinv(", ",fp)); string[] sfp = getfilestringparts(sf); print("string: { %s }\n",string.joinv(", ",sfp)); }
#+RESULTS:
src...: ./test/a/file/goes.here file..: { /home/usr/Desktop/test/source/test/a/file, goes, here } string: { ./test/a/file, goes, here }
LOADFILETOSTRING
string loadfiletostring(string f) { StringBuilder sb = new StringBuilder(""); GLib.File ff = GLib.File.new_for_path(f); if (ff.query_exists()) { GLib.FileStream fstr = GLib.FileStream.open(f,"r"); while (true) { string fs = fstr.read_line(); if (fs == null) { break; } sb.append(fs + "\n"); } } return sb.str; }
LOADORGARTICLE

Load a top-level article from an org file.
(Double semi-colons inserted into results here to prevent orgception, which is not fun)

// load an orgmode heading and its sub-headings // by c.p.brown 2024 // remove double semicolons before use (I test these in orgmode itself) string loadinf (string t, string f) { string doctitle = ("* " + t); string helpfile = "./" + f + "/" + f + ".org"; string oo = ""; GLib.File orgfile = GLib.File.new_for_path(helpfile); if (orgfile.query_exists() == true) { GLib.FileStream s = GLib.FileStream.open(helpfile,"r"); string l = s.read_line(); bool amreading = false; string tabs = ""; string aa = "**********"; while (l != null) { if (!amreading) { if (strcmp(l.substring(0,doctitle.length),doctitle) == 0) { amreading = true; tabs = ("%*s").printf(1," ").replace(" ","\t"); oo = (oo + ";;" + l + "\n"); l = s.read_line(); continue; } } else { int nind = 0; int ll = l.length; if (ll > 1) { if (strcmp(l.substring(0,2),"* ") == 0) { amreading = false; break; } } if (ll > 0) { if (strcmp(l.substring(0,1),"*") == 0) { for (int g = 2; g < 11; g++) { if (ll > g) { string ss = "%.*s ".printf(g,aa); if (strcmp(l.substring(0,(g+1)),ss) == 0) { nind = (g-1); } } } } } if (nind > 0) { tabs = ("%*s").printf(nind," ").replace(" ","\t"); oo = (oo + ";;" + tabs + l + "\n"); nind += 1; tabs = ("%*s").printf(nind," ").replace(" ","\t"); } else { oo = (oo + ";;" + tabs + l + "\n"); } } l = s.read_line(); } } return oo; } void main () { string s = "AUTOTYPE"; string a = loadinf(s); print(a); }
#+RESULTS:
;;* AUTOTYPE ;; ;; Attemps to determine type of a column by analyzing column content. ;; Autotype can be costly, use with caution. ;; ;; Min node inputs: 1 ;; Max node inputs: 1 ;; ;; ** Parameters ;; ;; 1. FIRST ;; Examine 1st row only. ;; ;; 2. LAST ;; Examine last row only ;; ;; 3. DELIMITER ;; String that delimits words in a list. ;; ;; 4. ALL ;; Examine all rows (slow). ;; ;; 5. RANDOM ;; Examine a random sample of rows. ;; ;; 1. ACCURACY (double) ;; Slider represents % of rows to sample. ;; Less samples = speed, more samples = accuracy. ;; ;; 6. ROW Num ;; Examine a singe ROW. ;; ;; 1. ROW (int) ;; Single row to examine. ;; ;; 7. ROW RANGE ;; Examine rows from FROM, to TO. ;; ;; 1. FROM (int) ;; First row of a range. ;; 2. TO (int) ;; Second row of a range. ;; ;; 8. NTH ROW ;; Examine every nth row from FROM by NTH. ;; ;; 1. FROM (int) ;; Start row. ;; 2. NTH (int) ;; Nth row to examine. ;; ;; ** Data ;; ;; 0. serarchby, str str, menu options: ;; 1. searchin, str int, what row number | row from ;; 2. searchto, str int, row to ;; 3. searchaccuracy, str double, samples as 0.0~1.0 ;; 4. searchdelimit, str str, list delimiter ;; ;; ** Examples ;; ;; rows=ALL, DELIMITER=" ", dat={ ;; "aa", "2024-06-20", "aa bb cc", "3", ;; "bb", "2024-07-10", "cc", "5", ;; "cc", "2024-09-29", "aa cc", "7" ;; } ;; = { ;; "header_0", "string", "24352624", "0", "0", ;; "header_1", "date", "37774721", "0", "0", ;; "header_2", "list", "98488123", "03749201","24352624", ;; "header_3", "int", "12628931", "0", "0" ;; }
READFILETOSTRINGS
READFILETOSTRINGS_INF

Read lines of a file to a string[]

Usage:

string[] s = readfiletostrings(string p);

  • string p is the path to the file, which may be absolute or relative to this program

READFILETOSTRINGS_SRC
string[] readfiletostrings (string p) { string[] o = {}; GLib.FileStream fs; try { fs = GLib.FileStream.open(p,"r"); StringBuilder sb = new StringBuilder(""); while (true) { string l = fs.read_line(); if (l == null) { break; } sb.erase(); sb.append(l.dup()); o += sb.str; } } catch (Error e) { print("file error: %s\n",e.message); } return o; }
READLINE

Read a particular line from a huge file.
Pre-index the lines to allow multithreading.
Requested line number is 1-based.

// read pre-determined lines from a pre-indexed file // by cpbrown 2024 GLib.Mutex mutex; struct packet { public uint[] items; } string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } packet[] packseq ( uint[] x, uint c, bool q, int y, int z, int u) { //print("packseq started...\n"); // x = items to package // q = use items if true, use items count if false, eg {2,12,34,43} vs {0,1,2,3} // y = max packets, usually thread-count // z = nth item to package, eg {0,1,2,3,4,5} nth 2 is {0,2,4} // u = offset items, eg {0,1,2,3,4,5} offset 2 is {2,3,4,5}, {0,1,2,3,4,5} nth 2 offset 1 is {1,3,5} packet[] o = new packet[0]; uint[] srcitems = x; int maxpackets = y; int nthsrc = z; // nth int srcoffset = u; // offset uint srclen = c; uint[] sampleditems = {}; if (q) { srclen = srcitems.length; for (uint j = srcoffset; j < srclen; j += nthsrc) { sampleditems += srcitems[j]; } } else { for (uint j = srcoffset; j < srclen; j += nthsrc) { sampleditems += j; } } //print("sampleditems.length is %d, maxpackets is %d\n",sampleditems.length,maxpackets); if (sampleditems.length > maxpackets) { // y packets of n items uint itemsperpacket = (sampleditems.length / maxpackets); double neededpackets = ((double) sampleditems.length) / ((double) itemsperpacket); uint mxn = 0; //print("itemsperpacket is %u, neededpackets is %.1f\n",itemsperpacket,neededpackets); while (neededpackets > maxpackets) { if (mxn > 1000000) { //print("max packet count of 1 million packets reached, bailing...\n"); return o; } itemsperpacket += 1; neededpackets = ((double) sampleditems.length) / ((double) itemsperpacket); mxn += 1; } //print("itemsperpacket is %u, neededpackets is %.1f\n",itemsperpacket,neededpackets); uint np = (uint) neededpackets; uint dregs = sampleditems.length - (itemsperpacket * ((uint) neededpackets)); uint h = 0; if (dregs > 0) { h = 1; } if ((np + h) > 0) { o = new packet[(np+h)]; uint f = 0; for (uint i = 0; i < np; i++) { o[i] = new packet(); for (uint t = 0; t < itemsperpacket; t++) { o[i].items += sampleditems[f]; f += 1; } } if (dregs > 0) { o[np] = new packet(); for (uint t = 0; t < dregs; t++) { o[np].items += sampleditems[f]; f += 1; } } } } else { // one item per packet for (uint k = 0; k < sampleditems.length; k++) { packet oo = new packet(); oo.items += sampleditems[k]; o += oo; } } //print("packseq complete.\n"); return o; } class gnafdetailsearch : Object { private uint[] chunks; private uint thispacket; private string[] addresscodes; private string[] loccodes; private string postcode; private string streetnum; private string detailsfilepath; public gnafdetailsearch ( uint pak, uint[] chu, string[] ady, string[] loc, string poc, string num, string det ) { thispacket = pak; chunks = chu; addresscodes = ady; loccodes = loc; postcode = poc; streetnum = num; detailsfilepath = det; } public void eval (ref string[] geocodes, ref int packetscomplete, ref int weredonehere, int64[] bidx) { foreach (uint x in chunks) { if (weredonehere > 0) { break; } GLib.File addressfile = GLib.File.new_for_path(detailsfilepath); if (addressfile.query_exists()) { GLib.FileStream dfstr = GLib.FileStream.open(detailsfilepath,"r"); StringBuilder dline = new StringBuilder(""); dfstr.seek(((long) bidx[x]),SET); string drl = dfstr.read_line(); if (drl != null) { dline.append(drl.strip()); if (dline.str.char_count() > 0) { string[] dcols = dline.str.split("|"); for (int n = 0; n < addresscodes.length; n++) { int ii = dline.str.index_of(addresscodes[n]); if (ii != -1) { int qq = dline.str.index_of(loccodes[n]); if (qq != -1) { int oo = dline.str.index_of(postcode); if (oo != -1) { bool gg = ((strcmp(dcols[6],streetnum) == 0) || (strcmp(dcols[17],streetnum) == 0)); if (gg) { int rr = dline.str.index_of("GA"); if (rr != -1) { //rr += 1; int hh = dline.str.index_of("|",rr); if (hh != -1) { StringBuilder adcode = new StringBuilder(""); adcode.append(dline.str.substring(rr,(hh - rr))); mutex.lock(); geocodes[thispacket] = adcode.str; weredonehere = 1; packetscomplete += 1; mutex.unlock(); return; //print("found possible match: %s\n",geocodes[geocodes.length - 1]); } } } } } } } } } } } mutex.lock(); packetscomplete += 1; mutex.unlock(); } } void main() { mutex = GLib.Mutex(); int nthr = ((int) GLib.get_num_processors()); int64[] bidx = {}; uint g = 1000000; string psvdir = "./psv/"; string detailsfilename = "NSW_ADDRESS_DETAIL_psv.psv"; GLib.File detailsfile = GLib.File.new_for_path(psvdir + detailsfilename); if (detailsfile.query_exists()) { print("detailsfile found: %s\n",detailsfile.get_path()); GLib.FileStream fstr = GLib.FileStream.open((psvdir + detailsfilename),"r"); StringBuilder sbline = new StringBuilder(""); int64 accumulatedlines = 0; while (true) { string s = fstr.read_line(); if (s == null) { break; } accumulatedlines += (s.length + 1); bidx += accumulatedlines; } print("%s has %d lines\n",detailsfilename,bidx.length); GLib.FileStream sstr = GLib.FileStream.open((psvdir + detailsfilename),"r"); sstr.seek(((long) bidx[g-1]),SET); string s = sstr.read_line(); if (s != null) { sbline.append(s); } if (sbline.str.char_count() > 0) { print("index check: line 1000000 is %s\n",sbline.str.strip()); } string[] addresscodes = {"SW2880444","SW2880461","SW2873828","SW2880443","SW327749","SW2880450","SW2880438","SW2880437","SW2880447","SW2880458","SW3565179","SW2880446","SW2880445","SW2880441","SW2880439","SW2880455","SW2880453","SW2880449","SW3576944","SW2880464","SW2993890","SW2880460","SW2880442","SW2880454","SW2880451","SW2880448","SW2880452","SW2880440","SW3561635","SW2880459","SW2880456","SW2880457"}; string[] loccodes = {"loceaa57fa3272e","locdd9679f44083","loc96da8afc3d2d","loc2fdf87e092bc","loc7b58be2bee5d","loc22a73fe48374","loc04e9f4bdba8c","locc0764149b600","loc505caada930b","loca9e740a3c1e3","locc28a9c36431f","loc5560df1ac440","locef05745fb16d","loc6b9200960de8","loc768adb4ecaa1","loc730f8cb0d761","loc771141cd5b15","locc606180ec0a9","loc52d65ddc6414","locf43b9d9f4240","loc9c0a49900253","locf27d731b0255","loc48d3cabbbc14","loc67395bf5b53d","loc64288deecac1","loc8ec1cb764645","locb0165da80688","loc435dda1f552b","loc7fac84f28841","loc0dafe55d09fe","loc5a4cd11021e1","loce6b9edea9174"}; string postcode = "2750"; string streetnumber = "2"; string detailsfilepath = (psvdir + detailsfilename); print("multithreading search of %d lines...\n",bidx.length); int64 tts = GLib.get_monotonic_time(); uint[] bq = new uint[0]; packet[] pak = packseq(bq,((uint) bidx.length),false,nthr,1,0); print("split indices into %d packets of %d items...\n",pak.length,pak[0].items.length); string[] geocodes = new string[pak.length]; int weredonehere = 0; int packetscomplete = 0; ThreadPool<gnafdetailsearch> gs = new ThreadPool<gnafdetailsearch>.with_owned_data( (gnafdetailsearch) => {gnafdetailsearch.eval(ref geocodes, ref packetscomplete, ref weredonehere, bidx); },nthr,false ); int pc = 0; for (uint x = 0; x < pak.length; x++) { gs.add( new gnafdetailsearch( x, pak[x].items, addresscodes, loccodes, postcode, streetnumber, detailsfilepath ) ); pc += 1; } while (packetscomplete != pc) { GLib.Thread.usleep(1); } int64 tte = GLib.get_monotonic_time(); print("multithreaded search took %s\n",printusecs(tte-tts)); for (int i = 0; i < geocodes.length; i++) { if (geocodes[i] != null) { print("found geocode id %s\n",geocodes[i]); } } } }
#+RESULTS:
Compilation succeeded - 5 warning(s) NSW_ADDRESS_DETAIL_psv.psv has 5093369 lines index check: line 1000000 is GANSW715681425|2008-04-18|2021-07-07||||1733|||||||||||16|||||NSW2868058||loc91fd57f2790a|P|2330||1733/1062060|2|711245734|7||3048244| multithreading search of 5093369 lines... split indices into 16 packets of 318336 items... multithreaded search took 2.39 s found geocode id GANSW705642589
WRITEFILE
// write string to file, with optional backup // by c.p.brown 2023 bool spew; void backupmyfile (int ind, string f, string d) { File tq = File.new_for_path(f); string bakdirname = d; if (tq.query_exists()) { bool allgood = true; string tabs = ("%*s").printf(ind," ").replace(" ","\t"); string basedir = Path.get_dirname(f); string basefile = Path.get_basename(f); string bakdir = basedir.concat("/",bakdirname,"/"); if (spew) { print("[I/O] %s\t backupfile is %s\n",tabs,basefile); print("[I/O] %s\t backuppath is %s\n",tabs,bakdir); } GLib.Dir bp = null; try { bp = Dir.open (bakdir, 0); } catch (Error e) { print("[I/O] %s WRITE checkdir failed: %s\n",tabs,e.message); allgood = false; } if (!allgood) { try { File tdir = File.new_for_path(bakdir); tdir.make_directory_with_parents(); } catch (Error e) { print("[I/O] %s WRITE makedirs failed: %s\n",tabs,e.message); allgood = false; } } try { bp = Dir.open (bakdir, 0); } catch (Error e) { print("[I/O] %s WRITE checkdir failed: %s\n",tabs,e.message); allgood = false; } if (allgood) { string[] ofx = basefile.split("."); string ofa = ofx[0]; string ofe = ofx[ofx.length - 1]; // find existing backups string ffn = bp.read_name(); int maxincr = 0; while (ffn != null) { if (spew) { print("[I/O] %s\t found backup file: %s\n",tabs,ffn); } string[] ffx = ffn.split("."); if (ffx.length > 1) { string ffc = ffx[ffx.length - 1]; string ffj = ffx[0]; string[] ffs = ffj.split("_"); if (ffs.length > 1) { string ffa = ffs[0]; string ffb = ffs[ffs.length - 1]; if (strcmp(ffa,ofa) == 0) { maxincr = int.max(maxincr,int.parse(ffb)); if (spew) { print("[I/O] %s\t\t backup file name part: %s\n",tabs,ffa); print("[I/O] %s\t\t backup file num part: %s\n",tabs,ffb); print("[I/O] %s\t\t backup file ext part: %s\n",tabs,ffc); } } } } ffn = bp.read_name(); } if (spew) { print("[I/O] %s\t backup max num is %d\n",tabs,maxincr); } maxincr += 1; string[]cmda = {"cp", tq.get_path(), bakdir.concat(ofa, "_", "%d".printf(maxincr), ".", ofe)}; if (spew) { print("[I/O] %s\t\t attempting to back-up %s to %s...\n",tabs,tq.get_path(),"%s%s_%d.%s".printf(bakdir,ofa,maxincr,ofe)); } try { Pid backpid; GLib.Process.spawn_async(null, cmda, null, GLib.SpawnFlags.SEARCH_PATH, null, out backpid); if (spew) { print("[I/O] %s\t\t\t file copied.\n",tabs); } } catch (Error e) { print("[I/O] %s\t\t cp spawn failed: %s\n", tabs, e.message); } } } } string writefiletosubdir (int ind, string p, string n, string e, string s, bool b) { string tabs = ("%*s").printf(ind," ").replace(" ","\t"); if (spew) { print("[I/O] %s WRITE started...\n",tabs); } if (s.strip() != "" && n.strip() != "" && e.strip() != "") { bool dobackup = b; bool allgood = true; string pth = GLib.Environment.get_current_dir(); if (p.strip() != "") { pth = pth.concat("/", p, "/"); } else { pth = pth.concat("/"); } GLib.Dir dcr = null; if (spew) { print("[I/O] %s WRITE check dir: %s\n",tabs,pth); } try { dcr = Dir.open (pth, 0); } catch (Error e) { print("[I/O] %s WRITE checkdir failed: %s\n",tabs,e.message); allgood = false; } File hfile = File.new_for_path(pth.concat(n,".",e)); File hdir = File.new_for_path(pth); if (allgood == false) { if (spew) { print("[I/O] %s WRITE make dir...\n",tabs); } try { hdir.make_directory_with_parents(); if (spew) { print("[I/O] %s WRITE made export dir: %s\n",tabs,pth); } allgood = true; } catch (Error e) { print("[I/O] %s WRITE makedirs failed: %s\n",tabs,e.message); allgood = false; } } if (allgood) { if (dobackup) { backupmyfile ((ind + 1), hfile.get_path(), "bak"); } if (spew) { print("[I/O] %s WRITE writing...\n",tabs); } try { FileOutputStream hose = hfile.replace(null,false,FileCreateFlags.PRIVATE); hose.write(s.data); if (spew) { print("[I/O] %s WRITE written to: %s\n",tabs,hfile.get_path()); } if (spew) { print("[I/O] %s WRITE ended.\n",tabs); } return hfile.get_path(); } catch (Error e) { print("[I/O] %s WRITE failed: %s\n",tabs,e.message); } } else { if (spew) { print("[I/O] %s WRITE couldn't make dir, aborting export.\n",tabs); } } } else { if (spew) { print("[I/O] %s WRITE empty input, aborting.\n",tabs); } } return ""; } void main() { spew = true; string wp = writefiletosubdir(0,"testfile", "test", "txt", "file content", true); }
#+RESULTS:
Compilation succeeded - 1 warning(s) [I/O] WRITE started... [I/O] backupfile is test.txt [I/O] found backup file: test_1.txt [I/O] backup file name part: test [I/O] backup file num part: 1 [I/O] backup file ext part: txt [I/O] found backup file: test_2.txt [I/O] backup file name part: test [I/O] backup file num part: 2 [I/O] backup file ext part: txt [I/O] found backup file: test_3.txt [I/O] backup file name part: test [I/O] backup file num part: 3 [I/O] backup file ext part: txt [I/O] found backup file: test_4.txt [I/O] backup file name part: test [I/O] backup file num part: 4 [I/O] backup file ext part: txt [I/O] backup max num is 4 [I/O] file copied. [I/O] WRITE writing... [I/O] WRITE ended.
GTK4
GESTUREDRAG

test gesture events...

// test gtk events in a bare-minimum application // by c.p.brown 2023 using Gtk; int main (string[] args) { Gtk.Application wut = new Gtk.Application ("com.test.test", GLib.ApplicationFlags.FLAGS_NONE); wut.activate.connect(() => { double[] mdn = {0.0,0.0}; double[] moo = {0.0,0.0}; double[] mof = {0.0,0.0}; Gtk.ApplicationWindow win = new Gtk.ApplicationWindow(wut); Gtk.DrawingArea im = new Gtk.DrawingArea(); im.margin_top = 10; im.margin_bottom = 10; im.margin_start = 10; im.margin_end = 10; Gtk.GestureDrag gd = new Gtk.GestureDrag(); im.add_controller(gd); im.set_draw_func((da,ctx,daw,dah) => { var bc = Gdk.RGBA(); bc.parse("#112633"); ctx.set_source_rgba(bc.red,bc.green,bc.blue,1); ctx.paint(); bc.parse("#DDDD88DD"); ctx.set_source_rgba(bc.red,bc.green,bc.blue,bc.alpha); ctx.set_line_width(2.0); ctx.move_to(mof[0],0.0); ctx.line_to(mof[0],dah); ctx.stroke(); ctx.move_to(0.0,mof[1]); ctx.line_to(daw,mof[1]); ctx.stroke(); string inf = "x = %0.2f, y = %0.2f".printf(moo[0],moo[1]); ctx.select_font_face("Monospace",Cairo.FontSlant.NORMAL,Cairo.FontWeight.BOLD); Cairo.TextExtents extents; ctx.text_extents (inf, out extents); ctx.set_source_rgba(((float) 0.9),((float) 0.9),((float) 0.4),((float) 0.9)); ctx.move_to(20.0,(dah - extents.height)); ctx.show_text(inf); }); gd.drag_begin.connect((event,x,y) => { print("device button is %u\n", event.get_current_button()); mdn = {x,y}; }); gd.drag_update.connect((event,x,y) => { moo = {x,y}; mof = {mdn[0] + x,mdn[1] + y}; im.queue_draw(); }); win.default_width = 300; win.default_height = 300; win.set_child(im); win.present(); }); return wut.run(args); }
#+RESULTS:

GTKMENU

custom gtk menu

// custom menu example // menu items change state of other items // by c.p.brown 2025 bool doup; public class mymenu : Gtk.Box { public class mymenuitem : Gtk.Box { public int index; public Gtk.ToggleButton itemtoggle; public mymenuitem (int x, string n, bool t) { index = x; itemtoggle = new Gtk.ToggleButton(); itemtoggle.set_label(n); itemtoggle.set_active(t); itemtoggle.hexpand = true; this.append(itemtoggle); itemtoggle.toggled.connect((buh) => { if (doup) { doup = false; myparams mycontainercontainer = (myparams) this.get_ancestor(typeof(myparams)); mycontainercontainer.myselectionlabel.set_text(buh.get_label()); mymenu mycontainer = (mymenu) this.get_ancestor(typeof(mymenu)); mymenuitem mysibling = (mymenuitem) mycontainer.get_first_child(); while (mysibling != null) { if (mysibling.index != index) { mysibling.itemtoggle.active = false; } mysibling = (mymenuitem) mysibling.get_next_sibling(); } doup = true; } }); } } public mymenu (string[] d) { if ((d.length & 1) == 0) { int x = 0; for (int i = 0; i < d.length; i+=2) { bool tf = false; if (strcmp(d[i+1],"TRUE") == 0) { tf = true; } this.append(new mymenuitem (x, "%d_%s".printf(x,d[i]), tf)); x += 1; } } this.set_orientation(VERTICAL); this.set_spacing(2); } } public class myparams : Gtk.Box { public Gtk.Label myselectionlabel; public myparams () { this.set_orientation(VERTICAL); this.set_spacing(10); Gtk.MenuButton mymenubutton = new Gtk.MenuButton(); Gtk.Popover mymenupopover = new Gtk.Popover(); Gtk.ScrolledWindow mymenuscroll = new Gtk.ScrolledWindow(); myselectionlabel = new Gtk.Label(""); string[] mymenudata = { "ONE","FALSE", "TWO","FALSE", "THREE","FALSE", "FOUR","FALSE", "FIVE","FALSE", "SIX","FALSE", "SEVEN","FALSE", "EIGHT","FALSE", "NINE","FALSE", "TEN","FALSE" }; mymenu mymenuscrollbox = new mymenu(mymenudata); mymenupopover.set_child(mymenuscroll); mymenuscroll.set_child(mymenuscrollbox); mymenubutton.popover = mymenupopover; mymenubutton.hexpand = true; myselectionlabel.hexpand = true; Gtk.Requisition rq = new Gtk.Requisition(); Gtk.Requisition mq = new Gtk.Requisition(); mymenuscrollbox.get_preferred_size(out mq,out rq); mymenupopover.width_request = rq.width + 30; mymenupopover.height_request = int.min(360,rq.height); this.append(mymenubutton); this.append(myselectionlabel); } } int main(string[] args) { Gtk.Application myapp = new Gtk.Application("com.mytest.mytest",GLib.ApplicationFlags.DEFAULT_FLAGS); myapp.activate.connect (() => { doup = false; Gtk.ApplicationWindow mywin = new Gtk.ApplicationWindow(myapp); mywin.set_child(new myparams()); doup = true; mywin.default_width = 120; mywin.default_height = 120; mywin.present(); }); return myapp.run(args); }
HSV

Simple GTK4 hsv<->rgb test.

double dmod (double l, double r) { if (l >= 0) { return (l % r); } if (l >= -r) { return (l + r); } return ((l % r) + r) % r; } double[] drgbatodhsva (double r, double g, double b, double a) { // pack rgba into a single 32-bit integer as hsva // by c.p.brown 2026 // // based on Alvy Ray Smith's HSV specification (1978) // https://alvyray.com/Papers/CG/hsv2rgb.htm // // depends on dmod() modulo function to handle negative numbers double cr = double.max(0.0,double.min(1.0,r)); double cg = double.max(0.0,double.min(1.0,g)); double cb = double.max(0.0,double.min(1.0,b)); double ca = double.max(0.0,double.min(1.0,a)); double h = 0.0; double s = 0.0; double v = 0.0; double mx = double.max(cr,double.max(cg,cb)); double mi = double.min(cr,double.min(cg,cb)); double d = mx - mi; v = mx; if (v == 0.0) { s = 0.0; } else { s = d / mx; } if (mx == mi) { h = 0.0; } else { if (mx == cr) { h = dmod(((1.0 / 6.0) * ((cg - cb) / d)),1.0); } else { if (mx == cg) { h = ((1.0 / 6.0) * (2.0 + ((cb - cr) / d))); } else { h = ((1.0 / 6.0) * (4.0 + ((cr - cg) / d))); } } } h = double.min(double.max(h,0.0),1.0); s = double.min(double.max(s,0.0),1.0); v = double.min(double.max(v,0.0),1.0); a = ca; return {h,s,v,a}; } double[] dhsvatodrgba (double h, double s, double v, double a) { // convert double h,s,v,a to double[] rgba // by c.p.brown 2026 // // based on the work of Alvy Ray Smith (1978) // https://alvyray.com/Papers/CG/hsv2rgb.htm // // p 1 prints color information // p 2 prints a list of uints to copy for reverse conversion tests double hh = double.max(0.0,double.min(1.0,h)); double ss = double.max(0.0,double.min(1.0,s)); double vv = double.max(0.0,double.min(1.0,v)); double aa = double.max(0.0,double.min(1.0,a)); double rr = vv; double gg = vv; double bb = vv; if (ss > 0.0) { double hd = h * 6.0; int seg = (int) hd; double frac = hd - seg; if ((seg & 1) == 0) { frac = (1.0 - frac); } double xx = vv * (1.0 - ss); double yy = vv * (1.0 - (ss * frac)); if (seg == 0) { rr = vv; gg = yy; bb = xx; } else { if (seg == 1) { rr = yy; gg = vv; bb = xx; } else { if (seg == 2) { rr = xx; gg = vv; bb = yy; } else { if (seg == 3) { rr = xx; gg = yy; bb = vv; } else { if (seg == 4) { rr = yy; gg = xx; bb = vv; } else { if (seg == 5) { rr = vv; gg = xx; bb = yy; } } } } } } } return {rr,gg,bb,aa}; } string drgbatohex (double r, double g, double b, double a) { uint8 rr = ((uint8) ((double.min(double.max(r,0.0),1.0) * 255.0) + 0.5)); uint8 gg = ((uint8) ((double.min(double.max(g,0.0),1.0) * 255.0) + 0.5)); uint8 bb = ((uint8) ((double.min(double.max(b,0.0),1.0) * 255.0) + 0.5)); uint8 aa = ((uint8) ((double.min(double.max(a,0.0),1.0) * 255.0) + 0.5)); StringBuilder sb = new StringBuilder(""); sb.append("#%02X%02X%02X%02X".printf(rr,gg,bb,aa)); return sb.str; } double[] hextodrgba (string hex) { // read colors from hex, // removes leading hash, ensures hex string is 8 characters // by c.p.brown 2026 StringBuilder sb = new StringBuilder(""); sb.append(hex); if (sb.str.get_char(sb.str.index_of_nth_char(0)) == '#') { sb.replace("#","",1); } if (sb.str.char_count() > 8) { sb.str = sb.str.substring(0,8); } while (sb.str.char_count() < 8) { sb.append("0"); } uint v = uint.parse(sb.str,16); double r = ((double) ((v >> 24) & 0xFF)) / 255.0; double g = ((double) ((v >> 16) & 0xFF)) / 255.0; double b = ((double) ((v >> 8) & 0xFF)) / 255.0; double a = ((double) (v & 0xFF)) / 255.0; return {r,g,b,a}; } bool doup; public class myparams : Gtk.Box { public Gtk.DrawingArea colorbox; public Gtk.Scale redscale; public Gtk.Scale greenscale; public Gtk.Scale bluescale; public Gtk.Scale huescale; public Gtk.Scale satscale; public Gtk.Scale valscale; public Gtk.Label redlabel; public Gtk.Label greenlabel; public Gtk.Label bluelabel; public Gtk.Label huelabel; public Gtk.Label satlabel; public Gtk.Label vallabel; public Gtk.SpinButton redentry; public Gtk.SpinButton greenentry; public Gtk.SpinButton blueentry; public Gtk.SpinButton hueentry; public Gtk.SpinButton satentry; public Gtk.SpinButton valentry; public Gtk.Entry hexentry; public myparams () { // adjustment last two args are for scrollbar handles, to limit how far the scale can go without moving the handle 'offscreen'. Set to zero for sliders, otherwise the slider can't reach the upper range. Gtk.Adjustment redadjustment = new Gtk.Adjustment(0.0,0.0,1.0,0.1,0.0,0.0); Gtk.Adjustment greenadjustment = new Gtk.Adjustment(0.0,0.0,1.0,0.1,0.0,0.0); Gtk.Adjustment blueadjustment = new Gtk.Adjustment(0.0,0.0,1.0,0.1,0.0,0.0); Gtk.Adjustment hueadjustment = new Gtk.Adjustment(0.0,0.0,1.0,0.1,0.0,0.0); Gtk.Adjustment satadjustment = new Gtk.Adjustment(0.0,0.0,1.0,0.1,0.0,0.0); Gtk.Adjustment valadjustment = new Gtk.Adjustment(0.0,0.0,1.0,0.1,0.0,0.0); colorbox = new Gtk.DrawingArea(); redscale = new Gtk.Scale(HORIZONTAL,redadjustment); greenscale = new Gtk.Scale(HORIZONTAL,greenadjustment); bluescale = new Gtk.Scale(HORIZONTAL,blueadjustment); huescale = new Gtk.Scale(HORIZONTAL,hueadjustment); satscale = new Gtk.Scale(HORIZONTAL,satadjustment); valscale = new Gtk.Scale(HORIZONTAL,valadjustment); redlabel = new Gtk.Label("R"); greenlabel = new Gtk.Label("G"); bluelabel = new Gtk.Label("B"); huelabel = new Gtk.Label("H"); satlabel = new Gtk.Label("S"); vallabel = new Gtk.Label("V"); redentry = new Gtk.SpinButton(redadjustment,1.0,3); greenentry = new Gtk.SpinButton(greenadjustment,1.0,3); blueentry = new Gtk.SpinButton(blueadjustment,1.0,3); hueentry = new Gtk.SpinButton(hueadjustment,1.0,3); satentry = new Gtk.SpinButton(satadjustment,1.0,3); valentry = new Gtk.SpinButton(valadjustment,1.0,3); hexentry = new Gtk.Entry(); Pango.Layout wc = new Pango.Layout(this.get_pango_context()); wc.set_text("W",-1); int fontwidth = 10; int fontheight = 10; wc.get_size(out fontwidth, out fontheight); wc.get_pixel_size(out fontwidth, out fontheight); redlabel.width_request = (fontwidth * 3); redscale.hexpand = true; //redlabel.xalign = ((float) 0.0); greenlabel.width_request = (fontwidth * 3); greenscale.hexpand = true; bluelabel.width_request = (fontwidth * 3); bluescale.hexpand = true; huelabel.width_request = (fontwidth * 3); huescale.hexpand = true; satlabel.width_request = (fontwidth * 3); satscale.hexpand = true; vallabel.width_request = (fontwidth * 3); valscale.hexpand = true; colorbox.height_request = 200; hexentry.set_text("#00000000"); hexentry.hexpand = true; Gtk.Box redbox = new Gtk.Box(HORIZONTAL,0); Gtk.Box greenbox = new Gtk.Box(HORIZONTAL,0); Gtk.Box bluebox = new Gtk.Box(HORIZONTAL,0); Gtk.Box huebox = new Gtk.Box(HORIZONTAL,0); Gtk.Box satbox = new Gtk.Box(HORIZONTAL,0); Gtk.Box valbox = new Gtk.Box(HORIZONTAL,0); Gtk.Box hexbox = new Gtk.Box(HORIZONTAL,0); redbox.append(redlabel); redbox.append(redscale); redbox.append(redentry); greenbox.append(greenlabel); greenbox.append(greenscale); greenbox.append(greenentry); bluebox.append(bluelabel); bluebox.append(bluescale); bluebox.append(blueentry); huebox.append(huelabel); huebox.append(huescale); huebox.append(hueentry); satbox.append(satlabel); satbox.append(satscale); satbox.append(satentry); valbox.append(vallabel); valbox.append(valscale); valbox.append(valentry); hexbox.append(hexentry); redscale.value_changed.connect(() => { if (doup) { doup = false; double[] hsv = drgbatodhsva(redscale.adjustment.value,greenscale.adjustment.value,bluescale.adjustment.value,1.0); huescale.set_value(hsv[0]); satscale.set_value(hsv[1]); valscale.set_value(hsv[2]); hexentry.set_text(drgbatohex(redscale.adjustment.value,greenscale.adjustment.value,bluescale.adjustment.value,1.0)); colorbox.queue_draw(); doup = true; } }); greenscale.value_changed.connect(() => { if (doup) { doup = false; double[] hsv = drgbatodhsva(redscale.adjustment.value,greenscale.adjustment.value,bluescale.adjustment.value,1.0); huescale.set_value(hsv[0]); satscale.set_value(hsv[1]); valscale.set_value(hsv[2]); hexentry.set_text(drgbatohex(redscale.adjustment.value,greenscale.adjustment.value,bluescale.adjustment.value,1.0)); colorbox.queue_draw(); doup = true; } }); bluescale.value_changed.connect(() => { if (doup) { doup = false; double[] hsv = drgbatodhsva(redscale.adjustment.value,greenscale.adjustment.value,bluescale.adjustment.value,1.0); huescale.set_value(hsv[0]); satscale.set_value(hsv[1]); valscale.set_value(hsv[2]); hexentry.set_text(drgbatohex(redscale.adjustment.value,greenscale.adjustment.value,bluescale.adjustment.value,1.0)); colorbox.queue_draw(); doup = true; } }); huescale.value_changed.connect(() => { if (doup) { doup = false; double[] rgb = dhsvatodrgba(huescale.adjustment.value,satscale.adjustment.value,valscale.adjustment.value,1.0); redscale.set_value(rgb[0]); greenscale.set_value(rgb[1]); bluescale.set_value(rgb[2]); hexentry.set_text(drgbatohex(redscale.adjustment.value,greenscale.adjustment.value,bluescale.adjustment.value,1.0)); colorbox.queue_draw(); doup = true; } }); satscale.value_changed.connect(() => { if (doup) { doup = false; double[] rgb = dhsvatodrgba(huescale.adjustment.value,satscale.adjustment.value,valscale.adjustment.value,1.0); redscale.set_value(rgb[0]); greenscale.set_value(rgb[1]); bluescale.set_value(rgb[2]); hexentry.set_text(drgbatohex(redscale.adjustment.value,greenscale.adjustment.value,bluescale.adjustment.value,1.0)); colorbox.queue_draw(); doup = true; } }); valscale.value_changed.connect(() => { if (doup) { doup = false; double[] rgb = dhsvatodrgba(huescale.adjustment.value,satscale.adjustment.value,valscale.adjustment.value,1.0); redscale.set_value(rgb[0]); greenscale.set_value(rgb[1]); bluescale.set_value(rgb[2]); hexentry.set_text(drgbatohex(redscale.adjustment.value,greenscale.adjustment.value,bluescale.adjustment.value,1.0)); colorbox.queue_draw(); doup = true; } }); hexentry.changed.connect(() => { if (doup) { doup = false; if (hexentry.text.char_count() != 0) { double[] rgb = hextodrgba(hexentry.text); redscale.set_value(rgb[0]); greenscale.set_value(rgb[1]); bluescale.set_value(rgb[2]); double[] hsv = drgbatodhsva(rgb[0],rgb[1],rgb[2],1.0); huescale.set_value(hsv[0]); satscale.set_value(hsv[1]); valscale.set_value(hsv[2]); colorbox.queue_draw(); } doup = true; } }); colorbox.set_draw_func((ds,ctx,daw,dah) => { ctx.set_source_rgba( redscale.adjustment.value, greenscale.adjustment.value, bluescale.adjustment.value, 1.0 ); ctx.paint(); }); this.orientation = VERTICAL; this.spacing = 5; this.append(colorbox); this.append(redbox); this.append(greenbox); this.append(bluebox); this.append(huebox); this.append(satbox); this.append(valbox); this.append(hexbox); } } int main(string[] args) { Gtk.Application myapp = new Gtk.Application("com.mytest.mytest",GLib.ApplicationFlags.DEFAULT_FLAGS); myapp.activate.connect (() => { doup = false; Gtk.ApplicationWindow mywin = new Gtk.ApplicationWindow(myapp); mywin.set_child(new myparams()); doup = true; mywin.default_width = 500; mywin.default_height = 120; mywin.present(); }); return myapp.run(args); }
REDBUTTON

A button with a signal that changes its color
Try to make this code as simple as possible without golfing.
GTK OOP is great for complex interfaces, onerous for simple ones, and thus a massive hurdle for new users, especially those who were spoiled with things like:

RED [ needs 'View ] View/tight [ panel [ buton 120x30 red "DOIT" [ face/color: green face/text: "DONE" ] ] ]
// gtk ui simplification challenge // make a red button that changes to green when clicked // reduce the code as much as possible without golfing // by c.b.brown 2024 using Gtk; int main(string[] args) { Gtk.Application myapp = new Gtk.Application("com.mytest.mytest",GLib.ApplicationFlags.DEFAULT_FLAGS); myapp.activate.connect (() => { Gtk.ApplicationWindow mywin = new Gtk.ApplicationWindow(myapp); Gtk.Box mybox = new Gtk.Box(HORIZONTAL,0); Gtk.Button mybutton = new Gtk.Button.with_label("DOIT"); mybutton.set_css_classes({"redbutton"}); mybutton.hexpand = true; mybox.append(mybutton); mybutton.clicked.connect(() => { mybutton.set_css_classes({"greenbutton"}); mybutton.label = "DONE"; }); string mycss = """ .redbutton { background: #FF0000; } .greenbutton { background: #00FF00; } """; Gtk.CssProvider mycsp = new Gtk.CssProvider(); mycsp.load_from_string(mycss); Gdk.Display thisdisplay = Gdk.Display.get_default(); Gtk.StyleContext.add_provider_for_display(thisdisplay,mycsp,Gtk.STYLE_PROVIDER_PRIORITY_USER); mywin.set_child(mybox); mywin.default_width = 120; mywin.default_height = 70; mywin.present(); }); return myapp.run(args); }
SCRAPE

Get rendered text of a html/java document.
Uses webkit, which has to display in a ui before it will do anything else.
There might be a workaround, need more testing.

int main() { string u = "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent"; // TODO: research how to check site existence without leaking infos WebKit.Settings wvs = new WebKit.Settings(); // disable unnecessary web-browser features wvs.set_javascript_can_access_clipboard(false); wvs.set_javascript_can_open_windows_automatically(false); wvs.set_hardware_acceleration_policy(NEVER); wvs.set_enable_webgl(false); wvs.set_enable_webaudio(false); wvs.set_enable_page_cache(false); wvs.set_enable_offline_web_application_cache(false); wvs.set_enable_media_stream(false); wvs.set_enable_html5_local_storage(false); wvs.set_enable_html5_database(false); wvs.set_user_agent_with_application_details("Mozilla","5.0"); wvs.set_allow_modal_dialogs(false); wvs.set_allow_file_access_from_file_urls(false); print("webview user agent is: %s\n",wvs.get_user_agent()); print("loading url: %s ...\n",u); Gtk.Application myapp = new Gtk.Application("com.mytest.webkittest",GLib.ApplicationFlags.DEFAULT_FLAGS); myapp.activate.connect (() => { Gtk.Box listbox = new Gtk.Box(VERTICAL,0); Gtk.Box controlbox = new Gtk.Box(HORIZONTAL,5); Gtk.Button jsbutton = new Gtk.Button.with_label("run"); Gtk.Entry addy = new Gtk.Entry(); Gtk.Button gobutton = new Gtk.Button.with_label("go"); Gtk.ApplicationWindow mywin = new Gtk.ApplicationWindow(myapp); Gtk.ScrolledWindow wvsv = new Gtk.ScrolledWindow(); WebKit.WebView wv = new WebKit.WebView(); wv.set_settings(wvs); wv.vexpand = true; wv.hexpand = true; wvsv.hexpand = true; addy.hexpand = true; controlbox.hexpand = false; controlbox.append(jsbutton); controlbox.append(addy); controlbox.append(gobutton); wvsv.set_child(wv); listbox.append(wvsv); listbox.append(controlbox); mywin.set_child(listbox); mywin.default_width = 800; mywin.default_height = 800; mywin.present(); StringBuilder tidyurl = new StringBuilder(""); gobutton.clicked.connect(() => { u = addy.text.strip(); tidyurl.erase(0,-1); tidyurl.append(u); tidyurl.replace(".html",""); tidyurl.replace("http://",""); tidyurl.replace("https://",""); tidyurl.replace("www.",""); tidyurl.replace("/","_"); tidyurl.replace(".","_"); tidyurl.replace("?",""); tidyurl.replace("%%",""); tidyurl.replace("=",""); tidyurl.replace("-",""); tidyurl.replace("+",""); tidyurl.replace("*",""); tidyurl.replace("\\",""); tidyurl.replace("&",""); wv.load_uri(u); }); wv.load_changed.connect((lev) => { if (lev == FINISHED) { print("page loaded: %s\n",wv.uri); addy.text = wv.uri; u = addy.text.strip(); tidyurl.erase(0,-1); tidyurl.append(u); tidyurl.replace(".html",""); tidyurl.replace("http://",""); tidyurl.replace("https://",""); tidyurl.replace("www.",""); tidyurl.replace("/","_"); tidyurl.replace(".","_"); tidyurl.replace("?",""); tidyurl.replace("%%",""); tidyurl.replace("=",""); tidyurl.replace("-",""); tidyurl.replace("+",""); tidyurl.replace("*",""); tidyurl.replace("\\",""); tidyurl.replace("&",""); } }); jsbutton.clicked.connect(() => { StringBuilder extracted = new StringBuilder(""); print("evaluating script...\n"); Value h = new Value(typeof(string)); StringBuilder pagetitle = new StringBuilder(""); pagetitle.append(wv.title); pagetitle.replace(" ","_",-1); //wv.evaluate_javascript( // "document.write(document.body.innerText)",-1,null,null,null //); //const links = document.getElementsByTagName('a'); //for (let link of links) { console.log(link.href); } wv.evaluate_javascript( "document.body.innerText",-1,null,null,null,(webv,asyres) => { print("result type is %s\n",asyres.get_type().name()); WebKit.WebView wwebv = (WebKit.WebView) webv; var huh = wwebv.evaluate_javascript.end(asyres); extracted.append(huh.to_string()); //print("result val is %s\n",extracted.str); //GLib.Thread.usleep(5000); if (extracted.str.char_count() > 0) { if (extracted.str.strip().char_count() > 0) { print("OK\n"); print("saving scraped text..."); string l = ("./" + tidyurl.str + "_" + pagetitle.str + ".txt"); File lf = File.new_for_path(l); try { FileOutputStream lfs = lf.replace(null,false,FileCreateFlags.PRIVATE); lfs.write(extracted.data); print("DONE, saved to: %s\n",l); } catch (Error e) { print("error writing to %s:\n\t%s\n",l,e.message); } } else { print("error: extracted text is emty\n"); } } else { print("error: extracted text is empty\n"); } } ); }); //wv.terminate_web_process(); //wv.try_close(); }); return myapp.run(); }
#+RESULTS:
Compilation succeeded - 4 warning(s) webview user agent is: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/60.5 Safari/605.1.15 Mozilla/5.0 loading url: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent ... page loaded: https://mapdoor.com/au/nsw/bunnings evaluating script... result type is GTask OK saving scraped text...DONE, saved to: ./mapdoor_com_au_nsw_bunnings_Bunnings_locations_in_New_South_Wales_|_Mapdoor.txt page loaded: https://mapdoor.com/au/vic/bunnings evaluating script... result type is GTask OK saving scraped text...DONE, saved to: ./mapdoor_com_au_vic_bunnings_Bunnings_locations_in_Victoria_|_Mapdoor.txt page loaded: https://mapdoor.com/au/act/bunnings evaluating script... result type is GTask OK saving scraped text...DONE, saved to: ./mapdoor_com_au_act_bunnings_Bunnings_locations_in_Australian_Capital_Territory_|_Mapdoor.txt page loaded: https://mapdoor.com/au/sa/bunnings evaluating script... result type is GTask OK saving scraped text...DONE, saved to: ./mapdoor_com_au_sa_bunnings_Bunnings_locations_in_South_Australia_|_Mapdoor.txt page loaded: https://mapdoor.com/au/wa/bunnings evaluating script... result type is GTask OK saving scraped text...DONE, saved to: ./mapdoor_com_au_wa_bunnings_Bunnings_locations_in_Western_Australia_|_Mapdoor.txt page loaded: https://mapdoor.com/au/nt/bunnings evaluating script... result type is GTask OK saving scraped text...DONE, saved to: ./mapdoor_com_au_nt_bunnings_Bunnings_locations_in_Northern_Territory_|_Mapdoor.txt page loaded: https://mapdoor.com/au/qld/bunnings evaluating script... result type is GTask OK saving scraped text...DONE, saved to: ./mapdoor_com_au_qld_bunnings_Bunnings_locations_in_Queensland_|_Mapdoor.txt page loaded: https://mapdoor.com/au/tas/bunnings evaluating script... result type is GTask OK saving scraped text...DONE, saved to: ./mapdoor_com_au_tas_bunnings_Bunnings_locations_in_Tasmania_|_Mapdoor.txt page loaded: https://www.bunnings.com.au/stores evaluating script... result type is GTask OK saving scraped text...DONE, saved to: ./bunnings_com_au_stores_Our_Stores_-_Bunnings_Australia.txt
SCROLLEDWINDOW
// test hexpand for a forum question using Gtk; int main(string[] args) { Gtk.Application myapp = new Gtk.Application("com.mytest.mytest",GLib.ApplicationFlags.DEFAULT_FLAGS); myapp.activate.connect (() => { Gtk.ApplicationWindow mywin = new Gtk.ApplicationWindow(myapp); Gtk.Box mybox = new Gtk.Box(VERTICAL,0); Gtk.ScrolledWindow myscroll = new Gtk.ScrolledWindow(); Gtk.TextView myeditor = new Gtk.TextView(); Gtk.Label mystatus = new Gtk.Label("infos go here"); myeditor.vexpand = true; myscroll.set_child(myeditor); mybox.append(myscroll); mybox.append(mystatus); mywin.set_child(mybox); myeditor.buffer.changed.connect(() => { StringBuilder bb = new StringBuilder(); bb.append(myeditor.buffer.text); int cc = bb.str.char_count(); uint nwl = bb.replace("\n","",0) + 1; mystatus.label = "%u lines, %d characters".printf(nwl,cc); }); mywin.default_width = 500; mywin.default_height = 500; mywin.present(); }); return myapp.run(args); }
MISC_TESTS
BITWISE

Misc bitwise tests.

string printallmyuint8bits (uint8 n) { int b = 7; string o = ""; for (int i = b; i >= 0; i--) { o = o + "%d".printf((n >> i) & 1); } return o; } string printuintarray (uint[] s, uint f, uint b) { string[] ii = {"", "\"", "{", "[", "[", "| ", "", ""}; string[] dd = {";", ",", ",", " ", ",", " | ", " ", "\n"}; string[] oo = {"", "\"", "}", "]", "]", " |", "", ""}; string o = ii[f]; bool bitshift = (b > 0); for (uint i = 0; i < (s.length - 1); i++) { if (bitshift) { o = (o + "%u".printf((s[i] >> b)) + dd[f]); } else { o = (o + "%u".printf(s[i]) + dd[f]); } } if (bitshift) { o = (o + "%u".printf((s[s.length - 1] >> b)) + oo[f]); } else { o = (o + "%u".printf(s[s.length - 1]) + oo[f]); } return o; } string printmem (int64 m) { // m is the memory in bytes string ms = "%.2f PB".printf((((double) m) / 1000000000000000.0) ); if (m < 1000) { return "%lld bytes".printf(m); } if (m < 1000000) { return "%.2f KB".printf((((double) m) / 1000.0) ); } if (m < 1000000000) { return "%.2f MB".printf((((double) m) / 1000000.0) ); } if (m < 1000000000000) { return "%.2f GB".printf((((double) m) / 1000000000.0)); } if (m < 1000000000000000) { return "%.2f TB".printf((((double) m) / 1000000000000.0)); } return ms; } void main() { print("int.MAX is %u\n",((uint) int.MAX)); print("uint.MAX is %lld\n",((int64) uint.MAX)); print("int64.MAX is %lld\n",((int64) int64.MAX)); print("size of uint is %u bytes\n",((uint) sizeof(uint))); print("max size of uint[int.MAX] is %s\n",printmem(((int64) sizeof(uint)) * ((int64) int.MAX))); print("size of uint8 is %u bytes\n",((uint) sizeof(uint8))); print("max size of uint8[int.MAX] is %s\n\n",printmem(((int64) sizeof(uint8)) * ((int64) int.MAX))); print("\nstoring id + value...\n\n"); uint i = 123456789; print("index i is %u, value is 1\n",i); print("(i |= 1) is %u\n",(i |= 1)); print("(i & 1) is %u\n",(i & 1)); print("i & ~(1 << 1) is %u\n",(i & ~(1 << 1))); i = 123456789; print("\nindex i is %u, value is 0\n",i); print("(i |= 0) is %u\n",(i |= 0)); print("(i & 1) is %u\n",(i & 0)); print("i & ~(1 << 1) is %u\n",(i & ~(1 << 1))); i = 123456789; print("\nindex i is %u, value is 1\n",i); i = ((i << 1) | 1); print("(i << 1) |= 1 is %u\n",i); print("(i & 1) is %u\n",(i & 1)); print("(i >> 1) is %u\n",(i >> 1)); i = 123456789; print("\nindex i is %u, value is 0\n",i); i = ((i << 1) | 0); print("(i << 1) |= 0 is %u\n",i); print("(i & 1) is %u\n",(i & 1)); print("(i >> 1) is %u\n",(i >> 1)); i = 123456789; uint v = 3; print("\nindex i is %u, value v is %u\n",i,v); uint r = ((i << 4) | v); print("(i << 4) | %u is %u\n",v,r); print("(i & 0xF) is %u\n",(r & 0xF)); print("(i >> 4) is %u\n",(r >> 4)); i = 123456789; v = 15; print("\nindex i is %u, value v is %u (max @ 4bit)\n",i,v); r = ((i << 4) | v); print("(i << 4) | %u is %u\n",v,r); print("(i & 0xF) is %u\n",(r & 0xF)); print("(i >> 4) is %u\n",(r >> 4)); i = 123456789; v = 255; print("\nindex i is %u, value v is %u (max @ 8bit)\n",i,v); r = ((i << 8) | v); print("(i << 8) | %u is %u\n",v,r); print("(i & 0xFF) is %u\n",(r & 0xFF)); print("(i >> 8) is %u -- not enough free bits\n",(r >> 8)); i = 12; v = 255; print("\nindex i is %u, value v is %u (max @ 8bit)\n",i,v); r = ((i << 8) | v); print("(i << 8) | %u is %u\n",v,r); print("(i & 0xFF) is %u\n",(r & 0xFF)); print("(i >> 8) is %u -- works as %u has enough bits to spare\n",(r >> 8),i); i = 1000000000; print("\nreal-world case, store a 1 or 0 value with a cell index in a large-ish array:\nindex i is %u, value is 1\n",i); i = ((i << 1) | 1); print("(i << 1) |= 1 is %u\n",i); print("(i & 1) is %u\n",(i & 1)); print("(i >> 1) is %u\n",(i >> 1)); i = 1000000000; print("\nindex i is %u, value v is 0\n",i); i = ((i << 1) | 0); print("(i << 1) |= 0 is %u\n",i); print("(i & 1) is %u\n",(i & 1)); print("(i >> 1) is %u\n",(i >> 1)); uint64 q = 1000000000; print("\nindex q is %lld, value v is 500 000 000\n",q); q = ((q << 30) | 500000000); print("(q << 30) | 500000000 is %lld\n",q); print("(q & 30) is %lld\n",(q & 30)); print("(q & ((1 << 30) - 1)) is %lld\n",(q & ((1 << 30) - 1))); print("(q >> 30) is %lld\n",(q >> 30)); q = 1000000000; print("\nindex q is %lld, value v is 500 000 000\n",q); q = ((q << 32) | 500000000); print("(q << 32) | 500000000 is %lld\n",q); print("(q & 32) is %lld\n",(q & 32)); print("(q & 0xFFFFFFFF) is %lld\n",(q & 0xFFFFFFFF)); print("(q >> 32) is %lld\n",(q >> 32)); q = 1000000000; print("\nindex q is %lld, value v is 500 000 000\n",q); q = ((q << 32) | 500000000); print("(q << 32) | 500000000 is %lld\n",q); print("(q & 32) is %lld\n",(q & 32)); print("(q >> 32) is %lld\n",(q >> 32)); print("(q & 0xFFFFFFFF) is %lld\n",(q & 0xFFFFFFFF)); uint8 j = 10; uint8 n = 13; print("\nindex j is %d (%s), value is %d (%s)\n",j,printallmyuint8bits(j),n,printallmyuint8bits(n)); j = ((j << 4) | n); print("(j << 4) | 13 is %d (%s)\n",j,printallmyuint8bits(j)); print("(j & 0xF) is %d (%s)\n",(j & 0xF),printallmyuint8bits(j & 0xF)); j = (j >> 4); print("(j >> 4) is %d (%s)\n",j,printallmyuint8bits(j)); int ll = 91; int rr = 95; print("\nll is %d, rr is %d\n",ll,rr); print("(ll+rr)>>1) is %d\n",((ll+rr)>>1)); print("((rr-ll)/2)+ll is %d\n\n",(((rr-ll)/2)+ll)); int ee = 22; int oo = 33; print("(%d & 1) is %d\n",ee,(ee & 1)); print("(%d & 1) is %d\n\n",oo,(oo & 1)); uint qq = 0; uint[] vv = {1,1,0,0,1,0,1,0,0,1,1}; foreach (uint iv in vv) { qq = ((qq << 1) | iv); print("((qq << 1) | %u) is %u\n",iv,qq); } print("mask values are %s\n",printuintarray(vv,2,0)); print("packed mask values as int is %u\n",qq); print("packed bits are\n"); for (int x = 31; x >= 0; x--) { print("[%d] %u\n",x,(qq & 1)); qq = (qq >> 1); } }
#+RESULTS:
int.MAX is 2147483647 uint.MAX is 4294967295 uint.MAX is 4294967295 int64.MAX is 9223372036854775807 size of uint is 4 bytes max size of uint[int.MAX] is 8.59 GB size of uint8 is 1 bytes max size of uint8[int.MAX] is 2.15 GB storing id + value... index i is 123456789, value is 1 (i |= 1) is 123456789 (i & 1) is 1 i & ~(1 << 1) is 123456789 index i is 123456789, value is 0 (i |= 0) is 123456789 (i & 1) is 0 i & ~(1 << 1) is 123456789 index i is 123456789, value is 1 (i << 1) |= 1 is 246913579 (i & 1) is 1 (i >> 1) is 123456789 index i is 123456789, value is 0 (i << 1) |= 0 is 246913578 (i & 1) is 0 (i >> 1) is 123456789 index i is 123456789, value v is 3 (i << 4) | 3 is 1975308627 (i & 0xF) is 3 (i >> 4) is 123456789 index i is 123456789, value v is 15 (max @ 4bit) (i << 4) | 15 is 1975308639 (i & 0xF) is 15 (i >> 4) is 123456789 index i is 123456789, value v is 255 (max @ 8bit) (i << 8) | 255 is 1540167167 (i & 0xFF) is 255 (i >> 8) is 6016277 -- not enough free bits index i is 12, value v is 255 (max @ 8bit) (i << 8) | 255 is 3327 (i & 0xFF) is 255 (i >> 8) is 12 -- works as 12 has enough bits to spare real-world case, store a 1 or 0 value with a cell index in a large-ish array: index i is 1000000000, value is 1 (i << 1) |= 1 is 2000000001 (i & 1) is 1 (i >> 1) is 1000000000 index i is 1000000000, value v is 0 (i << 1) |= 0 is 2000000000 (i & 1) is 0 (i >> 1) is 1000000000 index q is 1000000000, value v is 500 000 000 (q << 30) | 500000000 is 1073741824500000000 (q & 30) is 0 (q & ((1 << 30) - 1)) is 500000000 (q >> 30) is 1000000000 index q is 1000000000, value v is 500 000 000 (q << 32) | 500000000 is 4294967296500000000 (q & 32) is 0 (q & 0xFFFFFFFF) is 500000000 (q >> 32) is 1000000000 index q is 1000000000, value v is 500 000 000 (q << 32) | 500000000 is 4294967296500000000 (q & 32) is 0 (q >> 32) is 1000000000 (q & 0xFFFFFFFF) is 500000000 index j is 10 (00001010), value is 13 (00001101) (j << 4) | 13 is 173 (10101101) (j & 0xF) is 13 (00001101) (j >> 4) is 10 (00001010) ll is 91, rr is 95 (ll+rr)>>1) is 93 ((rr-ll)/2)+ll is 93 (22 & 1) is 0 (33 & 1) is 1 ((qq << 1) | 1) is 1 ((qq << 1) | 1) is 3 ((qq << 1) | 0) is 6 ((qq << 1) | 0) is 12 ((qq << 1) | 1) is 25 ((qq << 1) | 0) is 50 ((qq << 1) | 1) is 101 ((qq << 1) | 0) is 202 ((qq << 1) | 0) is 404 ((qq << 1) | 1) is 809 ((qq << 1) | 1) is 1619 mask values are {1,1,0,0,1,0,1,0,0,1,1} packed mask values as int is 1619 packed bits are [31] 1 [30] 1 [29] 0 [28] 0 [27] 1 [26] 0 [25] 1 [24] 0 [23] 0 [22] 1 [21] 1 [20] 0 [19] 0 [18] 0 [17] 0 [16] 0 [15] 0 [14] 0 [13] 0 [12] 0 [11] 0 [10] 0 [9] 0 [8] 0 [7] 0 [6] 0 [5] 0 [4] 0 [3] 0 [2] 0 [1] 0 [0] 0
NESTEDLOGIC

Group items of a comparison list using an indent value, to emulate things like:
true AND true OR (false OR true) AND true

// cumulative grouped tests // by c.p.brown 2024 struct packet { int[] items; } packet[] clusteredints (int[] n) { packet[] o = {}; packet p = packet(); p.items += 0; o += p; for (int i = 1; i < n.length; i++) { if ((n[i] - n[i-1]) != 0) { packet b = packet(); b.items += i; o += b; } else { o[o.length - 1].items += i; } } return o; } string printclusters (packet[] b) { string o = ""; for (int c = 0; c < b.length; c++) { o = "%sblock %d has %d members ".printf(o,c,b[c].items.length); o = "%s\t{".printf(o); for (int i = 0; i < b[c].items.length; i++) { if (i < (b[c].items.length - 1)) { o = "%s%d,".printf(o,b[c].items[i]); } else { o = "%s%d}\n".printf(o,b[c].items[i]); } } } return o; } void main () { // +---+--------------------+-------+---------------+---------------------+ // | 0 | B == B = true | OR | true = true | true OR | // +---+--------------------+-------+---------------+ | // | 1 | B == A = false | AND | false AND | | // +---+--------------------+-------+ | false = true, AND | // | 1 | B == C = false | AND | false = false | | // +---+--------------------+-------+---------------+ | // | 0 | B == B = true | (AND) | true = true | true = true | // +---+--------------------+-------+---------------+---------------------+ // | d | 1. eval each rule | c | 2. compare | 3. compare clusters | // | | | | per cluster | | // +---+--------------------+-------+---------------+---------------------+ // // for round 3, use last comparison (c) of the cluster, apply to next cluster // omit comparison from last rule as nothing follows it string[] t = {"B","A","C","B"}; string[] c = {"OR","AND","AND","AND"}; int[] d = {1,0,0,1}; string q = "B"; packet[] qq = clusteredints(d); print(printclusters(qq)); bool[] j = new bool[t.length]; bool[] r = new bool[qq.length]; for (int i = 0; i < r.length; i++) { r[i] = false; } //r[0] = true; if (false && false) { print("double negatives are true in Vala\n"); } // 1. stash tests... for (int i = 0; i < j.length; i++){ j[i] = (t[i] == q); if (j[i]) { print("[%d] %s == %s is true\n",i,q,t[i]); } else { print("[%d] %s == %s is false\n",i,q,t[i]); } } // 2. cumulative test, per packet for (int k = 0; k < qq.length; k++) { bool lc = j[qq[k].items[0]]; for (int i = 0; i < qq[k].items.length; i++) { print("block %d, index %d\n",k,qq[k].items[i]); int lcx = qq[k].items[i]; if (strcmp(c[qq[k].items[i-1]],"AND") == 0) { string lcs = "false"; if (lc) { lcs = "true"; } string jcs = "false"; if (j[lcx]) { jcs = "true"; } if (i > 0) { lc = (j[lcx] && lc); if (lc) { print("[%d][%d] (rule result) %s && (lastcond) %s is true\n",k,lcx,jcs,lcs); } else { print("[%d][%d] (rule result) %s && (lastcond) %s is false\n",k,lcx,jcs,lcs); } } else { if (lc) { print("[%d][%d] (rule result) %s is true\n",k,lcx,lcs); } else { print("[%d][%d] (rule result) %s is false\n",k,lcx,lcs); } } } else { if (strcmp(c[qq[k].items[i-1]],"OR") == 0) { string lcs = "false"; if (lc) { lcs = "true"; } string jcs = "false"; if (j[lcx]) { jcs = "true"; } if (i > 0) { lc = (j[lcx] && lc); if (lc) { print("[%d][%d] (rule result) %s || (lastcond) %s is true\n",k,lcx,jcs,lcs); } else { print("[%d][%d] (rule result) %s || (lastcond) %s is false\n",k,lcx,jcs,lcs); } } else { if (lc) { print("[%d][%d] (rule result) %s is true\n",k,lcx,lcs); } else { print("[%d][%d] (rule result) %s is false\n",k,lcx,lcs); } } } } } r[k] = lc; } // 3. cumulative test bool lc = r[0]; for (int k = 1; k < qq.length; k++) { int lcx = qq[k-1].items[(qq[k-1].items.length - 1)]; if (strcmp(c[lcx],"AND") == 0) { string lcs = "false"; if (lc) { lcs = "true"; } string rks = "false"; if (r[k]) { rks = "true"; } lc = r[k] && lc; if (lc) { print("[%d] %s && %s is true\n",k,rks,lcs); } else { print("[%d] %s && %s is false\n",k,rks,lcs); } } else { if (strcmp(c[lcx],"OR") == 0) { string lcs = "false"; if (lc) { lcs = "true"; } string rks = "false"; if (r[k]) { rks = "true"; } lc = r[k] || lc; if (lc) { print("[%d] %s || %s is true\n",k,rks,lcs); } else { print("[%d] %s || %s is false\n",k,rks,lcs); } } } } if (lc) { print("result is true\n"); } else { print("result is false\n"); } }
#+RESULTS:
Compilation succeeded - 1 warning(s) block 0 has 1 members {0} block 1 has 2 members {1,2} block 2 has 1 members {3} [0] B == B is true [1] B == A is false [2] B == C is false [3] B == B is true block 0, index 0 [0][0] (rule result) true is true block 1, index 1 [1][1] (rule result) false is false block 1, index 2 [1][2] (rule result) false && (lastcond) false is false block 2, index 3 [2][3] (rule result) true is true [1] false || true is true [2] true && true is true result is true
OOPVSNATIVE

Test to determine costs of abstraction when writing to int[] arrays.

GLib.Mutex mutex; string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } int[] rangeseq (int p, int s) { // p packet count, s sequence count int[] o = {}; int tasksperthread = s / p; int dreg = 0; int lthr = p; double npt = ((double) s) / ((double) tasksperthread); if ((tasksperthread * p) < s) { double mxp = ((double) p); while (npt > mxp) { tasksperthread += 1; npt = ((double) s) / ((double) tasksperthread); } dreg = s - (tasksperthread * ((int) npt)); if (dreg > 0) { lthr = p - 1; } } int np = (int) npt; for (int i = 0; i < np; i++) { o += (i * tasksperthread); o += ((i * tasksperthread) + (tasksperthread - 1)); } if (dreg > 0) { o += (np * tasksperthread); o += ((np * tasksperthread) + (dreg - 1)); } return o; } public class tmpidx : Object { private int[] items; public void additem (int d) { items += d; } public void additemrange (int s, int e) { for (int i = s; i <= e; i++) { items += i; } } public void copyitem (int i, int j) { items[i] = items[j]; } public void swapitems (int i, int j) { int t = items[i]; items[i] = items[j]; items[j] = t; } public void setitemcount (int i) { items.resize(i); } public void putitem (int i, int d) { items[i] = d; } public int getlastitem () { return items.length - 1; } public int getitemcount () { return items.length; } public int getitem (int i) { return items[i]; } public int[] provideitems () { return items; } public tmpidx () { items = {}; } } class addtonativearray : Object { int d; public addtonativearray (int x) { d = x; } public void eval(ref int[] a) { //a += d; } } class addtoobjectarray : Object { int d; public addtoobjectarray (int x) { d = x; } public void eval(tmpidx o) { o.additem(d); } } class addrangetoobjectarray : Object { int s; int e; public addrangetoobjectarray (int x, int y) { s = x; e = y; } public void eval(tmpidx o) { o.additemrange(s,e); } } void addtoobjectarrayfn (tmpidx o, int d) { o.additem(d); } void addrangetoobjectarrayfn (tmpidx o, int s, int e) { o.additemrange(s,e); } class tpadditems : Object { int s; int e; public tpadditems (int x, int y) { s = x; e = y; } public void eval(tmpidx o, ref int packetscomplete) { for (int i = s; i <= e; i++) { o.putitem(i,i); } mutex.lock(); packetscomplete += 1; mutex.unlock(); } } class resizeaddtonativearray : Object { int x; public resizeaddtonativearray (int d) { x = d; } public void eval(ref int[] i) { i.resize(i.length + 1); i[(i.length - 1)] = x; } } void resizeaddtonativearrayfn (ref int[] a, int d) { a.resize(a.length + 1); a[(a.length - 1)] = d; } void addtonativearrayfn (ref int[] a, int d) { //a += d; } void addtoobjectparam (tmpidx o, int d) { o.additem(d); } void main() { mutex = new GLib.Mutex(); GLib.Intl.setlocale(ALL,""); int nthr = (int) GLib.get_num_processors(); int ee = 100000000; int si = ee - 1; print("\nadd 100M items to array:\n\n"); int64 wtts = GLib.get_monotonic_time(); tmpidx widx = new tmpidx(); widx.setitemcount(ee); int packetscomplete = 0; ThreadPool<tpadditems> qst = new ThreadPool<tpadditems>.with_owned_data( (tpadditems) => { tpadditems.eval(widx,ref packetscomplete); },nthr,false ); int maxpackets = (nthr * 2); int[] seq = rangeseq(maxpackets,ee); int q = 0; int seqpackets = (seq.length / 2); if (seqpackets == maxpackets) { while (q < seq.length) { qst.add(new tpadditems(seq[q],seq[q+1])); q += 2; } while (packetscomplete < seqpackets) { GLib.Thread.usleep(1); } } else { print("seqpackets %d != maxpackets %d, aborted mutlithreading.\n",seqpackets,maxpackets); } //while ((qst.unprocessed() > 0) || (qst.get_num_threads() > 0)) { GLib.Thread.usleep(1); } int64 wtte = GLib.get_monotonic_time(); print("multithreaded obj.putitem(i) via object took %s, item[%d] is %d\n",printusecs(wtte-wtts),si,widx.getitem(si)); int[] nidx = {}; int64 ntts = GLib.get_monotonic_time(); for (int i = 0; i < ee; i++) { nidx += i; } int64 ntte = GLib.get_monotonic_time(); print("a += i took ................................. %s, item[%d] is %d\n",printusecs(ntte-ntts),si,nidx[si]); tmpidx yidx = new tmpidx(); int64 ytts = GLib.get_monotonic_time(); yidx.additemrange(0,ee); int64 ytte = GLib.get_monotonic_time(); print("obj.additemrange(0,e) took .................. %s, item[%d] is %d\n",printusecs(ytte-ytts),si,yidx.getitem(si)); tmpidx qidx = new tmpidx(); int64 qtts = GLib.get_monotonic_time(); addrangetoobjectarrayfn(qidx,0,ee); int64 qtte = GLib.get_monotonic_time(); print("obj.additemrange(0,e) via function took ..... %s, item[%d] is %d\n",printusecs(qtte-qtts),si,qidx.getitem(si)); tmpidx fidx = new tmpidx(); int64 ftts = GLib.get_monotonic_time(); addrangetoobjectarray fc = new addrangetoobjectarray(0,ee); fc.eval(fidx); int64 ftte = GLib.get_monotonic_time(); print("obj.additemrange(0,e) via object took ....... %s, item[%d] is %d\n",printusecs(ftte-ftts),si,fidx.getitem(si)); tmpidx idx = new tmpidx(); int64 tts = GLib.get_monotonic_time(); for (int i = 0; i < ee; i++) { idx.additem(i); } int64 tte = GLib.get_monotonic_time(); print("obj.additem(i) took ......................... %s, item[%d] is %d\n",printusecs(tte-tts),si,idx.getitem(si)); tmpidx uidx = new tmpidx(); int64 utts = GLib.get_monotonic_time(); for (int i = 0; i < ee; i++) { addtoobjectarrayfn(uidx,i); } int64 utte = GLib.get_monotonic_time(); print("obj.additem(i) via function took ............ %s, item[%d] is %d\n",printusecs(utte-utts),si,uidx.getitem(si)); GLib.Array<int> gidx = new GLib.Array<int> (); int64 gtts = GLib.get_monotonic_time(); for (int i = 0; i < ee; i++) { gidx.append_val(i); } int64 gtte = GLib.get_monotonic_time(); print("a<int>.append_val(i) took ................... %s, item[%d] is %d\n",printusecs(gtte-gtts),si,gidx.index(si)); int[] ridx = {}; int64 rtts = GLib.get_monotonic_time(); for (int i = 0; i < ee; i++) { ridx.resize(ridx.length + 1); ridx[ridx.length - 1] = i; } int64 rtte = GLib.get_monotonic_time(); print("a.resize() a[-1] = i took ................... %s, item[%d] is %d\n",printusecs(rtte-rtts),si,ridx[si]); int[] xidx = {}; int64 xtts = GLib.get_monotonic_time(); for (int i = 0; i < ee; i++) { resizeaddtonativearrayfn(ref xidx, i); } int64 xtte = GLib.get_monotonic_time(); print("a.resize() a[-1] = i via function took ...... %s, item[%d] is %d\n",printusecs(xtte-xtts),si,xidx[si]); print("\nunrealistic, but tested anyway:\n"); tmpidx kidx = new tmpidx(); int64 ktts = GLib.get_monotonic_time(); for (int i = 0; i < ee; i++) { addtoobjectarray h = new addtoobjectarray(i); h.eval(kidx); } int64 ktte = GLib.get_monotonic_time(); print("obj.additem(i) via object function took ..... %s, item[%d] is %d\n",printusecs(ktte-ktts),si,kidx.getitem(si)); int[] oidx = {}; int64 otts = GLib.get_monotonic_time(); for (int i = 0; i < ee; i++) { resizeaddtonativearray h = new resizeaddtonativearray(i); h.eval(ref oidx); } int64 otte = GLib.get_monotonic_time(); print("a.resize() a[-1] = i via object function took %s, item[%d] is %d\n",printusecs(otte-otts),si,oidx[si]); //int[] lidx = {}; //int64 ltts = GLib.get_monotonic_time(); //for (int i = 0; i < ee; i++) { // addtonativearrayfn(ref lidx, i); //} //int64 ltte = GLib.get_monotonic_time(); //print("a += i via function took %s\n",printusecs(ltte-ltts)); print("\na += i via function is not possible in Vala\n"); //int[] vidx = {}; //int64 vtts = GLib.get_monotonic_time(); //for (int i = 0; i < ee; i++) { // addtonativearray h = new addtonativearray(i); // h.eval(ref vidx); //} //int64 vtte = GLib.get_monotonic_time(); //print("a += i via object function took %s\n",printusecs(vtte-vtts)); print("a += i via object function is not possible in Vala\n"); }
#+RESULTS:
Compilation succeeded - 6 warning(s) add 100M items to array: multithreaded obj.putitem(i) via object took 154.59 ms, item[99999999] is 99999999 a += i took ................................. 330.68 ms, item[99999999] is 99999999 obj.additemrange(0,e) took .................. 379.20 ms, item[99999999] is 99999999 obj.additemrange(0,e) via function took ..... 398.94 ms, item[99999999] is 99999999 obj.additemrange(0,e) via object took ....... 397.63 ms, item[99999999] is 99999999 obj.additem(i) took ......................... 470.70 ms, item[99999999] is 99999999 obj.additem(i) via function took ............ 548.92 ms, item[99999999] is 99999999 a<int>.append_val(i) took ................... 803.39 ms, item[99999999] is 99999999 a.resize() a[-1] = i took ................... 21.70 s, item[99999999] is 99999999 a.resize() a[-1] = i via function took ...... 16.06 s, item[99999999] is 99999999 unrealistic, but tested anyway: obj.additem(i) via object function took ..... 13.78 s, item[99999999] is 99999999 a.resize() a[-1] = i via object function took 35.70 s, item[99999999] is 99999999 a += i via function is not possible in Vala a += i via object function is not possible in Vala
UINT

Check behavior of uint here.

Notes:
  • uint can be used to clearly define a variable shouldn't be negative, hovever:
  • casting a negaitve int to uint will wrap it around to a huge number
  • subtracting two uints to negative will also wrap it
  • wrapped numbers can't be checked for an invalid negative number with u > -1

Conclusion: don't use uint unless you need to store a number from 2 to 4 billion without going 64-bit, or unless some other function requires/generates it, eg string.hash().

// "resize" fixed string array without overflow string[] resizestringarray (string[] o, uint l) { string[] n = new string[l]; for (uint i = 0; i < l; i++) { if (i < o.length) { n[i] = o[i]; } else { n[i] = ""; } } o = null; // this may not be necessary, still investigating... return n; } void main() { uint x = 3; uint z = 10; print("bool as uint\n"); print("((uint) (%u < 2)) * %u is %u\n",x,z,(((uint) (x < 2)) * z)); print("((uint) (%u > 2)) * %u is %u\n",x,z,(((uint) (x > 2)) * z)); print("\n"); uint y = 10; string[] s = {"zero","one","two","three","four","five","six","seven","eight","nine","ten"}; print("string[] s:\n{%s}\n",string.joinv(",",s)); print("uint s[%u] is \"%s\"\n",y,s[y]); uint n = 5; s = resizestringarray(s,n); print("s.length is now %d\n",s.length); print("uint s[(%u - 1)] is \"%s\"\n",n,s[(n - 1)]); uint r = 3; uint q = s.length / r; print("\ns.length %d (int) / %u (uint) is %u (uint)\n",s.length,r,q); q = r - n; print("%u - %u is %u\n",r,n,q); int[] ids = {0,1,2,3,4}; int sel = 4; for (int i = 0; i < ids.length; i++) { int ofs = (sel - i); print("offset is %.2f\n",(0.5 + ((20.0 * ofs) / 100.0))); } int64 lx = GLib.get_monotonic_time(); print("\nGLib.get_monotonic_time() is lx %lld\n",lx); int dx = (int) lx; print("lx as int is dx %d\n",dx); uint ux = (uint) lx; print("lx as uint is ux %u\n",ux); dx = (int) ux; print("ux as int is %d\n",dx); dx = (int) (lx & 0xFFFFFFFF); print("lx as (lx & 0xFFFFFFFF) is %d\n",dx); print("lx is %lld\n",lx); dx = ((int) (lx >> 32)) ^ ((int) (lx & 0xFFFFFFFF)); print("lx as (int) (lx >> 32) ^ (int) (lx & 0xFFFFFFFF) is %d\n",dx); }
#+RESULTS:
bool as uint ((uint) (3 < 2)) * 10 is 0 ((uint) (3 > 2)) * 10 is 10 string[] s: {zero,one,two,three,four,five,six,seven,eight,nine,ten} uint s[10] is "ten" s.length is now 5 uint s[(5 - 1)] is "four" s.length 5 (int) / 3 (uint) is 1 (uint) 3 - 5 is 4294967294 offset is 1.30 offset is 1.10 offset is 0.90 offset is 0.70 offset is 0.50 GLib.get_monotonic_time() is lx 4203852999653 lx as int is dx -919983131 lx as uint is ux 3374984165 ux as int is -919983131 lx as (lx & 0xFFFFFFFF) is -919983131 lx is 4203852999653 lx as (int) (lx >> 32) ^ (int) (lx & 0xFFFFFFFF) is -919984073
UNICHAR
void main() { string nl = "\n"; unichar nlc = nl.get_char(0); bool k = true; string cr = "a row with \"a quoted \n\" in it\nand another without"; unichar n = 0; for (int i = 0; cr.get_next_char (ref i, out n);) { int s = i - 1; if (n == '\"') { k = !k; cr = cr.splice(s, i, ""); i = i - 1; } if (n == nlc && !k) { cr = cr.splice(s, i, "\\n"); } } string[] sr = cr.split("\n"); foreach (string s in sr) { print("row = %s\n",s); } }
#+RESULTS:
row = a row with a quoted \n in it row = and another without
UNICHAR2

Misc unichar tests

void main() { GLib.Intl.setlocale(ALL,""); string strs = "test零string"; int strscc = strs.char_count(); print("%s.length is %d\n",strs,strs.length); print("%s.char_count() is %d\n",strs,strscc); unichar[] chs = {}; for (int i = 0; i < strscc; i++) { chs += strs.get_char(strs.index_of_nth_char(i)); } for (int i = 0; i < chs.length; i++) { print("chs[%d] is \'%s\'\n",i,chs[i].to_string()); } unichar g = 'g'; unichar k = 'k'; int gn = (int) g; print("digit of g is %d\n",gn); int kn = (int) k; print("digit of k is %d\n",kn); int av = (gn + kn) / 2; print("%lc is halfway between %lc and %lc\n",((unichar) av),g,k); string s = "零1234五67«八»9零"; int lc = s.char_count() - 1; unichar l = '零'; int slc = s.char_count() - 2; unichar sl = '9'; if (s.last_index_of_char(l) == s.index_of_nth_char(lc)) { print("last char of %s is \'%s\'\n",s,s.get_char(s.index_of_nth_char(lc)).to_string()); } if (s.last_index_of_char(sl) == s.index_of_nth_char(slc)) { print("second-last char of %s is \'%s\'\n",s,s.get_char(s.index_of_nth_char(slc)).to_string()); } unichar comma = ','; print(", is char %d\n",((int) comma)); for (int i = 32; i < 48; i++) { print("%02d %s\n",i,((unichar) i).to_string()); } for (int i = 0; i < s.char_count(); i++) { int c = (int) s.get_char(s.index_of_nth_char(i)); print("%02d %s\n",i,((unichar) c).to_string()); } int b = 2; int e = 8; uint mt = (uint) GLib.get_monotonic_time(); Random.set_seed(mt); for (int i = 0; i < 10; i++) { Random.set_seed(mt + i); int q = Random.int_range(0,10); print( "(((%.2f/%.2f)=%.2f) * ((%d-%d)=%d))+%d = %d\n", ((double) q), 9.0, (((double) q) / 9.0), e, b, (e-b), b, (((int) (( ((double) q) / 9.0) * ((double) (e-b)))) + b) ); } mt = (uint) GLib.get_monotonic_time(); for (int i = 0; i < 10; i++) { Random.set_seed(mt + i); int q = i;//Random.int_range(0,10); print( "(%d %% ((((%d+1)=%d)-%d)=%d)+%d)= %.2f\n", q, e, (e+1), b, ((e+1)-b), b, ((q % ((e+1)-b)) + b) ); } print("零.to_ascii() is %s\n","零".to_ascii()); print("Ä.to_ascii() is %s\n","Ä".to_ascii()); print("ฒ.to_ascii() is %s\n","ฒ".to_ascii()); print("ư.to_ascii() is %s\n","ư".to_ascii()); print("ố.to_ascii() is %s\n","ố".to_ascii()); print("គ.to_ascii() is %s\n","គ".to_ascii()); print("ம்.to_ascii() is %s\n","ம்".to_ascii()); print("チ.to_ascii() is %s\n","チ".to_ascii()); print("Θ.to_ascii() is %s\n","Θ".to_ascii()); print("ξ.to_ascii() is %s\n","ξ".to_ascii()); string sxc = "零12345"; int sxcl = sxc.length; for (int i = 0; i < 12; i++) { int p = sxc.index_of_nth_char(i); print("\"%s\".index_of_nth_char(%d) is %d/%d\n",sxc,i,p,sxcl); print("\tchar %d at pos %d is \'%s\'\n",i,p,sxc.get_char(p).to_string()); if (p == (sxcl - 1)) { print("\t\tthis is the last char\n"); } } }
#+RESULTS:
test零string.length is 13 test零string.char_count() is 11 chs[0] is 't' chs[1] is 'e' chs[2] is 's' chs[3] is 't' chs[4] is '零' chs[5] is 's' chs[6] is 't' chs[7] is 'r' chs[8] is 'i' chs[9] is 'n' chs[10] is 'g' digit of g is 103 digit of k is 107 i is halfway between g and k last char of 零1234五67«八»9零 is '零' second-last char of 零1234五67«八»9零 is '9' , is char 44 32 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / 00 零 01 1 02 2 03 3 04 4 05 五 06 6 07 7 08 « 09 八 10 » 11 9 12 零 (((3.00/9.00)=0.33) * ((8-2)=6))+2 = 4 (((0.00/9.00)=0.00) * ((8-2)=6))+2 = 2 (((3.00/9.00)=0.33) * ((8-2)=6))+2 = 4 (((4.00/9.00)=0.44) * ((8-2)=6))+2 = 4 (((6.00/9.00)=0.67) * ((8-2)=6))+2 = 6 (((8.00/9.00)=0.89) * ((8-2)=6))+2 = 7 (((5.00/9.00)=0.56) * ((8-2)=6))+2 = 5 (((8.00/9.00)=0.89) * ((8-2)=6))+2 = 7 (((9.00/9.00)=1.00) * ((8-2)=6))+2 = 8 (((2.00/9.00)=0.22) * ((8-2)=6))+2 = 3 (0 % ((((8+1)=9)-2)=7)+2)= 2.00 (1 % ((((8+1)=9)-2)=7)+2)= 3.00 (2 % ((((8+1)=9)-2)=7)+2)= 4.00 (3 % ((((8+1)=9)-2)=7)+2)= 5.00 (4 % ((((8+1)=9)-2)=7)+2)= 6.00 (5 % ((((8+1)=9)-2)=7)+2)= 7.00 (6 % ((((8+1)=9)-2)=7)+2)= 8.00 (7 % ((((8+1)=9)-2)=7)+2)= 2.00 (8 % ((((8+1)=9)-2)=7)+2)= 3.00 (9 % ((((8+1)=9)-2)=7)+2)= 4.00 零.to_ascii() is ? Ä.to_ascii() is A ฒ.to_ascii() is ? ư.to_ascii() is u ố.to_ascii() is o គ.to_ascii() is ? ம்.to_ascii() is ?? チ.to_ascii() is ? Θ.to_ascii() is ? ξ.to_ascii() is ? "零12345".index_of_nth_char(0) is 0/8 char 0 at pos 0 is '零' "零12345".index_of_nth_char(1) is 3/8 char 1 at pos 3 is '1' "零12345".index_of_nth_char(2) is 4/8 char 2 at pos 4 is '2' "零12345".index_of_nth_char(3) is 5/8 char 3 at pos 5 is '3' "零12345".index_of_nth_char(4) is 6/8 char 4 at pos 6 is '4' "零12345".index_of_nth_char(5) is 7/8 char 5 at pos 7 is '5' this is the last char "零12345".index_of_nth_char(6) is 8/8 char 6 at pos 8 is '' "零12345".index_of_nth_char(7) is 9/8 char 7 at pos 9 is '' "零12345".index_of_nth_char(8) is 10/8 char 8 at pos 10 is '' "零12345".index_of_nth_char(9) is 11/8 char 9 at pos 11 is '' "零12345".index_of_nth_char(10) is 12/8 char 10 at pos 12 is '' "零12345".index_of_nth_char(11) is 13/8 char 11 at pos 13 is ''
UNDO

Simple undo test using a function arg buffer.
Buffer grows as required, up to a cap, then re-uses positions.

// undo test // by c.p.brown 2024 int intmod (int l, int r) { if (l >= 0) { return (l % r); } if (l >= -r) { return (l + r); } return ((l % r) + r) % r; } int mathfunc (int a, int b, int c) { if (c == 0) { return (a + b); } if (c == 1) { return (a - b); } if (c == 2) { return (a * b); } if (c == 3) { return (a / b); } return 0; } struct mistake { int[] payload; } mistake[] mistakes; int ugh = -1; int doit (int[] a) { // grow the undo buffer as required, cap it at 5 in this case if ((ugh+1) >= mistakes.length) { if (mistakes.length < 5) { mistakes.resize(mistakes.length + 1); } } int ml = int.min(mistakes.length,5); ugh = intmod((ugh+1),ml); print("do %.2d : ",ugh); mistake ms = new mistake(); ms.payload = a; mistakes[ugh] = ms; return mathfunc(a[0],a[1],a[2]); } int undoit () { ugh = intmod((ugh-1),mistakes.length); print("undo %.2d : ",ugh); int[] a = mistakes[ugh].payload; return mathfunc(a[0],a[1],a[2]); } void main() { int m = doit({2,3,0}); string[] s = {"+","-","*","/"}; print("m = 2 + 3 = %d\n",m); m = doit({2,3,1}); print("m = 2 - 3 = %d\n",m); m = undoit(); print("m after undo is %d %s %d = %d\n",mistakes[ugh].payload[0],s[mistakes[ugh].payload[2]],mistakes[ugh].payload[1],m); m = doit({2,3,2}); print("m = 2 * 3 = %d\n",m); m = doit({2,3,3}); print("m = 2 / 3 = %d\n",m); m = doit({20,1,3}); print("m = 20 / 1 = %d\n",m); m = undoit(); print("m after undo is %d %s %d = %d\n",mistakes[ugh].payload[0],s[mistakes[ugh].payload[2]],mistakes[ugh].payload[1],m); m = undoit(); print("m after undo is %d %s %d = %d\n",mistakes[ugh].payload[0],s[mistakes[ugh].payload[2]],mistakes[ugh].payload[1],m); m = undoit(); print("m after undo is %d %s %d = %d\n",mistakes[ugh].payload[0],s[mistakes[ugh].payload[2]],mistakes[ugh].payload[1],m); m = undoit(); print("m after undo is %d %s %d = %d\n",mistakes[ugh].payload[0],s[mistakes[ugh].payload[2]],mistakes[ugh].payload[1],m); m = doit({18,2,2}); print("m = 18 * 2 = %d\n",m); m = undoit(); print("m after undo is %d %s %d = %d\n",mistakes[ugh].payload[0],s[mistakes[ugh].payload[2]],mistakes[ugh].payload[1],m); m = doit({18,4,0}); print("m = 18 + 4 = %d\n",m); m = doit({7,2,2}); print("m = 7 * 2 = %d\n",m); m = undoit(); print("m after undo is %d %s %d = %d\n",mistakes[ugh].payload[0],s[mistakes[ugh].payload[2]],mistakes[ugh].payload[1],m); }
#+RESULTS:
Compilation succeeded - 1 warning(s) do 00 : m = 2 + 3 = 5 do 01 : m = 2 - 3 = -1 undo 00 : m after undo is 2 + 3 = 5 do 01 : m = 2 * 3 = 6 do 02 : m = 2 / 3 = 0 do 03 : m = 20 / 1 = 20 undo 02 : m after undo is 2 / 3 = 0 undo 01 : m after undo is 2 * 3 = 6 undo 00 : m after undo is 2 + 3 = 5 undo 03 : m after undo is 20 / 1 = 20 do 04 : m = 18 * 2 = 36 undo 03 : m after undo is 20 / 1 = 20 do 04 : m = 18 + 4 = 22 do 00 : m = 7 * 2 = 14 undo 04 : m after undo is 18 + 4 = 22
NUMBERS
[5_DONE]INTDIGITS
int intdigits (int n, bool a) { int x = n.abs(); int r = 0; if ((!a) && (n < 0)) { r += 1; } if (x < 10) { return (1 + r); } if (x < 100) { return (2 + r); } if (x < 1000) { return (3 + r); } if (x < 10000) { return (4 + r); } if (x < 100000) { return (5 + r); } if (x < 1000000) { return (6 + r); } if (x < 10000000) { return (7 + r); } if (x < 100000000) { return (8 + r); } if (x < 1000000000) { return (9 + r); } return (10 + r); // int32.MAX is 10 digits }
DOUBLEDIGITS_TEST
string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } int intdigits (int n, bool a) { int x = n.abs(); int r = 0; if ((!a) && (n < 0)) { r += 1; } if (x < 10) { return (1 + r); } if (x < 100) { return (2 + r); } if (x < 1000) { return (3 + r); } if (x < 10000) { return (4 + r); } if (x < 100000) { return (5 + r); } if (x < 1000000) { return (6 + r); } if (x < 10000000) { return (7 + r); } if (x < 100000000) { return (8 + r); } if (x < 1000000000) { return (9 + r); } return (10 + r); // int32.MAX is 10 digits } void main() { GLib.Intl.setlocale(ALL,""); int p = 1234; print("%d has %d characters\n\n",p,intdigits(p,false)); p = -1234; print("%d has %d characters\n\n",p,intdigits(p,false)); p = 123456789; print("%d has %d characters\n\n",p,intdigits(p,false)); p = -123456789; print("%d has %d characters\n\n",p,intdigits(p,false)); p = -0; print("%d has %d characters\n\n",p,intdigits(p,false)); p = 0; print("%d has %d characters\n\n",p,intdigits(p,false)); p = -123456789; int64 tts = GLib.get_monotonic_time(); int cc = intdigits(p,true); int64 tte = GLib.get_monotonic_time(); print("abs %d has %d characters\n\n",p,cc); print("intdigits took %s\n",printusecs(tte-tts)); }
#+RESULTS:
1234 has 4 characters -1234 has 5 characters 123456789 has 9 characters -123456789 has 10 characters 0 has 1 characters 0 has 1 characters abs -123456789 has 9 characters intdigits took 0 μs
[5_DONE]DOUBLEDIGITS
void doubledigitss (double n, int r, bool a, out int tdc, out int frc) { // used to calculate number widths for rendering // tdc is total digit count, including '-' and '.' // frc is the fractional digit count, use for "%.*f",frac // frc is capped to keep total digit count below 16 print("frc is %d, tdc is %d\n",tdc,frc); double x = n.abs(); int s = 1; if ((!a) && (n < 0)) { s = 2; } if (x < 10.0) { frc = int.min(14,r); tdc = (s + 1 + frc); return; } if (x < 100.0) { frc = int.min(13,r); tdc = (s + 2 + frc); return; } if (x < 1000.0) { frc = int.min(12,r); tdc = (s + 3 + frc); return; } if (x < 10000.0) { frc = int.min(11,r); tdc = (s + 4 + frc); return; } if (x < 100000.0) { frc = int.min(10,r); tdc = (s + 5 + frc); return; } if (x < 1000000.0) { frc = int.min(9,r); tdc = (s + 6 + frc); return; } if (x < 10000000.0) { frc = int.min(8,r); tdc = (s + 7 + frc); return; } if (x < 100000000.0) { frc = int.min(7,r); tdc = (s + 8 + frc); return; } if (x < 1000000000.0) { frc = int.min(6,r); tdc = (s + 9 + frc); return; } if (x < 10000000000.0) { frc = int.min(5,r); tdc = (s + 10 + frc); return; } if (x < 100000000000.0) { frc = int.min(4,r); tdc = (s + 11 + frc); return; } if (x < 1000000000000.0) { frc = int.min(3,r); tdc = (s + 12 + frc); return; } if (x < 10000000000000.0) { frc = int.min(2,r); tdc = (s + 13 + frc); return; } frc = int.min(1,r); tdc = (s + 14 + frc); }
DOUBLEDIGITS_TEST
string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } void doubledigitss (double n, int r, bool a, out int tdc, out int frc) { // used to calculate number widths for rendering // tdc is total digit count, including '-' and '.' // frc is the fractional digit count, use for "%.*f",frac // frc is capped to keep total digit count below 16 print("frc is %d, tdc is %d\n",tdc,frc); double x = n.abs(); int s = 1; if ((!a) && (n < 0)) { s = 2; } if (x < 10.0) { frc = int.min(14,r); tdc = (s + 1 + frc); return; } if (x < 100.0) { frc = int.min(13,r); tdc = (s + 2 + frc); return; } if (x < 1000.0) { frc = int.min(12,r); tdc = (s + 3 + frc); return; } if (x < 10000.0) { frc = int.min(11,r); tdc = (s + 4 + frc); return; } if (x < 100000.0) { frc = int.min(10,r); tdc = (s + 5 + frc); return; } if (x < 1000000.0) { frc = int.min(9,r); tdc = (s + 6 + frc); return; } if (x < 10000000.0) { frc = int.min(8,r); tdc = (s + 7 + frc); return; } if (x < 100000000.0) { frc = int.min(7,r); tdc = (s + 8 + frc); return; } if (x < 1000000000.0) { frc = int.min(6,r); tdc = (s + 9 + frc); return; } if (x < 10000000000.0) { frc = int.min(5,r); tdc = (s + 10 + frc); return; } if (x < 100000000000.0) { frc = int.min(4,r); tdc = (s + 11 + frc); return; } if (x < 1000000000000.0) { frc = int.min(3,r); tdc = (s + 12 + frc); return; } if (x < 10000000000000.0) { frc = int.min(2,r); tdc = (s + 13 + frc); return; } frc = int.min(1,r); tdc = (s + 14 + frc); } void main() { GLib.Intl.setlocale(ALL,""); double p = 0.123456789123456789; int d = 0; int f = 0; doubledigits(p,2,false,out d,out f); print("%.*f @ %df is %d characters\n\n",f,p,f,d); d = 0; f = 0; doubledigits(p,4,false,out d,out f); print("%.*f @ %df is %d characters\n\n",f,p,f,d); d = 0; f = 0; doubledigits(p,15,false,out d,out f); print("%.*f @ %df is %d characters\n\n",f,p,f,d); p = 123456789.123456789123456789; d = 0; f = 0; doubledigits(p,4,false,out d,out f); print("%.*f @ %df is %d characters\n\n",f,p,f,d); d = 0; f = 0; doubledigits(p,15,false,out d,out f); print("%.*f @ %df is %d characters\n\n",f,p,f,d); p = 12345678912345678.123456789123456789; d = 0; f = 0; doubledigits(p,4,false,out d,out f); print("%.*f @ %df is %d characters\n\n",f,p,f,d); d = 0; f = 0; doubledigits(p,30,false,out d,out f); print("%.*f @ %df is %d characters\n\n",f,p,f,d); p = 12345678912345678.123456789123456789; d = 0; f = 0; doubledigits(p,4,false,out d,out f); print("%.*f @ %df is %d characters\n\n",f,p,f,d); d = 0; f = 0; int64 tts = GLib.get_monotonic_time(); doubledigits(p,30,false,out d,out f); int64 tte = GLib.get_monotonic_time(); print("%.*f @ %df is %d characters\n\n",f,p,f,d); print("doubledigits took %s\n",printusecs(tte-tts)); }
#+RESULTS:
Compilation succeeded - 2 warning(s) frc is 0, tdc is 0 0.12 @ 2f is 4 characters frc is 0, tdc is 0 0.1235 @ 4f is 6 characters frc is 0, tdc is 0 0.12345678912346 @ 14f is 16 characters frc is 0, tdc is 0 123456789.1235 @ 4f is 14 characters frc is 0, tdc is 0 123456789.123457 @ 6f is 16 characters frc is 0, tdc is 0 12345678912345678.0 @ 1f is 16 characters frc is 0, tdc is 0 12345678912345678.0 @ 1f is 16 characters frc is 0, tdc is 0 12345678912345678.0 @ 1f is 16 characters frc is 0, tdc is 0 12345678912345678.0 @ 1f is 16 characters doubledigits took 1 μs
DMOD
double dmod (double l, double r) { if (l >= 0) { return (l % r); } if (l >= -r) { return (l + r); } return ((l % r) + r) % r; }
INTMOD
int intmod (int l, int r) { if (l >= 0) { return (l % r); } if (l >= -r) { return (l + r); } return ((l % r) + r) % r; }
[5_DONE]INTMAX
INTMAX_SRC
int intmax (int[] a) { int m = 0; int l = a.length; // 3M arrived-at via testing, // MT was slower with less than 2~3M if (l > 3000000) { // tasks are identical, use packetsize of threadcount int[] intranges = rangeseq(nthr,l); int[] maxs = new int[intranges.length]; int packetscomplete = 0; ThreadPool<mtintmax> imx = new ThreadPool<mtintmax>.with_owned_data((mtintmax) => { mtintmax.eval(ref packetscomplete,ref maxs,a);},nthr,false); int n = 0; for (int x = 0; x < intranges.length; x += 2) { imx.add(new mtintmax(n,intranges[x],intranges[x+1])); n += 1; } while (packetscomplete != n) {GLib.Thread.usleep(1);} foreach (int i in maxs) { m = int.max(m,i); } } else { foreach (int i in a) { m = int.max(m,i); } } return m; }
INTMAX_TEST
GLib.Mutex mutex; int nthr; string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } int xrintr (int i, int s, int e, bool t, bool m) { // pseudo-random integer range // by c.p.brown 2025 // // i is seed, s is min value, e is max value, // t is use time + seed (different result each eval) // m is modulo within range rather than scale to range // // uses xorshift offsets by George Marsaglia (2003) // https://www.jstatsoft.org/article/view/v008i14 int[] ph = { 4,3,27, // 31 ▂█▄▇▃▃▇▄█▂▆▁▅█▄▇▃▅▁▆▂▂▆▁▅▃▇▄█▄ 5,27,25, // 44 ▃▅▇▁▃▅▇▁▃█▆▄▂█▆▄▂█▆▄▂█▆▄▂▇▅▃▁▇ 1,9,29, // 03 ▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆ 13,3,17, // 71 ▁▃▄▂█▆▃▁▇▅▂▄▆█▁▃▅▇█▆▄▂▇▅▃▁▆█▂▄ 9,5,25, // 61 ▆▃▄▁▂▇█▅▆▃▄▁▂█▇▆▅▄▃▂▁█▇▆▅▄▃▂▁▅ 3,7,29, // 25 ▅█▇▂▁▄▃▃▄▁▂▇█▅▆▃▄▁▂▇█▅▆▄▃▂▁█▇▆ 3,5,25, // 24 █▁▁▂▂▃▃▄▄▃▃▄▄▁▁▂▂▇▇██▅▅▆▆▄▄▃▃▂ 15,1,29 // 77 ▄▂▁▁▂▄▃▇█▆▅▅▆█▇▃▄▂▁▁▂▄▃▇█▆▅▅▆█ }; int phl = ph.length / 3; uint th = (uint) i; if (t) { th = (uint) GLib.get_monotonic_time() + i; } int pl = (i % phl) * 3; th^=(th<<ph[pl]); th^=(th>>ph[pl+1]); th^=(th<<ph[pl+2]); if (m) { return ((int) (th % ((uint) ((e+1)-s)))) + s; } return ((int) ((((double) th) / uint32.MAX) * ((double) ((e+1)-s)))) + s; } none int intmax (int[] a) { int m = 0; int l = a.length; // 3M arrived-at via testing, // MT was slower with less than 2~3M if (l > 3000000) { // tasks are identical, use packetsize of threadcount int[] intranges = rangeseq(nthr,l); int[] maxs = new int[intranges.length]; int packetscomplete = 0; ThreadPool<mtintmax> imx = new ThreadPool<mtintmax>.with_owned_data((mtintmax) => { mtintmax.eval(ref packetscomplete,ref maxs,a);},nthr,false); int n = 0; for (int x = 0; x < intranges.length; x += 2) { imx.add(new mtintmax(n,intranges[x],intranges[x+1])); n += 1; } while (packetscomplete != n) {GLib.Thread.usleep(1);} foreach (int i in maxs) { m = int.max(m,i); } } else { foreach (int i in a) { m = int.max(m,i); } } return m; } int[] rangeseq (int p, int s) { // rangeseq // by c.p.brown 2026 // // p packet count, s sequence count // returns rangefrom,rangeto pairs in an unrolled 1d array int[] o = {}; if (s > p) { int t = s / p; double dp = ((double) p); double npt = ((double) s) / ((double) p); int v = 0; int x = 0; if ((double) t < npt) { double rem = npt - t; x = ((int) Math.round(rem * dp)); } for (int i = 0; i < p; i++) { o += v; v += (t - 1); if (x > 0) { v += 1; } o += v; v += 1; x = int.max(0,(x - 1)); } } else { for (int i = 0; i < s; i++) { o += i; o += i; } } return o; } void main() { GLib.Intl.setlocale(ALL,""); mutex = GLib.Mutex(); nthr = int.max(1,((int) GLib.get_num_processors())); int[] a = {}; int ic = 100000000; for (int i = 0; i < ic; i++) { a += xrintr(i,0,111222333,false,true); } print("get max item...\n"); int64 tts = GLib.get_monotonic_time(); int m = intmax(a); int64 tte = GLib.get_monotonic_time(); print("multithreaded intmax of %d items took %s\n",ic,printusecs(tte-tts)); print("maximum number is %d\n\n",m); a.resize(0); m = 0; ic = 3000000; for (int i = 0; i < ic; i++) { a += xrintr(i,0,111444777,false,true); } tts = GLib.get_monotonic_time(); m = intmax(a); tte = GLib.get_monotonic_time(); print("monothreaded intmax of %d items took %s\n",ic,printusecs(tte-tts)); print("maximum number is %d\n\n",m); a.resize(0); m = 0; ic = 1000000; for (int i = 0; i < ic; i++) { a += xrintr(i,0,1234567,false,true); } tts = GLib.get_monotonic_time(); m = intmax(a); tte = GLib.get_monotonic_time(); print("monothreaded intmax of %d items took %s\n",ic,printusecs(tte-tts)); print("maximum number is %d\n\n",m); }
#+RESULTS:
Compilation succeeded - 2 warning(s) get max item... multithreaded intmax of 100000000 items took 19.64 ms maximum number is 111222332 monothreaded intmax of 3000000 items took 2.92 ms maximum number is 111444772 monothreaded intmax of 1000000 items took 970 μs maximum number is 1234566
[5_DONE]XRDUBR
XDUBR_SRC
double xrdubr (int i, bool t, bool m) { // pseudo-random double between 0.0 and 1.0 // by c.p.brown 2025 // // i is seed, // t is use time + seed (different result each eval) // m is modulo i 10000 / 10000 to get numbers of 4 decimal places // // uses xorshift offsets by George Marsaglia (2003) // https://www.jstatsoft.org/article/view/v008i14 int[] ph = { 4,3,27, // 31 ▂█▄▇▃▃▇▄█▂▆▁▅█▄▇▃▅▁▆▂▂▆▁▅▃▇▄█▄ 5,27,25, // 44 ▃▅▇▁▃▅▇▁▃█▆▄▂█▆▄▂█▆▄▂█▆▄▂▇▅▃▁▇ 1,9,29, // 03 ▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆ 13,3,17, // 71 ▁▃▄▂█▆▃▁▇▅▂▄▆█▁▃▅▇█▆▄▂▇▅▃▁▆█▂▄ 9,5,25, // 61 ▆▃▄▁▂▇█▅▆▃▄▁▂█▇▆▅▄▃▂▁█▇▆▅▄▃▂▁▅ 3,7,29, // 25 ▅█▇▂▁▄▃▃▄▁▂▇█▅▆▃▄▁▂▇█▅▆▄▃▂▁█▇▆ 3,5,25, // 24 █▁▁▂▂▃▃▄▄▃▃▄▄▁▁▂▂▇▇██▅▅▆▆▄▄▃▃▂ 15,1,29 // 77 ▄▂▁▁▂▄▃▇█▆▅▅▆█▇▃▄▂▁▁▂▄▃▇█▆▅▅▆█ }; int phl = ph.length / 3; uint th = (uint) i; if (t) { th = (uint) GLib.get_monotonic_time() + i; } int pl = (i % phl) * 3; th^=(th<<ph[pl]); th^=(th>>ph[pl+1]); th^=(th<<ph[pl+2]); if (m) { return ((double) (th % 10000)) / 10000.0; } return (((double) th) / uint32.MAX); }
XRDUBR_TEST
double xrdubr (int i, bool t, bool m) { // pseudo-random double between 0.0 and 1.0 // by c.p.brown 2025 // // i is seed, // t is use time + seed (different result each eval) // m is modulo i 10000 / 10000 to get numbers of 4 decimal places // // uses xorshift offsets by George Marsaglia (2003) // https://www.jstatsoft.org/article/view/v008i14 int[] ph = { 4,3,27, // 31 ▂█▄▇▃▃▇▄█▂▆▁▅█▄▇▃▅▁▆▂▂▆▁▅▃▇▄█▄ 5,27,25, // 44 ▃▅▇▁▃▅▇▁▃█▆▄▂█▆▄▂█▆▄▂█▆▄▂▇▅▃▁▇ 1,9,29, // 03 ▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆ 13,3,17, // 71 ▁▃▄▂█▆▃▁▇▅▂▄▆█▁▃▅▇█▆▄▂▇▅▃▁▆█▂▄ 9,5,25, // 61 ▆▃▄▁▂▇█▅▆▃▄▁▂█▇▆▅▄▃▂▁█▇▆▅▄▃▂▁▅ 3,7,29, // 25 ▅█▇▂▁▄▃▃▄▁▂▇█▅▆▃▄▁▂▇█▅▆▄▃▂▁█▇▆ 3,5,25, // 24 █▁▁▂▂▃▃▄▄▃▃▄▄▁▁▂▂▇▇██▅▅▆▆▄▄▃▃▂ 15,1,29 // 77 ▄▂▁▁▂▄▃▇█▆▅▅▆█▇▃▄▂▁▁▂▄▃▇█▆▅▅▆█ }; int phl = ph.length / 3; uint th = (uint) i; if (t) { th = (uint) GLib.get_monotonic_time() + i; } int pl = (i % phl) * 3; th^=(th<<ph[pl]); th^=(th>>ph[pl+1]); th^=(th<<ph[pl+2]); if (m) { return ((double) (th % 10000)) / 10000.0; } return (((double) th) / uint32.MAX); } void main() { GLib.Intl.setlocale(ALL,""); int s = 20; double f = 0.05; print("scale to range using fixed seed\n"); for (int i = 0; i < s; i++) { double r = xrdubr(i,false,false); print("[%03d] %0.8f ",i,r); for (double b = 0.0; b < r; b += f) { print("█"); } print("\n"); } print("\nmodulo within range using fixed seed\n"); for (int i = 0; i < s; i++) { double r = xrdubr(i,false,true); print("[%03d] %0.8f ",i,r); for (double b = 0.0; b < r; b += f) { print("█"); } print("\n"); } print("\nscale to range using seed+time\n"); for (int i = 0; i < s; i++) { double r = xrdubr(i,true,false); print("[%03d] %0.8f ",i,r); for (double b = 0.0; b < r; b += f) { print("█"); } print("\n"); } print("\nmodulo within range using seed+time\n"); for (int i = 0; i < s; i++) { double r = xrdubr(i,true,true); print("[%03d] %0.8f ",i,r); for (double b = 0.0; b < r; b += f) { print("█"); } print("\n"); } }
#+RESULTS:
scale to range using fixed seed [000] 0.00000000 [001] 0.25781251 ██████ [002] 0.75000000 ████████████████ [003] 0.84384799 █████████████████ [004] 0.53125049 ███████████ [005] 0.62500001 █████████████ [006] 0.42968751 █████████ [007] 0.50003433 ███████████ [008] 0.78125004 ████████████████ [009] 0.32031257 ███████ [010] 0.75000001 ████████████████ [011] 0.59407497 ████████████ [012] 0.59375148 ████████████ [013] 0.62500002 █████████████ [014] 0.97656253 ████████████████████ [015] 0.00006485 █ [016] 0.56250007 ████████████ [017] 0.38281263 ████████ [018] 0.75000001 ████████████████ [019] 0.34424091 ███████ modulo within range using fixed seed [000] 0.00000000 [001] 0.62890000 █████████████ [002] 0.54780000 ███████████ [003] 0.95230000 ████████████████████ [004] 0.34920000 ███████ [005] 0.46050000 ██████████ [006] 0.38150000 ████████ [007] 0.11080000 ███ [008] 0.33530000 ███████ [009] 0.20090000 █████ [010] 0.55020000 ████████████ [011] 0.25540000 ██████ [012] 0.31800000 ███████ [013] 0.46610000 ██████████ [014] 0.41250000 █████████ [015] 0.85360000 ██████████████████ [016] 0.94100000 ███████████████████ [017] 0.77290000 ████████████████ [018] 0.55260000 ████████████ [019] 0.34410000 ███████ scale to range using seed+time [000] 0.95566606 ████████████████████ [001] 0.03534285 █ [002] 0.77861259 ████████████████ [003] 0.24497789 █████ [004] 0.80925123 █████████████████ [005] 0.21059330 █████ [006] 0.95574079 ████████████████████ [007] 0.97821163 ████████████████████ [008] 0.51816583 ███████████ [009] 0.47284205 ██████████ [010] 0.52861254 ███████████ [011] 0.43427981 █████████ [012] 0.73893002 ███████████████ [013] 0.33559358 ███████ [014] 0.83074065 █████████████████ [015] 0.22734185 █████ [016] 0.51816618 ███████████ [017] 0.63690405 █████████████ [018] 0.02861250 █ [019] 0.43637028 █████████ modulo within range using seed+time [000] 0.39540000 ████████ [001] 0.73830000 ███████████████ [002] 0.25260000 ██████ [003] 0.47970000 ██████████ [004] 0.66620000 ██████████████ [005] 0.49110000 ██████████ [006] 0.36020000 ████████ [007] 0.74250000 ███████████████ [008] 0.13500000 ███ [009] 0.96850000 ████████████████████ [010] 0.33760000 ███████ [011] 0.36820000 ████████ [012] 0.06530000 ██ [013] 0.29660000 ██████ [014] 0.46820000 ██████████ [015] 0.41760000 █████████ [016] 0.15540000 ████ [017] 0.28430000 ██████ [018] 0.97800000 ████████████████████ [019] 0.21240000 █████
[5_DONE]XRINTR
XRINTR_SRC
int xrintr (int i, int s, int e, bool t, bool m) { // pseudo-random integer range // by c.p.brown 2025 // // i is seed, s is min value, e is max value, // t is use time + seed (different result each eval) // m is modulo within range rather than scale to range // // uses xorshift offsets by George Marsaglia (2003) // https://www.jstatsoft.org/article/view/v008i14 int[] ph = { 4,3,27, // 31 ▂█▄▇▃▃▇▄█▂▆▁▅█▄▇▃▅▁▆▂▂▆▁▅▃▇▄█▄ 5,27,25, // 44 ▃▅▇▁▃▅▇▁▃█▆▄▂█▆▄▂█▆▄▂█▆▄▂▇▅▃▁▇ 1,9,29, // 03 ▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆ 13,3,17, // 71 ▁▃▄▂█▆▃▁▇▅▂▄▆█▁▃▅▇█▆▄▂▇▅▃▁▆█▂▄ 9,5,25, // 61 ▆▃▄▁▂▇█▅▆▃▄▁▂█▇▆▅▄▃▂▁█▇▆▅▄▃▂▁▅ 3,7,29, // 25 ▅█▇▂▁▄▃▃▄▁▂▇█▅▆▃▄▁▂▇█▅▆▄▃▂▁█▇▆ 3,5,25, // 24 █▁▁▂▂▃▃▄▄▃▃▄▄▁▁▂▂▇▇██▅▅▆▆▄▄▃▃▂ 15,1,29 // 77 ▄▂▁▁▂▄▃▇█▆▅▅▆█▇▃▄▂▁▁▂▄▃▇█▆▅▅▆█ }; int phl = ph.length / 3; uint th = (uint) i; if (t) { th = (uint) GLib.get_monotonic_time() + i; } int pl = (i % phl) * 3; th^=(th<<ph[pl]); th^=(th>>ph[pl+1]); th^=(th<<ph[pl+2]); if (m) { return ((int) (th % ((uint) ((e+1)-s)))) + s; } return ((int) ((((double) th) / uint32.MAX) * ((double) ((e+1)-s)))) + s; }
XRINTR_TEST
int xrintr (int i, int s, int e, bool t, bool m) { // pseudo-random integer range // by c.p.brown 2025 // // i is seed, s is min value, e is max value, // t is use time + seed (different result each eval) // m is modulo within range rather than scale to range // // uses xorshift offsets by George Marsaglia (2003) // https://www.jstatsoft.org/article/view/v008i14 int[] ph = { 4,3,27, // 31 ▂█▄▇▃▃▇▄█▂▆▁▅█▄▇▃▅▁▆▂▂▆▁▅▃▇▄█▄ 5,27,25, // 44 ▃▅▇▁▃▅▇▁▃█▆▄▂█▆▄▂█▆▄▂█▆▄▂▇▅▃▁▇ 1,9,29, // 03 ▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆ 13,3,17, // 71 ▁▃▄▂█▆▃▁▇▅▂▄▆█▁▃▅▇█▆▄▂▇▅▃▁▆█▂▄ 9,5,25, // 61 ▆▃▄▁▂▇█▅▆▃▄▁▂█▇▆▅▄▃▂▁█▇▆▅▄▃▂▁▅ 3,7,29, // 25 ▅█▇▂▁▄▃▃▄▁▂▇█▅▆▃▄▁▂▇█▅▆▄▃▂▁█▇▆ 3,5,25, // 24 █▁▁▂▂▃▃▄▄▃▃▄▄▁▁▂▂▇▇██▅▅▆▆▄▄▃▃▂ 15,1,29 // 77 ▄▂▁▁▂▄▃▇█▆▅▅▆█▇▃▄▂▁▁▂▄▃▇█▆▅▅▆█ }; int phl = ph.length / 3; uint th = (uint) i; if (t) { th = (uint) GLib.get_monotonic_time() + i; } int pl = (i % phl) * 3; th^=(th<<ph[pl]); th^=(th>>ph[pl+1]); th^=(th<<ph[pl+2]); if (m) { return ((int) (th % ((uint) ((e+1)-s)))) + s; } return ((int) ((((double) th) / uint32.MAX) * ((double) ((e+1)-s)))) + s; } void main() { GLib.Intl.setlocale(ALL,""); int s = 20; print("scale to range using fixed seed\n"); for (int i = 0; i < s; i++) { int r = xrintr(i,0,10,false,false); print("[%03d] %03d ",i,r); for (int b = 0; b < r; b++) { print("█"); } print("\n"); } print("\nmodulo within range using fixed seed\n"); for (int i = 0; i < s; i++) { int r = xrintr(i,0,10,false,true); print("[%03d] %03d ",i,r); for (int b = 0; b < r; b++) { print("█"); } print("\n"); } print("\nscale to range using seed+time\n"); for (int i = 0; i < s; i++) { int r = xrintr(i,0,10,true,false); print("[%03d] %03d ",i,r); for (int b = 0; b < r; b++) { print("█"); } print("\n"); } print("\nmodulo within range using seed+time\n"); for (int i = 0; i < s; i++) { int r = xrintr(i,0,10,true,true); print("[%03d] %03d ",i,r); for (int b = 0; b < r; b++) { print("█"); } print("\n"); } }
#+RESULTS:
scale to range using fixed seed [000] 000 [001] 001 █ [002] 005 █████ [003] 002 ██ [004] 004 ████ [005] 007 ███████ [006] 002 ██ [007] 005 █████ [008] 002 ██ [009] 001 █ [010] 006 ██████ [011] 006 ██████ [012] 007 ███████ [013] 007 ███████ [014] 002 ██ [015] 000 [016] 005 █████ [017] 000 [018] 007 ███████ [019] 001 █ modulo within range using fixed seed [000] 000 [001] 004 ████ [002] 000 [003] 000 [004] 006 ██████ [005] 008 ████████ [006] 000 [007] 007 ███████ [008] 002 ██ [009] 005 █████ [010] 003 ███ [011] 000 [012] 008 ████████ [013] 008 ████████ [014] 008 ████████ [015] 005 █████ [016] 004 ████ [017] 009 █████████ [018] 006 ██████ [019] 007 ███████ scale to range using seed+time [000] 005 █████ [001] 009 █████████ [002] 008 ████████ [003] 009 █████████ [004] 002 ██ [005] 006 ██████ [006] 009 █████████ [007] 010 ██████████ [008] 006 ██████ [009] 008 ████████ [010] 007 ███████ [011] 007 ███████ [012] 000 [013] 000 [014] 003 ███ [015] 003 ███ [016] 007 ███████ [017] 008 ████████ [018] 004 ████ [019] 000 modulo within range using seed+time [000] 001 █ [001] 007 ███████ [002] 000 [003] 004 ████ [004] 006 ██████ [005] 003 ███ [006] 010 ██████████ [007] 008 ████████ [008] 004 ████ [009] 003 ███ [010] 005 █████ [011] 005 █████ [012] 005 █████ [013] 003 ███ [014] 002 ██ [015] 000 [016] 010 ██████████ [017] 009 █████████ [018] 003 ███ [019] 000
[5_DONE]BIASGAIN
BIASGAIN_SRC
double biasgain (double x, double g, double s) { // biasgain // by c.p.brown 2026 // // this is derivative of: // Christophe Schlick // https://dept-info.labri.fr/~schlick/DOC/gem2.html // Jonathan T Barron // https://ar5iv.labs.arxiv.org/html/2010.09714 // Thomas Mann // https://github.com/tixl3d/tixl/blob/main/Core/Utils/MathUtils.cs double o = 0.0; double e = double.EPSILON; double r = 200.0; double b = s * 2.0; //double t = f; if (b < 1.0) { b = Math.pow(r,(1.0 - b)); } else { b = (1.0 / Math.pow(r,(b - 1.0))); } if (x < g) { o = ((g * x) / ((x + (b * (g - x))) + e)); } else { o = ((((1.0 - g) * (x - 1.0)) / (((1.0 - x) - (b * (g - x))) + e)) + 1.0); } return o; }
BIASGAIN_TEST
// biasgain test // by c.p.brown 2026 // // plot numbers are fudged to make them 1-based for illustrative purposes string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } double biasgain (double x, double g, double s) { // biasgain // by c.p.brown 2026 // // this is derivative of: // Christophe Schlick // https://dept-info.labri.fr/~schlick/DOC/gem2.html // Jonathan T Barron // https://ar5iv.labs.arxiv.org/html/2010.09714 // Thomas Mann // https://github.com/tixl3d/tixl/blob/main/Core/Utils/MathUtils.cs double o = 0.0; double e = double.EPSILON; double r = 200.0; double b = s * 2.0; //double t = f; if (b < 1.0) { b = Math.pow(r,(1.0 - b)); } else { b = (1.0 / Math.pow(r,(b - 1.0))); } if (x < g) { o = ((g * x) / ((x + (b * (g - x))) + e)); } else { o = ((((1.0 - g) * (x - 1.0)) / (((1.0 - x) - (b * (g - x))) + e)) + 1.0); } return o; } void main() { int64 tts = GLib.get_monotonic_time(); GLib.Intl.setlocale(ALL,""); //int st = 0; double[] sfs = { 0.0, 0.33, 0.0, 0.5, 0.0, 0.66, 0.2, 0.66, 0.5, 0.66, 0.8, 0.66, 0.5, 0.5, 0.2, 0.33, 0.5, 0.33, 0.8, 0.33 }; int w = 19; int c = 10; double l = (double) (c - 1); for (int i = 0; i < sfs.length; i += 2) { double f = sfs[i]; double s = sfs[i+1]; print("s = %.2f, f = %.2f\n",s,f); for (int n = 0; n < c; n++) { double x = (n * 1.0) / l; double g = biasgain(x,f,s); int bar = ((int) (g * w)) + 1; string plot = ""; for (int j = 1; j <= bar; j++) { plot = plot + "█"; } print("%02d | %0.2f | %0.2f\t| %02d | %s\n",n,x,g,bar,plot); } print("\n"); } int64 tte = GLib.get_monotonic_time(); print("\nbiasgain test took %s\n",printusecs(tte - tts)); }
#+RESULTS:
s = 0.33, f = 0.00 00 | 0.00 | 0.00 | 01 | █ 01 | 0.11 | 0.43 | 09 | █████████ 02 | 0.22 | 0.63 | 13 | █████████████ 03 | 0.33 | 0.75 | 15 | ███████████████ 04 | 0.44 | 0.83 | 16 | ████████████████ 05 | 0.56 | 0.88 | 17 | █████████████████ 06 | 0.67 | 0.92 | 18 | ██████████████████ 07 | 0.78 | 0.95 | 19 | ███████████████████ 08 | 0.89 | 0.98 | 19 | ███████████████████ 09 | 1.00 | 1.00 | 20 | ████████████████████ s = 0.50, f = 0.00 00 | 0.00 | 0.00 | 01 | █ 01 | 0.11 | 0.11 | 03 | ███ 02 | 0.22 | 0.22 | 05 | █████ 03 | 0.33 | 0.33 | 07 | ███████ 04 | 0.44 | 0.44 | 09 | █████████ 05 | 0.56 | 0.56 | 11 | ███████████ 06 | 0.67 | 0.67 | 13 | █████████████ 07 | 0.78 | 0.78 | 15 | ███████████████ 08 | 0.89 | 0.89 | 17 | █████████████████ 09 | 1.00 | 1.00 | 20 | ████████████████████ s = 0.66, f = 0.00 00 | 0.00 | 0.00 | 01 | █ 01 | 0.11 | 0.02 | 01 | █ 02 | 0.22 | 0.05 | 01 | █ 03 | 0.33 | 0.08 | 02 | ██ 04 | 0.44 | 0.13 | 03 | ███ 05 | 0.56 | 0.19 | 04 | ████ 06 | 0.67 | 0.27 | 06 | ██████ 07 | 0.78 | 0.39 | 08 | ████████ 08 | 0.89 | 0.59 | 12 | ████████████ 09 | 1.00 | 1.00 | 20 | ████████████████████ s = 0.66, f = 0.20 00 | 0.00 | 0.00 | 01 | █ 01 | 0.11 | 0.17 | 04 | ████ 02 | 0.22 | 0.20 | 04 | ████ 03 | 0.33 | 0.23 | 05 | █████ 04 | 0.44 | 0.26 | 05 | █████ 05 | 0.56 | 0.30 | 06 | ██████ 06 | 0.67 | 0.36 | 07 | ███████ 07 | 0.78 | 0.46 | 09 | █████████ 08 | 0.89 | 0.63 | 12 | ████████████ 09 | 1.00 | 1.00 | 20 | ████████████████████ s = 0.66, f = 0.50 00 | 0.00 | 0.00 | 01 | █ 01 | 0.11 | 0.30 | 06 | ██████ 02 | 0.22 | 0.41 | 08 | ████████ 03 | 0.33 | 0.46 | 09 | █████████ 04 | 0.44 | 0.49 | 10 | ██████████ 05 | 0.56 | 0.51 | 10 | ██████████ 06 | 0.67 | 0.54 | 11 | ███████████ 07 | 0.78 | 0.59 | 12 | ████████████ 08 | 0.89 | 0.70 | 14 | ██████████████ 09 | 1.00 | 1.00 | 20 | ████████████████████ s = 0.66, f = 0.80 00 | 0.00 | 0.00 | 01 | █ 01 | 0.11 | 0.37 | 08 | ████████ 02 | 0.22 | 0.54 | 11 | ███████████ 03 | 0.33 | 0.64 | 13 | █████████████ 04 | 0.44 | 0.70 | 14 | ██████████████ 05 | 0.56 | 0.74 | 15 | ███████████████ 06 | 0.67 | 0.77 | 15 | ███████████████ 07 | 0.78 | 0.80 | 16 | ████████████████ 08 | 0.89 | 0.83 | 16 | ████████████████ 09 | 1.00 | 1.00 | 20 | ████████████████████ s = 0.50, f = 0.50 00 | 0.00 | 0.00 | 01 | █ 01 | 0.11 | 0.11 | 03 | ███ 02 | 0.22 | 0.22 | 05 | █████ 03 | 0.33 | 0.33 | 07 | ███████ 04 | 0.44 | 0.44 | 09 | █████████ 05 | 0.56 | 0.56 | 11 | ███████████ 06 | 0.67 | 0.67 | 13 | █████████████ 07 | 0.78 | 0.78 | 15 | ███████████████ 08 | 0.89 | 0.89 | 17 | █████████████████ 09 | 1.00 | 1.00 | 20 | ████████████████████ s = 0.33, f = 0.20 00 | 0.00 | 0.00 | 01 | █ 01 | 0.11 | 0.03 | 01 | █ 02 | 0.22 | 0.32 | 07 | ███████ 03 | 0.33 | 0.64 | 13 | █████████████ 04 | 0.44 | 0.78 | 15 | ███████████████ 05 | 0.56 | 0.86 | 17 | █████████████████ 06 | 0.67 | 0.92 | 18 | ██████████████████ 07 | 0.78 | 0.95 | 19 | ███████████████████ 08 | 0.89 | 0.98 | 19 | ███████████████████ 09 | 1.00 | 1.00 | 20 | ████████████████████ s = 0.33, f = 0.50 00 | 0.00 | 0.00 | 01 | █ 01 | 0.11 | 0.02 | 01 | █ 02 | 0.22 | 0.06 | 02 | ██ 03 | 0.33 | 0.12 | 03 | ███ 04 | 0.44 | 0.28 | 06 | ██████ 05 | 0.56 | 0.72 | 14 | ██████████████ 06 | 0.67 | 0.88 | 17 | █████████████████ 07 | 0.78 | 0.94 | 18 | ██████████████████ 08 | 0.89 | 0.98 | 19 | ███████████████████ 09 | 1.00 | 1.00 | 20 | ████████████████████ s = 0.33, f = 0.80 00 | 0.00 | 0.00 | 01 | █ 01 | 0.11 | 0.02 | 01 | █ 02 | 0.22 | 0.05 | 01 | █ 03 | 0.33 | 0.08 | 02 | ██ 04 | 0.44 | 0.14 | 03 | ███ 05 | 0.56 | 0.22 | 05 | █████ 06 | 0.67 | 0.36 | 07 | ███████ 07 | 0.78 | 0.68 | 13 | █████████████ 08 | 0.89 | 0.97 | 19 | ███████████████████ 09 | 1.00 | 1.00 | 20 | ████████████████████ biasgain test took 202 μs
MODULO

Misc modulo sanity-checks go here...

int imod (int l, int r) { if (l >= 0) { return (l % r); } if (l >= -r) { return (l + r); } return ((l % r) + r) % r; } void main() { for (int i = 0; i < 32; i++) { if ((i % 9) == 0) { print("\n"); } print("ROW %d (%d / %d)\n",(i / 9),1,9); print("COL %d (%d %% %d)\n",(i % 9),i,9); print(""); } int[] nums = {}; for (int i = 0; i < 10; i++) { nums += i; } int l = nums.length; print("\ncycle through an array of 10 items, from 0 to 9 using i %% length; (10)...\n"); for (int i = 3; i < 12; i++) { print("nums[%d] is %d\n",(i % l),nums[(i % l)]); } print("\n cycle through several lots of 1 to 12...\n"); for (int i = 0; i < 30; i++) { print("((%d %% 12) + 1) is %d\n",i,((i % 12) + 1)); } print("\nsubtract 1 from a month, wrapping from 1 to 12...\n"); for (int i = 1; i < 13; i++) { print("month (%d-1) is %d\n",i,(i-1)); print("month (((%d-2)%%12)+1) is %d\n",i,(imod((i-2),12)+1)); } print("\nis it a leap year?\n"); print("1600 % 100 is %d\n",(1600 % 100)); print("1600 % 400 is %d\n",(1600 % 400)); print("1600 % 4 is %d\n",(1600 % 4)); print("1700 % 100 is %d\n",(1700 % 100)); print("1700 % 400 is %d\n",(1700 % 400)); print("1700 % 4 is %d\n",(1700 % 4)); print("1800 % 100 is %d\n",(1800 % 100)); print("1800 % 400 is %d\n",(1800 % 400)); print("1800 % 4 is %d\n",(1800 % 4)); print("1900 % 100 is %d\n",(1900 % 100)); print("1900 % 400 is %d\n",(1900 % 400)); print("1900 % 4 is %d\n",(1900 % 4)); print("2000 % 100 is %d\n",(2000 % 100)); print("2000 % 400 is %d\n",(2000 % 400)); print("2000 % 4 is %d\n",(2000 % 4)); print("2024 % 100 is %d\n",(2024 % 100)); print("2024 % 400 is %d\n",(2024 % 400)); print("2024 % 4 is %d\n",(2024 % 4)); print("2025 % 100 is %d\n",(2025 % 100)); print("2025 % 400 is %d\n",(2025 % 400)); print("2025 % 4 is %d\n",(2025 % 4)); print("2100 % 100 is %d\n",(2100 % 100)); print("2100 % 400 is %d\n",(2100 % 400)); print("2100 % 4 is %d\n",(2100 % 4)); print("\n"); print("(%d + %d) %% 2 is %d\n",0,1,((0+1)%2)); print("(%d + %d) %% 2 is %d\n",0,0,((0+0)%2)); print("(%d + %d) %% 2 is %d\n",1,1,((1+1)%2)); print("(%d + %d) %% 2 is %d\n",1,0,((1+0)%2)); }
#+RESULTS:
ROW 0 (1 / 9) COL 0 (0 % 9) ROW 0 (1 / 9) COL 1 (1 % 9) ROW 0 (1 / 9) COL 2 (2 % 9) ROW 0 (1 / 9) COL 3 (3 % 9) ROW 0 (1 / 9) COL 4 (4 % 9) ROW 0 (1 / 9) COL 5 (5 % 9) ROW 0 (1 / 9) COL 6 (6 % 9) ROW 0 (1 / 9) COL 7 (7 % 9) ROW 0 (1 / 9) COL 8 (8 % 9) ROW 1 (1 / 9) COL 0 (9 % 9) ROW 1 (1 / 9) COL 1 (10 % 9) ROW 1 (1 / 9) COL 2 (11 % 9) ROW 1 (1 / 9) COL 3 (12 % 9) ROW 1 (1 / 9) COL 4 (13 % 9) ROW 1 (1 / 9) COL 5 (14 % 9) ROW 1 (1 / 9) COL 6 (15 % 9) ROW 1 (1 / 9) COL 7 (16 % 9) ROW 1 (1 / 9) COL 8 (17 % 9) ROW 2 (1 / 9) COL 0 (18 % 9) ROW 2 (1 / 9) COL 1 (19 % 9) ROW 2 (1 / 9) COL 2 (20 % 9) ROW 2 (1 / 9) COL 3 (21 % 9) ROW 2 (1 / 9) COL 4 (22 % 9) ROW 2 (1 / 9) COL 5 (23 % 9) ROW 2 (1 / 9) COL 6 (24 % 9) ROW 2 (1 / 9) COL 7 (25 % 9) ROW 2 (1 / 9) COL 8 (26 % 9) ROW 3 (1 / 9) COL 0 (27 % 9) ROW 3 (1 / 9) COL 1 (28 % 9) ROW 3 (1 / 9) COL 2 (29 % 9) ROW 3 (1 / 9) COL 3 (30 % 9) ROW 3 (1 / 9) COL 4 (31 % 9) cycle through an array of 10 items, from 0 to 9 using i % length; (10)... nums[3] is 3 nums[4] is 4 nums[5] is 5 nums[6] is 6 nums[7] is 7 nums[8] is 8 nums[9] is 9 nums[0] is 0 nums[1] is 1 cycle through several lots of 1 to 12... ((0 % 12) + 1) is 1 ((1 % 12) + 1) is 2 ((2 % 12) + 1) is 3 ((3 % 12) + 1) is 4 ((4 % 12) + 1) is 5 ((5 % 12) + 1) is 6 ((6 % 12) + 1) is 7 ((7 % 12) + 1) is 8 ((8 % 12) + 1) is 9 ((9 % 12) + 1) is 10 ((10 % 12) + 1) is 11 ((11 % 12) + 1) is 12 ((12 % 12) + 1) is 1 ((13 % 12) + 1) is 2 ((14 % 12) + 1) is 3 ((15 % 12) + 1) is 4 ((16 % 12) + 1) is 5 ((17 % 12) + 1) is 6 ((18 % 12) + 1) is 7 ((19 % 12) + 1) is 8 ((20 % 12) + 1) is 9 ((21 % 12) + 1) is 10 ((22 % 12) + 1) is 11 ((23 % 12) + 1) is 12 ((24 % 12) + 1) is 1 ((25 % 12) + 1) is 2 ((26 % 12) + 1) is 3 ((27 % 12) + 1) is 4 ((28 % 12) + 1) is 5 ((29 % 12) + 1) is 6 subtract 1 from a month, wrapping from 1 to 12... month (1-1) is 0 month (((1-2)%12)+1) is 12 month (2-1) is 1 month (((2-2)%12)+1) is 1 month (3-1) is 2 month (((3-2)%12)+1) is 2 month (4-1) is 3 month (((4-2)%12)+1) is 3 month (5-1) is 4 month (((5-2)%12)+1) is 4 month (6-1) is 5 month (((6-2)%12)+1) is 5 month (7-1) is 6 month (((7-2)%12)+1) is 6 month (8-1) is 7 month (((8-2)%12)+1) is 7 month (9-1) is 8 month (((9-2)%12)+1) is 8 month (10-1) is 9 month (((10-2)%12)+1) is 9 month (11-1) is 10 month (((11-2)%12)+1) is 10 month (12-1) is 11 month (((12-2)%12)+1) is 11 is it a leap year? 1600 % 100 is 0 1600 % 400 is 0 1600 % 4 is 0 1700 % 100 is 0 1700 % 400 is 100 1700 % 4 is 0 1800 % 100 is 0 1800 % 400 is 200 1800 % 4 is 0 1900 % 100 is 0 1900 % 400 is 300 1900 % 4 is 0 2000 % 100 is 0 2000 % 400 is 0 2000 % 4 is 0 2024 % 100 is 24 2024 % 400 is 24 2024 % 4 is 0 2025 % 100 is 25 2025 % 400 is 25 2025 % 4 is 1 2100 % 100 is 0 2100 % 400 is 100 2100 % 4 is 0 (0 + 1) % 2 is 1 (0 + 0) % 2 is 0 (1 + 1) % 2 is 0 (1 + 0) % 2 is 1
PARSING
GOLDPACT

Check char pair balance.
Used to validate expressions before parsing them.

// char-pair check // unroll to visualize, assuming the string passes the check // by c.p.brown, 2024 // // TODO: check for escape chars, quotes and commented lines string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.3f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.3f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.3f m".printf((((double) u) / 60000000.0)); } return us; } bool goldpact(string s, unichar c) { StringBuilder xpr = new StringBuilder(""); xpr.append(s.strip()); unichar a = '('; unichar b = ')'; bool isidentical = false; if (c == '[') { a = '['; b = ']'; } else { if (c == '{') { a = '{'; b = '}'; } else { if (c == '<') { a = '<'; b = '>'; } else { if (c == '\"') { a = '\"'; b = '\"'; isidentical = true; } else { if (c == '\'') { a = '\''; b = '\''; isidentical = true; } else { print("invalid character %s\n",c.to_string()); return false; } } } } } int ii = xpr.str.index_of_char(a); int oo = xpr.str.index_of_char(b,(ii+1)); int i = 0; int o = 0; int pos = 0; int n = 0; if ((ii != -1) && (oo != -1)) { if (ii == 0) { i += 1; } while (pos != -1) { int nxt = xpr.str.index_of_char(a,(pos+1)); if (!isidentical) { oo = xpr.str.index_of_char(b,pos+1); if ((nxt != -1) && (nxt < oo)) { i += 1; } pos = nxt; if (oo != -1) { if (oo < nxt) { pos = oo; o += 1; } if (nxt == -1) { pos = oo; o += 1; } } } else { if (nxt != -1) { i += 1; } pos = nxt; } n += 1; } print("goldpact ran %d iterations\n",n); if (isidentical) { //i -= 1; return ((i & 1) == 0); } else { return (i == o); } } return false; } string unroll (string s, unichar c) { StringBuilder xpr = new StringBuilder(""); xpr.append(s.strip()); unichar a = '('; unichar b = ')'; bool isidentical = false; if (c == '[') { a = '['; b = ']'; } else { if (c == '{') { a = '{'; b = '}'; } else { if (c == '<') { a = '<'; b = '>'; } else { if (c == '\"') { a = '\"'; b = '\"'; isidentical = true; } else { if (c == '\'') { a = '\''; b = '\''; isidentical = true; } else { return "invalid character %s".printf(c.to_string()); } } } } } int ii = xpr.str.index_of_char(a); int oo = xpr.str.index_of_char(b,(ii+1)); int pos = 0; int i = 0; string u = ""; string tabs = ""; int n = 0; while (pos != -1) { int nxt = xpr.str.index_of_char(a,pos); if (!isidentical) { int npos = nxt; oo = xpr.str.index_of_char(b,pos); if ((nxt != -1) && (nxt < oo)) { i += 1; npos += 1; u = u + tabs + xpr.str.substring(pos,(npos-pos)).strip()+ "\n"; tabs = ("%*s").printf(i,"").replace(" ","\t"); //u = u + tabs + "%s".printf(a.to_string()) + "\n"; } if (oo != -1) { if ((oo < nxt) || (nxt == -1)) { i -= 1; string thisline = xpr.str.substring(pos,(oo-pos)).strip(); if (thisline.char_count() > 0) { u = u + tabs + xpr.str.substring(pos,(oo-pos)).strip() + "\n"; } tabs = ("%*s").printf(i,"").replace(" ","\t"); u = u + tabs + "%s".printf(b.to_string()) + "\n"; pos = oo + 1; } else { pos = npos; } } else { pos = npos; } } else { if (nxt != -1) { n += 1; if ((n & 1) != 0) { i += 1; u = u + tabs + xpr.str.substring(pos,((nxt+1)-pos)).strip()+ "\n"; tabs = ("%*s").printf(i,"").replace(" ","\t"); } else { i -= 1; string thisline = xpr.str.substring(pos,(nxt-pos)).strip(); if (thisline.char_count() > 0) { u = u + tabs + xpr.str.substring(pos,(nxt-pos)).strip() + "\n"; } tabs = ("%*s").printf(i,"").replace(" ","\t"); u = u + tabs + "%s".printf(b.to_string()) + "\n"; } pos = nxt + 1; } else { break; } } } return u; } void main () { GLib.Intl.setlocale(ALL,""); string s = "[ MUL X [PARAM 0.1 0.0 1.0 ][ DIV [ COMP A ] X ]]"; bool isbalanced = goldpact(s,'['); if (isbalanced) { print("expression has balanced brackets:\n%s\n",unroll(s,'[')); } else { print("expression is unbalanced: %s\n\n",s); } s = "[ MUL X [PARAM 0.1 0.0 1.0 [ DIV [ COMP A ] X ]]"; isbalanced = goldpact(s,'['); if (isbalanced) { print("expression has balanced brackets:\n%s\n",unroll(s,'[')); } else { print("expression is unbalanced: %s\n\n",s); } s = "[[[MUL X[PARAM 0.1 0.0 1.0][DIV[COMP A]X]]]]"; isbalanced = goldpact(s,'['); if (isbalanced) { print("expression has balanced brackets:\n%s\n",unroll(s,'[')); } else { print("expression is unbalanced: %s\n\n",s); } s = "[[[[[[MUL X[PARAM 0.1 0.0 1.0 DIV[][]]]COMP A]X][]]]"; isbalanced = goldpact(s,'['); if (isbalanced) { print("expression has balanced brackets:\n%s\n",unroll(s,'[')); } else { print("expression is unbalanced: %s\n\n",s); } s = "COMMENT[][][MUL X[PARAM 0.1 0.0 1.0][DIV[COMP A []][]X]][][]"; isbalanced = goldpact(s,'['); if (isbalanced) { print("expression has balanced brackets:\n%s\n",unroll(s,'[')); } else { print("expression is unbalanced: %s\n\n",s); } s = "a \"string \"in a\" string\" ?"; isbalanced = goldpact(s,'\"'); if (isbalanced) { print("text has balanced quotes, however unrolling it isn't useful:\n%s\n",unroll(s,'\"')); } else { print("string quotes are unbalanced: %s\n\n",s); } print("\n\ncheck a 4305-line file:\n"); StringBuilder sb = new StringBuilder(""); string testfile = "test_zui.vala"; string ff = Path.build_filename ("./", testfile); GLib.File og = File.new_for_path(ff); if (og.query_exists() == true) { try { uint8[] ca; string oe; og.load_contents (null, out ca, out oe); sb.append((string) ca); } catch (Error e) { print ("\tfailed to read %s: %s\n", og.get_path(), e.message); } } int64 tts = GLib.get_monotonic_time(); isbalanced = goldpact(sb.str,'{'); if (isbalanced) { print("test_zui.vala is balanced\n"); } else { print("test_zui.vala is not balanced, probably because we're not looking for commented, quoted or escaped curlies here\n"); } int64 tte = GLib.get_monotonic_time(); print("goldpact stress test took %s\n",printusecs(tte-tts)); }
#+RESULTS:
goldpact ran 8 iterations expression has balanced brackets: [ MUL X [ PARAM 0.1 0.0 1.0 ] [ DIV [ COMP A ] X ] ] goldpact ran 7 iterations expression is unbalanced: [ MUL X [PARAM 0.1 0.0 1.0 [ DIV [ COMP A ] X ]] goldpact ran 12 iterations expression has balanced brackets: [ [ [ MUL X[ PARAM 0.1 0.0 1.0 ] [ DIV[ COMP A ] X ] ] ] ] goldpact ran 19 iterations expression is unbalanced: [[[[[[MUL X[PARAM 0.1 0.0 1.0 DIV[][]]]COMP A]X][]]] goldpact ran 21 iterations expression has balanced brackets: COMMENT[ ] [ ] [ MUL X[ PARAM 0.1 0.0 1.0 ] [ DIV[ COMP A [ ] ] [ ] X ] ] [ ] [ ] goldpact ran 5 iterations text has balanced quotes, however unrolling it isn't useful: a " string " in a" string " check a 4305-line file: goldpact ran 2071 iterations text_zui.vala is not balanced, probably because we're not looking for commented or escaped curlies here goldpact stress test took 252 μs
PRINT
PRINT1DARRAY
PRINT1DARRAY_SRC
string print1darray (int ind, string[] dat, int dsz, bool h, bool rnm, bool cnm, int mw, int m, uint8[] hc) { // print an unrolled 2d array // by c.p.brown, 2025..2026 // // dat is the string[] // dsz is column count // h is render header // rnm is render row numbers // cnm is render cell numbers // mw is what to mask: 0 nothing 1 row 2 col // m is row/column to highlight string tabs = ("%*s").printf(ind," ").replace(" ","\t"); string spc = " "; int chc = 0; bool domask = (m > -1) && (mw > 0); bool maskcols = mw == 2; int rcols = dsz; int rowcount = dat.length / dsz; int firstcol = 0; string dlm = " | "; uint8 ir = hc[0]; uint8 ig = hc[1]; uint8 ib = hc[2]; if (rnm) { firstcol = 1; rcols = dsz + 1; } if (cnm) { chc = "%d".printf((dat.length - 1)).char_count(); } int[] cw = new int[rcols]; for (int i = 0; i < cw.length; i++) { cw[i] = 0; } if (rnm) { cw[0] = "%d".printf((dat.length/dsz)).char_count(); } if (h) { for (int i = firstcol; i < cw.length; i++) { string hh = ""; int d = (i-firstcol)+1; // shift to 1-based while (d > 0) { int x = ((d - 1) % 26); hh = "%c%s".printf((x+65),hh); d = ((d - x) - 1) / 26; } hh = "%d %s".printf((i-firstcol),hh); cw[i] = hh.char_count(); } } string o = ""; string ln = ""; // get counts 1st for (int i = 0; i < dat.length; i++) { int c = (i % dsz); if (rnm) { c = c + 1; } int cc = 0; if (dat[i] != null) { cc = dat[i].char_count() + chc + 3; if (cc > 0) { int nwlat = dat[i].index_of("\n"); if (nwlat != -1) { cc = (nwlat + 3 + chc + 3); } } } cw[c] = int.max(cw[c],cc); } // print header if (h) { for (int i = 0; i < cw.length; i++) { dlm = " | "; if (rnm && (i == 0)) { dlm = "%s| ".printf(tabs); string hh = "#"; o = "%s%s%-*s".printf(o,dlm,cw[i],hh); } else { if (i == 0) { dlm = "%s| ".printf(tabs); } string hh = ""; int d = (i-firstcol)+1; // shift to 1-based while (d > 0) { int x = ((d - 1) % 26); hh = "%c%s".printf((x+65),hh); d = ((d - x) - 1) / 26; } hh = "%d %s".printf((i-firstcol),hh); o = "%s%s%-*s".printf(o,dlm,cw[i],hh); } if (i == (cw.length - 1)) { o = "%s |\n".printf(o); } } // print line for (int i = 0; i < cw.length; i++) { dlm = "-+-"; if (i == 0) { dlm = "%s|-".printf(tabs); } ln = "%s%s%-*s".printf(ln,dlm,cw[i]," ").replace(" ","-"); if (i == (cw.length - 1)) { ln = "%s-|\n".printf(ln); } } o = "%s%s".printf(o,ln); } // print rows for (int r = 0; r < rowcount; r++) { for (int c = 0; c < cw.length; c++) { string datpart = ""; if ((c == 0) && rnm) { dlm = "%s| ".printf(tabs); o = "%s%s%0*d".printf(o,dlm,cw[0],r); } else { dlm = " | "; if (c == 0) { dlm = "%s| ".printf(tabs); } int j = (r * dsz) + (c - firstcol); int cc = dat[j].char_count(); if (dat[j] != null) { if (cc > 0) { datpart = dat[j]; int nwlat = dat[j].index_of("\n"); if (nwlat != -1) { //trunc = true; datpart = (dat[j].substring(0,nwlat) + "..."); cc = (nwlat + 3); } } else { cc = int.max(cc,1); } } string clen = ""; if (cnm) { clen = "(%0*d) ".printf(chc,j); } int padlen = (cw[c] - cc) - clen.char_count(); padlen = int.max(padlen,0); datpart = "%s%s%.*s".printf(clen,datpart,padlen,spc); if (domask) { bool ismakked = false; if (maskcols) { ismasked = ((m+firstcol) == c); } else { ismasked = (m == r); } if (ismasked) { datpart = "\x1b[48;2;%u;%u;%um%s\x1b[0m".printf(ir,ig,ib,datpart); //datpart = "\x1b[48;2;76;25;25m%s\x1b[0m".printf(datpart); } } o = "%s%s%s".printf(o,dlm,datpart); if (c == (cw.length - 1)) { o = "%s |\n".printf(o); } } } } cw = null; return o; }
PRINT1DARRAY_TEST

Assumes array is an unrolled 2d string[]

// test print1darray // by c.p.brown 2026 string print1darray (int ind, string[] dat, int dsz, bool h, bool rnm, bool cnm, int mw, int m, uint8[] hc) { // print an unrolled 2d array // by c.p.brown, 2025..2026 // // dat is the string[] // dsz is column count // h is render header // rnm is render row numbers // cnm is render cell numbers // mw is what to mask: 0 nothing 1 row 2 col // m is row/column to highlight string tabs = ("%*s").printf(ind," ").replace(" ","\t"); string spc = " "; int chc = 0; bool domask = (m > -1) && (mw > 0); bool maskcols = mw == 2; int rcols = dsz; int rowcount = dat.length / dsz; int firstcol = 0; string dlm = " | "; uint8 ir = hc[0]; uint8 ig = hc[1]; uint8 ib = hc[2]; if (rnm) { firstcol = 1; rcols = dsz + 1; } if (cnm) { chc = "%d".printf((dat.length - 1)).char_count(); } int[] cw = new int[rcols]; for (int i = 0; i < cw.length; i++) { cw[i] = 0; } if (rnm) { cw[0] = "%d".printf((dat.length/dsz)).char_count(); } if (h) { for (int i = firstcol; i < cw.length; i++) { string hh = ""; int d = (i-firstcol)+1; // shift to 1-based while (d > 0) { int x = ((d - 1) % 26); hh = "%c%s".printf((x+65),hh); d = ((d - x) - 1) / 26; } hh = "%d %s".printf((i-firstcol),hh); cw[i] = hh.char_count(); } } string o = ""; string ln = ""; // get counts 1st for (int i = 0; i < dat.length; i++) { int c = (i % dsz); if (rnm) { c = c + 1; } int cc = 0; if (dat[i] != null) { cc = dat[i].char_count() + chc + 3; if (cc > 0) { int nwlat = dat[i].index_of("\n"); if (nwlat != -1) { cc = (nwlat + 3 + chc + 3); } } } cw[c] = int.max(cw[c],cc); } // print header if (h) { for (int i = 0; i < cw.length; i++) { dlm = " | "; if (rnm && (i == 0)) { dlm = "%s| ".printf(tabs); string hh = "#"; o = "%s%s%-*s".printf(o,dlm,cw[i],hh); } else { if (i == 0) { dlm = "%s| ".printf(tabs); } string hh = ""; int d = (i-firstcol)+1; // shift to 1-based while (d > 0) { int x = ((d - 1) % 26); hh = "%c%s".printf((x+65),hh); d = ((d - x) - 1) / 26; } hh = "%d %s".printf((i-firstcol),hh); o = "%s%s%-*s".printf(o,dlm,cw[i],hh); } if (i == (cw.length - 1)) { o = "%s |\n".printf(o); } } // print line for (int i = 0; i < cw.length; i++) { dlm = "-+-"; if (i == 0) { dlm = "%s|-".printf(tabs); } ln = "%s%s%-*s".printf(ln,dlm,cw[i]," ").replace(" ","-"); if (i == (cw.length - 1)) { ln = "%s-|\n".printf(ln); } } o = "%s%s".printf(o,ln); } // print rows for (int r = 0; r < rowcount; r++) { for (int c = 0; c < cw.length; c++) { string datpart = ""; if ((c == 0) && rnm) { dlm = "%s| ".printf(tabs); o = "%s%s%0*d".printf(o,dlm,cw[0],r); } else { dlm = " | "; if (c == 0) { dlm = "%s| ".printf(tabs); } int j = (r * dsz) + (c - firstcol); int cc = dat[j].char_count(); if (dat[j] != null) { if (cc > 0) { datpart = dat[j]; int nwlat = dat[j].index_of("\n"); if (nwlat != -1) { //trunc = true; datpart = (dat[j].substring(0,nwlat) + "..."); cc = (nwlat + 3); } } else { cc = int.max(cc,1); } } string clen = ""; if (cnm) { clen = "(%0*d) ".printf(chc,j); } int padlen = (cw[c] - cc) - clen.char_count(); padlen = int.max(padlen,0); datpart = "%s%s%.*s".printf(clen,datpart,padlen,spc); if (domask) { bool ismakked = false; if (maskcols) { ismasked = ((m+firstcol) == c); } else { ismasked = (m == r); } if (ismasked) { datpart = "\x1b[48;2;%u;%u;%um%s\x1b[0m".printf(ir,ig,ib,datpart); //datpart = "\x1b[48;2;76;25;25m%s\x1b[0m".printf(datpart); } } o = "%s%s%s".printf(o,dlm,datpart); if (c == (cw.length - 1)) { o = "%s |\n".printf(o); } } } } cw = null; return o; } void main() { string[] s = {"0","100","2000","30000","A","B","C","DEE","X","Y","ZED","DONE"}; uint8[] hc = {}; hc += ((uint8) ((0.4 * 255.0) + 0.5)); hc += ((uint8) ((0.1 * 255.0) + 0.5)); hc += ((uint8) ((0.2 * 255.0) + 0.5)); print("all features\n"); print("%s",print1darray(1,s,4,true,true,true,1,hc)); print("\nno cell indices\n"); print("%s",print1darray(1,s,4,true,true,false,1,hc)); print("\nno row header\n"); print("%s",print1darray(1,s,4,true,false,true,1,hc)); print("\nno column header\n"); print("%s",print1darray(1,s,4,false,true,true,1,hc)); print("\nno row and column header\n"); print("%s",print1darray(1,s,4,false,false,true,1,hc)); print("\nno row header and cell indices\n"); print("%s",print1darray(1,s,4,true,false,false,1,hc)); print("\nno column header and cell indices\n"); print("%s",print1darray(1,s,4,false,true,false,1,hc)); print("\nno row and column header, no cell indices\n"); print("%s",print1darray(1,s,4,false,false,false,1,hc)); print("\nall features disabled\n"); print("%s",print1darray(1,s,4,false,false,false,-1,hc)); }
#+RESULTS:
all features | # | 0 A | 1 B | 2 C | 3 D | |---+--------+----------+-----------+------------| | 0 | (00) 0 | (01) 100 | (02) 2000 | (03) 30000 | | 1 | (04) A | (05) B | (06) C | (07) DEE | | 2 | (08) X | (09) Y | (10) ZED | (11) DONE | no cell indices | # | 0 A | 1 B | 2 C | 3 D | |---+-----+-----+------+-------| | 0 | 0 | 100 | 2000 | 30000 | | 1 | A | B | C | DEE | | 2 | X | Y | ZED | DONE | no row header | 0 A | 1 B | 2 C | 3 D | |--------+----------+-----------+------------| | (00) 0 | (01) 100 | (02) 2000 | (03) 30000 | | (04) A | (05) B | (06) C | (07) DEE | | (08) X | (09) Y | (10) ZED | (11) DONE | no column header | 0 | (00) 0 | (01) 100 | (02) 2000 | (03) 30000 | | 1 | (04) A | (05) B | (06) C | (07) DEE | | 2 | (08) X | (09) Y | (10) ZED | (11) DONE | no row and column header | (00) 0 | (01) 100 | (02) 2000 | (03) 30000 | | (04) A | (05) B | (06) C | (07) DEE | | (08) X | (09) Y | (10) ZED | (11) DONE | no row header and cell indices | 0 A | 1 B | 2 C | 3 D | |-----+-----+------+-------| | 0 | 100 | 2000 | 30000 | | A | B | C | DEE | | X | Y | ZED | DONE | no column header and cell indices | 0 | 0 | 100 | 2000 | 30000 | | 1 | A | B | C | DEE | | 2 | X | Y | ZED | DONE | no row and column header, no cell indices | 0 | 100 | 2000 | 30000 | | A | B | C | DEE | | X | Y | ZED | DONE | all features disabled | 0 | 100 | 2000 | 30000 | | A | B | C | DEE | | X | Y | ZED | DONE |
PRINT1DARRAY_TODO (1/2)
  • [X] remove rgb object dependency, supply a uint8[] of rgba instead
  • [ ] fix potential busted-printf issues
PRINT2DARRAY

// print a 2d array // by c.p.brown 2024 string[,] foldarray (int w, string[] s) { int h = s.length / w; string[,] o = new string[h,w]; for (int i = 0; i < s.length; i++) { int r = i / w; int c = i % w; o[r,c] = s[i]; } return o; } string print2dstringarray (string[,] s) { int w = s.length[1] + 1; int h = s.length[0] + 1; int wcc = "%d".printf(s.length[1]).char_count(); int hcc = "%d".printf(s.length[0]).char_count(); string hline = "---------------------------------------------------------------------------------"; int[] cw = new int [w]; string o = ""; for (int r = 0; r < h; r ++) { if (r == 0) { for (int c = 0; c < w; c ++) { if (c > 0) { cw[c] = wcc; } else { cw[c] = hcc; } } } else { for (int c = 0; c < w; c ++) { if (c == 0) { cw[c] = hcc; } else { //print("row %d col %d s[%d,%d] %s char_count is %d\n",r,c,(r-1),(c-1),s[(r-1),(c-1)],s[(r-1),(c-1)].char_count()); cw[c] = int.max(s[(r-1),(c-1)].char_count(),cw[c]); } } } } for (int r = 0; r < h; r ++) { string ro = ""; if (r == 0) { for (int c = 0; c < w; c++) { if (c == 0) { ro = "%s %.*s |".printf(ro,hcc," "); } else { if (c == (w-1)) { ro = "%s %.*d\n".printf(ro,cw[c],c); } else { ro = "%s %.*d ".printf(ro,cw[c],c); } } } ro = "%s-%.*s-+".printf(ro,hcc,hline); for (int c = 1; c < w; c++) { if (c == (w-1)) { ro = "%s-%.*s-\n".printf(ro,cw[c],hline); } else { ro = "%s-%.*s-".printf(ro,cw[c],hline); } } } else { for (int c = 0; c < w; c ++) { if (c == 0) { ro = "%s %.*d |".printf(ro,hcc,r); } else { int cc = s[(r-1),(c-1)].char_count(); if (c == (w-1)) { ro = "%s %s\n".printf(ro,s[(r-1),(c-1)]); } else { ro = "%s %-*s ".printf(ro,cw[c],s[(r-1),(c-1)]); } } } } o = o + ro; } return o; } void main() { string[] d = {"0","100","2000","30000","A","B","C","DEE","X","Y","ZED","DONE"}; string[,] s = foldarray(4,d); print(print2dstringarray(s)); }
#+RESULTS:
Compilation succeeded - 1 warning(s) | 1 002 0003 00004 | ---+--------------------- 1 | 0 100 2000 30000 2 | A B C DEE 3 | X Y ZED DONE
PRINTALLMY8BITS
string printallmy8bits (uint8 n) { int b = 7; string o = ""; string[] s = {"0","1"}; for (int i = b; i >= 0; i--) { if ((((i+1) % 8) == 0) && (i < b)) { o = o + " "; } o = o + "%s".printf(s[((n >> i) & 1)]); } return o; }
PRINTALLMY16BITS
string printallmy16bits (uint16 n) { int b = 15; string o = ""; string[] s = {"0","1"}; for (int i = b; i >= 0; i--) { if ((((i+1) % 8) == 0) && (i < b)) { o = o + " "; } o = o + "%s".printf(s[((n >> i) & 1)]); } return o; }
PRINTALLMY32BITS
string printallmyu32bits (uint n) { int b = 31; string o = ""; string[] s = {"0","1"}; for (int i = b; i >= 0; i--) { if ((((i+1) % 8) == 0) && (i < b)) { o = o + " "; } o = o + "%s".printf(s[((n >> i) & 1)]); } return o; }
PRINTINTARRAY
string printintarray (int[] s, int f, int w) { string[] ii = {"", "\"", "{", "[", "[", "| ", "", ""}; string[] dd = {";", ",", ",", " ", ",", " | ", " ", "\n"}; string[] oo = {"", "\"", "}", "]", "]", " |", "", ""}; string o = ii[f]; for (int i = 0; i < (s.length - 1); i++) { o = (o + "%0*d".printf(w,s[i]) + dd[f]); } o = (o + "%0*d".printf(w,s[s.length - 1]) + oo[f]); return o; }
PRINTF

Misc print and printf tests go here...

void main (string[] args) { string s = "******************"; string t = "text"; int mxd = 12; print("%.*s%s\n",(mxd - t.char_count()),s,t); mxd = 0; print("dotstar 0 +string: %.*s%s\n",int.max(0,(mxd - t.char_count())),s,t); print("star 0 +string: %*s%s\n",int.max(0,(mxd - t.char_count())),s,t); print("%s\n","star 0 nostring : \"%*s\"".printf(0,"").replace(" ","\t")); mxd = 12; print("%*s\n",12,t); print("%*s\n",0,t); print("\"%-*s\"\n",12,t); print("%0*d\n",mxd,1234); // width from elsewhere print("%012d\n",1234); // hardcoded width string r = ("%*s%s").printf(4," ","indent").replace(" ","\t"); print("%s\n",r); print("s contains * : %s\n",((s.index_of("*") != -1)?"true":"false")); GLib.Rand q = new GLib.Rand(); int rch = q.int_range(65,90); print("random char index is %d",rch); print(" (%s)\n",((unichar) rch).to_string()); int[] mch = {65,66,67,68,69,70}; string smch = (string) mch; char* ech; bool siv = (smch.validate(-1,out ech)); print("int array as string is \"%s\"\n",smch); if (siv) { print("string is valid\n"); } StringBuilder sbch = new StringBuilder(""); for (int i = 0; i < mch.length; i++) { sbch.append_unichar(mch[i]); } print("int array as stringbuilder is \"%s\"\n", sbch.str); string lon = "-33.689990"; string lat = "150.546212"; string locurl = "https://www.google.com/search?q=%s+%s".printf(lon,lat); print("locurl = %s\n",locurl); print("|"); int dsz = 12; int w = "%d".printf(dsz).char_count(); for (int i = 0; i < dsz; i++) { print(" col_%0*d |",w,i); } print("\n"); string tch = "0123456789"; tch = "%-*s%s".printf(10," ",tch); print("\"%s\"\n",tch); tch = "0123456789"; tch = "%-*s%s".printf(5," ",tch); print("\"%s\"\n",tch); tch = "0123456789"; tch = "%-*s%s".printf(0," ",txt); print("\"%s\"\n",tch); }
#+RESULTS:
********text dotstar 0 +string: text star 0 +string: ******************text star 0 nostring : "" text text "text " 000000001234 000000001234 indent s contains * : true random char index is 84 (T) int array as string is "A" string is valid int array as stringbuilder is "ABCDEF" locurl = https://www.google.com/search?q=-33.689990+150.546212 | col_00 | col_01 | col_02 | col_03 | col_04 | col_05 | col_06 | col_07 | col_08 | col_09 | col_10 | col_11 | " 0123456789" " 0123456789" " 0123456789"
PRINTCPUINF
void printcpuinf () { string maxhz = "unknown"; string frqfile = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq"; GLib.File ff = GLib.File.new_for_path(frqfile); if (ff.query_exists() == true) { GLib.FileStream s = GLib.FileStream.open(frqfile,"r"); string l = s.read_line(); if (l != null) { StringBuilder sb = new StringBuilder(""); sb.append(l); maxhz = sb.str; } } string cpufile = "/proc/cpuinfo"; string[] pinf = {}; ff = GLib.File.new_for_path(cpufile); if (ff.query_exists() == true) { GLib.FileStream s = GLib.FileStream.open(cpufile,"r"); string l = s.read_line(); while (l != null) { StringBuilder sb = new StringBuilder(""); sb.append(l); // bail after 1st cpu uint f = sb.replace("power ","",1); if (f > 0) { break; } pinf += sb.str; l = s.read_line(); } } for (int i = 0; i < pinf.length; i++) { StringBuilder sb = new StringBuilder(""); sb.append(pinf[i]); uint f = sb.replace("model name", "", 1); if (f > 0) { print("%s\n",pinf[i]); } else { f = sb.replace("cpu MHz", "", 1); if (f > 0) { print("cpu hz\t\t: %s/%s\n",pinf[i].substring((pinf[i].index_of(": ") + 2)).replace(".",""),maxhz); } else { f = sb.replace("cache size", "", 1); if (f > 0) { print("%s\n",pinf[i]); } else { f = sb.replace("cpu cores", "", 1); if (f > 0) { print("%s\n\n",pinf[i]); break; } } } } } }
PRINTSTRINGARRAY
string printstringarray (string[] s, int f) { // 0 1 2 3 4 5 6 7 8 9 string[] ii = {"", "\"", "{", "{\"", "[", "[", "| ", "", "", ""}; string[] dd = {";", ",", ",", "\",\"", " ", ",", " | ", " ", "\n", ",\n"}; string[] oo = {"", "\"", "}", "\"}", "]", "]", " |", "", "", ""}; string o = ii[f]; for (int i = 0; i < (s.length - 1); i++) { o = (o + "%s".printf(s[i]) + dd[f]); } o = (o + "%s".printf(s[s.length - 1]) + oo[f]); return o; }
PRINTUSECS
string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; }
PRINTGMEM
string printgmem (int64 m) { // m is memory in bytes if (m < 1000) { return "%lld bytes".printf(m); } if (m < 1000000) { return "%.2f KB".printf((((double) m) / 1000.0) ); } if (m < 1000000000) { return "%.2f MB".printf((((double) m) / 1000000.0) ); } if (m < 1000000000000) { return "%.2f GB".printf((((double) m) / 1000000000.0)); } if (m < 1000000000000000) { return "%.2f TB".printf((((double) m) / 1000000000000.0)); } return "%.2f PB".printf((((double) m) / 1000000000000000.0) ); }
RANDOM
RANDOCHAR

xorshift vs GLib.Rand()

Based on Xorshift RNGs (2003) by George Marsaglia.

xorshift is many times faster than GLib.Rand(), however there's some noticeable repetition.
Results are also highly sensitive to the number provided as a seed (to offset), where a set of offsets that works with 1+i may fail to produce pseudo-random results with 1000000+i.


// xorshift vs GLib.Rand() test // xorshift technique from Xorshift RNGs by George Marsaglia // https://www.jstatsoft.org/article/view/v008i14 // // by c.p.brown 2025 string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } string printallmyuint20bits (uint n) { int b = 31; string o = ""; string[] s = {"▁","█"}; for (int i = b; i >= 0; i--) { if (((i+1) % 4) == 0) { o = o + " "; } //o = o + "%u".printf((n >> i) & 1); o = o + "%s".printf(s[((n >> i) & 1)]); } return o; } int[] ph; int[] phx; void xrintr (uint i, int s, int e, bool m, int x, bool y, out int g, out uint u) { int phxl = phx.length / 3; int64 mo = GLib.get_monotonic_time(); uint th = ((uint) mo) + i; int pl = 0; if (x > -1) { if (!y) { print("%u uint(%019lld)+%d =%010u ",i,mo,i,th); } pl = (x * 3); th^=(th<<ph[pl]); th^=(th>>ph[pl+1]); th^=(th<<ph[pl+2]); } else { pl = (int) (i % phxl) * 3; th^=(th<<phx[pl]); th^=(th>>phx[pl+1]); th^=(th<<phx[pl+2]); } if (m) { g = ((int) (th % ((uint) ((e+1)-s)))) + s; } else { g = ((int) ((((double) th) / uint32.MAX) * ((double) ((e+1)-s)))) + s; } u = th; } string[] randochar (int n, int b, int e, int[] c, ref int[] rc, bool p, int x, int y) { string[] s = {}; string k = "========================================="; int cl = c.length; int lc = c.length - 1; if (p) { print("xorshift with prints...\n"); print("\n[ln]\trand binary\n"); } for (int i = 0; i < n; i += 1) { int cc = 0; uint t = 0; xrintr(i,b,e,false,x,false,out cc, out t); if (p) { print("[%02d]\t%10llu ",i,t); print("%s | %d\n",printallmyuint20bits((uint) t),cc); } StringBuilder rsb = new StringBuilder(""); for (uint h = 0; h < cc; h++) { int hc = 0; uint ht = 0; xrintr(h,0,lc,false,y,true,out hc,out ht); if (y > -1) { print("%d",hc); } if (p) { if (h < (cc - 1)) { print("[%02d]\t|-- %010llu %s | %d | %.*s%*s|",i,ht,printallmyuint20bits((uint) ht),hc,hc,k,(10-hc)," "); if (y == -1) { int phxl = phx.length / 3; int pl = (int) ((h % ((uint) phxl)) * 3); print(" %02u/%02d {%d,%d,%d}\n",(h % ((uint) phxl)),(phxl - 1),phx[pl],phx[pl+1],phx[pl+2]); } else { print("\n"); } } else { print("[%02d]\t+-- %010llu %s | %d | %.*s%*s|",i,ht,printallmyuint20bits((uint) ht),hc,hc,k,(10-hc)," "); if (y == -1) { int phxl = phx.length / 3; int pl = (int) (h % phxl) * 3; print(" %02u/%02d {%d,%d,%d}\n\n",(h % phxl),(phxl - 1),phx[pl],phx[pl+1],phx[pl+2]); } else { print("\n\n"); } } } rsb.append_unichar((unichar) c[hc]); rc[hc] += 1; } if (y > -1) { print("\n"); } s += rsb.str; } return s; } void printrandos (int n, string[] s, string[] g, int[] rc, int[] gc, int cl, int64 rtt, int64 gtt) { int lhp = 0; for (int i = 0; i < n; i++) { lhp = int.max(lhp,s[i].char_count()); } print("\n## | xorshift%*s| ## | GLib.Rand()\n",(lhp - 7)," "); for (int i = 0; i < n; i++) { print("%02d | %s%*s",i,s[i],((lhp - s[i].char_count()) + 1)," "); print("| %02d | %s\n",i,g[i]); } string rusec = printusecs(rtt); int rsc = rusec.char_count(); print("mt | %s%*s| mt | %s\n",rusec,((lhp - rsc) + 1)," ",printusecs(gtt)); lhp = 0; for (int i = 0; i < cl; i++) { lhp = int.max(lhp,rc[i]); } int rhp = 0; for (int i = 0; i < cl; i++) { rhp = int.max(rhp,gc[i]); } print("\nch | ### | xorshift%*s| ch | ### | GLib.Rand()\n",(20 - 8)," "); for (int i = 0; i < cl; i++) { print("%02d | %03d |",i,rc[i]); int lv = (int) ((((double) rc[i]) / ((double) lhp)) * 20.0); for (int x = 0; x < lv; x++) { print("%s","█"); } print("%*s| %02d | %03d |",((20 - lv) + 1)," ",i,gc[i]); int rv = (int) ((((double) gc[i]) / ((double) rhp)) * 20.0); for (int x = 0; x < rv; x++) { print("%s","█"); } print("\n"); } } void printrandotestblock (int n, string[] s, int[] rc, int cl, int64 rtt) { int lhp = 0; int cw = 25; for (int i = 0; i < n; i++) { lhp = int.max(lhp,s[i].char_count()); } print("\n## | xorshift chars%*s|\n",(lhp - 13)," "); for (int i = 0; i < n; i++) { print("%02d | %s%*s",i,s[i],((lhp - s[i].char_count()) + 1)," "); print("|\n"); } string rusec = printusecs(rtt); int rsc = rusec.char_count(); print("mt | %s%*s|\n",rusec,((lhp - rsc) + 1)," "); lhp = 0; for (int i = 0; i < cl; i++) { lhp = int.max(lhp,rc[i]); } print("\nch | ### | xorshift char count%*s|\n",(cw - 31)," "); for (int i = 0; i < cl; i++) { print("%02d | %03d |",i,rc[i]); int lv = (int) ((((double) rc[i]) / ((double) lhp)) * ((double) cw)); for (int x = 0; x < lv; x++) { print("%s","█"); } print("%*s|\n",((cw - lv) + 1)," "); } } string[] grandochar (int n, int b, int e, int[] c, ref int[] gc) { string[] g = {}; int lc = c.length; GLib.Rand rando = new GLib.Rand(); for (int i = 0; i < n; i += 1) { uint64 ot = GLib.get_monotonic_time(); rando.set_seed((uint) ot); int cc = rando.int_range(b,e); StringBuilder rsb = new StringBuilder(""); for (int h = 0; h < cc; h++) { rando.set_seed(rando.next_int()); int hc = rando.int_range(0,lc); rsb.append_unichar((unichar) c[hc]); gc[hc] += 1; } g += rsb.str; } return g; } void main() { GLib.Intl.setlocale(ALL,""); // Uses xorshift offsets by George Marsaglia ph = { 1,3,10, 1,5,16, 1,5,19, 1,9,29, 1,11,6, 1,11,16, 1,19,3, 1,21,20, 1,27,27, 2,5,15, 2,5,21, 2,7,7, 2,7,9, 2,7,25, 2,9,15, 2,15,17, 2,15,25, 2,21,9, 3,1,14, 3,3,26, 3,3,28, 3,3,29, 3,5,20, 3,5,22, 3,5,25, 3,7,29, 3,13,7, 3,23,25, 3,25,24, 3,27,11, 4,3,17, 4,3,27, 4,5,15, 5,3,21, 5,7,22, 5,9,7, 5,9,28, 5,9,31, 5,13,6, 5,15,17, 5,17,13, 5,21,12, 5,27,8, 5,27,21, 5,27,25, 5,27,28, 6,1,11, 6,3,17, 6,17,9, 6,21,7, 6,21,13, 7,1,9, 7,1,18, 7,1,25, 7,13,25, 7,17,21, 7,25,12, 7,25,20, 8,7,23, 8,9,23, 9,5,1, 9,5,25, 9,11,19, 9,21,16, 10,9,21, 10,9,25, 11,7,12, 11,7,16, 11,17,13, 11,21,13, 12,9,23, 13,3,17, 13,3,27, 13,5,19, 13,17,15, 14,1,15, 14,13,15, 15,1,29, 17,15,20, 17,15,23, 17,15,26 }; phx = { 13,3,17, // 71 ▁▃▄▂█▆▃▁▇▅▂▄▆█▁▃▅▇█▆▄▂▇▅▃▁▆█▂▄ 3,7,29, // 25 ▅█▇▂▁▄▃▃▄▁▂▇█▅▆▃▄▁▂▇█▅▆▄▃▂▁█▇▆ 5,27,25, // 44 ▃▅▇▁▃▅▇▁▃█▆▄▂█▆▄▂█▆▄▂█▆▄▂▇▅▃▁▇ 3,5,25, // 24 █▁▁▂▂▃▃▄▄▃▃▄▄▁▁▂▂▇▇██▅▅▆▆▄▄▃▃▂ 4,3,27, // 31 ▂█▄▇▃▃▇▄█▂▆▁▅█▄▇▃▅▁▆▂▂▆▁▅▃▇▄█▄ 9,5,25, // 61 ▆▃▄▁▂▇█▅▆▃▄▁▂█▇▆▅▄▃▂▁█▇▆▅▄▃▂▁▅ 1,9,29, // 03 ▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆ 15,1,29 // 77 ▄▂▁▁▂▄▃▇█▆▅▅▆█▇▃▄▂▁▁▂▄▃▇█▆▅▅▆█ }; int n = 30; int b = 1; int e = 20; // test offsets, 10 lines per offset, 30 chars print("\nTest of offset combos found here:\n%s\nEach seeded with ((uint) GLib.get_monotonic_time()), then offset with a per-character iteratior.\n\n","https://www.jstatsoft.org/article/view/v008i14"); int[] j = {}; for (int i = 9601; i < 9609; i++) { j += i; } n = 10; b = 30; e = 30; int phr = ph.length / 3; for (int i = 0; i < phr; i++) { print("\n-------------------------------------\n"); print("\noffset %02d {%d,%d,%d}\n\n",i,ph[(i*3)],ph[(i*3)+1],ph[(i*3)+2]); int[] rc = new int[j.length]; int64 rtts = GLib.get_monotonic_time(); string[] d = randochar(n,b,e,j,ref rc,false,i,i); int64 rtte = GLib.get_monotonic_time(); printrandotestblock(n,d,rc,j.length,(rtte-rtts)); } // 1st round, 30 lines n = 30; b = 1; e = 20; int oo = 31; int[] c = {}; for (int i = 48; i < 58; i++) { c += i; } print("\n-------------------------------------\n"); print("\n30 lines, 1..20 chars, of %d chars\n",c.length); //print("offset %02d {%d,%d,%d}\n\n",oo,ph[(oo*3)],ph[(oo*3)+1],ph[(oo*3)+2]); print("phased offset\n\n"); int[] gc = new int[c.length]; int[] rc = new int[c.length]; int64 rtts = GLib.get_monotonic_time(); string[] s = randochar(n,b,e,c,ref rc,false,-1,-1); int64 rtte = GLib.get_monotonic_time(); int64 gtts = GLib.get_monotonic_time(); string[] g = grandochar(n,b,e,c,ref gc); int64 gtte = GLib.get_monotonic_time(); printrandos(n,s,g,rc,gc,c.length,(rtte-rtts),(gtte-gtts)); // 2nd round, 10 lines, more characters int[] a = {}; for (int i = 9601; i < 9609; i++) { a += i; } print("\n-------------------------------------\n"); print("\n30 lines, 1..20 chars, of %d chars\n",a.length); //print("offset %02d {%d,%d,%d}\n\n",oo,ph[(oo*3)],ph[(oo*3)+1],ph[(oo*3)+2]); print("phased offset\n\n"); rc = new int[a.length]; gc = new int[a.length]; rtts = GLib.get_monotonic_time(); s = randochar(10,b,e,a,ref rc,false,-1,-1); rtte = GLib.get_monotonic_time(); gtts = GLib.get_monotonic_time(); g = grandochar(10,b,e,a,ref gc); gtte = GLib.get_monotonic_time(); printrandos(10,s,g,rc,gc,a.length,(rtte-rtts),(gtte-gtts)); // 3rd round, 10 lines with prints n = 10; b = 3; e = 10; rc = new int[c.length]; gc = new int[c.length]; print("\n-------------------------------------\n"); print("\n10 lines, 3..10 chars, of %d chars\nphased offset\n\n",c.length); rtts = GLib.get_monotonic_time(); s = randochar(n,b,e,c,ref rc,true,-1,-1); rtte = GLib.get_monotonic_time(); gtts = GLib.get_monotonic_time(); g = grandochar(n,b,e,c,ref gc); gtte = GLib.get_monotonic_time(); printrandos(n,s,g,rc,gc,c.length,(rtte-rtts),(gtte-gtts)); }
#+RESULTS:
Compilation succeeded - 2 warning(s) Test of offset combos found here: https://www.jstatsoft.org/article/view/v008i14 Each seeded with ((uint) GLib.get_monotonic_time()), then offset with a per-character iteratior. ------------------------------------- offset 00 {1,3,10} 0 uint(0000002128285260964)+0 =2276449444 111111111111111111111111111111 1 uint(0000002128285260999)+1 =2276449480 111111111111111111111111111111 2 uint(0000002128285261036)+2 =2276449518 111111111111111111111111111111 3 uint(0000002128285261068)+3 =2276449551 111111111111111111111111111111 4 uint(0000002128285261099)+4 =2276449583 111111111111111111111111111111 5 uint(0000002128285261131)+5 =2276449616 111111111111111111111111111111 6 uint(0000002128285261163)+6 =2276449649 111111111111111111111111111111 7 uint(0000002128285261193)+7 =2276449680 111111111111111111111111111111 8 uint(0000002128285261228)+8 =2276449716 111111111111111111111111111111 9 uint(0000002128285261263)+9 =2276449752 111111111111111111111111111111 ## | xorshift chars | 00 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 01 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 02 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 03 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 04 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 05 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 06 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 07 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 08 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 09 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | mt | 335 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 300 |█████████████████████████ | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 000 | | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 01 {1,5,16} 0 uint(0000002128285261375)+0 =2276449855 333333333333333333333333333333 1 uint(0000002128285261413)+1 =2276449894 333333333333333333333333333333 2 uint(0000002128285261448)+2 =2276449930 333333333333333333333333333333 3 uint(0000002128285261485)+3 =2276449968 333333333333333333333333333333 4 uint(0000002128285261520)+4 =2276450004 333333333333333333333333333333 5 uint(0000002128285261559)+5 =2276450044 333333333333333333333333333333 6 uint(0000002128285261595)+6 =2276450081 333333333333333333333333333333 7 uint(0000002128285261630)+7 =2276450117 333333333333333333333333333333 8 uint(0000002128285261666)+8 =2276450154 333333333333333333333333333333 9 uint(0000002128285261701)+9 =2276450190 333333333333333333333333333333 ## | xorshift chars | 00 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 01 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 02 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 03 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 04 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 05 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 06 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 07 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 08 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 09 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | mt | 363 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 300 |█████████████████████████ | 04 | 000 | | 05 | 000 | | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 02 {1,5,19} 0 uint(0000002128285261814)+0 =2276450294 444444444444444444444444444444 1 uint(0000002128285261849)+1 =2276450330 444444444444444444444444444444 2 uint(0000002128285261884)+2 =2276450366 444444444444444444444444444444 3 uint(0000002128285261921)+3 =2276450404 444444444444444444444444444444 4 uint(0000002128285261956)+4 =2276450440 444444444444444444444444444444 5 uint(0000002128285261993)+5 =2276450478 444444444444444444444444444444 6 uint(0000002128285262030)+6 =2276450516 444444444444444444444444444444 7 uint(0000002128285262067)+7 =2276450554 444444444444444444444444444444 8 uint(0000002128285262102)+8 =2276450590 444444444444444444444444444444 9 uint(0000002128285262139)+9 =2276450628 444444444444444444444444444444 ## | xorshift chars | 00 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 01 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 02 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 03 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 04 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 05 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 06 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 07 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 08 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 09 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | mt | 360 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 300 |█████████████████████████ | 05 | 000 | | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 03 {1,9,29} 0 uint(0000002128285262248)+0 =2276450728 617530260275374602431756046317 1 uint(0000002128285262285)+1 =2276450766 746045317502460153124602713572 2 uint(0000002128285262320)+2 =2276450802 607531742067157420623571064205 3 uint(0000002128285262357)+3 =2276450840 574064207135640671374206235715 4 uint(0000002128285262394)+4 =2276450878 206135713642357306420713571510 5 uint(0000002128285262457)+5 =2276450942 267135720642071357106413513064 6 uint(0000002128285262496)+6 =2276450982 413512064257135620671371206435 7 uint(0000002128285262531)+7 =2276451018 374206435713042057157420643560 8 uint(0000002128285262566)+8 =2276451054 420671574206024602753146246531 9 uint(0000002128285262604)+9 =2276451093 146047531702460275317624653150 ## | xorshift chars | 00 | ▇▂█▆▄▁▃▇▁▃█▆▄█▅▇▁▃▅▄▂█▆▇▁▅▇▄▂█ | 01 | █▅▇▁▅▆▄▂█▆▁▃▅▇▁▂▆▄▂▃▅▇▁▃█▂▄▆█▃ | 02 | ▇▁█▆▄▂█▅▃▁▇█▂▆█▅▃▁▇▃▄▆█▂▁▇▅▃▁▆ | 03 | ▆█▅▁▇▅▃▁█▂▄▆▇▅▁▇█▂▄█▅▃▁▇▃▄▆█▂▆ | 04 | ▃▁▇▂▄▆█▂▄▇▅▃▄▆█▄▁▇▅▃▁█▂▄▆█▂▆▂▁ | 05 | ▃▇█▂▄▆█▃▁▇▅▃▁█▂▄▆█▂▁▇▅▂▄▆▂▄▁▇▅ | 06 | ▅▂▄▆▂▃▁▇▅▃▆█▂▄▆▇▃▁▇█▂▄█▂▃▁▇▅▄▆ | 07 | ▄█▅▃▁▇▅▄▆█▂▄▁▅▃▁▆█▂▆█▅▃▁▇▅▄▆▇▁ | 08 | ▅▃▁▇█▂▆█▅▃▁▇▁▃▅▇▁▃█▆▄▂▅▇▃▅▇▆▄▂ | 09 | ▂▅▇▁▅█▆▄▂█▁▃▅▇▁▃█▆▄▂█▇▃▅▇▆▄▂▆▁ | mt | 391 μs | ch | ### | xorshift char count | 00 | 041 |█████████████████████████ | 01 | 037 |██████████████████████ | 02 | 035 |█████████████████████ | 03 | 034 |████████████████████ | 04 | 036 |█████████████████████ | 05 | 037 |██████████████████████ | 06 | 039 |███████████████████████ | 07 | 041 |█████████████████████████ | ------------------------------------- offset 04 {1,11,6} 0 uint(0000002128285262882)+0 =2276451362 555555555555555555555555555555 1 uint(0000002128285262917)+1 =2276451398 555555555555555555555555555555 2 uint(0000002128285262954)+2 =2276451436 555555555555555555555555555555 3 uint(0000002128285262989)+3 =2276451472 555555555555555555555555555555 4 uint(0000002128285263028)+4 =2276451512 555555555555555555555555555555 5 uint(0000002128285263066)+5 =2276451551 555555555555555555555555555555 6 uint(0000002128285263103)+6 =2276451589 555555555555555555555555555555 7 uint(0000002128285263138)+7 =2276451625 555555555555555555555555555555 8 uint(0000002128285263176)+8 =2276451664 555555555555555555555555555555 9 uint(0000002128285263211)+9 =2276451700 555555555555555555555555555555 ## | xorshift chars | 00 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 01 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 02 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 03 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 04 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 05 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 06 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 07 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 08 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 09 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | mt | 365 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 300 |█████████████████████████ | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 05 {1,11,16} 0 uint(0000002128285263323)+0 =2276451803 555555555555555555555555555555 1 uint(0000002128285263358)+1 =2276451839 555555555555555555555555555555 2 uint(0000002128285263394)+2 =2276451876 555555555555555555555555555555 3 uint(0000002128285263431)+3 =2276451914 555555555555555555555555555555 4 uint(0000002128285263467)+4 =2276451951 555555555555555555555555555555 5 uint(0000002128285263502)+5 =2276451987 555555555555555555555555555555 6 uint(0000002128285263538)+6 =2276452024 555555555555555555555555555555 7 uint(0000002128285263573)+7 =2276452060 555555555555555555555555555555 8 uint(0000002128285263611)+8 =2276452099 555555555555555555555555555555 9 uint(0000002128285263646)+9 =2276452135 555555555555555555555555555555 ## | xorshift chars | 00 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 01 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 02 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 03 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 04 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 05 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 06 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 07 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 08 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 09 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | mt | 359 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 300 |█████████████████████████ | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 06 {1,19,3} 0 uint(0000002128285263755)+0 =2276452235 666666666666666666666666666666 1 uint(0000002128285263792)+1 =2276452273 666666666666666666666666666666 2 uint(0000002128285263828)+2 =2276452310 666666666666666666666666666666 3 uint(0000002128285263865)+3 =2276452348 666666666666666666666666666666 4 uint(0000002128285263901)+4 =2276452385 666666666666666666666666666666 5 uint(0000002128285263937)+5 =2276452422 666666666666666666666666666666 6 uint(0000002128285263974)+6 =2276452460 666666666666666666666666666666 7 uint(0000002128285264016)+7 =2276452503 666666666666666666666666666666 8 uint(0000002128285264050)+8 =2276452538 666666666666666666666666666666 9 uint(0000002128285264087)+9 =2276452576 666666666666666666666666666666 ## | xorshift chars | 00 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 01 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 02 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 03 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 04 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 05 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 06 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 07 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 08 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 09 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | mt | 368 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 000 | | 06 | 300 |█████████████████████████ | 07 | 000 | | ------------------------------------- offset 07 {1,21,20} 0 uint(0000002128285264172)+0 =2276452652 333333333333333333333333333333 1 uint(0000002128285264197)+1 =2276452678 333333333333333333333333333333 2 uint(0000002128285264221)+2 =2276452703 333333333333333333333333333333 3 uint(0000002128285264245)+3 =2276452728 333333333333333333333333333333 4 uint(0000002128285264282)+4 =2276452766 333333333333333333333333333333 5 uint(0000002128285264318)+5 =2276452803 333333333333333333333333333333 6 uint(0000002128285264355)+6 =2276452841 333333333333331111111111111111 7 uint(0000002128285264390)+7 =2276452877 111111111111111111111111111111 8 uint(0000002128285264425)+8 =2276452913 111111111111111111111111111111 9 uint(0000002128285264461)+9 =2276452950 111111111111111111111111111111 ## | xorshift chars | 00 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 01 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 02 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 03 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 04 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 05 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 06 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 07 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 08 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 09 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | mt | 326 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 106 |█████████████ | 02 | 000 | | 03 | 194 |█████████████████████████ | 04 | 000 | | 05 | 000 | | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 08 {1,27,27} 0 uint(0000002128285264586)+0 =2276453066 744576211001367544576231013267 1 uint(0000002128285264624)+1 =2276453105 457231000326754557621001326754 2 uint(0000002128285264659)+2 =2276453141 623110132675445762100132675447 3 uint(0000002128285264697)+3 =2276453180 310013275445762310132665445763 4 uint(0000002128285264734)+4 =2276453218 003267545776310013677544762310 5 uint(0000002128285264772)+5 =2276453257 326544576231001267754576231001 6 uint(0000002128285264808)+6 =2276453294 754455623101326754457300132675 7 uint(0000002128285264849)+7 =2276453336 762230013265544562310013267445 8 uint(0000002128285264886)+8 =2276453374 231001266754576231001327544456 9 uint(0000002128285264923)+9 =2276453412 101332674457663100126775457623 ## | xorshift chars | 00 | █▅▅▆█▇▃▂▂▁▁▂▄▇█▆▅▅▆█▇▃▄▂▁▂▄▃▇█ | 01 | ▅▆█▃▄▂▁▁▁▄▃▇█▆▅▆▆█▇▃▂▁▁▂▄▃▇█▆▅ | 02 | ▇▃▄▂▂▁▂▄▃▇█▆▅▅▆█▇▃▂▁▁▂▄▃▇█▆▅▅█ | 03 | ▄▂▁▁▂▄▃█▆▅▅▆█▇▃▄▂▁▂▄▃▇▇▆▅▅▆█▇▄ | 04 | ▁▁▄▃▇█▆▅▆██▇▄▂▁▁▂▄▇██▆▅▅█▇▃▄▂▁ | 05 | ▄▃▇▆▅▅▆█▇▃▄▂▁▁▂▃▇██▆▅▆█▇▃▄▂▁▁▂ | 06 | █▆▅▅▆▆▇▃▄▂▁▂▄▃▇█▆▅▅▆█▄▁▁▂▄▃▇█▆ | 07 | █▇▃▃▄▁▁▂▄▃▇▆▆▅▅▆▇▃▄▂▁▁▂▄▃▇█▅▅▆ | 08 | ▃▄▂▁▁▂▃▇▇█▆▅▆█▇▃▄▂▁▁▂▄▃█▆▅▅▅▆▇ | 09 | ▂▁▂▄▄▃▇█▅▅▆█▇▇▄▂▁▁▂▃▇██▆▅▆█▇▃▄ | mt | 374 μs | ch | ### | xorshift char count | 00 | 037 |███████████████████████ | 01 | 038 |███████████████████████ | 02 | 035 |█████████████████████ | 03 | 036 |██████████████████████ | 04 | 036 |██████████████████████ | 05 | 039 |████████████████████████ | 06 | 039 |████████████████████████ | 07 | 040 |█████████████████████████ | ------------------------------------- offset 09 {2,5,15} 0 uint(0000002128285265224)+0 =2276453704 777777777777777777777777777777 1 uint(0000002128285265260)+1 =2276453741 777777777777777777777777777777 2 uint(0000002128285265296)+2 =2276453778 777777777777777777777777777777 3 uint(0000002128285265331)+3 =2276453814 777777777777777777777777777777 4 uint(0000002128285265366)+4 =2276453850 777777777777777777777777777777 5 uint(0000002128285265401)+5 =2276453886 777777777777777777777777777777 6 uint(0000002128285265437)+6 =2276453923 777777777777777777777777777777 7 uint(0000002128285265472)+7 =2276453959 777777777777777777777777777777 8 uint(0000002128285265508)+8 =2276453996 777777777777777777777777777777 9 uint(0000002128285265544)+9 =2276454033 777777777777777777777777777777 ## | xorshift chars | 00 | ██████████████████████████████ | 01 | ██████████████████████████████ | 02 | ██████████████████████████████ | 03 | ██████████████████████████████ | 04 | ██████████████████████████████ | 05 | ██████████████████████████████ | 06 | ██████████████████████████████ | 07 | ██████████████████████████████ | 08 | ██████████████████████████████ | 09 | ██████████████████████████████ | mt | 355 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 000 | | 06 | 000 | | 07 | 300 |█████████████████████████ | ------------------------------------- offset 10 {2,5,21} 0 uint(0000002128285265650)+0 =2276454130 333333555555555555555555555555 1 uint(0000002128285265687)+1 =2276454168 555555555555555555554444444444 2 uint(0000002128285265722)+2 =2276454204 554444444444444444444444444444 3 uint(0000002128285265758)+3 =2276454241 444444444444444477777777777777 4 uint(0000002128285265793)+4 =2276454277 777777777777777777777777777777 5 uint(0000002128285265829)+5 =2276454314 777777777777666666666666666666 6 uint(0000002128285265865)+6 =2276454351 666666666666666666666666655555 7 uint(0000002128285265901)+7 =2276454388 666666666555555555555555555555 8 uint(0000002128285265937)+8 =2276454425 555555555555555555555544444444 9 uint(0000002128285265974)+9 =2276454463 555544444444444444444444444444 ## | xorshift chars | 00 | ▄▄▄▄▄▄▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 01 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▅▅▅▅▅▅▅▅▅▅ | 02 | ▆▆▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 03 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅██████████████ | 04 | ██████████████████████████████ | 05 | ████████████▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 06 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▆▆▆▆▆ | 07 | ▇▇▇▇▇▇▇▇▇▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 08 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▅▅▅▅▅▅▅▅ | 09 | ▆▆▆▆▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | mt | 365 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 006 |█ | 04 | 088 |██████████████████████ | 05 | 098 |█████████████████████████ | 06 | 052 |█████████████ | 07 | 056 |██████████████ | ------------------------------------- offset 11 {2,7,7} 0 uint(0000002128285266143)+0 =2276454623 444444444444444444444444444444 1 uint(0000002128285266200)+1 =2276454681 444444444444444444444444444444 2 uint(0000002128285266234)+2 =2276454716 444444444444444444444444444444 3 uint(0000002128285266271)+3 =2276454754 444444444444444444444444444444 4 uint(0000002128285266306)+4 =2276454790 444444444444444444444444444444 5 uint(0000002128285266343)+5 =2276454828 444444444444444444444444444444 6 uint(0000002128285266380)+6 =2276454866 444444444444444444444444444444 7 uint(0000002128285266417)+7 =2276454904 444444444444444444444444444444 8 uint(0000002128285266454)+8 =2276454942 444444444444444444444444444444 9 uint(0000002128285266491)+9 =2276454980 444444444444444444444444444444 ## | xorshift chars | 00 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 01 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 02 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 03 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 04 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 05 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 06 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 07 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 08 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 09 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | mt | 386 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 300 |█████████████████████████ | 05 | 000 | | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 12 {2,7,9} 0 uint(0000002128285266603)+0 =2276455083 666666666666666666666666666666 1 uint(0000002128285266641)+1 =2276455122 666666666666666666666666666666 2 uint(0000002128285266682)+2 =2276455164 666666666666666666666666666666 3 uint(0000002128285266708)+3 =2276455191 666666666666666666666666666666 4 uint(0000002128285266735)+4 =2276455219 666666666666666666666666666666 5 uint(0000002128285266761)+5 =2276455246 666666666666666666666666666666 6 uint(0000002128285266786)+6 =2276455272 666666666666666666666666666666 7 uint(0000002128285266813)+7 =2276455300 666666666666666666666666666666 8 uint(0000002128285266839)+8 =2276455327 666666666666666666666666666666 9 uint(0000002128285266866)+9 =2276455355 666666666666666666666666666666 ## | xorshift chars | 00 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 01 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 02 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 03 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 04 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 05 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 06 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 07 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 08 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 09 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | mt | 288 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 000 | | 06 | 300 |█████████████████████████ | 07 | 000 | | ------------------------------------- offset 13 {2,7,25} 0 uint(0000002128285266944)+0 =2276455424 011122335544477662223000117766 1 uint(0000002128285266971)+1 =2276455452 662223300117766555444455567771 2 uint(0000002128285266997)+2 =2276455479 444455566777111033322667744455 3 uint(0000002128285267028)+3 =2276455511 003332267774455532221100001112 4 uint(0000002128285267055)+4 =2276455539 533221100000122233554447666223 5 uint(0000002128285267082)+5 =2276455567 233354447766223330011776665444 6 uint(0000002128285267107)+6 =2276455593 230001177665544444566677110003 7 uint(0000002128285267135)+7 =2276455622 444556677711003322267774455332 8 uint(0000002128285267160)+8 =2276455648 322266774445333221100000122233 9 uint(0000002128285267188)+9 =2276455677 221110000011122333554447776622 ## | xorshift chars | 00 | ▁▂▂▂▃▃▄▄▆▆▅▅▅██▇▇▃▃▃▄▁▁▁▂▂██▇▇ | 01 | ▇▇▃▃▃▄▄▁▁▂▂██▇▇▆▆▆▅▅▅▅▆▆▆▇███▂ | 02 | ▅▅▅▅▆▆▆▇▇███▂▂▂▁▄▄▄▃▃▇▇██▅▅▅▆▆ | 03 | ▁▁▄▄▄▃▃▇███▅▅▆▆▆▄▃▃▃▂▂▁▁▁▁▂▂▂▃ | 04 | ▆▄▄▃▃▂▂▁▁▁▁▁▂▃▃▃▄▄▆▆▅▅▅█▇▇▇▃▃▄ | 05 | ▃▄▄▄▆▅▅▅██▇▇▃▃▄▄▄▁▁▂▂██▇▇▇▆▅▅▅ | 06 | ▃▄▁▁▁▂▂██▇▇▆▆▅▅▅▅▅▆▇▇▇██▂▂▁▁▁▄ | 07 | ▅▅▅▆▆▇▇███▂▂▁▁▄▄▃▃▃▇███▅▅▆▆▄▄▃ | 08 | ▄▃▃▃▇▇██▅▅▅▆▄▄▄▃▃▂▂▁▁▁▁▁▂▃▃▃▄▄ | 09 | ▃▃▂▂▂▁▁▁▁▁▂▂▂▃▃▄▄▄▆▆▅▅▅███▇▇▃▃ | mt | 262 μs | ch | ### | xorshift char count | 00 | 038 |█████████████████████ | 01 | 036 |████████████████████ | 02 | 045 |█████████████████████████ | 03 | 038 |█████████████████████ | 04 | 041 |██████████████████████ | 05 | 031 |█████████████████ | 06 | 034 |██████████████████ | 07 | 037 |████████████████████ | ------------------------------------- offset 14 {2,9,15} 0 uint(0000002128285267359)+0 =2276455839 666666666666666666666666666666 1 uint(0000002128285267386)+1 =2276455867 666666666666666666666666666666 2 uint(0000002128285267413)+2 =2276455895 666666666666666666666666666666 3 uint(0000002128285267439)+3 =2276455922 666666666666666666666666666666 4 uint(0000002128285267468)+4 =2276455952 666666666666666666666666666666 5 uint(0000002128285267493)+5 =2276455978 666666666666666666666666666666 6 uint(0000002128285267520)+6 =2276456006 666666666666666666666666666666 7 uint(0000002128285267546)+7 =2276456033 666666666666666666666666666666 8 uint(0000002128285267573)+8 =2276456061 666666666666666666666666666666 9 uint(0000002128285267599)+9 =2276456088 666666666666666666666666666666 ## | xorshift chars | 00 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 01 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 02 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 03 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 04 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 05 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 06 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 07 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 08 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 09 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | mt | 267 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 000 | | 06 | 300 |█████████████████████████ | 07 | 000 | | ------------------------------------- offset 15 {2,15,17} 0 uint(0000002128285267678)+0 =2276456158 555555555555555555555555555555 1 uint(0000002128285267705)+1 =2276456186 555555555555555555555555555555 2 uint(0000002128285267739)+2 =2276456221 555555555555555555555555555555 3 uint(0000002128285267776)+3 =2276456259 555555555555555555555555555555 4 uint(0000002128285267811)+4 =2276456295 555555555555555555555555555555 5 uint(0000002128285267849)+5 =2276456334 555555555555555555555555555555 6 uint(0000002128285267887)+6 =2276456373 555555555555555555555555555555 7 uint(0000002128285267923)+7 =2276456410 555555555555555666666666666666 8 uint(0000002128285267967)+8 =2276456455 666666666666666666666666666666 9 uint(0000002128285268010)+9 =2276456499 666666666666666666666666666666 ## | xorshift chars | 00 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 01 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 02 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 03 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 04 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 05 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 06 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 07 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 08 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 09 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | mt | 350 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 225 |█████████████████████████ | 06 | 075 |████████ | 07 | 000 | | ------------------------------------- offset 16 {2,15,25} 0 uint(0000002128285268089)+0 =2276456569 666666774455532221100445556777 1 uint(0000002128285268115)+1 =2276456596 221100045556677110003222223300 2 uint(0000002128285268142)+2 =2276456624 711003322222300011776655540001 3 uint(0000002128285268168)+3 =2276456651 011177665544001112333554447666 4 uint(0000002128285268195)+4 =2276456679 112233555447776666774455332211 5 uint(0000002128285268222)+5 =2276456707 666774455533221100445556777110 6 uint(0000002128285268250)+6 =2276456736 100044556677110003222222300011 7 uint(0000002128285268275)+7 =2276456762 003332222330001777665544000122 8 uint(0000002128285268301)+8 =2276456789 777666554400112233355447766666 9 uint(0000002128285268328)+9 =2276456817 223335444776666774455533221100 ## | xorshift chars | 00 | ▇▇▇▇▇▇██▅▅▆▆▆▄▃▃▃▂▂▁▁▅▅▆▆▆▇███ | 01 | ▃▃▂▂▁▁▁▅▆▆▆▇▇██▂▂▁▁▁▄▃▃▃▃▃▄▄▁▁ | 02 | █▂▂▁▁▄▄▃▃▃▃▃▄▁▁▁▂▂██▇▇▆▆▆▅▁▁▁▂ | 03 | ▁▂▂▂██▇▇▆▆▅▅▁▁▂▂▂▃▄▄▄▆▆▅▅▅█▇▇▇ | 04 | ▂▂▃▃▄▄▆▆▆▅▅███▇▇▇▇██▅▅▆▆▄▄▃▃▂▂ | 05 | ▇▇▇██▅▅▆▆▆▄▄▃▃▂▂▁▁▅▅▆▆▆▇███▂▂▁ | 06 | ▂▁▁▁▅▅▆▆▇▇██▂▂▁▁▁▄▃▃▃▃▃▃▄▁▁▁▂▂ | 07 | ▁▁▄▄▄▃▃▃▃▄▄▁▁▁▂███▇▇▆▆▅▅▁▁▁▂▃▃ | 08 | ███▇▇▇▆▆▅▅▁▁▂▂▃▃▄▄▄▆▆▅▅██▇▇▇▇▇ | 09 | ▃▃▄▄▄▆▅▅▅██▇▇▇▇██▅▅▆▆▆▄▄▃▃▂▂▁▁ | mt | 266 μs | ch | ### | xorshift char count | 00 | 045 |█████████████████████████ | 01 | 036 |████████████████████ | 02 | 040 |██████████████████████ | 03 | 031 |█████████████████ | 04 | 032 |█████████████████ | 05 | 039 |█████████████████████ | 06 | 040 |██████████████████████ | 07 | 037 |████████████████████ | ------------------------------------- offset 17 {2,21,9} 0 uint(0000002128285268516)+0 =2276456996 555555555555555555555555555555 1 uint(0000002128285268541)+1 =2276457022 555555555555555555555555555555 2 uint(0000002128285268568)+2 =2276457050 555555555555555555555555555555 3 uint(0000002128285268594)+3 =2276457077 555555555555555555555555555555 4 uint(0000002128285268620)+4 =2276457104 555555555555555555555555555555 5 uint(0000002128285268646)+5 =2276457131 555555555555555555555555555555 6 uint(0000002128285268673)+6 =2276457159 555555555555555555555555555555 7 uint(0000002128285268699)+7 =2276457186 555555555555555555555555555555 8 uint(0000002128285268725)+8 =2276457213 555555555555555555555555555555 9 uint(0000002128285268752)+9 =2276457241 555555555555555555555555555555 ## | xorshift chars | 00 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 01 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 02 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 03 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 04 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 05 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 06 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 07 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 08 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 09 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | mt | 262 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 300 |█████████████████████████ | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 18 {3,1,14} 0 uint(0000002128285268844)+0 =2276457324 777777777777777777777777777777 1 uint(0000002128285268882)+1 =2276457363 777777777777777777777777777777 2 uint(0000002128285268917)+2 =2276457399 777777777777777777777777777777 3 uint(0000002128285268954)+3 =2276457437 777777777777777777777777777777 4 uint(0000002128285268990)+4 =2276457474 777777777777777777777777777777 5 uint(0000002128285269060)+5 =2276457545 777777777777777777777777777777 6 uint(0000002128285269121)+6 =2276457607 777777777777777777777777777777 7 uint(0000002128285269181)+7 =2276457668 777777777777777777777777777777 8 uint(0000002128285269241)+8 =2276457729 777777777777777777777777777777 9 uint(0000002128285269301)+9 =2276457790 777777777777777777777777777777 ## | xorshift chars | 00 | ██████████████████████████████ | 01 | ██████████████████████████████ | 02 | ██████████████████████████████ | 03 | ██████████████████████████████ | 04 | ██████████████████████████████ | 05 | ██████████████████████████████ | 06 | ██████████████████████████████ | 07 | ██████████████████████████████ | 08 | ██████████████████████████████ | 09 | ██████████████████████████████ | mt | 517 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 000 | | 06 | 000 | | 07 | 300 |█████████████████████████ | ------------------------------------- offset 19 {3,3,26} 0 uint(0000002128285269477)+0 =2276457957 507315375135135134134134134134 1 uint(0000002128285269536)+1 =2276458017 712704624126036036036036036046 2 uint(0000002128285269593)+2 =2276458075 624037137136025264062731731631 3 uint(0000002128285269654)+3 =2276458137 606532063106532063207423742317 4 uint(0000002128285269686)+4 =2276458170 065317420172017423742317231642 5 uint(0000002128285269712)+5 =2276458197 423164316453045306430675310257 6 uint(0000002128285269738)+6 =2276458224 206752675201057603560354603760 7 uint(0000002128285269765)+7 =2276458252 703546054613541354613461324132 8 uint(0000002128285269792)+8 =2276458280 134613241324712470136013461346 9 uint(0000002128285269818)+9 =2276458307 470134603460134613467146713471 ## | xorshift chars | 00 | ▆▁█▄▂▆▄█▆▂▄▆▂▄▆▂▄▅▂▄▅▂▄▅▂▄▅▂▄▅ | 01 | █▂▃█▁▅▇▃▅▂▃▇▁▄▇▁▄▇▁▄▇▁▄▇▁▄▇▁▅▇ | 02 | ▇▃▅▁▄█▂▄█▂▄▇▁▃▆▃▇▅▁▇▃█▄▂█▄▂▇▄▂ | 03 | ▇▁▇▆▄▃▁▇▄▂▁▇▆▄▃▁▇▄▃▁█▅▃▄█▅▃▄▂█ | 04 | ▁▇▆▄▂█▅▃▁▂█▃▁▂█▅▃▄█▅▃▄▂█▃▄▂▇▅▃ | 05 | ▅▃▄▂▇▅▄▂▇▅▆▄▁▅▆▄▁▇▅▄▁▇█▆▄▂▁▃▆█ | 06 | ▃▁▇█▆▃▇█▆▃▁▂▁▆█▇▁▄▆▇▁▄▆▅▇▁▄█▇▁ | 07 | █▁▄▆▅▇▁▆▅▇▂▄▆▅▂▄▆▅▇▂▄▅▇▂▄▃▅▂▄▃ | 08 | ▂▄▅▇▂▄▃▅▂▄▃▅█▂▃▅█▁▂▄▇▁▂▄▅▇▂▄▅▇ | 09 | ▅█▁▂▄▅▇▁▄▅▇▁▂▄▅▇▂▄▅▇█▂▅▇█▂▄▅█▂ | mt | 368 μs | ch | ### | xorshift char count | 00 | 037 |████████████████ | 01 | 044 |███████████████████ | 02 | 028 |████████████ | 03 | 056 |█████████████████████████ | 04 | 041 |██████████████████ | 05 | 022 |█████████ | 06 | 043 |███████████████████ | 07 | 029 |████████████ | ------------------------------------- offset 20 {3,3,28} 0 uint(0000002128285269957)+0 =2276458437 555115400444044333773377226622 1 uint(0000002128285269982)+1 =2276458463 337773377226622662511515540044 2 uint(0000002128285270012)+2 =2276458494 625115511550044004403777773366 3 uint(0000002128285270038)+3 =2276458521 044007773773336226662221551115 4 uint(0000002128285270065)+4 =2276458549 622662261555115510440044403773 5 uint(0000002128285270090)+5 =2276458575 510444004403777377332662266221 6 uint(0000002128285270117)+6 =2276458603 377337622266226155115551044004 7 uint(0000002128285270142)+7 =2276458629 155111511444044400773377736662 8 uint(0000002128285270169)+8 =2276458657 400773377337622666221155115510 9 uint(0000002128285270196)+9 =2276458685 666226155115550440004003773377 ## | xorshift chars | 00 | ▆▆▆▂▂▆▅▁▁▅▅▅▁▅▅▄▄▄██▄▄██▃▃▇▇▃▃ | 01 | ▄▄███▄▄██▃▃▇▇▃▃▇▇▃▆▂▂▆▂▆▆▅▁▁▅▅ | 02 | ▇▃▆▂▂▆▆▂▂▆▆▁▁▅▅▁▁▅▅▁▄█████▄▄▇▇ | 03 | ▁▅▅▁▁███▄██▄▄▄▇▃▃▇▇▇▃▃▃▂▆▆▂▂▂▆ | 04 | ▇▃▃▇▇▃▃▇▂▆▆▆▂▂▆▆▂▁▅▅▁▁▅▅▅▁▄██▄ | 05 | ▆▂▁▅▅▅▁▁▅▅▁▄███▄██▄▄▃▇▇▃▃▇▇▃▃▂ | 06 | ▄██▄▄█▇▃▃▃▇▇▃▃▇▂▆▆▂▂▆▆▆▂▁▅▅▁▁▅ | 07 | ▂▆▆▂▂▂▆▂▂▅▅▅▁▅▅▅▁▁██▄▄███▄▇▇▇▃ | 08 | ▅▁▁██▄▄██▄▄█▇▃▃▇▇▇▃▃▂▂▆▆▂▂▆▆▂▁ | 09 | ▇▇▇▃▃▇▂▆▆▂▂▆▆▆▁▅▅▁▁▁▅▁▁▄██▄▄██ | mt | 266 μs | ch | ### | xorshift char count | 00 | 036 |████████████████████ | 01 | 037 |█████████████████████ | 02 | 036 |████████████████████ | 03 | 035 |████████████████████ | 04 | 038 |██████████████████████ | 05 | 039 |██████████████████████ | 06 | 036 |████████████████████ | 07 | 043 |█████████████████████████ | ------------------------------------- offset 21 {3,3,29} 0 uint(0000002128285270376)+0 =2276458856 000003333222255555444477776666 1 uint(0000002128285270402)+1 =2276458883 555444477777666611111000033332 2 uint(0000002128285270428)+2 =2276458910 611111000033332222255555444477 3 uint(0000002128285270455)+3 =2276458938 222225555444477777666611111000 4 uint(0000002128285270481)+4 =2276458965 777666661111000003333222255555 5 uint(0000002128285270507)+5 =2276458992 003333222225555444447777666611 6 uint(0000002128285270534)+6 =2276459020 444447777666611111100003333222 7 uint(0000002128285270560)+7 =2276459047 111100003333322225555444447777 8 uint(0000002128285270587)+8 =2276459075 222555544447777766661111000003 9 uint(0000002128285270612)+9 =2276459101 766666111100003333322225555444 ## | xorshift chars | 00 | ▁▁▁▁▁▄▄▄▄▃▃▃▃▆▆▆▆▆▅▅▅▅████▇▇▇▇ | 01 | ▆▆▆▅▅▅▅█████▇▇▇▇▂▂▂▂▂▁▁▁▁▄▄▄▄▃ | 02 | ▇▂▂▂▂▂▁▁▁▁▄▄▄▄▃▃▃▃▃▆▆▆▆▆▅▅▅▅██ | 03 | ▃▃▃▃▃▆▆▆▆▅▅▅▅█████▇▇▇▇▂▂▂▂▂▁▁▁ | 04 | ███▇▇▇▇▇▂▂▂▂▁▁▁▁▁▄▄▄▄▃▃▃▃▆▆▆▆▆ | 05 | ▁▁▄▄▄▄▃▃▃▃▃▆▆▆▆▅▅▅▅▅████▇▇▇▇▂▂ | 06 | ▅▅▅▅▅████▇▇▇▇▂▂▂▂▂▂▁▁▁▁▄▄▄▄▃▃▃ | 07 | ▂▂▂▂▁▁▁▁▄▄▄▄▄▃▃▃▃▆▆▆▆▅▅▅▅▅████ | 08 | ▃▃▃▆▆▆▆▅▅▅▅█████▇▇▇▇▂▂▂▂▁▁▁▁▁▄ | 09 | █▇▇▇▇▇▂▂▂▂▁▁▁▁▄▄▄▄▄▃▃▃▃▆▆▆▆▅▅▅ | mt | 263 μs | ch | ### | xorshift char count | 00 | 040 |█████████████████████████ | 01 | 039 |████████████████████████ | 02 | 038 |███████████████████████ | 03 | 035 |█████████████████████ | 04 | 038 |███████████████████████ | 05 | 038 |███████████████████████ | 06 | 035 |█████████████████████ | 07 | 037 |███████████████████████ | ------------------------------------- offset 22 {3,5,20} 0 uint(0000002128285270799)+0 =2276459279 000000000000000000000000001111 1 uint(0000002128285270826)+1 =2276459307 000000000000111111111111111111 2 uint(0000002128285270852)+2 =2276459334 111111111111111111111111111111 3 uint(0000002128285270878)+3 =2276459361 111111111111111111122222222222 4 uint(0000002128285270904)+4 =2276459388 111122222222222222222222222222 5 uint(0000002128285270929)+5 =2276459414 222222222222222222222222223333 6 uint(0000002128285270956)+6 =2276459442 222222222223333333333333333333 7 uint(0000002128285270981)+7 =2276459468 333333333333333333333333333333 8 uint(0000002128285271008)+8 =2276459496 333333377777777777777777777666 9 uint(0000002128285271085)+9 =2276459574 777777666666666666666666666655 ## | xorshift chars | 00 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂▂▂▂ | 01 | ▁▁▁▁▁▁▁▁▁▁▁▁▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 02 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 03 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▃▃▃▃▃▃▃▃▃▃▃ | 04 | ▂▂▂▂▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃ | 05 | ▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▄▄▄▄ | 06 | ▃▃▃▃▃▃▃▃▃▃▃▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 07 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 08 | ▄▄▄▄▄▄▄████████████████████▇▇▇ | 09 | ██████▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▆▆ | mt | 346 μs | ch | ### | xorshift char count | 00 | 038 |████████████ | 01 | 075 |█████████████████████████ | 02 | 074 |████████████████████████ | 03 | 060 |████████████████████ | 04 | 000 | | 05 | 002 | | 06 | 025 |████████ | 07 | 026 |████████ | ------------------------------------- offset 23 {3,5,22} 0 uint(0000002128285271394)+0 =2276459874 333332222244444455555566666777 1 uint(0000002128285271454)+1 =2276459935 666666777770000001111112222223 2 uint(0000002128285271512)+2 =2276459994 111222222333333222223333330000 3 uint(0000002128285271567)+3 =2276460050 333333000001111116666677777744 4 uint(0000002128285271626)+4 =2276460110 667777774444445555553333322222 5 uint(0000002128285271683)+5 =2276460168 333322222111111000007777776666 6 uint(0000002128285271745)+6 =2276460231 777776666665555554444440000001 7 uint(0000002128285271799)+7 =2276460286 444000001111122222233333344444 8 uint(0000002128285271858)+8 =2276460346 333334444455555666666777771111 9 uint(0000002128285271920)+9 =2276460409 777771111110000003333322222255 ## | xorshift chars | 00 | ▄▄▄▄▄▃▃▃▃▃▅▅▅▅▅▅▆▆▆▆▆▆▇▇▇▇▇███ | 01 | ▇▇▇▇▇▇█████▁▁▁▁▁▁▂▂▂▂▂▂▃▃▃▃▃▃▄ | 02 | ▂▂▂▃▃▃▃▃▃▄▄▄▄▄▄▃▃▃▃▃▄▄▄▄▄▄▁▁▁▁ | 03 | ▄▄▄▄▄▄▁▁▁▁▁▂▂▂▂▂▂▇▇▇▇▇██████▅▅ | 04 | ▇▇██████▅▅▅▅▅▅▆▆▆▆▆▆▄▄▄▄▄▃▃▃▃▃ | 05 | ▄▄▄▄▃▃▃▃▃▂▂▂▂▂▂▁▁▁▁▁██████▇▇▇▇ | 06 | █████▇▇▇▇▇▇▆▆▆▆▆▆▅▅▅▅▅▅▁▁▁▁▁▁▂ | 07 | ▅▅▅▁▁▁▁▁▂▂▂▂▂▃▃▃▃▃▃▄▄▄▄▄▄▅▅▅▅▅ | 08 | ▄▄▄▄▄▅▅▅▅▅▆▆▆▆▆▇▇▇▇▇▇█████▂▂▂▂ | 09 | █████▂▂▂▂▂▂▁▁▁▁▁▁▄▄▄▄▄▃▃▃▃▃▃▆▆ | mt | 584 μs | ch | ### | xorshift char count | 00 | 037 |██████████████████ | 01 | 037 |██████████████████ | 02 | 044 |██████████████████████ | 03 | 049 |█████████████████████████ | 04 | 033 |████████████████ | 05 | 025 |████████████ | 06 | 034 |█████████████████ | 07 | 041 |████████████████████ | ------------------------------------- offset 24 {3,5,25} 0 uint(0000002128285272153)+0 =2276460633 103267452330176543221022107654 1 uint(0000002128285272179)+1 =2276460660 543221022107654233016745100254 2 uint(0000002128285272206)+2 =2276460688 233016745100324476001245567674 3 uint(0000002128285272233)+3 =2276460716 546001234567667522301765433214 4 uint(0000002128285272260)+4 =2276460744 452301176443210456770233547610 5 uint(0000002128285272287)+5 =2276460772 456770233547710332577610324566 6 uint(0000002128285272313)+6 =2276460799 332547610332556701237665322106 7 uint(0000002128285272342)+7 =2276460829 701123665432106774233010123445 8 uint(0000002128285272369)+8 =2276460857 674523010112345671002544762301 9 uint(0000002128285272394)+9 =2276460883 671103254762231667453310776577 ## | xorshift chars | 00 | ▂▁▄▃▇█▅▆▃▄▄▁▂█▇▆▅▄▃▃▂▁▃▃▂▁█▇▆▅ | 01 | ▆▅▄▃▃▂▁▃▃▂▁█▇▆▅▃▄▄▁▂▇█▅▆▂▁▁▃▆▅ | 02 | ▃▄▄▁▂▇█▅▆▂▁▁▄▃▅▅█▇▁▁▂▃▅▆▆▇█▇█▅ | 03 | ▆▅▇▁▁▂▃▄▅▆▇█▇▇█▆▃▃▄▁▂█▇▆▅▄▄▃▂▅ | 04 | ▅▆▃▄▁▂▂█▇▅▅▄▃▂▁▅▆▇██▁▃▄▄▆▅█▇▂▁ | 05 | ▅▆▇██▁▃▄▄▆▅██▂▁▄▄▃▆██▇▂▁▄▃▅▆▇▇ | 06 | ▄▄▃▆▅█▇▂▁▄▄▃▆▆▇█▁▂▃▄█▇▇▆▄▃▃▂▁▇ | 07 | █▁▂▂▃▄▇▇▆▅▄▃▂▁▇██▅▃▄▄▁▂▁▂▃▄▅▅▆ | 08 | ▇█▅▆▃▄▁▂▁▂▂▃▄▅▆▇█▂▁▁▃▆▅▅█▇▃▄▁▂ | 09 | ▇█▂▂▁▄▃▆▅█▇▃▃▄▂▇▇█▅▆▄▄▂▁██▇▆██ | mt | 268 μs | ch | ### | xorshift char count | 00 | 038 |███████████████████████ | 01 | 037 |██████████████████████ | 02 | 041 |█████████████████████████ | 03 | 041 |█████████████████████████ | 04 | 035 |█████████████████████ | 05 | 033 |████████████████████ | 06 | 037 |██████████████████████ | 07 | 038 |███████████████████████ | ------------------------------------- offset 25 {3,7,29} 0 uint(0000002128285272581)+0 =2276461061 102470135023563065320523174316 1 uint(0000002128285272609)+1 =2276461090 065320523164316454615461325023 2 uint(0000002128285272636)+2 =2276461118 654613246325702570236430653107 3 uint(0000002128285272663)+3 =2276461146 356036531053207423752011347124 4 uint(0000002128285272688)+4 =2276461172 420174011245714570356035463675 5 uint(0000002128285272715)+5 =2276461200 571354135462075201731065306546 6 uint(0000002128285272742)+6 =2276461228 201743065320545712470254615461 7 uint(0000002128285272769)+7 =2276461256 702357234613461327201742065320 8 uint(0000002128285272795)+8 =2276461283 027423742317320753031064316420 9 uint(0000002128285272822)+9 =2276461311 754203065310520174317410271024 ## | xorshift chars | 00 | ▂▁▃▅█▁▂▄▆▁▃▄▆▇▄▁▇▆▄▃▁▆▃▄▂█▅▄▂▇ | 01 | ▁▇▆▄▃▁▆▃▄▂▇▅▄▂▇▅▆▅▇▂▆▅▇▂▄▃▆▁▃▄ | 02 | ▇▆▅▇▂▄▃▅▇▄▃▆█▁▃▆█▁▃▄▇▅▄▁▇▆▄▂▁█ | 03 | ▄▆▇▁▄▇▆▄▂▁▆▄▃▁█▅▃▄█▆▃▁▂▂▄▅█▂▃▅ | 04 | ▅▃▁▂█▅▁▂▂▃▅▆█▂▅▆█▁▄▆▇▁▄▆▅▇▄▇█▆ | 05 | ▆█▂▄▆▅▂▄▆▅▇▃▁█▆▃▁▂█▄▂▁▇▆▄▁▇▆▅▇ | 06 | ▃▁▂█▅▄▁▇▆▄▃▁▆▅▆█▂▃▅█▁▃▆▅▇▂▆▅▇▂ | 07 | █▁▃▄▆█▃▄▅▇▂▄▅▇▂▄▃█▃▁▂█▅▃▁▇▆▄▃▁ | 08 | ▁▃█▅▃▄█▅▃▄▂█▄▃▁█▆▄▁▄▂▁▇▅▄▂▇▅▃▁ | 09 | █▆▅▃▁▄▁▇▆▄▂▁▆▃▁▂█▅▄▂█▅▂▁▃█▂▁▃▅ | mt | 268 μs | ch | ### | xorshift char count | 00 | 043 |███████████████████████ | 01 | 037 |████████████████████ | 02 | 039 |█████████████████████ | 03 | 045 |█████████████████████████ | 04 | 036 |████████████████████ | 05 | 039 |█████████████████████ | 06 | 031 |█████████████████ | 07 | 030 |████████████████ | ------------------------------------- offset 26 {3,13,7} 0 uint(0000002128285272992)+0 =2276461472 555555555555555555555555555555 1 uint(0000002128285273014)+1 =2276461495 555555555555555555555555555555 2 uint(0000002128285273032)+2 =2276461514 555555555555555555555555555555 3 uint(0000002128285273060)+3 =2276461543 555555555555555555555555555555 4 uint(0000002128285273085)+4 =2276461569 555555555555555555555555555555 5 uint(0000002128285273112)+5 =2276461597 555555555555555555555555555555 6 uint(0000002128285273141)+6 =2276461627 555555555555555555555555555555 7 uint(0000002128285273168)+7 =2276461655 555555555555555555555555555555 8 uint(0000002128285273194)+8 =2276461682 555555555555555555555555555555 9 uint(0000002128285273222)+9 =2276461711 555555555555555555555555555555 ## | xorshift chars | 00 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 01 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 02 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 03 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 04 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 05 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 06 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 07 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 08 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 09 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | mt | 260 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 300 |█████████████████████████ | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 27 {3,23,25} 0 uint(0000002128285273307)+0 =2276461787 100567701335476103222011674532 1 uint(0000002128285273335)+1 =2276461816 103222011674432110765401223566 2 uint(0000002128285273361)+2 =2276461843 110765541223456610332577667442 3 uint(0000002128285273389)+3 =2276461872 671332547667745230176553221045 4 uint(0000002128285273416)+4 =2276461900 233176654321045560112354461003 5 uint(0000002128285273441)+5 =2276461926 567011354476103222306674532107 6 uint(0000002128285273468)+6 =2276461954 222301674553100765441233457710 7 uint(0000002128285273495)+7 =2276461982 065440133456670332547667445300 8 uint(0000002128285273521)+8 =2276462009 032547767745233176654322045567 9 uint(0000002128285273548)+9 =2276462037 017665322104567011234476103223 ## | xorshift chars | 00 | ▂▁▁▆▇██▁▂▄▄▆▅█▇▂▁▄▃▃▃▁▂▂▇█▅▆▄▃ | 01 | ▂▁▄▃▃▃▁▂▂▇█▅▅▄▃▂▂▁█▇▆▅▁▂▃▃▄▆▇▇ | 02 | ▂▂▁█▇▆▆▅▂▃▃▄▅▆▇▇▂▁▄▄▃▆██▇▇█▅▅▃ | 03 | ▇█▂▄▄▃▆▅█▇▇██▅▆▃▄▁▂█▇▆▆▄▃▃▂▁▅▆ | 04 | ▃▄▄▂█▇▇▆▅▄▃▂▁▅▆▆▇▁▂▂▃▄▆▅▅▇▂▁▁▄ | 05 | ▆▇█▁▂▂▄▆▅▅█▇▂▁▄▃▃▃▄▁▇▇█▅▆▄▃▂▁█ | 06 | ▃▃▃▄▁▂▇█▅▆▆▄▂▁▁█▇▆▅▅▂▃▄▄▅▆██▂▁ | 07 | ▁▇▆▅▅▁▂▄▄▅▆▇▇█▁▄▄▃▆▅█▇▇█▅▅▆▄▁▁ | 08 | ▁▄▃▆▅██▇██▅▆▃▄▄▂█▇▇▆▅▄▃▃▁▅▆▆▇█ | 09 | ▁▂█▇▇▆▄▃▃▂▁▅▆▇█▁▂▂▃▄▅▅█▇▂▁▄▃▃▄ | mt | 267 μs | ch | ### | xorshift char count | 00 | 036 |██████████████████████ | 01 | 038 |███████████████████████ | 02 | 039 |████████████████████████ | 03 | 040 |█████████████████████████ | 04 | 036 |██████████████████████ | 05 | 036 |██████████████████████ | 06 | 039 |████████████████████████ | 07 | 036 |██████████████████████ | ------------------------------------- offset 28 {3,25,24} 0 uint(0000002128285273737)+0 =2276462217 110077665554222330011167774455 1 uint(0000002128285273763)+1 =2276462244 330001166774455111003322255447 2 uint(0000002128285273789)+2 =2276462271 511000322255447766001112333445 3 uint(0000002128285273816)+3 =2276462299 766600112233344556677776665544 4 uint(0000002128285273843)+4 =2276462327 556667777665554333221100666744 5 uint(0000002128285273870)+5 =2276462355 433221110666774455222330011554 6 uint(0000002128285273897)+6 =2276462383 445222330011155447766611003322 7 uint(0000002128285273923)+7 =2276462410 444776611000322244556677701112 8 uint(0000002128285273949)+8 =2276462437 244555677700012223333221110777 9 uint(0000002128285273975)+9 =2276462464 223333221110777665544422330116 ## | xorshift chars | 00 | ▂▂▁▁██▇▇▆▆▆▅▃▃▃▄▄▁▁▂▂▂▇███▅▅▆▆ | 01 | ▄▄▁▁▁▂▂▇▇██▅▅▆▆▂▂▂▁▁▄▄▃▃▃▆▆▅▅█ | 02 | ▆▂▂▁▁▁▄▃▃▃▆▆▅▅██▇▇▁▁▂▂▂▃▄▄▄▅▅▆ | 03 | █▇▇▇▁▁▂▂▃▃▄▄▄▅▅▆▆▇▇████▇▇▇▆▆▅▅ | 04 | ▆▆▇▇▇████▇▇▆▆▆▅▄▄▄▃▃▂▂▁▁▇▇▇█▅▅ | 05 | ▅▄▄▃▃▂▂▂▁▇▇▇██▅▅▆▆▃▃▃▄▄▁▁▂▂▆▆▅ | 06 | ▅▅▆▃▃▃▄▄▁▁▂▂▂▆▆▅▅██▇▇▇▂▂▁▁▄▄▃▃ | 07 | ▅▅▅██▇▇▂▂▁▁▁▄▃▃▃▅▅▆▆▇▇███▁▂▂▂▃ | 08 | ▃▅▅▆▆▆▇███▁▁▁▂▃▃▃▄▄▄▄▃▃▂▂▂▁███ | 09 | ▃▃▄▄▄▄▃▃▂▂▂▁███▇▇▆▆▅▅▅▃▃▄▄▁▂▂▇ | mt | 268 μs | ch | ### | xorshift char count | 00 | 035 |████████████████████ | 01 | 043 |█████████████████████████ | 02 | 040 |███████████████████████ | 03 | 035 |████████████████████ | 04 | 036 |████████████████████ | 05 | 036 |████████████████████ | 06 | 037 |█████████████████████ | 07 | 038 |██████████████████████ | ------------------------------------- offset 29 {3,27,11} 0 uint(0000002128285274158)+0 =2276462638 111111111111111111111111111111 1 uint(0000002128285274183)+1 =2276462664 111111111111111111111111111111 2 uint(0000002128285274210)+2 =2276462692 111111111111111111111111111111 3 uint(0000002128285274236)+3 =2276462719 111111111111111111111111111111 4 uint(0000002128285274263)+4 =2276462747 111111111111111111111111111111 5 uint(0000002128285274290)+5 =2276462775 111111111111111111111111111111 6 uint(0000002128285274317)+6 =2276462803 111111111111111111111111111111 7 uint(0000002128285274343)+7 =2276462830 111111111111111111111111111111 8 uint(0000002128285274369)+8 =2276462857 111111111111111111111111111111 9 uint(0000002128285274396)+9 =2276462885 111111111111111111111111111111 ## | xorshift chars | 00 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 01 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 02 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 03 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 04 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 05 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 06 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 07 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 08 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 09 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | mt | 266 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 300 |█████████████████████████ | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 000 | | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 30 {4,3,17} 0 uint(0000002128285274476)+0 =2276462956 555555555555555555555555555555 1 uint(0000002128285274503)+1 =2276462984 555555555555555555555555555555 2 uint(0000002128285274530)+2 =2276463012 555555555555555555555555555555 3 uint(0000002128285274556)+3 =2276463039 555555555555555555555555555555 4 uint(0000002128285274583)+4 =2276463067 555555555555555555555666666666 5 uint(0000002128285274610)+5 =2276463095 555555666666666666666666666666 6 uint(0000002128285274638)+6 =2276463124 666666666666666666666666666666 7 uint(0000002128285274664)+7 =2276463151 666666666666666666666666666666 8 uint(0000002128285274690)+8 =2276463178 666666666666666666666666666666 9 uint(0000002128285274718)+9 =2276463207 666666666666666666666666666666 ## | xorshift chars | 00 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 01 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 02 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 03 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 04 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▇▇▇▇▇▇▇▇▇ | 05 | ▆▆▆▆▆▆▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 06 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 07 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 08 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 09 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | mt | 269 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 147 |████████████████████████ | 06 | 153 |█████████████████████████ | 07 | 000 | | ------------------------------------- offset 31 {4,3,27} 0 uint(0000002128285274813)+0 =2276463293 154637245510737601453262540057 1 uint(0000002128285274842)+1 =2276463323 601045262354017626104364150267 2 uint(0000002128285274869)+2 =2276463351 326714324510237720514623251001 3 uint(0000002128285274894)+3 =2276463377 720455623675001576375445365402 4 uint(0000002128285274922)+4 =2276463406 572275040165106776015523736410 5 uint(0000002128285274949)+5 =2276463434 772015523736400573223540137673 6 uint(0000002128285274976)+6 =2276463462 413223750157263143761510270510 7 uint(0000002128285275006)+7 =2276463493 032045546233645156326710401662 8 uint(0000002128285275030)+8 =2276463518 504632354451326710015710463764 9 uint(0000002128285275056)+9 =2276463545 754041265023364011623320401376 ## | xorshift chars | 00 | ▂▆▅▇▄█▃▅▆▆▂▁█▄█▇▁▂▅▆▄▃▇▃▆▅▁▁▆█ | 01 | ▇▁▂▁▅▆▃▇▃▄▆▅▁▂█▇▃▇▂▁▅▄▇▅▂▆▁▃▇█ | 02 | ▄▃▇█▂▅▄▃▅▆▂▁▃▄██▃▁▆▂▅▇▃▄▃▆▂▁▁▂ | 03 | █▃▁▅▆▆▇▃▄▇█▆▁▁▂▆█▇▄█▆▅▅▆▄▇▆▅▁▃ | 04 | ▆█▃▃█▆▁▅▁▂▇▆▂▁▇██▇▁▂▆▆▃▄█▄▇▅▂▁ | 05 | ██▃▁▂▆▆▃▄█▄▇▅▁▁▆█▄▃▃▄▆▅▁▂▄█▇█▄ | 06 | ▅▂▄▃▃▄█▆▁▂▆█▃▇▄▂▅▄█▇▂▆▂▁▃█▁▆▂▁ | 07 | ▁▄▃▁▅▆▆▅▇▃▄▄▇▅▆▂▆▇▄▃▇█▂▁▅▁▂▇▇▃ | 08 | ▆▁▅▇▄▃▄▆▅▅▆▂▄▃▇█▂▁▁▂▆█▂▁▅▇▄█▇▅ | 09 | █▆▅▁▅▂▃▇▆▁▃▄▄▇▅▁▂▂▇▃▄▄▃▁▅▁▂▄█▇ | mt | 270 μs | ch | ### | xorshift char count | 00 | 043 |█████████████████████████ | 01 | 036 |████████████████████ | 02 | 037 |█████████████████████ | 03 | 037 |█████████████████████ | 04 | 034 |███████████████████ | 05 | 042 |████████████████████████ | 06 | 037 |█████████████████████ | 07 | 034 |███████████████████ | ------------------------------------- offset 32 {4,5,15} 0 uint(0000002128285275235)+0 =2276463715 444444444444444444444444444444 1 uint(0000002128285275262)+1 =2276463743 444444444444444444444444444444 2 uint(0000002128285275290)+2 =2276463772 444444444444444444444444444444 3 uint(0000002128285275315)+3 =2276463798 444444444444444444444444444444 4 uint(0000002128285275340)+4 =2276463824 444444444444444444444444444444 5 uint(0000002128285275380)+5 =2276463865 444444444444444444444444444444 6 uint(0000002128285275408)+6 =2276463894 444444444444444444444444444444 7 uint(0000002128285275433)+7 =2276463920 444444444444444444444444444444 8 uint(0000002128285275460)+8 =2276463948 444444444444444444444444444444 9 uint(0000002128285275488)+9 =2276463977 444444444444444444444444444444 ## | xorshift chars | 00 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 01 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 02 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 03 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 04 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 05 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 06 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 07 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 08 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 09 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | mt | 280 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 300 |█████████████████████████ | 05 | 000 | | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 33 {5,3,21} 0 uint(0000002128285275554)+0 =2276464034 666677777444445555533332222211 1 uint(0000002128285275576)+1 =2276464057 555553333222221111000077777666 2 uint(0000002128285275602)+2 =2276464084 111000077777666655554444477776 3 uint(0000002128285275628)+3 =2276464111 655555444477776666655554444333 4 uint(0000002128285275655)+4 =2276464139 666665555444443333222211110000 5 uint(0000002128285275682)+5 =2276464167 333222221111000066666777744444 6 uint(0000002128285275708)+6 =2276464194 006666777774444555552222333300 7 uint(0000002128285275734)+7 =2276464221 455552222333300000111155555444 8 uint(0000002128285275761)+8 =2276464249 000111155555444477777666611111 9 uint(0000002128285275789)+9 =2276464278 447777666611110000003333222244 ## | xorshift chars | 00 | ▇▇▇▇█████▅▅▅▅▅▆▆▆▆▆▄▄▄▄▃▃▃▃▃▂▂ | 01 | ▆▆▆▆▆▄▄▄▄▃▃▃▃▃▂▂▂▂▁▁▁▁█████▇▇▇ | 02 | ▂▂▂▁▁▁▁█████▇▇▇▇▆▆▆▆▅▅▅▅▅████▇ | 03 | ▇▆▆▆▆▆▅▅▅▅████▇▇▇▇▇▆▆▆▆▅▅▅▅▄▄▄ | 04 | ▇▇▇▇▇▆▆▆▆▅▅▅▅▅▄▄▄▄▃▃▃▃▂▂▂▂▁▁▁▁ | 05 | ▄▄▄▃▃▃▃▃▂▂▂▂▁▁▁▁▇▇▇▇▇████▅▅▅▅▅ | 06 | ▁▁▇▇▇▇█████▅▅▅▅▆▆▆▆▆▃▃▃▃▄▄▄▄▁▁ | 07 | ▅▆▆▆▆▃▃▃▃▄▄▄▄▁▁▁▁▁▂▂▂▂▆▆▆▆▆▅▅▅ | 08 | ▁▁▁▂▂▂▂▆▆▆▆▆▅▅▅▅█████▇▇▇▇▂▂▂▂▂ | 09 | ▅▅████▇▇▇▇▂▂▂▂▁▁▁▁▁▁▄▄▄▄▃▃▃▃▅▅ | mt | 260 μs | ch | ### | xorshift char count | 00 | 034 |██████████████████ | 01 | 034 |██████████████████ | 02 | 031 |████████████████ | 03 | 030 |████████████████ | 04 | 044 |███████████████████████ | 05 | 046 |█████████████████████████ | 06 | 040 |█████████████████████ | 07 | 041 |██████████████████████ | ------------------------------------- offset 34 {5,7,22} 0 uint(0000002128285275962)+0 =2276464442 011667744452223330111667744552 1 uint(0000002128285275989)+1 =2276464470 330011667775223300117765554433 2 uint(0000002128285276022)+2 =2276464504 000117766655433322211007766654 3 uint(0000002128285276048)+3 =2276464531 332211000766655443322110007766 4 uint(0000002128285276076)+4 =2276464560 443332111007766555433322110077 5 uint(0000002128285276103)+5 =2276464588 555443322110077765554433221110 6 uint(0000002128285276130)+6 =2276464616 766555433322110077766554433321 7 uint(0000002128285276156)+7 =2276464643 007766554433322110007666554433 8 uint(0000002128285276183)+8 =2276464671 110007766554443222110077666544 9 uint(0000002128285276210)+9 =2276464699 222110007666554433222100077665 ## | xorshift chars | 00 | ▁▂▂▇▇██▅▅▅▆▃▃▃▄▄▄▁▂▂▂▇▇██▅▅▆▆▃ | 01 | ▄▄▁▁▂▂▇▇███▆▃▃▄▄▁▁▂▂██▇▆▆▆▅▅▄▄ | 02 | ▁▁▁▂▂██▇▇▇▆▆▅▄▄▄▃▃▃▂▂▁▁██▇▇▇▆▅ | 03 | ▄▄▃▃▂▂▁▁▁█▇▇▇▆▆▅▅▄▄▃▃▂▂▁▁▁██▇▇ | 04 | ▅▅▄▄▄▃▂▂▂▁▁██▇▇▆▆▆▅▄▄▄▃▃▂▂▁▁██ | 05 | ▆▆▆▅▅▄▄▃▃▂▂▁▁███▇▆▆▆▅▅▄▄▃▃▂▂▂▁ | 06 | █▇▇▆▆▆▅▄▄▄▃▃▂▂▁▁███▇▇▆▆▅▅▄▄▄▃▂ | 07 | ▁▁██▇▇▆▆▅▅▄▄▄▃▃▂▂▁▁▁█▇▇▇▆▆▅▅▄▄ | 08 | ▂▂▁▁▁██▇▇▆▆▅▅▅▄▃▃▃▂▂▁▁██▇▇▇▆▅▅ | 09 | ▃▃▃▂▂▁▁▁█▇▇▇▆▆▅▅▄▄▃▃▃▂▁▁▁██▇▇▆ | mt | 275 μs | ch | ### | xorshift char count | 00 | 042 |█████████████████████████ | 01 | 039 |███████████████████████ | 02 | 034 |████████████████████ | 03 | 040 |███████████████████████ | 04 | 032 |███████████████████ | 05 | 036 |█████████████████████ | 06 | 040 |███████████████████████ | 07 | 037 |██████████████████████ | ------------------------------------- offset 35 {5,9,7} 0 uint(0000002128285276397)+0 =2276464877 555555555555555555555555555555 1 uint(0000002128285276424)+1 =2276464905 555555555555555555555555555555 2 uint(0000002128285276450)+2 =2276464932 555555555555555555555555555555 3 uint(0000002128285276476)+3 =2276464959 555555555555555555555555555555 4 uint(0000002128285276503)+4 =2276464987 555555555555555555555555555555 5 uint(0000002128285276530)+5 =2276465015 555555555555555555555555555555 6 uint(0000002128285276557)+6 =2276465043 555555555555555555555555555555 7 uint(0000002128285276582)+7 =2276465069 555555555555555555555555555555 8 uint(0000002128285276609)+8 =2276465097 555555555555555555555555555555 9 uint(0000002128285276637)+9 =2276465126 555555555555555555555555555555 ## | xorshift chars | 00 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 01 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 02 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 03 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 04 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 05 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 06 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 07 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 08 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 09 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | mt | 266 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 300 |█████████████████████████ | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 36 {5,9,28} 0 uint(0000002128285276717)+0 =2276465197 234567012237554321106554321067 1 uint(0000002128285276742)+1 =2276465223 321107654321167445230167752330 2 uint(0000002128285276769)+2 =2276465251 745233067445230110032447610325 3 uint(0000002128285276796)+3 =2276465279 010032547611032547601134556711 4 uint(0000002128285276823)+4 =2276465307 544701234570122346673210766542 5 uint(0000002128285276854)+5 =2276465339 345663221076543221066542330677 6 uint(0000002128285276879)+6 =2276465365 321076642230167452231167455547 7 uint(0000002128285276906)+7 =2276465393 745220166745547661322547610322 8 uint(0000002128285276932)+8 =2276465420 661032547661322456601223456701 9 uint(0000002128285276958)+9 =2276465447 455670123456671223765432210665 ## | xorshift chars | 00 | ▃▄▅▆▇█▁▂▃▃▄█▆▆▅▄▃▂▂▁▇▆▆▅▄▃▂▁▇█ | 01 | ▄▃▂▂▁█▇▆▅▄▃▂▂▇█▅▅▆▃▄▁▂▇██▆▃▄▄▁ | 02 | █▅▆▃▄▄▁▇█▅▅▆▃▄▁▂▂▁▁▄▃▅▅█▇▂▁▄▃▆ | 03 | ▁▂▁▁▄▃▆▅█▇▂▂▁▄▃▆▅█▇▁▂▂▄▅▆▆▇█▂▂ | 04 | ▆▅▅█▁▂▃▄▅▆█▁▂▃▃▄▅▇▇█▄▃▂▁█▇▇▆▅▃ | 05 | ▄▅▆▇▇▄▃▃▂▁█▇▆▅▄▃▃▂▁▇▇▆▅▃▄▄▁▇██ | 06 | ▄▃▂▁█▇▇▅▃▃▄▁▂▇█▅▆▃▃▄▂▂▇█▅▆▆▆▅█ | 07 | █▅▆▃▃▁▂▇▇█▅▆▆▅█▇▇▂▄▃▃▆▅█▇▂▁▄▃▃ | 08 | ▇▇▂▁▄▃▆▅█▇▇▂▄▃▃▅▆▇▇▁▂▃▃▄▅▆▇█▁▂ | 09 | ▅▆▆▇█▁▂▃▄▅▆▇▇█▂▃▃▄█▇▆▅▄▃▃▂▁▇▇▆ | mt | 268 μs | ch | ### | xorshift char count | 00 | 031 |████████████████ | 01 | 038 |████████████████████ | 02 | 046 |█████████████████████████ | 03 | 036 |███████████████████ | 04 | 036 |███████████████████ | 05 | 037 |████████████████████ | 06 | 043 |███████████████████████ | 07 | 033 |█████████████████ | ------------------------------------- offset 37 {5,9,31} 0 uint(0000002128285277163)+0 =2276465643 733337733773377337737737733373 1 uint(0000002128285277190)+1 =2276465671 333773773777333377337737337733 2 uint(0000002128285277215)+2 =2276465697 773337737337773773733373337377 3 uint(0000002128285277242)+3 =2276465725 777373377337377333733333733777 4 uint(0000002128285277267)+4 =2276465751 337733337733773733773377377337 5 uint(0000002128285277293)+5 =2276465778 733773377373377333377333733333 6 uint(0000002128285277321)+6 =2276465807 337777337733337773773773773337 7 uint(0000002128285277348)+7 =2276465835 333377773377337377337733733733 8 uint(0000002128285277373)+8 =2276465861 737337773737773377373377337777 9 uint(0000002128285277400)+9 =2276465889 773333377337777337733737733773 ## | xorshift chars | 00 | █▄▄▄▄██▄▄██▄▄██▄▄██▄██▄██▄▄▄█▄ | 01 | ▄▄▄██▄██▄███▄▄▄▄██▄▄██▄█▄▄██▄▄ | 02 | ██▄▄▄██▄█▄▄███▄██▄█▄▄▄█▄▄▄█▄██ | 03 | ███▄█▄▄██▄▄█▄██▄▄▄█▄▄▄▄▄█▄▄███ | 04 | ▄▄██▄▄▄▄██▄▄██▄█▄▄██▄▄██▄██▄▄█ | 05 | █▄▄██▄▄██▄█▄▄██▄▄▄▄██▄▄▄█▄▄▄▄▄ | 06 | ▄▄████▄▄██▄▄▄▄███▄██▄██▄██▄▄▄█ | 07 | ▄▄▄▄████▄▄██▄▄█▄██▄▄██▄▄█▄▄█▄▄ | 08 | █▄█▄▄███▄█▄███▄▄██▄█▄▄██▄▄████ | 09 | ██▄▄▄▄▄██▄▄████▄▄██▄▄█▄██▄▄██▄ | mt | 263 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 156 |█████████████████████████ | 04 | 000 | | 05 | 000 | | 06 | 000 | | 07 | 144 |███████████████████████ | ------------------------------------- offset 38 {5,13,6} 0 uint(0000002128285277494)+0 =2276465974 000000000000000000000000000000 1 uint(0000002128285277521)+1 =2276466002 000000000000000000000000000000 2 uint(0000002128285277548)+2 =2276466030 000000000000000000000000000000 3 uint(0000002128285277577)+3 =2276466060 000000000000000000000000000000 4 uint(0000002128285277602)+4 =2276466086 000000000000000000000000000000 5 uint(0000002128285277629)+5 =2276466114 000000000000000000000000000000 6 uint(0000002128285277655)+6 =2276466141 000000000000000000000000000000 7 uint(0000002128285277681)+7 =2276466168 000000000000000000000000000000 8 uint(0000002128285277706)+8 =2276466194 000000000000000000000000000000 9 uint(0000002128285277734)+9 =2276466223 000000000000000000000000000000 ## | xorshift chars | 00 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 01 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 02 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 03 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 04 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 05 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 06 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 07 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 08 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 09 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | mt | 266 μs | ch | ### | xorshift char count | 00 | 300 |█████████████████████████ | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 000 | | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 39 {5,15,17} 0 uint(0000002128285277808)+0 =2276466288 000000000011111111111111111111 1 uint(0000002128285277826)+1 =2276466307 111111111111111111111111111111 2 uint(0000002128285277844)+2 =2276466326 111111111111111111111111111111 3 uint(0000002128285277869)+3 =2276466352 111111111111111111111111111111 4 uint(0000002128285277896)+4 =2276466380 111111111111111111111111111111 5 uint(0000002128285277922)+5 =2276466407 111111111111111122222222222222 6 uint(0000002128285277948)+6 =2276466434 122222222222222222222222222222 7 uint(0000002128285277977)+7 =2276466464 222222222222222222222222222222 8 uint(0000002128285278007)+8 =2276466495 222222222222222222222222222222 9 uint(0000002128285278033)+9 =2276466522 222222222222222222222222233333 ## | xorshift chars | 00 | ▁▁▁▁▁▁▁▁▁▁▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 01 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 02 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 03 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 04 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 05 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▃▃▃▃▃▃▃▃▃▃▃▃▃▃ | 06 | ▂▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃ | 07 | ▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃ | 08 | ▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃ | 09 | ▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▄▄▄▄▄ | mt | 253 μs | ch | ### | xorshift char count | 00 | 010 |█ | 01 | 157 |█████████████████████████ | 02 | 128 |████████████████████ | 03 | 005 | | 04 | 000 | | 05 | 000 | | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 40 {5,17,13} 0 uint(0000002128285278128)+0 =2276466608 000000000000000000000000000000 1 uint(0000002128285278153)+1 =2276466634 000000000000000000000000000007 2 uint(0000002128285278180)+2 =2276466662 000000000000000777777777777777 3 uint(0000002128285278206)+3 =2276466689 077777777777777777777777777777 4 uint(0000002128285278233)+4 =2276466717 777777777777777777777777777777 5 uint(0000002128285278259)+5 =2276466744 777777777777777777777777777777 6 uint(0000002128285278285)+6 =2276466771 777777777777777777777777777777 7 uint(0000002128285278312)+7 =2276466799 777777777777777777777777777777 8 uint(0000002128285278338)+8 =2276466826 777777777777777777777777777777 9 uint(0000002128285278364)+9 =2276466853 777777777777777777777777777777 ## | xorshift chars | 00 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 01 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ | 02 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███████████████ | 03 | ▁█████████████████████████████ | 04 | ██████████████████████████████ | 05 | ██████████████████████████████ | 06 | ██████████████████████████████ | 07 | ██████████████████████████████ | 08 | ██████████████████████████████ | 09 | ██████████████████████████████ | mt | 263 μs | ch | ### | xorshift char count | 00 | 075 |████████ | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 000 | | 06 | 000 | | 07 | 225 |█████████████████████████ | ------------------------------------- offset 41 {5,21,12} 0 uint(0000002128285278449)+0 =2276466929 111111111111111111111111111111 1 uint(0000002128285278475)+1 =2276466956 111111111111111111111111111111 2 uint(0000002128285278502)+2 =2276466984 111111111111111111111111111111 3 uint(0000002128285278527)+3 =2276467010 111111111111111111111111111111 4 uint(0000002128285278553)+4 =2276467037 111111111111111111111111111111 5 uint(0000002128285278581)+5 =2276467066 111111111111111111111111111111 6 uint(0000002128285278606)+6 =2276467092 111111111111111111111111111111 7 uint(0000002128285278632)+7 =2276467119 111111111111111111111111111111 8 uint(0000002128285278658)+8 =2276467146 111111111111111111111111111111 9 uint(0000002128285278683)+9 =2276467172 111111111111111111111111111111 ## | xorshift chars | 00 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 01 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 02 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 03 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 04 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 05 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 06 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 07 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 08 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 09 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | mt | 261 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 300 |█████████████████████████ | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 000 | | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 42 {5,27,8} 0 uint(0000002128285278762)+0 =2276467242 666666666666666666666666666666 1 uint(0000002128285278789)+1 =2276467270 666666666666666666666666666666 2 uint(0000002128285278815)+2 =2276467297 666666666666666666666666666666 3 uint(0000002128285278842)+3 =2276467325 666666666666666666666666666666 4 uint(0000002128285278866)+4 =2276467350 666666666666666666666666666666 5 uint(0000002128285278893)+5 =2276467378 666666666666666666666666666666 6 uint(0000002128285278919)+6 =2276467405 666666666666666666666666666666 7 uint(0000002128285278945)+7 =2276467432 666666666666666666666666666666 8 uint(0000002128285278971)+8 =2276467459 666666666666666666666666666666 9 uint(0000002128285278998)+9 =2276467487 666666666666666666666666666666 ## | xorshift chars | 00 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 01 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 02 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 03 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 04 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 05 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 06 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 07 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 08 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 09 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | mt | 268 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 000 | | 06 | 300 |█████████████████████████ | 07 | 000 | | ------------------------------------- offset 43 {5,27,21} 0 uint(0000002128285279082)+0 =2276467562 555666677770000011112222333333 1 uint(0000002128285279108)+1 =2276467589 001111222233333444445555666667 2 uint(0000002128285279135)+2 =2276467617 344444555566667777700001111222 3 uint(0000002128285279160)+3 =2276467643 777700001111122223333444445555 4 uint(0000002128285279186)+4 =2276467670 222333334444555566666777777776 5 uint(0000002128285279213)+5 =2276467698 556666777777777666655555444433 6 uint(0000002128285279238)+6 =2276467724 666665555444433333222211110007 7 uint(0000002128285279268)+7 =2276467755 322222111100007777766665555544 8 uint(0000002128285279295)+8 =2276467783 777766666555554444333322222111 9 uint(0000002128285279321)+9 =2276467810 444333332222111100000777766665 ## | xorshift chars | 00 | ▆▆▆▇▇▇▇████▁▁▁▁▁▂▂▂▂▃▃▃▃▄▄▄▄▄▄ | 01 | ▁▁▂▂▂▂▃▃▃▃▄▄▄▄▄▅▅▅▅▅▆▆▆▆▇▇▇▇▇█ | 02 | ▄▅▅▅▅▅▆▆▆▆▇▇▇▇█████▁▁▁▁▂▂▂▂▃▃▃ | 03 | ████▁▁▁▁▂▂▂▂▂▃▃▃▃▄▄▄▄▅▅▅▅▅▆▆▆▆ | 04 | ▃▃▃▄▄▄▄▄▅▅▅▅▆▆▆▆▇▇▇▇▇████████▇ | 05 | ▆▆▇▇▇▇█████████▇▇▇▇▆▆▆▆▆▅▅▅▅▄▄ | 06 | ▇▇▇▇▇▆▆▆▆▅▅▅▅▄▄▄▄▄▃▃▃▃▂▂▂▂▁▁▁█ | 07 | ▄▃▃▃▃▃▂▂▂▂▁▁▁▁█████▇▇▇▇▆▆▆▆▆▅▅ | 08 | ████▇▇▇▇▇▆▆▆▆▆▅▅▅▅▄▄▄▄▃▃▃▃▃▂▂▂ | 09 | ▅▅▅▄▄▄▄▄▃▃▃▃▂▂▂▂▁▁▁▁▁████▇▇▇▇▆ | mt | 266 μs | ch | ### | xorshift char count | 00 | 027 |███████████████ | 01 | 032 |█████████████████ | 02 | 036 |████████████████████ | 03 | 038 |█████████████████████ | 04 | 036 |████████████████████ | 05 | 041 |██████████████████████ | 06 | 045 |█████████████████████████ | 07 | 045 |█████████████████████████ | ------------------------------------- offset 44 {5,27,25} 0 uint(0000002128285279495)+0 =2276467975 375172406204613715371572046240 1 uint(0000002128285279520)+1 =2276468001 515735172404640265351737562040 2 uint(0000002128285279548)+2 =2276468030 267375137516204620405133513710 3 uint(0000002128285279574)+3 =2276468057 062005137351714026462603157315 4 uint(0000002128285279599)+4 =2276468083 464046243153755375062606204313 5 uint(0000002128285279625)+5 =2276468110 715262046204153715735062404647 6 uint(0000002128285279652)+6 =2276468138 353715020462604617315331426442 7 uint(0000002128285279678)+7 =2276468165 677517311620422042577157354624 8 uint(0000002128285279704)+8 =2276468192 062071537157364624046273153715 9 uint(0000002128285279731)+9 =2276468220 264026035173157204260426437573 ## | xorshift chars | 00 | ▄█▆▂█▃▅▁▇▃▁▅▇▂▄█▂▆▄█▂▆█▃▁▅▇▃▅▁ | 01 | ▆▂▆█▄▆▂█▃▅▁▅▇▅▁▃▇▆▄▆▂█▄█▆▇▃▁▅▁ | 02 | ▃▇█▄█▆▂▄█▆▂▇▃▁▅▇▃▁▅▁▆▂▄▄▆▂▄█▂▁ | 03 | ▁▇▃▁▁▆▂▄█▄▆▂█▂▅▁▃▇▅▇▃▇▁▄▂▆█▄▂▆ | 04 | ▅▇▅▁▅▇▃▅▄▂▆▄█▆▆▄█▆▁▇▃▇▁▇▃▁▅▄▂▄ | 05 | █▂▆▃▇▃▁▅▇▃▁▅▂▆▄█▂▆█▄▆▁▇▃▅▁▅▇▅█ | 06 | ▄▆▄█▂▆▁▃▁▅▇▃▇▁▅▇▂█▄▂▆▄▄▂▅▃▇▅▅▃ | 07 | ▇██▆▂█▄▂▂▇▃▁▅▃▃▁▅▃▆██▂▆█▄▆▅▇▃▅ | 08 | ▁▇▃▁█▂▆▄█▂▆█▄▇▅▇▃▅▁▅▇▃█▄▂▆▄█▂▆ | 09 | ▃▇▅▁▃▇▁▄▆▂█▄▂▆█▃▁▅▃▇▁▅▃▇▅▄█▆█▄ | mt | 262 μs | ch | ### | xorshift char count | 00 | 037 |███████████████████████ | 01 | 036 |███████████████████████ | 02 | 037 |███████████████████████ | 03 | 037 |███████████████████████ | 04 | 038 |████████████████████████ | 05 | 039 |█████████████████████████ | 06 | 037 |███████████████████████ | 07 | 039 |█████████████████████████ | ------------------------------------- offset 45 {5,27,28} 0 uint(0000002128285279922)+0 =2276468402 567012334577012334677012345667 1 uint(0000002128285279949)+1 =2276468430 234566712234567011245567012344 2 uint(0000002128285279974)+2 =2276468456 001234567001244567012334567012 3 uint(0000002128285280002)+3 =2276468485 560112347702334567701344567012 4 uint(0000002128285280032)+4 =2276468516 467701234567701334566712234567 5 uint(0000002128285280059)+5 =2276468544 223456701223567001234567701234 6 uint(0000002128285280085)+6 =2276468571 770124456771233456701223456601 7 uint(0000002128285280110)+7 =2276468597 345670112455670123445670123445 8 uint(0000002128285280137)+8 =2276468625 012344670012445677123345770122 9 uint(0000002128285280162)+9 =2276468651 667012345667112345670012445670 ## | xorshift chars | 00 | ▆▇█▁▂▃▄▄▅▆██▁▂▃▄▄▅▇██▁▂▃▄▅▆▇▇█ | 01 | ▃▄▅▆▇▇█▂▃▃▄▅▆▇█▁▂▂▃▅▆▆▇█▁▂▃▄▅▅ | 02 | ▁▁▂▃▄▅▆▇█▁▁▂▃▅▅▆▇█▁▂▃▄▄▅▆▇█▁▂▃ | 03 | ▆▇▁▂▂▃▄▅██▁▃▄▄▅▆▇██▁▂▄▅▅▆▇█▁▂▃ | 04 | ▅▇██▁▂▃▄▅▆▇██▁▂▄▄▅▆▇▇█▂▃▃▄▅▆▇█ | 05 | ▃▃▄▅▆▇█▁▂▃▃▄▆▇█▁▁▂▃▄▅▆▇██▁▂▃▄▅ | 06 | ██▁▂▃▅▅▆▇██▂▃▄▄▅▆▇█▁▂▃▃▄▅▆▇▇▁▂ | 07 | ▄▅▆▇█▁▂▂▃▅▆▆▇█▁▂▃▄▅▅▆▇█▁▂▃▄▅▅▆ | 08 | ▁▂▃▄▅▅▇█▁▁▂▃▅▅▆▇██▂▃▄▄▅▆██▁▂▃▃ | 09 | ▇▇█▁▂▃▄▅▆▇▇█▂▂▃▄▅▆▇█▁▁▂▃▅▅▆▇█▁ | mt | 267 μs | ch | ### | xorshift char count | 00 | 035 |███████████████████ | 01 | 037 |█████████████████████ | 02 | 039 |██████████████████████ | 03 | 034 |███████████████████ | 04 | 042 |███████████████████████ | 05 | 032 |██████████████████ | 06 | 037 |█████████████████████ | 07 | 044 |█████████████████████████ | ------------------------------------- offset 46 {6,1,11} 0 uint(0000002128285280319)+0 =2276468799 333333333333333333333333333333 1 uint(0000002128285280346)+1 =2276468827 333333333333333333333333333333 2 uint(0000002128285280371)+2 =2276468853 333333333333333333333333333333 3 uint(0000002128285280397)+3 =2276468880 333333333333333333333333333333 4 uint(0000002128285280423)+4 =2276468907 333333333333333333333333333333 5 uint(0000002128285280449)+5 =2276468934 333333333333333333333333333333 6 uint(0000002128285280475)+6 =2276468961 333333333333333333333333333333 7 uint(0000002128285280501)+7 =2276468988 333333333333333333333333333333 8 uint(0000002128285280529)+8 =2276469017 333333333333333333333333333333 9 uint(0000002128285280554)+9 =2276469043 333333333333333333333333333333 ## | xorshift chars | 00 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 01 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 02 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 03 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 04 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 05 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 06 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 07 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 08 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 09 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | mt | 260 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 300 |█████████████████████████ | 04 | 000 | | 05 | 000 | | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 47 {6,3,17} 0 uint(0000002128285280630)+0 =2276469110 000003333333333333333333333333 1 uint(0000002128285280656)+1 =2276469137 333333333333333333333333332222 2 uint(0000002128285280682)+2 =2276469164 333333333333222222222222222222 3 uint(0000002128285280709)+3 =2276469192 222222222222222222222222222222 4 uint(0000002128285280735)+4 =2276469219 222222222222222222444444444444 5 uint(0000002128285280761)+5 =2276469246 222244444444444444444444444444 6 uint(0000002128285280786)+6 =2276469272 444444444444444444444444555555 7 uint(0000002128285280814)+7 =2276469301 444444444455555555555555555555 8 uint(0000002128285280838)+8 =2276469326 555555555555555555555555555555 9 uint(0000002128285280865)+9 =2276469354 555555555555555556666666666666 ## | xorshift chars | 00 | ▁▁▁▁▁▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 01 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▃▃▃▃ | 02 | ▄▄▄▄▄▄▄▄▄▄▄▄▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃ | 03 | ▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃ | 04 | ▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▅▅▅▅▅▅▅▅▅▅▅▅ | 05 | ▃▃▃▃▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 06 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▆▆▆▆▆▆ | 07 | ▅▅▅▅▅▅▅▅▅▅▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 08 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 09 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▇▇▇▇▇▇▇▇▇▇▇▇▇ | mt | 261 μs | ch | ### | xorshift char count | 00 | 005 |█ | 01 | 000 | | 02 | 074 |█████████████████████████ | 03 | 063 |█████████████████████ | 04 | 072 |████████████████████████ | 05 | 073 |████████████████████████ | 06 | 013 |████ | 07 | 000 | | ------------------------------------- offset 48 {6,17,9} 0 uint(0000002128285280994)+0 =2276469474 000000000000000000000000000000 1 uint(0000002128285281028)+1 =2276469509 000000000000000000000000000000 2 uint(0000002128285281051)+2 =2276469533 000000000000000000000000000000 3 uint(0000002128285281077)+3 =2276469560 000000000000000000000000000000 4 uint(0000002128285281102)+4 =2276469586 000000000000000000000000000000 5 uint(0000002128285281127)+5 =2276469612 000000000000000000000000000000 6 uint(0000002128285281152)+6 =2276469638 000000000000000000000000000000 7 uint(0000002128285281177)+7 =2276469664 000000000000000000000000000000 8 uint(0000002128285281202)+8 =2276469690 000000000000000000000000000000 9 uint(0000002128285281227)+9 =2276469716 000000000000000000000000000000 ## | xorshift chars | 00 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 01 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 02 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 03 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 04 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 05 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 06 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 07 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 08 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 09 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | mt | 258 μs | ch | ### | xorshift char count | 00 | 300 |█████████████████████████ | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 000 | | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 49 {6,21,7} 0 uint(0000002128285281303)+0 =2276469783 555555555555555555555555555555 1 uint(0000002128285281330)+1 =2276469811 555555555555555555555555555555 2 uint(0000002128285281355)+2 =2276469837 555555555555555555555555555555 3 uint(0000002128285281380)+3 =2276469863 555555555555555555555555555555 4 uint(0000002128285281405)+4 =2276469889 555555555555555555555555555555 5 uint(0000002128285281430)+5 =2276469915 555555555555555555555555555555 6 uint(0000002128285281454)+6 =2276469940 555555555555555555555555555555 7 uint(0000002128285281479)+7 =2276469966 555555555555555555555555555555 8 uint(0000002128285281504)+8 =2276469992 555555555555555555555555555555 9 uint(0000002128285281529)+9 =2276470018 555555555555555555555555555555 ## | xorshift chars | 00 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 01 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 02 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 03 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 04 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 05 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 06 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 07 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 08 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | 09 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ | mt | 251 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 300 |█████████████████████████ | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 50 {6,21,13} 0 uint(0000002128285281604)+0 =2276470084 000000000000000000000000000000 1 uint(0000002128285281629)+1 =2276470110 000000000000000000000000000000 2 uint(0000002128285281654)+2 =2276470136 000000000000000000000000000000 3 uint(0000002128285281678)+3 =2276470161 000000000000000000000000000000 4 uint(0000002128285281705)+4 =2276470189 000000000000000000000000000000 5 uint(0000002128285281730)+5 =2276470215 000000000000000000000000000000 6 uint(0000002128285281754)+6 =2276470240 000000000000000000000000000000 7 uint(0000002128285281779)+7 =2276470266 000000000000000000000000000000 8 uint(0000002128285281806)+8 =2276470294 000000000000000000000000000000 9 uint(0000002128285281831)+9 =2276470320 000000000000000000000000000000 ## | xorshift chars | 00 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 01 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 02 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 03 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 04 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 05 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 06 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 07 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 08 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | 09 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | mt | 251 μs | ch | ### | xorshift char count | 00 | 300 |█████████████████████████ | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 000 | | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 51 {7,1,9} 0 uint(0000002128285281905)+0 =2276470385 444444444444444444444444444444 1 uint(0000002128285281931)+1 =2276470412 444444444444444444444444444444 2 uint(0000002128285281956)+2 =2276470438 444444444444444444444444444444 3 uint(0000002128285281981)+3 =2276470464 444444444444444444444444444444 4 uint(0000002128285282012)+4 =2276470496 444444444444444444444444444444 5 uint(0000002128285282036)+5 =2276470521 444444444444444444444444444444 6 uint(0000002128285282062)+6 =2276470548 444444444444444444444444444444 7 uint(0000002128285282088)+7 =2276470575 444444444444444444444444444444 8 uint(0000002128285282115)+8 =2276470603 444444444444444444444444444444 9 uint(0000002128285282140)+9 =2276470629 444444444444444444444444444444 ## | xorshift chars | 00 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 01 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 02 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 03 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 04 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 05 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 06 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 07 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 08 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 09 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | mt | 259 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 300 |█████████████████████████ | 05 | 000 | | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 52 {7,1,18} 0 uint(0000002128285282213)+0 =2276470693 333332222222222666666666777777 1 uint(0000002128285282239)+1 =2276470720 266666666677777777755555555444 2 uint(0000002128285282263)+2 =2276470745 777755555555544444444466666666 3 uint(0000002128285282288)+3 =2276470771 444444446666666667777777775555 4 uint(0000002128285282315)+4 =2276470799 666777777777775555555555444444 5 uint(0000002128285282332)+5 =2276470817 775555555555544444444440000000 6 uint(0000002128285282350)+6 =2276470836 544444444444000000000111111111 7 uint(0000002128285282371)+7 =2276470858 000000011111111333333333222222 8 uint(0000002128285282398)+8 =2276470886 133333333322222222222222222233 9 uint(0000002128285282423)+9 =2276470912 222222222222223333333331111111 ## | xorshift chars | 00 | ▄▄▄▄▄▃▃▃▃▃▃▃▃▃▃▇▇▇▇▇▇▇▇▇██████ | 01 | ▃▇▇▇▇▇▇▇▇▇█████████▆▆▆▆▆▆▆▆▅▅▅ | 02 | ████▆▆▆▆▆▆▆▆▆▅▅▅▅▅▅▅▅▅▇▇▇▇▇▇▇▇ | 03 | ▅▅▅▅▅▅▅▅▇▇▇▇▇▇▇▇▇█████████▆▆▆▆ | 04 | ▇▇▇███████████▆▆▆▆▆▆▆▆▆▆▅▅▅▅▅▅ | 05 | ██▆▆▆▆▆▆▆▆▆▆▆▅▅▅▅▅▅▅▅▅▅▁▁▁▁▁▁▁ | 06 | ▆▅▅▅▅▅▅▅▅▅▅▅▁▁▁▁▁▁▁▁▁▂▂▂▂▂▂▂▂▂ | 07 | ▁▁▁▁▁▁▁▂▂▂▂▂▂▂▂▄▄▄▄▄▄▄▄▄▃▃▃▃▃▃ | 08 | ▂▄▄▄▄▄▄▄▄▄▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▄▄ | 09 | ▃▃▃▃▃▃▃▃▃▃▃▃▃▃▄▄▄▄▄▄▄▄▄▂▂▂▂▂▂▂ | mt | 235 μs | ch | ### | xorshift char count | 00 | 023 |███████████ | 01 | 025 |████████████ | 02 | 049 |█████████████████████████ | 03 | 034 |█████████████████ | 04 | 047 |███████████████████████ | 05 | 043 |█████████████████████ | 06 | 038 |███████████████████ | 07 | 041 |████████████████████ | ------------------------------------- offset 53 {7,1,25} 0 uint(0000002128285282583)+0 =2276471063 266204400440045515511151555155 1 uint(0000002128285282608)+1 =2276471089 515551155551151114404440046226 2 uint(0000002128285282634)+2 =2276471116 154004440440226222662377337733 3 uint(0000002128285282659)+3 =2276471142 226662277337733773377737662266 4 uint(0000002128285282686)+4 =2276471170 773377337732662266620440044001 5 uint(0000002128285282710)+5 =2276471195 226620440004005551551111155115 6 uint(0000002128285282735)+6 =2276471221 511551151551115510440044004622 7 uint(0000002128285282760)+7 =2276471247 111540044004422662266637733377 8 uint(0000002128285282785)+8 =2276471273 662266637773373337737773376226 9 uint(0000002128285282811)+9 =2276471300 377337773376226662660004004441 ## | xorshift chars | 00 | ▃▇▇▃▁▅▅▁▁▅▅▁▁▅▆▆▂▆▆▂▂▂▆▂▆▆▆▂▆▆ | 01 | ▆▂▆▆▆▂▂▆▆▆▆▂▂▆▂▂▂▅▅▁▅▅▅▁▁▅▇▃▃▇ | 02 | ▂▆▅▁▁▅▅▅▁▅▅▁▃▃▇▃▃▃▇▇▃▄██▄▄██▄▄ | 03 | ▃▃▇▇▇▃▃██▄▄██▄▄██▄▄███▄█▇▇▃▃▇▇ | 04 | ██▄▄██▄▄██▄▃▇▇▃▃▇▇▇▃▁▅▅▁▁▅▅▁▁▂ | 05 | ▃▃▇▇▃▁▅▅▁▁▁▅▁▁▆▆▆▂▆▆▂▂▂▂▂▆▆▂▂▆ | 06 | ▆▂▂▆▆▂▂▆▂▆▆▂▂▂▆▆▂▁▅▅▁▁▅▅▁▁▅▇▃▃ | 07 | ▂▂▂▆▅▁▁▅▅▁▁▅▅▃▃▇▇▃▃▇▇▇▄██▄▄▄██ | 08 | ▇▇▃▃▇▇▇▄███▄▄█▄▄▄██▄███▄▄█▇▃▃▇ | 09 | ▄██▄▄███▄▄█▇▃▃▇▇▇▃▇▇▁▁▁▅▁▁▅▅▅▂ | mt | 253 μs | ch | ### | xorshift char count | 00 | 037 |███████████████████████ | 01 | 037 |███████████████████████ | 02 | 036 |██████████████████████ | 03 | 035 |█████████████████████ | 04 | 038 |███████████████████████ | 05 | 037 |███████████████████████ | 06 | 040 |█████████████████████████ | 07 | 040 |█████████████████████████ | ------------------------------------- offset 54 {7,13,25} 0 uint(0000002128285282995)+0 =2276471475 555552222222233333333300000000 1 uint(0000002128285283026)+1 =2276471507 333333300000000011111111166666 2 uint(0000002128285283053)+2 =2276471535 001111111166666666677777777744 3 uint(0000002128285283077)+3 =2276471560 666666777777777444444444555555 4 uint(0000002128285283102)+4 =2276471586 444444444555555555222222222333 5 uint(0000002128285283129)+5 =2276471614 555522222222233333333300000000 6 uint(0000002128285283154)+6 =2276471640 333333330000000001111111116666 7 uint(0000002128285283179)+7 =2276471666 001111111116666666667777777774 8 uint(0000002128285283204)+8 =2276471692 666666777777777744444444455555 9 uint(0000002128285283229)+9 =2276471718 774444444455555555522222222233 ## | xorshift chars | 00 | ▆▆▆▆▆▃▃▃▃▃▃▃▃▄▄▄▄▄▄▄▄▄▁▁▁▁▁▁▁▁ | 01 | ▄▄▄▄▄▄▄▁▁▁▁▁▁▁▁▁▂▂▂▂▂▂▂▂▂▇▇▇▇▇ | 02 | ▁▁▂▂▂▂▂▂▂▂▇▇▇▇▇▇▇▇▇█████████▅▅ | 03 | ▇▇▇▇▇▇█████████▅▅▅▅▅▅▅▅▅▆▆▆▆▆▆ | 04 | ▅▅▅▅▅▅▅▅▅▆▆▆▆▆▆▆▆▆▃▃▃▃▃▃▃▃▃▄▄▄ | 05 | ▆▆▆▆▃▃▃▃▃▃▃▃▃▄▄▄▄▄▄▄▄▄▁▁▁▁▁▁▁▁ | 06 | ▄▄▄▄▄▄▄▄▁▁▁▁▁▁▁▁▁▂▂▂▂▂▂▂▂▂▇▇▇▇ | 07 | ▁▁▂▂▂▂▂▂▂▂▂▇▇▇▇▇▇▇▇▇█████████▅ | 08 | ▇▇▇▇▇▇██████████▅▅▅▅▅▅▅▅▅▆▆▆▆▆ | 09 | ██▅▅▅▅▅▅▅▅▆▆▆▆▆▆▆▆▆▃▃▃▃▃▃▃▃▃▄▄ | mt | 259 μs | ch | ### | xorshift char count | 00 | 038 |████████████████████████ | 01 | 035 |██████████████████████ | 02 | 035 |██████████████████████ | 03 | 038 |████████████████████████ | 04 | 038 |████████████████████████ | 05 | 038 |████████████████████████ | 06 | 039 |█████████████████████████ | 07 | 039 |█████████████████████████ | ------------------------------------- offset 55 {7,17,21} 0 uint(0000002128285283417)+0 =2276471897 476110355476613225476613225477 1 uint(0000002128285283443)+1 =2276471924 332577610335477610025447610025 2 uint(0000002128285283468)+2 =2276471950 761032554761032554711032254661 3 uint(0000002128285283493)+3 =2276471976 224766103354776103324776103354 4 uint(0000002128285283518)+4 =2276472002 610325447610325547110325546110 5 uint(0000002128285283543)+5 =2276472028 557661032547661022547760223456 6 uint(0000002128285283568)+6 =2276472054 033254470112345670112355670013 7 uint(0000002128285283594)+7 =2276472081 567012334567012334567012234567 8 uint(0000002128285283619)+8 =2276472107 223566701224556701224556701234 9 uint(0000002128285283644)+9 =2276472133 601123456700123456700134456770 ## | xorshift chars | 00 | ▅█▇▂▂▁▄▆▆▅█▇▇▂▄▃▃▆▅█▇▇▂▄▃▃▆▅██ | 01 | ▄▄▃▆██▇▂▁▄▄▆▅██▇▂▁▁▃▆▅▅█▇▂▁▁▃▆ | 02 | █▇▂▁▄▃▆▆▅█▇▂▁▄▃▆▆▅█▂▂▁▄▃▃▆▅▇▇▂ | 03 | ▃▃▅█▇▇▂▁▄▄▆▅██▇▂▁▄▄▃▅██▇▂▁▄▄▆▅ | 04 | ▇▂▁▄▃▆▅▅█▇▂▁▄▃▆▆▅█▂▂▁▄▃▆▆▅▇▂▂▁ | 05 | ▆▆█▇▇▂▁▄▃▆▅█▇▇▂▁▃▃▆▅██▇▁▃▃▄▅▆▇ | 06 | ▁▄▄▃▆▅▅█▁▂▂▃▄▅▆▇█▁▂▂▃▄▆▆▇█▁▁▂▄ | 07 | ▆▇█▁▂▃▄▄▅▆▇█▁▂▃▄▄▅▆▇█▁▂▃▃▄▅▆▇█ | 08 | ▃▃▄▆▇▇█▁▂▃▃▅▆▆▇█▁▂▃▃▅▆▆▇█▁▂▃▄▅ | 09 | ▇▁▂▂▃▄▅▆▇█▁▁▂▃▄▅▆▇█▁▁▂▄▅▅▆▇██▁ | mt | 254 μs | ch | ### | xorshift char count | 00 | 036 |█████████████████████ | 01 | 038 |███████████████████████ | 02 | 038 |███████████████████████ | 03 | 036 |█████████████████████ | 04 | 034 |████████████████████ | 05 | 041 |█████████████████████████ | 06 | 039 |███████████████████████ | 07 | 038 |███████████████████████ | ------------------------------------- offset 56 {7,25,12} 0 uint(0000002128285283827)+0 =2276472307 777777777777777777777777777777 1 uint(0000002128285283852)+1 =2276472333 777777777777777777777777777777 2 uint(0000002128285283877)+2 =2276472359 777777777777777777777777777777 3 uint(0000002128285283902)+3 =2276472385 777777777777777777777777777777 4 uint(0000002128285283926)+4 =2276472410 777777777777777777777777777777 5 uint(0000002128285283951)+5 =2276472436 777777777777777777777777777777 6 uint(0000002128285283977)+6 =2276472463 777777777777777777777777777777 7 uint(0000002128285284005)+7 =2276472492 777777777777777777777777777777 8 uint(0000002128285284033)+8 =2276472521 777777777777777777777777777777 9 uint(0000002128285284058)+9 =2276472547 777777777777777777777777777777 ## | xorshift chars | 00 | ██████████████████████████████ | 01 | ██████████████████████████████ | 02 | ██████████████████████████████ | 03 | ██████████████████████████████ | 04 | ██████████████████████████████ | 05 | ██████████████████████████████ | 06 | ██████████████████████████████ | 07 | ██████████████████████████████ | 08 | ██████████████████████████████ | 09 | ██████████████████████████████ | mt | 256 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 000 | | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 000 | | 06 | 000 | | 07 | 300 |█████████████████████████ | ------------------------------------- offset 57 {7,25,20} 0 uint(0000002128285284133)+0 =2276472613 333222554477666110033222544477 1 uint(0000002128285284159)+1 =2276472640 110003322554447666111033322554 2 uint(0000002128285284185)+2 =2276472667 776611003332255447776611000332 3 uint(0000002128285284210)+3 =2276472693 544476661100032225544776661100 4 uint(0000002128285284235)+4 =2276472719 322554477766110033325554477761 5 uint(0000002128285284260)+5 =2276472745 003322555447766611003322255447 6 uint(0000002128285284285)+6 =2276472771 661000332255444776611100332255 7 uint(0000002128285284310)+7 =2276472797 477661110033225554777666677744 8 uint(0000002128285284335)+8 =2276472823 554447766667774455223330111666 9 uint(0000002128285284360)+9 =2276472849 445522230001166774445522330001 ## | xorshift chars | 00 | ▄▄▄▃▃▃▆▆▅▅██▇▇▇▂▂▁▁▄▄▃▃▃▆▅▅▅██ | 01 | ▂▂▁▁▁▄▄▃▃▆▆▅▅▅█▇▇▇▂▂▂▁▄▄▄▃▃▆▆▅ | 02 | ██▇▇▂▂▁▁▄▄▄▃▃▆▆▅▅███▇▇▂▂▁▁▁▄▄▃ | 03 | ▆▅▅▅█▇▇▇▂▂▁▁▁▄▃▃▃▆▆▅▅██▇▇▇▂▂▁▁ | 04 | ▄▃▃▆▆▅▅███▇▇▂▂▁▁▄▄▄▃▆▆▆▅▅███▇▂ | 05 | ▁▁▄▄▃▃▆▆▆▅▅██▇▇▇▂▂▁▁▄▄▃▃▃▆▆▅▅█ | 06 | ▇▇▂▁▁▁▄▄▃▃▆▆▅▅▅██▇▇▂▂▂▁▁▄▄▃▃▆▆ | 07 | ▅██▇▇▂▂▂▁▁▄▄▃▃▆▆▆▅███▇▇▇▇███▅▅ | 08 | ▆▆▅▅▅██▇▇▇▇███▅▅▆▆▃▃▄▄▄▁▂▂▂▇▇▇ | 09 | ▅▅▆▆▃▃▃▄▁▁▁▂▂▇▇██▅▅▅▆▆▃▃▄▄▁▁▁▂ | mt | 251 μs | ch | ### | xorshift char count | 00 | 036 |█████████████████████ | 01 | 033 |████████████████████ | 02 | 037 |██████████████████████ | 03 | 036 |█████████████████████ | 04 | 041 |█████████████████████████ | 05 | 037 |██████████████████████ | 06 | 041 |█████████████████████████ | 07 | 039 |███████████████████████ | ------------------------------------- offset 58 {8,7,23} 0 uint(0000002128285284539)+0 =2276473019 731551155115511151154404400044 1 uint(0000002128285284566)+1 =2276473047 551154004440440004400440044404 2 uint(0000002128285284590)+2 =2276473072 004400444004400440044004440551 3 uint(0000002128285284616)+3 =2276473099 440044004400451155115551555115 4 uint(0000002128285284640)+4 =2276473124 155115511551115117773377337773 5 uint(0000002128285284665)+5 =2276473150 111773377337733373377622662266 6 uint(0000002128285284690)+6 =2276473176 773377736622266226622666222666 7 uint(0000002128285284715)+7 =2276473202 266622662262666266222662266226 8 uint(0000002128285284740)+8 =2276473228 266222622666226733773337337773 9 uint(0000002128285284766)+9 =2276473255 633773377337733377355511555155 ## | xorshift chars | 00 | █▄▂▆▆▂▂▆▆▂▂▆▆▂▂▂▆▂▂▆▅▅▁▅▅▁▁▁▅▅ | 01 | ▆▆▂▂▆▅▁▁▅▅▅▁▅▅▁▁▁▅▅▁▁▅▅▁▁▅▅▅▁▅ | 02 | ▁▁▅▅▁▁▅▅▅▁▁▅▅▁▁▅▅▁▁▅▅▁▁▅▅▅▁▆▆▂ | 03 | ▅▅▁▁▅▅▁▁▅▅▁▁▅▆▂▂▆▆▂▂▆▆▆▂▆▆▆▂▂▆ | 04 | ▂▆▆▂▂▆▆▂▂▆▆▂▂▂▆▂▂███▄▄██▄▄███▄ | 05 | ▂▂▂██▄▄██▄▄██▄▄▄█▄▄██▇▃▃▇▇▃▃▇▇ | 06 | ██▄▄███▄▇▇▃▃▃▇▇▃▃▇▇▃▃▇▇▇▃▃▃▇▇▇ | 07 | ▃▇▇▇▃▃▇▇▃▃▇▃▇▇▇▃▇▇▃▃▃▇▇▃▃▇▇▃▃▇ | 08 | ▃▇▇▃▃▃▇▃▃▇▇▇▃▃▇█▄▄██▄▄▄█▄▄███▄ | 09 | ▇▄▄██▄▄██▄▄██▄▄▄██▄▆▆▆▂▂▆▆▆▂▆▆ | mt | 252 μs | ch | ### | xorshift char count | 00 | 034 |████████████████████ | 01 | 036 |█████████████████████ | 02 | 036 |█████████████████████ | 03 | 036 |█████████████████████ | 04 | 041 |█████████████████████████ | 05 | 038 |███████████████████████ | 06 | 041 |█████████████████████████ | 07 | 038 |███████████████████████ | ------------------------------------- offset 59 {8,9,23} 0 uint(0000002128285284933)+0 =2276473413 400040044400440044000400444004 1 uint(0000002128285284958)+1 =2276473439 044004440040004400062226622662 2 uint(0000002128285284983)+2 =2276473465 440462226626662266266622226666 3 uint(0000002128285285015)+3 =2276473498 662226226622266226622273377333 4 uint(0000002128285285040)+4 =2276473524 226622662377737733377377333733 5 uint(0000002128285285065)+5 =2276473550 733773377737773377737733377377 6 uint(0000002128285285090)+6 =2276473576 377337733373377737377733773377 7 uint(0000002128285285115)+7 =2276473602 733337733773377733733377337733 8 uint(0000002128285285140)+8 =2276473628 737733377337733773377333722266 9 uint(0000002128285285165)+9 =2276473654 773377737722266266622662266226 ## | xorshift chars | 00 | ▅▁▁▁▅▁▁▅▅▅▁▁▅▅▁▁▅▅▁▁▁▅▁▁▅▅▅▁▁▅ | 01 | ▁▅▅▁▁▅▅▅▁▁▅▁▁▁▅▅▁▁▁▇▃▃▃▇▇▃▃▇▇▃ | 02 | ▅▅▁▅▇▃▃▃▇▇▃▇▇▇▃▃▇▇▃▇▇▇▃▃▃▃▇▇▇▇ | 03 | ▇▇▃▃▃▇▃▃▇▇▃▃▃▇▇▃▃▇▇▃▃▃█▄▄██▄▄▄ | 04 | ▃▃▇▇▃▃▇▇▃▄███▄██▄▄▄██▄██▄▄▄█▄▄ | 05 | █▄▄██▄▄███▄███▄▄███▄██▄▄▄██▄██ | 06 | ▄██▄▄██▄▄▄█▄▄███▄█▄███▄▄██▄▄██ | 07 | █▄▄▄▄██▄▄██▄▄███▄▄█▄▄▄██▄▄██▄▄ | 08 | █▄██▄▄▄██▄▄██▄▄██▄▄██▄▄▄█▃▃▃▇▇ | 09 | ██▄▄███▄██▃▃▃▇▇▃▇▇▇▃▃▇▇▃▃▇▇▃▃▇ | mt | 257 μs | ch | ### | xorshift char count | 00 | 028 |████████ | 01 | 000 | | 02 | 048 |███████████████ | 03 | 075 |███████████████████████ | 04 | 025 |███████ | 05 | 000 | | 06 | 045 |██████████████ | 07 | 079 |█████████████████████████ | ------------------------------------- offset 60 {9,5,1} 0 uint(0000002128285285291)+0 =2276473771 111111111111111111111111111111 1 uint(0000002128285285316)+1 =2276473797 111111111111111111111111111111 2 uint(0000002128285285340)+2 =2276473822 111111111111111111111111111111 3 uint(0000002128285285367)+3 =2276473850 111111111111111111111111111111 4 uint(0000002128285285391)+4 =2276473875 111111111111111111111111111111 5 uint(0000002128285285416)+5 =2276473901 111111111111111111111111111111 6 uint(0000002128285285441)+6 =2276473927 111111111111111111111111111111 7 uint(0000002128285285466)+7 =2276473953 111111111111111111111111111111 8 uint(0000002128285285492)+8 =2276473980 111111111111111111111111111111 9 uint(0000002128285285517)+9 =2276474006 111111111111111111111111111111 ## | xorshift chars | 00 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 01 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 02 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 03 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 04 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 05 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 06 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 07 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 08 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 09 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | mt | 250 μs | ch | ### | xorshift char count | 00 | 000 | | 01 | 300 |█████████████████████████ | 02 | 000 | | 03 | 000 | | 04 | 000 | | 05 | 000 | | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 61 {9,5,25} 0 uint(0000002128285285590)+0 =2276474070 467127521764217530675010257105 1 uint(0000002128285285616)+1 =2276474097 752175201057603541245702573106 2 uint(0000002128285285641)+2 =2276474123 247023560356320652075231643164 3 uint(0000002128285285666)+3 =2276474149 054217543645306757102571246713 4 uint(0000002128285285691)+4 =2276474175 745760357634571245027643104310 5 uint(0000002128285285715)+5 =2276474200 035602365206532042316453132471 6 uint(0000002128285285740)+6 =2276474226 167530675010257605761346724672 7 uint(0000002128285285765)+7 =2276474252 603546045702357106531062317423 8 uint(0000002128285285791)+8 =2276474279 320653265231642164546134613256 9 uint(0000002128285285816)+9 =2276474305 306457102471026013460375420752 ## | xorshift chars | 00 | ▅▇█▂▃█▆▃▂█▇▅▃▂█▆▄▁▇█▆▁▂▁▃▆█▂▁▆ | 01 | █▆▃▂█▆▃▁▂▁▆█▇▁▄▆▅▂▃▅▆█▁▃▆█▄▂▁▇ | 02 | ▃▅█▁▃▄▆▇▁▄▆▇▄▃▁▇▆▃▁█▆▃▄▂▇▅▄▂▇▅ | 03 | ▁▆▅▃▂█▆▅▄▇▅▆▄▁▇█▆█▂▁▃▆█▂▃▅▇█▂▄ | 04 | █▅▆█▇▁▄▆█▇▄▅▆█▂▃▅▆▁▃█▇▅▄▂▁▅▄▂▁ | 05 | ▁▄▆▇▁▃▄▇▆▃▁▇▆▄▃▁▅▃▄▂▇▅▆▄▂▄▃▅█▂ | 06 | ▂▇█▆▄▁▇█▆▁▂▁▃▆█▇▁▆█▇▂▄▅▇█▃▅▇█▃ | 07 | ▇▁▄▆▅▇▁▅▆█▁▃▄▆█▂▁▇▆▄▂▁▇▃▄▂█▅▃▄ | 08 | ▄▃▁▇▆▄▃▇▆▃▄▂▇▅▃▂▇▅▆▅▇▂▄▅▇▂▄▃▆▇ | 09 | ▄▁▇▅▆█▂▁▃▅█▂▁▃▇▁▂▄▅▇▁▄█▆▅▃▁█▆▃ | mt | 251 μs | ch | ### | xorshift char count | 00 | 040 |███████████████████████ | 01 | 034 |███████████████████ | 02 | 038 |██████████████████████ | 03 | 036 |████████████████████ | 04 | 032 |██████████████████ | 05 | 043 |█████████████████████████ | 06 | 040 |███████████████████████ | 07 | 037 |█████████████████████ | ------------------------------------- offset 62 {9,11,19} 0 uint(0000002128285285991)+0 =2276474471 233016745201164552301174452301 1 uint(0000002128285286019)+1 =2276474500 455231167445230167445230167745 2 uint(0000002128285286043)+2 =2276474525 167745233166745223166745520116 3 uint(0000002128285286069)+3 =2276474552 523011674523001674523001674423 4 uint(0000002128285286094)+4 =2276474578 167452330177452230667455231167 5 uint(0000002128285286119)+5 =2276474604 230016745230016445233017745233 6 uint(0000002128285286143)+6 =2276474629 774522316674522011674553011674 7 uint(0000002128285286168)+7 =2276474655 301167452300164452330177452330 8 uint(0000002128285286194)+8 =2276474682 745220166745230116745230116745 9 uint(0000002128285286219)+9 =2276474708 011744523016744520016774233016 ## | xorshift chars | 00 | ▃▄▄▁▂▇█▅▆▃▁▂▂▇▅▆▆▃▄▁▂▂█▅▅▆▃▄▁▂ | 01 | ▅▆▆▃▄▂▂▇█▅▅▆▃▄▁▂▇█▅▅▆▃▄▁▂▇██▅▆ | 02 | ▂▇██▅▆▃▄▄▂▇▇█▅▆▃▃▄▂▇▇█▅▆▆▃▁▂▂▇ | 03 | ▆▃▄▁▂▂▇█▅▆▃▄▁▁▂▇█▅▆▃▄▁▁▂▇█▅▅▃▄ | 04 | ▂▇█▅▆▃▄▄▁▂██▅▆▃▃▄▁▇▇█▅▆▆▃▄▂▂▇█ | 05 | ▃▄▁▁▂▇█▅▆▃▄▁▁▂▇▅▅▆▃▄▄▁▂██▅▆▃▄▄ | 06 | ██▅▆▃▃▄▂▇▇█▅▆▃▃▁▂▂▇█▅▆▆▄▁▂▂▇█▅ | 07 | ▄▁▂▂▇█▅▆▃▄▁▁▂▇▅▅▆▃▄▄▁▂██▅▆▃▄▄▁ | 08 | █▅▆▃▃▁▂▇▇█▅▆▃▄▁▂▂▇█▅▆▃▄▁▂▂▇█▅▆ | 09 | ▁▂▂█▅▅▆▃▄▁▂▇█▅▅▆▃▁▁▂▇██▅▃▄▄▁▂▇ | mt | 253 μs | ch | ### | xorshift char count | 00 | 034 |██████████████████ | 01 | 045 |█████████████████████████ | 02 | 037 |████████████████████ | 03 | 037 |████████████████████ | 04 | 041 |██████████████████████ | 05 | 036 |████████████████████ | 06 | 033 |██████████████████ | 07 | 037 |████████████████████ | ------------------------------------- offset 63 {9,21,16} 0 uint(0000002128285286389)+0 =2276474869 111111555555555444444444777777 1 uint(0000002128285286414)+1 =2276474895 544444444777777777766666666111 2 uint(0000002128285286439)+2 =2276474921 777766666666661111111110000000 3 uint(0000002128285286465)+3 =2276474948 111111110000000003333333332222 4 uint(0000002128285286490)+4 =2276474974 000333333333222222222555555555 5 uint(0000002128285286515)+5 =2276475000 222222255555555544444444477777 6 uint(0000002128285286540)+6 =2276475026 554444444447777777777666666661 7 uint(0000002128285286565)+7 =2276475052 777777666666666111111111000000 8 uint(0000002128285286589)+8 =2276475077 661111111110000000003333333332 9 uint(0000002128285286614)+9 =2276475103 000003333333332222222225555555 ## | xorshift chars | 00 | ▂▂▂▂▂▂▆▆▆▆▆▆▆▆▆▅▅▅▅▅▅▅▅▅██████ | 01 | ▆▅▅▅▅▅▅▅▅██████████▇▇▇▇▇▇▇▇▂▂▂ | 02 | ████▇▇▇▇▇▇▇▇▇▇▂▂▂▂▂▂▂▂▂▁▁▁▁▁▁▁ | 03 | ▂▂▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁▄▄▄▄▄▄▄▄▄▃▃▃▃ | 04 | ▁▁▁▄▄▄▄▄▄▄▄▄▃▃▃▃▃▃▃▃▃▆▆▆▆▆▆▆▆▆ | 05 | ▃▃▃▃▃▃▃▆▆▆▆▆▆▆▆▆▅▅▅▅▅▅▅▅▅█████ | 06 | ▆▆▅▅▅▅▅▅▅▅▅██████████▇▇▇▇▇▇▇▇▂ | 07 | ██████▇▇▇▇▇▇▇▇▇▂▂▂▂▂▂▂▂▂▁▁▁▁▁▁ | 08 | ▇▇▂▂▂▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁▄▄▄▄▄▄▄▄▄▃ | 09 | ▁▁▁▁▁▄▄▄▄▄▄▄▄▄▃▃▃▃▃▃▃▃▃▆▆▆▆▆▆▆ | mt | 250 μs | ch | ### | xorshift char count | 00 | 039 |█████████████████████ | 01 | 045 |█████████████████████████ | 02 | 030 |████████████████ | 03 | 036 |████████████████████ | 04 | 035 |███████████████████ | 05 | 037 |████████████████████ | 06 | 037 |████████████████████ | 07 | 041 |██████████████████████ | ------------------------------------- offset 64 {10,9,21} 0 uint(0000002128285286782)+0 =2276475262 540004000440044004400440004004 1 uint(0000002128285286808)+1 =2276475289 004400444044000440044004400440 2 uint(0000002128285286833)+2 =2276475315 400444044000440444004440440004 3 uint(0000002128285286859)+3 =2276475342 444004400440044004440440004004 4 uint(0000002128285286884)+4 =2276475368 004400440004004404000440044004 5 uint(0000002128285286908)+5 =2276475393 444004440044004400440004004440 6 uint(0000002128285286933)+6 =2276475419 400440004004440044004400440044 7 uint(0000002128285286958)+7 =2276475445 440044404400044004400440044000 8 uint(0000002128285286984)+8 =2276475472 004404400044004400400044404455 9 uint(0000002128285287014)+9 =2276475503 044400444044400551155111511155 ## | xorshift chars | 00 | ▆▅▁▁▁▅▁▁▁▅▅▁▁▅▅▁▁▅▅▁▁▅▅▁▁▁▅▁▁▅ | 01 | ▁▁▅▅▁▁▅▅▅▁▅▅▁▁▁▅▅▁▁▅▅▁▁▅▅▁▁▅▅▁ | 02 | ▅▁▁▅▅▅▁▅▅▁▁▁▅▅▁▅▅▅▁▁▅▅▅▁▅▅▁▁▁▅ | 03 | ▅▅▅▁▁▅▅▁▁▅▅▁▁▅▅▁▁▅▅▅▁▅▅▁▁▁▅▁▁▅ | 04 | ▁▁▅▅▁▁▅▅▁▁▁▅▁▁▅▅▁▅▁▁▁▅▅▁▁▅▅▁▁▅ | 05 | ▅▅▅▁▁▅▅▅▁▁▅▅▁▁▅▅▁▁▅▅▁▁▁▅▁▁▅▅▅▁ | 06 | ▅▁▁▅▅▁▁▁▅▁▁▅▅▅▁▁▅▅▁▁▅▅▁▁▅▅▁▁▅▅ | 07 | ▅▅▁▁▅▅▅▁▅▅▁▁▁▅▅▁▁▅▅▁▁▅▅▁▁▅▅▁▁▁ | 08 | ▁▁▅▅▁▅▅▁▁▁▅▅▁▁▅▅▁▁▅▁▁▁▅▅▅▁▅▅▆▆ | 09 | ▁▅▅▅▁▁▅▅▅▁▅▅▅▁▁▆▆▂▂▆▆▂▂▂▆▂▂▂▆▆ | mt | 256 μs | ch | ### | xorshift char count | 00 | 140 |████████████████████████ | 01 | 008 |█ | 02 | 000 | | 03 | 000 | | 04 | 142 |█████████████████████████ | 05 | 010 |█ | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 65 {10,9,25} 0 uint(0000002128285287092)+0 =2276475572 554444444444555557777666662222 1 uint(0000002128285287115)+1 =2276475596 555777766662222233331111100000 2 uint(0000002128285287140)+2 =2276475622 233333111100000000001111333332 3 uint(0000002128285287165)+3 =2276475648 000000111133333222266667777755 4 uint(0000002128285287191)+4 =2276475675 222226666777775555544444444455 5 uint(0000002128285287216)+5 =2276475701 555554444444455555777766666222 6 uint(0000002128285287241)+6 =2276475727 555777777666622222333311111000 7 uint(0000002128285287265)+7 =2276475752 222233331111000000000111113333 8 uint(0000002128285287290)+8 =2276475778 000000011111133332222666667777 9 uint(0000002128285287314)+9 =2276475803 333222266666777755555444444444 ## | xorshift chars | 00 | ▆▆▅▅▅▅▅▅▅▅▅▅▆▆▆▆▆████▇▇▇▇▇▃▃▃▃ | 01 | ▆▆▆████▇▇▇▇▃▃▃▃▃▄▄▄▄▂▂▂▂▂▁▁▁▁▁ | 02 | ▃▄▄▄▄▄▂▂▂▂▁▁▁▁▁▁▁▁▁▁▂▂▂▂▄▄▄▄▄▃ | 03 | ▁▁▁▁▁▁▂▂▂▂▄▄▄▄▄▃▃▃▃▇▇▇▇█████▆▆ | 04 | ▃▃▃▃▃▇▇▇▇█████▆▆▆▆▆▅▅▅▅▅▅▅▅▅▆▆ | 05 | ▆▆▆▆▆▅▅▅▅▅▅▅▅▆▆▆▆▆████▇▇▇▇▇▃▃▃ | 06 | ▆▆▆██████▇▇▇▇▃▃▃▃▃▄▄▄▄▂▂▂▂▂▁▁▁ | 07 | ▃▃▃▃▄▄▄▄▂▂▂▂▁▁▁▁▁▁▁▁▁▂▂▂▂▂▄▄▄▄ | 08 | ▁▁▁▁▁▁▁▂▂▂▂▂▂▄▄▄▄▃▃▃▃▇▇▇▇▇████ | 09 | ▄▄▄▃▃▃▃▇▇▇▇▇████▆▆▆▆▆▅▅▅▅▅▅▅▅▅ | mt | 246 μs | ch | ### | xorshift char count | 00 | 040 |█████████████████████████ | 01 | 037 |███████████████████████ | 02 | 040 |█████████████████████████ | 03 | 038 |███████████████████████ | 04 | 036 |██████████████████████ | 05 | 037 |███████████████████████ | 06 | 036 |██████████████████████ | 07 | 036 |██████████████████████ | ------------------------------------- offset 66 {11,7,12} 0 uint(0000002128285287498)+0 =2276475978 444444444444444444444444444444 1 uint(0000002128285287523)+1 =2276476004 444444444444444777777777777777 2 uint(0000002128285287550)+2 =2276476032 477777777777777777777777777777 3 uint(0000002128285287574)+3 =2276476057 777777777777777777777776666666 4 uint(0000002128285287599)+4 =2276476083 777777777666666666666666666666 5 uint(0000002128285287624)+5 =2276476109 666666666666666666666666666666 6 uint(0000002128285287650)+6 =2276476136 666666666666666661111111111111 7 uint(0000002128285287675)+7 =2276476162 666111111111111111111111111111 8 uint(0000002128285287700)+8 =2276476188 111111111111111111111111100000 9 uint(0000002128285287725)+9 =2276476214 111111111100000000000000000000 ## | xorshift chars | 00 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅ | 01 | ▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅███████████████ | 02 | ▅█████████████████████████████ | 03 | ███████████████████████▇▇▇▇▇▇▇ | 04 | █████████▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 05 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 06 | ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▂▂▂▂▂▂▂▂▂▂▂▂▂ | 07 | ▇▇▇▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 08 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▁▁▁▁▁ | 09 | ▂▂▂▂▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ | mt | 251 μs | ch | ### | xorshift char count | 00 | 025 |████████ | 01 | 075 |████████████████████████ | 02 | 000 | | 03 | 000 | | 04 | 046 |██████████████ | 05 | 000 | | 06 | 078 |█████████████████████████ | 07 | 076 |████████████████████████ | ------------------------------------- offset 67 {11,7,16} 0 uint(0000002128285287848)+0 =2276476328 111077766555433322111077766654 1 uint(0000002128285287872)+1 =2276476353 332211000776655444332211000766 2 uint(0000002128285287897)+2 =2276476379 544333221100777655544222300011 3 uint(0000002128285287922)+3 =2276476405 666554442333001116777445522233 4 uint(0000002128285287947)+4 =2276476431 016667744452223300116667744555 5 uint(0000002128285287972)+5 =2276476457 330011167774455523330001666774 6 uint(0000002128285287996)+6 =2276476482 522333001116677744522230001166 7 uint(0000002128285288023)+7 =2276476510 444522233000166677445522233001 8 uint(0000002128285288049)+8 =2276476537 667444555223300116667444552223 9 uint(0000002128285288075)+9 =2276476564 111667744455223300011667744452 ## | xorshift chars | 00 | ▂▂▂▁███▇▇▆▆▆▅▄▄▄▃▃▂▂▂▁███▇▇▇▆▅ | 01 | ▄▄▃▃▂▂▁▁▁██▇▇▆▆▅▅▅▄▄▃▃▂▂▁▁▁█▇▇ | 02 | ▆▅▅▄▄▄▃▃▂▂▁▁███▇▆▆▆▅▅▃▃▃▄▁▁▁▂▂ | 03 | ▇▇▇▆▆▅▅▅▃▄▄▄▁▁▂▂▂▇███▅▅▆▆▃▃▃▄▄ | 04 | ▁▂▇▇▇██▅▅▅▆▃▃▃▄▄▁▁▂▂▇▇▇██▅▅▆▆▆ | 05 | ▄▄▁▁▂▂▂▇███▅▅▆▆▆▃▄▄▄▁▁▁▂▇▇▇██▅ | 06 | ▆▃▃▄▄▄▁▁▂▂▂▇▇███▅▅▆▃▃▃▄▁▁▁▂▂▇▇ | 07 | ▅▅▅▆▃▃▃▄▄▁▁▁▂▇▇▇██▅▅▆▆▃▃▃▄▄▁▁▂ | 08 | ▇▇█▅▅▅▆▆▆▃▃▄▄▁▁▂▂▇▇▇█▅▅▅▆▆▃▃▃▄ | 09 | ▂▂▂▇▇██▅▅▅▆▆▃▃▄▄▁▁▁▂▂▇▇██▅▅▅▆▃ | mt | 253 μs | ch | ### | xorshift char count | 00 | 038 |███████████████████████ | 01 | 038 |███████████████████████ | 02 | 038 |███████████████████████ | 03 | 036 |█████████████████████ | 04 | 041 |█████████████████████████ | 05 | 034 |████████████████████ | 06 | 040 |████████████████████████ | 07 | 035 |█████████████████████ | ------------------------------------- offset 68 {11,17,13} 0 uint(0000002128285288256)+0 =2276476736 222222222222222223333333333333 1 uint(0000002128285288283)+1 =2276476764 222333333333333333334444444444 2 uint(0000002128285288307)+2 =2276476789 333333344444444444444444455555 3 uint(0000002128285288332)+3 =2276476815 444444444445555555555555555556 4 uint(0000002128285288357)+4 =2276476841 555555555555555666666666666666 5 uint(0000002128285288382)+5 =2276476867 566666666666666666677777777777 6 uint(0000002128285288406)+6 =2276476892 666667777777777777777770000000 7 uint(0000002128285288431)+7 =2276476918 777777777000000000000000000111 8 uint(0000002128285288457)+8 =2276476945 000000000000111111111111111111 9 uint(0000002128285288482)+9 =2276476971 111111111111111112222222222222 ## | xorshift chars | 00 | ▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▄▄▄▄▄▄▄▄▄▄▄▄▄ | 01 | ▃▃▃▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▅▅▅▅▅▅▅▅▅▅ | 02 | ▄▄▄▄▄▄▄▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▆▆▆▆▆ | 03 | ▅▅▅▅▅▅▅▅▅▅▅▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▇ | 04 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 05 | ▆▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇███████████ | 06 | ▇▇▇▇▇██████████████████▁▁▁▁▁▁▁ | 07 | █████████▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂▂▂ | 08 | ▁▁▁▁▁▁▁▁▁▁▁▁▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ | 09 | ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▃▃▃▃▃▃▃▃▃▃▃▃▃ | mt | 251 μs | ch | ### | xorshift char count | 00 | 037 |███████████████████████ | 01 | 038 |████████████████████████ | 02 | 033 |█████████████████████ | 03 | 037 |███████████████████████ | 04 | 039 |█████████████████████████ | 05 | 039 |█████████████████████████ | 06 | 039 |█████████████████████████ | 07 | 038 |████████████████████████ | ------------------------------------- offset 69 {11,21,13} 0 uint(0000002128285288671)+0 =2276477151 777777777777777777700000000000 1 uint(0000002128285288696)+1 =2276477177 777700000000000000000011111111 2 uint(0000002128285288720)+2 =2276477202 000000001111111111111111112222 3 uint(0000002128285288745)+3 =2276477228 111111111111222222222222222222 4 uint(0000002128285288770)+4 =2276477254 222222222222222233333333333333 5 uint(0000002128285288796)+5 =2276477281 223333333333333333333444444444 6 uint(0000002128285288821)+6 =2276477307 333333444444444444444444555555 7 uint(0000002128285288845)+7 =2276477332 444444444445555555555555555556 8 uint(0000002128285288870)+8 =2276477358 555555555555556666666666666666 9 uint(0000002128285288895)+9 =2276477384 566666666666666666677777777777 ## | xorshift chars | 00 | ███████████████████▁▁▁▁▁▁▁▁▁▁▁ | 01 | ████▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂▂▂▂▂▂▂▂ | 02 | ▁▁▁▁▁▁▁▁▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▃▃▃▃ | 03 | ▂▂▂▂▂▂▂▂▂▂▂▂▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃ | 04 | ▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 05 | ▃▃▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▅▅▅▅▅▅▅▅▅ | 06 | ▄▄▄▄▄▄▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▆▆▆▆▆▆ | 07 | ▅▅▅▅▅▅▅▅▅▅▅▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▇ | 08 | ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | 09 | ▆▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇███████████ | mt | 249 μs | ch | ### | xorshift char count | 00 | 037 |███████████████████████ | 01 | 038 |███████████████████████ | 02 | 040 |█████████████████████████ | 03 | 039 |████████████████████████ | 04 | 038 |███████████████████████ | 05 | 039 |████████████████████████ | 06 | 035 |█████████████████████ | 07 | 034 |█████████████████████ | ------------------------------------- offset 70 {12,9,23} 0 uint(0000002128285289083)+0 =2276477563 226666677774444455552222333330 1 uint(0000002128285289108)+1 =2276477589 445555522223333000001111777776 2 uint(0000002128285289134)+2 =2276477616 300001111177777666655554444433 3 uint(0000002128285289157)+3 =2276477640 666666555544444333332222111110 4 uint(0000002128285289181)+4 =2276477665 433333222211111000000001111122 5 uint(0000002128285289207)+5 =2276477692 100000000011112222233334444455 6 uint(0000002128285289232)+6 =2276477718 222233333444455555666667777111 7 uint(0000002128285289256)+7 =2276477743 555566666777711110000033332222 8 uint(0000002128285289281)+8 =2276477769 111000003333322225555544447777 9 uint(0000002128285289306)+9 =2276477795 222555554444777776666222223333 ## | xorshift chars | 00 | ▃▃▇▇▇▇▇████▅▅▅▅▅▆▆▆▆▃▃▃▃▄▄▄▄▄▁ | 01 | ▅▅▆▆▆▆▆▃▃▃▃▄▄▄▄▁▁▁▁▁▂▂▂▂█████▇ | 02 | ▄▁▁▁▁▂▂▂▂▂█████▇▇▇▇▆▆▆▆▅▅▅▅▅▄▄ | 03 | ▇▇▇▇▇▇▆▆▆▆▅▅▅▅▅▄▄▄▄▄▃▃▃▃▂▂▂▂▂▁ | 04 | ▅▄▄▄▄▄▃▃▃▃▂▂▂▂▂▁▁▁▁▁▁▁▁▂▂▂▂▂▃▃ | 05 | ▂▁▁▁▁▁▁▁▁▁▂▂▂▂▃▃▃▃▃▄▄▄▄▅▅▅▅▅▆▆ | 06 | ▃▃▃▃▄▄▄▄▄▅▅▅▅▆▆▆▆▆▇▇▇▇▇████▂▂▂ | 07 | ▆▆▆▆▇▇▇▇▇████▂▂▂▂▁▁▁▁▁▄▄▄▄▃▃▃▃ | 08 | ▂▂▂▁▁▁▁▁▄▄▄▄▄▃▃▃▃▆▆▆▆▆▅▅▅▅████ | 09 | ▃▃▃▆▆▆▆▆▅▅▅▅█████▇▇▇▇▃▃▃▃▃▄▄▄▄ | mt | 248 μs | ch | ### | xorshift char count | 00 | 038 |█████████████████████ | 01 | 039 |█████████████████████ | 02 | 045 |█████████████████████████ | 03 | 044 |████████████████████████ | 04 | 035 |███████████████████ | 05 | 038 |█████████████████████ | 06 | 030 |████████████████ | 07 | 031 |█████████████████ | ------------------------------------- offset 71 {13,3,17} 0 uint(0000002128285289462)+0 =2276477942 342751041306315405762751046326 1 uint(0000002128285289486)+1 =2276477967 540236205302352043746513407314 2 uint(0000002128285289511)+2 =2276477993 706375057362750413726454027162 3 uint(0000002128285289534)+3 =2276478017 046352047402716453026157437560 4 uint(0000002128285289559)+4 =2276478043 427512417063154073620530467264 5 uint(0000002128285289583)+5 =2276478068 427164053261570435605134251241 6 uint(0000002128285289608)+6 =2276478094 231540276205304652043746513427 7 uint(0000002128285289632)+7 =2276478119 415706316057362710463526174627 8 uint(0000002128285289657)+8 =2276478145 073026150437560534275104372641 9 uint(0000002128285289681)+9 =2276478170 271620530635204376251340712415 ## | xorshift chars | 00 | ▄▅▃█▆▂▁▅▂▄▁▇▄▂▆▅▁▆█▇▃█▆▂▁▅▇▄▃▇ | 01 | ▆▅▁▃▄▇▃▁▆▄▁▃▄▆▃▁▅▄█▅▇▆▂▄▅▁█▄▂▅ | 02 | █▁▇▄█▆▁▆█▄▇▃█▆▁▅▂▄█▃▇▅▆▅▁▃█▂▇▃ | 03 | ▁▅▇▄▆▃▁▅█▅▁▃█▂▇▅▆▄▁▃▇▂▆█▅▄█▆▇▁ | 04 | ▅▃█▆▂▃▅▂█▁▇▄▂▆▅▁█▄▇▃▁▆▄▁▅▇█▃▇▅ | 05 | ▅▃█▂▇▅▁▆▄▃▇▂▆█▁▅▄▆▇▁▆▂▄▅▃▆▂▃▅▂ | 06 | ▃▄▂▆▅▁▃█▇▃▁▆▄▁▅▇▆▃▁▅▄█▅▇▆▂▄▅▃█ | 07 | ▅▂▆█▁▇▄▂▇▁▆█▄▇▃█▂▁▅▇▄▆▃▇▂█▅▇▃█ | 08 | ▁█▄▁▃▇▂▆▁▅▄█▆▇▁▆▄▅▃█▆▂▁▅▄█▃▇▅▂ | 09 | ▃█▂▇▃▁▆▄▁▇▄▆▃▁▅▄█▇▃▆▂▄▅▁█▂▃▅▂▆ | mt | 244 μs | ch | ### | xorshift char count | 00 | 041 |████████████████████████ | 01 | 031 |██████████████████ | 02 | 038 |██████████████████████ | 03 | 037 |██████████████████████ | 04 | 042 |█████████████████████████ | 05 | 039 |███████████████████████ | 06 | 036 |█████████████████████ | 07 | 036 |█████████████████████ | ------------------------------------- offset 72 {13,3,27} 0 uint(0000002128285289856)+0 =2276478336 001112333445566677111033322554 1 uint(0000002128285289881)+1 =2276478362 667711000332255444776622333001 2 uint(0000002128285289905)+2 =2276478387 544477662223300116667744553332 3 uint(0000002128285289929)+3 =2276478412 011166774455533221100077665554 4 uint(0000002128285289953)+4 =2276478437 322111007766555444455566770011 5 uint(0000002128285289977)+5 =2276478462 444445556777000112233555477666 6 uint(0000002128285290003)+6 =2276478489 011222335557776611003332266777 7 uint(0000002128285290028)+7 =2276478515 661100033226677745552233300117 8 uint(0000002128285290053)+8 =2276478541 774555223330111777655544333211 9 uint(0000002128285290078)+9 =2276478567 177665554433222110000111233344 ## | xorshift chars | 00 | ▁▁▂▂▂▃▄▄▄▅▅▆▆▇▇▇██▂▂▂▁▄▄▄▃▃▆▆▅ | 01 | ▇▇██▂▂▁▁▁▄▄▃▃▆▆▅▅▅██▇▇▃▃▄▄▄▁▁▂ | 02 | ▆▅▅▅██▇▇▃▃▃▄▄▁▁▂▂▇▇▇██▅▅▆▆▄▄▄▃ | 03 | ▁▂▂▂▇▇██▅▅▆▆▆▄▄▃▃▂▂▁▁▁██▇▇▆▆▆▅ | 04 | ▄▃▃▂▂▂▁▁██▇▇▆▆▆▅▅▅▅▆▆▆▇▇██▁▁▂▂ | 05 | ▅▅▅▅▅▆▆▆▇███▁▁▁▂▂▃▃▄▄▆▆▆▅██▇▇▇ | 06 | ▁▂▂▃▃▃▄▄▆▆▆███▇▇▂▂▁▁▄▄▄▃▃▇▇███ | 07 | ▇▇▂▂▁▁▁▄▄▃▃▇▇███▅▆▆▆▃▃▄▄▄▁▁▂▂█ | 08 | ██▅▆▆▆▃▃▄▄▄▁▂▂▂███▇▆▆▆▅▅▄▄▄▃▂▂ | 09 | ▂██▇▇▆▆▆▅▅▄▄▃▃▃▂▂▁▁▁▁▂▂▂▃▄▄▄▅▅ | mt | 246 μs | ch | ### | xorshift char count | 00 | 034 |████████████████████ | 01 | 042 |█████████████████████████ | 02 | 033 |███████████████████ | 03 | 042 |█████████████████████████ | 04 | 032 |███████████████████ | 05 | 042 |█████████████████████████ | 06 | 035 |████████████████████ | 07 | 040 |███████████████████████ | ------------------------------------- offset 73 {13,5,19} 0 uint(0000002128285290256)+0 =2276478736 332211000776655544333211100777 1 uint(0000002128285290281)+1 =2276478762 554433221110077665554433222110 2 uint(0000002128285290306)+2 =2276478788 766654443322210007766555443322 3 uint(0000002128285290331)+3 =2276478814 107776655543332221000776665444 4 uint(0000002128285290355)+4 =2276478839 221100077665554433321110077765 5 uint(0000002128285290380)+5 =2276478865 443322211007766655443322211007 6 uint(0000002128285290405)+6 =2276478891 655444333221100777655544333211 7 uint(0000002128285290429)+7 =2276478916 077666554443322110077666554443 8 uint(0000002128285290454)+8 =2276478942 211007776655543332211100001122 9 uint(0000002128285290477)+9 =2276478966 333222110000111223344555667700 ## | xorshift chars | 00 | ▄▄▃▃▂▂▁▁▁██▇▇▆▆▆▅▅▄▄▄▃▂▂▂▁▁███ | 01 | ▆▆▅▅▄▄▃▃▂▂▂▁▁██▇▇▆▆▆▅▅▄▄▃▃▃▂▂▁ | 02 | █▇▇▇▆▅▅▅▄▄▃▃▃▂▁▁▁██▇▇▆▆▆▅▅▄▄▃▃ | 03 | ▂▁███▇▇▆▆▆▅▄▄▄▃▃▃▂▁▁▁██▇▇▇▆▅▅▅ | 04 | ▃▃▂▂▁▁▁██▇▇▆▆▆▅▅▄▄▄▃▂▂▂▁▁███▇▆ | 05 | ▅▅▄▄▃▃▃▂▂▁▁██▇▇▇▆▆▅▅▄▄▃▃▃▂▂▁▁█ | 06 | ▇▆▆▅▅▅▄▄▄▃▃▂▂▁▁███▇▆▆▆▅▅▄▄▄▃▂▂ | 07 | ▁██▇▇▇▆▆▅▅▅▄▄▃▃▂▂▁▁██▇▇▇▆▆▅▅▅▄ | 08 | ▃▂▂▁▁███▇▇▆▆▆▅▄▄▄▃▃▂▂▂▁▁▁▁▂▂▃▃ | 09 | ▄▄▄▃▃▃▂▂▁▁▁▁▂▂▂▃▃▄▄▅▅▆▆▆▇▇██▁▁ | mt | 246 μs | ch | ### | xorshift char count | 00 | 041 |█████████████████████████ | 01 | 040 |████████████████████████ | 02 | 040 |████████████████████████ | 03 | 040 |████████████████████████ | 04 | 035 |█████████████████████ | 05 | 037 |██████████████████████ | 06 | 032 |███████████████████ | 07 | 035 |█████████████████████ | ------------------------------------- offset 74 {13,17,15} 0 uint(0000002128285290657)+0 =2276479137 556701234556701234456001234457 1 uint(0000002128285290682)+1 =2276479163 123446770123356770122346670122 2 uint(0000002128285290705)+2 =2276479187 667011235567011244567001344567 3 uint(0000002128285290730)+3 =2276479213 233456771223456601223455701123 4 uint(0000002128285290755)+4 =2276479239 670012345670012345677023345667 5 uint(0000002128285290781)+5 =2276479266 234567012234567011234567001234 6 uint(0000002128285290805)+6 =2276479291 700124456770133456770223456671 7 uint(0000002128285290830)+7 =2276479317 345560112345570012344670012335 8 uint(0000002128285290855)+8 =2276479343 701234566701234566701234566701 9 uint(0000002128285290880)+9 =2276479369 456670223455671123445600123445 ## | xorshift chars | 00 | ▆▆▇█▁▂▃▄▅▆▆▇█▁▂▃▄▅▅▆▇▁▁▂▃▄▅▅▆█ | 01 | ▂▃▄▅▅▇██▁▂▃▄▄▆▇██▁▂▃▃▄▅▇▇█▁▂▃▃ | 02 | ▇▇█▁▂▂▃▄▆▆▇█▁▂▂▃▅▅▆▇█▁▁▂▄▅▅▆▇█ | 03 | ▃▄▄▅▆▇██▂▃▃▄▅▆▇▇▁▂▃▃▄▅▆▆█▁▂▂▃▄ | 04 | ▇█▁▁▂▃▄▅▆▇█▁▁▂▃▄▅▆▇██▁▃▄▄▅▆▇▇█ | 05 | ▃▄▅▆▇█▁▂▃▃▄▅▆▇█▁▂▂▃▄▅▆▇█▁▁▂▃▄▅ | 06 | █▁▁▂▃▅▅▆▇██▁▂▄▄▅▆▇██▁▃▃▄▅▆▇▇█▂ | 07 | ▄▅▆▆▇▁▂▂▃▄▅▆▆█▁▁▂▃▄▅▅▇█▁▁▂▃▄▄▆ | 08 | █▁▂▃▄▅▆▇▇█▁▂▃▄▅▆▇▇█▁▂▃▄▅▆▇▇█▁▂ | 09 | ▅▆▇▇█▁▃▃▄▅▆▆▇█▂▂▃▄▅▅▆▇▁▁▂▃▄▅▅▆ | mt | 248 μs | ch | ### | xorshift char count | 00 | 038 |████████████████████████ | 01 | 036 |███████████████████████ | 02 | 038 |████████████████████████ | 03 | 036 |███████████████████████ | 04 | 039 |█████████████████████████ | 05 | 037 |███████████████████████ | 06 | 039 |█████████████████████████ | 07 | 037 |███████████████████████ | ------------------------------------- offset 75 {14,1,15} 0 uint(0000002128285291071)+0 =2276479551 765122156765123156764122054764 1 uint(0000002128285291095)+1 =2276479576 205477413301477402301467502321 2 uint(0000002128285291119)+2 =2276479601 651232157641232047641033047745 3 uint(0000002128285291143)+3 =2276479626 314676502215676513215676412205 4 uint(0000002128285291168)+4 =2276479652 641320547740330147750232146651 5 uint(0000002128285291193)+5 =2276479678 246765123216765123256764103054 6 uint(0000002128285291217)+6 =2276479703 413305477403301467502321566512 7 uint(0000002128285291242)+7 =2276479729 156651232057641232547641033547 8 uint(0000002128285291267)+8 =2276479755 503014674523214676123215675123 9 uint(0000002128285291291)+9 =2276479780 576410320476410301477502301466 ## | xorshift chars | 00 | █▇▆▂▃▃▂▆▇█▇▆▂▃▄▂▆▇█▇▅▂▃▃▁▆▅█▇▅ | 01 | ▃▁▆▅██▅▂▄▄▁▂▅██▅▁▃▄▁▂▅▇█▆▁▃▄▃▂ | 02 | ▇▆▂▃▄▃▂▆█▇▅▂▃▄▃▁▅█▇▅▂▁▄▄▁▅██▅▆ | 03 | ▄▂▅▇█▇▆▁▃▃▂▆▇█▇▆▂▄▃▂▆▇█▇▅▂▃▃▁▆ | 04 | ▇▅▂▄▃▁▆▅██▅▁▄▄▁▂▅██▆▁▃▄▃▂▅▇▇▆▂ | 05 | ▃▅▇█▇▆▂▃▄▃▂▇█▇▆▂▃▄▃▆▇█▇▅▂▁▄▁▆▅ | 06 | ▅▂▄▄▁▆▅██▅▁▄▄▁▂▅▇█▆▁▃▄▃▂▆▇▇▆▂▃ | 07 | ▂▆▇▇▆▂▃▄▃▁▆█▇▅▂▃▄▃▆▅█▇▅▂▁▄▄▆▅█ | 08 | ▆▁▄▁▂▅▇█▅▆▃▄▃▂▅▇█▇▂▃▄▃▂▆▇█▆▂▃▄ | 09 | ▆█▇▅▂▁▄▃▁▅█▇▅▂▁▄▁▂▅██▆▁▃▄▁▂▅▇▇ | mt | 247 μs | ch | ### | xorshift char count | 00 | 031 |██████████████████ | 01 | 043 |█████████████████████████ | 02 | 040 |███████████████████████ | 03 | 034 |███████████████████ | 04 | 039 |██████████████████████ | 05 | 037 |█████████████████████ | 06 | 040 |███████████████████████ | 07 | 036 |████████████████████ | ------------------------------------- offset 76 {14,13,15} 0 uint(0000002128285291466)+0 =2276479946 431064106431063106531053207532 1 uint(0000002128285291490)+1 =2276479971 320754205421752176421643176410 2 uint(0000002128285291516)+2 =2276479998 306431065306532053207520754217 3 uint(0000002128285291540)+3 =2276480023 176421763176431043106531653206 4 uint(0000002128285291565)+4 =2276480049 075320542075427542176417643106 5 uint(0000002128285291591)+5 =2276480076 764310431065326532075307542075 6 uint(0000002128285291615)+6 =2276480101 754275421764217431764376431065 7 uint(0000002128285291639)+7 =2276480126 643106431063106531653106530653 8 uint(0000002128285291664)+8 =2276480152 752075420742075421752176427642 9 uint(0000002128285291689)+9 =2276480178 641764317631065310532065320532 ## | xorshift chars | 00 | ▅▄▂▁▇▅▂▁▇▅▄▂▁▇▄▂▁▇▆▄▂▁▆▄▃▁█▆▄▃ | 01 | ▄▃▁█▆▅▃▁▆▅▃▂█▆▃▂█▇▅▃▂▇▅▄▂█▇▅▂▁ | 02 | ▄▁▇▅▄▂▁▇▆▄▁▇▆▄▃▁▆▄▃▁█▆▃▁█▆▅▃▂█ | 03 | ▂█▇▅▃▂█▇▄▂█▇▅▄▂▁▅▄▂▁▇▆▄▂▇▆▄▃▁▇ | 04 | ▁█▆▄▃▁▆▅▃▁█▆▅▃█▆▅▃▂█▇▅▂█▇▅▄▂▁▇ | 05 | █▇▅▄▂▁▅▄▂▁▇▆▄▃▇▆▄▃▁█▆▄▁█▆▅▃▁█▆ | 06 | █▆▅▃█▆▅▃▂█▇▅▃▂█▅▄▂█▇▅▄█▇▅▄▂▁▇▆ | 07 | ▇▅▄▂▁▇▅▄▂▁▇▄▂▁▇▆▄▂▇▆▄▂▁▇▆▄▁▇▆▄ | 08 | █▆▃▁█▆▅▃▁█▅▃▁█▆▅▃▂█▆▃▂█▇▅▃█▇▅▃ | 09 | ▇▅▂█▇▅▄▂█▇▄▂▁▇▆▄▂▁▆▄▃▁▇▆▄▃▁▆▄▃ | mt | 247 μs | ch | ### | xorshift char count | 00 | 040 |████████████████████████ | 01 | 038 |███████████████████████ | 02 | 033 |████████████████████ | 03 | 041 |█████████████████████████ | 04 | 036 |█████████████████████ | 05 | 037 |██████████████████████ | 06 | 040 |████████████████████████ | 07 | 035 |█████████████████████ | ------------------------------------- offset 77 {15,1,29} 0 uint(0000002128285291856)+0 =2276480336 651232054764232054774102054774 1 uint(0000002128285291880)+1 =2276480361 301474502301476502321676512325 2 uint(0000002128285291904)+2 =2276480386 641220567641320547710330147450 3 uint(0000002128285291929)+3 =2276480412 014745023216765123216765123216 4 uint(0000002128285291954)+4 =2276480438 412320676410325477450331467450 5 uint(0000002128285291977)+5 =2276480462 146765122156765122056764102076 6 uint(0000002128285292005)+6 =2276480491 032054741033054771033014775023 7 uint(0000002128285292028)+7 =2276480515 464502321567512321566512320566 8 uint(0000002128285292053)+8 =2276480541 232057641033067641032056651232 9 uint(0000002128285292077)+9 =2276480566 665123215765123206764103054774 ## | xorshift chars | 00 | ▇▆▂▃▄▃▁▆▅█▇▅▃▄▃▁▆▅██▅▂▁▃▁▆▅██▅ | 01 | ▄▁▂▅█▅▆▁▃▄▁▂▅█▇▆▁▃▄▃▂▇█▇▆▂▃▄▃▆ | 02 | ▇▅▂▃▃▁▆▇█▇▅▂▄▃▁▆▅██▂▁▄▄▁▂▅█▅▆▁ | 03 | ▁▂▅█▅▆▁▃▄▃▂▇█▇▆▂▃▄▃▂▇█▇▆▂▃▄▃▂▇ | 04 | ▅▂▃▄▃▁▇█▇▅▂▁▄▃▆▅██▅▆▁▄▄▂▅▇█▅▆▁ | 05 | ▂▅▇█▇▆▂▃▃▂▆▇█▇▆▂▃▃▁▆▇█▇▅▂▁▃▁█▇ | 06 | ▁▄▃▁▆▅█▅▂▁▄▄▁▆▅██▂▁▄▄▁▂▅██▆▁▃▄ | 07 | ▅▇▅▆▁▃▄▃▂▆▇█▆▂▃▄▃▂▆▇▇▆▂▃▄▃▁▆▇▇ | 08 | ▃▄▃▁▆█▇▅▂▁▄▄▁▇█▇▅▂▁▄▃▁▆▇▇▆▂▃▄▃ | 09 | ▇▇▆▂▃▄▃▂▆█▇▆▂▃▄▃▁▇█▇▅▂▁▄▁▆▅██▅ | mt | 246 μs | ch | ### | xorshift char count | 00 | 039 |██████████████████████ | 01 | 038 |█████████████████████ | 02 | 044 |█████████████████████████ | 03 | 033 |██████████████████ | 04 | 035 |███████████████████ | 05 | 037 |█████████████████████ | 06 | 039 |██████████████████████ | 07 | 035 |███████████████████ | ------------------------------------- offset 78 {17,15,20} 0 uint(0000002128285292249)+0 =2276480729 000000000000000000000033333333 1 uint(0000002128285292274)+1 =2276480755 000000033333333333333333333333 2 uint(0000002128285292299)+2 =2276480781 333333333333333333333333333333 3 uint(0000002128285292323)+3 =2276480806 333333333333333333333333333333 4 uint(0000002128285292348)+4 =2276480832 333333333333333333333333333333 5 uint(0000002128285292373)+5 =2276480858 333333333333333333333333222222 6 uint(0000002128285292397)+6 =2276480883 333333333322222222222222222222 7 uint(0000002128285292422)+7 =2276480909 222222222222222222222222222222 8 uint(0000002128285292447)+8 =2276480935 222222222222222222222222222222 9 uint(0000002128285292471)+9 =2276480960 222222222222222222222222222222 ## | xorshift chars | 00 | ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▄▄▄▄▄▄▄▄ | 01 | ▁▁▁▁▁▁▁▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 02 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 03 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 04 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | 05 | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▃▃▃▃▃▃ | 06 | ▄▄▄▄▄▄▄▄▄▄▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃ | 07 | ▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃ | 08 | ▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃ | 09 | ▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃ | mt | 247 μs | ch | ### | xorshift char count | 00 | 029 |████ | 01 | 000 | | 02 | 116 |██████████████████ | 03 | 155 |█████████████████████████ | 04 | 000 | | 05 | 000 | | 06 | 000 | | 07 | 000 | | ------------------------------------- offset 79 {17,15,23} 0 uint(0000002128285292560)+0 =2276481040 555555555666666666777777777711 1 uint(0000002128285292584)+1 =2276481065 666677777777771111111110000000 2 uint(0000002128285292608)+2 =2276481090 111111111000000000333333333322 3 uint(0000002128285292632)+3 =2276481115 000003333333332222222266666666 4 uint(0000002128285292657)+4 =2276481141 222222226666666667777777777444 5 uint(0000002128285292680)+5 =2276481165 666677777777744444444455555555 6 uint(0000002128285292705)+6 =2276481191 444444445555555555333333333222 7 uint(0000002128285292730)+7 =2276481217 555333333333222222222111111111 8 uint(0000002128285292754)+8 =2276481242 222222221111111110000000000000 9 uint(0000002128285292779)+9 =2276481268 110000000000000000000111111111 ## | xorshift chars | 00 | ▆▆▆▆▆▆▆▆▆▇▇▇▇▇▇▇▇▇██████████▂▂ | 01 | ▇▇▇▇██████████▂▂▂▂▂▂▂▂▂▁▁▁▁▁▁▁ | 02 | ▂▂▂▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁▄▄▄▄▄▄▄▄▄▄▃▃ | 03 | ▁▁▁▁▁▄▄▄▄▄▄▄▄▄▃▃▃▃▃▃▃▃▇▇▇▇▇▇▇▇ | 04 | ▃▃▃▃▃▃▃▃▇▇▇▇▇▇▇▇▇██████████▅▅▅ | 05 | ▇▇▇▇█████████▅▅▅▅▅▅▅▅▅▆▆▆▆▆▆▆▆ | 06 | ▅▅▅▅▅▅▅▅▆▆▆▆▆▆▆▆▆▆▄▄▄▄▄▄▄▄▄▃▃▃ | 07 | ▆▆▆▄▄▄▄▄▄▄▄▄▃▃▃▃▃▃▃▃▃▂▂▂▂▂▂▂▂▂ | 08 | ▃▃▃▃▃▃▃▃▂▂▂▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁ | 09 | ▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂▂▂▂▂▂▂▂▂ | mt | 243 μs | ch | ### | xorshift char count | 00 | 053 |█████████████████████████ | 01 | 049 |███████████████████████ | 02 | 038 |█████████████████ | 03 | 037 |█████████████████ | 04 | 020 |█████████ | 05 | 030 |██████████████ | 06 | 034 |████████████████ | 07 | 039 |██████████████████ | ------------------------------------- offset 80 {17,15,26} 0 uint(0000002128285292927)+0 =2276481407 554761123776522301110224567731 1 uint(0000002128285292952)+1 =2276481433 230110332456732110674454476012 2 uint(0000002128285292977)+2 =2276481459 221667455547001233765423011103 3 uint(0000002128285293002)+3 =2276481485 123376544230100324557322106675 4 uint(0000002128285293026)+4 =2276481510 032456733210074555477012237654 5 uint(0000002128285293051)+5 =2276481536 445547601223765423301103244567 6 uint(0000002128285293076)+6 =2276481562 542231110322457732110644554770 7 uint(0000002128285293100)+7 =2276481587 673220677455446001237754423011 8 uint(0000002128285293124)+8 =2276481612 660122375542300103324556322106 9 uint(0000002128285293148)+9 =2276481637 111032446773210074555477012237 ## | xorshift chars | 00 | ▆▆▅█▇▂▂▃▄██▇▆▃▃▄▁▂▂▂▁▃▃▅▆▇██▄▂ | 01 | ▃▄▁▂▂▁▄▄▃▅▆▇█▄▃▂▂▁▇█▅▅▆▅▅█▇▁▂▃ | 02 | ▃▃▂▇▇█▅▆▆▆▅█▁▁▂▃▄▄█▇▆▅▃▄▁▂▂▂▁▄ | 03 | ▂▃▄▄█▇▆▅▅▃▄▁▂▁▁▄▃▅▆▆█▄▃▃▂▁▇▇█▆ | 04 | ▁▄▃▅▆▇█▄▄▃▂▁▁█▅▆▆▆▅██▁▂▃▃▄█▇▆▅ | 05 | ▅▅▆▆▅█▇▁▂▃▃▄█▇▆▅▃▄▄▁▂▂▁▄▃▅▅▆▇█ | 06 | ▆▅▃▃▄▂▂▂▁▄▃▃▅▆██▄▃▂▂▁▇▅▅▆▆▅██▁ | 07 | ▇█▄▃▃▁▇██▅▆▆▅▅▇▁▁▂▃▄██▆▅▅▃▄▁▂▂ | 08 | ▇▇▁▂▃▃▄█▆▆▅▃▄▁▁▂▁▄▄▃▅▆▆▇▄▃▃▂▁▇ | 09 | ▂▂▂▁▄▃▅▅▇██▄▃▂▁▁█▅▆▆▆▅██▁▂▃▃▄█ | mt | 246 μs | ch | ### | xorshift char count | 00 | 037 |████████████████████ | 01 | 040 |██████████████████████ | 02 | 045 |█████████████████████████ | 03 | 038 |█████████████████████ | 04 | 039 |█████████████████████ | 05 | 037 |████████████████████ | 06 | 026 |██████████████ | 07 | 038 |█████████████████████ | ------------------------------------- 30 lines, 1..20 chars, of 10 chars phased offset ## | xorshift | ## | GLib.Rand() 00 | 891812116994435769 | 00 | 687 01 | 188913523894435769 | 01 | 853126171867806330 02 | 186160970776929286 | 02 | 5165277563025 03 | 376 | 03 | 378689 04 | 37616096863720 | 04 | 5334213505784 05 | 564 | 05 | 798362560466985 06 | 5640117686372071 | 06 | 1655340158933 07 | 742257685305896323 | 07 | 535 08 | 74225768530 | 08 | 1682228801978202 09 | 4391290974 | 09 | 97253511356 10 | 4391290974750804 | 10 | 573997120952407199 11 | 227385499159 | 11 | 8695995 12 | 22738549915 | 12 | 886766236 13 | 227385481229162 | 13 | 6901 14 | 914246 | 14 | 2298267815595359159 15 | 91424628 | 15 | 017 16 | 914284163 | 16 | 7447172658 17 | 692484163807731118 | 17 | 2602941491025221661 18 | 69 | 18 | 59048317395 19 | 3894435 | 19 | 5985 20 | 3894435769787252 | 20 | 20184777763 21 | 3894 | 21 | 12201037597703 22 | 0776929286521197565 | 22 | 464316580490022 23 | 07769 | 23 | 127951 24 | 0777207 | 24 | 1706210335834846864 25 | 863720710731507637 | 25 | 1 26 | 86372 | 26 | 856378051 27 | 53058963 | 27 | 3083483865845160260 28 | 5305896323100 | 28 | 792319167925155899 29 | 53058963248 | 29 | 079911107734381 mt | 13 μs | mt | 384 μs ch | ### | xorshift | ch | ### | GLib.Rand() 00 | 025 |████████████ | 00 | 030 |█████████████ 01 | 031 |███████████████ | 01 | 041 |██████████████████ 02 | 037 |██████████████████ | 02 | 033 |███████████████ 03 | 036 |█████████████████ | 03 | 034 |███████████████ 04 | 030 |██████████████ | 04 | 020 |█████████ 05 | 029 |██████████████ | 05 | 044 |████████████████████ 06 | 037 |██████████████████ | 06 | 036 |████████████████ 07 | 041 |████████████████████ | 07 | 035 |███████████████ 08 | 033 |████████████████ | 08 | 035 |███████████████ 09 | 040 |███████████████████ | 09 | 034 |███████████████ ------------------------------------- 30 lines, 1..20 chars, of 8 chars phased offset ## | xorshift | ## | GLib.Rand() 00 | ▁▃█ | 00 | ▆▃▅▁ 01 | ▁▃█▇▃▁▃▂ | 01 | ▁▄ 02 | ▁▃▁▇█▂▄▁▁▃▁▃▂▂▄▅▃▃█▁ | 02 | ▅▂▃ 03 | ▇▄▁▇█▂▄▁▁▃▁▃▆▇▁▇▁ | 03 | ▆ 04 | ▅▆▃█▄▇▁▃▃▆ | 04 | ▃▅▂▅▆▆▇▇▃▂▅█▄▂ 05 | ▅▆▃█▄▆█▃▄▇▁▁▃▆█▇▆ | 05 | █▁▇▃█▅▄▇█▆▆ 06 | ▂▇▁▅▅▆█▃▄▂▃▂▇▆▅▅█▇▆ | 06 | ▄▃▄▅▅▅ 07 | ▄▂▃ | 07 | ▇▅█▅▃█▃ 08 | ▄▂▃▆ | 08 | ▆▅▅▇█▅▁▄▁ 09 | ▄▂▃▆▁ | 09 | ▅▆▆▁▆▄▄▁▂▄▇▂▆▂▅▂█ mt | 7 μs | mt | 87 μs ch | ### | xorshift | ch | ### | GLib.Rand() 00 | 020 |██████████████████ | 00 | 007 |████████ 01 | 011 |██████████ | 01 | 008 |██████████ 02 | 022 |████████████████████ | 02 | 008 |██████████ 03 | 011 |██████████ | 03 | 009 |███████████ 04 | 007 |██████ | 04 | 016 |████████████████████ 05 | 012 |██████████ | 05 | 011 |█████████████ 06 | 012 |██████████ | 06 | 007 |████████ 07 | 011 |██████████ | 07 | 008 |██████████ ------------------------------------- 10 lines, 3..10 chars, of 10 chars phased offset xorshift with prints... [ln] rand binary [00] 656596324 ▁▁█▁ ▁███ ▁▁█▁ ▁▁█▁ ██▁█ ██▁█ ▁██▁ ▁█▁▁ | 4 [00] |-- 3208089966 █▁██ ████ ▁▁██ ▁███ █▁▁█ ▁▁▁█ ▁██▁ ███▁ | 7 | ======= | 00/07 {13,3,17} [00] |-- 3141979672 █▁██ █▁██ ▁█▁▁ ▁██▁ ██▁▁ ███▁ ▁▁▁█ █▁▁▁ | 7 | ======= | 01/07 {3,7,29} [00] |-- 3854272074 ███▁ ▁█▁█ █▁██ █▁██ █▁▁▁ ▁██▁ ▁█▁▁ █▁█▁ | 8 | ======== | 02/07 {5,27,25} [00] +-- 0904084933 ▁▁██ ▁█▁█ ███▁ ▁▁██ ▁▁██ ██▁█ ██▁▁ ▁█▁█ | 2 | == | 03/07 {3,5,25} [01] 4215721410 ████ █▁██ ▁█▁▁ ▁██▁ ██▁▁ ██▁█ ██▁▁ ▁▁█▁ | 10 [01] |-- 0533512468 ▁▁▁█ ████ ██▁▁ ██▁▁ ██▁▁ ▁▁▁█ ▁▁▁█ ▁█▁▁ | 1 | = | 00/07 {13,3,17} [01] |-- 2605108489 █▁▁█ █▁██ ▁█▁▁ ▁██▁ ██▁▁ ██▁█ ▁▁▁▁ █▁▁█ | 6 | ====== | 01/07 {3,7,29} [01] |-- 2277213307 █▁▁▁ ▁███ █▁██ █▁██ █▁▁▁ ▁█▁▁ ▁███ █▁██ | 5 | ===== | 02/07 {5,27,25} [01] |-- 0501431633 ▁▁▁█ ██▁█ ███▁ ▁▁██ ▁▁██ ██▁█ ▁█▁█ ▁▁▁█ | 1 | = | 03/07 {3,5,25} [01] |-- 2200110444 █▁▁▁ ▁▁██ ▁▁█▁ ▁▁██ ▁▁▁▁ ▁█▁█ ▁██▁ ██▁▁ | 5 | ===== | 04/07 {4,3,27} [01] |-- 3962957830 ███▁ ██▁▁ ▁▁██ ▁█▁█ ████ ▁▁▁▁ ▁▁▁▁ ▁██▁ | 9 | ========= | 05/07 {9,5,25} [01] |-- 0680823645 ▁▁█▁ █▁▁▁ █▁▁█ ▁█▁▁ █▁▁▁ █▁██ ▁█▁█ ██▁█ | 1 | = | 06/07 {1,9,29} [01] |-- 2091282844 ▁███ ██▁▁ █▁█▁ ▁██▁ ▁███ ▁▁▁█ █▁▁█ ██▁▁ | 4 | ==== | 07/07 {15,1,29} [01] |-- 1468163377 ▁█▁█ ▁███ █▁▁▁ ▁▁█▁ ▁██▁ ▁█▁█ ▁▁██ ▁▁▁█ | 3 | === | 00/07 {13,3,17} [01] +-- 4215720994 ████ █▁██ ▁█▁▁ ▁██▁ ██▁▁ ██▁▁ ▁▁█▁ ▁▁█▁ | 9 | ========= | 01/07 {3,7,29} [02] 3048964962 █▁██ ▁█▁█ █▁██ █▁██ █▁▁▁ ▁▁██ ▁██▁ ▁▁█▁ | 8 [02] |-- 0528498992 ▁▁▁█ ████ █▁▁▁ ▁▁▁▁ ▁█▁▁ ▁▁▁█ ▁▁██ ▁▁▁▁ | 1 | = | 00/07 {13,3,17} [02] |-- 3678850091 ██▁█ █▁██ ▁█▁▁ ▁██▁ ██▁▁ ██▁▁ ▁▁█▁ █▁██ | 8 | ======== | 01/07 {3,7,29} [02] |-- 0029065272 ▁▁▁▁ ▁▁▁█ █▁██ █▁██ █▁▁▁ ▁▁▁▁ ▁▁██ █▁▁▁ | 0 | | 02/07 {5,27,25} [02] |-- 2044935267 ▁███ █▁▁█ ███▁ ▁▁██ ▁▁██ ██▁▁ ▁██▁ ▁▁██ | 4 | ==== | 03/07 {3,5,25} [02] |-- 0186844989 ▁▁▁▁ █▁██ ▁▁█▁ ▁▁██ ▁▁▁▁ ▁███ ▁▁██ ██▁█ | 0 | | 04/07 {4,3,27} [02] |-- 1983261643 ▁███ ▁██▁ ▁▁██ ▁██▁ ▁▁█▁ █▁██ ██▁▁ █▁██ | 4 | ==== | 05/07 {9,5,25} [02] |-- 2291435880 █▁▁▁ █▁▁▁ █▁▁█ ▁█▁▁ █▁▁▁ █▁▁█ ▁██▁ █▁▁▁ | 5 | ===== | 06/07 {1,9,29} [02] +-- 2620240011 █▁▁█ ██▁▁ ▁▁█▁ ██▁█ █▁██ ▁▁▁▁ █▁▁▁ █▁██ | 6 | ====== | 07/07 {15,1,29} [03] 65221214 ▁▁▁▁ ▁▁██ ███▁ ▁▁██ ▁▁██ ▁▁█▁ ▁█▁█ ███▁ | 3 [03] |-- 0470008044 ▁▁▁█ ██▁▁ ▁▁▁▁ ▁▁██ ██▁▁ ▁▁▁▁ ███▁ ██▁▁ | 1 | = | 00/07 {13,3,17} [03] |-- 2068234966 ▁███ █▁██ ▁█▁▁ ▁██▁ ██▁▁ ▁▁█▁ ██▁█ ▁██▁ | 4 | ==== | 01/07 {3,7,29} [03] +-- 0129744315 ▁▁▁▁ ▁███ █▁██ █▁██ █▁██ ██▁█ █▁██ █▁██ | 0 | | 02/07 {5,27,25} [04] 3676510983 ██▁█ █▁██ ▁▁█▁ ▁▁██ ▁▁▁█ █▁██ ▁▁▁▁ ▁███ | 9 [04] |-- 3559367935 ██▁█ ▁█▁▁ ▁▁█▁ ▁███ █▁█▁ ▁█▁▁ ████ ████ | 8 | ======== | 00/07 {13,3,17} [04] |-- 2068235134 ▁███ █▁██ ▁█▁▁ ▁██▁ ██▁▁ ▁▁██ ▁███ ███▁ | 4 | ==== | 01/07 {3,7,29} [04] |-- 3820731337 ███▁ ▁▁██ █▁██ █▁██ █▁██ █▁██ ██▁▁ █▁▁█ | 8 | ======== | 02/07 {5,27,25} [04] |-- 1071854400 ▁▁██ ████ ███▁ ▁▁██ ▁▁██ ▁▁██ ▁█▁▁ ▁▁▁▁ | 2 | == | 03/07 {3,5,25} [04] |-- 1394809270 ▁█▁█ ▁▁██ ▁▁█▁ ▁▁██ ▁▁▁█ █▁▁█ █▁██ ▁██▁ | 3 | === | 04/07 {4,3,27} [04] |-- 3627435164 ██▁█ █▁▁▁ ▁▁██ ▁██▁ ▁█▁▁ ▁█▁▁ █▁▁█ ██▁▁ | 8 | ======== | 05/07 {9,5,25} [04] |-- 1217694014 ▁█▁▁ █▁▁▁ █▁▁█ ▁█▁▁ █▁▁▁ █▁▁█ ▁▁██ ███▁ | 2 | == | 06/07 {1,9,29} [04] |-- 4231540896 ████ ██▁▁ ▁▁██ █▁▁▁ ▁▁██ ▁▁▁▁ █▁█▁ ▁▁▁▁ | 9 | ========= | 07/07 {15,1,29} [04] +-- 0344704172 ▁▁▁█ ▁█▁▁ █▁▁▁ █▁██ ██▁▁ ▁█▁▁ █▁█▁ ██▁▁ | 0 | | 00/07 {13,3,17} [05] 1043768303 ▁▁██ ███▁ ▁▁██ ▁██▁ █▁█▁ ▁▁██ ███▁ ████ | 4 [05] |-- 3968153771 ███▁ ██▁▁ █▁▁▁ ▁█▁█ ▁▁██ █▁▁▁ █▁█▁ █▁██ | 9 | ========= | 00/07 {13,3,17} [05] |-- 0457621557 ▁▁▁█ █▁██ ▁█▁▁ ▁██▁ ██▁▁ ▁▁▁▁ ▁▁██ ▁█▁█ | 1 | = | 01/07 {3,7,29} [05] |-- 1002157605 ▁▁██ █▁██ █▁██ █▁██ █▁██ ▁██▁ ▁▁█▁ ▁█▁█ | 2 | == | 02/07 {5,27,25} [05] +-- 2212704286 █▁▁▁ ▁▁██ ███▁ ▁▁██ ▁▁██ ▁▁▁▁ ▁▁▁█ ███▁ | 5 | ===== | 03/07 {3,5,25} [06] 3365177738 ██▁▁ █▁▁▁ █▁▁█ ▁█▁▁ █▁▁▁ █▁▁█ █▁▁▁ █▁█▁ | 9 [06] |-- 1822652601 ▁██▁ ██▁▁ █▁█▁ ▁▁██ ▁███ █▁▁▁ █▁██ █▁▁█ | 4 | ==== | 00/07 {13,3,17} [06] |-- 0994492580 ▁▁██ █▁██ ▁█▁▁ ▁██▁ ██▁▁ ▁▁▁▁ █▁█▁ ▁█▁▁ | 2 | == | 01/07 {3,7,29} [06] |-- 0465286197 ▁▁▁█ █▁██ █▁██ █▁██ █▁██ ▁█▁▁ ▁▁██ ▁█▁█ | 1 | = | 02/07 {5,27,25} [06] |-- 0736309578 ▁▁█▁ █▁██ ███▁ ▁▁██ ▁▁██ ▁▁▁█ ▁█▁▁ █▁█▁ | 1 | = | 03/07 {3,5,25} [06] |-- 2065898515 ▁███ █▁██ ▁▁█▁ ▁▁██ ▁▁▁█ ██▁▁ ▁▁▁█ ▁▁██ | 4 | ==== | 04/07 {4,3,27} [06] |-- 3828807938 ███▁ ▁█▁▁ ▁▁██ ▁██▁ ████ █▁▁█ ▁▁▁▁ ▁▁█▁ | 8 | ======== | 05/07 {9,5,25} [06] |-- 2828306881 █▁█▁ █▁▁▁ █▁▁█ ▁█▁▁ █▁▁▁ █▁▁█ ██▁▁ ▁▁▁█ | 6 | ====== | 06/07 {1,9,29} [06] |-- 2618159307 █▁▁█ ██▁▁ ▁▁▁▁ ██▁█ ████ ▁▁▁▁ ██▁▁ █▁██ | 6 | ====== | 07/07 {15,1,29} [06] +-- 1290234009 ▁█▁▁ ██▁▁ ███▁ ▁███ ▁██▁ █▁▁▁ █▁▁█ █▁▁█ | 3 | === | 00/07 {13,3,17} [07] 470544583 ▁▁▁█ ██▁▁ ▁▁▁▁ █▁██ ████ ▁▁▁▁ ██▁▁ ▁███ | 3 [07] |-- 1290234009 ▁█▁▁ ██▁▁ ███▁ ▁███ ▁██▁ █▁▁▁ █▁▁█ █▁▁█ | 3 | === | 00/07 {13,3,17} [07] |-- 4215718378 ████ █▁██ ▁█▁▁ ▁██▁ ██▁▁ ▁▁▁█ ███▁ █▁█▁ | 9 | ========= | 01/07 {3,7,29} [07] +-- 1404809361 ▁█▁█ ▁▁██ █▁██ █▁██ █▁██ ▁▁▁▁ █▁▁█ ▁▁▁█ | 3 | === | 02/07 {5,27,25} [08] 3846126715 ███▁ ▁█▁█ ▁▁██ ████ ▁▁██ ██▁▁ ▁███ █▁██ | 10 [08] |-- 2233764982 █▁▁▁ ▁█▁█ ▁▁█▁ ▁█▁▁ █▁▁▁ ██▁▁ ▁███ ▁██▁ | 5 | ===== | 00/07 {13,3,17} [08] |-- 0457623197 ▁▁▁█ █▁██ ▁█▁▁ ▁██▁ ██▁▁ ▁██▁ █▁▁█ ██▁█ | 1 | = | 01/07 {3,7,29} [08] |-- 4055608896 ████ ▁▁▁█ █▁██ █▁██ █▁█▁ ███▁ ▁█▁▁ ▁▁▁▁ | 9 | ========= | 02/07 {5,27,25} [08] |-- 3856873005 ███▁ ▁█▁█ ███▁ ▁▁██ ▁▁██ ▁██▁ ▁▁█▁ ██▁█ | 8 | ======== | 03/07 {3,5,25} [08] |-- 2736984776 █▁█▁ ▁▁██ ▁▁█▁ ▁▁██ ▁▁▁█ ▁▁█▁ ██▁▁ █▁▁▁ | 6 | ====== | 04/07 {4,3,27} [08] |-- 2184650417 █▁▁▁ ▁▁█▁ ▁▁██ ▁███ ▁▁▁█ ███▁ █▁██ ▁▁▁█ | 5 | ===== | 05/07 {9,5,25} [08] |-- 3902048403 ███▁ █▁▁▁ █▁▁█ ▁█▁▁ █▁▁▁ █▁▁▁ █▁▁█ ▁▁██ | 9 | ========= | 06/07 {1,9,29} [08] |-- 2085761140 ▁███ ██▁▁ ▁█▁█ ▁▁█▁ ▁▁██ ▁▁▁▁ ▁███ ▁█▁▁ | 4 | ==== | 07/07 {15,1,29} [08] |-- 1434412121 ▁█▁█ ▁█▁█ ▁███ ████ ▁██▁ ▁█▁▁ ▁█▁█ █▁▁█ | 3 | === | 00/07 {13,3,17} [08] +-- 0994494324 ▁▁██ █▁██ ▁█▁▁ ▁██▁ ██▁▁ ▁███ ▁███ ▁█▁▁ | 2 | == | 01/07 {3,7,29} [09] 3141977936 █▁██ █▁██ ▁█▁▁ ▁██▁ ██▁▁ ▁███ ▁█▁█ ▁▁▁▁ | 8 [09] |-- 3313183835 ██▁▁ ▁█▁█ ▁███ █▁██ ▁▁█▁ ██▁▁ ▁█▁█ █▁██ | 7 | ======= | 00/07 {13,3,17} [09] |-- 2068236134 ▁███ █▁██ ▁█▁▁ ▁██▁ ██▁▁ ▁███ ▁██▁ ▁██▁ | 4 | ==== | 01/07 {3,7,29} [09] |-- 2176559480 █▁▁▁ ▁▁▁█ █▁██ █▁██ █▁█▁ █▁▁█ ▁███ █▁▁▁ | 5 | ===== | 02/07 {5,27,25} [09] |-- 1608726384 ▁█▁█ ████ ███▁ ▁▁██ ▁▁██ ▁███ ▁███ ▁▁▁▁ | 3 | === | 03/07 {3,5,25} [09] |-- 3542290630 ██▁█ ▁▁██ ▁▁█▁ ▁▁██ ▁▁▁█ ▁▁▁▁ ██▁▁ ▁██▁ | 8 | ======== | 04/07 {4,3,27} [09] |-- 0339192186 ▁▁▁█ ▁█▁▁ ▁▁██ ▁███ █▁█▁ █▁▁█ ▁███ █▁█▁ | 0 | | 05/07 {9,5,25} [09] |-- 3902048299 ███▁ █▁▁▁ █▁▁█ ▁█▁▁ █▁▁▁ █▁▁▁ ▁▁█▁ █▁██ | 9 | ========= | 06/07 {1,9,29} [09] +-- 2625482795 █▁▁█ ██▁▁ ▁███ ██▁█ █▁██ ▁▁▁▁ ▁▁█▁ █▁██ | 6 | ====== | 07/07 {15,1,29} ## | xorshift | ## | GLib.Rand() 00 | 7782 | 00 | 690637 01 | 1651591439 | 01 | 47892204 02 | 18040456 | 02 | 11724168 03 | 140 | 03 | 9571 04 | 848238290 | 04 | 888756428 05 | 9125 | 05 | 703697669 06 | 421148663 | 06 | 560168398 07 | 393 | 07 | 2253334 08 | 5198659432 | 08 | 572437420 09 | 74538096 | 09 | 77288 mt | 280 μs | mt | 87 μs ch | ### | xorshift | ch | ### | GLib.Rand() 00 | 005 |███████████ | 00 | 005 |█████████ 01 | 009 |████████████████████ | 01 | 005 |█████████ 02 | 006 |█████████████ | 02 | 009 |████████████████ 03 | 007 |███████████████ | 03 | 007 |████████████ 04 | 009 |████████████████████ | 04 | 007 |████████████ 05 | 007 |███████████████ | 05 | 005 |█████████ 06 | 006 |█████████████ | 06 | 009 |████████████████ 07 | 003 |██████ | 07 | 011 |████████████████████ 08 | 008 |█████████████████ | 08 | 010 |██████████████████ 09 | 008 |█████████████████ | 09 | 006 |██████████
SEQUENCE
PACKSEQ

Get lists of ints in range by nth + offset, using max list size

Useful for threading x items over y threads.
Nth & offset useful for skipping items, like quoted parts of strings for example

PACKSEQ_SRC
packet[] packseq (int ind, int[] ix, int cc, bool qq, int mxp, int nth, int ofs, string mth, double[]? dx, double? gv, double? bv) { // distribute array items (or sequences) over n packets // by c.p.brown 2026 // // optional gain gv and bias bv to unevenly distribute items // optional dx parameter to override the 0.0~1.0 range, // otherwise the range defaults to packet/packetcount // ix = items to package // cc = item count // qq = use items if true, use items count if false, eg {2,12,34,43} vs {0,1,2,3} // mxp = max packets, usually thread-count // nth = nth item to package, eg {0,1,2,3,4,5} nth 2 is {0,2,4} // ofs = offset items, eg {0,1,2,3,4,5} offset 2 is {2,3,4,5}, {0,1,2,3,4,5} nth 2 offset 1 is {1,3,5} // mth = mode "" is uniform packets, "BIAS" uses biasgain // dx = overridden 0.0~1.0 range, instead of default linear range // gv = gain value if using BIAS // bv = bias value if using BIAS packet[] opk = {}; int[] srcitems = ix; int maxpackets = mxp; int nthsrc = nth; // nth int srcoffset = ofs; // offset int srclen = cc; int[] sampleditems = {}; int[] itempacket = {}; if (qq) { srclen = srcitems.length; for (int j = srcoffset; j < srclen; j += nthsrc) { sampleditems += srcitems[j]; } } else { for (int j = srcoffset; j < srclen; j += nthsrc) { sampleditems += j; } } if (sampleditems.length > maxpackets) { if (mth == "BIAS") { //print("sample length is %d\n",sampleditems.length); int lastpacket = (maxpackets - 1); double w = (double) lastpacket; //int qb = 0; int sl = sampleditems.length; int ll = sampleditems.length - 1; int rl = sl - maxpackets; int rll = rl - 1; //print("sample length - packet length is %d\n",rl); double s = 0.8; double f = 1.0; if (gv != null) { s = double.max(0.0,double.min(1.0,gv)); //print("s is %.2f\n",s); } if (bv != null) { f = double.max(0.0,double.min(1.0,bv)); //print("f is %.2f\n",f); } int totalcount = 0; for (int i = 0; i < maxpackets; i++) { itempacket += 1; totalcount += 1; } double[] biases = {}; double totalbias = 0.0; if ((dx != null) && (dx.length >= maxpackets)) { for (int n = 0; n < maxpackets; n++) { double x = dx[n] / w; double g = biasgain(x,s,f); biases += g; totalbias += g; } } else { for (int n = 0; n < maxpackets; n++) { double x = (n * 1.0) / w; double g = biasgain(x,s,f); biases += g; totalbias += g; } } //print("total bias is %.2f\n",totalbias); //print("(1.0 / %.2f) * %d is %d\n",totalbias,rl,((int) Math.round((1.0 / totalbias) * rl))); for (int n = 0; n < maxpackets; n++) { int bar = (int) Math.round((biases[n] / totalbias) * rl); itempacket[n] += bar; totalcount += bar; } //print("totalcount is %d, sample length is %d\n",totalcount,sl); //print("correcting %d rounding errors...\n",(sl - totalcount).abs()); while (totalcount < sl) { itempacket[lastpacket] += 1; totalcount += 1; } while (totalcount > sl) { itempacket[lastpacket] -= 1; totalcount -= 1; } //print("totalcount is %d\n",totalcount); //int il = itempacket.length; //for (int k = 0; k < il; k++) { // string plot = ""; // for (int j = 0; j < itempacket[k]; j++) { // plot = plot + "█"; // } // print("[%d] bias=%.2f, count=%02d, rl=%d | %s\n",k,biases[k],itempacket[k],rl,plot); //} int u = 0; for (int i = 0; i < maxpackets; i++) { opk += new packet(); for (int k = 0; k < itempacket[i]; k++) { opk[i].items += sampleditems[u]; u += 1; } } return opk; } else { int t = (sampleditems.length / maxpackets); int dreg = 0; double dp = ((double) maxpackets); double npt = ((double) sampleditems.length) / ((double) maxpackets); int v = 0; int x = 0; if ((double) t < npt) { double rem = npt - t; x = ((int) Math.round(rem * dp)); } for (int i = 0; i < maxpackets; i++) { opk += new packet(); int aa = v; v += (t - 1); if (x > 0) { v += 1; } for (int j = aa; j <= v; j++) { opk[(opk.length - 1)].items += sampleditems[j]; } v += 1; x = int.max(0,(x - 1)); } return opk; } } else { // one item per packet for (int k = 0; k < sampleditems.length; k++) { packet oo = new packet(); oo.items += sampleditems[k]; opk += oo; } return opk; } packet[] ov = new packet[0]; return ov; }
PACKSEQ_TEST
// packseq test // by cpbrown 2026 struct packet { public int[] items; } string printintarray (int[] s, int f, int w) { string[] ii = {"", "\"", "{", "[", "[", "| ", "", ""}; string[] dd = {";", ",", ",", " ", ",", " | ", " ", "\n"}; string[] oo = {"", "\"", "}", "]", "]", " |", "", ""}; string o = ii[f]; for (int i = 0; i < (s.length - 1); i++) { o = (o + "%0*d".printf(w,s[i]) + dd[f]); } o = (o + "%0*d".printf(w,s[s.length - 1]) + oo[f]); return o; } double biasgain (double x, double g, double s) { // biasgain // by c.p.brown 2026 // // this is derivative of: // Christophe Schlick // https://dept-info.labri.fr/~schlick/DOC/gem2.html // Jonathan T Barron // https://ar5iv.labs.arxiv.org/html/2010.09714 // Thomas Mann // https://github.com/tixl3d/tixl/blob/main/Core/Utils/MathUtils.cs double o = 0.0; double e = double.EPSILON; double r = 200.0; double b = s * 2.0; //double t = f; if (b < 1.0) { b = Math.pow(r,(1.0 - b)); } else { b = (1.0 / Math.pow(r,(b - 1.0))); } if (x < g) { o = ((g * x) / ((x + (b * (g - x))) + e)); } else { o = ((((1.0 - g) * (x - 1.0)) / (((1.0 - x) - (b * (g - x))) + e)) + 1.0); } return o; } packet[] packseq (int ind, int[] ix, int cc, bool qq, int mxp, int nth, int ofs, string mth, double[]? dx, double? gv, double? bv) { // distribute array items (or sequences) over n packets // by c.p.brown 2026 // // optional gain gv and bias bv to unevenly distribute items // optional dx parameter to override the 0.0~1.0 range, // otherwise the range defaults to packet/packetcount // ix = items to package // cc = item count // qq = use items if true, use items count if false, eg {2,12,34,43} vs {0,1,2,3} // mxp = max packets, usually thread-count // nth = nth item to package, eg {0,1,2,3,4,5} nth 2 is {0,2,4} // ofs = offset items, eg {0,1,2,3,4,5} offset 2 is {2,3,4,5}, {0,1,2,3,4,5} nth 2 offset 1 is {1,3,5} // mth = mode "" is uniform packets, "BIAS" uses biasgain // dx = overridden 0.0~1.0 range, instead of default linear range // gv = gain value if using BIAS // bv = bias value if using BIAS packet[] opk = {}; int[] srcitems = ix; int maxpackets = mxp; int nthsrc = nth; // nth int srcoffset = ofs; // offset int srclen = cc; int[] sampleditems = {}; int[] itempacket = {}; if (qq) { srclen = srcitems.length; for (int j = srcoffset; j < srclen; j += nthsrc) { sampleditems += srcitems[j]; } } else { for (int j = srcoffset; j < srclen; j += nthsrc) { sampleditems += j; } } if (sampleditems.length > maxpackets) { if (mth == "BIAS") { //print("sample length is %d\n",sampleditems.length); int lastpacket = (maxpackets - 1); double w = (double) lastpacket; //int qb = 0; int sl = sampleditems.length; int ll = sampleditems.length - 1; int rl = sl - maxpackets; int rll = rl - 1; //print("sample length - packet length is %d\n",rl); double s = 0.8; double f = 1.0; if (gv != null) { s = double.max(0.0,double.min(1.0,gv)); //print("s is %.2f\n",s); } if (bv != null) { f = double.max(0.0,double.min(1.0,bv)); //print("f is %.2f\n",f); } int totalcount = 0; for (int i = 0; i < maxpackets; i++) { itempacket += 1; totalcount += 1; } double[] biases = {}; double totalbias = 0.0; if ((dx != null) && (dx.length >= maxpackets)) { for (int n = 0; n < maxpackets; n++) { double x = dx[n] / w; double g = biasgain(x,s,f); biases += g; totalbias += g; } } else { for (int n = 0; n < maxpackets; n++) { double x = (n * 1.0) / w; double g = biasgain(x,s,f); biases += g; totalbias += g; } } //print("total bias is %.2f\n",totalbias); //print("(1.0 / %.2f) * %d is %d\n",totalbias,rl,((int) Math.round((1.0 / totalbias) * rl))); for (int n = 0; n < maxpackets; n++) { int bar = (int) Math.round((biases[n] / totalbias) * rl); itempacket[n] += bar; totalcount += bar; } //print("totalcount is %d, sample length is %d\n",totalcount,sl); //print("correcting %d rounding errors...\n",(sl - totalcount).abs()); while (totalcount < sl) { itempacket[lastpacket] += 1; totalcount += 1; } while (totalcount > sl) { itempacket[lastpacket] -= 1; totalcount -= 1; } //print("totalcount is %d\n",totalcount); //int il = itempacket.length; //for (int k = 0; k < il; k++) { // string plot = ""; // for (int j = 0; j < itempacket[k]; j++) { // plot = plot + "█"; // } // print("[%d] bias=%.2f, count=%02d, rl=%d | %s\n",k,biases[k],itempacket[k],rl,plot); //} int u = 0; for (int i = 0; i < maxpackets; i++) { opk += new packet(); for (int k = 0; k < itempacket[i]; k++) { opk[i].items += sampleditems[u]; u += 1; } } return opk; } else { int t = (sampleditems.length / maxpackets); int dreg = 0; double dp = ((double) maxpackets); double npt = ((double) sampleditems.length) / ((double) maxpackets); int v = 0; int x = 0; if ((double) t < npt) { double rem = npt - t; x = ((int) Math.round(rem * dp)); } for (int i = 0; i < maxpackets; i++) { opk += new packet(); int aa = v; v += (t - 1); if (x > 0) { v += 1; } for (int j = aa; j <= v; j++) { opk[(opk.length - 1)].items += sampleditems[j]; } v += 1; x = int.max(0,(x - 1)); } return opk; } } else { // one item per packet for (int k = 0; k < sampleditems.length; k++) { packet oo = new packet(); oo.items += sampleditems[k]; opk += oo; } return opk; } packet[] ov = new packet[0]; return ov; } void main() { GLib.Intl.setlocale(ALL,""); int[] nup = new int[0]; packet[] p = packseq(0,nup,30,false,16,1,0,"",null,null,null); print("packet.length is %d\n",p.length); print("sample.length is %d\n",30); for (int x = 0; x < p.length; x++) { print("[%03d/%03d] %s\n",x,(p.length - 1),printintarray(p[x].items,2,2)); } print("\n"); nup.resize(0); for (int i = 0; i < 50; i++) { nup += i; } p = packseq(0,nup,nup.length,true,6,1,0,"",null,null,null); print("packet.length is %d\n",p.length); print("sample.length is %d\n",nup.length); for (int x = 0; x < p.length; x++) { print("[%03d/%03d] %s\n",x,(p.length - 1),printintarray(p[x].items,2,2)); } print("\n"); nup.resize(0); for (int i = 0; i < 100; i++) { nup += i; } p = packseq(0,nup,nup.length,true,10,1,0,"BIAS",null,0.0,0.7); print("packet.length is %d\n",p.length); print("sample.length is %d\n",nup.length); for (int x = 0; x < p.length; x++) { print("[%03d/%03d] %s\n",x,(p.length - 1),printintarray(p[x].items,2,2)); } print("\n"); p = packseq(0,nup,nup.length,true,10,1,0,"BIAS",null,0.0,0.3); print("packet.length is %d\n",p.length); print("sample.length is %d\n",nup.length); for (int x = 0; x < p.length; x++) { print("[%03d/%03d] %s\n",x,(p.length - 1),printintarray(p[x].items,2,2)); } print("\n"); p = packseq(0,nup,nup.length,true,10,1,0,"BIAS",null,0.5,0.3); print("packet.length is %d\n",p.length); print("sample.length is %d\n",nup.length); for (int x = 0; x < p.length; x++) { print("[%03d/%03d] %s\n",x,(p.length - 1),printintarray(p[x].items,2,2)); } print("\n"); p = packseq(0,nup,nup.length,true,10,1,0,"BIAS",null,0.5,0.7); print("packet.length is %d\n",p.length); print("sample.length is %d\n",nup.length); for (int x = 0; x < p.length; x++) { print("[%03d/%03d] %s\n",x,(p.length - 1),printintarray(p[x].items,2,2)); } print("\n"); }
#+RESULTS:
Compilation succeeded - 7 warning(s) packet.length is 16 sample.length is 30 [000/015] {00,01} [001/015] {02,03} [002/015] {04,05} [003/015] {06,07} [004/015] {08,09} [005/015] {10,11} [006/015] {12,13} [007/015] {14,15} [008/015] {16,17} [009/015] {18,19} [010/015] {20,21} [011/015] {22,23} [012/015] {24,25} [013/015] {26,27} [014/015] {28} [015/015] {29} packet.length is 6 sample.length is 50 [000/005] {00,01,02,03,04,05,06,07,08} [001/005] {09,10,11,12,13,14,15,16,17} [002/005] {18,19,20,21,22,23,24,25} [003/005] {26,27,28,29,30,31,32,33} [004/005] {34,35,36,37,38,39,40,41} [005/005] {42,43,44,45,46,47,48,49} packet.length is 10 sample.length is 100 [000/009] {00} [001/009] {01,02} [002/009] {03,04} [003/009] {05,06,07} [004/009] {08,09,10,11} [005/009] {12,13,14,15,16,17} [006/009] {18,19,20,21,22,23,24,25,26} [007/009] {27,28,29,30,31,32,33,34,35,36,37,38,39} [008/009] {40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59} [009/009] {60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99} packet.length is 10 sample.length is 100 [000/009] {00} [001/009] {01,02,03,04,05,06,07} [002/009] {08,09,10,11,12,13,14,15,16} [003/009] {17,18,19,20,21,22,23,24,25,26} [004/009] {27,28,29,30,31,32,33,34,35,36,37} [005/009] {38,39,40,41,42,43,44,45,46,47,48,49} [006/009] {50,51,52,53,54,55,56,57,58,59,60,61} [007/009] {62,63,64,65,66,67,68,69,70,71,72,73} [008/009] {74,75,76,77,78,79,80,81,82,83,84,85,86} [009/009] {87,88,89,90,91,92,93,94,95,96,97,98,99} packet.length is 10 sample.length is 100 [000/009] {00} [001/009] {01} [002/009] {02,03} [003/009] {04,05,06} [004/009] {07,08,09,10,11} [005/009] {12,13,14,15,16,17,18,19,20,21,22,23,24,25,26} [006/009] {27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43} [007/009] {44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61} [008/009] {62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80} [009/009] {81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99} packet.length is 10 sample.length is 100 [000/009] {00} [001/009] {01,02,03,04,05,06,07} [002/009] {08,09,10,11,12,13,14,15,16} [003/009] {17,18,19,20,21,22,23,24,25} [004/009] {26,27,28,29,30,31,32,33,34,35} [005/009] {36,37,38,39,40,41,42,43,44,45} [006/009] {46,47,48,49,50,51,52,53,54,55,56} [007/009] {57,58,59,60,61,62,63,64,65,66,67} [008/009] {68,69,70,71,72,73,74,75,76,77,78,79,80} [009/009] {81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99}
RANGESEQ

Break seqential range into n packets, return in/out indices only.

RANGESEQ_SRC
int[] rangeseq (int p, int s) { // rangeseq // by c.p.brown 2026 // // p packet count, s sequence count // returns rangefrom,rangeto pairs in an unrolled 1d array int[] o = {}; if (s > p) { int t = s / p; double dp = ((double) p); double npt = ((double) s) / ((double) p); int v = 0; int x = 0; if ((double) t < npt) { double rem = npt - t; x = ((int) Math.round(rem * dp)); } for (int i = 0; i < p; i++) { o += v; v += (t - 1); if (x > 0) { v += 1; } o += v; v += 1; x = int.max(0,(x - 1)); } } else { for (int i = 0; i < s; i++) { o += i; o += i; } } return o; }
RANGESEQ_TEST
// rangeseq test // by c.p.brown 2026 string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } int[] rangeseq (int p, int s) { // rangeseq // by c.p.brown 2026 // // p packet count, s sequence count // returns rangefrom,rangeto pairs in an unrolled 1d array int[] o = {}; if (s > p) { int t = s / p; double dp = ((double) p); double npt = ((double) s) / ((double) p); int v = 0; int x = 0; if ((double) t < npt) { double rem = npt - t; x = ((int) Math.round(rem * dp)); } for (int i = 0; i < p; i++) { o += v; v += (t - 1); if (x > 0) { v += 1; } o += v; v += 1; x = int.max(0,(x - 1)); } } else { for (int i = 0; i < s; i++) { o += i; o += i; } } return o; } void main() { int64 tts = GLib.get_monotonic_time(); GLib.Intl.setlocale(ALL,""); int[] sq = rangeseq(7,29); print("rangeseq returns %d sequences\n",(sq.length / 2)); int sqc = sq.length; int n = 0; for (int i = 0; i < sqc; i += 2) { print("[%03d] %03d..%03d (%d)\n",n,sq[i],sq[i+1],((sq[i+1]+1)-sq[i])); n += 1; } int64 tte = GLib.get_monotonic_time(); print("rangeseq test took %s\n",printusecs(tte - tts)); }
#+RESULTS:
rangeseq returns 7 sequences [000] 000..004 (5) [001] 005..008 (4) [002] 009..012 (4) [003] 013..016 (4) [004] 017..020 (4) [005] 021..024 (4) [006] 025..028 (4) rangeseq test took 64 μs
SEARCH
FINDINSTRING
FINDINSTRING_INF

Returns indices of string[] that contain a search pattern.

Construction:

findstring fs = new findinstring(int itr, int s, int e, string p, bool nc, bool wc);

  • int itr is the current packet number
  • int s is the first index of string[] to search (see Usage below)
  • int e is the last index of string[] to search
  • string p is the pattern to search with
  • bool nc is to ignore case when searching (slower)
  • bool wc is to use "*" as a wildcard in the pattern

Usage:

fc.run(ref int pc, string[] s, uint8[] rm);

  • ref int pc is the packet-complete counter that may be used to wait for all packets when multithreading
  • string[] s contains the strings to search
  • uint8[] rm stores 1 at index if the row at index contains a match

uint8[] rm must be initialized to the length of string[] s with values of 0. rm may then be used to build an integer array of row indices, or used directly.

FINDINSTRING_SRC
public class FindInString : Object { private int first; private int last; private int packetnum; private string pattern; private bool nocase; private bool wildcard; private string[] patterns; private int patterncount; private bool isvalid; public FindInString ( int itr, int s, int e, string p, bool nc, bool wc ) { packetnum = itr; first = s; last = e; nocase = nc; if (nocase) { pattern = p.up(); } else { pattern = p.dup(); } wildcard = wc; patterns = {}; isvalid = (pattern.char_count() > 0); isvalid = (isvalid && (first <= last)); if (isvalid && wildcard) { int ii = pattern.index_of_char('*'); if (ii > -1) { string[] px = pattern.split("*"); foreach (string x in px) { if (x != "") { patterns += x; } } patterncount = patterns.length; // handle patterns like "******" if (patterncount == 0) { isvalid = false; } } else { wildcard = false; } } } public void run(ref int pc, string[] s, uint8[] rm) { if (isvalid) { int sl = s.length; int rl = rm.length; if (sl != rl) { print("FindInString fatal error: string[] s.length %d !- uint8[] rm.length %d. Aborting...\n",sl,rl); assert(false); } if (last >= sl) { print("FindInString fatal error: last item %d >= string[] s.length %d, Aborting...\n",last,sl); assert(false); } for (int r = first; r <= last; r++) { if (nocase) { StringBuilder sb = new StringBuilder(""); sb.append(s[r].up()); if (sb.str != "") { if (wildcard) { int i = 0; int c = 0; foreach (string p in patterns) { i = sb.str.index_of(p,i); if (i > -1) {i += 1; c += 1; } } if (c == patterncount) { rm[r] = 1; } } else { int i = sb.str.index_of(pattern); if (i > -1) { rm[r] = 1; } } } } else { // case-sensitive search if (s[r] != "") { if (wildcard) { int i = 0; int c = 0; foreach (string p in patterns) { i = s[r].index_of(p,i); if (i > -1) {i += 1; c += 1; } } if (c == patterncount) { rm[r] = 1; } } else { int i = s[r].index_of(pattern); if (i > -1) { rm[r] = 1; } } } } } } mutex.lock(); pc += 1; mutex.unlock(); } }
FINSINSTRING_TEST
GLib.Mutex mutex; string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } int[] rangeseq (int p, int s) { // rangeseq // by c.p.brown 2026 // // p packet count, s sequence count // returns rangefrom,rangeto pairs in an unrolled 1d array int[] o = {}; if (s > p) { int t = s / p; double dp = ((double) p); double npt = ((double) s) / ((double) p); int v = 0; int x = 0; if ((double) t < npt) { double rem = npt - t; x = ((int) Math.round(rem * dp)); } for (int i = 0; i < p; i++) { o += v; v += (t - 1); if (x > 0) { v += 1; } o += v; v += 1; x = int.max(0,(x - 1)); } } else { for (int i = 0; i < s; i++) { o += i; o += i; } } return o; } public class FindInString : Object { private int first; private int last; private int packetnum; private string pattern; private bool nocase; private bool wildcard; private string[] patterns; private int patterncount; private bool isvalid; public FindInString ( int itr, int s, int e, string p, bool nc, bool wc ) { packetnum = itr; first = s; last = e; nocase = nc; if (nocase) { pattern = p.up(); } else { pattern = p.dup(); } wildcard = wc; patterns = {}; isvalid = (pattern.char_count() > 0); isvalid = (isvalid && (first <= last)); if (isvalid && wildcard) { int ii = pattern.index_of_char('*'); if (ii > -1) { string[] px = pattern.split("*"); foreach (string x in px) { if (x != "") { patterns += x; } } patterncount = patterns.length; // handle patterns like "******" if (patterncount == 0) { isvalid = false; } } else { wildcard = false; } } } public void run(ref int pc, string[] s, uint8[] rm) { if (isvalid) { int sl = s.length; int rl = rm.length; if (sl != rl) { print("FindInString fatal error: string[] s.length %d !- uint8[] rm.length %d. Aborting...\n",sl,rl); assert(false); } if (last >= sl) { print("FindInString fatal error: last item %d >= string[] s.length %d, Aborting...\n",last,sl); assert(false); } for (int r = first; r <= last; r++) { if (nocase) { StringBuilder sb = new StringBuilder(""); sb.append(s[r].up()); if (sb.str != "") { if (wildcard) { int i = 0; int c = 0; foreach (string p in patterns) { i = sb.str.index_of(p,i); if (i > -1) {i += 1; c += 1; } } if (c == patterncount) { rm[r] = 1; } } else { int i = sb.str.index_of(pattern); if (i > -1) { rm[r] = 1; } } } } else { // case-sensitive search if (s[r] != "") { if (wildcard) { int i = 0; int c = 0; foreach (string p in patterns) { i = s[r].index_of(p,i); if (i > -1) {i += 1; c += 1; } } if (c == patterncount) { rm[r] = 1; } } else { int i = s[r].index_of(pattern); if (i > -1) { rm[r] = 1; } } } } } } mutex.lock(); pc += 1; mutex.unlock(); } } string[] readfiletostrings (string p) { string[] o = {}; GLib.FileStream fs; try { fs = GLib.FileStream.open(p,"r"); StringBuilder sb = new StringBuilder(""); while (true) { string l = fs.read_line(); if (l == null) { break; } sb.erase(); sb.append(l.dup()); o += sb.str; } } catch (Error e) { print("file error: %s\n",e.message); } return o; } void main() { mutex = new GLib.Mutex(); GLib.Intl.setlocale(ALL,""); int packetscomplete = 0; string[] s = { "find 零 in this string that contains 零 in it...", "Find 零, or Not", "anything between 零 and words up to This is ok", "零th 零 In five words", "only zer0 in here" }; int ll = s.length - 1; uint8[] rm = {}; print("\ncase-insensitive wildcard:\n"); string p = "零* t"; for (int i = 0; i < s.length; i++) { rm += 0; } FindInString fs = new FindInString(0,0,ll,p,true,true); fs.run(ref packetscomplete,s,rm); for (int i = 0; i < rm.length; i++) { if (rm[i] > 0) { print("string[%d] contains \"%s\" : \"%s\"\n",i,p,s[i]); } } print("\ncase-sensitive wildcard:\n"); p = "F*零*N"; for (int i = 0; i < s.length; i++) { rm[i] = (uint8) 0; } fs = new FindInString(0,0,ll,p,false,true); fs.run(ref packetscomplete,s,rm); for (int i = 0; i < rm.length; i++) { if (rm[i] > 0) { print("string[%d] contains \"%s\" : \"%s\"\n",i,p,s[i]); } } print("\ncase-sensitive no wildcard:\n"); p = "零 I"; for (int i = 0; i < s.length; i++) { rm[i] = (uint8) 0; } fs = new FindInString(0,0,ll,p,false,false); fs.run(ref packetscomplete,s,rm); for (int i = 0; i < rm.length; i++) { if (rm[i] > 0) { print("string[%d] contains \"%s\" : \"%s\"\n",i,p,s[i]); } } print("\ncase-insensitive no wildcard:\n"); p = "零 I"; for (int i = 0; i < s.length; i++) { rm[i] = (uint8) 0; } fs = new FindInString(0,0,ll,p,true,false); fs.run(ref packetscomplete,s,rm); for (int i = 0; i < rm.length; i++) { if (rm[i] > 0) { print("string[%d] contains \"%s\" : \"%s\"\n",i,p,s[i]); } } print("\nno-natch test:\n"); p = "Xerxes"; for (int i = 0; i < s.length; i++) { rm[i] = (uint8) 0; } fs = new FindInString(0,0,ll,p,true,false); fs.run(ref packetscomplete,s,rm); for (int i = 0; i < rm.length; i++) { if (rm[i] > 0) { print("string[%d] contains \"%s\" : \"%s\"\n",i,p,s[i]); } } print("\nstresstest: find \"Austral*fish\" in leipzig1M.txt:\n"); s = readfiletostrings("./testdata/leipzig1M.txt"); int64 tts = GLib.get_monotonic_time(); int sl = s.length; rm.resize(0); for (int i = 0; i < sl; i++) { rm += 0; } int nthr = int.max(1,((int) GLib.get_num_processors())); int[] rowranges = rangeseq(nthr,sl); p = "Austral*fish"; packetscomplete = 0; ThreadPool<FindInString> fstr = new ThreadPool<FindInString>.with_owned_data((FindInString) => { FindInString.run(ref packetscomplete, s, rm); },nthr,false); int rc = 0; for (int x = 0; x < rowranges.length; x += 2) { fstr.add( new FindInString( rc, rowranges[x], rowranges[x+1], p, false, true )); rc += 1; } while (packetscomplete != rc) { GLib.Thread.usleep(1); } int[] ridx = {}; for (int i = 0; i < sl; i++) { if (rm[i] == 1) { ridx += i; } } int rxl = ridx.length; int64 tte = GLib.get_monotonic_time(); print("FindInString stress test took %s\n",printusecs(tte-tts)); print("found %d strings containing \"%s\" in leipzig1M.txt\n\n",rxl,p); if (rxl < 11) { for (int i = 0; i < rxl; i++) { print("[%d] {%s}\n",ridx[i],s[ridx[i]]); } } print("\nstresstest: find \"零\" in leipzig1M.txt:\n"); //s = readfiletostrings("./testdata/leipzig1M.txt"); //int sl = s.length; tts = GLib.get_monotonic_time(); rm.resize(0); for (int i = 0; i < sl; i++) { rm += 0; } //int nthr = int.max(1,((int) GLib.get_num_processors())); rowranges = rangeseq(nthr,sl); p = "零"; packetscomplete = 0; ThreadPool<FindInString> fstrz = new ThreadPool<FindInString>.with_owned_data((FindInString) => { FindInString.run(ref packetscomplete, s, rm); },nthr,false); rc = 0; for (int x = 0; x < rowranges.length; x += 2) { fstrz.add( new FindInString( rc, rowranges[x], rowranges[x+1], p, false, true )); rc += 1; } while (packetscomplete != rc) { GLib.Thread.usleep(1); } ridx.resize(0); for (int i = 0; i < sl; i++) { if (rm[i] == 1) { ridx += i; } } rxl = ridx.length; tte = GLib.get_monotonic_time(); print("FindInString stress test took %s\n",printusecs(tte-tts)); print("found %d strings containing \"%s\" in leipzig1M.txt\n\n",rxl,p); if (rxl < 11) { for (int i = 0; i < rxl; i++) { print("[%d] {%s}\n",ridx[i],s[ridx[i]]); } } }
#+RESULTS:
Compilation succeeded - 6 warning(s) case-insensitive wildcard: string[0] contains "零* t" : "find 零 in this string that contains 零 in it..." string[2] contains "零* t" : "anything between 零 and words up to This is ok" case-sensitive wildcard: string[1] contains "F*零*N" : "Find 零, or Not" case-sensitive no wildcard: string[3] contains "零 I" : "零th 零 In five words" case-insensitive no wildcard: string[0] contains "零 I" : "find 零 in this string that contains 零 in it..." string[3] contains "零 I" : "零th 零 In five words" no-natch test: stresstest: find "Austral*fish" in leipzig1M.txt: FindInString stress test took 12.60 ms found 2 strings containing "Austral*fish" in leipzig1M.txt [377878] {Thousands of pelicans have died of starvation as an oasis in Australia's harsh outback country begins to dry up, killing fish the birds feed on, officials say.} [394105] {The royal Dutch navy's HMS Witte de With was on its way from Australia to the Netherlands when it found the four in the sea Tuesday after their fishing boat sank, the embassy said.} stresstest: find "零" in leipzig1M.txt: FindInString stress test took 9.16 ms found 0 strings containing "零" in leipzig1M.txt
FILTERARRAY
FILTERARRAY_INF

Remove items from string[] a using indices in int[] b, and compact a.
b is copied to int[] c, which is sorted using hybrid quicksort/shellsort, unless bool s is false. b must be sorted for this function to work as expected.

Usage:
filterarray(ref string[] a, int[] b, bool s);
  • ref string[] a is the string to edit. ref allows this function to resize it.
  • int[] b is the list of indices to remove, it must be sorted for this function to work correctly, it is checked for out-of-bounds indices and empties.
  • bool s is to tell this function to sort b if true, or use it as-is if false, assuming b is already sorted.

FILTERARRAY_SRC
public void filterarray (ref string[] a, int[] b, bool s) { // remove items from array by index // by c.p.brown 2026 int bl = b.length; if (bl == 0) { return; } int al = a.length; int[] c = {}; for (int i = 0; i < bl; i++) { if (b[i] < al) { c += b[i]; } } bl = c.length; if (bl == 0) { return; } if ((bl > 1) && s) { intshellsort(c,false); } int la = al - 1; int lb = bl - 1; int k = 1; int nx = la + 1; if (bl > 1) { nx = c[1]; k = 1; } int x = c[0]; int p = x + 1; int r = 0; while (p <= la) { //print("X%d NX%d P%d\n",x,nx,p); if (p < nx) { //print("\ta[%d] <- a[%d] %s <- %s ",x,p,a[x],a[p]); a[x] = a[p]; x += 1; } else { k += 1; r += 1; if (k > lb) { nx = (la + 1); } else { nx = c[k]; } //print("\tX%d NX%d P%d\n",x,nx,p); } p += 1; //print("\n"); } if (c[0] > la) { k = 0; } //print("R%d\n",(a.length - k)); a.resize(a.length - k); }
FILTERARRAY_TEST
// test filterarray in-place array item removal // by c.p.brown 2026 string printintarray (int[] s, int f, int w) { string[] ii = {"", "\"", "{", "[", "[", "| ", "", ""}; string[] dd = {";", ",", ",", " ", ",", " | ", " ", "\n"}; string[] oo = {"", "\"", "}", "]", "]", " |", "", ""}; string o = ii[f]; for (int i = 0; i < (s.length - 1); i++) { o = (o + "%0*d".printf(w,s[i]) + dd[f]); } o = (o + "%0*d".printf(w,s[s.length - 1]) + oo[f]); return o; } string printstringarray (string[] s, int f) { // 0 1 2 3 4 5 6 7 8 9 string[] ii = {"", "\"", "{", "{\"", "[", "[", "| ", "", "", ""}; string[] dd = {";", ",", ",", "\",\"", " ", ",", " | ", " ", "\n", ",\n"}; string[] oo = {"", "\"", "}", "\"}", "]", "]", " |", "", "", ""}; string o = ii[f]; for (int i = 0; i < (s.length - 1); i++) { o = (o + "%s".printf(s[i]) + dd[f]); } o = (o + "%s".printf(s[s.length - 1]) + oo[f]); return o; } int[] makeleegaps(int n) { int thn = int.min((n / 3),(int32.MAX / 3)); int[] spag = {}; int l = 1; while (l < 100) { int g = (int) Math.floor( Math.pow(2.243609061420001,((double) l)) / (2.243609061420001 - 1.0) ); if (g > thn) { break; } spag += g; l += 1; } //print("makeleegaps l is %d\n",l); int ll = spag.length - 1; if (ll > -1) { int[] gaps = new int[(ll+1)]; for (int i = ll; i >= 0; i--) { gaps[ll-i] = spag[i]; } return gaps; } return {331490,147748,65853,29351,13082,5830,2598,1158,516,230,102,45,20,9,4,1}; } void intshellsort (int[] p, bool r) { // sort p, reverse if r if (p.length > 0) { int[] gaps = makeleegaps(p.length); foreach (int g in gaps) { for (int i = g; i < p.length; i++) { int t = p[i]; int j = i; bool cond = true; while (cond) { if (j < g) { break; } if (r) { cond = (p[j - g] < t); } else { cond = (p[j - g] > t); } if (cond) { p[j] = p[j - g]; j -= g; } } p[j] = t; } } } } public void filterarray (ref string[] a, int[] b, bool s) { // remove items from array by index // by c.p.brown 2026 int bl = b.length; if (bl == 0) { return; } int al = a.length; int[] c = {}; for (int i = 0; i < bl; i++) { if (b[i] < al) { c += b[i]; } } bl = c.length; if (bl == 0) { return; } if ((bl > 1) && s) { intshellsort(c,false); } int la = al - 1; int lb = bl - 1; int k = 1; int nx = la + 1; if (bl > 1) { nx = c[1]; k = 1; } int x = c[0]; int p = x + 1; int r = 0; while (p <= la) { //print("X%d NX%d P%d\n",x,nx,p); if (p < nx) { //print("\ta[%d] <- a[%d] %s <- %s ",x,p,a[x],a[p]); a[x] = a[p]; x += 1; } else { k += 1; r += 1; if (k > lb) { nx = (la + 1); } else { nx = c[k]; } //print("\tX%d NX%d P%d\n",x,nx,p); } p += 1; //print("\n"); } if (c[0] > la) { k = 0; } //print("R%d\n",(a.length - k)); a.resize(a.length - k); } void main() { string[] a = {"ZERO","ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN"}; int[] b = {0,2,5,6}; print("removing items %s\nfrom %s\n",printintarray(b,2,0),printstringarray(a,2)); filterarray(ref a,b,false); for (int i = 0; i < a.length; i++) { print("[%d] %s\n",i,a[i]); } a = {"ZERO","ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN"}; b = {0,1,6,7}; print("\nremoving items %s\nfrom %s\n",printintarray(b,2,0),printstringarray(a,2)); filterarray(ref a,b,false); for (int i = 0; i < a.length; i++) { print("[%d] %s\n",i,a[i]); } a = {"ZERO","ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN"}; b = {2,3,4,5}; print("\nremoving items %s\nfrom %s\n",printintarray(b,2,0),printstringarray(a,2)); filterarray(ref a,b,true); for (int i = 0; i < a.length; i++) { print("[%d] %s\n",i,a[i]); } a = {"ZERO","ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN"}; b = {5,0,3,1}; print("\nremoving items %s\nfrom %s\n",printintarray(b,2,0),printstringarray(a,2)); filterarray(ref a,b,true); for (int i = 0; i < a.length; i++) { print("[%d] %s\n",i,a[i]); } a = {"ZERO","ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN"}; b = {0,1,9,10}; print("\nremoving items %s\nfrom %s\n",printintarray(b,2,0),printstringarray(a,2)); filterarray(ref a,b,true); for (int i = 0; i < a.length; i++) { print("[%d] %s\n",i,a[i]); } a = {"ZERO","ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN"}; b = {10,12,9,230}; print("\nremoving items %s\nfrom %s\n",printintarray(b,2,0),printstringarray(a,2)); filterarray(ref a,b,true); for (int i = 0; i < a.length; i++) { print("[%d] %s\n",i,a[i]); } a = {"ZERO","ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN"}; b = {7}; print("\nremoving items %s\nfrom %s\n",printintarray(b,2,0),printstringarray(a,2)); filterarray(ref a,b,true); for (int i = 0; i < a.length; i++) { print("[%d] %s\n",i,a[i]); } a = {"ZERO","ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN"}; b = {6}; print("\nremoving items %s\nfrom %s\n",printintarray(b,2,0),printstringarray(a,2)); filterarray(ref a,b,true); for (int i = 0; i < a.length; i++) { print("[%d] %s\n",i,a[i]); } a = {"ZERO","ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN"}; b = {0}; print("\nremoving items %s\nfrom %s\n",printintarray(b,2,0),printstringarray(a,2)); filterarray(ref a,b,true); for (int i = 0; i < a.length; i++) { print("[%d] %s\n",i,a[i]); } a = {"ZERO","ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN"}; b = {}; print("\nremoving items %s\nfrom %s\n",printintarray(b,2,0),printstringarray(a,2)); filterarray(ref a,b,true); for (int i = 0; i < a.length; i++) { print("[%d] %s\n",i,a[i]); } string v = "FOO"; a = {"ZEERUW","WVN","TUU","QREE",v,"FUIX","SIKS","SEXN"}; b = {3}; v = "XXXX"; print("\nremoving items %s\nfrom %s\n",printintarray(b,2,0),printstringarray(a,2)); filterarray(ref a,b,true); for (int i = 0; i < a.length; i++) { print("[%d] %s\n",i,a[i]); } }
#+RESULTS:
removing items {0,2,5,6} from {ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN} [0] ONE [1] THREE [2] FOUR [3] SEVEN removing items {0,1,6,7} from {ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN} [0] TWO [1] THREE [2] FOUR [3] FIVE removing items {2,3,4,5} from {ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN} [0] ZERO [1] ONE [2] SIX [3] SEVEN removing items {5,0,3,1} from {ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN} [0] TWO [1] FOUR [2] SIX [3] SEVEN removing items {0,1,9,10} from {ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN} [0] TWO [1] THREE [2] FOUR [3] FIVE [4] SIX [5] SEVEN removing items {10,12,9,230} from {ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN} [0] ZERO [1] ONE [2] TWO [3] THREE [4] FOUR [5] FIVE [6] SIX [7] SEVEN removing items {7} from {ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN} [0] ZERO [1] ONE [2] TWO [3] THREE [4] FOUR [5] FIVE [6] SIX removing items {6} from {ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN} [0] ZERO [1] ONE [2] TWO [3] THREE [4] FOUR [5] FIVE [6] SEVEN removing items {0} from {ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN} [0] ONE [1] TWO [2] THREE [3] FOUR [4] FIVE [5] SIX [6] SEVEN removing items { } from {ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN} [0] ZERO [1] ONE [2] TWO [3] THREE [4] FOUR [5] FIVE [6] SIX [7] SEVEN removing items {3} from {ZEERUW,WVN,TUU,QREE,FOO,FUIX,SIKS,SEXN} [0] ZEERUW [1] WVN [2] TUU [3] FOO [4] FUIX [5] SIKS [6] SEXN
REPLACEVSSPLIT

Test (ab)use of stringbuilder.replace vs string.split for finding substrings.

Result: same for small strings, StringBuilder many times faster for large strings, presumably because it isn't creating a string array.

string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.3f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.3f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.3f m".printf((((double) u) / 60000000.0)); } return us; } StringBuilder readfiletostringbuilder (string f) { print("readlines started...\n"); int64 tts = GLib.get_monotonic_time(); StringBuilder sb = new StringBuilder(""); int maxlines = 0; GLib.File ff = GLib.File.new_for_path(f); if (ff.query_exists()) { GLib.FileStream fstr = GLib.FileStream.open(f,"r"); while (true) { string s = fstr.read_line(); if (s == null) { break; } sb.append(s); maxlines += 1; } } int64 tte = GLib.get_monotonic_time(); print("read %d lines from %s took %s\n\n".printf(maxlines,f,printusecs(tte-tts))); return sb; } void main() { GLib.Intl.setlocale(ALL,""); string s = "aajghjrhgur984tp23gn5hgapg mva0t44av3-2956 agsahrvt37646-3468qarejcah ;sirghspr hg4556yw prthcw 492-6985y6c ghsprghsrth952-695y6h vcsh giuhrcphcgsgh25hq-h-sptchap[htpiht5-69732sar7g8h76tra-h87srtsrjsmv 7ry-w7r-hsy7ha-7hah m hrkgjhpap5jz;;gsrig[ry9b g=as0ryuw57yfgpj"; uint f = 0; string n = "gsrig["; int64 tts = GLib.get_monotonic_time(); StringBuilder sb = new StringBuilder(""); sb.append(s); f = sb.replace(n,"",1); int64 tte = GLib.get_monotonic_time(); print("stringbuilder.replace took %s\n",printusecs(tte-tts)); if (f > 0) { print("stringbuilder.replace found the text\n\n"); } tts = GLib.get_monotonic_time(); f = s.split(n).length; tte = GLib.get_monotonic_time(); print("string.split took %s\n",printusecs(tte-tts)); if (f > 0) { print("string.split found the text\n\n"); } StringBuilder ls = readfiletostringbuilder("./cpbrown_notes.org"); tts = GLib.get_monotonic_time(); f = ls.replace(n,"",1); tte = GLib.get_monotonic_time(); print("large stringbuilder.replace took %s\n",printusecs(tte-tts)); if (f > 0) { print("large stringbuilder.replace found the text\n\n"); } tts = GLib.get_monotonic_time(); f = ls.str.split(n).length; tte = GLib.get_monotonic_time(); print("large string.split took %s\n",printusecs(tte-tts)); if (f > 0) { print("large string.split found the text\n\n"); } }
#+RESULTS:
stringbuilder.replace took 2 μs stringbuilder.replace found the text string.split took 2 μs string.split found the text readlines started... read 25031 lines from ./cpbrown_notes.org took 10.613 ms large stringbuilder.replace took 56 μs large stringbuilder.replace found the text large string.split took 378 μs large string.split found the text
[2_FIX.]SMID

1st unsuccessful attemt at testing vector comparison in Vala via CCode (its poorly documented).

This may be useful for speeding up tedious counting/replace operations where we need to find legit newlines in something like:

"\"a\nb\","b","\"\nc\"\\"\"c\",~d\'\n\'~\'\"d\'\"\',\"~\n\'e\'\"~\"\"e\"" where "~..~", "".."" and "'..'" are verbatim enclosures, and "\" is a single-char escape.

[CCode (cname = "vec4u", cheader_filename = ""; cname = "typedef unsigned int vec4u __attribute__ ((vector_size (16)))")] extern void declare_vec4u(); void main() { vec4u a = {'a','b','c','d'}; vec4u b = {'b','b','b','b'}; vec4u c = (a == b); print("{"); for (int i = 1; 1 < 3; i++) { print("%s,",c[i].to_string()); } print("%s}\n",c[3].to_string()); }
#+RESULTS:
Compilation failed: 3 error(s), 0 warning(s)
SORT
[5_DONE]STRQUICKSORT
[5_DONE]STRQUICKSORT_SRC
public class strquicksort : Object { // quicksort object with shellsort fallback // by c.p.brown 2026 int s; // start index int e; // end index int g; // recursion generation bool n; // reverse sort bool k; // case sensitive public strquicksort ( int ge, int st, int en, bool ng, bool cs) { s = st; e = en; g = ge; n = ng; k = cs; } public void run(ref int[] b, string[] tx, ref int packetscomplete) { // note: this sorts ints in b[], not the strings in tx[] // use b[] to copy strings in tx[] to a new sorted array bool xtime = false; bool xmod = false; int rng = (e - s) + 1; if (rng < 2) { return; } if (rng < 101) { int[] gaps = {57, 23, 10, 4, 1}; foreach (int w in gaps) { for (int i = s; i <= e; i++) { if (i >= w) { int ti = b[i]; //print("[%d] tx[b[%d]] is %s\n",w,i,tx[b[i]]); int j = i; if (n) { if (k) { while ( (j >= w) && ((j-w) >= s) && (strcmp(tx[b[(j-w)]],tx[ti]) < 0) ) { //print("[%d]\tb[%d] = b[(%d-%d) %d]\n",w,j,j,w,(j-w)); b[j] = b[(j-w)]; j -= w; } } else { while ( (j >= w) && ((j-w) >= s) && (tx[b[(j-w)]].ascii_casecmp(tx[ti]) < 0) ) { //print("[%d]\tb[%d] = b[(%d-%d) %d]\n",w,j,j,w,(j-w)); b[j] = b[(j-w)]; j -= w; } } } else { if (k) { while ( (j >= w) && ((j-w) >= s) && (strcmp(tx[b[(j-w)]],tx[ti]) > 0) ) { //print("[%d]\tb[%d] = b[(%d-%d) %d]\n",w,j,j,w,(j-w)); b[j] = b[(j-w)]; j -= w; } } else { while ( (j >= w) && ((j-w) >= s) && (tx[b[(j-w)]].ascii_casecmp(tx[ti]) > 0) ) { //print("[%d]\tb[%d] = b[(%d-%d) %d]\n",w,j,j,w,(j-w)); b[j] = b[(j-w)]; j -= w; } } } if ( (j != i) && (j >= s) ) { //print("[%d]\tb[%d] = ti %d\n",w,j,ti); b[j] = ti; } } } } } else { int p = s; // samples int[] px = new int[3]; int z = xrintr(0,(s+1),(e-1),xtime,xmod); px[0] = z; z = xrintr(z,(s+1),(e-1),xtime,xmod); int f = z; bool cond = true; if (k) { cond = (strcmp(tx[b[z]],tx[b[px[0]]]) < 0); } else { cond = (tx[b[z]].ascii_casecmp(tx[b[px[0]]]) < 0); } if (cond) { px[1] = px[0]; px[0] = z; } else { px[1] = z; } z = xrintr(f,(s+1),(e-1),xtime,xmod); cond = true; if (k) { cond = (strcmp(tx[b[z]],tx[b[px[1]]]) < 0); } else { cond = (tx[b[z]].ascii_casecmp(tx[b[px[1]]]) < 0); } if (cond) { px[2] = px[1]; px[1] = z; } else { px[2] = z; } p = px[1]; //print("g %04d pivot[0] %d row %d %s\n",g,px[0],b[px[0]],tx[b[px[0]]]); //print("g %04d pivot[1] %d row %d %s\n",g,px[1],b[px[1]],tx[b[px[1]]]); //print("g %04d pivot[2] %d row %d %s\n",g,px[2],b[px[2]],tx[b[px[2]]]); int i = s; int j = e; string pstr = tx[b[p]]; // cache the string for strcmp //print("g %04d pivot %d row %d is %s\n\n",g,p,b[p],pstr); while (i <= j) { if (n) { if (k) { while (strcmp(tx[b[i]],pstr) > 0) { i += 1; } while (strcmp(tx[b[j]],pstr) < 0) { j -= 1; } } else { while (tx[b[i]].ascii_casecmp(pstr) > 0) { i += 1; } while (tx[b[j]].ascii_casecmp(pstr) < 0) { j -= 1; } } } else { if (k) { while (strcmp(tx[b[i]],pstr) < 0) { i += 1; } while (strcmp(tx[b[j]],pstr) > 0) { j -= 1; } } else { while (tx[b[i]].ascii_casecmp(pstr) < 0) { i += 1; } while (tx[b[j]].ascii_casecmp(pstr) > 0) { j -= 1; } } } if (i <= j) { int t = b[i]; b[i] = b[j]; b[j] = t; i += 1; j -= 1; } } if (((j+1)-s) > 0) { if (s < j) { strquicksort qs = new strquicksort((g+1),s,j,n,k); qs.run(ref b, tx, ref packetscomplete); } } if (((e+1)-i) > 0) { if (i < e) { strquicksort qs = new strquicksort((g+1),i,e,n,k); qs.run(ref b, tx, ref packetscomplete); } } } // only complete task at gen 0 if (g == 0) { mutex.lock(); packetscomplete += 1; mutex.unlock(); } } }
[5_DONE]STRQUICKSORT_TEST1
// test strquicksprt // by c.p.brown 2026 GLib.Mutex mutex; string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } string print1darray (int ind, string[] dat, int dsz, bool h, bool rnm, bool cnm, int mw, int m, uint8[] hc) { // print an unrolled 2d array // by c.p.brown, 2025..2026 // // dat is the string[] // dsz is column count // h is render header // rnm is render row numbers // cnm is render cell numbers // mw is what to mask: 0 nothing 1 row 2 col // m is row/column to highlight string tabs = ("%*s").printf(ind," ").replace(" ","\t"); string spc = " "; int chc = 0; bool domask = (m > -1) && (mw > 0); bool maskcols = mw == 2; int rcols = dsz; int rowcount = dat.length / dsz; int firstcol = 0; string dlm = " | "; uint8 ir = hc[0]; uint8 ig = hc[1]; uint8 ib = hc[2]; if (rnm) { firstcol = 1; rcols = dsz + 1; } if (cnm) { chc = "%d".printf((dat.length - 1)).char_count(); } int[] cw = new int[rcols]; for (int i = 0; i < cw.length; i++) { cw[i] = 0; } if (rnm) { cw[0] = "%d".printf((dat.length/dsz)).char_count(); } if (h) { for (int i = firstcol; i < cw.length; i++) { string hh = ""; int d = (i-firstcol)+1; // shift to 1-based while (d > 0) { int x = ((d - 1) % 26); hh = "%c%s".printf((x+65),hh); d = ((d - x) - 1) / 26; } hh = "%d %s".printf((i-firstcol),hh); cw[i] = hh.char_count(); } } string o = ""; string ln = ""; // get counts 1st for (int i = 0; i < dat.length; i++) { int c = (i % dsz); if (rnm) { c = c + 1; } int cc = 0; if (dat[i] != null) { cc = dat[i].char_count() + chc + 3; if (cc > 0) { int nwlat = dat[i].index_of("\n"); if (nwlat != -1) { cc = (nwlat + 3 + chc + 3); } } } cw[c] = int.max(cw[c],cc); } // print header if (h) { for (int i = 0; i < cw.length; i++) { dlm = " | "; if (rnm && (i == 0)) { dlm = "%s| ".printf(tabs); string hh = "#"; o = "%s%s%-*s".printf(o,dlm,cw[i],hh); } else { if (i == 0) { dlm = "%s| ".printf(tabs); } string hh = ""; int d = (i-firstcol)+1; // shift to 1-based while (d > 0) { int x = ((d - 1) % 26); hh = "%c%s".printf((x+65),hh); d = ((d - x) - 1) / 26; } hh = "%d %s".printf((i-firstcol),hh); o = "%s%s%-*s".printf(o,dlm,cw[i],hh); } if (i == (cw.length - 1)) { o = "%s |\n".printf(o); } } // print line for (int i = 0; i < cw.length; i++) { dlm = "-+-"; if (i == 0) { dlm = "%s|-".printf(tabs); } ln = "%s%s%-*s".printf(ln,dlm,cw[i]," ").replace(" ","-"); if (i == (cw.length - 1)) { ln = "%s-|\n".printf(ln); } } o = "%s%s".printf(o,ln); } // print rows for (int r = 0; r < rowcount; r++) { for (int c = 0; c < cw.length; c++) { string datpart = ""; if ((c == 0) && rnm) { dlm = "%s| ".printf(tabs); o = "%s%s%0*d".printf(o,dlm,cw[0],r); } else { dlm = " | "; if (c == 0) { dlm = "%s| ".printf(tabs); } int j = (r * dsz) + (c - firstcol); int cc = dat[j].char_count(); if (dat[j] != null) { if (cc > 0) { datpart = dat[j]; int nwlat = dat[j].index_of("\n"); if (nwlat != -1) { //trunc = true; datpart = (dat[j].substring(0,nwlat) + "..."); cc = (nwlat + 3); } } else { cc = int.max(cc,1); } } string clen = ""; if (cnm) { clen = "(%0*d) ".printf(chc,j); } int padlen = (cw[c] - cc) - clen.char_count(); padlen = int.max(padlen,0); datpart = "%s%s%.*s".printf(clen,datpart,padlen,spc); if (domask) { bool ismakked = false; if (maskcols) { ismasked = ((m+firstcol) == c); } else { ismasked = (m == r); } if (ismasked) { datpart = "\x1b[48;2;%u;%u;%um%s\x1b[0m".printf(ir,ig,ib,datpart); //datpart = "\x1b[48;2;76;25;25m%s\x1b[0m".printf(datpart); } } o = "%s%s%s".printf(o,dlm,datpart); if (c == (cw.length - 1)) { o = "%s |\n".printf(o); } } } } cw = null; return o; } int xrintr (int i, int s, int e, bool t, bool m) { // pseudo-random integer range // by c.p.brown 2025 // // i is seed, s is min value, e is max value, // t is use time + seed (different result each eval) // m is modulo within range rather than scale to range // // uses xorshift offsets by George Marsaglia (2003) // https://www.jstatsoft.org/article/view/v008i14 int[] ph = { 4,3,27, // 31 ▂█▄▇▃▃▇▄█▂▆▁▅█▄▇▃▅▁▆▂▂▆▁▅▃▇▄█▄ 5,27,25, // 44 ▃▅▇▁▃▅▇▁▃█▆▄▂█▆▄▂█▆▄▂█▆▄▂▇▅▃▁▇ 1,9,29, // 03 ▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆ 13,3,17, // 71 ▁▃▄▂█▆▃▁▇▅▂▄▆█▁▃▅▇█▆▄▂▇▅▃▁▆█▂▄ 9,5,25, // 61 ▆▃▄▁▂▇█▅▆▃▄▁▂█▇▆▅▄▃▂▁█▇▆▅▄▃▂▁▅ 3,7,29, // 25 ▅█▇▂▁▄▃▃▄▁▂▇█▅▆▃▄▁▂▇█▅▆▄▃▂▁█▇▆ 3,5,25, // 24 █▁▁▂▂▃▃▄▄▃▃▄▄▁▁▂▂▇▇██▅▅▆▆▄▄▃▃▂ 15,1,29 // 77 ▄▂▁▁▂▄▃▇█▆▅▅▆█▇▃▄▂▁▁▂▄▃▇█▆▅▅▆█ }; int phl = ph.length / 3; uint th = (uint) i; if (t) { th = (uint) GLib.get_monotonic_time() + i; } int pl = (i % phl) * 3; th^=(th<<ph[pl]); th^=(th>>ph[pl+1]); th^=(th<<ph[pl+2]); if (m) { return ((int) (th % ((uint) ((e+1)-s)))) + s; } return ((int) ((((double) th) / uint32.MAX) * ((double) ((e+1)-s)))) + s; } public class strquicksort : Object { // quicksort object with shellsort fallback // by c.p.brown 2026 int s; // start index int e; // end index int g; // recursion generation bool n; // reverse sort bool k; // case sensitive public strquicksort ( int ge, int st, int en, bool ng, bool cs) { s = st; e = en; g = ge; n = ng; k = cs; } public void run(ref int[] b, string[] tx, ref int packetscomplete) { // note: this sorts ints in b[], not the strings in tx[] // use b[] to copy strings in tx[] to a new sorted array bool xtime = false; bool xmod = false; int rng = (e - s) + 1; if (rng < 2) { return; } if (rng < 101) { int[] gaps = {57, 23, 10, 4, 1}; foreach (int w in gaps) { for (int i = s; i <= e; i++) { if (i >= w) { int ti = b[i]; //print("[%d] tx[b[%d]] is %s\n",w,i,tx[b[i]]); int j = i; if (n) { if (k) { while ( (j >= w) && ((j-w) >= s) && (strcmp(tx[b[(j-w)]],tx[ti]) < 0) ) { //print("[%d]\tb[%d] = b[(%d-%d) %d]\n",w,j,j,w,(j-w)); b[j] = b[(j-w)]; j -= w; } } else { while ( (j >= w) && ((j-w) >= s) && (tx[b[(j-w)]].ascii_casecmp(tx[ti]) < 0) ) { //print("[%d]\tb[%d] = b[(%d-%d) %d]\n",w,j,j,w,(j-w)); b[j] = b[(j-w)]; j -= w; } } } else { if (k) { while ( (j >= w) && ((j-w) >= s) && (strcmp(tx[b[(j-w)]],tx[ti]) > 0) ) { //print("[%d]\tb[%d] = b[(%d-%d) %d]\n",w,j,j,w,(j-w)); b[j] = b[(j-w)]; j -= w; } } else { while ( (j >= w) && ((j-w) >= s) && (tx[b[(j-w)]].ascii_casecmp(tx[ti]) > 0) ) { //print("[%d]\tb[%d] = b[(%d-%d) %d]\n",w,j,j,w,(j-w)); b[j] = b[(j-w)]; j -= w; } } } if ( (j != i) && (j >= s) ) { //print("[%d]\tb[%d] = ti %d\n",w,j,ti); b[j] = ti; } } } } } else { int p = s; // samples int[] px = new int[3]; int z = xrintr(0,(s+1),(e-1),xtime,xmod); px[0] = z; z = xrintr(z,(s+1),(e-1),xtime,xmod); int f = z; bool cond = true; if (k) { cond = (strcmp(tx[b[z]],tx[b[px[0]]]) < 0); } else { cond = (tx[b[z]].ascii_casecmp(tx[b[px[0]]]) < 0); } if (cond) { px[1] = px[0]; px[0] = z; } else { px[1] = z; } z = xrintr(f,(s+1),(e-1),xtime,xmod); cond = true; if (k) { cond = (strcmp(tx[b[z]],tx[b[px[1]]]) < 0); } else { cond = (tx[b[z]].ascii_casecmp(tx[b[px[1]]]) < 0); } if (cond) { px[2] = px[1]; px[1] = z; } else { px[2] = z; } p = px[1]; //print("g %04d pivot[0] %d row %d %s\n",g,px[0],b[px[0]],tx[b[px[0]]]); //print("g %04d pivot[1] %d row %d %s\n",g,px[1],b[px[1]],tx[b[px[1]]]); //print("g %04d pivot[2] %d row %d %s\n",g,px[2],b[px[2]],tx[b[px[2]]]); int i = s; int j = e; string pstr = tx[b[p]]; // cache the string for strcmp //print("g %04d pivot %d row %d is %s\n\n",g,p,b[p],pstr); while (i <= j) { if (n) { if (k) { while (strcmp(tx[b[i]],pstr) > 0) { i += 1; } while (strcmp(tx[b[j]],pstr) < 0) { j -= 1; } } else { while (tx[b[i]].ascii_casecmp(pstr) > 0) { i += 1; } while (tx[b[j]].ascii_casecmp(pstr) < 0) { j -= 1; } } } else { if (k) { while (strcmp(tx[b[i]],pstr) < 0) { i += 1; } while (strcmp(tx[b[j]],pstr) > 0) { j -= 1; } } else { while (tx[b[i]].ascii_casecmp(pstr) < 0) { i += 1; } while (tx[b[j]].ascii_casecmp(pstr) > 0) { j -= 1; } } } if (i <= j) { int t = b[i]; b[i] = b[j]; b[j] = t; i += 1; j -= 1; } } if (((j+1)-s) > 0) { if (s < j) { strquicksort qs = new strquicksort((g+1),s,j,n,k); qs.run(ref b, tx, ref packetscomplete); } } if (((e+1)-i) > 0) { if (i < e) { strquicksort qs = new strquicksort((g+1),i,e,n,k); qs.run(ref b, tx, ref packetscomplete); } } } // only complete task at gen 0 if (g == 0) { mutex.lock(); packetscomplete += 1; mutex.unlock(); } } } void main() { GLib.Intl.setlocale(ALL,""); mutex = new GLib.Mutex(); // desired result: // "AAa","CXs","ArE","Imw","jOw","PXa","AAn", // "AAA","Jhz","KJM","fUN","hNE","hjC","wfi", <-- this range is sorted // "GHG","fhE","bSB","lMT","wwg","WdO","VjM", // "Aaa","isn","hmn","IXI","LbT","yjj","AxO", string[] d = { "AAa","CXs","ArE","Imw","jOw","PXa","AAn", "hNE","AAA","Jhz","fUN","KJM","wfi","hjC", "GHG","fhE","bSB","lMT","wwg","WdO","VjM", "Aaa","isn","hmn","IXI","LbT","yjj","AxO", }; int s = 7; int e = 13; int[] ix = {}; for (int i = 0; i < d.length; i++) { ix += i; } int packetscomplete = 0; strquicksort srt = new strquicksort(0,s,e,false,true); srt.run(ref ix, d, ref packetscomplete); string[] sd = {}; foreach (int i in ix) { sd += d[i]; } uint8[] hc = {}; hc += ((uint8) ((0.4 * 255.0) + 0.5)); hc += ((uint8) ((0.1 * 255.0) + 0.5)); hc += ((uint8) ((0.2 * 255.0) + 0.5)); print("%s\n",print1darray(1,d,7,true,true,true,1,1,hc)); print("%s\n",print1darray(1,sd,7,true,true,true,1,1,hc)); }
#+RESULTS:
Compilation succeeded - 2 warning(s) | # | 0 A | 1 B | 2 C | 3 D | 4 E | 5 F | 6 G | |---+----------+----------+----------+----------+----------+----------+----------| | 0 | (00) AAa | (01) CXs | (02) ArE | (03) Imw | (04) jOw | (05) PXa | (06) AAn | | 1 | (07) hNE | (08) AAA | (09) Jhz | (10) fUN | (11) KJM | (12) wfi | (13) hjC | | 2 | (14) GHG | (15) fhE | (16) bSB | (17) lMT | (18) wwg | (19) WdO | (20) VjM | | 3 | (21) Aaa | (22) isn | (23) hmn | (24) IXI | (25) LbT | (26) yjj | (27) AxO | | # | 0 A | 1 B | 2 C | 3 D | 4 E | 5 F | 6 G | |---+----------+----------+----------+----------+----------+----------+----------| | 0 | (00) AAa | (01) CXs | (02) ArE | (03) Imw | (04) jOw | (05) PXa | (06) AAn | | 1 | (07) AAA | (08) Jhz | (09) KJM | (10) fUN | (11) hNE | (12) hjC | (13) wfi | | 2 | (14) GHG | (15) fhE | (16) bSB | (17) lMT | (18) wwg | (19) WdO | (20) VjM | | 3 | (21) Aaa | (22) isn | (23) hmn | (24) IXI | (25) LbT | (26) yjj | (27) AxO |
[5_DONE]STRQUICKSORT_TEST2

Stress test

// stresstest strquicksprt // by c.p.brown 2026 GLib.Mutex mutex; string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } string[] readfiletostrings (string p) { string[] o = {}; GLib.FileStream fs; try { fs = GLib.FileStream.open(p,"r"); StringBuilder sb = new StringBuilder(""); while (true) { string l = fs.read_line(); if (l == null) { break; } sb.erase(); sb.append(l.dup()); o += sb.str; } } catch (Error e) { print("file error: %s\n",e.message); } return o; } int xrintr (int i, int s, int e, bool t, bool m) { // pseudo-random integer range // by c.p.brown 2025 // // i is seed, s is min value, e is max value, // t is use time + seed (different result each eval) // m is modulo within range rather than scale to range // // uses xorshift offsets by George Marsaglia (2003) // https://www.jstatsoft.org/article/view/v008i14 int[] ph = { 4,3,27, // 31 ▂█▄▇▃▃▇▄█▂▆▁▅█▄▇▃▅▁▆▂▂▆▁▅▃▇▄█▄ 5,27,25, // 44 ▃▅▇▁▃▅▇▁▃█▆▄▂█▆▄▂█▆▄▂█▆▄▂▇▅▃▁▇ 1,9,29, // 03 ▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆ 13,3,17, // 71 ▁▃▄▂█▆▃▁▇▅▂▄▆█▁▃▅▇█▆▄▂▇▅▃▁▆█▂▄ 9,5,25, // 61 ▆▃▄▁▂▇█▅▆▃▄▁▂█▇▆▅▄▃▂▁█▇▆▅▄▃▂▁▅ 3,7,29, // 25 ▅█▇▂▁▄▃▃▄▁▂▇█▅▆▃▄▁▂▇█▅▆▄▃▂▁█▇▆ 3,5,25, // 24 █▁▁▂▂▃▃▄▄▃▃▄▄▁▁▂▂▇▇██▅▅▆▆▄▄▃▃▂ 15,1,29 // 77 ▄▂▁▁▂▄▃▇█▆▅▅▆█▇▃▄▂▁▁▂▄▃▇█▆▅▅▆█ }; int phl = ph.length / 3; uint th = (uint) i; if (t) { th = (uint) GLib.get_monotonic_time() + i; } int pl = (i % phl) * 3; th^=(th<<ph[pl]); th^=(th>>ph[pl+1]); th^=(th<<ph[pl+2]); if (m) { return ((int) (th % ((uint) ((e+1)-s)))) + s; } return ((int) ((((double) th) / uint32.MAX) * ((double) ((e+1)-s)))) + s; } none public class strquicksort : Object { // quicksort object with shellsort fallback // by c.p.brown 2026 int s; // start index int e; // end index int g; // recursion generation bool n; // reverse sort bool k; // case sensitive public strquicksort ( int ge, int st, int en, bool ng, bool cs) { s = st; e = en; g = ge; n = ng; k = cs; } public void run(ref int[] b, string[] tx, ref int packetscomplete) { // note: this sorts ints in b[], not the strings in tx[] // use b[] to copy strings in tx[] to a new sorted array bool xtime = false; bool xmod = false; int rng = (e - s) + 1; if (rng < 2) { return; } if (rng < 101) { int[] gaps = {57, 23, 10, 4, 1}; foreach (int w in gaps) { for (int i = s; i <= e; i++) { if (i >= w) { int ti = b[i]; //print("[%d] tx[b[%d]] is %s\n",w,i,tx[b[i]]); int j = i; if (n) { if (k) { while ( (j >= w) && ((j-w) >= s) && (strcmp(tx[b[(j-w)]],tx[ti]) < 0) ) { //print("[%d]\tb[%d] = b[(%d-%d) %d]\n",w,j,j,w,(j-w)); b[j] = b[(j-w)]; j -= w; } } else { while ( (j >= w) && ((j-w) >= s) && (tx[b[(j-w)]].ascii_casecmp(tx[ti]) < 0) ) { //print("[%d]\tb[%d] = b[(%d-%d) %d]\n",w,j,j,w,(j-w)); b[j] = b[(j-w)]; j -= w; } } } else { if (k) { while ( (j >= w) && ((j-w) >= s) && (strcmp(tx[b[(j-w)]],tx[ti]) > 0) ) { //print("[%d]\tb[%d] = b[(%d-%d) %d]\n",w,j,j,w,(j-w)); b[j] = b[(j-w)]; j -= w; } } else { while ( (j >= w) && ((j-w) >= s) && (tx[b[(j-w)]].ascii_casecmp(tx[ti]) > 0) ) { //print("[%d]\tb[%d] = b[(%d-%d) %d]\n",w,j,j,w,(j-w)); b[j] = b[(j-w)]; j -= w; } } } if ( (j != i) && (j >= s) ) { //print("[%d]\tb[%d] = ti %d\n",w,j,ti); b[j] = ti; } } } } } else { int p = s; // samples int[] px = new int[3]; int z = xrintr(0,(s+1),(e-1),xtime,xmod); px[0] = z; z = xrintr(z,(s+1),(e-1),xtime,xmod); int f = z; bool cond = true; if (k) { cond = (strcmp(tx[b[z]],tx[b[px[0]]]) < 0); } else { cond = (tx[b[z]].ascii_casecmp(tx[b[px[0]]]) < 0); } if (cond) { px[1] = px[0]; px[0] = z; } else { px[1] = z; } z = xrintr(f,(s+1),(e-1),xtime,xmod); cond = true; if (k) { cond = (strcmp(tx[b[z]],tx[b[px[1]]]) < 0); } else { cond = (tx[b[z]].ascii_casecmp(tx[b[px[1]]]) < 0); } if (cond) { px[2] = px[1]; px[1] = z; } else { px[2] = z; } p = px[1]; //print("g %04d pivot[0] %d row %d %s\n",g,px[0],b[px[0]],tx[b[px[0]]]); //print("g %04d pivot[1] %d row %d %s\n",g,px[1],b[px[1]],tx[b[px[1]]]); //print("g %04d pivot[2] %d row %d %s\n",g,px[2],b[px[2]],tx[b[px[2]]]); int i = s; int j = e; string pstr = tx[b[p]]; // cache the string for strcmp //print("g %04d pivot %d row %d is %s\n\n",g,p,b[p],pstr); while (i <= j) { if (n) { if (k) { while (strcmp(tx[b[i]],pstr) > 0) { i += 1; } while (strcmp(tx[b[j]],pstr) < 0) { j -= 1; } } else { while (tx[b[i]].ascii_casecmp(pstr) > 0) { i += 1; } while (tx[b[j]].ascii_casecmp(pstr) < 0) { j -= 1; } } } else { if (k) { while (strcmp(tx[b[i]],pstr) < 0) { i += 1; } while (strcmp(tx[b[j]],pstr) > 0) { j -= 1; } } else { while (tx[b[i]].ascii_casecmp(pstr) < 0) { i += 1; } while (tx[b[j]].ascii_casecmp(pstr) > 0) { j -= 1; } } } if (i <= j) { int t = b[i]; b[i] = b[j]; b[j] = t; i += 1; j -= 1; } } if (((j+1)-s) > 0) { if (s < j) { strquicksort qs = new strquicksort((g+1),s,j,n,k); qs.run(ref b, tx, ref packetscomplete); } } if (((e+1)-i) > 0) { if (i < e) { strquicksort qs = new strquicksort((g+1),i,e,n,k); qs.run(ref b, tx, ref packetscomplete); } } } // only complete task at gen 0 if (g == 0) { mutex.lock(); packetscomplete += 1; mutex.unlock(); } } } struct packet { int[] items; } void main() { GLib.Intl.setlocale(ALL,""); mutex = new GLib.Mutex(); string[] f = readfiletostrings("./testdata/leipzig1M.txt"); int64 tts = GLib.get_monotonic_time(); int pc = 0; int[] ix = {}; int l = f.length; for (int i = 0; i < l; i++) { ix += i; } strquicksort qs = new strquicksort(0,0,(l - 1),false,false); qs.run(ref ix, f, ref pc); int64 tte = GLib.get_monotonic_time(); int c = 0; for (int i = 60000; i < l; i += 1) { if (c > 10) { break; } print("QS [%d (%d)] %s...\n",i,ix[i],f[ix[i]].substring(0,20)); c += 1; } for (int i = 1; i < ix.length; i++) { if (f[ix[i]].ascii_casecmp(f[ix[i-1]]) < 0) { print("\nSORT ERROR\n\t[%d](%d) \"%s\"\n\t[%d](%d) \"%s\"\n",(i-1),ix[i-1],f[ix[i-1]].substring(0,20),i,ix[i],f[ix[i]].substring(0,20)); break; } } print("\ncase-insensitive strquicksort of leipzig1M.txt took %s\n\n",printusecs(tte-tts)); tts = GLib.get_monotonic_time(); pc = 0; ix.resize(0); for (int i = 0; i < l; i++) { ix += i; } strquicksort rqs = new strquicksort(0,0,(l - 1),true,false); rqs.run(ref ix, f, ref pc); tte = GLib.get_monotonic_time(); c = 0; for (int i = (1000000 - 60011); i < l; i += 1) { if (c > 10) { break; } print("QS [%d (%d)] %s...\n",i,ix[i],f[ix[i]].substring(0,20)); c += 1; } for (int i = 1; i < ix.length; i++) { if (f[ix[i]].ascii_casecmp(f[ix[i-1]]) > 0) { print("\nSORT ERROR\n\t[%d](%d) \"%s\"\n\t[%d](%d) \"%s\"\n",(i-1),ix[i-1],f[ix[i-1]].substring(0,20),i,ix[i],f[ix[i]].substring(0,20)); break; } } print("\nreverse case-insensitive strquicksort of leipzig1M.txt took %s\n\n",printusecs(tte-tts)); tts = GLib.get_monotonic_time(); pc = 0; ix.resize(0); for (int i = 0; i < l; i++) { ix += i; } strquicksort cqs = new strquicksort(0,0,(l - 1),false,true); cqs.run(ref ix, f, ref pc); tte = GLib.get_monotonic_time(); c = 0; for (int i = 0; i < l; i += 1) { if (c > 10) { break; } print("QS [%d (%d)] %s...\n",i,ix[i],f[ix[i]].substring(0,20)); c += 1; } for (int i = 1; i < ix.length; i++) { if (strcmp(f[ix[i]],f[ix[i-1]]) < 0) { print("\nSORT ERROR\n\t[%d](%d) \"%s\"\n\t[%d](%d) \"%s\"\n",(i-1),ix[i-1],f[ix[i-1]].substring(0,20),i,ix[i],f[ix[i]].substring(0,20)); break; } } print("\ncase-sensitive strquicksort of leipzig1M.txt took %s\n\n",printusecs(tte-tts)); int nthr = (int) GLib.get_num_processors(); int64 btts = GLib.get_monotonic_time(); pc = 0; ix.resize(0); for (int i = 0; i < l; i++) { ix += i; } int maxpackets = (2 * nthr); int mtb = (l / maxpackets); int req = 0; tmpidx idx = new tmpidx(mtb); fillmemybuckets(f,0,ref idx,ix,mtb,req,false,true); if (idx.getrowcount() != l) { print("idx.rows.length %d != f.length %d\n",idx.getrowcount(),l); assert(false); } int[] bix = {}; for (int i = 0; i < l; i++) { bix += idx.getrow(i); } int64 btte = GLib.get_monotonic_time(); print("\nbucketsort of leipzig1M.txt took %s\n\n",printusecs(btte-btts)); print("\tidx packetsize is %d\n",idx.packetsize); print("\tidx range pair count is %d\n",idx.getrangecount() / 2); print("\tidx.getrangestart(0) is %d\n",idx.getrangestart(0)); print("\tidx.getrangeend(0) is %d\n",idx.getrangeend(0)); print("\n"); c = 0; for (int i = 0; i < l; i += 1) { if (c > 10) { break; } print("BS [%d (%d)] %s...\n",i,bix[i],f[bix[i]].substring(0,20)); c += 1; } print("\n"); int64 mtts = GLib.get_monotonic_time(); int rc = idx.getrangecount(); if (( rc & 1) != 0) { print("idx.getrangecount() %d is odd, aborting\n",rc); assert(false); } pc = 0; ThreadPool<strquicksort> bqs = new ThreadPool<strquicksort>.with_owned_data((strquicksort) => { strquicksort.run(ref bix, f, ref pc);},nthr,false); //rc = rc / 2; int acc = 0; for (int x = 0; x < rc; x += 2) { print("P%d S%d E%d\n",acc,idx.getrangestart(x),idx.getrangeend(x)); bqs.add(new strquicksort(0,idx.getrangestart(x),idx.getrangeend(x),false,true)); acc += 1; } while (pc != acc) { GLib.Thread.usleep(1); } int64 mtte = GLib.get_monotonic_time(); //print("\n%s\n",idx.printranges()); print("\n"); c = 0; for (int i = 0; i < l; i += 1) { if (c > 10) { break; } print("MHS [%d (%d)] %s...\n",i,bix[i],f[bix[i]].substring(0,20)); c += 1; } // brute-force check for (int i = 1; i < bix.length; i++) { if (strcmp(f[bix[i]],f[bix[i-1]]) < 0) { print("\nSORT ERROR\n\t[%d](%d) \"%s\"\n\t[%d](%d) \"%s\"\n",(i-1),bix[i-1],f[bix[i-1]].substring(0,20),i,bix[i],f[bix[i]].substring(0,20)); break; } } print("\nmultithreaded case-sensitive strquicksort of leipzig1M.txt took %s + bucketsort partitioning %s = %s\n\n",printusecs(mtte-mtts),printusecs(btte-btts),printusecs(((mtte-mtts)+(btte-btts)))); }
#+RESULTS:
Compilation succeeded - 6 warning(s) QS [60000 (193865)] "This one was an eas... QS [60001 (926559)] "This one will kill ... QS [60002 (887924)] "This one will take ... QS [60003 (624797)] "This one's gold-pla... QS [60004 (652873)] "This one," he mumbl... QS [60005 (500555)] "This only adds cred... QS [60006 (717271)] "This only could hav... QS [60007 (617684)] "This only deepens o... QS [60008 (650258)] "This opens the floo... QS [60009 (23302)] "This ordinance will... QS [60010 (269667)] "This organization h... case-insensitive strquicksort of leipzig1M.txt took 682.35 ms QS [939989 (269667)] "This organization h... QS [939990 (23302)] "This ordinance will... QS [939991 (650258)] "This opens the floo... QS [939992 (617684)] "This only deepens o... QS [939993 (717271)] "This only could hav... QS [939994 (500555)] "This only adds cred... QS [939995 (652873)] "This one," he mumbl... QS [939996 (624797)] "This one's gold-pla... QS [939997 (887924)] "This one will take ... QS [939998 (926559)] "This one will kill ... QS [939999 (193865)] "This one was an eas... reverse case-insensitive strquicksort of leipzig1M.txt took 673.68 ms QS [0 (626381)] " "And I said, `I li... QS [1 (707759)] " "Bob turns around ... QS [2 (596666)] " "I would hate to s... QS [3 (665456)] " "I'm not running t... QS [4 (97208)] " "She says, `You go... QS [5 (78822)] " "There never has b... QS [6 (350973)] " "We just jibber-ja... QS [7 (40816)] " 'Tell us on the ph... QS [8 (580784)] " A casino's "win" i... QS [9 (465232)] " A rescuer eventual... QS [10 (486472)] " A visit to the hou... case-sensitive strquicksort of leipzig1M.txt took 535.29 ms bucketsort of leipzig1M.txt took 225.88 ms idx packetsize is 31250 idx range pair count is 32 idx.getrangestart(0) is 0 idx.getrangeend(0) is 31249 BS [0 (11707)] " Henderson often te... BS [1 (13949)] " He called on his s... BS [2 (26254)] " Hydrogen is highly... BS [3 (40816)] " 'Tell us on the ph... BS [4 (48253)] " `The Pelican Brief... BS [5 (57874)] " Scott McCartney is... BS [6 (70128)] " The Department of ... BS [7 (78822)] " "There never has b... BS [8 (83466)] " Up until the invas... BS [9 (93365)] " Thousands of Armen... BS [10 (94733)] " Stock said. "It wa... P0 S0 E31249 P1 S31250 E62499 P2 S62500 E93749 P3 S93750 E124999 P4 S125000 E156249 P5 S156250 E187499 P6 S187500 E218749 P7 S218750 E249999 P8 S250000 E281249 P9 S281250 E312499 P10 S312500 E343749 P11 S343750 E374999 P12 S375000 E406249 P13 S406250 E437499 P14 S437500 E468749 P15 S468750 E499999 P16 S500000 E531249 P17 S531250 E562499 P18 S562500 E593749 P19 S593750 E624999 P20 S625000 E656249 P21 S656250 E687499 P22 S687500 E718749 P23 S718750 E749999 P24 S750000 E781249 P25 S781250 E812499 P26 S812500 E843749 P27 S843750 E874999 P28 S875000 E906249 P29 S906250 E937499 P30 S937500 E968749 P31 S968750 E999999 MHS [0 (626381)] " "And I said, `I li... MHS [1 (707759)] " "Bob turns around ... MHS [2 (596666)] " "I would hate to s... MHS [3 (665456)] " "I'm not running t... MHS [4 (97208)] " "She says, `You go... MHS [5 (78822)] " "There never has b... MHS [6 (350973)] " "We just jibber-ja... MHS [7 (40816)] " 'Tell us on the ph... MHS [8 (580784)] " A casino's "win" i... MHS [9 (465232)] " A rescuer eventual... MHS [10 (486472)] " A visit to the hou... multithreaded case-sensitive strquicksort of leipzig1M.txt took 42.02 ms + bucketsort partitioning 225.88 ms = 267.90 ms
[5_DONE]MAKELEEGAPS

Based on the following technique by Ying Wai Lee:
Empirically Improved Tokuda Gap Sequence in Shellsort

| n |  gap |     ng | plot                                               |
|---+------+--------+----------------------------------------------------|
| 9 | 1158 | 1.0000 | ██████████████████████████████████████████████████ |
| 8 |  516 | 0.4456 | ███████████████████████                            |
| 7 |  230 | 0.1986 | ██████████                                         |
| 6 |  102 | 0.0881 | █████                                              |
| 5 |   45 | 0.0389 | ██                                                 |
| 4 |   20 | 0.0173 | █                                                  |
| 3 |    9 | 0.0078 | █                                                  |
| 2 |    4 | 0.0035 | █                                                  |
| 1 |    1 | 0.0009 |                                                    |
|---+------+--------+----------------------------------------------------|
#+TBLFM: $2=(floor((pow(2.243609061420001,$1)/(2.243609061420001 - 1.0)))) :: $3=($2/@2$2);%.4f :: $4='(orgtbl-uc-draw-cont $2 1.0 1158.0 50) 

int[] makeleegaps(int n) { int thn = int.min((n / 3),(int32.MAX / 3)); int[] spag = {}; int l = 1; while (l < 100) { int g = (int) Math.floor( Math.pow(2.243609061420001,((double) l)) / (2.243609061420001 - 1.0) ); if (g > thn) { break; } spag += g; l += 1; } //print("makeleegaps l is %d\n",l); int ll = spag.length - 1; if (ll > -1) { int[] gaps = new int[(ll+1)]; for (int i = ll; i >= 0; i--) { gaps[ll-i] = spag[i]; } return gaps; } return {331490,147748,65853,29351,13082,5830,2598,1158,516,230,102,45,20,9,4,1}; }
[5_DONE]INTSHELLSORT
INTSHELLSORT_INF

intshellsort sorts a referenced int[] array in-place.
Uses MAKELEEGAPS to create an optimal gap sequence.
Ideal application is for <10000 items, otherwise use INTQUICKSORT.

Usage:
intshellsort(ref int[] p, bool r)

  • int[] p is the int array to sort
  • bool r is to reverse-sort

INTSHELLSORT_SRC
void intshellsort (int[] p, bool r) { // sort p, reverse if r if (p.length > 0) { int[] gaps = makeleegaps(p.length); foreach (int g in gaps) { for (int i = g; i < p.length; i++) { int t = p[i]; int j = i; bool cond = true; while (cond) { if (j < g) { break; } if (r) { cond = (p[j - g] < t); } else { cond = (p[j - g] > t); } if (cond) { p[j] = p[j - g]; j -= g; } } p[j] = t; } } } }
INTSHELLSORT_TEST
Note: XRINTR may not use the full range specified. Decrease the range to increase the chance of both min and max values being present.
string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } int xrintr (int i, int s, int e, bool t, bool m) { // pseudo-random integer range // by c.p.brown 2025 // // i is seed, s is min value, e is max value, // t is use time + seed (different result each eval) // m is modulo within range rather than scale to range // // uses xorshift offsets by George Marsaglia (2003) // https://www.jstatsoft.org/article/view/v008i14 int[] ph = { 4,3,27, // 31 ▂█▄▇▃▃▇▄█▂▆▁▅█▄▇▃▅▁▆▂▂▆▁▅▃▇▄█▄ 5,27,25, // 44 ▃▅▇▁▃▅▇▁▃█▆▄▂█▆▄▂█▆▄▂█▆▄▂▇▅▃▁▇ 1,9,29, // 03 ▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆ 13,3,17, // 71 ▁▃▄▂█▆▃▁▇▅▂▄▆█▁▃▅▇█▆▄▂▇▅▃▁▆█▂▄ 9,5,25, // 61 ▆▃▄▁▂▇█▅▆▃▄▁▂█▇▆▅▄▃▂▁█▇▆▅▄▃▂▁▅ 3,7,29, // 25 ▅█▇▂▁▄▃▃▄▁▂▇█▅▆▃▄▁▂▇█▅▆▄▃▂▁█▇▆ 3,5,25, // 24 █▁▁▂▂▃▃▄▄▃▃▄▄▁▁▂▂▇▇██▅▅▆▆▄▄▃▃▂ 15,1,29 // 77 ▄▂▁▁▂▄▃▇█▆▅▅▆█▇▃▄▂▁▁▂▄▃▇█▆▅▅▆█ }; int phl = ph.length / 3; uint th = (uint) i; if (t) { th = (uint) GLib.get_monotonic_time() + i; } int pl = (i % phl) * 3; th^=(th<<ph[pl]); th^=(th>>ph[pl+1]); th^=(th<<ph[pl+2]); if (m) { return ((int) (th % ((uint) ((e+1)-s)))) + s; } return ((int) ((((double) th) / uint32.MAX) * ((double) ((e+1)-s)))) + s; } int[] makeleegaps(int n) { int thn = int.min((n / 3),(int32.MAX / 3)); int[] spag = {}; int l = 1; while (l < 100) { int g = (int) Math.floor( Math.pow(2.243609061420001,((double) l)) / (2.243609061420001 - 1.0) ); if (g > thn) { break; } spag += g; l += 1; } //print("makeleegaps l is %d\n",l); int ll = spag.length - 1; if (ll > -1) { int[] gaps = new int[(ll+1)]; for (int i = ll; i >= 0; i--) { gaps[ll-i] = spag[i]; } return gaps; } return {331490,147748,65853,29351,13082,5830,2598,1158,516,230,102,45,20,9,4,1}; } void intshellsort (int[] p, bool r) { // sort p, reverse if r if (p.length > 0) { int[] gaps = makeleegaps(p.length); foreach (int g in gaps) { for (int i = g; i < p.length; i++) { int t = p[i]; int j = i; bool cond = true; while (cond) { if (j < g) { break; } if (r) { cond = (p[j - g] < t); } else { cond = (p[j - g] > t); } if (cond) { p[j] = p[j - g]; j -= g; } } p[j] = t; } } } } void main() { GLib.Intl.setlocale(ALL,""); int[] a = {}; int ic = 30000000; for (int i = 1; i <= ic; i++) { a += xrintr(i,33,12333444,false,true); } print("unsorted a[0] is %d\n",a[0]); print("unsorted a[(a.length - 1)] is %d\n",a[(a.length - 1)]); int64 tts = GLib.get_monotonic_time(); intshellsort(ref a, false); int64 tte = GLib.get_monotonic_time(); print("sorted a[0] is %d\n",a[0]); print("sorted a[(a.length - 1)] is %d\n",a[(a.length - 1)]); print("intshellsort of %d items took %s\n\n",ic,printusecs(tte-tts)); tts = GLib.get_monotonic_time(); intshellsort(ref a, true); tte = GLib.get_monotonic_time(); print("reversed a[0] is %d\n",a[0]); print("reversed a[(a.length - 1)] is %d\n",a[(a.length - 1)]); print("reverse intshellsort of %d items took %s\n\n",ic,printusecs(tte-tts)); a.resize(0); ic = 3000000; for (int i = 1; i <= ic; i++) { a += xrintr(i,33,1222333,false,true); } print("unsorted a[0] is %d\n",a[0]); print("unsorted a[(a.length - 1)] is %d\n",a[(a.length - 1)]); tts = GLib.get_monotonic_time(); intshellsort(ref a, false); tte = GLib.get_monotonic_time(); print("sorted a[0] is %d\n",a[0]); print("sorted a[(a.length - 1)] is %d\n",a[(a.length - 1)]); print("intshellsort of %d items took %s\n\n",ic,printusecs(tte-tts)); a.resize(0); ic = 30000; for (int i = 1; i <= ic; i++) { a += xrintr(i,33,12333,false,true); } print("unsorted a[0] is %d\n",a[0]); print("unsorted a[(a.length - 1)] is %d\n",a[(a.length - 1)]); tts = GLib.get_monotonic_time(); intshellsort(ref a, false); tte = GLib.get_monotonic_time(); print("sorted a[0] is %d\n",a[0]); print("sorted a[(a.length - 1)] is %d\n",a[(a.length - 1)]); print("intshellsort of %d items took %s\n\n",ic,printusecs(tte-tts)); a.resize(0); ic = 3000; for (int i = 1; i <= ic; i++) { a += xrintr(i,33,1222,false,true); } print("unsorted a[0] is %d\n",a[0]); print("unsorted a[(a.length - 1)] is %d\n",a[(a.length - 1)]); tts = GLib.get_monotonic_time(); intshellsort(ref a, false); tte = GLib.get_monotonic_time(); print("sorted a[0] is %d\n",a[0]); print("sorted a[(a.length - 1)] is %d\n",a[(a.length - 1)]); print("intshellsort of %d items took %s\n\n",ic,printusecs(tte-tts)); }
#+RESULTS:
unsorted a[0] is 9622654 unsorted a[(a.length - 1)] is 3512497 sorted a[0] is 33 sorted a[(a.length - 1)] is 12333444 intshellsort of 30000000 items took 8.73 s reversed a[0] is 12333444 reversed a[(a.length - 1)] is 33 reverse intshellsort of 30000000 items took 2.78 s unsorted a[0] is 1113917 unsorted a[(a.length - 1)] is 301321 sorted a[0] is 33 sorted a[(a.length - 1)] is 1222333 intshellsort of 3000000 items took 744.62 ms unsorted a[0] is 9506 unsorted a[(a.length - 1)] is 825 sorted a[0] is 33 sorted a[(a.length - 1)] is 12333 intshellsort of 30000 items took 4.51 ms unsorted a[0] is 132 unsorted a[(a.length - 1)] is 1190 sorted a[0] is 33 sorted a[(a.length - 1)] is 1222 intshellsort of 3000 items took 323 μs
[5_DONE]SCRAMBLE
[5_DONE]INTSCRAMBLE_INF

Scramble integers in an array by pseudo-randomly swapping items.
Pseudo-ramdom number is generated by xorshifting GLib.get_monotonic_time() + i using one of a number of xorshifts published by George Marsaglia here. This technique is much faster than GLib.random, howver xorshifting is not truly random and shouldn't be used to obfusicate sensitive data.

Usage:

intscramble iscr = new intscramble(int s, int e);
iscr.run(ref int[] p[], ref int packetscomplete);

  • int s is the 1st item of the array to scramble.
  • int e is the last item of the array to scramble.
  • ref int[] p is the int[] to scramble
  • ref int packetscomplete is a counter to tell main() to wait if multithreading

[5_DONE]INTSCRAMBLE_SRC
public class intscramble : Object { int s; int e; int r; public intscramble (int st, int en) { s = st; e = en; r = (e - s) + 1; } public void run (ref int[] p, ref int packetscomplete) { if (r < 2) { return; } int[] gaps = makeleegaps(r); foreach (int g in gaps) { for (int i = s; i <= e; i++) { if (i >= g) { int t = p[i]; int j = i; while ( (j >= g) && ((j - g) >= s) && ((xrintr(i,0,999,true,true) & 1) == 0) ) { p[j] = p[(j - g)]; j -= g; } if ((j != i) && (j >= s)) { p[j] = t; } } } } mutex.lock(); packetscomplete += 1; mutex.unlock(); } }
[5_DONE]INTSCRAMBLE_TEST
GLib.Mutex mutex; string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } int xrintr (int i, int s, int e, bool t, bool m) { // pseudo-random integer range // by c.p.brown 2025 // // i is seed, s is min value, e is max value, // t is use time + seed (different result each eval) // m is modulo within range rather than scale to range // // uses xorshift offsets by George Marsaglia (2003) // https://www.jstatsoft.org/article/view/v008i14 int[] ph = { 4,3,27, // 31 ▂█▄▇▃▃▇▄█▂▆▁▅█▄▇▃▅▁▆▂▂▆▁▅▃▇▄█▄ 5,27,25, // 44 ▃▅▇▁▃▅▇▁▃█▆▄▂█▆▄▂█▆▄▂█▆▄▂▇▅▃▁▇ 1,9,29, // 03 ▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆▁▄▃▂▅█▇▆ 13,3,17, // 71 ▁▃▄▂█▆▃▁▇▅▂▄▆█▁▃▅▇█▆▄▂▇▅▃▁▆█▂▄ 9,5,25, // 61 ▆▃▄▁▂▇█▅▆▃▄▁▂█▇▆▅▄▃▂▁█▇▆▅▄▃▂▁▅ 3,7,29, // 25 ▅█▇▂▁▄▃▃▄▁▂▇█▅▆▃▄▁▂▇█▅▆▄▃▂▁█▇▆ 3,5,25, // 24 █▁▁▂▂▃▃▄▄▃▃▄▄▁▁▂▂▇▇██▅▅▆▆▄▄▃▃▂ 15,1,29 // 77 ▄▂▁▁▂▄▃▇█▆▅▅▆█▇▃▄▂▁▁▂▄▃▇█▆▅▅▆█ }; int phl = ph.length / 3; uint th = (uint) i; if (t) { th = (uint) GLib.get_monotonic_time() + i; } int pl = (i % phl) * 3; th^=(th<<ph[pl]); th^=(th>>ph[pl+1]); th^=(th<<ph[pl+2]); if (m) { return ((int) (th % ((uint) ((e+1)-s)))) + s; } return ((int) ((((double) th) / uint32.MAX) * ((double) ((e+1)-s)))) + s; } int[] makeleegaps(int n) { int thn = int.min((n / 3),(int32.MAX / 3)); int[] spag = {}; int l = 1; while (l < 100) { int g = (int) Math.floor( Math.pow(2.243609061420001,((double) l)) / (2.243609061420001 - 1.0) ); if (g > thn) { break; } spag += g; l += 1; } //print("makeleegaps l is %d\n",l); int ll = spag.length - 1; if (ll > -1) { int[] gaps = new int[(ll+1)]; for (int i = ll; i >= 0; i--) { gaps[ll-i] = spag[i]; } return gaps; } return {331490,147748,65853,29351,13082,5830,2598,1158,516,230,102,45,20,9,4,1}; } public class intscramble : Object { int s; int e; int r; public intscramble (int st, int en) { s = st; e = en; r = (e - s) + 1; } public void run (ref int[] p, ref int packetscomplete) { if (r < 2) { return; } int[] gaps = makeleegaps(r); foreach (int g in gaps) { for (int i = s; i <= e; i++) { if (i >= g) { int t = p[i]; int j = i; while ( (j >= g) && ((j - g) >= s) && ((xrintr(i,0,999,true,true) & 1) == 0) ) { p[j] = p[(j - g)]; j -= g; } if ((j != i) && (j >= s)) { p[j] = t; } } } } mutex.lock(); packetscomplete += 1; mutex.unlock(); } } void main() { GLib.Intl.setlocale(ALL,""); mutex = new GLib.Mutex(); int[] ph = { 0,0,0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4,4,4, 5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7, 8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9 }; int phr = ph.length; int pc = 0; int[] ix = {}; for (int i = 0; i < phr; i++) { ix += ph[i]; } int64 tts = GLib.get_monotonic_time(); intscramble iscr = new intscramble(0,(ix.length - 1)); iscr.run(ref ix, ref pc); int64 tte = GLib.get_monotonic_time(); print("\nfull intscramble took %s\n",printusecs(tte-tts)); for (int i = 0; i < ix.length; i += 1) { if ((i % 10) == 0) { print("\n\t\t"); } print("%d",ix[i]); } print("\n"); // scramble a sub-range ix.resize(0); for (int i = 0; i < phr; i++) { ix += ph[i]; } tts = GLib.get_monotonic_time(); intscramble siscr = new intscramble(21,69); siscr.run(ref ix, ref pc); tte = GLib.get_monotonic_time(); print("\npartial intscramble took %s\n",printusecs(tte-tts)); for (int i = 0; i < ix.length; i += 1) { if ((i % 10) == 0) { print("\n\t\t"); } print("%d",ix[i]); } print("\n"); }
#+RESULTS:
Compilation succeeded - 1 warning(s) full intscramble took 170 μs 9592890413 0130903363 5483827542 3001943378 1756181592 7402214125 8666276457 4019587076 0465289895 6437261798 partial intscramble took 31 μs 0000000000 1111111111 2342453632 3264566225 6634653644 6425453256 3324455532 7777777777 8888888888 9999999999
STRINGS
[5_DONE]MAXFRAC
[5_DONE]MAXFRAC_INF

Returns a string from double with up to 16 digits, excluding the radix.
Significant digits are prioritized over fractional digits.
Trailing zeroes can be stripped using STRIPZEROES.

Used to store numbers as strings with the greatest accuracy allowed by double, for later use via double.parse()

Usage:

maxfrac(double n)

  • double n is the number to convert

[5_DONE]MAXFRAC_SRC
string maxfrac (double n) { double x = n.abs(); if (x < 10.0) { return "%.*f".printf(15,n); } if (x < 100.0) { return "%.*f".printf(14,n); } if (x < 1000.0) { return "%.*f".printf(13,n); } if (x < 10000.0) { return "%.*f".printf(12,n); } if (x < 100000.0) { return "%.*f".printf(11,n); } if (x < 1000000.0) { return "%.*f".printf(10,n); } if (x < 10000000.0) { return "%.*f".printf(9,n); } if (x < 100000000.0) { return "%.*f".printf(8,n); } if (x < 1000000000.0) { return "%.*f".printf(7,n); } if (x < 10000000000.0) { return "%.*f".printf(6,n); } if (x < 109999999999.0) { return "%.*f".printf(5,n); } if (x < 1000000000000.0) { return "%.*f".printf(4,n); } if (x < 10000000000000.0) { return "%.*f".printf(3,n); } if (x < 100000000000000.0) { return "%.*f".printf(2,n); } return "%.*f".printf(1,n); }
[5_DONE]MAXFRAC_TEST
// made to check the point of overflow // seems to be fine with 16 digits in total excluding radix and sign // by c.p.brown 2026 string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } string maxfrac (double n) { double x = n.abs(); if (x < 10.0) { return "%.*f".printf(15,n); } if (x < 100.0) { return "%.*f".printf(14,n); } if (x < 1000.0) { return "%.*f".printf(13,n); } if (x < 10000.0) { return "%.*f".printf(12,n); } if (x < 100000.0) { return "%.*f".printf(11,n); } if (x < 1000000.0) { return "%.*f".printf(10,n); } if (x < 10000000.0) { return "%.*f".printf(9,n); } if (x < 100000000.0) { return "%.*f".printf(8,n); } if (x < 1000000000.0) { return "%.*f".printf(7,n); } if (x < 10000000000.0) { return "%.*f".printf(6,n); } if (x < 109999999999.0) { return "%.*f".printf(5,n); } if (x < 1000000000000.0) { return "%.*f".printf(4,n); } if (x < 10000000000000.0) { return "%.*f".printf(3,n); } if (x < 100000000000000.0) { return "%.*f".printf(2,n); } return "%.*f".printf(1,n); } void main() { int64 tts = GLib.get_monotonic_time(); GLib.Intl.setlocale(ALL,""); double n = 0.0; n = 999999999999999.9; print("%s\n",maxfrac(n)); n = 123456789123456.1; print("%s\n",maxfrac(n)); n = 12345678912345.12; print("%s\n",maxfrac(n)); n = 1234567891234.123; print("%s\n",maxfrac(n)); n = 123456789123.1234; print("%s\n",maxfrac(n)); n = 12345678912.12345; print("%s\n",maxfrac(n)); n = 1234567891.123456; print("%s\n",maxfrac(n)); n = 123456789.1234567; print("%s\n",maxfrac(n)); n = 12345678.12345678; print("%s\n",maxfrac(n)); n = 1234567.123456789; print("%s\n",maxfrac(n)); n = 123456.1234567891; print("%s\n",maxfrac(n)); n = 12345.12345678912; print("%s\n",maxfrac(n)); n = 1234.123456789123; print("%s\n",maxfrac(n)); n = 123.1234567891234; print("%s\n",maxfrac(n)); n = 12.12345678912345; print("%s\n",maxfrac(n)); n = 1.123456789123456; print("%s\n",maxfrac(n)); n = 0.0; print("%s\n",maxfrac(n)); n = -1.123456789123456; print("%s\n",maxfrac(n)); n = -12.12345678912345; print("%s\n",maxfrac(n)); n = -123.1234567891234; print("%s\n",maxfrac(n)); n = -1234.123456789123; print("%s\n",maxfrac(n)); n = -12345.12345678912; print("%s\n",maxfrac(n)); n = -123456.1234567891; print("%s\n",maxfrac(n)); n = -1234567.123456789; print("%s\n",maxfrac(n)); n = -12345678.12345678; print("%s\n",maxfrac(n)); n = -123456789.1234567; print("%s\n",maxfrac(n)); n = -1234567891.123456; print("%s\n",maxfrac(n)); n = -12345678912.12345; print("%s\n",maxfrac(n)); n = -123456789123.1234; print("%s\n",maxfrac(n)); n = -1234567891234.123; print("%s\n",maxfrac(n)); n = -12345678912345.12; print("%s\n",maxfrac(n)); n = -123456789123456.1; print("%s\n",maxfrac(n)); n = -999999999999999.9; print("%s\n",maxfrac(n)); int64 tte = GLib.get_monotonic_time(); print("maxfrac test took %s",printusecs(tte - tts)); }
#+RESULTS:
999999999999999.9 123456789123456.1 12345678912345.12 1234567891234.123 123456789123.1234 12345678912.12345 1234567891.123456 123456789.1234567 12345678.12345678 1234567.123456789 123456.1234567891 12345.12345678912 1234.123456789123 123.1234567891234 12.12345678912345 1.123456789123456 0.000000000000000 -1.123456789123456 -12.12345678912345 -123.1234567891234 -1234.123456789123 -12345.12345678912 -123456.1234567891 -1234567.123456789 -12345678.12345678 -123456789.1234567 -1234567891.123456 -12345678912.12345 -123456789123.1234 -1234567891234.123 -12345678912345.12 -123456789123456.1 -999999999999999.9 maxfrac test took 87 μs
[5_DONE]ISANUMBER
[5_DONE]ISANUMBER_INF

This is a slow/careful function.

Check if a string is a parseable number, also output a cleaned variant of the string.
Cleaning removes commas and certain prefixes, as well as up to 2 leading spaces, and a space between prefix and the number.

Depends on MAXFRAC to store numbers at greatest accuracy.
Depends on STRIPZEROES for formatting.

Usage:

bool isanumber(string s, bool pc, out string c)

  • string s is the string to check
  • bool pc is to convert percentages into a multiplier, eg: 80% as 0.8
  • out string c is the string to output a parseable string (using double.parse())

Returns:
  • true if string s is a parsable representation of a number
  • false if string s :
    • cannot be parsed as a number, eg: "thirty"
    • requires too much preprocessing to parse, eg: "EUR 100,000.00 €"
    • is too ambiguous to parse, eg: "120:10:24:5"

[5_DONE]ISANUMBER_SRC
bool isanumber (string s, bool pc, out string c) { StringBuilder sb = new StringBuilder(""); StringBuilder sbs = new StringBuilder(""); sbs.append(s); sbs.str = sbs.str.strip(); bool hasradix = false; int scc = sbs.str.char_count(); int pfx = 0; int pnc = 0; bool prx = true; bool pre = true; for (int x = 0; x < scc; x++) { int i = sbs.str.index_of_nth_char(x); unichar u = sbs.str.get_char(i); if (pre) { if (u == ' ') { continue; } if (u == ',') { c = ""; return false; } if (u == '-') { pfx = (x + 1); pre = false; sb.append_unichar(u); continue; } if (u == '+') { pfx = (x + 1); pre = false; continue; } if (u == '$') { pfx = (x + 1); pre = false; continue; } if (u == '±') { pfx = (x + 1); pre = false; continue; } } if (x == pfx) { if (u == ' ') { continue; } } if (u == ',') { continue; } if (u == '.') { if (!hasradix) { pre = false; prx = false; sb.append_unichar(u); hasradix = true; continue; } else { c = ""; return false; } } if (u.isdigit() == false) { if (!pre) { if (x == (scc - 2)) { if (u == ' ') { unichar j = sbs.str.get_char(sbs.str.index_of_nth_char(x+1)); if (j == '°') { if (sb.str.char_count() > 0) { c = maxfrac(double.parse(sb.str)); c = stripzeroes(c); return true; } } } } else { if (x == (scc - 1)) { if (u == '°') { if (sb.str.char_count() > 0) { c = maxfrac(double.parse(sb.str.dup())); c = stripzeroes(c); return true; } } if (u == '%') { if (sb.str.char_count() > 0) { if (pc) { double perc = double.parse(sb.str); c = maxfrac((perc / 100.0)); } else { c = maxfrac(double.parse(sb.str.dup())); } c = stripzeroes(c); return true; } } } } } c = ""; return false; } pre = false; sb.append_unichar(u); pnc += 1; if (pnc > 14) { if (sb.str.char_count() > 0) { c = maxfrac(double.parse(sb.str.dup())); c = stripzeroes(c); return true; } } } c = maxfrac(double.parse(sb.str.dup())); c = c = stripzeroes(c); return true; }
[5_DONE]ISANUMBER_TEST
// scrutinize various string representations of numbers // by c.p.brown 2026 string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } string stripzeroes (string s) { int q = s.index_of_char('.'); int scc = s.char_count(); if ((scc > 0) && (q == -1)) { return s; } int l = s.index_of_nth_char(scc - 1); unichar lc = s.get_char(l); if (lc == '0') { if((q + 1) != l) { int ee = l; int i = l; for (int x = (scc - 1); x >= 0; x--) { i = s.index_of_nth_char(x); unichar u = s.get_char(i); if (u == '.') { ee += 1; break; } if (u != '0') { break; } ee = int.max(0,int.min(l,i)); } return s.splice(ee,(l+1),""); } } return s; } string maxfrac (double n) { double x = n.abs(); if (x < 10.0) { return "%.*f".printf(15,n); } if (x < 100.0) { return "%.*f".printf(14,n); } if (x < 1000.0) { return "%.*f".printf(13,n); } if (x < 10000.0) { return "%.*f".printf(12,n); } if (x < 100000.0) { return "%.*f".printf(11,n); } if (x < 1000000.0) { return "%.*f".printf(10,n); } if (x < 10000000.0) { return "%.*f".printf(9,n); } if (x < 100000000.0) { return "%.*f".printf(8,n); } if (x < 1000000000.0) { return "%.*f".printf(7,n); } if (x < 10000000000.0) { return "%.*f".printf(6,n); } if (x < 109999999999.0) { return "%.*f".printf(5,n); } if (x < 1000000000000.0) { return "%.*f".printf(4,n); } if (x < 10000000000000.0) { return "%.*f".printf(3,n); } if (x < 100000000000000.0) { return "%.*f".printf(2,n); } return "%.*f".printf(1,n); } bool isanumber (string s, bool pc, out string c) { StringBuilder sb = new StringBuilder(""); StringBuilder sbs = new StringBuilder(""); sbs.append(s); sbs.str = sbs.str.strip(); bool hasradix = false; int scc = sbs.str.char_count(); int pfx = 0; int pnc = 0; bool prx = true; bool pre = true; for (int x = 0; x < scc; x++) { int i = sbs.str.index_of_nth_char(x); unichar u = sbs.str.get_char(i); if (pre) { if (u == ' ') { continue; } if (u == ',') { c = ""; return false; } if (u == '-') { pfx = (x + 1); pre = false; sb.append_unichar(u); continue; } if (u == '+') { pfx = (x + 1); pre = false; continue; } if (u == '$') { pfx = (x + 1); pre = false; continue; } if (u == '±') { pfx = (x + 1); pre = false; continue; } } if (x == pfx) { if (u == ' ') { continue; } } if (u == ',') { continue; } if (u == '.') { if (!hasradix) { pre = false; prx = false; sb.append_unichar(u); hasradix = true; continue; } else { c = ""; return false; } } if (u.isdigit() == false) { if (!pre) { if (x == (scc - 2)) { if (u == ' ') { unichar j = sbs.str.get_char(sbs.str.index_of_nth_char(x+1)); if (j == '°') { if (sb.str.char_count() > 0) { c = maxfrac(double.parse(sb.str)); c = stripzeroes(c); return true; } } } } else { if (x == (scc - 1)) { if (u == '°') { if (sb.str.char_count() > 0) { c = maxfrac(double.parse(sb.str.dup())); c = stripzeroes(c); return true; } } if (u == '%') { if (sb.str.char_count() > 0) { if (pc) { double perc = double.parse(sb.str); c = maxfrac((perc / 100.0)); } else { c = maxfrac(double.parse(sb.str.dup())); } c = stripzeroes(c); return true; } } } } } c = ""; return false; } pre = false; sb.append_unichar(u); pnc += 1; if (pnc > 14) { if (sb.str.char_count() > 0) { c = maxfrac(double.parse(sb.str.dup())); c = stripzeroes(c); return true; } } } c = maxfrac(double.parse(sb.str.dup())); c = c = stripzeroes(c); return true; } void main() { int64 tts = GLib.get_monotonic_time(); GLib.Intl.setlocale(ALL,""); string[] s = { "1", "-1", "11", "1.0", "-1.0", " 1", "1 ", ".5", ",5", "25%", "- 75%", "-80.5%", "+ 99.99 %", "- 50.123456%", "1234567.7654321%", "12345678912345.9", "1234567891234.98", "12345678.9876543", "1234.98765432198", "1.98765432198765", "+30+10+5", "20-10-10", "1A", "$1", "1 $", "$ 150,000", " $ 50.25", "AUD$ 100.0", "5\'2\"", "#7", "29°", "29 °", "10.3.5", "+1", "1,2", "1,2.5", "1.2,5", "± 6", " ± 50.5", "+ 50,000", "100_000", "10:39:04", "- 180.05", "= 100.00", " - 10.0", " - 10.0", " -- 20.1", "+,.,", "-+,.,", " - ,.," }; int sl = s.length; print("| NUMBER | CLEAN | PARSED |\n"); print("|-- | | |\n"); for (int i = 0; i < sl; i++) { string c = ""; if (isanumber(s[i], true, out c)) { print("| \"%s\" | \"%s\" | %.2f |\n",s[i],c,(double.parse(c))); } else { print("| \"%s\" | \"%s\" | |\n",s[i],c); } } int64 tte = GLib.get_monotonic_time(); print("isanumber test took %s",printusecs(tte - tts)); }
#+RESULTS:
| NUMBER | CLEAN | PARSED | |--------------------+--------------------+-------------------| | "1" | "1.0" | 1.00 | | "-1" | "-1.0" | -1.00 | | "11" | "11.0" | 11.00 | | "1.0" | "1.0" | 1.00 | | "-1.0" | "-1.0" | -1.00 | | " 1" | "1.0" | 1.00 | | "1 " | "1.0" | 1.00 | | ".5" | "0.5" | 0.50 | | ",5" | "" | | | "25%" | "0.25" | 0.25 | | "- 75%" | "-0.75" | -0.75 | | "-80.5%" | "-0.805" | -0.81 | | "+ 99.99 %" | "" | | | "- 50.123456%" | "-0.50123456" | -0.50 | | "1234567.7654321%" | "12345.677654321" | 12345.68 | | "12345678912345.9" | "12345678912345.9" | 12345678912345.90 | | "1234567891234.98" | "1234567891234.98" | 1234567891234.98 | | "12345678.9876543" | "12345678.9876543" | 12345678.99 | | "1234.98765432198" | "1234.98765432198" | 1234.99 | | "1.98765432198765" | "1.98765432198765" | 1.99 | | "+30+10+5" | "" | | | "20-10-10" | "" | | | "1A" | "" | | | "$1" | "1.0" | 1.00 | | "1 $" | "" | | | "$ 150,000" | "150000.0" | 150000.00 | | " $ 50.25" | "50.25" | 50.25 | | "AUD$ 100.0" | "" | | | "5'2"" | "" | | | "#7" | "" | | | "29°" | "29.0" | 29.00 | | "29 °" | "29.0" | 29.00 | | "10.3.5" | "" | | | "+1" | "1.0" | 1.00 | | "1,2" | "12.0" | 12.00 | | "1,2.5" | "12.5" | 12.50 | | "1.2,5" | "1.25" | 1.25 | | "± 6" | "6.0" | 6.00 | | " ± 50.5" | "50.5" | 50.50 | | "+ 50,000" | "50000.0" | 50000.00 | | "100_000" | "" | | | "10:39:04" | "" | | | "- 180.05" | "-180.05" | -180.05 | | "= 100.00" | "" | | | " - 10.0" | "-10.0" | -10.00 | | " - 10.0" | "-10.0" | -10.00 | | " -- 20.1" | "" | | | "+,.," | "0.0" | 0.00 | | "-+,.," | "" | | | " - ,.," | "0.0" | 0.00 | isanumber test took 153 μs
[5_DONE]STRIPZEROES
[5_DONE]STRIPZEROES_INF

Strips a contigious sequence of zeroes from the end of a string, if to the right of a radix. Will leave at least one zero after the radix if the sequence starts there.

Use with strings formatted with "%.*f".printf(x,n), where x is larger than the required number of digits, for example:
  • "%.*f".printf(6,50.123)
    • = "50.123000"
    • stripzeroes("50.123000")
      • = "50.123"

Examples:

  • stripzeroes("50.0")
    • = "50.0"
  • stripzeroes("50.000")
    • = "50.0"
  • stripzeroes("50.1000")
    • = "50.1"
  • stripzeroes("50.")
    • = "50."
  • stripzeroes("50.零0")
    • = "50.零"

Usage:

string stripzeroes(string s)

  • string s is the string to strip trailing zeroes from

Returns:

  • string s with trailing zeroes removed, except the 1st zero after the radix

[5_DONE]STRIPZEROES_SRC
string stripzeroes (string s) { int q = s.index_of_char('.'); int scc = s.char_count(); if ((scc > 0) && (q == -1)) { return s; } int l = s.index_of_nth_char(scc - 1); unichar lc = s.get_char(l); if (lc == '0') { if((q + 1) != l) { int ee = l; int i = l; for (int x = (scc - 1); x >= 0; x--) { i = s.index_of_nth_char(x); unichar u = s.get_char(i); if (u == '.') { ee += 1; break; } if (u != '0') { break; } ee = int.max(0,int.min(l,i)); } return s.splice(ee,(l+1),""); } } return s; }
[5_DONE]STRIPZEROES_TEST
string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } string stripzeroes (string s) { int q = s.index_of_char('.'); int scc = s.char_count(); if ((scc > 0) && (q == -1)) { return s; } int l = s.index_of_nth_char(scc - 1); unichar lc = s.get_char(l); if (lc == '0') { if((q + 1) != l) { int ee = l; int i = l; for (int x = (scc - 1); x >= 0; x--) { i = s.index_of_nth_char(x); unichar u = s.get_char(i); if (u == '.') { ee += 1; break; } if (u != '0') { break; } ee = int.max(0,int.min(l,i)); } return s.splice(ee,(l+1),""); } } return s; } void main() { int64 tts = GLib.get_monotonic_time(); GLib.Intl.setlocale(ALL,""); string[] s = { "0", "00", "000", "0.", ".0", "0.0", "00.0", "0.00", ".000", "0.零0", "零.零0", "0.零0零0", "0.零00", "0.0000000000000000000000000000000000000000000000000" }; for(int i = 0; i < s.length; i++) { print(" \"%s\"\n=\"%s\"\n\n",s[i],stripzeroes(s[i])); } int64 tte = GLib.get_monotonic_time(); print("stripwhat test took %s",printusecs(tte - tts)); } #+RESULTS:
Compilation succeeded - 1 warning(s) "0" ="0" "00" ="00" "000" ="000" "0." ="0." ".0" =".0" "0.0" ="0.0" "00.0" ="00.0" "0.00" ="0.0" ".000" =".0" "0.零0" ="0.零" "零.零0" ="零.零" "0.零0零0" ="0.零0零" "0.零00" ="0.零" "0.0000000000000000000000000000000000000000000000000" ="0.0" stripwhat test took 89 μs
SPLICE
SPLICE_TEST

Test to see how splice() can remove the last character, and to verify if splice(a,b,s) is splice(start,offset,string), or splice(start,end,string).

Results:
  • start and end are absolute positions, unlike substring()
  • splicing with the same start and end positions will insert before the start position
  • splicing from the position of the last char (l) to l+last_char.length won't remove the terminator

void main() { string s = "0123456789"; int a = 9; int b = 10; string p = s.splice(a,b,"X"); print("splice %s from %d to %d: %s\n",s,a,b,p); if (p[p.length] == '\0') { print("spliced string is valid\n"); } a = 3; b = 3; p = s.splice(a,b,"XXX"); print("splice %s from %d to %d: %s\n",s,a,b,p); if (p[p.length] == '\0') { print("spliced string is valid\n"); } a = 3; b = 3+3; p = s.splice(a,b,"XXX"); print("splice %s from %d to %d: %s\n",s,a,b,p); if (p[p.length] == '\0') { print("spliced string is valid\n"); } }
#+RESULTS:
splice 0123456789 from 9 to 10: 012345678X spliced string is valid splice 0123456789 from 3 to 3: 012XXX3456789 spliced string is valid splice 0123456789 from 3 to 6: 012XXX6789 spliced string is valid
[5_DONE]CHARCOUNT
[5_DONE]CHARCOUNT_INF

Count occurances of char c in string s, unless escaped by e if x is true.

charcount(string s, unichar c, unichar e, bool x);

  • string s is the string to search
  • unichar c is the character to count
  • unichar e is the escape character
  • bool x is to use the escape character

Example:
int charcount(string s, unichar c, unichar e, bool x) { // written by c.p.brown 2026 int cc = 0; int ii = s.index_of_char(c); if (x) { while (ii > -1) { unowned string atp = s.offset(ii); atp = atp.prev_char(); if (atp.get_char(0) != e) { cc += 1; } ii = s.index_of_char(c,(ii+1)); } } else { while (ii > -1) { cc += 1; ii = s.index_of_char(c,(ii+1)); } } print("charcount returns %d\n",cc); return cc; } void main() { string s = "a\nmultiline\nstring\ngoes\\nhere\n"; int cc = charcount(s, '\n', '\\', true); print("%d",cc); }
#+RESULTS:
4
[5_DONE]CHARCOUNT_SRC
int charcount(string s, unichar c, unichar e, bool x) { // written by c.p.brown 2026 int cc = 0; int ii = s.index_of_char(c); if (x) { while (ii > -1) { unowned string atp = s.offset(ii); atp = atp.prev_char(); if (atp.get_char(0) != e) { cc += 1; } ii = s.index_of_char(c,(ii+1)); } } else { while (ii > -1) { cc += 1; ii = s.index_of_char(c,(ii+1)); } } print("charcount returns %d\n",cc); return cc; }
[5_DONE]CHARCOUNT_TEST

compare monothreaded charcount with multithreaded tpcharcount

compare with StringBuilder.replace()

note: StringBuilder.replace() is slower but better suited for finding strings, and escaping with mult-char escapes.
For open/close escape tags, with multiple escape tags it may be necessary to fall back to tracking state in a char-loop.

// string.index_of_char() vs StringBuilder.replace() // by c.p.brown 2026 GLib.Mutex mutex; string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } int[] rangeseq (int p, int s) { // rangeseq // by c.p.brown 2026 // // p packet count, s sequence count // returns rangefrom,rangeto pairs in an unrolled 1d array int[] o = {}; if (s > p) { int t = s / p; double dp = ((double) p); double npt = ((double) s) / ((double) p); int v = 0; int x = 0; if ((double) t < npt) { double rem = npt - t; x = ((int) Math.round(rem * dp)); } for (int i = 0; i < p; i++) { o += v; v += (t - 1); if (x > 0) { v += 1; } o += v; v += 1; x = int.max(0,(x - 1)); } } else { for (int i = 0; i < s; i++) { o += i; o += i; } } return o; } int charcount(string s, unichar c, unichar e, bool x) { // written by c.p.brown 2026 int cc = 0; int ii = s.index_of_char(c); if (x) { while (ii > -1) { unowned string atp = s.offset(ii); atp = atp.prev_char(); if (atp.get_char(0) != e) { cc += 1; } ii = s.index_of_char(c,(ii+1)); } } else { while (ii > -1) { cc += 1; ii = s.index_of_char(c,(ii+1)); } } print("charcount returns %d\n",cc); return cc; } public class tpcharcount : Object { // by c.p.brown 2026 private int packetnum; private int first; private int last; private unichar n; private unichar e; private bool x; public tpcharcount (int pn, int f, int l, unichar fc, unichar ec, bool de) { packetnum = pn; first = f; last = l; n = fc; e = ec; x = de; } public void run(string[] s, int[] ccs, ref int packetscomplete) { int pcc = 0; for (int i = first; i <= last; i++) { int cc = 0; int ii = s[i].index_of_char(n); if (x) { while (ii > -1) { unowned string atp = s[i].offset(ii); atp = atp.prev_char(); if (atp.get_char(0) != e) { cc += 1; } ii = s[i].index_of_char(n,(ii+1)); } } else { while (ii > -1) { cc += 1; ii = s[i].index_of_char(n,(ii+1)); } } pcc += cc; } ccs[packetnum] = pcc; mutex.lock(); packetscomplete += 1; mutex.unlock(); } } uint sbstringcount(string h, string n, string e) { StringBuilder sb = new StringBuilder(""); sb.append(h); if (e != "") { string en = (e + n); string d = '\x1D'.to_string(); sb.replace(en,d,0); } return sb.replace(n,n,0); } void main() { GLib.Intl.setlocale(ALL,""); mutex = new GLib.Mutex(); string f = "./testdata/leipzig1M.txt"; string[] l = {}; GLib.File ff = GLib.File.new_for_path(f); if (ff.query_exists()) { GLib.FileStream fstr = GLib.FileStream.open(f,"r"); StringBuilder sb = new StringBuilder(""); while (true) { string fs = fstr.read_line(); if (fs == null) { break; } sb.erase(); sb.append(fs); l += sb.str.dup(); } } int ll = l.length; // monothreaded index_of_char() int64 tts = GLib.get_monotonic_time(); int cc = 0; for (int i = 0; i < ll; i++) { cc += charcount(l[i],'.',' ',true); } int64 tte = GLib.get_monotonic_time(); print("it took %s to count %d unescaped \'.\' in %d strings via string.index_of_char()\n\n",printusecs(tte - tts),cc,ll); tts = GLib.get_monotonic_time(); cc = 0; for (int i = 0; i < ll; i++) { cc += charcount(l[i],'.',' ',false); } tte = GLib.get_monotonic_time(); print("it took %s to count %d \'.\' in %d strings via string.index_of_char()\n\n",printusecs(tte - tts),cc,ll); tts = GLib.get_monotonic_time(); cc = charcount("",'.',' ',false); tte = GLib.get_monotonic_time(); print("it took %s to count %u \".\" in no_string via string.index_of_char()\n\n",printusecs(tte - tts),cc); // multithreaded index_of_char() tts = GLib.get_monotonic_time(); int nthr = (int) GLib.get_num_processors(); int packetcount = nthr * 2; int packetscomplete = 0; int[] rr = rangeseq(packetcount,ll); int pc = 0; int[] ccs = {}; for (int i = 0; i < packetcount; i++) { ccs += 0; } ThreadPool<tpcharcount> tcc = new ThreadPool<tpcharcount>.with_owned_data((tpcharcount) => { tpcharcount.run(l,ccs,ref packetscomplete); },nthr,false); for (int i = 0; i < rr.length; i += 2) { tcc.add(new tpcharcount( pc, rr[i], rr[i+1], '.', ' ', true )); pc += 1; } while (packetscomplete != pc) { GLib.Thread.usleep(1); } int tpcc = 0; foreach (int i in ccs) { tpcc += i; } tte = GLib.get_monotonic_time(); print("it took %s to count %u unescaped \'.\' in %d strings via tpcharcount\n\n",printusecs(tte - tts),tpcc,ll); // monothreaded StringBuilder.replace() tts = GLib.get_monotonic_time(); uint ucc = 0; for (int i = 0; i < ll; i++) { ucc += sbstringcount(l[i],"."," "); } tte = GLib.get_monotonic_time(); print("it took %s to count %u unescaped \".\" in %d strings via StringBuilder.replace()\n\n",printusecs(tte - tts),ucc,ll); tts = GLib.get_monotonic_time(); ucc = 0; for (int i = 0; i < ll; i++) { ucc += sbstringcount(l[i],".",""); } tte = GLib.get_monotonic_time(); print("it took %s to count %u \".\" in %d strings via StringBuilder.replace()\n\n",printusecs(tte - tts),ucc,ll); }
#+RESULTS:
Compilation succeeded - 3 warning(s) it took 48.22 ms to count 1395687 unescaped '.' in 1000000 strings via string.index_of_char() it took 40.33 ms to count 1395892 '.' in 1000000 strings via string.index_of_char() it took 0 μs to count 0 "." in no_string via string.index_of_char() it took 6.14 ms to count 1395687 unescaped '.' in 1000000 strings via tpcharcount it took 198.45 ms to count 1395687 unescaped "." in 1000000 strings via StringBuilder.replace() it took 95.11 ms to count 1395892 "." in 1000000 strings via StringBuilder.replace()
[5_DONE]TPCHARCOUNT
Tested in CHARCOUNT
[5_DONE]TPCHARCOUNT_INF

Wrapper for CHARCOUNT to operate in a ThreadPool.

Creation:

tpcharcount tcc = new tpcharcount(int pn, int f, int l, unichar fc, unichar ec, bool de);

  • int pn is the nth partition of s[] this will count
  • int f is the 1st item of s[] to count
  • int ; is the last item of s[] to count
  • unichar fc is the character to count
  • unichar ec is the character that escapes fc
  • bool de is do escape

Usage:

tcc.run(string[] s, int[] ccs, ref int packetscomplete)

  • string[] s refers ti the array of strings to process
  • int[] ccs is the array of character counts for each item in s[]
  • ref int packetscomplete is a counter that is incramented by each tpcharcount in the pool, and is used by the main program to wait until all tasks are complete

[5_DONE]TPCHARCOUNT_SRC
public class tpcharcount : Object { // by c.p.brown 2026 private int packetnum; private int first; private int last; private unichar n; private unichar e; private bool x; public tpcharcount (int pn, int f, int l, unichar fc, unichar ec, bool de) { packetnum = pn; first = f; last = l; n = fc; e = ec; x = de; } public void run(string[] s, int[] ccs, ref int packetscomplete) { int pcc = 0; for (int i = first; i <= last; i++) { int cc = 0; int ii = s[i].index_of_char(n); if (x) { while (ii > -1) { unowned string atp = s[i].offset(ii); atp = atp.prev_char(); if (atp.get_char(0) != e) { cc += 1; } ii = s[i].index_of_char(n,(ii+1)); } } else { while (ii > -1) { cc += 1; ii = s[i].index_of_char(n,(ii+1)); } } pcc += cc; } ccs[packetnum] = pcc; mutex.lock(); packetscomplete += 1; mutex.unlock(); } }
[1_IP..]DELIMITNEWLINES
DELIMITNEWLINES_TODO (0/0)
= [ ] write test
DELIMITNEWLINES_INF

Replace "\n" with '\x1E'.to_string(), excluding "\\n".

NOTE: This is a slow but reliable function, see DELIMITCHAR for a faster alternative.

DELIMITNEWLINES_SRC
string delimitnewlines(string s) { StringBuilder sb = new StringBuilder(""); sb.append(s); sb.replace("\\n",'\x1D'.to_string()); sb.replace("\n",'\x1E'.to_string()); sb.replace('\x1D'.to_string(),"\\n"); return sb.str; }
[5_DONE]DELIMITCHARS
[5_DONE]DELIMITCHARS_INF

Replace each occurance of a character with another character, if not preceeded by an escape character.

Construction:

delimitchars (int pn, int f, int l, unichar fc, unichar dc, unichar ec, bool de)

  • int pn is the current packet
  • int f is the 1st item of s[] to process
  • int l is the last item of s[] to process
  • unichar fc is the character to replace
  • unichar dc is the character to replace with
  • unichar ec is the character to escape fc
  • bool de is to check for fc

Usage:

dch.run(string[] s, ref int pc)

  • string[] s is the array of strings to process
  • ref int packetscomplete is a counter that is incramented by each delimitchars in the pool, and is used by the main program to wait until all tasks are complete

[5_DONE]DELIMITCHARS_SRC
public class delimitchars : Object { // written by c.p.brown 2026 private int packetnum; private int first; private int last; private unichar n; private unichar d; private unichar e; private bool x; public delimitchars (int pn, int f, int l, unichar fc, unichar dc, unichar ec, bool de) { packetnum = pn; first = f; last = l; n = fc; d = dc; e = ec; x = de; } public void run(string[] s, ref int packetscomplete) { string ns = ""; for (int i = first; i <= last; i++) { ns = ""; int cc = 0; int hh = 0; int ii = s[i].index_of_char(n); if (x) { while (ii > -1) { unowned string atp = s[i].offset(ii); atp = atp.prev_char(); if (atp.get_char(0) != e) { ns += s[i].substring(hh,(ii - hh)); ns += d.to_string(); hh = ii + 1; cc += 1; } ii = s[i].index_of_char(n,(ii + 1)); } } else { while (ii > -1) { ns += s[i].substring(hh,(ii - hh)); ns += d.to_string(); hh = ii + 1; cc += 1; ii = s[i].index_of_char(n,hh); } } if (hh < (s[i].length - 1)) { ns += s[i].substring(hh); } s[i] = ns; } mutex.lock(); packetscomplete += 1; mutex.unlock(); } }
[5_DONE]DELIMITCHARS_TEST
string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } string printstringarray (string[] s, int f) { // 0 1 2 3 4 5 6 7 8 9 string[] ii = {"", "\"", "{", "{\"", "[", "[", "| ", "", "", ""}; string[] dd = {";", ",", ",", "\",\"", " ", ",", " | ", " ", "\n", ",\n"}; string[] oo = {"", "\"", "}", "\"}", "]", "]", " |", "", "", ""}; string o = ii[f]; for (int i = 0; i < (s.length - 1); i++) { o = (o + "%s".printf(s[i]) + dd[f]); } o = (o + "%s".printf(s[s.length - 1]) + oo[f]); return o; } int[] rangeseq (int p, int s) { // rangeseq // by c.p.brown 2026 // // p packet count, s sequence count // returns rangefrom,rangeto pairs in an unrolled 1d array int[] o = {}; if (s > p) { int t = s / p; double dp = ((double) p); double npt = ((double) s) / ((double) p); int v = 0; int x = 0; if ((double) t < npt) { double rem = npt - t; x = ((int) Math.round(rem * dp)); } for (int i = 0; i < p; i++) { o += v; v += (t - 1); if (x > 0) { v += 1; } o += v; v += 1; x = int.max(0,(x - 1)); } } else { for (int i = 0; i < s; i++) { o += i; o += i; } } return o; } public class delimitchars : Object { // written by c.p.brown 2026 private int packetnum; private int first; private int last; private unichar n; private unichar d; private unichar e; private bool x; public delimitchars (int pn, int f, int l, unichar fc, unichar dc, unichar ec, bool de) { packetnum = pn; first = f; last = l; n = fc; d = dc; e = ec; x = de; } public void run(string[] s, ref int packetscomplete) { string ns = ""; for (int i = first; i <= last; i++) { ns = ""; int cc = 0; int hh = 0; int ii = s[i].index_of_char(n); if (x) { while (ii > -1) { unowned string atp = s[i].offset(ii); atp = atp.prev_char(); if (atp.get_char(0) != e) { ns += s[i].substring(hh,(ii - hh)); ns += d.to_string(); hh = ii + 1; cc += 1; } ii = s[i].index_of_char(n,(ii + 1)); } } else { while (ii > -1) { ns += s[i].substring(hh,(ii - hh)); ns += d.to_string(); hh = ii + 1; cc += 1; ii = s[i].index_of_char(n,hh); } } if (hh < (s[i].length - 1)) { ns += s[i].substring(hh); } s[i] = ns; } mutex.lock(); packetscomplete += 1; mutex.unlock(); } } GLib.Mutex mutex; void main() { mutex = new GLib.Mutex(); GLib.Intl.setlocale(ALL,""); string[] s = { "xxxx", "0xxx", "x0xx", "xx0x", "xxx0", "\\0xxx", "x\\0xx", "0x\\0x", "x0x\\0", "\\xx0x", "xxx0\\", "\\\\00xx", "\\x\\0xx", "\\x\\x\\x\\0\\", "\\\\\\\\", "0000", "" }; string[] o = {}; for (int i = 0; i < s.length; i++) { o += s[i].dup(); } //print("%s\n",printstringarray(s,9)); int64 tts = GLib.get_monotonic_time(); int pc = 0; delimitchars dc = new delimitchars( 0, 0, (s.length - 1), '0', '_', '\\', true ); dc.run(s,ref pc); int64 tte = GLib.get_monotonic_time(); print("delimitchars tool %s\n",printusecs(tte-tts)); for (int i = 0; i < s.length; i++) { print("| %02d | %s | %s |\n",i,o[i],s[i]); } print("\ndelimitchars stresstest:\n"); string f = "./testdata/leipzig1M.txt"; string[] l = {}; GLib.File ff = GLib.File.new_for_path(f); if (ff.query_exists()) { GLib.FileStream fstr = GLib.FileStream.open(f,"r"); StringBuilder sb = new StringBuilder(""); while (true) { string fs = fstr.read_line(); if (fs == null) { break; } sb.erase(); sb.append(fs); l += sb.str.dup(); } } tts = GLib.get_monotonic_time(); pc = 0; int nthr = (int) GLib.get_num_processors(); int[] lineranges = rangeseq((nthr * 2),l.length); ThreadPool<delimitchars> dcs = new ThreadPool<delimitchars>.with_owned_data((delimitchars) => { delimitchars.run(l, ref pc); },nthr,false); int k = 0; for (int i = 0; i < lineranges.length; i += 2) { dcs.add(new delimitchars( k, lineranges[i], lineranges[i+1], 'e', '3', 'e', true )); k += 1; } while (pc != k) { GLib.Thread.usleep(1); } tte = GLib.get_monotonic_time(); print("delimitchars of 1M strings took %s\n\n",printusecs(tte-tts)); int mx = 0; for (int i = 1; i < 1000000; i += 830) { if (mx > 5) { break; } print("[%d] %s\n\n",i,l[i]); mx += 1; } }
#+RESULTS:
Compilation succeeded - 4 warning(s) delimitchars tool 17 μs | 00 | xxxx | xxxx | | 01 | 0xxx | _xxx | | 02 | x0xx | x_xx | | 03 | xx0x | xx_ | | 04 | xxx0 | xxx_ | | 05 | \0xxx | \0xxx | | 06 | x\0xx | x\0xx | | 07 | 0x\0x | _x\0x | | 08 | x0x\0 | x_x\0 | | 09 | \xx0x | \xx_ | | 10 | xxx0\ | xxx_ | | 11 | \\00xx | \\0_xx | | 12 | \x\0xx | \x\0xx | | 13 | \x\x\x\0\ | \x\x\x\0\ | | 14 | \\\\ | \\\\ | | 15 | 0000 | ____ | | 16 | | | delimitchars stresstest: delimitchars of 1M strings took 154.75 ms [1] Authoriti3s last w3ek issu3d a vacat3 ord3r for a club in Manhattan and clos3d anoth3r in th3 Bronx. [831] Sinc3 its founding in 1879, lawy3rs at th3 firm hav3 h3lp3d organiz3 U.S. St3el in th3 lat3 1880s, h3lp3d plan th3 construction of th3 Panama Canal and h3lp3d n3gotiat3 an 3nd to th3 Kor3an War. [1661] Unit3d Parc3l S3rvic3 has announc3d it will match th3 d3liv3ry and pickup tim3s of ov3rnight d3liv3ry comp3titor F3d3ral Expr3ss Corp. [2491] BUSINESS INCUBATORS gain ground d3spit3 tough 3conomic tim3s. [3321] In a mov3 that was anticipat3d, Chas3 Manhattan Corp. said it plac3d about $2.3 billion of loans to Brazil on non-accrual status. [4151] "W3'r3 in this for th3 long haul," Arm3ntrout said. "W3 hav3 m3mori3s as to what happ3n3d to p3opl3 who sold out at th3 bottom of th3 crash in 1987.
[2_FIX.]COMPACTSTRING:vala:

[0_TODO]COMPACTSTRING_SRC

modify CHARCOUNTS to remove contigious whitespace...

public class compactstrings : Object { // by c.p.brown 2026 private int packetnum; private int first; private int last; private unichar n; private unichar e; private bool x; public compactstrings (int pn, int f, int l, unichar fc, unichar ec, bool de) { packetnum = pn; first = f; last = l; n = fc; e = ec; x = de; } public void run(string[] s, int[] ccs, ref int packetscomplete) { int pcc = 0; for (int i = first; i <= last; i++) { int cc = 0; int ii = 0; if (x) { while (ii > -1) { if (!ws && s[i].isspace()) { unowned string atp = s[i].offset(ii); atp = atp.prev_char(); ws = (atp.get_char(0) != e) } else { if (ws) { o.append(s.substring(ts,tl)); } } else { while (ii > -1) { cc += 1; ii = s[i].index_of_char(n,(ii+1)); } } pcc += cc; } ccs[packetnum] = pcc; mutex.lock(); packetscomplete += 1; mutex.unlock(); } }
string compactstring (string s, bool n) { // compact string // by cpbrown 2024 // // n = remove newlines StringBuilder compacted = new StringBuilder(""); if (n) { for (int i = 0; i < s.char_count(); i++) { unichar tc = s.get_char(s.index_of_nth_char(i)); if (!tc.isspace()) { compacted.append_unichar(tc); continue; } else { unichar pc = 'A'; if (i > 0) { pc = s.get_char(s.index_of_nth_char(i-1)); } if (pc.isspace()) { continue; } tc = ' '; compacted.append_unichar(tc); } } } else { for (int i = 0; i < s.char_count(); i++) { unichar tc = s.get_char(s.index_of_nth_char(i)); if (tc == '\n') { compacted.append_unichar(tc); continue; } if (!tc.isspace()) { compacted.append_unichar(tc); continue; } else { unichar pc = 'A'; if (i > 0) { pc = s.get_char(s.index_of_nth_char(i-1)); } if (pc != '\n') { if (pc.isspace()) { continue; } } tc = ' '; compacted.append_unichar(tc); } } } compacted.str = compacted.str.strip(); return compacted.str; }
COMPACTSTRING_TEST
string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } public class compactstrings : Object { // by c.p.brown 2026 private int packetnum; private int first; private int last; private unichar n; private unichar e; private bool x; public compactstrings (int pn, int f, int l, unichar fc, unichar ec, bool de) { packetnum = pn; first = f; last = l; n = fc; e = ec; x = de; } public void run(string[] s, int[] ccs, ref int packetscomplete) { int pcc = 0; for (int i = first; i <= last; i++) { int cc = 0; int ii = 0; if (x) { while (ii > -1) { if (!ws && s[i].isspace()) { unowned string atp = s[i].offset(ii); atp = atp.prev_char(); ws = (atp.get_char(0) != e) } else { if (ws) { o.append(s.substring(ts,tl)); } } else { while (ii > -1) { cc += 1; ii = s[i].index_of_char(n,(ii+1)); } } pcc += cc; } ccs[packetnum] = pcc; mutex.lock(); packetscomplete += 1; mutex.unlock(); } } void main() { int64 tts = GLib.get_monotonic_time(); GLib.Intl.setlocale(ALL,""); string s = " a messy aut零parsed\tline\t\t\n of\n «text» "; print("original string is:\n\"%s\"\n\n",s); string compacted = compactstring(s,true); print("\ncompacted string without newlines is:\n\"%s\"\n\n",compacted); compacted = compactstring(s,false); print("\ncompacted string with newlines is:\n\"%s\"\n",compacted); int64 tte = GLib.get_monotonic_time(); print("\ncompactstring_test took %s\n",printusecs(tte - tts)); }
#+RESULTS:
Compilation failed: 3 error(s), 0 warning(s)
[5_DONE]CONTIGUOUSSTRINGS
[5_DONE]CONTIGIOUSSTRINGS_SRC
string[] contigiousstrings(string s) { // break a string into a string[] of contigious characters // by c.p.brown 2026 int64 w = 0; int g = 0; unowned string x = s.offset(0); unowned string y = s.offset(s.length); y = y.prev_char(); unichar c = s.get_char(0); unichar n = c; string[] o = {}; o += c.to_string(); while (direct_equal(x,y) == false) { if (w > 1000000000) { break; } x = x.next_char(); n = x.get_char(0); if (n == c) { o[g] += n.to_string(); } else { g += 1; o += n.to_string(); } c = n; w += 5; } print("contigiousstrings consumed approx %s\n",printgmem(w)); return o; }
[5_DONE]CONTIGIOUSSTRINGS_TEST
string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } string printgmem (int64 m) { // m is memory in bytes if (m < 1000) { return "%lld bytes".printf(m); } if (m < 1000000) { return "%.2f KB".printf((((double) m) / 1000.0) ); } if (m < 1000000000) { return "%.2f MB".printf((((double) m) / 1000000.0) ); } if (m < 1000000000000) { return "%.2f GB".printf((((double) m) / 1000000000.0)); } if (m < 1000000000000000) { return "%.2f TB".printf((((double) m) / 1000000000000.0)); } return "%.2f PB".printf((((double) m) / 1000000000000000.0) ); } string loadfiletostring(string f) { StringBuilder sb = new StringBuilder(""); GLib.File ff = GLib.File.new_for_path(f); if (ff.query_exists()) { GLib.FileStream fstr = GLib.FileStream.open(f,"r"); while (true) { string fs = fstr.read_line(); if (fs == null) { break; } sb.append(fs + "\n"); } } return sb.str; } string[] contigiousstrings(string s) { // break a string into a string[] of contigious characters // by c.p.brown 2026 int64 w = 0; int g = 0; unowned string x = s.offset(0); unowned string y = s.offset(s.length); y = y.prev_char(); unichar c = s.get_char(0); unichar n = c; string[] o = {}; o += c.to_string(); while (direct_equal(x,y) == false) { if (w > 1000000000) { break; } x = x.next_char(); n = x.get_char(0); if (n == c) { o[g] += n.to_string(); } else { g += 1; o += n.to_string(); } c = n; w += 5; } print("contigiousstrings consumed approx %s\n",printgmem(w)); return o; } void main() { GLib.Intl.setlocale(ALL,""); string s = "gHHH5YY++///\\"; int64 tts = GLib.get_monotonic_time(); string[] p = contigiousstrings(s); int64 tte = GLib.get_monotonic_time(); print("partition took %s\n",printusecs(tte-tts)); print("%s\n%s\n\n",s,string.joinv(",",p)); // stress test string f = loadfiletostring("./testdata/leipzig1M.txt"); tts = GLib.get_monotonic_time(); string[] fp = contigiousstrings(f); tte = GLib.get_monotonic_time(); print("partition leipzig1M into %d partitions took %s\n",fp.length,printusecs(tte-tts)); int lpz = 0; int lpx = 0; int fpl = fp.length; int cc = 0; for (int i = 0; i < fpl; i++) { cc = fp[i].char_count(); if (lpz < cc) { lpz = cc; lpx = i; } } print("largest partition is %d chars at index %d \"%s\"\n\n",lpz,lpx,fp[lpx]); fp.resize(0); // stress test 2 string fo = loadfiletostring("./cpbrown_notes.org"); tts = GLib.get_monotonic_time(); string[] fpa = contigiousstrings(fo); tte = GLib.get_monotonic_time(); print("partition this file into %d partitions took %s\n",fpa.length,printusecs(tte-tts)); lpz = 0; lpx = 0; fpl = fpa.length; cc = 0; for (int i = 0; i < fpl; i++) { cc = fpa[i].char_count(); if (lpz < cc) { lpz = cc; lpx = i; } } print("largest partition is %d chars at index %d \"%s\"\n\n",lpz,lpx,fpa[lpx]); fpa.resize(0); }
#+RESULTS:
contigiousstrings consumed approx 60 bytes partition took 28 μs gHHH5YY++///\ g,HHH,5,YY,++,///,\ contigiousstrings consumed approx 648.22 MB partition leipzig1M into 127350762 partitions took 4.42 s largest partition is 71 chars at index 16596182 "-----------------------------------------------------------------------" contigiousstrings consumed approx 6.23 MB partition this file into 1030934 partitions took 43.58 ms largest partition is 498 chars at index 805875 "------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------"
[0_TODO]COLUMNID
break into src inf and test
// Convert to/from spreadsheet codes, // assuming A->Z, then AA->AZ..ZA->ZZ, then AAA->AZZ..ZAA->ZZZ, and so-on. // This is derivative work from many sources. Couldn't find a primary source, as the idea seems to go back to pre-computer times. void main () { string[] s = { "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","AA", "BB", "AZ", "ZZ", "AAA", "CR", "DX", "CQ" }; for (int i = 0; i < s.length; i++) { int colnum = 0; int scc = s[i].char_count(); for (int c = 0; c < scc; c++) { int cc = (((int) s[i].get_char(s[i].index_of_nth_char(c))) - 65); // A = 65 colnum = colnum * 26; // nth letter is nth * number of letters colnum += (cc + 1); } print("%s = %d\n",s[i],colnum); } // I 01 10 20 30 40 50 100 128 // J 00 09 19 29 39 49 099 127 I-1 // K 00 09 19 03 13 23 021 023 J%26 // 65 74 84 68 78 88 086 088 K+65 // A J T D N X V X TOSTRING // L 00 08 18 26 26 26 078 104 I-K-1 // I 00 00 00 01 01 01 003 004 L/26 // (LOOP WHILE I > 0) // J 00 00 00 002 003 I-1 // 00 00 00 002 003 J%26 // A A A C D // A J T AD AN AX CV DX for (int i = 1; i < 130; i++) { string o = ""; int d = i; while (d > 0) { int x = ((d - 1) % 26); o = "%c%s".printf((x+65),o); d = ((d - x) - 1) / 26; } print("%03d: %s\n",i,o); } print("\n"); for (int i = 1; i < 2000; i += 66) { string o = ""; int d = i; while (d > 0) { int x = ((d - 1) % 26); o = "%c%s".printf((x+65),o); d = ((d - x) - 1) / 26; } print("%03d: %s\n",i,o); } }
#+RESULTS:
A = 1 B = 2 C = 3 D = 4 E = 5 F = 6 G = 7 H = 8 I = 9 J = 10 K = 11 L = 12 M = 13 N = 14 O = 15 P = 16 Q = 17 R = 18 S = 19 T = 20 U = 21 V = 22 W = 23 X = 24 Y = 25 Z = 26 AA = 27 BB = 54 AZ = 52 ZZ = 702 AAA = 703 CR = 96 DX = 128 CQ = 95 001: A 002: B 003: C 004: D 005: E 006: F 007: G 008: H 009: I 010: J 011: K 012: L 013: M 014: N 015: O 016: P 017: Q 018: R 019: S 020: T 021: U 022: V 023: W 024: X 025: Y 026: Z 027: AA 028: AB 029: AC 030: AD 031: AE 032: AF 033: AG 034: AH 035: AI 036: AJ 037: AK 038: AL 039: AM 040: AN 041: AO 042: AP 043: AQ 044: AR 045: AS 046: AT 047: AU 048: AV 049: AW 050: AX 051: AY 052: AZ 053: BA 054: BB 055: BC 056: BD 057: BE 058: BF 059: BG 060: BH 061: BI 062: BJ 063: BK 064: BL 065: BM 066: BN 067: BO 068: BP 069: BQ 070: BR 071: BS 072: BT 073: BU 074: BV 075: BW 076: BX 077: BY 078: BZ 079: CA 080: CB 081: CC 082: CD 083: CE 084: CF 085: CG 086: CH 087: CI 088: CJ 089: CK 090: CL 091: CM 092: CN 093: CO 094: CP 095: CQ 096: CR 097: CS 098: CT 099: CU 100: CV 101: CW 102: CX 103: CY 104: CZ 105: DA 106: DB 107: DC 108: DD 109: DE 110: DF 111: DG 112: DH 113: DI 114: DJ 115: DK 116: DL 117: DM 118: DN 119: DO 120: DP 121: DQ 122: DR 123: DS 124: DT 125: DU 126: DV 127: DW 128: DX 129: DY 001: A 067: BO 133: EC 199: GQ 265: JE 331: LS 397: OG 463: QU 529: TI 595: VW 661: YK 727: AAY 793: ADM 859: AGA 925: AIO 991: ALC 1057: ANQ 1123: AQE 1189: ASS 1255: AVG 1321: AXU 1387: BAI 1453: BCW 1519: BFK 1585: BHY 1651: BKM 1717: BNA 1783: BPO 1849: BSC 1915: BUQ 1981: BXE
DSVALIGN

Align columns of a dsv string to acommodate their content.

// expand a dsv string to make it more readable // by c.p.brown, 2025 string expanddsv (string[] dat, int dsz, string d) { string o = ""; int[] cw = new int[dsz]; int rowcount = dat.length / dsz; string dlm = (" " + d + " "); for (int c = 0; c < dsz; c++) { int maxc = 0; for (int r = 0; r < rowcount; r++) { maxc = int.max(maxc,dat[(dsz*r)+c].strip().char_count()); } cw[c] = maxc; } for (int r = 0; r < rowcount; r++) { for (int c = 0; c < dsz; c++) { string cel = dat[(dsz*r)+c].strip(); int cc = cel.char_count(); if (c == (dsz - 1)) { o = "%s%s".printf(o,cel); } else { string spc = ""; if ((cw[c]-cc) > 0) { spc = "%*s".printf((cw[c]-cc)," "); } o = "%s%s%s%s".printf(o,cel,spc,dlm); } } o = "%s\n".printf(o); } return o; } void main() { string s = "column_0;column_1;column_2;column_3\none;twelve thousand eight hundred and seven;ten;thirty\nseventeen hundred;sixty;ninety eight;eleven\nthirty two;five;three thousand and four;fourty three"; print("\noriginal csv:\n%s\n",s); string[] dat = {}; string[] rows = s.split("\n"); int dsz = 1; for (int i = 0; i < rows.length; i++) { string[] cols = rows[i].split(";"); dsz = int.max(dsz,cols.length); for (int c = 0; c < cols.length; c++) { dat += cols[c]; } } print("\nexpanded csv:\n%s\n",expanddsv(dat,dsz,";")); }
#+RESULTS:
original csv: column_0;column_1;column_2;column_3 one;twelve thousand eight hundred and seven;ten;thirty seventeen hundred;sixty;ninety eight;eleven thirty two;five;three thousand and four;fourty three expanded csv: column_0 ; column_1 ; column_2 ; column_3 one ; twelve thousand eight hundred and seven ; ten ; thirty seventeen hundred ; sixty ; ninety eight ; eleven thirty two ; five ; three thousand and four ; fourty three
DUHWADE

Get parent of relative path

// get parent relative path of s // by c.p.brown 2024 string getrelativedirparent (string s) { string filepath = s; string pfd = "../"; if (filepath.has_suffix("/") == false) { filepath = filepath + "/"; } bool eatit = false; if (strcmp(filepath,"./") == 0) { pfd = "../"; } else { if (filepath.has_prefix("./")) { eatit = true;; } else { string nbk = filepath.replace("../","").strip(); if (nbk.char_count() == 0) { pfd = "../" + filepath; } else { if (filepath.has_prefix("../")) { eatit = true; } } } } if (eatit) { int ldl = filepath.last_index_of("/"); if (ldl != -1) { pfd = filepath.substring(0,ldl); ldl = pfd.last_index_of("/"); if (ldl != -1) { pfd = pfd.substring(0,ldl); pfd = pfd + "/"; } else { print("error: cant find 2nd last \"/\" in %s\n",filepath); } } else { print("error: cant find last \"/\" in %s\n",filepath); } } return pfd; } void main() { string[] s = { "./", "./a/", "./a/b/", "./a/b/c/", "../", "../../", "../../../a/", "../../../a/b/", ".", "./a", "./a/b", "./a/b/c", "..", "../..", "../../../a", "../../../a/b" }; for (int i = 0; i < s.length; i++) { string pfd = getrelativedirparent(s[i]); print("parent dir of %*s is %s\n",14,s[i],pfd); } }
#+RESULTS:
parent dir of ./ is ../ parent dir of ./a/ is ./ parent dir of ./a/b/ is ./a/ parent dir of ./a/b/c/ is ./a/b/ parent dir of ../ is ../../ parent dir of ../../ is ../../../ parent dir of ../../../a/ is ../../../ parent dir of ../../../a/b/ is ../../../a/ parent dir of . is ../ parent dir of ./a is ./ parent dir of ./a/b is ./a/ parent dir of ./a/b/c is ./a/b/ parent dir of .. is ../../ parent dir of ../.. is ../../../ parent dir of ../../../a is ../../../ parent dir of ../../../a/b is ../../../a/
FOLD

tokenize_and_fold vs string._delimit & split...

_delimit pros
  • much faster, even with cleanup
  • preserves case
  • can choose exactly what to use as delimiters

_delimit cons
  • won't work with multi-character delimiters - as with tokenize, to be fair
  • will insert sequential delimiters, resulting in empty array items when split
  • adds an extra empty array item at the end if the last char is a delimiter
  • removing empties requires onerous cleanup work & testing,
  • or handling emties every time the array is accessed

// tokenize_and_fold vs _delimit & split // by c.p.brown 2024 void main() { string[] o; string s = "1,2;3\"45\"\n6-78\'AB.C_DE(F)$GH{I\nJK}AB101"; int64 tts = GLib.get_monotonic_time(); string[] tkn = s.tokenize_and_fold("en_US",out o); int64 ttl = GLib.get_monotonic_time(); print("string.tokenize_and_fold is {\n"); for (int i = 0; i < tkn.length; i++) { print("\"" + tkn[i] + "\"\n"); } print("}\n"); print("tokenize_and_fold took %.2f microseconds\n\n",((double) (ttl - tts))); string q = "1,2;3\"45\"\n6-78\'AB.C_DE(F)$GH{I\nJK}AB101"; string d = ",;\"\';._-$(){}\n"; char npdc = '\x1F'; string npd = "%c".printf(npdc); tts = GLib.get_monotonic_time(); q._delimit(d,npdc); string[] w = q.split(npd); int[] rr = {}; for (int i = 0; i < w.length; i++) { if ((w[i] == null) || (w[i].strip() == "") || (w[i].strip() == "\n")) { rr += i; } } if (rr.length > 1) { int[] gaps = {693731, 270033, 133481, 7106, 3121, 1303, 701, 301, 132, 57, 23, 10, 4, 1}; int n = rr.length; foreach (int g in gaps) { for (int i = 0; i < n; i++) { int t = rr[i]; int j = i; if (j >= g) { bool c = (rr[j - g] < t); while (c) { rr[j] = rr[j - g]; j -= g; if (j < g) { break; } c = (rr[j - g] < t); } } rr[j] = t; } } n = 0; int a = rr[rr.length - 1]; int j = rr.length; int f = 0; for (int i = a; i < (w.length - j); i++) { int b = (i + f); while (b in rr) { f += 1; b += 1; rr.resize(rr.length - 1); } w[i] = w[i + f]; } w.resize(w.length - j); } else { if (rr.length == 1) { for (int i = rr[0]; i < w.length; i++) { if ((i + 1) < w.length) { w[i] = w[i + 1]; } } w.resize(w.length - 1); } } ttl = GLib.get_monotonic_time(); print("string._delimit and split is {\n"); for (int i = 0; i < w.length; i++) { print("\"" + w[i] + "\"\n"); } print("}\n"); print("_delimit and split took %.2f microseconds\n\n",((double) (ttl - tts))); }
#+RESULTS:
string.tokenize_and_fold is { "1" "2" "3" "45" "6" "78" "ab" "c" "de" "f" "gh" "i" "jk" "ab101" } tokenize_and_fold took 16.00 microseconds string._delimit and split is { "1" "2" "3" "45" "6" "78" "AB" "C" "DE" "F" "GH" "I" "JK" "AB101" } _delimit and split took 5.00 microseconds
IJGLICNUMS_GFN

Convert numbers to its English description.
Obsolete, needs rewrite for multithreading.

// numbers to english // by c.p.brown 2024 string ands (int n) { if (n > 0) { return " and "; } return ""; } string andhypers(int n, int l) { string[] hypers = {" "," hundred"," thousand"," million"," billion"," trillion"}; if (n > 0) { return hypers[l]; } return ""; } int isum (ref int[] n) { int r = 0; foreach (int i in n) { r += i; } return r; } string[] maketens () { string[] ones = { "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; string[] reftens = { "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" }; string[] tentens = { "twenty", "thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninety" }; string[] tens = {}; for (int t = 0; t < ones.length; t++) { tens += ones[t]; } for (int t = 0; t < reftens.length; t++) { tens += reftens[t]; } for (int tt = 0; tt < tentens.length; tt++) { for (int t = 0; t < reftens.length; t++) { if (t > 0) { tens += (tentens[tt] + "-" + ones[t]); } else { tens += tentens[tt]; } } } return tens; } string inglicnums (int64 n, bool ano, ref string[] tens) { string[] ones = { "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; int[] p = new int[16]; string sn = "%lld".printf(n); int snc = sn.char_count(); if (snc == 1) { if (n == 0) { if (ano) { return ("%lld".printf(n) + " (" + ones[n] + ")"); } else { return ones[n]; } } } int ofs = 16 - snc; for (int c = 0; c < snc; c++) { if (c < 16) { p[c+ofs] = sn.get_char(c).digit_value(); } else { if (ano) { return ("%lld".printf(n) + " (squillions)"); } else { return "squillions"; } } } if (isum(ref p) == 0) { if (ano) { return ("%lld".printf(n) + " (zero)"); } else { return "zero"; } } if (snc > 15) { if (ano) { return ("%lld".printf(n) + " (squillions)"); } else { return "squillions"; } } if (snc == 1) { if (n == 0) { if (ano) { return ("%lld".printf(n) + " (" + ones[n] + ")"); } else { return ones[n]; } } } string incq = ""; if (snc > 1) { incq = tens[((p[14]*10)+p[15])]; } if (snc > 2) { incq = (andhypers(p[13],0) + ones[p[13]] + andhypers(p[13],1) + ands(p[14]+p[15]) + incq); } if (snc > 3) { incq = (tens[((p[11]*10)+p[12])] + andhypers((p[11]+p[12]+p[10]),2) + incq); } if (snc > 5) { incq = (andhypers(p[10],0) + ones[p[10]] + andhypers(p[10],1) + ands(p[11]+p[12]) + incq); } if (snc > 6) { incq = (tens[((p[8]*10)+p[9])] + andhypers((p[8]+p[9]+p[7]),3) + incq); } if (snc > 8) { incq = (andhypers(p[7],0) + ones[p[7]] + andhypers(p[7],1) + ands(p[8]+p[9]) + incq); } if (snc > 9) { incq = (tens[((p[5]*10)+p[6])] + andhypers((p[5]+p[6]+p[4]),4) + incq); } if (snc > 11) { incq = (andhypers(p[4],0) + ones[p[4]] + andhypers(p[4],1) + ands(p[5]+p[6]) + incq); } if (snc > 12) { incq = (tens[((p[2]*10)+p[3])] + andhypers((p[2]+p[3]+p[1]),5) + incq); } if (snc > 14) { incq = (andhypers(p[1],0) + ones[p[1]] + andhypers(p[1],1) + ands(p[2]+p[3]) + incq); } incq._chug(); if (ano) { incq = ("%lld".printf(n) + " (" + incq + ")"); } return incq; } void main () { string[] k = {}; k += "1000000001"; for (int64 i = 10; i < 10000000000000000; i *= 2) { if (i > 0) { k += "%lld".printf(i); } } //print("nums: \n{\n\t%s\n}\n",string.joinv(",\n\t",k)); string[] tens = maketens(); int64 mtts = GLib.get_monotonic_time(); for (int i = 0; i < k.length; i++) { int64 ii = int64.parse(k[i]); k[i] = inglicnums(ii,true,ref tens); } int64 mtte = GLib.get_monotonic_time(); print("nums+words: \n{\n\t%s\n}\n",string.joinv(",\n\t",k)); print("nums to text took %.4f seconds\n",(((double) (mtte - mtts)) / 1000000.0)); }
#+RESULTS:
nums+words: { 1000000001 (one billion and one), 10 (ten), 20 (twenty), 40 (fourty), 80 (eighty), 160 (one hundred and sixty), 320 (three hundred and twenty), 640 (six hundred and fourty), 1280 (one thousand two hundred and eighty), 2560 (two thousand five hundred and sixty), 5120 (five thousand one hundred and twenty), 10240 (ten thousand two hundred and fourty), 20480 (twenty thousand four hundred and eighty), 40960 (fourty thousand nine hundred and sixty), 81920 (eighty-one thousand nine hundred and twenty), 163840 (one hundred and sixty-three thousand eight hundred and fourty), 327680 (three hundred and twenty-seven thousand six hundred and eighty), 655360 (six hundred and fifty-five thousand three hundred and sixty), 1310720 (one million three hundred and ten thousand seven hundred and twenty), 2621440 (two million six hundred and twenty-one thousand four hundred and fourty), 5242880 (five million two hundred and fourty-two thousand eight hundred and eighty), 10485760 (ten million four hundred and eighty-five thousand seven hundred and sixty), 20971520 (twenty million nine hundred and seventy-one thousand five hundred and twenty), 41943040 (fourty-one million nine hundred and fourty-three thousand and fourty), 83886080 (eighty-three million eight hundred and eighty-six thousand and eighty), 167772160 (one hundred and sixty-seven million seven hundred and seventy-two thousand one hundred and sixty), 335544320 (three hundred and thirty-five million five hundred and fourty-four thousand three hundred and twenty), 671088640 (six hundred and seventy-one million and eighty-eight thousand six hundred and fourty), 1342177280 (one billion three hundred and fourty-two million one hundred and seventy-seven thousand two hundred and eighty), 2684354560 (two billion six hundred and eighty-four million three hundred and fifty-four thousand five hundred and sixty), 5368709120 (five billion three hundred and sixty-eight million seven hundred and nine thousand one hundred and twenty), 10737418240 (ten billion seven hundred and thirty-seven million four hundred and eighteen thousand two hundred and fourty), 21474836480 (twenty-one billion four hundred and seventy-four million eight hundred and thirty-six thousand four hundred and eighty), 42949672960 (fourty-two billion nine hundred and fourty-nine million six hundred and seventy-two thousand nine hundred and sixty), 85899345920 (eighty-five billion eight hundred and ninety-nine million three hundred and fourty-five thousand nine hundred and twenty), 171798691840 (one hundred and seventy-one billion seven hundred and ninety-eight million six hundred and ninety-one thousand eight hundred and fourty), 343597383680 (three hundred and fourty-three billion five hundred and ninety-seven million three hundred and eighty-three thousand six hundred and eighty), 687194767360 (six hundred and eighty-seven billion one hundred and ninety-four million seven hundred and sixty-seven thousand three hundred and sixty), 1374389534720 (one trillion three hundred and seventy-four billion three hundred and eighty-nine million five hundred and thirty-four thousand seven hundred and twenty), 2748779069440 (two trillion seven hundred and fourty-eight billion seven hundred and seventy-nine million and sixty-nine thousand four hundred and fourty), 5497558138880 (five trillion four hundred and ninety-seven billion five hundred and fifty-eight million one hundred and thirty-eight thousand eight hundred and eighty), 10995116277760 (ten trillion nine hundred and ninety-five billion one hundred and sixteen million two hundred and seventy-seven thousand seven hundred and sixty), 21990232555520 (twenty-one trillion nine hundred and ninety billion two hundred and thirty-two million five hundred and fifty-five thousand five hundred and twenty), 43980465111040 (fourty-three trillion nine hundred and eighty billion four hundred and sixty-five million one hundred and eleven thousand and fourty), 87960930222080 (eighty-seven trillion nine hundred and sixty billion nine hundred and thirty million two hundred and twenty-two thousand and eighty), 175921860444160 (one hundred and seventy-five trillion nine hundred and twenty-one billion eight hundred and sixty million four hundred and fourty-four thousand one hundred and sixty), 351843720888320 (three hundred and fifty-one trillion eight hundred and fourty-three billion seven hundred and twenty million eight hundred and eighty-eight thousand three hundred and twenty), 703687441776640 (seven hundred and three trillion six hundred and eighty-seven billion four hundred and fourty-one million seven hundred and seventy-six thousand six hundred and fourty), 1407374883553280 (squillions), 2814749767106560 (squillions), 5629499534213120 (squillions) } nums to text took 0.0002 seconds
MAKENUM

Obsolete. See ISANUMBER

string makenum (string v) { StringBuilder sb = new StringBuilder(""); sb.append(v); int cc = sb.str.char_count(); if (cc == 0) { return sb.str; } StringBuilder sbo = new StringBuilder(""); string[] presyms = {"$","£","₵","€","₡‎","R$"}; string[] sufsyms = {"L","R","L","D","VT","zł","Kč","kr","kr.","CHF","Db"}; int prec = presyms.length; int sufc = sufsyms.length; unichar[] npunc = {'.','-','+',',','\''}; // commonly found in numbers, but exclude from result unichar[] nnpunc = {'.','-'}; // inclue in result bool isprobablymoney = false; for (int i = 0; i < prec; i++) { isprobablymoney = sb.str.has_prefix(presyms[i]); if (isprobablymoney) { break; } } if (!isprobablymoney) { for (int i = 0; i < sufc; i++) { isprobablymoney = sb.str.has_suffix(sufsyms[i]); if (isprobablymoney) { break; } } } for (int i = 0; i < cc; i++) { unichar ch = sb.str.get_char(sb.str.index_of_nth_char(i)); bool isnum = (ch.isdigit() || (ch in nnpunc)); bool isprobablynum = (ch in npunc); if (isnum || isprobablynum || isprobablymoney) { if (isnum) { sbo.append_unichar(ch); } } else { return "(NaN)"; } } return sbo.str; } void main() { if ('.'.isdigit()) { print("\".\" is a digit\n"); } if ('-'.isdigit()) { print("\"-\" is a digit\n"); } if ('+'.isdigit()) { print("\"+\" is a digit\n"); } if ('/'.isdigit()) { print("\"/\" is a digit\n"); } if (','.isdigit()) { print("\",\" is a digit\n"); } if ('\''.isdigit()) { print("\"\'\" is a digit\n"); } print("\"+1\" is %d\n",int.parse("+1")); print("\"-1\" is %d\n",int.parse("-1")); print("\"1/1/11\" is %d\n",int.parse("1/1/11")); print("\"$1\" is %d\n",int.parse("$1")); print("\"$1.50\" is %.2f\n",double.parse("$1.50")); print("\"1000\'000\" is %d\n",int.parse("1000\'000")); print("\"1.0\" is %.2f\n",double.parse("1.0")); print("\"1,1\" is %.2f\n",double.parse("1,1")); print("\"1:1\" is %d\n",int.parse("1:0")); print("\"10_\" is %d\n",int.parse("10_")); print("\"+10VT\" is %d\n",int.parse("+10VT")); print("\"1.0_ABC_2.0\" is %d\n",int.parse("1.0_ABC_2.0")); print("\nmakenum() results:\n"); print("\"+1\" is %s\n",makenum("+1")); print("\"-1\" is %s\n",makenum("-1")); print("\"1/1/11\" is %s\n",makenum("1/1/11")); print("\"$1\" is %s\n",makenum("$1")); print("\"$1.50\" is %s\n",makenum("$1.50")); print("\"1000\'000\" is %s\n",makenum("1000\'000")); print("\"1.0\" is %s\n",makenum("1.0")); print("\"1,1\" is %s\n",makenum("1,1")); print("\"1:1\" is %s\n",makenum("1:0")); print("\"10_\" is %s\n",makenum("10_")); print("\"+10VT\" is %s\n",makenum("+10VT")); print("\"1.0_ABC_2.0\" is %s\n",makenum("1.0_ABC_2.0")); }
#+RESULTS:
"+1" is 1 "-1" is -1 "1/1/11" is 1 "$1" is 0 "$1.50" is 0.00 "1000'000" is 1000 "1.0" is 1.00 "1,1" is 1.00 "1:1" is 1 "10_" is 10 "+10VT" is 10 "1.0_ABC_2.0" is 1 makenum() results: "+1" is 1 "-1" is -1 "1/1/11" is (NaN) "$1" is 1 "$1.50" is 1.50 "1000'000" is 1000000 "1.0" is 1.0 "1,1" is 11 "1:1" is (NaN) "10_" is (NaN) "+10VT" is 10 "1.0_ABC_2.0" is (NaN)
SHARESTRING

Rough test of string[] i/o issues.

AMD Ryzen 9 7940HS

StringBuilder erase 1M strings takes about 1.4ms
StringBuilder append 1M strings takes about 15ms
StringBuilder replace 1M strings takes about 90ms
Writing to 1M strings in string[] takes about 30ms
Performing the avobve via object getters/setters took about +40ms
Performing the above form one object to another tool about 10ms (50ms total)

string printusecs (int64 u) { string us = "%lld h".printf((((double) u) / 3600000000)); if (u < 1000) { return "%lld μs".printf(u); } if (u < 1000000) { return "%.2f ms".printf((((double) u) / 1000.0)); } if (u < 60000000) { return "%.2f s".printf((((double) u) / 1000000.0)); } if (u < 3600000000) { return "%.2f m".printf((((double) u) / 60000000.0)); } return us; } void printcpuinf () { string maxhz = "unknown"; string frqfile = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq"; GLib.File ff = GLib.File.new_for_path(frqfile); if (ff.query_exists() == true) { GLib.FileStream s = GLib.FileStream.open(frqfile,"r"); string l = s.read_line(); if (l != null) { StringBuilder sb = new StringBuilder(""); sb.append(l); maxhz = sb.str; } } string cpufile = "/proc/cpuinfo"; string[] pinf = {}; ff = GLib.File.new_for_path(cpufile); if (ff.query_exists() == true) { GLib.FileStream s = GLib.FileStream.open(cpufile,"r"); string l = s.read_line(); while (l != null) { StringBuilder sb = new StringBuilder(""); sb.append(l); // bail after 1st cpu uint f = sb.replace("power ","",1); if (f > 0) { break; } pinf += sb.str; l = s.read_line(); } } for (int i = 0; i < pinf.length; i++) { StringBuilder sb = new StringBuilder(""); sb.append(pinf[i]); uint f = sb.replace("model name", "", 1); if (f > 0) { print("%s\n",pinf[i]); } else { f = sb.replace("cpu MHz", "", 1); if (f > 0) { print("cpu hz\t\t: %s/%s\n",pinf[i].substring((pinf[i].index_of(": ") + 2)).replace(".",""),maxhz); } else { f = sb.replace("cache size", "", 1); if (f > 0) { print("%s\n",pinf[i]); } else { f = sb.replace("cpu cores", "", 1); if (f > 0) { print("%s\n\n",pinf[i]); break; } } } } } } class objstring : Object { public int vlength; private string[] vals; public objstring () { vals = {}; vlength = 0; } public int getlength () { return vals.length; } public void ingest (string[] s) { vals.resize(0); vlength = s.length; for (int i = 0; i < vlength; i++) { vals += s[i].dup(); } } public string readval (int i) { return vals[i]; } public void writeval (int i, string s) { vals[i] = s.dup(); } } string[] readfiletostrings (string p) { string[] o = {}; GLib.FileStream fs; try { fs = GLib.FileStream.open(p,"r"); StringBuilder sb = new StringBuilder(""); while (true) { string l = fs.read_line(); if (l == null) { break; } sb.erase(); sb.append(l.dup()); o += sb.str; } } catch (Error e) { print("file error: %s\n",e.message); } return o; } string[] gs; void copytoknown () { int gsl = gs.length; StringBuilder sb = new StringBuilder(""); for (int i = 0; i < gsl; i++) { sb.erase(); sb.append(gs[i]); sb.replace("the","QE",0); gs[i] = sb.str; } } void copytostrings (string[] s) { StringBuilder sb = new StringBuilder(""); for (int i = 0; i < s.length; i++) { sb.erase(); sb.append(s[i]); sb.replace("the","QE",0); s[i] = sb.str; } } objstring os; void copytostringvals () { int sl = os.vlength; StringBuilder sb = new StringBuilder(""); for (int i = 0; i < sl; i++) { sb.erase(); sb.append(os.readval(i)); sb.replace("the","QE",0); os.writeval(i,sb.str); } } class objectobject : Object { private string[] vals; public objectobject () { vals = {}; } public void copytostringvals () { vals.resize(0); int sl = os.vlength; StringBuilder sb = new StringBuilder(""); for (int i = 0; i < sl; i++) { sb.erase(); sb.append(os.readval(i)); sb.replace("the","QE",0); vals += sb.str.dup(); } } } void main() { GLib.Intl.setlocale(ALL,""); printcpuinf(); print("\n"); gs = readfiletostrings("./testdata/leipzig1M.txt"); int64 tts = GLib.get_monotonic_time(); copytoknown(); int64 tte = GLib.get_monotonic_time(); print("backwash string to global string[] took %s\n",printusecs(tte-tts)); string[] s = readfiletostrings("./testdata/leipzig1M.txt"); tts = GLib.get_monotonic_time(); copytostrings(s); tte = GLib.get_monotonic_time(); print("backwash string to main string[] took %s\n",printusecs(tte-tts)); os = new objstring(); os.ingest(readfiletostrings("./testdata/leipzig1M.txt")); tts = GLib.get_monotonic_time(); copytostringvals(); tte = GLib.get_monotonic_time(); print("backwash string to object string[] took %s\n",printusecs(tte-tts)); os = new objstring(); os.ingest(readfiletostrings("./testdata/leipzig1M.txt")); tts = GLib.get_monotonic_time(); objectobject objobj = new objectobject(); objobj.copytostringvals(); tte = GLib.get_monotonic_time(); print("copy string[] from known object to object took %s\n",printusecs(tte-tts)); }
#+RESULTS:
Compilation succeeded - 2 warning(s) model name : AMD Ryzen 9 7940HS w/ Radeon 780M Graphics cpu hz : 1955507/5263061 cache size : 1024 KB cpu cores : 8 backwash string to global string[] took 126.64 ms backwash string to main string[] took 128.33 ms backwash string to object string[] took 150.04 ms copy string[] from known object to object took 159.62 ms
SPLICE

Test to see how splice() can remove the last character, and to verify if splice(a,b,s) is splice(start,offset,string), or splice(start,end,string).

Results:
  • start and end are absolute positions, unlike substring()
  • splicing with the same start and end positions will insert before the start position
  • splicing from the position of the last char (l) to l+last_char.length won't remove the terminator

void main() { string s = "0123456789"; int a = 9; int b = 10; string p = s.splice(a,b,"X"); print("splice %s from %d to %d: %s\n",s,a,b,p); if (p[p.length] == '\0') { print("spliced string is valid\n"); } a = 3; b = 3; p = s.splice(a,b,"XXX"); print("splice %s from %d to %d: %s\n",s,a,b,p); if (p[p.length] == '\0') { print("spliced string is valid\n"); } a = 3; b = 3+3; p = s.splice(a,b,"XXX"); print("splice %s from %d to %d: %s\n",s,a,b,p); if (p[p.length] == '\0') { print("spliced string is valid\n"); } }
#+RESULTS:
splice 0123456789 from 9 to 10: 012345678X spliced string is valid splice 0123456789 from 3 to 3: 012XXX3456789 spliced string is valid splice 0123456789 from 3 to 6: 012XXX6789 spliced string is valid
SPLIT

NOTE: split may return empty strings when the delimiter is at either end of the string

string ";1;2;3;4;5; split ^|^|^|^|^|^ |;|;|;|;|;|;| | |1|2|3|4|5| | partitions |1|2|3|4|5|6|7|
Split quoted test.
Practical example of replacing unquoted text.

Uses the following for delimiters:
  • ROW '\x1E' (^^) row delimiter
  • COL '\x1F' (^_) column delimiter
  • ESC '\x1D' (^]) generic escaped char
  • QUO '\x1C' (^\) quote/verbatim delimiter (both open & close)
The last two can be used to replace escaped row/col delimiters, then restored after a row/col split.
The following code doesn't have escapes for 'newline' ("x" in this case), but if it had escapes, it would temporarily use \x1D to replace "\x", and "\x1F" to replace """, then split quoted, count & delimit "x" then restore the escaped chars...

For multithreaded stresstests see CACHELC.

public uint8 squo (int itr, string s, unichar qoc, unichar qcc, unichar nlc, out string uqs) { uqs = s.dup(); // arbitrary load limit, about half 1nt32.MAX // array[].length is int32 in Vala so its possible to exceed 2B in a forloop if (itr > 1000000000) { return 0; } // offset to determine the 1st unquoted string segment, given split() will crete a blank entry before a quote on the 0th char int ofs = 0; if (s.get_char(0) == qoc) { ofs = 2; } // prep vars string qocs = qoc.to_string(); string qccs = qcc.to_string(); string nwls = nlc.to_string(); string qodlm = '\x1C'.to_string(); // string rowdlm = '\x1E'.to_string(); // use instead of '0' for out uqs IRL usage StringBuilder sb = new StringBuilder(""); sb.append(s.dup()); // replace quote pairs with a generic delimiter and count them uint occ = sb.replace(qocs,qodlm,0); uint ccc = sb.replace(qccs,qodlm,0); int qtc = (int) (occ + ccc); string[] segs = sb.str.split(qodlm); // count int tnc = 0; for (int i = ofs; i < segs.length; i += 2) { StringBuilder seg = new StringBuilder(""); if ((segs[i] != null) && (segs[i] != "")) { seg.append(segs[i]); uint nc = seg.replace(nwls,"0",9); segs[i] = seg.str; tnc += (int) nc; } } // backtrack & re-count unquoted in the last segemt if a quote was left open int ls = -1; if ((qtc & 1) == 1) { ls = (segs.length - 1); if ((segs[ls] != null) && (segs[ls] != "")) { StringBuilder seg = new StringBuilder(""); seg.append(segs[ls]); uint nc = seg.replace(nwls,"0",9); segs[ls] = seg.str; tnc += (int) nc; } } // reassemble output string // normally this would include /x1E delimiter for newline so we don't have to do this again when rendering a string in Cairo ofs = 1; for (int i = ofs; i < segs.length; i += 2) { if ((segs[i] != null) && (segs[i] != "")) { if (i == ls) { segs[i] = segs[i]; } else { segs[i] = qocs + segs[i] + qccs; } } } uqs = string.joinv("",segs); return (uint8) int.min(255,tnc); } void main(string[] args) { string[] t = { "\"xxxx\"", "x\"x\"xx", "x\"x\"x\"x", "x\"x\"x\"x\"", "\"x\"x\"x\"x\"", "x\"xx\"x", "x\"xxx\"", "\"xxx\"x", "\"xx\"xx\"", "xxxx\"", "\"xxxx", "\"\"xxxx", "xxxx\"\"", "\"\"xxxx\"\"", "\"\"xx\"xx\"\"", "xxxx" }; for (int q = 0; q < t.length; q++) { print("\n{%s}\n",t[q]); string[] p = t[q].split("\""); print("|"); for (int i = 0; i < p.length; i++) { print(" %s |",p[i]); } print("\n"); string uqs = ""; uint8 xc = squo(0,t[q],'\"','\"','x',out uqs); print("{%s} has %u unquoted \"x\"\n{%s}\n",t[q],xc,uqs); } }
#+RESULTS:
{"xxxx"} | | xxxx | | {"xxxx"} has 0 unquoted "x" {"xxxx"} {x"x"xx} | x | x | xx | {x"x"xx} has 3 unquoted "x" {0"x"00} {x"x"x"x} | x | x | x | x | {x"x"x"x} has 3 unquoted "x" {0"x"00} {x"x"x"x"} | x | x | x | x | | {x"x"x"x"} has 2 unquoted "x" {0"x"0"x"} {"x"x"x"x"} | | x | x | x | x | | {"x"x"x"x"} has 2 unquoted "x" {"x"0"x"0} {x"xx"x} | x | xx | x | {x"xx"x} has 2 unquoted "x" {0"xx"0} {x"xxx"} | x | xxx | | {x"xxx"} has 1 unquoted "x" {0"xxx"} {"xxx"x} | | xxx | x | {"xxx"x} has 1 unquoted "x" {"xxx"0} {"xx"xx"} | | xx | xx | | {"xx"xx"} has 2 unquoted "x" {"xx"00} {xxxx"} | xxxx | | {xxxx"} has 4 unquoted "x" {0000} {"xxxx} | | xxxx | {"xxxx} has 4 unquoted "x" {0000} {""xxxx} | | | xxxx | {""xxxx} has 4 unquoted "x" {0000} {xxxx""} | xxxx | | | {xxxx""} has 4 unquoted "x" {0000} {""xxxx""} | | | xxxx | | | {""xxxx""} has 4 unquoted "x" {0000} {""xx"xx""} | | | xx | xx | | | {""xx"xx""} has 2 unquoted "x" {00"xx"} {xxxx} | xxxx | {xxxx} has 4 unquoted "x" {0000}
SUBSTRING

Note: ASCII only.

Substring is (from-and-including-index,to-and-excluding-index)


substring(1,2) of "012345" is 1+2 is 3, -1 is 2 ||: "12" substring(4,2) of "012345" is 4+2 is 6, -1 is 5 || "45" substring(0,2) of "012345" is 0+2 is 2, -1 is 1 ||: "01"

substring(x,(y-x)), where x is from and including, y is to and excluding, eg:

substring(1,(4-1)) of "012345" is "123" substring(3,(5-3)) of "012345" is "34"
substring(x,((y-x)+1)), where x is from and including, y is to and including, eg:

substring(1,((4-1)+1)) of "012345" is "1234" substring(3,((5-3)+1)) of "012345" is "345"

To get first/last n characters:

void main (string[] args) { string s = "file.ext"; int ii = s.last_index_of("."); print("file part .....: %s\n",s.substring(0,ii)); print("extension part : %s\n",s.substring(ii)); }
#+RESULTS:
file part .....: file extension part : .ext
to get from-and-including 2 to-and-including 5 from "0123456789"
start....... 2 ( 01[23456789 ) 12^ end......... 5+1 ( 01[234567]89 ) 12 123456^ end (5+1)-start ( 01[2345]6789 ) 12 1234^ int s = 2; int e = 5; substring(s,((e+1)-s)); substring(2,6) = "234567"
substring(2,(6-2)) = "2345"


void main (string[] args) { string s = "012345"; string t = "ABCDE"; string u = "((AA + (BB / CC)) * EE)"; print("\"%s\".substring(-1) is %s\n",s,s.substring(-1)); print("\"%s\".substring(0,(s.last_index_of_char('5'))) is %s\n",s,s.substring(0,(s.last_index_of_char('5')))); print("\"%s\".substring(1,2) is %s\n",s,s.substring(1,2)); print("\"%s\".substring(4,2) is %s\n",s,s.substring(4,2)); print("\"%s\".substring(1,(4-1)) is %s\n",s,s.substring(1,(4-1))); print("\"%s\".substring(3,(5-3)) is %s\n",s,s.substring(3,(5-3))); print("\"%s\".substring(1,((4-1)+1)) is %s\n",s,s.substring(1,((4-1)+1))); print("\"%s\".substring(3,((5-3)+1)) is %s\n",s,s.substring(3,((5-3)+1))); print("\"%s\".substring(2) is %s\n",s,s.substring(2)); print("\"%s\".substring(0,100) is %s (generates string assertion error)\n",s,s.substring(0,100)); print("\"%s\".substring(0,s.char_count()) is %s\n",s,s.substring(0,s.char_count())); print("\"%s\".substring(2,(2-2)) is %s\n",s,s.substring(2,(2-2))); int ii = u.last_index_of("("); string m = u.substring(ii); int oo = m.index_of(")") + 1; print("inner expression of %s is %s\n",u,u.substring(ii,oo)); }
#+RESULTS:
Compilation succeeded - 1 warning(s) "012345".substring(-1) is 5 "012345".substring(0,(s.last_index_of_char('5'))) is 01234 "012345".substring(1,2) is 12 "012345".substring(4,2) is 45 "012345".substring(1,(4-1)) is 123 "012345".substring(3,(5-3)) is 34 "012345".substring(1,((4-1)+1)) is 1234 "012345".substring(3,((5-3)+1)) is 345 "012345".substring(2) is 2345 "012345".substring(0,100) is (null) (generates string assertion error) "012345".substring(0,s.char_count()) is 012345 "012345".substring(2,(2-2)) is inner expression of ((AA + (BB / CC)) * EE) is (BB / CC)
Practical usage: extract a link from a paragraph
void main (string[] args) { string p = "some paragraph\nwith a [[val:variable]] link in it\nand [[val:another]], just to be difficult"; string c = p; string[] l = {}; int s = 0; while (c.contains("[[val:") && c.contains("]]")) { int ii = c.index_of("[[val:"); int oo = c.index_of("]]") + 2; //print("ii = %d, oo = %d\n",ii,oo); if (oo > ii) { string e = c.substring(ii,(oo - ii)); //print("\tfound link: (%s)\n",e); if (e != "") { l += e.replace("]]","").split(":")[1]; c = c.replace(e,""); //print("c = %s\n",c); } } s += 1; if (s > 10) { break; } } print("original paragraph:\n\t%s\n\n",p.replace("\n","\n\t")); print("leftover paragraph:\n\t%s\n\n",c.replace("\n","\n\t")); print("harvested linked vars:\n"); foreach (string k in l) { print("\t%s\n",k); } }
#+RESULTS:
original paragraph: some paragraph with a [[val:variable]] link in it and [[val:another]], just to be difficult leftover paragraph: some paragraph with a link in it and , just to be difficult harvested linked vars: variable another
TRUNCATE

Truncate a string

// truncate a string to a set length, include a tripple elipsis at the last char // by c.p.brown, 2025 string truncate(string s, int l, bool e) { StringBuilder sb = new StringBuilder(""); if ((s.char_count() - 1) > l) { int lc = l; if (e) { lc = (l - 1); } for (int i = 0; i <= lc; i++) { sb.append_unichar(s.get_char(s.index_of_nth_char(i))); } if (e) { sb.append("…"); } } else { sb.append(s); } return sb.str; } void main() { GLib.Intl.setlocale(ALL,""); int tl = 26; print("always use elipsis where text is truncated:\n"); string s = "truncate this to %d chars".printf(tl); for (int i = tl; i >= 0; i--) { s = "truncate this to %d chars".printf(i+1); print("\"%s\"\n",truncate(s,i,true)); } bool skp = false; print("use elipsis only when a word is cut:\n"); s = "truncate this to %d chars".printf(tl); for (int i = tl; i >= 0; i--) { s = "truncate this to %d chars".printf(i+1); unichar l = s.get_char(s.index_of_nth_char(i)); if (l == ' ') { skp = true; print("\"%s\"\n",truncate(s,i,false)); } else { if (skp == true) { print("\"%s\"\n",truncate(s,i,false)); skp = false; } else { print("\"%s\"\n",truncate(s,i,true)); } } } }
#+RESULTS:
always use elipsis where text is truncated: "truncate this to 27 chars" "truncate this to 26 chars" "truncate this to 25 chars" "truncate this to 24 cha…" "truncate this to 23 ch…" "truncate this to 22 c…" "truncate this to 21 …" "truncate this to 20…" "truncate this to 1…" "truncate this to …" "truncate this to…" "truncate this t…" "truncate this …" "truncate this…" "truncate thi…" "truncate th…" "truncate t…" "truncate …" "truncate…" "truncat…" "trunca…" "trunc…" "trun…" "tru…" "tr…" "t…" "…" use elipsis only when a word is cut: "truncate this to 27 chars" "truncate this to 26 chars" "truncate this to 25 chars" "truncate this to 24 cha…" "truncate this to 23 ch…" "truncate this to 22 c…" "truncate this to 21 …" "truncate this to 20 " "truncate this to 19" "truncate this to …" "truncate this to " "truncate this to" "truncate this …" "truncate this " "truncate this" "truncate th…" "truncate t…" "truncate …" "truncate " "truncate" "trunca…" "trunc…" "trun…" "tru…" "tr…" "t…" "…"
UNIQUENAME
bool instringarray (string n, string[] h) { for (int i = 0; i < h.length; i++) { if (h[i] == n) { return true; } } return false; } bool cinstringarray (string n, string[] h) { for (int i = 0; i < h.length; i++) { if (strcmp(n,h[i]) == 0) { return true; } } return false; } void main () { string n = "name"; string[] a = { "name", "name_3", "name_03", "name_031", "name031", "name_04", "name04", "name_0301" }; int64 xtts = GLib.get_real_time(); int x = 1; string k = n; while (instringarray(k,a)) { int ld = (k.length - 1); while (ld > 0 && k[ld].isdigit()) { ld--; } string digs = k.substring((ld + 1),(k.length - (ld + 1))); k = "%s%d".printf(n.substring(0,(ld + 1)),(int.parse(digs) + 1)); x += 1; if (x > 100) { break; } } int64 xtte = GLib.get_real_time(); print("uniquename via k == a[i] loop took %f micorseconds @%d rounds and returned: %s\n",((double) (xtte - xtts)),x,k); xtts = GLib.get_real_time(); x = 1; k = n; while (cinstringarray(k,a)) { int ld = (k.length - 1); while (ld > 0 && k[ld].isdigit()) { ld--; } string digs = k.substring((ld + 1),(k.length - (ld + 1))); k = "%s%d".printf(n.substring(0,(ld + 1)),(int.parse(digs) + 1)); x += 1; if (x > 100) { break; } } xtte = GLib.get_real_time(); print("uniquename via strcmp look took %f micorseconds @%d rounds and returned: %s\n",((double) (xtte - xtts)),x,k); xtts = GLib.get_real_time(); x = 1; k = n; while ((k in a) == true) { int ld = (k.length - 1); while (ld > 0 && k[ld].isdigit()) { ld--; } string digs = k.substring((ld + 1),(k.length - (ld + 1))); k = "%s%d".printf(n.substring(0,(ld + 1)),(int.parse(digs) + 1)); x += 1; if (x > 100) { break; } } xtte = GLib.get_real_time(); print("uniquename via (k in a) took %f micorseconds @%d rounds and returned: %s\n",((double) (xtte - xtts)),x,k); }
#+RESULTS:
uniquename via k == a[i] loop took 16.000000 micorseconds @2 rounds and returned: name1 uniquename via strcmp look took 1.000000 micorseconds @2 rounds and returned: name1 uniquename via (k in a) took 1.000000 micorseconds @2 rounds and returned: name1
WHIGGLE

BYKOZ IJGLIC IS DQ LAJGWIDC OX KAIOS...

void main() { string whiggle (int n) { int l = n % 10; if (l == 0) { return "th"; } int ll = n % 100; if ((ll > 10) && (ll < 20)) { return "th"; } if (l < 4) { string[] w = {"th","st","nd","rd"}; return w[l]; } return "th"; } for (int n = 1; n < 131; n++) { print("%03d%s ",n,whiggle(n)); if ((n > 0) && ((n % 10) == 0)) { print("\n"); } } }
#+RESULTS:
Compilation succeeded - 1 warning(s) 001st 002nd 003rd 004th 005th 006th 007th 008th 009th 010th 011th 012th 013th 014th 015th 016th 017th 018th 019th 020th 021st 022nd 023rd 024th 025th 026th 027th 028th 029th 030th 031st 032nd 033rd 034th 035th 036th 037th 038th 039th 040th 041st 042nd 043rd 044th 045th 046th 047th 048th 049th 050th 051st 052nd 053rd 054th 055th 056th 057th 058th 059th 060th 061st 062nd 063rd 064th 065th 066th 067th 068th 069th 070th 071st 072nd 073rd 074th 075th 076th 077th 078th 079th 080th 081st 082nd 083rd 084th 085th 086th 087th 088th 089th 090th 091st 092nd 093rd 094th 095th 096th 097th 098th 099th 100th 101st 102nd 103rd 104th 105th 106th 107th 108th 109th 110th 111th 112th 113th 114th 115th 116th 117th 118th 119th 120th 121st 122nd 123rd 124th 125th 126th 127th 128th 129th 130th
TABLE
GETDUPES

Obsolete work, strip it for parts.

// get rows of duplicates in a column // uses an int[] of row indices instead of data[i] // indices[] may be in a different order to data[] // indices[] permits cheaper pre-partitioning for multithreading // // optionally search within a range of rows // // by c.p.brown, 2025 string printintarray (int[] s, int f) { string[] ii = {"", "\"", "{", "[", "[", "| ", "", ""}; string[] dd = {";", ",", ",", " ", ",", " | ", " ", "\n"}; string[] oo = {"", "\"", "}", "]", "]", " |", "", ""}; string o = ii[f]; for (int i = 0; i < (s.length - 1); i++) { o = (o + "%d".printf(s[i]) + dd[f]); } o = (o + "%d".printf(s[s.length - 1]) + oo[f]); return o; } string printunrolledarray (int ind, string[] dat, int dsz, bool h, bool rnm, bool cnm, int m) { string tabs = ("%*s").printf(ind," ").replace(" ","\t"); string spc = " "; bool domask = (m > -1); string dlm = " | "; int rcols = dsz; int rowcount = dat.length / dsz; if (rnm) { rcols = dsz+1; } int chc = 0; if (cnm) { chc = "%d".printf((dat.length - 1)).char_count(); } int[] cw = new int[rcols]; for (int i = 0; i < cw.length; i++) { cw[i] = 0; } if (rnm) { cw[0] = "%d".printf((dat.length/dsz)).char_count(); } if (h) { for (int i = 1; i < cw.length; i++) { string hh = "col %u".printf(i); cw[i] = hh.char_count(); } } string o = ""; string ln = ""; // get counts 1st for (int i = 0; i < dat.length; i++) { int c = (i % dsz); if (rnm) { c = c + 1; } int cc = 0; if (dat[i] != null) { cc = dat[i].char_count() + chc + 3; if (cc > 0) { int nwlat = dat[i].index_of("\n"); if (nwlat != -1) { cc = (nwlat + 3 + chc + 3); } } } cw[c] = int.max(cw[c],cc); } // print header if (h) { for (int i = 0; i < cw.length; i++) { dlm = " | "; if (i == 0) { dlm = "%s| ".printf(tabs); } if (i == 0) { string hh = "#"; o = "%s%s%-*s".printf(o,dlm,cw[i],hh); } else { string hh = "col %d".printf(i-1); o = "%s%s%-*s".printf(o,dlm,cw[i],hh); } if (i == (cw.length - 1)) { o = "%s |\n".printf(o); } } // print line for (int i = 0; i < cw.length; i++) { dlm = "-+-"; if (i == 0) { dlm = "%s|-".printf(tabs); } ln = "%s%s%-*s".printf(ln,dlm,cw[i]," ").replace(" ","-"); if (i == (cw.length - 1)) { ln = "%s-|\n".printf(ln); } } o = "%s%s".printf(o,ln); } int n = 0; int rcc = dsz + 1; for (int r = 0; r < rowcount; r++) { for (int c = 0; c < rcc; c++) { string datpart = ""; if (c == 0) { dlm = "%s| ".printf(tabs); o = "%s%s%s%.*s".printf(o,dlm,"%d".printf(r),(cw[0]-1),spc); } else { if (c == 1) { dlm = "%s| ".printf(tabs); } int j = (r * dsz) + (c - 1); int cc = dat[j].char_count(); if (dat[j] != null) { if (cc > 0) { datpart = dat[j]; int nwlat = dat[j].index_of("\n"); if (nwlat != -1) { //trunc = true; datpart = (dat[j].substring(0,nwlat) + "..."); cc = (nwlat + 3); } } else { cc = int.max(cc,1); } } dlm = " | "; string clen = " (%*d)".printf(chc,j); int padlen = (cw[c] - cc) - clen.char_count(); padlen = int.max(padlen,0); datpart = "%s%s%.*s".printf(datpart,clen,padlen,spc); if (domask) { bool ismasked = (((j % dsz) + m) == 0); if (ismasked) { n += 2; datpart = "\x1b[48;5;5m%s\x1b[0m".printf(datpart); } } o = "%s%s%s".printf(o,dlm,datpart); if (c == dsz) { dlm = " |\n"; o = "%s%s".printf(o,dlm); } } } } cw = null; return o; } string printallmyuint64bits (uint64 n) { string o = ""; for (int i = 63; i >= 0; i--) { o = o + "%lld".printf((n >> i) & 1); } return o; } string printallmyuint32bits (uint n) { string o = ""; for (int i = 31; i >= 0; i--) { o = o + "%ld".printf((n >> i) & 1); } return o; } uint64[] getduperowsbycol(int dsz, int[] dxs, int col, string[] s, int fr, int lr) { // note: start/end range packing sets an upper limit of about 4.2 billion rows // dxs is an array of row numbers, they are scrambled // dsz is the column count // fr is first row in dxs, lr is last row in dxs // to get an absolute index from dxs[i]: (dxs[i] * dsz) + col uint64[] o = {}; uint a = 0; // first row uint b = 0; // last row int r = -1; // recording? for (int i = (fr+1); i <= lr; i++) { int p = (dxs[i] * dsz) + col; int op = (dxs[i-1] * dsz) + col; //print("comparing col %d row %d s[%d] (%s) with col %d row %d s[%d] (%s)\n",col,dxs[i],p,s[p],col,dxs[i-1],op,s[op]); if (strcmp(s[p],s[op]) == 0) { if (r == -1) { // start recording print("\t1st duplicate row is %d...\n",(i-1)); a = (i-1); o += a; b = 0; r = 1; } else { // keep recording print("\tlatest duplicate row is %d...\n",(i-1)); b = (i-1); uint64 t = a; o[o.length - 1] = (t << 32) | b; } } else { // stop recording if (r == 1) { print("\tlast duplicate row is %d...\n",(i-1)); b = (i-1); uint64 t = a; o[o.length - 1] = (t << 32) | b; } a = 0; b = 0; r = -1; } if (i == lr) { // eof if (r == 1) { if (b != lr) { b = lr; uint64 t = a; o[o.length - 1] = (t << 32) | b; } } a = 0; b = 0; r = -1; } } return o; } void main() { string[] s = { "AA", "00", "{", "BB", "01", "{", "CC", "02", "{", "CC", "03", "}", "DD", "03", "[", "EE", "04", "[", "EE", "04", "]", "EE", "05", ")" }; int c = 0; int cc = 3; int[] dxs = {}; int rowcount = (s.length / cc); for (int i = 0; i < rowcount; i++) { dxs += i; } int rando = Random.int_range(0,(rowcount - 1)); uint n = 11; int m = 1; for (int i = (rowcount - 1); i >= 0; i--) { int t = dxs[i]; dxs[i] = dxs[rando]; dxs[rando] = t; n += 1; Random.set_seed(n); rando = Random.int_range(0,(rowcount - m)); m += 1; } print("\n%d SCRAMBLED ROW INDICES (dxs[]):\n",dxs.length); for (int i = 0; i < dxs.length; i++) { print("%d | %d | %s %s %s\n",i,dxs[i],s[dxs[i]*cc],s[(dxs[i]*cc)+1],s[(dxs[i]*cc)+2]); } print("\nRAW DATA:\n%s\n",printunrolledarray(1,s,3,true,true,true,-1)); for (int i = 0; i < cc; i++) { print("finding dupes in col %d rows %d to %d...\n",i,0,7); uint64[] dupes = getduperowsbycol(cc,dxs,i,s,0,7); for (int q = 0; q < dupes.length; q++) { uint64 bb = (dupes[q] & 0xFFFFFFFF); uint64 aa = (dupes[q] >> 32); int dxa = ((int) aa); int dxb = ((int) bb); print("\tduplicates of s[dxs[%d] (%d) *cc+1] (%d) \"%s\" in col %d starts on dxs[%d] (%lld), ends on dxs[%d] (%lld)\n",dxa,dxs[dxa],((dxs[dxa]*cc)+i),s[((dxs[dxa]*cc)+i)],i,dxa,aa,dxb,bb); } } }
#+RESULTS:
Compilation succeeded - 4 warning(s) 8 SCRAMBLED ROW INDICES (dxs[]): 0 | 3 | CC 03 } 1 | 2 | CC 02 { 2 | 7 | EE 05 ) 3 | 6 | EE 04 ] 4 | 0 | AA 00 { 5 | 4 | DD 03 [ 6 | 5 | EE 04 [ 7 | 1 | BB 01 { RAW DATA: | # | col 0 | col 1 | col 2 | |---+---------+---------+--------| | 0 | AA ( 0) | 00 ( 1) | { ( 2) | | 1 | BB ( 3) | 01 ( 4) | { ( 5) | | 2 | CC ( 6) | 02 ( 7) | { ( 8) | | 3 | CC ( 9) | 03 (10) | } (11) | | 4 | DD (12) | 03 (13) | [ (14) | | 5 | EE (15) | 04 (16) | [ (17) | | 6 | EE (18) | 04 (19) | ] (20) | | 7 | EE (21) | 05 (22) | ) (23) | finding dupes in col 0 rows 0 to 7... 1st duplicate row is 0... last duplicate row is 1... 1st duplicate row is 2... last duplicate row is 3... duplicates of s[dxs[0] (3) *cc+1] (9) "CC" in col 0 starts on dxs[0] (0), ends on dxs[1] (1) duplicates of s[dxs[2] (7) *cc+1] (21) "EE" in col 0 starts on dxs[2] (2), ends on dxs[3] (3) finding dupes in col 1 rows 0 to 7... finding dupes in col 2 rows 0 to 7... 1st duplicate row is 5... last duplicate row is 6... duplicates of s[dxs[5] (4) *cc+1] (14) "[" in col 2 starts on dxs[5] (5), ends on dxs[6] (6)
XFORMRC

Transform sequential columns into sequential rows, with gaps in the data...

// transform col sequence to rows, include placeholders for missing data // by c.p.brown 2024 void main() { string[] s = {"0A","1A","0B","1B","2B","0C","0D","1D"}; int[] rc = {2,3,1,2}; int xr = 3; for (int r = 0; r < xr; r++) { int p = r; for (int c = 0; c < rc.length; c++) { if (c > 0) { p += rc[c-1]; } if (r < rc[c]) { print("[%d] s[%d] is %s\n",r,p,s[p]); } else { print("[%d] (missing)\n",r); } } } }
#+RESULTS:
[0] s[0] is 0A [0] s[2] is 0B [0] s[5] is 0C [0] s[6] is 0D [1] s[1] is 1A [1] s[3] is 1B [1] (missing) [1] s[7] is 1D [2] (missing) [2] s[4] is 2B [2] (missing) [2] (missing)
TBLFM ELISP:org:

Test common Elisp functions in org tblfm formulae

upcase

Convert text to uppercase

| ! | ITEM  | UP    |
|---+-------+-------|
| 1 | green | GREEN |
| 2 | blue  | BLUE  |
| 3 | red   | RED   |
#+TBLFM: @2$3..@4$3='(upcase $2)

downcase
convert text to lowercase

| ! | ITEM  | DOWN  |
|---+-------+-------|
| 1 | GREEN | green |
| 2 | BLUE  | blue  |
| 3 | RED   | red   |
#+TBLFM: @2$3..@4$3='(downcase $2)

format
format text using tags

| ! | ITEM  | COST | FORMAT  |
|---+-------+------+---------|
| 1 | GREEN |   30 | EUR €30 |
| 2 | BLUE  |   10 | EUR €10 |
| 3 | RED   |   18 | EUR €18 |
#+TBLFM: @2$4..@4$4='(format "EUR €%d" (string-to-number $3))

concat
Combine strings

| ! | ITEM  | CONCAT     |
|---+-------+------------|
| 1 | GREEN | RGBA_GREEN |
| 2 | BLUE  | RGBA_BLUE  |
| 3 | RED   | RGBA_RED   |
#+TBLFM: @2$3..@4$3='(concat "RGBA_" $2)

make-string
Create a string of n characters
Args are:
  • make-string command
  • number of characters
  • character to use, prefixed with a question-mark
  • switch for ascii/unicode, 0 or 1

| ! | ITEM  | QTY | PLOT     |
|---+-------+-----+----------|
| 1 | GREEN |   2 | ██       |
| 2 | BLUE  |   6 | ██████   |
| 3 | RED   |   8 | ████████ |
#+TBLFM: @2$4..@4$4='(make-string (string-to-number $3) ?█ 1)

substring
Extract part of a string

Args are:
  • substring command
  • string to extract a substring from
  • start index of substring
  • length of string to extract, after start
Negative start denotes last n characters
Negative length denotes maximum length - n, after start

| ! | ITEM      | SUBSTR | -S   | -L    | -S-L |
|---+-----------+--------+------+-------+------|
| 1 | GREENISHY | GRE    | ISHY | GREEN | ISH  |
| 2 | BLUEISHY  | BLU    | ISHY | BLUE  | ISH  |
| 3 | REDISHY   | RED    | ISHY | RED   | ISH  |
#+TBLFM: @2$3..@4$3='(substring $2 0 3) :: @2$4..@4$4='(substring $2 -4 nil) :: @2$5..@4$5='(substring $2 0 -4) :: @2$6..@4$6='(substring $2 -4 -1)

string
Create a string from characters

Each character must be prefixed with a question-mark.

| ! | ITEM  | STRING |
|---+-------+--------|
| 1 | GREEN | COLOR  |
| 2 | BLUE  | COLOR  |
| 3 | RED   | COLOR  |
#+TBLFM: @2$3..@4$3='(string ?C ?O ?L ?O ?R)

abs
Absolute value of a number

| ! |  A |  B | ABS |
|---+----+----+-----|
| 1 |  2 | 30 |  60 |
| 2 | -6 | 10 |  60 |
| 3 | -8 | 18 | 144 |
#+TBLFM: @2$4..@4$4='(abs (* (string-to-number $2) (string-to-number $3)))

mod
Modulo

| ! |   A |  B | MOD |
|---+-----+----+-----|
| 1 | 203 | 30 |  23 |
| 2 | 612 | 10 |   2 |
| 3 | 800 | 18 |   8 |
#+TBLFM: @2$4..@4$4='(mod (string-to-number $2) (string-to-number $3))

random
Generate a random number
Numeric arg is the upper limit, from 0.

| ! | A |  B | RAND |
|---+---+----+------|
| 1 | 2 | 30 |   28 |
| 2 | 6 | 10 |    6 |
| 3 | 8 | 18 |   15 |
#+TBLFM: @2$4..@4$4='(random (string-to-number $3))
celing
Round a number up

| ! | A |    B | CEIL |
|---+---+------+------|
| 1 | 2 | 30.8 |   31 |
| 2 | 6 | 10.1 |   11 |
| 3 | 8 | 18.4 |   19 |
#+TBLFM: @2$4..@4$4='(ceiling (string-to-number $3))

floor
Round a number down, towards negative infinity.

| ! | A |     B | FLOOR |
|---+---+-------+-------|
| 1 | 2 |  30.8 |    30 |
| 2 | 6 |  10.1 |    10 |
| 3 | 8 | -18.4 |   -19 |
#+TBLFM: @2$4..@4$4='(floor (string-to-number $3))

round
Round a number to the nearest integer.

| ! | A |     B | ROUND |
|---+---+-------+-------|
| 1 | 2 |  30.8 |    31 |
| 2 | 6 |  10.1 |    10 |
| 3 | 8 | -18.4 |   -18 |
#+TBLFM: @2$4..@4$4='(round (string-to-number $3))

truncate
Similar to floor, however truncates towards zero.

| ! | A |     B | TRUNC |
|---+---+-------+-------|
| 1 | 2 |  30.8 |    30 |
| 2 | 6 |  10.1 |    10 |
| 3 | 8 | -18.4 |   -18 |
#+TBLFM: @2$4..@4$4='(truncate (string-to-number $3))

min
Minimum of two numbers

| ! |  A |    B |  MIN |
|---+----+------+------|
| 1 |  2 |   30 |    2 |
| 2 | 60 | 10.1 | 10.1 |
| 3 | -8 |   -9 |   -9 |
#+TBLFM: @2$4..@4$4='(min (string-to-number $2) (string-to-number $3))

max
Maximum of two numbers

| ! |  A |    B | MAX |
|---+----+------+-----|
| 1 |  2 |   30 |  30 |
| 2 | 60 | 10.1 |  60 |
| 3 | -8 |   -9 |  -8 |
#+TBLFM: @2$4..@4$4='(max (string-to-number $2) (string-to-number $3))

sqrt
Square root of A.

| ! |   A |               SQRT |
|---+-----+--------------------|
| 1 | 2.2 | 1.4832396974191326 |
| 2 | 0.5 | 0.7071067811865476 |
| 3 | 1.5 |  1.224744871391589 |
#+TBLFM: @2$3..@4$3='(sqrt (string-to-number $2))

expt
A to the power of B.

Use with caution.

| ! |  A |   B |                   EXPT |
|---+----+-----+------------------------|
| 1 |  2 | -30 |  9.313225746154785e-10 |
| 2 | 60 | -10 | 1.6538171687920202e-18 |
| 3 |  8 |  -9 |  7.450580596923828e-09 |
#+TBLFM: @2$4..@4$4='(expt (string-to-number $2) (string-to-number $3))

exp
A to the power of e.

| ! |   A |                EXP |
|---+-----+--------------------|
| 1 | 2.2 |  9.025013499434122 |
| 2 | 0.5 | 1.6487212707001282 |
| 3 | 1.5 | 4.4816890703380645 |
#+TBLFM: @2$3..@4$3='(exp (string-to-number $2))

log
Logarithm of A, with a base of B, or e if the base isn't specified.

Use with caution.

| ! |   A |    B |                 LOG |
|---+-----+------+---------------------|
| 1 | 2.2 |  5.0 | 0.48989610240497816 |
| 2 | 0.5 | 10.0 | -0.3010299956639812 |
| 3 | 1.5 |  6.0 | 0.22629438553091683 |
#+TBLFM: @2$4..@4$4='(log (string-to-number $2) (string-to-number $3))

asin
Arc sine of A.

|  r |     A |     SIN |                      |                      |
|----+-------+---------+----------------------+----------------------|
|  2 | -2.00 |     nan |                      |                      |
|  3 | -1.80 |     nan |                      |                      |
|  4 | -1.60 |     nan |                      |                      |
|  5 | -1.40 |     nan |                      |                      |
|  6 | -1.20 |     nan |                      |                      |
|  7 | -1.00 | -1.5708 | ████████████████████ |                      |
|  8 | -0.80 | -0.9273 |         ████████████ |                      |
|  9 | -0.60 | -0.6435 |             ████████ |                      |
| 10 | -0.40 | -0.4115 |               ██████ |                      |
| 11 | -0.20 | -0.2014 |                  ███ |                      |
| 12 |  0.00 |  0.0000 |                      |                      |
| 13 |  0.20 |  0.2014 |                      | ███                  |
| 14 |  0.40 |  0.4115 |                      | ██████               |
| 15 |  0.60 |  0.6435 |                      | ████████             |
| 16 |  0.80 |  0.9273 |                      | ████████████         |
| 17 |  1.00 |  1.5708 |                      | ████████████████████ |
| 18 |  1.20 |     nan |                      |                      |
| 19 |  1.40 |     nan |                      |                      |
| 20 |  1.60 |     nan |                      |                      |
| 21 |  1.80 |     nan |                      |                      |
| 22 |  2.00 |     nan |                      |                      |
#+TBLFM: @2$2..@22$2=((($1-1.9999)-10.0)/5.0);%.2f :: @2$3..@22$3='(asin (string-to-number $2));%.4f :: $4='(orgtbl-uc-draw-cont $3 0.0 -1.6 20) :: $5='(orgtbl-uc-draw-cont $3 0.0 1.6 20) 

acos
Arc cosine of A.

|  r |     A |    SIN |     |                      |
|----+-------+--------+-----+----------------------|
|  2 | -2.00 |    nan |     |                      |
|  3 | -1.80 |    nan |     |                      |
|  4 | -1.60 |    nan |     |                      |
|  5 | -1.40 |    nan |     |                      |
|  6 | -1.20 |    nan |     |                      |
|  7 | -1.00 | 3.1416 |     | ████████████████████ |
|  8 | -0.80 | 2.4981 |     | ████████████████     |
|  9 | -0.60 | 2.2143 |     | ██████████████       |
| 10 | -0.40 | 1.9823 |     | █████████████        |
| 11 | -0.20 | 1.7722 |     | ████████████         |
| 12 |  0.00 | 1.5708 |     | ██████████           |
| 13 |  0.20 | 1.3694 |     | █████████            |
| 14 |  0.40 | 1.1593 |     | ████████             |
| 15 |  0.60 | 0.9273 |     | ██████               |
| 16 |  0.80 | 0.6435 |     | ████                 |
| 17 |  1.00 | 0.0000 |     |                      |
| 18 |  1.20 |    nan |     |                      |
| 19 |  1.40 |    nan |     |                      |
| 20 |  1.60 |    nan |     |                      |
| 21 |  1.80 |    nan |     |                      |
| 22 |  2.00 |    nan |     |                      |
#+TBLFM: @2$2..@22$2=((($1-1.9999)-10.0)/5.0);%.2f :: @2$3..@22$3='(acos (string-to-number $2));%.4f :: $4='(orgtbl-uc-draw-cont $3 0.0 -1.6 20) :: $5='(orgtbl-uc-draw-cont $3 0.0 3.1416 20) 

atan
Arc tangent of A.

|  r |     A |     SIN |                |                |
|----+-------+---------+----------------+----------------|
|  2 | -2.00 | -1.1071 | ██████████████ |                |
|  3 | -1.80 | -1.0637 | ██████████████ |                |
|  4 | -1.60 | -1.0122 |  █████████████ |                |
|  5 | -1.40 | -0.9505 |   ████████████ |                |
|  6 | -1.20 | -0.8761 |    ███████████ |                |
|  7 | -1.00 | -0.7854 |     ██████████ |                |
|  8 | -0.80 | -0.6747 |      █████████ |                |
|  9 | -0.60 | -0.5404 |        ███████ |                |
| 10 | -0.40 | -0.3805 |          █████ |                |
| 11 | -0.20 | -0.1974 |            ███ |                |
| 12 |  0.00 |  0.0000 |                |                |
| 13 |  0.20 |  0.1974 |                | ███            |
| 14 |  0.40 |  0.3805 |                | █████          |
| 15 |  0.60 |  0.5404 |                | ███████        |
| 16 |  0.80 |  0.6747 |                | █████████      |
| 17 |  1.00 |  0.7854 |                | ██████████     |
| 18 |  1.20 |  0.8761 |                | ███████████    |
| 19 |  1.40 |  0.9505 |                | ████████████   |
| 20 |  1.60 |  1.0122 |                | █████████████  |
| 21 |  1.80 |  1.0637 |                | ██████████████ |
| 22 |  2.00 |  1.1071 |                | ██████████████ |
#+TBLFM: @2$2..@22$2=((($1-1.9999)-10.0)/5.0);%.2f :: @2$3..@22$3='(atan (string-to-number $2));%.4f :: $4='(orgtbl-uc-draw-cont $3 0.0 -1.6 20) :: $5='(orgtbl-uc-draw-cont $3 0.0 1.6 20) 

sin
Sine of A.

|  r |     A |     SIN |               |               |
|----+-------+---------+---------------+---------------|
|  2 | -2.00 | -0.9093 |  ████████████ |               |
|  3 | -1.80 | -0.9738 | █████████████ |               |
|  4 | -1.60 | -0.9996 | █████████████ |               |
|  5 | -1.40 | -0.9854 | █████████████ |               |
|  6 | -1.20 | -0.9320 |  ████████████ |               |
|  7 | -1.00 | -0.8415 |   ███████████ |               |
|  8 | -0.80 | -0.7174 |     █████████ |               |
|  9 | -0.60 | -0.5646 |       ███████ |               |
| 10 | -0.40 | -0.3894 |         █████ |               |
| 11 | -0.20 | -0.1987 |           ███ |               |
| 12 |  0.00 |  0.0000 |               |               |
| 13 |  0.20 |  0.1987 |               | ███           |
| 14 |  0.40 |  0.3894 |               | █████         |
| 15 |  0.60 |  0.5646 |               | ███████       |
| 16 |  0.80 |  0.7174 |               | █████████     |
| 17 |  1.00 |  0.8415 |               | ███████████   |
| 18 |  1.20 |  0.9320 |               | ████████████  |
| 19 |  1.40 |  0.9854 |               | █████████████ |
| 20 |  1.60 |  0.9996 |               | █████████████ |
| 21 |  1.80 |  0.9738 |               | █████████████ |
| 22 |  2.00 |  0.9093 |               | ████████████  |
#+TBLFM: @2$2..@22$2=((($1-1.9999)-10.0)/5.0);%.2f :: @2$3..@22$3='(sin (string-to-number $2));%.4f :: $4='(orgtbl-uc-draw-cont $3 0.0 -1.6 20) :: $5='(orgtbl-uc-draw-cont $3 0.0 1.6 20) 

cos
Cosine of A

|  r |     A |     SIN |        |               |
|----+-------+---------+--------+---------------|
|  2 | -2.00 | -0.4161 | ██████ |               |
|  3 | -1.80 | -0.2272 |    ███ |               |
|  4 | -1.60 | -0.0292 |      █ |               |
|  5 | -1.40 |  0.1700 |        | ███           |
|  6 | -1.20 |  0.3624 |        | █████         |
|  7 | -1.00 |  0.5403 |        | ███████       |
|  8 | -0.80 |  0.6967 |        | █████████     |
|  9 | -0.60 |  0.8253 |        | ███████████   |
| 10 | -0.40 |  0.9211 |        | ████████████  |
| 11 | -0.20 |  0.9801 |        | █████████████ |
| 12 |  0.00 |  1.0000 |        | █████████████ |
| 13 |  0.20 |  0.9801 |        | █████████████ |
| 14 |  0.40 |  0.9211 |        | ████████████  |
| 15 |  0.60 |  0.8253 |        | ███████████   |
| 16 |  0.80 |  0.6967 |        | █████████     |
| 17 |  1.00 |  0.5403 |        | ███████       |
| 18 |  1.20 |  0.3624 |        | █████         |
| 19 |  1.40 |  0.1700 |        | ███           |
| 20 |  1.60 | -0.0292 |      █ |               |
| 21 |  1.80 | -0.2272 |    ███ |               |
| 22 |  2.00 | -0.4161 | ██████ |               |
#+TBLFM: @2$2..@22$2=((($1-1.9999)-10.0)/5.0);%.2f :: @2$3..@22$3='(cos (string-to-number $2));%.4f :: $4='(orgtbl-uc-draw-cont $3 0.0 -1.6 20) :: $5='(orgtbl-uc-draw-cont $3 0.0 1.6 20) 

tan
Tangent of A

|  r |     A |      SIN |                      |                      |
|----+-------+----------+----------------------+----------------------|
|  2 | -2.00 |   2.1850 |                      |                      |
|  3 | -1.80 |   4.2863 |                      |                      |
|  4 | -1.60 |  34.2325 |                      |                      |
|  5 | -1.40 |  -5.7979 |                      |                      |
|  6 | -1.20 |  -2.5722 |                      |                      |
|  7 | -1.00 |  -1.5574 | ████████████████████ |                      |
|  8 | -0.80 |  -1.0296 |        █████████████ |                      |
|  9 | -0.60 |  -0.6841 |            █████████ |                      |
| 10 | -0.40 |  -0.4228 |               ██████ |                      |
| 11 | -0.20 |  -0.2027 |                  ███ |                      |
| 12 |  0.00 |   0.0000 |                      |                      |
| 13 |  0.20 |   0.2027 |                      | ███                  |
| 14 |  0.40 |   0.4228 |                      | ██████               |
| 15 |  0.60 |   0.6841 |                      | █████████            |
| 16 |  0.80 |   1.0296 |                      | █████████████        |
| 17 |  1.00 |   1.5574 |                      | ████████████████████ |
| 18 |  1.20 |   2.5722 |                      |                      |
| 19 |  1.40 |   5.7979 |                      |                      |
| 20 |  1.60 | -34.2325 |                      |                      |
| 21 |  1.80 |  -4.2863 |                      |                      |
| 22 |  2.00 |  -2.1850 |                      |                      |
#+TBLFM: @2$2..@22$2=((($1-1.9999)-10.0)/5.0);%.2f :: @2$3..@22$3='(tan (string-to-number $2));%.4f :: $4='(orgtbl-uc-draw-cont $3 0.0 -1.6 20) :: $5='(orgtbl-uc-draw-cont $3 0.0 1.6 20) 

float-pi
PI

| ! |    A |   PI |
|---+------+------|
| 1 |  1.0 | 3.14 |
| 2 | 10.0 | 3.14 |
| 3 | 20.0 | 3.14 |
#+TBLFM: @2$3..@4$3='(eval float-pi);%.2f

float-e
e

| ! |    A |    e |
|---+------+------|
| 1 |  1.0 | 2.72 |
| 2 | 10.0 | 2.72 |
| 3 | 20.0 | 2.72 |
#+TBLFM: @2$3..@4$3='(eval float-e);%.2f

FONTFAMILY:elisp:

This prints to message buffer

(dolist (a (font-family-list)) (message a))
HEXTILE:hou::vex:

Hextile gradient inline vex (COPs).
Derivative work of various sources, most helpful was Procedural Graphics Tutorial: Hexagon Effects by Andrew Hung.
Used as a transition input for another effect.

// hextiles // this is a derivative work, from many conflicting sources // uses in-situ colormap for the control gradient, as its uvs are derived by the hex coords // code is unrolled for clarity float sqa = 1.0; float sqb = sqrt(3.0); float uu = $X; float vv = $Y; vector2 uv = set(uu,vv); float squ = (sqb * 0.5); float sqv = 0.5; float hxca = floor(uu / sqa) + 0.5; float hxcb = floor(vv / sqb) + 0.5; float hxcc = floor((uu - 0.5) / sqa) + 0.5; float hxcd = floor((vv - 1.0) / sqb) + 0.5; float ofsa = (uu - (hxca * sqa)); float ofsb = (vv - (hxcb * sqb)); float ofsc = (uu - ((hxcc + 0.5) * sqa)); float ofsd = (vv - ((hxcd + 0.5) * sqb)); vector2 aa = set(ofsa,ofsb); vector2 bb = set(ofsc,ofsd); float da = length(aa); float db = length(bb); float dsta = ofsc; float dstb = ofsd; float dstc = hxcc * 0.1; float dstd = hxcd * 0.5; float idx = hxcc * 1.0; float idy = hxcd * 1.0; if (da < db) { dsta = ofsa; dstb = ofsb; dstc = hxca; dstd = hxcb; idx = hxca - 1.0; idy = hxcb - 1.0; } float adsta = abs(dsta); float adstb = abs(dstb); float adstc = abs(dstc); float adstd = abs(dstd); vector2 sqh = set(0.5,(sqb * 0.5)); vector2 sqq = set(sqa,sqb); vector2 dsva = set(adsta,adstb); vector2 dsvb = set(adstc,adstd); float gg = max(dot(sqh,dsva),adsta); float mm = $MM; float cc = 0.9; float gsu = clamp((idx / $WW),0.0,1.0); $width = gsu; float gsv = clamp((idy / $WW),0.0,1.0); $height = gsv; vector4 pxl = colormap($IMG,gsu,gsv); $heximg = pxl; float bw = (gsu + pxl.x); $dist = clamp(((gg - (pxl.y + $MM)) / 0.05),0.0,1.0); $tile = abs(idy);
SDFBOXMASK:hou::vex:

Rectangular sdf mask inline vex (COPs).
This is a vex translation of a polygon shader by Inigo Quilez here.
Used for masking with rounded corners.

// vex translation of this shader by Inigo Quilez: // https://www.shadertoy.com/view/wdBXRW float uu = $X; float vv = $Y; vector2 p = set(uu,vv); float hrr = $RR * 1.0; vector2 tl = set($XEA+hrr,$YEA-hrr); vector2 bl = set($XEA+hrr,$YEB+hrr); vector2 br = set($XEB-hrr,$YEB+hrr); vector2 tr = set($XEB-hrr,$YEA-hrr); vector2 v[] = array(tl,bl,br,tr); int num = 4; float d = dot((p - v[0]),(p - v[0])); float s = 1.0; for( int i=0, j=num-1; i<num; j=i, i++ ) { // distance vector2 e = v[j] - v[i]; vector2 w = p - v[i]; vector2 b = w - (e * clamp((dot(w,e) / dot(e,e)), 0.0, 1.0)); d = min(d, dot(b,b)); //winding number from http://geomalgorithms.com/a03-_inclusion.html vector cond = set( (p.y >= v[i].y), (p.y < v[j].y), ((e.x * w.y) > (e.y * w.x))); if (((cond[0] == 1) && (cond[1] == 1) && (cond[2] == 1)) || ((cond[0] == 0) && (cond[1] == 0) && (cond[2] == 0))) { s = -s; } } float dist = (s * sqrt(d)); //float dist = -(sqrt(d.x) * sign(d.y)); dist = dist - $RR; dist = clamp(dist,0.0,1.0); $OUT = 1.0 - clamp((dist / 0.005),0.0,1.0);
GTKICONS:gtk4::vala:
// show gtk4 icons // by c.p.brown 2023 // icon list copied from: https://github.com/GNOME/gtk/blob/main/demos/icon-browser/icon.list // Gtk.Image.set_pixel_size() is super slow for some reason // shoudl be faster in Cairo, but heaps more work... using Gtk; int main (string[] args) { Gtk.Application wut = new Gtk.Application ("com.test.test", GLib.ApplicationFlags.DEFAULT_FLAGS); wut.activate.connect(() => { Gtk.ApplicationWindow win = new Gtk.ApplicationWindow(wut); Gtk.Box content = new Gtk.Box(VERTICAL,10); Gtk.ScrolledWindow contentscroll = new Gtk.ScrolledWindow(); Gtk.Box contentbox = new Gtk.Box(VERTICAL,10); Gtk.Entry searchentry = new Gtk.Entry(); searchentry.hexpand = true; contentscroll.vexpand = true; //contentscroll.hexpand = true; string[] icons = { "accessories-calculator", "accessories-character-map", "accessories-dictionary", "accessories-text-editor", "action-unavailable", "address-book-new", "airplane-mode", "alarm", "application-certificate", "application-exit", "application-rss+xml", "application-x-addon", "application-x-appliance", "application-x-executable", "applications-accessories", "applications-development", "applications-engineering", "applications-games", "applications-graphics", "applications-internet", "applications-multimedia", "applications-office", "applications-other", "applications-science", "applications-system", "applications-utilities", "appointment-missed", "appointment-new", "appointment-soon", "audio-card", "audio-headphones", "audio-headset", "audio-input-microphone", "audio-speakers", "audio-volume-high", "audio-volume-low", "audio-volume-medium", "audio-volume-muted", "audio-x-generic", "avatar-default", "battery", "battery-caution", "battery-caution-charging", "battery-empty", "battery-empty-charging", "battery-full", "battery-full-charged", "battery-full-charging", "battery-good", "battery-good-charging", "battery-low", "battery-low-charging", "battery-missing", "bluetooth-active", "bluetooth-disabled", "bookmark-new", "call-missed", "call-start", "call-stop", "camera-photo", "camera-video", "camera-web", "changes-allow", "changes-prevent", "channel-insecure", "channel-secure", "colorimeter-colorhug", "computer", "computer-apple-ipad", "computer-fail", "contact-new", "content-loading", "daytime-sunrise", "daytime-sunset", "dialog-error", "dialog-information", "dialog-password", "dialog-question", "dialog-warning", "display-brightness", "display-projector", "document-edit", "document-new", "document-open", "document-open-recent", "document-page-setup", "document-print", "document-print-preview", "document-properties", "document-revert", "document-save", "document-save-as", "document-send", "drive-harddisk", "drive-harddisk-ieee1394", "drive-harddisk-system", "drive-multidisk", "drive-optical", "drive-removable-media", "edit-clear", "edit-clear-all", "edit-copy", "edit-cut", "edit-delete", "edit-find", "edit-find-replace", "edit-paste", "edit-redo", "edit-select", "edit-select-all", "edit-undo", "emblem-default", "emblem-documents", "emblem-downloads", "emblem-favorite", "emblem-generic", "emblem-important", "emblem-mail", "emblem-new", "emblem-ok", "emblem-package", "emblem-photos", "emblem-readonly", "emblem-shared", "emblem-symbolic-link", "emblem-synchronized", "emblem-synchronizing", "emblem-system", "emblem-unreadable", "emblem-urgent", "emblem-videos", "emblem-web", "error-correct", "face-angel", "face-angry", "face-cool", "face-crying", "face-devilish", "face-embarrassed", "face-kiss", "face-laugh", "face-monkey", "face-plain", "face-raspberry", "face-sad", "face-shutmouth", "face-sick", "face-smile", "face-smile-big", "face-smirk", "face-surprise", "face-tired", "face-uncertain", "face-wink", "face-worried", "face-yawn", "find-location", "folder", "folder-documents", "folder-download", "folder-drag-accept", "folder-music", "folder-new", "folder-open", "folder-pictures", "folder-publicshare", "folder-remote", "folder-saved-search", "folder-templates", "folder-videos", "folder-visiting", "font-x-generic", "format-indent-less", "format-indent-more", "format-justify-center", "format-justify-fill", "format-justify-left", "format-justify-right", "format-text-bold", "format-text-direction-ltr", "format-text-direction-rtl", "format-text-italic", "format-text-strikethrough", "format-text-underline", "go-bottom", "go-down", "go-first", "go-home", "go-jump", "go-last", "go-next", "go-previous", "go-top", "go-up", "help-about", "help-browser", "help-contents", "help-faq", "image-loading", "image-missing", "image-x-generic", "input-dialpad", "input-gaming", "input-keyboard", "input-mouse", "input-tablet", "input-touchpad", "insert-image", "insert-link", "insert-object", "insert-text", "keyboard-brightness", "list-add", "list-remove", "list-remove-all", "mail-attachment", "mail-forward", "mail-mark-important", "mail-mark-junk", "mail-mark-notjunk", "mail-mark-read", "mail-mark-unread", "mail-message-new", "mail-read", "mail-replied", "mail-reply-all", "mail-reply-sender", "mail-send", "mail-send-receive", "mail-signed", "mail-signed-verified", "mail-unread", "mark-location", "media-eject", "media-flash", "media-floppy", "media-optical", "media-optical-bd", "media-optical-cd-audio", "media-optical-dvd", "media-playback-pause", "media-playback-start", "media-playback-stop", "media-playlist-consecutive", "media-playlist-repeat", "media-playlist-repeat-song", "media-playlist-shuffle", "media-record", "media-removable", "media-seek-backward", "media-seek-forward", "media-skip-backward", "media-skip-forward", "media-tape", "media-view-subtitles", "media-zip", "microphone-sensitivity-high", "microphone-sensitivity-low", "microphone-sensitivity-medium", "microphone-sensitivity-muted", "modem", "multimedia-player", "multimedia-player-apple-ipod-touch", "multimedia-volume-control", "network-cellular-3g", "network-cellular-4g", "network-cellular-acquiring", "network-cellular-connected", "network-cellular-edge", "network-cellular-gprs", "network-cellular-no-route", "network-cellular-offline", "network-cellular-signal-excellent", "network-cellular-signal-good", "network-cellular-signal-none", "network-cellular-signal-ok", "network-cellular-signal-weak", "network-cellular-umts", "network-error", "network-idle", "network-offline", "network-receive", "network-server", "network-transmit", "network-transmit-receive", "network-vpn", "network-vpn", "network-vpn-acquiring", "network-wired", "network-wired-acquiring", "network-wired-disconnected", "network-wired-no-route", "network-wired-offline", "network-wireless", "network-wireless-acquiring", "network-wireless-connected", "network-wireless-encrypted", "network-wireless-hotspot", "network-wireless-no-route", "network-wireless-offline", "network-wireless-signal-excellent", "network-wireless-signal-good", "network-wireless-signal-none", "network-wireless-signal-ok", "network-wireless-signal-weak", "network-workgroup", "night-light", "non-starred", "object-flip-horizontal", "object-flip-vertical", "object-rotate-left", "object-rotate-right", "object-select", "off", "on", "open-menu", "package-x-generic", "pan-down", "pan-end", "pan-start", "pan-up", "pda", "phone", "phone-apple-iphone", "preferences-desktop", "preferences-desktop-accessibility", "preferences-desktop-display", "preferences-desktop-font", "preferences-desktop-keyboard", "preferences-desktop-keyboard-shortcuts", "preferences-desktop-locale", "preferences-desktop-multimedia", "preferences-desktop-peripherals", "preferences-desktop-personal", "preferences-desktop-remote-desktop", "preferences-desktop-screensaver", "preferences-desktop-theme", "preferences-desktop-wallpaper", "preferences-other", "preferences-system", "preferences-system-network", "preferences-system-privacy", "preferences-system-windows", "printer", "printer-error", "printer-network", "printer-printing", "printer-warning", "process-stop", "rotation-allowed", "rotation-locked", "scanner", "security-high", "security-low", "security-medium", "semi-starred", "send-to", "software-update-available", "software-update-urgent", "star-new", "starred", "start-here", "sync-error", "sync-synchronizing", "system-file-manager", "system-help", "system-lock-screen", "system-log-out", "system-reboot", "system-run", "system-search", "system-shutdown", "system-software-install", "system-software-update", "system-users", "tab-new", "task-due", "task-past-due", "text-html", "text-x-generic", "text-x-generic-template", "text-x-preview", "text-x-script", "tools-check-spelling", "touchpad-disabled", "trophy-bronze", "trophy-gold", "trophy-silver", "uninterruptible-power-supply", "user-available", "user-away", "user-bookmarks", "user-busy", "user-desktop", "user-home", "user-idle", "user-info", "user-invisible", "user-offline", "user-status-pending", "user-trash", "user-trash-full", "utilities-system-monitor", "utilities-terminal", "video-display", "video-x-generic", "view-continuous", "view-dual", "view-fullscreen", "view-grid", "view-list", "view-more", "view-paged", "view-pin", "view-refresh", "view-restore", "view-sort-ascending", "view-sort-descending", "view-wrapped", "weather-clear", "weather-clear-night", "weather-few-clouds", "weather-few-clouds-night", "weather-fog", "weather-overcast", "weather-severe-alert", "weather-showers", "weather-showers-scattered", "weather-snow", "weather-storm", "weather-windy", "window-close", "window-maximize", "window-minimize", "window-new", "window-restore", "x-office-address-book", "x-office-calendar", "x-office-document", "x-office-document-template", "x-office-presentation", "x-office-presentation-template", "x-office-spreadsheet", "x-office-spreadsheet-template", "x-package-repository", "zoom-fit-best", "zoom-in", "zoom-original", "zoom-out" }; int washeight = 500; for (int i = 0; i < icons.length; i++) { Gtk.Image ib = new Gtk.Image.from_icon_name(icons[i]); ib.set_pixel_size(win.default_height / 5); Gtk.Label ilbl = new Gtk.Label(icons[i]); ilbl.selectable = true; Gtk.Box ibx = new Gtk.Box(HORIZONTAL,10); ibx.append(ib); ibx.append(ilbl); contentbox.append(ibx); } searchentry.changed.connect(() => { if (searchentry.text.strip() != "") { while (contentbox.get_first_child() != null) { contentbox.remove(contentbox.get_first_child()); } for (int i = 0; i < icons.length; i++) { if (icons[i].contains(searchentry.text)) { Gtk.Image ib = new Gtk.Image.from_icon_name(icons[i]); ib.set_pixel_size(win.default_height / 5); Gtk.Label ilbl = new Gtk.Label(icons[i]); ilbl.selectable = true; Gtk.Box ibx = new Gtk.Box(HORIZONTAL,10); ibx.append(ib); ibx.append(ilbl); contentbox.append(ibx); } } } else { for (int i = 0; i < icons.length; i++) { Gtk.Image ib = new Gtk.Image.from_icon_name(icons[i]); ib.set_pixel_size(win.default_height / 5); Gtk.Label ilbl = new Gtk.Label(icons[i]); ilbl.selectable = true; Gtk.Box ibx = new Gtk.Box(HORIZONTAL,10); ibx.append(ib); ibx.append(ilbl); contentbox.append(ibx); } } }); win.notify.connect(() => { if (((int) win.default_height) != washeight) { Gtk.Box bb = (Gtk.Box) contentbox.get_first_child(); while (bb != null) { Gtk.Image ii = (Gtk.Image) bb.get_first_child(); ii.set_pixel_size(win.default_height / 5); bb = (Gtk.Box) bb.get_next_sibling(); } washeight =((int) win.default_height); } }); contentscroll.set_child(contentbox); content.append(searchentry); content.append(contentscroll); win.set_child(content); win.default_width = 500; win.default_height = 500; win.present(); }); return wut.run(args); }
TBLFM PARSER:vala:

Old primitive attempt at parsing OrgMode table formulae. Wouldn't use it (lots of splice() and substring() based on index_of() !), but has a few ideas worth picking over if needed later... 3 years was so long ago looking at it now.

// parse and run org tblfm expressions // by c.p.brown, 2023 // // todo next: finish elisp functions bool spew; int imod (int a, int b) { if (a >= 0) { return (a % b); } if (a >= -b) { return (a + b); } return ((a % b) + b) % b; } string[,] orgtodat (int ind, string org) { int64 odtts = GLib.get_real_time(); string tabs = ("%*s").printf(ind," ").replace(" ","\t"); string[,] dat = {{""}}; string[] rr = org.split("\n"); if (rr[0].has_prefix("|")) { int ii = rr[0].index_of("|"); int oo = rr[0].last_index_of("|"); string headrow = rr[0]; if(oo > (ii + 1)) { headrow = rr[0].substring((ii+1),(oo - (ii + 1))); } string[] hh = headrow.split("|"); string[] headers = {}; for (int h = 0; h < hh.length; h++) { if(hh[h].strip() != "") { headers += hh[h].strip(); } } int num_rows = 0; int num_columns = headers.length; for (int r = 0; r < rr.length; r++) { if (rr[r] != null && rr[r].strip() != "" && rr[r].has_prefix("|") == true) { num_rows += 1; } } dat = new string[num_rows,num_columns]; int tr = 0; for (int r = 0; r < rr.length; r++) { if (rr[r] != null && rr[r].strip() != "" && rr[r].has_prefix("|") == true) { ii = rr[r].index_of("|"); oo = rr[r].last_index_of("|"); if (oo > (ii + 1)) { rr[r] = rr[r].substring((ii+1),(oo - (ii + 1))); } string[] cc = rr[r].split("|"); if (cc.length == 1 && cc[0].contains("-+-")) { cc = rr[r].split("+"); } for (int c = 0; c < num_columns; c++) { dat[tr,c] = cc[c].strip(); } tr += 1; } } } int64 odtte = GLib.get_real_time(); if (spew) { print("%sorgtodat took %f microseconds\n",tabs,((double) (odtte - odtts)));} return dat; } string reorgtable (int ind, string[,] dat) { int64 reots = GLib.get_real_time(); string tabs = ("%*s").printf(ind," ").replace(" ","\t"); int[] maxlen = new int[dat.length[1]]; string o = ""; string hln = "------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------"; for (int m = 0; m < maxlen.length; m++) { maxlen[m] = 0; } for (int r = 0; r < dat.length[0]; r++) { for (int c = 0; c < dat.length[1]; c++) { string lc = dat[r,c].replace("-",""); if (lc.strip().length == 0) { continue; } maxlen[c] = int.max(maxlen[c],dat[r,c].length); } } for (int r = 0; r < dat.length[0]; r++) { bool ishline = false; string hc = dat[r,0].replace("-","").strip(); if (hc.length == 0) { for (int c = 1; c < dat.length[1]; c++) { hc = hc.concat(dat[r,c]); } hc = hc.replace("-","").strip(); if (hc.length == 0) { ishline = true; } } if (ishline) { o = o.concat("|"); for (int c = 0; c < (dat.length[1] - 1); c++) { //print("%.*s%s\n",5,s,"heading"); o = "%s-%.*s%s+".printf(o,maxlen[c],hln,"-"); } o = "%s-%.*s%s|\n".printf(o,maxlen[(dat.length[1] - 1)],hln,"-"); } else { o = o.concat("| "); for (int c = 0; c < dat.length[1]; c++) { o = "%s%-*s | ".printf(o,maxlen[c],dat[r,c]); } o._chomp(); o = o.concat("\n"); } } int64 reote = GLib.get_real_time(); if (spew) { print("%sreorgtable took %f microseconds\n",tabs,((double) (reote - reots)));} return o; } // TODO: handle pre-trimmed input... int getrefindex (int ind, int myi, string r, string[,] dat) { int64 idxts = GLib.get_real_time(); string tabs = ("%*s").printf(ind," ").replace(" ","\t"); int o = 0; if (r != null && r.strip() != "") { if (spew) { print("%sgetrefindex: input is %s\n",tabs,r); } string s = r; s.canon("1234567890<>I",'.'); int oo = s.index_of("."); if (oo > 0) { s = s.substring(0,oo); switch (s.get_char(0)) { case '>': if (spew) { print("%s\tget prev ref (>)...\n",tabs); } o = (myi - (s.split(">").length - 1)); break; case '<': if (spew) { print("%s\tget next ref (<)...\n",tabs); } o = (myi + (s.split("<").length - 1)); break; case 'I': if (spew) { print("%s\tget hline ref (I)...\n",tabs); } int qq = 0; int x = s.split("I").length - 1; for (int i = 0; i < dat.length[0]; i++) { if (dat[i,0].has_prefix("--")) { qq += 1; if (qq == x) { o = i + 1; break; } } } break; default: o = int.parse(s) - 1; break; } } else { int t = 0; if (int.try_parse(s,out t)) { o = t - 1; } } } if (spew) { print("%sgetrefindex: zero-based cell ref is %d\n",tabs,o); } int64 idxte = GLib.get_real_time(); if (spew) { print("%sgetrefindex: took %f microseconds\n",tabs,((double) (idxte - idxts)));} return o; } // separate subtraction (a - b) from negative (-a) string subminus (int ind, string s) { int64 pusts = GLib.get_real_time(); string tabs = ("%*s").printf(ind," ").replace(" ","\t"); string o = s; if (s.contains("-")) { char[] nums = {'0','1','2','3','4','5','6','7','8','9'}; for (int h = 0; h < s.length; h++) { if (s[h] == '-') { if (h > 0 && h < (s.length - 1)) { if (s[(h-1)] in nums && s[(h+1)] in nums) { o = o.splice(h,(h+1),"!"); } else { // 3-1 if (s[(h-1)] == ')' && s[(h+1)] in nums) { o = o.splice(h,(h+1),"!"); } else { // )-1 if (s[(h-1)] == ')' && s[(h+1)] == '(') { o = o.splice(h,(h+1),"!"); } else { // )-( if (s[(h-1)] in nums && s[(h+1)] == ' ') { o = o.splice(h,(h+1),"!"); } else { // 3- if (s[(h-1)] in nums && s[(h+1)] == '(') { o = o.splice(h,(h+1),"!"); } else { // 3-( if (s[(h-1)] == ')' && s[(h+1)] == ' ') { o = o.splice(h,(h+1),"!"); } else { // )- if (s[(h-1)] == ' ' && s[(h+1)] == ' ') { o = o.splice(h,(h+1),"!"); } // - } } } } } } } } } } int64 puste = GLib.get_real_time(); if (spew) { print("%ssubminus took %f microseconds\n",tabs,((double) (puste - pusts)));} return o; } string replacerefs (int ind, int myr, int myc, string inner, string[,] tbldat) { int64 refts = GLib.get_real_time(); string tabs = ("%*s").printf(ind," ").replace(" ","\t"); if (inner != null && inner.strip() != "") { if (inner.contains("@") || inner.contains("$")) { if (spew) { print("%sreplacerefs: input is %s\n",tabs,inner); } string s = inner; int[] rc = {-1,-1}; int y = 0; int b = 0; int r = myr; int c = myc; while (s.contains("@") || s.contains("$")) { if (y > 100) {break;} string t = s; t.canon("$@1234567890<>I",'.'); //print("\tevallisp: s.canon = %s\n",t); for (int h = b; h < t.length; h ++) { //print("evallisp: \tchecking char %d %c in block starting at %d\n",h,t[h],b); if (t[h] == '.' || (h == t.length - 1)) { if ((rc[0] + rc[1]) != -2) { //print("evallisp: \t\trc[0] = %d, rc[1] = %d\n",rc[0],rc[1]); if (rc[0] == -1) { r = myr; rc[0] = 99999; } if (rc[1] == -1) { c = myc; rc[1] = 99999;} if(spew) { print("%s\tr = %d, c = %d\n",tabs,r,c); } s = s.splice(int.min(rc[0],rc[1]),h,tbldat[r,c]); if (spew) { print("%sreplacerefs: spliced expression: %s\n",tabs,s); } } rc = {-1,-1}; b = ((h + 1) - (t.length - s.length)); r = myr; c = myc; break; } if (t[h] == '$') { string cs = t.substring((h+1)); //print("\tevallisp: \t\tcs = %s\n",cs); rc[1] = h; c = getrefindex((ind + 1),myc,cs, tbldat); //print("\tevallisp: \t\tc = %d\n",c); } if (t[h] == '@') { string rs = t.substring((h + 1)); //print("\tevallisp: \t\trs = %s\n",rs); rc[0] = h; r = getrefindex((ind + 1),myr,rs, tbldat); //print("\tevallisp: \t\tr = %d\n",r); } } y += 1; } int64 refte = GLib.get_real_time(); if (spew) { print("%sreplacerefs took %f microseconds\n",tabs,((double) (refte - refts)));} return s; } } int64 refte = GLib.get_real_time(); if (spew) { print("%sreplacerefs took %f microseconds\n",tabs,((double) (refte - refts)));} return inner; } string evalmaths (int ind, int myr, int myc, string inner, string[,] tbldat) { int64 mthts = GLib.get_real_time(); string tabs = ("%*s").printf(ind," ").replace(" ","\t"); string o = inner; string[] ops = {"*", "/", "+", "!"}; if (inner != null && inner.strip() != "") { if (spew) { print("%sdomaths input .....: %s\n",tabs,inner); } string s = inner; if (inner.contains("@") || inner.contains("$")) { s = replacerefs((ind + 1),myr, myc, inner, tbldat); } if (s.contains("-")) { s = subminus((ind + 1),s); s = s.replace("-"," -"); } if (spew) { print("%sdomaths expression : %s\n",tabs,s); } int y = 0; foreach (string x in ops) { //if (s.contains(x)) { while (s.contains(x)) { //print("domaths: \texpression contains %s\n",x); if (y > 10) { break; } double sm = 0.0; string t = s; switch (x) { case "*": t.canon("1234567890.*-",'_'); break; case "/": t.canon("1234567890./-",'_'); break; case "+": t.canon("1234567890.+-",'_'); break; case "!": t.canon("1234567890.!-",'_'); break; default: t.canon("1234567890.",'_'); break; } //print("domaths: \ts.canon: %s\n",t); string[] sp = t.split(x); if (sp.length > 1) { //print("domaths: \tleft = %s, right = %s\n",sp[0],sp[1]); int aii = 0; int oo = sp[1].length - 1; int splen = sp[0].length; if (sp[0].length > 0 && sp[0].contains("_")) { for ( int h = (sp[0].length - 1); h >= 0; h--) { //print("domaths: \tleft tail search at %d: %c == %c ?\n",h,sp[0][h],'_'); if (sp[0][h] != '_') { oo = h; break; } } for ( int h = oo; h >= 0; h--) { //print("domaths: \tleft head search at %d: %c == %c ?\n",h,sp[0][h],'_'); if (sp[0][h] == '_') { aii = h + 1; break; } } //if (oo > 0 && oo < (sp[0].length - 2)) { oo += 1; } //print("domaths: left starts at %d, ends at %d\n",aii,oo); if (aii < sp[0].length && aii < oo && oo < sp[0].length) { sp[0] = sp[0].substring(aii,(oo - aii + 1)); //print("domaths: left substring(%d,%d): %s\n",aii,(oo - aii),sp[0]); } } int ii = 0; if (sp[1].length > 0 && sp[1].contains("_")) { for ( int h = (sp[1].length - 1); h >= 0; h--) { if (sp[1][h] != '_') { oo = h; break; } } for ( int h = oo; h >= 0; h--) { if (sp[1][h] == '_') { ii = h + 1; break; } } if (ii < sp[1].length && ii < oo && oo < sp[1].length) { sp[1] = sp[1].substring(ii,(oo - ii + 1)); //print("domaths: right substring(%d,%d): %s\n",ii,(oo - ii + 1),sp[1]); } } //print("domaths: \tleft = %s, right = %s\n",sp[0],sp[1]); oo = oo + splen + 2; double aa = 0.0; double bb = 0.0; if (double.try_parse(sp[0].strip(),out aa)) { if (double.try_parse(sp[1].strip(),out bb)) { switch (x) { case "*": sm = aa * bb; break; case "/": sm = aa / bb; break; case "+": sm = aa + bb; break; case "!": sm = aa - bb; break; default: sm = 0.0; break; } } else { print("%sERROR: %s or %s are not float",tabs,sp[0],sp[1]); break; } } else { print("%sERROR: %s or %s are not float",tabs,sp[0],sp[1]); break; } //print("domaths: s.length: %d\n",s.length); //print("domaths: \tsplicing from %d to %d\n",aii,oo); if (aii >= 0 && aii < s.length && aii < oo) { if (oo > aii && oo <= s.length) { s = s.splice(aii,oo,"%f".printf(sm)); print("%sdomaths splice ....: %s\n",tabs,s); } } y += 1; } else { break; } } } //} o = s; } int64 mthte = GLib.get_real_time(); if (spew) { print("%sdomaths took %f microseconds\n",tabs,((double) (mthte - mthts)));} return o; } string doformat (int ind, string n) { int64 frmts = GLib.get_real_time(); string tabs = ("%*s").printf(ind," ").replace(" ","\t"); if (n != null && n != "") { if (spew) { print("%sdoformat: input is %s\n",tabs,n); } string[] np = n.split(";"); if (np.length == 2) { if (np[0] != "" && np[1] != "") { string h = np[1].printf(double.parse(np[0])); int64 frmte = GLib.get_real_time(); if (spew) { print("%sdoformat took %f microseconds\n",tabs,((double) (frmte - frmts)));} return h; } } } int64 frmte = GLib.get_real_time(); if (spew) { print("%sdoformat took %f microseconds\n",tabs,((double) (frmte - frmts)));} return n; } string evallisp (int ind, int myr, int myc, string instr, string[,] tbldat) { int64 lspts = GLib.get_real_time(); string tabs = ("%*s").printf(ind," ").replace(" ","\t"); string inner = instr; if (inner != null && inner.strip() != "") { if (spew) { print("%sevallisp: input is %s\n",tabs,inner); } int ic = 1; int ii = -1; if (inner.contains("format")) { if (spew) { print("%s\tformat...\n",tabs); } inner = inner.replace("format",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.split(" "); int ptl = 0; string[] k = {}; foreach (string g in pts) { if (g.strip() != "") { ptl += 1; k += g.strip(); } } if (k.length > 1 && k[0].contains("%")) { if (spew) { print("%s\t\tgetting tokens in %s\n",tabs,k[0]); } int n = 1; int ival = 0; double dval = 0.0; k[0] = k[0].replace("%","%%"); int y = 0; while (k[0].contains("%")) { if (y > 10) { break; } ii = k[0].index_of("%"); string tk = k[0].substring(ii,3); if (strcmp(tk,"%%d") == 0) { if (int.try_parse(k[n],out ival)) { k[0] = k[0].splice(ii,(ii+3),k[n]); if (spew) { print("%s\t\tspliced format: %s\n",tabs,k[0]); } n += 1; } else { int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp format took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "ERROR: format arg %d not an int".printf(n); } } if (strcmp(tk,"%%f") == 0) { if (double.try_parse(k[n],out dval)) { k[0] = k[0].splice(ii,(ii+3),k[n]); if (spew) { print("%s\t\tspliced format: %s\n",tabs,k[0]); } n += 1; } else { int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp format took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "ERROR: format arg %d not an int".printf(n); } } if (strcmp(tk,"%%s") == 0) { k[0] = k[0].splice(ii,(ii+3),k[n]); if (spew) { print("%s\t\tspliced format: %s\n",tabs,k[0]); } n += 1; } y += 1; } int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp format took %f microseconds\n",tabs,((double) (lspte - lspts)));} return k[0]; } } if (inner.contains("make-string")) { // (make-string 5 ?x) if (spew) { print("%s\tmake-string...\n",tabs); } inner = inner.replace("make-string",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.split(" "); if (pts.length > 1 && pts[0] != "") { bool docount = false; for (int h = 0; h < pts.length; h++) { string hh = pts[h].replace("\"","").strip(); if (pts[h].has_prefix("?") == false) { pts[0] = "%.*s".printf(ic,hh); } ic = 1; docount = int.try_parse(hh,out ic); } int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp make-string took %f microseconds\n",tabs,((double) (lspte - lspts)));} return string.joinv(" ",pts); } return "ERROR: malformed make-string expression"; } if (inner.contains("substring")) { // (substring ?a ?b ?c...) if (spew) { print("%s\tsubstring...\n",tabs); } inner = inner.replace("substring",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.split(" "); if (pts.length > 1 && pts[0] != "") { string sp = pts[0].replace("\"","").strip(); int si = 0; if (int.try_parse(pts[1],out si)) { if (pts.length > 2) { int so = 0; if (int.try_parse(pts[2],out so)) { if (si >= 0 && so > si) { sp = sp.substring(si,so); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp substring took %f microseconds\n",tabs,((double) (lspte - lspts)));} return sp; } } } else { if (si >= 0) { sp = sp.substring(si); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp substring took %f microseconds\n",tabs,((double) (lspte - lspts)));} return sp; } } } } int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp substring took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "ERROR: malformed substring expression"; } if (inner.contains("string")) { // (string ?a ?b ?c...) if (spew) { print("%s\tstring...\n",tabs); } inner = inner.replace("string",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.split(" "); if (pts.length > 0 && pts[0] != "") { for (int h = 0; h < pts.length; h++) { if (pts[h].has_prefix("?")) { string hh = pts[h].replace("\"","").strip(); hh = hh.replace("?",""); pts[h] = "%s".printf(hh); } } int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp string took %f microseconds\n",tabs,((double) (lspte - lspts)));} return string.joinv(" ",pts); } return "ERROR: malformed string expression"; } if (inner.contains("concat")) { // (concat "s" "s") if (spew) { print("%s\tconcat...\n",tabs); } inner = inner.replace("concat",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.split(" "); if (pts.length > 0 && pts[0] != "") { for (int h = 0; h < pts.length; h++) { string hh = pts[h].replace("\"","").strip(); pts[h] = hh; } int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp concat took %f microseconds\n",tabs,((double) (lspte - lspts)));} return string.joinv("",pts); } return "ERROR: malformed concat expression"; } if (inner.contains("downcase")) { // (downcase "s") if (spew) { print("%s\tdowncase...\n",tabs); } inner = inner.replace("downcase",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp downcase took %f microseconds\n",tabs,((double) (lspte - lspts)));} return inner.down(); } if (inner.contains("upcase")) { // (upcase "s") if (spew) { print("%s\tupcase...\n",tabs); } inner = inner.replace("upcase",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp upcase took %f microseconds\n",tabs,((double) (lspte - lspts)));} return inner.up(); } // number if (inner.contains("abs")) { // (abs -1) if (spew) { print("%s\tabs...\n",tabs); } inner = inner.replace("abs",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length == 1 && pts[0] != "") { double v = 0.0; if (double.try_parse(pts[0], out v)) { v = v.abs(); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp abs took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } } return "ERROR: malformed abs expression"; } if (inner.contains("mod")) { // (mod 9 4) if (spew) { print("%s\tmod...\n",tabs); } inner = inner.replace("mod",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length == 2 && pts[0] != "") { double uu = 0.0; if (double.try_parse(pts[0],out uu)) { double vv = 0.0; if (double.try_parse(pts[1],out(vv))) { if (spew) { print("%s\tfmod(%f,%f)\n",tabs,uu,vv); } uu = Math.fmod(uu,vv); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp fmod took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(uu); } } int u = 0; if (int.try_parse(pts[0], out u)) { int v = 0; if (int.try_parse(pts[1], out v)) { u = imod(u,v); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp mod took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%d".printf(u); } } } return "ERROR: malformed mod expression"; } if (inner.contains("random")) { if (spew) { print("%s\trand...\n",tabs); } inner = inner.replace("random",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length == 1) { int u = 0; if (int.try_parse(pts[0],out u)) { GLib.Rand rnd = new GLib.Rand(); int64 lspte = GLib.get_real_time(); rnd.set_seed(((int32) lspte)); if (spew) { print("%sevallisp random took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%d".printf(rnd.int_range(0,((int32) u))); } } return "ERROR: malformed random expression"; } if (inner.contains("ceiling")) { // (ceiling 1.5) if (spew) { print("%s\tceiling...\n",tabs); } inner = inner.replace("ceiling",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length == 1 && pts[0] != "") { double v = 0.0; if (double.try_parse(pts[0], out v)) { v = Math.ceil(v); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp ceiling took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } } return "ERROR: malformed ceiling expression"; } if (inner.contains("floor")) { // (floor 1.5) if (spew) { print("%s\tfloor...\n",tabs); } inner = inner.replace("floor",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length == 1 && pts[0] != "") { double v = 0.0; if (double.try_parse(pts[0], out v)) { v = Math.floor(v); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp floor took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } } return "ERROR: malformed floor expression"; } if (inner.contains("round")) { // (round 1.5) if (spew) { print("%s\tround...\n",tabs); } inner = inner.replace("round",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length == 1 && pts[0] != "") { double v = 0.0; if (double.try_parse(pts[0], out v)) { v = Math.round(v); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp round took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } } return "ERROR: malformed round expression"; } if (inner.contains("truncate")) { // (truncate 1.5) if (spew) { print("%s\ttruncate...\n",tabs); } inner = inner.replace("truncate",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length == 1 && pts[0] != "") { double v = 0.0; if (double.try_parse(pts[0], out v)) { v = Math.trunc(v); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp truncate took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } } return "ERROR: malformed truncate expression"; } if (inner.contains("min")) { // (min 1 2 3...) if (spew) { print("%s\tmin...\n",tabs); } inner = inner.replace("min",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length > 1 && pts[0] != "") { double v = 0.0; if (double.try_parse(pts[0], out v)) { for (int h = 1; h < pts.length; h++) { double j = 0.0; if (double.try_parse(pts[h],out j)) { v = double.min(v,j); } } int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } } return "ERROR: malformed min expression"; } if (inner.contains("max")) { // (max 1 2 3...) if (spew) { print("%s\tmax...\n",tabs); } inner = inner.replace("max",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length > 1 && pts[0] != "") { double v = 0.0; if (double.try_parse(pts[0], out v)) { for (int h = 1; h < pts.length; h++) { double j = 0.0; if (double.try_parse(pts[h],out j)) { v = double.max(v,j); } } int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } } return "ERROR: malformed max expression"; } if (inner.contains("expt")) { // (expt 2.0 1.2) if (spew) { print("%s\texpt...\n",tabs); } inner = inner.replace("expt",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length > 1 && pts[0] != "") { double v = 0.0; if (double.try_parse(pts[0], out v)) { for (int h = 1; h < pts.length; h++) { double j = 0.0; if (double.try_parse(pts[h],out j)) { v = Math.pow(v,j); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp expt took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } } } } return "ERROR: malformed expt (pow) expression"; } if (inner.contains("exp")) { // (exp 1.5) if (spew) { print("%s\texp...\n",tabs); } inner = inner.replace("exp",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length == 1 && pts[0] != "") { double v = 0.0; if (double.try_parse(pts[0], out v)) { v = Math.exp(v); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp exp took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } } return "ERROR: malformed exp expression"; } if (inner.contains("log")) { // (log 1.5) if (spew) { print("%s\tlog...\n",tabs); } inner = inner.replace("log",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length == 1 && pts[0] != "") { double v = 0.0; if (double.try_parse(pts[0], out v)) { v = Math.log(v); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp log took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } } return "ERROR: malformed log expression"; } if (inner.contains("asin")) { // (asin 1.5) if (spew) { print("%s\tasin...\n",tabs); } inner = inner.replace("asin",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length == 1 && pts[0] != "") { double v = 0.0; if (double.try_parse(pts[0], out v)) { v = Math.asin(v); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp asin took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } } return "ERROR: malformed asin expression"; } if (inner.contains("acos")) { // (acos 1.5) if (spew) { print("%s\tacos...\n",tabs); } inner = inner.replace("acos",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length == 1 && pts[0] != "") { double v = 0.0; if (double.try_parse(pts[0], out v)) { v = Math.acos(v); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp acos took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } } return "ERROR: malformed acos expression"; } if (inner.contains("atan")) { // (atan 1.5) if (spew) { print("%s\tatan...\n",tabs); } inner = inner.replace("atan",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length == 1 && pts[0] != "") { double v = 0.0; if (double.try_parse(pts[0], out v)) { v = Math.atan(v); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp atan took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } } return "ERROR: malformed atan expression"; } if (inner.contains("sin")) { // (sin 1.5) if (spew) { print("%s\tsin...\n",tabs); } inner = inner.replace("sin",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length == 1 && pts[0] != "") { double v = 0.0; if (double.try_parse(pts[0], out v)) { v = Math.sin(v); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp sin took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } } return "ERROR: malformed sin expression"; } if (inner.contains("cos")) { // (cos 1.5) if (spew) { print("%s\tcos...\n",tabs); } inner = inner.replace("cos",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length == 1 && pts[0] != "") { double v = 0.0; if (double.try_parse(pts[0], out v)) { v = Math.cos(v); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp cos took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } } return "ERROR: malformed cos expression"; } if (inner.contains("tan")) { // (tan 1.5) if (spew) { print("%s\ttan...\n",tabs); } inner = inner.replace("tan",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length == 1 && pts[0] != "") { double v = 0.0; if (double.try_parse(pts[0], out v)) { v = Math.tan(v); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp tan took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } } return "ERROR: malformed tan expression"; } if (inner.contains("sqrt")) { // (sqrt 1.5) if (spew) { print("%s\tsqrt...\n",tabs); } inner = inner.replace("sqrt",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); string[] pts = inner.strip().split(" "); if (pts.length == 1 && pts[0] != "") { double v = 0.0; if (double.try_parse(pts[0], out v)) { v = Math.sqrt(v); int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp sqrt took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } } return "ERROR: malformed sqrt expression"; } if (inner.contains("float-pi")) { // (float-pi) if (spew) { print("%s\tfloat-pi...\n",tabs); } inner = inner.replace("float-pi",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); double v = Math.PI; int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp PI took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } if (inner.contains("float-e")) { // (float-e) if (spew) { print("%s\tfloat-e...\n",tabs); } inner = inner.replace("float-e",""); inner = inner.replace("(",""); inner = inner.replace(")","").strip(); double v = Math.E; int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp E took %f microseconds\n",tabs,((double) (lspte - lspts)));} return "%f".printf(v); } } int64 lspte = GLib.get_real_time(); if (spew) { print("%sevallisp took %f microseconds\n",tabs,((double) (lspte - lspts)));} return instr; } double dosum (int ind, int myr, int myc, string inner, string[,] tbldat) { int64 sumts = GLib.get_real_time(); string tabs = ("%*s").printf(ind," ").replace(" ","\t"); double sm = 0.0; if (inner != null && inner.strip() != "") { if (spew) { print("%sdosum: %s\n",tabs,inner); } string[] sp = inner.split(".."); if (sp.length == 2) { if (sp[0].strip() != "" && sp[1].strip() != "") { int[] coords = {-1,-1,-1,-1}; for (int x = 0; x < 2; x++) { int b = 0; int[] rc = {-1,-1}; int y = 0; int r = myr; int c = myc; while (sp[x].contains("@") || sp[x].contains("$")) { if (y > 200) { print("ERROR: reference string stuck in the loop: %s\n",sp[x]); break; } string t = sp[x]; t.canon("$@1234567890<>I",'.'); for (int h = b; h < t.length; h ++) { if (t[h] == '.' || (h == t.length - 1)) { if ((rc[0] + rc[1]) != -2) { if (rc[0] == -1) { r = myr; rc[0] = 99999; } if (rc[1] == -1) { c = myc; rc[1] = 99999; } coords[(x+x)] = r; coords[(1+(x+x))] = c; sp[x] = sp[x].splice(int.min(rc[0],rc[1]),h,""); if (spew) { print("%sdosum: part%d row = %d, col = %d\n",tabs,x,r,c); } } rc = {-1,-1}; b = ((h + 1) - (t.length - sp[x].length)); r = myr; c = myc; break; } if (t[h] == '$') { string cs = t.substring((h+1)); rc[1] = h; c = getrefindex((ind + 1),myc,cs, tbldat); } if (t[h] == '@') { string rs = t.substring((h + 1)); rc[0] = h; r = getrefindex((ind + 1),myr,rs, tbldat); } } y += 1; } } if (spew) { print("%sdosum: zero-based cell refs...\n",tabs); } if (spew) { print("%s\trow1=%d, col1=%d\n%s\trow2=%d, col2=%d\n",tabs,coords[0],coords[1],tabs,coords[2],coords[3]); } if (coords[0] == coords[2]) { for (int i = coords[1]; i <= coords[3]; i++) { double dd = 0.0; if (double.try_parse(tbldat[coords[0],i])) { if ( dd != 0.0) { sm += dd; } } } if (spew) { print("%s\thsum = %f\n",tabs,sm); } } if (coords[1] == coords[3]) { for (int i = coords[0]; i <= coords[2]; i++) { double dd = 0.0; if (double.try_parse(tbldat[i,coords[1]],out dd)) { if ( dd != 0.0) { sm += dd; } } } if (spew) { print("%s\tvsum = %f\n",tabs,sm); } } } } } int64 sumte = GLib.get_real_time(); if (spew) { print("%sdosum took %f microseconds\n",tabs,((double) (sumte - sumts)));} return sm; } string doelisp (int ind, int r, int c, string e, string[,] tbldat) { string ret = e; int y = 0; while (ret.contains("'(")) { if (spew) { print("\t\telisp: lisp expression is %s\n",e); } if (y > 200) { print("ERROR: expression stuck in a loop: %s\n",e); break; } string o = e; int qii = e.index_of("'(") + 1; int qoo = -1; int oc = 0; // match brace of elisp ret = ret.splice((qii - 1),qii," "); if (spew) { print("\t\telisp: spliced comma: %s\n",e); } for (int h = qii; h < o.length; h++) { if (o[h] == '(') { if (h == qii) { oc = 1; } else { oc += 1; } } if (o[h] == ')') { oc -= 1; qoo = h; if ( oc == 0 ) { break; } } } // isolate elisp o = e.substring(qii,(qoo - (qii - 1))); if (spew) { print("\t\telisp: outer lisp expression is %s\n",o); } int z = 0; // sub-expressions while (o.contains("(")) { if (z > 200) { print("\nERROR: expression stuck in the elisp inner loop: %s\n\n",o); break; } // incasement if (spew) { print("\t\t\telisp inner: iteration %d\n",z); } int eii = 0; int eoo = -1; eii = o.last_index_of("("); string m = o.substring(eii); eoo = m.index_of(")") + 1; if (eoo != -1) { string inner = o.substring(eii,eoo); if (inner.contains("@") || inner.contains("$")) { inner = replacerefs(4,r, c, inner, tbldat); } if (spew) { print("\t\t\telisp inner: lisp expression: %s\n",inner); } string em = evallisp(4,r,c,inner,tbldat); if ( em == inner ) { em = em.replace("(",""); em = em.replace(")",""); em = "ERROR: unknown function %s".printf(em); } o = o.splice(eii,(eoo + eii),em); o = o.replace("\"",""); if (spew) { print("\t\t\telisp inner: spliced expression = %s\n",o); } } else { break; } z += 1; } ret = ret.splice(qii,qoo+1,o); } return ret; } string domaths (int ind, int r, int c, string e, string[,] tbldat) { string ret = e; if ( e.strip() != "") { string o = e; int z = 0; int tii = -1; int too = -1; string inner = e; if (spew) { print("\ttblfm checking expression: %s\n",e); } while (o.contains("(")) { if (z > 200) { print("\nERROR: expression stuck in the tblfm inner loop: %s\n\n",o); break; } tii = o.last_index_of("("); string m = o.substring(tii); too = m.index_of(")") + 1; inner = o.substring(tii,too); if (spew) { print("\t\ttblfm: inner expression: %s\n",inner); } if (inner.contains("..")) { m = o.substring(0,tii); double sm = dosum(3,r,c,inner,tbldat); tii = m.last_index_of("vsum"); if (spew) { print("\t\ttblfm: sum = %f\n",sm); } o = o.splice(tii,(too + tii + 4),"%f".printf(sm)); if (spew) { print("\t\ttblfm: spliced expression = %s\n",o); } } if (inner.contains("/") || inner.contains("*") || inner.contains("+") || inner.contains("-")){ inner = inner.replace("(",""); inner = inner.replace(")",""); string sm = evalmaths(3,r, c, inner, tbldat); if (spew) { print("\t\ttblfm: result = %s\n",sm); } o = o.splice(tii,(too + tii),sm); if (spew) { print("\t\ttblfm: spliced expression = %s\n",o); } } if (o == e) { o = "ERROR: unknown function %s".printf(o); break; } z += 1; } if(o != null && o.strip() != "") { ret = o; } } return ret; } void main() { int64 ofmts = GLib.get_real_time(); spew = true; string[,] dat; string orgtbl = """| AA | BB | CC | DD |\n |--------+-------+--------+----------|\n | 68.0 | 39.47 | 128.15 | 337.59 |\n | 403.88 | 16.21 | 117.03 | -9.0 |\n | 5.8 | 14.73 | 58.1 | 107.64 |\n |--------+-------+--------+----------|\n | | | | |"""; dat = orgtodat(0,orgtbl); string theformula = "@>$4=((vsum(@1$4..@>>>$4) / 1000.0 ) * 20.0);%.2f\n@>$2='(format \"%s_%f\" (downcase @1$2) @>>>$1)\n@>$1='(min @4$2 (max @3 @5))\n@>$3=@4$1-((@4$3 / @4$4) + 0.5)\n@1$2='(concat \"2_\" @1$2)\n@1$3 = '(abs @4$4) + '(org-sbe \"x\")\n$4=($1*$2);%.2f\n@1='(concat \"[\" @1 \"]\")\n@3$3='(random 100)\n@4$3='(mod $< 10)"; //string e = theformula; // we need 9.0846 from the above string[] xprs = theformula.split("\n"); int ii = 0; int oo = 0; int r = 0; int c = 0; string fm = ""; foreach (string e in xprs) { if (spew) { print("reading formula : %s\n",e); } string[] ep = e.split("="); ii = -1; oo = -1; r = -1; c = -1; fm = ""; if (ep.length == 2) { ep[0] = ep[0].strip(); ep[1] = ep[1].strip(); if (ep[0] != "" && ep[1] != "") { // TODO: // handle whole row/col target loops, eg: $3=($1*$2) -> for i in rows { cell[i,2] = cell[i,0] * cell[i,1] } if (spew) { print("\tget target cell...\n"); } ii = ep[0].index_of("@"); oo = ep[0].index_of("$"); print("index_of @ is %d, index_of $ is %d\n",ii,oo); if (ii > -1) { string rs = ep[0].substring((ii+1)); r = getrefindex(2,dat.length[0],rs,dat); if (spew) { print("\ttarget row: %d (%s)\n",r,rs); } } if (oo > -1) { string cs = ep[0].substring((oo + 1)); c = getrefindex(2,dat.length[1],cs,dat); if (spew) { print("\ttarget col: %d, (%s)\n",c,cs); } } // target is valid if ((r + c) != -2) { // eval a row loop if (c == -1) { print("\tlooping over columns...\n"); for (int i = 0; i < dat.length[1]; i++) { string ie = ep[1]; if (i > 100) { break; } c = i; if (dat[r,c].has_prefix("--") == false) { ie = doelisp(2,r,c,ie,dat); if (ie.contains("@") || ie.contains("$")) { if (ie[0] != '(') { ie = "(%s)".printf(ie); } } ie = domaths(2,r,c,ie,dat); if ( ie.strip() != "") { if (ie.contains(";")) {fm = doformat(0,ie);} else {fm = ie;} if (spew) { print("\tformula changed dat[%d,%d] from \"%s\" to %s\n\n",r,c,dat[r,c],fm); } dat[r,c] = fm; } } } } else { // eval a column loop if (r == -1) { print("\tlooping over rows...\n"); for (int i = 0; i < dat.length[0]; i++) { string ie = ep[1]; if (i > 100) { break; } r = i; if (dat[r,c].has_prefix("--") == false) { ie = doelisp(2,r,c,ie,dat); if (ie.contains("@") || ie.contains("$")) { if (ie[0] != '(') { ie = "(%s)".printf(ie); } } ie = domaths(2,r,c,ie,dat); if ( ie.strip() != "") { if (ie.contains(";")) {fm = doformat(0,ie);} else {fm = ie;} if (spew) { print("\tformula changed dat[%d,%d] from \"%s\" to %s\n\n",r,c,dat[r,c],fm); } dat[r,c] = fm; } } } } else { // eval once for a cell... ep[1] = doelisp(2,r,c,ep[1],dat); if (ep[1].contains("@") || ep[1].contains("$")) { if (ep[1][0] != '(') { ep[1] = "(%s)".printf(ep[1]); } } ep[1] = domaths(2,r,c,ep[1],dat); if ( ep[1].strip() != "") { if (ep[1].contains(";")) {fm = doformat(0,ep[1]);} else {fm = ep[1];} if (spew) { print("\tformula changed dat[%d,%d] from \"%s\" to %s\n\n",r,c,dat[r,c],fm); } dat[r,c] = fm; } } } if (spew) { print("\n%s\n",reorgtable(0,dat)); } if (spew) { print("\n#+TBLFM: %s\n",theformula); } int64 ofmte = GLib.get_real_time(); if (spew) { print("\ntable formula took %f microts\n\n",(((double) (ofmte - ofmts))/1000000.0) ); } } } } } }
#+RESULTS:
orgtodat took 37.000000 microseconds reading formula : @>$4=((vsum(@1$4..@>>>$4) / 1000.0 ) * 20.0);%.2f get target cell... index_of @ is 0, index_of $ is 2 getrefindex: input is >$4 get prev ref (>)... getrefindex: zero-based cell ref is 6 getrefindex: took 7.000000 microseconds target row: 6 (>$4) getrefindex: input is 4 getrefindex: zero-based cell ref is 3 getrefindex: took 3.000000 microseconds target col: 3, (4) tblfm checking expression: ((vsum(@1$4..@>>>$4) / 1000.0 ) * 20.0);%.2f tblfm: inner expression: (@1$4..@>>>$4) dosum: (@1$4..@>>>$4) getrefindex: input is 1$4 getrefindex: zero-based cell ref is 0 getrefindex: took 4.000000 microseconds getrefindex: input is 4 getrefindex: zero-based cell ref is 3 getrefindex: took 3.000000 microseconds dosum: part0 row = 0, col = 3 getrefindex: input is >>>$4. get prev ref (>)... getrefindex: zero-based cell ref is 3 getrefindex: took 4.000000 microseconds getrefindex: input is 4. getrefindex: zero-based cell ref is 3 getrefindex: took 3.000000 microseconds dosum: part1 row = 3, col = 3 dosum: zero-based cell refs... row1=0, col1=3 row2=3, col2=3 vsum = 328.590000 dosum took 30.000000 microseconds tblfm: sum = 328.590000 tblfm: spliced expression = ((328.590000 / 1000.0 ) * 20.0);%.2f tblfm: inner expression: (328.590000 / 1000.0 ) domaths input .....: 328.590000 / 1000.0 domaths expression : 328.590000 / 1000.0 domaths splice ....: 0.328590 domaths took 9.000000 microseconds tblfm: result = 0.328590 tblfm: spliced expression = (0.328590 * 20.0);%.2f tblfm: inner expression: (0.328590 * 20.0) domaths input .....: 0.328590 * 20.0 domaths expression : 0.328590 * 20.0 domaths splice ....: 6.571800 domaths took 5.000000 microseconds tblfm: result = 6.571800 tblfm: spliced expression = 6.571800;%.2f doformat: input is 6.571800;%.2f doformat took 2.000000 microseconds formula changed dat[6,3] from "" to 6.57 reorgtable took 33.000000 microseconds | AA | BB | CC | DD | |--------+-------+--------+--------| | 68.0 | 39.47 | 128.15 | 337.59 | | 403.88 | 16.21 | 117.03 | -9.0 | | 5.8 | 14.73 | 58.1 | 107.64 | |--------+-------+--------+--------| | | | | 6.57 | ,#+TBLFM: @>$4=((vsum(@1$4..@>>>$4) / 1000.0 ) * 20.0);%.2f @>$2='(format "%s_%f" (downcase @1$2) @>>>$1) @>$1='(min @4$2 (max @3 @5)) @>$3=@4$1-((@4$3 / @4$4) + 0.5) @1$2='(concat "2_" @1$2) @1$3 = '(abs @4$4) + '(org-sbe "x") $4=($1*$2);%.2f @1='(concat "[" @1 "]") @3$3='(random 100) @4$3='(mod $< 10) table formula took 0.000192 microts reading formula : @>$2='(format "%s_%f" (downcase @1$2) @>>>$1) get target cell... index_of @ is 0, index_of $ is 2 getrefindex: input is >$2 get prev ref (>)... getrefindex: zero-based cell ref is 6 getrefindex: took 4.000000 microseconds target row: 6 (>$2) getrefindex: input is 2 getrefindex: zero-based cell ref is 1 getrefindex: took 3.000000 microseconds target col: 1, (2) elisp: lisp expression is '(format "%s_%f" (downcase @1$2) @>>>$1) elisp: spliced comma: '(format "%s_%f" (downcase @1$2) @>>>$1) elisp: outer lisp expression is (format "%s_%f" (downcase @1$2) @>>>$1) elisp inner: iteration 0 replacerefs: input is (downcase @1$2) getrefindex: input is 1$2. getrefindex: zero-based cell ref is 0 getrefindex: took 3.000000 microseconds getrefindex: input is 2. getrefindex: zero-based cell ref is 1 getrefindex: took 2.000000 microseconds r = 0, c = 1 replacerefs: spliced expression: (downcase BB) replacerefs took 14.000000 microseconds elisp inner: lisp expression: (downcase BB) evallisp: input is (downcase BB) downcase... evallisp downcase took 8.000000 microseconds elisp inner: spliced expression = (format %s_%f bb @>>>$1) elisp inner: iteration 1 replacerefs: input is (format %s_%f bb @>>>$1) getrefindex: input is >>>$1. get prev ref (>)... getrefindex: zero-based cell ref is 3 getrefindex: took 5.000000 microseconds getrefindex: input is 1. getrefindex: zero-based cell ref is 0 getrefindex: took 3.000000 microseconds r = 3, c = 0 replacerefs: spliced expression: (format %s_%f bb 403.88) replacerefs took 16.000000 microseconds elisp inner: lisp expression: (format %s_%f bb 403.88) evallisp: input is (format %s_%f bb 403.88) format... getting tokens in %s_%f spliced format: bb_%%f spliced format: bb_403.88 evallisp format took 10.000000 microseconds elisp inner: spliced expression = bb_403.88 tblfm checking expression: bb_403.88 formula changed dat[6,1] from "" to bb_403.88 reorgtable took 31.000000 microseconds | AA | BB | CC | DD | |--------+------------+--------+--------| | 68.0 | 39.47 | 128.15 | 337.59 | | 403.88 | 16.21 | 117.03 | -9.0 | | 5.8 | 14.73 | 58.1 | 107.64 | |--------+------------+--------+--------| | | bb_403.88 | | 6.57 | ,#+TBLFM: @>$4=((vsum(@1$4..@>>>$4) / 1000.0 ) * 20.0);%.2f @>$2='(format "%s_%f" (downcase @1$2) @>>>$1) @>$1='(min @4$2 (max @3 @5)) @>$3=@4$1-((@4$3 / @4$4) + 0.5) @1$2='(concat "2_" @1$2) @1$3 = '(abs @4$4) + '(org-sbe "x") $4=($1*$2);%.2f @1='(concat "[" @1 "]") @3$3='(random 100) @4$3='(mod $< 10) table formula took 0.000311 microts reading formula : @>$1='(min @4$2 (max @3 @5)) get target cell... index_of @ is 0, index_of $ is 2 getrefindex: input is >$1 get prev ref (>)... getrefindex: zero-based cell ref is 6 getrefindex: took 3.000000 microseconds target row: 6 (>$1) getrefindex: input is 1 getrefindex: zero-based cell ref is 0 getrefindex: took 2.000000 microseconds target col: 0, (1) elisp: lisp expression is '(min @4$2 (max @3 @5)) elisp: spliced comma: '(min @4$2 (max @3 @5)) elisp: outer lisp expression is (min @4$2 (max @3 @5)) elisp inner: iteration 0 replacerefs: input is (max @3 @5) getrefindex: input is 3.@5. getrefindex: zero-based cell ref is 2 getrefindex: took 2.000000 microseconds r = 2, c = 0 replacerefs: spliced expression: (max 68.0 @5) getrefindex: input is 5. getrefindex: zero-based cell ref is 4 getrefindex: took 2.000000 microseconds r = 4, c = 0 replacerefs: spliced expression: (max 68.0 5.8) replacerefs took 12.000000 microseconds elisp inner: lisp expression: (max 68.0 5.8) evallisp: input is (max 68.0 5.8) max... evallisp took 6.000000 microseconds elisp inner: spliced expression = (min @4$2 68.000000) elisp inner: iteration 1 replacerefs: input is (min @4$2 68.000000) getrefindex: input is 4$2.68.000000. getrefindex: zero-based cell ref is 3 getrefindex: took 3.000000 microseconds getrefindex: input is 2.68.000000. getrefindex: zero-based cell ref is 1 getrefindex: took 3.000000 microseconds r = 3, c = 1 replacerefs: spliced expression: (min 16.21 68.000000) replacerefs took 12.000000 microseconds elisp inner: lisp expression: (min 16.21 68.000000) evallisp: input is (min 16.21 68.000000) min... evallisp took 6.000000 microseconds elisp inner: spliced expression = 16.210000 tblfm checking expression: 16.210000 formula changed dat[6,0] from "" to 16.210000 reorgtable took 30.000000 microseconds | AA | BB | CC | DD | |------------+------------+--------+--------| | 68.0 | 39.47 | 128.15 | 337.59 | | 403.88 | 16.21 | 117.03 | -9.0 | | 5.8 | 14.73 | 58.1 | 107.64 | |------------+------------+--------+--------| | 16.210000 | bb_403.88 | | 6.57 | ,#+TBLFM: @>$4=((vsum(@1$4..@>>>$4) / 1000.0 ) * 20.0);%.2f @>$2='(format "%s_%f" (downcase @1$2) @>>>$1) @>$1='(min @4$2 (max @3 @5)) @>$3=@4$1-((@4$3 / @4$4) + 0.5) @1$2='(concat "2_" @1$2) @1$3 = '(abs @4$4) + '(org-sbe "x") $4=($1*$2);%.2f @1='(concat "[" @1 "]") @3$3='(random 100) @4$3='(mod $< 10) table formula took 0.000411 microts reading formula : @>$3=@4$1-((@4$3 / @4$4) + 0.5) get target cell... index_of @ is 0, index_of $ is 2 getrefindex: input is >$3 get prev ref (>)... getrefindex: zero-based cell ref is 6 getrefindex: took 3.000000 microseconds target row: 6 (>$3) getrefindex: input is 3 getrefindex: zero-based cell ref is 2 getrefindex: took 3.000000 microseconds target col: 2, (3) tblfm checking expression: (@4$1-((@4$3 / @4$4) + 0.5)) tblfm: inner expression: (@4$3 / @4$4) domaths input .....: @4$3 / @4$4 replacerefs: input is @4$3 / @4$4 getrefindex: input is 4$3...@4$4 getrefindex: zero-based cell ref is 3 getrefindex: took 3.000000 microseconds getrefindex: input is 3...@4$4 getrefindex: zero-based cell ref is 2 getrefindex: took 3.000000 microseconds r = 3, c = 2 replacerefs: spliced expression: 117.03 / @4$4 getrefindex: input is 4$4 getrefindex: zero-based cell ref is 3 getrefindex: took 3.000000 microseconds getrefindex: input is 4 getrefindex: zero-based cell ref is 3 getrefindex: took 3.000000 microseconds r = 3, c = 3 replacerefs: spliced expression: 117.03 / -9.04 replacerefs took 22.000000 microseconds subminus took 1.000000 microseconds domaths expression : 117.03 / -9.04 domaths splice ....: -12.945796 domaths took 33.000000 microseconds tblfm: result = -12.945796 tblfm: spliced expression = (@4$1-(-12.945796 + 0.5)) tblfm: inner expression: (-12.945796 + 0.5) domaths input .....: -12.945796 + 0.5 subminus took 1.000000 microseconds domaths expression : -12.945796 + 0.5 domaths splice ....: -12.445796 domaths took 9.000000 microseconds tblfm: result = -12.445796 tblfm: spliced expression = (@4$1- -12.445796) tblfm: inner expression: (@4$1- -12.445796) domaths input .....: @4$1- -12.445796 replacerefs: input is @4$1- -12.445796 getrefindex: input is 4$1...12.445796 getrefindex: zero-based cell ref is 3 getrefindex: took 4.000000 microseconds getrefindex: input is 1...12.445796 getrefindex: zero-based cell ref is 0 getrefindex: took 3.000000 microseconds r = 3, c = 0 replacerefs: spliced expression: 403.88- -12.445796 replacerefs took 13.000000 microseconds subminus took 1.000000 microseconds domaths expression : 403.88! -12.445796 domaths splice ....: 416.325796 domaths took 23.000000 microseconds tblfm: result = 416.325796 tblfm: spliced expression = 416.325796 formula changed dat[6,2] from "" to 416.325796 reorgtable took 30.000000 microseconds | AA | BB | CC | DD | |------------+------------+------------+--------| | 68.0 | 39.47 | 128.15 | 337.59 | | 403.88 | 16.21 | 117.03 | -9.0 | | 5.8 | 14.73 | 58.1 | 107.64 | |------------+------------+------------+--------| | 16.210000 | bb_403.88 | 416.325796 | 6.57 | ,#+TBLFM: @>$4=((vsum(@1$4..@>>>$4) / 1000.0 ) * 20.0);%.2f @>$2='(format "%s_%f" (downcase @1$2) @>>>$1) @>$1='(min @4$2 (max @3 @5)) @>$3=@4$1-((@4$3 / @4$4) + 0.5) @1$2='(concat "2_" @1$2) @1$3 = '(abs @4$4) + '(org-sbe "x") $4=($1*$2);%.2f @1='(concat "[" @1 "]") @3$3='(random 100) @4$3='(mod $< 10) table formula took 0.000546 microts reading formula : @1$2='(concat "2_" @1$2) get target cell... index_of @ is 0, index_of $ is 2 getrefindex: input is 1$2 getrefindex: zero-based cell ref is 0 getrefindex: took 4.000000 microseconds target row: 0 (1$2) getrefindex: input is 2 getrefindex: zero-based cell ref is 1 getrefindex: took 3.000000 microseconds target col: 1, (2) elisp: lisp expression is '(concat "2_" @1$2) elisp: spliced comma: '(concat "2_" @1$2) elisp: outer lisp expression is (concat "2_" @1$2) elisp inner: iteration 0 replacerefs: input is (concat "2_" @1$2) getrefindex: input is 1$2. getrefindex: zero-based cell ref is 0 getrefindex: took 3.000000 microseconds getrefindex: input is 2. getrefindex: zero-based cell ref is 1 getrefindex: took 5.000000 microseconds r = 0, c = 1 replacerefs: spliced expression: (concat "2_" BB) replacerefs took 17.000000 microseconds elisp inner: lisp expression: (concat "2_" BB) evallisp: input is (concat "2_" BB) concat... evallisp concat took 8.000000 microseconds elisp inner: spliced expression = 2_BB tblfm checking expression: 2_BB formula changed dat[0,1] from "BB" to 2_BB reorgtable took 36.000000 microseconds | AA | 2_BB | CC | DD | |------------+------------+------------+--------| | 68.0 | 39.47 | 128.15 | 337.59 | | 403.88 | 16.21 | 117.03 | -9.0 | | 5.8 | 14.73 | 58.1 | 107.64 | |------------+------------+------------+--------| | 16.210000 | bb_403.88 | 416.325796 | 6.57 | ,#+TBLFM: @>$4=((vsum(@1$4..@>>>$4) / 1000.0 ) * 20.0);%.2f @>$2='(format "%s_%f" (downcase @1$2) @>>>$1) @>$1='(min @4$2 (max @3 @5)) @>$3=@4$1-((@4$3 / @4$4) + 0.5) @1$2='(concat "2_" @1$2) @1$3 = '(abs @4$4) + '(org-sbe "x") $4=($1*$2);%.2f @1='(concat "[" @1 "]") @3$3='(random 100) @4$3='(mod $< 10) table formula took 0.000648 microts reading formula : @1$3 = '(abs @4$4) + '(org-sbe "x") get target cell... index_of @ is 0, index_of $ is 2 getrefindex: input is 1$3 getrefindex: zero-based cell ref is 0 getrefindex: took 3.000000 microseconds target row: 0 (1$3) getrefindex: input is 3 getrefindex: zero-based cell ref is 2 getrefindex: took 3.000000 microseconds target col: 2, (3) elisp: lisp expression is '(abs @4$4) + '(org-sbe "x") elisp: spliced comma: '(abs @4$4) + '(org-sbe "x") elisp: outer lisp expression is (abs @4$4) elisp inner: iteration 0 replacerefs: input is (abs @4$4) getrefindex: input is 4$4. getrefindex: zero-based cell ref is 3 getrefindex: took 4.000000 microseconds getrefindex: input is 4. getrefindex: zero-based cell ref is 3 getrefindex: took 4.000000 microseconds r = 3, c = 3 replacerefs: spliced expression: (abs -9.0) replacerefs took 16.000000 microseconds elisp inner: lisp expression: (abs -9.0) evallisp: input is (abs -9.0) abs... evallisp abs took 6.000000 microseconds elisp inner: spliced expression = 9.000000 elisp: lisp expression is '(abs @4$4) + '(org-sbe "x") elisp: spliced comma: '(abs @4$4) + '(org-sbe "x") elisp: outer lisp expression is (abs @4$4) elisp inner: iteration 0 replacerefs: input is (abs @4$4) getrefindex: input is 4$4. getrefindex: zero-based cell ref is 3 getrefindex: took 3.000000 microseconds getrefindex: input is 4. getrefindex: zero-based cell ref is 3 getrefindex: took 3.000000 microseconds r = 3, c = 3 replacerefs: spliced expression: (abs -9.0) replacerefs took 14.000000 microseconds elisp inner: lisp expression: (abs -9.0) evallisp: input is (abs -9.0) abs... evallisp abs took 5.000000 microseconds elisp inner: spliced expression = 9.000000 elisp: lisp expression is '(abs @4$4) + '(org-sbe "x") elisp: spliced comma: '(abs @4$4) + '(org-sbe "x") elisp: outer lisp expression is (abs @4$4) elisp inner: iteration 0 replacerefs: input is (abs @4$4) getrefindex: input is 4$4. getrefindex: zero-based cell ref is 3 getrefindex: took 5.000000 microseconds getrefindex: input is 4. getrefindex: zero-based cell ref is 3 getrefindex: took 2.000000 microseconds r = 3, c = 3 replacerefs: spliced expression: (abs -9.0) replacerefs took 13.000000 microseconds elisp inner: lisp expression: (abs -9.0) evallisp: input is (abs -9.0) abs... evallisp abs took 4.000000 microseconds elisp inner: spliced expression = 9.000000 tblfm checking expression: 9.000000(org-sbe "x") tblfm: inner expression: (org-sbe "x") domaths input .....: org-sbe "x" subminus took 1.000000 microseconds domaths expression : org -sbe "x" domaths took 5.000000 microseconds tblfm: result = org -sbe "x" tblfm: spliced expression = 9.000000org -sbe "x" formula changed dat[0,2] from "CC" to 9.000000org -sbe "x" reorgtable took 31.000000 microseconds | AA | 2_BB | 9.000000org -sbe "x" | DD | |------------+------------+-----------------------+--------| | 68.0 | 39.47 | 128.15 | 337.59 | | 403.88 | 16.21 | 117.03 | -9.0 | | 5.8 | 14.73 | 58.1 | 107.64 | |------------+------------+-----------------------+--------| | 16.210000 | bb_403.88 | 416.325796 | 6.57 | ,#+TBLFM: @>$4=((vsum(@1$4..@>>>$4) / 1000.0 ) * 20.0);%.2f @>$2='(format "%s_%f" (downcase @1$2) @>>>$1) @>$1='(min @4$2 (max @3 @5)) @>$3=@4$1-((@4$3 / @4$4) + 0.5) @1$2='(concat "2_" @1$2) @1$3 = '(abs @4$4) + '(org-sbe "x") $4=($1*$2);%.2f @1='(concat "[" @1 "]") @3$3='(random 100) @4$3='(mod $< 10) table formula took 0.000806 microts reading formula : $4=($1*$2);%.2f get target cell... index_of @ is -1, index_of $ is 0 getrefindex: input is 4 getrefindex: zero-based cell ref is 3 getrefindex: took 3.000000 microseconds target col: 3, (4) looping over rows... tblfm checking expression: ($1*$2);%.2f tblfm: inner expression: ($1*$2) domaths input .....: $1*$2 replacerefs: input is $1*$2 getrefindex: input is 1.$2 getrefindex: zero-based cell ref is 0 getrefindex: took 3.000000 microseconds r = 0, c = 0 replacerefs: spliced expression: AA*$2 getrefindex: input is 2 getrefindex: zero-based cell ref is 1 getrefindex: took 3.000000 microseconds r = 0, c = 1 replacerefs: spliced expression: AA* 2_BB2 replacerefs took 14.000000 microseconds domaths expression : AA* 2_BB2 ERROR: __ or _2___2 are not float domaths took 21.000000 microseconds tblfm: result = AA* 2_BB2 tblfm: spliced expression = AA* 2_BB2;%.2f doformat: input is AA* 2_BB2;%.2f doformat took 2.000000 microseconds formula changed dat[0,3] from "DD" to 0.00 tblfm checking expression: ($1*$2);%.2f tblfm: inner expression: ($1*$2) domaths input .....: $1*$2 replacerefs: input is $1*$2 getrefindex: input is 1.$2 getrefindex: zero-based cell ref is 0 getrefindex: took 2.000000 microseconds r = 2, c = 0 replacerefs: spliced expression: 68.0*$2 getrefindex: input is 2 getrefindex: zero-based cell ref is 1 getrefindex: took 2.000000 microseconds r = 2, c = 1 replacerefs: spliced expression: 68.0*39.472 replacerefs took 15.000000 microseconds domaths expression : 68.0*39.472 domaths splice ....: 2684.096000 domaths took 22.000000 microseconds tblfm: result = 2684.096000 tblfm: spliced expression = 2684.096000;%.2f doformat: input is 2684.096000;%.2f doformat took 2.000000 microseconds formula changed dat[2,3] from "337.59" to 2684.10 tblfm checking expression: ($1*$2);%.2f tblfm: inner expression: ($1*$2) domaths input .....: $1*$2 replacerefs: input is $1*$2 getrefindex: input is 1.$2 getrefindex: zero-based cell ref is 0 getrefindex: took 3.000000 microseconds r = 3, c = 0 replacerefs: spliced expression: 403.88*$2 getrefindex: input is 2 getrefindex: zero-based cell ref is 1 getrefindex: took 3.000000 microseconds r = 3, c = 1 replacerefs: spliced expression: 403.88*16.212 replacerefs took 14.000000 microseconds domaths expression : 403.88*16.212 domaths splice ....: 6547.702560 domaths took 20.000000 microseconds tblfm: result = 6547.702560 tblfm: spliced expression = 6547.702560;%.2f doformat: input is 6547.702560;%.2f doformat took 2.000000 microseconds formula changed dat[3,3] from "-9.0" to 6547.70 tblfm checking expression: ($1*$2);%.2f tblfm: inner expression: ($1*$2) domaths input .....: $1*$2 replacerefs: input is $1*$2 getrefindex: input is 1.$2 getrefindex: zero-based cell ref is 0 getrefindex: took 3.000000 microseconds r = 4, c = 0 replacerefs: spliced expression: 5.8*$2 getrefindex: input is 2 getrefindex: zero-based cell ref is 1 getrefindex: took 2.000000 microseconds r = 4, c = 1 replacerefs: spliced expression: 5.8*14.732 replacerefs took 13.000000 microseconds domaths expression : 5.8*14.732 domaths splice ....: 85.445600 domaths took 19.000000 microseconds tblfm: result = 85.445600 tblfm: spliced expression = 85.445600;%.2f doformat: input is 85.445600;%.2f doformat took 2.000000 microseconds formula changed dat[4,3] from "107.64" to 85.45 tblfm checking expression: ($1*$2);%.2f tblfm: inner expression: ($1*$2) domaths input .....: $1*$2 replacerefs: input is $1*$2 getrefindex: input is 1.$2 getrefindex: zero-based cell ref is 0 getrefindex: took 3.000000 microseconds r = 6, c = 0 replacerefs: spliced expression: 16.210000*$2 getrefindex: input is 2 getrefindex: zero-based cell ref is 1 getrefindex: took 2.000000 microseconds r = 6, c = 1 replacerefs: spliced expression: 16.210000* bb_403.882 replacerefs took 13.000000 microseconds domaths expression : 16.210000* bb_403.882 domaths splice ....: 6546.927220 domaths took 20.000000 microseconds tblfm: result = 6546.927220 tblfm: spliced expression = 6546.927220;%.2f doformat: input is 6546.927220;%.2f doformat took 2.000000 microseconds formula changed dat[6,3] from "6.57" to 6546.93 reorgtable took 31.000000 microseconds | AA | 2_BB | 9.000000org -sbe "x" | 0.00 | |------------+------------+-----------------------+---------| | 68.0 | 39.47 | 128.15 | 2684.10 | | 403.88 | 16.21 | 117.03 | 6547.70 | | 5.8 | 14.73 | 58.1 | 85.45 | |------------+------------+-----------------------+---------| | 16.210000 | bb_403.88 | 416.325796 | 6546.93 | ,#+TBLFM: @>$4=((vsum(@1$4..@>>>$4) / 1000.0 ) * 20.0);%.2f @>$2='(format "%s_%f" (downcase @1$2) @>>>$1) @>$1='(min @4$2 (max @3 @5)) @>$3=@4$1-((@4$3 / @4$4) + 0.5) @1$2='(concat "2_" @1$2) @1$3 = '(abs @4$4) + '(org-sbe "x") $4=($1*$2);%.2f @1='(concat "[" @1 "]") @3$3='(random 100) @4$3='(mod $< 10) table formula took 0.001008 microts reading formula : @1='(concat "[" @1 "]") get target cell... index_of @ is 0, index_of $ is -1 getrefindex: input is 1 getrefindex: zero-based cell ref is 0 getrefindex: took 3.000000 microseconds target row: 0 (1) looping over columns... elisp: lisp expression is '(concat "[" @1 "]") elisp: spliced comma: '(concat "[" @1 "]") elisp: outer lisp expression is (concat "[" @1 "]") elisp inner: iteration 0 replacerefs: input is (concat "[" @1 "]") getrefindex: input is 1..... getrefindex: zero-based cell ref is 0 getrefindex: took 3.000000 microseconds r = 0, c = 0 replacerefs: spliced expression: (concat "[" AA "]") replacerefs took 9.000000 microseconds elisp inner: lisp expression: (concat "[" AA "]") evallisp: input is (concat "[" AA "]") concat... evallisp concat took 8.000000 microseconds elisp inner: spliced expression = [AA] tblfm checking expression: [AA] formula changed dat[0,0] from "AA" to [AA] elisp: lisp expression is '(concat "[" @1 "]") elisp: spliced comma: '(concat "[" @1 "]") elisp: outer lisp expression is (concat "[" @1 "]") elisp inner: iteration 0 replacerefs: input is (concat "[" @1 "]") getrefindex: input is 1..... getrefindex: zero-based cell ref is 0 getrefindex: took 3.000000 microseconds r = 0, c = 1 replacerefs: spliced expression: (concat "[" 2_BB "]") replacerefs took 10.000000 microseconds elisp inner: lisp expression: (concat "[" 2_BB "]") evallisp: input is (concat "[" 2_BB "]") concat... evallisp concat took 7.000000 microseconds elisp inner: spliced expression = [2_BB] tblfm checking expression: [2_BB] formula changed dat[0,1] from " 2_BB" to [2_BB] elisp: lisp expression is '(concat "[" @1 "]") elisp: spliced comma: '(concat "[" @1 "]") elisp: outer lisp expression is (concat "[" @1 "]") elisp inner: iteration 0 replacerefs: input is (concat "[" @1 "]") getrefindex: input is 1..... getrefindex: zero-based cell ref is 0 getrefindex: took 3.000000 microseconds r = 0, c = 2 replacerefs: spliced expression: (concat "[" 9.000000org -sbe "x" "]") replacerefs took 9.000000 microseconds elisp inner: lisp expression: (concat "[" 9.000000org -sbe "x" "]") evallisp: input is (concat "[" 9.000000org -sbe "x" "]") concat... evallisp concat took 9.000000 microseconds elisp inner: spliced expression = [9.000000org-sbex] tblfm checking expression: [9.000000org-sbex] formula changed dat[0,2] from " 9.000000org -sbe "x"" to [9.000000org-sbex] elisp: lisp expression is '(concat "[" @1 "]") elisp: spliced comma: '(concat "[" @1 "]") elisp: outer lisp expression is (concat "[" @1 "]") elisp inner: iteration 0 replacerefs: input is (concat "[" @1 "]") getrefindex: input is 1..... getrefindex: zero-based cell ref is 0 getrefindex: took 3.000000 microseconds r = 0, c = 3 replacerefs: spliced expression: (concat "[" 0.00 "]") replacerefs took 10.000000 microseconds elisp inner: lisp expression: (concat "[" 0.00 "]") evallisp: input is (concat "[" 0.00 "]") concat... evallisp concat took 7.000000 microseconds elisp inner: spliced expression = [0.00] tblfm checking expression: [0.00] formula changed dat[0,3] from "0.00" to [0.00] reorgtable took 32.000000 microseconds | [AA] | [2_BB] | [9.000000org-sbex] | [0.00] | |------------+------------+---------------------+---------| | 68.0 | 39.47 | 128.15 | 2684.10 | | 403.88 | 16.21 | 117.03 | 6547.70 | | 5.8 | 14.73 | 58.1 | 85.45 | |------------+------------+---------------------+---------| | 16.210000 | bb_403.88 | 416.325796 | 6546.93 | ,#+TBLFM: @>$4=((vsum(@1$4..@>>>$4) / 1000.0 ) * 20.0);%.2f @>$2='(format "%s_%f" (downcase @1$2) @>>>$1) @>$1='(min @4$2 (max @3 @5)) @>$3=@4$1-((@4$3 / @4$4) + 0.5) @1$2='(concat "2_" @1$2) @1$3 = '(abs @4$4) + '(org-sbe "x") $4=($1*$2);%.2f @1='(concat "[" @1 "]") @3$3='(random 100) @4$3='(mod $< 10) table formula took 0.001170 microts reading formula : @3$3='(random 100) get target cell... index_of @ is 0, index_of $ is 2 getrefindex: input is 3$3 getrefindex: zero-based cell ref is 2 getrefindex: took 3.000000 microseconds target row: 2 (3$3) getrefindex: input is 3 getrefindex: zero-based cell ref is 2 getrefindex: took 3.000000 microseconds target col: 2, (3) elisp: lisp expression is '(random 100) elisp: spliced comma: '(random 100) elisp: outer lisp expression is (random 100) elisp inner: iteration 0 elisp inner: lisp expression: (random 100) evallisp: input is (random 100) rand... evallisp random took 39.000000 microseconds elisp inner: spliced expression = 72 tblfm checking expression: 72 formula changed dat[2,2] from "128.15" to 72 reorgtable took 35.000000 microseconds | [AA] | [2_BB] | [9.000000org-sbex] | [0.00] | |------------+------------+---------------------+---------| | 68.0 | 39.47 | 72 | 2684.10 | | 403.88 | 16.21 | 117.03 | 6547.70 | | 5.8 | 14.73 | 58.1 | 85.45 | |------------+------------+---------------------+---------| | 16.210000 | bb_403.88 | 416.325796 | 6546.93 | ,#+TBLFM: @>$4=((vsum(@1$4..@>>>$4) / 1000.0 ) * 20.0);%.2f @>$2='(format "%s_%f" (downcase @1$2) @>>>$1) @>$1='(min @4$2 (max @3 @5)) @>$3=@4$1-((@4$3 / @4$4) + 0.5) @1$2='(concat "2_" @1$2) @1$3 = '(abs @4$4) + '(org-sbe "x") $4=($1*$2);%.2f @1='(concat "[" @1 "]") @3$3='(random 100) @4$3='(mod $< 10) table formula took 0.001281 microts reading formula : @4$3='(mod $< 10) get target cell... index_of @ is 0, index_of $ is 2 getrefindex: input is 4$3 getrefindex: zero-based cell ref is 3 getrefindex: took 3.000000 microseconds target row: 3 (4$3) getrefindex: input is 3 getrefindex: zero-based cell ref is 2 getrefindex: took 3.000000 microseconds target col: 2, (3) elisp: lisp expression is '(mod $< 10) elisp: spliced comma: '(mod $< 10) elisp: outer lisp expression is (mod $< 10) elisp inner: iteration 0 replacerefs: input is (mod $< 10) getrefindex: input is <.10. get next ref (<)... getrefindex: zero-based cell ref is 3 getrefindex: took 5.000000 microseconds r = 3, c = 3 replacerefs: spliced expression: (mod 6547.70 10) replacerefs took 11.000000 microseconds elisp inner: lisp expression: (mod 6547.70 10) evallisp: input is (mod 6547.70 10) mod... fmod(6547.700000,10.000000) evallisp fmod took 10.000000 microseconds elisp inner: spliced expression = 7.700000 tblfm checking expression: 7.700000 formula changed dat[3,2] from "117.03" to 7.700000 reorgtable took 33.000000 microseconds | [AA] | [2_BB] | [9.000000org-sbex] | [0.00] | |------------+------------+---------------------+---------| | 68.0 | 39.47 | 72 | 2684.10 | | 403.88 | 16.21 | 7.700000 | 6547.70 | | 5.8 | 14.73 | 58.1 | 85.45 | |------------+------------+---------------------+---------| | 16.210000 | bb_403.88 | 416.325796 | 6546.93 | ,#+TBLFM: @>$4=((vsum(@1$4..@>>>$4) / 1000.0 ) * 20.0);%.2f @>$2='(format "%s_%f" (downcase @1$2) @>>>$1) @>$1='(min @4$2 (max @3 @5)) @>$3=@4$1-((@4$3 / @4$4) + 0.5) @1$2='(concat "2_" @1$2) @1$3 = '(abs @4$4) + '(org-sbe "x") $4=($1*$2);%.2f @1='(concat "[" @1 "]") @3$3='(random 100) @4$3='(mod $< 10) table formula took 0.001370 microts
MONO:fluff:
SPACE
| FONT            | SERIF | CODE        | PROSE       | TABLE   | PLOT   | UNICODE  | NOTE           |
|-----------------+-------+-------------+-------------+---------+--------+----------+----------------|
| ADWAITA         | NO    | OK          | OK          | V-GAPS  | OK     | ALMOST   | allgood        |
| JULIA MONO      | NO    | OK          | OK          | SOLID-V | OK     | ALMOST   | allgood        |
| APORETIC S MONO | SEMI  | OK          | BIT CRAMPED | OK      | OK     | ALMOST   | allgood        |
| APORETIC MONO   | NO    | OK          | BIT CRAMPED | OK      | OK     | ALMOST   | allgood        |
| APL 386         | NO    | GREAT       | WIDE        | V-GAPS  | OK     | NOT MONO | use for code   |
| FIRA CODE       | SEMI  | ASSUMPTIONS | OK          | OK      | GREAT  | NOT MONO | use for tables |
| LUXI MONO       | VERY  | OK          | GREAT       | OK      | V-GAPS | NOT MONO | use for prose  |
| IBM PLEX MONO   | SEMI  | OK          | OK          | V-GAPS  | V-GAPS | NOT MONO |                |
| JETBRAINS MONO  | NO    | OK          | TALL CAPS   | HV-GAPS | OK     | NOT MONO |                |
| LIBERATION MONO | NO    | OK          | SHORT       | H-GAPS  | OK     | NOT MONO |                |
| NOTO SANS MONO  | SEMI  | OK          | V-GAPS      | HV-GAPS | V-GAPS | NOT MONO |                |
| INTEL ONE MONO  | SEMI  | SHORT       | SHORT       | HV-GAPS | OK     | NOT MONO |                |
| NIMBUS PS MONO  | YES   | HEAVY ',;'  | OK          | SOLID-V | V-GAPS | NOT MONO |                |
| SOURCE CODE PRO | NO    | OK          | SHORT       | OK      | HEAVY  | NOT MONO |                |
| MONOID          | NO    | OK          | TALL        | OK      | V-GAPS | NOT MONO | scale down     |
| KURINTO MONO    | SEMI  | OK          | OK          | H-GAPS  | OK     | NOT MONO |                |
| OVERPASS MONO   | SEMI  | OK          | BIT SHORT   | SOLID-V | V-GAPS | NOT MONO |                |
| EVERSON MONO    | NO    | CRAMPED     | CRAMPED     | V-GAPS  | V-GAPS | ALMOST   |                |

Adwaita Mono and Julia Mono had the least issues with this orgfile in Emacs, with the latter being slightly busier, also with distracting solid vertical lines in tables ('|').
I liked the look of APL-386 for code, however it couldn't correctly render keyboards in AANTEE below, and found it a little too wide for prose.

Not mono but tested anyway:
| FONT     | SERIF | CODE   | PROSE | TABLE | PLOT   | UNICODE  | NOTE                |
|----------+-------+--------+-------+-------+--------+----------+---------------------|
| SQUARISH | NO    | ISSUES | SHORT | WONKY | V-GAPS | NOT MONO | looks great in caps |
AANTEE:fluff::wip:

FNETIK SPELIJ OX ANTIPYDEEYN IJGLIC IUUSIJ UWNLI VNDYFAISD LATN ALFVBET (US-ASCII). RVFLI BAISD ON 'IPA', WIQ SVM TCEETS.
AANTEE WOZ MAID IN ANGV: DQ OLDV UI GET, DQ MOO VNOIJ IJGLIC SPELIJ HAZ BIKVM. UIM SLUWLI VDOPTIJ AANTEE FOO MUI UWN NUWTS, WITC WIL INKREESIJLEE VPIV ELSWEV IN DQIS DOKIUUMYNT UWXV TAIM.

|----+----+---------------------------+-----------------------------------------|
| iː | EE | feet leak eat free        | should be 'II', but 'II' is for 'yi'    |
|    |    | FEET LEEK EET FREE        | CWD BEE 'II', BVT 'II' IS FOO 'yi'      |
|----+----+---------------------------+-----------------------------------------|
| ɪ  | I  | fit little inch thirty    |                                         |
|    |    | FIT LITL   INTC QYYTI     |                                         |
|----+----+---------------------------+-----------------------------------------|
| j  | I  | few  lanyard yellow       | 'y' sounds are made by  prefixing  'I'  |
|    |    | FIUU LANIVVD IELUW        | 'y' SAWNS  VV  MAID BUI PREEFIKSIJ 'I'  |
|----+----+---------------------------+-----------------------------------------|
| ɪʌ | IV | fear leer ear             |                                         |
|    |    | FIV  LIV  IV              |                                         |
|----+----+---------------------------+-----------------------------------------|
| ɛ  | E  | fed let expresso          |                                         |
|    |    | FED LED EKSPRESUW         |                                         |
|----+----+---------------------------+-----------------------------------------|
| ɛː | EH | Fair lair air aerosol     | 'EH' & 'EV' are mostly   interchangable |
|    |    | FEH  LEH  EH  EHRYSOL     | 'EH' & 'EV' VV  MUWSTLEE INTVTCAINDCYBL |
|----+----+---------------------------+-----------------------------------------|
| ɛʌ | EV | fair lair air             | 'EH' & 'EV' are mostly   interchangable |
|    |    | FEV  LEV  EV              | 'EH' & 'EV' VV  MUWSTLEE INTVTCAINDCYBL |
|----+----+---------------------------+-----------------------------------------|
| ə  | Y  | forget lacerate enrage    |                                         |
|    |    | FYGET  LASYRAIT YNRAIDC   |                                         |
|----+----+---------------------------+-----------------------------------------|
| ɜː | YY | fur lurk earth err        |                                         |
|    |    | FYY LYYK YYQ   YY         |                                         |
|----+----+---------------------------+-----------------------------------------|
| æ  | A  | fat lad attic attack      |                                         |
|    |    | FAT LAD ATIK  VTAK        |                                         |
|----+----+---------------------------+-----------------------------------------|
| æː | AA | fan  lamb answer          |                                         |
|    |    | FAAN LAAM AANSV           |                                         |
|----+----+---------------------------+-----------------------------------------|
| æʊ | AW | found loud owl            |                                         |
|    |    | FAWND LAWD AWL            |                                         |
|----+----+---------------------------+-----------------------------------------|
| æɪ | AI | fate late april MAY       |                                         |
|    |    | FAIT LAIT AIPRL MAI       |                                         |
|----+----+---------------------------+-----------------------------------------|
| ʌ  | V  | fun luck another          |                                         |
|    |    | FVN LVK  VNVDQV           |                                         |
|----+----+---------------------------+-----------------------------------------|
| ɐː | VV | fart laugh arbitrate      |                                         |
|    |    | FVVT LVVF  VVBITRAIT      |                                         |
|----+----+---------------------------+-----------------------------------------|
| ?? | UI | fight light island bye    | no  correct IPA  found for this sound   |
|    |    | FUIT  LUIT  UILND  BUI    | NUW KREKT  'IPA' FAWND FOO DQIS SAWND   |
|----+----+---------------------------+-----------------------------------------|
| ?? | UW | flow know own             | no  correct IPA  found for this sound   |
|    |    | FLUW NUW  UWN             | NUW KREKT  'IPA' FAWND FOO DQIS SAWND   |
|----+----+---------------------------+-----------------------------------------|
| ɔ  | O  | fog lot on old operate    |                                         |
|    |    | FOG LOT ON OWD OPYRAIT    |                                         |
|----+----+---------------------------+-----------------------------------------|
| ɔː | OO | fall lore autobot  naught |                                         |
|    |    | FOOL LOO  OOTUWBOT NOOT   |                                         |
|----+----+---------------------------+-----------------------------------------|
| ɔɪ | OI | foil loin oil annoy       |                                         |
|    |    | FOIL LOIN OIL VNOI        |                                         |
|----+----+---------------------------+-----------------------------------------|
| ʊ  | W  | foot look oops whoops     | W is also   used  to  make 'w' sounds   |
|    |    | FWT  LWK  WPS  WWPS       | W IS OOLSUW IUUSD TUU MAIK 'w' SAWNS    |
|----+----+---------------------------+-----------------------------------------|
| ʉː | UU | food lose uber woo        |                                         |
|    |    | FUUD LUUS UUBV WUU        |                                         |
|----+----+---------------------------+-----------------------------------------|
| ʃ  | C  | fish lash shoe            | C is freed by  correct use  of K and S  |
|    |    | FIC  LAC  CUU             | C IS FREED BUI KYREKT  IUUS OF K AND S  |
|----+----+---------------------------+-----------------------------------------|
| ʧ  | TC | fetch latch chair         |                                         |
|    |    | FETC  LATC  TCEV          |                                         |
|----+----+---------------------------+-----------------------------------------|
| ʤ  | DC | fudge lodge jump  enjoy   |                                         |
|    |    | FVDC  LODC  DCVMP ENDCOI  |                                         |
|----+----+---------------------------+-----------------------------------------|
| ʒ  | ZC | fusion  luge  regime      |                                         |
|    |    | FIUUZCN LUUZC RAIZCEEM    |                                         |
|----+----+---------------------------+-----------------------------------------|
| θ  | Q  | fifth length three        | Q resembles θ                           |
|    |    | FIQ   LEJQ   QREE         | Q RYZEMBLS θ                            |
|----+----+---------------------------+-----------------------------------------|
| ð  | DQ | bother mother the width   | 'DQY' the  can drop the 'eh'            |
|    |    | BODQV  MVDQV  DQ  WIDQ    | DQY 'the' KAN DROP DQ  'Y'              |
|----+----+---------------------------+-----------------------------------------|
| ŋ  | J  | finger lung nguyen        | J resembles ŋ                           |
|    |    | FIJGV  LVJ  JWN           | J RYZEMBLS ŋ                            |
|----+----+---------------------------+-----------------------------------------|
| v  | X  | favour livid vain         | think of teeth touching lip: X          |
|    |    | FAIXV  LIXYD XAIN         | QIJK  OX TEEQ  TVTCIJ   LIP: X          |
|----+----+---------------------------+-----------------------------------------|

AANTEE IS STRIKTLEE FNETIK. MEENIJ IUU KAAN RUIT IN XEHRIVS AKSENTS.
ITS IMPOOTNT TUU BEV DQIS IN MUIND AND QIJK OX HAW IT SAWNS, RVVDQV DQAN GET HVJ VP ON "KYREKT" SPELIJ, AS DQIS HABYT NUW LONGV VPLUIS. IF IUU KAAN VNDVSTAAND IT, ITS KYREKT!

EGZAAML: DIFRNT WAIS TUU RUIT 'fine':
  • FUIN
  • FVVIN
  • FVVN
  • FVIN
  • FEIN
  • FOIN
  • FWOIN

FNETIK XAWLS VV KWONTUISD TUU RYMUUV OOLMUWST UIDENTIKL SAWNS. AANTEE ISNT KAIPYBL OF KYMIUUNIKAITIJ SAWNS WIQ EKSTREEM TVJ KYNTOOCNS, TVJ MUUXMNTS, GYYGLZ, SLYYPS, SNOOTS, KLIKS, IRVPTCNS, ETS... IN SUTC KAISYS DCVST PAIST DQ FORYN IUUNIKUWD IN KWUWTS.

| i~e          | grunts  | aa~a     | ooh~aah   | oo~o     | aww,augh  |
|--------------+---------+----------+-----------+----------+-----------|
| EE (been)[1] |         |          | UU (boon) | W (book) |           |
| I  (bin)     | Y (bn)  | AA (ban) | YY (burn) | U [2]    | OO (born) |
| E  (ben)     | V (bun) | A  (bat) | VV (bahn) | O (bon)  |           |

[1] 'EE' CWD BEE 'II' HAWEXVV: 'I' IS IUUSD AS AI PREEFIKS FOO 'y' SAWNS, MAIKIJ 'II' 'yi'.

[2] 'UW' AND 'UI' VV COOTHAAND FOO KOMPLEKS TRIPQOJS 'oh' AND 'eye' WITC TAIK AI TRIP QRUU AT LEEST QREE XAWLS IN VSTRAILIYN. 'UV' CWD OOLSUW SYYX AS COOTHAAND FOO DQ VMERIKN 'o' as in 'Tod' (TUVD), WITC KVVNT BEE SPELD IUUSIJ 'TVVD' ('tahd') or 'TOD' (VST/I.K 'Tod').

╭─────╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭─────╮ │ ⇥ ││ H ││ A ││ I ││ J ││ T ││ Z ││ K ││ B ││ M ││ F ││ [ ││ ] ││ \ │ ╰─────╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰─────╯ ╭───────╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭────────╮ │ KAPS ││ V ││ E ││ U ││ C ││ D ││ S ││ G ││ P ││ X ││ ; ││ ' ││ ↵ │ ╰───────╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰────────╯ ╭─────────╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───────────╮ │ ⇧ ││ Y ││ O ││ W ││ Q ││ N ││ L ││ R ││ , ││ . ││ / ││ ⇧ │ ╰─────────╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───────────╯
CIFT:
(DQEES CWD BEE RYPLAISD WIQ PRUWGRAAMIJ COOTKVTS FOO KOMN KONSTRVKTS, VSIUUMIJ AN AANTEE PRUWGRAAMINJ LAJGWIDC IS DYXELYPD)

╭─────╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭─────╮ │ ⇥ ││ ✔ ││ ↑ ││ ✘ ││ … ││ ┌ ││ ┬ ││ ┐ ││ █ ││ ± ││ ° ││ { ││ } ││ | │ ╰─────╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰─────╯ ╭───────╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭────────╮ │ KAPS ││ ← ││ ↓ ││ → ││ ─ ││ ├ ││ ┼ ││ ┤ ││ │ ││ µ ││ : ││ " ││ ↵ │ ╰───────╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰────────╯ ╭─────────╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───────────╮ │ ⇧ ││ • ││ ¶ ││ § ││ ☞ ││ └ ││ ┴ ││ ┘ ││ < ││ > ││ ? ││ ⇧ │ ╰─────────╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───────────╯
KAPS (LEGYSEE MUWD):

╭─────╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭─────╮ │ ⇥ ││ q ││ w ││ e ││ r ││ t ││ y ││ u ││ i ││ o ││ p ││ [ ││ ] ││ \ │ ╰─────╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰─────╯ ╭───────╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭────────╮ │ KAPS ││ a ││ s ││ d ││ f ││ g ││ h ││ j ││ k ││ l ││ ; ││ ' ││ ↵ │ ╰───────╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰────────╯ ╭─────────╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───╮╭───────────╮ │ ⇧ ││ z ││ x ││ c ││ v ││ b ││ n ││ m ││ , ││ . ││ / ││ ⇧ │ ╰─────────╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───╯╰───────────╯
PRUWS:
  • NUW NEED FOO SPEL-TCEKIJ
  • KYNSISTNT FYNETIK RUULS
  • NUW RYDVNDNT LUWVKAIS
  • MOO SIMBLS GIXN DQEE VBVX
  • DQYS YS SYLEE; KAN RUIT IN AKSENTS

KONS:
  • MVST PVVS EETC WYYD RVVDQV DQAN PATYN-MATC IT
  • MOO UWNYRS TUU RUIT GIXN DVBL KARAKTV KOMBUWS: UW UI AA EE OO UU VV YY, ETS.
  • TAIKS V FIUU DAIS TUU GET IUUSD TUU IT
  • SVM FUIND VPVKAIS TUIRIJ TUU REED, OO 'CAWTI'
  • PRES BUWT

SAAMPLS
PRUWS
FOO DQ AXRIDC DCUW SLOB, DQ PWL OX WYYKIJ WIQ DQ V.I. WOS SIMPLEE DQIS: TRVST. TRVST DQAT IT WUWNT LUI TUU HIM, TRVST DQAT IT WUWNT WIQHOWD PAI, TRVST DQAT IT WUWNT PVNIC EFYT, TRVST DQAT IT WUWNT SVBOODINAIT AND HIUUMILIAIT, TRVST DQAT IT WUWNT PRAI VPON HIS TCILDRN, TRVST DQAT IT WUWNT LEEX HIM TU DUI IF SIK OO INDCYD, TRVST DQAT IT WUWNT VBAANDN HIM WEN OWD & FRAIYL... TRVST DQAT IT DCENRLEE WUWNT KIK HIM WUIL HEES DAWN.
PLAIS NAIMS
VSTRAILIV
NIUU SAWQ WAILS
KWEENSLAAND
NOOQN TERYTREE
XIKTOORIV
TASMAINIV
V.K.T
WESTN VSTRAILIV
SAWQ VSTRAILIV
ADYLAID
SIDNEE
MELBN
HUWBVVT
PYYQ
DVVWN
BRISBN
KAANBRV
TVGRVNOJ
NUNVWOL
GVNGVVLN
BRINDVBELV
GOLBN
IAS
WOGVWOGV
DVBUW
MITVGOJ
KAWRV
BALVRAT
HAI
IUUWN
OOBREE
WYDOJGV
BENDIGUW
BEVNSDAIL
MALVKUUTV
MYRIMBIUULV
DCINDVBUIN
KUUMV
BAITMYNS BAI
DVRYS
KOFS HVVBV
TWEED HEDS
KUULYNGATV
ROKHAAMPTN
TAWNSXIL
KUUKTAWN
WEEPV
KVRVMBV
NVLVNBUI
MANIJGRYDV
KAQRYN
KVNVNVRV
BRUUM
POOT HEDLN
KVRVQV
EKSMYQ
KVNVVXN
DCERLTN
BVNBREE
OOLBNEE
ESPRYNS
SYDIUUNV
POOT OOGVSTV
ALYS SPRIJS
MAWNT UISV
TENYNT KREEK
IUULVVRV
BALGUW
WOOBYTN
KALGUULI
KUULGVVDI
NIUUMN
MAWNT MAGNYT

ORGNQQ:rebol3:

screenie
gifded queue to export an orgfile to html.
Used to make this site.

Mostly written in Rebol3, a beutiful low-effort high-payoff language... reminds me of Python before the crowds...

The queue:
preflight
shellscript node to clear out pub dirs
Also:

cp ../presets/org_title.r3 ./org_title.txt cp ../presets/org_headlines.r3 ./org_headlines.txt cp ../presets/org_noexport.r3 ./org_noexport.txt cp ../presets/org_tables.r3 ./org_tables.txt cp ../presets/org_source.r3 ./org_source.txt cp ../presets/org_checkboxes.r3 ./org_checkboxes.txt cp ../presets/org_lists.r3 ./org_lists.txt cp ../presets/org_properties.r3 ./org_properties.txt cp ../presets/org_dates.r3 ./org_dates.txt cp ../presets/org_links.r3 ./org_links.txt cp ../presets/org_style.r3 ./org_style.txt cp ../presets/org_include.r3 ./org_include.txt cp ../presets/linebreaks.r3 ./linebreaks.txt cp ../presets/savefonts.r3 ./savefonts.txt
#+RESULTS:

loader
hardcoded vala node to load a file
org title:rebol3:


org headlines:rebol3:


org noexport:wip::rebol3:
needs to be fixed as the technique doesn't cover all possible cases


org tables:rebol3:


org source:rebol3:


org checkboxes:rebol3:


org lists:rebol3:


org properties:rebol3:


org dates:rebol3:


org links:rebol3:


org style:rebol3:


org include:rebol3:


linebreak content:wip::rebol3:
fix to ignore tags in xmp or pre


insert script
html node that simply replaces <!--[lastres]--> with the incoming text
prepend css
html node that simply replaces <!--[lastres]--> with the incoming text
save fonts:rebol3:


save html
Hardcoded Vala node that saves the incoming text to index file
publish
shellscript node to copy everything to a publish location
ORG SBE:org:
REBOL[] r: read/lines https://www.rba.gov.au/rss/rss-cb-exchange-rates.xml b: copy "" foreach l r [ if parse l [ thru ">AU:" a: to "EUR" :a copy b to "EUR" to end ] [ break ]] probe (1.0 / (to-decimal trim b))
#+NAME: x
#+RESULTS:
: 1.64446637066272


| ITEM  |   VAL |  XCH | ATAX |   AUD |
|-------+-------+------+------+-------|
| AUD   | 100.0 |  1.0 | 0.76 |  76.0 |
| EUR   | 100.0 | 1.64 | 0.52 |  85.3 |
|-------+-------+------+------+-------|
| TOTAL |       |      |      | 161.3 |
#+TBLFM: @3$3='(org-sbe "x");%.2f :: $5=(($2*$3)*$4);%.1f :: @>$5=vsum(@I$5..@II$5);%.1f

DOTEMACS:el:
REBOLMODE:el:

Rebol3 for orgmode src blocks.

;; rebol3 (load-file "~/.emacs.d/rebol3-mode.el") (require 'rebol3-mode) (add-to-list 'auto-mode-alist '("\\.r3\\'" . rebol3-mode)) (add-to-list 'auto-mode-alist '("\\.r\\'" . rebol3-mode)) (add-to-list 'auto-mode-alist '("\\.reb\\'" . rebol3-mode)) (load-file "~/.emacs.d/ob-rebol3.el")
rebol3-mode.el

cat ~/.emacs.d/rebol3-mode.el
#+RESULTS:
;;; rebol3-mode.el ;; mode for Rebol3: https://github.com/Oldes/Rebol3 ;; by c.p.brown 2020~2023 ;; acknowledgments above relevant code below ;; ;; do not use this mode, it is a derrived work for my own use, ;; and may contain elisp errors, has missing words, and definitely fights with emacs ;; colors cycle down the list, from red to red ;; originally made for a red-mode, blue colors were used for View and Draw, ;; left them spare, just in case... ;; ;; hex face approx. color ;; #FF4D4D control......... brown1, red (css) ;; #E65C73 specialstring... indianred2 ;; #CC5C81 series.......... palevioletred3 ;; #CC5C95 logic........... hotpink3 ;; #BF609F modifiers....... hotpink3 ;; #A6624B ;; #9966CC constants....... mediumpurple3 ;; #7F6CD9 datatypes....... mediumpurple3 ;; #6C7ED9 --++ ;; #527BCC || blue reserved for ;; #3992BF || ui, draw ;; #3EB2B3 --++ ;; #3EB38C context........ mediumseagreen ;; #3EB365 comment........ mediumseagreen ;; #3FB33E ;; #599C36 help........... olivegreen ;; #89B336 datetime....... olivedrab ;; #B3B22D system......... mustard ;; #BF8C26 io............. goldenrod ;; #CC7B29 ;; #D9662B comparison..... chocolate ;; #E64D2E math........... brown2 (defvar rebol3 nil "Support for the Rebol3 programming language, <https://github.com/Oldes/Rebol3>") ;; face definition based on this tutorial by Xah Lee: ;; http://xahlee.info/emacs/emacs/elisp_syntax_coloring.html (defvar rebol3-comparison-face 'rebol3-comparison-face) (defvar rebol3-constants-face 'rebol3-constants-face) (defvar rebol3-context-face 'rebol3-context-face) (defvar rebol3-control-face 'rebol3-control-face) (defvar rebol3-datatypes-face 'rebol3-datatypes-face) (defvar rebol3-datetime-face 'rebol3-datetime-face) (defvar rebol3-help-face 'rebol3-help-face) (defvar rebol3-io-face 'rebol3-io-face) (defvar rebol3-logic-face 'rebol3-logic-face) (defvar rebol3-math-face 'rebol3-math-face) (defvar rebol3-modifiers-face 'rebol3-modifiers-face) (defvar rebol3-series-face 'rebol3-series-face) (defvar rebol3-specialstring-face 'rebol3-specialstring-face) (defvar rebol3-system-face 'rebol3-system-face) (defvar rebol3-var-face 'rebol3-var-face) (defface rebol3-comparison-face '((t (:foreground "#D9662B" :weight bold))) "comparison" :group 'rebol3-mode) (defface rebol3-constants-face '((t (:foreground "#9966CC" :weight bold))) "constants" :group 'rebol3-mode) (defface rebol3-context-face '((t (:foreground "#3EB38C" :weight bold))) "context" :group 'rebol3-mode) (defface rebol3-control-face '((t (:foreground "#FF4D4D" :weight bold))) "control" :group 'rebol3-mode) (defface rebol3-datatypes-face '((t (:foreground "#7F6CD9" :weight bold))) "datatypes" :group 'rebol3-mode) (defface rebol3-datetime-face '((t (:foreground "#89B336" :weight bold))) "datetime" :group 'rebol3-mode) (defface rebol3-help-face '((t (:foreground "#599C36" :weight bold))) "help" :group 'rebol3-mode) (defface rebol3-io-face '((t (:foreground "#BF8C26" :weight bold))) "io" :group 'rebol3-mode) (defface rebol3-logic-face '((t (:foreground "#CC5C95" :weight bold))) "logic" :group 'rebol3-mode) (defface rebol3-math-face '((t (:foreground "#E64D2E" :weight bold))) "math" :group 'rebol3-mode) (defface rebol3-modifiers-face '((t (:foreground "#BF609F" :weight bold))) "modifiers" :group 'rebol3-mode) (defface rebol3-series-face '((t (:foreground "#CC5C81" :weight bold))) "series" :group 'rebol3-mode) (defface rebol3-specialstring-face '((t (:foreground "#E65C73" :weight bold))) "specialstring" :group 'rebol3-mode) (defface rebol3-system-face '((t (:foreground "#B3B22D" :weight bold))) "system" :group 'rebol3-mode) (defface rebol3-var-face '((t (:foreground "#B35147" :weight bold))) "user variables" :group 'rebol3-mode) (defconst rebol3-comparison-words '( "all" "and" "and~" "any" "end" "equal?" "even?" "greater-or-equal?" "greater?" "lesser-or-equal?" "lesser?" "negative?" "not" "not-equal?" "odd?" "or" "or~" "positive?" "same?" "sign?" "some" "strict-equal?" "xor" "xor?" "zero?" ) ) (defconst rebol3-control-words '( "REBOL" "attempt" "break" "case" "catch" "compose" "continue" "disarm" "dispatch" "do" "does" "either" "else" "exit" "for" "forall" "foreach" "forever" "forskip" "func" "function" "halt" "has" "if" "launch" "loop" "next" "opt" "quit" "reduce" "remove-each" "repeat" "return" "switch" "throw" "try" "unless" "until" "while" ) ) (defconst rebol3-system-words '( "bitsets" "browse" "call" "catalog" "component?" "link?" "numeric" "protect" "protect-system" "recycle" "system" "unprotect" "upgrade" ) ) (defconst rebol3-io-words '( "ask" "change-dir" "close" "confirm" "connected?" "delete" "dispatch" "echo" "exists?" "get-modes" "info?" "input" "input?" "list-dir" "make-dir" "modified?" "open" "query" "read" "read-io" "rename" "resend" "save" "script?" "secure" "send" "set-modes" "set-net" "size?" "to-local-file" "to-rebol-file" "update" "wait" "what-dir" "write" "write-io" ) ) (defconst rebol3-math-words '( "abs" "absolute" "acos" "add" "arccosine" "arcsine" "arctangent" "complement" "cosine" "divide" "exp" "log-10" "log-2" "log-e" "max" "maximum" "maximum-of" "min" "minimum" "multiply" "negate" "power" "random" "remainder" "round" "sine" "square-root" "subtract" "tangent" ) ) (defconst rebol3-specialstring-words '( "build-tag" "checksum" "clean-path" "compress" "debase" "decode-cgi" "decompress" "dehex" "detab" "dirize" "enbase" "entab" "form" "format" "import-email" "lowercase" "mold" "pad" "parse-xml" "quote" "reform" "rejoin" "remold" "reword" "split" "split-path" "suffix" "thru" "to" "trim" "uppercase" ) ) (defconst rebol3-datatypes-words '( "binary" "bitset" "block" "char" "charset" "construct" "date" "decimal" "email" "file" "get-word" "hash" "hex" "idate" "image" "integer" "issue" "list" "lit-path" "lit-word" "logic" "money" "pair" "paren" "path" "port" "refinement" "set-path" "set-word" "string" "tag" "time" "tuple" "url" "word" ) ) (defconst rebol3-context-words '( "alias" "bind" "context" "get" "in" "needs" "set" "unset" "use" "value?" ) ) (defconst rebol3-datetime-words '( "date" "day" "hour" "minute" "month" "now" "precise" "second" "time" "weekday" "year" ) ) (defconst rebol3-help-words '( "about" "comment" "dump-face" "dump-obj" "help" "license" "prin" "print" "probe" "source" "trace" "usage" "what" ) ) (defconst rebol3-modifiers-words '( "all" "compare" "deep" "direct" "escape" "filter" "first" "last" "left" "lines" "new" "no-wait" "off" "only" "output" "right" "with" ) ) (defconst rebol3-logic-words '( "any-block?" "any-function?" "any-string?" "any-type?" "any-word?" "as-pair" "binary?" "bitset?" "block?" "char?" "datatype?" "date?" "decimal?" "dir?" "dump-obj" "email?" "empty?" "error?" "event?" "false" "file?" "found?" "function?" "get-word?" "hash?" "head?" "image?" "integer?" "issue?" "library?" "list?" "lit-path?" "lit-word?" "logic?" "money?" "native?" "none" "none?" "number?" "object?" "op?" "pair?" "paren?" "path?" "port?" "refinement?" "routine?" "series?" "set-path?" "set-word?" "string?" "struct?" "suffix?" "tag?" "tail?" "time?" "true" "tuple?" "type?" "unset?" "url?" "word?" ) ) (defconst rebol3-series-words '( "alter" "append" "array" "at" "back" "change" "clear" "collect" "copy" "difference" "exclude" "extract" "find" "found?" "free" "head" "index?" "insert" "intersect" "join" "keep" "length?" "maximum-of" "minimum-of" "offset?" "parse" "pick" "poke" "remove" "remove-each" "repend" "replace" "reverse" "select" "skip" "sort" "switch" "tail" "take" "union" "unique" ) ) (defconst rebol3-constants-words '( "black" "blue" "cyan" "green" "magenta" "red" "white" "yellow" ) ) (defconst rebol3-font-lock-keywords (list `(,(regexp-opt rebol3-control-words 'words) . rebol3-control-face) `(,(regexp-opt rebol3-constants-words 'words) . rebol3-constants-face) `(,(regexp-opt rebol3-system-words 'words) . rebol3-system-face) `(,(regexp-opt rebol3-context-words 'words) . rebol3-context-face) `(,(regexp-opt rebol3-comparison-words 'words) . rebol3-comparison-face) `(,(regexp-opt rebol3-datetime-words 'words) . rebol3-datetime-face) `(,(regexp-opt rebol3-modifiers-words 'words) . rebol3-modifiers-face) `(,(regexp-opt rebol3-io-words 'words) . rebol3-io-face) `(,(regexp-opt rebol3-math-words 'words) . rebol3-math-face) `(,(regexp-opt rebol3-specialstring-words 'words) . rebol3-specialstring-face) `(,(regexp-opt rebol3-series-words 'words) . rebol3-series-face) `(,(regexp-opt rebol3-datatypes-words 'words) . rebol3-datatypes-face) `(,(regexp-opt rebol3-logic-words 'words) . rebol3-logic-face) `(,(regexp-opt rebol3-help-words 'words) . rebol3-help-face) ) ) (defconst rebol3-mode-syntax-table (let ( (table (make-syntax-table)) ) (modify-syntax-entry ?\n ">" table) ;; braces (modify-syntax-entry ?\[ "(]" table) (modify-syntax-entry ?\] ")[" table) (modify-syntax-entry ?\( "()" table) (modify-syntax-entry ?\) ")(" table) (modify-syntax-entry ?< "(>" table) (modify-syntax-entry ?> ")<" table) ;; string (modify-syntax-entry ?{ "|" table) (modify-syntax-entry ?} "|" table) (modify-syntax-entry ?\" "\"" table) (modify-syntax-entry ?^ "\\" table) ;; words (modify-syntax-entry ?_ "w" table) (modify-syntax-entry ?? "w" table) ;; not words (modify-syntax-entry ?, "." table) ;;(modify-syntax-entry ?\; "." table) ;; prefix (modify-syntax-entry ?' "_p" table) ;;(modify-syntax-entry ?` "_p" table) table ) ) (defvar rebol3-mode-hook nil "hook for rebol3-mode") ;;;###autiload (defun rebol3-mode () "Major mode for editing Rebol3 code" (kill-all-local-variables) (setq-local indent-tabs-mode 'only) ;(setq-local c-indent 4) ;(setq-local tab-width 4) ;(setq-local tab-stop-list (number-sequence 4 120 4)) ;(setq-local electric-indent-mode -1) (setq mode-name "rebol3" major-mode 'rebol3-mode) (setq-local comment-start ";") (set-syntax-table rebol3-mode-syntax-table) (setq-local font-lock-defaults '(rebol3-font-lock-keywords)) (run-hooks 'rebol3-mode-hook) ) (provide 'rebol3-mode)
ob-rebol3.el

cat ~/.emacs.d/ob-rebol3.el
#+RESULTS:
;; bare minimum rebol3 ob file ;; by c.p.brown 2023 ;; do not use this script, its for my own personal use only (require 'ob) (defun org-babel-execute:rebol3 (body params) "execute rebol3 code" (setq blkname (format "%s" (nth 4 (org-babel-get-src-block-info)))) ;;(setq tmpfile (org-babel-temp-file (format "%srebol3temp_" (file-name-directory buffer-file-name)) ".r3")) (setq tmpfile (format "%srebol3temp_%s.r3" (file-name-directory buffer-file-name) (org-element-property :title (org-element-at-point)) ) ) (setq par (mapconcat 'identity (org-babel-variable-assignments:rebol3 params) "\n")) (setq newblock (replace-regexp-in-string "\\(REBOL[ [a-zA-Z0-9:\n\t\"]+\\)\\([]]+\\)\\([[:unibyte:]]+\\)" (concat "\\1]\n" par "\n\\3") (org-babel-expand-body:generic body params) ) ) (print newblock) (with-temp-file tmpfile (insert newblock)) (org-babel-eval (format "%sr3 %s && rm %s" (file-name-directory buffer-file-name) (org-babel-process-file-name tmpfile) (org-babel-process-file-name tmpfile)) "") ) (defun org-babel-variable-assignments:rebol3 (params) "Return a list of rebol3 statements assigning the block's variables." (mapcar (lambda (pair) (cond ((numberp (cdr pair)) (format "\n%s: %s\n" (car pair) (cdr pair))) ((stringp (cdr pair)) (format "\n%s: {%s}\n" (car pair) (cdr pair))) (t "") ) ) (org-babel--get-vars params) ) ) (provide 'ob-rebol3)
VALAMODE:el:

Vala for orgmode src blocks

;; vala (load-file "~/.emacs.d/vala-mode.el") (require 'vala-mode) (load-file "~/.emacs.d/ob-vala.el") ( org-babel-do-load-languages 'org-babel-load-languages '( (shell . t) (python . t) (org . t) (vala . t) (rebol3 . t) ) ) ;; stop org from fighting with valamode and rebolmode ;; copied from https://emacs.stackexchange.com/questions/50216/org-mode-code-block-parentheses-mismatch (defun org-syntax-table-modify () "Modify `org-mode-syntax-table' for the current org buffer." (modify-syntax-entry ?< "." org-mode-syntax-table) (modify-syntax-entry ?> "." org-mode-syntax-table) ) (add-hook 'org-mode-hook #'org-syntax-table-modify)
vala_mode.el
Only includes keywords I usually see.
Brace matching detects commented braces.

cat ~/.emacs.d/vala-mode.el
#+RESULTS:
;;; vala-mode.el ;; mode for Vala: https://vala.dev ;; by c.p.brown 2022~2025 ;; acknowledgments above relevant code below ;; ;; do not use this mode, it is a derrived work for my own use, ;; and may contain elisp errors, has missing words, and definitely fights with emacs (defvar vala nil "Support for the awesome Vala programming language, <https://vala.dev>") ;; face definition based on this tutorial by Xah Lee: ;; http://xahlee.info/emacs/emacs/elisp_syntax_coloring.html (defvar vala-cairocmd-face 'vala-cairocmd-face) (defvar vala-cairoobj-face 'vala-cairoobj-face) (defvar vala-cairoprop-face 'vala-cairoprop-face) (defvar vala-comment-face 'vala-comment-face) (defvar vala-comparison-face 'vala-comparison-face) (defvar vala-constant-face 'vala-constant-face) (defvar vala-context-face 'vala-context-face) (defvar vala-control-face 'vala-control-face) (defvar vala-datatype-face 'vala-datatype-face) (defvar vala-datetime-face 'vala-datetime-face) (defvar vala-event-face 'vala-event-face) (defvar vala-gtkcmd-face 'vala-gtkcmd-face) (defvar vala-gtkobj-face 'vala-gtkobj-face) (defvar vala-gtkprop-face 'vala-gtkprop-face) (defvar vala-help-face 'vala-help-face) (defvar vala-io-face 'vala-io-face) (defvar vala-logic-face 'vala-logic-face) (defvar vala-math-face 'vala-math-face) (defvar vala-modifier-face 'vala-modifier-face) (defvar vala-series-face 'vala-series-face) (defvar vala-specialstring-face 'vala-specialstring-face) (defvar vala-system-face 'vala-system-face) (defvar vala-var-face 'vala-var-face) (defface vala-cairocmd-face '((t (:foreground "#527BCC" :weight bold))) "cairo commands" :group 'vala-mode) (defface vala-cairoobj-face '((t (:foreground "#6C7ED9" :weight bold))) "cairo objects" :group 'vala-mode) (defface vala-cairoprop-face '((t (:foreground "#3EB2B3" :weight bold))) "cairo object properties" :group 'vala-mode) (defface vala-comment-face '((t (:foreground "#3EB365" :weight bold))) "comments" :group 'vala-mode) (defface vala-comparison-face '((t (:foreground "#D9662B" :weight bold))) "comparison" :group 'vala-mode) (defface vala-constant-face '((t (:foreground "#9966CC" :weight bold))) "constants" :group 'vala-mode) (defface vala-context-face '((t (:foreground "#3EB38C" :weight bold))) "context" :group 'vala-mode) (defface vala-control-face '((t (:foreground "#FF4D4D" :weight bold))) "control" :group 'vala-mode) (defface vala-datatype-face '((t (:foreground "#7F6CD9" :weight bold))) "datatypes" :group 'vala-mode) (defface vala-datetime-face '((t (:foreground "#89B336" :weight bold))) "datetime" :group 'vala-mode) (defface vala-event-face '((t (:foreground "#CC7B29" :weight bold))) "events" :group 'vala-mode) (defface vala-gtkcmd-face '((t (:foreground "#527BCC" :weight bold))) "gtk commands" :group 'vala-mode) (defface vala-gtkobj-face '((t (:foreground "#6C7ED9" :weight bold))) "gtk objects" :group 'vala-mode) (defface vala-gtkprop-face '((t (:foreground "#3EB2B3" :weight bold))) "gtk object properties" :group 'vala-mode) (defface vala-help-face '((t (:foreground "#599C36" :weight bold))) "help" :group 'vala-mode) (defface vala-io-face '((t (:foreground "#BF8C26" :weight bold))) "io" :group 'vala-mode) (defface vala-logic-face '((t (:foreground "#CC5C95" :weight bold))) "logic" :group 'vala-mode) (defface vala-math-face '((t (:foreground "#E64D2E" :weight bold))) "math" :group 'vala-mode) (defface vala-modifier-face '((t (:foreground "#BF609F" :weight bold))) "modifiers" :group 'vala-mode) (defface vala-series-face '((t (:foreground "#CC5C81" :weight bold))) "series" :group 'vala-mode) (defface vala-specialstring-face '((t (:foreground "#E65C73" :weight bold))) "specialstring" :group 'vala-mode) (defface vala-system-face '((t (:foreground "#B3B22D" :weight bold))) "system" :group 'vala-mode) (defface vala-var-face '((t (:foreground "#B35147" :weight bold))) "user variables" :group 'vala-mode) (defconst vala-comparison-words '("not" "or" "xor" "compare")) (defconst vala-context-words '("public" "private" "context" "var" "construct")) (defconst vala-control-words '( "break" "case" "catch" "continue" "default" "do" "else" "for" "foreach" "if" "in" "next" "repeat" "return" "switch" "throw" "try" "while" ) ) (defconst vala-help-words '("prin" "print" "printf")) (defconst vala-logic-words '("true" "false")) (defconst vala-datatype-words '( "bool" "char" "class" "double" "float" "int" "int8" "int64" "null" "out" "size_t" "string" "StringBuilder" "struct" "uint" "uint8" "uint16" "uint32" "uint64" "unichar" "void" ) ) (defconst vala-math-words '("sqrt" "min" "max" "abs" "floor" "ceil" "round")) (defconst vala-io-words '( "Dir" "Document" "ExtractFlags" "File" "FileCreateFlags" "FileOutputStream" "FileQueryInfoFlags" "FileStream" "FileTest" "FileType" "FileUtils" "Path" "Pid" "Read" "Result" "SpawnError" "SpawnFlags" "WriteDisk" "append_to" "build_filename" "create_dests_tree" "delete" "errno" "error_string" "find_dest" "from_file" "get_attachments" "get_author" "get_basename" "get_creation_date" "get_creation_date_time" "get_creator" "get_current_dir" "get_dirname" "get_form_field" "get_id" "get_keywords" "get_metadata" "get_modification_date" "get_modification_date_time" "get_n_attachments" "get_n_pages" "get_n_signatures" "get_page" "get_page_by_label" "get_page_layout" "get_page_mode" "get_path" "get_pdf_conformance" "get_pdf_part" "get_pdf_subtype" "get_pdf_subtype_string" "get_pdf_version" "get_pdf_version_string" "get_permissions" "get_print_duplex" "get_print_n_copies" "get_print_page_ranges" "get_print_scaling" "get_producer" "get_signature_fields" "get_subject" "get_text" "get_title" "get_uri" "has_attachments" "has_javascript" "is_linearized" "load_contents" "make_directory_with_parents" "message" "new_for_path" "next_header" "open" "open_filename" "query_exists" "query_file_type" "read_data_block" "read_line" "read_name" "reset_form" "save" "save_a_copy" "save_to_fd" "set_author" "set_creation_date" "set_creator" "set_filename" "set_keywords" "set_modification_date" "set_modification_date_time" "set_options" "set_producer" "set_standard_lookup" "set_subject" "set_title" "spawn_async" "spawn_sync" "support_filter_all" "support_format_all" "write" "write_data_block" "write_header" ) ) (defconst vala-series-words '("join" "joinv" "length" "resize")) (defconst vala-specialstring-words '( "@get" "_chomp" "_chug" "_delimit" "_strip" "ascii_casecmp" "ascii_down" "ascii_ncasecmp" "ascii_up" "canon" "casefold" "char_count" "chomp" "chr" "chug" "collate" "collate_key" "collate_key_for_filename" "compress" "concat" "contains" "data" "delimit" "down" "dup" "erase" "escape" "first_index_of" "get_char" "get_char_validated" "get_next_char" "get_prev_char" "has_prefix" "has_suffix" "hash" "index_of" "index_of_char" "index_of_nth_char" "insert" "is_ascii" "isdigit" "join" "last_index_of" "last_index_of_char" "len" "locale_to_utf8" "make_valid" "match_string" "ndup" "next_char" "nfill" "normalize" "offset" "pointer_to_offset" "prev_char" "prepend" "rchr" "replace" "reverse" "rstr" "rstr_len" "scanf" "set_str" "size" "sizeof" "skip" "slice" "splice" "split" "split_set" "str" "strcmp" "strip" "substring" "to_ascii" "to_bool" "to_double" "to_int" "to_int64" "to_long" "to_string" "to_uint64" "to_ulong" "to_utf16" "to_utf32" "to_utf32_fast" "to_utf8" "tokenize_and_fold" "trim" "up" "utf8_offset" "valid_char" "validate" "validate_len" "vprintf" ) ) (defconst vala-system-words '( "ApplicationFlags" "Archive" "Cairo" "Display" "Environment" "Error" "EventControllerMotion" "EventControllerScroll" "EventControllerZoom" "free" "GLib" "Gdk" "GestureClick" "GestureDrag" "GestureZoom" "get_max_threads" "get_max_unused_threads" "get_num_processors" "get_num_threads" "get_num_unused_threads" "Gtk" "Math" "Orientation" "Pango" "Process" "Poppler" "RGBA" "application" "application_id" "args" "flags" "get_default" "init" "main" "main_quit" "move_to_front" "new" "read_line" "ref" "run" "set_max_idle_time" "set_max_unused_threads" "spawn_async" "stop_unused_threads" "ThreadPool" "unprocessed" "using" "weak" "with_owned_data" ) ) (defconst vala-datetime-words '( "Date" "DateDay" "DateMonth" "DateTime" "DateWeekday" "DateYear" "add_days" "add_months" "add_years" "date" "days_between" "get_day" "get_day_of_month" "get_iso8601_week_of_year" "get_monotonic_time" "get_month" "get_real_time" "get_weekday" "get_year" "month" "now" "now_local" "precise" "second" "set_day" "set_dmy" "set_month" "set_year" "strftime" "subtract_days" "subtract_months" "time" "valid" "weekday" "year" ) ) (defconst vala-gtkcmd-words '( "action_set_enabled" "activate" "activate_action" "activate_action_variant" "activate_default" "add_binding" "add_binding_action" "add_binding_signal" "add_class" "add_controller" "add_css_class" "add_events" "add_mnemonic_label" "add_provider" "add_provider_for_display" "add_shortcut" "add_tick_callback" "add_titled" "allocate" "allocate_size" "append" "append_page" "append_text" "attach" "bind_model" "bind_template_callback_full" "bind_template_child_full" "child_focus" "compute_bounds" "compute_expand" "compute_expand_internal" "compute_point" "compute_transform" "contains" "create_pango_context" "create_pango_layout" "css_changed" "dispose_template" "error_bell" "focus" "from_icon_name" "get_accessible_role" "get_activate_signal" "get_active" "get_allocated_baseline" "get_allocated_height" "get_allocated_width" "get_allocation" "get_ancestor" "get_approximate_digit_width" "get_baseline" "get_can_focus" "get_can_target" "get_child" "get_child_at_index" "get_child_visible" "get_clipboard" "get_color" "get_css_classes" "get_css_name" "get_current_button" "get_current_page" "get_cursor" "get_default_direction" "get_default_size" "get_direction" "get_display" "get_first_child" "get_focus_child" "get_focus_on_click" "get_focusable" "get_font_description" "get_font_map" "get_font_options" "get_frame_clock" "get_gutter" "get_halign" "get_has_tooltip" "get_height" "get_hexpand" "get_hexpand_set" "get_index" "get_language" "get_last_child" "get_layout_manager" "get_layout_manager_type" "get_limit_events" "get_line_count" "get_mapped" "get_margin_bottom" "get_margin_end" "get_margin_start" "get_margin_top" "get_metrics" "get_name" "get_native" "get_next_sibling" "get_opacity" "get_orientation" "get_overflow" "get_pango_context" "get_parent" "get_preferred_size" "get_prev_sibling" "get_primary_clipboard" "get_realized" "get_receives_default" "get_request_mode" "get_root" "get_row_at_index" "get_scale_factor" "get_scheme" "get_selected" "get_selected_row" "get_sensitive" "get_settings" "get_size" "get_size_request" "get_start_child" "get_state_flags" "get_string" "get_style_context" "get_template_child" "get_tooltip_markup" "get_tooltip_text" "get_valign" "get_value" "get_vexpand" "get_vexpand_set" "get_visible" "get_width" "grab_focus" "has_css_class" "has_visible_focus" "hsv_to_rgb" "in_destruction" "init_template" "insert" "insert_action_group" "insert_after" "insert_before" "install_action" "install_property_action" "is_ancestor" "is_drawable" "is_focus" "is_sensitive" "is_visible" "list_mnemonic_labels" "load_from_data" "load_from_string" "measure" "observe_children" "observe_controllers" "pick" "popdown" "popup" "present" "qsort_with_data" "query_action" "queue_allocate" "queue_draw" "queue_resize" "remove" "remove_controller" "remove_css_class" "remove_mnemonic_label" "remove_tick_callback" "reorder_child_after" "reorder_child_before" "rgb_to_hsv" "set_accessible_role" "set_activate_signal" "set_activate_signal_from_name" "set_active" "set_baseline_row" "set_button" "set_can_focus" "set_can_target" "set_child" "set_child_visible" "set_column_spacing" "set_css_classes" "set_css_name" "set_cursor" "set_cursor_from_name" "set_default_direction" "set_default_size" "set_direction" "set_draw_func" "set_end_child" "set_focus_child" "set_focus_on_click" "set_focusable" "set_font_map" "set_font_options" "set_halign" "set_has_tooltip" "set_hexpand" "set_hexpand_set" "set_highlight_syntax" "set_icon_name" "set_label" "set_language" "set_layout_manager" "set_layout_manager_type" "set_limit_events" "set_margin_bottom" "set_margin_end" "set_margin_start" "set_margin_top" "set_markup" "set_max_width_chars" "set_min_content" "set_model" "set_monospace" "set_name" "set_opacity" "set_orientation" "set_overflow" "set_overlay_scrolling" "set_parent" "set_policy" "set_position" "set_receives_default" "set_row_spacing" "set_selected" "set_selection_mode" "set_sensitive" "set_show_border" "set_shrink_end_child" "set_size_request" "set_spacing" "set_stack" "set_state_flags" "set_style_scheme" "set_tab" "set_tab_pos" "set_tabs" "set_template" "set_template_from_resource" "set_template_scope" "set_text" "set_title" "set_title_widget" "set_titlebar" "set_tooltip" "set_tooltip_markup" "set_tooltip_text" "set_transition_type" "set_valign" "set_value" "set_vexpand" "set_vexpand_set" "set_visible" "set_visible_child" "set_width_chars" "set_wrap_width" "should_layout" "show" "show_all" "show_close_button" "show_title_buttons" "size_allocate" "snapshot" "snapshot_child" "system_setting_changed" "translate_coordinates" "trigger_tooltip_query" "typeof" "units_to_double" "unparent" "unroot" "unset_state_flags" ) ) (defconst vala-gtkobj-words '( "ActionBar" "Adjustment" "Application" "ApplicationWindow" "Box" "Buffer" "Button" "ComboBox" "ComboBoxText" "CssProvider" "DrawingArea" "DropDown" "Entry" "EventBox" "FlowBox" "Grid" "GtkSource" "Gutter" "HeaderBar" "Image" "Label" "LanguageManager" "ListBox" "MenuButton" "Notebook" "Object" "Paned" "Picture" "Popover" "Requisition" "Scale" "ScrollDirection" "ScrolledWindow" "SpinButton" "Stack" "StackSwitcher" "StackTransitionType" "StringList" "StringObject" "StyleContext" "StyleSchemeManager" "TabArray" "TextTagTable" "TextView" "ToggleButton" "ToolButton" "View" "Widget" "Window" "space_drawer" "this" ) ) (defconst vala-gtkprop-words '( "accepts_tab" "active" "adjustment" "alpha" "border_width" "bottom_margin" "buffer" "can_focus" "can_shrink" "can_target" "column_spacing" "css_classes" "css_name" "cursor" "default_height" "default_width" "enable_matrix" "end_child" "focus_on_click" "focusable" "halign" "has_arrow" "has_default" "has_focus" "has_tooltip" "height_request" "hexpand" "hexpand_set" "highlight_current_line" "homogeneous" "icon_name" "indent_on_tab" "indent_width" "keep_aspect_ratio" "label" "layout_manager" "left_margin" "limit_events" "lower" "margin" "margin_bottom" "margin_end" "margin_start" "margin_top" "markup" "max_children_per_line" "min_children_per_line" "name" "opacity" "overflow" "override_background_color" "pack_end" "pack_start" "parent" "popover" "position" "receives_default" "resize_end_child" "resize_start_child" "right_margin" "root" "row_spacing" "scale_factor" "selected" "selected_item" "sensitive" "show_line_numbers" "spacing" "start_child" "tab_width" "text" "title" "tooltip_markup" "tooltip_text" "top_margin" "upper" "valign" "value" "vexpand" "vexpand_set" "visible" "wide_handle" "width_request" "with_buffer" "with_entry" "with_label" "with_range" "with_value" "wrap_width" "xalign" ) ) (defconst vala-constant-words '( "ACL" "ALPHA" "ALWAYS" "BAD_WEEKDAY" "BOLD" "BOTTOM" "BUTTON1_MOTION_MASK" "BUTTON2_MOTION_MASK" "BUTTON3_MOTION_MASK" "BUTTON_PRESS_MASK" "BUTTON_RELEASE_MASK" "CAPTURE" "DIGITS" "DIRECTORY" "DOWN" "EMAIL" "END" "EPSILON" "FFLAGS" "FLAGS_NONE" "FREE_FORM" "FRIDAY" "HORIZONTAL" "IS_DIR" "LEFT" "MONDAY" "NAME" "NEVER" "NONE" "NORMAL" "NUMBER" "OK" "PASSWORD" "PERM" "PHONE" "PIN" "POINTER_MOTION_MASK" "PRELIGHT" "PRIVATE" "RIGHT" "ROUND" "SATURDAY" "SCROLL_MASK" "SEARCH_PATH" "SELECTED" "SLIDE_LEFT_RIGHT" "SQUARE" "START" "STYLE_PROVIDER_PRIORITY_USER" "SUNDAY" "TERMINAL" "THURSDAY" "TIME" "TOP" "TOUCH_BEGIN" "TOUCH_END" "TOUCH_MASK" "TUESDAY" "UP" "URL" "VERTICAL" "WEDNESDAY" "black" "blue" "cyan" "green" "magenta" "red" "white" "yellow" ) ) (defconst vala-event-words '( "EventMask" "Gesture" "GestureMultiPress" "activate" "activated" "begin" "button_press" "button_press_event" "button_release" "changed" "clicked" "close_request" "connect" "destroy" "direction_changed" "drag_begin" "drag_end" "drag_update" "end" "event" "hide" "keynav_failed" "map" "mnemonic_activate" "motion" "motion_notify" "move_focus" "notify" "pressed" "query_tooltip" "realize" "released" "scroll" "selected" "show" "state_flags_changed" "stopped" "switch_page" "toggled" "touch" "unmap" "unrealize" "update" "value_changed" ) ) (defconst vala-cairocmd-words '( "close_path" "fill" "identity" "line_to" "move_to" "paint" "queue_draw" "select_font_face" "set_font_matrix" "set_font_size" "set_line_cap" "set_line_width" "set_source_rgba" "show_text" "stroke" ) ) (defconst vala-cairoobj-words '("rectangle" "line" "arc")) (defconst vala-cairoprop-words '("TextExtents" "FontSlant" "FontWeight" "height" "Matrix" "text_extents" "LineCap" "width")) (defconst vala-modifier-words '("parse" "to_string" "try_parse")) (defconst vala-font-lock-keywords (list `(,(regexp-opt vala-logic-words 'words) . vala-logic-face) `(,(regexp-opt vala-gtkcmd-words 'words) . vala-gtkcmd-face) `(,(regexp-opt vala-gtkprop-words 'words) . vala-gtkprop-face) `(,(regexp-opt vala-cairoprop-words 'words) . vala-cairoprop-face) `(,(regexp-opt vala-event-words 'words) . vala-event-face) `(,(regexp-opt vala-comparison-words 'words) . vala-comparison-face) `(,(regexp-opt vala-context-words 'words) . vala-context-face) `(,(regexp-opt vala-io-words 'words) . vala-io-face) `(,(regexp-opt vala-system-words 'words) . vala-system-face) `(,(regexp-opt vala-help-words 'words) . vala-help-face) `(,(regexp-opt vala-math-words 'words) . vala-math-face) `(,(regexp-opt vala-specialstring-words 'words) . vala-specialstring-face) `(,(regexp-opt vala-gtkobj-words 'words) . vala-gtkobj-face) `(,(regexp-opt vala-control-words 'words) . vala-control-face) `(,(regexp-opt vala-datatype-words 'words) . vala-datatype-face) `(,(regexp-opt vala-datetime-words 'words) . vala-datetime-face) `(,(regexp-opt vala-series-words 'words) . vala-series-face) `(,(regexp-opt vala-constant-words 'words) . vala-constant-face) `(,(regexp-opt vala-cairocmd-words 'words) . vala-cairocmd-face) `(,(regexp-opt vala-cairoobj-words 'words) . vala-cairoobj-face) `(,(regexp-opt vala-modifier-words 'words) . vala-modifier-face) ) ) (defconst vala-mode-syntax-table (let ( (table (make-syntax-table)) ) ;(modify-syntax-entry ?\ "_" table) (modify-syntax-entry ?\n ">" table) (modify-syntax-entry ?* ". 23b" table) (modify-syntax-entry ?/ ". 124" table) ;; braces (modify-syntax-entry ?\[ "(]" table) (modify-syntax-entry ?\] ")[" table) (modify-syntax-entry ?\( "()" table) (modify-syntax-entry ?\) ")(" table) (modify-syntax-entry ?\{ "(}" table) (modify-syntax-entry ?\} "){" table) ;; char (modify-syntax-entry ?\" "\'" table) ;; string (modify-syntax-entry ?\" "\"" table) (modify-syntax-entry ?\\ "\\" table) ;; words (modify-syntax-entry ?_ "w" table) ;; not words (modify-syntax-entry ?, "." table) (modify-syntax-entry ?\; "." table) ;; doesn't work (modify-syntax-entry ?> "." table) (modify-syntax-entry ?< "." table) table ) ) (defvar vala-mode-hook nil "hook for vala-mode") ;;;###autoload (defun vala-mode () "Major mode for editing Vala code" (kill-all-local-variables) (setq mode-name "vala" major-mode 'vala-mode) (setq-local comment-start "//") (set-syntax-table vala-mode-syntax-table) (setq-local font-lock-defaults '(vala-font-lock-keywords)) (run-hooks 'vala-mode-hook) ) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.vala\\'" . vala-mode)) (provide 'vala-mode)
ob-vala.el
Bare-minimum bridge to valac.
This will attempt to:
  • Save the src block code to a temp vala file
  • Compile the temp vala file using src block flags
  • Delete the temp vala file, so it could fuck-up and delete some other file
  • Run the resulting binary ./valatemp

cat ~/.emacs.d/ob-vala.el
#+RESULTS:
;; bare minimum vala ob file ;; by c.p.brown 2023~2025 ;; do not use this script, its for my own personal use only (require 'ob) (defun org-babel-execute:vala (body params) "execute vala code" (setq blkname (format "%s" (nth 4 (org-babel-get-src-block-info)))) ;;(setq tmpfile (org-babel-temp-file (format "%svalatemp_" (file-name-directory buffer-file-name)) ".vala")) (setq tmpfile (format "%svalatemp_%s.vala" (file-name-directory buffer-file-name) (org-element-property :title (org-element-at-point)) ) ) (setq par (mapconcat 'identity (org-babel-variable-assignments:vala params) "\n")) (setq flg (alist-get :flags (org-babel-process-params params))) (if (not flg) (setq flg "") ()) (with-temp-file tmpfile (insert (replace-regexp-in-string "main[\s(]+string[\s\[\]]+ args[\s)]+[\s{]+\n" (concat "main (string[] args) {\n\n" par "\n") (org-babel-expand-body:generic body params) ) ) ) (org-babel-eval (format "valac %s -o valatemp %s && rm %s && ./valatemp" (org-babel-process-file-name tmpfile) flg (org-babel-process-file-name tmpfile)) "" ) ) (defun org-babel-variable-assignments:vala (params) "Return a list of vala statements assigning the block's variables." (mapcar (lambda (pair) (cond ((numberp (cdr pair)) (format "\nstring %s = %s;\n" (car pair) (cdr pair))) ((stringp (cdr pair)) (format "\nstring %s = \"\"\"%s\"\"\";\n" (car pair) (cdr pair))) (t "") ) ) (org-babel--get-vars params) ) ) (provide 'ob-vala)
FORCEUTF8:el:

Used for testing unicode, and dealing with a newline issue.

;; brute force utf-8 (set-locale-environment "en.UTF-8") (add-to-list 'file-coding-system-alist '("\\.org" . utf-8-unix) ) (add-to-list 'file-coding-system-alist '("\\.txt" . utf-8-unix) ) (add-to-list 'file-coding-system-alist '("\\.el" . utf-8-unix) ) (add-to-list 'file-coding-system-alist '("\\.scratch" . utf-8-unix) ) (add-to-list 'file-coding-system-alist '("user_prefs" . utf-8-unix) ) (add-to-list 'process-coding-system-alist '("\\.txt" . utf-8-unix) ) (set-language-environment 'utf-8) (set-default-coding-systems 'utf-8-unix) (set-selection-coding-system 'utf-8-unix) (prefer-coding-system 'utf-8-unix) (set-terminal-coding-system 'utf-8-unix) (set-keyboard-coding-system 'utf-8-unix) (setq coding-system-for-read 'utf-8-unix) (setq coding-system-for-write 'utf-8-unix) (setq-default buffer-file-coding-system 'utf-8-unix) (setq utf-translate-cjk-mode nil)
QUOTELINE:el:

Wrap text on the current line in double-quotes.

;; quote lines of text, used for preparing a bunch of keywords pasted into mode files... (defun quote-lines () "Quote lines of text in the selected region." (interactive) ;; set start & end without moving (point) and losing the region (setq rstart (line-beginning-position)) (setq rend (line-end-position)) (setq lstart (line-number-at-pos rstart)) (setq lend (line-number-at-pos rend)) (message "start pos is %d, end pos is %d" rstart rend) ;; capture the region (when (use-region-p) (setq rstart (region-beginning)) (setq rend (region-end)) (setq lstart (line-number-at-pos rstart)) (setq lend (line-number-at-pos rend)) ) (setq lend (+ lend 1)) (message "start line is %d, end line is %d" lstart lend) (message "start pos is %d, end pos is %d" rstart rend) (goto-char rstart) (message "initial pos is %d" (point)) (while (< (line-number-at-pos (point)) lend) ;; move (point), set start start-of-text and end (beginning-of-line) (setq start (point)) (back-to-indentation) (setq tstart (point)) (end-of-line) (setq end (point)) (message "start point is %d, text point is %d, end point is %d" start tstart end) (let ( ;; get leading_whitespace, text, then remove line (lineind (buffer-substring start tstart)) (linetxt (buffer-substring tstart end)) (lineall (delete-and-extract-region start end)) ) ;; rebuild & insert as: leading_whitespace"text"\n ... without trailing spaces as it confuses delete-duplicate-lines (insert (concat lineind "\"" ( string-trim-right linetxt "[ \t]+" ) "\"")) ;; move to next line, since (insert) moves (point) to the end of the line here (forward-char) ) ) ) (global-set-key (kbd "<M-S-left>") 'quote-lines)
MOVELINE:el:

Derivative work, edited to keep cursor x pos

;; move lines ;; originally copied from: https://www.emacswiki.org/emacs/MoveLine ;; edited to retain the cursor position regardless of leading tab/space usage (defun move-line (n) "Move the current line up or down by N lines." (interactive "p") ;; get cursor position relative to start-of-line (setq mypos (- (point) (pos-bol))) ;; get region (beginning-of-line) (setq start (point)) (end-of-line) (forward-char) (setq end (point)) ;; copy, move to line, insert (let ( (line-text (delete-and-extract-region start end)) ) (forward-line n) (insert line-text) ;; pin cursor to 'moved' line (forward-line -1) (beginning-of-line) ( forward-char mypos ) ) ) (defun move-line-up (n) "Move the current line up by N lines." (interactive "p") (move-line (if (null n) -1 (- n))) ) (defun move-line-down (n) "Move the current line down by N lines." (interactive "p") (move-line (if (null n) 1 n)) )
HIGHLIGHTWORD:el:

Derivative work, minor edit.

;; highlight word ;; copied from: http://stackoverflow.com/questions/16016893/highlight-occurrences-on-click ;; doesn't work in some buffers... needs some work. (defun click-select-word (event) (interactive "e") (hi-lock-mode 0) (let ( (phrase (concat "\\b" (regexp-quote (thing-at-point 'symbol)) "\\b" ) ) ) ;(highlight-regexp (regexp-quote (thing-at-point 'symbol))) (highlight-regexp phrase) ) ) (global-set-key (kbd "<M-S-mouse-1>") 'click-select-word)
TAB=TAB:el:

This is getting old.
Malicious TAB defaults might drive me from Emacs.

I have a modern OrgMode replacement in the works, but it keeps getting put on hold for more urgent projects... Anger is a wonderful motivator of software development so it'll happen eventually.

;; tab = tab (setq-default tab-always-indent t) (setq-default indent-tabs-mode 'only) (setq-default tab-width 4) (setq-default tab-stop-list (number-sequence 4 120 4)) (electric-indent-mode -1) (add-hook 'after-change-major-mode-hook (lambda() (electric-indent-mode -1))) (global-set-key (kbd "<backspace>") 'backward-delete-char) (defun cpb-editing-hook () ;; tab indent unindent ;; posted by Stanley Bak ;; edited by 'mythicalcoder' ;; at: https://stackoverflow.com/questions/2249955/emacs-shift-tab-to-left-shift-the-block (defun just-insert-tab () "Insert a tab char. (ASCII 9, \t)" (interactive) (insert "\t") ) (defun just-insert-newline () "Insert a newline char" (interactive) (insert "\n") ) (defun indent-region-custom(numSpaces) (if (use-region-p) (progn ; default to start and end of current line (setq regionStart (line-beginning-position)) (setq regionEnd (line-end-position)) ; if there's a selection, use that instead of the current line (when (use-region-p) (setq regionStart (region-beginning)) (setq regionEnd (region-end)) ) (save-excursion ; restore the position afterwards (goto-char regionStart) ; go to the start of region (setq start (line-beginning-position)) ; save the start of the line (goto-char regionEnd) ; go to the end of region (setq end (line-end-position)) ; save the end of the line (indent-rigidly start end numSpaces) ; indent between start and end (setq deactivate-mark nil) ; restore the selected region ) ) (just-insert-tab) ) ) (defun untab-region (N) (interactive "p") (indent-region-custom -4) ) (defun tab-region (N) (interactive "p") (indent-region-custom 4) ) (setq indent-tabs-mode 'only) (setq tab-width 4) (setq tab-stop-list (number-sequence 4 120 4)) (electric-indent-mode -1) (local-set-key (kbd "<backspace>") 'backward-delete-char) (local-set-key (kbd "<M-S-up>") 'move-line-up) (local-set-key (kbd "<M-S-down>") 'move-line-down) (local-set-key (kbd "<backtab>") 'untab-region) (local-set-key (kbd "<tab>") 'tab-region) (local-set-key (kbd "TAB") 'tab-region) (local-set-key (kbd "<return>") 'just-insert-newline) ;; special cases for modes with a keymap (define-key emacs-lisp-mode-map (kbd "<return>") 'just-insert-newline) (define-key emacs-lisp-mode-map (kbd "TAB") 'tab-region) (define-key emacs-lisp-mode-map (kbd "<tab>") 'tab-region) (define-key emacs-lisp-mode-map (kbd "<backtab>") 'untab-region) ) ;; tab = tab for rebol3 (add-hook 'rebol3-mode-hook 'cpb-editing-hook) ;; tab = tab for python (add-hook 'python-mode-hook 'cpb-editing-hook) ;; tab = tab for xml (add-hook 'nxml-mode-hook 'cpb-editing-hook) ;; tab = tab for html (add-hook 'html-mode-hook 'cpb-editing-hook) ;; tab = tab or vala (add-hook 'vala-mode-hook 'cpb-editing-hook) ;; tab = tab for elsip (add-hook 'emacs-lisp-mode-hook 'cpb-editing-hook) ;; tab = tab for shell (add-hook 'shell-mode-hook 'cpb-editing-hook) ;; org src blocks (setq org-src-tab-acts-natively t) (setq org-src-preserve-indentation t) (setq org-edit-src-content-indentation 0) (setq org-src-fontify-natively t)
R3 RENAME:rebol3:

Batch rename with Rebol3.

sample name...: "Within Destruction - Lotus - 11 P.O.P..flac"
desired output: "within_destruction_lotus_11_pop.flac"

the crude way:

;; rename test ;; by c.p.brown 2023 f: read %./*.flac foreach x f [ n: lowercase (to-string x) replace n ".flac" "" n: reword/escape n [ " " "_" "." "" "-" "" "(" "" ")" "" ] none replace/all n "__" "_" n: join n ".flac" call compose [ "cp" (to-string x) (n) ] ]
the more reliable way, no duplicate underscores:

;; rename test using parse ;; by c.p.brown 2023 f: read %./*.flac nup: charset ".-()" foreach x f [ n: lowercase to-string x parse n [ a: any [ [ not ".flac" ] remove nup | skip ] :a any [ remove some #" " insert "_" | skip ] ] print [ "renaming from:" x "^/ to:" n "^/"] t: open/new/write to-file n write/binary t read/binary x ]
another test:
"Within Destruction - Lotus - (.- )- 11 P.O.P..flac"
output:
"within_destruction_lotus_11_pop.flac"
LYNX CRAWL:cmd:

lynx --dump --listonly --nonumbers http://www.yourdomain.com | grep http | grep yourdomain.com | sort | uniq > links.txt
then convert to a xml:
wrap each line in <url><loc> ... <loc><url>
insert a header:

<?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
then append </urlset>
and save as sitemap.xml

FIREJAIL FIREFOX:cmd:

sed -i 's/Exec=.*/Exec=firejail firefox -no-remote/g' /usr/share/applications/firefox.desktop
It won't take at first, so run the above command before loading firefox, open and close firefox, run the command again, wait a few seconds, run it a third time... then it should be firejailed. Check by looking at:

file:///home/yourusername
You should only see folders that firefox needs to use.

DUI:gtk3::red:

screenie
Dynamic ui test.
Creates fields/labels from items in a data structure.

Here for reference only. I've since moved from Red to Vala.

Red [ needs 'view ] ;; tag used for single line strings (fields), thanks to Boleslav Březovský re: "string" vs {string} recycle/off articledata: context[ thisis: 'articledata name: <article name> index: 1 ;; used for sorting poster: %./imagefile.png video: %./videofile.mp4 article: {article text^/goes here} onclick: protocol://path.goes.here credits: {credits^/* go^/* here} references: [ protocol://url.goes.here protocol://url.goes.here ] ] getext: func [ f ] [ last split to-string f "." ] makeparams: func [ d ] [ k: d/thisis w: words-of d v: values-of d i: 1 n: copy [] append n [ below ] foreach p w [ switch mold type? v/:i [ "integer!" [ append n compose/deep [ across text (to-string p) text (to-string v/(i)) return below ] ] "tag!" [ append n compose/deep [ text (to-string p) field 200x55 with [ text: (to-string v/(i)) ] on-change [ (to-set-path compose [ (k) (p) ]) to-tag face/text src/text: (quote mold ) (k) ] ] probe n ] "string!" [ append n compose/deep [ text (to-string p) area 200x100 with [ text: (to-string v/(i)) ] on-change [ (to-set-path compose [ (k) (p) ]) face/text src/text: (quote mold ) (k) ] ] ] "url!" [ append n compose/deep [ text (to-string p) field 200x55 with [ text: (to-string v/(i)) ] on-change [ (to-set-path compose [ (k) (p) ]) to-url face/text src/text: (quote mold ) (k) ] ] ] "block!" [ append n compose/deep [ text (to-string p) text-list 200x100 data [(v/(i))] on-change [ (to-set-path compose [ (k) (p) ]) face/data src/text: (quote mold ) (k) ] ] ] "file!" [ either (getext v/:i) = "png" [ append n compose/deep [ text (to-string p) image 200x200 with [ image: load (v/(i)) ] on-up [ img: request-file/filter ["pics" "*.png"] unless none? img [ img: to-file rejoin [ "./" second split-path img ] if exists? img [ face/image: load img unless none? face/image [ (to-set-path compose [ (k) (p) ]) img src/text: (quote mold ) (k) ] ] ] ] ] ] [ print [ "file not a png, skipping..." ] ] ] ] i: i + 1 ] n ] nudgev: func [ ] [ aa/offset/x: 0 pp/offset/y: 0 vv/offset/y: 0 aa/offset/y: 0 bb/offset/y: 0 aa/size/x: vv/offset/x src/size/x: aa/size/x - 20 bb/offset/x: vv/offset/x + vv/size/x bb/size/x: pp/size/x - (vv/offset/x + vv/size/x) cc/size/x: bb/size/x - 70 ] view/tight/flags/options [ title "auto param test" pp: panel 650x600 255.0.0 [ aa: panel 300x600 30.30.30 [ below src: area 300x510 40.40.40 font-name "consolas" font-size 10 font-color 128.255.128 doit: button 120x55 30.30.30 "update" font-name "consolas" font-size 16 font-color 128.128.128 [ tmp: do [ reduce load src/text ] articledata: reduce copy tmp/1 src/text: (mold articledata) clear cc/pane append cc/pane layout/only makeparams articledata ] ] vv: panel 10x600 15.15.15 loose on-drag [ nudgev ] bb: panel 300x600 30.30.30 [ cc: panel 300x1000 60.60.60 loose [ ] on-drag [ face/offset/x: 10 face/offset/y: min face/offset/y 10 ] on-wheel [ either event/picked > 0 [ face/offset/y: face/offset/y + 40 ] [ face/offset/y: face/offset/y - 40 ] bo: (bb/size/y - face/size/y) - 100 bo: min bo 0 face/offset/y: max bo min face/offset/y 10 ] ] ] do [ aa/offset/x: 0 append cc/pane layout/only makeparams articledata src/text: (mold articledata) nudgev ] ] [ resize ] [ actors: object [ on-resizing: function [ face event ] [ if face/size/x > 500 [ if face/size/y > 300 [ pp/size: face/size vv/size/y: face/size/y aa/size/y: face/size/y bb/size/y: face/size/y vv/offset/x: face/size/x - (bb/size/x + vv/size/x) doit/offset/y: face/size/y - (doit/size/y + 100) src/size/y: doit/offset/y - 20 nudgev ] ] ] ] ]
PIC
E72:pic::glsl::demo:
SDF fragment shader

Besides the watermark, this image is sdf math, including text decals, shader is here
It is not optimized; there is no bvh. It will cook your device, crash your display driver and log you out... view at your own risk.

Relies heavily on examples published by:
  • Inigo Quilez
  • Jamie Wong

Prototyped on cpu in Houdini Vex for safety, before finishing it off in KodeLife.
Render above is from the vex version, as its trivial to output an image sequence from Houdini.

Conclusion to this test: AA kills it. Running it on client hardware too risky. Try again later with WebGPU+Vulkan...

Not made for Bahco. Chosen as its a simple product to model, has text and movable parts, had the measurements on-hand.
2010s
PIC
multisolver:pic::hou::demo:
Supernova Slith:pic::hou::cine:
Slith fx lookdev
credits
Supernova_Slith

Who made this at Axis Productions

Modelling:
uncredited

Shaders:
Sergio Caires

Rigging:
David Gonzalez
Guilia Dell'Armi
Jose Cuenca
Marco Baldi
Mario Aquaro

Animation/Previz:
Kevin McDade
Luke Smith
Si Qi Ho
Steven Graham
Thorsten Kesse
Tracey Chung

FX:
Craig Brown
Hudson Martin
Jayden Patterson
Ola Hamlesten

Lighting/Compositing:
Abby Bar
Daniel Schindler
John Barclay
Romain Ferchat

Editing:
Louise McGreggor

Art Direction:
Ben Craig
GreyGoo Battle:pic::hou::cine:
Weapon fx, smoke, rbd sim, fluid sim

uncredited
wiresolver:pic::hou::demo:
CloneWars comets:pic::tvs:
Comet modeling, shading and scripting, cracked glass model
Lookdev & implementation
credits
Clonewars_Comets

Created and Executive Produced by: George Lucas

Supervising Director: Dave Filoni

Produced by: Cary Silver

Score by: Kevin Kiner

Original Star Wars Themes and Score by: John Williams

Line Producer: Athena Yvette Portillo

Supervising Editor or Editor: Jason W.A. Tucker

CG Supervisor - Lighting & FX: Joel Aron

Digital Asset Supervisor: Paul Zinnes

Animation Supervisor: Keith Kellogg

Lead Designer: Kilian Plunkett

Lead Modeler: Chris Bostjanick

Modelers:
John Dodelson
Jon Childress Farmer
Julian Gupner
Corey Weekley

Digital Artists:
Sang Lee
Cassandra Legro

Riggers:
Nicholas Bolden
Franklin Chance
Eddy Piedra

Texture Artists:
Kazunori Aruga
Ken Min
Pouchon Venerin

Lead 3D Story Artist: Daniel Zizmor

Lead Animator: Marchand Jooste

Senior Animators:
Alex Szeto Fai
Gaurav Dubey
JC Wong
Jim Hatibarua
Nirmal David Kolady

Animators:
Ong Geng Biao Alex
Bradley Lorimer
Chiong Ee Jun
Chng Siwei
Chua Han Xiang
Denis Tong Hor Kin
Gan Sze Ching
Jackson Yeoh
Joe Chye
Khet Yee Sang
Mahendra S. Sikarwar
Mohamed Irfan Syarial B Sharif
Norman Chong
Rishi Kaul
Shannan Wong
Vinod Reddy
Viru Sohal
Wong Chin Chiu Chris

Senior Layout Artist: Jebb Ng Ho Ting

Layout Artists:
Irene Koh Ailing
Lai Yeow Kuang
Vincent Sng

Overseas Associate Producer: Aamir Ghani

CG Supervisor: John Kilshaw

Overseas Associate Production Manager: Ellen Xie

Production Coordinators:
Ngan San San
Sarah Tan
Vanessa Seow

Production Assistants:
Christine S. Chan
Irene Cai
Joyce RuiFen Liew
Pearlyn Yeo

Production Accountant: Lynn Tan Si Min

Crowd Technical Director: Prashanth Bhagavan

Effects Lead: Craig Brown

Senior Effects Artist: Jimmy Leung Yin Lai

Effects Artists:
Chan Yuk Leung Mo
Daniel Li Chung Kei
Ricky Yau Kar Yin
Yau Kiu Fung Kaze

Digital Supervisor: Benjamin Radcliffe

Lead Lighting & Compositing Artist: Leo Liao Feng I

Senior Lighting & Compositing Artists:
Eugene Ko Jaehyuk
Jack Yeung Pak Man
Jesse Hildreth
Kathy Chi Sin Yu

Lighting & Compositing Artists:
CY Shih, Eric Tung Wai Chun
Gary K.L. Wong
Lo Wai Lun
Max Mak Tsz Yeung
Oliver Summa
Riuku Chiang Cho Leuk
Tuck Yin Wong
Woon Chi

Matte Painters: Shyam S. Deshpande

Rigging / Pipeline Lead: Seema Gopalakrishnan

Riggers:
Li Feng
C Man
Huang Shicong
Jiet Shern Neo

Lead Asset Artist: Josh Robinson

Senior Asset Artists:
Bobby Yoonsung Jeong
Harsh Borah

Asset Artists:
Low Hiang Yong Ron
Rajbir Singh Dhalla
Ridwan Chandra Choa
Zeng XiangJun

Editor: Nic Anastassiou

Associate Editor: Mathias Hilger

1st Assistant Editor: Kevin Stermer

2nd Assistant Editor: Nate Cormier

Music Editor: Dean Menta

Additional Music by:
Takeshi Furukawa
David Russell
Matthew St. Laurent

Colorist: Sean Wells

Story & Script Development: Steve Tzirlin

Script & Continuity Assistant Production Manager: Gary Scheppke

Script Coordinator: Darci DuBose

Casting Coordinator: Meagan Finnerty

Look Development Production Coordinator: Liz Marshall

Look Development Production Assistant: Megan Engle

Asset Production Supervisor: David Gray

Asset Production Coordinator: Betsy DeHont

Asset Production Assistant: Andy Heitz

3D Story Production Supervisor: Kristine Donovan

3D Story Production Coordinator: Sarah Lister

3D Story Production Assistant: Alex Spotswood

Animation, Lighting, & FX Coordinator: Julie Osborn

Animation & Cloth Production Assistants:
Caitlin Satchell
Brendan Szulik

Studio Post Production & Editorial Manager: Trisha Brunner

Editorial Production Assistant: Alyson Pierce

Editorial Technician: Charles Choo Jr.

Manager of Production Accounting: Darren Cowan

Production Accountant: Michael Peters

Studio Operations: Colum Slevin

Executive Assistant to George Lucas: Jane Bay

Assistant to George Lucas: Anne Merrifield

Additional Production Support:
Lynn Bartsch
Rob Bonstin
Diane Caliva
Brooke Chapman Gregory Tremelling Nick Provenzano / Michael Parkinson
Betsy Delis
Rob Gianino
Kara Henander
Clay Brown Gabrielle Levenson Tu-Anh Nguyen Karessa Bowens Anton Agana / Drew Patterson
Jayesh Dalal Lance Engle Dave Peticolas
Stacy Lundin
Herbert Primig
Trish Rush
Nicole Vigil
Rob Wynn

Scoring Mixer: Mark Evans

Dialogue Recording Services by: The L.A. STUDIOS, Inc.

Dialogue Recordist: Cameron Davis

Assistant Dialogue Recordist: Ryan Coursey

Post Production Sound Services provided by Skywalker Sound, a Lucasfilm Ltd. Company, Marin County, California

Supervising Sound Editor: Matthew Wood

Sound Designer: David Acord

Re-Recording Mixer: David Acord

Head of Animation Technologies: Monique Bradshaw

Quality & Control Lead: Angela Traeger

Pipeline Technical Director: Josh Rowe

Assistant Technical Directors:
Hoa Quang Bui
Gary Huang
David H. Lam
Derek Smith
Cooper Welch
Adrian Tan Seng Kee
CherFong Foo
Ding Xian Cong
Oliver S. Magno
Ong Chiak Shi

Technology Coordinator: Ariel Owens-Barham

Technical Assistants:
Doug Jung
Carl Leland Taylor
Eric Weber
Albin Ng
Beverley Joy G. Ang
Cai Weiyu
Chee Jun Ghai
Christian Gloor
Feon Sua Xin Miao
Francis Woon
Lau E. H. Melvin
Lee Jin Long
Lin YuanJing

Head of Software Development: Tommy Burnette

Project Manager:
Jessica A. Taul
Aishwarya RTK Prasad

Associate Project Manager: Chris Yeo Keng Hong

Software Manager: Mike King

Technical Resource Supervisor:
Christopher Marklund
Betty Shaw

Global Pipeline Engineers:
Aurelien Collard
Mark Hopkins
Zou Yan

Senior IS Developer: Senthil Kumaran

IS Developer: Steven Neo Say Bin

Lead Production Engineer: Boon Hean Low

Production Engineers:
Ed Caspersen
Purnell Davis III
Joe Hura
Akanksha Sahu
Stephan Steinbach
Alvin Ho Tsun Chuen

Junior Production Engineer:
Haw Shijun
Tien Vu Ho

Database Administrator: Yoel Ade Susanto

IT Manager:
Joe Giller
Teoh Shian Phan

IT Support:
Alan Malicse
Clayton Siemens
Azmi Mohamed Maniku
Barry Dexter A. Gonzaga
Benj Cabrera III
Brian V. Balundo
Chriciel DeChavez Rosel
Chris Chua Moo Lian
Dennis M. Allarey
Didik Achmadi
E. Michael Brown
Harvey B. Alegrado
Hendra Kieran
Japril Cudilla
Joanne Sze Kit Ying
Joseph Kan
Lim Soo Ghee Anthony
Nic Brown
Noorwallid Osman
Roy Halim
Sean S.R. Yeo
Tan Hua Pui Sebastian
Teo Say Chong
Ye Lynn Kyaw

Rights and clearances by:
Entertainment Clearances, Inc.
Cassandra Barbour
Laura Sevier
CloneWars Saber vs Stun:pic::tvs:
Saber vs stun-ring, saber vs pipe
Lookdev & implementation
credits
Clonewars_Saber_vs_Stun

Created and Executive Produced by: George Lucas

Supervising Director: Dave Filoni

Produced by: Cary Silver

Score by: Kevin Kiner

Original Star Wars Themes and Score by: John Williams

Line Producer: Athena Yvette Portillo

Supervising Editor or Editor: Jason W.A. Tucker

CG Supervisor - Lighting & FX: Joel Aron

Digital Asset Supervisor: Paul Zinnes

Animation Supervisor: Keith Kellogg

Lead Designer: Kilian Plunkett

Lead Modeler: Chris Bostjanick

Modelers:
John Dodelson
Jon Childress Farmer
Julian Gupner
Corey Weekley

Digital Artists:
Sang Lee
Cassandra Legro

Riggers:
Nicholas Bolden
Franklin Chance
Eddy Piedra

Texture Artists:
Kazunori Aruga
Ken Min
Pouchon Venerin

Lead 3D Story Artist: Daniel Zizmor

Lead Animator: Marchand Jooste

Senior Animators:
Alex Szeto Fai
Gaurav Dubey
JC Wong
Nirmal David Kolady

Animators
Chiong Ee Jun
Chng Siwei
Chua Han Xiang
Denis Tong Hor Kin
Gan Sze Ching
Jackson Yeoh
Joe Chye
Mahendra S. Sikarwar
Mohamed Irfan Syarial B Sharif
Norman Chong
Ong Geng Biao Alex
Rishi Kaul
Shannan Wong
Vinod Reddy
Viru Sohal
Wong Chin Chiu Chris

Senior Layout Artist: Jebb Ng Ho Ting

Layout Artists:
Irene Koh Ailing
Lai Yeow Kuang
Vincent Sng

Overseas Associate Producer: Aamir Ghani

CG Supervisor: John Kilshaw

Overseas Associate Production Manager: Ellen Xie

Production Coordinators:
Ngan San San
Sarah Tan
Vanessa Seow

Production Assistants:
Irene Cai
Joyce RuiFen Liew
Pearlyn Yeo

Production Accountant: Lynn Tan Si Min

Senior Cloth Artist: Kah Jeng Cheong
Cloth Artists:
AJ Siytangco
Chelsea Khoo Hui Ming
Jiang Han
K. Kothandaraman
Shiv sundar

Crowd Technical Director: Prashanth Bhagavan

Effects Lead: Craig Brown

Senior Effects Artist: Jimmy Leung Yin Lai

Effects Artists:
Chan Yuk Leung Mo
Daniel Li Chung Kei
Ricky Yau Kar Yin
Yau Kiu Fung Kaze

Digital Supervisor: Benjamin Radcliffe

Lead Lighting & Compositing Artist: Leo Liao Feng I

Senior Lighting & Compositing Artists:
Eugene Ko Jaehyuk
Jack Yeung Pak Man
Jesse Hildreth
Kathy Chi Sin Yu

Lighting & Compositing Artists:
CY Shih
Eric Tung Wai Chun
Gary K.L. Wong
Lo Wai Lun
Max Mak Tsz Yeung
Oliver Summa
Riuku Chiang Cho Leuk
Tuck Yin Wong
Woon Chi

Matte Painters: Shyam S. Deshpande

Rigging / Pipeline Lead: Seema Gopalakrishnan

Riggers:
C Man
Huang Shicong
Jiet Shern Neo

Lead Asset Artists: Josh Robinson

Senior Asset Artists:
Bobby Yoonsung Jeong
Semin Tho

Asset Artists:
Rajbir Singh Dhalla
Zeng XiangJun

Editor: Nic Anastassiou

Associate Editor: Mathias Hilger

1st Assistant Editor: Kevin Stermer

2nd Assistant Editor: Nate Cormier

Music Editor: Dean Menta

Additional Music by:
Takeshi Furukawa
David Russell
Matthew St. Laurent

Colorist: Sean Wells

Story & Script Development: Steve Tzirlin

Script & Continuity Assistant Production Manager: Gary Scheppke

Script Coordinator: Darci DuBose

Casting Coordinator: Meagan Finnerty

Look Development Production Coordinator: Liz Marshall

Look Development Production Assistant: Megan Engle

Asset Production Supervisor: David Gray

Asset Production Coordinator: Betsy DeHont

Asset Production Assistant: Andy Heitz

3D Story Production Supervisor: Kristine Donovan

3D Story Production Coordinator: Sarah Lister

3D Story Production Assistant: Alex Spotswood

Animation, Lighting, & FX Coordinator: Julie Osborn

Animation & Cloth Production Assistants:
Caitlin Satchell
Brendan Szulik

Studio Post Production & Editorial Manager: Trisha Brunner

Editorial Production Assistant: Alyson Pierce

Editorial Technician: Charles Choo Jr.

Manager of Production Accounting: Darren Cowan

Production Accountant: Michael Peters

Studio Operations: Colum Slevin

Executive Assistant to George Lucas: Jane Bay

Assistant to George Lucas: Anne Merrifield

Additional Production Support:
Lynn Bartsch
Rob Bonstin
Diane Caliva
Brooke Chapman Gregory Tremelling Nick Provenzano / Michael Parkinson
Betsy Delis
Rob Gianino
Kara Henander
Clay Brown Gabrielle Levenson Tu-Anh Nguyen Karessa Bowens Anton Agana / Drew Patterson
Jayesh Dalal Lance Engle Dave Peticolas
Stacy Lundin
Herbert Primig
Trish Rush
Nicole Vigil
Rob Wynn

Scoring Mixer: Mark Evans

Dialogue Recording Services by: The L.A. STUDIOS, Inc.

Dialogue Recordist: Cameron Davis

Assistant Dialogue Recordist: Ryan Coursey

Post Production Sound Services provided by: Skywalker Sound, a Lucasfilm Ltd. Company, Marin County, California

Supervising Sound Editor: Matthew Wood

Sound Designer: David Acord

Re-Recording Mixer: David Acord

Head of Animation Technologies: Monique Bradshaw

Quality & Control Lead: Angela Traeger

Pipeline Technical Director: Josh Rowe

Assistant Technical Directors:
Hoa Quang Bui
Gary Huang
David H. Lam
Derek Smith
Cooper Welch
CherFong Foo
Ding Xian Cong
Oliver S. Magno
Ong Chiak Shi

Technology Coordinator: Ariel Owens-Barham

Technical Assistants:
Doug Jung
Carl Leland Taylor
Eric Weber
Albin Ng
Beverley Joy G. Ang
Cai Weiyu
Chee Jun Ghai
Christian Gloor
Feon Sua Xin Miao
Francis Woon
Lau E. H. Melvin
Lee Jin Long
Lin YuanJing

Head of Software Development: Tommy Burnette

Project Manager:
Jessica A. Taul
Aishwarya RTK Prasad

Associate Project Manager: Chris Yeo Keng Hong

Software Manager: Mike King

Technical Resource Supervisor:
Christopher Marklund
Betty Shaw

Global Pipeline Engineers:
Aurelien Collard
Mark Hopkins
Zou Yan

Senior IS Developer: Senthil Kumaran

IS Developer: Steven Neo Say Bin

Lead Production Engineer: Boon Hean Low

Production Engineers:
Ed Caspersen
Purnell Davis III
Joe Hura
Akanksha Sahu
Stephan Steinbach
Alvin Ho Tsun Chuen

Junior Production Engineer:
Haw Shijun
Tien Vu Ho

Database Administrator: Yoel Ade Susanto

IT Manager:
Joe Giller
Teoh Shian Phan

IT Support:
Alan Malicse
Clayton Siemens
Azmi Mohamed Maniku
Barry Dexter A. Gonzaga
Benj Cabrera III
Brian V. Balundo
Chriciel DeChavez Rosel
Chris Chua Moo Lian
Dennis M. Allarey
Didik Achmadi
E. Michael Brown
Harvey B. Alegrado
Hendra Kieran
Japril Cudilla
Joanne Sze Kit Ying
Joseph Kan
Lim Soo Ghee Anthony
Nic Brown
Noorwallid Osman
Roy Halim
Sean S.R. Yeo
Tan Hua Pui Sebastian
Teo Say Chong
Ye Lynn Kyaw

Rights and clearances by:
Entertainment Clearances, Inc.
Cassandra Barbour
Laura Sevier
Racoon City fire:pic::hou::cine:
Fire and smoke simulation

uncredited
Diablo3 mist:pic::3ds::hou::cine:
Particles

credits
... are here:
https:www.mobygames.com/game/windows/diablo-iii/credits
Diablo3 re-entry:pic::3ds::cine:
Re-entry effect

credits
... are here:
https:www.mobygames.com/game/windows/diablo-iii/credits
TXT
vex:hou::vex:
mostly SOPs
get centroids:hou::vex:
int pp = addpoint(0,@P); vector nn = primuv(0,"N",@primnum,{0.5,0.5,0.0}); setpointattrib(0,"N",pp,nn); removeprim(0,@primnum,1);
normalized distance:hou::vex:
float maxd = 0.0; float mind = 99999.0; vector cp = set(ch("cpx"),ch("cpy"),ch("cpz")); for (int i = 0; i < @numpt; i++) { float d = distance(point(0,"P",i),cp); if (d > maxd) { maxd = d; } if (d < mind) { mind = d; } } @mind = mind; @maxd = maxd; @perp = clamp(((distance(@P,cp) - mind) / (maxd - mind)),0.0,1.0);
offset curve points:hou::vex:
float vv = (@ptnum*1.0)/(@numpt-1.0); vv = ((vv+ch("ofs"))%1.0); vector uvw = set(vv,0,0); @P = primuv(0,"P",0,uvw);
stacker:hou::vex:

Used to animate neon letters in sequence.

int pmax = prim(1,"textindex",0); int pnum = prim(0,"textindex",@primnum); float mo = (ch("ofs") % pnum); int p = pnum+mo; int m = (pmax+2) * @lm * ch("ll"); int x = pnum+mo; for (int i = 0; i<=ch("oo"); i++){ if (rint(p*m)!=x){ x = x + 1; } } //@wtf = x; @Cd = set(((x%m)==0),0,0);
prim in group:hou::vex:
int cc = i@class; string gn = "segment_" + itoa(cc); int hh = inprimgroup(0,gn,@primnum); if (hh == 1) { //do stuff here... }
carpetbombing:hou::vex:

(originally made for a carpet shader)
clamp down nn even further if there's warping.

float sc = 5.0; float spr = sc*0.5; int ten = 500; vector aa = set(0.0,0.0,0.0); for (int i = 0; i <= ten; i++) { float uu = $uv.x; float vv = $uv.y; float rr = random(i); uu = uu - 0.5; vv = vv - 0.5; uu = uu * sc; vv = vv * sc; matrix mx = 1; float dr = (rr * 360.0); dr = radians(dr); rotate(mx,dr,{0,0.0,1.0}); vector bb = set(uu,vv,0.0); bb = bb * mx; uu = bb.x; vv = bb.y; uu = uu + 0.5; vv = vv + 0.5; uu = uu+(((rand(i)*2)-1)*spr); vv = vv+(((rand(i+1)*2)-1)*spr); bb = set(uu,vv,0); float zz = length(bb - {0.5,0.5,0}); zz = 1 - clamp(zz,0.0,1.0); zz = fit(zz,0.45,1.0,0.0,1.0); float nn = anoise(((bb+rand(i+2))*2.0), 4, 0.8, (1-zz)); nn = nn * zz; float msx = (uu >= 0.0) && (uu <= 1.0); float msy = (vv >= 0.0) && (vv <= 1.0); float ms = msx * msy; zz = zz * ms; nn = fit(nn,0.19,0.2,0.0,1.0); nn = nn * ms; ms = ms * nn; bb = set((aa.x * (1-ms)) + (uu * ms), (aa.y * (1 - ms)) + (vv * ms),0.0); aa = bb; } $atlas = aa;
floorboards:hou::vex:

Probably obsolete, updated in Blender. Hopefully won't need to backport it.
Use $atlas for uvs, $rando to switch between several maps for more variety.

float sc = 5.0; float vg = $mm.y; float ug = $mm.x; float uu = $uv.x; float vv = $uv.y; uu = uu - 0.5; vv = vv - 0.5; uu = uu * sc; vv = vv * sc; uu = uu + 0.5; vv = vv + 0.5; uu = uu%1.0; vv = vv%1.0; float iv = int(vv * vg)/(vg-1); uu = uu + iv; float iu = int(uu * ug)/(ug-1); vv = vv + iu; float ru = rand(iu); float rv = rand(iv+ru); ru = rand(iu + rv + 5); uu = uu - ((iu - ru)*((1.0/ug)*(ug-1))); vv = vv - ((iv - rv)*((1.0/vg)*(vg-1))); uu = uu%1.0; vv = vv%1.0; //uu = ru; //vv = rv; vector bb = set(uu,vv,0); $atlas = bb; $rando = iu + rv;
colorbleed:hou::vex:
int @ptnum; int n =neighbourcount(0,@ptnum); float maxval = 0.0; for (int i=0; i <= n; i++) { int nn = neighbour(0,@ptnum,i); float cr = point(0,"Cd",nn); cr = cr * rand(nn); if (cr > @Cd.r) { maxval = cr; maxval = (@Cd.r + ((maxval - @Cd.r) * 0.5)); @Cd = set(maxval, maxval, maxval); } }
wetmap:hou::vex:
int h = pcopen(2,"P",@P,0.1,50); float mcd = point(1,"Cd",@ptnum); while (pciterate(h)) { vector ocd = {0,0,0}; pcimport(h,"Cd",ocd); if (ocd.r > mcd) { mcd = ocd.r; } } pcclose(h); @Cd = set(mcd,mcd,mcd);
shelftools:hou::py:
funnel:hou::py:

Last used with Houdini 18, probably obsolete.

# merge all visible sops from one object into another. # useful for converting assets, FBX and Alembics. # by c.p.brown. 2014~2018 import os nos = [] ds = [] dp = [] tn = "" us = hou.selectedNodes() for i in us : if i.type().category().name() == "Object" : nos.append(i) tn = i.name() c = 0 while len(nos) > c : for i in nos : subs = i.children() for s in subs : if s.type().category().name() == "Sop" : if s.type().isManager() == False : if s.isDisplayFlagSet() == True : if (s in ds) != True : ds.append(s) dp.append(s.path()) else: try: if s.isDisplayFlagSet() == True : nos.append(s) except: print("\tinvisible node found") c = (c + 1) c = 0 if len(ds) > 0 : for i in ds : print("harvested display SOP: " + i.name()) print("\t" + dp[c]) c = (c + 1) try: co = hou.node('/obj/funneled') print('found existing bgeo node : ' + co.name() + ', using it...') except: print("bgeo node not found, creating it...") obj = hou.node('/obj') co = obj.createNode("geo", "funneled") xu = co.children() for u in xu : u.destroy() omcr = 0 cvcr = 0 xfcr = 0 sncr = 0 swncr = 0 svcr = 0 swvcr = 0 cvncr = 0 rfcr = 0 bfcr = 0 swcr = 0 smcr = 0 outncr = 0 try: om = hou.node('/obj/funneled/merge_display_sops') print('object merge exists, clearing it...') om.parm("numobj").set(0) except: print('object merge SOP not found, creating it...') om = co.createNode("object_merge", "merge_display_sops") om.setCurrent(True) om.setSelected(True) om.setDisplayFlag(True) om.parm("xformtype").set(1) omcr = 1 c = 1 om.parm("numobj").set(len(ds)) for i in dp : om.parm("objpath" + str(c)).set(i) c = (c + 1) try: xf = hou.node('/obj/funneled/xf_fix') print('transform fix found: ' + xf.name() + ', using it...') if omcr == 1 : xf.setInput(0,om) except: print('transform SOP not found, creating it...') xf = co.createNode('xform', 'xf_fix') xf.setInput(0,om) xfcr = 1 try: cv = hou.node('/obj/funneled/convert_to_poly') print('converter found: ' + cv.name() + ', using it...') if xfcr == 1 : cv.setInput(0,xf) except: print('convert_to_poly SOP not found, creating it...') cv = co.createNode('convert', 'convert_to_poly') cv.setInput(0,xf) cvcr = 1 try: sn = hou.node('/obj/funneled/set_normals') print('normal found: ' + sn.name() + ', using it...') if cvcr == 1 : sn.setInput(0,cv) except: print('normals SOP not found, creating it...') sn = co.createNode('normal', 'set_normals') sn.setInput(0,cv) sncr = 1 try: swn = hou.node('/obj/funneled/normals_switch') print('normals switcher found: ' + swn.name() + ', using it...') if cvcr == 1: swn.setNextInput(cv) if sncr == 1: swn.setNextInput(sn) except: print('switch normals SOP not found, creating it...') swn = co.createNode('switch', 'normals_switch') swn.setNextInput(cv) swn.setNextInput(sn) swncr = 1 try: sv = hou.node('/obj/funneled/set_v') print('normal found: ' + sv.name() + ', using it...') if swncr == 1 : sv.setInput(0,swn) except: print('trail SOP not found, creating it...') sv = co.createNode('trail', 'set_v') sv.parm('result').set(3) sv.setInput(0,swn) svcr = 1 try: swv = hou.node('/obj/funneled/vel_switch') print('velocity switcher found: ' + swv.name() + ', using it...') if swncr == 1: swv.setNextInput(swn) if svcr == 1: swv.setNextInput(sv) except: print('switch velocity SOP not found, creating it...') swv = co.createNode('switch', 'vel_switch') swv.setNextInput(swn) swv.setNextInput(sv) swvcr = 1 try: cvn = hou.node('/obj/funneled/converted') print('Null found: ' + cvn.name() + ', using it...') if swvcr == 1 : cvn.setInput(0,swv) except: print('null SOP not found, creating it...') cvn = co.createNode('null', 'converted') cvn.setInput(0,swv) cvncr = 1 try: rf = hou.node('/obj/funneled/save_bgeo') print('ROP found: ' + rf.name() + ', using it...') except: print('ROP not found, creating it...') rf = co.createNode('rop_geometry', 'save_bgeo') rf.parm('trange').set(1) rf.parm('sopoutput').set('$HIP/bgeo/`opname("..")`/`opname("..")`.$F.bgeo.sc') rf.setInput(0,cvn) rfcr = 1 try: bf = hou.node('/obj/funneled/saved_bgeo') print('file-sop found: ' + bf.name() + ', using it...') except: print('file SOP not found, creating it...') bf = co.createNode('file', 'saved_bgeo') bf.parm('file').set('$HIP/bgeo/`opname("..")`/`opname("..")`.$F.bgeo.sc') bfcr = 1 try: sw = hou.node('/obj/funneled/geo_switcher') print('geo switcher found: ' + sw.name() + ', using it...') if xfcr == 1: sw.setNextInput(xf) if cvncr == 1: sw.setNextInput(cvn) if bfcr == 1: sw.setNextInput(bf) except: sw = co.createNode('switch', 'geo_switcher') sw.setNextInput(xf) sw.setNextInput(cvn) sw.setNextInput(bf) swcr = 1 try: sm = hou.node('/obj/funneled/set_material') print('set_material found: ' + sm.name() + ', using it...') if swcr == 1 : sm.setInput(0,sw) except: print('material SOP not found, creating it...') sm = co.createNode('material', 'set_material') sm.parm('shop_materialpath1').set('/shop/`opname("..")`') sm.setInput(0,sw) smcr = 1 try: outn = hou.node('/obj/funneled/OUT') print('OUT Null found: ' + outn.name() + ', using it...') if smcr == 1 : outn.setInput(0,sm) except: print('OUT null SOP not found, creating it...') outn = co.createNode('null', 'OUT') outn.setInput(0,sm) outncr = 1 outn.setCurrent(True) outn.setSelected(True) outn.setDisplayFlag(True) outn.setRenderFlag(True) acr = omcr + cvcr + xfcr + sncr + swncr + svcr + swvcr + cvncr + rfcr + bfcr + swcr + smcr + outncr if acr > 0 : co.layoutChildren()
nativecam:hou::py:

Last used with Houdini 18, probably obsolete.

# convert alembic camera to native # by cpbrown abc = hou.selectedNodes() ds = [] dp = [] nos = [] for i in abc: if i.type().category().name() == "Object" : nos.append(i) print("selected objects: " + str(nos)) c = 0 while len(nos) > c : for i in nos : subs = i.children() for s in subs : print("checking sub-node type : " + s.type().name()) if s.type().name() == "cam" : if (s in ds) != True : ds.append(s) dp.append(s.path()) if s.type().category().name() == "Object" : nos.append(s) c = c + 1 if len(ds) > 0 : c = 0 obj = hou.node('/obj') ch = 0 try: ch = hou.node('/obj/cam_convert') print("chopnet found, using it : " + ch.path()) xu = ch.children() for u in xu: u.destroy() except: print("chopnet not found, creating it...") ch = obj.createNode("chopnet", "cam_convert") oo = ch.createNode("ropnet", "save_animation") print("ropnet: " + oo.path()) for i in ds : print("\tharvested camera: " + i.name()) print("\t" + dp[c] + "\n") cc = 0 try: cc = hou.node('obj/native_cam_' + str(c)) print("\tnative camera found, using it : " + cc.path()) except: print("\tnative camera not found, creating it...") cc = obj.createNode("cam", ("native_cam_" + str(c))) print("\t\tnative cam : " + cc.path()) fe = ch.createNode("fetch", ("fetch_cam_parms_" + str(c))) fe.parm('nodepath').set(i.path()) fe.parm('path').set('aperture focal') ge = ch.createNode("object", ("get_cam_xf_" + str(c))) ge.parm('targetpath').set(i.path()) ge.parm('compute').set(8) mg = ch.createNode("merge", ("merge_channels_" + str(c))) mg.setNextInput(ge) mg.setNextInput(fe) sm = ch.createNode("null", "LIVE_" + str(c)) sm.setInput(0,mg) fi = ch.createNode("file", ("load_saved" + str(c))) fi.parm('file').set('$HIP/clip/native_cam_' + str(c) + '.bclip') sw = ch.createNode("switch", ("switch_to_saved" + str(c))) sw.setNextInput(sm) sw.setNextInput(fi) ou = ch.createNode("export", "OUT_" + str(c)) ou.setInput(0,sw) ou.parm('nodepath').set(cc.path()) ou.parm('path').set('tx ty tz rx ry rz sx sy sz aperture focal') ou.setCurrent(True) ou.setSelected(True) ou.setDisplayFlag(True) ou.setExportFlag(True) bc = oo.createNode("channel", ("save_bclip_" + str(c))) bc.parm('choppath').set(sm.path()) bc.parm('chopoutput').set('$HIP/clip/native_cam_' + str(c) + '.bclip') ch.layoutChildren()
objmerge:hou::py:
import glob import os hp = hou.hipFile.path() f = hou.ui.selectFile(multiple_select=True,start_directory=hp,file_type=hou.fileType.Geometry) print("f=" + str(f)) if f != '' : fc = f.split(';') if len(fc) > 0 : c = 0 obj = hou.node("/obj") npn = obj.createNode("geo",fc[0].split('/')[-1:][0].split('.')[0].strip()) xu = npn.children() for u in xu : u.destroy() mrg = npn.createNode("merge") for k in fc: dn = k.split('/')[-1:][0].split('.')[0].strip() print("dn="+dn) nfn = mrg.createInputNode(c,"file") nfn.parm('file').set(k.strip()) c = c + 1 npn.layoutChildren()
deadline:hou::py:
Made in anger.

Originally developed to bypass a whole department of studio 'pipeline' grifters, who later ratfucked it. This sort of problem was fairly common in vfx, and circumventing it could get you fired. Regardless, I'd always circumvent as a matter of professional hygiene.

The artist alone should be making decisions about how & when they work. If they get into trouble, they will get help from those they judge to be most effective. These are both important intrinsic skills that improve with use, atrophy with disuse.

Features of this script, that were lacking in the studio pipeline:
  • Send almost any ROP, and any number of selected ROPs to Deadline instantly with 1 click.
  • Not bother the artist with data-entry.
  • Work with vanilla daily-builds of Houdini.
  • Work with Houdini sessions launched however the artist likes.
  • Work with Hipfiles saved anywhere on the network (that the farm can see).
  • Support new ROPs by editing one line.

An pipeline ultimately boils down to a one-liner:
/path/to/program -arg "what the program needs to do"
Which takes surprisingly little effort to assemble. I've even seen artists type these direct commands faster than using a studio pipeline.

With Houdini, you the artist can even bring the chaosandanarchy by doing pipeline with vops; a native pipeline in your hipfile, not a single line of Python :)

Houdini to deadline sample shelftool (very old, obsolete):

# theoretical deadline job-submit shelftool # NOT TESTED: I've not had to do this for ages; have long-since switched to Linux + StuQ # use as reference only # by cpbrown 2016 & 2022 import os import string import getpass import time usr = getpass.getuser() fail = 0 pathtodeadline = "C:\\Program Files\\Thinkbox\\Deadline8\\bin\\deadlinecommand.exe" pathtohoudini = "C:\\hfs\\Houdini " + hou.applicationVersionString() nethfs = "N:\\hfs\\Houdini " + hou.applicationVersionString() ops = hou.selectedNodes() if len(ops) <= 0 : print('select a rop 1st...') fail = 1 for i in ops : otn = i.type().name() if otn != 'ifd' and otn != 'rop_geometry' and otn != 'rop_dop' and otn != 'geometry' and otn != 'wedge' and otn != 'rop_comp' and otn != 'comp' and otn != 'opengl': print('wrong node dude...') fail = 1 if fail == 0 : di = ("C:\\Users\\" + usr + "\\Desktop\\deadline_jobid\\") if not os.path.exists(di): os.mkdir(di) hscene = hou.hipFile.name() hname = hou.hipFile.path().split('.')[0].split('/')[-1] hdir = hou.hipFile.path().split('.')[0].split('/')[-3] deadlinecmd = "" xcmd = ("(xcopy \"" + nethfs + "\" \"" + pathtohoudini + "\\\" /d /e /v /c /r /y /h /i)") for i in ops : otn = i.type().name() opth = i.path() if otn == 'rop_geometry' or otn == 'rop_dop' or otn == 'geometry' or otn == 'wedge' or otn == 'rop_comp' or otn == 'comp' or otn == 'opengl' : opn = i.name() if otn == 'wedge' : drv = i.parm('driver').eval() wd = hou.node(drv) rng = wd.parm('trange').eval() if rng == 0 : fstart = str(int(hou.frame())) fend = fstart fdur = "1" else : fstart = str(int(wd.parm('f1').eval())) fend = str(int(wd.parm('f2').eval())) fdur = str(int(wd.parm('f2').eval() - (wd.parm('f1').eval()-1))) else : rng = i.parm('trange').eval() if rng == 0 : fstart = str(int(hou.frame())) fend = fstart fdur = "1" else : fstart = str(int(i.parm('f1').eval())) fend = str(int(i.parm('f2').eval())) fdur = str(int(i.parm('f2').eval() - (i.parm('f1').eval()-1))) deadlinecmd = "\"" + pathtodeadline + "\" -SubmitCommandLineJob -executable cmd.exe -arguments \"/c <QUOTE>" + nethfs + "\\bin\\hbatch.exe<QUOTE> -c <QUOTE>render " + opth + "<QUOTE> -c quit <QUOTE>" + hou.hipFile.path() + "<QUOTE>\" -frames " + fstart + "-" + fend + " -chunksize " + fdur + " -pool \"hbatch\" -priority 60 -name \"" + hname + "_" + opn + " - hbatch\" -initialstatus \"Active\" -prop MachineLimit=1" if otn == 'ifd' : opn = i.name() print('selected node is a mantra ROP : ' + opn) fstart = str(int(i.parm('f1').eval())) ifdf = i.parm('soho_diskfile').eval() ifdp = ifdf.split('.') if len(ifdp) > 1 : checkp = (ifdp[0] + '.' + fstart + '.' + ifdp[2]) print('checking ifd 1st frame : ' + checkp + '\n') if os.path.isfile(checkp) : rng = i.parm('trange').eval() ifs = i.parm('soho_diskfile').eval() ifa = ifs.split('.') ifs = (ifa[0] + '.<STARTFRAME>.' + ifa[2]) if rng == 0 : fstart = str(int(hou.frame())) fend = fstart else : fstart = str(int(i.parm('f1').eval())) fend = str(int(i.parm('f2').eval())) deadlinecmd = "\"" + pathtodeadline + "\" -SubmitCommandLineJob -executable cmd.exe -arguments \"/c <QUOTE>" + nethfs + "\\bin\\mantra.exe<QUOTE> -V 4a -j 0 -f <QUOTE>" + ifs + "<QUOTE>\" -frames " + fstart + "-" + fend + " -chunksize 1 -priority 60 -name \"" + hname + "_" + opn + "\" -pool \"mantra\" -initialstatus \"Active\" -prop MachineLimit=15" else : print('ifds are missing, write them out 1st...') else : print('ifd path not set...') if deadlinecmd != "" : print(deadlinecmd) j = (di + hname + "_" + opn + "_RENDER_jobID.txt") deadlinecmd = "(" + deadlinecmd + ")>>\"" + j + "\"" if not os.path.isdir(nethfs) : os.system(xcmd) os.system(deadlinecmd)
stuq:hou::py:

Stupidly simple Q

Used to replace Deadline for Indie work in 2017~2018.

Most of the code-bloat here is to compensate for the lack of $WEDGEVALUE in Houdini, preventing easy farming of wedge sub-ranges, a requirement at the time of writing stuq.


Stuq shelftool:
# batch command generator by c.p.brown, 2017~2019 # for encapsulated native projects # hbatch only # linux only import os import string import getpass import time from datetime import datetime from math import sqrt usr = getpass.getuser() pathtohoudini = "/opt/hfs" + hou.applicationVersionString() ops = hou.selectedNodes() # change this to whatever is default on your distro # don't use xterm as it locks-up houdini myfaveterm = "xfce4-terminal" # leading zeroes def prepadstr(instr, pad, padlen) : dif = (padlen - len(instr)) + 1 o = '' for i in range(1,dif) : o = o + pad o = o + instr #print(o) return(o) if len(ops) >= 1 : # get string vars for naming hscene = hou.hipFile.name() hname = hou.hipFile.path().split('.')[0].split('/')[-1].replace('_','-') hdir = hou.hipFile.path().split('.')[0].split('/')[-3].replace('_','-') hj = hou.hipFile.path().split('.')[0].split('/')[-2].replace('_','-') hprj = "/".join(hou.hipFile.path().split('.')[0].split('/')[:-2]) nx = datetime.strftime(datetime.now(),'%y%m%d_%H%M%S%f') print("\nthis project is : " + hprj) # setup the farm pendingdir = hprj + "/farm/pending" runningdir = hprj + "/farm/running" donedir = hprj + "/farm/done" themofile = hprj + "/farm/themo.sh" if not os.path.exists(pendingdir): os.makedirs(pendingdir) if not os.path.exists(runningdir): os.makedirs(runningdir) if not os.path.exists(donedir): os.makedirs(donedir) if not os.path.exists(themofile) : themoscript = """#!/bin/sh while true do iam=`hostname -s` mkdir ./running/$iam/ 2>/dev/null loc=`ls -1 ./pending/$iam/*.sh 2>/dev/null | wc -l` if [ $loc != 0 ]; then file=`ls ./pending/$iam/*.sh | head -n 1` echo $file if [ ! -z $file ]; then if [ -f $file ]; then src=$(readlink --canonicalize $file) fnm=$(basename $src) mv $src ./running/$iam/$fnm /bin/bash ./running/$iam/$fnm mv ./running/$iam/$fnm ./done/$fnm fi fi else file=`ls ./pending/*.sh | head -n 1` echo $file if [ ! -z $file ]; then if [ -f $file ]; then src=$(readlink --canonicalize $file) fnm=$(basename $src) mv $src ./running/$iam/$fnm /bin/bash ./running/$iam/$fnm mv ./running/$iam/$fnm ./done/$fnm fi fi fi file=0 src=0 fnm=0 loc=0 sleep 2 done """ #print("themo.sh doesn't exist, writing it...\n" + themoscript + "\n") # themo.sh doesn't exist... f = open(themofile,"w") print("themo.sh doesn't exist, writing it...\n") for line in themoscript.splitlines(): f.write(line + "\n") f.close() # chmod themo.sh mode = os.stat(themofile).st_mode mode |= (mode & 0o444) >> 2 os.chmod(themofile, mode) # save the scene hup = os.path.dirname(hou.hipFile.name()) + '/' + 'delme_' + nx + '.hip' hou.hipFile.save() cpycmd = "cp " + hou.hipFile.name() + " " + hup print("making a temp file for this job : " + cpycmd) os.system(cpycmd) # copy hfs to a farm-readable directory - yes this means it'll work with daily builds! nethfs = hprj + "/farm/hfs/hfs" + hou.applicationVersionString() + "/" if not os.path.exists(nethfs): os.makedirs(nethfs) if not os.path.exists(nethfs): print("ERROR: couldn't create nethfs dir : " + nethfs) else: xcmd = ("rsync -av " + pathtohoudini + "/ " + nethfs) print("sync hfs : " + xcmd) os.system(xcmd) # mind merged ROPs for i in ops : otn = i.type().name() if otn == 'merge' : for n in i.inputs() : if not n in ops : ops = ops + (n, ) # loop through selected ROPs for i in ops : isasim = 1 fto = '' batchcmd = "" otn = i.type().name() if otn == 'rop_geometry' or otn == 'rop_dop' or otn == 'geometry' or otn == 'wedge' or otn == 'rop_comp' or otn == 'comp' or otn == 'ifd' or otn == 'opengl' or otn == 'prepost': opn = i.name() opth = i.path() print("selected rop " + opn + " is type " + otn) # does it have a host filter? set paths to use it try : fto = i.parm('whitelist').eval() + '/' except : fto = '' if fto == '/' : fto = '' # its a wedge if otn == 'wedge' : drv = i.parm('driver').eval() wd = hou.node(drv) wub = 0 wisasim = 0 # get wedge range, check if custom parms for start & end exist for rendering a subset fstart = 0 fvstart = str(int(i.parm('range1x').eval())) fend = str(int(i.parm('steps1').eval())-1) fvend = str(int(i.parm('range1y').eval())-1) fvdur = str(int(i.parm('range1y').eval() - (i.parm('range1x').eval()-1))) fdur = str(int(i.parm('steps1').eval())) try: fvstart = str(int(i.parm('wubs').eval())) fvend = str(int(i.parm('wube').eval())) fvdur = str(int(i.parm('wube').eval() - (i.parm('wubs').eval()-1))) fend = str(int(i.parm('steps1').eval())-1) fdur = str(int(i.parm('steps1').eval())) wub = 1 except: print("\twedge has no wubs and wube parms, sending the whole thing...") # get wedge-driver range rng = wd.parm('trange').eval() if rng == 0 : sfstart = str(int(hou.frame())) sfend = fstart sfdur = "1" else : sfstart = str(int(wd.parm('f1').eval())) sfend = str(int(wd.parm('f2').eval())) sfdur = str(int(wd.parm('f2').eval() - (wd.parm('f1').eval()-1))) # is the wedge driver a sim? wisasim = 0 try : wisasim = wd.parm('initsim').eval() except: print("wedge driver isn't a sim") if wd.type().name() == 'opengl' : try : wisasim = wd.parm('soho_initsim').eval() except: print("wedge OGL driver isn't a sim") try : if wd.parm('vm_tile_render').eval() == True : wisasim = False except : print("wedge driver has no tile parameter") # get string vars from the wedge driver wpth = wd.path() wpn = wd.name() oldfn = "" wtn = wd.type().name() print("\twedge driver " + wpn + " is type " + wtn) if wtn == 'ifd' : oldfn = wd.parm('vm_picture').eval() if wtn == 'geometry' : oldfn = wd.parm('sopoutput').eval() if wtn == 'rop_geometry' : oldfn = wd.parm('sopoutput').eval() if wtn == 'comp' : oldfn = wd.parm('copoutput').eval() if wtn == 'rop_comp' : oldfn = wd.parm('copoutput').eval() if wtn == 'opengl' : oldfn = wd.parm('picture').eval() ext = oldfn.split(".")[-1] # loop through the wedges oldcc = 0 cc = int(fstart) for n in range(int(fdur)) : wv = (n/((int(fdur)-1) * 1.0)) * (int(fvdur) * 1.0) wv = int(wv) # set wedge range to single_wedge i.parm('wrange').set(1) # set wedge number: i.parm('wedgenum').set(cc) # set per-wedge overrides, since setting wedgenum doesn't work we're just bypassing wedge altogether for non-sims: ch = i.parm('chan1').eval() oldcc = hou.parm(ch).eval() hou.parm(ch).set(wv) print("\t\t\tset channel " + ch + " to value: " + str(wv)) # set wedge driver output manually as there is no wedgeval yet if wtn == 'ifd' : if wd.parm('vm_tile_render').eval() == True : wd.parm('vm_picture').set("$HIP/pic/${OS}/${OS}.pic") else : wd.parm('vm_picture').set("$HIP/pic/${OS}_" + str(cc) + "/${OS}_" + str(cc) + ".$F4.pic") if wtn == 'geometry' : wd.parm('sopoutput').set("$HIP/tmp/${OS}_" + str(cc) + "/${OS}_" + str(cc) + ".$F.bgeo.sc") if wtn == 'rop_geometry' : wd.parm('sopoutput').set("$HIP/tmp/${OS}_" + str(cc) + "/${OS}_" + str(cc) + ".$F.bgeo.sc") if wtn == 'comp' : wd.parm('copoutput').set("$HIP/out/${OS}_" + str(cc) + "/${OS}_" + str(cc) + ".$F4." + ext) if wtn == 'rop_comp' : wd.parm('copoutput').set("$HIP/out/${OS}_" + str(cc) + "/${OS}_" + str(cc) + ".$F4." + ext) if wtn == 'opengl' : wd.parm('picture').set("$HIP/pic/${OS}_" + str(cc) + "/${OS}_" + str(cc) + ".$F4." + ext) if wtn == 'ifd' : print('\t\t\tchecking matra ROP filename: ' + wd.parm('vm_picture').eval()) # save per-wedge hipfile: hou.hipFile.save() whup = os.path.dirname(hou.hipFile.name()) + '/' + 'delme_' + nx + '_wedge_' + str(cc) + '.hip' wcpycmd = "cp " + hou.hipFile.name() + " " + whup os.system(wcpycmd) print("\t\t\tsaved temp hipfile: " + whup) # create batch scripts per frame for non-sims: if not wisasim : print("\t\t\twedge_" + str(cc) + " is not a sim, sending per-frame commands...") scc = int(sfstart) for s in range(int(sfdur)) : pcc = prepadstr(str(scc), "0", len(sfdur)) batchcmd = nethfs + "/bin/hbatch -c \"render -V -f" + str(scc) + " " + str(scc) + " " + wpth + "\" -c \"quit\" " + whup if batchcmd != "" : nn = datetime.strftime(datetime.now(),'%y%m%d_%H%M%S%f') #print(batchcmd) bsh = (hprj + '/farm/pending/' + fto + nn + '_' + pcc + '_' + hdir + '_' + hj + '_' + hname + '_' + wpn + '_' + opn + '_wedge' + str(cc) + '.sh') #print(bsh) if not os.path.exists(os.path.dirname(bsh)): os.makedirs(os.path.dirname(bsh)) f = open(bsh,'w') f.write(batchcmd + '\n') f.close() scc = scc + 1 else: # driver is a sim, send one job per wedge only: print("\t\t\tis a sim, sending one job per wedge") batchcmd = nethfs + "/bin/hbatch -c \"render -V " + wpth + "\" -c \"quit\" " + whup if batchcmd != "" : nn = datetime.strftime(datetime.now(),'%y%m%d_%H%M%S%f') print("\t\t\t" + batchcmd) bsh = (hprj + '/farm/pending/' + fto + nn + '_' + hdir + '_' + hj + '_' + hname + '_' + wpn + '_' + opn + '_wedge' + str(cc) + '.sh') print("\t\t\t" + bsh) if not os.path.exists(os.path.dirname(bsh)): os.makedirs(os.path.dirname(bsh)) f = open(bsh,'w') f.write(batchcmd + '\n') f.close() # reset wedged channel value hou.parm(ch).set(oldcc) # next wedge cc = cc + 1 # reset wedge range mode i.parm('wrange').set(0) # reset the wedge driver file fields to my defaults if wtn == 'ifd' : wd.parm('vm_picture').set("$HIP/pic/${WEDGENUM}_${OS}/${WEDGENUM}_${OS}.$F4.pic") if wtn == 'geometry' : wd.parm('sopoutput').set("$HIP/tmp/${WEDGENUM}_${OS}/${WEDGENUM}_${OS}.$F.bgeo.sc") if wtn == 'rop_geometry' : wd.parm('sopoutput').set("$HIP/tmp/${WEDGENUM}_${OS}/${WEDGENUM}_${OS}.$F.bgeo.sc") if wtn == 'comp' : wd.parm('copoutput').set("$HIP/out/${WEDGENUM}_${OS}/${WEDGENUM}_${OS}.$F4." + ext) if wtn == 'rop_comp' : wd.parm('copoutput').set("$HIP/out/${WEDGENUM}_${OS}/${WEDGENUM}_${OS}.$F4." + ext) if wtn == 'opengl' : wd.parm('picture').set("$HIP/pic/${WEDGENUM}_${OS}/${WEDGENUM}_${OS}.$F4." + ext) # its not a wedge else : if otn != 'prepost' : # its not a utility rop # get ROP ranges rng = i.parm('trange').eval() if rng == 0 : fstart = str(int(hou.frame())) fend = fstart fdur = "1" else : fstart = str(int(i.parm('f1').eval())) fend = str(int(i.parm('f2').eval())) fdur = str(int(i.parm('f2').eval() - (i.parm('f1').eval()-1))) # is it a sim? try : isasim = i.parm('initsim').eval() except: try : isasim = i.parm('soho_initsim').eval() except: isasim = 0 # create batch scripts per frame if not a sim cc = int(fstart) print("is a sim: " + str(isasim)) if not isasim : if otn == 'comp' or otn == 'rop_comp' : # do 10s for COPs, change dv to desired frames-per-job dv = 10 print('is a COP:') cdur = int((int(fdur)) / float(dv)) print('\t'+str(dv)+'-frame job count = ' + str(cdur)) cdreg = (int(fdur))-(cdur*dv) print('\tCOP range = ' + str(int(fdur))) print('\tremainder = ' + str(cdreg)) print('\tsending '+str(dv)+'s...') for n in range(cdur) : cstart= (n*dv)+1 cend= (n*dv)+dv print('\t\tjob ' + str(n) + ' start = ' + str(cstart) + ', end = '+str(cend)) pcc = prepadstr(str(cstart), "0", len(fdur)) batchcmd = nethfs + "/bin/hbatch -c \"render -V -f " + str(cstart) + " " + str(cend) + " " + opth + "\" -c \"quit\" " + hup print('\tcmd = ' + batchcmd) if batchcmd != "" : nn = datetime.strftime(datetime.now(),'%y%m%d_%H%M%S%f') bsh = (hprj + '/farm/pending/' + fto + nn + '_' + pcc + '_' + hdir + '_' + hj + '_' + hname + '_' + opn + '.sh') if not os.path.exists(os.path.dirname(bsh)): os.makedirs(os.path.dirname(bsh)) f = open(bsh,'w') f.write(batchcmd + '\n') f.close() if cdreg > 0 : print('\tsending dregs...') cstart= (cdur*dv) + 1 cend= (int(fdur)) print('\t\tdregs start=' + str(cstart) + ', end = ' + str(cend)) pcc = prepadstr(str(cstart), "0", len(fdur)) batchcmd = nethfs + "/bin/hbatch -c \"render -V -f " + str(cstart) + " " + str(cend) + " " + opth + "\" -c \"quit\" " + hup print('\tcmd = ' + batchcmd) if batchcmd != "" : nn = datetime.strftime(datetime.now(),'%y%m%d_%H%M%S%f') bsh = (hprj + '/farm/pending/' + fto + nn + '_' + pcc + '_' + hdir + '_' + hj + '_' + hname + '_' + opn + '.sh') if not os.path.exists(os.path.dirname(bsh)): os.makedirs(os.path.dirname(bsh)) f = open(bsh,'w') f.write(batchcmd + '\n') f.close() else: for n in range(int(fdur)) : pcc = prepadstr(str(cc), "0", len(fdur)) batchcmd = nethfs + "/bin/hbatch -c \"render -V -f" + str(cc) + " " + str(cc) + " " + opth + "\" -c \"quit\" " + hup print('\tcmd = ' + batchcmd) if batchcmd != "" : nn = datetime.strftime(datetime.now(),'%y%m%d_%H%M%S%f') bsh = (hprj + '/farm/pending/' + fto + nn + '_' + pcc + '_' + hdir + '_' + hj + '_' + hname + '_' + opn + '.sh') if not os.path.exists(os.path.dirname(bsh)): os.makedirs(os.path.dirname(bsh)) f = open(bsh,'w') f.write(batchcmd + '\n') f.close() cc = cc + 1 # create batch script if sim else: batchcmd = nethfs + "/bin/hbatch -c \"render -V " + opth + "\" -c \"quit\" " + hup if batchcmd != "" : nn = datetime.strftime(datetime.now(),'%y%m%d_%H%M%S%f') #print(batchcmd) bsh = (hprj + '/farm/pending/' + fto + nn + '_' + hdir + '_' + hj + '_' + hname + '_' + opn + '.sh') if not os.path.exists(os.path.dirname(bsh)): os.makedirs(os.path.dirname(bsh)) f = open(bsh,'w') f.write(batchcmd + '\n') f.close() # its a utility ROP, just send it, see what happens... else: batchcmd = nethfs + "/bin/hbatch -c \"render -V " + opth + "\" -c \"quit\" " + hup if batchcmd != "" : nn = datetime.strftime(datetime.now(),'%y%m%d_%H%M%S%f') #print(batchcmd) bsh = (hprj + '/farm/pending/' + fto + nn + '_' + hdir + '_' + hj + '_' + hname + '_' + opn + '.sh') if not os.path.exists(os.path.dirname(bsh)): os.makedirs(os.path.dirname(bsh)) f = open(bsh,'w') f.write(batchcmd + '\n') f.close() # execute shell ROPs instantly if otn == 'shell': i.parm('execute').pressButton() time.sleep(1) # run themo if not running already: #import subprocess #pids = subprocess.check_output(["ps","-efl", (hprj + "/farm/*" + themofile)]) pids = -999 # psutil not available... #import psutil #for proc in psutil.process_iter(): # cmds = " ".join(proc.cmds()) # if (hprj + "/farm/*themo.sh") in cmds : # print("themo.sh is already running\n" + str(cmds)) # pids = 0 # break import subprocess ps = subprocess.Popen(['ps', 'efl'], stdout=subprocess.PIPE) pg = subprocess.Popen(['grep', 'themo.sh'], stdin=ps.stdout, stdout=subprocess.PIPE).communicate()[0] ps.stdout.close() if pg.strip() != "" : pids = 1 pg = 0 ps = 0 if pids == 1 : print("themo.sh is already running...") else : print("themo not running, starting it...") os.system(myfaveterm + " -e 'bash -c \"cd " + hprj + "/farm/; ./themo.sh\"'")
Thebeard.py
import os import glob import time from operator import itemgetter from itertools import groupby cdr = os.path.split(os.path.realpath('thebeard.py'))[0] #print('CURRENT DIR = ' + cdr + '\n') rd = cdr + '/running/' pd = cdr + '/pending/' #print('RUNNING DIR = ' + rd + '\n') #print('PENDING DIR = ' + rd + '\n') def padstr(instr, pad, padlen) : #print('FN: padstr(%s,%s,%i)' %(instr, pad, padlen)) dif = (padlen - len(instr)) + 1 o = instr for i in range(1,dif) : o = o + pad #print('\t'+o) return(o) def getjobs(p) : if os.path.isdir(p) : subs = os.listdir(p) #print("subdirs=" + str(subs)) shs = glob.glob(p + '*.sh*') for u in subs : #print("checking: " + p + u) sshs = glob.glob((p + u) + '/*.sh*') shs = shs + sshs #print("shs="+str(shs)) a = [] for s in shs : fp = s.split('_') #print('time = ' + (fp[0]+fp[1]).split('/')[-1:][0]) #print('frame = ' + fp[2]) #print('job = ' + fp[3]) #print('shot = ' + fp[4]) #print('scene = ' + fp[4]) #print('rop = ' + fp[5].split('.')[0]) a.append({'time':(fp[0]+fp[1]).split('/')[-1:][0], 'frame':fp[2], 'job':fp[3], 'shot':fp[4], 'scene':fp[4], 'rop':('_'.join(fp[5:]).split('.')[0])}) return(a) def calcjobs (a) : o = [] sbb = sorted(a, key=itemgetter('time')) maxlen = 0 for okey, ogroup in groupby(sbb, key=lambda x:x['shot']): og = list(ogroup) shotline = (' shot...: ' + okey) shotlen = len(shotline) if shotlen > maxlen : maxlen = shotlen o.append([shotline, str(len(og))]) og = sorted(og, key=itemgetter('scene')) for skey, sgroup in groupby(og, key=lambda x:x['scene']): sg = list(sgroup) sceneline = (' +scene: ' + skey) scenelen = len(sceneline) if scenelen > maxlen : maxlen = scenelen o.append([sceneline, str(len(sg))]) sg = sorted(sg, key=itemgetter('rop')) for rkey, rgroup in groupby(sg, key=lambda x:x['rop']): rg = list(rgroup) ropline = (' +rop.: ' + rkey) roplen = len(ropline) if roplen > maxlen : maxlen = roplen o.append([ropline, str(len(rg))]) return (o, maxlen) def listjobs(a) : o = "" for i in a[0] : pline = padstr(i[0],".",a[1]) o = o + (pline + ' : ' + i[1]) + '\n' return o bb = getjobs(pd) rr = getjobs(rd) jr = calcjobs(rr) jp = calcjobs(bb) lr = listjobs(jr) lb = listjobs(jp) print('running\n' + lr + '\npending\n' + lb)
shotgun:cmd::hou::py:
data
/skullet/GX1/intro/2/anim/whatever/the/hell/you/like | | | | | | | +--- taskname | | +------- shotname | +---------- sequencename +---------------- projectname args
[01] # projectname.............. get from path of file [02] # username................. get from OS [03] # sequencename............. get from path of file [04] # shotname................. get from path of file [05] # taskname................. get from path of file [06] # versionname.............. can be anything, but is required [07] # versioncomment (optional) can be anything [08] # 1stframeofrender......... get from 1st frame of sequence [09] # pathtoshotgunapi......... from shotgun_api3 import shotgun [10] # pathtoffmpeg............. needed to transcode the images
sendittoshotgun:cmd::py:

One-click Shotgun publish.
No data-entry, no bullshit.
Uses daily vanilla Houdini, Shotgun not installed.
Zero api key security.
Linux only.
Last used in 2018, before Autodesk got its hands on SG, so this is probably obsolete.

# direct shotgun publish script # by c.p.brown 2014~2018 # # shotgun should NOT be installed, just grab its 'api' (directory of scripts) # # dependencies - download/make these in a dir called 'sg' # ./sendittoshotgun.py : this script # ./res/python/shotgun_api3 : shotgun api (as of 2018) # ./res/ffmpeg/bin : ffmpeg binaries and resources (can be overridden) # ./res/icons/your_48x48_watermark.png : watermark for lower right of movies (can be overridden) # ./res/fonts/EnvyCode-R.ttf : font for overlay (can be overridden) # # usage # python sendittoshotgun.py "projectname" "sequencename" "shotname" "taskname" "versionname" "username" "fullimagepath" "comment" "fps" # # build this command in a nuke or houdini shelftool, select read-nodes or file-cops, hit the button, keep working... # a sample shelftool should be where you found this script # # minimal dir compliance # /skullet/GX1/intro/2/anim/then/whatever/the/hell/you/like # | | | | # | | | +--- taskname # | | +------- shotname # | +---------- sequencename # +---------------- projectname # # arg sources - there should be ZERO data entry - its the whole point of this excercise # [01] # projectname.............. get from path of file # [02] # username................. get from OS, must match shotgun username! # [03] # sequencename............. get from path of file # [04] # shotname................. get from path of file # [05] # taskname................. get from path of file # [06] # versionname.............. required, can be anything, build automatically, dont' ask user # [07] # versioncomment (optional) can be anything, build automatically, don't ask user by default; make a special shelftool for special people # [08] # 1stframeofrender......... get from 1st frame of sequence # [09] # pathtoshotgunapi......... from shotgun_api3 import shotgun # [10] # pathtoffmpeg............. optional ffmpeg override, eg: /server/tools/ffmpeg/bin/ # [11] # pathtowatermark.......... optional watermark override, must be a .png with alpha # [12] # pathtofont............... optional watermark font override, must be ttf, used for shot info overlay strip # # the srcipt and dependencies are encapsulated within one dir, so it can be copied and used offsite # to save xfer size, have offsite peeps install python and ffmpeg locally, however this may introduce errors, especially with ffmpeg # # NOTE: # this script is probably incompatible with the latest ffmpeg and shotgun_api # use for reference only # also probably won't work on windows. import os import sys import subprocess import shutil import glob import platform from datetime import datetime pn = sys.argv[1] # project name qn = sys.argv[2] # sequence name sn = sys.argv[3] # shot name tn = sys.argv[4] # task name vn = sys.argv[5] # version name un = sys.argv[6] # user name r = sys.argv[7] # 1st frame of render vc = sys.argv[8] # version comment (required, but can be blank) fs = sys.argv[9] # fps # sys.argv[10] is an optional ffmpeg override # sys.argv[11] is an optional watermark override # sys.argv[12] is an optional watermark font override def padz(s,p,l) : dif = (l - len(s)) + 1 o = '' for i in range(1,dif) : o = o + p o = o + s return o dn = datetime.now() dstr = (str(dn.year)[-2:] + padz(str(dn.month),'0',2) + padz(str(dn.day),'0',2)) # this probably won't work in windows... sucks you to be on windows locsg = "./res/" # import shotgun api : pyp = locsg + "python" sys.path.append(pyp) from shotgun_api3 import Shotgun # check it print 'sys.argv[0] = %s' % sys.argv[0] print 'sys.argv[1] = %s' % sys.argv[1] print 'sys.argv[2] = %s' % sys.argv[2] print 'sys.argv[3] = %s' % sys.argv[3] print 'sys.argv[4] = %s' % sys.argv[4] print 'sys.argv[5] = %s' % sys.argv[5] print 'sys.argv[6] = %s' % sys.argv[6] print 'sys.argv[7] = %s' % sys.argv[7] print 'sys.argv[8] = %s' % sys.argv[8] print 'sys.argv[9] = %s' % sys.argv[9] # default to 24fps if its missing if fs == '' : fs = '24' fexe = locsg + "ffmpeg/bin/ffmpeg.exe" fpro = locsg + "ffmpeg/bin/ffprobe.exe" if platform.system() == 'Linux' : fexe = locsg + "ffmpeg/bin/ffmpeg" fpro = locsg + "ffmpeg/bin/ffprobe" if len(sys.argv) > 10 : if os.path.exists(sys.argv[10]) : print "ffmpeg override supplied" fexe = sys.argv[10] fpro = os.path.dirname(sys.argv[10]) + '/ffprobe.exe' if platform.system() == 'Linux' : fpro = os.path.dirname(sys.argv[10]) + '/ffprobe' print '\tsys.argv[10] = %s' % sys.argv[10] wm = locsg + "icons/your_48x48_watermark.png" if len(sys.argv) > 11 : if os.path.exists(sys.argv[11]) : print "watermark override supplied" wm = sys.argv[11] print '\tsys.argv[11] = %s' % sys.argv[11] wmfont = locsg + "fonts/EnvyCode-R.ttf" if len(sys.argv) > 12 : if os.path.exists(sys.argv[12]) : print "watermark font supplied" wmfont = sys.argv[12] print '\tsys.argv[12] = %s' % sys.argv[12] else : print "watermark font not supplied, using default" wmfont = wmfont.replace("\\","/") wmfont = wmfont.replace(":","\\:") # [TODO] opt-out of watermarking watermarkit = 1 # python scripts have zero security, so not even bothering to hide this info # use NDAs, change api keys frequently SERVER_PATH = "https://yourdomain.shotgunstudio.com" SCRIPT_NAME = 'myfistyourface' SCRIPT_KEY = 'this_scripts_api_key' sg = Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY) #sg = 1 if sg != None : #make the mp4: rparts = r.split('.') #print "r = %s" % r # is it a sequence: path/name.####.ext ? if len(rparts) == 3 : rnums = rparts[len(rparts)-2] print "getting 1st frame num..." globie = rparts[0] + '*' + rparts[2] sq = glob.glob(globie) #sq.sort sq.sort(key=lambda x: x.lower()) sqp = sq[0].split('.') sqnums = sqp[len(sqp)-2] startnum = int(sqnums) print "1st frame num = %s" % startnum rs = rparts[0] + ('.'+'%0'+str(len(rnums))+'d.') + rparts[2] rvid = rparts[0] + '.mp4' # get optional lut files from version comments vfcubes = "" if vc != "" : vct = "" vcln = vc.decode("string_escape").splitlines() print "vcln = %s" % vcln for vl in vcln : vlt = vl print "\t\tchecking comment line for lookup path: %s" % vl vp = vl.split('.cube') if len(vp) > 1 : if os.path.exists(vl) : wvl = vl.replace('\\','/') wvl = wvl.replace(':','\\:') vfcubes = vfcubes + 'lut3d=\'' + wvl + '\', ' vlt = '' vct = vct + vlt + '\n' vc = vct #vfcubes = vfcubes.strip(', ') fcmd = "\"" + fexe + "\" -r " + fs + " -thread_queue_size 512 -start_number " + str(startnum) + " -i \"" + rs + "\" -filter_complex \"" + vfcubes + "scale=trunc(in_w/2)*2:trunc(in_h/2)*2\" -pix_fmt yuv420p -vcodec h264 -g 30 -b:v 2000k -vprofile high -bf 0 -y \""+ rvid + "\"" if watermarkit == 1 : imgn = os.path.basename(sys.argv[7]).split('.')[0] probe = fpro + " -i " + r + " -v error -of flat=s=_ -select_streams v:0 -show_entries stream=width,height" print "probing the image : %s" % probe ffs = "18" fpret = subprocess.Popen(probe, stdout=subprocess.PIPE, shell=True) probed = fpret.communicate()[0] print "probe returns : %s" % probed if '=' in probed : wmtxt = dstr + " | " + pn + " | SEQ=" + qn + " | SHOT=" + sn + " | " + imgn + " | " wmtxtlen = len(wmtxt) + 6 tiw = wmtxtlen * 10 print "estimated text width : %s" % tiw iw = int(probed.split('\n')[0].split('=')[1].strip()) #iw = max(iw,int(tiw)) iwf = int((iw / max(1000.0,float(tiw))) * 18) ffs = str(iwf) fbh = int(25.0 * (iwf / 18.0)) + 20 ih = str(int(probed.split('\n')[1].split('=')[1].strip())-fbh) probe = fpro + " -i " + r + " -v error -of flat=s=_ -select_streams v:0 -show_entries stream=sample_aspect_ratio" print "probing it again : %s" % probe fpret = subprocess.Popen(probe, stdout=subprocess.PIPE, shell=True) probed = fpret.communicate()[0] print "probe returns : %s" % probed forcesar = '[0:v]' if '=' in probed : ia = probed.split('\n')[0].split('=')[1].strip() print "found sample aspect : %s" % ia if ia != '' and len(ia.split(':')) > 1 : forcesar = ('setsar=' + ia + ', ') fcmd = "\"" + fexe + "\" -r " + fs + " -thread_queue_size 512 -start_number " + str(startnum) + " -i \"" + rs + "\" -i \"" + wm + "\" -filter_complex \"[0:v]" + forcesar + vfcubes + "scale=trunc(in_w/2)*2:trunc(in_h/2)*2[scale];[scale][1:v]overlay=x=(main_w-overlay_w)-20:y=(main_h-overlay_h)-(" + str(fbh) + "+15),drawbox=y=" + ih + ":color=black@0.3:width=" + str(iw) + ":height=" + str(fbh) + ":t=max,drawtext=fontfile='" + wmfont + "': text=\'" + dstr + " | " + pn + " | SEQ=" + qn + " | SHOT=" + sn + " | " + imgn + " | " + "f %{eif\\:n+1\\:d}\': fontcolor=white@0.5: fontsize=" + ffs + ": x=10: y=(main_h-text_h)-10\" -pix_fmt yuv420p -vcodec h264 -g 30 -b:v 2000k -vprofile high -bf 0 -y \""+ rvid + "\"" #print '\n' print "fcmd = %s" % fcmd fret = subprocess.call(fcmd, shell = True) fret = 1 if fret == 0 : # shotgun... # override username for offsite testing: #un = "cpb" filters = [ ['name','is',pn], ] p = sg.find_one('Project',filters) if p != None : pid = p['id'] #print "local login user is %s" % un filters = [ ['name','is', un], ] u = sg.find_one('HumanUser',filters) if u != None : uid = u['id'] #print "user = %s, sg_humanuser = %s, sg_uid = %s" % (un, u, uid) filters = [ ['project','is', {'type':'Project','id':pid}],['code', 'is', qn] ] q = sg.find_one('Sequence',filters) if q != None : filters = [ ['project','is', {'type':'Project','id':pid}],['code', 'is', sn] ] s = sg.find_one('Shot',filters) if s != None : sid = s['id'] filters = [ ['project','is', {'type':'Project','id':pid}],['entity','is',{'type':'Shot','id':sid}],['content','is',tn] ] t = sg.find_one('Task',filters) if t != None : tid = t['id'] data = { 'project': {'type':'Project','id':pid},'code': (sn+'_'+tn+'_'+vn),'description': vc,'created_by': {'type':'HumanUser', 'id':uid},'sg_path_to_frames': os.path.dirname(r),'sg_status_list': 'rev','entity': {'type':'Shot', 'id':sid},'sg_task': {'type':'Task', 'id':tid},'user': {'type':'HumanUser', 'id':uid} } v = sg.create('Version', data) if v != None : vid = v['id'] rps = r.split('/') # ---------- drive -------- shotgun ------ project ------ scene -------- shot --------- task --------- review reviewpath = rps[0] + '/' + rps[1] + '/' + rps[2] + '/' + rps[3] + '/' + rps[4] + '/' + rps[5] + '/' + "review" + '/' if not os.path.exists(reviewpath) : os.mkdir(reviewpath) reviewvid = reviewpath + os.path.basename(rvid) shutil.copy2(rvid,reviewvid) sg.upload_thumbnail("Version", vid, r) sg.upload("Version", vid,reviewvid,'sg_uploaded_movie') else : print "error: couldn't create new version: %s" % vn else : print "error: can't find task: %s" % tn else : print "error: can't find shot: %s" % sn else : print "error: can't find sequence: %s" % qn else : print "error: user %s isn't in shotgun" % un else : print "error: can't find project: %s" % pn else : print "error: couldn't make the mp4: %s" % rvid else : print "error: unhandled file format, expecting: name.nums.ext" else : print "error: couldn't connect to shotgun"
sample shelftool:hou::py:
# gather args from your scene + selected file-cops, send it to sendittoshotgun,py # by cpbrown 2014~2018 import os import getpass from datetime import datetime import platform import imp import sys import subprocess import shutil import glob def padz(s,p,l) : dif = (l - len(s)) + 1 o = '' for i in range(1,dif) : o = o + p o = o + s return o dn = datetime.now() dstr = (str(dn.year)[-2:] + padz(str(dn.month),'0',2) + padz(str(dn.day),'0',2)) locsg = "/path/to/sg" def sendittoshotgun(project, sequence, shot, task, user, render, version, comment, fps, ffmpeg, water, wfont): if project != '' and shot != '' and sequence != '' and task != '' and user != '' : pyx = locsg + "python/python" sgpy = locsg + "sendittoshotgun.py" qo = "\"" cmd = qo + sgpy + qo + ' ' + qo + project + qo + ' ' + qo + sequence + qo + ' ' + qo + shot + qo + ' ' + qo + task + qo + ' ' + qo + version + qo + ' ' + qo + user + qo + ' ' + qo + render + qo + ' ' + qo + comment + qo + ' ' + qo + fps + qo + ' ' + qo + ffmpeg + qo + ' ' + qo + water + qo + ' ' + qo + wfont + qo return [pyx,cmd] hdir = hou.hipFile.path() hname = hou.hipFile.basename() hp = hdir.split('/') print('hdir='+hdir) # quick test of hipfile location: if len(hp) > 3 : # vars for this scene pn = hp[2] qn = hp[3] sn = hp[4] tn = hp[5] thisdir = os.path.dirname(hdir).split('/')[-1] thisfile = hou.hipFile.name().split('.')[0].split('/')[-1] un=getpass.getuser() print("project== "+pn) print("sequence= "+qn) print("shot===== "+sn) print("task===== "+tn) print("thisdir== "+thisdir) print("thisfile= "+thisfile) print("user===== "+un) r = '' version = '' comment = '' ops = hou.selectedNodes() # loop through each node: for i in ops: otn = i.type().name() if otn == 'file' : version = (dstr + '_' + thisdir + '_' + thisfile + '_' + i.name()) r = i.parm('filename1').eval() comment = (dstr + ': another great update from ' + un + ' via Houdini') print("r======== "+r) print("version== "+version) print("comment== "+comment) print('\n') fps = str(hou.fps()) #send it: sgcmds = sendittoshotgun(pn, qn, sn, tn, un, r, version, comment, fps, "", "", "") print "shotgun command: %s" % sgcmds sgcmd = (sgcmds[0] + ' ' + sgcmds[1]) subprocess.call(sgcmd, shell = True)
REF
smellslikesmoke:cmd::py:
Bushfire alarm, successfully used during the 2019 season.
Required a non-suspending phone OS, used Sailfish... with some D-Bus modifications.
Data sourced from: http:www.rfs.nsw.gov.au/feeds/majorIncidents.xml

Don't repurpose this for future fires: you're roast-pig if you do it wrong.

# this script and notes are for my own personal use only. import urllib.request import xml.etree.ElementTree as et import os import subprocess import re, html from math import sin, cos, sqrt, atan2, radians # the most vunerable point in the evacuation route b = [-33.689990, 150.546212] # sound alarm if any fire poly-points are within this distance to the above # sound a warning if any fire poly-points are within twice this distance # distance based on approx. 20min evac, with fire traveling approx. 30km/h. # however this is risky, fire could be faster, or embers light-up everything way in advance. Check winds and predicted ember-drop zones, move somewhere safer if in doubt. tooclose = 12.0 # fire polys may not be up-to-date so as a fallback check suburb names... # sound alarm if any of these suburbs are mentioned in the xml redburbs = ['faulconbridge', 'springwood', 'linden', 'winmalee', 'valley heights', 'warrimoo', 'woodford', 'bunyan', 'yellow rock', 'mount hay'] # sound a warning if any of these suburbs are mentioned, # sound an alarm if these are described as 'out of control' or 'emergency' yellowburbs = ['tomah', 'bilpin', 'berambing', 'mount banks', 'wentworth falls', 'blaxland', 'glenbrook', 'bowen mountain', 'yarramundi', 'ruined castle'] def getdist(la, lb, oa, ob) : # function posted by gwaramadze & fixed by Michael0x2a on stackexchange, referring to Andrew Hedges, who referred to Bob Chamberlain # https://andrew.hedges.name/experiments/haversine/ # https://stackoverflow.com/questions/19412462/getting-distance-between-two-points-based-on-latitude-longitude # approximate radius of earth in km R = 6371.0 lat1 = lb lon1 = ob lat2 = la lon2 = oa dlon = radians(lon2 - lon1) dlat = radians(lat2 - lat1) a = (sin(dlat / 2) * sin(dlat / 2) + cos(radians(lat1)) * cos(radians(lat2)) * sin(dlon / 2) * sin(dlon / 2)) c = 2 * atan2(sqrt(a), sqrt(1 - a)) distance = R * c return(distance) tag_re = re.compile(r'(<!--.*?-->|<[^>]*>)') cdr = os.path.split(os.path.realpath('redzone.py'))[0] feed = cdr + "/feed.xml" print(feed) ac = [] s = urllib.request.urlretrieve('http://www.rfs.nsw.gov.au/feeds/majorIncidents.xml', feed) t = et.parse(feed).getroot() bb = 'gst-launch-1.0 -q filesrc location=' + cdr + '/jno.wav ! decodebin ! autoaudiosink' aa = 'gst-launch-1.0 -q filesrc location=' + cdr + '/jsu.wav ! decodebin ! autoaudiosink' for d in t.iter('item') : odk = 999.0 tt = "" dd = "" cc = "" isred = False isyellow = False for m in list(d.iter()) : if "title" in m.tag: tt = m.text if "description" in m.tag: dd = no_tags = tag_re.sub('', m.text) dd = html.escape(dd) if "polygon" in m.tag: pp = m.text c = iter(pp.split()) ci = ([x ,next(c, '')] for x in c) o = list(ci) e = [] for k in o : dk = getdist(float(k[0]), b[0], float(k[1]), b[1]) if dk < odk: odk = dk if "category" in m.tag: cc = m.text for r in redburbs : if r in dd.lower() : isred = True for y in yellowburbs : if y in dd.lower() : isyellow = True if isred: print("isred = " + str(isred)) if isyellow or (odk < (tooclose*2) and ("out of control" in dd.lower())): print("{0:.2f}".format(odk) + "Km : " + tt + " fire (" + cc + ")") for q in range(2) : subprocess.call(bb.split()) if isred or odk < tooclose or (isyellow and "emergency" in dd.lower()): print("\n") print("{0:.2f}".format(odk) + "Km : " + tt + " : (" + cc + ")\n\t" + dd + "\n") for q in range(10) : subprocess.call(aa.split())
chaosandanarchy:hou:
screenie
Send stuff to Deadline via VOPs, using daily vanilla Houdini, zero middleware.

Proof of concept... you really don't need a pipeline department to use a task scheduler.
hipfile
corner normals:hou::vex:

Derivative work, angle math was from a gamedev forum, but lost the bookmark, haven't been able to find it again. There was some related discussion here that may lead to a more elegant solution.

int nn = neighbourcount(0,$ptnum); int nb = neighbour(0,$ptnum,0); vector nbp = point(0,"P",nb); vector ab = -normalize(nbp - $P); int cave = 1; float pi = 3.14; vector zn = {0.0,1.0,0.0}; vector upd = normalize($N); if (nn > 1) { int nc = neighbour(0,$ptnum,1); vector ncp = point(0,"P",nc); vector ac = normalize($P - ncp); float ang = 0.0; if (upd.z == 1.0) { ang = ((atan2(ac.x, ac.y) - atan2(ab.x, ab.y) + pi * 2) % (pi * 2)) - pi; } if (upd.z == -1.0) { ang = ((atan2(ac.y, ac.x) - atan2(ab.y, ab.x) + pi * 2) % (pi * 2)) - pi; } if (upd.x == -1.0) { ang = ((atan2(ac.z, ac.y) - atan2(ab.z, ab.y) + pi * 2) % (pi * 2)) - pi; } if (upd.x == 1.0) { ang = ((atan2(ab.z, ab.y) - atan2(ac.z, ac.y) + pi * 2) % (pi * 2)) - pi; } if (abs(upd.y) == 1.0) { ang = ((atan2(ac.x, ac.z) - atan2(ab.x, ab.z) + pi * 2) % (pi * 2)) - pi; } $aa = ang; float rr = acos(dot(ab,ac)); matrix3 mx = 1; rr = degrees(rr); if (ang > 0.0) { rr = 360.0 - rr; } rr = -radians(rr); rr = rr * $blend; rotate(mx,rr,upd); ab = ab * mx; zn = -ab; if (ang < 0.0) { zn = -zn; } if($flf == 1 && $ptnum == 0) { zn = -zn; } if($fll == 1 && $ptnum == ($Npt - 1)) { zn = -zn; } if($fln != 0 && $ptnum == $fln) { zn = -zn; } //if (upd.x == 1.0 && ($ptnum % 3) != 1) { zn = -zn; } //if (upd.z == 1.0 && $ptnum == 0) { zn = -zn; } //if (upd.z == -1.0 && $ptnum != 0) { zn = -zn; } } else { zn = normalize(cross(ab,upd)); if (upd.z == -1.0) { zn = -zn; } if($ptnum == ($Npt-1)) { zn = -zn; } if($flf == 1 && $ptnum == 0) { zn = -zn; } } $zz = zn; $yy = upd;
org headers:org:
Used for admin work
basic headers:org:
Note: remove the comma at the start of the configuration line.

Ignoreheading prevents the contents from being excluded from the headers, its useful to hide lengthy org-file settings

Org-confirm-babel line just stops emacs from nagging every time you want to eval a src block

Startup entries makes it more readable for large orgfiles.
Options entries forces text/html export to behave, otherwise it makes assumptions...

# -*- mode:org; org-confirm-babel-evaluate: nil; -*- ,* Configuration :ignoreheading: #+STARTUP: indent overview #+STARTUP: align #+STARTUP: inlineimages #+CREATOR: c.p.brown #+OPTIONS: toc:nil num:nil title:nil author:nil #+OPTIONS: ^:nil #+OPTIONS: -:nil #+OPTIONS: \n:t #+OPTIONS: html-postamble:nil
todo headers:org:
set per-orgfile todos

1st line:
# -*- mode:org; org-todo-keyword-faces: (("[0_TODO]" . "orange") ("[1_IP..]" . "yellow") ("[2_FIX.]" . "red") ("[3_WAIT]" . "blue") ("[4_NOPE]" . "black") ("[5_DONE]" . "green")); -*-
then config:
#+TODO: [0_TODO] [1_IP..] [2_FIX.] [3_WAIT] [4_NOPE] [5_DONE]
plaintext latex headers:org:
Surprisingly difficult; org latex export makes a lot of assumptions...

#+LATEX_COMPILER: xelatex #+LATEX_CMD: xelatex #+LATEX_CLASS: koma-article #+LATEX_CLASS_OPTIONS: [a4paper] #+LATEX_HEADER: \usepackage{fontspec} #+LATEX_HEADER: \usepackage{verbatim} #+LATEX_HEADER: \usepackage{ragged2e} #+LATEX_HEADER: \setmainfont[Ligatures=TeX]{Latin Modern Mono} #+LATEX_HEADER: \renewcommand{\seriesdefault}{bx} #+LATEX_HEADER: \hypersetup{colorlinks=true} #+LATEX_HEADER: \usepackage[margin=1cm, ignorefoot, ignoremp, ignorehead]{geometry} #+LATEX_HEADER: \usepackage[utf8]{inputenc} #+LATEX_HEADER: \changefontsizes{14pt} #+LATEX_HEADER: \setlength{\parindent}{0pt} #+LATEX_HEADER: \frenchspacing #+LATEX_HEADER: \newgeometry{right=1cm,left=1cm,top=1cm} #+LATEX_HEADER: \usepackage{fancyhdr} #+LATEX_HEADER: \usepackage{lastpage} #+LATEX_HEADER: \fancyfoot[C]{Page \thepage\ of \pageref{LastPage}} #+LATEX_HEADER: \renewcommand{\headrulewidth}{0pt} #+LATEX_HEADER: \pagestyle{fancy} #+LATEX_HEADER: \usepackage{courier} #+LATEX_HEADER: \setmonofont[Scale=0.8]{Range Mono Medium}
org table:org:
Templates based on admin for vfx work
basic spreadsheet:org:
| item  | cost | qty |    sum |
|-------+------+-----+--------|
| one   | 50.3 |   2 | 100.60 |
| two   | 33.8 |   5 | 169.00 |
| three |  8.6 |   1 |   8.60 |
|-------+------+-----+--------|
| total |      |     | 278.20 |
#+TBLFM: $4=($2*$3);%.2f :: @>$4=vsum(@I$4..@II$4);%.2f
subcategory spreadsheet:org:
#+tblname: with-rownames
| !     | DESCRIPTION   |       SUB |
|-------+---------------+-----------|
| AAA02 | ideas         |  12340.56 |
| BBB15 | words         |  56780.90 |
| CCC35 | actions       |  12340.00 |
| CCC39 | actions       |  56780.00 |
| CCC40 | actions       |   9100.00 |
|-------+---------------+-----------|
|       | 147341.46     |           |
| ^     | income_total  |           |
|-------+---------------+-----------|
| DDD10 | actions       |  -1230.00 |
| DDD20 | actions       |  -4560.00 |
| EEE10 | things        |   -789.62 |
| EEE20 | things        |  -1000.74 |
|-------+---------------+-----------|
|       | -7580.36      |           |
| ^     | expense_total |           |
|-------+---------------+-----------|
| TOTAL |               | 139761.10 |
| %     |               |      95.6 |
#+TBLFM: @1$1=string("!") :: @1$2=string("DESCRIPTION") ::  $income_total=vsum(@I$SUB..@II$SUB);%.2f :: $expense_total=vsum(@III$SUB..@IIII$SUB)  :: @>>$3=vsum(@I$SUB..@IIII$SUB);%.2f ::  @>$3=(1.0 - (abs(@IIII$2) / @II$2)) * 100.0;%.1f
plot spreadsheet:org:
| temp c | temp f |   fn | plot                 | note       |
|--------+--------+------+----------------------+------------|
|    0.0 |   32.0 | 0.00 |                      |            |
|    2.0 |   35.6 | 0.00 |                      |            |
|    4.0 |   39.2 | 0.01 | ▎                    |            |
|    6.0 |   42.8 | 0.01 | ▎                    |            |
|    8.0 |   46.4 | 0.02 | ▍                    |            |
|   10.0 |   50.0 | 0.03 | ▋                    |            |
|   12.0 |   53.6 | 0.05 | █                    | <- heater  |
|   14.0 |   57.2 | 0.08 | █▋                   |            |
|   16.0 |   60.8 | 0.14 | ██▊                  | <- coat    |
|   18.0 |   64.4 | 0.22 | ████▍                |            |
|   20.0 |   68.0 | 0.33 | ██████▋              |            |
|   22.0 |   71.6 | 0.46 | █████████▎           | <- perfect |
|   24.0 |   75.2 | 0.61 | ████████████▎        |            |
|   26.0 |   78.8 | 0.73 | ██████████████▋      |            |
|   28.0 |   82.4 | 0.83 | ████████████████▋    | <- fan     |
|   30.0 |   86.0 | 0.89 | █████████████████▊   |            |
|   32.0 |   89.6 | 0.94 | ██████████████████▊  | <- aircon  |
|   34.0 |   93.2 | 0.96 | ███████████████████▎ |            |
|   36.0 |   96.8 | 0.98 | ███████████████████▋ |            |
|   38.0 |  100.4 | 0.99 | ███████████████████▊ |            |
|   40.0 |  104.0 | 0.99 | ███████████████████▊ |            |
|   42.0 |  107.6 | 1.00 | ████████████████████ |            |
|   44.0 |  111.2 | 1.00 | ████████████████████ |            |
|--------+--------+------+----------------------+------------|
#+TBLFM: $2=(($1*1.8)+32);%.1f :: $3=(1/(1+exp(-($1-(0.0 + ((50.0/10.0)*4.5)))/(50.0/10.0)*0.7)));%.2f :: $4='(orgtbl-uc-draw-cont $3 0.0 1.0 20) 

columnview spreadsheet:org:
useful when you have heaps of properties per item, but only want a few of them in the table
,* alist :PROPERTIES: :COLUMNS: %ITM %COS %QTY :END: ,** anitem :PROPERTIES: :ITM: one :COS: 34.80 :QTY: 3 :URL: storepage.com/one :END: ,** anotheritem :PROPERTIES: :ITM: two :COS: 7.50 :QTY: 12 :URL: storepage.com/two :END: ,** lastitem :PROPERTIES: :ITM: three :COS: 68.00 :QTY: 8 :URL: storepage.com/three :END: ,** line :PROPERTIES: :ITM: - :COS: :QTY: :URL: :END: ,** total :PROPERTIES: :ITM: Total :COS: :QTY: :URL: :END: ,** table #+BEGIN: columnview :id local :skip-empty-rows t | ITM | COS | QTY | |-------+-------+-------| | one | 34.80 | 3 | | two | 7.50 | 12 | | three | 68.00 | 8 | |-------+-------+-------| | Total | | 23.00 | #+TBLFM: @>$3=vsum(@I$3..@II$3);%.2f #+END
haichmonger:cmd:
backup hipfiles and important incidentals
ransacks:
/media/$USER/work/vfx/
/home/$USER/Downloads/
/home/$USER/Documents/
/home/$USER/Desktop/

#!/bin/bash td="$(printf '%s' "${PWD##*/}")" mkdir -p /media/$USER/$td/$USER/H/ mkdir -p /media/$USER/$td/$USER/H/textures/ mkdir -p /media/$USER/$td/$USER/py/ rsync -av --rsync-path="mkdir -p /media/$USER/$td/$USER/H" --prune-empty-dirs --exclude="backup" --exclude="farm" --exclude="delme*.*" --include="*/" --include="*.hip*" --include="*.rat*" --include="*/src/*.*" --exclude="*" /media/$USER/work/vfx/ /media/$USER/$td/$USER/H/$USER_project_backup/ rsync -av --rsync-path="mkdir -p /media/$USER/$td/$USER/H" --prune-empty-dirs --exclude="backup" --exclude="farm" --exclude="delme*.*" --include="*/" --include="*.hip*" --include="*.rat*" --include="*/src/*.*" --exclude="*" /home/$USER/Desktop/ /media/$USER/$td/$USER/H/$USER_project_backup/ rsync -av --rsync-path="mkdir -p /media/$USER/$td/$USER/H" --prune-empty-dirs --exclude="backup" --exclude="farm" --exclude="delme*.*" --include="*/" --include="*.hip*" --include="*.rat*" --include="*/src/*.*" --exclude="*" /home/$USER/Documents/ /media/$USER/$td/$USER/H/$USER_project_backup/ rsync -av --rsync-path="mkdir -p /media/$USER/$td/$USER/H" --prune-empty-dirs --exclude="backup" --exclude="farm" --exclude="delme*.*" --include="*/" --include="*.hip*" --include="*.rat*" --exclude="*" /home/$USER/Downloads/ /media/$USER/$td/$USER/H/download/ find /home/$USER/Desktop/ -name "*.hdr" -type f -size +1024k -exec cp "{}" /media/$USER/$td/$USER/H/textures/ \; find /home/$USER/Downloads/ -name "*.hdr" -type f -size +1024k -exec cp "{}" /media/$USER/$td/$USER/H/textures/ \; find /media/$USER/work/vfx/ -name "*.hdr" -type f -size +1024k -exec cp "{}" /media/$USER/$td/$USER/H/textures/ \; find /home/$USER/Desktop/ -name "*.py" -type f -size +1024k -exec cp "{}" /media/$USER/$td/$USER/py/ \; find /home/$USER/Documents/ -name "*.py" -type f -size +1024k -exec cp "{}" /media/$USER/$td/$USER/py/ \;
indie network:cmd:
network 4 machines via switch
- name server as..: 10.0.0.1 gateway 255.255.255.0 - name client 1 as: 10.0.0.2 gateway 255.255.255.0 - name client 2 as: 10.0.0.3 gateway 255.255.255.0 - name client 3 as: 10.0.0.4 gateway 255.255.255.0 - install ssh server on server: sudo apt install openssh-server - check /etc/hosts, add hosts and ips - check /etc/hosts.allow, add sshd: 10.0.0.2, sshd: 10.0.0.3, sshd: 10.0.0.4 - add a newline at the end of hosts.allow - mkdir ~/Desktop/projectname on all 4 machines - install ssh on clients : sudo apt-get install sshfs - sudo groupadd fuse - sudo adduser $USER fuse - sudo chown $USER:fuse /dev/fuse - sudo chmod +x /dev/fusermount - sshfs $USER@10.0.0.1:/home/$USER/Desktop/projectname ~/Desktop/projectname
INK
ghost:ink:
ghost
EOF

summary of a 20 year career in vfx

| role                  | started | ended |  cvr | exit               | learned                            |       |       |
|-----------------------+---------+-------+------+--------------------+------------------------------------+-------+-------|
| compositor/mograph    |    1998 |  1999 |  2.5 | quit               | 3DSMax, Digital Fusion             |       | ███   |
| 3D generalist         |    1999 |  2004 |  4.5 | quit/fired         | to much to list here               |       | █████ |
| FX specialist         |    2005 |  2008 |  2.0 | quit               | Thinking Particles, ICE            |       | ██    |
| 3D generalist         |    2008 |  2009 | -1.7 | quit/fired         | stay away from Hollywood           |    ██ |       |
| 3D generalist         |    2009 |  2009 | -1.8 | quit/fired         | Houdini                            |    ██ |       |
| FX specialist         |    2010 |  2011 | -4.3 | quit/fired         | rank & departments are retarded    | █████ |       |
| FX vendor             |    2012 |  2012 | -0.3 | contract complete  | Houdini simulations                |     █ |       |
| ██ ██████████         |    ████ |  ████ |  2.8 | ███████ █████████  | █████, ███████, ████████ & ███████ |       | ███   |
| FX vendor             |    2014 |  2015 |  0.5 | contracts complete | Vex, deadline                      |       | █     |
| FX specialist         |    2015 |  2015 | -4.3 | contract complete  | Emacs Org-Mode                     | █████ |       |
| 3D generalist         |    2016 |  2016 | -3.1 | quit               | 3DSMax still sucks                 |   ███ |       |
| 3D vendor             |    2015 |  2018 |  1.7 | contracts complete | quoting, negotiating               |       | ██    |
| middleware specialist |    2016 |  2016 |  2.7 | contract complete  | Ffmpeg, Shotgun                    |       | ███   |
| middleware vendor     |    2017 |  2018 | -1.1 | contract complete  | documentation                      |     █ |       |
|-----------------------+---------+-------+------+--------------------+------------------------------------+-------+-------|
#+TBLFM: $7='(orgtbl-uc-draw-cont $4 0.0 -5.0 5) :: $8='(orgtbl-uc-draw-cont $4 0.0 5.0 5)

  • CVR is weighted. Score represents overall value, not conditions on exit.
  • Early CVR scores were higher as there was more to learn, more direct contact with people I considered masters of their craft, and a relative lack of parasitism within studios.
  • Quit was due to an external factor in one case, disgust in the other cases.
  • Quit/fired was mostly due to retaliation against 'insubordination', which for an artist is about as fucking weird as bitching at a plumber for not wearing heels & makeup. This pest problem was belatedly remedied by independent contracting, which hilariously worked like a Jedi mind-trick as the "contractor" is "outside" of the "org-tree". Everybody would mind their manners (or be made to) while the vfx work carried on as usual. The pay was also way better. Contracting improved things, but by then I couldn't see much of a future in vfx. It was exactly like staying at a party long after all the fun people have left.

CVR
cost vs reward

Score is +1 for yes, -1 for no, 0 for sometimes,
weight according to priorities,
if the result is above zero, you're being rewarded,
if below zero, you're being punished.

Is your work reel-worthy?
Can you point at a hero sequence and say "yeah I did that"... or do you point to the 40 frames of motion-blurred dust-puffs and say "my 5 supervisors made me do those".
I weighted this at 1.0.
Do you control how to work?
Basic professional prerogative, one's innate desire to exercise one's own brains & vision, the fundamental driver of creative work... Deprive artists of this motivation and the work gets real fucking slow'n'sloppy.
I weighted this at 1.0.
Do you control when to work?
As above, but its a little more interesting with employees: If you complete 10 days of work in 5, you do not get 5 days off, you are saddled with 10 days of extra work with a 5-day deadline, without proportional pay, becoming 2x cheaper... and you'll probably be treated accordingly.
Pay-for-time proactively punishes efficiency this way, leading to what I call a 'pro-slacker' culture who game the system to their advantage. Those who don't quit anyway. Pro-slackers are generally not in the business of learning to work more efficiently, so they don't improve, becoming retarded versions of their potential selves. This is the real reason this question has to be asked.
I weighted this at 0.9.
Do you work with masters?
This will change over time as your skills improve; people you thought were awesome become just okay, but its important to measure this at the time, as there's just so much to be learned from highly effective people. Personally I also considered producers and support when answering this question, as I've learned quite a lot form exceptional people in these roles.
I weighted this at 0.8.
Are you learning new skills?
Not necessarily VFX skills, just anything useful.
I weighted this at 0.7.
Is the workload reasonable?
Not so slow you're inventing problems to solve, not such a brutal deathmarch that you risk dying on the way home. Personally the ideal for me was 6h of actual focused work per day, anything beyond that yielded severely diminishing returns.
I weighted this at 0.6, due to being used to heavy workloads since school.
Are you paid well?
in proportion to the value of your work to your employer/client.
For example: Were you paid a decent percentage of the 4M full CG campaign you personally made, or 20k on a flat day-rate? The answer to this question is always 'lol fuck-no', so having it on the CVR is of questionable value.
I weighted this at 0.5.

VFX POSTMORTEM

TL;DR for studios __---- burnouts 0 .'................ `-+-, /| + / | / \. / | -----+/ | talent . +/ | ./ | /......|................. ____--'| | | | | nubs |......|......|................. | test | keep | fire X= Age of artist experience Y= Moving-median success/fail trajectory (deliver on-time, on-spec, un-managed)
TL;DR for artists punishment __---- (stolen prestige) 0 .'.................. `-+-, /| + / | / \. / | reward -----+/ | (prestige) . +/ | ./ | /......|................... _____--'| | poverty | | | (limited prestige) |.......|......|................... | watch | stay | leave X= Age of studio Y= Fame of studio
The most important lessons from vfx:
  • Great work requires great talent, and great talent is forged in free pursuit of prestige, to succeed or fail by their efforts alone.
  • Prestige can be measured by three dimensions:
    • Fame: Scope of quality work one can claim credit for.
    • Fortune: Payment proportional to the value of one's work.
    • Freedom: Professional prerogative, including time tools & technique.
  • Talent may also value team-spirit (Friends) or the right to mount peers (Fuckery), however both steal prestige from others, breaking the model.
  • Talent includes salespeople who can identify and sell great work throughout the show, and support who can facilitate the work without parasitizing it.
  • A studio can become successful by riding a wave of great talent in its ascent by offering prestige, protection from theft of prestige, and access to tools & assistance.
  • Owners of a successful prestige-driven studio will eventually confuse people with talent, plant an org-tree by entertaining the delusion of hierarchy.
  • An org-tree will proactively steal prestige from talent, it cannot exist without doing-so.
  • An org-tree will try to quickly kill the host if threatened.
  • Independent studios with an org-tree, with no other source of income, tend to collapse. The org-tree will have irrecoverably starved & strangled the fundamental driver of a creative business: Great talent in free pursuit of great prestige.

2000s
PIC
fakeascii:pic::hou::demo:
rectanglepacking:pic::hou::demo:
2012:pic::3ds::film:
Whitehouse & garden: modelling, texturing, lighting, destruction

credits
2012_Whitehouse

Who made this pucture at Scanline LA:
(Camera, original whitehouse model and props were made by 3rd parties)

Matte Painter:
Jay Seo

Modeling and texturing:
Craig Brown (whitehouse and grounds)
David Bryant (background buildings)
Kevin Mains (debris)
Olek Lyzwanski (aircraft carrier)

Animation:
Craig Brown (trees)
Justin Mitchell (vehicles)

Water Simulation:
Andy Byrne
Stephan Trojansky

Lighting:
Craig Brown (whitehouse and grounds)
David Bryant (background buildings)
Andy Byrne (water)
Olek Lyzwanski (aircraft carrier)


Dynamics and particle fx:
Craig Brown (whitehouse and grounds)
Justin Mitchell (ash, small vehicles and debris)

Compositing and 2D effects:
Matt Doll

QC & creative direction:
Stephan Trojansky
Halo:pic::3ds::cine:
Cloak fx

credits
Halo_Cloak

who made this picture at Blur Studio:

Concept Design:
Hugo Martin
Sean McNally
Francisco Ruiz Velasco
Chuck Wojtkiewicz

Matte Painters:
Jaime Jasso
Hugo Martin

Layout:
Franck Balson
David Nibbellin
Nick Whitmire

Mocap Talent:
Gavin Carlton
Steve Gibbons
Heather McKenney
Paul Barthdmsew
Chris Bedrosian
Vanessa Vander Plum
Derron Ross

Mocap Prep and Clean-up:
Ryan Girard

Modeling:
Shaun Absher
Leandro Amaral
Alessandro Baldasseroni
Toni Bratincevic
Corey Butler
Darren Butler
Luis Calero
Zack Cork
Marek Denko
Chris Grim
Jinho Jang
Jaime Jasso
Sze Jones
Tim Jones
Ian Joyner
Kris Kaufman
James Ku
Alex Litchinko
Kevin Margo
Barrett Meeker
Jeremy Strong
Daniel Trbovic

Rigging:
Bryan Hillestad
Enoch Ihde
Michael Stieber
Brian Whitmire

Animation:
Ander Bergstrom
Joseph Chong
Bryan Hillestad
Jeremiah Izzard
Eddie Kim
Michael Loeck
Nick Maw-Naing
Derek Raymond
Davy Sabbe
Emil Simeonov
Peter Starostin
Rini Sugianto
William Vanoost
August Wartenberg
Brian Whitmire
Nick Whitmire
Jeff Wilson

Hair and Cloth Simulation:
Becca Baldwin
Jon Jordan

Lighting and Compositing:
Leandro Amaral
Heikki Anttila
Chris Bedrosian
Toni Bratincevic
Corey Butler
Darren Butler
Jaime Jasso
Tim Jones
Kris Kaufman
Greg Kegel
Patrick Killik
Jan Major
Kevin Margo
Barrett Meeker
Laurent Pierlot
Brian Prince
Fabio Stabel
Daniel Trbovic
Olivier Vernay-Kim
Dave Wilson
Dan Woje

FX:
Craig Brown
Ian Farnsworth
Seung Jae Lee
Andrew Melnychuk-Oseen
Kirby Miller
Brandon Riza
Mark Theriault
Brandon Young

Creative Director:
Tim Miller
Niagara:pic::3ds::cine:
Aurora

credits
Niagara_Aurora

Tim Jones:
Terrain.

C.P.Brown:
Aurora effect, starfield, compositing.
SuperBowl:pic::3ds::tvc:
Morph effect

credits
Superbowl_Morph

who made this picture at Blur Studio:

Mocap:
Ryan Girard

Mocap actor:
Chris Bedrosian

Layout/Animatic:
Andrew Grisdale
David Nibbelin

Rigging:
Mattias Jervill
Adam Swaab

Animation:
Ander Bergstrom
Adam Swaab

Modeling:
Luis Calero
James Ku

Lighting and Compositing:
Adam Swaab
Colin James
Chris Kelley

FX:
Craig Brown
Adam Swaab

Art Direction & QC:
Adam Swaab

Final QC:
Jennifer Miller
Jericho:pic::3ds::cine:
Clouds

credits
Jericho_Cloud

who made this picture at Blur Studio:

Mocap actors:
Gavin Carlton
Christopher Hicks
Heather Miller
Josh Sweeney

Mocap:
Ryan Girard
Jeff Weisend

Layout/Animatic:
Jean-Dominique Fievet

Character Modeling:
Shaun Absher
Luis Calero
Sze Jones
Ian Joyner
Barrett Meeker
Laurent Pierlot

Rigging:
Steve Guevara
Malcolm Thomas-Gustave
Bryan Hillestad

Animation:
Jean-Dominique Fievet
Ryan Girard
Bryan Hillestad
Jacob Patrick
Peter Starostin
Brian Whitmire

Hair and Cloth Simulation:
Rebecca Baldwin
Jon Jordan

Environment and Prop Modeling:
Sebastien Chort
Zack Cork
Daniel Trbovic

Lighting & Compositing:
Luis Calero
Sebastien Chort
Laurent Pierlot
David Stinnett

FX:
Brandon Riza
David Stinnett
c.p.brown

Art direction & QC:
Jerome Denjean

Final QC:
Tim Miller
imagetofrags:pic::hou::demo:
Sonic Next:pic::3ds::cine:
CG fire

credits
Sonic_Next_Fire

who made this picture at Blur Studio:

Mocap actors:
(? uncredited)

Mocap:
Ryan Girard

Layout/Animatic:
Leo Santos
Jean-Dominique Fievet

Character Modeling:
Sze Jones
Barrett Meeker
Cemre Ozkurt
Dan Rice
Juan Solis

Rigging:
Bryan Hillestad
Steve Guevara
Mattias Jervill
Malcolm Thomas-Gustave

Animation:
Ruel Pascual
Jacob Patrick
Leo Santos
George Schermer
Dave Vallone

Hair and Cloth Simulation:
Jon Jordan
Malcolm Thomas-Gustave

Environment and Prop Modeling:
Tim Jones
Cemre Ozkurt
Dan Rice
Daniel Trbovic

Lighting & Compositing:
Chris Bedrosian
Luis Calero
Sebastien Chort
Joshua Cox
Barrett Meeker
Dan Rice
Daniel Trbovic

FX:
Craig Brown
Jiyoung Hong
Sam Khorshid
Dan Knight

Art direction & QC:
Dan Rice

Final QC:
Tim Miller
Titan Quest:pic::3ds::cine:
Energy effect

credits
Titan_Quest_Telkine

who made this picture at Blur Studio:

Storyboards:
Chuck Wojtkiewicz

Concept Design:
Sean McNally

Matte Painter:
Dylan Cole

Mocap actors:
Steve Gibbons
Christopher Hicks
Vanessa Vander Pluym

Mocap:
Ryan Girard

Layout/Animatic:
Andrew Grisdale
David Nibbellin

Modeling
Shaun Absher
Chris Bedrosian
Luis Calero
Zack Cork
Tim Jones
Ian Joyner
Barrett Meeker
Iain Morton
Laurent Pierlot

Rigging:
Mattias Jervill
Remi McGill

Animation:
Jeff Fowler
Bryan Hillestad
Jacob Patrick
Davy Sabbe
Jason Taylor

Hair and Cloth Simulation:
Jon Jordan
Malcolm Thomas-Gustave

Lighting & Compositing:
Tim Jones
Barrett Meeker
Iain Morton

FX:
Craig Brown
Gus Wartenburg

Art direction & QC:
Tim Jones

Final QC:
Tim Miller
House of Flying Daggers:pic::3ds::film:
Beans

credits
House_of_Flying_Daggers_Beans

Maryanne Lauric: compositing.

Nigel Waddington:
rendering, additional lighting.

C.P.Brown:
animation (pflow setup),
modelling,
texturing and lighting,
scripting (bean randomiser).
Farscape Moya:pic::3ds::tvs:
Moya modelling & texturing, lighting & compositing

credits
Farscape_Moya

Sebastian Olivero: design.

Nigel Waddington: modelling (station).

Josh Simmonds: additional modelling (station).

Jon Thorsen: texturing (station).

Ben West: previs.

Marco Nero: background image.

Serge Kovalenko: moya modelling.

C.P.Brown :
moya modelling and texturing.
additional modelling (station).
animation.
lighting and compositing.
Farscape noseprobe:pic::3ds::tvs:
CG

credits
Farscape_NoseProbe

C.P.Brown :
Design.
Tracking and animation.
Shading.
Compositing.
Farscape starburst:pic::3ds::tvs:
Starburst effect

credits
Farscape_Starburst

Nick Martinelli: set design.

Sebastian Olivero: set design.

Octavio De Lellis: modelling and texturing (hangar).

Ben Malter: Talyn Prop.

Josh Simmonds: smoke shader.

C.P.Brown:
animation and particle fx.
additional texturing (starburst effect).
lighting and compositing.
Farscape frozen:pic::3ds::tvs:
CG

credits
Farscape_Frozen

C.P.Brown :
Camera match and animation.
Modelling and texturing.
Scripting (conditional param linking).
Lighting and compositing.
Farscape city:pic::3ds::tvs:
Lighting, compositing, atmos, shading, modelling, camera.

credits
Farscape_City

Nick Martinelli: Design.

Josh Simmonds: modelling (buildings).

Alex Scollay: modelling (traffic).

Ben Malter:
modelling and texturing
(foreground detail, traffic).
animation (foreground traffic).
fx (foreground fire).

C.P.Brown :
modelling and texturing (buildings, traffic).
camera match.
animation (background traffic).
atmospherics.
lighting and compositing.
Farscape eject:pic::3ds::tvs:
camera animation hair fx lighting

credits
Farscape_Eject

Thomas Kayser:
Matte-painting.

Alex Scolay:
Modeling & texturing.

C.P.Brown:
Camera, animation, fx, hair, lighting.
Farscape Stark:pic::3ds::tvs:
CG

credits
Farscape_Stark

C.P.Brown:
Tracking.
Scripting (3-point tracking helper).
Modelling and texturing.
Lighting and compositing.
Farscape crystals:pic::3ds::tvs:
CG

credits
Farscape_Crystals

C.P.Brown:
Design.
Camera match.
Modelling and texturing.
Lighting and compositing.
TXT
Maxscripts

All of these are obsolete, I stopped using 3DSMax in 2011... with a brief & embarrassing relapse in 2016.

Some scripts are missing, notably:
  • Nibbler(?): Boolean interface.
  • Fura: Fume wedging, sim-queue and previewing tool.

Pro-tip: Write your scripts at home, publish online, then only use at work if acquisitive inventions articles (invention assignment agreement) are struck out of your contract.

None of the following Maxscripts would have been possible without early mentoring/examples by Chris Cooper and Alex Mcleod. Lukas Lepicovsky helped with optimization & organization of heavier scripts later on.

pile:mxs::3ds:
screenie
download

Selectionset manager
Scene management functions
Object management functions
One-click scene-state capture/restore capability, similar in principle to Takes in Houdini

Used extensively for VFX work over many years.
pile history
Evolution of pile, in chronological order...
pile1
The original, purely a selection-set manager with basic per-set overrides.
Selection sets were chosen over newly introduced Layers for speed & versatility.

pile1

pile2
1st re-write: added object settings, capture/restore of unlimited renderer setting loadouts (3dsmax only had 2).
Data was stored in object user-data, which took more work than globaltracks or an external file, but it was extremely robust: pile set/object settings could be restored from a small number of objects in a heavily decimated scene, or imported 3ds geometry. Data loss was my greatest concern with alternative tools at this time.
My second greatest concern with alternatives was redundant ui: some of these tools literally replicated every renderer parameter in its own ui, which made no sense as we get the params for free with max. In pile I would just capture/restore renderer-settings with 1 click, too easy. It would take me a while to do the same with object/selectionset settings.

pile2

pile5
Pile 3, 4 & 5 gradually introduced params for scene management to cope with the effects of contrived departments (silos). In particular handling of source data that was not permitted to be designed for lateral work (or-else), and is constantly undergoing internal departmental revisions, for a heavy workload of up to 40 scenes at any given time.

pile5

pile6
Re-write, compacted most tools into rc-menus.
Added an expandable side panel for extra utilities like renaming and testrender history.
Finally added 1-click capture/restore for object/selectionset settings.
Capture/restore worked via a hierarchy of needs:
  • scene settings
    • renderer settings (and env)
      • unified state of settings/assignments per selection set
        • per object on/off, visibility, frozen, moblur etc.
These also came with toggles and overrides, plus a maxscript override that could do just about anything.
They were also saved per object, per set... so almost impossible to loose or corrupt the settings without using maxscript to purge them.

pile6

pile7
Removed side panel, condensed the new utilities into as little ui as possible. Everything had to be doable with one or two clicks, no data entry if possible.
Also added diagnostics which helped with detection of various bottlenecks.

pile7

troller:mxs::3ds:
screenie
download

Fast trackview bypass
Useful in heavy scenes where the trackview lags
bag:mxs::3ds:
screenie
download

script repo browser with localize functions
lampr:mxs::3ds:
screenie
download

bake nulls onto the surface of a deforming mesh
mostly used to anchor emitters to pre-cached characters
peel:mxs::3ds:
screenie
download

maxscript versioning maxscript
bakeme:mxs::3ds:
screenie
download

bake transforms of selected object
keybaker:mxs::3ds:
screenie
download

bake transforms of selected using another object
facet:mxs::3ds:
screenie
download

make an object look more faceted
not very useful, just trying to replicate something Alex Mcleod did
INK
buttons:ink:
buttons
mulch:ink:
mulch
gathering:ink:
gathering
unroll:ink:
unroll
component:ink:
component
staple:ink:
staple
actuator:ink:
actuator
shamble:ink:
shamble
ambule:ink:
ambule
bind:ink:
bind
wand:ink:
wand
bone:ink:
bone
twice:ink:
twice
dan:ink:
dan
conduit:ink:
conduit
lattice:ink:
lattice
object:ink:
object
moya:ink:
moya
scrapheap
gage:ink:
gage
elac:ink:
elac
unk1:ink:
unk1
unk2:ink:
unk2
unk3:ink:
unk3
blade:ink:
blade
1990s
INK

Mostly ballpoint, under 10x10cm
Hit any :ink: tag to doomscroll the whole lot...

animal:ink:
animal
direct:ink:
direct
thinking:ink:
thinking
doctor:ink:
doctor
drill:ink:
drill
plate:ink:
plate
hungry:ink:
hungry
teory:ink:
teory
cyborg:ink:
cyborg
loop:ink:
loop
lush:ink:
lush
batch:ink:
batch
assessment:ink:
assessment
shorts:ink:
shorts
fingers:ink:
fingers
july:ink:
july
stamp:ink:
stamp
feast:ink:
feast
nine:ink:
nine
PIC

Student work and demos.
Most Amiga digital work is lost.
Also lost a bunch of early commercial work, that had to be mastered direct to vhs in a hurry.

3dsmax_studies:pic::3ds::demo:
3dsmax_studies
Learning 3DSMax
Textures for top two images courtesy of PhotoAccess Canberra.
prisms:pic::demo:
prisms
Stills from student animations
Made with Prisms at ACAT Canberra.
deluxe_paint:pic::demo:
screenie
Scan of a print of a scan of a print of a negative of a photograph of a monitor-screen of pixel-pushing, made with Deluxe Paint on the A500.
Probably from around 1991. The only surviving example I could find.
Inspired by team portraits in SpeedBall2 by The Bitmap Brothers.
ABOUT

The :tags: are a toggle to filter & expand articles: click once to filter, click it again to unfilter.

  • TXT are scripts or programs I've created and used.
  • REF are notes, derivative works, or instructions for 3rd party technology. REF may also contain some of my abandoned/incomplete works that I need to keep online for my own reference.
  • PIC are artworks I've contributed to in some significant way. Group efforts are accompanied by credits where provided.
  • INK are old drawings. Bit cringe, but I get complaints every time they're taken-down.

Note: This site is exported from a living document. Articles may change over time, and many are gradually culled as they become less useful.

DISCLAIMERS AND DISCLOSURES

  • Texts elsewhere on this site are an exercise in fictional creative-writing, created for my own amusement.
  • Computer programs on this site do not come with a license for use, unless otherwise specified in both the code itself and the description of it on this site. If you copy and execute such programs and code regardless, you are cruising for a bruising: such programs may cause harm to you, your computer, your data, your career, your employer & colleagues, your clients & vendors, your friends & family, innocent bystanders and any related works, possessions and reputations thereof.
  • My programs are not generated by machine-learning (ML) software, as I doubt such practice leads to intrinsic ability. However: Derivative works on this site may or may not have been partly authored by ML without my knowledge, and I often ask ML dumb questions about basic math/comp-sci stuff I never learned at school.
  • The site is self-contained, doesn't use cookies or analytics: Don't know who visits, don't care.
  • This site was created in Org-Mode, then exported to html using a gifded queue written in Rebol3.