mirror of
https://github.com/golang/go
synced 2024-10-04 11:21:21 -06:00
432 lines
4.8 KiB
C
432 lines
4.8 KiB
C
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
#include "go.h"
|
||
|
|
||
|
int
|
||
|
mpcmpfixfix(Mpint *a, Mpint *b)
|
||
|
{
|
||
|
if(a->val > b->val)
|
||
|
return +1;
|
||
|
if(a->val < b->val)
|
||
|
return -1;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
mpcmpfixc(Mpint *b, vlong c)
|
||
|
{
|
||
|
Mpint a;
|
||
|
|
||
|
mpmovecfix(&a, c);
|
||
|
return mpcmpfixfix(&a, b);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
mpcmpfltflt(Mpflt *a, Mpflt *b)
|
||
|
{
|
||
|
if(a->val > b->val)
|
||
|
return +1;
|
||
|
if(a->val < b->val)
|
||
|
return -1;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
mpcmpfltc(Mpint *b, double c)
|
||
|
{
|
||
|
Mpint a;
|
||
|
|
||
|
mpmovecflt(&a, c);
|
||
|
return mpcmpfltflt(&a, b);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpaddfixfix(Mpint *a, Mpint *b)
|
||
|
{
|
||
|
a->val += b->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpsubfixfix(Mpint *a, Mpint *b)
|
||
|
{
|
||
|
a->val -= b->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpmulfixfix(Mpint *a, Mpint *b)
|
||
|
{
|
||
|
a->val *= b->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpdivfixfix(Mpint *a, Mpint *b)
|
||
|
{
|
||
|
a->val /= b->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpmodfixfix(Mpint *a, Mpint *b)
|
||
|
{
|
||
|
a->val %= b->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mporfixfix(Mpint *a, Mpint *b)
|
||
|
{
|
||
|
a->val |= b->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpandfixfix(Mpint *a, Mpint *b)
|
||
|
{
|
||
|
a->val &= b->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpxorfixfix(Mpint *a, Mpint *b)
|
||
|
{
|
||
|
a->val ^= b->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mplshfixfix(Mpint *a, Mpint *b)
|
||
|
{
|
||
|
a->val <<= b->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mprshfixfix(Mpint *a, Mpint *b)
|
||
|
{
|
||
|
a->val >>= b->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpnegfix(Mpint *a)
|
||
|
{
|
||
|
a->val = -a->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpcomfix(Mpint *a)
|
||
|
{
|
||
|
a->val = ~a->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpaddfltflt(Mpflt *a, Mpflt *b)
|
||
|
{
|
||
|
a->val += b->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpsubfltflt(Mpflt *a, Mpflt *b)
|
||
|
{
|
||
|
a->val -= b->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpmulfltflt(Mpflt *a, Mpflt *b)
|
||
|
{
|
||
|
a->val *= b->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpdivfltflt(Mpflt *a, Mpflt *b)
|
||
|
{
|
||
|
a->val /= b->val;
|
||
|
}
|
||
|
|
||
|
vlong
|
||
|
mpgetfix(Mpint *a)
|
||
|
{
|
||
|
return a->val;
|
||
|
}
|
||
|
|
||
|
double
|
||
|
mpgetflt(Mpflt *a)
|
||
|
{
|
||
|
return a->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpmovefixfix(Mpint *a, Mpint *b)
|
||
|
{
|
||
|
*a = *b;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpmovefltflt(Mpflt *a, Mpflt *b)
|
||
|
{
|
||
|
*a = *b;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpmovefixflt(Mpflt *a, Mpint *b)
|
||
|
{
|
||
|
a->val = b->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpmovecfix(Mpint *a, vlong c)
|
||
|
{
|
||
|
a->val = c;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpmovecflt(Mpflt *a, double c)
|
||
|
{
|
||
|
a->val = c;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpmovefltfix(Mpint *a, Mpflt *b)
|
||
|
{
|
||
|
a->val = b->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpnegflt(Mpflt *a)
|
||
|
{
|
||
|
a->val = -a->val;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpaddcflt(Mpflt *a, double c)
|
||
|
{
|
||
|
Mpflt b;
|
||
|
|
||
|
mpmovecflt(&b, c);
|
||
|
mpaddfltflt(a, &b);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpmulcflt(Mpflt *a, double c)
|
||
|
{
|
||
|
Mpflt b;
|
||
|
|
||
|
mpmovecflt(&b, c);
|
||
|
mpmulfltflt(a, &b);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpaddcfix(Mpint *a, vlong c)
|
||
|
{
|
||
|
Mpint b;
|
||
|
|
||
|
mpmovecfix(&b, c);
|
||
|
mpaddfixfix(a, &b);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
mpmulcfix(Mpint *a, vlong c)
|
||
|
{
|
||
|
Mpint b;
|
||
|
|
||
|
mpmovecfix(&b, c);
|
||
|
mpmulfixfix(a, &b);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// power of ten
|
||
|
//
|
||
|
static double
|
||
|
tentab[] = { 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9 };
|
||
|
|
||
|
static double
|
||
|
dppow10(int n)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
if(n < 0)
|
||
|
return 1.0/dppow10(-n);
|
||
|
|
||
|
if(n < nelem(tentab))
|
||
|
return tentab[n];
|
||
|
|
||
|
i = n/2;
|
||
|
return dppow10(i) * dppow10(n-i);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// floating point input
|
||
|
// required syntax is [+-]d*[.]d*[e[+-]d*]
|
||
|
//
|
||
|
void
|
||
|
mpatoflt(Mpflt *a, char *as)
|
||
|
{
|
||
|
int dp, c, f, ef, ex, zer;
|
||
|
char *s;
|
||
|
|
||
|
s = as;
|
||
|
dp = 0; /* digits after decimal point */
|
||
|
f = 0; /* sign */
|
||
|
ex = 0; /* exponent */
|
||
|
zer = 1; /* zero */
|
||
|
|
||
|
mpmovecflt(a, 0);
|
||
|
for(;;) {
|
||
|
switch(c = *s++) {
|
||
|
default:
|
||
|
goto bad;
|
||
|
|
||
|
case '-':
|
||
|
f = 1;
|
||
|
|
||
|
case ' ':
|
||
|
case '\t':
|
||
|
case '+':
|
||
|
continue;
|
||
|
|
||
|
case '.':
|
||
|
dp = 1;
|
||
|
continue;
|
||
|
|
||
|
case '1':
|
||
|
case '2':
|
||
|
case '3':
|
||
|
case '4':
|
||
|
case '5':
|
||
|
case '6':
|
||
|
case '7':
|
||
|
case '8':
|
||
|
case '9':
|
||
|
zer = 0;
|
||
|
|
||
|
case '0':
|
||
|
mpmulcflt(a, 10);
|
||
|
mpaddcflt(a, c-'0');
|
||
|
if(dp)
|
||
|
dp++;
|
||
|
continue;
|
||
|
|
||
|
case 'E':
|
||
|
case 'e':
|
||
|
ex = 0;
|
||
|
ef = 0;
|
||
|
for(;;) {
|
||
|
c = *s++;
|
||
|
if(c == '+' || c == ' ' || c == '\t')
|
||
|
continue;
|
||
|
if(c == '-') {
|
||
|
ef = 1;
|
||
|
continue;
|
||
|
}
|
||
|
if(c >= '0' && c <= '9') {
|
||
|
ex = ex*10 + (c-'0');
|
||
|
continue;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
if(ef)
|
||
|
ex = -ex;
|
||
|
|
||
|
case 0:
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if(dp)
|
||
|
dp--;
|
||
|
if(mpcmpfltc(a, 0.0) != 0)
|
||
|
mpmulcflt(a, dppow10(ex-dp));
|
||
|
if(f)
|
||
|
mpnegflt(a);
|
||
|
return;
|
||
|
|
||
|
bad:
|
||
|
warn("set ovf in mpatof");
|
||
|
mpmovecflt(a, 0.0);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// fixed point input
|
||
|
// required syntax is [+-][0[x]]d*
|
||
|
//
|
||
|
void
|
||
|
mpatofix(Mpint *a, char *as)
|
||
|
{
|
||
|
|
||
|
int c, f;
|
||
|
char *s;
|
||
|
|
||
|
s = as;
|
||
|
f = 0;
|
||
|
mpmovecfix(a, 0);
|
||
|
|
||
|
c = *s++;
|
||
|
switch(c) {
|
||
|
case '-':
|
||
|
f = 1;
|
||
|
|
||
|
case '+':
|
||
|
c = *s++;
|
||
|
if(c != '0')
|
||
|
break;
|
||
|
|
||
|
case '0':
|
||
|
goto oct;
|
||
|
}
|
||
|
|
||
|
while(c) {
|
||
|
if(c >= '0' && c <= '9') {
|
||
|
mpmulcfix(a, 10);
|
||
|
mpaddcfix(a, c-'0');
|
||
|
c = *s++;
|
||
|
continue;
|
||
|
}
|
||
|
goto bad;
|
||
|
}
|
||
|
goto out;
|
||
|
|
||
|
oct:
|
||
|
c = *s++;
|
||
|
if(c == 'x' || c == 'X')
|
||
|
goto hex;
|
||
|
while(c) {
|
||
|
if(c >= '0' && c <= '7') {
|
||
|
mpmulcfix(a, 8);
|
||
|
mpaddcfix(a, c-'0');
|
||
|
c = *s++;
|
||
|
continue;
|
||
|
}
|
||
|
goto bad;
|
||
|
}
|
||
|
goto out;
|
||
|
|
||
|
hex:
|
||
|
c = *s++;
|
||
|
while(c) {
|
||
|
if(c >= '0' && c <= '9') {
|
||
|
mpmulcfix(a, 16);
|
||
|
mpaddcfix(a, c-'0');
|
||
|
c = *s++;
|
||
|
continue;
|
||
|
}
|
||
|
if(c >= 'a' && c <= 'f') {
|
||
|
mpmulcfix(a, 16);
|
||
|
mpaddcfix(a, c+10-'a');
|
||
|
c = *s++;
|
||
|
continue;
|
||
|
}
|
||
|
if(c >= 'A' && c <= 'F') {
|
||
|
mpmulcfix(a, 16);
|
||
|
mpaddcfix(a, c+10-'A');
|
||
|
c = *s++;
|
||
|
continue;
|
||
|
}
|
||
|
goto bad;
|
||
|
}
|
||
|
|
||
|
out:
|
||
|
if(f)
|
||
|
mpnegfix(a);
|
||
|
return;
|
||
|
|
||
|
bad:
|
||
|
warn("set ovf in mpatov: %s", as);
|
||
|
mpmovecfix(a, 0);
|
||
|
}
|