![]() |
How to init an array in Posix bc?
Posix bc allows array variables and parameters, but I have only found one-element-at-a-time init to work, e.g. to declare and init a 2-element array 'a':
a[2]; a[0]=1; a[1]=2; (Interestingly, adding a[2]=3 does not give an error and the resulting 3 element value are correct, so possibly bc auto-expands the array size in such cases, but I wouldn't count on this happening, i.e. best to init only within the declared array index range.) Especially for many-element arrays it would be really nice to be able to combine declare/init in a fashion akin to C, e.g. 'a[2] = {1,2}', but I have found no syntax for the initializers which works, and websearch turns up only parroted manpages, none of which discuss array-init. |
[QUOTE=ewmayer;469427]Posix bc allows array variables and parameters, but I have only found one-element-at-a-time init to work, e.g. to declare and init a 2-element array 'a':
a[2]; a[0]=1; a[1]=2; (Interestingly, adding a[2]=3 does not give an error and the resulting 3 element value are correct, so possibly bc auto-expands the array size in such cases, but I wouldn't count on this happening, i.e. best to init only within the declared array index range.) Especially for many-element arrays it would be really nice to be able to combine declare/init in a fashion akin to C, e.g. 'a[2] = {1,2}', but I have found no syntax for the initializers which works, and websearch turns up only parroted manpages, none of which discuss array-init.[/QUOTE] [url]https://web.archive.org/web/20090501204511/http://manpages.ubuntu.com/manpages/jaunty/en/man1/bc.1posix.html[/url] is the best I could find. |
[QUOTE=ewmayer;469427]Posix bc allows array variables and parameters, but I have only found one-element-at-a-time init to work, e.g. to declare and init a 2-element array 'a':
a[2]; a[0]=1; a[1]=2; (Interestingly, adding a[2]=3 does not give an error and the resulting 3 element value are correct, so possibly bc auto-expands the array size in such cases, but I wouldn't count on this happening, i.e. best to init only within the declared array index range.) Especially for many-element arrays it would be really nice to be able to combine declare/init in a fashion akin to C, e.g. 'a[2] = {1,2}', but I have found no syntax for the initializers which works, and websearch turns up only parroted manpages, none of which discuss array-init.[/QUOTE] It can't be done. Your first use of [c]a[2];[/c] returns [c]0[/c], as would the uninitialized [c]a[100];[/c]. |
GNU bc has an extension to allow passing arrays using "call by variable".
It looks like zero( *a[], n ) { for( i = 0; i < n; i++ ) a[i] = 0; } This is from reading the YACC grammar. I have not tried it. |
[QUOTE=paulunderwood;469461]It can't be done.
Your first use of [c]a[2];[/c] returns [c]0[/c], as would the uninitialized [c]a[100];[/c].[/QUOTE] For the 2-element-dimensioned array example I gave a[2] returns 0 before I init it, but afterward the value is preserved perfectly fine, at least in my version of bc: [code] My-MacBook:src ewmayer$ bc bc 1.06 Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc. This is free software with ABSOLUTELY NO WARRANTY. For details type `warranty'. a[2]; a[0]=1; a[1]=2; 0 <*** ewm: '0' here is return value of array-declaration statement *** a[2] 0 <*** Out-of-range element prior to initing it a[2]=3 a[2] 3 a[0]*a[2] 3 a[1]*a[2] 6 a[2]*a[2] 9[/code] Brian, I saw the passing-array-argument stuff, but that does not help with the init issue ... as Paul notes, it appears bc simply was not et up to allow convenience of inits. Similarly, one cannot declare an automatic variable in a bc function and init said variable in the same declaration statement - the init must come via separate statement after the declaration. |
[QUOTE=ewmayer;469546]For the 2-element-dimensioned array example I gave a[2] returns 0 before I init it, but afterward the value is preserved perfectly fine, at least in my version of bc:[/QUOTE]
You are still thinking "a[2]" as a declaration, while paul is saying that it is evaluating the third element of a[]. What happens if you omit your "declaration" a[2] altogether? Will it still work the same? |
[CODE]bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc. This is free software with ABSOLUTELY NO WARRANTY. For details type `warranty'. a[0]=1; a[1]=2; a[2] 0 a[2]=3 a[2] 3 a[0]*a[2] 3 a[1]*a[2] 6 a[2]*a[2] 9 [/CODE] Basically, you can think of all possible arrays pre-existing up to the internally set length and that they are all filled with zeroes, until you set a value to an element. In other words, you do not need to declare/dimension an array and undefined/unassigned array elements will return 0. |
Not directly related - except in the sense that the array-init question came up while I was doing early prototyping - but a not-terribly-optimized but decently functional bc-based small-p sieve code follows:
[code]/* returns 1 if p is a base-z Fermat pseudoprime, 0 otherwise. */ define pprimef(p,base) { auto n,y,z,flag y = 1; n = p-1; z = base; while(n) { flag = n%2; n /= 2; if(flag) y = (y*z)%p; z = (z*z)%p; if(!z) return(0); } return(y==1); } define isprp(p) { if(p == 2) return(1); if(p%2 == 0) return(0); /* Must only use inputs > the largest pprimef-base used below ... better, use that 341 is the smallest base-2 Fermat-pseudoprime: */ if(p <= 341) { return(pprimef(p,2)) } return(pprimef(p,2) && pprimef(p,3) && pprimef(p,5) && pprimef(p,7) && pprimef(p,11) && pprimef(p,13)); } define trailz(n) { auto i i = 0 while(n && (n%2 == 0)) { i += 1; n /= 2; } return(i) } define bits(n) { auto i; i = 0; while(n) { n /= 2; i += 1; } return(i) } define reverse(n,nbits) { auto tmp; tmp = 0; while(nbits) { tmp = 2*tmp + (n % 2); n /= 2; nbits -= 1; } return(tmp); } define abs(n) { if(n < 0) return(-n); return(n); } /* Find all prime factors of n which are <= max: */ define trialdiv(n,max) { auto i,p,ndiv if(max < 2) return(0); /* Only allow positive small-prime divisors */ if(abs(n) < 2) return(0); ndiv = n; i = trailz(ndiv); if(i) { print "Input ",n," has a small factor: 2^",i,"\n"; ndiv /= 2^i; } /* Now loop over odd primes <= max: */ p = 3; while(p <= max && p <= sqrt(ndiv)) { i = 0; while(ndiv%p == 0) { i++; ndiv/= p; } if(i) { print p^i*ndiv," has a small factor: ",p,"^",i,"\n"; if(isprp(ndiv)) { print "Remaining cofactor ",ndiv," is prime.\n"; break; } } /* find next-larger prime (actually, base-2 Fermat-PRP is fine in this context): */ while(1) { p += 2; if(pprimef(p,2)) { break; } } } return(0); }[/code] I have a bunch of such utils which I plan to port to bc over time, because I am sick of the hassle of finding/building versions of Pari/GP and GMP on my several-years-behind-the-latest version of OS X (FYI, I have good reasons not to 'upgrade'), and I usually don't need it to be super fast, I just need it to !$&$@ work. Had Pari/GP (I think v2.5-something) installed and working on my old Mac hard drive which finally gave up the ghost last month, had such a devil of a time over the weekend trying to find a currently-available version of Pari/GP which will run on my reconstructed system (OS X 10.7) that I was led to consider rolling my own basic stuff in bc, because if I have a Posix-style OS, I know bc will work, even if it's not great. Now, something like a basic ECM implementation in bc to extend my factoring capability beyond TF - that might be an interesting side project for the coming year. |
[QUOTE=ewmayer;469605]Not directly related - except in the sense that the array-init question came up while I was doing early prototyping - but a not-terribly-optimized but decently functional bc-based small-p sieve code follows:
[code]/* returns 1 if p is a base-z Fermat pseudoprime, 0 otherwise. */ define pprimef(p,base) { auto n,y,z,flag y = 1; n = p-1; z = base; while(n) { flag = n%2; n /= 2; if(flag) y = (y*z)%p; z = (z*z)%p; if(!z) return(0); } return(y==1); } define isprp(p) { if(p == 2) return(1); if(p%2 == 0) return(0); /* Must only use inputs > the largest pprimef-base used below ... better, use that 341 is the smallest base-2 Fermat-pseudoprime: */ if(p <= 341) { return(pprimef(p,2)) } return(pprimef(p,2) && pprimef(p,3) && pprimef(p,5) && pprimef(p,7) && pprimef(p,11) && pprimef(p,13)); } define trailz(n) { auto i i = 0 while(n && (n%2 == 0)) { i += 1; n /= 2; } return(i) } define bits(n) { auto i; i = 0; while(n) { n /= 2; i += 1; } return(i) } define reverse(n,nbits) { auto tmp; tmp = 0; while(nbits) { tmp = 2*tmp + (n % 2); n /= 2; nbits -= 1; } return(tmp); } define abs(n) { if(n < 0) return(-n); return(n); } /* Find all prime factors of n which are <= max: */ define trialdiv(n,max) { auto i,p,ndiv if(max < 2) return(0); /* Only allow positive small-prime divisors */ if(abs(n) < 2) return(0); ndiv = n; i = trailz(ndiv); if(i) { print "Input ",n," has a small factor: 2^",i,"\n"; ndiv /= 2^i; } /* Now loop over odd primes <= max: */ p = 3; while(p <= max && p <= sqrt(ndiv)) { i = 0; while(ndiv%p == 0) { i++; ndiv/= p; } if(i) { print p^i*ndiv," has a small factor: ",p,"^",i,"\n"; if(isprp(ndiv)) { print "Remaining cofactor ",ndiv," is prime.\n"; break; } } /* find next-larger prime (actually, base-2 Fermat-PRP is fine in this context): */ while(1) { p += 2; if(pprimef(p,2)) { break; } } } return(0); }[/code] I have a bunch of such utils which I plan to port to bc over time, because I am sick of the hassle of finding/building versions of Pari/GP and GMP on my several-years-behind-the-latest version of OS X (FYI, I have good reasons not to 'upgrade'), and I usually don't need it to be super fast, I just need it to !$&$@ work. Had Pari/GP (I think v2.5-something) installed and working on my old Mac hard drive which finally gave up the ghost last month, had such a devil of a time over the weekend trying to find a currently-available version of Pari/GP which will run on my reconstructed system (OS X 10.7) that I was led to consider rolling my own basic stuff in bc, because if I have a Posix-style OS, I know bc will work, even if it's not great. Now, something like a basic ECM implementation in bc to extend my factoring capability beyond TF - that might be an interesting side project for the coming year.[/QUOTE] does [url]http://pari.math.u-bordeaux.fr/gp.html[/url] not work ? |
[QUOTE=science_man_88;469606]does [url]http://pari.math.u-bordeaux.fr/gp.html[/url] not work ?[/QUOTE]
Didn't know there was a browser option, but in any case I don't want to have to have an internet pipe open. (I wonder if one could 'save the webpage' and have one's browser store all the underlying code locally - feel free to play around with this.) I wonder - given essentially the same level of underlying code optimization - which would be faster, pari-via-browser or bc-run-locally-based multiprecision? UPDATE: Moot in my case - tried a simple 'factor' job of a 64-bit composite in the Pari/GP web app ... first nothing. Enabled JS for the website, that caused something to start loading, but completely locked up my browser (FF) with a "Transferring data from uni.bordeaux.fr..." in the lower-left page-load infospace. Killed FF from a shell, reopened, retried, same locking-up occurred. One more application flunks the ewmayer "I just want it to !^*&$@% work" ease-of-use criterion. |
[QUOTE=ewmayer;469608]
I wonder - given essentially the same level of underlying code optimization - which would be faster, pari-via-browser or bc-run-locally-based multiprecision? [/QUOTE] bc seems to be doing base 10 arithmetic. gmp and most "advanced" packages do base 2^32 (or close) arithmetic. |
| All times are UTC. The time now is 08:57. |
Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.