package main

import "fmt"

// kuadrat kecil dan sederhana: kandidat kuat inlining, panggilannya
// diganti salinan isi fungsi sehingga bebas biaya pemanggilan.
func kuadrat(x int) int {
	return x * x
}

// prosesBerat terlalu besar untuk anggaran inlining compiler, sehingga
// setiap pemanggilan tetap menjadi instruksi call sungguhan.
func prosesBerat(xs []int) int {
	akumulator := 0
	for i := 0; i < len(xs); i++ {
		v := xs[i]
		if v > 0 {
			akumulator += v * v
		} else if v < 0 {
			akumulator -= v
		} else {
			akumulator += 1
		}
		switch v % 4 {
		case 0:
			akumulator += 2
		case 1:
			akumulator += 3
		case 2:
			akumulator += 5
		default:
			akumulator += 7
		}
		if akumulator > 1_000_000 {
			akumulator -= 1_000_000
		}
		if akumulator < -1_000_000 {
			akumulator += 1_000_000
		}
	}
	return akumulator
}

// jumlahDenganIndeks memakai pola i < len(xs): compiler membuktikan
// indeks selalu valid dan menghilangkan bounds check di dalam loop.
func jumlahDenganIndeks(xs []int) int {
	total := 0
	for i := 0; i < len(xs); i++ {
		total += xs[i]
	}
	return total
}

// ambilAman memeriksa batas secara eksplisit sebelum mengakses elemen.
func ambilAman(xs []int, i int) int {
	if i < 0 || i >= len(xs) {
		return 0
	}
	return xs[i]
}

// ambilLangsung mengakses elemen tanpa bukti kevalidan indeks: compiler
// tidak dapat menghilangkan bounds check pada fungsi ini.
func ambilLangsung(xs []int, i int) int {
	return xs[i]
}

// Bentuk interface dengan satu method; Persegi adalah implementasinya.
type Bentuk interface {
	Luas() int
}

type Persegi struct {
	sisi int
}

func (p Persegi) Luas() int { return p.sisi * p.sisi }

func main() {
	angka := []int{1, 2, 3, 4, 5, 6, 7, 8}
	fmt.Println("kuadrat(12)            :", kuadrat(12))
	fmt.Println("prosesBerat(angka)     :", prosesBerat(angka))
	fmt.Println("jumlahDenganIndeks     :", jumlahDenganIndeks(angka))
	fmt.Println("ambilAman(angka, 3)    :", ambilAman(angka, 3))
	fmt.Println("ambilAman(angka, 9)    :", ambilAman(angka, 9))
	fmt.Println("ambilLangsung(angka, 2):", ambilLangsung(angka, 2))
	p := Persegi{sisi: 7}
	var b Bentuk = p
	fmt.Println("Luas lewat interface   :", b.Luas())
}
