SWIG 磨人
SWIG 自1995 年开始, 至今也算稳定了. 只是稳定到一个不够 versatile 的状态.
SWIG的Typemap很方便, 只可惜, 找不到将多参数一起解析, 或者解析时引用前面参数的方法. 文档里倒是明确提到 numinputs 须为0或1, 像是不支持这个.
文档里找不到, 邮件列表里没人解答, 虽然还没到最后一步看实现, 估计我也放弃了. 有新资源申请依赖参数时, 手写Python扩展也比这个框架下写接口来得快.
``SWIG垃圾, 支持多语言的自然做不好.''
``框架!''
虽然, 倒是从 numpy.i 里找出一些代码, 包装数组挺方便的.
纯属测试: 中共匪然海外的都与敏感词相关么.
几种简单的排序算法比较次数比较
几种简单的排序算法比较次数比较
1 说明
几种排序算法, 有一些是简单实现, 另有 glibc 的 qsort 和 GNU C++ 库的 std::sort. 下面的时间是排序 long 型数组的时间. 其实, 是一个 C 里 Sequence, 但此 Sequence 占用的时间和时间的误差相近, 在 10% 左右.
比较程序使用 random 生成数组, 在数组比较小时, 排序并打乱数组多次, 取时 间平均值, 最后几个, 因时间比较大, 只比较一次. 所以, 在所有的时间里, 有 打乱数组的时间开销, 大致为 O(size * time(random)). 本文只关心相对比较明 显的差异, 故不细分这些.
各排序算法如其名. 其中 quicksort_nr 是快速排序的非递归版, cqsort 是调 C 标准库函数 qsort. std::sort(iterator) 中的 get/set 不能区分, 统一计在 get 下.
C 的 qsort 由于必须有函数指针, 比较是相对较大开销, 所以在数组较小, 且内 存足够时采用需要额外内存但比较次数最少的归并排序. C++ 采用的是 quicksort 和 heapsort 的杂交 introsort, 比较次数相对归并排序多一点, 但 对整数而言, 比较仅是减法, 受限于内存访问的时间, 估可以次要考虑.
2 sort comparisons table
| Algo. | Size | time | # comparisons/size | # gets/size | # sets/size |
|---|---|---|---|---|---|
| introsort | 2^5 | 2.29932e-06 | 5.27492 | 9.38623 | 4.00063 |
| heapsort | 2^5 | 2.70095e-06 | 5.18218 | 13.2291 | 8.45347 |
| mergesort | 2^5 | 2.37965e-06 | 3.79695 | 9.29695 | 6 |
| quicksort | 2^5 | 2.19414e-06 | 5.56079 | 8.359 | 2.83799 |
| quicksort_nr | 2^5 | 2.15747e-06 | 5.36925 | 8.23558 | 2.85841 |
| cqsort | 2^5 | 2.98512e-06 | 3.79623 | NA | NA |
| combsort | 2^5 | 2.41381e-06 | 8.80184 | 17.6123 | 3.36478 |
| std::sort(iterator) | 32 | 4.68653e-06 | 5.95218 | 13.9444 | NA |
| std::sort | 32 | 1.65281e-06 | 5.94951 | NA | NA |
| introsort | 2^6 | 4.42774e-06 | 6.51571 | 11.0817 | 4.47673 |
| heapsort | 2^6 | 5.82915e-06 | 6.26207 | 15.305 | 9.46844 |
| mergesort | 2^6 | 4.97256e-06 | 4.76615 | 10.2662 | 6 |
| quicksort | 2^6 | 4.87501e-06 | 6.77834 | 10.0566 | 3.35011 |
| quicksort_nr | 2^6 | 4.76849e-06 | 6.60236 | 9.94205 | 3.3574 |
| cqsort | 2^6 | 6.40913e-06 | 4.76535 | NA | NA |
| combsort | 2^6 | 5.18118e-06 | 11.6094 | 23.2234 | 4.28761 |
| std::sort(iterator) | 64 | 3.99712e-06 | 7.11533 | 15.4967 | NA |
| std::sort | 64 | 3.62354e-06 | 7.12488 | NA | NA |
| introsort | 2^7 | 1.00313e-05 | 7.76488 | 12.8293 | 4.99319 |
| heapsort | 2^7 | 1.28292e-05 | 7.30858 | 17.3461 | 10.4755 |
| mergesort | 2^7 | 1.94854e-05 | 5.74942 | 13.2494 | 8 |
| quicksort | 2^7 | 1.06718e-05 | 7.98551 | 11.737 | 3.83951 |
| quicksort_nr | 2^7 | 1.05284e-05 | 7.80488 | 11.614 | 3.8471 |
| cqsort | 2^7 | 1.41386e-05 | 5.74657 | NA | NA |
| combsort | 2^7 | 1.22646e-05 | 14.5126 | 29.0274 | 5.30448 |
| std::sort(iterator) | 128 | 8.65036e-06 | 8.32369 | 17.1383 | NA |
| std::sort | 128 | 7.87806e-06 | 8.31551 | NA | NA |
| introsort | 2^8 | 2.16346e-05 | 8.96745 | 14.5286 | 5.49551 |
| heapsort | 2^8 | 2.79746e-05 | 8.33321 | 19.3682 | 11.4748 |
| mergesort | 2^8 | 2.38339e-05 | 6.74197 | 14.242 | 8 |
| quicksort | 2^8 | 2.26148e-05 | 9.21454 | 13.4375 | 4.31297 |
| quicksort_nr | 2^8 | 2.29063e-05 | 9.00217 | 13.2955 | 4.34143 |
| cqsort | 2^8 | 3.07402e-05 | 6.74541 | NA | NA |
| combsort | 2^8 | 2.71602e-05 | 17.383 | 34.7672 | 6.34737 |
| std::sort(iterator) | 256 | 1.99121e-05 | 9.54765 | 18.8368 | NA |
| std::sort | 256 | 1.73477e-05 | 9.57421 | NA | NA |
| introsort | 2^9 | 4.58946e-05 | 10.1556 | 16.2247 | 6.01352 |
| heapsort | 2^9 | 6.01988e-05 | 9.35496 | 21.3922 | 12.4821 |
| mergesort | 2^9 | 5.17732e-05 | 7.73911 | 17.2391 | 1NA |
| quicksort | 2^9 | 4.92418e-05 | 10.3618 | 15.0615 | 4.8 |
| quicksort_nr | 2^9 | 4.81522e-05 | 10.1833 | 14.9512 | 4.81563 |
| cqsort | 2^9 | 6.54729e-05 | 7.74022 | NA | NA |
| combsort | 2^9 | 5.884e-05 | 20.3521 | 40.7047 | 7.38508 |
| std::sort(iterator) | 512 | 4.32935e-05 | 10.7954 | 20.6048 | NA |
| std::sort | 512 | 3.68822e-05 | 10.7974 | NA | NA |
| introsort | 2^10 | 0.000100438 | 11.3582 | 17.9356 | 6.51449 |
| heapsort | 2^10 | 0.000128305 | 10.361 | 23.3974 | 13.4805 |
| mergesort | 2^10 | 0.000106804 | 8.73833 | 18.2383 | 10 |
| quicksort | 2^10 | 0.000104649 | 11.5757 | 16.7461 | 5.26775 |
| quicksort_nr | 2^10 | 0.000102984 | 11.4302 | 16.6564 | 5.27142 |
| cqsort | 2^10 | 0.000185398 | 8.73907 | NA | NA |
| combsort | 2^10 | 0.000144469 | 23.9508 | 47.9019 | 8.49806 |
| std::sort(iterator) | 1024 | 8.9258e-05 | 11.9546 | 22.1866 | NA |
| std::sort | 1024 | 7.89147e-05 | 12.0618 | NA | NA |
| introsort | 2^11 | 0.000230655 | 12.5322 | 19.6955 | 7.09028 |
| heapsort | 2^11 | 0.000288267 | 11.3662 | 25.4025 | 14.4817 |
| mergesort | 2^11 | 0.000239689 | 9.7364 | 21.2364 | 12 |
| quicksort | 2^11 | 0.00024103 | 12.7323 | 18.3789 | 5.75391 |
| quicksort_nr | 2^11 | 0.000217546 | 12.5383 | 18.2607 | 5.76871 |
| cqsort | 2^11 | 0.000305481 | 9.737 | NA | NA |
| combsort | 2^11 | 0.000289749 | 27.0919 | 54.184 | 9.64027 |
| std::sort(iterator) | 2048 | 0.000190891 | 13.1735 | 23.8782 | NA |
| std::sort | 2048 | 0.00016664 | 13.1915 | NA | NA |
| introsort | 2^12 | 0.000462502 | 13.8416 | 21.6096 | 7.6772 |
| heapsort | 2^12 | 0.000570066 | 12.37 | 27.405 | 15.4825 |
| mergesort | 2^12 | 0.000510409 | 10.7365 | 22.2365 | 12 |
| quicksort | 2^12 | 0.000469625 | 13.9459 | 20.0833 | 6.24193 |
| quicksort_nr | 2^12 | 0.00046391 | 13.706 | 19.9027 | 6.24634 |
| cqsort | 2^12 | 0.000642657 | 10.7388 | NA | NA |
| combsort | 2^12 | 0.000638999 | 30.2622 | 60.5245 | 10.6047 |
| std::sort(iterator) | 4096 | 0.000405341 | 14.4655 | 25.6454 | NA |
| std::sort | 4096 | 0.000358723 | 14.6613 | NA | NA |
| introsort | 2^13 | 0.000944316 | 14.9803 | 23.2548 | 8.18111 |
| heapsort | 2^13 | 0.0012345 | 13.3728 | 29.4096 | 16.483 |
| mergesort | 2^13 | 0.00111294 | 11.7366 | 25.2366 | 14 |
| quicksort | 2^13 | 0.00100707 | 15.1234 | 21.7303 | 6.71223 |
| quicksort_nr | 2^13 | 0.000998065 | 14.8599 | 21.535 | 6.73174 |
| cqsort | 2^13 | 0.00133355 | 11.7354 | NA | NA |
| combsort | 2^13 | 0.00143582 | 33.8422 | 67.6845 | 11.7082 |
| std::sort(iterator) | 8192 | 0.000863686 | 15.7674 | 27.4121 | NA |
| std::sort | 8192 | 0.00074625 | 15.6189 | NA | NA |
| introsort | 2^14 | 0.00210512 | 16.126 | 24.9677 | 8.75029 |
| heapsort | 2^14 | 0.00262052 | 14.3694 | 31.4035 | 17.4816 |
| mergesort | 2^14 | 0.00231299 | 12.7382 | 26.2382 | 14 |
| quicksort | 2^14 | 0.00242236 | 16.1358 | 23.2343 | 7.2082 |
| quicksort_nr | 2^14 | 0.00239414 | 16.1299 | 23.2688 | 7.187 |
| cqsort | 2^14 | 0.00295651 | 12.7369 | NA | NA |
| combsort | 2^14 | 0.00316426 | 37.0912 | 74.1825 | 12.864 |
| std::sort(iterator) | 16384 | 0.00181475 | 17.1119 | 29.2536 | NA |
| std::sort | 16384 | 0.00160038 | 17.1486 | NA | NA |
| introsort | 2^15 | 0.00504923 | 17.3696 | 26.8373 | 9.35675 |
| heapsort | 2^15 | 0.00568175 | 15.3648 | 33.3989 | 18.474 |
| mergesort | 2^15 | 0.00549728 | 13.7331 | 29.2331 | 16 |
| quicksort | 2^15 | 0.00467777 | 17.7633 | 25.2896 | 7.6303 |
| quicksort_nr | 2^15 | 0.00500149 | 17.2662 | 24.8932 | 7.67592 |
| cqsort | 2^15 | 0.00653201 | 13.7351 | NA | NA |
| combsort | 2^15 | 0.0070073 | 40.2167 | 80.4334 | 13.9531 |
| std::sort(iterator) | 32768 | 0.00384778 | 18.3338 | 30.9398 | NA |
| std::sort | 32768 | 0.00335026 | 17.9507 | NA | NA |
| introsort | 2^16 | 0.00969255 | 18.5172 | 28.5819 | 9.94678 |
| heapsort | 2^16 | 0.0119691 | 16.3619 | 35.3975 | 19.4703 |
| mergesort | 2^16 | 0.0105975 | 14.7329 | 30.2329 | 16 |
| quicksort | 2^16 | 0.00940704 | 18.3235 | 26.4023 | 8.18502 |
| quicksort_nr | 2^16 | 0.00956297 | 18.1066 | 26.2475 | 8.1935 |
| cqsort | 2^16 | 0.0129935 | 14.7351 | NA | NA |
| combsort | 2^16 | 0.0143045 | 43.2142 | 86.4284 | 15.0652 |
| std::sort(iterator) | 65536 | 0.0081985 | 19.5519 | 32.6143 | NA |
| std::sort | 65536 | 0.0070591 | 19.4078 | NA | NA |
| introsort | 2^17 | 0.0198309 | 19.2521 | 29.6758 | 10.3184 |
| heapsort | 2^17 | 0.026468 | 17.3554 | 37.3895 | 20.462 |
| mergesort | 2^17 | 0.0243878 | 15.7346 | 33.2346 | 18 |
| quicksort | 2^17 | 0.024967 | 19.9184 | 28.4427 | 8.62446 |
| quicksort_nr | 2^17 | 0.0206831 | 19.6728 | 28.2809 | 8.6527 |
| cqsort | 2^17 | 0.028708 | 15.7364 | NA | NA |
| combsort | 2^17 | 0.031451 | 46.2132 | 92.4263 | 16.2224 |
| std::sort(iterator) | 131072 | 0.017206 | 20.7359 | 34.2805 | NA |
| std::sort | 131072 | 0.0147529 | 20.7001 | NA | NA |
| introsort | 2^18 | 0.0428371 | 20.7763 | 31.9917 | 11.08 |
| heapsort | 2^18 | 0.060225 | 18.354 | 39.3878 | 21.461 |
| mergesort | 2^18 | 0.054204 | 16.7354 | 34.2354 | 18 |
| quicksort | 2^18 | 0.0449061 | 20.9323 | 29.9506 | 9.11972 |
| quicksort_nr | 2^18 | 0.0444071 | 20.7911 | 29.8584 | 9.11888 |
| cqsort | 2^18 | 0.0612371 | 16.7355 | NA | NA |
| combsort | 2^18 | 0.0704291 | 49.2127 | 98.4253 | 17.2837 |
| std::sort(iterator) | 262144 | 0.0369871 | 21.8056 | 35.8416 | NA |
| std::sort | 262144 | 0.0335541 | 21.7911 | NA | NA |
| introsort | 2^19 | 0.10531 | 22.1166 | 33.9756 | 11.7039 |
| heapsort | 2^19 | 0.169231 | 19.354 | 41.3876 | 22.4603 |
| mergesort | 2^19 | 0.128936 | 17.7362 | 37.2362 | 20 |
| quicksort | 2^19 | 0.105645 | 22.1267 | 31.6042 | 9.58018 |
| quicksort_nr | 2^19 | 0.105005 | 22.234 | 31.7777 | 9.59514 |
| cqsort | 2^19 | 0.150182 | 17.7361 | NA | NA |
| combsort | 2^19 | 0.184128 | 52.2115 | 104.423 | 18.3483 |
| std::sort(iterator) | 524288 | 0.0942211 | 23.3306 | 37.815 | NA |
| std::sort | 524288 | 0.0859551 | 24.1802 | NA | NA |
| introsort | 2^20 | 0.247764 | 23.4475 | 36.0754 | 12.4453 |
| heapsort | 2^20 | 0.442663 | 20.3545 | 43.3887 | 23.4609 |
| mergesort | 2^20 | 0.290556 | 18.736 | 38.236 | 20 |
| quicksort | 2^20 | 0.250626 | 23.2412 | 33.2074 | 10.0712 |
| quicksort_nr | 2^20 | 0.253931 | 23.3071 | 33.3181 | 10.0623 |
| cqsort | 2^20 | 0.344221 | 18.736 | NA | NA |
| combsort | 2^20 | 0.43086 | 56.2095 | 112.419 | 19.3904 |
| std::sort(iterator) | 1048576 | 0.230459 | 23.9554 | 38.9847 | NA |
| std::sort | 1048576 | 0.20572 | 24.3193 | NA | NA |
| introsort | 2^21 | 0.554712 | 24.1748 | 37.1598 | 12.82 |
| heapsort | 2^21 | 1.07549 | 21.3544 | 45.3889 | 24.4613 |
| mergesort | 2^21 | 0.658452 | 19.7361 | 41.2361 | 22 |
| quicksort | 2^21 | 0.564909 | 24.3394 | 34.7983 | 10.5612 |
| quicksort_nr | 2^21 | 0.556773 | 24.0509 | 34.5808 | 10.582 |
| cqsort | 2^21 | 0.757419 | 19.7364 | NA | NA |
| combsort | 2^21 | 0.976948 | 59.2084 | 118.417 | 20.509 |
| std::sort(iterator) | 2097152 | 0.504422 | 25.5021 | 40.9916 | NA |
| std::sort | 2097152 | 0.472489 | 25.5631 | NA | NA |
| introsort | 2^22 | 1.20346 | 25.5088 | 39.1727 | 13.4783 |
| heapsort | 2^22 | 2.48213 | 22.3542 | 47.3885 | 25.4608 |
| mergesort | 2^22 | 1.38512 | 20.7357 | 42.2357 | 22 |
| quicksort | 2^22 | 1.2088 | 25.6059 | 36.5275 | 11.0243 |
| quicksort_nr | 2^22 | 1.19371 | 25.8683 | 36.813 | 10.995 |
| cqsort | 2^22 | 1.5637 | 20.7359 | NA | NA |
| combsort | 2^22 | 2.02832 | 62.2124 | 124.425 | 21.6898 |
| std::sort(iterator) | 4194304 | 1.07368 | 26.5342 | 42.514 | NA |
| std::sort | 4194304 | 0.977382 | 26.8222 | NA | NA |
| introsort | 2^23 | 2.48107 | 26.9948 | 41.4251 | 14.2166 |
| heapsort | 2^23 | 5.70184 | 23.3539 | 49.3881 | 26.4607 |
| mergesort | 2^23 | 2.93492 | 21.7357 | 45.2357 | 24 |
| quicksort | 2^23 | 2.53937 | 26.4896 | 37.9226 | 11.5348 |
| quicksort_nr | 2^23 | 2.52298 | 28.0309 | 39.3913 | 11.4106 |
| cqsort | 2^23 | 3.28481 | 21.7354 | NA | NA |
| combsort | 2^23 | 4.3994 | 66.2117 | 132.423 | 22.7599 |
| std::sort(iterator) | 8388608 | 2.23899 | 27.8882 | 44.3053 | NA |
| std::sort | 8388608 | 2.05833 | 27.8466 | NA | NA |
| introsort | 2^24 | 5.28411 | 28.7927 | 44.2796 | 15.2239 |
| heapsort | 2^24 | 12.9595 | 24.3541 | 51.3883 | 27.4607 |
| mergesort | 2^24 | 5.96994 | 22.7357 | 46.2357 | 24 |
| quicksort | 2^24 | 5.19425 | 27.9376 | 39.8182 | 11.9814 |
| quicksort_nr | 2^24 | 5.23735 | 27.9376 | 39.8573 | 11.9697 |
| cqsort | 2^24 | 6.77857 | 22.7356 | NA | NA |
| combsort | 2^24 | 8.84291 | 69.2087 | 138.417 | 23.8582 |
| std::sort(iterator) | 16777216 | 4.70659 | 28.795 | 45.7217 | NA |
| std::sort | 16777216 | 4.29975 | 29.2741 | NA | NA |
對接口編程, 不要對結構編程 ---- Python 經驗對 C 編程的考慮
通常, 如果幾行SHELL可以搞定, 不會用 Python. 幾行 Python 可以搞定的, 也就懶得用 C 了.
Python 最好用的是語言級的 list 和 dict 支持. 還有如 generator 可以帶來另外的編程範式, C 裏類似的效果, 常伴隨理解困難和BUG. 另外一個是Python的文件模塊化, 對象抽象和各種類似于Decorator的東西, 不僅是編程方便, 也提供了編碼工程上必須的分離. lambda 表達式也是 C 裏尚沒有的.
前時, 泛讀了 C Interfaces and Implementations (是的, 窮人的電子版), 突然對以前在哪看過的一句話非常贊同起來: 編程, 對外暴露接口, 不要暴露數據結構. 如此相反的觀點, 任何抽象都太重, 曾經左右我.
如果能接受腳本語言, 自然能接受C語言裏抽象的接口, 而隱藏數據結構. Python 的方便其實也自此而來.
Python 相比 C 的問題主要是運行慢, C 相比 Python 的問題主要是編碼慢, 易錯, 調試難, 缺泛強大的標准庫.
如果有熟悉的 LIST, Hash-Table, AVL, Sequence 的實現, 熟悉到可以像 Python 的 list, dict 那樣隨手拈來, 用 C 編碼也是很快的. 這些數據結構的通用實現, 自然要求隱藏數據結構. 這樣, 只要接口不變, 你可以方便的換一個實現, 只是需要重新編譯, 或者, 再加一層, 用來轉發到具體的實現, 像在很多 C++ 代碼裏見到的 FooInterface, FooImpl.
喜歡 Generator 的人不好應付一些. C 裏有一些 coroutine 的庫, 但在各堆棧跳來跳去是此編程方式的BUG發源地. 用事件狀態機加多線程是C的經典且易理解的編程方式, 我放棄協程這一條, 就像 Lambda 一樣.
程序, 大部分處理數據, 部分生成數據(處理需要理解, 比生成困難), 小部分是生成不可預測的數據, 也就是 BUG 隱藏地和隨機數的生成地.
在所有的調試方法裏, 某些人偏好 printf 和 assert. 對一個函數的前件和後件多作一些 assert, 很多BUG可以不寫測試也能發現. 程序正確性証明的一個方法就是証明不變量, 對不變量作 assert, 就會c對程序的正確性自信得多.
半年用 Python 的經驗是 Python 更容易寫錯誤的代碼, 多半是運行時才會發現. 只是Python會打印一個錯誤堆棧和出錯位置, C 裏同樣的功能可以設置 core 文件大小限制來得到.
C 的一种易调试的宏用法, 以做代码模板
1 C 的一种易调试的宏用法, 以做代码模板
用 C 比较多时, utils 库其实是不缺的, 但要熟悉起来, 编码才会高效. 前一阵子尝试写哈稀表, 承蒙标准云的张教主找来一个哈稀表的评测, 里面有些简易实现 -— 是的, 我只看简单的东西. 看完之后, 我站在别人的脚趾头上再实现了几个.
哈稀表实现有开放寻址和链表, 链表实现容易, 但时间和空间开销都较开放寻址 浪费. 做成高效通用的哈稀表, 有时, 多余函数调用的开销也是关键的, 宏和 inline 函数便在此处出现.
inline 函数很好, 不好的地方是类型检查上不绕开不方便, 绕开不安全. 但, 要 函数指针的形式, 便 inline 不得了. 最后一个考虑是宏了.
``该死的宏.''
宏不方便调试. 在写的时候要将几百行串成一行, 编译运行, 可能只告诉你宏调 用那一行有错, 这时要去那几百行慢慢找.
为此, 我看过 CPP 的文档, 失望而归. 然后, 在考虑写软件包自动编译安装脚本时, 发现 M4.
在 M4 之前, 我是想用 sed 来做这事的, 最后还是决定尝试一下不熟悉的 M4.
首先, 如常写 C 头文件代码(设为文件 ht.h.m4), 只是按一种约定, 一种类型的 操作给个共同的函数, 类型名前缀(这不算太坏的编码的规范, 如果不算好), 需 要做为泛型参数的给个名字. 最终, 我期望用 M4 处理一下这文件, 得到, 比如, 哈稀表的宏实现
HT_INIT(name, key_t, val_t, key_hash, key_equal).
其中, name 为结构名, 所有生成的函数结构将都以 name_ 开头. 如 key_hash 原型为
integer key_hash(key_t key)
具体可以是宏, 也可以是函数.
在测试时, 我只要定义好 key_t, val_t, key_hash, key_equal, 再包含头文件 (假设为 ht.h.m4), 就可以测试调用函数, 如
val_t name_get(name_t *p, key_t k).
测试完后, 可以用 m4 -P ht.h.m4 > ht.h 来生成头文件 ht.h, 里面有期望的 HT_INIT 宏. 在用 make 时, 可以添加规则.
%.h: %.h.m4
m4 -I$(srcdir) -P $^ > $(notdir $@)
%.c: %.c.m4
m4 -I$(srcdir) -P $^ > $(notdir $@)
挂羊头, 卖狗肉, 下面给另一个例子.
2 实例
CSEQ, 一个 C 的 sequnce 的实现.
2.1 文件 cpptemps.m4
文件内容如下段, 抽出来, 可以复用.
m4_divert(-1)
m4_define(`CS_QUOTE', `m4_ifelse(`$#', `0', `', ``$*'')')
m4_define(`CS_FOREACH', `m4_pushdef(`$1')_CS_FOREACH($@)m4_popdef(`$1')')
m4_define(`_CS_ARG1', `$1')
m4_define(`_CS_FOREACH', `m4_ifelse(`$2', `()', `',
`m4_define(`$1', _CS_ARG1$2)$3`'$0(`$1',(m4_shift$2), `$3')')')
m4_define(`CS_NO_ARGS',`_CS_NO_ARGS(`$1',`$2', `$'`#', `$'`@')')
m4_define(`_CS_NO_ARGS',`m4_pushdef(`$1',`$2`'m4_ifelse($3,0,,`('`$4'`)')')')
m4_define(`CS_APPEND_BACK_SLASH',`m4_patsubst(`$*',`
.',`\\\&')')
m4_define(`CS_LSTRIP',`m4_patsubst(`$*',`^[
]*')')
m4_define(`CS_DELETE_COMMENT_LINES',`m4_patsubst(`$*',`//[^
]*')')
m4_define(`CS_CASCAT',`CS_APPEND_BACK_SLASH(CS_LSTRIP(CS_DELETE_COMMENT_LINES($@)))')
m4_divert`'m4_dnl
2.2 文件 cseq.h.m4
实现文件, 主题无关的不优雅代码, 所以不全. 其中 defs.h 文件是一些包装内存分配等常见宏的定义.
CSEQ_FUNCS 里都是函数名, 如 size 对应 name_size, 在 CSEQ_INIT(cvs, char) 后, 将生成 cvs_size 函数.
///redundant comment introduced by m4`'m4_ifdef(`CS_FILE_CSEQ_H_M4',`',`m4_define(`CS_FILE_CSEQ_H_M4',`1')
#ifndef FILE_CSEQ_H__
#define FILE_CSEQ_H__ 1
#include "defs.h"
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
__attribute__((__const__))
static inline size_t cseq_cal_resize(size_t n) {
if (n > 134217728UL) {
return n + (n >> 1);
}
return n + n;
}
///m4_ifelse(
/*)
m4_include(cpptemps.m4)
m4_define(`CSEQ_INIT', `m4_ifelse(
CS_NO_ARGS(`name_t', ``$1''`_t')
CS_NO_ARGS(`val_t', ``$2'')
m4_ifelse(m4_eval($# < 3),1,
`CS_NO_ARGS(`CSEQ_FUNC_ATTR', `static inline')',
`CS_NO_ARGS(`CSEQ_FUNC_ATTR', `$3')'
)
m4_pushdef(`CSEQ_FUNCS', (append, array, check_capacity,
free, get, init, new, prepend, realloc, release,
reverse, rmhead, rmtail, set, size, resize, splice, move__,
add, copy, detach, attach))
CS_FOREACH(`x', CSEQ_FUNCS, `CS_NO_ARGS(`name_'x, ``$1_''``''x)')
)m4_dnl*/
typedef struct {
val_t *base;
size_t capacity;
size_t size;
int start;
} name_t;
CSEQ_FUNC_ATTR void name_init(name_t *p) {
memset(p, 0, sizeof(*p));
}
CSEQ_FUNC_ATTR void name_release(name_t *p) {
xfree(p->base);
memset(p, 0, sizeof(*p));
}
CSEQ_FUNC_ATTR name_t* name_new() {
name_t *p = xmalloc(sizeof(name_t));
name_init(p);
return p;
}
CSEQ_FUNC_ATTR void name_free(name_t *p) {
name_release(p);
xfree(p);
}
CSEQ_FUNC_ATTR size_t name_size(name_t *p) {
return p->size;
}
// more bulk such as splice ...
///m4_ifelse(
///m4_popdef(`name_t')
///m4_popdef(`val_t')
///CS_FOREACH(`x', CSEQ_FUNCS, `m4_popdef(`name_'x)')
///m4_popdef(`CSEQ_FUNCS')
///m4_popdef(`CSEQ_FUNC_ATTR')
///)')
#define CSEQ_INIT(name, cval_t) \
CS_CASCAT(CSEQ_INIT(`name``##''',`cval_t'))
滑稽之难
晚起, 走在路上想起昨天晚上看见别人推荐说鲁迅故居开拆的网址, 当时连
点过去看的兴致都没有. 当今文化继承上先天不足, 区区一被抬政治
身价的文人故居, 便我自居念旧者也不当回事.
鲁迅故居被拆自是不对, 且不说这个, 我所想的却是鲁迅在前朝与今地位的差异.
大抵历代都有褒贬与前相异的事情. 除开小时间段上的政治因素, 也有一部分移
风移俗的原因在里面. 如盗跖寿终, 人们骂天不公已有千年, 今天却觉自然. 再
如李自成起义, 便我不学无术辈, 也曾略听说过有几篇小说, 说得李自成十分不
堪. 最近如洪秀全, 祠堂里尚有记忆, 乡老口中长毛一词, 态度尽与受过民国以
降教育的不同.
昔时年少, 观古人颇有不通处, 尤其所喜人物, 念念间以此求全. 后来, 自己稍
通, 便开解了些. 后之视今, 便如今之视昔, 不知可有赞扬今天不耻的事情, 或
者有以今天光荣为耻的? 苟同于今天的荣耻, 大抵或也会被后辈小子冠以不通? 如早
期, 伤风败俗是近乎致命的罪项了. 而今, 风俗之力渐弱, 但能视风俗篾如却仍
无几. 大抵超脱点, 便是远远避开.
由此, 便想到滑稽. 滑稽难于雍穆.
六年,七年
下午林海峰答辩, 和尹超一起去围观. 时间比预想的慢了一个小时, 林海峰留下, 我和尹超回来看会电影, 牛钧便开始喊大家出发. 十几个人聚在门前闲聊带等的过了半个小时, 一起四五一组坐车去嘉陵江畔.
席间交错, 有些兴头, 酒便多起来, 头有些晕乎. 想起明天是工作日, 便和另几个同学先坐车回来了.
最后与一个寝室的牛钧, 林海峰碰杯, 牛钧哭道: ``老蒋, 六年了.''
认识牛钧兄七年, 自一起做本科生科研后, 走得近些, 算来也是六年.
牛钧兄达人, 识人多, 常有我辈意外之举, 诗人, 战士几成2002级数院本科生周知的典故.
本科生科研时, 牛钧和我常聚与图书馆自习, 所聊者为数学时甚少, 效率不是一般的低. 我不务正业的看 Knuth 的 The TeXBook, 即而对计算机引起兴趣. 牛兄也有自己的事情, 只偶尔看看, 一起讨论. 有时因为赶时间, 晚上常一起去南门的城隍庙, 也常是坐下来, 闲聊一会, 吃点东西, 又走了.
牛兄随身带着一个精致笔记本, 记些事情. 我翻过几页, 但有几页是牛兄不让看的.
进入研究生后, 与牛兄一个寝室. 牛兄两次出行, 得美人, 闪婚后生下一女, 两个月时眉目间即与牛兄极其相类, 观看的没有不大笑的. 前一阵子阿雅来校, 牛兄以其惊人的能量与其相抱.
我们常坐的新书阅览室前那张桌子, 桌子上提醒牌子后面各自写下有一段话, 引起好几篇留言, 保留约有几年, 现在不在了.
美丽有两种, 一是深刻又动人的方程, 一是你泛着倦意淡淡的笑容.
看一看冷月的桥影, 数一数螺细的花纹, 我倚暖了石栏的青笞, 青笞凉透了我的心坎.
匆匆一别, 默愿牛兄美国求学顺利, 新加坡孩子健康.