第3章 基本操作

本文详细介绍了TomMath库中用于mp_int结构的操作,包括mp_copy实现的结构拷贝、mp_init_copy的结构克隆、mp_zero的结构清零、mp_abs的取绝对值、mp_neg的取反以及mp_set和mp_set_int的常量设置。同时展示了这些操作的原理、实现和使用示例,涉及到了无符号和有符号的比较功能mp_cmp_mag和mp_cmp。
摘要由CSDN通过智能技术生成

第3章 基本操作

3.1 简介

在这里插入图片描述

3.2 为mp_int结构赋值

3.2.1 拷贝一个mp_int

mp_copy的原理

在这里插入图片描述

mp_copy的实现
		/*拷贝mp_int结构a到mp_int结构b*/
18		/* copy, b = a */
19		int 
20		mp_copy (mp_int * a, mp_int * b)
21		{
22		  int     res, n;
23
			/*mp_int结构a和b是同一个,则立刻返回*/
24		  /* if dst == src do nothing */
25		  if (a == b) {
26			return MP_OKAY;
27		  }
28
			/*如果b的alloc小于a的used(即b分配的内存太小),则对b进行grow操作*/
29		  /* grow dest */
30		  if (b->alloc < a->used) {
31			 if ((res = mp_grow (b, a->used)) != MP_OKAY) {
32				return res;
33			 }
34		  }
35
36		  /* zero b and copy the parameters over */
37		  {
			/*Register变量是C语言中允许将局部变量的值放在CPU中的寄存器中需要时直接从寄存器中取出来参加运算,不必再到内存中提
			取,但是计算机系统中寄存器数量有限,不能任意定义任意多的存储器,局部静态变量不能定义为寄存器变量。*/
38			register mp_digit *tmpa, *tmpb;
39
40			/* pointer aliases */
41
42			/* source */
43			tmpa = a->dp;
44
45			/* destination */
46			tmpb = b->dp;
47
			/*对于a.used到b.used-1之间的n,执行b_n=a_n*/
48			/* copy all the digits */
49			for (n = 0; n < a->used; n++) {
50			  *tmpb++ = *tmpa++;
51			}
52
			/*对于a.used到b.used-1之间的n,执行b_n=0*/
53			/* clear high digits */
54			for (; n < b->used; n++) {
55			  *tmpb++ = 0;
56			}
57		  }
58
			/*将a的used值和sign值赋值给b*/
59		  /* copy used count and sign */
60		  b->used = a->used;
61		  b->sign = a->sign;
62		  return MP_OKAY;
63		}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

mp_copy的使用
#include <stdio.h>
#include <stdlib.h>

#include "utils.h"

int main(){
    printf("hello libtommath\n");

    mp_int a,b;
    mp_init_multi(&a,&b,NULL);
    mp_read_radix(&a,"0A0B0C0D",16);
    mp_copy(&a,&b);
    printf("结构a的值为:");
    for(int i=0;i<a.used;i++)
    {
        printf("%.8lx  ",*(a.dp+i));
    }
    printf("\n结构b的值为:");
    for(int i=0;i<b.used;i++)
    {
        printf("%.8lx  ",*(b.dp+i));
    }
    return 0;
}
=================================================
:~/workspace/tommath_test$ ./a.out 
hello libtommath
结构a的值为:0a0b0c0d  
结构b的值为:0a0b0c0d

3.2.2 克隆

mp_init_copy的原理

在这里插入图片描述

mp_init_copy的实现
18		/* creates "a" then copies b into it */
19		int mp_init_copy (mp_int * a, mp_int * b)
20		{
21		  int     res;
22
			/*对a进行初始化*/
23		  if ((res = mp_init (a)) != MP_OKAY) {
24			return res;
25		  }
			/*将b复制给a*/
26		  return mp_copy (b, a);
27		}

在这里插入图片描述

mp_init_copy的使用
#include <stdio.h>
#include <stdlib.h>

#include "utils.h"

int main(){
    printf("hello libtommath\n");

    mp_int a,b;
    mp_init(&a);
    mp_read_radix(&a,"0A0B0C0D",16);
    mp_init_copy(&b,&a);
    printf("结构a的值为:");
    for(int i=0;i<a.used;i++)
    {
        printf("%.8lx  ",*(a.dp+i));
    }
    printf("\n结构b的值为:");
    for(int i=0;i<b.used;i++)
    {
        printf("%.8lx  ",*(b.dp+i));
    }
    return 0;
}
==============================================
:~/workspace/tommath_test$ ./a.out 
hello libtommath
结构a的值为:0a0b0c0d  
结构b的值为:0a0b0c0d

3.3 将整数清零

mp_zero的原理

在这里插入图片描述

mp_zero的实现
		/*将mp_int重置成初始状态*/
18		/* set to zero */
19		void mp_zero (mp_int * a)
20		{
21		  int       n;
22		  mp_digit *tmp;
23
			/*设置sign和used的值*/
24		  a->sign = MP_ZPOS;
25		  a->used = 0;
26
27		  tmp = a->dp;
			/*将mp_int中的数据赋值为0*/
28		  for (n = 0; n < a->alloc; n++) {
29			 *tmp++ = 0;
30		  }
31		}

