├── .gitignore ├── LICENSE ├── README.md ├── asciiart.js ├── bigDecimal.js ├── docs.js ├── files ├── Inconsolata-UFW.woff ├── OFL.txt ├── chars.txt ├── chartable.md ├── codepage.txt └── implemented.md ├── index.html ├── main.js ├── node.js ├── old ├── asciiartB2.js ├── asciiartB3.js ├── main0.js ├── main1.js ├── main2.js ├── main3.js ├── main4.js ├── main5.js ├── main6.js └── main7.js ├── package-lock.json ├── package.json └── style.css /.gitignore: -------------------------------------------------------------------------------- 1 | temp/ 2 | node_modules/ 3 | .fuse_hidden* 4 | .idea/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 dzaima 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Canvas 2 | Canvas is a stack-based golfing language, mainly made to be a better version of [SOGL](https://github.com/dzaima/SOGLOnline). For more info, check [the wiki](https://github.com/dzaima/Canvas/wiki) 3 | -------------------------------------------------------------------------------- /asciiart.js: -------------------------------------------------------------------------------- 1 | //# sourceURL=Canvas 2 | if (module) var Big = require('./bigDecimal'); 3 | // undefined - background 4 | // null - wasn't there originally - e.g. edges on a ragged array 5 | class Canvas { 6 | 7 | constructor (preset, p = preset.p) { 8 | if (p === undefined) throw new Error("no parent"); 9 | this.p = p; 10 | this.repr = []; 11 | this.possiblyMultiline = false; 12 | this.background = p? p.background : " "; 13 | this.sx = 0; 14 | this.sy = 0; 15 | this.ex = 0; 16 | this.ey = 0; 17 | if (typeof preset === "number" || preset instanceof Big) { 18 | preset = preset.toString(); 19 | } 20 | if (typeof preset === "string") { 21 | preset = preset.split("\n"); 22 | } 23 | if (preset instanceof Canvas) { 24 | this.repr = preset.repr.slice().map(c => c.slice()); 25 | this.sx = preset.sx; 26 | this.sy = preset.sy; 27 | this.ex = preset.ex; 28 | this.ey = preset.ey; 29 | this.background = preset.background; 30 | } 31 | if (Array.isArray(preset)) { 32 | const na = []; 33 | for (const c of preset) { 34 | if (isArt(c)) na.push(...c.repr); 35 | else na.push(c); 36 | } 37 | preset = na; 38 | this.ey = preset.length; 39 | let longestLine = 0; 40 | this.repr = preset.map((line) => { 41 | if (typeof line === "string" || isNum(line) || isJSNum(line)) { 42 | line = ""+line; 43 | if (line.length > longestLine) longestLine = line.length; 44 | return line.split(""); 45 | } else { 46 | let out = []; 47 | flatten(line).forEach((part) => { 48 | if (part === undefined) out.push(undefined); 49 | if (part === null) out.push(null); 50 | else out = out.concat(part.toString().split("")); 51 | }); 52 | if (out.length > longestLine) longestLine = out.length; 53 | return out; 54 | } 55 | }); 56 | this.repr = this.repr.map((line) => { 57 | while (line.length < longestLine) line.push(null); 58 | return line; 59 | }); 60 | this.ex = longestLine; 61 | } 62 | } 63 | toString(nullChr = this.background) { 64 | let res = ""; 65 | this.repr.forEach((line) => { 66 | line.forEach((chr) => { 67 | if (chr === undefined) res+= this.background; // this probably 68 | else if (chr === null ) res+= nullChr ; // shouldn't be 69 | else res+= chr ; // this aligned 70 | }); 71 | res+= "\n"; 72 | }); 73 | return res.slice(0,-1); 74 | } 75 | toDebugString(descLine) { 76 | const temp = this.background; 77 | if (this.background === ' ') this.background = '∙'; 78 | const out = this.toString('•'); 79 | this.background = temp; 80 | return out+(descLine? "\n" : "")+`<${this.sx};${this.sy},${this.ex};${this.ey} "${this.background}">`; 81 | } 82 | 83 | toArr() { 84 | const res = []; 85 | this.repr.forEach((line) => { 86 | let cline = ""; 87 | line.forEach((chr) => { 88 | if (chr === undefined || chr === null) cline+= this.background; 89 | else cline+= chr; 90 | }); 91 | res.push(cline); 92 | }); 93 | return res; 94 | } 95 | 96 | get width() { return this.ex-this.sx } 97 | get height() { return this.ey-this.sy } 98 | 99 | stringForm() { 100 | var res = ""; 101 | for (let y = 0; y < this.ey; y++) { 102 | for (let x = 0; x < this.ex; x++) { 103 | res+= this.getChr(x, y); 104 | } 105 | res+= "\n"; 106 | } 107 | return res.substring(0, res.length-1); 108 | } 109 | 110 | copy() { 111 | let res = new Canvas(this); 112 | res.sx = this.sx; 113 | res.sy = this.sy; 114 | res.ex = this.ex; 115 | res.ey = this.ey; 116 | res.background = this.background; 117 | res.possiblyMultiline = this.possiblyMultiline; 118 | return res; 119 | } 120 | 121 | get (x, y) { 122 | return (this.repr[y-this.sy] === undefined || this.repr[y-this.sy][x-this.sx] === undefined)? undefined : (this.repr[y-this.sy][x-this.sx]) 123 | } 124 | getChr (x,y) { 125 | return this.get(x,y) || this.background; 126 | } 127 | 128 | set (x, y, chr, leaveSize) { 129 | this.allocate(x, y, leaveSize); 130 | this.repr[y-this.sy][x-this.sx] = chr; 131 | return this; 132 | } 133 | 134 | included (x, y) { 135 | return y>this.ey && x>this.ex; 136 | } 137 | 138 | translate (x, y) { 139 | this.sx+= x; 140 | this.sy+= y; 141 | this.ex+= x; 142 | this.ey+= y; 143 | } 144 | 145 | allocate (x, y, leaveSize) { 146 | if (x < this.sx) { 147 | let spacing = new Array(this.sx - x).fill(null); 148 | this.repr = this.repr.map((line) => spacing.slice().concat(line)); 149 | this.sx = x; 150 | // console.log("a= this.ex) { 160 | let spacing = new Array(x - this.ex + 1).fill(null); 161 | this.repr = this.repr.map((line) => line.concat(spacing.slice())); 162 | if (!leaveSize) this.ex = x+1; 163 | // console.log("x>=ex"); 164 | } 165 | if (y >= this.ey) { 166 | let spacing = new Array(this.width).fill(null); 167 | for (let i = 0; i < y - this.ey + 1; i++) this.repr.push(spacing.slice()); 168 | if (!leaveSize) this.ey = y+1; 169 | // console.log("y>=ey"); 170 | } 171 | 172 | return this; 173 | } 174 | 175 | appendVertically (canvas) { 176 | this.overlap(canvas, this.sx, this.ey); 177 | return this; 178 | } 179 | appendHorizontally (canvas) { 180 | this.overlap(canvas, this.ex, this.sy); 181 | return this; 182 | } 183 | subsection (nsx, nsy, nex, ney) { 184 | if (nsx !== undefined) nsx+= this.sx; 185 | if (nsy !== undefined) nsy+= this.sy; 186 | // if (nex !== undefined) nex+= this.sx; 187 | // if (ney !== undefined) ney+= this.sy; 188 | // return new Canvas(this.repeatingSubsection(nex, ney).repr.slice(nsy).map(c => c.slice(nsx)), this.p); 189 | let resc = new Canvas(this); 190 | resc.allocate(nex, ney); 191 | return new Canvas(resc.repr.slice(nsy, ney).map(c => c.slice(nsx, nex)), this.p); 192 | } 193 | repeatingSubsection (x, y) { 194 | var r = this.repr; 195 | while (r.length < y) r = r.concat(this.repr); 196 | return new Canvas(r.slice(0, y).map(c => { 197 | var cr = c; 198 | while (cr.length < x) cr = cr.concat(c); 199 | return cr.slice(0, x); 200 | }), this.p); 201 | } 202 | forEach (lambda) { 203 | for (let x = this.sx; x < this.ex; x++) { 204 | for (let y = this.sy; y < this.ey; y++) { 205 | let chr = this.get(x, y); 206 | lambda(chr, x, y); 207 | } 208 | } 209 | } 210 | forEachChar (lambda) { 211 | for (let x = this.sx; x < this.ex; x++) { 212 | for (let y = this.sy; y < this.ey; y++) { 213 | let chr = this.get(x, y); 214 | if (chr !== null) lambda(chr, x, y); 215 | } 216 | } 217 | } 218 | 219 | mapSet (lambda) { 220 | for (let x = this.sx; x < this.ex; x++) { 221 | for (let y = this.sy; y < this.ey; y++) { 222 | let chr = this.get(x, y); 223 | this.set(x, y, lambda(chr, x, y)); 224 | } 225 | } 226 | } 227 | 228 | 229 | overlap (canvas, ox, oy, method = simpleOverlap) { 230 | if (typeof ox !== "number") ox = Number.parseInt(ox); 231 | if (typeof oy !== "number") oy = Number.parseInt(oy); 232 | canvas.forEach((chr, x, y) => {//console.log(chr,x,y,ox,oy); 233 | this.set(x+ox, y+oy, method(this.get(x+ox, y+oy), chr, x+ox, y+oy)); 234 | }); 235 | return this; 236 | } 237 | 238 | trimmedLine (y) { 239 | const res = this.repr[y - this.sy]; 240 | while (res.length > 0 && (res[0] === undefined || res[0] === null)) res.shift(); 241 | while (res.length > 0 && (res[res.length-1] === undefined || res[res.length-1] === null)) res.pop(); 242 | return res; 243 | } 244 | 245 | horizReverse () { 246 | this.repr.forEach((line) => line.reverse()); 247 | this.sx = this.repr.length-this.height; 248 | this.ex = this.repr.length>0? this.repr[0].length : 0; 249 | return this; 250 | } 251 | vertReverse () { 252 | this.repr.reverse(); 253 | this.sy = this.repr.length-this.ey; 254 | this.ey = this.repr.length+this.sy; 255 | return this; 256 | } 257 | horizMirror () { 258 | this.horizReverse(); 259 | this.mapSet((chr) => { 260 | let mirrorable = "\\/<>(){}[]"; 261 | if (mirrorable.includes(chr)) return mirrorable[mirrorable.indexOf(chr)^1]; 262 | return chr; 263 | }); 264 | return this; 265 | } 266 | vertMirror (fromSmart) { 267 | this.vertReverse(); 268 | this.mapSet((chr) => { 269 | let mirrorable = "\\/^v'.`,V^"; 270 | if (!fromSmart) if (chr === '‾') return "_"; 271 | if (mirrorable.includes(chr)) return mirrorable[mirrorable.indexOf(chr)^1]; 272 | return chr; 273 | }); 274 | return this; 275 | } 276 | 277 | vertMirrorSmart (overlapMode) { 278 | this.vertMirror(true); 279 | this.forEach((chr, x, y) => { 280 | if (chr === "_") { 281 | this.set(x, y, undefined); 282 | this.set(x, y-1, overlapMode(this.get(x, y-1), "_"), true); 283 | } 284 | if (chr === "‾") this.set(x, y, "_"); 285 | }); 286 | return this; 287 | } 288 | 289 | rotate (times, rotateMode) { 290 | if (!rotateMode) rotateMode = c=>c; 291 | for (let i = 0; i < (times%4 + 4)%4; i++) { 292 | let osx = this.sx, 293 | osy = this.sy, 294 | oex = this.ex, 295 | oey = this.ey; 296 | 297 | let newrepr = []; 298 | let orepr = this.repr; 299 | this.sy = osx; 300 | this.sx = orepr.length-oey; 301 | this.ex = this.sx + oey-osy; 302 | this.ey = this.sy + oex-osx; 303 | const len = orepr[0] === undefined ? 0 : orepr[0].length; 304 | for (let x = 0; x < len; x++) { 305 | let cline = []; 306 | for (let y = 0; y < orepr.length; y++) { 307 | cline.push(rotateMode(orepr[orepr.length-y-1][x])); 308 | } 309 | newrepr.push(cline); 310 | } 311 | this.repr = newrepr; 312 | } 313 | return this; 314 | } 315 | 316 | palindromize (...args) { 317 | for (let i = 0; i < args.length; i+= 4) { 318 | let mode = args[i]; 319 | let mirrormode = args[i+1]; 320 | let overlapSize = args[i+2]; 321 | let overlapMode = args[i+3]; 322 | if (mode === H) { 323 | let reversed = this.copy(); 324 | if (mirrormode === "mirror") reversed.horizMirror(); 325 | else if (mirrormode === "reverse") reversed.horizReverse(); 326 | else if (mirrormode !== "no") throw "invalid mirror mode " + mirrormode; 327 | this.overlap(reversed, this.width-overlapSize, 0, overlapMode); 328 | } else if (mode === V) { 329 | let reversed = this.copy(); 330 | if (mirrormode === "mirror") reversed.vertMirror(); 331 | else if (mirrormode === "reverse") reversed.vertReverse(); 332 | else if (typeof mirrormode === "function") reversed.vertMirrorSmart(mirrormode); 333 | else if (mirrormode !== "no") throw "invalid mirror mode " + mirrormode; 334 | this.overlap(reversed, 0, this.height-overlapSize, overlapMode); 335 | } else throw "invalid palindromizing mode " + mode; 336 | } 337 | return this; 338 | } 339 | c(){ console.log(this.toDebugString()) } 340 | } 341 | 342 | function flatten (inp, rec) { 343 | if (Array.isArray(inp)) { 344 | let out = []; 345 | for (let item of inp) { 346 | out = out.concat(flatten(item, true)); 347 | } 348 | return out; 349 | } else return rec? ((inp===null || inp===undefined)? inp : inp.toString()) : [...inp.toString()]; 350 | } 351 | //new Canvas(["/-\\",["|",[" ",[[[["|"]]]]]],"+-+"]).set(-1,-3,'~').set(4,4,'_').get(-1,-3) 352 | 353 | var simpleOverlap = (a, b) => { 354 | return b; 355 | }; 356 | 357 | var noBGOverlap = (a, b) => { 358 | if (b === undefined || b === null) return a; 359 | return b; 360 | }; 361 | 362 | var H = 1, 363 | V = 2; 364 | var smartOverlap = (a, b) => smartOverlapDef(a, b, b); 365 | var smartOverlapBehind = (a, b) => smartOverlapDef(a, b, a); 366 | var smartOverlapDef = function (a, b, def) { 367 | if (a===null || a===undefined || a===" ") return b; 368 | if (b===null || b===undefined || b===" ") return a; 369 | if (a==='_' && b!==' ') return b; 370 | if (b==='_' && a!==' ') return a; 371 | switch (a+b) { 372 | case "/\\": return "X"; 373 | case "\\/": return "X"; 374 | case "-|": return "+"; 375 | case "|-": return "+"; 376 | case "_.": return "_"; 377 | case "_,": return "_"; 378 | case "._": return "_"; 379 | case ",_": return "_"; 380 | 381 | case ",.": return ","; 382 | case ".,": return ","; 383 | case ",`": return ";"; 384 | case ",'": return ";"; 385 | case "`,": return ";"; 386 | case "',": return ";"; 387 | case ".`": return ":"; 388 | case ".'": return ":"; 389 | case "`.": return ":"; 390 | case "'.": return ":"; 391 | 392 | case "‾_": return "="; 393 | case "_‾": return "="; 394 | case "": return ""; 395 | default: return def; 396 | } 397 | }; 398 | 399 | // NOTE: rotates clockwise 400 | var smartRotate = function (chr) { 401 | var cycles = ["-|", "/\\", "<^>v", "_|"]; 402 | var found = cycles.find(c=>c.includes(chr)); 403 | if (found) return found[(found.indexOf(chr)+1) % found.length]; 404 | return chr; 405 | }; 406 | 407 | // var canvas0 = new Canvas(["/-\\",["|",[undefined,[[[["|"]]]]]],"+-+"]); 408 | // var canvas1 = canvas0.copy().set(-1,-3,'~').set(6,6,'_').set(1,1,undefined); 409 | // var canvas2 = canvas1.copy().overlap(canvas1, -2, 0, smcanvasOverlap).overlap(canvas1, -3, 1, smcanvasOverlap) 410 | // var canvas10 = new Canvas(" _,.-\n ,-'\\ _\n / _ \\ \n , \\ \n |-------\\"); 411 | // var canvas11 = canvas10.palindromize(H, "mirror", 1, smcanvasOverlap, V, (a, b) => smcanvasOverlapDef(a, b, a), 1, smcanvasOverlap); 412 | 413 | 414 | if (module) { 415 | module.exports = { 416 | smartRotate: smartRotate, 417 | smartOverlapDef: smartOverlapDef, 418 | smartOverlapBehind: smartOverlapBehind, 419 | smartOverlap: smartOverlap, 420 | noBGOverlap: noBGOverlap, 421 | simpleOverlap: simpleOverlap, 422 | Canvas: Canvas, 423 | }; 424 | } else window.Canvas = Canvas; -------------------------------------------------------------------------------- /bigDecimal.js: -------------------------------------------------------------------------------- 1 | /* big.js v3.1.3 https://github.com/MikeMcl/big.js/LICENCE */ 2 | ;(function (global) { 3 | 'use strict'; 4 | 5 | /* 6 | big.js v3.1.3 7 | A small, fast, easy-to-use library for arbitrary-precision decimal arithmetic. 8 | https://github.com/MikeMcl/big.js/ 9 | Copyright (c) 2014 Michael Mclaughlin 10 | MIT Expat Licence 11 | */ 12 | 13 | /***************************** EDITABLE DEFAULTS ******************************/ 14 | 15 | // The default values below must be integers within the stated ranges. 16 | 17 | /* 18 | * The maximum number of decimal places of the results of operations 19 | * involving divideision: divide and sqrt, and pow with negative exponents. 20 | */ 21 | var DP = 20, // 0 to MAX_DP 22 | 23 | /* 24 | * The rounding mode used when rounding to the above decimal places. 25 | * 26 | * 0 Towards zero (i.e. truncate, no rounding). (ROUND_DOWN) 27 | * 1 To nearest neighbour. If equidistant, round up. (ROUND_HALF_UP) 28 | * 2 To nearest neighbour. If equidistant, to even. (ROUND_HALF_EVEN) 29 | * 3 Away from zero. (ROUND_UP) 30 | */ 31 | RM = 1, // 0, 1, 2 or 3 32 | 33 | // The maximum value of DP and Big.DP. 34 | MAX_DP = 1E6, // 0 to 1000000 35 | 36 | // The maximum magnitude of the exponent argument to the pow method. 37 | MAX_POWER = 1E6, // 1 to 1000000 38 | ZERO = "0", 39 | ONE = "1", 40 | /* 41 | * The exponent value at and beneath which toString returns exponential 42 | * notation. 43 | * JavaScript's Number type: -7 44 | * -1000000 is the minimum recommended exponent value of a Big. 45 | */ 46 | E_NEG = -1000000, // 0 to -1000000 47 | 48 | /* 49 | * The exponent value at and above which toString returns exponential 50 | * notation. 51 | * JavaScript's Number type: 21 52 | * 1000000 is the maximum recommended exponent value of a Big. 53 | * (This limit is not enforced or checked.) 54 | */ 55 | E_POS = 1000000, // 0 to 1000000 56 | 57 | /******************************************************************************/ 58 | 59 | // The shared prototype object. 60 | P = {}, 61 | isValid = /^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i, 62 | Big; 63 | 64 | 65 | /* 66 | * Create and return a Big constructor. 67 | * 68 | */ 69 | function bigFactory() { 70 | 71 | /* 72 | * The Big constructor and exported function. 73 | * Create and return a new instance of a Big number object. 74 | * 75 | * n {number|string|Big} A numeric value. 76 | */ 77 | function Big(n) { 78 | var x = this; 79 | 80 | // Enable constructor usage without new. 81 | if (!(x instanceof Big)) { 82 | return n === void 0 ? bigFactory() : new Big(n); 83 | } 84 | 85 | // Duplicate. 86 | if (n instanceof Big) { 87 | x.s = n.s; 88 | x.e = n.e; 89 | x.c = n.c.slice(); 90 | } else { 91 | parse(x, n); 92 | } 93 | 94 | /* 95 | * Retain a reference to this Big constructor, and shadow 96 | * Big.prototype.constructor which points to Object. 97 | */ 98 | x.constructor = Big; 99 | } 100 | 101 | Big.prototype = P; 102 | Big.DP = DP; 103 | Big.RM = RM; 104 | Big.E_NEG = E_NEG; 105 | Big.E_POS = E_POS; 106 | Big.ZERO = Big("0"); 107 | Big.ONE = Big("1"); 108 | Big.ROUND_HALF_UP = 1; 109 | Big.ROUND_CEILING = 3; 110 | Big.ROUND_FLOOR = 0; 111 | 112 | return Big; 113 | } 114 | 115 | 116 | // Private functions 117 | 118 | 119 | /* 120 | * Return a string representing the value of Big x in normal or exponential 121 | * notation to dp fixed decimal places or significant digits. 122 | * 123 | * x {Big} The Big to format. 124 | * dp {number} Integer, 0 to MAX_DP inclusive. 125 | * toE {number} 1 (toExponential), 2 (toPrecision) or undefined (toFixed). 126 | */ 127 | function format(x, dp, toE) { 128 | var Big = x.constructor, 129 | 130 | // The index (normal notation) of the digit that may be rounded up. 131 | i = dp - (x = new Big(x)).e, 132 | c = x.c; 133 | 134 | // Round? 135 | if (c.length > ++dp) { 136 | rnd(x, i, Big.RM); 137 | } 138 | 139 | if (!c[0]) { 140 | ++i; 141 | } else if (toE) { 142 | i = dp; 143 | 144 | // toFixed 145 | } else { 146 | c = x.c; 147 | 148 | // Recalculate i as x.e may have changed if value rounded up. 149 | i = x.e + i + 1; 150 | } 151 | 152 | // Append zeros? 153 | for (; c.length < i; c.push(0)) { 154 | } 155 | i = x.e; 156 | 157 | /* 158 | * toPrecision returns exponential notation if the number of 159 | * significant digits specified is less than the number of digits 160 | * necessary to represent the integer part of the value in normal 161 | * notation. 162 | */ 163 | return toE === 1 || toE && (dp <= i || i <= Big.E_NEG) ? 164 | 165 | // Exponential notation. 166 | (x.s < 0 && c[0] ? '-' : '') + 167 | (c.length > 1 ? c[0] + '.' + c.join('').slice(1) : c[0]) + 168 | (i < 0 ? 'e' : 'e+') + i 169 | 170 | // Normal notation. 171 | : x.toString(); 172 | } 173 | 174 | 175 | /* 176 | * Parse the number or string value passed to a Big constructor. 177 | * 178 | * x {Big} A Big number instance. 179 | * n {number|string} A numeric value. 180 | */ 181 | function parse(x, n) { 182 | var e, i, nL; 183 | 184 | // Minus zero? 185 | if (n === 0 && 1 / n < 0) { 186 | n = '-0'; 187 | 188 | // Ensure n is string and check validity. 189 | } else if (!isValid.test(n += '')) { 190 | throwErr(NaN); 191 | } 192 | 193 | // Determine sign. 194 | x.s = n.charAt(0) == '-' ? (n = n.slice(1), -1) : 1; 195 | 196 | // Decimal point? 197 | if ((e = n.indexOf('.')) > -1) { 198 | n = n.replace('.', ''); 199 | } 200 | 201 | // Exponential form? 202 | if ((i = n.search(/e/i)) > 0) { 203 | 204 | // Determine exponent. 205 | if (e < 0) { 206 | e = i; 207 | } 208 | e += +n.slice(i + 1); 209 | n = n.substring(0, i); 210 | 211 | } else if (e < 0) { 212 | 213 | // Integer. 214 | e = n.length; 215 | } 216 | 217 | // Determine leading zeros. 218 | for (i = 0; n.charAt(i) == '0'; i++) { 219 | } 220 | 221 | if (i == (nL = n.length)) { 222 | 223 | // Zero. 224 | x.c = [ x.e = 0 ]; 225 | } else { 226 | 227 | // Determine trailing zeros. 228 | for (; n.charAt(--nL) == '0';) { 229 | } 230 | 231 | x.e = e - i - 1; 232 | x.c = []; 233 | 234 | // Convert string to array of digits without leading/trailing zeros. 235 | for (e = 0; i <= nL; x.c[e++] = +n.charAt(i++)) { 236 | } 237 | } 238 | 239 | return x; 240 | } 241 | 242 | 243 | /* 244 | * Round Big x to a maximum of dp decimal places using rounding mode rm. 245 | * Called by divide, sqrt and round. 246 | * 247 | * x {Big} The Big to round. 248 | * dp {number} Integer, 0 to MAX_DP inclusive. 249 | * rm {number} 0, 1, 2 or 3 (DOWN, HALF_UP, HALF_EVEN, UP) 250 | * [more] {boolean} Whether the result of divideision was truncated. 251 | */ 252 | function rnd(x, dp, rm, more) { 253 | var u, 254 | xc = x.c, 255 | i = x.e + dp + 1; 256 | 257 | if (rm === 1) { 258 | 259 | // xc[i] is the digit after the digit that may be rounded up. 260 | more = xc[i] >= 5; 261 | } else if (rm === 2) { 262 | more = xc[i] > 5 || xc[i] == 5 && 263 | (more || i < 0 || xc[i + 1] !== u || xc[i - 1] & 1); 264 | } else if (rm === 3) { 265 | more = more || xc[i] !== u || i < 0; 266 | } else { 267 | more = false; 268 | 269 | if (rm !== 0) { 270 | throwErr('!Big.RM!'); 271 | } 272 | } 273 | 274 | if (i < 1 || !xc[0]) { 275 | 276 | if (more) { 277 | 278 | // 1, 0.1, 0.01, 0.001, 0.0001 etc. 279 | x.e = -dp; 280 | x.c = [1]; 281 | } else { 282 | 283 | // Zero. 284 | x.c = [x.e = 0]; 285 | } 286 | } else { 287 | 288 | // Remove any digits after the required decimal places. 289 | xc.length = i--; 290 | 291 | // Round up? 292 | if (more) { 293 | 294 | // Rounding up may mean the previous digit has to be rounded up. 295 | for (; ++xc[i] > 9;) { 296 | xc[i] = 0; 297 | 298 | if (!i--) { 299 | ++x.e; 300 | xc.unshift(1); 301 | } 302 | } 303 | } 304 | 305 | // Remove trailing zeros. 306 | for (i = xc.length; !xc[--i]; xc.pop()) { 307 | } 308 | } 309 | 310 | return x; 311 | } 312 | 313 | P.setScale = function (dp, rm) { 314 | return rnd(this, dp, rm, false); 315 | } 316 | /* 317 | * Throw a BigError. 318 | * 319 | * message {string} The error message. 320 | */ 321 | function throwErr(message) { 322 | var err = new Error(message); 323 | err.name = 'BigError'; 324 | 325 | throw err; 326 | } 327 | 328 | 329 | // Prototype/instance methods 330 | 331 | 332 | /* 333 | * Return a new Big whose value is the absolute value of this Big. 334 | */ 335 | P.abs = function () { 336 | var x = new this.constructor(this); 337 | x.s = 1; 338 | 339 | return x; 340 | }; 341 | 342 | 343 | /* 344 | * Return 345 | * 1 if the value of this Big is greater than the value of Big y, 346 | * -1 if the value of this Big is less than the value of Big y, or 347 | * 0 if they have the same value. 348 | */ 349 | 350 | P.compareTo = P.cmp = function (y) { 351 | var xNeg, 352 | x = this, 353 | xc = x.c, 354 | yc = (y = new x.constructor(y)).c, 355 | i = x.s, 356 | j = y.s, 357 | k = x.e, 358 | l = y.e; 359 | 360 | // Either zero? 361 | if (!xc[0] || !yc[0]) { 362 | return !xc[0] ? !yc[0] ? 0 : -j : i; 363 | } 364 | 365 | // Signs differ? 366 | if (i != j) { 367 | return i; 368 | } 369 | xNeg = i < 0; 370 | 371 | // Compare exponents. 372 | if (k != l) { 373 | return k > l ^ xNeg ? 1 : -1; 374 | } 375 | 376 | i = -1; 377 | j = (k = xc.length) < (l = yc.length) ? k : l; 378 | 379 | // Compare digit by digit. 380 | for (; ++i < j;) { 381 | 382 | if (xc[i] != yc[i]) { 383 | return xc[i] > yc[i] ^ xNeg ? 1 : -1; 384 | } 385 | } 386 | 387 | // Compare lengths. 388 | return k == l ? 0 : k > l ^ xNeg ? 1 : -1; 389 | }; 390 | 391 | 392 | /* 393 | * Return a new Big whose value is the value of this Big divided by the 394 | * value of Big y, rounded, if necessary, to a maximum of Big.DP decimal 395 | * places using rounding mode Big.RM. 396 | */ 397 | P.divide = function (y) { 398 | var x = this, 399 | Big = x.constructor, 400 | // dividend 401 | dvd = x.c, 402 | //divisor 403 | dvs = (y = new Big(y)).c, 404 | s = x.s == y.s ? 1 : -1, 405 | dp = Big.DP; 406 | 407 | if (dp !== ~~dp || dp < 0 || dp > MAX_DP) { 408 | throwErr('!Big.DP!'); 409 | } 410 | 411 | // Either 0? 412 | if (!dvd[0] || !dvs[0]) { 413 | 414 | // If both are 0, throw NaN 415 | if (dvd[0] == dvs[0]) { 416 | throwErr(NaN); 417 | } 418 | 419 | // If dvs is 0, throw +-Infinity. 420 | if (!dvs[0]) { 421 | throwErr(s / 0); 422 | } 423 | 424 | // dvd is 0, return +-0. 425 | return new Big(s * 0); 426 | } 427 | 428 | var dvsL, dvsT, next, cmp, remI, u, 429 | dvsZ = dvs.slice(), 430 | dvdI = dvsL = dvs.length, 431 | dvdL = dvd.length, 432 | // remainder 433 | rem = dvd.slice(0, dvsL), 434 | remL = rem.length, 435 | // quotient 436 | q = y, 437 | qc = q.c = [], 438 | qi = 0, 439 | digits = dp + (q.e = x.e - y.e) + 1; 440 | 441 | q.s = s; 442 | s = digits < 0 ? 0 : digits; 443 | 444 | // Create version of divideisor with leading zero. 445 | dvsZ.unshift(0); 446 | 447 | // Add zeros to make remainder as long as divideisor. 448 | for (; remL++ < dvsL; rem.push(0)) { 449 | } 450 | 451 | do { 452 | 453 | // 'next' is how many times the divideisor goes into current remainder. 454 | for (next = 0; next < 10; next++) { 455 | 456 | // Compare divideisor and remainder. 457 | if (dvsL != (remL = rem.length)) { 458 | cmp = dvsL > remL ? 1 : -1; 459 | } else { 460 | 461 | for (remI = -1, cmp = 0; ++remI < dvsL;) { 462 | 463 | if (dvs[remI] != rem[remI]) { 464 | cmp = dvs[remI] > rem[remI] ? 1 : -1; 465 | break; 466 | } 467 | } 468 | } 469 | 470 | // If divideisor < remainder, subtract divideisor from remainder. 471 | if (cmp < 0) { 472 | 473 | // Remainder can't be more than 1 digit longer than divideisor. 474 | // Equalise lengths using divideisor with extra leading zero? 475 | for (dvsT = remL == dvsL ? dvs : dvsZ; remL;) { 476 | 477 | if (rem[--remL] < dvsT[remL]) { 478 | remI = remL; 479 | 480 | for (; remI && !rem[--remI]; rem[remI] = 9) { 481 | } 482 | --rem[remI]; 483 | rem[remL] += 10; 484 | } 485 | rem[remL] -= dvsT[remL]; 486 | } 487 | for (; !rem[0]; rem.shift()) { 488 | } 489 | } else { 490 | break; 491 | } 492 | } 493 | 494 | // Add the 'next' digit to the result array. 495 | qc[qi++] = cmp ? next : ++next; 496 | 497 | // Update the remainder. 498 | if (rem[0] && cmp) { 499 | rem[remL] = dvd[dvdI] || 0; 500 | } else { 501 | rem = [ dvd[dvdI] ]; 502 | } 503 | 504 | } while ((dvdI++ < dvdL || rem[0] !== u) && s--); 505 | 506 | // Leading zero? Do not remove if result is simply zero (qi == 1). 507 | if (!qc[0] && qi != 1) { 508 | 509 | // There can't be more than one zero. 510 | qc.shift(); 511 | q.e--; 512 | } 513 | 514 | // Round? 515 | if (qi > digits) { 516 | rnd(q, dp, Big.RM, rem[0] !== u); 517 | } 518 | 519 | return q; 520 | }; 521 | 522 | 523 | /* 524 | * Return true if the value of this Big is equal to the value of Big y, 525 | * otherwise returns false. 526 | */ 527 | P.eq = function (y) { 528 | return !this.cmp(y); 529 | }; 530 | 531 | 532 | /* 533 | * Return true if the value of this Big is greater than the value of Big y, 534 | * otherwise returns false. 535 | */ 536 | P.gt = function (y) { 537 | return this.cmp(y) > 0; 538 | }; 539 | 540 | 541 | /* 542 | * Return true if the value of this Big is greater than or equal to the 543 | * value of Big y, otherwise returns false. 544 | */ 545 | P.gte = function (y) { 546 | return this.cmp(y) > -1; 547 | }; 548 | 549 | 550 | /* 551 | * Return true if the value of this Big is less than the value of Big y, 552 | * otherwise returns false. 553 | */ 554 | P.lt = function (y) { 555 | return this.cmp(y) < 0; 556 | }; 557 | 558 | 559 | /* 560 | * Return true if the value of this Big is less than or equal to the value 561 | * of Big y, otherwise returns false. 562 | */ 563 | P.lte = function (y) { 564 | return this.cmp(y) < 1; 565 | }; 566 | 567 | 568 | /* 569 | * Return a new Big whose value is the value of this Big minus the value 570 | * of Big y. 571 | */ 572 | P.sub = P.minus = P.subtract = function (y) { 573 | var i, j, t, xLTy, 574 | x = this, 575 | Big = x.constructor, 576 | a = x.s, 577 | b = (y = new Big(y)).s; 578 | 579 | // Signs differ? 580 | if (a != b) { 581 | y.s = -b; 582 | return x.plus(y); 583 | } 584 | 585 | var xc = x.c.slice(), 586 | xe = x.e, 587 | yc = y.c, 588 | ye = y.e; 589 | 590 | // Either zero? 591 | if (!xc[0] || !yc[0]) { 592 | 593 | // y is non-zero? x is non-zero? Or both are zero. 594 | return yc[0] ? (y.s = -b, y) : new Big(xc[0] ? x : 0); 595 | } 596 | 597 | // Determine which is the bigger number. 598 | // Prepend zeros to equalise exponents. 599 | if (a = xe - ye) { 600 | 601 | if (xLTy = a < 0) { 602 | a = -a; 603 | t = xc; 604 | } else { 605 | ye = xe; 606 | t = yc; 607 | } 608 | 609 | t.reverse(); 610 | for (b = a; b--; t.push(0)) { 611 | } 612 | t.reverse(); 613 | } else { 614 | 615 | // Exponents equal. Check digit by digit. 616 | j = ((xLTy = xc.length < yc.length) ? xc : yc).length; 617 | 618 | for (a = b = 0; b < j; b++) { 619 | 620 | if (xc[b] != yc[b]) { 621 | xLTy = xc[b] < yc[b]; 622 | break; 623 | } 624 | } 625 | } 626 | 627 | // x < y? Point xc to the array of the bigger number. 628 | if (xLTy) { 629 | t = xc; 630 | xc = yc; 631 | yc = t; 632 | y.s = -y.s; 633 | } 634 | 635 | /* 636 | * Append zeros to xc if shorter. No need to add zeros to yc if shorter 637 | * as subtraction only needs to start at yc.length. 638 | */ 639 | if (( b = (j = yc.length) - (i = xc.length) ) > 0) { 640 | 641 | for (; b--; xc[i++] = 0) { 642 | } 643 | } 644 | 645 | // Subtract yc from xc. 646 | for (b = i; j > a;){ 647 | 648 | if (xc[--j] < yc[j]) { 649 | 650 | for (i = j; i && !xc[--i]; xc[i] = 9) { 651 | } 652 | --xc[i]; 653 | xc[j] += 10; 654 | } 655 | xc[j] -= yc[j]; 656 | } 657 | 658 | // Remove trailing zeros. 659 | for (; xc[--b] === 0; xc.pop()) { 660 | } 661 | 662 | // Remove leading zeros and adjust exponent accordingly. 663 | for (; xc[0] === 0;) { 664 | xc.shift(); 665 | --ye; 666 | } 667 | 668 | if (!xc[0]) { 669 | 670 | // n - n = +0 671 | y.s = 1; 672 | 673 | // Result must be zero. 674 | xc = [ye = 0]; 675 | } 676 | 677 | y.c = xc; 678 | y.e = ye; 679 | 680 | return y; 681 | }; 682 | 683 | 684 | /* 685 | * Return a new Big whose value is the value of this Big modulo the 686 | * value of Big y. 687 | */ 688 | P.remainder = P.mod = function (y) { 689 | var yGTx, 690 | x = this, 691 | Big = x.constructor, 692 | a = x.s, 693 | b = (y = new Big(y)).s; 694 | 695 | if (!y.c[0]) { 696 | throwErr(NaN); 697 | } 698 | 699 | x.s = y.s = 1; 700 | yGTx = y.cmp(x) == 1; 701 | x.s = a; 702 | y.s = b; 703 | 704 | if (yGTx) { 705 | return new Big(x); 706 | } 707 | 708 | a = Big.DP; 709 | b = Big.RM; 710 | Big.DP = Big.RM = 0; 711 | x = x.divide(y); 712 | Big.DP = a; 713 | Big.RM = b; 714 | 715 | return this.minus( x.multiply(y) ); 716 | }; 717 | 718 | 719 | /* 720 | * Return a new Big whose value is the value of this Big plus the value 721 | * of Big y. 722 | */ 723 | P.add = P.plus = function (y) { 724 | var t, 725 | x = this, 726 | Big = x.constructor, 727 | a = x.s, 728 | b = (y = new Big(y)).s; 729 | 730 | // Signs differ? 731 | if (a != b) { 732 | y.s = -b; 733 | return x.minus(y); 734 | } 735 | 736 | var xe = x.e, 737 | xc = x.c, 738 | ye = y.e, 739 | yc = y.c; 740 | 741 | // Either zero? 742 | if (!xc[0] || !yc[0]) { 743 | 744 | // y is non-zero? x is non-zero? Or both are zero. 745 | return yc[0] ? y : new Big(xc[0] ? x : a * 0); 746 | } 747 | xc = xc.slice(); 748 | 749 | // Prepend zeros to equalise exponents. 750 | // Note: Faster to use reverse then do unshifts. 751 | if (a = xe - ye) { 752 | 753 | if (a > 0) { 754 | ye = xe; 755 | t = yc; 756 | } else { 757 | a = -a; 758 | t = xc; 759 | } 760 | 761 | t.reverse(); 762 | for (; a--; t.push(0)) { 763 | } 764 | t.reverse(); 765 | } 766 | 767 | // Point xc to the longer array. 768 | if (xc.length - yc.length < 0) { 769 | t = yc; 770 | yc = xc; 771 | xc = t; 772 | } 773 | a = yc.length; 774 | 775 | /* 776 | * Only start adding at yc.length - 1 as the further digits of xc can be 777 | * left as they are. 778 | */ 779 | for (b = 0; a;) { 780 | b = (xc[--a] = xc[a] + yc[a] + b) / 10 | 0; 781 | xc[a] %= 10; 782 | } 783 | 784 | // No need to check for zero, as +x + +y != 0 && -x + -y != 0 785 | 786 | if (b) { 787 | xc.unshift(b); 788 | ++ye; 789 | } 790 | 791 | // Remove trailing zeros. 792 | for (a = xc.length; xc[--a] === 0; xc.pop()) { 793 | } 794 | 795 | y.c = xc; 796 | y.e = ye; 797 | 798 | return y; 799 | }; 800 | 801 | 802 | /* 803 | * Return a Big whose value is the value of this Big raised to the power n. 804 | * If n is negative, round, if necessary, to a maximum of Big.DP decimal 805 | * places using rounding mode Big.RM. 806 | * 807 | * n {number} Integer, -MAX_POWER to MAX_POWER inclusive. 808 | */ 809 | P.pow = function (n) { 810 | var x = this, 811 | one = new x.constructor(1), 812 | y = one, 813 | isNeg = n < 0; 814 | 815 | if (n !== ~~n || n < -MAX_POWER || n > MAX_POWER) { 816 | throwErr('!pow!'); 817 | } 818 | 819 | n = isNeg ? -n : n; 820 | 821 | for (;;) { 822 | 823 | if (n & 1) { 824 | y = y.multiply(x); 825 | } 826 | n >>= 1; 827 | 828 | if (!n) { 829 | break; 830 | } 831 | x = x.multiply(x); 832 | } 833 | 834 | return isNeg ? one.divide(y) : y; 835 | }; 836 | 837 | 838 | /* 839 | * Return a new Big whose value is the value of this Big rounded to a 840 | * maximum of dp decimal places using rounding mode rm. 841 | * If dp is not specified, round to 0 decimal places. 842 | * If rm is not specified, use Big.RM. 843 | * 844 | * [dp] {number} Integer, 0 to MAX_DP inclusive. 845 | * [rm] 0, 1, 2 or 3 (ROUND_DOWN, ROUND_HALF_UP, ROUND_HALF_EVEN, ROUND_UP) 846 | */ 847 | P.round = function (dp, rm) { 848 | var x = this, 849 | Big = x.constructor; 850 | 851 | if (dp == null) { 852 | dp = 0; 853 | } else if (dp !== ~~dp || dp < 0 || dp > MAX_DP) { 854 | throwErr('!round!'); 855 | } 856 | rnd(x = new Big(x), dp, rm == null ? Big.RM : rm); 857 | 858 | return x; 859 | }; 860 | 861 | 862 | /* 863 | * Return a new Big whose value is the square root of the value of this Big, 864 | * rounded, if necessary, to a maximum of Big.DP decimal places using 865 | * rounding mode Big.RM. 866 | */ 867 | P.sqrt = function () { 868 | var estimate, r, approx, 869 | x = this, 870 | Big = x.constructor, 871 | xc = x.c, 872 | i = x.s, 873 | e = x.e, 874 | half = new Big('0.5'); 875 | 876 | // Zero? 877 | if (!xc[0]) { 878 | return new Big(x); 879 | } 880 | 881 | // If negative, throw NaN. 882 | if (i < 0) { 883 | throwErr(NaN); 884 | } 885 | 886 | // Estimate. 887 | i = Math.sqrt(x.toString()); 888 | 889 | // Math.sqrt underflow/overflow? 890 | // Pass x to Math.sqrt as integer, then adjust the result exponent. 891 | if (i === 0 || i === 1 / 0) { 892 | estimate = xc.join(''); 893 | 894 | if (!(estimate.length + e & 1)) { 895 | estimate += '0'; 896 | } 897 | 898 | r = new Big( Math.sqrt(estimate).toString() ); 899 | r.e = ((e + 1) / 2 | 0) - (e < 0 || e & 1); 900 | } else { 901 | r = new Big(i.toString()); 902 | } 903 | 904 | i = r.e + (Big.DP += 4); 905 | 906 | // Newton-Raphson iteration. 907 | do { 908 | approx = r; 909 | r = half.multiply( approx.plus( x.divide(approx) ) ); 910 | } while ( approx.c.slice(0, i).join('') !== 911 | r.c.slice(0, i).join('') ); 912 | 913 | rnd(r, Big.DP -= 4, Big.RM); 914 | 915 | return r; 916 | }; 917 | 918 | 919 | /* 920 | * Return a new Big whose value is the value of this Big times the value of 921 | * Big y. 922 | */ 923 | P.mul = P.multiply = function (y) { 924 | var c, 925 | x = this, 926 | Big = x.constructor, 927 | xc = x.c, 928 | yc = (y = new Big(y)).c, 929 | a = xc.length, 930 | b = yc.length, 931 | i = x.e, 932 | j = y.e; 933 | 934 | // Determine sign of result. 935 | y.s = x.s == y.s ? 1 : -1; 936 | 937 | // Return signed 0 if either 0. 938 | if (!xc[0] || !yc[0]) { 939 | return new Big(y.s * 0); 940 | } 941 | 942 | // Initialise exponent of result as x.e + y.e. 943 | y.e = i + j; 944 | 945 | // If array xc has fewer digits than yc, swap xc and yc, and lengths. 946 | if (a < b) { 947 | c = xc; 948 | xc = yc; 949 | yc = c; 950 | j = a; 951 | a = b; 952 | b = j; 953 | } 954 | 955 | // Initialise coefficient array of result with zeros. 956 | for (c = new Array(j = a + b); j--; c[j] = 0) { 957 | } 958 | 959 | // Multiply. 960 | 961 | // i is initially xc.length. 962 | for (i = b; i--;) { 963 | b = 0; 964 | 965 | // a is yc.length. 966 | for (j = a + i; j > i;) { 967 | 968 | // Current sum of products at this digit position, plus carry. 969 | b = c[j] + yc[i] * xc[j - i - 1] + b; 970 | c[j--] = b % 10; 971 | 972 | // carry 973 | b = b / 10 | 0; 974 | } 975 | c[j] = (c[j] + b) % 10; 976 | } 977 | 978 | // Increment result exponent if there is a final carry. 979 | if (b) { 980 | ++y.e; 981 | } 982 | 983 | // Remove any leading zero. 984 | if (!c[0]) { 985 | c.shift(); 986 | } 987 | 988 | // Remove trailing zeros. 989 | for (i = c.length; !c[--i]; c.pop()) { 990 | } 991 | y.c = c; 992 | 993 | return y; 994 | }; 995 | 996 | 997 | /* 998 | * Return a string representing the value of this Big. 999 | * Return exponential notation if this Big has a positive exponent equal to 1000 | * or greater than Big.E_POS, or a negative exponent equal to or less than 1001 | * Big.E_NEG. 1002 | */ 1003 | P.toString = P.valueOf = P.toJSON = function () { 1004 | var x = this, 1005 | Big = x.constructor, 1006 | e = x.e, 1007 | str = x.c.join(''), 1008 | strL = str.length; 1009 | 1010 | // Exponential notation? 1011 | if (e <= Big.E_NEG || e >= Big.E_POS) { 1012 | str = str.charAt(0) + (strL > 1 ? '.' + str.slice(1) : '') + 1013 | (e < 0 ? 'e' : 'e+') + e; 1014 | 1015 | // Negative exponent? 1016 | } else if (e < 0) { 1017 | 1018 | // Prepend zeros. 1019 | for (; ++e; str = '0' + str) { 1020 | } 1021 | str = '0.' + str; 1022 | 1023 | // Positive exponent? 1024 | } else if (e > 0) { 1025 | 1026 | if (++e > strL) { 1027 | 1028 | // Append zeros. 1029 | for (e -= strL; e-- ; str += '0') { 1030 | } 1031 | } else if (e < strL) { 1032 | str = str.slice(0, e) + '.' + str.slice(e); 1033 | } 1034 | 1035 | // Exponent zero. 1036 | } else if (strL > 1) { 1037 | str = str.charAt(0) + '.' + str.slice(1); 1038 | } 1039 | 1040 | // Avoid '-0' 1041 | return x.s < 0 && x.c[0] ? '-' + str : str; 1042 | }; 1043 | 1044 | 1045 | /* 1046 | *************************************************************************** 1047 | * If toExponential, toFixed, toPrecision and format are not required they 1048 | * can safely be commented-out or deleted. No redundant code will be left. 1049 | * format is used only by toExponential, toFixed and toPrecision. 1050 | *************************************************************************** 1051 | */ 1052 | 1053 | 1054 | /* 1055 | * Return a string representing the value of this Big in exponential 1056 | * notation to dp fixed decimal places and rounded, if necessary, using 1057 | * Big.RM. 1058 | * 1059 | * [dp] {number} Integer, 0 to MAX_DP inclusive. 1060 | */ 1061 | P.toExponential = function (dp) { 1062 | 1063 | if (dp == null) { 1064 | dp = this.c.length - 1; 1065 | } else if (dp !== ~~dp || dp < 0 || dp > MAX_DP) { 1066 | throwErr('!toExp!'); 1067 | } 1068 | 1069 | return format(this, dp, 1); 1070 | }; 1071 | 1072 | 1073 | /* 1074 | * Return a string representing the value of this Big in normal notation 1075 | * to dp fixed decimal places and rounded, if necessary, using Big.RM. 1076 | * 1077 | * [dp] {number} Integer, 0 to MAX_DP inclusive. 1078 | */ 1079 | P.toFixed = function (dp) { 1080 | var str, 1081 | x = this, 1082 | Big = x.constructor, 1083 | neg = Big.E_NEG, 1084 | pos = Big.E_POS; 1085 | 1086 | // Prevent the possibility of exponential notation. 1087 | Big.E_NEG = -(Big.E_POS = 1 / 0); 1088 | 1089 | if (dp == null) { 1090 | str = x.toString(); 1091 | } else if (dp === ~~dp && dp >= 0 && dp <= MAX_DP) { 1092 | str = format(x, x.e + dp); 1093 | 1094 | // (-0).toFixed() is '0', but (-0.1).toFixed() is '-0'. 1095 | // (-0).toFixed(1) is '0.0', but (-0.01).toFixed(1) is '-0.0'. 1096 | if (x.s < 0 && x.c[0] && str.indexOf('-') < 0) { 1097 | //E.g. -0.5 if rounded to -0 will cause toString to omit the minus sign. 1098 | str = '-' + str; 1099 | } 1100 | } 1101 | Big.E_NEG = neg; 1102 | Big.E_POS = pos; 1103 | 1104 | if (!str) { 1105 | throwErr('!toFix!'); 1106 | } 1107 | 1108 | return str; 1109 | }; 1110 | 1111 | 1112 | /* 1113 | * Return a string representing the value of this Big rounded to sd 1114 | * significant digits using Big.RM. Use exponential notation if sd is less 1115 | * than the number of digits necessary to represent the integer part of the 1116 | * value in normal notation. 1117 | * 1118 | * sd {number} Integer, 1 to MAX_DP inclusive. 1119 | */ 1120 | P.toPrecision = function (sd) { 1121 | 1122 | if (sd == null) { 1123 | return this.toString(); 1124 | } else if (sd !== ~~sd || sd < 1 || sd > MAX_DP) { 1125 | throwErr('!toPre!'); 1126 | } 1127 | 1128 | return format(this, sd - 1, 2); 1129 | }; 1130 | 1131 | P.intValue = P.byteValue = P.longValue = function () { 1132 | return parseInt(this.toString()); 1133 | } 1134 | P.floatValue = P.doubleValue = function () { 1135 | return parseFloat(this.toString()); 1136 | } 1137 | P.divideAndRemainder = function (inp) { 1138 | var remr = this.mod(inp); 1139 | if (remr.lt(0)) remr = remr.add(inp); 1140 | var divr = this.subtract(remr).divide(inp); 1141 | return [divr, remr]; 1142 | } 1143 | P.equals = function (inp) { 1144 | return this.sub(inp).intValue() == 0 1145 | } 1146 | // Export 1147 | P.toBigInteger = function () { 1148 | return this; 1149 | } 1150 | P.toBigDecimal = function () { 1151 | return this; 1152 | } 1153 | P.movePointLeft = function (inp) { 1154 | return this.divide(new Big("10").pow(inp)); 1155 | } 1156 | P.signum = function () { 1157 | return Math.sign(this.floatValue()); 1158 | } 1159 | 1160 | Big = bigFactory(); 1161 | 1162 | //AMD. 1163 | if (typeof define === 'function' && define.amd) { 1164 | define(function () { 1165 | return Big; 1166 | }); 1167 | 1168 | // Node and other CommonJS-like environments that support module.exports. 1169 | } else if (typeof module !== 'undefined' && module.exports) { 1170 | module.exports = Big; 1171 | 1172 | //Browser. 1173 | } else { 1174 | global.Big = Big; 1175 | } 1176 | 1177 | })(this); -------------------------------------------------------------------------------- /docs.js: -------------------------------------------------------------------------------- 1 | //# sourceURL=Docs 2 | 3 | var cycles = [ 4 | 5 | "AA","BB","CC","DD","EE","FF","GG","HH","II","JJ","KK","LL","MM", 6 | "NN","OO","PP","QQ","RR","SS","TT","UU","VV","WW","XX","YY","ZZ", 7 | "aaα","bb","cc","dd","ee","ff","gg","hh","ii","jj","kk","ll","mm", 8 | "nn","oo","pp","qq","rr√ŗ","ss∑","tt","uu","vv","wwω","xx","yy","zz", 9 | 10 | "00⁰","11¹","22²","33³","44⁴","55⁵","66⁶","77⁷","88⁸","99⁹", 11 | "!!‼", "@@", "##", "%%", "^^", 12 | "++╋∔", "--─∔", "*×*", "//÷", "\\\", "||│║", 13 | "::", ";;", "??‽", "\"”‟", "'“„", 14 | "((", "))", "[[", "]]", "{{", "}}", "<<≤«", ">>≥»", 15 | "=≡≠═", 16 | " ∙", "\n¶" 17 | ]; 18 | 19 | var transforms = []; 20 | var otransforms = Object.entries({ 21 | "||-": "╫", 22 | "--|": "╪", 23 | "=|": "╪", 24 | "|": "│", 25 | "||": "║", 26 | "-": "─", 27 | "--": "═", 28 | "-|": "┼", 29 | "--||": "╬", 30 | "=||": "╬", 31 | "<>": "↔", 32 | "+-": "±", // also horizontal reverse 33 | "^v": "↕", 34 | "rev": "⇵", 35 | "cw": "↷", 36 | "ccw": "↶", 37 | "rot": "⟳", 38 | "o/": "ø", // empty art obj 39 | "o\\": "ø", 40 | "new": "ø", 41 | "pop": "┐", // pop & remove item 42 | "tri": "⌐", // triplicate 43 | "dup": "┌", // duplicate 2nd from top 44 | "g2": "┌", // duplicate 2nd from top 45 | "3rd": "┘", // duplicate 2nd from top 46 | "swap": "└", 47 | "//": "⤢", 48 | "abs": "⤢", 49 | "+2": "├", 50 | "inc": "╵", 51 | "+1": "╵", 52 | "-1": "╷", 53 | "dec": "╷", 54 | "-2": "┤", 55 | "to": "┬", // to base (2 nums -> arr) 56 | "from": "┴", // from base (arr & base -> num) 57 | "dig": "◂", 58 | "=/": "≠", 59 | "!!": "‼", 60 | "12": "½", 61 | "1/2": "½", 62 | "/2": "½", 63 | "rt": "√", 64 | "╴": "prev", 65 | "╶": "next", 66 | "": "", 67 | }); 68 | for (let [k, v] of otransforms) { 69 | transforms.push([[...k].sort().join(''), v]); 70 | } 71 | 72 | transforms.sort((a,b)=>{ 73 | let p1 = b[0].length-a[0].length; 74 | if (p1) return p1; 75 | return (b[0]>a[0]) - (b[0] item.c === chr); 134 | if (!dataItem) { 135 | console.warn("char not found: "+chr); 136 | continue; 137 | } 138 | dataItem.impl = {}; 139 | if (cols.length > 1 || cols[0].length > 1) { 140 | let tarr = cols.length === 5? ["N", "S", "A", "}", "]"] : cols.length === 3? ["N", "S", "A"] : ["NN", "SS", "AA", "NS", "AN", "AS","_","_","_"].slice(0, cols.length); 141 | cols.forEach((impl, index) => { 142 | if (impl.length === 1) dataItem.impl[tarr[index]] = impl==="✓"; 143 | else { 144 | let parts = impl.split(" "); 145 | dataItem.impl[parts[0].toUpperCase()] = parts[1]==="✓"; 146 | } 147 | }); 148 | } else { 149 | dataItem.impl[""] = cols[0]==="✓"; 150 | } 151 | } 152 | console.log("implementation data added!"); 153 | createTable(); 154 | if (search.value !== lastSearch && searched) searched(search.value); 155 | } 156 | }); 157 | } 158 | }); 159 | 160 | 161 | function searched (sv) { 162 | lastSearch = sv; 163 | const scores = {}; 164 | let i = 0; 165 | for (let term of sv.split("|")) { 166 | for (let item of data) { 167 | let score = 0; 168 | if (term.length === 1) { 169 | score = (item.c === term || (item.raw.split("//SUB ")[1]||"").includes(term))? i+1e15 : -Infinity; 170 | if (!scores[item.c] || scores[item.c] < 0) scores[item.c] = score; 171 | } else { 172 | if (!item.raw.toLowerCase().includes(term.toLowerCase())) { 173 | score = -Infinity; 174 | } 175 | if (item.c.includes(term)) score+= 1e14; 176 | if (item.desc.includes(term)) score+= 1e13; 177 | score-= 1000000*(item.c.length - 1); 178 | score-= 10000*item.desc.length; 179 | score+= codepage.indexOf(item.c); 180 | scores[item.c] = scores[item.c]? Math.max(scores[item.c], score, scores[item.c] + score) : score; 181 | } 182 | } 183 | i++; 184 | } 185 | const order = [...document.getElementsByClassName("chrinf")].sort((a, b) => { 186 | if (a.chr === b.chr) { 187 | if (a.classList.length > b.classList.length) return 1; 188 | if (a.classList.length < b.classList.length) return -1; 189 | } else { 190 | let sa = scores[a.chr]; 191 | let sb = scores[b.chr]; 192 | if (sa > sb) return -1; 193 | if (sa < sb) return 1; 194 | } 195 | return 0 196 | }); 197 | for (let el of order) { 198 | if (scores[el.chr] > -Infinity) { 199 | el.style.display = "table-row"; 200 | docstable.children[2].prepend(el); 201 | } else { 202 | el.style.display = "none"; 203 | } 204 | } 205 | } 206 | 207 | 208 | function createTable() { 209 | if (!docstable.children[2]) docstable.createTBody(); 210 | docstable.children[2].innerHTML = ""; 211 | for (let item of data) { 212 | let desc = docstable.children[2].insertRow(-1); 213 | desc.classList.add("sdesc", "chrinf"); 214 | desc.chr = item.c; 215 | let title = ""; 216 | otransforms.filter(c=>c[1]==item.c).forEach(c => title+= [...c[0]].join(" ")+" \n"); 217 | cycles.filter(c => c.includes(item.c)).map(c=> title+= c[0] + " ".repeat(c.indexOf(item.c)) + "\n"); 218 | title = title.replace(/"/g, '"'); 219 | desc.innerHTML = `${item.c}`; 220 | desc.insertCell(1).innerHTML = item.desc.replace(/`([^`]+)`/g, '$1'); 221 | let el = desc.children[0].children[0].children[0]; 222 | if (item.impl !== undefined) el.style.color = Object.values(item.impl).includes(true)? "#55bb55" : "#bb5555"; 223 | // simple examples 224 | if (item.examples.length > 0) { 225 | let examplesRow = docstable.insertRow(-1); 226 | examplesRow.classList.add("chrinf"); 227 | examplesRow.chr = item.c; 228 | let examplesCell = examplesRow.insertCell(0); 229 | examplesCell.colSpan = 2; 230 | examplesCell.innerHTML = '
'; 231 | let examplesTable = examplesCell.children[0]; 232 | for (let example of item.examples) { 233 | let exampleRow = examplesTable.insertRow(-1); 234 | let indent = exampleRow.insertCell(0); 235 | indent.classList.add("dindent"); 236 | let code = exampleRow.insertCell(1); 237 | code.innerHTML = '' + example.c + '' 238 | let result = exampleRow.insertCell(2); 239 | result.innerHTML = ' ' + example.r + '' 240 | } 241 | } 242 | // typed descs & examples 243 | 244 | if (item.types.length > 0) { 245 | let typesRow = docstable.insertRow(-1); 246 | typesRow.classList.add("chrinf"); 247 | typesRow.chr = item.c; 248 | let typesCell = typesRow.insertCell(0); 249 | typesCell.colSpan = 2; 250 | typesCell.innerHTML = '
'; 251 | let typesTable = typesCell.children[0]; 252 | // type list 253 | let first = true; 254 | for (let typeObj of item.types) { 255 | let typeRow = typesTable.insertRow(-1); 256 | typeRow.innerHTML = '' : ' class="typecellmid">') + typeObj.t.split(/, ?/).map(c=> ''+c+'').join('
') + ''; 257 | if (item.impl !== undefined) { 258 | for (let el of typeRow.children[0].children) { 259 | let key = item.impl[[...el.innerText.toUpperCase()].sort().join("")]; 260 | if (key !== undefined) el.style.color = key? "#55bb55" : "#bb5555"; 261 | } 262 | } 263 | let typeDesc = typeRow.insertCell(1); 264 | typeDesc.innerHTML = ' ' + typeObj.desc + ''; 265 | // type examples 266 | 267 | typeDesc.innerHTML+= '
'; 268 | let examplesTable = typeDesc.children[1]; 269 | let first2 = true; 270 | for (let example of typeObj.e) { 271 | let exampleRow = examplesTable.insertRow(-1); 272 | let indent = exampleRow.insertCell(0); 273 | indent.classList.add("dindent"); 274 | if (first2) indent.classList.add("di-t"); 275 | let code = exampleRow.insertCell(1); 276 | code.innerHTML = '' + example.c + ''; 277 | let result = exampleRow.insertCell(2); 278 | result.innerHTML = ' ' + example.r + ''; 279 | first2 = false; 280 | } 281 | first = false; 282 | } 283 | } 284 | } 285 | // various actions 286 | $("a.chr").click(function (e) { 287 | e.preventDefault(); 288 | const startPos = program.selectionStart; 289 | const endPos = program.selectionEnd; 290 | program.value = program.value.substring(0, startPos) + e.target.innerText + program.value.substring(endPos, program.value.length); 291 | program.selectionStart = program.selectionEnd = startPos+e.target.innerText.length; 292 | program.focus(); 293 | update(); 294 | }); 295 | $(".ex").wrap(' '); 296 | $(".example").click(function (e) { 297 | e.preventDefault(); 298 | program.value = e.target.innerText; 299 | program.focus(); 300 | update(); 301 | runMain(); 302 | }); 303 | console.log("table created!"); 304 | } 305 | let tkey = localStorage.kpr? eval(localStorage.kpr) : c => c.key === "F1" || c.key === "F2"; 306 | 307 | inputs.onkeydown = program.onkeydown = function (e) { 308 | // console.log(e); 309 | let el = e.srcElement 310 | if (el.selectionStart === el.selectionEnd) { 311 | if (e.key === "Tab") { 312 | e.preventDefault(); 313 | var ptr = el.selectionStart; 314 | var schr = el.value[ptr-1]; 315 | var cycle = cycles.find(c=>c.includes(schr)); 316 | if (!cycle) return; 317 | var chr = cycle[(cycle.indexOf(schr) + 1) % cycle.length]; 318 | el.value = el.value.substring(0,ptr-1)+chr+el.value.substring(ptr); 319 | el.selectionStart = el.selectionEnd = ptr; 320 | } else if (tkey(e)) { 321 | let ptr = el.selectionStart; 322 | const PV = el.value; 323 | for (let [k, v] of transforms) { 324 | //console.log([...PV.slice(ptr-k.length, ptr)].sort().join(''), k); 325 | if ([...PV.slice(ptr-k.length, ptr)].sort().join('') === k) { 326 | el.value = PV.slice(0, ptr-k.length)+v+PV.slice(ptr, PV.length); 327 | el.selectionStart = el.selectionEnd = ptr-k.length + v.length; 328 | break; 329 | } 330 | } 331 | e.preventDefault(); 332 | } 333 | } 334 | } -------------------------------------------------------------------------------- /files/Inconsolata-UFW.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dzaima/Canvas/2dac13b7129633281a2422b0f36da6b3631cd93e/files/Inconsolata-UFW.woff -------------------------------------------------------------------------------- /files/OFL.txt: -------------------------------------------------------------------------------- 1 | Copyright 2006 The Inconsolata Project Authors 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /files/chars.txt: -------------------------------------------------------------------------------- 1 | ⁰ wrap the top same type items on the stack in an array 2 | ¹-⁹ context & input & program dependant variables.
from 1 onwards are loop data. The outermost loop has ¹, inner one - ², ect. Every loop might set other values it uses in further ones.
Helper functions are in order below `⁹`
before the last helpers superscript come the inputs
If unset, defaults: //KEYW //SUB ⁰¹²³⁴⁵⁶⁷⁸⁹ 3 | ¹: Infinity 4 | ²: 256 5 | ³: 13 6 | ⁴: 64 7 | ⁵: 11 8 | ⁶: 12 9 | ⁷: 16 10 | ⁸: 128 11 | ⁹: call main program 12 | ¹-x: loop counters & stuff 13 | 14 | + add / join horizontally 15 | NN: add the numbers 16 | `78+` → 15 17 | aa: add the two items together horizontally 18 | `hello¶worl∙ ¶d!+` → "hello ¶worl d!" 19 | - subtract 20 | `59-` → -4 21 | ( start an array wrapping 22 | `12(345)` → 1, 2, [3, 4, 5] 23 | ) end array wrapping. ( can be implicit 24 | [ loop 25 | N: repeat that many times (not pushing anything) 26 | `672[!+P` → "7!¶6!" 27 | S: for each prefix 28 | `abc[P` → "a¶ab¶abc" 29 | A: for each prefix 30 | `123)[!+]` 31 | ] close a loop as map 32 | `hello{[ŗ]]∑` → "[h][e][l][l][o]" 33 | { loop 34 | N: repeat from 1 to that number, pushing the counter 35 | `3{a×P` → "a¶aa¶aaa" 36 | S: for each character, pushing it 37 | `abc{-pp` → "-a-b-c" 38 | a: for each character 39 | `ab¶c{!+O` → "a!¶b!¶c!¶ !" 40 | `ab¶c{U]` → "AB¶C " 41 | A: for each item, pushing it 42 | } close a loop 43 | < less than 44 | NN: less than 45 | `46<` → 1 46 | > greater than 47 | NN: greater than 48 | `27>` → 0 49 | ‰ 50 | ø push an empty art object //KEYW new canvas object 51 | `ø3{1hi╋` → "hhhi" 52 | ^ power 53 | NN: x^y 54 | `A3^` → 1000 55 | ◂ push "0123456789" 56 | `◂` → "0123456789" //TEST 57 | ◂◂ push ["1234567890","qwertyuiop","asdfghjkl","zxcvbnm"] 58 | `◂◂` → ["1234567890","qwertyuiop","asdfghjkl","zxcvbnm"] //TEST 59 | ← 60 | ↑ 61 | → 62 | ↓ 63 | ↖ 64 | ↗ 65 | ↘ 66 | ↙ 67 | ↔ mirror horizontally 68 | S, A: mirror horizontally - reverse & swap chars as required 69 | `\_/-↔` → "-\_/" 70 | ↕ mirror vertically 71 | S, a: mirror vertically - reverse vertically & swap chars as required 72 | `_/¶ v↕` → "_^¶ \" 73 | N: floor divide by 2 + 1 74 | `5↕` → 3 75 | `6↕` → 4 76 | 77 | 78 | ┌ duplicate the item 2nd from top 79 | `123┌)` → [1,2,3,2] 80 | ┐ pop & remove an item 81 | `123┐)` → [1,2] 82 | └ swap the two items below ToS 83 | `123└)` → [2,1,3] 84 | ┘ put the 3rd item from top ontop //KEYW get swap 85 | `123┘)` → [2,3,1] 86 | ├ double increment / uppercase first letter 87 | N: increase by 2 88 | `7├` → 9 89 | S: uppercase the first letter of the first word 90 | ` hello, world!├` → " Hello, world!" 91 | A: vectorize 92 | ┤ double decrement 93 | N: decrease by 2 94 | `0┤` → -2 95 | S: cast to number 96 | A: put all the elements on the stack 97 | ┬ decode from base 10 98 | NN: convert x from base 10 to an array of digits of it in base y 99 | `A2┬` → [1,0,1,0] 100 | ┴ encode into base 10 101 | AN: convert the array, interpreted as base y, to a base 10 number 102 | `1010)2┴` → 10 103 | ╴ previous input 104 | ╵ increment / sentence case 105 | N: increase by 1 106 | `7╷` → 8 //TEST 107 | S: uppercase every letter after any of ".?!" and in the beginning 108 | ` hello, world! goodbye, world!╵` → " Hello, world! Goodbye, world!" 109 | A: vectorize 110 | ╶ next input 111 | ╷ decrement / title case 112 | N: decrease by 1 113 | `7╷` → 6 //TEST 114 | S: uppercase the first letter of every word 115 | `hello, world!╷` → "Hello, World!" 116 | A: vectorize 117 | ╋ overlap / replace 118 | SSS: replace in the first the second with the third 119 | aaNN: overlap the 2nd art over the 1st at x;y using smartOverlap 120 | ╋╋ simple overlap 121 | aaNN: overlap the 2nd art over the 1st at x;y using simpleOverlap 122 | × repeat horizontally / prepend 123 | NN: multiply the numbers 124 | `67×` → 42 125 | NA, AN, SN, NS: repeat horizontally 126 | `string3×` → "stringstringstring" 127 | `hello¶world!2×` → "hello hello ¶world!world!" 128 | `hello∙world!)2×` → ["hello hello ", "world!world!"] 129 | aa: reverse join / prepend //KEYW reverse add 130 | `World!∙Hello, ×` → "Hello, World!" 131 | * repeat vertically / join string 132 | SN, NS: repeat the string vertically that many times 133 | `foo¶bar3*` → "foo¶bar¶foo¶bar¶foo¶bar" 134 | NA, AN: multiply the array vertically that many times 135 | `a∙b)2*` → ["a","b","a","b"] 136 | aNN: expand the ascii-art by the numbers 137 | `foo¶bar23*` → "ffoooo¶ffoooo¶ffoooo¶bbaarr¶bbaarr¶bbaarr" 138 | AS, SA: join the array with the string 139 | `3R:*` → "1:2:3" 140 | SS: insert the second string between the firsts chars 141 | `2xy∙^*` → "2^x^y" 142 | ÷ divide 143 | NN: divide the numbers 144 | `34÷` 145 | ± horizontal reverse / negate 146 | N: negate 147 | `4±` → -4 148 | a: reverse horizontally 149 | `\abc/±` → "/cba\" 150 | `abc∙(def))±` → [" cba", ")fed("] 151 | « shift left 152 | N: shift left by 1 bit / multiply by 2 153 | `6«` → 12 154 | S: put the first char at the end 155 | `hello«` → "elloh" 156 | A: put the first item at the end 157 | `123)«` → [2,3,1] 158 | » shift right 159 | N: shift right by 1 bit / floor divide by 2, storing the remainder 160 | `7»` → 3 161 | `8»` → 4 162 | S: put the last char at the beginning 163 | `hello»` → "ohell" 164 | A: put the last item at the beginning 165 | `123)«` → [2,3,1] 166 | ≤ 167 | ≥ 168 | ≡ equal 169 | ≠ not equal 170 | A push 10 171 | B 172 | C push the ASCII characters (' '..'~') 173 | D deduplicate 174 | `132341)D` → [1,3,2,4] 175 | E eval pop as Canvas code 176 | `5“2+”wEyE` → 9 177 | F 178 | G 179 | H equal to ø;{ 180 | I 181 | J pop the first item / first line 182 | `helloJ` → "ello", "h" 183 | K pop the last item / last line 184 | `helloJ` → "hell", "o" 185 | L get length 186 | S, A, N: get length and pop the item 187 | `helloL)` → [5] 188 | `‾⁹L)` → [2] 189 | a: get width, don't pop 190 | `a¶bcdefL` → 5 191 | M maximum 192 | NN: maximum 193 | `84M` → 8 194 | N 195 | R range / set default background 196 | N: range from 1 to N, inclusive 197 | `4R` → [1,2,3,4] 198 | S: set the default background to the string 199 | `.Rø22+╋` → "..¶.+" 200 | S split on spaces 201 | S: split on spaces 202 | `hi thereS` → ["hi", "there"] 203 | U uppercase/ceiling 204 | S: uppercase the string 205 | `HiU` → "HI" 206 | N: get the ceiling of the number 207 | `5½U` → 3 208 | A: vectorize 209 | u lowercase/floor 210 | S: lowercase the string 211 | `Hiu` → "hi" 212 | N: get the floor of the number 213 | `5½u` → 2 214 | A: vectorize 215 | V increment x 216 | `3{V]x` → 3 217 | W while 218 | }: do..while(pop) 219 | `helloWKl;O}` → "o¶l¶l¶e¶h" 220 | ]: while(ToS) 221 | `5W╷T]` → "4¶3¶2¶1¶0" 222 | Z push the uppercase alphabet 223 | `Z` → "ABCDEFGHIJKLMNOPQRSTUVWXYZ" //TEST 224 | a 225 | b 226 | c convert to/from unicode 227 | N: convert from unicode codepoint 228 | `A6×c` → "<" 229 | S: convert to unicode codepoint 230 | `hc` → 104 231 | `helloc` → [104, 101, 108, 108, 111] //NOTE (note that this only happens if length>1, be careful) 232 | A: convert to 2D array of codepoints 233 | `ab¶cc` → [[97, 98], [99, 0]] 234 | d 235 | e encase in a letter 236 | SS: encase the 1st string in the 2nd 237 | `hello∙'e` → "'hello'" 238 | f 239 | g push the last remainder 240 | `5⇵g)` → [3,1] 241 | h 242 | i 243 | j remove first item / first line 244 | `helloj)` → ["ello"] 245 | k remove last item / last line 246 | `hellok)` → ["hell"] 247 | l get length 248 | S, A, N: get length, without popping 249 | `hellol)` → ["hello", 5] 250 | a: get height, don't pop 251 | m mold to length / reshape 252 | aN: reshape to the width of the number 253 | `abc8m` → "abcabcab" 254 | NN: minimum 255 | `47m` → 4 256 | n split into chunks / divmod 257 | NS, SN: split the string into chunks of length N 258 | `hello2n` → ["he","ll", "o"] 259 | NA, AN: split the array into arrays of length N. If there aren't enough items, just leave as-is. 260 | `123456)4n` → [[1,2,3,4],[5,6]] 261 | NN: push the result of floor division and then modulo 262 | `73n)` → [2, 1] 263 | aa: overlap the two 264 | `--∙|¶|n` → "+-¶| " 265 | r lowered range / set background / center 266 | N: range from 0 to N-1, inclusive 267 | `4r` → [0,1,2,3] 268 | aS: set the arts background character to that 269 | `ø.r22+╋` → "..¶.+" 270 | a: center the art, preferring to go left 271 | `a¶bc¶defgr` → " a ¶ bc ¶defg" 272 | s split 273 | SS: split the 1st string on the 2nd 274 | `hello∙els` → ["h", "lo"] 275 | SN: split the string on the number 276 | v increment/append 277 | N: increment x & push the result 278 | `hi!{v]` → ["h",1,"i",2,"!",3] 279 | S: add the value to X 280 | `”Xabc{!+v}x` → "a!b!c!" 281 | A: push the value to X 282 | w set the variable Y without popping 283 | `fooYybarwy)` → ["foo", "bar", "bar"] 284 | x get the value of the variable X 285 | y get the value of the variable Y 286 | X set the variable X to POP 287 | Y set the variable Y to POP 288 | z push the lowercase alphabet 289 | `z` → "abcdefghijklmnopqrstuvwxyz" //TEST 290 | // newline pop disable auto output 291 | // O x x 292 | // P x x x 293 | // Q x 294 | // T x x 295 | // o x 296 | // p x x 297 | // q 298 | // t x 299 | 300 | O output in a new line, popping the item 301 | P output in a new line, popping the item 302 | Q output in a new line 303 | T output in a new line, disabling implicit output 304 | o output in the current line, popping the item 305 | p output in the current line, popping the item 306 | q output in the current line 307 | t output in the current line, disabling implicit output 308 | 0-9 push that number (0123456789) //KEYW 0 1 2 3 4 5 6 7 8 9 //SUB 0123456789 309 | ‼ normalize 310 | N: 1 if the number isn't 0, otherwise 0 311 | S: 0 if the string is empty, otherwise 1 312 | a: move the [1;1] point to the top-left of the visible art 313 | ¼ 314 | ½ halve //KEYW half halve 315 | N: divide by 2 316 | `9½` → 4.5 317 | ¾ 318 | √ square root 319 | N: get the square root 320 | `92√×U` → 13 321 | / create an antidiagonal 322 | N: create a antidiagonal of that length 323 | `2/` → " /¶/ " 324 | S: create a antidiagonal of the characters of that string 325 | `ab/` → " a¶b " 326 | a: prepend each line with one less space than the last, the last line having 0 spaces 327 | `ab¶cd¶ef/` → " ab¶ cd ¶ef " 328 | \ create a diagonal 329 | N: create a diagonal of that length 330 | `2\` → "\ ¶ \" 331 | S: create a diagonal of the characters of that string 332 | `ab\` → "a ¶ b" 333 | a: prepend each line with one more space than the last, the first having 0 spaces 334 | `ab¶cd¶ef\` → "ab ¶ cd ¶ ef" 335 | ∑ join/sum 336 | A: join the array together or sum if array only contains numbers 337 | `((ab∙cd)(ef∙gh))∑` → "abcdefgh" 338 | `4R∑` → 10 339 | `5R{R]∑` → 35 340 | N, S: join the stack until `(` or end into a string 341 | ∙ NOP / separator / space 342 | NOOP if both or no sides are ASCII 343 | `abc∙def┐` → "abc" 344 | if ASCII is only on one side, pushes a space 345 | `abc∙*` → "a b c" 346 | ‽ if not / switch 347 | }: if not POP 348 | `‽false!}` - if POP is falsy //NOTTEST 349 | ]: switch over the results before `]`, calling the one to its right. The last case, without a `]`, is the default result 350 | `‽N∙n]north}S∙s]south}E∙e]east}west}` - expands the direction name of the cardinal //NOTTEST 351 | ? if/switch 352 | }: if 353 | `?truthy!}` pushes "truthy" if the input is truthy //NOTTEST 354 | ]}: switch for numbers 0..x. first is default, next is 0 (or anything falsy), next - 1, next - 2, ect.
If only 2 blocks are used, this is basically if/else. 355 | `?truthy!]falsy.}` outputs "truthy" if the input is truthy //NOTTEST 356 | `?not zero nor one]zero]one}` self explanatory //NOTTEST 357 | ‾ 1-char number constant 358 | ⇵ reverse vertically 359 | N: ceiling divide by 2, storing the remainder 360 | `7⇵` → 4 361 | A: reverse the items 362 | `12)hello(7world))⇵` → [[7,"world"], "hello", [1,2]] 363 | a: reverse vertically 364 | : duplicate ToS 365 | `la:+` → "lala" 366 | ⌐ duplicate POP twice //KEYW triplicate 367 | `la⌐)∑` → "lalala" 368 | ; swap top two stack items 369 | `49;-` → 5 370 | ⟳ rotate clockwise w/o character changing 371 | a: rotate clockwise once 372 | `i∙h!∔⟳` → "hi¶! " 373 | aN: rotate clockwise that many times 374 | A, AN: rotate the items so that it looks rotated if printed 375 | ⤢ transpose / absolute value 376 | a: transpose around main diagonal 377 | `ab¶cd⤢` → "ac¶bd" 378 | N: absolute value 379 | `4⤢` → 4 380 | `4±⤢` → 4 381 | ∔ add vertically / reverse subtract 382 | NN: reverse subtract 383 | `47∔` → 3 384 | SS: add the two together with a separating newline 385 | `abc∙de∔` → "abc¶de " 386 | AS: move the string into the array 387 | `a3R∔` → ["a", 1, 2, 3] 388 | `3Ra∔` → [1, 2, 3, "a"] 389 | AA: add the two arrays together 390 | `2R3R∔` → [1, 2, 1, 2, 3] 391 | aa: add the two vertically 392 | `ab¶cd∙1¶2∔` → "ab¶cd¶1 ¶2 " 393 | ŗ replace in a string with pop 394 | `World∙Hello, ŗ!` → "Hello, World!" 395 | “ string starter 396 | `“hi` → "hi" 397 | ” string ender 398 | `hi”` → "hi" 399 | `abc”12”)` → ["abc", "12"] 400 | „ compressed number (ctrl+O → number compress to generate) 401 | ‟ compressed string ender (ctrl+O → string compress to generate) 402 | ↶ rotate anticlockwise 403 | a: rotate counter clockwise, rotating characters that make sense to be rotated 404 | `//¶/↶` → "\ ¶\\" 405 | aN: rotate anticlockwise that many times 406 | `abc¶d2↶` → " d¶cba" 407 | ↷ rotate clockwise 408 | a: rotate clockwise, rotating characters that make sense to be rotated 409 | `//¶/↷` → "\\¶ \" 410 | aN: rotate clockwise that many times 411 | `abc¶d2↷` → " d¶cba" 412 | 413 | @ get item 414 | AN, NA: push that item (1-indexed) from the array 415 | `987)5@` → 8 416 | SN, NS: push that char (1-indexed) from the string 417 | `Z4@` → "D" 418 | `AB5@` → "A" 419 | aNN: get the character at the positions [x; y] in the canvas 420 | `AB¶CD22@` → "D" 421 | aNNNN: get a subsection from the canvas by the params [x; y; w; h] 422 | `Z5n2233@` → "GHI¶LMN¶QRS" 423 | # execute as JS 424 | `"Hello, "+"JS!"#` → "Hello, JS!" 425 | % modulo 426 | NN: modulo 427 | `83%` → 2 428 | ! not / transpose 429 | N: `1` if value is `0`, else `0` 430 | S: is string empty 431 | a: transpose around antidiagonal 432 | α get the second to last argument used in a simpleFunction //KEYW history 433 | `73÷1%α;-` → 2 //NOTE (floor division implementation) 434 | ω get the last argument used in a simpleFunction //KEYW history 435 | `73÷αω%ω÷-` → 2 //NOTE (floor division implementation) 436 | 437 | ─ palindromize vertically with 1 overlap 438 | ═ palindromize vertically with 0 overlap 439 | │ palindromize horizontally with 1 overlap 440 | ║ palindromize horizontally with 0 overlap 441 | ┼ quad-palindromize with 1 overlap 442 | ╬ quad-palindromize with 0 overlap 443 | ╫ quad-palindromize with 1 overlap vertically and 0 horizontally 444 | ╪ quad-palindromize with 0 overlap vertically and 1 horizontally 445 | two of the same palindromizators next to each other disable character mirroring 446 | if after a double-line there's a character with that as a single line, it's replaced by a remainder. 447 | So ╫│ is vertical palindromization with overlap 1 and horizontal with overlap of the remainder 448 | ╬┼ quad palindromize with remainder overlap 449 | `3⇵-×:↷n╬┼` → "+-+¶| |¶+-+" 450 | `4⇵-×:↷n╬┼` → "+--+¶| |¶| |¶+--+" 451 | 452 | 453 | 454 | -------------------------------------------------------------------------------- /files/chartable.md: -------------------------------------------------------------------------------- 1 | | | _0 | _1 | _2 | _3 | _4 | _5 | _6 | _7 | _8 | _9 | _A | _B | _C | _D | _E | _F | 2 | |:------:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:| 3 | | **0_** | `⁰` | `¹` | `²` | `³` | `⁴` | `⁵` | `⁶` | `⁷` | `⁸` | `⁹` | `¶` | \n | `+` | `-` | `(` | `)` | 4 | | **1_** | `[` | `]` | `{` | `}` | `<` | `>` | `‰` | `ø` | `^` | `◂` | `←` | `↑` | `→` | `↓` | `↔` | `↕` | 5 | | **2_** |   | `!` | `"` | `#` | `$` | `%` | `&` | `'` | `(` | `)` | `*` | `+` | `,` | `-` | `.` | `/` | 6 | | **3_** | `0` | `1` | `2` | `3` | `4` | `5` | `6` | `7` | `8` | `9` | `:` | `;` | `<` | `=` | `>` | `?` | 7 | | **4_** | `@` | `A` | `B` | `C` | `D` | `E` | `F` | `G` | `H` | `I` | `J` | `K` | `L` | `M` | `N` | `O` | 8 | | **5_** | `P` | `Q` | `R` | `S` | `T` | `U` | `V` | `W` | `X` | `Y` | `Z` | `[` | `\` | `]` | `^` | `_` | 9 | | **6_** | ` | `a` | `b` | `c` | `d` | `e` | `f` | `g` | `h` | `i` | `j` | `k` | `l` | `m` | `n` | `o` | 10 | | **7_** | `p` | `q` | `r` | `s` | `t` | `u` | `v` | `w` | `x` | `y` | `z` | `{` | \| | `}` | `~` | `┌` | 11 | | **8_** | `┐` | `└` | `┘` | `├` | `┤` | `┬` | `┴` | `╴` | `╵` | `╶` | `╷` | `╋` | `↖` | `↗` | `↘` | `↙` | 12 | | **9_** | `×` | `÷` | `±` | `«` | `»` | `≤` | `≥` | `≡` | `≠` | `A` | `B` | `C` | `D` | `E` | `F` | `G` | 13 | | **A_** | `H` | `I` | `J` | `K` | `L` | `M` | `N` | `O` | `P` | `Q` | `R` | `S` | `T` | `U` | `V` | `W` | 14 | | **B_** | `X` | `Y` | `Z` | `a` | `b` | `c` | `d` | `e` | `f` | `g` | `h` | `i` | `j` | `k` | `l` | `m` | 15 | | **C_** | `n` | `o` | `p` | `q` | `r` | `s` | `t` | `u` | `v` | `w` | `x` | `y` | `z` | `0` | `1` | `2` | 16 | | **D_** | `3` | `4` | `5` | `6` | `7` | `8` | `9` | `‟` | `‼` | `¼` | `½` | `¾` | `√` | `/` | `\` | `∑` | 17 | | **E_** | `∙` | `‽` | `‾` | `⇵` | `∔` | `:` | `;` | `⟳` | `⤢` | `⌐` | `ŗ` | `“` | `”` | `„` | `?` | `*` | 18 | | **F_** | `↶` | `↷` | `@` | `#` | `%` | `!` | `─` | `│` | `┼` | `═` | `║` | `╫` | `╪` | `╬` | `α` | `ω` | -------------------------------------------------------------------------------- /files/codepage.txt: -------------------------------------------------------------------------------- 1 | v literal newline 2 | ⁰¹²³⁴⁵⁶⁷⁸⁹¶N+-()[]{}<>‰ø^◂←↑→↓↔↕ !"#$%&'()*+,-./0123456789:;<=>?@ 3 | ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~┌┐└┘├┤┬┴╴╵╶╷╋↖↗↘↙×÷±«»≤≥≡≠ 4 | ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 5 | 0123456789‟‼¼½¾√/\∑∙‽‾⇵∔:;⟳⤢⌐ŗ“”„?*↶↷@#%!─│┼═║╫╪╬αω 6 | 7 | ║╬│─ 8 | 9 | ╱╲ 10 | not on the keyboard: 11 | ‰▸▾◂←↑→↓↔↕↖↗↘↙↶↷ 12 | ≡≠‟‼‾∔⌐“”„ 13 | ¼½¾ -------------------------------------------------------------------------------- /files/implemented.md: -------------------------------------------------------------------------------- 1 | 2 | □ = documented 3 | ✓ = implemented 4 | 5 | if only N exists, it's if it's implemented at all 6 | if 3 columns exist, it's a monadic function 7 | if 6 columns exist, it's a dyadic+ function (higher adicies are complicated) 8 | if 5 columns exist, it's a loop(ish thing) starter they correspond to `NSA}]` where NSA are what types it works for and brackets - for what bracket types it works for 9 | 10 | | CHR | N
NN | S
SS
| A
AA
| }
NS | ]
NA |
SA 11 | |:---:|:-:|:-:|:-:|:-:|:-:|:-: 12 | |`⁰` | ✓ | 13 | |`╫` | ✓ | 14 | |`+` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 15 | |`-` | ✓ | | | | | | 16 | |`(` | ✓ | 17 | |`)` | ✓ | 18 | |`[` | ✓ | ✓ | ✓ | ✓ | ✓ | 19 | |`]` | ✓ | 20 | |`{` | ✓ | ✓ | ✓ | ✓ | ✓ | 21 | |`}` | ✓ | 22 | |`<` | ✓ | | | | | | 23 | |`>` | ✓ | | | | | | 24 | |`‰` | 25 | |`ø` | ✓ | 26 | |`^` | ✓ | | | | | | 27 | |`◂` | ✓ | 28 | |`◂◂` | ✓ | 29 | |`←` | 30 | |`↑` | 31 | |`→` | 32 | |`↓` | 33 | |`↔` | | ✓ | ✓ | 34 | |`↕` | ✓ | ✓ | ✓ | 35 | |ascii| 36 | |`─` | ✓ | 37 | |`│` | ✓ | 38 | |`┌` | ✓ | 39 | |`┐` | ✓ | 40 | |`└` | ✓ | 41 | |`┘` | ✓ | 42 | |`├` | ✓ | ✓ | ✓ | 43 | |`┤` | ✓ | ✓ | ✓ | 44 | |`┬` | ✓ | | | | | | 45 | |`┴` | | | | | ✓ | | 46 | |`┼` | ✓ | 47 | |`╴` | ✓ | 48 | |`╵` | ✓ | ✓ | ✓ | 49 | |`╶` | ✓ | 50 | |`╷` | ✓ | ✓ | ✓ | 51 | |`╪` | ✓ | 52 | |`╋` | SSS ✓ | aaNN ✓ | 53 | |`╋╋` | aaNN ✓ | 54 | |`↖` | 55 | |`↗` | 56 | |`↘` | 57 | |`↙` | 58 | |`×` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 59 | |`*` | □ | ✓ | | ✓ | ✓ | ✓ | aNN ✓ | 60 | |`÷` | ✓ | | | | | | 61 | |`±` | ✓ | ✓ | ✓ | 62 | |`«` | ✓ | ✓ | ✓ | 63 | |`»` | ✓ | ✓ | ✓ | 64 | |`≤` | 65 | |`≥` | 66 | |`≡` | ✓ | 67 | |`≠` | ✓ | 68 | |`A` | ✓ | 69 | |`B` | 70 | |`C` | ✓ | 71 | |`D` | | □ | ✓ | 72 | |`E` | | ✓ | | 73 | |`F` | 74 | |`G` | 75 | |`H` | ✓ | ✓ | ✓ | ✓ | | 76 | |`I` | 77 | |`J` | | ✓ | ✓ | 78 | |`K` | | ✓ | ✓ | 79 | |`L` | ✓ | ✓ | ✓ | 80 | |`M` | ✓ | | | | | | 81 | |`N` | 82 | |`O` | ✓ | 83 | |`P` | ✓ | 84 | |`Q` | ✓ | 85 | |`R` | ✓ | ✓ | | 86 | |`S` | | ✓ | | 87 | |`T` | ✓ | 88 | |`U` | ✓ | ✓ | ✓ | 89 | |`V` | ✓ | | | 90 | |`W` | ✓ | ✓ | ✓ | ✓ | ✓ | 91 | |`X` | ✓ | 92 | |`Y` | ✓ | 93 | |`Z` | ✓ | 94 | |`a` | 95 | |`b` | 96 | |`c` | ✓ | ✓ | ✓ | 97 | |`d` | 98 | |`e` | | ✓ | | | | | 99 | |`f` | 100 | |`g` | ✓ | 101 | |`h` | 102 | |`i` | 103 | |`j` | | ✓ | ✓ | 104 | |`k` | | ✓ | ✓ | 105 | |`l` | ✓ | ✓ | ✓ | 106 | |`m` | ✓ | | | ✓ | ✓ | | 107 | |`n` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 108 | |`o` | ✓ | 109 | |`p` | ✓ | 110 | |`q` | ✓ | 111 | |`r` | ✓ | aS ✓ | ✓ | 112 | |`s` | | ✓ | | ✓ | | | 113 | |`t` | ✓ | 114 | |`u` | ✓ | ✓ | ✓ | 115 | |`v` | ✓ | ✓ | ✓ | 116 | |`w` | ✓ | 117 | |`x` | ✓ | 118 | |`y` | ✓ | 119 | |`z` | ✓ | 120 | |0-9| ✓ | 121 | |`‟` | ✓ | 122 | |`‼` | ✓ | ✓ | ✓ | 123 | |`¼` | 124 | |`½` | ✓ | | ✓ | 125 | |`¾` | 126 | |`√` | ✓ | | | 127 | |`/` | ✓ | ✓ | ✓ | 128 | |`\` | ✓ | ✓ | ✓ | 129 | |`∑` | □ | □ | ✓ | 130 | |`∙` | ✓ | 131 | |`‽` | ✓ | ✓ | ✓ | ✓ | ✓ | 132 | |`‾` | ✓ | 133 | |`⇵` | ✓ | | ✓ | 134 | |`∔` | ✓ | ✓ | ✓ | | | ✓ | 135 | |`:` | ✓ | 136 | |`;` | ✓ | 137 | |`⟳` | aN ✓ | ✓ | ✓ | 138 | |`⤢` | ✓ | ✓ | ✓ | 139 | |`⌐` | ✓ | 140 | |`═` | ✓ | 141 | |`║` | ✓ | 142 | |`╬` | ✓ | 143 | |`“` | ✓ | 144 | |`”` | ✓ | 145 | |`„` | ✓ | 146 | |`?` | ✓ | ✓ | ✓ | ✓ | ]} ✓ | 147 | |`↶` | aN ✓ | ✓ | ✓ | 148 | |`↷` | aN ✓ | ✓ | ✓ | 149 | |`@` | | | | ✓ | ✓ | | aNN ✓ | aNNNN ✓ | 150 | |`#` | ✓ | 151 | |`%` | ✓ | | | | | | 152 | |`!` | ✓ | ✓ | ✓ | 153 | |`α` | ✓ | 154 | |`ω` | ✓ | 155 | |`ŗ` | ✓ | 156 | |`¹-⁹` | ✓ | 157 | |`0-9` | ✓ | 158 | 159 | table of the palindromizators 160 | 161 | 162 | |1st| ─ | ═ | │ | ║ | ┼ | ╫ | ╪ | ╬ | 163 | |:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:| 164 | |2nd| ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 165 | | ─ | ✓ | □ | | | | □ | | □ | 166 | | ═ | | ✓ | | | | | | | 167 | | │ | | | ✓ | □ | □ | | | ✓ | 168 | | ║ | | | | ✓ | | | | | 169 | | ┼ | | | | | ✓ | | | | 170 | | ╫ | | | | | | ✓ | | | 171 | | ╪ | | | | | | | ✓ | ✓ | 172 | | ╬ | | | | | | | ✓ | ✓ | 173 | ### palindromizator defs 174 | 175 | - Hx = horizontal palindromization with x overlap 176 | - mH = mirror horizontal - the reverse part gets characters swapped 177 | - Hr = overlap = remainder 178 | - Vx = vertical palindromization with x overlap 179 | - mV = mirror vertical - the reverse part gets mirrored vertically 180 | - sV = smart vertical - mV, but underscores get moved around to look better 181 | - Vr = overlap = remainder 182 | - xO = overlap mode 183 | - bO = basic overlap - simpleOverlap (aka just choose the 2nd) 184 | - gO = background overlap - noBGOverlap (aka basic overlap, but spaces get deprioritized) 185 | - sO = smart overlap - smartOverlap (aka overlap smartly (e.g. \ + / -> X)) 186 | 187 | 188 | | 1st | ─ | ═ | │ | ║ | ╫ | ╪ | ┼ | ╬ | 189 | |:-----:|:---------:|:---------:|:---------:|:---------:|:---------:|:---------:|:---------:|:---------:| 190 | |**2nd**| mH1 | mH0 | sV1 | sV0 | mH0 sV1 | mH1 sV0 | mH1 sV1 | mH0 sV0 | 191 | |** ─ **| H1 | Hr | | | | mH1 sVr | | mH0 sVr | 192 | |** ═ **| | H0 | | | | | | | 193 | |** │ **| | | V1 | Vr | mHr sV1 | | | mHr sV0 | 194 | |** ║ **| | | | V0 | | | | | 195 | |** ╫ **| | | | | H0 V1 | | | | 196 | |** ╪ **| | | | | | H1 V0 | | | 197 | |** ┼ **| | | | | | | H1 V1 | Hr0 Vr1 | 198 | |** ╬ **| | | | | | | Hr1 Vr0 | H0 V0 | 199 | 200 | overlap table: 201 | 202 | | H | V |code 203 | |:-:|:-:|:-: 204 | | r | | ║│ 205 | | | r | ═─ 206 | | 0 | 0 | ╬ 207 | | 0 | 1 | ╫ 208 | | 1 | 0 | ╪ 209 | | 1 | 1 | ┼ 210 | | 0 | r | ╬─ 211 | | 1 | r | ╪─ 212 | | r | 0 | ╬│ 213 | | r | 1 | ╫│ 214 | | r | r | ╬┼ | or ┼╬ with reversed usage of remainders 215 | 216 | 217 | loop starters: `‽?[{` 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Canvas 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | Canvas 13 |
14 |
0 bytes
15 |
16 |
17 | 18 |
19 |
20 | 21 | 39 | 56 |
57 | 58 |
59 |
60 |
61 |
62 | 63 |
64 | 65 |

66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | 74 | 75 | 76 |
77 |
78 | 79 | 80 | 81 |
82 |
83 | dev mode
84 |
85 | 86 | 87 |
88 |
89 |
90 | 91 |