《科学不是用来被宗教骑劫的》

《科学不是用来被宗教骑劫的》
作者:伍思源


  关键词:形而上学(Metaphysics)、伪科学(Pseudoscience)、骑劫(Hijacking)、量子力学、量子纠缠、量子神秘主义(Quantum mysticism)、心灵感应、平行宇宙、量子佛学。

一、“有些事情是科学解析不了的”、“好多事情都是科学无法解析的”、“科学的尽头是神学”、“科学的尽头是哲学,哲学的尽头是佛学”、“当科学家们历尽千辛攀登上真理的顶峰时,却发现神学家们早已在那里等待了几千年”——类似这样的话,读者朋友们是否有听说过?二十一世纪,如果还有人说这样的话,要么他是别有用心,要么他就是纯纯粹粹的无知兼且还喜欢人云亦云(前半句很好理解:宗教信徒为了弱化科学的作用而故弄玄虚,企图浑水摸鱼、诱导他人接受灵魂假说;而后半句,则是一般人所不能或不愿接受的——这也是本文讨论的重点)

当下最热的话题莫过于量子力学、量子纠缠,见下面网址
量子力学:en.wikipedia.org/wiki/Quantum_mechanics
量子纠缠:en.wikipedia.org/wiki/Quantum_entanglement
我不知道读者朋友们打开这两个网址看了内容之后会有什么感受?我的感受就是大学四年的数学都白读了:里面出现的公式、函数,我居然几乎连标点符号都看不懂。
问题的提出:既然量子力学、量子纠缠那么难理解(我从未在任何一篇相关的文章当中能够找到有效的、合理的、全面的数据分析),为什么还会有那么多人(甚至连跳广场舞的大妈都在把弄“量子”一词,比如“量子佛学”)热衷于讨论呢?

量子力学、量子纠缠相关的数学公式、函数,一般人是不能理解的(当然也包括我),但是以下描述(爱因斯坦对量子纠缠的描述)却很好理解:“spooky action at a distance”,翻译过来大意就是“鬼魅般的远距离作用(效应)”——“鬼魅”?看来量子纠缠是一个颠覆一般人认知、逻辑的事物。
下面本人也将为大家介绍一个“鬼魅”般的事物(一个一般程序员都能驾驭的事物),然后分析一下这个“鬼魅”般事物背后的真相,最后回归到量子纠缠以及由此而“衍生”出来的量子神秘主义(如心灵感应、平行宇宙)

------------------------------------------------
我们的日常生活离不开各种形形色色的电子数据,而这些数据,概括起来主要有两种状态:储存状态和传输状态。这两种状态一般都需要和物理介质打交道(比如硬盘、光盘、闪存、光纤、电缆、大气),那么问题来了:因为介质的因素(比如硬件故障或老化、电磁或电流干扰)而导致储存或传输的数据出错,这个时候应该怎么办?
如果是数据传输的话,那么还好办一些:根据相应的协议或机制重传数据就可以了(事实上,如果有一点点错误就重传数据的话,那么,数据的传输效率将会变得非常非常低),问题是,如果连储存设备的数据(假设所有的数据都是孤本)也出错了,怎么办?这可是连重来的机会都没有啊(在高度集成化的硬盘盘片里面,“比特”是会经常出错的)