在这里插入图片描述

mp_zero的使用
#include <stdio.h>
#include <stdlib.h>

#include "utils.h"

int main(){
    printf("hello libtommath\n");

    mp_int a,b;
    mp_init(&a);
    mp_read_radix(&a,"0A0B0C0D",16);
    printf("结构a的值为:");
    for(int i=0;i<a.used;i++)
    {
        printf("%.8lx  ",*(a.dp+i));
    }
    mp_zero(&a);
    printf("\n结构a的值为:");
    for(int i=0;i<a.used;i++)
    {
        printf("%.8lx  ",*(a.dp+i));
    }
    return 0;
}
===============================================
:~/workspace/tommath_test$ ./a.out 
hello libtommath
结构a的值为:0a0b0c0d  
结构a的值为:

3.4 符号操作

3.4.1 绝对值

mp_abs的原理

在这里插入图片描述

mp_abs的实现
18		/* b = |a| */
19		/**/
20		/* Simple function copies the input and fixes the sign to positive*/
21		/**/
22		int
23		mp_abs (mp_int * a, mp_int * b)
24		{
25		  int     res;
26
			/*如果a!=b,则将a复制到b*/
27		  /* copy a to b */
28		  if (a != b) {
29			 if ((res = mp_copy (a, b)) != MP_OKAY) {
30			   return res;
31			 }
32		  }
33
			/*将b的sign赋值为MP_ZPOS*/
34		  /* force the sign of b to positive */
35		  b->sign = MP_ZPOS;
36
37		  return MP_OKAY;
38		}

在这里插入图片描述

mp_abs的使用
#include <stdio.h>
#include <stdlib.h>

#include "utils.h"

int main(){
    printf("hello libtommath\n");

    mp_int a,b;
    mp_init_multi(&a,&b,NULL);
    mp_read_radix(&a,"-0A0B0C0D",16);
    printf("a的sign值为:%d\n",a.sign);
    mp_abs(&a,&b);
    printf("b的sign值为:%d\n",b.sign);
    return 0;
}
================================================
:~/workspace/tommath_test$ ./a.out 
hello libtommath
a的sign值为:1
b的sign值为:0

3.4.2 整数取反

mp_neg的原理

在这里插入图片描述

mp_neg的实现
		/*对mp_int整数进行取反运算*/
18		/* b = -a */
19		int mp_neg (mp_int * a, mp_int * b)
20		{
21		  int     res;
			/*如果a和b不相等,则将a复制到b*/
22		  if (a != b) {
23			 if ((res = mp_copy (a, b)) != MP_OKAY) {
24				return res;
25			 }
26		  }
27
			/*如果b不为0,则将b的符号变换*/
28		  if (mp_iszero(b) != MP_YES) {
29			 b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS;
30		  } else {
			/*如果b为0,则将b的符号置为MP_ZPOS*/
31			 b->sign = MP_ZPOS;
32		  }
33
34		  return MP_OKAY;
35		}

在这里插入图片描述

mp_neg的使用
#include <stdio.h>
#include <stdlib.h>

#include "utils.h"

int main(){
    printf("hello libtommath\n");

    mp_int a,b;
    mp_init_multi(&a,&b,NULL);
    mp_read_radix(&a,"0A0B0C0D",16);
    printf("a的sign值为:%d\n",a.sign);
    mp_neg(&a,&b);
    printf("b的sign值为:%d\n",b.sign);
    return 0;
}
==================================================
:~/workspace/tommath_test$ ./a.out 
hello libtommath
a的sign值为:0
b的sign值为:1

3.5 小常量

3.5.1 设置小常量

mp_set的原理

在这里插入图片描述

mp_set的实现
		/*将mp_int设置成一个相对较小的值*/
18		/* set to a digit */
19		void mp_set (mp_int * a, mp_digit b)
20		{
			/*将a清零*/
21		  mp_zero (a);
			/*对a_0进行赋值*/
22		  a->dp[0] = b & MP_MASK;
			/*对used进行赋值*/
23		  a->used  = (a->dp[0] != 0) ? 1 : 0;
24		}

在这里插入图片描述

mp_set的使用
#include <stdio.h>
#include <stdlib.h>

#include "utils.h"

int main(){
    printf("hello libtommath\n");

    mp_int a;
    mp_digit b=5;
    mp_init(&a);
    mp_read_radix(&a,"0A0B0C0D",16);
    printf("a的数据值为:%lx\n",*(a.dp));
    mp_set(&a,b);
    printf("a的数据值为:%lx\n",*(a.dp));
    return 0;
}
===============================================
:~/workspace/tommath_test$ ./a.out 
hello libtommath
a的数据值为:a0b0c0d
a的数据值为:5

3.5.2 设置大常量

mp_set_int的原理

在这里插入图片描述

mp_set_int的实现
		/*对mp_int整数a赋值一个长数据类型*/
18		/* set a 32-bit const */
19		int mp_set_int (mp_int * a, unsigned long b)
20		{
21		  int     x, res;
22
			/*将a清零*/
23		  mp_zero (a);
24		  
			/*一次移动4位*/
25		  /* set four bits at a time */
26		  for (x = 0; x < 8; x++) {
27			/* shift the number up four bits */
28			if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) {
29			  return res;
30			}
31
32			/* OR in the top four bits of the source */
33			a->dp[0] |= (b >> 28) & 15;
34
35			/* shift the source up to the next four bits */
36			b <<= 4;
37
38			/* ensure that digits are not clamped off */
39			a->used += 1;
40		  }
41		  mp_clamp (a);
42		  return MP_OKAY;
43		}

在这里插入图片描述

mp_set_int的使用
#include <stdio.h>
#include <stdlib.h>

#include "utils.h"

int main(){
    printf("hello libtommath\n");

    mp_int a;
    unsigned long b=0x31415926;
    mp_init(&a);
    mp_read_radix(&a,"0A0B0C0D",16);
    printf("a的数据值为:%lx\n",*(a.dp));
    mp_set_int(&a,b);
    printf("a的数据值为:%lx\n",*(a.dp));
    return 0;
}
==================================================
:~/workspace/tommath_test$ ./a.out 
hello libtommath
a的数据值为:a0b0c0d
a的数据值为:31415926

3.6 比较

3.6.1 无符号数比较

mp_cmp_mag的原理

在这里插入图片描述

mp_cmp_mag的实现
		/*无符号数的比较*/
18		/* compare maginitude of two ints (unsigned) */
19		int mp_cmp_mag (mp_int * a, mp_int * b)
20		{
21		  int     n;
22		  mp_digit *tmpa, *tmpb;
23
			/*如果a.used大于b.used,则直接返回a>b*/
24		  /* compare based on # of non-zero digits */
25		  if (a->used > b->used) {
26			return MP_GT;
27		  }
28		  
			/*如果a.used小于b.used,则直接返回a<b*/
29		  if (a->used < b->used) {
30			return MP_LT;
31		  }
32
33		  /* alias for a */
34		  tmpa = a->dp + (a->used - 1);
35
36		  /* alias for b */
37		  tmpb = b->dp + (a->used - 1);
38
			/*从高位开始进行比较*/
39		  /* compare based on digits  */
40		  for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
41			if (*tmpa > *tmpb) {
42			  return MP_GT;
43			}
44
45			if (*tmpa < *tmpb) {
46			  return MP_LT;
47			}
48		  }
49		  return MP_EQ;
50		}

在这里插入图片描述

mp_cmp_mag的使用
#include <stdio.h>
#include <stdlib.h>

#include "utils.h"

int main(){
    printf("hello libtommath\n");

    mp_int a,b;
    mp_init_multi(&a,&b,NULL);
    mp_read_radix(&a,"0A0B0C0D",16);
    mp_read_radix(&b,"-0A0B0C0D",16);
    int ret = mp_cmp_mag(&a,&b);
    printf("a和b比较的结果:%d\n",ret);
    return 0;
}
=================================================
:~/workspace/tommath_test$ ./a.out 
hello libtommath
a和b比较的结果:0

3.6.2 有符号数比较

mp_cmp的原理

在这里插入图片描述

mp_cmp的实现
		/*有符号数比较*/
18		/* compare two ints (signed)*/
19		int 
20		mp_cmp (mp_int * a, mp_int * b)
21		{
			/*如果a和b的符号不同*/
22		  /* compare based on sign */
23		  if (a->sign != b->sign) {
				/*如果a的符号为负,则b的符号为正,a<b*/
24			 if (a->sign == MP_NEG) {
25				return MP_LT;
				/*如果a的符号为正,则b的符号为负,a>b*/
26			 } else {
27				return MP_GT;
28			 }
29		  }
30		  
			/*a和b符号相同的情况*/
31		  /* compare digits */
			/*如果a和b都是负数,则比较mp_cmp_mag(b,a)*/
32		  if (a->sign == MP_NEG) {
33			 /* if negative compare opposite direction */
34			 return mp_cmp_mag(b, a);
			/*如果a和b都是正数,则比较mp_cmp_mag(a,b)*/
35		  } else {
36			 return mp_cmp_mag(a, b);
37		  }
38		}

在这里插入图片描述

mp_cmp的使用
#include <stdio.h>
#include <stdlib.h>

#include "utils.h"

int main(){
    printf("hello libtommath\n");

    mp_int a,b;
    mp_init_multi(&a,&b,NULL);
    mp_read_radix(&a,"0A0B0C0D",16);
    mp_read_radix(&b,"-0A0B0C0D",16);
    int ret = mp_cmp(&a,&b);
    printf("a和b比较的结果:%d\n",ret);
    return 0;
}
=================================================
:~/workspace/tommath_test$ ./a.out 
hello libtommath
a和b比较的结果:1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值