// File: /workspace/github_cpp_makefile_star2_O3/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 $0x80000000, %r12d      # imm = 0x80000000
leaq 0x7fffffff(%r12), %rax
leaq -0x30(%rbp), %rbx
movq %rax, (%rbx)
movq 0x3c54(%rip), %r14      # 0x5fd0
leaq 0x1c81(%rip), %rsi      # 0x4004
movl $0x8, %edx
movq %r14, %rdi
callq 0x2110
movq %r14, %rdi
movq %rbx, %rsi
callq 0x2cdb
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %r14, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
xorl %ecx, %ecx
movq (%rbx), %rax
btsq %rcx, %rax
addq $0x2, %rcx
cmpq $0x20, %rcx
jne 0x23ca
xorl %ecx, %ecx
btsq %rcx, %rax
addq $0x2, %rcx
cmpq $0x20, %rcx
jne 0x23da
movabsq $-0x80000002, %r13      # imm = 0xFFFFFFFF7FFFFFFE
andq %r13, %rax
incq %rax
movq %rax, -0x30(%rbp)
movq 0x3bcd(%rip), %rbx      # 0x5fd0
leaq 0x1c03(%rip), %rsi      # 0x400d
movl $0x1e, %edx
movq %rbx, %rdi
callq 0x2110
xorl %r14d, %r14d
leaq 0x1c25(%rip), %r15      # 0x4046
movq -0x30(%rbp), %rax
btq %r14, %rax
jae 0x2446
movq %rbx, %rdi
movl %r14d, %esi
callq 0x21d0
movl $0x1, %edx
movq %rax, %rdi
movq %r15, %rsi
callq 0x2110
incq %r14
cmpq $0x20, %r14
jne 0x2421
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
andq -0x30(%rbp), %r13
orq %r12, %r13
movq %r13, -0x30(%rbp)
leaq 0x1ba4(%rip), %rsi      # 0x402c
movl $0x9, %edx
movq %rbx, %rdi
callq 0x2110
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
leaq -0xb8(%rbp), %r12
movq $0x1eef, (%r12)         # imm = 0x1EEF
leaq -0xb0(%rbp), %r14
movq $0xbeef, (%r14)         # imm = 0xBEEF
leaq -0xc8(%rbp), %r15
movq $-0x1, (%r15)
xorl %r13d, %r13d
movq %r13, 0x8(%r15)
leaq 0x1b41(%rip), %rsi      # 0x4036
movl $0x8, %edx
movq %rbx, %rdi
callq 0x2110
movq %rbx, %rdi
movq %r12, %rsi
callq 0x2dfd
movq %rax, %r12
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %r12, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
leaq 0x1b01(%rip), %rsi      # 0x403f
movl $0x8, %edx
movq %rbx, %rdi
callq 0x2110
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2f1f
movq %rax, %r12
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %r12, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
leaq 0x1ac1(%rip), %rsi      # 0x4048
movl $0x9, %edx
movq %rbx, %rdi
callq 0x2110
movq %rbx, %rdi
movq %r15, %rsi
callq 0x3041
movq %rax, %r15
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %r15, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
leaq 0x1a82(%rip), %rsi      # 0x4052
movl $0xa, %edx
movq %rbx, %rdi
callq 0x2110
movl (%r14), %esi
andl $0x1, %esi
movq %rbx, %rdi
callq 0x21b0
movq %rax, %r15
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %r15, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
leaq 0x1a41(%rip), %rsi      # 0x405d
movl $0xb, %edx
movq %rbx, %rdi
callq 0x2110
movl (%r14), %esi
shrl $0x13, %esi
andl $0x1, %esi
movq %rbx, %rdi
callq 0x21b0
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %r14, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
movl $0xffff, %eax           # imm = 0xFFFF
leaq -0x40(%rbp), %r12
movq %rax, (%r12)
leaq -0xa8(%rbp), %r15
movq %rax, (%r15)
leaq -0xa0(%rbp), %r14
movq %rax, (%r14)
movq %r13, 0x8(%r14)
leaq 0x19d9(%rip), %rsi      # 0x4069
movl $0x9, %edx
movq %rbx, %rdi
callq 0x2110
movq %rbx, %rdi
movq %r12, %rsi
callq 0x2cdb
movq %rax, %r12
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %r12, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
leaq 0x199a(%rip), %rsi      # 0x4073
movl $0x9, %edx
movq %rbx, %rdi
callq 0x2110
movq %rbx, %rdi
movq %r15, %rsi
callq 0x3163
movq %rax, %r12
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %r12, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
leaq 0x195b(%rip), %rsi      # 0x407d
movl $0xb, %edx
movq %rbx, %rdi
callq 0x2110
movl (%r15), %esi
andl $0x1, %esi
movq %rbx, %rdi
callq 0x21b0
movq %rax, %r12
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %r12, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
leaq 0x191b(%rip), %rsi      # 0x4089
movl $0xc, %edx
movq %rbx, %rdi
callq 0x2110
movl (%r15), %esi
shrl $0x1f, %esi
movq %rbx, %rdi
callq 0x21b0
movq %rax, %r15
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %r15, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
leaq 0x18dc(%rip), %rsi      # 0x4096
movl $0x9, %edx
movq %rbx, %rdi
callq 0x2110
movq %rbx, %rdi
movq %r14, %rsi
callq 0x3041
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %r14, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
leaq -0x38(%rbp), %r14
movq %r13, (%r14)
movl $0x31, (%rsp)
leaq 0x188f(%rip), %r15      # 0x40a0
movl $0x4, %edx
movl $0x4, %r8d
movq %r14, %rdi
movq %r15, %rsi
xorl %ecx, %ecx
movl $0x30, %r9d
callq 0x3848
leaq 0x186f(%rip), %rsi      # 0x40a5
movl $0x8, %edx
movq %rbx, %rdi
callq 0x2110
movl $0x4, %edx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x2110
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
leaq 0x182d(%rip), %rsi      # 0x40ae
movl $0x9, %edx
movq %rbx, %rdi
callq 0x2110
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2cdb
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
leaq -0x50(%rbp), %r14
movq %r14, -0x10(%r14)
leaq 0x17e6(%rip), %rsi      # 0x40b8
leaq 0x17f5(%rip), %rdx      # 0x40ce
leaq -0x60(%rbp), %rbx
movq %rbx, %rdi
callq 0x38aa
leaq -0x90(%rbp), %rdi
movl $0x5, %edx
movl $0x4, %ecx
movq %rbx, %rsi
callq 0x3286
leaq -0x60(%rbp), %rsi
movq 0x8(%rsi), %rdx
addq $-0x4, %rdx
leaq -0x88(%rbp), %rdi
callq 0x32d0
movq 0x36b3(%rip), %rdi      # 0x5fd0
leaq 0x17ab(%rip), %rsi      # 0x40cf
movl $0x5, %edx
callq 0x2110
movq -0x60(%rbp), %rsi
movq -0x58(%rbp), %rdx
movq 0x3693(%rip), %rdi      # 0x5fd0
callq 0x2110
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
movq 0x365d(%rip), %rdi      # 0x5fd0
leaq 0x175b(%rip), %rsi      # 0x40d5
movl $0x9, %edx
callq 0x2110
movq 0x3645(%rip), %rdi      # 0x5fd0
leaq -0x90(%rbp), %rsi
callq 0x2cdb
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
movq 0x3608(%rip), %rdi      # 0x5fd0
leaq 0x1700(%rip), %rsi      # 0x40cf
movl $0x5, %edx
callq 0x2110
movq -0x60(%rbp), %rsi
movq -0x58(%rbp), %rdx
movq 0x35e8(%rip), %rdi      # 0x5fd0
callq 0x2110
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
movq 0x35b2(%rip), %rdi      # 0x5fd0
leaq 0x16ba(%rip), %rsi      # 0x40df
movl $0x9, %edx
callq 0x2110
movq 0x359a(%rip), %rdi      # 0x5fd0
leaq -0x88(%rbp), %rsi
callq 0x2cdb
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
cmpq $0x0, -0x98(%rbp)
jne 0x2ca3
movq -0xa0(%rbp), %rbx
movq 0x3548(%rip), %rdi      # 0x5fd0
leaq 0x165a(%rip), %rsi      # 0x40e9
movl $0x8, %edx
callq 0x2110
movq 0x3530(%rip), %rdi      # 0x5fd0
movq %rbx, %rsi
callq 0x2090
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
movq -0x38(%rbp), %rax
andq -0x40(%rbp), %rax
movq %rax, -0x80(%rbp)
movq 0x34eb(%rip), %rdi      # 0x5fd0
leaq 0x1606(%rip), %rsi      # 0x40f2
movl $0x9, %edx
callq 0x2110
movq 0x34d3(%rip), %rdi      # 0x5fd0
leaq -0x80(%rbp), %rsi
callq 0x2cdb
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
movq -0x38(%rbp), %rax
orq -0x40(%rbp), %rax
movq %rax, -0x78(%rbp)
movq 0x348d(%rip), %rdi      # 0x5fd0
leaq 0x15b2(%rip), %rsi      # 0x40fc
movl $0x9, %edx
callq 0x2110
movq 0x3475(%rip), %rdi      # 0x5fd0
leaq -0x78(%rbp), %rsi
callq 0x2cdb
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
leaq -0x70(%rbp), %rdi
movq $0x0, (%rdi)
movl $0x31, (%rsp)
leaq 0x155f(%rip), %rsi      # 0x4106
movl $0x15, %edx
movl $0x15, %r8d
xorl %ecx, %ecx
movl $0x30, %r9d
callq 0x3948
movq 0x340a(%rip), %rdi      # 0x5fd0
leaq 0x154f(%rip), %rsi      # 0x411c
movl $0x5, %edx
callq 0x2110
movq 0x33f2(%rip), %rdi      # 0x5fd0
leaq -0x70(%rbp), %rsi
callq 0x331e
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
leaq -0x68(%rbp), %rsi
movq $0x0, (%rsi)
movq 0x33bd(%rip), %rdi      # 0x5fe0
callq 0x3440
movq 0x33a1(%rip), %rdi      # 0x5fd0
leaq 0x14ec(%rip), %rsi      # 0x4122
movl $0x6, %edx
callq 0x2110
movq 0x3389(%rip), %rdi      # 0x5fd0
leaq -0x68(%rbp), %rsi
callq 0x331e
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x20f0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20a0
movq -0x60(%rbp), %rdi
cmpq %r14, %rdi
je 0x2c8f
movq -0x50(%rbp), %rsi
incq %rsi
callq 0x2100
xorl %eax, %eax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x1508(%rip), %rdi      # 0x41b2
callq 0x2130
jmp 0x2cbb
jmp 0x2cbb
jmp 0x2cbb
jmp 0x2cbb
jmp 0x2cbb
jmp 0x2cbb
movq %rax, %rbx
movq -0x60(%rbp), %rdi
cmpq %r14, %rdi
je 0x2cd3
movq -0x50(%rbp), %rsi
incq %rsi
callq 0x2100
movq %rbx, %rdi
callq 0x21e0