找回密码
 欢迎注册
楼主: forcal

[讨论] 用Forcal封装HugeCalc大数算法库

[复制链接]
发表于 2010-8-5 12:04:28 | 显示全部楼层
HugeCalc 的 C++ 接口中产生的临时变量管理机制是由 C++ 标准负责的,HugeCalc 并没有特别维护。(C 接口则有特别维护)

比如说,“c=a+b”,其实它调用了两个运算符:+、=
前者产生一个临时变量,然后赋值给显示变量,而后就可销毁了。
具体是否如此作为,得看C++机制了。

“(a+b)*(a+b) ”中共产生3个临时变量,但有两个是(a+b)产生的,它们是不同的临时对象,内存地址不会相同。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2010-8-5 12:33:05 | 显示全部楼层
我查到一个说明:C++运算符重载函数为值返回的时候会产生临时变量,临时变量与局部变量result的复制会调用拷贝构造函数,临时变量的生命周期是在拷贝构造函数运行完成后才结束。

这样说来,c=a+b,这是可以正常运行而没有内存泄露的,a+b产生了临时变量,直到赋值给c后该临时变量的生命期才结束。

但c=(a+b)*(a+b) ,产生的3个临时变量,只有最后一个赋值给c后可以正常销毁,而(a+b)产生的两个临时变量由于没有赋值,是不是没有销毁而存在内存泄露呢?

有点题外话了,但这个不是很懂,还是请教一下?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2010-8-5 13:09:32 | 显示全部楼层
(a+b) 应该是在调用乘法运算符后自动销毁的。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2010-8-5 15:26:11 | 显示全部楼层
(a+b) 应该是在调用乘法运算符后自动销毁的。
gxqcn 发表于 2010-8-5 13:09

恩,是这样的。
C++ 临时变量应该在导致临时变量创建的"完整表达式"求值过程的最后一个步骤被析构。

这样,脚本还得依靠自己管理临时变量。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2010-8-5 17:06:18 | 显示全部楼层
在Forcal脚本中将通过函数和运算符两种方式实现HugeCalc 的大数运算功能。

以加法为例,函数Add(a,b,c)将实现a=b+c,或者在函数oo中直接使用b+c。

对没有提供运算符的运算,用函数实现,如乘方,一般格式Pow(a,b,c)将实现a=b^c,在函数oo中可使用函数Pow(b,c),不过Pow(b,c)将返回一个临时对象。

在函数oo中使用运算符或函数,表达式将非常简洁,容易理解,但由于存在很多临时变量的生成和销毁,故效率较低。

个人感觉,C++提供了运算符重载,主要是为了用户的方便,效率将<=函数实现,故建议HugeCalc 在最新版本中增加与运算符重载等效的函数实现形式,所有函数的对象参数都用指针形式。一点个人意见,呵呵。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2010-8-6 08:05:44 | 显示全部楼层
运算符重载包括函数实现很难做到复杂的数学式的高效对象管理
需要有个好的方式管理内存
如果长度固定,可以采取不销毁的内存池方式
如果长度不固定,则不太好处理

考虑某些运算中,长度是线性增加的
也许有个不太好的方式不销毁内存而高效分配吧

说白了是自己实现局部垃圾回收
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2010-8-6 09:15:51 | 显示全部楼层
这种优化应该在编译器内部做(既然Forcal作为一种语言)
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2010-8-6 10:25:14 | 显示全部楼层
26# 无心人

恩,Forcal将自己实现局部垃圾回收,采用不销毁内存而高效分配方式。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2010-8-6 10:34:53 | 显示全部楼层
这种优化应该在编译器内部做(既然Forcal作为一种语言)
mathe 发表于 2010-8-6 09:15


Forcal是这样做的:外部模块(如Forcal扩展库)函数通知Forcal核心库哪些是临时变量,核心库通知外部模块哪些临时变量的生命期已结束,需要销毁。是否真正销毁临时变量由外部模块说了算。
计划在封装HugeCalc的扩展库中设置一个缓冲区,专门存放临时变量,一般并不真正销毁它,这样可提高效率。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2010-8-6 20:22:10 | 显示全部楼层
FcHugeCalc重新进行了更新,仍然使用1#的下载地址(需重新下载OpenFC)。

虽然函数并没有增加很多,但程序框架已较为完整,以后剩下的基本是体力活了。

函数名已更新,最新的说明如下:

=====================================
        Forcal扩展库之FcHugeCalc:郭先强超大整数完全精度快速算法库
=====================================

用法:

1、下载OpenFC,无需安装,仅需按readme设置好。

2、复制FcHugeCalc32W.dll和HugeCalc.dll两个文件到文件夹“OpenFC\dll”。

3、打开工作区文件“OpenFC.ini”,在#LOAD{... ...}中添加如下行:

        "dll\FcHugeCalc32W.dll"        //郭先强超大整数完全精度快速算法库

4、执行“设置->重载动态库扩展”。

5、可能需要注册后才能正常使用,参考“HugeCalc.chm”。

=====================================

当前可用的函数:

1、HugeCalc::SetHCMax(20000):设置最多可用的HugeCalc对象,默认最多10000个HugeCalc对象

2、HugeCalc::DelAllHC():销毁所有的HugeCalc对象

3、HugeCalc::NowHCNum(100):查看当前存在,尚未销毁的HugeCalc对象,最多显示100个对象

4、HugeCalc::NewHC(HugeCalc::HI)、HugeCalc::NewHC(HugeCalc::HIX)、HugeCalc::NewHC(HugeCalc::VUI32):申请HugeInt对象、申请HugeIntX对象、申请VECTOR_UINT32对象

5、HugeCalc::DelHC(p):销毁HugeCalc对象p,p是由函数newhc返回的对象指针

6、HugeCalc::SetStr(p,"123"):给HugeCalc对象p赋值为123

   HugeCalc::SetNum(p,123):给HugeCalc对象p赋值为123

   HugeCalc::Set(p,q):给HugeCalc对象p赋值为q,q也是HugeCalc对象

7、HugeCalc::Show(p):输出HugeCalc对象p的内容

8、HugeCalc::Add(a,b,c):计算a=b+c,在函数oo可直接用运算符计算b+c,返回一个临时对象

9、HugeCalc::Sub(a,b,c):计算a=b-c,在函数oo可直接用运算符计算b-c,返回一个临时对象

10、HugeCalc::Mul(a,b,c):计算a=b*c,在函数oo可直接用运算符计算b*c,返回一个临时对象

11、HugeCalc::Div(a,b,c):计算a=b/c,在函数oo可直接用运算符计算b/c,返回一个临时对象

12、HugeCalc::Mod(a,b,c):计算a=b%c,在函数oo可直接用运算符计算b%c,返回一个临时对象

13、HugeCalc::Pow(a,b,c):计算a=b^c,a、b为HugeCalc对象,c为整数;在函数oo中可使用Pow(b,c),返回一个临时对象

14、HugeCalc::Fac(a,100):计算a=100!

15、HugeCalc::NextPrime(a,b):计算a=比b大的最小的素数

16、HugeCalc::GT(a,b):关系运算a>b,在函数oo可直接使用此关系运算符,返回逻辑值

17、HugeCalc::GE(a,b):关系运算a>=b,在函数oo可直接使用此关系运算符,返回逻辑值

18、HugeCalc::LT(a,b):关系运算a<b,在函数oo可直接使用此关系运算符,返回逻辑值

19、HugeCalc::LE(a,b):关系运算a<=b,在函数oo可直接使用此关系运算符,返回逻辑值

20、HugeCalc::EQ(a,b):关系运算a==b,在函数oo可直接使用此关系运算符,返回逻辑值

21、HugeCalc::NE(a,b):关系运算a!=b,在函数oo可直接使用此关系运算符,返回逻辑值

=====================================

例子1:
  1. SetTalk[false];                //关闭计算结果及运行错误输出,并不阻止函数的输出
  2. !using["HugeCalc"];        //使用命名空间HugeCalc,可简化函数的使用
  3. mvar:                        //使用隐含模块变量声明方式
  4. i: printff["\r\n"],        //输出一个换行符
  5.    a=NewHC[HI].SetStr["1111111111111111111111111111111"].free[],        //申请HugeInt对象并赋值,自动销毁该对象
  6.    b=NewHC[HI].SetStr["11111111112222222222222"].free[],                //申请HugeInt对象并赋值,自动销毁该对象
  7.    c=NewHC[HI].Add[a,b].Show[].free[],        //申请HugeInt对象c,计算c=a+b并输出结果,自动销毁该对象
  8.    printff["\r\n"],                        //输出一个换行符
  9.    oo{[a+(b+c)+(a+b)].Show[]};                //函数oo中的运算符是重载的,计算a+(b+c)+(a+b)并输出结果
复制代码
-------------------------------------

例子2:
  1. SetTalk[false];
  2. !using["HugeCalc"];
  3. mvar:
  4. i: printff["\r\n"],
  5.    a=NewHC[HI].SetStr["1111111111111111111111111111111"].free[],
  6.    b=NewHC[HI].SetNum[1111111122222222].free[],
  7.    oo{[c=a%b, a+(b-a%b)*(a+b/c)].Show[]};
复制代码
-------------------------------------

例子3:
  1. !using["HugeCalc"];
  2. mvar:
  3. i: oo{
  4.         printff["\r\n"],
  5.         //函数oofree[]指出由oo函数销毁该对象
  6.         a=NewHC[HI].SetStr["1111111111111111111111111111111"].oofree[],
  7.         b=NewHC[HI].SetStr["11111111112222222222222"].oofree[],
  8.         {d=[a*b], c=Pow(a,10), a+(d-Pow(a,50)%b)*(c+c/b)}.Show[]
  9.    };
复制代码
-------------------------------------

例子4:
  1. !using["HugeCalc"];
  2. mvar:
  3. t0=sys::clock();
  4. i: printff["\r\n"],
  5.    a=NewHC[HI].SetNum[10000000].free[],
  6.    b=NewHC[HI].SetNum[20000000].free[],
  7.    c=NewHC[HI].SetNum[0].free[],
  8.    aa=NewHC[HI].free[],
  9.    i=0, a.NextPrime[a], aa.NextPrime[a],
  10.    while{LE(aa,b),
  11.      oo{
  12.        dd=[a*aa], cc=Pow(aa,50),
  13.        c.Set[c+Pow(a,100)*(a+aa)*(a*aa%(a+b))+(c+cc)/dd]
  14.      },
  15.      a.Set[aa], aa.NextPrime[a],
  16.      i++
  17.    },
  18.    c.Show(),
  19.    i;
  20. [sys::clock()-t0]/1000;
复制代码
=====================================

forcal        2010.8.6
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-3-29 10:18 , Processed in 0.046225 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表