1 #ifndef _G_DBSEQ_INLINE_H
2 #define _G_DBSEQ_INLINE_H
5 #include <stdint.h> // int_fast8_t
6 #include <stdlib.h> // malloc
12 FORCE_INLINE
uint64_t *dibmalloc(size_t len
){
13 size_t needtomallocQQW
= (len
+31u)>>5;
14 uint64_t *outseq
= malloc(needtomallocQQW
*8);
18 FORCE_INLINE
uint64_t singlebase2dbitplus(const char *const base
, unsigned char *const hexBQchr
, size_t *const Ncountp
) {
33 *hexBQchr
= 1u<<7; // 128 for N
35 // DONOT use `|=` since the memory is just malloced
38 } // Whether a looking-up array[64] can be faster ?
42 FORCE_INLINE
size_t base2dbit(size_t seqlen
,
43 const char *const baseschr
, const char *const qstr
,
44 uint64_t *diBseq
, unsigned char *hexBQ
) {
45 // First, do the bases, overwrite output arrays since we have just malloc without setting to zero.
48 const size_t seqlenDowntoDW
= seqlen
& ~((2u<<4)-1);
50 printf("[b2d]%zu %zu\n",seqlen
,seqlenDowntoDW
);
53 for (i
=0;i
<seqlenDowntoDW
;i
+=32u) {
56 //tmpqdbase |= singlebase2dbit(baseschr+i+j,hexBQ+i+j)<<(62u-j);
57 tmpqdbase
|= singlebase2dbitplus(baseschr
+i
+j
,hexBQ
+i
+j
,&Ncount
)<<(j
*2);
58 // printf(" A{%lx,%.1s,%lx}",tmpqdbase,baseschr+i+j,singlebase2dbit(baseschr+i+j,hexBQ+i+j)<<(j*2));
60 *diBseq
++ = tmpqdbase
;
62 // printf("[b]%zu %zu\n",i,j);
64 for (j
=0;j
<seqlen
-i
;j
++) { // seqlen starts from 0.
65 // Cannot use 'j<=seqlen-i-1' here since 'size_t j' cannot be negative.
66 tmpqdbase
|= singlebase2dbitplus(baseschr
+i
+j
,hexBQ
+i
+j
,&Ncount
)<<(j
*2);
67 // printf(" B{%lx,%.1s,%lx}",tmpqdbase,baseschr+i+j,singlebase2dbit(baseschr+i+j,hexBQ+i+j)<<(j*2));
69 *diBseq
++ = tmpqdbase
;
70 // Everything should done in for-cycle when seqlen%4 == 0.
71 // No need to add '/0' since we have got seqlen, and there may be poly-A.
72 // Then, for the Q values ...
74 for (i
=0;i
<=seqlen
;i
++) {
75 if ( qstr
[i
] >= '@' && qstr
[i
] <= 'h' )
76 tmpqdbase
= qstr
[i
] - '?'; // @=1, A=2, B=3
78 hexBQ
[i
] |= tmpqdbase
; // lower 7bit already Zero-ed.
81 // Eamss-masking will be considered later.
85 FORCE_INLINE
uint64_t unitReverseComp(uint64_t seq32mer
){
87 seq32mer
= ((seq32mer
& 0x3333333333333333LLU
)<< 2) | ((seq32mer
& 0xCCCCCCCCCCCCCCCCLLU
)>> 2);
88 seq32mer
= ((seq32mer
& 0x0F0F0F0F0F0F0F0FLLU
)<< 4) | ((seq32mer
& 0xF0F0F0F0F0F0F0F0LLU
)>> 4);
89 #if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 3)
90 // see also https://github.com/damm/ffi/raw/7d11ff675759ca47243bb901e4226ee3ec6de0c6/ext/ffi_c/AbstractMemory.c
91 seq32mer
= ((seq32mer
& 0x00FF00FF00FF00FFLLU
)<< 8) | ((seq32mer
& 0xFF00FF00FF00FF00LLU
)>> 8);
92 seq32mer
= ((seq32mer
& 0x0000FFFF0000FFFFLLU
)<<16) | ((seq32mer
& 0xFFFF0000FFFF0000LLU
)>>16);
93 seq32mer
= ((seq32mer
& 0x00000000FFFFFFFFLLU
)<<32) | ((seq32mer
& 0xFFFFFFFF00000000LLU
)>>32);
95 seq32mer
= __builtin_bswap64(seq32mer
);
100 0xABCDEF0123456789 -> cgagtcgcccactagacaaattgtctattggg
101 revcomp -> cccaatagacaatttgtctagtgggcgactcg
103 //FORCE_INLINE uint64_t QQWkmerMovHigher(uint64_t *seq32mer, unsigned char bphigher, uint64_t ){}
105 // *base must have been Normalized to /[ATCGN]*/
106 FORCE_INLINE
uint64_t singlebase2dbit(const char *const base
, size_t *const Ncountp
) {
107 #ifdef NEWTRY /* slower than switch */
108 const unsigned char baseswitcher
[]={
119 // Now, only /[ATCG]/
120 unsigned char thebase
= *base
- 64;
121 thebase
= baseswitcher
[thebase
];
139 // DONOT use `|=` since the memory is just malloced
142 } // Whether a looking-up array[32] can be faster ?
145 FORCE_INLINE
size_t ChrSeq2dib(const char *const baseschr
, size_t seqlen
, uint64_t **diBseqp
, size_t *const puint64cnt
){
146 size_t needtomallocQQW
= (seqlen
+31u)>>5; // in fact length in sizeof(uint64_t)
147 if (needtomallocQQW
> *puint64cnt
) {
148 *diBseqp
= realloc(*diBseqp
, needtomallocQQW
*8);
149 *puint64cnt
= needtomallocQQW
;
151 uint64_t *tmpdiBseqp
= *diBseqp
;
154 const size_t seqlenDowntoDW
= seqlen
& ~((2u<<4)-1);
156 for (i
=0;i
<seqlenDowntoDW
;i
+=32u) {
159 tmpqdbase
|= singlebase2dbit(baseschr
+i
+j
,&Ncount
)<<(j
*2);
161 *tmpdiBseqp
++ = tmpqdbase
;
164 for (j
=0;j
<seqlen
-i
;j
++) { // seqlen starts from 0.
165 tmpqdbase
|= singlebase2dbit(baseschr
+i
+j
,&Ncount
)<<(j
*2);
167 *tmpdiBseqp
++ = tmpqdbase
;
169 while (tmpdiBseqp
< (*diBseqp
)+*puint64cnt
) {
170 *tmpdiBseqp
++ = 0LLU;
172 #endif // not nessary since we already have seqlen and the last uint64 is always with tailing 0s.
174 printf("[s2d]%zu %zu [%lx] [%.*s]\n",seqlen
,*puint64cnt
,**diBseqp
,(int)seqlen
,baseschr
); // just show the 1st one.
179 #endif // 2bitseqinline.h
182 NEWTRY(use array instead of switch) is slower ...
183 and User: 183.165154(s) if const uint64_t baseswitcher[]
186 User: 143.039254(s), System: 0.682896(s). Real: 144.603003(s).
187 Sleep: 0.880853(s). Block I/O times: 0/0. MaxRSS: 0 kiB.
188 Wait(s): 117(nvcsw) + 14195(nivcsw). Page Fault(s): 41291(minflt) + 0(majflt).
191 User: 132.749818(s), System: 1.740735(s). Real: 136.756637(s).
192 Sleep: 2.266084(s). Block I/O times: 0/0. MaxRSS: 0 kiB.
193 Wait(s): 71(nvcsw) + 42227(nivcsw). Page Fault(s): 41292(minflt) + 0(majflt).