Posting results and work in process for just the add function.  Sample code 
fully goes from Jxints to BN garbage collected objects and back to a Jxint 
result.  library attached at bottom.
Uses a class based approach to facilitate memory management/cleanup, and 
inherritance for secure contexts, and managed code.  Btw, one of the supposed 
benefits of BN over GMP is that it is more memory efficient

fibtest =: 3 : 0 
  'fibCtx' coassign  '' conew 'bnctx' 
  (codestroy__fibCtx@:(''"_) ] ,.@('toX a:'&inl)) MANAGED__fibCtx[(1 2 
0{][BNadd__fibCtx)^:y  '<I'inl newM__fibCtx 1 1 1 
)

starts getting faster around 6000 iterations
timespacex 'fibtest 10000' 
0.0298173 61312 
timespacex '({: , +/)^:(10000) 1 1x' 
0.0367766 44928 

timespacex 'fibtest 50000' 
0.199689 157952 
timespacex '({: , +/)^:(50000) 1 1x' 
0.765411 167808 

timespacex '({: , +/)^:(80000) 1 1x' 
1.79307 331648 
timespacex 'fibtest 80000' 
0.370815 289024 



As a stress test, sums with managed memory context
sum =: 3 : 0 
 acc =. newM {: y 
 toX__acc (}: y)  4 : 'y[ BNfree a [ BNadd I__y;I__y;a =. newI x' reduce acc 
)


timespacex '''sum'' withtemp_bnctx_ (0 ". ''x'',~ 990 # ''123'') + i.4530' 
0.91709 7.73599e7 
timespacex '''sum'' withtemp_bnctx_  i.4530' 
0.227081 979072


timespacex '+/ (0 ". ''x'',~ 990 # ''123'') + i.4530' 
0.0640345 3.80096e7 

timespacex '+/ i.4530x' 
0.00184256 747776 


with manual context, the extra time saved is mostly large int copies into code

C =. '' conew 'bnctx'
timespacex 'sum__C (0 ". ''x'',~ 990 # ''123'') + i.4530' 
0.813071 3.88996e7 

timespacex 'sum__C  i.4530' 
0.243128 902016 


an oop version is slow though, though almost tacit.  addX function adds a J int 
to a BN. (stores in same BN) add stores in itself but needs a BN argument.  The 
first function is useful for temp BN's as it autodestroys the number.

sum3 =: 3 : 0 
acc =. newM {: y 
toX__acc (}: y)  addX__acc@[ reduce acc 
)


