免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 4411 | 回复: 29

[C++] Functional Programming in C++14 [复制链接]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2015-06-15 20:35 |显示全部楼层
本帖最后由 lost_templar 于 2015-06-15 20:36 编辑

这一阵子折腾 C++14,练手的时候把自己之前写过的一个 生成非均匀随机变量的库重构了一下,还没有搞完,记录了重构的大概过程,先发过来大家瞧瞧。

https://github.com/fengwang/vg

标准组件 (Stardard Components)

Seed

写一个函数,这个函数返回一个随机整数。

Write a function that returns a random integer.

  1. inline auto make_seed() noexcept
  2. {
  3.     typedef std::uint_fast64_t        seed_type;
  4.     auto const now                  = std::chrono::system_clock::now();
  5.     auto const duration             = now.time_since_epoch();
  6.     seed_type  const nano_seed      = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count();
  7.     seed_type const random_address  = reinterpret_cast<seed_type>( &nano_seed );
  8.     seed_type ans                   = nano_seed + ( random_address | (random_address << 32) );
  9.     ans                             = ( ans & 0x5555555555555555ULL ) <<  1 | ( ans & 0xAAAAAAAAAAAAAAAAULL ) >>  1;
  10.     ans                             = ( ans & 0x3333333333333333ULL ) <<  2 | ( ans & 0xCCCCCCCCCCCCCCCCULL ) >>  2;
  11.     ans                             = ( ans & 0x0F0F0F0F0F0F0F0FULL ) <<  4 | ( ans & 0xF0F0F0F0F0F0F0F0ULL ) >>  4;
  12.     ans                             = ( ans & 0x00FF00FF00FF00FFULL ) <<  8 | ( ans & 0xFF00FF00FF00FF00ULL ) >>  8;
  13.     ans                             = ( ans & 0x0000FFFF0000FFFFULL ) << 16 | ( ans & 0xFFFF0000FFFF0000ULL ) >> 16;
  14.     ans                             = ( ans & 0x00000000FFFFFFFFULL ) << 32 | ( ans & 0xFFFFFFFF00000000ULL ) >> 32;
  15.     ans                            ^= nano_seed;
  16.     return                            ans;
  17. }
复制代码
引擎 -- Engine

写一个函数,这个函数返回另外一个函数,返回的函数被调用后返回一个在 [0,1] 区间服从均匀分布的随机数。

Write a function that return a function that returns a random variate that uniformly distributed in range [0,1].

  1. inline auto linear_congruential() noexcept
  2. {
  3.     static const std::uint_fast64_t a_ = 6364136223846793005ULL;
  4.     static const std::uint_fast64_t c_ = 1442695040888963407ULL;
  5.     std::uint_fast64_t              x_ = make_seed();

  6.     return [=]() mutable noexcept
  7.     {
  8.         x_ *= a_;
  9.         x_ += c_;
  10.         return static_cast<long double>( x_ ) / static_cast<long double>( std::numeric_limits<std::uint_fast64_t>::max() );
  11.     };
  12. }
复制代码
Reference

    D. E. Knuth. The Art of Computer Programming, Volume 2: Seminumerical Algorithms, Third Edition. Addison-Wesley, 1997. ISBN 0-201-89684-2. Section 3.2.1: The Linear Congruential Method, pp. 10–26.

分布 -- Distribution
正态分布 -- Normal

写一个函数,这个函数返回一个函数 g, g 返回一个函数 h,h 接收一个函数 e 作为参数,h 返回一个服从 N(0,1) 分布的随机数,而作为函数 h 参数的函数 e 被调用后会返回一个在区间 [0,1] 上服从均匀分布的随机数。

