Skip to content

Instantly share code, notes, and snippets.

@Recoskie
Last active June 30, 2022 09:44
Show Gist options
  • Save Recoskie/3475a124f095c90bb090bc096bcf0e0c to your computer and use it in GitHub Desktop.
Save Recoskie/3475a124f095c90bb090bc096bcf0e0c to your computer and use it in GitHub Desktop.
Geometric Number data type.
function cf( a, b )
{
this.a = []; this.b = []; this.length = 0;
//Data type methods.
this.valueOf = function()
{
for( var i = this.length - 1, v = 0; i >= 0; i-- )
{
if( i > 0 )
{
v = this.b[i-1] / (this.a[i] + v);
}
else { v += this.a[i]; }
}
return( v );
};
this.log = function() { console.log("A=" + this.a + ""); console.log("B=" + this.b + ""); };
this.expand = function(a,b)
{
var c = this, x = this.length - 1, A = c.b[x-1], B = c.a[x], Ar = c.a[x-1];
if( x <= 0 || a > Ar ){ return(false); }
if(a) { A += B * (Ar - (c.a[x-1] = a)); }; if(b) { B *= b; }
if( !isFinite(A) || !isFinite(B) ){ c.a[x-1] = Ar; return(false); }
c.a[x] = (B / A) & -1; c.b[x] = B % A; c.a[x+1] = A;
c.b[x-1] = b || 1; c.b[x+1] = 1; c.length += 1;
if(c.b[x] == 0 || c.a[x] == 0) { c.combine(); return(false); };
return(true);
};
this.combine = function()
{
c = this; if( (x = this.length - 1) <= 1 ){ return(false); }
c.a[x]/=c.b[x-2]; c.b[x-1]/=c.b[x-2];
c.a[x-1] = c.b[x-1] + (c.a[x] * c.a[x-1]);
c.b[x-2] = c.a[x] * c.b[x-2]; c.b[x-1] = 1;
this.pop(); return(true);
};
this.getFract = function() { while( this.combine() ); return(this.a[0]*this.a[1]+this.b[0] + "\xF7" + this.a[1] + ""); }
this.adjA = function( el, v )
{
var d = ((v - this.a[el]) / this.a[el]) + 1;
this.a[el] = v;
this.b[el] *= d; this.b[el-1] *= d;
};
this.adjB = function( el, v )
{
var d = v/this.b[el-1];
this.a[el] = this.a[el] + (this.a[el] * (d-1));
this.b[el] *= d; this.b[el-1] *= d;
};
this.A = function(){ return(this.a[this.length-3]||0); }
this.B = function() { return(this.b[this.length-3]||0); }
this.int = function() { return(this.a[this.length-2]); }
this.re = function(int) { return((this.a[this.length-1]/(this.b[this.length-2]+this.a[this.length-1]*((c.int()-int)||0)))); }
this.pop = function() { if( this.length >= 1 ) { this.length--; return([this.a.pop(), this.b.pop()]); } };
this.push = function(a,b){ if(b){ a = [a,b]; } this.a.push(a[0]); this.b.push(a[1]); this.length++; }
//Directly set A and B.
if( isNaN(a) ) { this.a = a || []; this.b = b || []; this.length=Math.min(this.a.length,this.b.length); }
//Split the number apart in A=int,B=1.
else
{
b = a = Math.abs(a); while( b - this != 0 )
{
a = 1 / ( a - (this.a[this.length] = a & -1) ); this.b[this.length++] = 1;
}
}
};

This tool lets you work with numbers in a geometric space.

Start with any number you like.

var c = new cf(1.618033988749895);

c.log();

console.log(c * 2);

The method log displays the A=int, B=scale.

The number data type operates as a regular number and allows all forums of math and arithmetic as a number type.

var c = new cf([2,1,2,3],[1,1,2,3]);

c.log(); console.log(c + "");

c.push(4,4);

c.log(); console.log(c + "");

var p = c.pop();

c.log(); console.log(c + "");

c.push( p );

c.log(); console.log(c + "");

console.log( "length = " + c.length + "");

We can build a number structurally and also push and pop parts and get the geometric length of the number.

When we change the parts in the number using push and pop it changes the value of the number.

var c = new cf(1.618033988749895);

c.log(); console.log(c + "");

for( var i = 1; i < c.length; i++ )
{
  c.adjA( i, i );
}

c.log(); console.log(c + "");

for( var i = 1; i < c.length; i++ )
{
  c.adjB( i, 1 );
}

c.log(); console.log(c + "");

The method adjA will adjust an integer part to what you want well equally adjusting the values in B.

The method adjB will adjust an scale factor to what you want well equally adjusting the values in A.

These methods can find different ways to compute the same number per part as the values in A or B take on a new pattern per part in ratio to each part.

var c = new cf(1.618033988749895);

While( c.combine() );

c.log(); console.log(c + "");

console.log( c.getFract() );

The combine method combines the last part to previous part. The combine method returns true as long as there are parts to combine together.

The method get fraction combines all the parts together as well then returns the smallest fraction.

var c = new cf(2.718281828459045);

c.log(); console.log(c + "");

while( c.combine() );

c.log(); console.log(c + "");

c.expand(); for( var i = 1; c.expand(i,i); i++ );

c.log(); console.log(c + "");

In order to use the expand method we must combine parts otherwise we can not expand the default A by B geometric sequence.

The default geometric expansion is:

A=max integer, and B=1 in scale.

We can leave input A and B undefined. If B is null or undefined then B is assumed to be 1 in value. If Input A is null or undefined then input A is assumed to be set to max value for next part.

The value for the next expanded integer part can be made smaller than the max value for the next integer part and B scale can be made as big as we like. The value for B scale makes the next integer part bigger in value.

The expand method returns false if the value can not be expanded with the set A=int input as the integer can not be bigger than max int. The B scale changes the size of the next integer part.

The expand method also returns false if the value can not be expanded any further.

var c = new cf(Math.PI);

c.log(); console.log(c + "");

while( c.combine() );

c.log(); console.log(c + "");

while( c.expand(c.int() - 1, 2) )
{
  console.log("Next int = " + c.int() + "");
}

c.log(); console.log(c + "");

The method int tells us what the max integer size is for the next part.

In the above example I subtracted the integer size by 1 per expansion.

If you add +1 to int then the expand method will return false and the expansion is not possible.

The geometric sequence of a number can be aligned into an regular pattern.

Doing this gives us a way to compute a number using a regular countable pattern for A to B in ratio.

function t(x) { return( 1 + x * 4 + x ** 2 * 4 ); }

var c = new cf(Math.PI);

c.log(); console.log(c + "");

while( c.combine() );

c.log(); console.log(c + "");

c.expand(); var i = 1; while( c.expand(6,t(i++)) );

c.log(); console.log(c + "");

The default geometric expansion of the number PI seams to have no pattern or is chaotic, but can be lined up into a regular pattern.

We can use the pattern to compute the number.

Every root of a number even square root and cube root all have regular computational patterns that can be used to compute the root of any number. You can solve the pattern to all roots if you like as a bit of fun.

Sine and cosine trigonometry functions also have regular patterns.

If you wish you can create an algorithm that finds the regular pattern to all numbers.

var c = new cf(Math.random());

c.log(); console.log(c.getFract() + " = " + c + "");

c.log(); console.log(c + "");

while( c.expand(c.int(), 1) );

c.log(); console.log(c + "");

You can also use the built in math random method in JavaScript to get a random number which you can convert to a regular pattern if you like for fun.

Analyzing the built in math random function in JavaScript is actually a lot of fun.

Solving number patterns.

There are a few rules to building an algorithm that solves the regular pattern to a number.

var c = new cf(NaN);

for( var i = 1; i < 12; c.push(i++,1) );

console.log("value = " + c + ""); c.log();

while( c.combine() ); c.log();

while( c.expand( c.int(), 1 ) ); c.log();

You can create a number one part at a time and combine it or expand it back.

No matter what we set the values for A=int it will expand back as long as the values for B=1.

If we change the value for B to say B=2 then the value for each A=int will expand back differently using default expansion B=1.

