diff --git a/extensions/Complexity!.js b/extensions/Complexity!.js
new file mode 100644
index 0000000000..731cf5de54
--- /dev/null
+++ b/extensions/Complexity!.js
@@ -0,0 +1,1007 @@
+/*
+Name: Complexity!
+ID: complexMath
+Description: Play with Complex Numbers in TurboWarp!
+By Clickertale_2 and Kenay
+Cool License: MIT AND MPL-2.0
+Thanks "rawify" for the complexity
+complexCode source: https://github.com/rawify/Complex.js/tree/main
+*/
+if (!Scratch.extensions.unsandboxed) {
+ throw new Error("We don't like sand :(");
+}
+
+const OGcomplexCode = `
+/*
+Complex.js v2.4.2 11/5/2024
+https://raw.org/article/complex-numbers-in-javascript/
+Copyright (c) 2024, Robert Eisele (https://raw.org/)
+Licensed under the MIT license. Function
+*/
+'use strict';(function(r){function l(a,b){if(void 0===a||null===a)f.re=f.im=0;else if(void 0!==b)f.re=a,f.im=b;else switch(typeof a){case "object":if("im"in a&&"re"in a)f.re=a.re,f.im=a.im;else if("abs"in a&&"arg"in a){if(!isFinite(a.abs)&&isFinite(a.arg))return c.INFINITY;f.re=a.abs*Math.cos(a.arg);f.im=a.abs*Math.sin(a.arg)}else if("r"in a&&"phi"in a){if(!isFinite(a.r)&&isFinite(a.phi))return c.INFINITY;f.re=a.r*Math.cos(a.phi);f.im=a.r*Math.sin(a.phi)}else 2===a.length?(f.re=a[0],f.im=a[1]):m();
+break;case "string":f.im=f.re=0;a=a.replace(/_/g,"").match(/\\d+\\.?\\d*e[+-]?\\d+|\\d+\\.?\\d*|\\.\\d+|./g);b=1;let d=0;null===a&&m();for(let e=0;ea)return Math.sqrt(a*a+b*b);b/=a;return a*Math.sqrt(1+b*b)}function p(a,b){const d=Math.abs(a),e=Math.abs(b);if(0===a)return Math.log(e);if(0===b)return Math.log(d);if(3E3>d&&3E3>e)return.5*Math.log(a*a+b*b);a*=.5;b*=.5;return.5*Math.log(a*a+b*b)+Math.LN2}function c(a,b){if(!(this instanceof c))return new c(a,b);a=l(a,
+b);this.re=a.re;this.im=a.im}const h=Math.cosh||function(a){return 1E-9>Math.abs(a)?1-a:.5*(Math.exp(a)+Math.exp(-a))},k=Math.sinh||function(a){return 1E-9>Math.abs(a)?a:.5*(Math.exp(a)-Math.exp(-a))},f={re:0,im:0};c.prototype={re:0,im:0,sign:function(){const a=n(this.re,this.im);return new c(this.re/a,this.im/a)},add:function(a,b){a=l(a,b);b=this.isInfinite();const d=!(isFinite(a.re)&&isFinite(a.im));return b||d?b&&d?c.NAN:c.INFINITY:new c(this.re+a.re,this.im+a.im)},sub:function(a,b){a=l(a,b);b=this.isInfinite();const d=!(isFinite(a.re)&&isFinite(a.im));return b||d?b&&d?c.NAN:c.INFINITY:new c(this.re-a.re,this.im-a.im)},mul:function(a,b){a=l(a,b);b=this.isInfinite();const d=!(isFinite(a.re)&&isFinite(a.im)),e=0===this.re&&0===this.im,g=0===a.re&&0===a.im;return b&&g||d&&e?c.NAN:b||d?c.INFINITY:0===a.im&&0===this.im?new c(this.re*a.re,0):new c(this.re*a.re-this.im*a.im,this.re*a.im+this.im*a.re)},div:function(a,b){a=l(a,b);b=this.isInfinite();const d=!(isFinite(a.re)&&isFinite(a.im)),e=0===
+this.re&&0===this.im,g=0===a.re&&0===a.im;if(e&&g||b&&d)return c.NAN;if(g||b)return c.INFINITY;if(e||d)return c.ZERO;if(0===a.im)return new c(this.re/a.re,this.im/a.re);if(Math.abs(a.re)b?-e:e):new c(e,0>b?-d:d)},exp:function(){const a=Math.exp(this.re);return 0===this.im?new c(a,0):new c(a*Math.cos(this.im),a*Math.sin(this.im))},expm1:function(){const a=this.re,b=this.im;var d=Math.expm1(a)*Math.cos(b);var e=Math.PI/4;-e>b||b>e?e=Math.cos(b)-1:(e=b*b,e*=e*(e*(e*(e*(e*(e*(e/20922789888E3-1/87178291200)+1/479001600)-1/3628800)+1/40320)-1/720)+1/24)-.5);return new c(d+e,Math.exp(a)*Math.sin(b))},
+log:function(){const a=this.re,b=this.im;return 0===b&&0=a.im){var b=a.re;a.re=-a.im;a.im=b}else b=a.im,a.im=-a.re,a.re=b;return a},atanh:function(){var a=this.re,b=this.im;const d=1b?(b=-b,d+="-"):d+="+",d+=" "):0>b&&(b=-b,d+="-");1!==
+b&&(d+=b);return d+"i"},toVector:function(){return[this.re,this.im]},valueOf:function(){return 0===this.im?this.re:null},isNaN:function(){return isNaN(this.re)||isNaN(this.im)},isZero:function(){return 0===this.im&&0===this.re},isFinite:function(){return isFinite(this.re)&&isFinite(this.im)},isInfinite:function(){return!this.isFinite()}};c.ZERO=new c(0,0);c.ONE=new c(1,0);c.I=new c(0,1);c.PI=new c(Math.PI,0);c.E=new c(Math.E,0);c.INFINITY=new c(Infinity,Infinity);c.NAN=new c(NaN,NaN);c.EPSILON=1E-15;
+"function"===typeof define&&define.amd?define([],function(){return c}):"object"===typeof exports?(Object.defineProperty(c,"__esModule",{value:!0}),c["default"]=c,c.Complex=c,module.exports=c):r.Complex=c})(window);`;
+
+(function (Scratch) {
+ "use strict";
+ function coolCis(ANGLE) {
+ const result = Complex(ANGLE).mul("i").exp();
+ return result;
+ }
+ class ComplexityExtension {
+ constructor() {
+ this.trig = [
+ "sin",
+ "cos",
+ "tan",
+ "cot",
+ "sec",
+ "csc",
+ "asin",
+ "acos",
+ "atan",
+ "acot",
+ "asec",
+ "acsc",
+ "sinh",
+ "cosh",
+ "tanh",
+ "coth",
+ "sech",
+ "csch",
+ "asinh",
+ "acosh",
+ "atanh",
+ "acoth",
+ "asech",
+ "acsch",
+ ];
+
+ try {
+ eval(OGcomplexCode);
+ if (window.Complex) {
+ this.Complex = window.Complex;
+ } else {
+ console.log("Complex is not defined on window");
+ }
+ } catch (e) {
+ console.log("Error evaluating ComplexNumbersCode:", e);
+ }
+ }
+
+ getInfo() {
+ return {
+ id: "complexMath",
+ name: "Complexity!",
+ color1: "#8d3d73",
+ color2: "#4c213e",
+ color3: "#562747",
+ menuIconURI:
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAE7mlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgOS4xLWMwMDIgNzkuYTFjZDEyZiwgMjAyNC8xMS8xMS0xOTowODo0NiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDI2LjQgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyNS0wNC0yMlQxNzoyODowOS0wNTowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjUtMDQtMjJUMTc6Mjk6MDItMDU6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjUtMDQtMjJUMTc6Mjk6MDItMDU6MDAiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjYzMjVjOWRlLTExNzktYTI0OC05NzU0LWZlODFlOTI3YzY1NiIgeG1wTU06RG9jdW1lbnRJRD0i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",
+ blocks: [
+ {
+ opcode: "Complexity",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "New Complex [REAL] [IMAG]",
+ arguments: {
+ REAL: { type: Scratch.ArgumentType.NUMBER, defaultValue: "3" },
+ IMAG: { type: Scratch.ArgumentType.NUMBER, defaultValue: "4" },
+ },
+ },
+ {
+ blockType: Scratch.BlockType.LABEL,
+ text: Scratch.translate("Rectangular Tools"),
+ },
+ {
+ opcode: "rectComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "[REAL] + [IMAG] 𝙞",
+ arguments: {
+ REAL: { type: Scratch.ArgumentType.STRING, defaultValue: "3" },
+ IMAG: { type: Scratch.ArgumentType.STRING, defaultValue: "4" },
+ },
+ },
+ {
+ opcode: "reComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "Real Part of [COMPLEX]",
+ arguments: {
+ COMPLEX: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "1+2i",
+ },
+ },
+ },
+ {
+ opcode: "imComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "Im. Part of [COMPLEX]",
+ arguments: {
+ COMPLEX: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "1+2i",
+ },
+ },
+ },
+ {
+ opcode: "conjugateComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "Conjugate of [COMPLEX]",
+ arguments: {
+ COMPLEX: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ },
+ },
+ {
+ blockType: Scratch.BlockType.LABEL,
+ text: Scratch.translate("Binary operators"),
+ },
+ {
+ opcode: "addComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "[COMPLEX1] + [COMPLEX2]",
+ arguments: {
+ COMPLEX1: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ COMPLEX2: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "1+2i",
+ },
+ },
+ },
+ {
+ opcode: "subtractComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "[COMPLEX1] - [COMPLEX2]",
+ arguments: {
+ COMPLEX1: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ COMPLEX2: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "1+2i",
+ },
+ },
+ },
+ {
+ opcode: "multiplyComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "[COMPLEX1] × [COMPLEX2]",
+ arguments: {
+ COMPLEX1: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ COMPLEX2: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "1+2i",
+ },
+ },
+ },
+ {
+ opcode: "divideComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "[COMPLEX1] / [COMPLEX2]",
+ arguments: {
+ COMPLEX1: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ COMPLEX2: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "1+2i",
+ },
+ },
+ },
+ {
+ opcode: "powComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "[COMPLEX1] ^ [COMPLEX2]",
+ arguments: {
+ COMPLEX1: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "2+i",
+ },
+ COMPLEX2: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3",
+ },
+ },
+ },
+ {
+ opcode: "rootComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "[COMPLEX1] √ [COMPLEX2]",
+ arguments: {
+ COMPLEX1: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3",
+ },
+ COMPLEX2: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "2+11i",
+ },
+ },
+ },
+ {
+ opcode: "logComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "log [BASE] [INPUT]",
+ arguments: {
+ BASE: { type: Scratch.ArgumentType.STRING, defaultValue: "2+i" },
+ INPUT: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "2+11i",
+ },
+ },
+ },
+ {
+ opcode: "equalsComplex",
+ blockType: Scratch.BlockType.BOOLEAN,
+ text: "[COMPLEX1] =? [COMPLEX2]",
+ arguments: {
+ COMPLEX1: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ COMPLEX2: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ },
+ },
+ {
+ blockType: Scratch.BlockType.LABEL,
+ text: Scratch.translate("Polar Tools"),
+ },
+ {
+ opcode: "polarComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "Polar [RADIUS] ∠ [ANGLE]",
+ arguments: {
+ RADIUS: { type: Scratch.ArgumentType.STRING, defaultValue: 5 },
+ ANGLE: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "0.9272952180016122",
+ },
+ },
+ },
+ {
+ opcode: "absComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "Magnitude of [COMPLEX]",
+ arguments: {
+ COMPLEX: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ }, //Magnitude = sqrt(Re^2 + Im^2)
+ },
+ {
+ opcode: "complexSign",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "∠ [COMPLEX]",
+ arguments: {
+ COMPLEX: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ }, //Sign = Complex/Magnitude
+ },
+ {
+ opcode: "cisThingie",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "CiS [ANGLE]",
+ arguments: {
+ ANGLE: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "0.9272952180016122",
+ },
+ }, //CiS = e^(i*Angle)
+ },
+ {
+ opcode: "argComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "Argument of [COMPLEX]",
+ arguments: {
+ COMPLEX: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ }, //Angle = -i*ln(Sign)
+ },
+ {
+ blockType: Scratch.BlockType.LABEL,
+ text: Scratch.translate("Product tools"),
+ },
+ {
+ opcode: "expComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "𝑒 [COMPLEX]",
+ arguments: {
+ COMPLEX: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ },
+ description: "Raises 𝑒 to the Complex",
+ },
+ {
+ opcode: "lnComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "ln [COMPLEX]",
+ arguments: {
+ COMPLEX: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ },
+ },
+ {
+ opcode: "ComplexTimesI",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "[COMPLEXY] 𝙞",
+ arguments: {
+ COMPLEXY: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ },
+ hideFromPalette: true,
+ },
+ {
+ opcode: "sqrtComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "Square Root of [COMPLEX]",
+ arguments: {
+ COMPLEX: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ },
+ },
+ {
+ opcode: "negComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "Negative [COMPLEX]",
+ arguments: {
+ COMPLEX: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ },
+ },
+ {
+ opcode: "inverseComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "Inverse of [COMPLEX]",
+ arguments: {
+ COMPLEX: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ },
+ },
+ {
+ opcode: "getPI",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "[NUM] 𝜋",
+ arguments: {
+ NUM: { type: Scratch.ArgumentType.STRING, defaultValue: "" },
+ },
+ },
+ {
+ opcode: "toDegrees",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "[ANGLE] degs to rads",
+ arguments: {
+ ANGLE: { type: Scratch.ArgumentType.STRING, defaultValue: "30" },
+ },
+ },
+ {
+ blockType: Scratch.BlockType.LABEL,
+ text: Scratch.translate("Vectors"),
+ },
+ {
+ filter: [Scratch.TargetType.SPRITE],
+ opcode: "getPosition",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "Complex Position",
+ },
+ {
+ filter: [Scratch.TargetType.SPRITE],
+ opcode: "goToComplex",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "Go to [COMPLEX]",
+ arguments: {
+ COMPLEX: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "30+40i",
+ },
+ },
+ },
+ {
+ filter: [Scratch.TargetType.SPRITE],
+ opcode: "goAddComplex",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "Move by [COMPLEX]",
+ arguments: {
+ COMPLEX: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "30+40i",
+ },
+ },
+ },
+ {
+ filter: [Scratch.TargetType.SPRITE],
+ opcode: "GoMulComplex",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "Mul position by [COMPLEX]",
+ arguments: {
+ COMPLEX: { type: Scratch.ArgumentType.STRING, defaultValue: 5 },
+ },
+ },
+ {
+ filter: [Scratch.TargetType.SPRITE],
+ opcode: "goToPolar",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "Go polar [RADII] ∠ [ANGLY]",
+ arguments: {
+ RADII: { type: Scratch.ArgumentType.STRING, defaultValue: 50 },
+ ANGLY: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "0.9272952180016122",
+ },
+ },
+ },
+ {
+ opcode: "mulVectorAroundPoint",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "mul [VECTOR] around [POINT] by [FACTOR]",
+ arguments: {
+ VECTOR: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "1+0i",
+ },
+ POINT: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "0+0i",
+ },
+ FACTOR: { type: Scratch.ArgumentType.STRING, defaultValue: 2 },
+ },
+ },
+ {
+ opcode: "rotateVectorAroundPoint",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "rotate [VECTOR] around [POINT] by angle [ANGLE]",
+ arguments: {
+ VECTOR: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "1+0i",
+ },
+ POINT: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "0+0i",
+ },
+ ANGLE: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: 3.1415,
+ },
+ },
+ },
+ {
+ blockType: Scratch.BlockType.LABEL,
+ text: Scratch.translate("Trigonometry"),
+ },
+ {
+ opcode: "trigOfComplex",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "[TRIG] of [COMPLEX]",
+ arguments: {
+ COMPLEX: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ TRIG: { type: Scratch.ArgumentType.STRING, menu: "trigs" },
+ },
+ },
+ {
+ blockType: Scratch.BlockType.LABEL,
+ text: Scratch.translate("Test the numbers"),
+ },
+ {
+ opcode: "getEpsilon",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "Small",
+ },
+ {
+ opcode: "isNaNComplex",
+ blockType: Scratch.BlockType.BOOLEAN,
+ text: "[COMPLEX] is NaN?",
+ arguments: {
+ COMPLEX: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ },
+ },
+ {
+ opcode: "isFiniteComplex",
+ blockType: Scratch.BlockType.BOOLEAN,
+ text: "[COMPLEX] is finite?",
+ arguments: {
+ COMPLEX: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "3+4i",
+ },
+ },
+ },
+ {
+ opcode: "gammaOf",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "Γ ([ZED])",
+ arguments: {
+ ZED: { type: Scratch.ArgumentType.STRING, defaultValue: "3+4i" },
+ },
+ hideFromPalette: true,
+ },
+ ],
+ menus: {
+ trigs: { acceptReporters: true, items: this.trig },
+ },
+ };
+ }
+
+ Complexity({ REAL, IMAG }) {
+ try {
+ const cInstance = new this.Complex(parseFloat(REAL), parseFloat(IMAG));
+ return cInstance.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ rectComplex({ REAL, IMAG }) {
+ try {
+ const cInstance = Complex(IMAG).mul("i").add(Complex(REAL));
+ return cInstance.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ reComplex({ COMPLEX }) {
+ try {
+ const cInstance = new this.Complex(COMPLEX);
+ return cInstance.re;
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ imComplex({ COMPLEX }) {
+ try {
+ const cInstance = new this.Complex(COMPLEX);
+ return cInstance.im;
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ polarComplex({ RADIUS, ANGLE }) {
+ try {
+ const cInstance = coolCis(Complex(ANGLE)).mul(Complex(RADIUS));
+ return cInstance.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ cisThingie({ ANGLE }) {
+ try {
+ return coolCis(ANGLE).toString().replace(/\s+/g, ""); //Meet my creation!
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ addComplex({ COMPLEX1, COMPLEX2 }) {
+ try {
+ const c1 = new this.Complex(COMPLEX1);
+ const c2 = new this.Complex(COMPLEX2);
+ const result = c1.add(c2); //Uses the structure a1.func(a2)
+ return result.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ subtractComplex(
+ { COMPLEX1, COMPLEX2 } //Same
+ ) {
+ try {
+ const c1 = new this.Complex(COMPLEX1);
+ const c2 = new this.Complex(COMPLEX2);
+ const result = c1.sub(c2);
+ return result.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ multiplyComplex(
+ { COMPLEX1, COMPLEX2 } //Again
+ ) {
+ try {
+ const c1 = new this.Complex(COMPLEX1);
+ const c2 = new this.Complex(COMPLEX2);
+ const result = c1.mul(c2);
+ return result.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ ComplexTimesI(
+ { COMPLEXY } //Forever
+ ) {
+ try {
+ const c1 = new this.Complex(COMPLEXY);
+ const result = c1.mul(Complex.I);
+ return result.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ divideComplex(
+ { COMPLEX1, COMPLEX2 } //And ever
+ ) {
+ try {
+ const c1 = new this.Complex(COMPLEX1);
+ const c2 = new this.Complex(COMPLEX2);
+ const result = c1.div(c2);
+ return result.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ powComplex(
+ { COMPLEX1, COMPLEX2 } //ever...
+ ) {
+ try {
+ const c1 = new this.Complex(COMPLEX1);
+ const c2 = new this.Complex(COMPLEX2);
+ const result = c1.pow(c2);
+ return result.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ rootComplex({ COMPLEX1, COMPLEX2 }) {
+ try {
+ const c1 = new this.Complex(COMPLEX2);
+ const c2 = new this.Complex(COMPLEX1).inverse();
+ const result = c1.pow(c2);
+ return result.toString().replace(/\s+/g, ""); //Meet my... other creations!
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ sqrtComplex({ COMPLEX }) {
+ try {
+ const cInstance = new this.Complex(COMPLEX);
+ const result = cInstance.sqrt();
+ return result.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ logComplex({ BASE, INPUT }) {
+ try {
+ const cBase = new this.Complex(BASE);
+ const cInput = new this.Complex(INPUT);
+ const result = cInput.log().div(cBase.log());
+ return result.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ expComplex({ COMPLEX }) {
+ try {
+ const cInstance = new this.Complex(COMPLEX);
+ const result = cInstance.exp();
+ return result.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ lnComplex({ COMPLEX }) {
+ try {
+ const cInstance = new this.Complex(COMPLEX);
+ const result = cInstance.log();
+ return result.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ conjugateComplex({ COMPLEX }) {
+ try {
+ const cInstance = new this.Complex(COMPLEX);
+ const result = cInstance.conjugate();
+ return result.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ complexSign({ COMPLEX }) {
+ try {
+ const cInstance = new this.Complex(COMPLEX);
+ const result = cInstance.sign();
+ return result.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ absComplex({ COMPLEX }) {
+ try {
+ const cInstance = new this.Complex(COMPLEX);
+ const result = cInstance.abs();
+ return result.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ argComplex({ COMPLEX }) {
+ try {
+ const cInstance = new this.Complex(COMPLEX);
+ const result = cInstance.arg();
+ return result.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ inverseComplex({ COMPLEX }) {
+ try {
+ const cInstance = new this.Complex(COMPLEX);
+ const result = cInstance.inverse();
+ return result.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ negComplex({ COMPLEX }) {
+ try {
+ const cInstance = new this.Complex(COMPLEX);
+ const result = cInstance.neg();
+ return result.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ mulVectorAroundPoint({ VECTOR, POINT, FACTOR }) {
+ try {
+ const p = new this.Complex(POINT);
+ const result = Complex(VECTOR).sub(p).mul(Complex(FACTOR)).add(p);
+ return result.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ rotateVectorAroundPoint({ VECTOR, POINT, ANGLE }) {
+ try {
+ const a = new this.Complex(ANGLE);
+ const p = new this.Complex(POINT);
+ const result = Complex(VECTOR).sub(p).mul(coolCis(a)).add(p);
+ return result.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ getPosition(args, util) {
+ try {
+ return Complex(util.target.x, util.target.y)
+ .toString()
+ .replace(/\s+/g, "");
+ } catch (e) {
+ if (util.target.y < 0) {
+ let imPart = util.target.y + "i";
+ return util.target.x + imPart;
+ }
+ return util.target.x + "+" + util.target.y + "i";
+ }
+ }
+
+ goToComplex(args, util) {
+ try {
+ const cInstance = new this.Complex(args.COMPLEX);
+ util.target.setXY(cInstance.re, cInstance.im);
+ } catch (e) {
+ util.target.setXY(util.target.x, util.target.y);
+ }
+ }
+
+ goAddComplex(args, util) {
+ try {
+ const cInstance = new this.Complex(args.COMPLEX);
+ util.target.setXY(
+ util.target.x + cInstance.re,
+ util.target.y + cInstance.im
+ );
+ } catch (e) {
+ util.target.setXY(util.target.x, util.target.y);
+ }
+ }
+
+ goToPolar(args, util) {
+ try {
+ const cInstance = coolCis(args.ANGLY).mul(args.RADII);
+ util.target.setXY(cInstance.re, cInstance.im);
+ } catch (e) {
+ util.target.setXY(util.target.x, util.target.y);
+ }
+ }
+
+ GoMulComplex(args, util) {
+ try {
+ const cIn = Complex(args.COMPLEX);
+ const cInstance = Complex(util.target.x, util.target.y).mul(cIn);
+ util.target.setXY(cInstance.re, cInstance.im);
+ } catch (e) {
+ util.target.setXY(util.target.x, util.target.y);
+ }
+ }
+
+ trigOfComplex({ COMPLEX, TRIG }) {
+ try {
+ const cInstance = new this.Complex(COMPLEX);
+ const trigMethod = TRIG.toLowerCase();
+ const validTrigFunctions = this.trig;
+ if (
+ validTrigFunctions.includes(trigMethod) &&
+ typeof cInstance[trigMethod] === "function"
+ ) {
+ const result = cInstance[trigMethod]();
+ return result.toString().replace(/\s+/g, "");
+ } else {
+ return "0";
+ }
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ getPI({ NUM }) {
+ try {
+ if (NUM == "") {
+ return Complex.PI;
+ }
+ const n = Complex(NUM).mul(Complex.PI);
+ return n.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ toDegrees({ ANGLE }) {
+ try {
+ const cInstance = Complex(ANGLE).mul(0.017453292519943295);
+ return cInstance.toString().replace(/\s+/g, "");
+ } catch (e) {
+ return NaN;
+ }
+ }
+
+ equalsComplex({ COMPLEX1, COMPLEX2 }) {
+ try {
+ const c1 = new this.Complex(COMPLEX1);
+ const c2 = new this.Complex(COMPLEX2);
+ return c1.equals(c2);
+ } catch (e) {
+ return false;
+ }
+ }
+
+ gammaOf({ ZED }) {
+ let c = [
+ 0, //term 0
+ 12660849.842047213,
+ -50335415.002908535,
+ 84454267.34858105, //3
+ -77919883.76930115,
+ 43222228.65544386,
+ -14822605.274039656,
+ 3120357.332437802, //7
+ -387970.92317872215,
+ 26862.929569096596,
+ -580.6487234445449,
+ 312.43962238445295, //11
+ 300.96569466095724,
+ 301.00429242666866,
+ 301.00427867948963,
+ 301.00427867952084, //15
+ ];
+ const Z = Complex(ZED);
+ if (Z.re < 0.5) {
+ return Complex.PI.div(
+ z
+ .mul(3.1415926535897932)
+ .sin()
+ .mul(gammaOf(Complex(1).sub(Z)))
+ );
+ }
+
+ const z = Z.sub(1);
+ let x = Complex(2.5066282746310002);
+ let a;
+
+ for (var i = 1; i < 15; i++) {
+ x = Complex(c[i]).div(z.add(i)).add(x).toString();
+ }
+ const b = z.add(15).pow(z.add(0.5)).mul(z.neg().sub(15).exp()).mul(x);
+ return b.toString().replace(/\s+/g, "");
+ }
+
+ getEpsilon() {
+ try {
+ return this.Complex.EPSILON;
+ } catch (e) {
+ return 0.000000000000001;
+ }
+ }
+
+ isNaNComplex({ COMPLEX }) {
+ try {
+ const cInstance = new this.Complex(COMPLEX);
+ return cInstance.isNaN();
+ } catch (e) {
+ return false;
+ }
+ }
+
+ isFiniteComplex({ COMPLEX }) {
+ try {
+ const cInstance = new this.Complex(COMPLEX);
+ return cInstance.isFinite();
+ } catch (e) {
+ return false;
+ }
+ }
+ }
+ Scratch.extensions.register(new ComplexityExtension());
+})(Scratch);