Annotation of 43BSD/contrib/icon/operators/random.c, revision 1.1

1.1     ! root        1: #include "../h/rt.h"
        !             2: #include "../h/record.h"
        !             3: #define randval (RSCALE*(k_random=(RANDA*k_random+RANDC)&MAXLONG))
        !             4: 
        !             5: /*
        !             6:  * ?x - produce a randomly selected element of x.
        !             7:  */
        !             8: 
        !             9: random(nargs, arg1v, arg1, arg0)
        !            10: int nargs;
        !            11: struct descrip arg1v, arg1, arg0;
        !            12:    {
        !            13:    register int val, i, j;
        !            14:    register union block *bp;
        !            15:    double r1;
        !            16:    char sbuf[MAXSTRING];
        !            17:    union block *ep;
        !            18:    struct descrip *dp;
        !            19:    extern char *alcstr();
        !            20: 
        !            21:    SetBound;
        !            22:    arg1v = arg1;
        !            23:    DeRef(arg1)
        !            24: 
        !            25:    /*
        !            26:     * x must not be null.
        !            27:     */
        !            28:    if (NULLDESC(arg1))
        !            29:       runerr(113, &arg1);
        !            30: 
        !            31:    if (QUAL(arg1)) {
        !            32:       /*
        !            33:        * x is a string, produce a random character in it as the result.
        !            34:        *  Note that a substring trapped variable is returned.
        !            35:        */
        !            36:       if ((val = STRLEN(arg1)) <= 0)
        !            37:          fail();
        !            38:       hneed(sizeof(struct b_tvsubs));
        !            39:       mksubs(&arg1v, &arg1, (int)(randval*val)+1, 1, &arg0);
        !            40:       ClearBound;
        !            41:       return;
        !            42:       }
        !            43: 
        !            44:    switch (TYPE(arg1)) {
        !            45:       case T_CSET:
        !            46:          /*
        !            47:           * x is a cset.  Convert it to a string, select a random character
        !            48:           *  of that string and return it.  Note that a substring trapped
        !            49:           *  variable is not needed.
        !            50:           */
        !            51:          cvstr(&arg1, sbuf);
        !            52:          if ((val = STRLEN(arg1)) <= 0)
        !            53:             fail();
        !            54:          sneed(1);
        !            55:          STRLEN(arg0) = 1;
        !            56:          STRLOC(arg0) = alcstr(STRLOC(arg1)+(int)(randval*val), 1);
        !            57:          ClearBound;
        !            58:          return;
        !            59: 
        !            60:       case T_REAL:
        !            61:          /*
        !            62:           * x is real.  Convert it to an integer and be sure that it is
        !            63:           *  non-negative and less than MAXSHORT.  Jump to common code
        !            64:           *  to compute a random value.  Note that reals are functionally
        !            65:           *  equivalent to integers.
        !            66:           */
        !            67:          r1 = BLKLOC(arg1)->realblk.realval;
        !            68:          if (r1 < 0 || r1 > MAXSHORT)
        !            69:             runerr(205, &arg1);
        !            70:          val = (int)r1;
        !            71:          goto getrand;
        !            72: 
        !            73:       case T_INTEGER:
        !            74:          /*
        !            75:           * x is an integer, be sure that it's non-negative.
        !            76:           */
        !            77:          val = INTVAL(arg1);
        !            78:          if (val < 0)
        !            79:             runerr(205, &arg1);
        !            80:       getrand:
        !            81:          /*
        !            82:           * val contains the integer value of x.  If val is 0, return
        !            83:           *  a real in the range [0,1), else return an integer in the
        !            84:           *  range [1,val].
        !            85:           */
        !            86:          if (val == 0)
        !            87:             mkreal(randval, &arg0);
        !            88:          else
        !            89:             mkint((long)(randval*val) + 1, &arg0);
        !            90:          ClearBound;
        !            91:          return;
        !            92: 
        !            93: #ifdef LONGS
        !            94:       case T_LONGINT:
        !            95:          /*
        !            96:           * Produce an error if x is a long integer.
        !            97:           */
        !            98:          runerr(205, &arg1);
        !            99: #endif LONGS
        !           100:       case T_LIST:
        !           101:          /*
        !           102:           * x is a list.  Set i to a random number in the range [1,*x],
        !           103:           *  failing if the list is empty.
        !           104:           */
        !           105:          bp = BLKLOC(arg1);
        !           106:          val = bp->list.cursize;
        !           107:          if (val <= 0)
        !           108:             fail();
        !           109:          i = (int)(randval*val) + 1;
        !           110:             j = 1;
        !           111:          /*
        !           112:           * Work down chain list of list blocks and find the block that
        !           113:           *  contains the selected element.
        !           114:           */
        !           115:             bp = BLKLOC(BLKLOC(arg1)->list.listhead);
        !           116:             while (i >= j + bp->lelem.nused) {
        !           117:                j += bp->lelem.nused;
        !           118:                if (TYPE(bp->lelem.listnext) != T_LELEM)
        !           119:                syserr("list reference out of bounds in random");
        !           120:                bp = BLKLOC(bp->lelem.listnext);
        !           121:             }
        !           122:          /*
        !           123:           * Locate the appropriate element and return a variable 
        !           124:           * that points to it.
        !           125:           */
        !           126:             i += bp->lelem.first - j;
        !           127:          if (i >= bp->lelem.nelem)
        !           128:             i -= bp->lelem.nelem;
        !           129:          dp = &bp->lelem.lslots[i];
        !           130:          arg0.type = D_VAR + ((int *)dp - (int *)bp);
        !           131:          VARLOC(arg0) = dp;
        !           132:          ClearBound;
        !           133:             return;
        !           134: 
        !           135:       case T_TABLE:
        !           136:           /*
        !           137:            * x is a table.  Set i to a random number in the range [1,*x],
        !           138:            *  failing if the table is empty.
        !           139:            */
        !           140:           bp = BLKLOC(arg1);
        !           141:           val = bp->table.cursize;
        !           142:           if (val <= 0)
        !           143:              fail();
        !           144:           i = (int)(randval*val) + 1;
        !           145:           /*
        !           146:            * Work down the chain of elements in each bucket and return
        !           147:            *  a variable that points to the i'th element encountered.
        !           148:            */
        !           149:           for (j = 0; j < NBUCKETS; j++) {
        !           150:              for (ep = BLKLOC(bp->table.buckets[j]); ep != NULL;
        !           151:                      ep = BLKLOC(ep->telem.blink)) {
        !           152:                 if (--i <= 0) {
        !           153:                    dp = &ep->telem.tval;
        !           154:                    arg0.type = D_VAR + ((int *)dp - (int *)bp);
        !           155:                    VARLOC(arg0) = dp;
        !           156:                    ClearBound;
        !           157:                    return;
        !           158:                    }
        !           159:                 }
        !           160:              }
        !           161: #ifdef SETS
        !           162:       case T_SET:
        !           163:          /*
        !           164:           * x is a set.  Set i to a random number in the range [1,*x],
        !           165:           *  failing if the set is empty.
        !           166:           */
        !           167:          bp = BLKLOC(arg1);
        !           168:          val = bp->set.setsize;
        !           169:          if (val <= 0)
        !           170:             fail();
        !           171:          i = (int)(randval*val) + 1;
        !           172:          /*
        !           173:           * Work down the chain of elements in each bucket and return
        !           174:           *  the value of the i'th element encountered.
        !           175:           */
        !           176:          for (j = 0; j < NBUCKETS; j++) {
        !           177:             for (ep = BLKLOC(bp->set.sbucks[j]); ep != NULL;
        !           178:                ep = BLKLOC(ep->selem.sblink)) {
        !           179:                   if (--i <= 0) {
        !           180:                      arg0 = ep->selem.setmem;
        !           181:                      ClearBound;
        !           182:                      return;
        !           183:                      }
        !           184:                  }   
        !           185:              }
        !           186: #endif SETS
        !           187: 
        !           188:       case T_RECORD:
        !           189:          /*
        !           190:           * x is a record.  Set val to a random number in the range [1,*x]
        !           191:           *  (*x is the number of fields), failing if the record has no
        !           192:           *  fields.
        !           193:           */
        !           194:          bp = BLKLOC(arg1);
        !           195:          val = bp->record.recptr->nfields;
        !           196:          if (val <= 0)
        !           197:             fail();
        !           198:          /*
        !           199:           * Locate the selected element and return a variable
        !           200:           * that points to it
        !           201:           */
        !           202:             dp = &bp->record.fields[(int)(randval*val)];
        !           203:               arg0.type = D_VAR + ((int *)dp - (int *)bp);
        !           204:          VARLOC(arg0) = dp;
        !           205:          ClearBound;
        !           206:             return;
        !           207: 
        !           208:       default:
        !           209:          /*
        !           210:           * x is of a type for which there is no notion of elements.
        !           211:           */
        !           212:          runerr(113, &arg1);
        !           213:       }
        !           214:    }
        !           215: 
        !           216: Opblockx(random,2,"?",1)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.