seed ops #176
seed ops #176
Conversation
…for accessing rand_states, updated seed and init functions for rand_states
…_state_t random_next call
"merge upstream"
|
also wanted to note this PR relies on this change made to libavr 32: I noticed that the teletype libavr32 still links to the version before this change. not exactly sure how recursive repositories work. |
| "DRUNK.SD" => { MATCH_OP(E_OP_SYM_DRUNK_SD); }; | ||
| "P.SEED" => { MATCH_OP(E_OP_P_SEED); }; | ||
| "P.SD" => { MATCH_OP(E_OP_SYM_P_SD); }; | ||
|
|
scanner-darkly
Jan 15, 2019
•
Member
indentation seems off?
indentation seems off?
alpha-cactus
Jan 15, 2019
Author
Contributor
strange. I ran git-clang-format. will investigate when I get home later.
strange. I ran git-clang-format. will investigate when I get home later.
scanner-darkly
Jan 16, 2019
Member
it's likely due to tabs being used which i think clang-format is supposed to convert (teletype uses 4 spaces convention)
it's likely due to tabs being used which i think clang-format is supposed to convert (teletype uses 4 spaces convention)
alpha-cactus
Jan 16, 2019
Author
Contributor
oh okay I think I'm using 2 spaces because that's norns convention.
oh okay I think I'm using 2 spaces because that's norns convention.
| const tele_op_t op_DRUNK_SEED = MAKE_SEED_OP(DRUNK.SEED, rand_states.s.drunk); | ||
| const tele_op_t op_SYM_DRUNK_SD = MAKE_SEED_OP(DRUNK.SD, rand_states.s.drunk); | ||
| const tele_op_t op_P_SEED = MAKE_SEED_OP(P.SEED, rand_states.s.pattern); | ||
| const tele_op_t op_SYM_P_SD = MAKE_SEED_OP(P.SD, rand_states.s.pattern); |
scanner-darkly
Jan 15, 2019
•
Member
indentation seems off?
indentation seems off?
alpha-cactus
Jan 15, 2019
Author
Contributor
yup probably some sort of tab issue. will fix.
yup probably some sort of tab issue. will fix.
| exec_state_t *NOTUSED(es), command_state_t *cs) { | ||
| char *base = (char *)ss; | ||
| size_t offset = (size_t)data; | ||
| rand_set_t *ptr = (rand_set_t *)(base + offset); |
scanner-darkly
Jan 15, 2019
Member
does this depend on specific order of members in scene_state_t?
does this depend on specific order of members in scene_state_t?
alpha-cactus
Jan 15, 2019
Author
Contributor
no I don't think order matters. I'm using the same technique as the MAKE_SIMPLE_VARIABLE_OP macro, but the warning comment for variable order is related to something else.
https://llllllll.co/t/teletype-firmware-discussion/13961/38?u=alphacactus
no I don't think order matters. I'm using the same technique as the MAKE_SIMPLE_VARIABLE_OP macro, but the warning comment for variable order is related to something else.
https://llllllll.co/t/teletype-firmware-discussion/13961/38?u=alphacactus
|
great, added some comments! re: for more info on working with submodule check out the guide @samdoshi put together: https://samdoshi.com/post/2016/03/git-submodules/ |
| @@ -240,6 +247,26 @@ void op_poke_i16(const void *data, scene_state_t *ss, exec_state_t *NOTUSED(es), | |||
| tele_vars_updated(); | |||
| } | |||
|
|
|||
| void op_peek_seed_i16(const void *data, scene_state_t *ss, | |||
alpha-cactus
Jan 15, 2019
Author
Contributor
actually can probably move these and the macros into seed.c
actually can probably move these and the macros into seed.c
still concerned about this. |
|
not sure i fully understand - are you saying it doesn't respect the seed? |
actually don't think I was clear in my original post. output would look like this.
which probably isn't good. if we can eliminate the LSB from the equation it should be fine. maybe a bit SHIFT and OR? although at that point is it worth the trouble. |
|
ya sorry post got cut off early. |
|
ah i see, so the least significant bit is not random. does this apply to bigger ranges too? say if i did |
|
yes that's why I had to change |
|
yeah we could try right shifting it by 1 or XORing 2 numbers but that might also affect the quality of the algorithm.. |
|
ya looking at it now probably premature for this PR given the issue. I guess I wanted to see what others had to say on it. can probably close this for now and just have a single |
|
let's leave it open - these are fantastic ops and very useful, we just need to find a better algo! |
ok cool I had already been looking at a few should be able to come up with something before the weekend.
yes that's my understanding of it. |
|
in this case one way would be to reproduce the implementation but with the ability to maintain several states/seeds, and add an index parameter to |
|
oh ya hadn't really considered that! I'll look into it if not just to see how it works. |
|
doing a quick search, this: http://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/random_r.c;hb=glibc-2.15#l361 has the ability to switch states. also this: http://www.cse.yorku.ca/~oz/marsaglia-rng.html has several algos that might work? |
|
yes! didn't have much time last night, but I literally book marked those exact two pages for reading today. |
|
code is a little dirty, but I think the Marsaglia KISS algorithm seems sufficient. still uses a Linear Congruential Generator like libavr32 so it can be seeded. however the MWC and SHR3 algorithms improve the randomness of the lower bits. I'll work it in to the teletype firmware if it looks good to you. initial testing looks good. from what I can tell. |
|
i only have basic knowledge about random generators, so i'm good with whatever you think will work best! |
|
alright this should be the final revision. I could move give me a few days to run this through some tests before merging. |
| command_state_t *cs); | ||
|
|
||
| // clang-format off | ||
| const tele_op_t op_SEED = MAKE_GET_SET_OP(SEED, op_SEED_get, op_SEED_set, 0, true); |
scanner-darkly
Jan 20, 2019
Member
indentation off
indentation off
| @@ -96,7 +98,8 @@ typedef struct { | |||
| uint8_t time_act; | |||
| int16_t tr[TR_COUNT]; | |||
| int16_t tr_pol[TR_COUNT]; | |||
| int16_t tr_time[TR_COUNT]; | |||
| int16_t tr_time[TR_COUNT]; | |||
scanner-darkly
Jan 20, 2019
Member
indentation off?
indentation off?
alpha-cactus
Jan 20, 2019
Author
Contributor
ugh. fixed what was causing this, so it shouldn't be an issue going forward. I went through my previous commits & pull requests and have hopefully fixed everything now. must've missed this one.
ugh. fixed what was causing this, so it shouldn't be an issue going forward. I went through my previous commits & pull requests and have hopefully fixed everything now. must've missed this one.
scanner-darkly
Mar 27, 2019
•
Member
looks like indentation is still off here and on the next line
looks like indentation is still off here and on the next line
| exec_state_t *NOTUSED(es), command_state_t *cs) { | ||
| cs_push(cs, rand() & 1); | ||
| tele_rand_t *r = &ss->rand_states.s.toss; | ||
| cs_push(cs, (tele_rand(r) >> 3) & 1); |
scanner-darkly
Jan 20, 2019
Member
do we still need to use a different bit with the latest algo?
do we still need to use a different bit with the latest algo?
alpha-cactus
Jan 20, 2019
•
Author
Contributor
probably not. I think the issue with less random lower bits is only tied to the linear congruential generator algorithm. I'll run some tests using the new algorithm with the lsb to verify.
probably not. I think the issue with less random lower bits is only tied to the linear congruential generator algorithm. I'll run some tests using the new algorithm with the lsb to verify.
|
added some minor comments, other than that looks good! |
ya I'm curious how many firmwares(if any) are using the current libavr32 random. I'd prefer updating it rather than adding a second random function to the library. should be simple enough to just replace the algorithm without changing any of the other functionality. |
|
i did a search in trilogy/ansible/aleph repos and looks like the only thing that uses |
|
@scanner-darkly link to my current version: new version would leave range limiting responsibility to the caller. I could keep the range functionality, but would want to then probably remove it from the teletype firmware where possible since modulus operations are kind of expensive if I recall. |
|
i would leave it in, unless that involves more changes, otherwise we'll have to check if anything uses it (and i don't think modulus would be a huge concern performance wise in the big scheme of things). why would you need to remove it from teletype though? so it doesn't do it twice? |
|
well the libavr32 algorithm generates a number in the range 0x0-0x7FFFFFF. then that number is cut down to the specified min/max range and returned to teletype. in the case of an op like ya I was thinking maybe we could have libavr32 just perform all the range limiting. however, that might just reduce code readability/maintainability for what ends up being a really small optimization. |
|
wouldn't |
|
right it's currently built into the https://github.com/monome/libavr32/blob/377bc181a81ed616647f2cb644f662711238e579/src/random.c#L26 |
|
ran some quick tests to confirm the libavr32 integration is good. bit of a wild PR thanks for sticking with it. |
|
thanks for doing it! |
|
I think the indentation is actually still off... let me fix that first. edit: |
|
ah sorry, didn't see your edit of the previous message - github doesn't send notification for edits. yeah indentation looks fine to me except a couple of lines, i left a comment there. |
|
fantastic! |


What does this PR do?
changes the random number generator for all ops using
stdlibrand()to uselibavr32rand_state_t. addSEEDop to set seed for all ops usingrand. add separate ops to set seed for any individual op.list of all added ops including aliases:
SEEDRAND.SEED/RAND.SD/R.SDTOSS.SEED/TOSS.SDPROB.SEED/PROB.SDDRUNK.SEED/DRUNK.SDP.SEED/P.SDthe algorithm used by
rand_state_tcomes from here(page 10):numerical recipes
Provide links to any related discussion on lines.
How should this be manually tested?
I've been running these ops through multiple scripts the past few weeks. also wrote a simple teletype script to test that the seed setting functionality works. confirmed the stream of number generated is the same when setting the same seed.
only issue I found in testing is that the LSB oscillates between 0 and 1. I had to update the
TOSSop to test bit 4 because of this. note this does cause something like the following to oscillate between the min/max number:RRAND 8 9will flip between returning 8 and 9. I understand this may be a serious concern. if so I can work on finding a better pnrg algorithm that can be seeded.
Any background context you want to provide?
added new file
seed.cto house seed ops. added macroMAKE_SEED_OPfor creating seed ops in 1 line. the macro functions similar to theMAKE_SIMPLE_VARIABLE_OP.because all the seed ops are using the same function aliases are also made using the
MAKE_SEED_OPmacro.used a union for housing the
random_state_tstructures for each op. this allows them to be accessed individually by nam, or iterated over for initialization and theSEEDop.If the related Github issues aren't referenced in your commits, please link to them here.
I have,
CHANGELOG.mdmake formaton each commit