## View: bcmod

 Function: Description: Get the modulus of the left_operand using modulus.
Code
```1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
```
```/*
Note: this function is a hack, and it only supports the use cases I require at
the moment, being: an arbitrary precision decimal left_operand and native precision positive decimal modulus (must fit in a native number, i.e. a double).
*/
function bcmod( left_operand, modulus ) {
// John was here!
// Key was here!
var i, d;
function split( operand ) {
var parts = operand.split( '.' );
var i = parts[ 0 ];
var d = '0.' + ( parts.length > 1 ? parts[ 1 ] : '0' );
return { "i": i, "d": d };
}
//modulus = Math.round( parseFloat( modulus ) );
modulus = parseFloat( modulus );
modulus = abs( modulus );
if ( modulus === 0 ) { return null; }
var take = 4;
var modulus_limit = Math.pow( 10, take );
if ( modulus >= modulus_limit  ) {
throw new Error( "Modulus cannot be " + modulus_limit + " or greater." );
}
var result = 0;
var r = split( left_operand );
i = r.i; d = r.d;
read_length = i.length < take ? i.length : ( take );
var result = i.substr( 0, take );
i = i.substr( take );
return result;
}
function round( value ) {
//console.log( "V:" + value );
//0.8999999999999997
//0.09999999999999984
//0.29999999999999993
//0.7999999999999998
//0.8999999999999999
//0.10000000000000009
//0.029999999999999985
var units = '0.0000000000000000';
function get_chars( s ) {
var result = [];
for ( var j = 0, jl = s.length; j < jl; j++ ) {
result.unshift( s.charAt( j ) );
}
return result;
}
value = value.toString();
var r = split( value );
var d_chars = get_chars( r.d.substring( 0, units.length ) );
//console.log( "D:" + d_chars.toString() );
var carry = 0;
for ( var ci = 0, cl = d_chars.length; ci < cl; ci++ ) {
var c = d_chars[ ci ];
if ( ! /^[0-9]\$/.test( c ) ) { break; }
if ( ci === 0 && cl >= units.length ) {
carry = Math.round( parseFloat( '0.' + c ) );
d_chars[ ci ] = '0';
}
else {
var v = parseInt( c ) + carry;
if ( v >= 10 ) {
carry = 1;
v -= 10;
}
else {
carry = 0;
}
d_chars[ ci ] = v.toString();
}
}
var result = ( parseInt( r.i ) + carry ).toString() +
array_reverse( d_chars.slice( 0, -1 ) ).join( '' ).replace( /[0.]*\$/, '' );
//console.log( "N:" + result );
return result;
}
do {
var n = parseInt( read() );
//console.log( result );
result = ( result * Math.pow( 10, read_length ) + n ) % modulus;
var temp = parseFloat( round( result ) );
//console.log( "R:" + result );
//console.log( "T:" + temp );
if ( ( temp - modulus ) >= 0 ) {
temp -= modulus;
//console.log( "T:" + temp );
result = temp;
}
}
while ( i.length > 0 );
result += parseFloat( d );
var test = result - modulus;
result = test < 0 ? result : test;
result = round( result );
//console.log( result );
//console.log();
return result;
}
```
Comment on bcmod version 521
Tests
```1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
```
```function bcmod_tests() {

// API reference: http://docs.jquery.com/QUnit
module( "bcmod" );

test( "bcmod", function() {

// some basic modulus cases:
equal( bcmod( '4', '2' ), '0', "bcmod( '4', '2' )" );
equal( bcmod( '2', '4' ), '2', "bcmod( '2', '4' )" );
equal( bcmod( '123456', '1000' ), '456', "bcmod( '123456', '1000' )" );
equal( bcmod( '12345', '1000' ), '345', "bcmod( '12345', '1000' )" );
equal( bcmod( '1234', '1000' ), '234', "bcmod( '1234', '1000' )" );
equal( bcmod( '123', '1000' ), '123', "bcmod( '123', '1000' )" );
equal( bcmod( '12', '1000' ), '12', "bcmod( '12', '1000' )" );
equal( bcmod( '1', '1000' ), '1', "bcmod( '1', '1000' )" );
equal( bcmod( '123456', '100' ), '56', "bcmod( '123456', '100' )" );
equal( bcmod( '12345', '100' ), '45', "bcmod( '12345', '100' )" );
equal( bcmod( '1234', '100' ), '34', "bcmod( '1234', '100' )" );
equal( bcmod( '123', '100' ), '23', "bcmod( '123', '100' )" );
equal( bcmod( '12', '100' ), '12', "bcmod( '12', '100' )" );
equal( bcmod( '1', '100' ), '1', "bcmod( '1', '100' )" );
equal( bcmod( '123456', '10' ), '6', "bcmod( '123456', '10' )" );
equal( bcmod( '12345', '10' ), '5', "bcmod( '12345', '10' )" );
equal( bcmod( '1234', '10' ), '4', "bcmod( '1234', '10' )" );
equal( bcmod( '123', '10' ), '3', "bcmod( '123', '10' )" );
equal( bcmod( '12', '10' ), '2', "bcmod( '12', '10' )" );
equal( bcmod( '1', '10' ), '1', "bcmod( '1', '10' )" );
equal( bcmod( '123456', '1' ), '0', "bcmod( '123456', '1' )" );
equal( bcmod( '12345', '1' ), '0', "bcmod( '12345', '1' )" );
equal( bcmod( '1234', '1' ), '0', "bcmod( '1234', '1' )" );
equal( bcmod( '123', '1' ), '0', "bcmod( '123', '1' )" );
equal( bcmod( '12', '1' ), '0', "bcmod( '12', '1' )" );
equal( bcmod( '1', '1' ), '0', "bcmod( '1', '1' )" );

// fractional modulus is now supported:
equal( bcmod( '10', '1.3' ), '0.9', "bcmod( '10', '1.3' )" );

// testing negative left_operand:
equal( bcmod( '-11', '2' ), '-1', "bcmod( '-11', '2' )" );

// testing zero modulus and fractional modulus:
equal( bcmod( '3', '0' ), null, "bcmod( '3', '0' )" );
equal( bcmod( '3', '0.0' ), null, "bcmod( '3', '0.0' )" );
bcmod_test( 3, 0.1, 0, 0.09999999999999984 );
bcmod_test( 3, 0.11, 0.03, 0.029999999999999985 );
bcmod_test( 3, 0.111, 0.003, 0.002999999999999961 );
equal( bcmod( '3', '0.5' ), '0', "bcmod( '3', '0.5' )" );
equal( bcmod( '3', '0.9' ), '0.3', "bcmod( '3', '0.9' )" );
equal( bcmod( '3', '1' ), '0', "bcmod( '3', '1' )" );
equal( bcmod( '3', '1.0' ), '0', "bcmod( '3', '1.0' )" );
equal( bcmod( '3', '1.1' ), '0.8', "bcmod( '3', '1.1' )" );
equal( bcmod( '3', '1.5' ), '0', "bcmod( '3', '1.5' )" );
equal( bcmod( '3', '1.9' ), '1.1', "bcmod( '3', '1.9' )" );
equal( bcmod( '3', '2' ), '1', "bcmod( '3', '2' )" );
equal( bcmod( '3', '2.0' ), '1', "bcmod( '3', '2.0' )" );
equal( bcmod( '3', '2.1' ), '0.9', "bcmod( '3', '2.1' )" );
equal( bcmod( '3', '2.5' ), '0.5', "bcmod( '3', '2.5' )" );
equal( bcmod( '3', '2.9' ), '0.1', "bcmod( '3', '2.9' )" );
equal( bcmod( '3', '3' ), '0', "bcmod( '3', '3' )" );

ok( true, "all pass" );

} );

}

function bcmod_test( left_operand, modulus, expect, broken_js ) {
if ( typeof broken_js === "undefined" ) { broken_js = expect; }
equal( left_operand % modulus, broken_js, left_operand + " % " + modulus );
equal(
bcmod( left_operand.toString(), modulus.toString() ),
expect.toString(),
"bcmod( '" + left_operand + "', '" + modulus + "' )"
);
}
```
Comment on bcmod version 44 tests
Benchmark
```1
2
3
4
5
6
7
8
```
```function bcmod_benchmark() {

for ( var i = 0; i < 1000; i++ ) {

var result = bcmod( '123456', i.toString() );

}
}
```
[top]