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