From 9696c9b2753f5d7a55eca94331d1ec01ced08e52 Mon Sep 17 00:00:00 2001 From: pommicket Date: Sun, 16 Oct 2016 15:07:39 -0400 Subject: Added complex RPN functions --- complexfunctions.html | 89 ++++++++++++++++ css/styleNew.css | 25 +++++ js/complex.js | 282 +++++++++++++++++++++++++++++++++++++++++++++++++ js/complexfunctions.js | 86 +++++++++++++++ 4 files changed, 482 insertions(+) create mode 100644 complexfunctions.html create mode 100644 css/styleNew.css create mode 100644 js/complex.js create mode 100644 js/complexfunctions.js diff --git a/complexfunctions.html b/complexfunctions.html new file mode 100644 index 0000000..f815b41 --- /dev/null +++ b/complexfunctions.html @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + Complex Functions + + + +
+ + + +

Graph reverse polish notation + complex functions

+ + See explanation below. + + +
+ +
+
+ Function + +
+
+
+ +
+
+ +
+ +
+

Explanation

+ The x axis represents the real component, and the y axis represents the imaginary component. + Complex numbers are numbers with both real and imaginary parts: + $$z = a + b\sqrt{-1} = a + bi$$ + Reverse Polish Notation, or postfix notation is a way of writing functions. Normally, most people would write functions using + infix notation like this: + $$a + b + \sin c$$ + Postfix notation looks like this: + $$a\ b + c \sin +$$ + For a more simple example, $a + b$ would be $a\ b\ +$, and $\sin x$ would be $x \sin$. +

List of all functions and constants