Write a function that returns a function that takes a function, which returns a random variate uniform in range [0,1], and returns a variate that is subject to N(0,1).

  1. inline auto normal() noexcept
  2. {
  3.     return []() noexcept
  4.     {
  5.         return []( auto& engine ) noexcept
  6.         {
  7.             long double const one = 1;

  8.             for (;;)
  9.             {
  10.                 auto const u1 = engine();
  11.                 auto const u2 = engine();
  12.                 auto const v1 = u1 + u1 - one;
  13.                 auto const v2 = u2 + u2 - one;
  14.                 auto const s = v1 * v1 + v2 * v2;

  15.                 if ( s < one )
  16.                 {
  17.                     auto const tmp = -std::log( s );
  18.                     return v1 * std::sqrt(( tmp + tmp ) / s );
  19.                 }
  20.             }
  21.         };
  22.     };
  23. }
复制代码
Reference

    G. E. P. Box and Mervin E. Muller, A Note on the Generation of Random Normal Deviates, The Annals of Mathematical Statistics (195, Vol. 29, No. 2 pp. 610-611

均匀分布 -- Uniform

仿照正态分布的生成函数,写一个在区间 [lower, upper] 上服从均匀分布的函数。

Write a uniform ditribution function defined in range [lower, upper].

  1. auto inline uniform() noexcept
  2. {
  3.     return []( auto lower, auto upper ) noexcept
  4.     {
  5.         return [=]( auto& engine ) noexcept
  6.         {
  7.             return engine() * ( upper - lower ) + lower;
  8.         };
  9.     };
  10. }
复制代码
Generator

写一个函数,这个函数接收两个参数,第一个参数是一个生成具体随机变量分布 F 的算法的函数 f(分布),第二个参数是一个生成在 [0,1] 区间服从均匀分布随机数的函数 g(引擎), 返回一个函数 h,h 接收任意数量的参数并返回一个函数 i,i 被调用后组合 f 与 g 生成服从 F 分布的随机变量。

Write a function that takes two functions as parameters, the first one for a specified distribution F, the second one is an engine generating uniform random variates in range [0,1], returns a function that takes arbitrary parameters and returns a function that returns a random variate subject to distribution F.

  1. template< typename Distribution, typename Engine >
  2. auto make_generator( Distribution distribution, Engine engine ) noexcept
  3. {
  4.     auto engine_ = engine();
  5.     return [=]( auto ... args ) mutable noexcept
  6.     {
  7.         return [=]() mutable noexcept
  8.         {
  9.             return distribution()( args... )( engine_ );
  10.         };
  11.     };
  12. }   
复制代码
如果 Generator 的引擎没有指定,缺省使用 linear_congruential 引擎。

If the engine parameter for the make_generator is not specified, use linear_congruential.

  1. template< typename Distribution >
  2. auto make_generator( Distribution distribution ) noexcept
  3. {
  4.     return make_generator( distribution, mitchell_moore );
  5. }
复制代码
Test:

  1. //normal_test.cc
  2. auto v = make_generator(normal)();

  3. map<int, int> sample;

  4. for ( unsigned long int i = 0; i != 500; ++i )
  5.     sample[static_cast<int>(round(4.0*v()))]++;

  6. for ( auto element : sample )
  7. {
  8.     cout << "\n" << element.first << "\t";
  9.     for ( auto j = 0; j < element.second; ++j ) cout << "*";
  10. }
复制代码
Output:

  1. -13 *
  2. -12 *
  3. -10 **
  4. -9  *******
  5. -8  ******
  6. -7  ***************
  7. -6  ********************
  8. -5  ******************
  9. -4  *******************************
  10. -3  ************************************
  11. -2  *****************************************
  12. -1  *********************************************
  13. 0   *******************************************************
  14. 1   *************************************************
  15. 2   ******************************************
  16. 3   *******************************************
  17. 4   *****************************
  18. 5   ***************************
  19. 6   ********
  20. 7   ****
  21. 8   ***********
  22. 9   ****
  23. 10  **
复制代码
其他引擎 -- More Engines
mt19937

  1. inline auto mt19937() noexcept
  2. {
  3.     std::uint_fast64_t                      mt[312];
  4.     std::uint_fast64_t                      mag01[2];
  5.     std::size_t                             mti;

  6.     mt[0]    = make_seed();
  7.     mag01[0] = 0ULL;
  8.     mag01[1] = 0xB5026F5AA96619E9ULL;

  9.     for ( mti = 1; mti < 312; ++mti )
  10.     {
  11.         mt[mti] =  6364136223846793005ULL * ( mt[mti-1] ^( mt[mti-1] >> 62 ) );
  12.         mt[mti] += mti;
  13.     }

  14.     return [=]() mutable noexcept
  15.     {
  16.         std::uint_fast64_t x;

  17.         if ( mti > 311 )
  18.         {
  19.             for ( std::size_t i = 0; i < 156; ++i )
  20.             {
  21.                 x = ( mt[i] & 0xFFFFFFFF80000000ULL ) | ( mt[i+1] & 0x7FFFFFFFULL );
  22.                 mt[i] = mt[i+156] ^( x >> 1 ) ^ mag01[x&1];
  23.             }

  24.             for ( std::size_t i = 156; i < 311; ++i )
  25.             {
  26.                 x = ( mt[i] & 0xFFFFFFFF80000000ULL ) | ( mt[i+1] & 0x7FFFFFFFULL );
  27.                 mt[i] = mt[i-156] ^( x >> 1 ) ^ mag01[x&1];
  28.             }

  29.             x = ( mt[311] & 0xFFFFFFFF80000000ULL ) | ( mt[0] & 0x7FFFFFFFULL );
  30.             mt[311] = mt[155] ^( x >> 1 ) ^ mag01[x&1];
  31.             mti = 0;
  32.         }

  33.         x  = mt[mti++];
  34.         x ^= ( x >> 29 ) & 0x5555555555555555ULL;
  35.         x ^= ( x << 17 ) & 0x71D67FFFEDA60000ULL;
  36.         x ^= ( x << 37 ) & 0xFFF7EEE000000000ULL;
  37.         x ^= ( x >> 43 );

  38.         return static_cast<long double>( x ) / static_cast<long double>( std::numeric_limits<std::uint_fast64_t>::max() );
  39.     };
  40. }
复制代码
Reference

    Makoto Matsumoto, Takuji Nishimura: Mersenne twister. A 623-dimensionally equidistributed uniform pseudorandom number generator. In: ACM Transactions on Modeling and Computer Simulation. 8, 1998, ISSN 1049-3301, S. 3–30.

lagged_fibonacci

  1. inline auto lagged_fibonacci() noexcept
  2. {
  3.     std::uint_fast64_t data[44497];
  4.     std::size_t mti = make_seed() % 21034;

  5.     data[0] = 1;
  6.     data[1] = 1;

  7.     for ( std::size_t index = 2; index != 44497; ++index )
  8.         data[index] = data[index-2] + data[index-1];

  9.     return[=]() mutable noexcept
  10.     {
  11.         if ( mti > 21034 )
  12.         {
  13.             mti = 0;
  14.             std::copy( data+21034, data+44497, data );
  15.             for ( std::size_t index = 23463; index != 44497; ++index ) data[index] = data[index-2] + data[index-1];
  16.         }

  17.         auto const mtj  = mti + 23463;
  18.         auto const x    = data[mti++] + data[mtj];
  19.         auto const ans  = static_cast<long double>( x ) / static_cast<long double>( std::numeric_limits<std::uint_fast64_t>::max() );
  20.         return ans;
  21.     };
  22. }
复制代码
Reference

    A New Class of Random Number Generators, George Marsaglia and Arif Zaman, The Annals of Applied Probability, Vol. 1, No. 3, 1991

其他非均匀分布 -- More Non-Uniform Distributions

If not specified, the reference for the distribution generator is

    Devroye, Luc 1986, Non-Uniform Random Variate Generation. New York: Springer-Verlag.

gaussian

  1. inline auto gaussian() noexcept
  2. {
  3.     return []( auto mean, auto variance ) noexcept
  4.     {
  5.         return [=]( auto& engine ) noexcept
  6.         {
  7.             long double const normal_ = normal()()( engine );
  8.             return normal_ * variance + mean;
  9.         };
  10.     };
  11. }
复制代码
当均值为 0, 方差为 1 的时候,高斯分布退化为正态分布。

Normal distribution is a special case of Gaussian distribution when the average is 0 and the variance is 1.

Test:

  1. auto v = vg::make_generator(vg::gaussian, vg::mt19937)( 0.0, 4.0 );

  2. map< int, int > sample;

  3. for ( unsigned long int i = 0; i != 500; ++i )
  4.     sample[static_cast<int>(round(v()))]++;

  5. for ( auto i = sample.begin(); i != sample.end(); ++i )
  6. {
  7.     cout << "\n" << (*i).first << "\t";
  8.     for ( auto j = 0; j < (*i).second; ++j ) cout << "*";
  9. }
复制代码
Output:

  1. -12 *
  2. -11 *
  3. -10 **
  4. -9  *********
  5. -8  *******
  6. -7  *********
  7. -6  *******************
  8. -5  **************************
  9. -4  **************************
  10. -3  *********************************************
  11. -2  *****************************************
  12. -1  **********************************************
  13. 0   **********************************************************
  14. 1   ****************************************
  15. 2   ******************************************
  16. 3   *************************************
  17. 4   *********************************
  18. 5   *****************************
  19. 6   *********
  20. 7   *****
  21. 8   *****
  22. 9   *****
  23. 10  ***
  24. 11  *
复制代码
gamma

  1. inline auto gamma() noexcept
  2. {
  3.     return []( auto alpha, auto beta ) noexcept
  4.     {
  5.         assert( alpha > 0.0 );
  6.         assert( beta > 0.0 );

  7.         return [=]( auto& engine ) noexcept
  8.         {
  9.             long double const zero  = 0.0;
  10.             long double const one   = 1.0;
  11.             long double const three = 3.0;
  12.             long double const a     = alpha < one ? alpha + one : alpha;
  13.             long double const d     = a - one / three;
  14.             long double const c     = one / (three * std::sqrt( d ));
  15.             long double u           = zero;
  16.             long double v           = zero;
  17.             long double x           = zero;

  18.             for ( ;; )
  19.             {
  20.                 for ( ;; )
  21.                 {
  22.                     x = normal()()( engine );
  23.                     v = one + c * x;

  24.                     if ( v > zero ) break;
  25.                 }

  26.                 const long double xx = x * x;

  27.                 v *= v * v;

  28.                 u = engine();

  29.                 if ( u < one - 0.0331 * xx * xx )
  30.                     break;

  31.                 if ( std::log( u ) < 0.5 * xx + d * ( one - v + std::log( v ) ) )
  32.                     break;
  33.             }

  34.             long double tmp = d * v;

  35.             if ( alpha < one )
  36.                 tmp *= std::pow( engine(), one / alpha );

  37.             return tmp * beta;
  38.         };
  39.     };
  40. }
复制代码
Reference

    Marsaglia and Tsang, "A Simple Method for generating gamma variables", ACM Transactions on Mathematical Software, Vol 26, No 3 (2000), p363-372.

Test:

  1. auto v = vg::make_generator(vg::gamma)( 1.0, 2.0 );

  2. map<int, int> sample;

  3. for ( unsigned long int i = 0; i != 100; ++i )
  4.     sample[static_cast<int>(std::round(v()))]++;

  5. for ( auto element : sample )
  6. {
  7.     cout << "\n" << element.first << "\t";
  8.     for ( auto j = 0; j < element.second; ++j ) cout << "*";
  9. }
复制代码
Output:

  1. 0   ***********************************************
  2. 1   **************************
  3. 2   **********
  4. 3   ***
  5. 4   ***
  6. 5   ***
  7. 6   *****
  8. 8   *
  9. 9   *
  10. 11  *      
复制代码
beta

  1. inline auto beta() noexcept
  2. {
  3.     return []( auto alpha, auto beta ) noexcept
  4.     {
  5.         return [=]( auto& engine ) noexcept
  6.         {
  7.             long double one = 1.0;
  8.             auto const a = gamma()( alpha, one )( engine );
  9.             auto const b = gamma()( beta, one )( engine );
  10.             return a / ( a + b );
  11.         };
  12.     };
  13. }
复制代码
如果 G_a 和 G_b 不相关,并且分别服从 gamma(a,1), gamma(b,1) 分布,那么 G_a/(G_a+G_b) 服从 beta(a,b) 分布。

If G_a and G_b are indenpendent gamma(a,1), gamma(b,1) random variables, then G_a/(G_a+G_b) is beta(a,b) distributed.


更多在 https://github.com/fengwang/vg

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
发表于 2015-06-15 21:21 |显示全部楼层
珍爱生命,远离C++

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2015-06-15 21:55 |显示全部楼层
cokeboL 发表于 2015-06-15 21:21
珍爱生命,远离C++


其实, C++11/14 已经重新发明了 C++;
函数式编程,放弃了 class/struct,远离了虚拟,继承,多态,深拷贝,浅拷贝等阴暗角落,尤其是对 GP 依赖的减少,使得智商因素对代码质量的影响没有那么大了。
建议重新审视一番。

Life is too short to learn C++ 已经不再总是成立了。

论坛徽章:
89
水瓶座
日期:2014-04-01 08:53:31天蝎座
日期:2014-04-01 08:53:53天秤座
日期:2014-04-01 08:54:02射手座
日期:2014-04-01 08:54:15子鼠
日期:2014-04-01 08:55:35辰龙
日期:2014-04-01 08:56:36未羊
日期:2014-04-01 08:56:27戌狗
日期:2014-04-01 08:56:13亥猪
日期:2014-04-01 08:56:02亥猪
日期:2014-04-08 08:38:58程序设计版块每日发帖之星
日期:2016-01-05 06:20:00程序设计版块每日发帖之星
日期:2016-01-07 06:20:00
发表于 2015-06-16 08:56 |显示全部楼层
我只能说:C++真强大、lz真会玩。

C++是个筐,啥都能往里装。

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
发表于 2015-06-16 09:55 |显示全部楼层
回复 3# lost_templar


远离的原因不是难学,而是为了学语言花费的时间太久,审视成本太大
而且,c++这些东西,不用c++都能搞定而且花费的成本更少

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
发表于 2015-06-16 12:42 |显示全部楼层
回复 5# cokeboL

汽车能跑飞机能飞船能下水,但问题是有时候你就需要在一个项目里上天入地下海挨个干一遍,此时除了搞一辆会飞的水陆两用车你还能怎么办?

论坛徽章:
0
发表于 2015-06-16 13:17 |显示全部楼层
functional programming体现在什么地方?

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
发表于 2015-06-16 13:33 |显示全部楼层
回复 6# windoze


    如果一定需要啥,就搞啥。。

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
发表于 2015-06-16 13:44 |显示全部楼层
本帖最后由 windoze 于 2015-06-16 13:45 编辑

回复 8# cokeboL

C++最适合的场合就是JVM之类的项目,既有机器级底层操作,又有上层的高度抽象,外加对性能还有变态的需求,代码规模还特别大。

你说这一类的项目,除了C++你还有什么可以用?Rust?

论坛徽章:
14
水瓶座
日期:2014-06-10 09:51:0215-16赛季CBA联赛之江苏
日期:2017-11-27 11:42:3515-16赛季CBA联赛之八一
日期:2017-04-12 14:26:2815-16赛季CBA联赛之吉林
日期:2016-08-20 10:43:1215-16赛季CBA联赛之广夏
日期:2016-06-23 09:53:58程序设计版块每日发帖之星
日期:2016-02-11 06:20:00程序设计版块每日发帖之星
日期:2016-02-09 06:20:0015-16赛季CBA联赛之上海
日期:2015-12-25 16:40:3515-16赛季CBA联赛之广夏
日期:2015-12-22 09:39:36程序设计版块每日发帖之星
日期:2015-08-24 06:20:002015亚冠之德黑兰石油
日期:2015-08-07 09:57:302015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2015-06-16 13:58 |显示全部楼层
lost_templar 发表于 2015-06-15 21:55
其实, C++11/14 已经重新发明了 C++;
函数式编程,放弃了 class/struct,远离了虚拟,继承,多态,深 ...

我靠,这么说正在学的过时了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP