mirror of
https://github.com/Michaelangel007/apple2_russian_peasant_multiplication.git
synced 2025-01-02 15:29:22 +00:00
Object Orientated Programming Javascript
This commit is contained in:
parent
5af3b5b4e5
commit
2dbc120e02
273
rpm_oop.js
Normal file
273
rpm_oop.js
Normal file
@ -0,0 +1,273 @@
|
||||
/* Object Orientated Version */
|
||||
"use strict"; // Idiotic JavaScript design requires kludge for type safety
|
||||
|
||||
/*
|
||||
To run from the command line:
|
||||
|
||||
node rpm_oop [-v] [# [#]]
|
||||
|
||||
Legend:
|
||||
[] Paramater is optional
|
||||
-v Turn on verbose output
|
||||
# Number
|
||||
|
||||
Requires: node.js
|
||||
*/
|
||||
|
||||
var LOG = 0; // Verbose logging
|
||||
var BASE = 10;
|
||||
|
||||
var defaultA = "86";
|
||||
var defaultB = "57";
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// BCD Type
|
||||
var BCD = function( width, text )
|
||||
{
|
||||
this.array = new Array( width );
|
||||
|
||||
if (text !== undefined)
|
||||
this.Fill( text );
|
||||
}
|
||||
|
||||
BCD.prototype =
|
||||
{
|
||||
constructor: BCD,
|
||||
|
||||
/** lhs += rhs
|
||||
*/
|
||||
// ========================================================================
|
||||
Add2: function( rhs )
|
||||
{
|
||||
var n = this.array.length;
|
||||
var carry = 0;
|
||||
var sum = 0;
|
||||
|
||||
for( var i = 0; i < n; ++i )
|
||||
{
|
||||
sum = this.array[i] + rhs.array[i] + carry;
|
||||
carry = (sum >= BASE) | 0;
|
||||
|
||||
if (sum >= BASE)
|
||||
sum -= BASE;
|
||||
|
||||
this.array[ i ] = sum;
|
||||
}
|
||||
},
|
||||
|
||||
/** Print array BCD digits
|
||||
* Stored little endian: LSB[0] MSB[n]
|
||||
*/
|
||||
// ========================================================================
|
||||
Dump: function( prefix )
|
||||
{
|
||||
var n = this.array.length;
|
||||
var text = prefix ? prefix : "";
|
||||
|
||||
for( var i = n - 1; i >= 0; --i )
|
||||
text += this.array[ i ];
|
||||
|
||||
console.log( text );
|
||||
},
|
||||
|
||||
/** Convert string to BCD array, aka, atoi()
|
||||
Remaining digits are zero filled
|
||||
* @param {Number[]} array
|
||||
* @param {String} text
|
||||
*/
|
||||
// ========================================================================
|
||||
Fill: function( text )
|
||||
{
|
||||
var i;
|
||||
var n = this.array.length;
|
||||
var m = text.length;
|
||||
var v;
|
||||
|
||||
// Extra error checking would verify m > n
|
||||
|
||||
// Set all digits from string -- set in reverse order
|
||||
for( i = 0; i < m; ++i )
|
||||
this.array[ (m-1) - i ] = text.charCodeAt( i ) - 48;
|
||||
|
||||
// Set remaining digits to zero
|
||||
for( ; i < n; ++i )
|
||||
this.array[ i ] = 0;
|
||||
},
|
||||
|
||||
// ========================================================================
|
||||
isOdd: function()
|
||||
{
|
||||
return this.array[0] & 1 ? true : false;
|
||||
},
|
||||
|
||||
// ========================================================================
|
||||
isZero: function( )
|
||||
{
|
||||
var i;
|
||||
var n = this.array.length;
|
||||
var zero = true; // default to all zeroes until we find otherwise
|
||||
|
||||
for( i = 0; i < n; ++i )
|
||||
zero &= (this.array[i] == 0);
|
||||
|
||||
return zero;
|
||||
},
|
||||
|
||||
// Print array digits in reverse
|
||||
// ========================================================================
|
||||
Print: function( prefix )
|
||||
{
|
||||
var i;
|
||||
var n = this.array.length;
|
||||
var text = prefix ? prefix : "";
|
||||
var zero = true; // assume leading zero -> skip digit
|
||||
|
||||
for( i = n - 1; i >= 0; --i )
|
||||
{
|
||||
zero &= (this.array[ i ] == 0);
|
||||
if( !zero )
|
||||
text += this.array[ i ];
|
||||
}
|
||||
|
||||
console.log( text );
|
||||
},
|
||||
|
||||
// ========================================================================
|
||||
Shl1: function()
|
||||
{
|
||||
var i;
|
||||
var n = this.array.length;
|
||||
var carry = 0;
|
||||
var sum = 0;
|
||||
|
||||
for( i = 0; i < n; ++i )
|
||||
{
|
||||
sum = this.array[ i ]*2 + carry;
|
||||
carry = (sum >= BASE) | 0;
|
||||
|
||||
if (sum >= BASE)
|
||||
sum -= BASE;
|
||||
|
||||
this.array[ i ] = sum;
|
||||
}
|
||||
},
|
||||
|
||||
// ========================================================================
|
||||
Shr1: function()
|
||||
{
|
||||
var i;
|
||||
var n = this.array.length;
|
||||
var carry = 0;
|
||||
var q = 0;
|
||||
var div = 0;
|
||||
var rem = 0;
|
||||
|
||||
for( i = n-1; i >= 0; --i )
|
||||
{
|
||||
div = this.array[ i ] + carry; // dividend
|
||||
q = (div / 2) | 0; // 2 is divisor
|
||||
this.array[i] = q;
|
||||
rem = div - q*2; // 2 is divisor
|
||||
carry = rem * BASE;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** Russian Peasant Multiplication with native integers
|
||||
* @param {Number} a
|
||||
* @param {Number} b
|
||||
*/
|
||||
// ========================================================================
|
||||
function RPM( x, y )
|
||||
{
|
||||
var a = x; // Javascript has no native unsigned 32-bit nor 64-bit integers
|
||||
var b = y; // ctypes.UInt64() is only Firefox "extension"
|
||||
var sum = 0;
|
||||
|
||||
while( b )
|
||||
{
|
||||
if (b & 1)
|
||||
sum += a;
|
||||
|
||||
if(LOG) console.log( "A: " + a + ", B: " + b + ", Sum: " + sum );
|
||||
if (a < 0)
|
||||
return console.log( "ERROR: 31-bit integer overflow. Number too large after shifting left: " + x );
|
||||
|
||||
a <<= 1;
|
||||
b >>= 1;
|
||||
}
|
||||
|
||||
console.log( x + " x " + y + " = " + sum );
|
||||
}
|
||||
|
||||
|
||||
/** Russian Peasant Multiplication with strings
|
||||
* @param {String} a
|
||||
* @param {String} b
|
||||
*/
|
||||
// ========================================================================
|
||||
function RPM_String( a, b )
|
||||
{
|
||||
var n = a.length; // i.e. 32-bit, e.g. 999
|
||||
var m = b.length; // i.e. 32-bit e.g. 999
|
||||
var s = n + m ; // i.e 32-bit * 32b-bit = 64-bit e.g. 998001
|
||||
|
||||
var digitsA = new BCD( s, a );
|
||||
var digitsB = new BCD( s, b );
|
||||
var digitsS = new BCD( s, "0" );
|
||||
|
||||
while( true )
|
||||
{
|
||||
var done = digitsB.isZero();
|
||||
if( done )
|
||||
break;
|
||||
|
||||
var odd = digitsB.isOdd();
|
||||
if( odd )
|
||||
digitsS.Add2( digitsA ); // S += A
|
||||
|
||||
if(LOG) digitsA.Dump( " A = " );
|
||||
digitsA.Shl1();
|
||||
if(LOG) digitsA.Dump( " A << " );
|
||||
if(LOG) digitsB.Dump( " B = " );
|
||||
digitsB.Shr1();
|
||||
if(LOG) digitsB.Dump( " B >> " );
|
||||
if(LOG) digitsS.Dump( "Sum: " );
|
||||
}
|
||||
digitsS.Print();
|
||||
}
|
||||
|
||||
|
||||
// ========================================================================
|
||||
function main()
|
||||
{
|
||||
var args = process.argv.slice( process.execArgv.length + 2 );
|
||||
var param = 0;
|
||||
|
||||
if (args[0] === '-v')
|
||||
{
|
||||
LOG = 1;
|
||||
param++; // skip switches to first paramater
|
||||
}
|
||||
|
||||
var params = [];
|
||||
params.push( (args[param+0] === undefined) ? defaultA : args[param+0] );
|
||||
params.push( (args[param+1] === undefined) ? defaultB : args[param+1] );
|
||||
|
||||
console.log( "= Integer = " );
|
||||
RPM( params[0] | 0, params[1] | 0);
|
||||
console.log( "\n" );
|
||||
|
||||
console.log( "= BCD String =" );
|
||||
RPM_String( params[0], params[1] );
|
||||
console.log( "\n" );
|
||||
}
|
||||
|
||||
main();
|
||||
|
Loading…
Reference in New Issue
Block a user