+ + + + + + + + + + + + + + + + + + + + + + + + +
Function or constant What it means
x The input to the function.
i $i = \sqrt{-1}$
n (e.g. 5, 4, 3.1, -32.123) A real number.
ni (e.g. 5i, 4i, 3.1i, -32.123i) $i$ ($\sqrt{-1}$) times a certain real number.
+ Addition
- Subtraction
* Multiplication
/ Division
^ Exponentiation ($a^b$)
re Real component. If $z = a+bi$, $\textrm{Re}(z) = a$
im Imaginary component. If $z = a+bi$, $\textrm{Im}(z) = b$
pi $\pi = 3.14159265...$
e $e = 2.7182818...$
sqrt $\sqrt{x}$
exp $e^x$
sin Sine
cos Cosine
tan Tangent
sinh Hyperbolic sine
cosh Hyperbolic cosine
tanh Hyperbolic tangent
+
+ +
+ + diff --git a/css/styleNew.css b/css/styleNew.css new file mode 100644 index 0000000..467e428 --- /dev/null +++ b/css/styleNew.css @@ -0,0 +1,25 @@ +#navbar +{ + margin-top: 10px; +} + +footer +{ + font-size:12px; +} + +.project-title +{ + font-size: 22px; +} + +.checkbox +{ + width: 20px; + height: 20px; +} + +.with-margin +{ + margin-bottom: 5px; +} diff --git a/js/complex.js b/js/complex.js new file mode 100644 index 0000000..3f009bd --- /dev/null +++ b/js/complex.js @@ -0,0 +1,282 @@ +/* + complex.js + Client-side complex numbers in JavaScript +*/ +var complex = {}; + +complex.i = [0, 1]; +complex.logi = [0, 0.682188177]; +complex.PI = [Math.PI, 0]; +complex.E = [Math.E, 0]; + +complex.lnAccuracy = 20; + + +complex.re = function (a) +{ + return a[0]; +} + +complex.im = function (a) +{ + return a[1]; +} + +// Create a complex number from a real number +complex.reToC = function (a) +{ + return [a, 0]; +} + +complex.reC = function (a) +{ + return complex.reToC(complex.re(a)); +} + +complex.imC = function (a) +{ + return complex.reToC(complex.im(a)); +} + + + +complex.show = function (a) +{ + var im = complex.im(a); + var re = complex.re(a); + if (im == 1 && re == 0) + return "i"; + if (im == 0) + return re.toString(); + if (im == 1) + return re + " + i"; + if (re == 0) + return im + "i"; + return re + " + " + im + "i"; +} + +complex.add = function (a, b) +{ + return [complex.re(a) + complex.re(b), complex.im(a) + complex.im(b)]; +} + +complex.neg = function (a) +{ + return [-complex.re(a), -complex.im(a)]; +} + +complex.sub = function (a, b) +{ + return complex.add(a, complex.neg(b)); +} + +complex.mult = function (a, b) +{ + var a_Re, a_Im, b_Re, b_Im; + a_Re = complex.re(a); + a_Im = complex.im(a); + b_Re = complex.re(b); + b_Im = complex.im(b); + return [a_Re * b_Re - a_Im * b_Im, a_Re * b_Im + a_Im * b_Re]; +} + +complex.recip = function (a) +{ + var re = complex.re(a); + var im = complex.im(a); + var divBy = re*re + im*im; + return [re/divBy, -im/divBy] +} + +complex.div = function (a, b) +{ + return complex.mult(a, complex.recip(b)); +} + +complex.exp = function (a) +{ + var re = complex.re(a); + var im = complex.im(a); + var expRe = Math.exp(re); + return [expRe * Math.cos(im), expRe * Math.sin(im)]; +} + +complex.theta = function (a) +{ + return Math.atan(complex.im(a) / complex.re(a)); +} + +complex.abs = function (a) +{ + var re = complex.re(a); + var im = complex.im(a); + return Math.sqrt(re*re + im*im); +} + +complex.polar = function (a) +{ + return [complex.abs(a), complex.theta(a)]; +} + +complex.arg = function (a) +{ + var x = complex.re(a); + var y = complex.im(a); + var theta = complex.theta(a); + if (x > 0) + return theta; + if (x < 0 && y >= 0) + return theta + Math.PI; + if (x < 0 && y < 0) + return theta - Math.PI; + if (x == 0 && y > 0) + return Math.PI / 2; + if (x == 0 && y < 0) + return -Math.PI / 2; + return 1 / 0; +} + +complex.ln = function (a) +{ + return [Math.log(complex.abs(a)), complex.arg(a)]; +} + +complex.log = function (base, a) +{ + return complex.div(complex.ln(a), complex.ln(base)); +} + +complex.pow = function (a, b) +{ + return complex.exp(complex.mult(b, complex.ln(a))); +} + +complex.sin = function (a) +{ + var ia = complex.mult(complex.i, a); + return complex.mult([0, 0.5], complex.sub(complex.exp(complex.neg(ia)), complex.exp(ia))); +} + +complex.cos = function (a) +{ + return complex.sin(complex.sub(complex.reToC(Math.PI / 2), a)); +} + +complex.tan = function (a) +{ + return complex.div(complex.sin(a), complex.cos(a)); +} + +complex.sqrt = function (a) +{ + return complex.pow(a, complex.reToC(0.5)); +} + +complex.sinh = function (a) +{ + return complex.mult([0.5, 0], complex.sub(complex.exp(a), complex.exp(complex.neg(a)))); +} + +complex.cosh = function (a) +{ + return complex.mult([0.5, 0], complex.add(complex.exp(a), complex.exp(complex.neg(a)))) +} + +complex.tanh = function (a) +{ + return complex.div(complex.sinh(a), complex.cosh(a)); +} + +complex.rpn = function (s) +{ + // complex.rpn :: String -> (Complex -> Complex) + + + var tokens = s.split(" "); + + return function(x) + { + var token; + var stack = []; + for (var i = 0; i < tokens.length; i++) + { + token = tokens[i]; + switch (token) + { + case "+": + stack.push(complex.add(stack.pop(), stack.pop())); + break; + case "*": + stack.push(complex.mult(stack.pop(), stack.pop())); + break; + case "-": + var val2 = stack.pop(); + var val1 = stack.pop(); + stack.push(complex.sub(val1, val2)); + break; + case "/": + var val2 = stack.pop(); + var val1 = stack.pop(); + stack.push(complex.div(val1, val2)); + break; + case "^": + var val2 = stack.pop(); + var val1 = stack.pop(); + stack.push(complex.pow(val1, val2)); + break; + case "sqrt": + stack.push(complex.sqrt(stack.pop())); + break; + case "exp": + stack.push(complex.exp(stack.pop())); + break; + case "sin": + stack.push(complex.sin(stack.pop())); + break; + case "cos": + stack.push(complex.cos(stack.pop())); + break; + case "tan": + stack.push(complex.tan(stack.pop())); + break; + case "sinh": + stack.push(complex.sinh(stack.pop())); + break; + case "cosh": + stack.push(complex.cosh(stack.pop())); + break; + case "tanh": + stack.push(complex.tanh(stack.pop())); + break; + case "re": + stack.push(complex.reC(stack.pop())); + break; + case "im": + stack.push(complex.imC(stack.pop())); + break; + case "x": + stack.push(x); + break; + case "i": + stack.push(complex.i); + break; + case "e": + stack.push(complex.E); + break; + case "pi": + stack.push(complex.PI); + break; + default: + if (token[token.length-1] == "i") + { + stack.push([0, parseFloat(token.substring(0, token.length-1))]); + } + else + { + stack.push(complex.reToC(parseFloat(token))); + } + } + } + return stack.pop(); + }; +} diff --git a/js/complexfunctions.js b/js/complexfunctions.js new file mode 100644 index 0000000..fce70a6 --- /dev/null +++ b/js/complexfunctions.js @@ -0,0 +1,86 @@ +var domainPoints; +var rangePoints; +var animating = false; +var t = 0; +var SCALE = 5; + +function drawPoints(points) +{ + background(255); + for (var i = 0; i < points.length; i++) + { + point((points[i][0]/SCALE+0.5)*width, (points[i][1]/SCALE+0.5)*height); + } +} + + +function mapFunc(func) +{ + var f = complex.rpn(func); + rangePoints = []; + for (var i = 0; i < domainPoints.length; i++) + { + rangePoints.push(f(domainPoints[i])); + } +} + +function drawFunc(func) +{ + mapFunc(func); + animating = true; +} + +function draw() +{ + + if (animating) + { + var midpoints = []; + for (var i = 0; i < domainPoints.length; i++) + midpoints.push(complex.add(complex.mult(domainPoints[i], complex.reToC(1-t)), complex.mult(rangePoints[i], complex.reToC(t)))); + + drawPoints(midpoints); + + t += 0.01; + if (t >= 1) + { + animating = false; + drawPoints(rangePoints); + } + + + } +} + +function setup() +{ + var canvas = createCanvas(750, 750); + canvas.parent("canvas"); + stroke(0,0,100); + domainPoints = []; + for (var i = 10; i < width; i += 50) + { + for (var j = 0; j < height; j++) + { + domainPoints.push([(j/width-0.5)*SCALE, (i/height-0.5)*SCALE]); + domainPoints.push([(i/width-0.5)*SCALE, (j/height-0.5)*SCALE]); + } + } + drawPoints(domainPoints); +} + +$(function() +{ + $("#animate").click(function() + { + t = 0; + animating = false; + var func = $("#function").val(); + drawFunc(func); + }); + $("#function").keydown(function(e) + { + if (e.keyCode == 13) + $("#animate").click(); + }); +}); -- cgit v1.2.3