~ubuntu-branches/debian/squeeze/erlang/squeeze

« back to all changes in this revision

Viewing changes to erts/emulator/beam/big.c

  • Committer: Bazaar Package Importer
  • Author(s): Erlang Packagers, Sergei Golovan
  • Date: 2006-12-03 17:07:44 UTC
  • mfrom: (2.1.11 feisty)
  • Revision ID: james.westby@ubuntu.com-20061203170744-rghjwupacqlzs6kv
Tags: 1:11.b.2-4
[ Sergei Golovan ]
Fixed erlang-base and erlang-base-hipe prerm scripts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1034
1034
}
1035
1035
 
1036
1036
/*
1037
 
** create bigint on heap if necessary
1038
 
** or a small_int which uses no heap
1039
 
** allocates new heap if necssary
 
1037
** Create bigint on heap if necessary. Like the previously existing
 
1038
** make_small_or_big(), except for a HAlloc() instead of an
 
1039
** ArithAlloc().
 
1040
** NOTE: Only use erts_make_integer(), when order of heap fragments is
 
1041
**       guaranteed to be correct.
1040
1042
*/
1041
 
Eterm make_small_or_big(Uint x, Process *p)
 
1043
Eterm
 
1044
erts_make_integer(Uint x, Process *p)
1042
1045
{
1043
1046
    Eterm* hp;
1044
1047
    if (IS_USMALL(0,x))
1045
1048
        return make_small(x);
1046
1049
    else {
1047
 
        /* Called from guard BIFs - must use ArithAlloc() here */
1048
 
        hp = ArithAlloc(p,BIG_NEED_SIZE(2));
 
1050
        hp = HAlloc(p, BIG_UINT_HEAP_SIZE);
1049
1051
        return uint_to_big(x,hp);
1050
1052
    }
1051
1053
}
 
1054
 
1052
1055
/*
1053
1056
** convert uint32 to bigint
1054
1057
** 32UPDATE (as macro?)
1059
1062
    *y = make_pos_bignum_header(1);
1060
1063
    BIG_DIGIT(y, 0) = DLOW(x);
1061
1064
    BIG_DIGIT(y, 1) = DHIGH(x);
1062
 
    ASSERT(SMALL_BITS <= 32);
1063
 
#ifdef ARCH_64
1064
 
    BIG_DIGIT(y, 2) = 0;
1065
 
    BIG_DIGIT(y, 3) = 0;
1066
 
#endif
1067
1065
    return make_big(y);
1068
1066
}
1069
1067
 
1082
1080
    }
1083
1081
    BIG_DIGIT(y, 0) = DLOW(x);
1084
1082
    BIG_DIGIT(y, 1) = DHIGH(x);
1085
 
#ifdef ARCH_64
1086
 
    BIG_DIGIT(y, 2) = 0;
1087
 
    BIG_DIGIT(y, 3) = 0;
1088
 
#endif
1089
1083
    return make_big(y);
1090
1084
}
1091
1085
 
1101
1095
    dsize_t xl = BIG_SIZE(xp);
1102
1096
    digit_t* s = BIG_V(xp) + xl;
1103
1097
    short xsgn = BIG_SIGN(xp);
1104
 
    ERTS_SAVE_FP_EXCEPTION();
 
1098
    volatile int *fpexnp = erts_get_current_fp_exception();
 
1099
    __ERTS_SAVE_FP_EXCEPTION(fpexnp);
1105
1100
 
1106
 
    ERTS_FP_CHECK_INIT();
 
1101
    __ERTS_FP_CHECK_INIT(fpexnp);
1107
1102
    while (xl--) {
1108
1103
        d = d * D_BASE + *--s;
1109
1104
 
1110
 
        ERTS_FP_ERROR(d, ERTS_RESTORE_FP_EXCEPTION(); return -1);
 
1105
        __ERTS_FP_ERROR(fpexnp, d, __ERTS_RESTORE_FP_EXCEPTION(fpexnp); return -1);
1111
1106
    }
1112
1107
 
1113
1108
    *resp = xsgn ? -d : d;
1114
 
    ERTS_FP_ERROR(*resp,;);
1115
 
    ERTS_RESTORE_FP_EXCEPTION();
 
1109
    __ERTS_FP_ERROR(fpexnp,*resp,;);
 
1110
    __ERTS_RESTORE_FP_EXCEPTION(fpexnp);
1116
1111
    return 0;
1117
1112
}
1118
1113
 
1131
1126
}
1132
1127
 
1133
1128
/*
1134
 
 ** Convert a bignum into a string of decimal numbers
1135
 
 */
