MPAライブラリ 数値設定ルーチン



[ 簡単な説明 ]

MPA値設定用の関数は、実数を設定する m_set( )、整数を設定する m_set_l( )、文字列で設定する m_set_a( )
を準備していますが、実数の定数を設定する場合には、m_set( )よりも m_set_a( )の方が正確に設定できます。

m_round( )では、仮数部 int 型配列をn個分に丸めます。

関数プロトタイプ 機能説明
MPA m_set(double a) MPA値設定 double → MPA
MPA m_set_a(char *s) 文字列 → MPA
MPA m_set_l(long n) long int → MPA
MPA m_int(MPA a) 部分抽出 整数部
MPA m_frac(MPA a) 小数部
MPA m_round(MPA a, int n) n 桁に丸め

プログラム・ソース("m_set.c")           top (トップに戻る)
/*		m_set.c		double --> MPA	*/
#include "mpa.h"

MPA m_set(double a)
{
	MPA m;
	int i;
	UINT *p;
	double t;

	m = _M0;
	if(a == 0.)	return m;
	m.zero = 0;
	if(a < 0.)
	{
		m.sign = 0;
		a = - a;
	}
	while(a >= (double)RADIX)
	{
		m.exp++;
		a /= (double)RADIX;
	}
	while(a < 1.)
	{
		m.exp--;
		a *= (double)RADIX;
	}
	p = m.num;
	i = 0;
	do
	{
		*p = (UINT)a;
		a -= (double)*p++;
		a *= (double)RADIX;
	} while(a != 0. && ++i <= NMPA);
	for(i++; i <= NMPA; i++)	*p++ = 0;
	return m;
}

/*		m_set_a			"xxx" --> MPA	*/

MPA m_set_a(char *s)
{
	MPA a, t;
	char *p;
	int c, exp, i, pflag, sign, zflag;
	UINT *q;

	p = s;
	sign = 1;
	if(*p == '-')
	{
		sign = 0;
		p++;
	}else if(*p == '+')	p++;
	a = t = _M0;
	t.zero = 0;
	exp = 0;
	pflag = zflag = 0;
	for(; *p != '\0'; p++)
	{
		if(*p == '.')
		{
			if(pflag)
			{
				fprintf(stderr, "Error : Illegal parameter in m_set_a()\n");
				return _M0;
			}
			pflag = 1;
		}
		else if(*p == 'E' || *p == 'e')
		{
			p++;
			exp -= atoi(p);
			break;
		}
		else if(*p == '+' || *p == '-')
		{
			exp -= atoi(p);
			break;
		}
		else if(*p != ' ' && (*p < '0' || *p > '9'))
		{
			fprintf(stderr, "Error : Illegal parameter  in m_set_a()\n");
			return _M0;
		}
		else
		{
			c = *p - '0';
			if(c != 0 || pflag != 0)	zflag = -1;
			else
			{
				if(zflag == 0)	zflag = 1;
				else if(zflag == 1)
				{
					fprintf(stderr, "Error : Illegal parameter  in m_set_a()\n");
					return _M0;
				}
			}
			m_mul1_s(&a, 10);
			if(c)
			{
				t.num[0] = c;
				a = m_add(a, t);
/*
				a = m_add_a(a, t);
*/
			}
			if(pflag == 1)	exp++;
		}
	}
	if(exp > MAXEXP)
	{
		fprintf(stderr, "Error : Overflow  in m_set_a()\n");
		return _MMAX;
	}
	if(exp < MINEXP)
	{
		fprintf(stderr, "Error : Underflow  in m_set_a()\n");
		return _M0;
	}
	a.sign = sign;
	if(exp > 0)	while(--exp >= 0)	m_div1_s(&a, 10);
	else		while(++exp <= 0)	m_mul1_s(&a, 10);
	m_z_chk(&a);
	return a;
}

/*		m_set_l.c		MPA <-- long	*/

MPA m_set_l(long n)
{
	MPA a;
	UINT *p, *q, w;

	a = _M0;
	if(n == 0L)	return a;
	a.zero = 0;
	if(n < 0L)
	{
		a.sign = 0;
		n = - n;
	}
	p = q = a.num;
	while(n != 0)
	{
		*p++ = n % RADIX;
		n /= RADIX;
		a.exp++;
	}
	a.exp--;
	p--;
	while(q < p)
	{
		w = *p;
		*p-- = *q;
		*q++ = w;
	}
	return a;
}

/*		m_int		integer MPA --> MPA		*/

MPA m_int(MPA a)
{
	int i;

	if(a.zero || a.exp < 0)	return _M0;
	if(a.exp >= NMPA)	return a;
	for(i = a.exp + 1; i <= NMPA; i++)	a.num[i] = 0;
	return a;
}

/*		m_frac			MPA - integer MPA --> MPA	*/

MPA m_frac(MPA a)
{
	MPA b;
	UINT *p, *q;
	int i;

	if(a.zero || a.exp >= NMPA)	return _M0;
	if(a.exp < 0)	return a;
	b.zero = 0;
	b.sign = a.sign;
	b.exp = -1;
	for(i = a.exp + 1, p = a.num + i, q = b.num; i <= NMPA; i++)
		*q++ = *p++;
	for(i = 0; i <= a.exp; i++)	*q++ = 0;
	return	b;
}

/*		m_round			round(MPA, n) --> MPA	*/

MPA m_round(MPA a, int n)
{
	MPA t;
	char s[15];

	sprintf(s, "+1.0e%d\0", n);
	t = m_set_a(s);
	return m_mul(m_int(m_add(m_div(a, t), m_set_a("0.5"))), t);
}