title: Discrepancy between generated Julia set and Wikipedia image
body: <p>I have written a small javascript program to view julia set images<a href="http://thejamespaterson.com/scripts/julia/" rel="nofollow noreferrer"> [link]</a>. I've ben implementing multiple iteration algorithms (Not just <code>z^2 + c</code>) and recently implemented <code>exp(z)</code>. However, my output differs from the wikipedia page image. Here's a comparison for the c value <code>-0.65</code>:</p>
  
  <p>My image: 
  <a href="https://i.stack.imgur.com/b2LUs.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/b2LUs.png" alt="My julia set"></a></p>
  
  <p>Wikipedia image<a href="https://i.stack.imgur.com/BIwqu.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/BIwqu.jpg" alt="enter image description here"></a></p>
  
  <p>Obviously, their output is a lot more colourful and shows a lot more detail! I was thinking it is probably a mistake in my implementation, or maybe my coloring algorithm? Or is the wikipedia result generated by some differing means? Below is an MVE with just the <code>e^z + c</code> algorithm and the relevant functions. If you want to play with the whole program feel free, it's hosted <a href="http://thejamespaterson.com/scripts/julia/" rel="nofollow noreferrer">on my site</a>. </p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>//globals
  var MAXITERATION = 2500;
  var BOUNDARY = 4;
  var CANVASID = "juliaDraw";
  var CANVAS = document.getElementById("juliaDraw");
  var CONTEXT = document.getElementById("juliaDraw").getContext('2d');
  var HEIGHT = 750;
  var WIDTH = 750;
  var CONVERGENCEITERCOUNT = 2500;
  
  /** Complex number functions **/
  
  function complexNum(real, imaginary) {
    this.real = real;
    this.imaginary = imaginary;
    return this;
  }
  
  // This is the bit that might be a problem but it seems to return correct results? 
  function raiseNumberToComplexPower(x, c) {
    var s = Math.pow(x, c.real);
    var pow = c.imaginary * Math.log(x);
    var num = new complexNum(Math.cos(pow), Math.sin(pow));
    return scalarComplex(s, num);
  }
  
  function addComplex(c1, c2) {
    var real = c1.real + c2.real;
    var imaginary = c1.imaginary + c2.imaginary;
    return new complexNum(real, imaginary);
  }
  
  function multComplex(c1, c2) {
    var real = (c1.real * c2.real) - (c1.imaginary * c2.imaginary);
    var imaginary = (c1.real * c2.imaginary) + (c2.real * c1.imaginary);
    return new complexNum(real, imaginary);
  }
  
  function scalarComplex(s, c) {
    return new complexNum(c.real * s, c.imaginary * s);
  }
  
  function getComplexModulus(c) {
   return Math.sqrt((c.real * c.real) + (c.imaginary * c.imaginary));
  }
  
  /** Drawing and manipulation **/
  
  function createArray(length) {
    var arr = new Array(length || 0),
      i = length;
    if (arguments.length &gt; 1) {
      var args = Array.prototype.slice.call(arguments, 1);
      while (i--) arr[length - 1 - i] = createArray.apply(this, args);
    }
    return arr;
  }
  
  function drawJulia() {
    CONTEXT.clearRect(0, 0, WIDTH, HEIGHT);
    var start = new complexNum(-2, 2);
    var c = new complexNum(readInput('realValue') * 1, readInput('imagValue') * 1);
    STARTPOS = {
      real: -2,
      imaginary: 2
    }
    RANGE = 4;
    plotJuliaSet(CANVASID, c);
  }
  
  function plotJuliaSet(canvasID, c) {
    var complexNumberArray = createArray(WIDTH + 1, HEIGHT + 1);
    var doesPointEscapeArray = createArray(WIDTH + 1, HEIGHT + 1);
    ITERALGO = exponential;
    for (var x = 0; x &lt;= WIDTH; x++) {
      for (var y = 0; y &lt;= HEIGHT; y++) {
        complexNumberArray[x][y] = new coordsToComplex({
          x: x,
          y: y
        });
        complexNumberArray[x][y] = complexNumberArray[x][y];
        doesPointEscapeArray[x][y] = doesPointEscape(c, complexNumberArray[x][y]);
        if (doesPointEscapeArray[x][y] &gt;= 0) {
          drawPointOnCanvas(x, y, getColor(doesPointEscapeArray[x][y]));
        } else {
          drawPointOnCanvas(x, y, 'black');
        }
      }
    }
    console.log('done');
  }
  
  function doesPointEscape(c, complexNum) {
    var iterations = 0;
    var iterationsToEscape = -1;
    var escaped = false;
    while ((!escaped) &amp;&amp; (iterations &lt; MAXITERATION)) {
      if (getComplexModulus(complexNum) &gt; BOUNDARY) {
        escaped = true;
        iterationsToEscape = iterations;
      }
      complexNum = ITERALGO(complexNum, c);
      iterations++;
    }
    return iterationsToEscape;
  }
  
  function exponential(complexNum, c) {
    // e^z + c
    return addComplex(raiseNumberToComplexPower(Math.E, complexNum), c);
  }
  
  function drawPointOnCanvas(x, y, color) {
    CONTEXT.fillStyle = color;
    CONTEXT.fillRect(x, y, 1, 1);
  }
  
  function getColor(iterations) {
    //console.log("Iterations: "+getBaseLog(iterations+1,255));
    var color = "rgb(" + Math.floor((8 * iterations) % 255) + "," + Math.floor(2 * iterations % 255) + "," + Math.floor(255 - ((8 * iterations) % 255)) + ")";
    //console.log(color);
    return color;
  }
  
  function coordsToComplex(coordinates) {
    return {
      real: ((coordinates.x / WIDTH) * RANGE + STARTPOS.real),
      imaginary: ((coordinates.y / HEIGHT) * -RANGE + STARTPOS.imaginary)
    };
  }
  
  function complexToCoords(c) {
    return {
      x: ((c.real - STARTPOS.real) / (RANGE)) * WIDTH,
      y: ((c.imaginary - STARTPOS.imaginary) / -(RANGE)) * HEIGHT
    };
  }
  
  function readInput(inputID) {
    return document.getElementById(inputID).value;
  }</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>.desc {
    float: right;
    width: 300px;
  }
  #juliaDraw {
    border: 1px dotted;
    float: left;
  }
  .canvasWrapper canvas {
    position: absolute;
    top: 0;
    left: 0;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;div class="desc"&gt;
    &lt;h1&gt;Julia Set Viewer&lt;/h1&gt; 
    &lt;form&gt;
      &lt;label&gt;Real:
        &lt;input type="text" id="realValue" value="-0.65"&gt;
      &lt;/label&gt;
      &lt;br&gt;
      &lt;label&gt;Imag:
        &lt;input type="text" id="imagValue" value="0"&gt;
      &lt;/label&gt;
      &lt;input type="button" onClick="drawJulia()" value="Draw"&gt;
    &lt;/form&gt;
  &lt;/div&gt;
  &lt;canvas id="juliaDraw" width=750 height=750 onClick="drawZoomJulia()"&gt;&lt;/canvas&gt;</code></pre>
  </div>
  </div>
  </p>