timespacex 'sum3__C  i.4530' 
0.679583 896896 
codestroy__C '' 
timespacex '''sum3'' withtemp_bnctx_  i.4530' NB. memory managed version
0.688436 973952 


A version that looks cleaner but uses more memory as it has to copy the pointer 
result for each element:

sum4 =: 3 : 0 
 acc =. newM {. y 
 toX__acc addX__acc"0 }.y 
)
timespacex 'sum4__C  i.4530' 
0.688726 3.38406e6



So, its fast when it doesn't need to create and destroy many BNs.  I'm sure 
there are plenty of other areas where a useful speedup is obtained.  I'll be 
adding more than add function.

The OOP interface is completely bypassable, but is convenient.  


require 'dll' 
cocurrent 'ssl' 
sslp =: IFWIN pick '';'D:\OpenSSL-Win64\bin\' 
sslp =: IFWIN pick ''; '/',~ jpath '~bin'  NB. with J802.  cut this line if you 
wish to point to downloaded folder 
NB. OPENSSL =: jpath '~system/ssleay32.dll ' 
NB.OPENSSL =: sslp , '\ssleay32.dll ' 
OPENSSL =: sslp , (IFIOS + (;: 'Win Linux Android Darwin') i. <UNAME_z_) pick 
'libeay32.dll '; (2 $ <'libssl.so.1.0.0 '),  (2 $ <'/usr/lib/libssl.dylib ') 
NB.OPENSSL =: sslp , (IFIOS + (;: 'Win Linux Android Darwin') i. <UNAME_z_) 
pick 'libeay32.dll '; (2 $ <'libssl.so ');  (2 $ <'libssl.0.9.8.dylib ') 

SSLE =: sslp , '\openssl' 
ssl =: 1 : '(OPENSSL , m)&cd' 

BNctxnew =: ' BN_CTX_new + x' ssl 
BNnew =: ' BN_new >+ x' ssl  NB. probably don't use... unamanaged memory 
version. 
BNmul =: ' BN_mul + i *x *x *x *x' ssl 
NB. BIGNUM *BN_bin2bn(const unsigned char *s,int len,BIGNUM *ret) 
BN2bn =: ' BN_bin2bn + *x *c l *x' ssl 
NB. int BN_bn2bin(const BIGNUM *a, unsigned char *to) 
BN2bin =: ' BN_bn2bin + i x *c' ssl 
BN_bn2hex=: ' BN_bn2hex + c x ' ssl NB.char * BN_bn2hex(const BIGNUM *a); 
BN_hex2bn =:  ' BN_hex2bn + i *x *c' ssl  NB.(BIGNUM **a, const char *str); 
BNnum_bytes=: ' BN_num_bytes  i *i' ssl  NB. doest work as its macro? 
NB. int BN_num_bits(const BIGNUM *a) 
BN_num_bits=: ' BN_num_bits + i x' ssl 
num_bytes =: 0.125 <.@* BN_num_bits 
BN2dec=: ' BN_bn2dec >+  x x' ssl NB. char *BN_bn2dec(const BIGNUM *num) 
dec2BN=: ' BN_dec2bn > + i *x *c' ssl NB. int BN_dec2bn(BIGNUM **num, const 
char *str) 
NB. BN_print(BIO *fp, const BIGNUM *a); 
BNfree =:  ' BN_free + n x' ssl NB.BN_free(bn: pBIGNUM); cdecl 
BNclear_free=:  ' BN_clear_free + n x' ssl NB.BN_free(bn: pBIGNUM); cdecl 
BNclear =:  ' BN_clear + n x' ssl NB.BN_free(bn: pBIGNUM); cdecl 
BNCTX_free=: 'BN_CTX_free+ n x' ssl  NB. void BN_CTX_free(BN_CTX *c); 
BNCTX_start =: 'BN_CTX_start+ n x' ssl  NB.void BN_CTX_start(BN_CTX *ctx); 
BNCTX_end =: 'BN_CTX_end + n x' ssl 
BNdup =:  ' BN_dup > + x x' ssl NB.BIGNUM *BN_dup(const BIGNUM *from); 
BNCTX_get =:  ' BN_CTX_get > + x x' ssl NB. BIGNUM *BN_CTX_get(BN_CTX *ctx); 
BNcopy =:  ' BN_copy > + x x x' ssl NB.BIGNUM *BN_copy(BIGNUM *to, const BIGNUM 
*from); 
BNswap =:  ' BN_swap > + x x x' ssl 
BNadd =:  ' BN_add > + i x x x' ssl   NB.int BN_add(BIGNUM *r, const BIGNUM *a, 
const BIGNUM *b) 

NB. coclass 'OOP' 
NB. OOP_z_ =: <'OOP' 
NB. Cbase =: <'base' 
NB. coclass_z_ =: 18!:4@boxxopen@:[ ((('_OOP_' ,~ 'C' ,  ]) assign boxopen)^:(0 
= L.)) 
NB. coclass =: 18!:4@boxxopen@:[ ((('_OOP_' ,~  'C' ,  ]) assign (][ 
coerase)@:boxopen)^:(0 = L.)) 
cocurrent 'z' 
pD_z_ =: 1!:2&2 
cders_z_ =: cder ; cderx 
coself_z_ =: coname@(''"_) 
codestroy =: (coerase@coname@(''"_) ] destroy :: ])"0 
coinsert=: 3 : 0 
n=. ;: :: ] y 
p=. ; (, 18!:2) @ boxopen each n 
p=. ~. ( 18!:2 coname''), p 
(p /: p = <,'z') 18!:2 coname'' 
) 
inl_z_ =: (cocurrent@] ".@] [)"1 0 
inlC_z_ =: 2 : 0 
(([: <^:(0=L.) v"_) inl~ m , ' ', lr@:]) :  (([: <^:(0=L.) v"_) inl~ (lr@:[), ' 
' ,m , ' ', lr@:] ) 
) 
inlA_z_ =: 1 : 'u inlC  (18!:5 '''')' 
coassign_z_ =: 4 : 0 NB.y is object or list of objects. x is string name 
try. (coerase  ] 'destroy a:'&inl :: ]) x~ catch. end. 
(x) =: y 
) 
lr_z_ =: 3 : '5!:5 < ''y''' 
loc =: (,&'_'@[ ,&'_'@, ":@>@])"1 0 
locs =: 1 : 'm loc 18!:5 ''''' 
eval_z_ =: 1 : ' a: 1 :  m' 
reduce =: 1 : '<"_1@[ ([: u &.>/(>@:) ,) <@:]' 

coclass 'bnctx' 
MANAGED =: i. 0 0 
coinsert 'ssl' 
create =: 3 : 0 
CTX =: BNctxnew 0{.a. 
) 
withtemp =: 1 : 0  NB.creates new ctx that will execute u  then destroy itself 
u incontext withtemp 
'tmpCtx' coassign a: conew 'bnctx' 
NB.('[: (] [', ' destroy' locs__tmpCtx , ') ' , u lrA inlA__tmpCtx lrA )eval 
('[: (] [', ' destroy' locs__tmpCtx , ') ' , m inlA__tmpCtx lrA)eval 
) 
NB. FUNCTIONS ON BNs 
new =: 3 : 'a [ (''coinsert '', lr coself a:) inl a=.''bn'' conew"0 1~ y' 
newI =: 3 : 'create_bn_ y'  NB. need to manually release, but no object at all. 
newM =: 3 : 'a [ (''coinsert '', lr coself a:) inl a [ MANAGED =: MANAGED , 
a=.''bn'' conew"0 1~ y'  NB. appends BN in public list. autodestroyed on 
destroy this. 

dup =: 3 : 'a [ coinsert__a coself a: [  a =. dup__y'  NB. just 1 BN. not list. 
kill=: 3 : 'codestroy__y a:' NB. just 1 BN. 
NB. incontext =: 1 : 0  NB. u is dyad, has access to faster autoreleased gets 
instead of new. 
NB. ('BNCTX_end_ssl_@(CTX"_) ] [(' , m , ' :: ((cders ; 13!:11 ; 13!:12 
)@:(''''"_))) ][ BNCTX_start_ssl_@(CTX"_)') eval 
NB. ) 
get =: 3 : 'BNCTX_get@(CTX"_)'  NB. not object and not managed. 
newGM =: 3 : 'a [ MANAGED =: MANAGED , a=. new_bnget_"_ 0 y' NB. requires an 
incontext adverb surrounding call. 