1136
 
char* big_to_decimal(Eterm y, char *p, int n)
1137
 
{
1138
 
    char* q = p+(n-1);
1139
 
    Eterm* yp = big_val(y);
1140
 
 
1141
 
    digit_t* x = BIG_V(yp);
1142
 
    dsize_t xl = BIG_SIZE(yp);
1143
 
    short sign = BIG_SIGN(yp);
1144
 
    digit_t rem;
1145
 
 
1146
 
    *q-- = '\0';
1147
 
 
1148
 
    if (xl == 1 && *x < D_DECIMAL_BASE) {
1149
 
        rem = *x;
1150
 
        if (rem == 0)
1151
 
            *q-- = '0';
1152
 
        else {
1153
 
            while(rem) {
1154
 
                *q-- = (rem % 10) + '0';
1155
 
                rem /= 10;
1156
 
            }
1157
 
        }
1158
 
    }
1159
 
    else {
1160
 
        digit_t* tmp  = (digit_t*) erts_alloc(ERTS_ALC_T_TMP,
1161
 
                                              sizeof(digit_t)*xl);
1162
 
        dsize_t tmpl = xl;
1163
 
 
1164
 
        MOVE_DIGITS(tmp, x, xl);
1165
 
 
1166
 
        while(1) {
1167
 
            tmpl = D_div(tmp, tmpl, D_DECIMAL_BASE, tmp, &rem);
1168
 
            if (tmpl == 1 && *tmp == 0) {
1169
 
                while(rem) {
1170
 
                    *q-- = (rem % 10) + '0';
1171
 
                    rem /= 10;
1172
 
                }
1173
 
                break;
1174
 
            }
1175
 
            else {
1176
 
                int i = D_DECIMAL_EXP;
1177
 
                while(i--) {
1178
 
                    *q-- = (rem % 10) + '0';
1179
 
                    rem /= 10;
1180
 
                }
1181
 
            }
1182
 
        }
1183
 
        erts_free(ERTS_ALC_T_TMP, (void *) tmp);
1184
 
    }
1185
 
    if (sign)
1186
 
        *q-- = '-';
1187
 
 
1188
 
    /* move to beginning of p */
1189
 
    q++;
1190
 
    if (p != q) {
1191
 
        char *p0 = p;
1192
 
 
1193
 
        while(*q != 0)
1194
 
            *p0++ = *q++;
1195
 
        *p0 = '\0';
1196
 
    }
1197
 
    return p;
1198
 
}
1199
 
 
1200
 
/*
1201
1129
** Convert a bignum into a string of decimal numbers
1202
1130
*/
1203
1131
 
1204
 
Eterm big_to_list(Eterm x, Eterm **hp)
 
