100 hz Square Wave of 50% duty cycle in digital pin 3 and verifying with pin 4
You wrote:
uint16_t val2 = pulseIn(4, HIGH);

It makes no sense to call this here, as the timer has not been
initialized. You probably cannot expect anything but a timeout in this
context.
noInterrupts();
cli();

These two are synonyms. No need to repeat yourself. Actually, no need to
block interrupts at all.
sei();
interrupts();

Ditto.
OCR1A = 19999; // = 16000000 / (8 * 100) - 1

This is supposed to fire interrupts at 100 Hz. But if you want a
100 Hz output signal, you should fire the interrupts at 200 Hz
(two interrupts per cycle). Thus:
OCR1A = 9999; // = (16 MHz / 8) / (2 * 100 Hz) - 1

Then,
// Set CS12, CS11 and CS10 bits for 8 prescaler
TCCR1B |= (0 &lt;&lt; CS12) | (1 &lt;&lt; CS11) | (0 &lt;&lt; CS10);

This is configuring Timer 1 for an external clock source. If you
want ÷8 prescaler, you should only set bit CS11. Check the datasheet.
uint16_t val = OCR1A/8;
ICR1 = val -1;
OCR1A = val/2 - 1 ; // 50% duty cycle for pin 3

This doesn't make any sense to me. Why are you setting ICR1? Why are
you changing OCR1A although it was already configured in setup()?
You can remove all this. Here is the loop() I used for testing:
void loop() {
    Serial.println(pulseIn(3, HIGH));
    delay(1000);
}

And it repeatedly printed 4955, which is quite close to the expected
value (namely 5000).