// File: /workspace/github_cpp_makefile_star2_O2/iZhangHui[P]CppPrimer/CH17_SpecializedLibraryFacilities/examples/bits.cc
// Function: main
int main() 
{
	bitset<32> bitvec(1U); // 32 bits; low-order bit is 1, 
	                       // remaining bits are 0
	bool is_set = bitvec.any();      // true, one bit is set
	bool is_not_set = bitvec.none(); // false, one bit is set
	bool all_set = bitvec.all();     // false, only one bit is set
	size_t onBits = bitvec.count();  // returns 1
	size_t sz = bitvec.size();       // returns 32
	
	bitvec.flip();     // reverses the value of all the bits in bitvec
	bitvec.reset();    // sets all the bits to 0
	bitvec.set();      // sets all the bits to 1
	
	cout << "bitvec: " << bitvec << endl;
	
	sz = bitvec.size();  // returns 32
	
	onBits = bitvec.count();  // returns 1, 
                              // i.e., the number of bits that are on
	
	// assign 1 to even numbered bits
	for (int index = 0; index != 32; index += 2)
		bitvec[index] = 1; 

	// equivalent loop using set operation
	for (int index = 0; index != 32; index += 2)
		bitvec.set(index); 
	
	// bitvec is unchanged
	auto b2 = ~bitvec;  // b2 is a copy of bitvec with every bit flipped

	// assign value of last bit in bitvec to the first bit in b2
	b2[0] = bitvec[bitvec.size() - 1]; 
	bitvec[0] = 0;          // turn off the bit at position 0
	bitvec[31] = bitvec[0]; // give last bit the same value as the first
	bitvec[0].flip();       // flip the value of the bit at position 0
	~bitvec[0];             // equivalent; flips the bit at position 0
	bool b = bitvec[0];     // convert the value of bitvec[0] to bool
	b2[0] = ~bitvec[0];     // first bit in b2 has the opposite value 
                            // of the first bit in bitvec
	
	unsigned i = 0;
	if (bitvec.test(i))
	     // bitvec[i] is on
	        ;
	
	//equivalent test using subscript
	if (bitvec[i])
	     // bitvec[i] is on
	        ;
	
	cout << "bitvec: positions turned on:\n\t";
	for (int index = 0; index != 32; ++index)
		if (bitvec[index])
	    	cout << index << " ";
	cout << endl;
	
	// equivalent; turn off first bit
	bitvec.flip(0);   // reverses the value of the first bit
	bitvec.set(bitvec.size() - 1);  // turns on the last bit
	bitvec.set(0, 0); // turns off the first bit
	bitvec.reset(i);  // turns off the ith bit 
	bitvec.test(0);   // returns false because the first bit is off
	bitvec[0] = 0;
	
	bitvec.flip(0);   // reverses value of first bit
	bitvec[0].flip(); // also reverses the first bit
	
	cout << "new inits" <<endl;
	// bits13 is smaller than the initializer; 
	// high-order bits from the initializer are discarded
	bitset<13> bits13(0xbeef);  // bits are 1111011101111 

	// bits20 is larger than the initializer; 
	// high-order bits in bits20 are set to zero
	bitset<20> bits20(0xbeef);  // bits are 00001011111011101111

	// on machines with 64-bit long long 0ULL is 64 bits of 0, 
	// so ~0ULL is 64 ones, so 0 ... 63 are one, and 64 ... 127 are zero
    // if long long has 32 bits, 0 ... 32 are one, 33 ... 127 are zero
	bitset<128> bits128(~0ULL); 
	cout << "bits13: " << bits13 << endl;
	cout << "bits20: " << bits20 << endl;
	cout << "bits128: " << bits128 << endl;
	cout << "bits20[0] " << bits20[0] << endl;
	cout << "bits20[19] " << bits20[19] << endl;
	
	// bitvec1 is smaller than the initializer
	bitset<32> bitvec1(0xffff);  // bits 0 ... 15 are set to 1; 
	                             // 16 ... 31 are 0
	
	// bitvec2 same size as initializer
	bitset<64> bitvec2(0xffff);  // bits 0 ... 15 are set to 1; 
	                             // 16 ... 63 are 0
	
	// assuming 64-bit long long, bits 0 to 63 initialized from 0xffff
	bitset<128> bitvec3(0xffff); // bits 32 through 127 are zero
	
	cout << "bitvec1: " << bitvec1 << endl;
	cout << "bitvec2: " << bitvec2 << endl;
	cout << "bitvec2[0] " << bitvec2[0] << endl;
	cout << "bitvec2[31] " << bitvec2[31] << endl;
	
	cout << "bitvec3: " << bitvec3 << endl;
	
	
	bitset<32> bitvec4("1100"); // bits 2 and 3 are 1, all others are 0
	
	cout << "strval: " << "1100" << endl;
	cout << "bitvec4: " << bitvec4 << endl;
	
	string str("1111111000000011001101");
	bitset<32> bitvec5(str, 5, 4); // four bits starting at str[5], 1100
	bitset<32> bitvec6(str, str.size()-4); // use last four characters 
	
	cout << "str: " << str << endl;
	cout << "bitvec5: " << bitvec5 << endl;
	
	cout << "str: " << str << endl;
	cout << "bitvec6: " << bitvec6 << endl;
	
	unsigned long ulong = bitvec3.to_ulong();
	cout << "ulong = " << ulong << endl;
	
	bitset<32> bitvec7 = bitvec1 & bitvec4;
	
	cout << "bitvec7: " << bitvec7 << endl;
	
	bitset<32> bitvec8 = bitvec1 | bitvec4;
	
	cout << "bitvec8: " << bitvec8 << endl;
	
	bitset<16> chk("111100110011001100000");
	cout << "chk: " << chk << endl;
	
	bitset<16> bits;
	cin >> bits;  // read up to 16 1 or 0 characters from cin
	cout << "bits: " << bits << endl; // print what we just read

	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movl $0xffffffff, %r12d      # imm = 0xFFFFFFFF
leaq -0x30(%rbp), %rbx
movq %r12, (%rbx)
movq 0x3c2c(%rip), %rdi      # 0x5fd0
leaq 0x1c59(%rip), %rsi      # 0x4004
callq 0x2160
movq %rax, %rdi
movq %rbx, %rsi
callq 0x299c
movq %rax, %rdi
callq 0x20a0
xorl %ecx, %ecx
movq (%rbx), %rax
cmpq $0x20, %rcx
je 0x23d8
btsq %rcx, %rax
addq $0x2, %rcx
jmp 0x23c8
leaq -0x30(%rbp), %rbx
movq %rax, (%rbx)
xorl %r14d, %r14d
pushq $0x1
popq %r15
cmpq $0x20, %r14
je 0x2400
movq %rbx, %rdi
movq %r14, %rsi
movl %r15d, %edx
callq 0x2a98
addq $0x2, %r14
jmp 0x23e6
movl -0x30(%rbp), %eax
xorq %r12, %rax
leaq -0xd0(%rbp), %r12
movq %rax, (%r12)
leaq -0x68(%rbp), %r14
movq %rbx, (%r14)
pushq $0x1f
popq %r13
movq %r13, 0x8(%r14)
leaq -0xa0(%rbp), %r15
movq %r12, (%r15)
andq $0x0, 0x8(%r15)
movq %r15, %rdi
movq %r14, %rsi
callq 0x2ace
andb $-0x2, -0x30(%rbp)
movq %rbx, (%r14)
andq $0x0, 0x8(%r14)
movq %rbx, (%r15)
movq %r13, 0x8(%r15)
leaq -0xa0(%rbp), %rdi
movq %r14, %rsi
callq 0x2ace
movq -0x30(%rbp), %rsi
movq %rsi, %rax
xorq $0x1, %rax
movq %rax, -0x30(%rbp)
andl $0x1, %esi
movq %r12, (%r14)
andq $0x0, 0x8(%r14)
leaq -0x68(%rbp), %rdi
callq 0x2a6a
xorl %r14d, %r14d
movq %rbx, %rdi
xorl %esi, %esi
callq 0x2b08
movq 0x3b3d(%rip), %rbx      # 0x5fd0
leaq 0x1b73(%rip), %rsi      # 0x400d
movq %rbx, %rdi
callq 0x2160
leaq 0x1b9d(%rip), %r15      # 0x4046
cmpq $0x20, %r14
je 0x24d4
movq -0x30(%rbp), %rax
btq %r14, %rax
jae 0x24cf
movq %rbx, %rdi
movl %r14d, %esi
callq 0x2210
movq %rax, %rdi
movq %r15, %rsi
callq 0x2160
incq %r14
jmp 0x24a9
movq 0x3af5(%rip), %rbx      # 0x5fd0
movq %rbx, %rdi
callq 0x20a0
leaq -0x30(%rbp), %r14
movq %r14, %rdi
xorl %esi, %esi
callq 0x2b30
pushq $0x1f
popq %rsi
pushq $0x1
popq %rdx
movq %r14, %rdi
callq 0x2a98
movq %r14, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2a98
movq %r14, %rdi
xorl %esi, %esi
callq 0x2b5c
movq %r14, %rdi
xorl %esi, %esi
callq 0x2b08
andb $-0x2, (%r14)
movq %r14, %rdi
xorl %esi, %esi
callq 0x2b30
xorb $0x1, (%r14)
leaq 0x1af4(%rip), %rsi      # 0x402c
movq %rbx, %rdi
callq 0x2160
movq %rax, %rdi
callq 0x20a0
leaq -0xc8(%rbp), %r12
movq $0x1eef, (%r12)         # imm = 0x1EEF
leaq -0xc0(%rbp), %r14
leaq -0xa0(%rbp), %r15
orq $-0x1, (%r15)
movq $0xbeef, (%r14)         # imm = 0xBEEF
andq $0x0, 0x8(%r15)
leaq 0x1aba(%rip), %rsi      # 0x4036
movq %rbx, %rdi
callq 0x2160
movq %rax, %rdi
movq %r12, %rsi
callq 0x2b88
movq %rax, %rdi
callq 0x20a0
leaq 0x1aa1(%rip), %rsi      # 0x403f
movq %rbx, %rdi
callq 0x2160
movq %rax, %rdi
movq %r14, %rsi
callq 0x2c55
movq %rax, %rdi
callq 0x20a0
leaq 0x1a88(%rip), %rsi      # 0x4048
movq %rbx, %rdi
callq 0x2160
movq %rax, %rdi
movq %r15, %rsi
callq 0x2d22
movq %rax, %rdi
callq 0x20a0
leaq 0x1a70(%rip), %rsi      # 0x4052
movq %rbx, %rdi
callq 0x2160
movl (%r14), %esi
andl $0x1, %esi
movq %rax, %rdi
callq 0x2200
movq %rax, %rdi
callq 0x20a0
leaq 0x1a56(%rip), %rsi      # 0x405d
movq %rbx, %rdi
callq 0x2160
movl (%r14), %esi
shrl $0x13, %esi
andl $0x1, %esi
movq %rax, %rdi
callq 0x2200
movq %rax, %rdi
callq 0x20a0
movl $0xffff, %eax           # imm = 0xFFFF
leaq -0x48(%rbp), %r12
movq %rax, (%r12)
leaq -0xb8(%rbp), %r15
movq %rax, (%r15)
leaq -0xb0(%rbp), %r14
movq %rax, (%r14)
andq $0x0, 0x8(%r14)
leaq 0x1a14(%rip), %rsi      # 0x4069
movq %rbx, %rdi
callq 0x2160
movq %rax, %rdi
movq %r12, %rsi
callq 0x299c
movq %rax, %rdi
callq 0x20a0
leaq 0x19fc(%rip), %rsi      # 0x4073
movq %rbx, %rdi
callq 0x2160
movq %rax, %rdi
movq %r15, %rsi
callq 0x2def
movq %rax, %rdi
callq 0x20a0
leaq 0x19e4(%rip), %rsi      # 0x407d
movq %rbx, %rdi
callq 0x2160
movl (%r15), %esi
andl $0x1, %esi
movq %rax, %rdi
callq 0x2200
movq %rax, %rdi
callq 0x20a0
leaq 0x19cb(%rip), %rsi      # 0x4089
movq %rbx, %rdi
callq 0x2160
movl (%r15), %esi
shrl $0x1f, %esi
movq %rax, %rdi
callq 0x2200
movq %rax, %rdi
callq 0x20a0
leaq 0x19b3(%rip), %rsi      # 0x4096
movq %rbx, %rdi
callq 0x2160
movq %rax, %rdi
movq %r14, %rsi
callq 0x2d22
movq %rax, %rdi
callq 0x20a0
leaq 0x199b(%rip), %r15      # 0x40a0
leaq -0x40(%rbp), %r14
pushq $-0x1
popq %rdx
pushq $0x30
popq %rcx
pushq $0x31
popq %r8
movq %r14, %rdi
movq %r15, %rsi
callq 0x2ebc
leaq 0x1980(%rip), %rsi      # 0x40a5
movq %rbx, %rdi
callq 0x2160
movq %rax, %rdi
movq %r15, %rsi
callq 0x2160
movq %rax, %rdi
callq 0x20a0
leaq 0x1967(%rip), %rsi      # 0x40ae
movq %rbx, %rdi
callq 0x2160
movq %rax, %rdi
movq %r14, %rsi
callq 0x299c
movq %rax, %rdi
callq 0x20a0
leaq 0x194f(%rip), %rsi      # 0x40b8
leaq -0x68(%rbp), %rbx
leaq -0x38(%rbp), %rdx
movq %rbx, %rdi
callq 0x2040
leaq -0x38(%rbp), %rdi
pushq $0x5
popq %rdx
pushq $0x4
popq %rcx
movq %rbx, %rsi
callq 0x2f26
leaq -0x68(%rbp), %rsi
movq 0x8(%rsi), %rdx
addq $-0x4, %rdx
leaq -0x90(%rbp), %rdi
callq 0x2f68
movq 0x3826(%rip), %rdi      # 0x5fd0
leaq 0x191e(%rip), %rsi      # 0x40cf
callq 0x2160
leaq -0x68(%rbp), %rsi
movq %rax, %rdi
callq 0x2140
movq %rax, %rdi
callq 0x20a0
movq 0x37ff(%rip), %rdi      # 0x5fd0
leaq 0x18fd(%rip), %rsi      # 0x40d5
callq 0x2160
leaq -0x38(%rbp), %rsi
movq %rax, %rdi
callq 0x299c
movq %rax, %rdi
callq 0x20a0
movq 0x37d8(%rip), %rdi      # 0x5fd0
leaq 0x18d0(%rip), %rsi      # 0x40cf
callq 0x2160
leaq -0x68(%rbp), %rsi
movq %rax, %rdi
callq 0x2140
movq %rax, %rdi
callq 0x20a0
movq 0x37b1(%rip), %rdi      # 0x5fd0
leaq 0x18b9(%rip), %rsi      # 0x40df
callq 0x2160
leaq -0x90(%rbp), %rsi
movq %rax, %rdi
callq 0x299c
movq %rax, %rdi
callq 0x20a0
leaq -0xb0(%rbp), %rdi
callq 0x3580
movq %rax, %rbx
movq 0x3778(%rip), %rdi      # 0x5fd0
leaq 0x188a(%rip), %rsi      # 0x40e9
callq 0x2160
movq %rax, %rdi
movq %rbx, %rsi
callq 0x2100
movq %rax, %rdi
callq 0x20a0
movq -0x40(%rbp), %rax
andq -0x48(%rbp), %rax
movq %rax, -0x88(%rbp)
movq 0x3743(%rip), %rdi      # 0x5fd0
leaq 0x185e(%rip), %rsi      # 0x40f2
callq 0x2160
leaq -0x88(%rbp), %rsi
movq %rax, %rdi
callq 0x299c
movq %rax, %rdi
callq 0x20a0
movq -0x40(%rbp), %rax
orq -0x48(%rbp), %rax
movq %rax, -0x80(%rbp)
movq 0x370d(%rip), %rdi      # 0x5fd0
leaq 0x1832(%rip), %rsi      # 0x40fc
callq 0x2160
leaq -0x80(%rbp), %rsi
movq %rax, %rdi
callq 0x299c
movq %rax, %rdi
callq 0x20a0
leaq 0x181c(%rip), %rsi      # 0x4106
leaq -0x78(%rbp), %rdi
pushq $-0x1
popq %rdx
pushq $0x30
popq %rcx
pushq $0x31
popq %r8
callq 0x2fa8
movq 0x36cc(%rip), %rdi      # 0x5fd0
leaq 0x1811(%rip), %rsi      # 0x411c
callq 0x2160
leaq -0x78(%rbp), %rsi
movq %rax, %rdi
callq 0x3011
movq %rax, %rdi
callq 0x20a0
leaq -0x70(%rbp), %rsi
andq $0x0, (%rsi)
movq 0x36ad(%rip), %rdi      # 0x5fe0
callq 0x30de
movq 0x3691(%rip), %rdi      # 0x5fd0
leaq 0x17dc(%rip), %rsi      # 0x4122
callq 0x2160
leaq -0x70(%rbp), %rsi
movq %rax, %rdi
callq 0x3011
movq %rax, %rdi
callq 0x20a0
leaq -0x68(%rbp), %rdi
callq 0x2080
xorl %eax, %eax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x2988
jmp 0x2988
jmp 0x2988
jmp 0x2988
jmp 0x2988
jmp 0x2988
movq %rax, %rbx
leaq -0x68(%rbp), %rdi
callq 0x2080
movq %rbx, %rdi
callq 0x2230