1132
static void write_big(Eterm x, void (*write_func)(void *, char), void *arg)
1205
1133
{
1206
1134
    Eterm* xp = big_val(x);
1207
1135
    digit_t* dx = BIG_V(xp);
1208
1136
    dsize_t xl = BIG_SIZE(xp);
1209
1137
    short sign = BIG_SIGN(xp);
1210
1138
    digit_t rem;
1211
 
    Eterm prev = NIL;
1212
 
    Eterm* curr = *hp;
1213
1139
 
1214
1140
    if (xl == 1 && *dx < D_DECIMAL_BASE) {
1215
1141
        rem = *dx;
1216
 
        if (rem == 0) {
1217
 
            prev = CONS(curr, make_small('0'), prev);
1218
 
            curr += 2;
1219
 
        }
 
1142
        if (rem == 0)
 
1143
            (*write_func)(arg, '0');
1220
1144
        else {
1221
1145
            while(rem) {
1222
 
                prev = CONS(curr, make_small((rem % 10)+'0'), prev);
1223
 
                curr += 2;
 
1146
                (*write_func)(arg, (rem % 10) + '0');
1224
1147
                rem /= 10;
1225
1148
            }
1226
1149
        }
1236
1159
            tmpl = D_div(tmp, tmpl, D_DECIMAL_BASE, tmp, &rem);
1237
1160
            if (tmpl == 1 && *tmp == 0) {
1238
1161
                while(rem) {
1239
 
                    prev = CONS(curr, make_small((rem % 10)+'0'), prev);
1240
 
                    curr += 2;
 
1162
                    (*write_func)(arg, (rem % 10)+'0');
1241
1163
                    rem /= 10;
1242
1164
                }
1243
1165
                break;
1245
1167
            else {
1246
1168
                int i = D_DECIMAL_EXP;
1247
1169
                while(i--) {
1248
 
                    prev = CONS(curr, make_small((rem % 10)+'0'), prev);
1249
 
                    curr += 2;
 
1170
                    (*write_func)(arg, (rem % 10)+'0');
1250
1171
                    rem /= 10;
1251
1172
                }
1252
1173
            }
1254
1175
        erts_free(ERTS_ALC_T_TMP, (void *) tmp);
1255
1176
    }
1256
1177
 
1257
 
    if (sign) {
1258
 
        prev = CONS(curr, make_small('-'), prev);
1259
 
        curr += 2;
1260
 
    }
1261
 
    *hp = curr;
1262
 
    return prev;
 
1178
    if (sign)
 
1179
        (*write_func)(arg, '-');
 
1180
}
 
1181
 
 
1182
struct big_list__ {
 
1183
    Eterm *hp;
 
1184
    Eterm res;
 
1185
};
 
1186
 
 
1187
static void
 
1188
write_list(void *arg, char c)
 
1189
{
 
1190
    struct big_list__ *blp = (struct big_list__ *) arg;
 
1191
    blp->res = CONS(blp->hp, make_small(c), blp->res);
 
1192
    blp->hp += 2;
 
1193
}
 
1194
 
 
1195
Eterm erts_big_to_list(Eterm x, Eterm **hpp)
 
1196
{
 
1197
    struct big_list__ bl;
 
1198
    bl.hp = *hpp;
 
1199
    bl.res = NIL;
 
1200
    write_big(x, write_list, (void *) &bl);
 
1201
    *hpp = bl.hp;
 
1202
    return bl.res;
 
1203
}
 
1204
 
 
1205
static void
 
1206
write_string(void *arg, char c)
 
1207
{
 
1208
    *(--(*((char **) arg))) = c;
 
1209
}
 
1210
 
 
1211
char *erts_big_to_string(Eterm x, char *buf, Uint buf_sz)
 
1212
{
 
1213
    char *big_str = buf + buf_sz - 1;
 
1214
    *big_str = '\0';
 
1215
    write_big(x, write_string, (void *) &big_str);
 
1216
    ASSERT(buf <= big_str && big_str <= buf + buf_sz - 1);
 
1217
    return big_str;
1263
1218
}
1264
1219
 
1265
1220
/*
1274
1229
    if (xl == 1) {
1275
1230
        Uint y = BIG_DIGIT(x, 0);
1276
1231
 
1277
 
        if (sign)
1278
 
            return make_small(-((Sint32)y));
1279
 
        else
1280
 
            return make_small(y);
 
1232
        if (D_EXP < SMALL_BITS || IS_USMALL(sign, y)) {
 
1233
            if (sign)
 
1234
                return make_small(-((Sint)y));
 
1235
            else
 
1236
                return make_small(y);
 
1237
        }
1281
1238
    }
1282
1239
    else if (xl == 2) {
1283
1240
        Uint y = BIG_DIGIT(x,0) + BIG_DIGIT(x,1)*D_BASE;
1284
1241
 
1285
1242
        if (IS_USMALL(sign, y)) {
1286
1243
            if (sign)
1287
 
                return make_small(-((Sint32)y));
 
1244
                return make_small(-((Sint)y));
1288
1245
            else
1289
1246
                return make_small(y);
1290
1247
        }
1302
1259
    }
1303
1260
 
1304
1261
    /* Its VERY important to patch a zero if odd number of digits! */
1305
 
#ifdef ARCH_64
1306
 
    switch(xl & 3) {
1307
 
    case 0:
1308
 
      break;
1309
 
    case 1:
1310
 
      BIG_DIGIT(x, xl+2) = 0;
1311
 
    case 2:
1312
 
      BIG_DIGIT(x, xl+1) = 0;
1313
 
    case 3:
1314
 
      BIG_DIGIT(x, xl) = 0;
1315
 
      break;
1316
 
    }
1317
 
#else
1318
1262
    switch(xl & 1) {
1319
1263
    case 0:
1320
1264
      break;
1322
1266
      BIG_DIGIT(x, xl) = 0;
1323
1267
      break;
1324
1268
    }
1325
 
#endif
1326
1269
 
1327
1270
    return make_big(x);
1328
1271
}
1363
1306
** Check if bytes in xp corresponds to a bignum y
1364
1307
** 32UPDATE
1365
1308
*/
 
