1 /* Invisible Vector Library
2 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3 * Understanding is not required. Only obedience.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 module iv
.follin
.cmacro
/*is aliced*/;
21 // cool helper to translate C defines
22 template cmacroFixVars(T
...) {
24 * 64-bit implementation of fasthash
31 * 32-bit or 64-bit hash
33 usize
hashBuffer (const(void)* buf
, usize len
, usize seed
=0) pure nothrow @trusted @nogc {
36 (cast(ulong)data
[1]<<8)|
37 (cast(ulong)data
[2]<<16)|
38 (cast(ulong)data
[3]<<24)|
39 (cast(ulong)data
[4]<<32)|
40 (cast(ulong)data
[5]<<40)|
41 (cast(ulong)data
[6]<<48)|
42 (cast(ulong)data
[7]<<56)
44 enum m
= 0x880355f21e6d1965UL
;
45 auto data
= cast(const(ubyte)*)buf
;
48 foreach (immutable _
; 0..len
/8) {
49 version(HasUnalignedOps
) {
53 t
= *cast(ulong*)data
;
60 t
*= 0x2127599bf4325c37UL
;
69 case 7: t ^
= cast(ulong)data
[6]<<48; goto case 6;
70 case 6: t ^
= cast(ulong)data
[5]<<40; goto case 5;
71 case 5: t ^
= cast(ulong)data
[4]<<32; goto case 4;
72 case 4: t ^
= cast(ulong)data
[3]<<24; goto case 3;
73 case 3: t ^
= cast(ulong)data
[2]<<16; goto case 2;
74 case 2: t ^
= cast(ulong)data
[1]<<8; goto case 1;
75 case 1: t ^
= cast(ulong)data
[0]; goto default;
78 t
*= 0x2127599bf4325c37UL
;
86 h
*= 0x2127599bf4325c37UL
;
88 static if (usize
.sizeof
== 4) {
90 // the following trick converts the 64-bit hashcode to Fermat
91 // residue, which shall retain information from both the higher
92 // and lower parts of hashcode.
93 return cast(usize
)(h
-(h
>>32));
99 string
cmacroFixVars (string s
, string
[] names
...) {
100 assert(T
.length
== names
.length
, "cmacroFixVars: names and arguments count mismatch");
101 enum tmpPfxName
= "__temp_prefix__";
105 // skip empty lines (for pretty printing)
106 // trim trailing spaces
107 while (s
.length
> 0 && s
[$-1] <= ' ') s
= s
[0..$-1];
108 uint linestpos
= 0; // start of the current line
109 while (pos
< s
.length
) {
110 if (s
[pos
] > ' ') break;
111 if (s
[pos
] == '\n') linestpos
= pos
+1;
115 while (pos
+2 < s
.length
) {
117 while (epos
+2 < s
.length
&& (s
[epos
] != '$' || s
[epos
+1] != '{')) ++epos
;
119 if (s
.length
-epos
< 3) break;
123 assert(s
[pos
] == '$' && s
[pos
+1] == '{');
126 if (s
.length
-pos
>= tmpPfxName
.length
+1 && s
[pos
+tmpPfxName
.length
] == '}' && s
[pos
..pos
+tmpPfxName
.length
] == tmpPfxName
) {
127 if (tmppfx
.length
== 0) {
128 // generate temporary prefix
129 auto hash
= hashBuffer(s
.ptr
, s
.length
);
130 immutable char[16] hexChars
= "0123456789abcdef";
131 tmppfx
= "_temp_macro_var_";
132 foreach_reverse (immutable idx
; 0..usize
.sizeof
*2) {
133 tmppfx
~= hexChars
[hash
&0x0f];
138 pos
+= tmpPfxName
.length
+1;
142 foreach (immutable nidx
, string oname
; T
) {
143 static assert(oname
.length
> 0);
144 if (s
.length
-pos
>= oname
.length
+1 && s
[pos
+oname
.length
] == '}' && s
[pos
..pos
+oname
.length
] == oname
) {
146 pos
+= oname
.length
+1;
152 assert(found
, "unknown variable in macro");
154 if (pos
< s
.length
) res
~= s
[pos
..$];
161 //void draw_line (float* ${output}, int ${x0}, int ${y0}, int ${x1}, int ${y1}, int ${n})
162 enum draw_line(string output, string x0, string y0, string x1, string y1, string n) = q{{
163 int ${__temp_prefix__}dy = ${y1}-${y0};
164 int ${__temp_prefix__}adx = ${x1}-${x0};
165 int ${__temp_prefix__}ady = mixin(ABS!"${__temp_prefix__}dy");
166 int ${__temp_prefix__}base;
167 int ${__temp_prefix__}x = ${x0}, ${__temp_prefix__}y = ${y0};
168 int ${__temp_prefix__}err = 0;
169 int ${__temp_prefix__}sy;
171 version(STB_VORBIS_DIVIDE_TABLE) {
172 if (${__temp_prefix__}adx < DIVTAB_DENOM && ${__temp_prefix__}ady < DIVTAB_NUMER) {
173 if (${__temp_prefix__}dy < 0) {
174 ${__temp_prefix__}base = -integer_divide_table[${__temp_prefix__}ady][${__temp_prefix__}adx];
175 ${__temp_prefix__}sy = ${__temp_prefix__}base-1;
177 ${__temp_prefix__}base = integer_divide_table[${__temp_prefix__}ady][${__temp_prefix__}adx];
178 ${__temp_prefix__}sy = ${__temp_prefix__}base+1;
181 ${__temp_prefix__}base = ${__temp_prefix__}dy/${__temp_prefix__}adx;
182 ${__temp_prefix__}sy = ${__temp_prefix__}base+(${__temp_prefix__}dy < 0 ? -1 : 1);
185 ${__temp_prefix__}base = ${__temp_prefix__}dy/${__temp_prefix__}adx;
186 ${__temp_prefix__}sy = ${__temp_prefix__}base+(${__temp_prefix__}dy < 0 ? -1 : 1);
188 ${__temp_prefix__}ady -= mixin(ABS!"${__temp_prefix__}base")*${__temp_prefix__}adx;
189 if (${x1} > ${n}) ${x1} = ${n};
190 mixin(LINE_OP!("${output}[${__temp_prefix__}x]", "inverse_db_table[${__temp_prefix__}y]"));
191 for (++${__temp_prefix__}x; ${__temp_prefix__}x < ${x1}; ++${__temp_prefix__}x) {
192 ${__temp_prefix__}err += ${__temp_prefix__}ady;
193 if (${__temp_prefix__}err >= ${__temp_prefix__}adx) {
194 ${__temp_prefix__}err -= ${__temp_prefix__}adx;
195 ${__temp_prefix__}y += ${__temp_prefix__}sy;
197 ${__temp_prefix__}y += ${__temp_prefix__}base;
199 mixin(LINE_OP!("${output}[${__temp_prefix__}x]", "inverse_db_table[${__temp_prefix__}y]"));
201 }}.cmacroFixVars!("output", "x0", "y0", "x1", "y1", "n")(output, x0, y0, x1, y1, n);