sum2 =: 3 : 0 NB. slow and mem hog demo 
acc =. newM {: y 
toX__acc (}: y)  ( [: add__acc newM@[) reduce acc 
) 

sum =: 3 : 0 
acc =. newM {: y 
toX__acc (}: y)  4 : 'y[ BNfree a [ BNadd I__y;I__y;a =. newI x' reduce acc 
) 
sum3 =: 3 : 0 
acc =. newM {: y 
toX__acc (}: y)  (][ [: addX__acc [) reduce acc 
) 
clearmanaged =: 'MANAGED'&coassign 
destroy =: 3 :  'clearmanaged i.0 0 [ BNCTX_free :: ] CTX '  NB. CTX_free may 
not exist 

cocurrent 'bn' 
coinsert 'ssl' 
create =: 3 : 0 
I =:  BNnew 0{.a. 
NB.pD Ia =:  15!:6 <'I' 
initlen =. dec2BN (,I);(": y) 
assert. initlen > 0 
I 
) 

todec =: 3 : 0 
o =. BN2dec  I 
memr o,0 _1 2 
) 
toX =: 0 ". 'x' ,~ todec 
Dbn_z_ =: 3 : 'todec__y a:' 
Xbn_z_ =: 3 : 'toX__y a:' 
dup =: 3 : 0 
b =. conew 'bn' 
I__b =: BNdup I 
b 
) 
add =: 3 : 0 NB. adds self to y (bn object) 
i =.BNadd I;I;I__y 
coself a: 
) 
addX =: 3 : 0 
a =. newI y 
i =.BNadd I;I;a 
BNfree a 
coself a: 
) 
destroy =: 3 : 0 
BNfree I 
1 
) 


coclass 'base' 
NB. (][BNadd__C)^:1000 I__a;I__a;I__a 
NB. FIBONACI full cycle 
fibtest =: 3 : 0 
'fibCtx' coassign  '' conew 'bnctx' 
(codestroy__fibCtx@:(''"_) ] ,.@('toX a:'&inl)) MANAGED__fibCtx[(1 2 
0{][BNadd__fibCtx)^:y  '<I'inl newM__fibCtx 1 1 1 
) 
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to