1309
#if 0   /* XXX: unused */
1366
1310
int bytes_eq_big(byte *xp, dsize_t xsz, int xsgn, Eterm y)
1367
1311
{
1368
1312
    if (is_big(y)) {
1422
1366
    }
1423
1367
    return 0;
1424
1368
}
 
1369
#endif  /* 0 */
1425
1370
 
1426
1371
/*
1427
1372
** Return number of bytes in the bignum
1434
1379
    dsize_t sz = BIG_SIZE(xp);
1435
1380
    digit_t d = BIG_DIGIT(xp, sz-1);
1436
1381
 
1437
 
    if (d < 256)
1438
 
        return 2*sz - 1;
1439
 
    return 2*sz;
 
1382
    sz = (sz-1) * sizeof(digit_t);
 
1383
    while (d != 0) {
 
1384
        ++sz;
 
1385
        d >>= 8;
 
1386
    }
 
1387
    return sz;
1440
1388
}
1441
1389
 
1442
1390
/*
1449
1397
    digit_t* rwp = BIG_V(r);
1450
1398
    dsize_t rsz = 0;
1451
1399
    digit_t d;
 
1400
    int i;
1452
1401
 
1453
 
    while(xsz >= 2) {
1454
 
        d = xp[0] | (xp[1] << 8);
 
1402
    while(xsz >= sizeof(digit_t)) {
 
1403
        d = 0;
 
1404
        for(i = sizeof(digit_t); --i >= 0;)
 
1405
            d = (d << 8) | xp[i];
1455
1406
        *rwp = d;
1456
1407
        rwp++;
1457
 
        xsz -= 2;
1458
 
        xp += 2;
 
1408
        xsz -= sizeof(digit_t);
 
1409
        xp += sizeof(digit_t);
1459
1410
        rsz++;
1460
1411
    }
1461
1412
 
1462
 
    if (xsz == 1) {
1463
 
        d = *xp;
 
1413
    if (xsz > 0) {
 
1414
        d = 0;
 
1415
        for(i = xsz; --i >= 0;)
 
1416
            d = (d << 8) | xp[i];
1464
1417
        *rwp = d;
1465
1418
        rwp++;
1466
1419
        rsz++;
1477
1430
    digit_t* xr = big_v(x);
1478
1431
    dsize_t  xl = big_size(x);
1479
1432
    digit_t d;
 
1433
    int i;
1480
1434
 
1481
1435
    while(xl > 1) {
1482
1436
        d = *xr;
1483
1437
        xr++;
1484
 
        p[0] = d & 0xff;
1485
 
        p[1] = (d >> 8) & 0xff;
1486
 
        p += 2;
 
1438
        for(i = 0; i < sizeof(digit_t); ++i) {
 
1439
            p[i] = d & 0xff;
 
1440
            d >>= 8;
 
1441
        }
 
1442
        p += sizeof(digit_t);
1487
1443
        xl--;
1488
1444
    }
1489
1445
    d = *xr;
1490
 
    *p++ = d & 0xff;
1491
 
    if (d < 256)
1492
 
        return p;
1493
 
    *p++ = (d >> 8) & 0xff;
 
1446
    do {
 
1447
        *p++ = d & 0xff;
 
1448
        d >>= 8;
 
1449
    } while (d != 0);
1494
1450
    return p;
1495
1451
}
1496
1452
 
1505
1461
int
1506
1462
term_to_Uint(Eterm term, Uint *up)
1507
1463
{
1508
 
   int i;
1509
 
 
1510
 
   if (is_small(term)) {
1511
 
       i = signed_val(term);
1512
 
       if (i < 0) {
1513
 
           return 0;
1514
 
       }
1515
 
       *up = (Uint) i;
1516
 
       return 1;
1517
 
   } else if (is_big(term)) {
1518
 
       digit_t* xr = big_v(term);
1519
 
       dsize_t  xl = big_size(term);
1520
 
       Uint uval = 0;
1521
 
       int n = 0;
1522
 
 
1523
 
       /* FIXED: for __alpha__ was sizeof(Uint) == 4 */
