<?php
/**
     This file will create an XML file meeting the aboutNumber.xsd schema

    it expects a URLecode variable number set to an integer value
    GermainPrimes are tested up to 16 bit; Fermats to 32 bits;
        GermainPrimes exceeding 16 bits will be returned as false

    it will return an AboutNumbers XML file,
    describing if the number isFermat and isGermainPrime

    Fermat and GermainPrime were calculated using a java Program
    and stored in a PHP Array, an internal  binarySearch function
    is used to find or not find a match.
 
    Future version will read from a database

    the xml file create is using the PHP DOM class SimpleXML
    
    @see also http://php.net/manual/en/book.simplexml.php

    when creating a XML file make sure you don't write anything
    the first string written has to be an XML header (at end of file)
    then the content of the xml document


    if you have taken cimw 245, you should be able to modify your
    numberInfo Assignment to generate an AboutNumber schema
    if you have taking cs4a and cimw260 in the spring you should
    be able to modify your JavaBean/JSP to support the AboutNumber schema

    Of course Minnie Mouse is not smart enough write this file,
    she got Goofy Goof to write it.

    Written 10/10/2014
    Bugs need to fix or throw exceptions when integers  are too large
*/

  //sent First two  lines in AbutNumber
  $xmlStr = "<?xml version='1.0' encoding='UTF-8'?>\n".
          /* "<?xml DOCTYPE AboutNumbers SYSTEM  'aboutNumber.dtd' ?>\n". 
          '<?xml-stylesheet href="aboutNumber.css" ?>'. */
          '<AboutNumbers></AboutNumbers>'; 

  //create an $xml object based on SimpleXMLElement.
  $xml = new SimpleXMLElement( $xmlStr );

   /** 
    Sophic Germain Primes were generated using a Java Prime Sieve 
    - didn't want to execute code on server for each request
       future results will be built into a database */

  $germainPrime = array( 2, 3, 5, 11, 23, 29, 41, 53, 83, 89, 113, 131,
     173, 179, 191, 233, 239, 251, 281, 293, 
         359, 419, 431, 443, 491, 509, 593, 641, 653,
     659, 683, 719, 743, 761, 809, 911, 953, 1013, 1019, 1031,
         1049, 1103, 1223, 1229, 1289, 1409, 1439, 1451, 1481, 1499,
     1511, 1559, 1583, 1601, 1733, 1811, 1889, 
         1901, 1931, 1973, 2003, 2039, 2063, 2069, 2129, 2141, 2273,
     2339, 2351, 2393, 2399, 2459, 2543, 2549,
         2693, 2699, 2741, 2753, 2819, 2903, 2939, 2963, 2969, 3023,
     3299, 3329, 3359, 3389, 3413, 3449, 3491,
         3539, 3593, 3623, 3761, 3779, 3803, 3821, 3851, 3863, 3911,
     4019, 4073, 4211, 4271, 4349, 4373, 4391, 
         4409, 4481, 4733, 4793, 4871, 4919, 4943, 5003, 5039, 5051,
     5081, 5171, 5231, 5279, 5303, 5333, 5399,
         5441, 5501, 5639, 5711, 5741, 5849, 5903, 6053, 6101, 6113,
     6131, 6173, 6263, 6269, 6323, 6329, 6449,
         6491, 6521, 6551, 6563, 6581, 6761, 6899, 6983, 7043, 7079,
     7103, 7121, 7151, 7193, 7211, 7349, 7433, 
         7541, 7643, 7649, 7691, 7823, 7841, 7883, 7901, 8069, 8093,
     8111, 8243, 8273, 8513, 8663, 8693, 8741,
         8951, 8969, 9029, 9059, 9221, 9293, 9371, 9419, 9473, 9479,
     9539, 9629, 9689, 9791, 10061, 10091, 10163, 
         10253, 10271, 10313, 10331, 10529, 10589, 10613, 10691, 10709,
     10733, 10781, 10799, 10883, 11171, 11321, 
         11369, 11393, 11471, 11519, 11549, 11579, 11699, 11783, 11801,
     11813, 11831, 11909, 11939, 12011, 12041,
            12101, 12119, 12203, 12263, 12329, 12653, 12671, 12791, 12821,
     12899, 12923, 12959, 13001, 13049, 13229, 
         13313, 13451, 13463, 13553, 13619, 13649, 13763, 13883, 13901,
     13913, 14009, 14081, 14153, 14159, 14249, 
         14303, 14321, 14489, 14561, 14621, 14669, 14699, 14741, 14783,
     14831, 14879, 14939, 15101, 15161, 15173,
         15233, 15269, 15401, 15569, 15629, 15773, 15791, 15803, 15923,
     16001, 16091, 16253, 16301, 16421, 16493, 
         16553, 16673, 16811, 16823, 16883, 16931, 17159, 17183, 17291,
     17333, 17351, 17579, 17669, 17681, 17939, 
            17981, 18041, 18131, 18149, 18191, 18233, 18341, 18443, 18461,
     18731, 18773, 18803, 18899, 19163, 19301, 
         19319, 19373, 19391, 19433, 19553, 19559, 19661, 19709, 19751,
     19889, 19913, 19919, 19991, 20063, 20249, 
         20369, 20393, 20411, 20441, 20693, 20753, 20759, 20771, 20789,
     20879, 20921, 20939, 20963, 21011, 21089,
         21149, 21179, 21221, 21341, 21383, 21419, 21611, 21701, 21713,
     21803, 21893, 22013, 22079, 22133, 22259,
         22271, 22343, 22349, 22409, 22433, 22469, 22481, 22541, 22751,
     22853, 22943, 23099, 23279, 23321, 23339,
         23459, 23561, 23603, 23669, 23753, 23819, 23909, 23981, 24203,
     24239, 24281, 24473, 24509, 24551, 24611,
         24683, 24749, 24971, 25073, 25229, 25523, 25601, 25643, 25673,
     25703, 25799, 25841, 25913, 25919, 26111,
         26189, 26459, 26501, 26573, 26633, 26849, 26879, 26891, 26993,
     27143, 27281, 27479, 27539, 27551, 27581,
         27743, 27773, 27809, 27893, 27983, 28001, 28019, 28403, 28499,
     28559, 28571, 28643, 28751, 28793, 28859,
         28901, 28949, 28961, 29021, 29033, 29201, 29339, 29363, 29453,
     29483, 29531, 29723, 29873, 30269, 30323,
         30389, 30449, 30671, 30689, 30773, 30851, 30983, 31019, 31151,
     31253, 31319, 31469, 31649, 31721, 31793,
         31799, 31859, 32003, 32009, 32141, 32159, 32381, 32531, 32561,
     32573, 32633 ); 

        $fermat = array( 3, 5, 17, 257, 65537, 2147483647 );
        
    //couldn't find a built in binary Search
    function binarySearch( $needle, $haystack )
    {
        $low = 0; $high = count( $haystack ) - 1;
        while( $low <= $high ) {
            $mid = floor( ($low+$high)/2 );

            if( $haystack[ $mid ] == $needle ) return $mid;
            elseif( $needle > $haystack[$mid] ) $low = $mid+1;
            else $high = $mid-1;
        }
        return -$mid;
    } //binarySearch


    function perfectSquare( $i )
    {
         $root = intval( sqrt( $i ) );
         return( $i == $root*$root );
    }

    function isFibonacci( $i )
    {
    return( perfectSquare( 5*$i*$i + 4) ||
                perfectSquare( 5*$i*$i - 4 ) );

    }

    if( array_key_exists( "number", $_GET ) ) $n = $_GET[ 'number' ];
    elseif( array_key_exists( "number", $_POST ) ) $n = $_POST[ 'number' ];
    else $n = 3;
    $n = intval( $n );
    

    /** set the two NumberInfo child nodes of AboutNumber */ 
    $child = $xml->addChild( "AboutNumber" );
    $child->addChild( "Number", $n );
    $nInfo = $child->addChild( "NumberInfo",
             (binarySearch( $n, $germainPrime )>=0?"true":"false") );

    $nInfo->addAttribute( "description",
     "Sophie Germain Prime, is a number n whereby both n, and 2*n+1 are prime" );
    $nInfo->addAttribute( "title", "germainPrime" );
    
    $nInfo = $child->addChild( "NumberInfo",
         (binarySearch( $n, $fermat )>=0?"true":"false") );

    $nInfo->addAttribute( "description",
             "Fermat 2^2^n + 1  its believed all Fermats are prime" );
    $nInfo->addAttribute( "title", "fermat" );
  
/*
    $nInfo = $child->addChild( "NumberInfo", (perfectSquare( $n )?"true":"false") );
    $nInfo->addAttribute( "description", "Perfect Square" );
    $nInfo->addAttribute( "title", "perfectSquare" );
*/

    $nInfo = $child->addChild( "NumberInfo", (isFibonacci( $n )?"true":"false") );
    $nInfo->addAttribute( "description", "Fibonacci Number fn = fn-1 + fn-2" );
    $nInfo->addAttribute( "title", "fibonacci" );
    
    // first send the correct http header
    header( 'Access-Control-Allow-Origin: *' ); //allow CORS but not working
    header( 'Content-type: text/xml' );
    echo $xml->asXML();
    
    /*
    echo binarySearch( 5, $germainPrime )."\n";
    echo binarySearch( 17, $fermat );
    echo binarySearch( 20, $fermat ); */
?>