private import std.c.stdlib; private import std.gc; /**************************************************************************** * 反則技w ****************************************************************************/ void* heap_base; void* hptr; static this() { version(Hansoku) { auto siz = 300*1024*1024; hptr = heap_base = std.c.stdlib.malloc(siz); //std.gc.addRange(heap_base, heap_base+siz); } } template use_special_heap() { version(Hansoku) { new( size_t s ) { void* p=hptr; hptr+=s; return p; } delete(void* p) {} } } void init_heap() { version(Hansoku){hptr=heap_base;} } /**************************************************************************** * 遅延されている値を表すクラステンプレート * * .evalを呼ぶと計算を実行して値が帰ってきます。 * めんどくさいので+,-,~しかもいい加減にしかしか演算子が * 定義されてませんが必要なら適当に足してください。 * * Authors: k.inaba * License: NYSL 0.9982 ****************************************************************************/ final class Lazy(T) { mixin use_special_heap!(); private: T delegate() thunk; T value; public: this(T delegate() t) { thunk=t; } this(T v) { value=v; } T eval() { if(thunk)value=thunk(),thunk=null; return value; } alias T value_t; private: // 演算子オーバーロードの補助 static T conv(T x) { return x; } static T conv(Lazy x) { return x.eval; } template impl(alias op) { Lazy impl() { class closure { mixin use_special_heap!(); typeof(l) lhs; typeof(r) rhs; T invoker() { return op(conv(lhs),conv(rhs)); } } with(new closure) { lhs=l; rhs=r; return new Lazy(&invoker); } } } public: // めんどくさいので引き算で。そのうちちゃんとやるかもしれない int opCmp(T r) { return cast(int)(eval - r); } int opCmp(Lazy r) { return cast(int)(eval - r.eval); } // 演算子オーバーロード static if( is(typeof(T+T):T) ) { private static T add(T x, T y) { return x+y; } Lazy opAdd(T r) { auto l = this; mixin impl!(add); return impl; } Lazy opAdd(Lazy r) { auto l = this; mixin impl!(add); return impl; } Lazy opAdd_r(T l) { auto r = this; mixin impl!(add); return impl; } } static if( is(typeof(T-T):T) ) { private static T sub(T x, T y) { return x-y; } Lazy opSub(T r) { auto l = this; mixin impl!(sub); return impl; } Lazy opSub(Lazy r) { auto l = this; mixin impl!(sub); return impl; } Lazy opSub_r(T l) { auto r = this; mixin impl!(sub); return impl; } } static if( is(typeof(T~T):T) ) { private static T cat(T x, T y) { return x~y; } Lazy opCat(T r) { auto l = this; mixin impl!(cat); return impl; } Lazy opCat(Lazy r) { auto l = this; mixin impl!(cat); return impl; } Lazy opCat_r(T l) { auto r = this; mixin impl!(cat); return impl; } } static if( is(typeof(T==T):int) ) { private static int eq(T x, T y) { return x==y; } Lazy opEquals(T r) { auto l = this; mixin impl!(eq); return impl; } Lazy opEquals(Lazy r) { auto l = this; mixin impl!(eq); return impl; } } // コピペ飽きた... (;´Д`) // そのうちちゃんと生成するスクリプトを書いて生成する... } /**************************************************************************** * 普通の値を遅延型に変換するテンプレート * * * Authors: k.inaba * License: NYSL 0.9982 ****************************************************************************/ template delay(T) { Lazy!(T) delay(T x) { return new Lazy!(T)(x); } } /// 可変個引数テンプレートのエミュレートのためのダミー private class __dummy_t {alias __dummy_t value_t;} private __dummy_t __dummy; /**************************************************************************** * 遅延評価される関数を定義するための補助mixin * * 醜い... * * Authors: k.inaba * License: NYSL 0.9982 ****************************************************************************/ template LazyFun( alias x1=__dummy ,alias x2=__dummy ,alias x3=__dummy ,alias x4=__dummy ,alias x5=__dummy ,alias x6=__dummy ,alias x7=__dummy ,alias x8=__dummy ,alias x9=__dummy ){ mixin use_special_heap!(); alias x1 __x1; alias x2 __x2; alias x3 __x3; alias x4 __x4; alias x5 __x5; alias x6 __x6; alias x7 __x7; alias x8 __x8; alias x9 __x9; alias typeof(x1) LT1; alias LT1.value_t T1; alias typeof(x2) LT2; alias LT2.value_t T2; alias typeof(x3) LT3; alias LT3.value_t T3; alias typeof(x4) LT4; alias LT4.value_t T4; alias typeof(x5) LT5; alias LT5.value_t T5; alias typeof(x6) LT6; alias LT6.value_t T6; alias typeof(x7) LT7; alias LT7.value_t T7; alias typeof(x8) LT8; alias LT8.value_t T8; alias typeof(x9) LT9; alias LT9.value_t T9; alias typeof(run()) LTR; alias LTR.value_t TR; static if( is(LT1==__dummy_t) ) const int __NP = 0; else static if( is(LT2==__dummy_t) ) const int __NP = 1; else static if( is(LT3==__dummy_t) ) const int __NP = 2; else static if( is(LT4==__dummy_t) ) const int __NP = 3; else static if( is(LT5==__dummy_t) ) const int __NP = 4; else static if( is(LT6==__dummy_t) ) const int __NP = 5; else static if( is(LT7==__dummy_t) ) const int __NP = 6; else static if( is(LT8==__dummy_t) ) const int __NP = 7; else static if( is(LT9==__dummy_t) ) const int __NP = 8; else const int __NP = 9; template opcall() { LTR opcall() { with(new typeof(this)) { static if( __NP>=1 ) __x1 = y1; static if( __NP>=2 ) __x2 = y2; static if( __NP>=3 ) __x3 = y3; static if( __NP>=4 ) __x4 = y4; static if( __NP>=5 ) __x5 = y5; static if( __NP>=6 ) __x6 = y6; static if( __NP>=7 ) __x7 = y7; static if( __NP>=8 ) __x8 = y8; static if( __NP>=9 ) __x9 = y9; return new LTR(&invoker); }}} TR invoker() { return run.eval; } public: static if( __NP==0 ) { static TR opCall() { mixin opcall!(); return opcall.eval; } } static if( __NP==1 ) { static LTR opCall(LT1 y1) { mixin opcall!(); return opcall; } static TR opCall(T1 y1) { init_heap; return opCall(delay(y1)).eval; } } static if( __NP==2 ) { static LTR opCall(LT1 y1,LT2 y2) { mixin opcall!(); return opcall; } static TR opCall(T1 y1,T2 y2) { init_heap; return opCall(delay(y1),delay(y2)).eval; } } static if( __NP==3 ) { static LTR opCall(LT1 y1,LT2 y2,LT3 y3) { mixin opcall!(); return opcall; } static TR opCall(T1 y1,T2 y2,T3 y3) { init_heap; return opCall(delay(y1),delay(y2),delay(y3)).eval; } } static if( __NP==4 ) { static LTR opCall(LT1 y1,LT2 y2,LT3 y3,LT4 y4) { mixin opcall!(); return opcall; } static TR opCall(T1 y1,T2 y2,T3 y3,T4 y4) { init_heap; return opCall(delay(y1),delay(y2),delay(y3),delay(y4)).eval; } } static if( __NP==5 ) { static LTR opCall(LT1 y1,LT2 y2,LT3 y3,LT4 y4,LT5 y5) { mixin opcall!(); return opcall; } static TR opCall(T1 y1,T2 y2,T3 y3,T4 y4,T5 y5) { init_heap; return opCall(delay(y1),delay(y2),delay(y3),delay(y4),delay(y5)).eval; } } // コピペ飽きた... (;´Д`) // そのうちちゃんと生成するスクリプトを書いて生成する... }