有没有一种“化腐朽为神奇”的方法,可以将错误的数据自动还原过来呢?——这听起来有点不可思议,但是这种技术在我们的日常生活中却会经常用到:“二维码”就是其中一个非常经典的例子(注:二维码的种类有很多,下面是最常见的QR码)
我们看上面的两个二维码:左边的那个是一个网址来的(chinaren),右边的那个是我在左边的基础上遮盖了一张小女孩图片,两者都可以正常扫码访问——这就奇怪了,为什么右边的二维码,明明被盖住了一部分内容(假设这导致字符串chinaren在被识别的时候变成了chinexen),仍然可以被正确识别?我们知道,要访问一个网站的时候,网址是不能出错的,显然,在这里,我们的扫码软件已经自动把这个错误纠正过来了(字符串chinexen被扫码软件还原成chinaren
------------------------------------------------

本文要介绍给大家认识的“鬼魅”般的事物就是“RS码”,之所以说“鬼魅”,是因为它能够自我修复(有了这样东西,“心有灵犀”从某种意义上来说就实现了:两个人之间的通信,即使有第三者干扰,仍然可以做到无差错交流)
注一:RS码是BCH码的子集,在QR码中,BCH(15,5) 用于存放纠错等级和掩码图形信息,BCH(18,6) 用于存放版本信息。
注二:类似于RS码的编码还有很多,比如卷积码、Turbo码、LDPC码、ECC码(ECC码比较高速,但纠错能力就没有那么强,一般用于数据存储或信道较稳定的数据传输)

附录一和附录二分别给出了RS码的编码和译码函数,下面我们来做一个小实验:
1、【张三】用编码函数对数据码字(781481441458939911029519510381108639100)进行编码,得出纠错码字(4719316615521718452052211),然后将它们串联成一整体(码字数组),发送给王五,见下图。
2、【李四】对张三发出的码字数组进行干扰,假设被干扰之后,码字数组变成(101481441458939911022001951038110863910017719316615516818602052211
注:上面红色部分的码字就是异常码字(异常数据),异常数据可以出现在任何位置(包括纠错码字:这也是循环码最神奇的地方),可以断续,也可以连续。
3、【王五】用译码函数对收到的、已经受到干扰的码字数组进行还原,见下图。
注:原本有错的数据已经还原过来了(王五已经“领悟”到张三想说什么了)




二、在科学领域,颠覆人认知的事物,往往是需要满足一定的条件才能够出现或发生的,而且,即使出现或发生了,也有其局限性。
上面介绍的“RS码”需要满足的条件或局限性有几个:码字总数有固定限制(不能多也不能少,不够的话要用填充码字补够)、数据码字数量和纠错码字数量也有固定限制(要想获得更强的纠错能力,纠错码字占比就要更大)、码字数据必须为零或正整数(整数值也有上限)、出错的码字总数不能超过一定的数量(否则无法纠错)——这些都取决于相关的数学参数(比如伽罗瓦域的大小、本原多项式的值)
注:上面的实验,rs(26,16) 需要满足的条件和局限性如下:一、码字总数要为26个,其中数据或填充码字16个,纠错码字10个;二、码字的数值范围是0~255;三、可纠错码字数最多为5个(局限性)

量子的种类有很多,而要使量子发生纠缠的方法也有好几种,最常见的方法就是利用光量子(光子),那么,要使光量子发生纠缠,需要满足的条件又是什么?
我们回到量子纠缠的维基资料页面,见下图:
从上图可知,要使光量子发生纠缠,起码要满足两个条件:
1、持续稳定的高功率光源(比如激光束),用以产生满足实验所需的光量子。
2、特定材质的透光靶(比如偏硼酸钡晶体、磷酸二氢钾晶体【用于产生偏振方向相同的纠缠的光量子对】),这些非线性晶体可以令前面产生的光量子发生衰变并分裂成两个互相纠缠的光量子(这个过程又叫做“自发性参数下转换”或“参数散射”,资料见下)
注一:即使上述两个条件都满足了,纠缠光量子对的获得率也是非常低的(大约只有十亿分之一的几率),而要想获得纠缠的光量子组(纠缠的光量子数大于两个),所需的条件将会更加复杂。
注二:要使光量子与原子发生纠缠,传统上,涉及几个关键的步骤:低噪或真空环境的制备;超冷原子(用激光可以把中性的重金属原子【比如铷原子、铯原子】冷却到接近绝对零度)的制备和捕捉(使用超冷原子可以减少、减轻原子与原子之间的碰撞,从而提高纠缠的成功率);(用静磁场)使原子的自旋(spins)方向对齐(磁场方向);单个光量子的介入与检测,下面是一份相关的研究报告:
www.nature.com/nature/journal/v519/n7544/full/nature14293.html
注三:原子与原子之间的纠缠(非核裂变:理论上核裂变也可以产生量子纠缠,但是裂变后不仅会产生新的原子,还会产生中子,要检测这些新量子的属性和维持它们的纠缠状态可以说非常困难,故而应用意义不大【又或者说没这个必要】),目前(2017年)只有依靠光量子才能实现(把光量子与光量子之间的纠缠转化成原子与原子【或离子与离子】之间的纠缠,这个过程又叫做“entanglement swapping”,纠缠交换,相关研究报告见下)
www.nature.com/nphys/journal/v3/n10/full/nphys700.html
注四:理论上,一个光量子是可以通过衰变分裂成多个光量子的(可以想象一下光的衍射现象),而且这一过程遵循能量守恒定律、动量守恒定律(这也就意味着新的光量子波长会更长),更多关于“自发性参数下转换”(SPDC)的介绍请见下面网址:
en.wikipedia.org/wiki/Spontaneous_parametric_down-conversion
注五:更多关于光量子“分裂”(split)的文章请参见下面网址:
physics.aps.org/story/v10/st3 (一分为二)
www.nature.com/news/2010/100728/full/news.2010.381.html (一分为三)
注六:在上面的表述中,我使用了“衰变”(decay)一词,出自于下面网址:
physicsworld.com/cws/article/news/2012/oct/25/physicists-entangle-100000-photons
注七:通过“自发性参数下转换”(SPDC)这种方法获得的纠缠光量子对往往不能满足实际通信应用的需要(因为其产生的光量子的波长太短,无法与光纤兼容),目前普遍使用“spontaneous four-wave mixing”(SFWM)这种方法产生窄带(波长较长)的纠缠光量子对,介绍从略(可以想象一下光的干涉现象,同样地,也遵循相关的守恒定律)


量子与量子之间的纠缠,其局限性又是什么?
纠缠量子对(或组)的制备条件越复杂,其纠缠状态就越难维持。比如“光量子与原子”、“原子与原子”之间的纠缠状态,目前在实验室的维持时间还是微秒(microseconds)级的。
“光量子与光量子”之间的纠缠状态,其维持时间应该要持久一些,因为光量子没有静止质量、没有核心(也就不那么容易受到干扰),只是一种能量波。


截至本段落,前面讨论量子纠缠的产生条件、局限性,其目的是想告诉大家,即使纠缠粒子(量子)之间真的存在着所谓的超光速(甚至是瞬时的)相互作用,那么,这种作用也是不可能常态般存在的。




三、量子纠缠是什么?下面我分成了几个部分来进行描述(之所以要这么做,是因为量子世界与宏观世界很不一样:这也是人们容易对量子纠缠产生误解的原因)

何为纠缠:所谓“纠缠”,其实是指属性相关(关联)。一双鞋子,一左,一右,就是一种纠缠:假设你手里端着左脚用的鞋子,那么,即使另一只鞋子远在天涯海角,你也必定知道它是右脚用的——在这个例子中,“左”和“右”就是鞋子的两个相关属性值。
注一:在量子层面又有什么属性是可以相关的?答案有:动量(或角动量)、位矢、自旋、极化(偏振方向)、能量等,它们的相关,多是基于各种守恒定律(比如角动量守恒定律、能量守恒定律、动量守恒定律),简单如“一加负一等于零”。
注二:接上面第一点,量子的属性以及对应值可参考:en.wikipedia.org/wiki/Qubit
注三:纠缠粒子(量子)之间并不存在着超光速(甚至是瞬时的)相互作用。正如前面所述的例子,假设我在地球,两只鞋子分别被发送到了月球和火星,当我知道月球上的鞋子是“左”时,瞬间就可以确定火星上的鞋子是“右”了(火星到地球的距离,即使是光也要跑上三五分钟,而我“瞬间”就知道火星上的情况了,可是,这能说明我获知信息的速度比光速还要快吗?显然不能,这完全就是两种概念,不可比较)
注四:接上面第三点,爱因斯坦的“鬼魅般的远距离作用(效应)”这句话,可以这样理解:“火星上有鬼!它可以瞬间把鞋子的信息传递给地球上的我”。
注五:量子纠缠的应用场景,目前主要还是通信加密(通过光量子与光量子之间的纠缠【偏振方向上的纠缠】,实现密钥【私钥】的分发;这是一种对称的加密方法,虽然容易被破解,但是却不容易被窃听【量子不可克隆】),具体密钥的生成原理参见下面网址:
en.wikipedia.org/wiki/Quantum_key_distribution
注六:接上面第五点,目前我们最常用的通信加密协议是SSL,它是基于RSA算法(一种非对称的加密方法)实现的,具体见:en.wikipedia.org/wiki/RSA_(cryptosystem)

波粒二象性:所有的微观粒子(量子)都同时具有粒子和波的特性——这也就意味着量子是无法静止的(除非达到绝对零度),一直在波动、振动(这点非常关键!)

量子态叠加:量子纠缠,指的是多个量子之间的属性关联,而量子态叠加,指的则是单个量子的某个属性值是动态变化的(故而存在两种,甚至是多种可能),只有经过测量才能够确定(不同时间的测量,得出的结果往往也是不一样的);在测量之前,量子的属性状态处于“叠加态”(在量子物理学的角度,叠加态就是所有可能属性状态的线性叠加)
注:线性叠加,就是把所有的可能的属性状态相加,这些状态,可以单个出现,可以部分出现,也可以全部同时出现——这仅仅是一种数学表达方式,与物理逻辑无关,我们见下面的数学表达式:
以原子的“位置”属性为例,由于原子是一直在振动的(量子的“波”特性),所以它的“位置”属性值也是不固定的(这一秒还在A点,下一秒就在B点了),只能说是在某个范围之内(具体波函数样例图片请参见下面的“量子态坍缩”)
注一:“范围”是由无数个位置点组成的,在没有被观测之前,原子可以处于振动范围内的任意位置点,即,原子的“位置”属性叠加态是“无数个位置点的线性叠加”。
注二:接上面第一点,假设我的“位置”属性叠加态是“上海、北京、广州,三地线性叠加”,那么我能同时处于这几个城市吗?在量子物理学、数学的角度,这是可以的。

以原子的“能级”属性为例,在没有被激发之前,它是处于“基态”的(电子绕近核轨道运动),由于其它原子的碰撞(又或者是电磁波的介入),它又可以处于“激发态”(电子绕远核轨道运动),可见,“能级”属性值也是只有经过观测才能确定的。

以电子的“自旋”属性为例(见下图),有时候它与原子的自旋方向相同,有时候它与原子的自旋方向相反,但更多的时候是不相同也不相反...
注:更多关于量子态叠加的资料请参见:
en.wikipedia.org/wiki/Quantum_superposition

量子态坍缩(波函数坍缩):量子的动态属性可以通过波函数来表示,比如“位置”属性,我们看下图:

在没有被测量之前,波函数(左图)很形象地反映了量子在空间中的位置、振动范围,经过测量之后,量子的位置属性值也就确定了(一个临时的确定值),波函数图形(右图)变成了一根柱子。从丰满的“波浪”图形变成了瘦削的“柱子”图形,我们把这一变化过程称之为“量子态坍缩”(波函数坍缩)
注一:由于量子已经是最小的物理实体(physical entity),所以任何的对量子的测量都会影响到其相关的属性和状态——这极有可能导致被测量子系统的状态发生改变(比如原有的量子之间的纠缠会被破坏:纠缠系统也就不复存在了)
注二:波函数坍缩只是一个人为选择的数学变化过程;“测量”这一动作并没有让量子的运动停下来,测量完之后量子将会恢复到叠加态。




四、量子神秘主义就是宗教信徒们对量子力学、量子纠缠的歪曲和唯心化解读——这是一种骑劫行为(由于普通人对量子力学、量子纠缠难以理解,所以他们在描述的时候可以很轻易地把自己的主观思想夹带进去,继而诱导他人相信和接受灵魂假说)

对量子力学的骑劫:“量子力学的惊人发现:一个粒子同時在三千个地方分身”、“量子力学证实佛法:粒子分身三千处!一切心想生!”。
注:我们在讨论“量子态叠加”的时候就已经分析过了:量子的位置属性的叠加态是由无数个可能位置线性叠加而成的(在量子物理学、数学的角度,这等同于“量子可以同时存在于这无数个地方”),然而,线性叠加终究只是一种数学表达方式,与物理逻辑无关,实际上,一个量子,一个确定的时间,只能处于一个地方(即量子态坍缩)

对量子纠缠的骑劫:“心灵感应”、“平行宇宙”。
支撑“理论”:纠缠量子之间存在着远距离的、超光速(瞬时)的相互作用。

心灵感应跟量子纠缠是如何扯上关系的?
假设有两个大脑,构成两个大脑的粒子(量子)是互相纠缠的,那么,当其中一个大脑在思考问题的时候,另一个大脑也必然会作出反应,而且由于“量子纠缠”的关系,两个大脑将会得出相同的思考结果——心有灵犀呀

平行宇宙跟量子纠缠是如何扯上关系的?
由于“量子纠缠”的相互作用距离是可以无限远的(而且是瞬时的),那么,有没有这么一个宇宙,它的构成粒子(量子)和我们所处宇宙的构成粒子(量子)是互相纠缠的呢?如果有的话,根据量子纠缠“理论”,我们在这个宇宙做什么,另一个宇宙的“他们”也会做什么,比如说,我吃饭的时候,另一个宇宙的“我”也在吃饭

上面这些脱离量子力学、量子纠缠本质的表述,只能算是望文生义、脑洞大开,就连形而上学、伪科学都够不上。




致谢:附录一和附录二的源代码由五邑大学心月湖工作室研发中心提供。

全文完



附录一:RS码的编码函数
/*
-------- 说明 --------
一、这是 ReedSolomon 纠错码字的生成函数。
二、请将本部分的代码保存成 C 文件(如 encode.c)以便测试。
三、测试环境:turboc 2.0
关键参数:
nd】数据码字数。
nc】纠错码字数。
wd[]】测试数组(整形、十进制),数组长度等于数据码字数加纠错码字数。
gf】伽罗瓦域的大小(这里是256,即二的八次方)
pp】多项式(这里是285,即100011101,多项式为x^8+x^4+x^3+x^2+1
*/
#include <malloc.h>
void main()
{
int i,j,k;
int *log,*alog,*c;
int nd = 16;
int nc = 10;
int gf = 256;
int pp = 285;
int wd[26]={78,148,144,145,89,39,91,102,95,195,103,8,110,86,39,100};/*数据码字*/
log = malloc(sizeof(int) * gf);
alog = malloc(sizeof(int) * gf);
log[0] = 1-gf; alog[0] = 1;
for (i = 1; i < gf; i++)
{
       alog[i] = alog[i-1] * 2;
       if (alog[i] >= gf) alog[i] ^= pp;
       log[alog[i]] = i;
}
c = malloc(sizeof(int) * (nc+1));
for (i=1; i<=nc; i++) c[i] = 0; c[0] = 1;
for (i=1; i<=nc; i++)
{
       c[i] = c[i-1];
       for (j=i-1; j>=1; j--)
       {
              c[j] = c[j-1] ^ prod(c[j],alog[i],log,alog,gf);
       }
       c[0] = prod(c[0],alog[i],log,alog,gf);
}
for (i=nd; i<=(nd+nc); i++) wd[i] = 0;
for (i=0; i<nd; i++)
{
       k = wd[nd] ^ wd[i] ;
       for (j=0; j<nc; j++)
       {
              wd[nd+j] = wd[nd+j+1] ^ prod(k,c[nc-j-1],log, alog,gf);
       }
}
free(c);
free(alog);
free(log);
for (i=0; i<26; i++)
{
    printf("%d  ",wd[i]);/*输出完整数组(数据码字+纠错码字)*/
}
system("pause");/*暂停、方便观察输出结果*/
/*生成的纠错码字:47,193,166,155,217,18,45,205,2,211*/
}
int prod(int x, int y, int *log, int *alog, int gf)
{
       if (!x || !y) return 0;
       else return alog[(log[x] + log[y]) % (gf-1)];
}




附录二:RS码的译码函数
/*
-------- 说明 --------
一、这是 ReedSolomon 纠错码字的译码函数:rs(26,16)
二、请将本部分的代码保存成 C 文件(如 decode.c)以便测试。
三、测试环境:turboc 2.0
四、rs(26,16) 的可纠错码字数是小于或等于五个:(n-k)/2
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

#define RS_NN_MAX 256
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define CLEAR(a,n) {\
int ci;\
for(ci=(n)-1;ci >=0;ci--)\
(a)[ci] = 0;\
}
#define COPY(a,b,n) {\
int ci;\
for(ci=(n)-1;ci >=0;ci--)\
(a)[ci] = (b)[ci];\
}
/*B0是多项式的第一个值*/
#define B0 1

/*声明函数或定义变量*/
void InitRS(int nn, int kk, int **Gg_ind, int **Gg_poly);
void GenerateGf(int mm);
int RSSyndrome(int *data, int *s, int nn, int kk);
int Modnn(int x);
int GfMulTab(int m1, int m2);
int RSDecode(int *data, int *s, int nn, int kk);/*译码函数*/
int A0;
int gf_mm,gf_nn_max;
int *Alpha_to,*Index_of;
int Pp[9]={1,0,1,1,1,0,0,0,1};
/*本人注:Pp用于存放多项式,本应由函数赋值,由于篇幅的关系我这里改了*/

int main()
{
int i;
int mm,nn,kk,no_p;
int *synd,*Gg_ind,*Gg_poly;
int err_cnt = 0;
int recvd[26] = {78,148,144,145,89,39,91,102,95,195,103,8,110,86,39,100,47,193,166,155,217,18,45,205,2,211};
mm = 8;/*GF(2**mm),码字的位数,这里等于8,数值范围就是0~255*/
nn = 26;/*码字总数*/
kk = 16;/*数据码字数*/
no_p = nn-kk;/*纠错码字数*/
synd = (int *) malloc( (no_p+1) * sizeof(int));
GenerateGf(mm);
InitRS(nn,kk,&Gg_ind,&Gg_poly);
for(i=0;i<no_p+1;i++) synd[i] = 0;
if (RSSyndrome(recvd,synd,nn,kk) != -1)
{
printf ("%s","Syndrome zero, no errors. ") ;
system("pause");/*暂停、方便观察输出结果*/  
}
else
{
err_cnt = RSDecode(recvd,synd,nn,kk);/*对数据进行纠错并输出正确结果*/
printf ("%s","\nError count: ");
printf("%d",err_cnt);/*输出错误码字数*/
printf ("%s","\n");
system("pause");
}
}

int RSSyndrome(int *data, int *s, int nn, int kk)
{
int i,j,no_p;
int sum,product;
no_p = nn-kk;
for (j = 1; j <= no_p; j++) s[j] = A0;
for (i = 0; i < nn; i++) {
for (j = 1; j <= no_p; j++) {
if (s[j] != A0) product = Modnn(j+s[j]);
else product = A0;
sum = Alpha_to[product] ^ data[i];
s[j] = Index_of[sum];
}
}
for (j = 1; j <= no_p; j++) {
if(s[j] != A0) return(-1);
}
return(0);
}

void InitRS(int nn, int kk, int **Gg_ind, int **Gg_poly)
{
int i, j;
*Gg_poly = (int *) malloc( (nn - kk + 1) * sizeof(int));
*Gg_ind = (int*) malloc( (nn - kk + 1) * sizeof(int));
(*Gg_poly)[0] = Alpha_to[B0];
(*Gg_poly)[1] = 1;
for (i = 2; i <= nn - kk; i++) {
(*Gg_poly)[i] = 1;
for (j = i - 1; j > 0; j--)
(*Gg_poly)[j] = (*Gg_poly)[j - 1] ^ GfMulTab((*Gg_poly)[j], Alpha_to[B0+i-1]);
(*Gg_poly)[0] = GfMulTab((*Gg_poly)[0], Alpha_to[B0+i-1]);
}
for (i = 0; i <= nn - kk; i++) (*Gg_ind)[i] = Index_of[(*Gg_poly)[i]];
}

int GfMulTab(int m1, int m2)
{
int m1_i,m2_i,prod_i,result;
if((m1 == 0) || (m2 == 0)) return(0);
m1_i = Index_of[m1];
m2_i = Index_of[m2];
prod_i = Modnn(m1_i + m2_i);
result = Alpha_to[prod_i];
return(result);
}

int Modnn(int x)
{
while (x >= gf_nn_max) {
x -= gf_nn_max;
x = (x >> gf_mm) + (x & gf_nn_max);
}
return x;
}

void GenerateGf(int mm)
{
int i, mask;
gf_mm = mm;
gf_nn_max = pow(2,mm)-1;
A0 = gf_nn_max;
Alpha_to = (int*) malloc( (gf_nn_max + 1) * sizeof(int));
Index_of = (int*) malloc( (gf_nn_max + 1) * sizeof(int));
for (i = 0; i <= gf_nn_max; i++ ) Alpha_to[i] = 0;
for (i = 0; i <= gf_nn_max; i++ ) Index_of[i] = 0;
mask = 1;
Alpha_to[mm] = 0;
for (i = 0; i < mm; i++) {
Alpha_to[i] = mask;
Index_of[Alpha_to[i]] = i;
if (Pp[i] != 0) Alpha_to[mm] ^= mask;
mask <<= 1;
}
Index_of[Alpha_to[mm]] = mm;
mask >>= 1;
for (i = mm + 1; i < gf_nn_max; i++) {
if (Alpha_to[i - 1] >= mask)
Alpha_to[i] = Alpha_to[mm] ^ ((Alpha_to[i - 1] ^ mask) << 1);
else
Alpha_to[i] = Alpha_to[i - 1] << 1;
Index_of[Alpha_to[i]] = i;
}
Index_of[0] = A0;
Alpha_to[gf_nn_max] = 0;
}

int RSDecode(int *data, int *s, int nn, int kk)
{
int deg_lambda, el, deg_omega;
int i, j, r, no_p;
int u,q,tmp,num1,num2,den,discr_r;
int lambda[RS_NN_MAX],b[RS_NN_MAX],t[RS_NN_MAX],omega[RS_NN_MAX];
int reg[RS_NN_MAX],root[RS_NN_MAX],loc[RS_NN_MAX];
int syn_error, count;
no_p = nn-kk;
CLEAR(&lambda[1],no_p);
lambda[0] = 1;
for(i=0;i<(no_p+1);i++) b[i] = Index_of[lambda[i]];
r = 0;
el = 0;
while (++r <= no_p) {
discr_r = 0;
for (i = 0; i < r; i++){
if ((lambda[i] != 0) && (s[r - i] != A0)) {
discr_r ^= Alpha_to[Modnn(Index_of[lambda[i]] + s[r - i])];
}
}
discr_r = Index_of[discr_r];
if (discr_r == A0) {
COPY(&b[1],b,no_p);
b[0] = A0;
}
else
{
t[0] = lambda[0];
for (i = 0 ; i < no_p; i++) {
if(b[i] != A0) t[i+1] = lambda[i+1] ^ Alpha_to[Modnn(discr_r + b[i])];
else t[i+1] = lambda[i+1];
}
if (2 * el <= r - 1) {
el = r - el;
for (i = 0; i <= no_p; i++)
b[i] = (lambda[i] == 0) ? A0 : Modnn(Index_of[lambda[i]] - discr_r + gf_nn_max);
}
else
{
COPY(&b[1],b,no_p);
b[0] = A0;
}
COPY(lambda,t,no_p+1);
}
}
deg_lambda = 0;
for(i=0;i<no_p+1;i++){
lambda[i] = Index_of[lambda[i]];
if(lambda[i] != A0)
deg_lambda = i;
}
COPY(&reg[1],&lambda[1],no_p);
count = 0;
for (i = 1; i <= gf_nn_max; i++) {
q = 1;
for (j = deg_lambda; j > 0; j--)
if (reg[j] != A0) {
reg[j] = Modnn(reg[j] + j);
q ^= Alpha_to[reg[j]];
}
if (!q) {
root[count] = i;
loc[count] = gf_nn_max - i;
count++;
}
}
for (i = 0; i < count; i++) {
loc[i] = nn-1-loc[i];
if(loc[i] < 0) return(-1);
}
deg_omega = 0;
for (i = 0; i < no_p;i++){
tmp = 0;
j = (deg_lambda < i) ? deg_lambda : i;
for(;j >= 0; j--){
if ((s[i + 1 - j] != A0) && (lambda[j] != A0))
tmp ^= Alpha_to[Modnn(s[i + 1 - j] + lambda[j])];
}
if(tmp != 0)
deg_omega = i;
omega[i] = Index_of[tmp];
}
omega[no_p] = A0;
for (j = count-1; j >=0; j--) {
num1 = 0;
for (i = deg_omega; i >= 0; i--) {
if (omega[i] != A0)
num1 ^= Alpha_to[Modnn(omega[i] + i * root[j])];
}
num2 = Alpha_to[Modnn(root[j] * (B0 - 1) + gf_nn_max)];
den = 0;
for (i = MIN(deg_lambda,no_p-1) & ~1; i >= 0; i -=2) {
if(lambda[i+1] != A0)
den ^= Alpha_to[Modnn(lambda[i+1] + i * root[j])];
}
if (num1 != 0) {
data[loc[j]] ^= Alpha_to[Modnn(Index_of[num1] + Index_of[num2] + gf_nn_max - Index_of[den])];
}
}
/*输出纠错结果:正确的数组*/
printf("%s","Correct data: ");
for (i=0; i<nn; i++) {
printf("%d  ",data[i]);/*数组data用于存放纠错结果*/
}
if (deg_lambda != count) return -1;
else return count;/*错误码字数,如果溢出则返回-1*/
}

评论

此博客中的热门博文

《佛教的四大危害》(最终更新)

《气候战争》

《基督教的没落与堕落》