1524
 
       ASSERT(sizeof(Uint) >= 4);
1525
 
       if (xl > 2 || big_sign(term)) {
1526
 
           return 0;
1527
 
       }
1528
 
       while (xl-- > 0) {
1529
 
           uval |= *xr++ << n;
1530
 
           n += 16;
1531
 
       }
1532
 
       *up = uval;
1533
 
       return 1;
1534
 
   } else {
1535
 
      return 0;
1536
 
  }
 
1464
    if (is_small(term)) {
 
1465
        Sint i = signed_val(term);
 
1466
        if (i < 0) {
 
1467
            return 0;
 
1468
        }
 
1469
        *up = (Uint) i;
 
1470
        return 1;
 
1471
    } else if (is_big(term)) {
 
1472
        digit_t* xr = big_v(term);
 
1473
        dsize_t  xl = big_size(term);
 
1474
        Uint uval = 0;
 
1475
        int n = 0;
 
1476
        
 
1477
        if (big_sign(term) || xl*D_EXP > sizeof(Uint)*CHAR_BIT) {
 
1478
            return 0;
 
1479
        }
 
1480
        while (xl-- > 0) {
 
1481
            uval |= ((Uint)(*xr++)) << n;
 
1482
            n += D_EXP;
 
1483
        }
 
1484
        *up = uval;
 
1485
        return 1;
 
1486
    } else {
 
1487
        return 0;
 
1488
    }
 
1489
}
 
1490
 
 
1491
int term_to_Sint(Eterm term, Sint *sp)
 
1492
{
 
1493
    if (is_small(term)) {
 
1494
        *sp = signed_val(term);
 
1495
        return 1;
 
1496
    } else if (is_big(term)) {
 
1497
        digit_t* xr = big_v(term);
 
1498
        dsize_t xl = big_size(term);
 
1499
        int sign = big_sign(term);
 
1500
        Uint uval = 0;
 
1501
        int n = 0;
 
1502
 
 
1503
        if (xl*D_EXP > sizeof(Uint)*CHAR_BIT) {
 
1504
            return 0;
 
1505
        }
 
1506
        while (xl-- > 0) {
 
1507
            uval |= ((Uint)(*xr++)) << n;
 
1508
            n += D_EXP;
 
1509
        }
 
1510
        if (sign) {
 
1511
            uval = -uval;
 
1512
            if ((Sint)uval > 0)
 
1513
                return 0;
 
1514
        } else {
 
1515
            if ((Sint)uval < 0)
 
1516
                return 0;
 
1517
        }
 
1518
        *sp = uval;
 
1519
        return 1;
 
1520
    } else {
 
1521
        return 0;
 
1522
    }
1537
1523
}
1538
1524
 