var c = new cf(NaN);

for( var i = 1; i < 12; c.push(i++,2) );

console.log("value = " + c + ""); c.log();

while( c.combine() ); c.log();

while( c.expand( c.int(), 1 ) ); c.log();

The pattern is very simple that created the number but when we expand it back we get a very chaotic looking set of values.

The only way to expand the number back the way it was is to expand using B=2.

var c = new cf(NaN);

for( var i = 1; i < 12; c.push(i++,2) );

console.log("value = " + c + ""); c.log();

while( c.combine() ); c.log();

while( c.expand( c.int(), 2 ) ); c.log();

Changing the value for B makes the next integer A expansion bigger.

This allows us to line up the next integer part as a regular continuous pattern.

If the value for B is set larger than the integer expansion in a value then the integer parts will be bigger even if we set the proper value for B while expanding.

var c = new cf(NaN);

for( var i = 1; i < 12; c.push(5,8), i++ );

console.log("value = " + c + ""); c.log();

while( c.combine() ); c.log();

c.expand( c.int(), 8 );

while( c.expand( c.int() - 1, 8 ) );

As you can see to expand this value back we need to subtract the maximum integer size by one even with the proper value set for B scale.

The integer value for A can be made smaller than the max integer value.

Creating an algorithm that rationalizes all numbers into their regular patterns means we must line up each integer with B. We then must also regularize the values for each max integer part.

var c = new cf(2.718281828459045);

console.log( c + ""); c.log();

while( c.combine() );

var dif=[0,0,0,0,0,0,0,0,0,0,0,0,0,0];
var scale=[1,1,2,3,4,5,6,7,8,9,10,11,12];

for( var i = 0; i < dif.length && c.expand( c.int() - dif[i], scale[i] ); i++ );

console.log( c + "" ); c.log();

In this example we raise the value of B and do not have to reduce the maximum integer parts to solve the pattern to the number.

This is because the value for scale gets larger or is equal to as we scale B to make the next integer part bigger or equal to.

Now we will move over to the number PI.

var c = new cf(Math.PI);

console.log( c + ""); c.log();

while( c.combine() );

var dif=[0,1,2,4,5,7,9,11,13,15,17,19];
var scale=[1,9,25,49,81,121,169,225,289,361,441];

for( var i = 0; i < dif.length && c.expand( c.int() - dif[i], scale[i] ); i++ );

console.log( c + "" ); c.log();

In the case of the number PI. As we raise the value for B to make the next integer part larger or equal to the previous we end up with the value for B not having to be raised in the next expansion to create a larger integer part.

This means we combine the last part back and add one to dif for the maximum integer difference and continue.

As we repeat this process we find the computational pattern for the number PI.

The results gives us the general continued calculation for the number PI.

There are faster ways to calculate alignment than combining the last part back and expanding it and making sure A and B are same or grater.

var c = new cf(2.718281828459045);

console.log(c + ""); c.log();

while( c.combine() );

while( c.expand( c.int(), Math.ceil( c.int() / c.re() ) ) );

console.log( c + "" ); c.log();

This code directly calculates the closest grater than or equal to expansion for each integer part.

We ask what is the next maximum integer part before expansion c.int(). The method c.re() tells us what the remainder is. Dividing the remainder into the next integer gives us what to set scale to make the next integer the same. We take this value and move it to its next whole number with Math.ceil. This finds the next closest expansion for each integer part.

If we subtract any scale value in B by one then the next integer part will be smaller than the previous integer.

It lacks one small thing. As one can see the value for B scale moves up and down and has to be regularized.

This eliminates us having to find the scale to line up the next equal or grater integer.

var c = new cf(2.718281828459045);

console.log(c + ""); c.log();

while( c.combine() );

while( c.expand( c.int(), Math.max( Math.ceil( c.int() / c.re() ), c.B() ) ) );

console.log( c + "" ); c.log();

This code does not let the value for scale drop bellow the current value for scale c.B().

This makes it so that scale is grater or equal to as we find what is the closest grater or equal to integer part.

This code can find the regular pattern to any square root.