1539
1525
/*
1661
1647
        dsize_t rem_sz;
1662
1648
 
1663
1649
        qsz = xsz - ysz + 1;
1664
 
        remp = q + 1 + ((qsz + 1) >> 1);
 
1650
        remp = q + BIG_NEED_SIZE(qsz);
1665
1651
        qsz = I_div(BIG_V(xp), xsz, BIG_V(yp), ysz, BIG_V(q), BIG_V(remp),
1666
1652
                    &rem_sz);
1667
1653
    }
1684
1670
        digit_t rem;
1685
1671
        rem = D_rem(BIG_V(xp), xsz, BIG_DIGIT(yp,0));
1686
1672
        if (sign)
1687
 
            return make_small(-rem);
 
1673
            return make_small(-(Sint)rem);
1688
1674
        else
1689
1675
            return make_small(rem);
1690
1676
    }
1808
1794
                             BIG_V(r)), (short) BIG_SIGN(xp));
1809
1795
}
1810
1796
 
1811
 
int big_fits_in_sint32(Eterm b)
1812
 
{
1813
 
  Eterm *p = big_val(b);
1814
 
  /* FIXED: for __alpha__ port BIG_ARITY => BIG_SIZE */
1815
 
  if (BIG_SIZE(p) > 2)
1816
 
    return 0;
1817
 
  if (BIG_SIGN(p))
1818
 
    return (BIG_DIGIT(p,1) <= 0x7FFF) || (BIG_DIGIT(p,1) == 0x8000 &&
1819
 
                                          BIG_DIGIT(p,0) == 0);
1820
 
  else
1821
 
    return BIG_DIGIT(p,1) <= 0x7FFF;
1822
 
}
1823
 
 
1824
 
int big_fits_in_uint32(Eterm b)
1825
 
{
1826
 
  Eterm *p = big_val(b);
1827
 
  return (BIG_SIZE(p) <= 2 && !BIG_SIGN(p));
1828
 
}
1829
 
 
1830
1797
/*
1831
1798
** Expects the big to fit.
1832
1799
*/
1833
1800
Uint32 big_to_uint32(Eterm b)
1834
1801
{
1835
 
    Eterm *p = big_val(b);
1836
 
    return (((Uint32) BIG_DIGIT(p,1)) << 16) | ((Uint32) BIG_DIGIT(p,0));
 
1802
    Uint u;
 
1803
    (void) term_to_Uint(b, &u);
 
1804
    return u;
1837
1805
}
1838
1806
 
1839
 
Sint32 big_to_sint32(Eterm b)
 
1807
/*
 
1808
 * Check if a fixnum or bignum equals 2^32.
 
1809
 */
 
1810
int term_equals_2pow32(Eterm x)
1840
1811
{
1841
 
    Sint32 res;
1842
 
    Eterm *p = big_val(b);
1843
 
    res = ((Sint32) ((((Uint32) BIG_DIGIT(p,1)) << 16) | 
1844
 
                     ((Uint32) BIG_DIGIT(p,0))));
1845
 
    return (BIG_SIGN(p)) ? -res : res;
 
1812
    if (sizeof(Uint) > 4) {
 
1813
        Uint u;
 
1814
        if (!term_to_Uint(x, &u))
 
1815
            return 0;
 
1816
        return (u & 0xFFFFFFFF) == 0 && ((u >> 16) >> 16) == 1;
 
1817
    } else {
 
1818
        Eterm *bp;
 
1819
        if (!is_big(x))
 
1820
            return 0;
 
1821
        bp = big_val(x);
 
1822
        if (BIG_SIZE(bp) == 3 && !BIG_DIGIT(bp,0) && !BIG_DIGIT(bp,1) &&
 
1823
            BIG_DIGIT(bp,2) == 1)
 
1824
            return 1;
 
1825
        return 0;
 
1826
    }
1846
1827
}
1847
 
 
1848