For example the square root of 23 regularizes as.

A=4,5,152,152
B=4,4,112,112

The number 1.10100100010000 also regularized as.

A=1,9,9,9,99,99,99,999,999,999
B=1,9,9,9,99,99,99,999,999,999

This code also lacks the ability to reduce the integer parts which is necessary to simplify and line up some numbers.

var c = new cf(Math.PI);

console.log(c + ""); c.log();

while( c.combine() );

var dif = [0,1,0,0,0];

var i = 0, d = 0;

while( c.expand( d = c.int() - (dif[i++]||0), Math.max( Math.ceil( d / c.re(d) ), c.B() ) ) );

console.log( c + "" ); c.log();

This version of the code lets you adjust the integer parts.

This version gets us extremely close to the polynomial expansion of number PI.

The method c.re(int) tells us what the remainder is if we expand the number useing a smaller integer value. In our case we want it to give us the remainder for what we subtract the integer part by. Dividing the remainder into a number tells us what to set the value for scale to make the next integer our selected value. Using Math.ceil moves the scale value to the nearest integer.

However the algorithm is not yet complete. We still must include differences for B scale.

var c = new cf(Math.PI);

console.log(c + ""); c.log();

while( c.combine() );

var dif = [0,1,2,4,5,7,9,11,13];
var sca = [0,2,10,24,45,74,111,155];

var i = 0, d = 0;

while( c.expand( d = c.int() - (dif[i]||0), Math.max( Math.ceil( d / c.re(d) ) + (sca[i++]||0), c.B() ) ) );

console.log( c + "" ); c.log();

The alignments of A and B are as close as they can be made.

This eliminates a large amount of calculations to finding the expansion.

We can also do all these calculations directly on a number as the whole value of the number is the integer part and subtracting it to zero and dividing the number into one gives us the next whole integer part.

This allows us to compute everything we are already computing directly with a number.

function cf( n,ad,bd )
{
  this.a = []; this.b = []; this.length = 0;
  
  //Data type methods.
  
  this.valueOf = function()
  {
    for( var i = this.length - 1, v = 0; i >= 0; i-- )
    {
      if( i > 0 )
      {
        v = this.b[i-1] / (this.a[i] + v);
      }
      else { v += this.a[i]; }
    }
  
    return( v );
  };
  this.log = function() { console.log("A=" + this.a + ""); console.log("B=" + this.b + ""); };
  
  //Split the number apart in A=int>=int,B=scale>=scale.
  
  var int = re = b = a = Math.abs(n); while( b - this != 0 )
  {
    int = (a&-1)-(ad[this.length]||0);
    int = Math.max(this.a[this.length-1]||1,int); re=a-int;
    
    this.a[this.length] = int;
    this.b[this.length] = Math.ceil(int/(1/re));
    
    this.b[this.length] += bd[this.length] || 0;
    this.b[this.length] = Math.max( this.b[this.length-1]||1, this.b[this.length] )
    
    a=1/(re/this.b[this.length++]);
  }
};

var c = new cf(Math.PI,
[0,1,2,4,5,7,9,11,13],
[0,2,10,24,45,74,111,155]);

c.log();

The only thing left to the algorithm is subtracting the previous A and B and adding the difference for the odd few numbers.

The value for B can be adjusted as high as we like and the value for A can be shrunk down. As long as the next closest value for A is grater or equal and the value for B is less or equal to our added difference then we do not have to average A and B in difference to the next part.

This gives a fast way to line up and to fourmulate the polynomial expansion of a number.

Additionaly there are other ways to line up a number and computing it's parts.

var a = 72, b = 911;

var c = new cf(a/2 + Math.sqrt(a*a/4 + b));

console.log("Value = " + c + ""); c.log();

while( c.combine() ); c.log();

while( c.expand( a, b ) ); c.log();

This code uses the calculation
(A÷2) + √(A2÷4+B)
to create a number value.

This calculation creates a number in which all A and B are the same.

You can also use a column vector to compute the pattern directly for A and B as well.

https://gist.github.com/Recoskie/0733fdd835a6e134bfc929072bbcf67e

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment